diff -Nru frama-c-20110201+carbon+dfsg/bin/sed_inplace frama-c-20111001+nitrogen+dfsg/bin/sed_inplace --- frama-c-20110201+carbon+dfsg/bin/sed_inplace 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/bin/sed_inplace 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#!/bin/sh - -#Compatibilty script for non-GNU seds to emulate the -i option - -new_temp=`mktemp /tmp/frama-c.XXXXXXX` || exit 1 -sed "$@" > $new_temp -eval last=\${$#} -mv $new_temp $last diff -Nru frama-c-20110201+carbon+dfsg/Changelog frama-c-20111001+nitrogen+dfsg/Changelog --- frama-c-20110201+carbon+dfsg/Changelog 2011-02-07 13:51:22.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/Changelog 2011-10-10 08:40:09.000000000 +0000 @@ -12,41 +12,497 @@ # '#?nnn' : OLD-BTS entry #nnn # ############################################################################### +##################################### +Open Source Release Nitrogen_20111001 +##################################### + +- Rte [2011/10/07] No longer position 'Don't know' statuses +- Value [2011/10/07] New alarm for left shift of negative values. + Minor other changes related to shift operation alarms. +o*! Rte [2011/10/06] Correct plug-in name for dynamically registered + RTE functions. +-* Kernel [2011/10/06] Warn when the plug-in specified by -load-module + or -load-script is not found (used to remain silent) +-!* Kernel [2011/10/06] Do not normalize Pre in Old, especially where Old + is not allowed. +- Value [2011/10/01] Do not continue evaluating successive 'requires' + or 'ensures' clauses if one of them is false. +- Kernel [2011/10/01] New kind of command-line parameter, for commands + that do heavy output. Used for Value, Pdg and Metrics. +-* Cil [2011/09/30] Correctly handle casts in switch. Fixes #961. +-! Rte [2011/09/30] Option -rte-precond is not entailed by -rte-all + anymore (precontion annotations must now be required explicitly). +-* Aorai [2011/09/30] Generation of loop invariant for intermediate + counter + fixes various issues +-! Slicing [2011/09/30] Option -slice-print is now deprecated: use instead + -then-on 'Slicing export' -print +- From [2011/09/29] Display results function by function, instead of + as one big block (may lower memory consumption considerably). +- Value [2011/09/27] New option -remove-redundant-alarms for removing + redundant alarms. This was previously done by default. Use this + option if you are going to inspect alarms emitted by Value. +-* Kernel [2011/09/26] Treat long bitfields the same way as gcc and clang. + Fixes #!959. +-* Kernel [2011/09/26] New exception for Ast.UntypedFiles.get when no + untyped AST is available. Fixes #954. +- Value [2011/09/23] New alarm, for programs that do not respect + C99 6.5.16.1:3 (overlapping assignment from lvalue to lvalue). + Partially supported (not emitted in some cases). +-* Kernel [2011/09/23] Fixes various performance issues when parsing very + large functions. Fixes #!965. +- Value [2011/09/23] Improved precision of if (x!=c) when the value set + of x is an interval of 9 elements. +-* Slicing [2011/09/23] Use correct function during generation of + sliced project. Fixes #!950. +o* Kernel [2011/09/22] Copy visitor creates new kf before visiting a + function, allowing to use it for creating Property.t items in + the new project during visit (fixes #!942). +-* Value [2011/09/22] Much more clever when interpreting logic terms, + including those containing \old (eg. formals in postconditions) +- Value [2011/09/21] Raised cut-off limit between sets and intervals + from 7 to 8 elements. +- Value [2011/09/21] New informative message when not using. + -val-signed-overflow-alarms "2's complement assumed for overflow" +o! Value [2011/09/18] Changed the representation of Ival.t. If an + external plug-in matches "Ival.Set s", a simple fix is + to add "let s = Ival.set_of_array s in" as first line of + that case. +- Value [2011/09/16] Improved precision of &. +- Value [2011/09/16] Improved precision when using -all-rounding-modes. +o Kernel [2011/09/09] Map_common_interface to have a merge function for + Ocaml < 3.12. +o Kernel [2011/09/09] Quadruple datatype. +- Value [2011/09/09] Better message when interpretation stops + for a function argument. +- Pdg [2011/09/06] Pdg can now be saved on disk. +-* Logic [2011/04/20] Fix bug #!501: volatile clauses relative to + partially volatile lvalues are handled by the kernel. +- Pdg [2011/09/03] Improved time and space complexity on big functions. +- Cil [2011/09/02] Add support for GCC specific cast from field of + union to union +-* Cil [2011/09/02] Fix merging bug (#!948). +-* Slicing [2011/09/02] Fix incorrect simplification of single-statement + block in presence of label. +- Value [2011/09/02] Wide strings more supported. +- Kernel [2011/09/02] Improve space complexity of function stmt_can_reach. +- Semantic Constant Folding [2011/09/02] All options are prefixed by "scf". + Use -scf-help for the details. Fixed #!946. + Compatibility is preserved thanks to option aliases. +- Value [2011/08/30] Remove non-relevant variables from the 'Modifies' + clauses of the GUI. +o! Kernel [2011/08/30] Add parameter ~with_locals to Db.accept_base + (prior this, ~with_locals was implicitly false) +o! Value [2011/08/30] Signature change in CilE: plugins that want to + emit Value analysis alarms must define their own emitters. +o! Value [2011/08/30] Add some missing ~with_alarms arguments, notably + to offsetmaps copy and paste. +o! Kernel [2011/08/29] Export datatype Varinfo.Hptset. Signature change + in functor Abstract_interp.Make_Hashconsed_Lattice_Set. +- Metrics [2011/08/26] New command-line options to compute the functions + potentially called from a given function, and the percentage + of functions analyzed by the value analysis. +- Value [2011/08/25] Improve handling of assigns in library functions. +- Occurrence [2011/08/25] Better pretty-printing: do not display + internal ids anymore. +-! Value [2011/08/24] Improve behavior in presence of errors during + the computation of the initial state. Allow non ISO global + initializers using the value of constant globals defined earlier. +o! Kernel [2011/08/23] Getters of Dynamic.Parameter now get an extra + argument of type unit. May improve efficiency a lot. +-* Kernel [2011/08/23] Fixes visitor bug + properly refresh ids of + properties in code transformation (in particular loop unrolling). +-* Kernel [2011/08/15] Add parameter ~declarations to + Globals.FileIndex.get_functions. Prevent duplication bug + in properties navigator of the GUI. +- Inout [2011/08/12] Operational inputs and outputs are now more precise + for library functions: assigns clause are evaluated at each call. +o! Inout [2011/08/12] Interface change. Non_contextual renamed to + Cumulative_analysis. +-* Cil [2011/08/10] Fix conversion bug for f(i++) or f(++i) when i has + size less than int, and f expects an int (bug #911). +- Value [2011/08/10] Loop invariants are now used to improve analysis. +- Value [2011/08/09] Uses "complete behaviors" information. +- Scope [2011/08/09] "Show Defs" is now an interprocedural analysis. +o! Value [2011/08/09] Module Cvalue_type renamed to Cvalue. + Module Relations_type removed. Use Cvalue instead. +- Value [2011/08/04] Postconditions containing \old are now handled. +- Kernel [2011/08/04] Current pragmas no longer give rise to code + annotations (as they do not contain anything that can be proven). +-! Gui [2011/08/04] Improve labels under the icons of the toolbar. Smart + constructors in Menu_manager now require a label and a tooltip. +o Kernel [2011/08/04] Add Kernel.Unicode.without_unicode, which applies + a function without upsetting the Unicode option in the gui. +-* Impact [2011/08/04] Correct a journalisation bug in gui mode. +- Value [2011/08/01] More precise when an alarm is emited in a loop. +o! Kernel [2011/08/01] Signature of Plugin renamed for consistency. + Use carbon2nitrogen for automatic translation. +o! Kernel [2011/08/01] Annotations.replace and + Globals.Annotations.replace_all are removed. +o! Kernel [2011/08/01] Add IPLemma, IPNotacsl and IPConjunction as new + constructors of Property.t; remove IPBehavior. +- Kernel [2011/08/01] Better pretty printing of lists of any elements +o! Kernel [2011/08/01] Properties_status is now called + Property_status. Fully new interface. +o! Cil [2011/08/01] Removing types about validity status from the AST. + Use module Property_status instead. +o Kernel [2011/07/25] Adding option ~dkey to Log.debug functions. + See Log.Messages for details. +o! Kernel [2011/07/22] Modification of Log.print_on_console. No more + based on Format.kfprintf to avoid deadlock when + error are raised by plugin pretty printers. +-* Logic [2011/07/22] Fixes bug #885 (wrong insertion of cast). +-* Logic [2011/07/21] Fixes bug #!887 (merging logic constants). +o* Kernel [2011/07/20] Ensures that a unique kf is generated per function + in each project, avoid using kf for project A in project B. +-! Kernel [2011/07/18] Better handling of comments with -keep-comments + and new API. See Cabshelper.Comments and Globals.get_comments_* +o! Aorai [2011/07/12] Redefinition of internal structures before + enabling Ya extensions for sequences +o! Value [2011/07/11] Add argument "exact" to Lmap.paste_offsetmap (which + was preciously supposed to be always true). +-* Cil [2011/07/06] Correct obscure Cil bug linked to the removal of + trivial unspecified sequences or blocks. Fixes bug #882. +- Value [2011/07/05] Option -val-builtin: experimental support for + builtins that can fail (by calling a fallback C function). +- Value [2011/07/04] New builtin Frama_C_dump_each_file, which dumps + the entire memory state into successive files. +o* Logic [2011/06/29] Fixes bug #751 (Cil.lconstant now returns terms of + type integer and not int) +- Metrics [2011/06/27] Improves efficiency of metrics computation. +o! Cil [2011/06/24] Improve performances of Cil_datatype.Typ.{compare, + equal, hash}. +- Cil [2011/06/22] Cache results of offsets computations. +-* Logic [2011/06/22] Fixed issue #!866 (merging specs included twice) +o Kernel [2011/06/16] Exporting Property_status.self state +o! Kernel [2011/06/16] Dynamic.load_module searches in plugin path as + advertised in its documentation +o*! Cil [2011/06/14] Support for large constants in programs. My_bigint + is now used instead of Int64.t in the AST. Fixes #!858. +o* Kernel [2011/06/10] Fix dynamic access to function [is_default] of + parameters. +o! Kernel [2011/06/10] New way for handling abstract type in the type + library. +-* Value [2011/06/09] Remove some uneeded warnings when comparing function + pointers with NULL. Fixes bug #!855. +-* Kernel [2011/06/09] Correct syntactic loop unrolling in presence of + switch. Fixes bug #861. +o! Kernel [2011/06/09] Remove function CilE.update_gotos. +o! Kernel [2011/06/09] new function Kernel_function.set_spec which + must be called whenever the spec of a kf is modified. +o! Kernel [2011/06/08] Remove Kernel_datatype (merge with Cil_datatatype). +o! Kernel [2011/06/07] Most types of module Property are now private. + Use smart constructors instead. +o Kernel [2011/06/07] New function Dynamic.is_plugin_present. +-* Cil [2011/06/07] Fixes bug #857 (problem with some C enum value and + Ocaml 32 bits 3.11.0). +-* Logic [2011/06/06] Normalization of assigns clause: \result and + \exit_status only appear if a \from is specified. + Fixes #!557, #!845 +o! Kernel [2011/06/06] Structural_descr.pack is now a private type. + Use smart constructors instead. +- Value [2011/06/04] Emit \pointer_comparable alarm for unspecified. + equality test between literal strings such as "foo" == "foo". +- GUI [2011/06/03] Double-clicking on a warning now displays the + pretty-printed source location +o! Value [2011/06/03] Functions valid_* now take an argument ~for_writing + Pass true when the lvalue being considered is used for + writing in the program. Pass false when unsure. +- Value [2011/06/03] Literal strings are now read-only. +- Value [2011/06/03] More agressive state reduction when emiting + pointer_comparable assertions. Use option + -undefined-pointer-comparison-propagate-all if you liked + the old behavior better. +o GUI [2011/06/02] Menu_manager now support check menus and toggle + buttons +- Value [2011/06/02] New option -no-val-show-progress +- Cil [2011/06/02] Pretty-printing lval and term_lval the same way +- Cil [2011/06/01] Normalization of lval: T+1 ==> &T[1] when T is in + fact an array (implies *(T+1) ==> T[1]) +-* Logic [2011/05/31] can have a local binding for a predicate (even + a constant one) without spurious warnings from typechecker. + (fixes #!848) ++ Ptests [2011/05/31] Add -xunit option to support JUnit like output. +o Kernel [2011/05/31] Cil_datatype.LogicLabel implemented +o Kernel [2011/05/31] New function File.new_machdep in order to + register a new machdep dynamically. +- Dominators,Postdominators [2011/05/31] No feedback by default. Use + -dominators-verbose 2 or -postdominators-verbose 2 if you need it. +-* Project [2011/05/31] Fix sharing bug when copying project. +- Value [2011/05/31] Alarms may pretty print the abstract value culprit + for the potential violation. This is particularly informative for + certain alarms. +- Cil [2011/05/30] Support for &"constant_string" in parser. +-* Kernel [2011/05/29] Fixed macros in limit.h. +- GUI [2011/05/28] Support to display the state of the absolute memory. +o! Kernel [2011/05/26] Module Parameters is dead. Each module + corresponding to a parameters is moved to Kernel. Module + Parameters.Dynamic is now Dynamic.Parameter while + Parameters.get_selection_context is now + Plugin.get_selection_context. You can use the script + bin/carbon2nitrogen to perform the translation (almost) + automatically. +- Value [2011/05/24] Option -val-after-results to control the recording + of post-statement states. Active by default in the GUI. +-* Cil [2011/05/24] Fixes bug #832 (spurious warning for read/write + accesses in undefined order) +o! Logic [2011/05/24] Add possibility to cast integer to C integral + type when type-checking (Changes parameter of Logic_typing.Make) +o! Kernel [2011/05/24] Kernel_function.find_return may now raise + exception Kernel_function.No_Statement. +-* Cil [2011/05/17] Fixes bug #771 (spurious warning for read/write + accesses in undefined order). +-* Kernel [2011/05/13] Support GCC like typing of enums. +- GUI [2011/05/13] Add history for navigating source code. +o! GUI [2011/05/13] Signature change for Filetree#add_select_function, + Filetree#select_global and Menu_manager.entry. Deprecate + Design.apply_on_selected. +-* Kernel [2011/05/12] Fixed typing of bitfields whose size is equal to the + size of int (bugs #823, #817). +-* Value [2011/05/11] Fixed undocumented builtin is_base_aligned. +-* Value [2011/05/11] Fixed bug when bitfield receives the result of + a function call (bug #819). +- GUI [2011/05/10] Menu to configure what is displayed in the filetree. +-* Logic [2011/05/08] Fixed overloading resolution (fixes bug #655). +-* Logic [2011/05/06] Fixed issue with -pp-annot (fix bug #691 and #812). +o Kernel [2011/05/05] Kernel now accepts declarations as main entry point. +- Aorai [2011/05/04] Automaton is handled by contract of leaf functions. +o Cil [2011/05/04] Various smart constructors and ast helper functions. +-* Cil [2011/05/04] Fixes wrong precedence of not in predicate when + pretty-printing. +- GUI [2011/05/04] Automatically show the main function at launch. +- GUI [2011/05/04] Hide empty plugins columns in the filetree. Add + support for hiding globals entirely. +o! GUI [2011/05/04] Signature change for Filetree#append_pixbuf_column. +o! Kernel [2011/05/03] Remove Db_types module. All types are now in + Cil_types. Moved type Alarms.t to Cil_types.alarm. +-* Kernel [2011/05/02] Support for GCC packed and aligned attributes and + for GCC pack pragmas. Fixes #719. +-* Configure [2011/05/02] Fix bug #!262: --disable-plugin works for external + plugins compiled from within Frama-C kernel. +- Dataflow [2011/04/29] Improve precision of backwards dataflow algorithm + and of postdominators on 'if' with a missing branch +-* Pdg [2011/04/28] Better precision in the dependencies. + Fix bug #787, #789 and #802 : infinite loops creation in slicing. +o Value [2011/04/28] Changed representation of bases for literal strings + in preparation of related checks. +o Postdominators [2011/04/27] Add Db.PostdominatorsValue: postdominators + taking into account value analysis results +-* Value [2011/04/24] Fixed crash for high values of -subdivide-float-var +- Value [2011/04/24] Improved results for operation % by zero. + Removed message about binary operators raising exceptions. +o Value [2011/04/24] Defunctorized Lattice_Interval_Set. +-* Logic [2011/04/20] Fix bug #761: adding \old in ensures clause for + parameters does not capture terms in associated offset. +-* Logic [2011/04/20] Fix bug #!501: volatile clauses are + handled by the kernel. +-* Slicing [2011/04/20] Fix bug #799: missing label in sliced program. +-* Value [2011/04/17] Fix bug #798: calls to functions that + return a value with latent conversion. +-* Cil [2011/04/15] Fix bug #785: promotion between long long and an + unsigned same-sized type. +-* Cil [2011/04/14] Fix bugs #780 and #791: use ids unique + between projects for varinfos, statements and expressions. +o*! Cil [2011/04/14] Remove incorrect Cil_const.Build_Counter; use + State_builder.SharedCounter instead. +-! Value [2011/04/14] Use hash-consed sets of statements, making + many analyses faster and leaner for large functions or idioms + that make functions large at normalization + (e.g. large initialized local arrays). +-* Kernel [2011/04/14] Fix 'make clean' of plug-ins. +-* Kernel [2011/04/13] Fix bug #769: merging issue for declared struct. +o* Kernel [2011/04/13] Fix bug #790: AST integrity checker issue. +-* Pdg [2011/04/13] Fix bug #787 but leads to less precise dependencies. +-* Slicing [2011/04/02] Fix bug #786: missing label in sliced program. +-* Value [2011/04/12] Correctly emit \pointer_comparable(...) alarms. +-* From [2011/04/11] Fix #781: handling of function calls with an implict + cast for the assignment of the result. +o Makefile [2011/04/08] Add target to launch the tests of a specific + dynamic internal plugin from Frama-C's main Makefile. +-* Aorai [2011/04/08] Existing assigns are augmented with the locations + corresponding to the instrumentation of the automaton. +- Value [2011/04/05] Each precondition can get a specific validity status. +-* Kernel [2011/04/01] Fixed bug #770 and #769, part 1. Fixed typo in + anonFieldName (was annonFieldName). +-* Kernel [2011/04/1] Fixed bug #775. Large octal and hexadecimal constants + are now correctly typed. +-* Occurrence [2011/04/01] Fixed bug when journalising. +-* Slicing [2011/04/01] Fixed bug #774: journalisation works again. +o Kernel [2011/03/30] Removed type Log.source. From now on all locations + have type Lexing.position. +- Kernel [2011/03/30] Some messages may be printed several time for + the same line if they refer to different columns. +-* Value [2011/03/30] Fixed bug #689. Each postcondition can get a + specific validity status. +-* Impact [2011/03/30] Bug fixed when plug-in `Security_slicing' + cannot be loaded or is incompatible with Impact. +-* Impact [2011/03/30] Bug fixed with '-impact-pragma f' on an unknown + function f. +-* Security_slicing [2011/03/30] Fixed bug #768 about exception raised when + analysing variadic functions. A warning is now emitted: + the function is ignored by the analyzer, thus the result is + potentially incorrect. +o! Kernel [2011/03/29] Alternative signature for dataflow initial state. + A few IntHash replaced by Stmt.Hashtbl. +- Users [2011/03/28] Calls to this plug-in are now written in the journal. +-* Value [2011/03/26] Some floating-point alarms could be printed several + times. Fixed. +o! Kernel [2011/03/25] get rid of bin/sed_inplace (use ISED from + share/Makefile.common where needed, which was the recommended + way from the beginning). +o* Kernel [2011/03/25] Makefile.plugin and .dynamic more robust wrt + external plugins (can make doc clean depend more easily; + fixes bug #754, improves bug #742). +-* Logic [2011/03/24] \at(t,L) when t is a C array is now a logic array + whose content is the one of t at L, not the address of the first + element of t (which stays the same between L and Here anyway). + partial fix of bug #761. +- Kernel [2011/03/24] \at(p,Old) is pretty-printed as \old(p). +o! Cil [2011/03/24] AST changed: removing Told and Pold constructs. +o! Kernel [2011/03/11] Following items are now deprecated: + function Kernel_function.pretty_name: use Kernel_function.pretty + module UseUnicode: use module Unicode. +o! Kernel [2011/03/11] Remove several kernel functions: + Ast_info.pretty_vname: use Cil_datatype.Varinfo.pretty_vname + Cil.print_utf8: use module Parameters.UseUnicode- + Clexer.keep_comment: use module Parameters.PrintComments + Cabshelper.continue_annot_error_set: + Cabshelper.continue_annot_error_set: use + Parameters.ContinueOnAnnotError.off + all Cil, Cilmsg and CilE functions for pretty printing: use Kernel + ones instead. +- From [2011/03/11] Display name of called function when displaying + results of option -calldeps. +o!* Logic [2011/03/11] Implementation of statement contracts for function + behaviors. +-* Value [2011/03/11] Fixed crash with ACSL assertions involving + floating-point variables (bug #752). +-* Logic [2011/03/10] Fixed bug #744 (comparison between arithmetic types + is done in the smallest possible type). +-* Kernel [2011/03/10] Bug fixed in File.create_project_from_visitor + potentially impacted programs transformation. +-* Kernel [2011/03/10] Bug fixed in pretty printer. + (incorrect precedences leading to missing parenthesis). +- Kernel [2011/03/09] Big integers can now be displayed using hexadecimal + notation. +- Value [2011/03/06] Improved option -subdivide-float-var when used + without -all-rounding-modes. Improvement marginal for + double computations and significant for float ones. +o! Cil [2011/03/04] AST changed: 'a before_after type is deleted. All + annotations are now attached before. +-* Value [2011/03/04] Fixed correctness bug when bitfield initializer + exceeds range (bug #721) (jrrt). +o! Value [2011/03/02] Minor interface changes in Value. Replace + some meaningless kinstr by stmt, and make the callbacks lazy. +o! From [2011/03/02] Minor interface changes in From. Replace + some meaningless kinstr by stmt, and make the callbacks lazy. +-! Cil [2011/03/02] Fixed #720 (incorrect simplification of switch). +- Kernel [2011/03/02] Better error message when plug-in crashes on + loading (bts #737). +o Kernel [2011/03/02] New function File.create_rebuilt_project_from_visitor +- Cil [2011/02/24] Implement precise dataflow on switch + constructs. As side effect, improve precision of value analysis. +o* Kernel [2011/02/24] Fixed bug #727 (visiting a GFun spec in frama-c + visitor was not done in the appropriate context). +o* Ptests [2011/02/24] Ptests adds filename of current test before the + options given to frama-c (see #736). +- Aorai [2011/02/24] Deterministic automata. +-* Aorai [2011/02/24] Fix issue in translation of guards + better error + messages. +o! Inout [2011/02/23] Db.InOutContext becomes Db.Operational_inputs. +- Inout [2011/02/23] Correctness in presence of recursive calls. + See issue #733. +- Value [2011/02/23] Improved informative messages about addresses + of locals escaping their scope. +o! Kernel [2011/02/22] Change semantics of ChangeDoChildrenPost for + vstmt_aux. See developer's manual for more precision. +- Value [2011/02/22] Take Flush-To-Zero possibility into account + for single-precision floats. +- Kernel [2011/02/22] Exit status on unknown error is now 125. 127 and + 126 are reserved for the shell by POSIX. +o!* Kernel [2011/02/21] Extlib.temp_file_cleanup_at_exit and + Extlib.temp_dir_cleanup_at_exit may now raise exception + Temp_file_error. They may raise an unspecified exception before. +-* Value [2011/02/20] Fixed bug #732: Synthetic results were partial + when -slevel was set not high enough to unroll loops + completely. +- Inout [2011/02/20] Improved messages in presence of recursive calls +o! Kernel [2011/02/18] Bts #729: calling function Plugin.is_visible + (resp. Plugin.is_invisible) forces to display + (resp. prevents from displaying) the corresponding + parameters in an help message. +o! Kernel [2011/02/18] module Service_graph: function entry_point in + input and output of functor Make now returns an option type. +- Syntactic Callgraph [2011/02/18] Fixed issue #723: syntactic callgraph + does not require an entry point anymore. If no entry point, + services are less precise yet. +-* Cil [2011/02/17] Fixed bug #725 (type-checking && operator). +- Inout [2011/02/17] Improved precision of the computation of + operational inputs in presence of function calls. +-* Logic [2011/02/17] Fixed bug #714 about lexing ACSL characters and + strings. +o Cil/Logic [2011/02/16] New functions Clexer.is_c_keyword and + Logic_lexer.is_acsl_keyword. +-! Cil [2011/02/16] Enumerated constants are kept in the AST. +-* Aorai [2011/02/16] State names used as enum constant are checked to be + admissible fresh C identifiers. +-* Value [2011/02/15] Fixed bug when passing struct as argument to + function with a big-endian target architecture. +- Value [2011/02/15] Uniformized message displayed when no information + is available for a function. +- Logic [2011/02/14] Added support for bitwise operators --> and <--> into + ACSL formula. +-* Slicing [2011/04/02] Fixed bug #709: missing statements in sliced program. +-* Value [2011/02/14] Fixed bug when passing bitfield + as argument to function. (jrrt) +-* Value [2011/02/12] Fixed forgotten warning when passing completely + undefined lvalue as argument to function. (jrrt) +-* Value [2011/02/12] Fixed correctness bug involving nested structs + (jrrt). +-* Value [2011/02/12] Fixed crash when passing invalid argument to + function, found by John Regehr using random testing (jrrt). +-* Value [2011/02/09] Fixed representation of unknown single-precision + floats in initial context (it used to be the same as for + an unknown double). +-* Value [2011/02/09] Changes related to 0., +0., -0., sort of thing. + Unwarranted loss of precision fixed. + ################################### Open Source Release Carbon_20110201 ################################### +- WP [2011/02/07] Plug-in WP removed from kernel-releases (now an + independent plug-in). - Logic [2011/02/04] Mentioning a formal on the left-hand side of an assigns clause is now an error when type-checking logic annotations. o! Logic [2011/02/04] Refactoring of assigns and from AST representation and of Property.identified_property. -- Value [2011/02/04] Changes in Frama_C_memcpy built-in. Still not +- Value [2011/02/04] Changes in Frama_C_memcpy built-in. Still not perfect. - Value [2011/02/04] Is is now possible to call Frama_C_show_each - without ..._x + without ..._x. - Value [2011/02/04] Generate independent assertions for signed overflow and signed underflow. In many cases only one is generated (win!). o! Value [2011/02/02] Renamed copy to copy_offsmap in Offsetmaps. The name "copy" clashed with Datatypes. o Kernel [2011/02/01] New syntactic context for memory accesses with - user-supplied validity range -- WP [2011/01/31] Option -wp-warnings to display additional + user-supplied validity range. ++ WP [2011/01/31] Option -wp-warnings to display additional informations for 'Stronger' and 'Degenerated' goals. -- WP [2011/01/24] Option -wp-split-dim to limit spliting ++ WP [2011/01/24] Option -wp-split-dim to limit spliting up to 2**n sub-goals (see -wp-split option). -! Kernel [2011/01/27] Handle errors better when they occur when exiting Frama-C. Slight semantic changes for exit code: - - old code 5 is now 127 - - code 5 is now: error raised when exiting Frama-C normally - - code 6: error raised when exiting Frama-C abnormally -- Kernel [2011/01/27] Improve performance on platform with dynamic - loading. Mainly impact value analysis. - (for developpers: improve efficiency of Dynamic.get) + - old code 5 is now 127; + - code 5 is now: error raised when exiting Frama-C normally; + - code 6: error raised when exiting Frama-C abnormally. +- Kernel [2011/01/27] Improve performance on platform with dynami.c + loading. Mainly impact value analysis + (for developers: improve efficiency of Dynamic.get). - Value [2011/01/25] Change in initial states generated by -lib-entry Much smaller. Perhaps more representative. -- WP [2011/01/24] When -rte-precond is not used, ++ WP [2011/01/24] When -rte-precond is not used, wp generates a separate proof obligation for each call site. -! Configure [2011/01/24] Frama-C does not require Apron anymore (Why does for Jessie). Thus fix bug #647. @@ -56,50 +512,50 @@ Plugin.add_alias is now deprecated and replaced by Plugin.add_aliases. o Kernel [2011/01/21] New function in API: - Kernel_function.find_syntactic_callsites -o WP [2011/01/20] Options -wp-status-xxx to refine goal selection -o Report [2011/01/20] Option -report no longer survive after -then -o WP [2011/01/19] Clarification of -save/-then effect on WP + Kernel_function.find_syntactic_callsites. ++ WP [2011/01/20] Options -wp-status-xxx to refine goal selection. +o Report [2011/01/20] Option -report no longer survive after -then. ++ WP [2011/01/19] Clarification of -save/-then effect on WP. * Slicing [2011/01/19] Fixed bug #673. -- Value [2011/01/19] Various minor speed improvements +- Value [2011/01/19] Various minor speed improvements. -* Value [2011/01/19] Fixed correctness bug involving pointers to signed integer pointing to memory locations containing unsigned integers or vice versa. -* Kernel [2011/01/19] Fixed bug if an empty string is given on the command line while an option name is expected. There is now a proper error message. -- Logic [2011/01/16] Fix priority bug in parser +- Logic [2011/01/16] Fix priority bug in parser. - Slicing [2011/01/14] New options added for fixing bug #668. o Sparecode [2011/01/14] API modified for fixing #668. -o GUI [2011/01/13] Added support for icons in Gtk_helper.Icon +o GUI [2011/01/13] Added support for icons in Gtk_helper.Icon. -* GUI [2011/01/12] Fixed bug #666. Do not display misleading - "After statement" -- Value [2011/01/12] Improve performance of callbacks + "After statement". +- Value [2011/01/12] Improve performance of callbacks. - GUI [2011/01/11] Display more precise state after statement - (http://blog.frama-c.com/index.php?post/2011/01/11/Seven-errors-game ) + (http://blog.frama-c.com/index.php?post/2011/01/11/Seven-errors-game). -o Value [2011/01/11] New callback for recording the state after a - statement --* WP [2011/01/10] Fixed incorrect status refresh problem in the GUI. + statement. ++* WP [2011/01/10] Fixed incorrect status refresh problem in the GUI. -* Kernel [2011/01/10] Fixed #!313. Entry point with a specification is no longer wiped out. -* GUI [2011/01/10] Fixed 100% cpu load while external command - are launched + are launched. - Value [2011/01/09] Disabled incorrect interpretation of - ACSL statement contracts -- Value [2011/01/07] Interpretation of ==> in ACSL annotations + ACSL statement contracts. +- Value [2011/01/07] Interpretation of ==> in ACSL annotations. -* Value [2011/01/07] Fixed obscure crash that could happen during very imprecise analyses. -* Makefile [2011/01/06] Fixed bug #!660 related to a default Frama-C-compatible ocamlgraph installation under Cygwin - (i.e. in a Win32 path containing the ':' character) -- Value [2011/01/06] Improved precision of & + (i.e. in a Win32 path containing the ':' character). +- Value [2011/01/06] Improved precision of & operator. - Value [2011/01/05] Added check that denormals work correctly on host computer (correction would be affected otherwise). o! Kernel [2011/01/05] Remove Messages.disable_echo (can be done using - Log module) and Messages.depend (can be done using Messages.self) + Log module) and Messages.depend (can be done using Messages.self). - Value [2011/01/05] New alarm for float -> int cast overflows. -- Value [2011/01/04] Improved precision of | --* WP [2011/01/04] Fixed bug #702 on Coq output with large integers. +- Value [2011/01/04] Improved precision of | operator. ++* WP [2011/01/04] Fixed bug #702 on Coq output with large integers. -* Inout [2010/12/22] Return statement dependencies were forgotten in operational input computations. Fixed. o! Kernel [2010/12/21] Remove API function Messages.enable_collect: @@ -127,7 +583,7 @@ Open Source Release Carbon_20101202 ################################### --* WP [2010/12/16] Fixed bug #639: no more compilation to shared +-* WP [2010/12/16] Fixed bug #639: no more Coq compilation to shared directory. - WP [2010/12/16] Accessibility of all provers from gui. @@ -145,7 +601,6 @@ used) when configuring Frama-C. -* Value [2010/12/09] Fixed bug that could happen in programs casting address of floating-point type to address of integer type -- WP [2010/12/06] New WP plugin. o! Kernel [2010/12/07] Remove function Globals.has_entry_point. Use Globals.entry_point instead. -* Syntactic callgraph [2010/12/07] Fixed bug #!587: proper error message @@ -156,7 +611,7 @@ - Value [2010/12/03] Preliminary support for interpreting C type float as IEEE 754 single-precision. -* Value [2010/12/02] Emit proper ACSL alarm for overflowing - floating-point binary and unary operators. Fixes #259. + floating-point binary and unary operators. Fixed #259. -* Value [2010/12/02] Emit alarm for overflowing floating-point constants instead of crashing. - Value [2010/12/02] Emit alarm for uninitialized arguments to library @@ -204,8 +659,8 @@ and fixes issue in overloading resolution -* Value [2010/08/27] Fixed performance bug that could lead to "stack overflow" error during large analyses. --* Logic [2010/08/27] fixes #549 (Arrays in the logic) --* Cil [2010/08/27] fixes #542 (now raises parse error when +-* Logic [2010/08/27] Fixed #549 (Arrays in the logic) +-* Cil [2010/08/27] Fixed #542 (now raises parse error when C function call dot not provide correct number of arguments) - Value [2010/08/26] "assert(TODO)", used when a property to check in the analyzed code cannot be expressed as ACSL and the user should diff -Nru frama-c-20110201+carbon+dfsg/cil/CHANGES frama-c-20111001+nitrogen+dfsg/cil/CHANGES --- frama-c-20110201+carbon+dfsg/cil/CHANGES 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/CHANGES 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -CHANGES with respect to original Cil library - -a) Replaced custom pretty printers by module Format -b) All types of module Cil are declared in module Cil_types -c) Module Util renamed to Cilutil -d) Modified AST to support logic annotation -e) Some extension from cil/src/ext/ not yet ported. -f) Dataflow module modified (improved ?) -g) type instr contains only one intr not a list of instr. -h) Modified visitor to also visit logic annotations (see item d) diff -Nru frama-c-20110201+carbon+dfsg/cil/LICENSE frama-c-20111001+nitrogen+dfsg/cil/LICENSE --- frama-c-20110201+carbon+dfsg/cil/LICENSE 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -Copyright (c) 2001-2005, - George C. Necula - Scott McPeak - Wes Weimer - Ben Liblit -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -3. The names of the contributors may not be used to endorse or promote -products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -(See http://www.opensource.org/licenses/bsd-license.php) diff -Nru frama-c-20110201+carbon+dfsg/cil/ocamlutil/alpha.ml frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/alpha.ml --- frama-c-20110201+carbon+dfsg/cil/ocamlutil/alpha.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/alpha.ml 2011-10-10 08:40:09.000000000 +0000 @@ -88,7 +88,7 @@ (make_new: bool) : string * 'a = let prefix, suffix, (numsuffix: Big_int.big_int) = splitNameForAlpha ~lookupname in if debugAlpha prefix then - (Cilmsg.debug "Alpha worker: prefix=%s suffix=%s (%s) create=%b. " + (Kernel.debug "Alpha worker: prefix=%s suffix=%s (%s) create=%b. " prefix suffix (Big_int.string_of_big_int numsuffix) make_new); let newname, (olddata: 'a) = try @@ -96,7 +96,7 @@ let max, suffixes = !rc in (* We have seen this prefix *) if debugAlpha prefix then - Cilmsg.debug " Old max %s. Old suffixes: @[%a@]" + Kernel.debug " Old max %s. Old suffixes: @[%a@]" (Big_int.string_of_big_int max) (Pretty_utils.pp_list (fun fmt (s,_) -> Format.fprintf fmt "%s" s)) suffixes ; (* Save the undo info *) @@ -122,7 +122,7 @@ Big_int.succ_big_int max, newsuffix, l, (newsuffix, data) :: suffixes else max, suffix, data, suffixes - | _ -> (Cilmsg.fatal "Cil.alphaWorker") + | _ -> (Kernel.fatal "Cil.alphaWorker") end in rc := (newmax, newsuffixes); @@ -132,12 +132,12 @@ Some l -> l := AlphaAddedSuffix prefix :: !l | _ -> ()); H.add alphaTable prefix (ref (numsuffix, [ (suffix, data) ])); - if debugAlpha prefix then (Cilmsg.debug " First seen. "); + if debugAlpha prefix then (Kernel.debug " First seen. "); lookupname, data (* Return the original name *) end in if debugAlpha prefix then - (Cilmsg.debug " Res=: %s \n" newname (* d_loc oldloc *)); + (Kernel.debug " Res=: %s \n" newname (* d_loc oldloc *)); newname, olddata (* Strip the suffix. Return the prefix, the suffix (including the separator @@ -186,7 +186,7 @@ where := old | AlphaAddedSuffix name -> if debugAlpha name then - (Cilmsg.debug "Removing %s from alpha table\n" name); + (Kernel.debug "Removing %s from alpha table\n" name); H.remove alphaTable name) undolist diff -Nru frama-c-20110201+carbon+dfsg/cil/ocamlutil/cilutil.ml frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/cilutil.ml --- frama-c-20110201+carbon+dfsg/cil/ocamlutil/cilutil.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/cilutil.ml 2011-10-10 08:40:09.000000000 +0000 @@ -51,30 +51,6 @@ let swap f x y = f y x -(** Print a hash table *) -let docHash ?(sep=format_of_string ",@ ") entry fmt h = - Format.fprintf fmt "@[" ; - ignore - (H.fold - (fun key data next -> - if next then Format.fprintf fmt sep ; - entry fmt key data ; - true) - h false) ; - Format.fprintf fmt "@]" - -let hash_to_list (h: ('a, 'b) H.t) : ('a * 'b) list = - H.fold - (fun key data acc -> (key, data) :: acc) - h - [] - -let keys (h: ('a, 'b) H.t) : 'a list = - H.fold - (fun key _data acc -> key :: acc) - h - [] - let hash_copy_into (hfrom: ('a, 'b) H.t) (hto: ('a, 'b) H.t) : unit = H.clear hto; H.iter (H.add hto) hfrom @@ -111,14 +87,13 @@ let (ys,zs) = list_span p xs' in (x::ys,zs) else ([],xs) end -;; let rec list_rev_append revxs ys = begin match revxs with | [] -> ys | x::xs -> list_rev_append xs (x::ys) end -;; + let list_insert_by (cmp : 'a -> 'a -> int) (x : 'a) (xs : 'a list) : 'a list = let rec helper revhs ts = @@ -130,14 +105,12 @@ end in helper [] xs -;; let list_head_default (d : 'a) (xs : 'a list) : 'a = begin match xs with | [] -> d | x::_ -> x end -;; let rec list_iter3 f xs ys zs = begin match xs, ys, zs with @@ -145,7 +118,6 @@ | x::xs, y::ys, z::zs -> f x y z; list_iter3 f xs ys zs | _ -> invalid_arg "Util.list_iter3" end -;; let rec list_last = function | [] -> invalid_arg "Cilutil.list_last" @@ -158,7 +130,6 @@ | None::xs -> get_some_option_list xs | Some x::xs -> x :: get_some_option_list xs end -;; (* tail-recursive append: reverses xs twice *) let list_append (xs: 'a list) (ys: 'a list): 'a list = @@ -194,15 +165,12 @@ in loop (0, start) l - let list_init (len : int) (init_fun : int -> 'a) : 'a list = let rec loop n acc = if n < 0 then acc else loop (n-1) ((init_fun n)::acc) in loop (len - 1) [] -;; - let rec list_find_first (l: 'a list) (f: 'a -> 'b option) : 'b option = match l with @@ -482,14 +450,14 @@ match findConfiguration key with ConfInt i -> i | _ -> - Cilmsg.warning "Configuration %s is not an integer" key; + Kernel.warning "Configuration %s is not an integer" key; raise Not_found let findConfigurationFloat (key: string) : float = match findConfiguration key with ConfFloat i -> i | _ -> - Cilmsg.warning "Configuration %s is not a float" key; + Kernel.warning "Configuration %s is not a float" key; raise Not_found let useConfigurationInt (key: string) (f: int -> unit) = @@ -504,7 +472,7 @@ match findConfiguration key with ConfString s -> s | _ -> - Cilmsg.warning "Configuration %s is not a string" key; + Kernel.warning "Configuration %s is not a string" key; raise Not_found let useConfigurationString (key: string) (f: string -> unit) = @@ -516,7 +484,7 @@ match findConfiguration key with ConfBool b -> b | _ -> - Cilmsg.warning "Configuration %s is not a boolean" key; + Kernel.warning "Configuration %s is not a boolean" key; raise Not_found let useConfigurationBool (key: string) (f: bool -> unit) = @@ -527,7 +495,7 @@ match findConfiguration key with ConfList l -> l | _ -> - Cilmsg.warning "Configuration %s is not a list" key; + Kernel.warning "Configuration %s is not a list" key; raise Not_found let useConfigurationList (key: string) (f: configData list -> unit) = @@ -558,7 +526,7 @@ | ConfString s -> if String.contains s '"' then - Cilmsg.fatal "Guilib: configuration string contains quotes"; + Kernel.fatal "Guilib: configuration string contains quotes"; Buffer.add_char buff '"'; Buffer.add_string buff s; Buffer.add_char buff '"'; (* '"' *) @@ -573,14 +541,14 @@ in try let oc = open_out fname in - Cilmsg.debug "Saving configuration to %s@." (absoluteFilename fname); + Kernel.debug "Saving configuration to %s@." (absoluteFilename fname); H.iter (fun k c -> output_string oc (k ^ "\n"); output_string oc ((configToString c) ^ "\n")) configurationData; close_out oc with _ -> - Cilmsg.warning "Cannot open configuration file %s\n" fname + Kernel.warning "Cannot open configuration file %s\n" fname (** Make some regular expressions early *) @@ -603,14 +571,14 @@ let p = Str.matched_group 1 s in (try ConfInt (int_of_string p) with Failure "int_of_string" -> - Cilmsg.warning "Invalid integer configuration element %s" p; + Kernel.warning "Invalid integer configuration element %s" p; raise Not_found) end else if Str.string_match floatRegexp s !idx then begin idx := Str.match_end (); let p = Str.matched_group 1 s in (try ConfFloat (float_of_string p) with Failure "float_of_string" -> - Cilmsg.warning "Invalid float configuration element %s" p; + Kernel.warning "Invalid float configuration element %s" p; raise Not_found) end else if Str.string_match boolRegexp s !idx then begin idx := Str.match_end (); @@ -623,7 +591,7 @@ incr idx; let rec loop (acc: configData list) : configData list = if !idx >= l then begin - Cilmsg.warning "Non-terminated list in configuration %s" s; + Kernel.warning "Non-terminated list in configuration %s" s; raise Not_found end; if String.get s !idx = ']' then begin @@ -634,7 +602,7 @@ in ConfList (loop []) end else begin - Cilmsg.warning "Bad configuration element in a list: %s" + Kernel.warning "Bad configuration element in a list: %s" (String.sub s !idx (l - !idx)); raise Not_found end @@ -643,7 +611,7 @@ in (try let ic = open_in fname in - Cilmsg.debug "Loading configuration from %s@." (absoluteFilename fname); + Kernel.debug "Loading configuration from %s@." (absoluteFilename fname); (try while true do let k = input_line ic in @@ -695,7 +663,7 @@ let pp_map fmt map = IH.iter (fun i k -> Format.fprintf fmt " %s -> %d\n" k i) map in - Cilmsg.result "Current symbols\n%a" pp_map symbolNames ; + Kernel.result "Current symbols\n%a" pp_map symbolNames ; end let newSymbol (n: string) : symbol = @@ -715,7 +683,7 @@ (** Register a range of symbols. The mkname function will be invoked for * indices starting at 0 *) let registerSymbolRange (count: int) (mkname: int -> string) : symbol = - if count < 0 then Cilmsg.fatal "registerSymbolRange: invalid counter"; + if count < 0 then Kernel.fatal "registerSymbolRange: invalid counter"; let first = !nextSymbolId in nextSymbolId := !nextSymbolId + count; symbolRangeNaming := @@ -735,39 +703,9 @@ IH.add symbolNames id n; n with Not_found -> - Cilmsg.warning "Cannot find the name of symbol %d" id; + Kernel.warning "Cannot find the name of symbol %d" id; "symbol" ^ string_of_int id -(************************************************************************) - -(** {1 Int32 Operators} *) - -module Int32Op = struct - exception IntegerTooLarge - let to_int (i: int32) = - let i' = Int32.to_int i in (* Silently drop the 32nd bit *) - if i = Int32.of_int i' then i' - else raise IntegerTooLarge - - let (<%) = (fun x y -> (Int32.compare x y) < 0) - let (<=%) = (fun x y -> (Int32.compare x y) <= 0) - let (>%) = (fun x y -> (Int32.compare x y) > 0) - let (>=%) = (fun x y -> (Int32.compare x y) >= 0) - let (<>%) = (fun x y -> (Int32.compare x y) <> 0) - - let (+%) = Int32.add - let (-%) = Int32.sub - let ( *% ) = Int32.mul - let (/%) = Int32.div - let (~-%) = Int32.neg - - (* We cannot use the <<% because it trips camlp4 *) - let sll = fun i j -> Int32.shift_left i (to_int j) - let (>>%) = fun i j -> Int32.shift_right i (to_int j) - let (>>>%) = fun i j -> Int32.shift_right_logical i (to_int j) -end - - (*********************************************************************) let equals x1 x2 : bool = compare x1 x2 = 0 diff -Nru frama-c-20110201+carbon+dfsg/cil/ocamlutil/cilutil.mli frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/cilutil.mli --- frama-c-20110201+carbon+dfsg/cil/ocamlutil/cilutil.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/cilutil.mli 2011-10-10 08:40:09.000000000 +0000 @@ -48,13 +48,6 @@ open Cil_types open Pretty_utils -val docHash : - ?sep:sformat -> ('a,'b) formatter2 -> (('a, 'b) Hashtbl.t) formatter - -val hash_to_list: ('a, 'b) Hashtbl.t -> ('a * 'b) list - -val keys: ('a, 'b) Hashtbl.t -> 'a list - (** composition of functions *) val ($) : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c @@ -251,31 +244,6 @@ (************************************************************************) -(** {1 Int32 Operators} *) - -module Int32Op : sig - val (<%) : int32 -> int32 -> bool - val (<=%) : int32 -> int32 -> bool - val (>%) : int32 -> int32 -> bool - val (>=%) : int32 -> int32 -> bool - val (<>%) : int32 -> int32 -> bool - - val (+%) : int32 -> int32 -> int32 - val (-%) : int32 -> int32 -> int32 - val ( *% ) : int32 -> int32 -> int32 - val (/%) : int32 -> int32 -> int32 - val (~-%) : int32 -> int32 - - val sll : int32 -> int32 -> int32 - val (>>%) : int32 -> int32 -> int32 - val (>>>%) : int32 -> int32 -> int32 - - exception IntegerTooLarge - val to_int : int32 -> int -end - -(************************************************************************) - (** This has the semantics of (=) on OCaml 3.07 and earlier. It can handle cyclic values as long as a structure in the cycle has a unique name or id in some field that occurs before any fields that have cyclic @@ -368,20 +336,6 @@ open Format -(** @deprecated Boron-20100401 see pretty_list instead *) -val print_list : - (formatter -> unit -> unit) -> - (formatter -> 'a -> unit) -> formatter -> 'a list -> unit -val print_if: bool -> formatter -> (formatter->unit->unit) -> unit -val comma : formatter -> unit -> unit -val underscore : formatter -> unit -> unit -val semi : formatter -> unit -> unit -val space : formatter -> unit -> unit -val alt : formatter -> unit -> unit -val newline : formatter -> unit -> unit -val arrow : formatter -> unit -> unit -val nothing : formatter -> unit -> unit - (** [pretty sep print fmt l] pretty-prints the elements of [l] according to the formatting function [print] separated by [sep] on [fmt] *) diff -Nru frama-c-20110201+carbon+dfsg/cil/ocamlutil/growArray.ml frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/growArray.ml --- frama-c-20110201+carbon+dfsg/cil/ocamlutil/growArray.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/growArray.ml 2011-10-10 08:40:09.000000000 +0000 @@ -213,7 +213,7 @@ in (fun () -> if ga.gaFill != old.gaFill then - Cilmsg.fatal "restoreGA to an array with a different fill." ; + Kernel.fatal "restoreGA to an array with a different fill." ; ga.gaMaxInitIndex <- old.gaMaxInitIndex; for i = 0 to max_init_index ga do set ga i (getg old i) diff -Nru frama-c-20110201+carbon+dfsg/cil/ocamlutil/intmap.ml frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/intmap.ml --- frama-c-20110201+carbon+dfsg/cil/ocamlutil/intmap.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/intmap.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,199 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - -(* $Id: intmap.ml,v 1.4 2008-03-06 14:04:26 uid528 Exp $ *) - -(* specialized to integer keys by George Necula *) - -type 'a t = - Empty - | Node of 'a t * int * 'a * 'a t * int - -let height = function - Empty -> 0 - | Node(_,_,_,_,h) -> h - -let create l x d r = - let hl = height l and hr = height r in - Node(l, x, d, r, (if hl >= hr then hl + 1 else hr + 1)) - -let bal l x d r = - let hl = match l with Empty -> 0 | Node(_,_,_,_,h) -> h in - let hr = match r with Empty -> 0 | Node(_,_,_,_,h) -> h in - if hl > hr + 2 then begin - match l with - Empty -> invalid_arg "Map.bal" - | Node(ll, lv, ld, lr, _) -> - if height ll >= height lr then - create ll lv ld (create lr x d r) - else begin - match lr with - Empty -> invalid_arg "Map.bal" - | Node(lrl, lrv, lrd, lrr, _)-> - create (create ll lv ld lrl) lrv lrd (create lrr x d r) - end - end else if hr > hl + 2 then begin - match r with - Empty -> invalid_arg "Map.bal" - | Node(rl, rv, rd, rr, _) -> - if height rr >= height rl then - create (create l x d rl) rv rd rr - else begin - match rl with - Empty -> invalid_arg "Map.bal" - | Node(rll, rlv, rld, rlr, _) -> - create (create l x d rll) rlv rld (create rlr rv rd rr) - end - end else - Node(l, x, d, r, (if hl >= hr then hl + 1 else hr + 1)) - -let empty = Empty - -let is_empty = function Empty -> true | _ -> false - -let rec add x data = function - Empty -> - Node(Empty, x, data, Empty, 1) - | Node(l, v, d, r, h) -> - if x = v then - Node(l, x, data, r, h) - else if x < v then - bal (add x data l) v d r - else - bal l v d (add x data r) - -let rec find x = function - Empty -> - raise Not_found - | Node(l, v, d, r, _) -> - if x = v then d - else find x (if x < v then l else r) - -let rec mem x = function - Empty -> - false - | Node(l, v, d, r, _) -> - x = v || mem x (if x < v then l else r) - -let rec min_binding = function - Empty -> raise Not_found - | Node(Empty, x, d, r, _) -> (x, d) - | Node(l, x, d, r, _) -> min_binding l - -let rec remove_min_binding = function - Empty -> invalid_arg "Map.remove_min_elt" - | Node(Empty, x, d, r, _) -> r - | Node(l, x, d, r, _) -> bal (remove_min_binding l) x d r - -let merge t1 t2 = - match (t1, t2) with - (Empty, t) -> t - | (t, Empty) -> t - | (_, _) -> - let (x, d) = min_binding t2 in - bal t1 x d (remove_min_binding t2) - -let rec remove x = function - Empty -> - Empty - | Node(l, v, d, r, h) -> - if x = v then - merge l r - else if x < v then - bal (remove x l) v d r - else - bal l v d (remove x r) - -let rec iter f = function - Empty -> () - | Node(l, v, d, r, _) -> - iter f l; f v d; iter f r - -let rec map f = function - Empty -> Empty - | Node(l, v, d, r, h) -> Node(map f l, v, f d, map f r, h) - -let rec mapi f = function - Empty -> Empty - | Node(l, v, d, r, h) -> Node(mapi f l, v, f v d, mapi f r, h) - -let rec fold f m accu = - match m with - Empty -> accu - | Node(l, v, d, r, _) -> - fold f l (f v d (fold f r accu)) - -type 'a enumeration = End | More of int * 'a * 'a t * 'a enumeration - -let rec cons_enum m e = - match m with - Empty -> e - | Node(l, v, d, r, _) -> cons_enum l (More(v, d, r, e)) - -let compare cmp m1 m2 = - let rec compare_aux e1 e2 = - match (e1, e2) with - (End, End) -> 0 - | (End, _) -> -1 - | (_, End) -> 1 - | (More(v1, d1, r1, e1), More(v2, d2, r2, e2)) -> - if v1 <> v2 then if v1 < v2 then -1 else 1 else - let c = cmp d1 d2 in - if c <> 0 then c else - compare_aux (cons_enum r1 e1) (cons_enum r2 e2) -in compare_aux (cons_enum m1 End) (cons_enum m2 End) - -let equal cmp m1 m2 = - let rec equal_aux e1 e2 = - match (e1, e2) with - (End, End) -> true - | (End, _) -> false - | (_, End) -> false - | (More(v1, d1, r1, e1), More(v2, d2, r2, e2)) -> - v1 = v2 && cmp d1 d2 && - equal_aux (cons_enum r1 e1) (cons_enum r2 e2) -in equal_aux (cons_enum m1 End) (cons_enum m2 End) - -(** Some definitions for ML2Coq *) -let _ = ignore "coq: -(* Some definitions for ML2Coq *) - -" diff -Nru frama-c-20110201+carbon+dfsg/cil/ocamlutil/intmap.mli frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/intmap.mli --- frama-c-20110201+carbon+dfsg/cil/ocamlutil/intmap.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/ocamlutil/intmap.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - -(* $Id: intmap.mli,v 1.3 2008-03-06 14:04:26 uid528 Exp $ *) - -(** Specialized to integer keys by George Necula *) - -(** Association tables over ordered types. - - This module implements applicative association tables, also known as - finite maps or dictionaries, given a total ordering function - over the keys. - All operations over maps are purely applicative (no side-effects). - The implementation uses balanced binary trees, and therefore searching - and insertion take time logarithmic in the size of the map. -*) - -type (+'a) t - (** The type of maps from type [key] to type ['a]. *) - -val empty: 'a t - (** The empty map. *) - -val is_empty: 'a t -> bool - (** Test whether a map is empty or not. *) - -val add: int -> 'a -> 'a t -> 'a t - (** [add x y m] returns a map containing the same bindings as - [m], plus a binding of [x] to [y]. If [x] was already bound - in [m], its previous binding disappears. *) - -val find: int -> 'a t -> 'a - (** [find x m] returns the current binding of [x] in [m], - or raises [Not_found] if no such binding exists. *) - -val remove: int -> 'a t -> 'a t - (** [remove x m] returns a map containing the same bindings as - [m], except for [x] which is unbound in the returned map. *) - -val mem: int -> 'a t -> bool - (** [mem x m] returns [true] if [m] contains a binding for [x], - and [false] otherwise. *) - -val iter: (int -> 'a -> unit) -> 'a t -> unit - (** [iter f m] applies [f] to all bindings in map [m]. - [f] receives the key as first argument, and the associated value - as second argument. The bindings are passed to [f] in increasing - order with respect to the ordering over the type of the keys. - Only current bindings are presented to [f]: - bindings hidden by more recent bindings are not passed to [f]. *) - -val map: ('a -> 'b) -> 'a t -> 'b t - (** [map f m] returns a map with same domain as [m], where the - associated value [a] of all bindings of [m] has been - replaced by the result of the application of [f] to [a]. - The bindings are passed to [f] in increasing order - with respect to the ordering over the type of the keys. *) - -val mapi: (int -> 'a -> 'b) -> 'a t -> 'b t - (** Same as {!Map.S.map}, but the function receives as arguments both the - key and the associated value for each binding of the map. *) - -val fold: (int -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b - (** [fold f m a] computes [(f kN dN ... (f k1 d1 a)...)], - where [k1 ... kN] are the keys of all bindings in [m] - (in increasing order), and [d1 ... dN] are the associated data. *) - -val compare: ('a -> 'a -> int) -> 'a t -> 'a t -> int - (** Total ordering between maps. The first argument is a total ordering - used to compare data associated with equal keys in the two maps. *) - -val equal: ('a -> 'a -> bool) -> 'a t -> 'a t -> bool - (** [equal cmp m1 m2] tests whether the maps [m1] and [m2] are - equal, that is, contain equal keys and associate them with - equal data. [cmp] is the equality predicate used to compare - the data associated with the keys. *) - diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil_const.ml frama-c-20111001+nitrogen+dfsg/cil/src/cil_const.ml --- frama-c-20110201+carbon+dfsg/cil/src/cil_const.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil_const.ml 2011-10-10 08:40:09.000000000 +0000 @@ -55,11 +55,6 @@ let voidType = TVoid([]) -let d_loc fmt loc = - fprintf fmt "%s:%d" (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum - -let d_thisloc (fmt: formatter) : unit = d_loc fmt (CurrentLoc.get ()) - (* let generic_bug s fstring = let f fmt = @@ -69,31 +64,11 @@ kfprintf f err_formatter "@[%t: %s: " d_thisloc s *) -let error fstring = Cilmsg.abort ~current:true fstring -let fatal fstring = Cilmsg.fatal ~current:true fstring - -module Build_Counter(Name:sig val name:string end) : sig - val next: unit -> int - val reset: unit -> unit - val get: unit -> int - val self: State.t -end = struct - include State_builder.Zero_ref - (struct - let dependencies = [] - let name = Name.name - let kind = `Internal - end) - let next () = - let n = get () in - if n = -1 then fatal "Too many values for counter %s." Name.name; - set (succ n); - get () - let reset = clear -end +let error fstring = Kernel.abort ~current:true fstring +let fatal fstring = Kernel.fatal ~current:true fstring -module Vid = Build_Counter(struct let name = "vid" end) +module Vid = State_builder.SharedCounter(struct let name = "vid_counter" end) let set_vid v = let n = Vid.next () in diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil_const.mli frama-c-20111001+nitrogen+dfsg/cil/src/cil_const.mli --- frama-c-20110201+carbon+dfsg/cil/src/cil_const.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil_const.mli 2011-10-10 08:40:09.000000000 +0000 @@ -39,7 +39,7 @@ (* énergies alternatives). *) (**************************************************************************) -(** smart constructors for some data types *) +(** Smart constructors for some CIL data types *) open Cil_types val voidType: typ @@ -47,32 +47,14 @@ (** forward reference to current location (see {!Cil.CurrentLoc})*) module CurrentLoc: State_builder.Ref with type data = location -(** Pretty-print a location *) -val d_loc: Format.formatter -> location -> unit - -(** Pretty-print the [(CurrentLoc.get ())] *) -val d_thisloc: Format.formatter -> unit - (** Localized user-error with exception raised. *) val error: ('a, Format.formatter, unit, 'b) format4 -> 'a (** Localized internal-error with exception raised. *) val fatal: ('a, Format.formatter, unit, 'b) format4 -> 'a -(** creates a new counter that is project-aware. - TODO: internalize this module and put all its instances from Cil to here. -*) -module Build_Counter(Name:sig val name:string end) : sig - val next: unit -> int - val reset: unit -> unit - val get: unit -> int - val self: State.t -end module Vid: sig val next: unit -> int - val reset: unit -> unit - val get: unit -> int - val self: State.t end diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil_datatype.ml frama-c-20111001+nitrogen+dfsg/cil/src/cil_datatype.ml --- frama-c-20110201+carbon+dfsg/cil/src/cil_datatype.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil_datatype.ml 2011-10-10 08:40:09.000000000 +0000 @@ -40,6 +40,9 @@ (**************************************************************************) open Cil_types +let (=?=) = Extlib.compare_basic +let compare_list = Extlib.list_compare +let hash_list f = List.fold_left (fun acc d -> 65537 * acc + f d) 1 (**************************************************************************) (** {3 Generic builders for Cil datatypes} *) @@ -89,14 +92,6 @@ let compare_chain cmp x1 x2 next arg = let res = cmp x1 x2 in if res = 0 then next arg else res -let rec compare_list f xs ys = - match xs , ys with - | [], [] -> 0 - | [], _ :: _ -> -1 - | _ :: _, [] -> 1 - | x :: xs, y :: ys -> - let c = f x y in - if c <> 0 then c else compare_list f xs ys let rank_term = function | TConst _ -> 0 @@ -115,7 +110,6 @@ | Tlambda _ -> 12 | TDataCons _ -> 13 | Tif _ -> 14 - | Told _ -> 15 | Tat _ -> 16 | Tbase_addr _ -> 17 | Tblock_length _ -> 18 @@ -151,6 +145,24 @@ (** {3 C types} *) (**************************************************************************) +module Position = + Make_with_collections + (struct + type t = Lexing.position + let name = "Position" + let reprs = [ Lexing.dummy_pos ] + let compare: t -> t -> int = (=?=) + let hash = Hashtbl.hash + let copy = Datatype.identity + let equal: t -> t -> bool = ( = ) + let internal_pretty_code = Datatype.undefined + let pretty fmt pos = + Format.fprintf fmt "%s:%d char %d" + pos.Lexing.pos_fname pos.Lexing.pos_lnum + (pos.Lexing.pos_cnum - pos.Lexing.pos_bol) + let varname _ = "pos" + end) + module Location = struct let unknown = Lexing.dummy_pos, Lexing.dummy_pos let pretty_ref = ref (fun _ _ -> assert false) @@ -159,7 +171,7 @@ type t = location let name = "Location" let reprs = [ unknown ] - let compare: location -> location -> int = Extlib.compare_basic + let compare: location -> location -> int = (=?=) let hash (b, _e) = Hashtbl.hash (b.Lexing.pos_fname, b.Lexing.pos_lnum) let copy = Datatype.identity (* immutable strings *) let equal : t -> t -> bool = ( = ) @@ -208,7 +220,8 @@ let pretty_ref = ref (fun _ _ -> assert false) - include Make_with_collections + module Aux = + Make_with_collections (struct type t = stmt let name = "Stmt" @@ -234,6 +247,20 @@ let varname _ = "stmt" end) + include Aux + + let pretty_sid fmt s = Format.pp_print_int fmt s.sid + + module Hptset = struct + include Hptset.Make + (struct include Aux + let id s = s.sid + let pretty = pretty_sid end) + (struct let v = [ [ ] ] end) + (struct let l = [ ] (* This should be [Ast.self], but cannot be done + here *) end) + end + let rec loc_skind = function | Return(_, l) | Goto(_, l) | Break(l) | Continue l | If(_, _, _, l) | Switch (_, _, _, l) | Loop (_, _, l, _, _) @@ -293,9 +320,152 @@ | Kstmt st -> Stmt.loc st | Kglobal -> assert false + let kinstr_of_opt_stmt = function + | None -> Kglobal + | Some s -> Kstmt s + end -let pTypeSig : (typ -> typsig) ref = ref (fun _ -> assert false) +let index_attrparam = function + | AInt _ -> 0 + | AStr _ -> 1 + | ACons _ -> 2 + | ASizeOf _ -> 3 + | ASizeOfE _ -> 4 + | ASizeOfS _ -> 5 + | AAlignOf _ -> 6 + | AAlignOfE _ -> 7 + | AAlignOfS _ -> 8 + | AUnOp _ -> 9 + | ABinOp _ -> 10 + | ADot _ -> 11 + | AStar _ -> 12 + | AAddrOf _ -> 13 + | AIndex _ -> 14 + | AQuestion _ -> 15 + +let index_typ = function + | TVoid _ -> 0 + | TInt _ -> 1 + | TFloat _ -> 2 + | TPtr _ -> 3 + | TArray _ -> 4 + | TFun _ -> 5 + | TNamed _ -> 6 + | TComp _ -> 7 + | TEnum _ -> 8 + | TBuiltin_va_list _ -> 9 + +let pbitsSizeOf = ref (fun _ -> failwith "pbitsSizeOf not yet defined") +let ptypeAddAttributes = + ref (fun _ _ -> failwith "ptypedAddAttributes not yet defined") + +let rec compare_attribute a1 a2 = match a1, a2 with + | Attr (s1, l1), Attr (s2, l2) -> + compare_chain (=?=) s1 s2 (compare_attrparam_list l1) l2 + | AttrAnnot s1, AttrAnnot s2 -> s1 =?= s2 + | Attr _, AttrAnnot _ -> -1 + | AttrAnnot _, Attr _ -> 1 +and compare_attributes l1 l2 = compare_list compare_attribute l1 l2 +and compare_attrparam_list l1 l2 = + compare_list compare_attrparam l1 l2 +and compare_attrparam a1 a2 = match a1, a2 with + | AInt i1, AInt i2 -> i1 =?= i2 + | AStr s1, AStr s2 -> s1 =?= s2 + | ACons (s1, l1), ACons (s2, l2) -> + compare_chain (=?=) s1 s2 (compare_attrparam_list l1) l2 + | ASizeOf t1, ASizeOf t2 -> compare_type t1 t2 + | ASizeOfE p1, ASizeOfE p2 -> compare_attrparam p1 p2 + | ASizeOfS s1, ASizeOfS s2 -> compare_typsig s1 s2 + | AAlignOf t1, AAlignOf t2 -> compare_type t1 t2 + | AAlignOfE p1, AAlignOfE p2 -> compare_attrparam p1 p2 + | AAlignOfS s1, AAlignOfS s2 -> compare_typsig s1 s2 + | AUnOp (op1, a1), AUnOp (op2, a2) -> + compare_chain (=?=) op1 op2 (compare_attrparam a1) a2 + | ABinOp (op1, a1, a1'), ABinOp (op2, a2, a2') -> + compare_chain (=?=) op1 op2 + (compare_chain compare_attrparam a1 a2 (compare_attrparam a1')) a2' + | ADot (a1, s1), ADot (a2, s2) -> + compare_chain (=?=) s1 s2 (compare_attrparam a1) a2 + | AStar a1, AStar a2 + | AAddrOf a1, AAddrOf a2 -> compare_attrparam a1 a2 + | AIndex (a1, a1'), AIndex (a2, a2') -> + compare_chain compare_attrparam a1 a2 (compare_attrparam a1') a2' + | AQuestion (a1, a1', a1''), AQuestion (a2, a2', a2'') -> + compare_chain compare_attrparam a1 a2 + (compare_chain compare_attrparam a1' a2' (compare_attrparam a1'')) a2'' + | (AInt _ | AStr _ | ACons _ | ASizeOf _ | ASizeOfE _ | ASizeOfS _ | + AAlignOf _ | AAlignOfE _ | AAlignOfS _ | AUnOp _ | ABinOp _ | ADot _ | + AStar _ | AAddrOf _ | AIndex _ | AQuestion _ as a1), a2 -> + index_attrparam a1 - index_attrparam a2 +and compare_type t1 t2 = + if t1 == t2 then 0 + else + match t1, t2 with + | TVoid l1, TVoid l2 -> compare_attributes l1 l2 + | TInt (i1, l1), TInt (i2, l2) -> + compare_chain (=?=) i1 i2 (compare_attributes l1) l2 + | TFloat (f1, l1), TFloat (f2, l2) -> + compare_chain (=?=) f1 f2 (compare_attributes l1) l2 + | TPtr (t1, l1), TPtr (t2, l2) -> + compare_chain compare_type t1 t2 (compare_attributes l1) l2 + | TArray (t1', _, _, l1), TArray (t2', _, _, l2) -> + compare_chain (=?=) (!pbitsSizeOf t1) (!pbitsSizeOf t2) + (compare_chain compare_type t1' t2' (compare_attributes l1)) l2 + | TFun (r1, a1, v1, l1), TFun (r2, a2, v2, l2) -> + compare_chain compare_type r1 r2 + (compare_chain (=?=) v1 v2 + (compare_chain compare_arg_list a1 a2 + (compare_attributes l1))) l2 + | TNamed (t1, l1), TNamed (t2, l2) -> + compare_type + (if l1 == [] then t1.ttype else !ptypeAddAttributes l1 t1.ttype) + (if l2 == [] then t2.ttype else !ptypeAddAttributes l2 t2.ttype) + | TComp (c1, _, l1), TComp (c2, _, l2) -> + compare_chain (=?=) c1.ckey c2.ckey (compare_attributes l1) l2 + | TEnum (e1, l1), TEnum (e2, l2) -> + compare_chain (=?=) e1.ename e2.ename (compare_attributes l1) l2 + | TBuiltin_va_list l1, TBuiltin_va_list l2 -> compare_attributes l1 l2 + | (TVoid _ | TInt _ | TFloat _ | TPtr _ | TArray _ | TFun _ | TNamed _ | + TComp _ | TEnum _ | TBuiltin_va_list _ as a1), a2 -> + index_typ a1 - index_typ a2 + +and compare_typsig _t1 _t2 = Kernel.not_yet_implemented "Typsig comparison" +and compare_arg_list l1 l2 = + Extlib.opt_compare + (compare_list + (fun (n1, t1, l1) (n2, t2, l2) -> + compare_chain (=?=) n1 n2 + (compare_chain compare_type t1 t2 (compare_attributes l1)) l2 + )) l1 l2 + +let hash_attribute = function + | AttrAnnot s -> Hashtbl.hash s + | Attr (s, _) -> (* We do not hash attrparams. There is a recursivity problem + with typ, and the equal function will be complicated enough in itself *) + 3 * Hashtbl.hash s + 117 +let hash_attributes = hash_list hash_attribute + +let rec hash_type = function + | TVoid l -> Hashtbl.hash (hash_attributes l, 1) + | TInt (i, l) -> Hashtbl.hash (i, 2, hash_attributes l) + | TFloat (f, l) -> Hashtbl.hash (f, 3, hash_attributes l) + | TPtr (t, l) -> Hashtbl.hash (hash_type t, 4, hash_attributes l) + | TArray (t, _, { scache = Computed i}, l) -> + Hashtbl.hash (hash_type t, 5, i, hash_attributes l) + | TArray (t, _, { scache = _}, l) as tar -> + Hashtbl.hash (hash_type t, 5, !pbitsSizeOf tar, hash_attributes l) + | TFun (r, a, v, l) -> + Hashtbl.hash (hash_type r, 6, hash_args a, v, hash_attributes l) + | TNamed (ti, l) -> Hashtbl.hash (ti.tname, 7, hash_attributes l) + | TComp (c, _, l) -> Hashtbl.hash (c.ckey, 8, hash_attributes l) + | TEnum (e, l) -> Hashtbl.hash (e.ename, 9, hash_attributes l) + | TBuiltin_va_list l -> Hashtbl.hash (hash_attributes l, 10) +and hash_args = function + | None -> 11713 + | Some l -> + hash_list (fun (n, t, l) -> Hashtbl.hash (n, 17, hash_type t, hash_attributes l)) l + module Typ = struct let pretty_ref = ref (fun _ _ -> assert false) include Make_with_collections @@ -303,10 +473,9 @@ type t = typ let name = "Typ" let reprs = [ TVoid [] ] - let tid ty = !pTypeSig ty - let compare ty1 ty2 = Pervasives.compare (tid ty1) (tid ty2) - let hash ty1 = Hashtbl.hash (tid ty1) - let equal ty1 ty2 = tid ty1 = tid ty2 + let compare = compare_type + let hash = hash_type + let equal = Datatype.from_compare let copy = Datatype.undefined let internal_pretty_code = Datatype.undefined let pretty fmt t = !pretty_ref fmt t @@ -330,49 +499,50 @@ let equal v1 v2 = v1.tname = v2.tname end) -module Exp = - Make_with_collections +module Exp = struct + let dummy = { eid = -1; enode = Const (CStr ""); eloc = Location.unknown } + include Make_with_collections (struct include Datatype.Undefined type t = exp let name = "Exp" let reprs = - [ { eid = -1; enode = Const (CStr ""); eloc = Location.unknown } ] + [ dummy ] let compare e1 e2 = Datatype.Int.compare e1.eid e2.eid let hash e = Hashtbl.hash e.eid let equal e1 e2 = e1.eid = e2.eid end) +end module Varinfo = struct let pretty_ref = ref (fun _ _ -> assert false) let internal_pretty_code_ref = ref (fun _ _ _ -> assert false) - include Make_with_collections - (struct + let dummy = + { vname = ""; + vorig_name = ""; + vtype = TVoid []; + vattr = []; + vstorage = NoStorage; + vglob = false; + vdefined = false; + vformal = false; + vinline = false; + vdecl = Location.unknown; + vid = -1; + vaddrof = false; + vreferenced = false; + vgenerated = false; + vdescr = None; + vdescrpure = false; + vghost = false; + vlogic = false; + vlogic_var_assoc = None } + + module Aux = Make_with_collections + (struct type t = varinfo let name = "Varinfo" - let reprs = - List.map - (fun loc -> - { vname = ""; - vorig_name = ""; - vtype = TVoid []; - vattr = []; - vstorage = NoStorage; - vglob = false; - vdefined = false; - vformal = false; - vinline = false; - vdecl = loc; - vid = -1; - vaddrof = false; - vreferenced = false; - vgenerated = false; - vdescr = None; - vdescrpure = false; - vghost = false; - vlogic = false; - vlogic_var_assoc = None }) - Location.reprs + let reprs = [ dummy ] let compare v1 v2 = Datatype.Int.compare v1.vid v2.vid let hash v = v.vid let equal v1 v2 = v1.vid = v2.vid @@ -381,6 +551,21 @@ let pretty fmt v = !pretty_ref fmt v let varname v = "vi_" ^ v.vorig_name end) + let pretty_vname fmt v = Format.pp_print_string fmt v.vname + + include Aux + + let pretty_vid fmt v = Format.pp_print_int fmt v.vid + + module Hptset = struct + include Hptset.Make + (struct include Aux + let id v = v.vid + let pretty = pretty_vid end) + (struct let v = [ [ ] ] end) + (struct let l = [ ] (* Should morally be [Ast.self] *) end) + end + end module Block = struct @@ -460,6 +645,25 @@ let varname = Datatype.undefined end) +let rec equal_lval (h1, o1) (h2, o2) = + equal_lhost h1 h2 && equal_offset o1 o2 + +and equal_lhost h1 h2 = + match h1,h2 with + | Var v1, Var v2 -> Datatype.Int.equal v1.vid v2.vid + | Mem e1, Mem e2 -> Exp.equal e1 e2 + | (Var _ | Mem _), _-> false + +and equal_offset o1 o2 = + match o1,o2 with + | NoOffset, NoOffset -> true + | Field(f1,o1), Field(f2,o2) -> + Fieldinfo.equal f1 f2 && equal_offset o1 o2 + | Index(e1,o1), Index(e2,o2) -> + Exp.equal e1 e2 && equal_offset o1 o2 + | (NoOffset | Field _ | Index _), _ -> false + + let rec compare_lval (h1,o1) (h2,o2) = compare_chain compare_lhost h1 h2 (compare_offset o1) o2 @@ -481,6 +685,19 @@ | (Field _, Index _) -> 1 | ((Field _ | Index _), (NoOffset | Field _ )) -> -1 + +let rec hash_lval (h,o) = + Hashtbl.hash (hash_lhost h, hash_offset o) + +and hash_lhost = function + | Var v -> 17 + v.vid + | Mem e -> 13 + 5 * e.eid + +and hash_offset = function + | NoOffset -> 19 + | Field(f,o) -> Hashtbl.hash (Fieldinfo.hash f, hash_offset o) + | Index (e, o) -> Hashtbl.hash (e.eid, hash_offset o) + module Lval = struct let pretty_ref = ref (fun _ -> assert false) include Make_with_collections @@ -489,15 +706,32 @@ let name = "Lval" let reprs = List.map (fun v -> Var v, NoOffset) Varinfo.reprs let compare = compare_lval - let equal = Datatype.from_compare + let equal = equal_lval + let hash = hash_lval let copy = Datatype.undefined - let hash = Hashtbl.hash (* could be optimized *) let internal_pretty_code = Datatype.undefined let pretty fmt x = !pretty_ref fmt x let varname _ = "lv" end) end +module Offset = struct + let pretty_ref = ref (fun _ -> assert false) + include Make_with_collections + (struct + type t = offset + let name = "Offset" + let reprs = [NoOffset] + let compare = compare_offset + let equal = equal_offset + let hash = hash_offset + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty fmt x = !pretty_ref fmt x + let varname _ = "offs" + end) +end + (**************************************************************************) (** {3 ACSL types} *) (**************************************************************************) @@ -593,56 +827,30 @@ let varname = Datatype.undefined end) -module Global = struct - - include Make - (struct - type t = global - let name = "Global" - let reprs = [ GText "" ] - let internal_pretty_code = Datatype.undefined - let pretty = Datatype.undefined - let varname = Datatype.undefined - end) - - let loc = function - | GFun(_, l) - | GType(_, l) - | GEnumTag(_, l) - | GEnumTagDecl(_, l) - | GCompTag(_, l) - | GCompTagDecl(_, l) - | GVarDecl(_, _, l) - | GVar(_, _, l) - | GAsm(_, l) - | GPragma(_, l) - | GAnnot (_, l) -> l - | GText _ -> Location.unknown - -end - -module Global_annotation = struct - - include Make +module Logic_info = + Make_with_collections (struct - type t = global_annotation - let name = "Global_annotation" - let reprs = List.map (fun l -> Daxiomatic ("", [], l)) Location.reprs + type t = logic_info + let name = "Logic_info" + let reprs = + List.map + (fun v -> + { l_var_info = v; + l_labels = []; + l_tparams = []; + l_type = None; + l_profile = []; + l_body = LBnone }) + Logic_var.reprs + let compare i1 i2 = Logic_var.compare i1.l_var_info i2.l_var_info + let equal i1 i2 = Logic_var.equal i1.l_var_info i2.l_var_info + let hash i = Logic_var.hash i.l_var_info + let copy = Datatype.undefined let internal_pretty_code = Datatype.undefined let pretty = Datatype.undefined - let varname = Datatype.undefined + let varname _ = "logic_varinfo" end) - let loc = function - | Dfun_or_pred(_, loc) - | Daxiomatic(_, _, loc) - | Dtype (_, loc) - | Dlemma(_, _, _, _, _, loc) - | Dinvariant(_, loc) - | Dtype_annot(_, loc) -> loc - -end - module Enuminfo = Make_with_collections (struct @@ -654,7 +862,8 @@ ename = ""; eitems = []; eattr = []; - ereferenced = false } ] + ereferenced = false; + ekind = IInt; } ] let compare v1 v2 = String.compare v1.ename v2.ename let hash v = Hashtbl.hash v.ename let equal v1 v2 = v1.ename = v2.ename @@ -743,37 +952,13 @@ end) end -module Logic_info = - Make_with_collections - (struct - type t = logic_info - let name = "Logic_info" - let reprs = - List.map - (fun v -> - { l_var_info = v; - l_labels = []; - l_tparams = []; - l_type = None; - l_profile = []; - l_body = LBnone }) - Logic_var.reprs - let compare i1 i2 = Logic_var.compare i1.l_var_info i2.l_var_info - let equal i1 i2 = Logic_var.equal i1.l_var_info i2.l_var_info - let hash i = Logic_var.hash i.l_var_info - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let pretty = Datatype.undefined - let varname _ = "logic_varinfo" - end) - (* -------------------------------------------------------------------------- *) (* --- Comparison Over Terms --- *) (* -------------------------------------------------------------------------- *) let compare_constant c1 c2 = match c1, c2 with | CInt64(v1,k1,_), CInt64(v2,k2,_) -> - compare_chain Int64.compare v1 v2 (Extlib.compare_basic k1) k2 + compare_chain My_bigint.compare v1 v2 (Extlib.compare_basic k1) k2 | CStr s1, CStr s2 -> Datatype.String.compare s1 s2 | CWStr s1, CWStr s2 -> compare_list Datatype.Int64.compare s1 s2 | CChr c1, CChr c2 -> Datatype.Char.compare c1 c2 @@ -827,7 +1012,6 @@ if cq <> 0 then cq else compare_list compare_term ts1 ts2 | Tif(c1,a1,b1) , Tif(c2,a2,b2) -> compare_list compare_term [c1;a1;b1] [c2;a2;b2] - | Told t1 , Told t2 | Tbase_addr t1 , Tbase_addr t2 | Tblock_length t1 , Tblock_length t2 -> compare_term t1 t2 @@ -939,14 +1123,309 @@ List.map (fun t -> { it_id = -1; it_content = t}) Term.reprs let compare x y = Pervasives.compare x.it_id y.it_id let equal x y = x.it_id = y.it_id - let copy x = (* NB: Term.copy itself is undefined. *) - { it_id = x.it_id; - it_content = Term.copy x.it_content } + let copy x = + (* NB: Term.copy itself is undefined. *) + { it_id = x.it_id; it_content = Term.copy x.it_content } let hash x = x.it_id let internal_pretty_code = Datatype.undefined let pretty = Datatype.undefined let varname _ = "id_term" - end) + end) + +module Term_lhost = + Make_with_collections + (struct + type t = term_lhost + let name = "Term_lhost" + let reprs = + List.fold_left + (fun acc ty -> + List.fold_left + (fun acc t -> TMem t :: acc) + (TResult ty :: acc) + Term.reprs) + (List.map (fun lv -> TVar lv) Logic_var.reprs) + Typ.reprs + let compare = compare_tlhost + let equal = Datatype.from_compare + let hash = Hashtbl.hash + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = Datatype.undefined + let varname = Datatype.undefined + end) + +module Term_offset = + Make_with_collections + (struct + type t = term_offset + let name = "Term_offset" + let reprs = [ TNoOffset ] + let compare = compare_toffset + let equal = Datatype.from_compare + let hash = Hashtbl.hash + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = Datatype.undefined + let varname = Datatype.undefined + end) + +module Term_lval = + Datatype.Pair_with_collections + (Term_lhost) + (Term_offset) + (struct let module_name = "Cil_datatype.Term_lval" end) + +module Logic_label = + Make_with_collections + (struct + type t = logic_label + let name = "Logic_label" + let reprs = + (LogicLabel (None,"Pre")) + :: List.map (fun x -> StmtLabel (ref x)) Stmt.reprs + let compare = compare_logic_label + let equal = Datatype.from_compare + let copy = Datatype.undefined + let hash x = + match x with + StmtLabel r -> 2*(Stmt.hash !r) + | LogicLabel(_,l) -> 2*(Hashtbl.hash l) + 1 + let internal_pretty_code = Datatype.undefined + let pretty = Datatype.undefined + let varname _ = "logic_label" + end) + +module Global_annotation = struct + + include Make_with_collections + (struct + type t = global_annotation + let name = "Global_annotation" + let reprs = List.map (fun l -> Daxiomatic ("", [], l)) Location.reprs + let internal_pretty_code = Datatype.undefined + let pretty = Datatype.undefined + let varname = Datatype.undefined + + let rec compare g1 g2 = + match g1,g2 with + | Dfun_or_pred (l1,_), Dfun_or_pred(l2,_) -> Logic_info.compare l1 l2 + | Dfun_or_pred _,_ -> -1 + | _, Dfun_or_pred _ -> 1 + | Dvolatile (it1,_,_,_), Dvolatile(it2,_,_,_) -> + compare_list Identified_term.compare it1 it2 + | Dvolatile _,_ -> -1 + | _,Dvolatile _ -> 1 + | Daxiomatic (_,g1,_), Daxiomatic (_,g2,_) -> + (* ACSL does not require the name to be unique. *) + compare_list compare g1 g2 + | Daxiomatic _, _ -> -1 + | _, Daxiomatic _ -> 1 + | Dtype(t1,_), Dtype(t2,_) -> Logic_type_info.compare t1 t2 + | Dtype _, _ -> -1 + | _, Dtype _ -> 1 + | Dlemma (l1,_,_,_,_,_), Dlemma(l2,_,_,_,_,_) -> + Datatype.String.compare l1 l2 + | Dlemma _, _ -> -1 + | _, Dlemma _ -> 1 + | Dinvariant (l1,_), Dinvariant (l2,_) -> Logic_info.compare l1 l2 + | Dinvariant _, _ -> -1 + | _, Dinvariant _ -> 1 + | Dtype_annot(l1, _), Dtype_annot (l2, _) -> Logic_info.compare l1 l2 + | Dtype_annot _, _ -> -1 + | _, Dtype_annot _ -> 1 + | Dmodel_annot(l1,_), Dmodel_annot(l2,_) -> Logic_info.compare l1 l2 + + let equal = Datatype.from_compare + + let rec hash g = match g with + | Dfun_or_pred (l,_) -> 2 * Logic_info.hash l + | Dvolatile ([],_,_,(source,_)) -> + Kernel.fatal ~source "Empty location list for volatile annotation" + | Dvolatile (t::_,_,_,_) -> 3 * Identified_term.hash t + | Daxiomatic (_,[],_) -> 5 + (* Empty axiomatic is weird but authorized. *) + | Daxiomatic (_,g::_,_) -> 5 * hash g + | Dtype (t,_) -> 7 * Logic_type_info.hash t + | Dlemma(n,_,_,_,_,_) -> 11 * Datatype.String.hash n + | Dinvariant(l,_) -> 13 * Logic_info.hash l + | Dtype_annot(l,_) -> 17 * Logic_info.hash l + | Dmodel_annot(l,_) -> 19 * Logic_info.hash l + + let copy = Datatype.undefined + end) + + let loc = function + | Dfun_or_pred(_, loc) + | Daxiomatic(_, _, loc) + | Dtype (_, loc) + | Dlemma(_, _, _, _, _, loc) + | Dinvariant(_, loc) + | Dtype_annot(_, loc) -> loc + | Dmodel_annot(_, loc) -> loc + | Dvolatile(_, _, _, loc) -> loc + +end + +module Global = struct + + include Make_with_collections + (struct + type t = global + let name = "Global" + let reprs = [ GText "" ] + let internal_pretty_code = Datatype.undefined + let pretty = Datatype.undefined + let varname = Datatype.undefined + + let compare g1 g2 = + match g1, g2 with + | GType (t1,_), GType (t2,_) -> Typeinfo.compare t1 t2 + | GType _,_ -> -1 + | _, GType _ -> 1 + | GCompTag (t1,_), GCompTag(t2,_) -> Compinfo.compare t1 t2 + | GCompTag _,_ -> -1 + | _, GCompTag _ -> 1 + | GCompTagDecl (t1,_), GCompTagDecl(t2,_) -> Compinfo.compare t1 t2 + | GCompTagDecl _,_ -> -1 + | _,GCompTagDecl _ -> 1 + | GEnumTag(t1,_), GEnumTag(t2,_) -> Enuminfo.compare t1 t2 + | GEnumTag _,_ -> -1 + | _, GEnumTag _ -> 1 + | GEnumTagDecl(t1,_), GEnumTagDecl(t2,_) -> Enuminfo.compare t1 t2 + | GEnumTagDecl _, _ -> -1 + | _, GEnumTagDecl _ -> 1 + | GVarDecl (_,v1,_), GVarDecl(_,v2,_) -> Varinfo.compare v1 v2 + | GVarDecl _,_ -> -1 + | _,GVarDecl _ -> 1 + | GVar (v1,_,_), GVar (v2,_,_) -> Varinfo.compare v1 v2 + | GVar _,_ -> -1 + | _, GVar _ -> 1 + | GFun(f1,_), GFun(f2,_) -> Varinfo.compare f1.svar f2.svar + | GFun _, _ -> -1 + | _, GFun _ -> 1 + | GAsm (_,l1), GAsm(_,l2) -> Location.compare l1 l2 + | GAsm _, _ -> -1 + | _, GAsm _ -> 1 + | GPragma(_,l1), GPragma(_,l2) -> Location.compare l1 l2 + | GPragma _, _ -> -1 + | _, GPragma _ -> 1 + | GText s1, GText s2 -> Datatype.String.compare s1 s2 + | GText _, _ -> -1 + | _, GText _ -> 1 + | GAnnot (g1,_), GAnnot(g2,_) -> Global_annotation.compare g1 g2 + + let equal = Datatype.from_compare + + let hash g = match g with + GType (t,_) -> 2 * Typeinfo.hash t + | GCompTag (t,_) -> 3 * Compinfo.hash t + | GCompTagDecl (t,_) -> 5 * Compinfo.hash t + | GEnumTag (t,_) -> 7 * Enuminfo.hash t + | GEnumTagDecl(t,_) -> 11 * Enuminfo.hash t + | GVarDecl (_,v,_) -> 13 * Varinfo.hash v + | GVar (v,_,_) -> 17 * Varinfo.hash v + | GFun (f,_) -> 19 * Varinfo.hash f.svar + | GAsm (_,l) -> 23 * Location.hash l + | GText t -> 29 * Datatype.String.hash t + | GAnnot (g,_) -> 31 * Global_annotation.hash g + | GPragma(_,l) -> 37 * Location.hash l + + let copy = Datatype.undefined + end) + + let loc = function + | GFun(_, l) + | GType(_, l) + | GEnumTag(_, l) + | GEnumTagDecl(_, l) + | GCompTag(_, l) + | GCompTagDecl(_, l) + | GVarDecl(_, _, l) + | GVar(_, _, l) + | GAsm(_, l) + | GPragma(_, l) + | GAnnot (_, l) -> l + | GText _ -> Location.unknown + +end + +module Kf = struct + + let vi kf = match kf.fundec with + | Definition (d, _) -> d.svar + | Declaration (_,vi,_, _) -> vi + + let id kf = (vi kf).vid + + let set_formal_decls = ref (fun _ _ -> assert false) + + include Datatype.Make_with_collections + (struct + type t = kernel_function + let name = "Cil_datatype.Kf" + let structural_descr = Structural_descr.Abstract + let reprs = + let empty_spec = + { spec_behavior = []; + spec_variant = None; + spec_terminates = None; + spec_complete_behaviors = []; + spec_disjoint_behaviors = [] } + in + List.fold_left + (fun acc loc -> + List.fold_left + (fun acc b -> + List.fold_left + (fun acc vi -> + { fundec = + Definition + ({ svar = vi; + smaxid = 0; + slocals = []; + sformals = []; + sbody = b; + smaxstmtid = None; + sallstmts = []; + sspec = empty_spec }, + loc); + return_stmt = None; + spec = empty_spec } :: acc) + acc + Varinfo.reprs) + acc + Block.reprs) + [] + Location.reprs + let compare k1 k2 = Datatype.Int.compare (id k1) (id k2) + let equal k1 k2 = + if k1 != k2 then + (assert + (Kernel.verify + ((id k1) <> (id k2)) "Two kf for %a(%d)" + Varinfo.pretty (vi k1) (id k1)); + false) + else true + let hash = id + let copy = Datatype.undefined + let rehash x = match x.fundec with + | Definition _ | Declaration (_, _, None, _)-> x + | Declaration (_, v, Some args, _) -> + !set_formal_decls v args; + x + let get_name_kf kf = (vi kf).Cil_types.vname + let internal_pretty_code p_caller fmt kf = + Type.par p_caller Type.Call fmt + (fun fmt -> + Format.fprintf fmt "@[Globals.Functions.find_by_name@;%S@]" + (get_name_kf kf)) + let pretty fmt kf = Varinfo.pretty fmt (vi kf) + let mem_project = Datatype.never_any_project + let varname kf = "kf_" ^ (get_name_kf kf) + end) + +end module Code_annotation = struct @@ -974,24 +1453,21 @@ end -module Annotation_status = - Make +module Rooted_code_annotation = + Datatype.Make (struct - type t = annotation_status - let name = "Annotation_status" - let reprs = [ Unknown; Checked { emitter = ""; valid = False } ] - let internal_pretty_code = Datatype.undefined - let pretty fmt s = - match s with - | Unknown -> Format.fprintf fmt "No proof attempted" - | Checked {emitter=s; valid=True} -> - Format.fprintf fmt "Valid according to %s" s - | Checked {emitter=s; valid=False} -> - Format.fprintf fmt "NOT valid according to %s" s - | Checked {emitter=s; valid=Maybe} -> - Format.fprintf fmt - "Unknown (%s could not decide the status for this property)" s - let varname = Datatype.undefined + include Datatype.Serializable_undefined + type t = rooted_code_annotation + let name = "rooted_code_annotation" + let reprs = + List.map (fun c -> User c) Code_annotation.reprs + let compare x y = match x, y with + | User a, User b + | AI(_, a), AI(_, b) -> Code_annotation.compare a b + | User _, AI _ -> -1 + | AI _, User _ -> 1 + let equal = Datatype.from_compare + let mem_project = Datatype.never_any_project end) (**************************************************************************) @@ -1021,6 +1497,45 @@ (Datatype.Int) (struct let module_name = "Inthash" end) +module Localisation = + Datatype.Make + (struct + include Datatype.Serializable_undefined + type t = localisation + let name = "Localisation" + let reprs = [ VGlobal ] + let internal_pretty_code p_caller fmt loc = + let pp s kf = + Type.par p_caller Type.Call fmt + (fun fmt -> + Format.fprintf fmt "@[%s@;%a@]" + s + (Kf.internal_pretty_code Type.Call) + kf) + in + match loc with + | VGlobal -> Format.fprintf fmt "Cil_types.VGlobal" + | VLocal kf -> pp "Cil_types.VLocal" kf + | VFormal kf -> pp "Cil_types.VFormal" kf + let mem_project = Datatype.never_any_project + end) + +module Alarm = + Make_with_collections + (struct + type t = alarm + let name = "Alarm" + let reprs = [ Division_alarm ] + let compare = Pervasives.compare + let equal = (=) + let hash = Hashtbl.hash + let copy = Datatype.identity + let pretty = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project + end) + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil_datatype.mli frama-c-20111001+nitrogen+dfsg/cil/src/cil_datatype.mli --- frama-c-20110201+carbon+dfsg/cil/src/cil_datatype.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil_datatype.mli 2011-10-10 08:40:09.000000000 +0000 @@ -39,7 +39,7 @@ (* énergies alternatives). *) (**************************************************************************) -(** Datatypes of some useful Cil types. +(** Datatypes of some useful CIL types. @plugin development guide *) open Cil_types @@ -60,17 +60,19 @@ module Compinfo: S_with_collections with type t = compinfo module Enuminfo: S_with_collections with type t = enuminfo module Enumitem: S_with_collections with type t = enumitem -module Exp: S_with_collections with type t = exp + +(** Note that the equality is based on eid. For structural equality, use + {!Cil.compareExp} *) +module Exp: sig + include S_with_collections with type t = exp + val dummy: exp (** @since Nitrogen-20111001 *) +end + module Fieldinfo: S_with_collections with type t = fieldinfo module File: S with type t = file module Global: sig - include S with type t = global - val loc: t -> location -end - -module Global_annotation: sig - include S with type t = global_annotation + include S_with_collections with type t = global val loc: t -> location end @@ -83,11 +85,20 @@ module Kinstr: sig include S_with_collections with type t = kinstr + val kinstr_of_opt_stmt: stmt option -> kinstr + (** @since Nitrogen-20111001. *) + val loc: t -> location end module Label: S with type t = label +(** Single position in a file + @since Nitrogen-20111001 +*) +module Position: S_with_collections with type t = Lexing.position + +(** Cil locations *) module Location: sig include S_with_collections with type t = location val unknown: t @@ -95,38 +106,75 @@ val pretty_ref: (Format.formatter -> t -> unit) ref end +(** Note that the equality is based on eid (for sub-expressions). + For structural equality, use {!Cil.compareLval} *) module Lval: sig include S_with_collections with type t = lval (**/**) val pretty_ref: (Format.formatter -> t -> unit) ref end +(** Same remark as for Lval. For structural equality, use {!Cil.compareOffset} *) +module Offset: sig + include S_with_collections with type t = offset + (**/**) + val pretty_ref: (Format.formatter -> t -> unit) ref +end + module Stmt: sig include S_with_collections with type t = stmt + module Hptset: sig include Hptset.S with type elt = stmt + val self: State.t end val loc: t -> location + val pretty_sid: Format.formatter -> t -> unit + (** Pretty print the sid of the statement + @since Nitrogen-20111001 *) (**/**) val pretty_ref: (Format.formatter -> t -> unit) ref end -module Typ: S_with_collections with type t = typ -val pTypeSig : (typ -> typsig) ref +module Typ: sig + include S_with_collections with type t = typ +(**/**) +val pretty_ref: (Format.formatter -> t -> unit) ref +end +(**/**) (* Forward declarations from Cil *) +val pbitsSizeOf : (typ -> int) ref +val ptypeAddAttributes: (attributes -> typ -> typ) ref +(**/**) + module Typeinfo: S_with_collections with type t = typeinfo module Varinfo: sig include S_with_collections with type t = varinfo + module Hptset: sig include Hptset.S with type elt = t + val self: State.t end + val dummy: t + val pretty_vname: Format.formatter -> t -> unit + (** Pretty print the name of the varinfo. + @since Nitrogen-20111001 *) (**/**) val pretty_ref: (Format.formatter -> t -> unit) ref val internal_pretty_code_ref: (Type.precedence -> Format.formatter -> t -> unit) ref end +module Kf: sig + include Datatype.S_with_collections with type t = kernel_function + val vi: t -> varinfo + val id: t -> int + + (**/**) + val set_formal_decls: (varinfo -> varinfo list -> unit) ref +(**/**) +end + (**************************************************************************) (** {3 ACSL types} Sorted by alphabetic order. *) (**************************************************************************) -module Annotation_status: S with type t = annotation_status module Builtin_logic_info: S_with_collections with type t = builtin_logic_info module Code_annotation: sig @@ -134,13 +182,20 @@ val loc: t -> location option end +module Rooted_code_annotation: Datatype.S with type t = rooted_code_annotation + +module Global_annotation: sig + include S_with_collections with type t = global_annotation + val loc: t -> location +end + module Logic_ctor_info: S_with_collections with type t = logic_ctor_info module Logic_info: S_with_collections with type t = logic_info module Logic_type: sig include S_with_collections with type t = logic_type (**/**) - val pretty_ref: (Format.formatter -> t -> unit) ref + val pretty_ref: (Format.formatter -> t -> unit) ref end module Logic_type_info: S_with_collections with type t = logic_type_info @@ -149,15 +204,21 @@ module Logic_var: sig include S_with_collections with type t = logic_var (**/**) - val pretty_ref: (Format.formatter -> t -> unit) ref + val pretty_ref: (Format.formatter -> t -> unit) ref end module Term: sig include S_with_collections with type t = term (**/**) - val pretty_ref: (Format.formatter -> t -> unit) ref + val pretty_ref: (Format.formatter -> t -> unit) ref end +module Term_lhost: S_with_collections with type t = term_lhost +module Term_offset: S_with_collections with type t = term_offset +module Term_lval: S_with_collections with type t = term_lval + +module Logic_label: S_with_collections with type t = logic_label + (**************************************************************************) (** {3 Logic_ptree} Sorted by alphabetic order. *) @@ -171,6 +232,10 @@ module Int_hashtbl: Hashtbl with type 'a t = 'a Inthash.t and type key = int +module Localisation: Datatype.S with type t = localisation + +module Alarm: Datatype.S_with_collections with type t = alarm + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil.ml frama-c-20111001+nitrogen+dfsg/cil/src/cil.ml --- frama-c-20110201+carbon+dfsg/cil/src/cil.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil.ml 2011-10-10 08:40:09.000000000 +0000 @@ -39,7 +39,7 @@ (* énergies alternatives). *) (**************************************************************************) - (* +(* * CIL: An intermediate language for analyzing C progams. * * Version Tue Dec 12 15:21:52 PST 2000 @@ -47,16 +47,11 @@ * *) -open Escape -module S = Stack -open Cilutil open Cil_const open Logic_const -module Stack = S open Format -module C = Cilutil -module IH = Inthash open Cil_datatype +open Cil_types (* ************************************************************************* *) (* Reporting messages *) @@ -64,61 +59,19 @@ (* A reference to the current location *) module CurrentLoc = Cil_const.CurrentLoc +let () = Log.set_current_source (fun () -> fst (CurrentLoc.get ())) -let source (loc,_) = - { Log.src_line = loc.Lexing.pos_lnum ; Log.src_file = loc.Lexing.pos_fname } -let () = Log.set_current_source (fun () -> source (CurrentLoc.get())) - -let d_loc = Cil_const.d_loc +let d_loc fmt loc = + fprintf fmt "%s:%d" (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum let () = Cil_datatype.Location.pretty_ref := d_loc -let d_thisloc = Cil_const.d_thisloc - -let error fmt = Cilmsg.error ~current:true fmt -let abort fmt = Cilmsg.abort ~current:true fmt -let warning fmt = Cilmsg.warning ~current:true fmt -let warnOpt fmt = if Cilmsg.warnFlag then warning fmt else Log.nullprintf fmt -let fatal fmt = Cilmsg.fatal ~current:true fmt - -let error_loc (file,line) msg = - Cilmsg.error ~source:{Log.src_file=file;Log.src_line=line} msg - -let abort_loc (file,line) msg = - Cilmsg.abort ~source:{Log.src_file=file;Log.src_line=line} msg - -let err msg = error msg -let info msg = Cilmsg.result ~current:true msg - -let warn ?(once=false) msg = Cilmsg.warning ~once ~current:true msg -let log ?(once=false) msg = Cilmsg.result ~once msg - -(* ************************************************************************* *) -(* ************************************************************************* *) -(* ************************************************************************* *) - -let print_utf8 = ref true - -(* The module Cilversion is generated automatically by Makefile from - * information in configure.in *) -(* -let cilVersion = "1.3.6" -let cilVersionMajor = 1 -let cilVersionMinor = 3 -let cilVersionRevision = 6 -*) -(* -module Build_BoolRef(X:sig val default:bool val name:string end) = - State_builder.Ref - (struct include Datatype.Bool let default = X.default end) - (struct - let name = Project.State_builder.Name.make X.name - let dependencies = [] - end) - -module Build_False -*) +let d_thisloc (fmt: formatter) : unit = d_loc fmt (CurrentLoc.get ()) -open Cil_types +let register_ast_dependencies, add_ast_dependency = + let list_self = ref [] in + (fun ast -> + State_dependency_graph.Static.add_dependencies ~from:ast !list_self), + (fun state -> list_self := state :: !list_self) let voidType = Cil_const.voidType let intType = TInt(IInt,[]) @@ -141,6 +94,7 @@ let floatType = TFloat(FFloat, []) let longDoubleType = TFloat (FLongDouble, []) +let empty_size_cache () = {scache=Not_Computed} type theMachine = { mutable msvcMode: bool; (** Whether the pretty printer should @@ -155,7 +109,6 @@ mutable little_endian: bool; mutable char_is_unsigned: bool; mutable underscore_name: bool; - mutable enum_are_signed: bool; mutable stringLiteralType: typ; mutable upointType: typ; mutable wcharKind: ikind; (** An integer type that fits wchar_t. *) @@ -164,7 +117,8 @@ mutable ptrdiffType: typ; mutable typeOfSizeOf: typ; (** An integer type that is the type of sizeof. *) - mutable kindOfSizeOf: ikind } + mutable kindOfSizeOf: ikind; + } type lineDirectiveStyle = | LineComment (** Before every element, print the line @@ -193,7 +147,6 @@ little_endian = true; char_is_unsigned = false; underscore_name = true; - enum_are_signed = true; stringLiteralType = charPtrType; upointType = voidType; wcharKind = IChar; @@ -212,7 +165,6 @@ dst.little_endian <- src.little_endian; dst.char_is_unsigned <- src.char_is_unsigned; dst.underscore_name <- src.underscore_name; - dst.enum_are_signed <- src.enum_are_signed; dst.stringLiteralType <- src.stringLiteralType; dst.upointType <- src.upointType; dst.wcharKind <- src.wcharKind; @@ -257,7 +209,7 @@ (struct let name = "theMachine" let unique_name = name - let dependencies = [] + let dependencies = [ Kernel.Machdep.self ] let kind = `Internal end) @@ -289,12 +241,11 @@ let debugConstFold = false (* TODO: migrate that to Cil_const as well *) -module Sid = Cil_const.Build_Counter(struct let name = "sid" end) +module Sid = State_builder.SharedCounter(struct let name = "sid" end) -module Eid = Cil_const.Build_Counter(struct let name = "eid" end) +module Eid = State_builder.SharedCounter(struct let name = "eid" end) -let new_exp ~loc e = - { eloc = loc; eid = Eid.next (); enode = e } +let new_exp ~loc e = { eloc = loc; eid = Eid.next (); enode = e } let dummy_exp e = { eid = -1; enode = e; eloc = Cil_datatype.Location.unknown } @@ -348,11 +299,15 @@ (* A hack to allow forward reference of d_exp *) let pd_exp : (formatter -> exp -> unit) ref = - ref (fun _ -> Cilmsg.fatal "pd_exp not initialized") + ref (fun _ -> Kernel.fatal "pd_exp not initialized") let pd_global : (formatter -> global -> unit) ref = - ref (fun _ -> Cilmsg.fatal "pd_global not initialized") + ref (fun _ -> Kernel.fatal "pd_global not initialized") let pd_type: (formatter -> typ -> unit) ref = - ref (fun _ -> Cilmsg.fatal "pd_type not initialized") + ref (fun _ -> Kernel.fatal "pd_type not initialized") +let pd_ikind = + ref (fun _ -> Kernel.fatal "pd_ikind not initialized") +let pd_attr = + ref (fun _ -> Kernel.fatal "pd_attr not initialized") let default_behavior_name = "default!" let is_default_behavior b = b.b_name = default_behavior_name && b.b_assumes =[] @@ -363,10 +318,270 @@ with Not_found -> None let find_default_requires behaviors = - try - (List.find is_default_behavior behaviors).b_requires + try (List.find is_default_behavior behaviors).b_requires with Not_found -> [] +let rec stripInfo e = + match e.enode with + | Info(e',_) -> stripInfo e' + | _ -> e + +let rec addOffset (toadd: offset) (off: offset) : offset = + match off with + | NoOffset -> toadd + | Field(fid', offset) -> Field(fid', addOffset toadd offset) + | Index(e, offset) -> Index(e, addOffset toadd offset) + +let rec addTermOffset (toadd: term_offset) (off: term_offset) : term_offset = + match off with + | TNoOffset -> toadd + | TField(fid', offset) -> TField(fid', addTermOffset toadd offset) + | TIndex(t, offset) -> TIndex(t, addTermOffset toadd offset) + +let mkBlock (slst: stmt list) : block = + { battrs = []; bstmts = slst; blocals = []} + +let mkStmt ?(ghost=false) ?(valid_sid=false) (sk: stmtkind) : stmt = + { skind = sk; + labels = []; + (* It is better to create statements with a valid sid, so that they can + safely be used in tables. I only do it when performing Jessie + analysis, as other plugins rely on specific sid values for their tests + (e.g. slicing). *) + sid = if valid_sid then Sid.next () else -1; + succs = []; preds = []; + ghost = ghost} + + let stmt_of_instr_list ?(loc=Location.unknown) = function + | [] -> Instr (Skip loc) + | [i] -> Instr i + | il -> + let b = mkBlock (List.map (fun i -> mkStmt (Instr i)) il) in + match b.bstmts with + | [] -> Instr (Skip loc) + | [s] when b.battrs = [] -> s.skind + | _ -> Block b + + (**** Utility functions ******) + (** Construct sorted lists of attributes ***) + let attributeName = function Attr(a, _) | AttrAnnot a -> a + + let addAttribute + (Attr(an, _) | AttrAnnot an as a: attribute) (al: attributes) = + let rec insertSorted = function + [] -> [a] + | ((Attr(an0, _) | AttrAnnot an0 as a0) :: rest) as l -> + if an < an0 then a :: l + else if Cilutil.equals a a0 then l (* Do not add if already in there *) + else a0 :: insertSorted rest (* Make sure we see all attributes with + * this name *) + in + insertSorted al + + (** The second attribute list is sorted *) + let addAttributes al0 (al: attributes) : attributes = + if al0 == [] then al else + List.fold_left (fun acc a -> addAttribute a acc) al al0 + + let dropAttribute (an: string) (al: attributes) = + List.filter (fun a -> attributeName a <> an) al + + let dropAttributes (anl: string list) (al: attributes) = + List.fold_left (fun acc an -> dropAttribute an acc) al anl + + let hasAttribute (s: string) (al: attribute list) : bool = + List.exists (fun a -> attributeName a = s) al + + let filterAttributes (s: string) (al: attribute list) : attribute list = + List.filter (fun a -> attributeName a = s) al + + let findAttribute (s: string) (al: attribute list) : attrparam list = + List.fold_left + (fun acc -> function + | Attr (an, param) when an = s -> param @ acc + | _ -> acc) + [] al + + let rec typeAttrs = function + TVoid a -> a + | TInt (_, a) -> a + | TFloat (_, a) -> a + | TNamed (t, a) -> addAttributes a (typeAttrs t.ttype) + | TPtr (_, a) -> a + | TArray (_, _, _,a) -> a + | TComp (comp, _, a) -> addAttributes comp.cattr a + | TEnum (enum, a) -> addAttributes enum.eattr a + | TFun (_, _, _, a) -> a + | TBuiltin_va_list a -> a + + let typeAttr = function + | TVoid a + | TInt (_, a) + | TFloat (_, a) + | TNamed (_, a) + | TPtr (_, a) + | TArray (_, _, _, a) + | TComp (_, _, a) + | TEnum (_, a) + | TFun (_, _, _, a) + | TBuiltin_va_list a -> a + + let setTypeAttrs t a = + match t with + TVoid _ -> TVoid a + | TInt (i, _) -> TInt (i, a) + | TFloat (f, _) -> TFloat (f, a) + | TNamed (t, _) -> TNamed(t, a) + | TPtr (t', _) -> TPtr(t', a) + | TArray (t', l, s, _) -> TArray(t', l, s, a) + | TComp (comp, s, _) -> TComp (comp, s, a) + | TEnum (enum, _) -> TEnum (enum, a) + | TFun (r, args, v, _) -> TFun(r,args,v,a) + | TBuiltin_va_list _ -> TBuiltin_va_list a + + let typeAddAttributes a0 t = + begin + match a0 with + | [] -> + (* no attributes, keep same type *) + t + | _ -> + (* anything else: add a0 to existing attributes *) + let add (a: attributes) = addAttributes a0 a in + match t with + TVoid a -> TVoid (add a) + | TInt (ik, a) -> TInt (ik, add a) + | TFloat (fk, a) -> TFloat (fk, add a) + | TEnum (enum, a) -> TEnum (enum, add a) + | TPtr (t, a) -> TPtr (t, add a) + | TArray (t, l, s, a) -> TArray (t, l, s, add a) + | TFun (t, args, isva, a) -> TFun(t, args, isva, add a) + | TComp (comp, s, a) -> TComp (comp, s, add a) + | TNamed (t, a) -> TNamed (t, add a) + | TBuiltin_va_list a -> TBuiltin_va_list (add a) + end + let () = ptypeAddAttributes := typeAddAttributes + + let typeRemoveAttributes (anl: string list) t = + let drop (al: attributes) = dropAttributes anl al in + match t with + TVoid a -> TVoid (drop a) + | TInt (ik, a) -> TInt (ik, drop a) + | TFloat (fk, a) -> TFloat (fk, drop a) + | TEnum (enum, a) -> TEnum (enum, drop a) + | TPtr (t, a) -> TPtr (t, drop a) + | TArray (t, l, s, a) -> TArray (t, l, s, drop a) + | TFun (t, args, isva, a) -> TFun(t, args, isva, drop a) + | TComp (comp, s, a) -> TComp (comp, s, drop a) + | TNamed (t, a) -> TNamed (t, drop a) + | TBuiltin_va_list a -> TBuiltin_va_list (drop a) + + let unrollType (t: typ) : typ = + let rec withAttrs (al: attributes) (t: typ) : typ = + match t with + TNamed (r, a') -> withAttrs (addAttributes al a') r.ttype + | x -> typeAddAttributes al x + in + withAttrs [] t + + let isFunctionType t = + match unrollType t with + TFun _ -> true + | _ -> false + + (* Make a varinfo. Used mostly as a helper function below *) + let makeVarinfo ?(logic=false) ?(generated=true) global formal name typ = + (* Strip const from type for locals *) + let vi = + { vorig_name = name; + vname = name; + vid = -1; + vglob = global; + vdefined = false; + vformal = formal; + vgenerated = generated; + vtype = if formal || global then typ + else typeRemoveAttributes ["const"] typ; + vdecl = Location.unknown; + vinline = false; + vattr = []; + vstorage = NoStorage; + vaddrof = false; + vreferenced = false; + vdescr = None; + vdescrpure = true; + vghost = false; + vlogic = logic; + vlogic_var_assoc = None + } + in + set_vid vi; + vi + + module FormalsDecl = + State_builder.Hashtbl + (Varinfo.Hashtbl) + (Datatype.List(Varinfo)) + (struct + let name = "FormalsDecl" + let dependencies = [] (* depends on Ast.self; see below *) + let size = 47 + let kind = `Internal + end) + + let selfFormalsDecl = FormalsDecl.self + let () = add_ast_dependency selfFormalsDecl + + let makeFormalsVarDecl (n,t,a) = + let vi = makeVarinfo ~generated:false false true n t in + vi.vattr <- a; + vi + + let setFormalsDecl vi typ = + match unrollType typ with + | TFun(_, Some args, _, _) -> + FormalsDecl.replace vi (List.map makeFormalsVarDecl args) + | TFun(_,None,_,_) -> () + | _ -> error + "trying to assigns formal parameters to an object which is not a function prototype" + + let getFormalsDecl vi = FormalsDecl.find vi + + let unsafeSetFormalsDecl vi args = + FormalsDecl.replace vi args + + let () = Cil_datatype.Kf.set_formal_decls := unsafeSetFormalsDecl + +(* Set the formals and re-create the function name based on the information*) + let setFormals (f: fundec) (forms: varinfo list) = + unsafeSetFormalsDecl f.svar forms; + List.iter (fun v -> v.vformal <- true) forms; + f.sformals <- forms; (* Set the formals *) + match unrollType f.svar.vtype with + TFun(rt, _, isva, fa) -> + f.svar.vtype <- + TFun(rt, + Some (List.map (fun a -> (a.vname, a.vtype, a.vattr)) forms), + isva, fa) + | _ -> + Kernel.abort "Set formals. %s does not have function type" f.svar.vname + + let empty_funspec () = + { spec_behavior = []; + spec_variant = None; + spec_terminates = None; + spec_complete_behaviors = []; + spec_disjoint_behaviors = [] } + + let is_empty_funspec (spec : funspec) = + spec.spec_behavior = [] && + spec.spec_variant = None && spec.spec_terminates = None && + spec.spec_complete_behaviors = [] && spec.spec_disjoint_behaviors = [] + +let is_empty_behavior b = + b.b_assumes = [] && b.b_requires = [] && b.b_post_cond = [] && + b.b_assigns = WritesAny && b.b_extended = [] + (** Different visiting actions. 'a will be instantiated with [exp], [instr], etc. @see Plugin Development Guide *) @@ -411,6 +626,7 @@ get_logic_info: logic_info -> logic_info; get_logic_type_info: logic_type_info -> logic_type_info; get_logic_var: logic_var -> logic_var; + get_kernel_function: kernel_function -> kernel_function; (* get the original value tied to a copy *) get_original_stmt: stmt -> stmt; get_original_compinfo: compinfo -> compinfo; @@ -422,6 +638,7 @@ get_original_logic_info: logic_info -> logic_info; get_original_logic_type_info: logic_type_info -> logic_type_info; get_original_logic_var: logic_var -> logic_var; + get_original_kernel_function: kernel_function -> kernel_function; (* change a binding... use with care *) set_stmt: stmt -> stmt -> unit; set_compinfo: compinfo -> compinfo -> unit; @@ -433,6 +650,7 @@ set_logic_info: logic_info -> logic_info -> unit; set_logic_type_info: logic_type_info -> logic_type_info -> unit; set_logic_var: logic_var -> logic_var -> unit; + set_kernel_function: kernel_function -> kernel_function -> unit; (* change a reference... use with care *) set_orig_stmt: stmt -> stmt -> unit; set_orig_compinfo: compinfo -> compinfo -> unit; @@ -444,6 +662,7 @@ set_orig_logic_info: logic_info -> logic_info -> unit; set_orig_logic_type_info: logic_type_info -> logic_type_info -> unit; set_orig_logic_var: logic_var -> logic_var -> unit; + set_orig_kernel_function: kernel_function -> kernel_function -> unit; (* copy fields that can referenced in other places of the AST*) memo_stmt: stmt -> stmt; memo_varinfo: varinfo -> varinfo; @@ -455,6 +674,7 @@ memo_logic_type_info: logic_type_info -> logic_type_info; memo_fieldinfo: fieldinfo -> fieldinfo; memo_logic_var: logic_var -> logic_var; + memo_kernel_function: kernel_function -> kernel_function; (* is the behavior a copy behavior *) is_copy_behavior: bool; (* reset memoizing tables *) @@ -468,10 +688,13 @@ reset_behavior_fieldinfo: unit -> unit; reset_behavior_stmt: unit -> unit; reset_logic_var: unit -> unit; + reset_behavior_kernel_function: unit -> unit } let is_copy_behavior b = b.is_copy_behavior +let memo_kernel_function b = b.memo_kernel_function + let reset_behavior_varinfo b = b.reset_behavior_varinfo () let reset_behavior_compinfo b = b.reset_behavior_compinfo () let reset_behavior_enuminfo b = b.reset_behavior_enuminfo () @@ -482,6 +705,7 @@ let reset_behavior_fieldinfo b = b.reset_behavior_fieldinfo () let reset_behavior_stmt b = b.reset_behavior_stmt () let reset_logic_var b = b.reset_logic_var () +let reset_behavior_kernel_function b = b.reset_behavior_kernel_function () let get_varinfo b = b.get_varinfo let get_compinfo b = b.get_compinfo @@ -493,6 +717,7 @@ let get_logic_info b = b.get_logic_info let get_logic_type_info b = b.get_logic_type_info let get_logic_var b = b.get_logic_var +let get_kernel_function b = b.get_kernel_function let get_original_varinfo b = b.get_original_varinfo let get_original_compinfo b = b.get_original_compinfo @@ -504,6 +729,7 @@ let get_original_logic_info b = b.get_original_logic_info let get_original_logic_type_info b = b.get_original_logic_type_info let get_original_logic_var b = b.get_original_logic_var +let get_original_kernel_function b = b.get_original_kernel_function let set_varinfo b = b.set_varinfo let set_compinfo b = b.set_compinfo @@ -515,6 +741,7 @@ let set_logic_info b = b.set_logic_info let set_logic_type_info b = b.set_logic_type_info let set_logic_var b = b.set_logic_var +let set_kernel_function b = b.set_kernel_function let set_orig_varinfo b = b.set_orig_varinfo let set_orig_compinfo b = b.set_orig_compinfo @@ -526,157 +753,219 @@ let set_orig_logic_info b = b.set_orig_logic_info let set_orig_logic_type_info b = b.set_orig_logic_type_info let set_orig_logic_var b = b.set_orig_logic_var +let set_orig_kernel_function b= b.set_orig_kernel_function -let inplace_visit () = - { cfile = (fun x -> x); - get_compinfo = (fun x -> x); - get_fieldinfo = (fun x -> x); - get_enuminfo = (fun x -> x); - get_enumitem = (fun x -> x); - get_typeinfo = (fun x -> x); - get_varinfo = (fun x -> x); - get_logic_var = (fun x -> x); - get_stmt = (fun x -> x); - get_logic_info = (fun x -> x); - get_logic_type_info = (fun x -> x); - get_original_compinfo = (fun x -> x); - get_original_fieldinfo = (fun x -> x); - get_original_enuminfo = (fun x -> x); - get_original_enumitem = (fun x -> x); - get_original_typeinfo = (fun x -> x); - get_original_varinfo = (fun x -> x); - get_original_logic_var = (fun x -> x); - get_original_stmt = (fun x -> x); - get_original_logic_info = (fun x -> x); - get_original_logic_type_info = (fun x -> x); - cinitinfo = (fun x -> x); - cfundec = (fun x -> x); - cblock = (fun x -> x); - cfunspec = (fun x -> x); - cfunbehavior = (fun x -> x); +let id x = x +let alphabetaunit _ _ = () +let alphabetabeta _ x = x +let alphabetafalse _ _ = false +let unitunit: unit -> unit = id +let alphatrue _ = true +let alphaunit _ = () + +let inplace_visit = + fun () -> + { cfile = id; + get_compinfo = id; + get_fieldinfo = id; + get_enuminfo = id; + get_enumitem = id; + get_typeinfo = id; + get_varinfo = id; + get_logic_var = id; + get_stmt = id; + get_logic_info = id; + get_logic_type_info = id; + get_kernel_function = id; + get_original_compinfo = id; + get_original_fieldinfo = id; + get_original_enuminfo = id; + get_original_enumitem = id; + get_original_typeinfo = id; + get_original_varinfo = id; + get_original_logic_var = id; + get_original_stmt = id; + get_original_logic_info = id; + get_original_logic_type_info = id; + get_original_kernel_function = id; + cinitinfo = id; + cfundec = id; + cblock = id; + cfunspec = id; + cfunbehavior = id; is_copy_behavior = false; - memo_varinfo = (fun x -> x); - memo_compinfo = (fun x -> x); - memo_enuminfo = (fun x -> x); - memo_enumitem = (fun x -> x); - memo_typeinfo = (fun x -> x); - memo_logic_info = (fun x -> x); - memo_logic_type_info = (fun x -> x); - memo_stmt = (fun x -> x); - memo_fieldinfo = (fun x -> x); - memo_logic_var = (fun x -> x); - set_varinfo = (fun _ _ -> ()); - set_compinfo = (fun _ _ -> ()); - set_enuminfo = (fun _ _ -> ()); - set_enumitem = (fun _ _ -> ()); - set_typeinfo = (fun _ _ -> ()); - set_logic_info = (fun _ _ -> ()); - set_logic_type_info = (fun _ _ -> ()); - set_stmt = (fun _ _ -> ()); - set_fieldinfo = (fun _ _ -> ()); - set_logic_var = (fun _ _ -> ()); - set_orig_varinfo = (fun _ _ -> ()); - set_orig_compinfo = (fun _ _ -> ()); - set_orig_enuminfo = (fun _ _ -> ()); - set_orig_enumitem = (fun _ _ -> ()); - set_orig_typeinfo = (fun _ _ -> ()); - set_orig_logic_info = (fun _ _ -> ()); - set_orig_logic_type_info = (fun _ _ ->()); - set_orig_stmt = (fun _ _ -> ()); - set_orig_fieldinfo = (fun _ _ -> ()); - set_orig_logic_var = (fun _ _ -> ()); - reset_behavior_varinfo = (fun () -> ()); - reset_behavior_compinfo = (fun () -> ()); - reset_behavior_enuminfo = (fun () -> ()); - reset_behavior_enumitem = (fun () -> ()); - reset_behavior_typeinfo = (fun () -> ()); - reset_behavior_logic_info = (fun () -> ()); - reset_behavior_logic_type_info = (fun () -> ()); - reset_behavior_fieldinfo = (fun () -> ()); - reset_behavior_stmt = (fun () -> ()); - reset_logic_var = (fun () -> ()); + memo_varinfo = id; + memo_compinfo = id; + memo_enuminfo = id; + memo_enumitem = id; + memo_typeinfo = id; + memo_logic_info = id; + memo_logic_type_info = id; + memo_stmt = id; + memo_fieldinfo = id; + memo_logic_var = id; + memo_kernel_function = id; + set_varinfo = alphabetaunit; + set_compinfo = alphabetaunit; + set_enuminfo = alphabetaunit; + set_enumitem = alphabetaunit; + set_typeinfo = alphabetaunit; + set_logic_info = alphabetaunit; + set_logic_type_info = alphabetaunit; + set_stmt = alphabetaunit; + set_fieldinfo = alphabetaunit; + set_logic_var = alphabetaunit; + set_kernel_function = alphabetaunit; + set_orig_varinfo = alphabetaunit; + set_orig_compinfo = alphabetaunit; + set_orig_enuminfo = alphabetaunit; + set_orig_enumitem = alphabetaunit; + set_orig_typeinfo = alphabetaunit; + set_orig_logic_info = alphabetaunit; + set_orig_logic_type_info = alphabetaunit; + set_orig_stmt = alphabetaunit; + set_orig_fieldinfo = alphabetaunit; + set_orig_logic_var = alphabetaunit; + set_orig_kernel_function = alphabetaunit; + reset_behavior_varinfo = unitunit; + reset_behavior_compinfo = unitunit; + reset_behavior_enuminfo = unitunit; + reset_behavior_enumitem = unitunit; + reset_behavior_typeinfo = unitunit; + reset_behavior_logic_info = unitunit; + reset_behavior_logic_type_info = unitunit; + reset_behavior_fieldinfo = unitunit; + reset_behavior_stmt = unitunit; + reset_logic_var = unitunit; + reset_behavior_kernel_function = unitunit; } let copy_visit () = - let varinfos = IH.create 103 in - let compinfos = IH.create 17 in - let enuminfos = Hashtbl.create 17 in - let enumitems = Hashtbl.create 17 in - let typeinfos = Hashtbl.create 17 in - let logic_infos = IH.create 17 in - let logic_type_infos = Hashtbl.create 17 in - let fieldinfos = Hashtbl.create 17 in - let stmts = IH.create 103 in - let logic_vars = IH.create 17 in - let orig_varinfos = IH.create 103 in - let orig_compinfos = IH.create 17 in - let orig_enuminfos = Hashtbl.create 17 in - let orig_enumitems = Hashtbl.create 17 in - let orig_typeinfos = Hashtbl.create 17 in - let orig_logic_infos = IH.create 17 in - let orig_logic_type_infos = Hashtbl.create 17 in - let orig_fieldinfos = Hashtbl.create 17 in - let orig_stmts = IH.create 103 in - let orig_logic_vars = IH.create 17 in + let varinfos = Cil_datatype.Varinfo.Hashtbl.create 103 in + let compinfos = Cil_datatype.Compinfo.Hashtbl.create 17 in + let enuminfos = Cil_datatype.Enuminfo.Hashtbl.create 17 in + let enumitems = Cil_datatype.Enumitem.Hashtbl.create 17 in + let typeinfos = Cil_datatype.Typeinfo.Hashtbl.create 17 in + let logic_infos = Cil_datatype.Logic_info.Hashtbl.create 17 in + let logic_type_infos = Cil_datatype.Logic_type_info.Hashtbl.create 17 in + let fieldinfos = Cil_datatype.Fieldinfo.Hashtbl.create 17 in + let stmts = Cil_datatype.Stmt.Hashtbl.create 103 in + let logic_vars = Cil_datatype.Logic_var.Hashtbl.create 17 in + let kernel_functions = Cil_datatype.Kf.Hashtbl.create 17 in + let orig_varinfos = Cil_datatype.Varinfo.Hashtbl.create 103 in + let orig_compinfos = Cil_datatype.Compinfo.Hashtbl.create 17 in + let orig_enuminfos = Cil_datatype.Enuminfo.Hashtbl.create 17 in + let orig_enumitems = Cil_datatype.Enumitem.Hashtbl.create 17 in + let orig_typeinfos = Cil_datatype.Typeinfo.Hashtbl.create 17 in + let orig_logic_infos = Cil_datatype.Logic_info.Hashtbl.create 17 in + let orig_logic_type_infos = Cil_datatype.Logic_type_info.Hashtbl.create 17 in + let orig_fieldinfos = Cil_datatype.Fieldinfo.Hashtbl.create 17 in + let orig_stmts = Cil_datatype.Stmt.Hashtbl.create 103 in + let orig_logic_vars = Cil_datatype.Logic_var.Hashtbl.create 17 in + let orig_kernel_functions = Cil_datatype.Kf.Hashtbl.create 17 in let temp_memo_logic_var x = (* Format.printf "search for %s#%d@." x.lv_name x.lv_id;*) let res = - try IH.find logic_vars x.lv_id + try Cil_datatype.Logic_var.Hashtbl.find logic_vars x with Not_found -> (* Format.printf "Not found@.";*) let new_x = { x with lv_id = x.lv_id } in - IH.add logic_vars x.lv_id new_x; - IH.add orig_logic_vars new_x.lv_id x; + Cil_datatype.Logic_var.Hashtbl.add logic_vars x new_x; + Cil_datatype.Logic_var.Hashtbl.add orig_logic_vars new_x x; new_x in (* Format.printf "res is %s#%d@." res.lv_name res.lv_id;*) res in + let temp_memo_varinfo x = + try Cil_datatype.Varinfo.Hashtbl.find varinfos x + with Not_found -> + let new_x = { x with vid = x.vid } in + Cil_datatype.Varinfo.Hashtbl.add varinfos x new_x; + Cil_datatype.Varinfo.Hashtbl.add orig_varinfos new_x x; + new_x + in { cfile = (fun x -> { x with fileName = x.fileName }); get_compinfo = - (fun x -> try IH.find compinfos x.ckey with Not_found -> x); + (fun x -> + try Cil_datatype.Compinfo.Hashtbl.find compinfos x with Not_found -> x); get_fieldinfo = - (fun x -> try Hashtbl.find fieldinfos (x.fname,x.fcomp.ckey) - with Not_found -> x); + (fun x -> + try Cil_datatype.Fieldinfo.Hashtbl.find fieldinfos x + with Not_found -> x); get_enuminfo = - (fun x -> try Hashtbl.find enuminfos x.ename with Not_found -> x); + (fun x -> + try Cil_datatype.Enuminfo.Hashtbl.find enuminfos x with Not_found -> x); get_enumitem = - (fun x -> try Hashtbl.find enumitems x.einame with Not_found -> x); + (fun x -> + try Cil_datatype.Enumitem.Hashtbl.find enumitems x with Not_found -> x); get_typeinfo = - (fun x -> try Hashtbl.find typeinfos x.tname with Not_found -> x); + (fun x -> + try Cil_datatype.Typeinfo.Hashtbl.find typeinfos x with Not_found -> x); get_varinfo = - (fun x -> try IH.find varinfos x.vid with Not_found -> x); - get_stmt = (fun x -> try IH.find stmts x.sid with Not_found -> x); + (fun x -> + try Cil_datatype.Varinfo.Hashtbl.find varinfos x with Not_found -> x); + get_stmt = + (fun x -> try Cil_datatype.Stmt.Hashtbl.find stmts x with Not_found -> x); get_logic_info = - (fun x -> try IH.find logic_infos x.l_var_info.lv_id - with Not_found -> x); + (fun x -> + try Cil_datatype.Logic_info.Hashtbl.find logic_infos x + with Not_found -> x); get_logic_type_info = - (fun x ->try Hashtbl.find logic_type_infos x.lt_name with Not_found -> x); - get_logic_var = (fun x -> try IH.find logic_vars x.lv_id - with Not_found -> x); + (fun x -> + try Cil_datatype.Logic_type_info.Hashtbl.find logic_type_infos x + with Not_found -> x); + get_logic_var = + (fun x -> + try Cil_datatype.Logic_var.Hashtbl.find logic_vars x + with Not_found -> x); + get_kernel_function = + (fun x -> + try Cil_datatype.Kf.Hashtbl.find kernel_functions x + with Not_found -> x); get_original_compinfo = - (fun x -> try IH.find orig_compinfos x.ckey with Not_found -> x); + (fun x -> + try Cil_datatype.Compinfo.Hashtbl.find orig_compinfos x + with Not_found -> x); get_original_fieldinfo = - (fun x -> try Hashtbl.find orig_fieldinfos (x.fname,x.fcomp.ckey) - with Not_found -> x); + (fun x -> + try Cil_datatype.Fieldinfo.Hashtbl.find orig_fieldinfos x + with Not_found -> x); get_original_enuminfo = - (fun x -> try Hashtbl.find orig_enuminfos x.ename with Not_found -> x); + (fun x -> + try Cil_datatype.Enuminfo.Hashtbl.find orig_enuminfos x + with Not_found -> x); get_original_enumitem = - (fun x -> try Hashtbl.find orig_enumitems x.einame with Not_found -> x); + (fun x -> + try Cil_datatype.Enumitem.Hashtbl.find orig_enumitems x + with Not_found -> x); get_original_typeinfo = - (fun x -> try Hashtbl.find orig_typeinfos x.tname with Not_found -> x); + (fun x -> + try Cil_datatype.Typeinfo.Hashtbl.find orig_typeinfos x + with Not_found -> x); get_original_varinfo = - (fun x -> try IH.find orig_varinfos x.vid with Not_found -> x); + (fun x -> + try Cil_datatype.Varinfo.Hashtbl.find orig_varinfos x + with Not_found -> x); get_original_stmt = - (fun x -> try IH.find orig_stmts x.sid with Not_found -> x); + (fun x -> + try Cil_datatype.Stmt.Hashtbl.find orig_stmts x with Not_found -> x); get_original_logic_var = - (fun x -> try IH.find orig_logic_vars x.lv_id with Not_found -> x); + (fun x -> + try Cil_datatype.Logic_var.Hashtbl.find orig_logic_vars x + with Not_found -> x); get_original_logic_info = - (fun x -> try IH.find orig_logic_infos x.l_var_info.lv_id + (fun x -> + try Cil_datatype.Logic_info.Hashtbl.find orig_logic_infos x with Not_found -> x); get_original_logic_type_info = - (fun x -> try Hashtbl.find orig_logic_type_infos x.lt_name - with Not_found -> x); + (fun x -> + try Cil_datatype.Logic_type_info.Hashtbl.find orig_logic_type_infos x + with Not_found -> x); + get_original_kernel_function = + (fun x -> + try Cil_datatype.Kf.Hashtbl.find orig_kernel_functions x + with Not_found -> x); cinitinfo = (fun x -> { init = x.init }); cfundec = ( fun x -> { x with svar = x.svar }); cblock = (fun x -> { x with battrs = x.battrs }); @@ -684,126 +973,160 @@ cfunbehavior = (fun x -> { x with b_name = x.b_name}); is_copy_behavior = true; reset_behavior_varinfo = - (fun () -> IH.clear varinfos; IH.clear orig_varinfos); + (fun () -> + Cil_datatype.Varinfo.Hashtbl.clear varinfos; + Cil_datatype.Varinfo.Hashtbl.clear orig_varinfos); reset_behavior_compinfo = - (fun () -> IH.clear compinfos; IH.clear orig_compinfos); + (fun () -> + Cil_datatype.Compinfo.Hashtbl.clear compinfos; + Cil_datatype.Compinfo.Hashtbl.clear orig_compinfos); reset_behavior_enuminfo = - (fun () -> Hashtbl.clear enuminfos; Hashtbl.clear orig_enuminfos); + (fun () -> + Cil_datatype.Enuminfo.Hashtbl.clear enuminfos; + Cil_datatype.Enuminfo.Hashtbl.clear orig_enuminfos); reset_behavior_enumitem = - (fun () -> Hashtbl.clear enumitems; Hashtbl.clear orig_enumitems); + (fun () -> + Cil_datatype.Enumitem.Hashtbl.clear enumitems; + Cil_datatype.Enumitem.Hashtbl.clear orig_enumitems); reset_behavior_typeinfo = - (fun () -> Hashtbl.clear typeinfos; Hashtbl.clear orig_typeinfos); + (fun () -> + Cil_datatype.Typeinfo.Hashtbl.clear typeinfos; + Cil_datatype.Typeinfo.Hashtbl.clear orig_typeinfos); reset_behavior_logic_info = - (fun () -> IH.clear logic_infos; IH.clear orig_logic_infos); + (fun () -> + Cil_datatype.Logic_info.Hashtbl.clear logic_infos; + Cil_datatype.Logic_info.Hashtbl.clear orig_logic_infos); reset_behavior_logic_type_info = (fun () -> - Hashtbl.clear logic_type_infos; Hashtbl.clear orig_logic_type_infos); + Cil_datatype.Logic_type_info.Hashtbl.clear logic_type_infos; + Cil_datatype.Logic_type_info.Hashtbl.clear orig_logic_type_infos); reset_behavior_fieldinfo = - (fun () ->Hashtbl.clear fieldinfos; Hashtbl.clear orig_fieldinfos); + (fun () -> + Cil_datatype.Fieldinfo.Hashtbl.clear fieldinfos; + Cil_datatype.Fieldinfo.Hashtbl.clear orig_fieldinfos); reset_behavior_stmt = - (fun () -> IH.clear stmts; IH.clear orig_stmts); + (fun () -> + Cil_datatype.Stmt.Hashtbl.clear stmts; + Cil_datatype.Stmt.Hashtbl.clear orig_stmts); reset_logic_var = - (fun () -> IH.clear logic_vars; IH.clear orig_logic_vars); - memo_varinfo = - (fun x -> - try IH.find varinfos x.vid - with Not_found -> - let new_x = { x with vid = x.vid } in - IH.add varinfos x.vid new_x; - IH.add orig_varinfos new_x.vid x; - new_x); + (fun () -> + Cil_datatype.Logic_var.Hashtbl.clear logic_vars; + Cil_datatype.Logic_var.Hashtbl.clear orig_logic_vars); + reset_behavior_kernel_function = + (fun () -> + Cil_datatype.Kf.Hashtbl.clear kernel_functions; + Cil_datatype.Kf.Hashtbl.clear orig_kernel_functions); + memo_varinfo = temp_memo_varinfo; memo_compinfo = (fun x -> - try IH.find compinfos x.ckey + try Cil_datatype.Compinfo.Hashtbl.find compinfos x with Not_found -> let new_x = { x with ckey = x.ckey } in - IH.add compinfos x.ckey new_x; - IH.add orig_compinfos new_x.ckey x; + Cil_datatype.Compinfo.Hashtbl.add compinfos x new_x; + Cil_datatype.Compinfo.Hashtbl.add orig_compinfos new_x x; new_x); memo_enuminfo = (fun x -> - try Hashtbl.find enuminfos x.ename + try Cil_datatype.Enuminfo.Hashtbl.find enuminfos x with Not_found -> let new_x = { x with ename = x.ename } in - Hashtbl.add enuminfos x.ename new_x; - Hashtbl.add orig_enuminfos new_x.ename x; + Cil_datatype.Enuminfo.Hashtbl.add enuminfos x new_x; + Cil_datatype.Enuminfo.Hashtbl.add orig_enuminfos new_x x; new_x); memo_enumitem = (fun x -> - try Hashtbl.find enumitems x.einame + try Cil_datatype.Enumitem.Hashtbl.find enumitems x with Not_found -> let new_x = { x with einame = x.einame } in - Hashtbl.add enumitems x.einame new_x; - Hashtbl.add orig_enumitems new_x.einame x; + Cil_datatype.Enumitem.Hashtbl.add enumitems x new_x; + Cil_datatype.Enumitem.Hashtbl.add orig_enumitems new_x x; new_x); memo_typeinfo = (fun x -> - try Hashtbl.find typeinfos x.tname + try Cil_datatype.Typeinfo.Hashtbl.find typeinfos x with Not_found -> let new_x = { x with tname = x.tname } in - Hashtbl.add typeinfos x.tname new_x; - Hashtbl.add orig_typeinfos new_x.tname x; + Cil_datatype.Typeinfo.Hashtbl.add typeinfos x new_x; + Cil_datatype.Typeinfo.Hashtbl.add orig_typeinfos new_x x; new_x); memo_logic_info = (fun x -> - try IH.find logic_infos x.l_var_info.lv_id + try Cil_datatype.Logic_info.Hashtbl.find logic_infos x with Not_found -> let new_v = temp_memo_logic_var x.l_var_info in let new_x = { x with l_var_info = new_v } in - IH.add logic_infos x.l_var_info.lv_id new_x; - IH.add orig_logic_infos new_v.lv_id x; + Cil_datatype.Logic_info.Hashtbl.add logic_infos x new_x; + Cil_datatype.Logic_info.Hashtbl.add orig_logic_infos new_x x; new_x); memo_logic_type_info = (fun x -> - try Hashtbl.find logic_type_infos x.lt_name + try Cil_datatype.Logic_type_info.Hashtbl.find logic_type_infos x with Not_found -> let new_x = { x with lt_name = x.lt_name } in - Hashtbl.add logic_type_infos x.lt_name new_x; - Hashtbl.add orig_logic_type_infos new_x.lt_name x; + Cil_datatype.Logic_type_info.Hashtbl.add logic_type_infos x new_x; + Cil_datatype.Logic_type_info.Hashtbl.add + orig_logic_type_infos new_x x; new_x); memo_stmt = (fun x -> - try IH.find stmts x.sid + try Cil_datatype.Stmt.Hashtbl.find stmts x with Not_found -> let new_x = { x with sid = x.sid } in - IH.add stmts x.sid new_x; - IH.add orig_stmts new_x.sid x; + Cil_datatype.Stmt.Hashtbl.add stmts x new_x; + Cil_datatype.Stmt.Hashtbl.add orig_stmts new_x x; new_x); memo_fieldinfo = (fun x -> - try Hashtbl.find fieldinfos (x.fname,x.fcomp.ckey) + try Cil_datatype.Fieldinfo.Hashtbl.find fieldinfos x with Not_found -> let new_x = { x with fname = x.fname } in - Hashtbl.add fieldinfos (x.fname, x.fcomp.ckey) new_x; - Hashtbl.add orig_fieldinfos (new_x.fname, new_x.fcomp.ckey) x; + Cil_datatype.Fieldinfo.Hashtbl.add fieldinfos x new_x; + Cil_datatype.Fieldinfo.Hashtbl.add orig_fieldinfos new_x x; new_x); memo_logic_var = temp_memo_logic_var; - set_varinfo = (fun x y -> IH.replace varinfos x.vid y); - set_compinfo = (fun x y -> IH.replace compinfos x.ckey y); - set_enuminfo = (fun x y -> Hashtbl.replace enuminfos x.ename y); - set_enumitem = (fun x y -> Hashtbl.replace enumitems x.einame y); - set_typeinfo = (fun x y -> Hashtbl.replace typeinfos x.tname y); - set_logic_info = - (fun x y -> IH.replace logic_infos x.l_var_info.lv_id y); - set_logic_type_info = - (fun x y -> Hashtbl.replace logic_type_infos x.lt_name y); - set_stmt = (fun x y -> IH.replace stmts x.sid y); - set_fieldinfo = - (fun x y -> Hashtbl.replace fieldinfos (x.fname,x.fcomp.ckey) y); - set_logic_var = (fun x y -> IH.replace logic_vars x.lv_id y); - set_orig_varinfo = (fun x y -> IH.replace orig_varinfos x.vid y); - set_orig_compinfo = (fun x y -> IH.replace orig_compinfos x.ckey y); - set_orig_enuminfo = (fun x y -> Hashtbl.replace orig_enuminfos x.ename y); - set_orig_enumitem = (fun x y -> Hashtbl.replace orig_enumitems x.einame y); - set_orig_typeinfo = (fun x y -> Hashtbl.replace orig_typeinfos x.tname y); + memo_kernel_function = + (fun x -> + try Cil_datatype.Kf.Hashtbl.find kernel_functions x + with Not_found -> + let fundec = + match x.fundec with + | Definition (f,l) -> + let f = { f with svar = temp_memo_varinfo f.svar } in + Definition (f,l) + | Declaration(s,v,p,l) -> + Declaration(s,temp_memo_varinfo v,p,l) + in + let new_x = { x with fundec = fundec } in + Cil_datatype.Kf.Hashtbl.add kernel_functions x new_x; + Cil_datatype.Kf.Hashtbl.add orig_kernel_functions new_x x; + new_x); + set_varinfo = Cil_datatype.Varinfo.Hashtbl.replace varinfos; + set_compinfo = Cil_datatype.Compinfo.Hashtbl.replace compinfos; + set_enuminfo = Cil_datatype.Enuminfo.Hashtbl.replace enuminfos; + set_enumitem = Cil_datatype.Enumitem.Hashtbl.replace enumitems; + set_typeinfo = Cil_datatype.Typeinfo.Hashtbl.replace typeinfos; + set_logic_info = Cil_datatype.Logic_info.Hashtbl.replace logic_infos; + set_logic_type_info = + Cil_datatype.Logic_type_info.Hashtbl.replace logic_type_infos; + set_stmt = Cil_datatype.Stmt.Hashtbl.replace stmts; + set_fieldinfo = Cil_datatype.Fieldinfo.Hashtbl.replace fieldinfos; + set_logic_var = Cil_datatype.Logic_var.Hashtbl.replace logic_vars; + set_kernel_function = Cil_datatype.Kf.Hashtbl.replace kernel_functions; + set_orig_varinfo = Cil_datatype.Varinfo.Hashtbl.replace orig_varinfos; + set_orig_compinfo = Cil_datatype.Compinfo.Hashtbl.replace orig_compinfos; + set_orig_enuminfo = Cil_datatype.Enuminfo.Hashtbl.replace orig_enuminfos; + set_orig_enumitem = Cil_datatype.Enumitem.Hashtbl.replace orig_enumitems; + set_orig_typeinfo = Cil_datatype.Typeinfo.Hashtbl.replace orig_typeinfos; set_orig_logic_info = - (fun x y -> IH.replace orig_logic_infos x.l_var_info.lv_id y); + Cil_datatype.Logic_info.Hashtbl.replace orig_logic_infos; set_orig_logic_type_info = - (fun x y -> Hashtbl.replace orig_logic_type_infos x.lt_name y); - set_orig_stmt = (fun x y -> IH.replace orig_stmts x.sid y); - set_orig_fieldinfo = - (fun x y -> Hashtbl.replace orig_fieldinfos (x.fname,x.fcomp.ckey) y); - set_orig_logic_var = (fun x y -> IH.replace orig_logic_vars x.lv_id y); + Cil_datatype.Logic_type_info.Hashtbl.replace orig_logic_type_infos; + set_orig_stmt = Cil_datatype.Stmt.Hashtbl.replace orig_stmts; + set_orig_fieldinfo = + Cil_datatype.Fieldinfo.Hashtbl.replace orig_fieldinfos; + set_orig_logic_var = Cil_datatype.Logic_var.Hashtbl.replace orig_logic_vars; + set_orig_kernel_function = + Cil_datatype.Kf.Hashtbl.replace orig_kernel_functions; } (* sm/gn: cil visitor interface for traversing Cil trees. *) @@ -922,6 +1245,8 @@ method vterm_offset: term_offset -> term_offset visitAction + method vlogic_label: logic_label -> logic_label visitAction + method vlogic_info_decl: logic_info -> logic_info visitAction method vlogic_info_use: logic_info -> logic_info visitAction @@ -971,6778 +1296,6988 @@ method get_filling_actions: (unit -> unit) Queue.t end -let assertEmptyQueue vis = - if vis#unqueueInstr () <> [] then - (* Either a visitor inserted an instruction somewhere that it shouldn't - have (i.e. at the top level rather than inside of a statement), or - there's a bug in the visitor engine. *) - Cilmsg.fatal "Visitor's instruction queue is not empty.\n You should only use queueInstr inside a function body!"; - () +(* the default visitor does nothing at each node, but does *) + (* not stop; hence they return true *) + class internal_genericCilVisitor current_func ?prj behavior: cilVisitor = + object + method behavior = behavior -(* sm: utility *) -let startsWith prefix s = - let prefixLen = String.length prefix in - String.length s >= prefixLen && String.sub s 0 prefixLen = prefix + method plain_copy_visitor = + new internal_genericCilVisitor current_func ?prj behavior + (* list of things to perform on the new project. Done at the end + of the analysis in order to minimize the number of project changes. + *) + val global_tables_action = Queue.create () -(* The next compindo identifier to use. Counts up. *) -let nextCompinfoKey = - let module M = Build_Counter(struct let name = "compinfokey" end) in - M.next + method fill_global_tables = + let action () = Queue.iter (fun f -> f()) global_tables_action in + (match prj with + None -> action () + | Some prj -> Project.on prj action ()); + Queue.clear global_tables_action + method get_filling_actions = global_tables_action -let bytesSizeOfInt (ik: ikind): int = - match ik with - | IChar | ISChar | IUChar -> 1 - | IBool | IInt | IUInt -> theMachine.theMachine.sizeof_int - | IShort | IUShort -> theMachine.theMachine.sizeof_short - | ILong | IULong -> theMachine.theMachine.sizeof_long - | ILongLong | IULongLong -> theMachine.theMachine.sizeof_longlong + method vfile _f = DoChildren + val current_stmt = Stack.create () + method push_stmt s = Stack.push s current_stmt + method pop_stmt _s = ignore (Stack.pop current_stmt) + method current_stmt = + try Some (Stack.top current_stmt) with Stack.Empty -> None -(** Returns true if and only if the given integer type is signed. *) -let isSigned = function - | IUChar | IBool - | IUShort - | IUInt - | IULong - | IULongLong -> - false - | ISChar - | IShort - | IInt - | ILong - | ILongLong -> - true - | IChar -> - not theMachine.theMachine.Cil_types.char_is_unsigned + method current_kinstr = + try Kstmt (Stack.top current_stmt) with Stack.Empty -> Kglobal -(* Represents an integer as for a given kind. - Returns a flag saying whether the value was changed - during truncation (because it was too large to fit in k). *) -let truncateInteger64 (k: ikind) (i: int64) : int64 * bool = - let nrBits = 8 * (bytesSizeOfInt k) in - let signed = isSigned k in - if nrBits = 64 then - i, false - else begin - let i1 = Int64.shift_left i (64 - nrBits) in - let i2 = - if signed then Int64.shift_right i1 (64 - nrBits) - else Int64.shift_right_logical i1 (64 - nrBits) - in - let truncated = - if i2 = i then false - else - (* Examine the bits that we chopped off. If they are all zero, then - * any difference between i2 and i is due to a simple sign-extension. - * e.g. casting the constant 0x80000000 to int makes it - * 0xffffffff80000000. - * Suppress the truncation warning in this case. *) - let chopped = Int64.shift_right_logical i (64 - nrBits) - in chopped <> Int64.zero - in - i2, truncated - end + method current_func = !current_func + method set_current_func f = current_func := Some f + method reset_current_func () = current_func := None -(* Construct an integer constant with possible truncation *) -let kinteger64_repr ~loc (k: ikind) (i: int64) repr = - let i', truncated = truncateInteger64 k i in - if truncated then - warnOpt "Truncating integer %s to %s" - (Int64.format "0x%x" i) (Int64.format "0x%x" i') ; - new_exp ~loc (Const (CInt64(i' , k, repr))) + method vvrbl (_v:varinfo) = DoChildren + method vvdec (_v:varinfo) = DoChildren + method vexpr (_e:exp) = DoChildren + method vlval (_l:lval) = DoChildren + method voffs (_o:offset) = DoChildren + method vinitoffs (_o:offset) = DoChildren + method vinst (_i:instr) = DoChildren + method vstmt (_s:stmt) = DoChildren + method vblock (_b: block) = DoChildren + method vfunc (_f:fundec) = DoChildren + method vglob (_g:global) = DoChildren + method vinit (_forg: varinfo) (_off: offset) (_i:init) = DoChildren + method vtype (_t:typ) = DoChildren + method vcompinfo _ = DoChildren + method venuminfo _ = DoChildren + method vfieldinfo _ = DoChildren + method venumitem _ = DoChildren + method vattr (_a: attribute) = DoChildren + method vattrparam (_a: attrparam) = DoChildren -let kinteger64 ~loc k i = kinteger64_repr ~loc k i None + val mutable instrQueue = [] -(* Construct an integer of a given kind. *) -let kinteger ~loc (k: ikind) (i: int) = kinteger64 ~loc k (Int64.of_int i) + method queueInstr (il: instr list) = + List.iter (fun i -> instrQueue <- i :: instrQueue) il -(* Construct an integer. Use only for values that fit on 31 bits *) -let integer_constant i = CInt64(Int64.of_int i, IInt, None) -(* Construct an integer. Use only for values that fit on 31 bits *) -let integer ~loc (i: int) = new_exp ~loc (Const (integer_constant i)) + method unqueueInstr () = + let res = List.rev instrQueue in + instrQueue <- []; + res -let zero ~loc = integer ~loc 0 -let one ~loc = integer ~loc 1 -let mone ~loc = integer ~loc (-1) + method vlogic_type _lt = DoChildren - let lconstant ?(loc=Location.unknown) v = - { term_node = TConst (CInt64(v, IInt, None)); term_loc = loc; - term_name = []; term_type = Ctype (TInt (IInt,[]));} - - let lzero ?(loc=Location.unknown) () = lconstant ~loc Int64.zero - let lone ?(loc=Location.unknown) () = lconstant ~loc Int64.one - let lmone ?(loc=Location.unknown) () = lconstant ~loc (Int64.minus_one) + method vterm _t = DoChildren - (** Given the character c in a (CChr c), sign-extend it to 32 bits. - (This is the official way of interpreting character constants, according to - ISO C 6.4.4.4.10, which says that character constants are chars cast to ints) - Returns CInt64(sign-extened c, IInt, None) *) - let charConstToInt (c: char) : constant = - let c' = Char.code c in - let value = - if c' < 128 - then Int64.of_int c' - else Int64.of_int (c' - 256) - in - CInt64(value, IInt, None) - - - let rec isInteger e = match e.enode with - | Const(CInt64 (n,_,_)) -> Some n - | Const(CChr c) -> isInteger (dummy_exp (Const (charConstToInt c))) - | Const(CEnum {eival = v}) -> isInteger v - | CastE(_, e) -> isInteger e - | _ -> None + method vlogic_label _l = DoChildren - (** Convert a 64-bit int to an OCaml int, or raise an exception if that - can't be done. *) - let i64_to_int (i: int64) : int = - let i': int = Int64.to_int i in (* i.e. i' = i mod 2^31 *) - if i = Int64.of_int i' then i' - else Cilmsg.abort "Int constant too large: %Ld\n" i - - let rec isZero (e: exp) : bool = isInteger e = Some Int64.zero - - let rec isLogicZero t = match t.term_node with - | TConst (CInt64 (n,_,_)) -> n = 0L - | TConst (CChr c) -> Char.code c = 0 - | TCastE(_, t) -> isLogicZero t - | _ -> false + method vterm_node _tn = DoChildren - let isLogicNull t = - isLogicZero t || - (let rec aux t = match t.term_node with - | Tnull -> true - | TCastE(_, t) -> aux t - | _ -> false - in aux t) + method vterm_lval _tl = DoChildren -let parseInt ~loc (str: string) : exp = - let hasSuffix str = - let l = String.length str in - fun s -> - let ls = String.length s in - l >= ls && s = String.uppercase (String.sub str (l - ls) ls) - in - let l = String.length str in - (* See if it is octal or hex *) - let octalhex = (l >= 1 && String.get str 0 = '0') in - (* The length of the suffix and a list of possible kinds. See ISO - * 6.4.4.1 *) - let hasSuffix = hasSuffix str in - let suffixlen, kinds = - if hasSuffix "ULL" || hasSuffix "LLU" then - 3, [IULongLong] - else if hasSuffix "LL" then - 2, if octalhex then [ILongLong; IULongLong] else [ILongLong] - else if hasSuffix "UL" || hasSuffix "LU" then - 2, [IULong; IULongLong] - else if hasSuffix "L" then - 1, if octalhex then [ILong; IULong; ILongLong; IULongLong] - else [ILong; ILongLong] - else if hasSuffix "U" then - 1, [IUInt; IULong; IULongLong] - else - 0, if octalhex || true (* !!! This is against the ISO but it - * is what GCC and MSVC do !!! *) - then [IInt; IUInt; ILong; IULong; ILongLong; IULongLong] - else [IInt; ILong; IUInt; ILongLong] - in - (* Convert to integer. To prevent overflow we do the arithmetic - * on Int64 and we take care of overflow. We work only with - * positive integers since the lexer takes care of the sign *) - let rec toInt (base: int64) (acc: int64) (idx: int) : int64 = - let doAcc (what: int) = - let acc' = - Int64.add (Int64.mul base acc) (Int64.of_int what) in - if acc < Int64.zero || (* We clearly overflow since base >= 2 - * *) - (acc' > Int64.zero && acc' < acc) then - fatal "Cannot represent on 64 bits the integer %s" str - else - toInt base acc' (idx + 1) - in - if idx >= l - suffixlen then begin - acc - end else - let ch = String.get str idx in - if ch >= '0' && ch <= '9' then - doAcc (Char.code ch - Char.code '0') - else if ch >= 'a' && ch <= 'f' then - doAcc (10 + Char.code ch - Char.code 'a') - else if ch >= 'A' && ch <= 'F' then - doAcc (10 + Char.code ch - Char.code 'A') - else - fatal "Invalid integer constant: %s" str - in - try - let i = - if octalhex then - if l >= 2 && - (let c = String.get str 1 in c = 'x' || c = 'X') then - toInt (Int64.of_int 16) Int64.zero 2 - else - toInt (Int64.of_int 8) Int64.zero 1 - else - toInt (Int64.of_int 10) Int64.zero 0 - in - let res = - let rec loop = function - k::rest -> - let nrBits = - let unsignedbits = 8 * (bytesSizeOfInt k) in - if isSigned k then - unsignedbits-1 - else - unsignedbits - in - (* Will i fit in nrBits bits? *) - let bound : int64 = Int64.shift_left 1L nrBits in - (* toInt has ensured that 0 <= i < 263. - So if nrBits >=63, i fits *) - if (nrBits >= 63) || (i < bound) then - kinteger64_repr ~loc k i (Some str) - else - loop rest - | [] -> - Cilmsg.fatal "Cannot represent the integer %s" (Int64.to_string i) - in - loop kinds - in - res - with Failure _ as e -> - begin - warning "int_of_string %s (%s)\n" str (Printexc.to_string e) ; - zero ~loc - end + method vterm_lhost _tl = DoChildren - let mkStmt ?(ghost=false) ?(valid_sid=false) (sk: stmtkind) : stmt = - { skind = sk; - labels = []; - (* It is better to create statements with a valid sid, so that they can - be safely be used in tables. I only do it when performing Jessie - analysis, as other plugins rely on specific sid values for their tests - (e.g. slicing). *) - sid = if valid_sid then Sid.next () else -1; - succs = []; preds = []; - ghost = ghost} + method vterm_offset _vo = DoChildren - let mkStmtCfg ~before ~(new_stmtkind:stmtkind) ~(ref_stmt:stmt) : stmt = - let new_ = { skind = new_stmtkind; - labels = []; - sid = -1; succs = []; preds = []; ghost = false } - in - new_.sid <- Sid.next (); - if before then begin - new_.succs <- [ref_stmt]; - let old_preds = ref_stmt.preds in - ref_stmt.preds <- [new_]; - new_.preds <- old_preds; - List.iter - (fun pred_stmt -> - pred_stmt.succs <- - (List.map - (fun a_succ -> if a_succ.sid = ref_stmt.sid then new_ else a_succ) - pred_stmt.succs)) - old_preds - end else begin - let old_succs = ref_stmt.succs in - ref_stmt.succs <- [new_]; - new_.preds <- [ref_stmt]; - new_.succs <- old_succs; - List.iter - (fun succ_stmt -> - succ_stmt.preds <- - (List.map - (fun a_pred -> if a_pred.sid = ref_stmt.sid then new_ else a_pred) - succ_stmt.preds)) - old_succs - end; - new_ + method vlogic_info_decl _li = DoChildren + method vlogic_info_use _li = DoChildren - let mkBlock (slst: stmt list) : block = - { battrs = []; bstmts = slst; blocals = []} + method vlogic_type_info_decl _ = DoChildren - let mkStmtCfgBlock sl = - let sid = Sid.next () in - let n = mkStmt (Block (mkBlock sl)) in - n.sid <- sid; - match sl with - | [] -> n - | s::_ -> - let old_preds = s.preds in - n.succs <- [s]; - n.preds <- s.preds; - List.iter - (fun pred_stmt -> - pred_stmt.succs <- - (List.map - (fun a_succ -> if a_succ.sid = s.sid then - n - else a_succ) - pred_stmt.succs)) - old_preds; - n + method vlogic_type_info_use _ = DoChildren - let stmt_of_instr_list ?(loc=Location.unknown) = function - | [] -> Instr (Skip loc) - | [i] -> Instr i - | il -> - let b = mkBlock (List.map (fun i -> mkStmt (Instr i)) il) in - match b.bstmts with - | [] -> Instr (Skip loc) - | [s] when b.battrs = [] -> s.skind - | _ -> Block b + method vlogic_type_def _ = DoChildren - let mkEmptyStmt ?ghost ?(loc=Location.unknown) () = mkStmt ?ghost (Instr (Skip loc)) - let mkStmtOneInstr ?ghost (i: instr) = mkStmt ?ghost (Instr i) + method vlogic_ctor_info_decl _ = DoChildren - let dummyInstr = Asm([], ["dummy statement!!"], [], [], [], Location.unknown) - let dummyStmt = mkStmt (Instr dummyInstr) + method vlogic_ctor_info_use _ = DoChildren - (*** - let compactStmts (b: stmt list) : stmt list = - (* Try to compress statements. Scan the list of statements and remember - * the last instrunction statement encountered, along with a Clist of - * instructions in it. *) - let rec compress (lastinstrstmt: stmt) (* Might be dummStmt *) - (lastinstrs: instr Clist.clist) - (body: stmt list) = - let finishLast (tail: stmt list) : stmt list = - if lastinstrstmt == dummyStmt then tail - else begin - lastinstrstmt.skind <- Instr (Clist.toList lastinstrs); - lastinstrstmt :: tail - end - in - match body with - [] -> finishLast [] - | ({skind=Instr il} as s) :: rest -> - let ils = Clist.fromList il in - if lastinstrstmt != dummyStmt && s.labels == [] then - compress lastinstrstmt (Clist.append lastinstrs ils) rest - else - finishLast (compress s ils rest) + method vlogic_var_decl _lv = DoChildren - | s :: rest -> - let res = s :: compress dummyStmt Clist.empty rest in - finishLast res - in - compress dummyStmt Clist.empty b - ***) + method vlogic_var_use _lv = DoChildren - (**** ATTRIBUTES ****) + method vquantifiers _q = DoChildren + method vpredicate _p = DoChildren - (* JS: build an attribute annotation from [s]. *) - let mkAttrAnnot s = "/*@ " ^ s ^ " */" + method vpredicate_named _p = DoChildren - (* JS: *) - let attributeName = function Attr(a, _) | AttrAnnot a -> a + method vbehavior _b = DoChildren -(* Internal attributes. Won't be pretty-printed *) -let reserved_attributes = ref ["FRAMA_C_KEEP_BLOCK"] -let register_shallow_attribute s = reserved_attributes:=s::!reserved_attributes + method vspec _s = DoChildren - (** Construct sorted lists of attributes ***) - let rec addAttribute - (Attr(an, _) | AttrAnnot an as a: attribute) (al: attributes) = - let rec insertSorted = function - [] -> [a] - | ((Attr(an0, _) | AttrAnnot an0 as a0) :: rest) as l -> - if an < an0 then a :: l - else if equals a a0 then l (* Do not add if already in there *) - else a0 :: insertSorted rest (* Make sure we see all attributes with - * this name *) - in - insertSorted al + method vassigns _s = DoChildren - (** The second attribute list is sorted *) - and addAttributes al0 (al: attributes) : attributes = - if al0 == [] then al else - List.fold_left (fun acc a -> addAttribute a acc) al al0 + method vloop_pragma _ = DoChildren - and dropAttribute (an: string) (al: attributes) = - List.filter (fun a -> attributeName a <> an) al + method vslice_pragma _ = DoChildren + method vimpact_pragma _ = DoChildren - and dropAttributes (anl: string list) (al: attributes) = - List.fold_left (fun acc an -> dropAttribute an acc) al anl + method vdeps _ = DoChildren - and filterAttributes (s: string) (al: attribute list) : attribute list = - List.filter (fun a -> attributeName a = s) al + method vfrom _ = DoChildren - and findAttribute (s: string) (al: attribute list) : attrparam list = - List.fold_left - (fun acc -> function - | Attr (an, param) when an = s -> param @ acc - | _ -> acc) - [] al + method vcode_annot _ca = DoChildren - let qualifier_attributes = [ "const"; "restrict"; "volatile"] + method vannotation _a = DoChildren - let filter_qualifier_attributes al = - List.filter - (fun a -> List.mem (attributeName a) qualifier_attributes) al + end - (* sm: *) - let hasAttribute s al = - (filterAttributes s al <> []) + class genericCilVisitor ?prj bhv = + let current_func = ref None in + internal_genericCilVisitor current_func ?prj bhv - type attributeClass = - | AttrName of bool - (* Attribute of a name. If argument is true and we are on MSVC then - * the attribute is printed using __declspec as part of the storage - * specifier *) - | AttrFunType of bool - (* Attribute of a function type. If argument is true and we are on - * MSVC then the attribute is printed just before the function name *) + class nopCilVisitor = object + inherit genericCilVisitor (inplace_visit ()) + end - | AttrType (* Attribute of a type *) +let assertEmptyQueue vis = + if vis#unqueueInstr () <> [] then + (* Either a visitor inserted an instruction somewhere that it shouldn't + have (i.e. at the top level rather than inside of a statement), or + there's a bug in the visitor engine. *) + Kernel.fatal + "Visitor's instruction queue is not empty.@\n\ + You should only use queueInstr inside a function body!"; + () - (* This table contains the mapping of predefined attributes to classes. - * Extend this table with more attributes as you need. This table is used to - * determine how to associate attributes with names or type during cabs2cil - * conversion *) - let attributeHash: (string, attributeClass) Hashtbl.t = - let table = Hashtbl.create 13 in - List.iter (fun a -> Hashtbl.add table a (AttrName false)) - [ "section"; "constructor"; "destructor"; "unused"; "used"; "weak"; - "no_instrument_function"; "alias"; "no_check_memory_usage"; - "exception"; "model"; (* "restrict"; *) - "aconst"; "__asm__" (* Gcc uses this to specifiy the name to be used in - * assembly for a global *)]; - (* Now come the MSVC declspec attributes *) - List.iter (fun a -> Hashtbl.add table a (AttrName true)) - [ "thread"; "naked"; "dllimport"; "dllexport"; - "selectany"; "allocate"; "nothrow"; "novtable"; "property"; "noreturn"; - "uuid"; "align" ]; - List.iter (fun a -> Hashtbl.add table a (AttrFunType false)) - [ "format"; "regparm"; "longcall"; "noinline"; "always_inline" ]; - List.iter (fun a -> Hashtbl.add table a (AttrFunType true)) - [ "stdcall";"cdecl"; "fastcall" ]; - List.iter (fun a -> Hashtbl.add table a AttrType) - [ "const"; "volatile"; "restrict"; "mode" ]; - table +(*** Define the visiting engine ****) +(* visit all the nodes in a Cil expression *) +let doVisit (vis: 'visitor) + only_copy_vis + (previsit: 'a -> 'a) + (startvisit: 'a -> 'a visitAction) + (children: 'visitor -> 'a -> 'a) + (node: 'a) : 'a = + let node' = previsit node in + let action = startvisit node' in + match action with + SkipChildren -> node' + | ChangeTo node' -> node' + | ChangeToPost (node',f) -> f node' + | DoChildren | JustCopy | ChangeDoChildrenPost _ | JustCopyPost _ -> + let nodepre = match action with + ChangeDoChildrenPost (node', _) -> node' + | _ -> node' + in + let vis = match action with + JustCopy | JustCopyPost _ -> only_copy_vis + | _ -> vis + in + let nodepost = children vis nodepre in + match action with + ChangeDoChildrenPost (_, f) | JustCopyPost f -> f nodepost + | _ -> nodepost - let attributeClass = Hashtbl.find attributeHash + let doVisitCil vis previsit startvisit children node = + doVisit vis vis#plain_copy_visitor previsit startvisit children node - let registerAttribute = Hashtbl.add attributeHash - let removeAttribute = Hashtbl.remove attributeHash + let rev_until i l = + let rec aux acc = + function + [] -> acc + | i'::_ when i' == i -> acc + | i'::l -> aux (i'::acc) l + in aux [] l - (** Partition the attributes into classes *) - let partitionAttributes - ~(default:attributeClass) - (attrs: attribute list) : - attribute list * attribute list * attribute list = - let rec loop (n,f,t) = function - [] -> n, f, t - | (Attr(an, _) | AttrAnnot an as a) :: rest -> - match (try Hashtbl.find attributeHash an with Not_found -> default) with - AttrName _ -> loop (addAttribute a n, f, t) rest - | AttrFunType _ -> - loop (n, addAttribute a f, t) rest - | AttrType -> loop (n, f, addAttribute a t) rest - in - loop ([], [], []) attrs + (* mapNoCopy is like map but avoid copying the list if the function does not + * change the elements. *) + let mapNoCopy (f: 'a -> 'a) orig = + let rec aux ((acc,has_changed) as res) l = + match l with + [] -> if has_changed then List.rev acc else orig + | i :: resti -> + let i' = f i in + if has_changed then + aux (i'::acc,true) resti + else if i' != i then + aux (i'::rev_until i orig,true) resti + else + aux res resti + in aux ([],false) orig + let mapNoCopyList (f: 'a -> 'a list) orig = + let rec aux ((acc,has_changed) as res) l = + match l with + [] -> if has_changed then List.rev acc else orig + | i :: resti -> + let l' = f i in + if has_changed then + aux (List.rev_append l' acc,true) resti + else + (match l' with + [i'] when i' == i -> aux res resti + | _ -> aux (List.rev_append l' (rev_until i orig), true) resti) + in aux ([],false) orig - (** Get the full name of a comp *) - let compFullName comp = - (if comp.cstruct then "struct " else "union ") ^ comp.cname +(* A visitor for lists *) +let doVisitList (vis: 'visit) + only_copy_vis + (previsit: 'a -> 'a) + (startvisit: 'a -> 'a list visitAction) + (children: 'visit -> 'a -> 'a) + (node: 'a) : 'a list = + let node' = previsit node in + let action = startvisit node' in + match action with + SkipChildren -> [node'] + | ChangeTo nodes' -> nodes' + | ChangeToPost (nodes',f) -> f nodes' + | _ -> + let nodespre = match action with + ChangeDoChildrenPost (nodespre, _) -> nodespre + | _ -> [node'] + in + let vis = match action with + JustCopy | JustCopyPost _ -> only_copy_vis + | _ -> vis + in + let nodespost = mapNoCopy (children vis) nodespre in + match action with + ChangeDoChildrenPost (_, f) | JustCopyPost f -> f nodespost + | _ -> nodespost + let doVisitListCil vis previsit startvisit children node = + doVisitList vis vis#plain_copy_visitor previsit startvisit children node - let missingFieldName = "_" (* "___missing_field_name"*) + let optMapNoCopy f o = + match o with + None -> o + | Some x -> + let x' = f x in if x' != x then Some x' else o - (** Creates a (potentially recursive) composite type. Make sure you add a - * GTag for it to the file! **) - let mkCompInfo - (isstruct: bool) - (n: string) - (* fspec is a function that when given a forward - * representation of the structure type constructs the type of - * the fields. The function can ignore this argument if not - * constructing a recursive type. *) - (mkfspec: compinfo -> (string * typ * int option * attribute list * - location) list) - (a: attribute list) : compinfo = + let opt_bind f = + function + None -> None + | Some x as o -> + match f x with + None -> None + | Some x' as o' -> if x != x' then o else o' - (* make a new name for anonymous structs *) - if n = "" then Cilmsg.fatal "mkCompInfo: missing structure name\n" ; - (* Make a new self cell and a forward reference *) - let comp = - { cstruct = isstruct; - corig_name = n; - cname = n; - ckey = nextCompinfoKey (); - cfields = []; (* fields will be added afterwards. *) - cattr = a; - creferenced = false; - (* Make this compinfo undefined by default *) - cdefined = false; } - in - let flds = - List.map (fun (fn, ft, fb, fa, fl) -> - { fcomp = comp; - ftype = ft; - forig_name = fn; - fname = fn; - fbitfield = fb; - fattr = fa; - floc = fl; - faddrof = false; - fsize_in_bits = None; - foffset_in_bits = None; - fpadding_in_bits = None; - }) (mkfspec comp) in - comp.cfields <- flds; - if flds <> [] then comp.cdefined <- true; - comp + let doVisitOption (vis: #cilVisitor as 'visit) + (previsit: 'a -> 'a) + (startvisit: 'a -> 'a option visitAction) + (children: 'visit -> 'a -> 'a) + (node: 'a) : 'a option = + let node' = previsit node in + let action = startvisit node' in + match action with + SkipChildren -> Some node' + | ChangeTo node' -> node' + | ChangeToPost (node',f) -> f node' + | _ -> + let nodepre = match action with + ChangeDoChildrenPost(nodepre,_) -> nodepre + | _ -> Some node' + in let vis = match action with + JustCopy | JustCopyPost _ -> vis#plain_copy_visitor + | _ -> vis + in let nodepost = optMapNoCopy (children vis) nodepre in + match action with + ChangeDoChildrenPost(_,f) | JustCopyPost f -> f nodepost + | _ -> nodepost - (** Make a copy of a compinfo, changing the name and the key *) - let copyCompInfo (ci: compinfo) (n: string) : compinfo = - let ci' = {ci with cname = n; ckey = nextCompinfoKey (); } in - (* Copy the fields and set the new pointers to parents *) - ci'.cfields <- List.map (fun f -> {f with fcomp = ci'}) ci'.cfields; - ci' + let debugVisit = false - (**** Utility functions ******) +let visitCilConst vis c = + match c with + | CEnum ei -> (* In case of deep copy, we must change the enumitem*) + let ei' = vis#behavior.get_enumitem ei in + if ei' != ei then CEnum ei' else c + | _ -> c - let rec typeAttrs = function - TVoid a -> a - | TInt (_, a) -> a - | TFloat (_, a) -> a - | TNamed (t, a) -> addAttributes a (typeAttrs t.ttype) - | TPtr (_, a) -> a - | TArray (_, _, _,a) -> a - | TComp (comp, _, a) -> addAttributes comp.cattr a - | TEnum (enum, a) -> addAttributes enum.eattr a - | TFun (_, _, _, a) -> a - | TBuiltin_va_list a -> a +let rec visitCilTerm vis t = + let oldloc = CurrentLoc.get () in + CurrentLoc.set t.term_loc; + let res = doVisitCil vis (fun x-> x) vis#vterm childrenTerm t in + CurrentLoc.set oldloc; res +and childrenTerm vis t = + let tn' = visitCilTermNode vis t.term_node in + let tt' = visitCilLogicType vis t.term_type in + if tn' != t.term_node || tt' != t.term_type then + { t with term_node = tn'; term_type = tt' } + else t +and visitCilTermNode vis tn = + doVisitCil vis id vis#vterm_node childrenTermNode tn +and childrenTermNode vis tn = + let vTerm t = visitCilTerm vis t in + let vTermLval tl = visitCilTermLval vis tl in + let vTyp t = visitCilType vis t in + let vLogicInfo li = visitCilLogicInfoUse vis li in + match tn with + | TConst c -> + let c' = visitCilConst vis c in + if c' != c then TConst c' else tn + | TDataCons (ci,args) -> + let ci' = + doVisitCil vis id vis#vlogic_ctor_info_use alphabetabeta ci + in + let args' = mapNoCopy vTerm args in + if ci' != ci || args != args' then TDataCons(ci',args') else tn + | TLval tl -> + let tl' = vTermLval tl in + if tl' != tl then TLval tl' else tn + | TSizeOf t -> + let t' = vTyp t in if t' != t then TSizeOf t' else tn + | TSizeOfE t -> + let t' = vTerm t in if t' != t then TSizeOfE t' else tn + | TSizeOfStr _ -> tn + | TAlignOf t -> + let t' = vTyp t in if t' != t then TAlignOf t' else tn + | TAlignOfE t -> + let t' = vTerm t in if t' != t then TAlignOfE t' else tn + | TUnOp (op,t) -> + let t' = vTerm t in if t' != t then TUnOp (op,t') else tn + | TBinOp(op,t1,t2) -> + let t1' = vTerm t1 in + let t2' = vTerm t2 in + if t1' != t1 || t2' != t2 then TBinOp(op,t1',t2') else tn + | TCastE(ty,te) -> + let ty' = vTyp ty in + let te' = vTerm te in + if ty' != ty || te' != te then TCastE(ty',te') else tn + | TAddrOf tl -> + let tl' = vTermLval tl in + if tl' != tl then TAddrOf tl' else tn + | TStartOf tl -> + let tl' = vTermLval tl in + if tl' != tl then TStartOf tl' else tn + | Tapp(li,labels,args) -> + let li' = vLogicInfo li in + let labels' = + mapNoCopy (visitCilLogicLabelApp vis) labels in +(* + Format.eprintf "Cil.children_term_node: li = %s(%d), li' = %s(%d)@." + li.l_var_info.lv_name li.l_var_info.lv_id + li'.l_var_info.lv_name li'.l_var_info.lv_id; +*) + let args' = mapNoCopy vTerm args in + if li' != li || labels' != labels || args' != args then + Tapp(li',labels',args') else tn + | Tif(test,ttrue,tfalse) -> + let test' = vTerm test in + let ttrue' = vTerm ttrue in + let tfalse' = vTerm tfalse in + if test' != test || ttrue' != ttrue || tfalse' != tfalse then + Tif(test',ttrue',tfalse') + else tn + | Tat(t,s) -> + let t' = vTerm t in + let s' = visitCilLogicLabel vis s in + if t' != t || s' != s then Tat (t',s') else tn + | Tbase_addr t -> + let t' = vTerm t in if t' != t then Tbase_addr t' else tn + | Tblock_length t -> + let t' = vTerm t in if t' != t then Tblock_length t' else tn + | Tnull -> tn + | TCoerce(te,ty) -> + let ty' = vTyp ty in + let te' = vTerm te in + if ty' != ty || te' != te then TCoerce(te',ty') else tn + | TCoerceE(te,tc) -> + let tc' = vTerm tc in + let te' = vTerm te in + if tc' != tc || te' != te then TCoerceE(te',tc') else tn + | TUpdate (tc,toff,te) -> + let tc' = vTerm tc in + let te' = vTerm te in + let toff' = visitCilTermOffset vis toff in + if tc' != tc || (te' != te || toff' != toff) + then TUpdate(tc',toff',te') else tn + | Tlambda(prms,te) -> + let prms' = visitCilQuantifiers vis prms in + let te' = vTerm te in + if prms' != prms || te' != te then Tlambda(prms',te') else tn + | Ttypeof t -> + let t' = vTerm t in if t' != t then Ttypeof t' else tn + | Ttype ty -> + let ty' = vTyp ty in if ty' != ty then Ttype ty' else tn + | Tunion locs -> + let locs' = mapNoCopy (visitCilTerm vis) locs in + if locs != locs' then Tunion(locs') else tn + | Tinter locs -> + let locs' = mapNoCopy (visitCilTerm vis) locs in + if locs != locs' then Tinter(locs') else tn + | Tcomprehension(lval,quant,pred) -> + let quant' = visitCilQuantifiers vis quant in + let lval' = visitCilTerm vis lval in + let pred' = (optMapNoCopy (visitCilPredicateNamed vis)) pred in + if lval' != lval || quant' != quant || pred' != pred + then + Tcomprehension(lval',quant',pred') + else + tn + | Tempty_set -> tn + | Trange(low,high) -> + let low' = optMapNoCopy (visitCilTerm vis) low in + let high' = optMapNoCopy (visitCilTerm vis) high in + if low != low' || high != high' then Trange(low',high') + else tn + | Tlet(def,body) -> + let def'= visitCilLogicInfo vis def in + let body' = visitCilTerm vis body in + if def != def' || body != body' then + Tlet(def',body') else tn - let typeAttr = function - | TVoid a - | TInt (_, a) - | TFloat (_, a) - | TNamed (_, a) - | TPtr (_, a) - | TArray (_, _, _, a) - | TComp (_, _, a) - | TEnum (_, a) - | TFun (_, _, _, a) - | TBuiltin_va_list a -> a +and visitCilLogicLabel vis l = + doVisitCil vis id vis#vlogic_label childrenLogicLabel l +and childrenLogicLabel vis l = + match l with + StmtLabel s -> s := vis#behavior.get_stmt !s; l + | LogicLabel _ -> l + +and visitCilLogicLabelApp vis (l1,l2 as p) = + let l1' = visitCilLogicLabel vis l1 in + let l2' = visitCilLogicLabel vis l2 in + if l1 != l1' || l2 != l2' then (l1',l2') else p - let setTypeAttrs t a = - match t with - TVoid _ -> TVoid a - | TInt (i, _) -> TInt (i, a) - | TFloat (f, _) -> TFloat (f, a) - | TNamed (t, _) -> TNamed(t, a) - | TPtr (t', _) -> TPtr(t', a) - | TArray (t', l, s, _) -> TArray(t', l, s, a) - | TComp (comp, s, _) -> TComp (comp, s, a) - | TEnum (enum, _) -> TEnum (enum, a) - | TFun (r, args, v, _) -> TFun(r,args,v,a) - | TBuiltin_va_list _ -> TBuiltin_va_list a + and visitCilTermLval vis tl = + doVisitCil vis id vis#vterm_lval childrenTermLval tl + and childrenTermLval vis ((tlv,toff) as tl)= + let tlv' = visitCilTermLhost vis tlv in + let toff' = visitCilTermOffset vis toff in + if tlv' != tlv || toff' != toff then (tlv',toff') else tl - let typeAddAttributes a0 t = - begin - match a0 with - | [] -> - (* no attributes, keep same type *) - t - | _ -> - (* anything else: add a0 to existing attributes *) - let add (a: attributes) = addAttributes a0 a in - match t with - TVoid a -> TVoid (add a) - | TInt (ik, a) -> TInt (ik, add a) - | TFloat (fk, a) -> TFloat (fk, add a) - | TEnum (enum, a) -> TEnum (enum, add a) - | TPtr (t, a) -> TPtr (t, add a) - | TArray (t, l, s, a) -> TArray (t, l, s, add a) - | TFun (t, args, isva, a) -> TFun(t, args, isva, add a) - | TComp (comp, s, a) -> TComp (comp, s, add a) - | TNamed (t, a) -> TNamed (t, add a) - | TBuiltin_va_list a -> TBuiltin_va_list (add a) - end + and visitCilTermLhost vis tl = + doVisitCil vis id vis#vterm_lhost childrenTermLhost tl - let typeRemoveAttributes (anl: string list) t = - let drop (al: attributes) = dropAttributes anl al in - match t with - TVoid a -> TVoid (drop a) - | TInt (ik, a) -> TInt (ik, drop a) - | TFloat (fk, a) -> TFloat (fk, drop a) - | TEnum (enum, a) -> TEnum (enum, drop a) - | TPtr (t, a) -> TPtr (t, drop a) - | TArray (t, l, s, a) -> TArray (t, l, s, drop a) - | TFun (t, args, isva, a) -> TFun(t, args, isva, drop a) - | TComp (comp, s, a) -> TComp (comp, s, drop a) - | TNamed (t, a) -> TNamed (t, drop a) - | TBuiltin_va_list a -> TBuiltin_va_list (drop a) + and childrenTermLhost vis tl = match tl with + TVar v -> + let v' = visitCilLogicVarUse vis v in if v' != v then TVar v' else tl + | TResult ty -> + let ty' = visitCilType vis ty in if ty' != ty then TResult ty' else tl + | TMem t -> + let t' = visitCilTerm vis t in if t' != t then TMem t' else tl - let unrollType (t: typ) : typ = - let rec withAttrs (al: attributes) (t: typ) : typ = - match t with - TNamed (r, a') -> withAttrs (addAttributes al a') r.ttype - | x -> typeAddAttributes al x - in - withAttrs [] t + and visitCilTermOffset vis toff = + doVisitCil vis id + vis#vterm_offset childrenTermOffset toff - let rec unrollTypeDeep (t: typ) : typ = - let rec withAttrs (al: attributes) (t: typ) : typ = - match t with - TNamed (r, a') -> withAttrs (addAttributes al a') r.ttype - | TPtr(t, a') -> TPtr(unrollTypeDeep t, addAttributes al a') - | TArray(t, l, s, a') -> TArray(unrollTypeDeep t, l, s, addAttributes al a') - | TFun(rt, args, isva, a') -> - TFun (unrollTypeDeep rt, - (match args with - None -> None - | Some argl -> - Some (List.map (fun (an,at,aa) -> - (an, unrollTypeDeep at, aa)) argl)), - isva, - addAttributes al a') - | x -> typeAddAttributes al x + and childrenTermOffset vis toff = + let vOffset o = visitCilTermOffset vis o in + let vTerm t = visitCilTerm vis t in + match toff with + TNoOffset -> toff + | TField (fi, t) -> + let t' = vOffset t in + let fi' = vis#behavior.get_fieldinfo fi in + if t' != t || fi != fi' then TField(fi',t') else toff + | TIndex(t,o) -> + let t' = vTerm t in let o' = vOffset o in + if t' != t || o' != o then TIndex(t',o') else toff + + and visitCilLogicInfoUse vis li = + (* First, visit the underlying varinfo to fill the copy tables if needed. *) + let new_v = visitCilLogicVarUse vis li.l_var_info in + let new_li = + doVisitCil vis vis#behavior.get_logic_info + vis#vlogic_info_use alphabetabeta li in - withAttrs [] t + new_li.l_var_info <- new_v; + new_li - let isVoidType t = - match unrollType t with - TVoid _ -> true - | _ -> false - let isVoidPtrType t = - match unrollType t with - TPtr(tau,_) when isVoidType tau -> true - | _ -> false + and visitCilLogicInfo vis li = + (* visit first the underlying varinfo. This will fill internal tables + of copy behavior if needed. + *) + let new_v = visitCilLogicVarDecl vis li.l_var_info in + let res = + doVisitCil + vis vis#behavior.memo_logic_info + vis#vlogic_info_decl childrenLogicInfo li + in res.l_var_info <- new_v; res - let isSignedInteger ty = - match unrollType ty with - | TInt(ik,_attr) -> isSigned ik - | TEnum _ -> theMachine.theMachine.Cil_types.enum_are_signed - | _ -> false + and childrenLogicInfo vis li = + (* NB: underlying varinfo has been already visited. *) + let lt = optMapNoCopy (visitCilLogicType vis) li.l_type in + let lp = mapNoCopy (visitCilLogicVarDecl vis) li.l_profile in + li.l_type <- lt; + li.l_profile <- lp; + li.l_body <- + begin + match li.l_body with + | LBnone -> li.l_body + | LBreads ol -> + let l = mapNoCopy (visitCilIdLocations vis) ol in + if l != ol then LBreads l else li.l_body + | LBterm ot -> + let t = visitCilTerm vis ot in + if t != ot then LBterm t else li.l_body + | LBinductive inddef -> + let i = + mapNoCopy + (fun (id,labs,tvars,p) -> + (id, labs, tvars, visitCilPredicateNamed vis p)) + inddef + in + if i != inddef then LBinductive i else li.l_body + | LBpred odef -> + let def = visitCilPredicateNamed vis odef in + if def != odef then LBpred def else li.l_body + end; + li - let var vi : lval = (Var vi, NoOffset) - (* let assign vi e = Cil_datatype.Instrs(Set (var vi, e), lu) *) + and visitCilLogicTypeInfo vis lt = + doVisitCil vis vis#behavior.memo_logic_type_info + vis#vlogic_type_info_decl childrenLogicTypeInfo lt -let mkString ~loc s = new_exp ~loc (Const(CStr s)) + and childrenLogicTypeInfo vis lt = + let def = optMapNoCopy (visitCilLogicTypeDef vis) lt.lt_def in + lt.lt_def <- def; lt -let mkWhile ~(guard:exp) ~(body: stmt list) : stmt list = - (* Do it like this so that the pretty printer recognizes it *) - [ mkStmt - (Loop ([], - mkBlock - (mkStmt - (If(guard, - mkBlock [ mkEmptyStmt () ], - mkBlock [ mkStmt (Break guard.eloc)], guard.eloc)) :: - body), guard.eloc, None, None)) ] + and visitCilLogicTypeDef vis def = + doVisitCil vis id vis#vlogic_type_def childrenLogicTypeDef def - let mkFor ~(start: stmt list) ~(guard: exp) ~(next: stmt list) - ~(body: stmt list) : stmt list = - (start @ - (mkWhile guard (body @ next))) + and childrenLogicTypeDef vis def = + match def with + | LTsum l -> + let l' = mapNoCopy (visitCilLogicCtorInfoAddTable vis) l in + if l != l' then LTsum l' else def + | LTsyn typ -> + let typ' = visitCilLogicType vis typ in + if typ != typ' then LTsyn typ else def -let mkForIncr ~(iter : varinfo) ~(first: exp) ~stopat:(past: exp) ~(incr: exp) - ~(body: stmt list) : stmt list = - (* See what kind of operator we need *) - let compop, nextop = - match unrollType iter.vtype with - TPtr _ -> Lt, PlusPI - | _ -> Lt, PlusA - in - mkFor - [ mkStmt (Instr (Set (var iter, first, first.eloc))) ] - (new_exp ~loc:past.eloc - (BinOp(compop, new_exp ~loc:past.eloc (Lval(var iter)), past, intType))) - [ mkStmt - (Instr - (Set - (var iter, - (new_exp ~loc:incr.eloc - (BinOp(nextop, - new_exp ~loc:past.eloc (Lval(var iter)), - incr, - iter.vtype))), - incr.eloc)))] - body + and visitCilLogicCtorInfoAddTable vis ctor = + let ctor' = visitCilLogicCtorInfo vis ctor in + if is_copy_behavior vis#behavior then + Queue.add + (fun () -> + Logic_env.add_logic_ctor ctor'.ctor_name ctor') + vis#get_filling_actions; + ctor' - let block_from_unspecified_sequence us = - { battrs = []; bstmts = List.map (fun (x,_,_,_,_) ->x) us; blocals = [] } + and visitCilLogicCtorInfo vis ctor = + doVisitCil vis id vis#vlogic_ctor_info_decl childrenLogicCtorInfo ctor - let rec stripCasts (e: exp) = - match e.enode with CastE(_, e') -> stripCasts e' | _ -> e + and childrenLogicCtorInfo vis ctor = + let ctor_type = doVisitCil vis vis#behavior.get_logic_type_info + vis#vlogic_type_info_use alphabetabeta ctor.ctor_type + in + let ctor_params = mapNoCopy (visitCilLogicType vis) ctor.ctor_params in + if ctor_type != ctor.ctor_type || ctor_params != ctor.ctor_params then + { ctor with ctor_type = ctor_type; ctor_params = ctor_params } + else ctor - let rec stripInfo (e: exp) = - match e.enode with Info(e',_) -> stripInfo e' | _ -> e + and visitCilLogicType vis t = + doVisitCil vis id vis#vlogic_type childrenLogicType t - let rec stripCastsAndInfo (e: exp) = - match e.enode with Info(e',_) | CastE(_,e') -> stripCastsAndInfo e' | _ -> e + and childrenLogicType vis ty = + match ty with + Ctype t -> + let t' = visitCilType vis t in + if t != t' then Ctype t' else ty + | Linteger | Lreal -> ty + | Ltype (s,l) -> + let s' = doVisitCil vis vis#behavior.get_logic_type_info + vis#vlogic_type_info_use alphabetabeta s in + let l' = mapNoCopy (visitCilLogicType vis) l in + if s' != s || l' != l then Ltype (s',l') else ty + | Larrow(args,rttyp) -> + let args' = mapNoCopy(visitCilLogicType vis) args in + let rttyp' = visitCilLogicType vis rttyp in + if args' != args || rttyp' != rttyp then Larrow(args',rttyp') else ty + | Lvar _ -> ty - let rec stripCastsButLastInfo (e: exp) = - match e.enode with - Info({enode = (Info _ | CastE _)} as e',_) - | CastE(_,e') -> - stripCastsButLastInfo e' - | _ -> e + and visitCilLogicVarDecl vis lv = + (* keep names in C and logic worlds in sync *) + (match lv.lv_origin with + None -> () + | Some cv -> lv.lv_name <- cv.vname); + doVisitCil vis vis#behavior.memo_logic_var vis#vlogic_var_decl + childrenLogicVarDecl lv - let rec stripTermCasts (t: term) = - match t.term_node with TCastE(_, t') -> stripTermCasts t' | _ -> t + and childrenLogicVarDecl vis lv = + lv.lv_type <- visitCilLogicType vis lv.lv_type; + lv.lv_origin <- + optMapNoCopy (visitCilVarUse vis) lv.lv_origin; + lv -let exp_info_of_term t = { exp_type = t.term_type; exp_name = t.term_name;} + and visitCilLogicVarUse vis lv = + if vis#behavior.is_copy_behavior && + Logic_env.is_builtin_logic_function lv.lv_name then begin + (* Do as if the variable has been declared. + We'll fill the logic info table of the new project at the end. + Behavior's logic_var table is filled as a side effect. + *) + let siblings = Logic_env.find_all_logic_functions lv.lv_name in + let siblings' = List.map (visitCilLogicInfo vis) siblings in + (*Format.printf "new vars:@."; + List.iter (fun x -> Format.printf "%s#%d@." x.l_var_info.lv_name x.l_var_info.lv_id) siblings'; + *) + Queue.add + (fun () -> + (* Add them to env only once *) + List.iter + (fun x -> + if not (Logic_env.Logic_builtin_used.mem x) then begin + (* Format.printf + "Adding info for %s#%d@." + x.l_var_info.lv_name x.l_var_info.lv_id; *) + Logic_env.Logic_builtin_used.add x; + Logic_env.Logic_info.add x.l_var_info.lv_name x + end) + siblings') + vis#get_filling_actions; + end; + doVisitCil vis vis#behavior.get_logic_var vis#vlogic_var_use + childrenLogicVarUse lv -let term_of_exp_info loc tnode einfo = - { - term_node = tnode; term_loc = loc; - term_type = einfo.exp_type; term_name = einfo.exp_name; - } + and childrenLogicVarUse vis lv = + lv.lv_origin <- optMapNoCopy (visitCilVarUse vis) lv.lv_origin; lv -let map_under_info f e = match e.enode with - | Info(e,einfo) -> new_exp ~loc:e.eloc (Info(f e,einfo)) - | _ -> f e + and visitCilQuantifiers vis lv = + doVisitCil vis id vis#vquantifiers + (fun vis l -> mapNoCopy (visitCilLogicVarDecl vis) l) lv - let app_under_info f e = match e.enode with - | Info(e,_) -> f e - | _ -> f e + and visitCilPredicate vis p = + doVisitCil vis id vis#vpredicate childrenPredicate p - (* the name of the C function we call to get ccgr ASTs - external parse : string -> file = "cil_main" - *) - (* - Pretty Printing - *) + and visitCilPredicateNamed vis p = + doVisitCil vis + id vis#vpredicate_named childrenPredicateNamed p - let d_annotation_status = Cil_datatype.Annotation_status.pretty + and childrenPredicateNamed vis p = + let content = visitCilPredicate vis p.content in + if content != p.content then { p with content = content} else p - let d_ikind fmt c = - fprintf fmt "%s" - ( match c with - | IChar -> "char" - | IBool -> "_Bool" - | ISChar -> "signed char" - | IUChar -> "unsigned char" - | IInt -> "int" - | IUInt -> "unsigned int" - | IShort -> "short" - | IUShort -> "unsigned short" - | ILong -> "long" - | IULong -> "unsigned long" - | ILongLong -> - if theMachine.msvcMode then "__int64" else "long long" - | IULongLong -> - if theMachine.msvcMode then "unsigned __int64" - else "unsigned long long") + and childrenPredicate vis p = + let vPred p = visitCilPredicateNamed vis p in + let vLogicInfo li = visitCilLogicInfoUse vis li in + let vTerm t = visitCilTerm vis t in + match p with + Pfalse | Ptrue -> p + | Papp (pred,labels,args) -> + let pred' = vLogicInfo pred in + let labels' = mapNoCopy (visitCilLogicLabelApp vis) labels in + let args' = mapNoCopy vTerm args in + if pred' != pred || labels' != labels || args' != args then + Papp(pred',labels',args') + else p + | Prel(rel,t1,t2) -> + let t1' = vTerm t1 in + let t2' = vTerm t2 in + if t1' != t1 || t2' != t2 then + Prel(rel,t1',t2') + else p + | Pand(p1,p2) -> + let p1' = vPred p1 in + let p2' = vPred p2 in + if p1' != p1 || p2' != p2 then + Pand(p1',p2') + else p + | Por(p1,p2) -> + let p1' = vPred p1 in + let p2' = vPred p2 in + if p1' != p1 || p2' != p2 then + Por(p1',p2') + else p + | Pxor(p1,p2) -> + let p1' = vPred p1 in + let p2' = vPred p2 in + if p1' != p1 || p2' != p2 then + Pxor(p1',p2') + else p + | Pimplies(p1,p2) -> + let p1' = vPred p1 in + let p2' = vPred p2 in + if p1' != p1 || p2' != p2 then + Pimplies(p1',p2') + else p + | Piff(p1,p2) -> + let p1' = vPred p1 in + let p2' = vPred p2 in + if p1' != p1 || p2' != p2 then + Piff(p1',p2') + else p + | Pnot p1 -> + let p1' = vPred p1 in + if p1' != p1 then Pnot p1' else p + | Pif(t,ptrue,pfalse) -> + let t' = vTerm t in + let ptrue' = vPred ptrue in + let pfalse' = vPred pfalse in + if t' != t || ptrue' != ptrue || pfalse' != pfalse then + Pif(t', ptrue',pfalse') + else p + | Plet(def,p1) -> + let def' = visitCilLogicInfo vis def in + let p1' = vPred p1 in + if def' != def || p1' != p1 then + Plet(def',p1') + else p + | Pforall(quant,p1) -> + let quant' = visitCilQuantifiers vis quant in + let p1' = vPred p1 in + if quant' != quant || p1' != p1 then + Pforall(quant', p1') + else p + | Pexists(quant,p1) -> + let quant' = visitCilQuantifiers vis quant in + let p1' = vPred p1 in + if quant' != quant || p1' != p1 then + Pexists(quant', p1') + else p + | Pat(p1,s) -> + let p1' = vPred p1 in + let s' = visitCilLogicLabel vis s in + if p1' != p1 || s != s' then Pat(p1',s') else p + | Pvalid t -> + let t' = vTerm t in if t' != t then Pvalid t' else p + | Pinitialized t -> + let t' = vTerm t in if t' != t then Pinitialized t' else p + | Pvalid_index (t1,t2) -> + let t1' = vTerm t1 in + let t2' = vTerm t2 in + if t1' != t1 || t2' != t2 then Pvalid_index (t1',t2') else p + | Pvalid_range(t1,t2,t3) -> + let t1' = vTerm t1 in + let t2' = vTerm t2 in + let t3' = vTerm t3 in + if t1' != t1 || t2' != t2 || t3' != t3 then + Pvalid_range (t1',t2',t3') else p + | Pseparated seps -> + let seps' = mapNoCopy vTerm seps in + if seps' != seps then Pseparated seps' else p + | Pfresh t -> + let t' = vTerm t in if t' != t then Pfresh t' else p + | Psubtype(te,tc) -> + let tc' = vTerm tc in + let te' = vTerm te in + if tc' != tc || te' != te then Psubtype(te',tc') else p - let d_fkind fmt = function - FFloat -> fprintf fmt "float" - | FDouble -> fprintf fmt "double" - | FLongDouble -> fprintf fmt "long double" + and visitCilIdLocations vis loc = + let loc' = visitCilTerm vis loc.it_content in + if loc' != loc.it_content then { loc with it_content = loc' } else loc - let d_storage fmt c = - fprintf fmt "%s" - ( match c with - | NoStorage -> "" - | Static -> "static " - | Extern -> "extern " - | Register -> "register ") + and visitCilAssigns vis a = + doVisitCil vis id vis#vassigns childrenAssigns a + and childrenAssigns vis a = + match a with + WritesAny -> a + | Writes l -> + let l' = mapNoCopy (visitCilFrom vis) l in + if l' != l then Writes l' else a - (* sm: need this value below *) - let mostNeg32BitInt : int64 = (Int64.of_string "-0x80000000") - let mostNeg64BitInt : int64 = (Int64.of_string "-0x8000000000000000") +and visitCilFrom vis f = + doVisitCil vis id vis#vfrom childrenFrom f +and childrenFrom vis ((b,f) as a) = + let b' = visitCilIdLocations vis b in + let f' = visitCilDeps vis f in + if b!=b' || f!=f' then (b',f') else a - (* constant *) - let d_const fmt c = - match c with - CInt64(_, _, Some s) -> fprintf fmt "%s" s (* Always print the text if there is one *) - | CInt64(i, ik, None) -> - (*fprintf fmt "/* %Lx */" i;*) - (** We must make sure to capture the type of the constant. For some - * constants this is done with a suffix, for others with a cast prefix.*) - let suffix : string = - match ik with - IUInt -> "U" - | ILong -> "L" - | IULong -> "UL" - | ILongLong -> if theMachine.msvcMode then "L" else "LL" - | IULongLong -> if theMachine.msvcMode then "UL" else "ULL" - | _ -> "" - in - let prefix : string = - if suffix <> "" then "" - else if ik = IInt then "" - else Pretty_utils.sfprintf "(%a)" d_ikind ik - in - (* Watch out here for negative integers that we should be printing as - * large positive ones *) - fprintf fmt "%s" - (if i < Int64.zero - && (match ik with - IUInt | IULong | IULongLong | IUChar | IUShort -> true | _ -> false) then - let high = Int64.shift_right i 32 in - if ik <> IULongLong && ik <> ILongLong && high = Int64.of_int (-1) then - (* Print only the low order 32 bits *) - (prefix ^ "0x" ^ - (Int64.format "%x" - (Int64.logand i (Int64.shift_right_logical high 32)) - ^ suffix)) - else - (prefix ^ "0x" ^ Int64.format "%x" i ^ suffix) - else ( - if (i = mostNeg32BitInt) then - (* sm: quirk here: if you print -2147483648 then this is two tokens *) - (* in C, and the second one is too large to represent in a signed *) - (* int.. so we do what's done in limits.h, and print (-2147483467-1); *) - (* in gcc this avoids a warning, but it might avoid a real problem *) - (* on another compiler or a 64-bit architecture *) - (prefix ^ "(-0x7FFFFFFF-1)") - else if (i = mostNeg64BitInt) then - (* The same is true of the largest 64-bit negative. *) - (prefix ^ "(-0x7FFFFFFFFFFFFFFF-1)") - else - (prefix ^ (Int64.to_string i ^ suffix)) - )) +and visitCilDeps vis d = + doVisitCil vis id vis#vdeps childrenDeps d +and childrenDeps vis d = + match d with + FromAny -> d + | From l -> + let l' = mapNoCopy (visitCilIdLocations vis) l in + if l !=l' then From l' else d - | CStr(s) -> fprintf fmt "\"%s\"" (escape_string s) - | CWStr(s) -> - (* text ("L\"" ^ escape_string s ^ "\"") *) - fprintf fmt "L"; - List.iter - (fun elt -> - if (elt >= Int64.zero && - elt <= (Int64.of_int 255)) then - fprintf fmt "%S" (escape_char (Char.chr (Int64.to_int elt))) - else - fprintf fmt "\"\\x%LX\"" elt; - fprintf fmt "@ ") - s; - (* we cannot print L"\xabcd" "feedme" as L"\xabcdfeedme" -- - * the former has 7 wide characters and the later has 3. *) +and visitCilBehavior vis b = + doVisitCil vis vis#behavior.cfunbehavior + vis#vbehavior childrenBehavior b - | CChr(c) -> fprintf fmt "'%s'" (escape_char c) - | CReal(_, _, Some s) -> fprintf fmt "%s" s - | CReal(f, fsize, None) -> - fprintf fmt "%s%s" (string_of_float f) - (match fsize with - FFloat -> "f" - | FDouble -> "" - | FLongDouble -> "L") - | CEnum {einame = s} -> fprintf fmt "%s" s +and childrenBehavior vis b = + b.b_assumes <- visitCilPredicates vis b.b_assumes; + b.b_requires <- visitCilPredicates vis b.b_requires; + b.b_post_cond <- + mapNoCopy + (function ((k,p) as pc) -> + let p' = visitCilIdPredicate vis p in if p != p' then (k,p') else pc) + b.b_post_cond; + b.b_assigns <- visitCilAssigns vis b.b_assigns; + b.b_extended <- mapNoCopy (visitCilExtended vis) b.b_extended; + b +and visitCilExtended vis (s,id,p as orig) = + let r = mapNoCopy (visitCilIdPredicate vis) p in + if r == p then orig else (s,id,r) - (* Parentheses/precedence level. An expression "a op b" is printed - * parenthesized if its parentheses level is >= that that of its context. - * Identifiers have the lowest level and weakly binding operators (e.g. |) - * have the largest level. The correctness criterion is that a smaller level - * MUST correspond to a stronger precedence! *) +and visitCilPredicates vis ps = mapNoCopy (visitCilIdPredicate vis) ps - let derefStarLevel = 20 - let indexLevel = 20 - let arrowLevel = 20 - let addrOfLevel = 30 - let additiveLevel = 60 - let comparativeLevel = 70 - let bitwiseLevel = 75 - let logic_level = 77 - let binderLevel = 90 - let questionLevel = 100 - let upperLevel = 110 +and visitCilIdPredicate vis ps = + let p' = visitCilPredicate vis ps.ip_content in + if p' != ps.ip_content then { ps with ip_content = p' } else ps - let getParenthLevelPred = function - | Pfalse - | Ptrue - | Papp _ - | Pold _ - | Pvalid _ - | Pseparated _ - | Pat _ - | Pfresh _ - | Pvalid_index _ - | Pvalid_range _ -> 0 + and visitCilBehaviors vis bs = mapNoCopy (visitCilBehavior vis) bs - | Psubtype _ -> 25 + and visitCilFunspec vis s = + doVisitCil vis vis#behavior.cfunspec vis#vspec childrenSpec s - | Pnot _ -> 30 + and childrenSpec vis s = + s.spec_behavior <- visitCilBehaviors vis s.spec_behavior; + s.spec_variant <- + optMapNoCopy (fun x -> (visitCilTerm vis (fst x), snd x)) s.spec_variant; + s.spec_terminates <- + optMapNoCopy (visitCilIdPredicate vis) s.spec_terminates; + (* nothing is done now for behaviors names, no need to visit complete and + disjoint behaviors clauses + *) + s - | Pand _ - | Por _ - | Pxor _ -> 40 + and visitCilSlicePragma vis p = + doVisitCil vis id vis#vslice_pragma childrenSlicePragma p - | Pimplies _ -> 50 - | Piff _ -> 60 - | Pif _ -> questionLevel + and childrenSlicePragma vis p = + match p with + | SPexpr t -> + let t' = visitCilTerm vis t in if t' != t then SPexpr t' else p + | SPctrl | SPstmt -> p - | Prel _ -> 0 + and visitCilImpactPragma vis p = + doVisitCil vis id vis#vimpact_pragma childrenImpactPragma p - | Plet _ - | Pforall _ - | Pexists _ -> binderLevel - - let getParenthLevel e = match (stripInfo e).enode with - | Info _ -> assert false - | BinOp((LAnd | LOr), _,_,_) -> 80 - (* Bit operations. *) - | BinOp((BOr|BXor|BAnd),_,_,_) -> bitwiseLevel (* 75 *) - - (* Comparisons *) - | BinOp((Eq|Ne|Gt|Lt|Ge|Le),_,_,_) -> - comparativeLevel (* 70 *) - (* Additive. Shifts can have higher - * level than + or - but I want - * parentheses around them *) - | BinOp((MinusA|MinusPP|MinusPI|PlusA| - PlusPI|IndexPI|Shiftlt|Shiftrt),_,_,_) - -> additiveLevel (* 60 *) - - (* Multiplicative *) - | BinOp((Div|Mod|Mult),_,_,_) -> 40 - - (* Unary *) - | CastE(_,_) -> 30 - | AddrOf(_) -> 30 - | StartOf(_) -> 30 - | UnOp((Neg|BNot|LNot),_,_) -> 30 - - (* Lvals *) - | Lval(Mem _ , _) -> derefStarLevel (* 20 *) - | Lval(Var _, (Field _|Index _)) -> indexLevel (* 20 *) - | SizeOf _ | SizeOfE _ | SizeOfStr _ -> 20 - | AlignOf _ | AlignOfE _ -> 20 - - | Lval(Var _, NoOffset) -> 0 (* Plain variables *) - | Const _ -> 0 (* Constants *) - - let getParenthLevelLogic = function - | Tlambda _ | Trange _ | Tlet _ -> binderLevel - | TBinOp((LAnd | LOr), _,_) -> 80 - (* Bit operations. *) - | TBinOp((BOr|BXor|BAnd),_,_) -> bitwiseLevel (* 75 *) + and childrenImpactPragma vis p = match p with + | IPexpr t -> let t' = visitCilTerm vis t in if t' != t then IPexpr t' else p + | IPstmt -> p - (* Comparisons *) - | TBinOp((Eq|Ne|Gt|Lt|Ge|Le),_,_) -> - comparativeLevel (* 70 *) - (* Additive. Shifts can have higher - * level than + or - but I want - * parentheses around them *) - | TBinOp((MinusA|MinusPP|MinusPI|PlusA| - PlusPI|IndexPI|Shiftlt|Shiftrt),_,_) - -> additiveLevel (* 60 *) + and visitCilLoopPragma vis p = + doVisitCil vis + id vis#vloop_pragma childrenLoopPragma p - (* Multiplicative *) - | TBinOp((Div|Mod|Mult),_,_) -> 40 + and childrenLoopPragma vis p = + match p with + | Unroll_level t -> let t' = visitCilTerm vis t in + if t' != t then Unroll_level t' else p + | Widen_hints lt -> let lt' = List.map (visitCilTerm vis) lt in + if lt' != lt then Widen_hints lt' else p + | Widen_variables lt -> let lt' = List.map (visitCilTerm vis) lt in + if lt' != lt then Widen_variables lt' else p - (* Unary *) - | TCastE(_,_) -> 30 - | TAddrOf(_) -> addrOfLevel - | TStartOf(_) -> 30 - | TUnOp((Neg|BNot|LNot),_) -> 30 - (* Unary post *) - | TCoerce _ | TCoerceE _ -> 25 + and visitCilAnnotation vis a = + let oldloc = CurrentLoc.get () in + CurrentLoc.set (Global_annotation.loc a); + let res = doVisitCil vis id vis#vannotation childrenAnnotation a in + CurrentLoc.set oldloc; + res - (* Lvals *) - | TLval(TMem _ , _) -> derefStarLevel - | TLval(TVar _, (TField _|TIndex _)) -> indexLevel - | TLval(TResult _,(TField _|TIndex _)) -> indexLevel - | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ -> 20 - | TAlignOf _ | TAlignOfE _ -> 20 - (* VP: I'm not sure I understand why sizeof(x) and f(x) should - have a separated treatment wrt parentheses. *) - (* application and applications-like constructions *) - | Tapp (_, _,_)|TDataCons _ - | Tblock_length _ | Tbase_addr _ | Tat (_, _) | Told _ - | Tunion _ | Tinter _ - | TUpdate _ | Ttypeof _ | Ttype _ -> 10 - | TLval(TVar _, TNoOffset) -> 0 (* Plain variables *) - (* Constructions that do not require parentheses *) - | TConst _ - | Tnull | TLval (TResult _,TNoOffset) | Tcomprehension _ | Tempty_set -> 0 - | Tif (_, _, _) -> logic_level + and visitCilAxiom vis ((id,p) as a) = + let p' = visitCilPredicateNamed vis p in + if p' != p then (id,p') else a - let getParenthLevelAttrParam (a: attrparam) = - (* Create an expression of the same shape, and use {!getParenthLevel} *) + and childrenAnnotation vis a = match a with - AInt _ | AStr _ | ACons _ -> 0 - | ASizeOf _ | ASizeOfE _ | ASizeOfS _ -> 20 - | AAlignOf _ | AAlignOfE _ | AAlignOfS _ -> 20 - | AUnOp (uo, _) -> getParenthLevel - (dummy_exp (UnOp(uo, zero ~loc:Cil_datatype.Location.unknown, intType))) - | ABinOp (bo, _, _) -> - getParenthLevel (dummy_exp(BinOp(bo, - zero ~loc:Cil_datatype.Location.unknown, - zero ~loc:Cil_datatype.Location.unknown, - intType))) - | AAddrOf _ -> 30 - | ADot _ | AIndex _ | AStar _ -> 20 - | AQuestion _ -> questionLevel + | Dfun_or_pred (li,loc) -> + let li' = visitCilLogicInfo vis li in + if vis#behavior.is_copy_behavior then + Queue.add + (fun () -> + Logic_env.add_logic_function_gen alphabetafalse li') + vis#get_filling_actions; + if li' != li then Dfun_or_pred (li',loc) else a + | Dtype (ti,loc) -> + let ti' = visitCilLogicTypeInfo vis ti in + if vis#behavior.is_copy_behavior then + Queue.add + (fun () -> + Logic_env.add_logic_type ti'.lt_name ti') + vis#get_filling_actions; + if ti' != ti then Dtype (ti',loc) else a + | Dlemma(s,is_axiom,labels,tvars,p,loc) -> + let p' = visitCilPredicateNamed vis p in + if p' != p then Dlemma(s,is_axiom,labels,tvars,p',loc) else a + | Dinvariant (p,loc) -> + let p' = visitCilLogicInfo vis p in + if vis#behavior.is_copy_behavior then + Queue.add + (fun () -> Logic_env.add_logic_function_gen alphabetafalse p') + vis#get_filling_actions; + if p' != p then Dinvariant (p',loc) else a + | Dtype_annot (ta,loc) -> + let ta' = visitCilLogicInfo vis ta in + if vis#behavior.is_copy_behavior then + Queue.add + (fun () -> Logic_env.add_logic_function_gen alphabetafalse ta') + vis#get_filling_actions; + if ta' != ta then Dtype_annot (ta',loc) else a + | Dmodel_annot (mfi,loc) -> + let mfi' = visitCilLogicInfo vis mfi in + if vis#behavior.is_copy_behavior then + Queue.add + (fun () -> Logic_env.add_logic_function_gen + alphabetafalse mfi') + vis#get_filling_actions; + if mfi' != mfi then Dmodel_annot (mfi',loc) else a + | Dvolatile(tset,rvi,wvi,loc) -> + let tset' = mapNoCopy (visitCilIdLocations vis) tset in + let rvi' = optMapNoCopy (visitCilVarUse vis) rvi in + let wvi' = optMapNoCopy (visitCilVarUse vis) wvi in + if tset' != tset || rvi' != rvi || wvi' != wvi then + Dvolatile(tset',rvi',wvi',loc) + else a + | Daxiomatic(id,l,loc) -> + (* + Format.eprintf "cil.visitCilAnnotation on axiomatic %s@." id; + *) + let l' = mapNoCopy (visitCilAnnotation vis) l in + if l' != l then Daxiomatic(id,l',loc) else a + and visitCilCodeAnnotation vis ca = + doVisitCil vis id vis#vcode_annot childrenCodeAnnot ca - (* Separate out the storage-modifier name attributes *) - let separateStorageModifiers (al: attribute list) = - let isstoragemod (Attr(an, _) | AttrAnnot an : attribute) : bool = - try - match Hashtbl.find attributeHash an with - AttrName issm -> issm - | _ -> false - with Not_found -> false - in - let stom, rest = List.partition isstoragemod al in - if not theMachine.msvcMode then - stom, rest - else - (* Put back the declspec. Put it without the leading __ since these will - * be added later *) - let stom' = - List.map - (function - | Attr(an, args) -> Attr("declspec", [ACons(an, args)]) - | AttrAnnot _ -> assert false) - stom - in - stom', rest + and childrenCodeAnnot vis ca = + let vPred p = visitCilPredicateNamed vis p in + let vTerm t = visitCilTerm vis t in + let vSpec s = visitCilFunspec vis s in + let change_content annot = { ca with annot_content = annot } in + match ca.annot_content with + AAssert (behav,p) -> + let p' = vPred p in if p' != p then + change_content (AAssert (behav,p')) + else ca + | APragma (Impact_pragma t) -> + let t' = visitCilImpactPragma vis t in + if t' != t then change_content (APragma (Impact_pragma t')) else ca + | APragma (Slice_pragma t) -> + let t' = visitCilSlicePragma vis t in + if t' != t then change_content (APragma (Slice_pragma t')) else ca + | APragma (Loop_pragma p) -> + let p' = visitCilLoopPragma vis p in + if p' != p then change_content (APragma (Loop_pragma p')) else ca + | AStmtSpec (behav,s) -> + let s' = vSpec s in + if s' != s then change_content (AStmtSpec (behav,s')) else ca + | AInvariant(behav,f,p) -> + let p' = vPred p in + if p' != p then change_content (AInvariant (behav,f,p')) else ca + | AVariant ((t,s)) -> + let t' = vTerm t in + if t != t' then change_content (AVariant ((t',s))) else ca + | AAssigns(behav, a) -> + let a' = visitCilAssigns vis a in + if a != a' then change_content (AAssigns (behav,a')) else ca +and visitCilExpr (vis: cilVisitor) (e: exp) : exp = + let oldLoc = CurrentLoc.get () in + CurrentLoc.set e.eloc; + let res = doVisitCil vis id vis#vexpr childrenExp e in + CurrentLoc.set oldLoc; res - let isCharType t = - match unrollType t with - | TInt((IChar|ISChar|IUChar),_) -> true - | _ -> false +and childrenExp (vis: cilVisitor) (e: exp) : exp = + let vExp e = visitCilExpr vis e in + let vTyp t = visitCilType vis t in + let vLval lv = visitCilLval vis lv in + let new_exp e' = { e with enode = e' } in + match (stripInfo e).enode with + | Info _ -> assert false + | Const c -> + let c' = visitCilConst vis c in + if c' != c then new_exp (Const c') else e + | SizeOf t -> + let t'= vTyp t in + if t' != t then new_exp (SizeOf t') else e + | SizeOfE e1 -> + let e1' = vExp e1 in + if e1' != e1 then new_exp (SizeOfE e1') else e + | SizeOfStr _s -> e -let isShortType t = - match unrollType t with - | TInt((IUShort|IShort),_) -> true - | _ -> false + | AlignOf t -> + let t' = vTyp t in + if t' != t then new_exp (AlignOf t') else e + | AlignOfE e1 -> + let e1' = vExp e1 in + if e1' != e1 then new_exp (AlignOfE e1') else e + | Lval lv -> + let lv' = vLval lv in + if lv' != lv then new_exp (Lval lv') else e + | UnOp (uo, e1, t) -> + let e1' = vExp e1 in let t' = vTyp t in + if e1' != e1 || t' != t then new_exp (UnOp(uo, e1', t')) else e + | BinOp (bo, e1, e2, t) -> + let e1' = vExp e1 in let e2' = vExp e2 in let t' = vTyp t in + if e1' != e1 || e2' != e2 || t' != t then + new_exp (BinOp(bo, e1',e2',t')) + else e + | CastE (t, e1) -> + let t' = vTyp t in let e1' = vExp e1 in + if t' != t || e1' != e1 then new_exp (CastE(t', e1')) else e + | AddrOf lv -> + let lv' = vLval lv in + if lv' != lv then new_exp (AddrOf lv') else e + | StartOf lv -> + let lv' = vLval lv in + if lv' != lv then new_exp (StartOf lv') else e -let isCharPtrType t = - match unrollType t with - TPtr(tau,_) when isCharType tau -> true - | _ -> false - - let isIntegralType t = - match unrollType t with - (TInt _ | TEnum _) -> true - | _ -> false - - let isLogicIntegralType t = - match t with - | Ctype t -> isIntegralType t - | Linteger -> true - | Lreal -> false - | Lvar _ | Ltype _ | Larrow _ -> false - - let isFloatingType t = - match unrollType t with - TFloat _ -> true - | _ -> false - - let isLogicFloatType t = - match t with - | Ctype t -> isFloatingType t - | Linteger -> false - | Lreal -> false - | Lvar _ | Ltype _ | Larrow _ -> false - - let isLogicRealOrFloatType t = - match t with - | Ctype t -> isFloatingType t - | Linteger -> false - | Lreal -> true - | Lvar _ | Ltype _ | Larrow _ -> false - - let isLogicRealType t = - match t with - | Ctype _ -> false - | Linteger -> false - | Lreal -> true - | Lvar _ | Ltype _ | Larrow _ -> false - - let isArithmeticType t = - match unrollType t with - (TInt _ | TEnum _ | TFloat _) -> true - | _ -> false - - let isLogicArithmeticType t = - match t with - | Ctype t -> isArithmeticType t - | Linteger | Lreal -> true - | Lvar _ | Ltype _ | Larrow _ -> false - - let isPointerType t = - match unrollType t with - TPtr _ -> true - | _ -> false - - let isTypeTagType t = - match t with - Ltype({lt_name = "typetag"},[]) -> true - | _ -> false - - let isFunctionType t = - match unrollType t with - TFun _ -> true - | _ -> false - - let getReturnType t = - match unrollType t with - | TFun(rt,_,_,_) -> rt - | _ -> Cilmsg.fatal "getReturnType: not a function type" - - let setReturnTypeVI (v: varinfo) (t: typ) = - match unrollType v.vtype with - | TFun (_, args, va, a) -> - v.vtype <- TFun (t, args, va, a) - | _ -> Cilmsg.fatal "setReturnType: not a function type" - - let setReturnType (f:fundec) (t:typ) = - setReturnTypeVI f.svar t - - (** Returns the type pointed by the given type. Asserts it is a pointer type *) - let typeOf_pointed typ = - match unrollType typ with - | TPtr (typ,_) -> typ - | _ -> assert false - - (** Returns the type of the elements of the array. Asserts it is an array type - *) - let typeOf_array_elem t = - match unrollType t with - | TArray (ty_elem, _, _, _) -> ty_elem - | _ -> assert false - - - (**** Compute the type of an expression ****) - let rec typeOf (e: exp) : typ = - match (stripInfo e).enode with - | Info _ -> assert false - | Const(CInt64 (_, ik, _)) -> TInt(ik, []) + and visitCilInit (vis: cilVisitor) (forglob: varinfo) + (atoff: offset) (i: init) : init = + let rec childrenInit (vis: cilVisitor) (i: init) : init = + let fExp e = visitCilExpr vis e in + let fTyp t = visitCilType vis t in + match i with + | SingleInit e -> + let e' = fExp e in + if e' != e then SingleInit e' else i + | CompoundInit (t, initl) -> + let t' = fTyp t in + (* Collect the new initializer list, in reverse. We prefer two + * traversals to ensure tail-recursion. *) + let newinitl : (offset * init) list ref = ref [] in + (* Keep track whether the list has changed *) + let hasChanged = ref false in + let doOneInit ((o, i) as oi) = + let o' = visitCilInitOffset vis o in (* use initializer version *) + let i' = visitCilInit vis forglob (addOffset o' atoff) i in + let newio = + if o' != o || i' != i then + begin hasChanged := true; (o', i') end else oi + in + newinitl := newio :: !newinitl + in + List.iter doOneInit initl; + let initl' = if !hasChanged then List.rev !newinitl else initl in + if t' != t || initl' != initl then CompoundInit (t', initl') else i + in + doVisitCil vis id (vis#vinit forglob atoff) childrenInit i - (* Character constants have type int. ISO/IEC 9899:1999 (E), - * section 6.4.4.4 [Character constants], paragraph 10, if you - * don't believe me. *) - | Const(CChr _) -> intType + and visitCilLval (vis: cilVisitor) (lv: lval) : lval = + doVisitCil vis id vis#vlval childrenLval lv + and childrenLval (vis: cilVisitor) (lv: lval) : lval = + (* and visit its subexpressions *) + let vExp e = visitCilExpr vis e in + let vOff off = visitCilOffset vis off in + match lv with + Var v, off -> + let v'= visitCilVarUse vis v in + let off' = vOff off in + if v' != v || off' != off then Var v', off' else lv + | Mem e, off -> + let e' = vExp e in + let off' = vOff off in + if e' != e || off' != off then Mem e', off' else lv - (* The type of a string is a pointer to characters ! The only case when - * you would want it to be an array is as an argument to sizeof, but we - * have SizeOfStr for that *) - | Const(CStr _s) -> theMachine.stringLiteralType + and visitCilOffset (vis: cilVisitor) (off: offset) : offset = + doVisitCil vis id vis#voffs childrenOffset off + and childrenOffset (vis: cilVisitor) (off: offset) : offset = + let vOff off = visitCilOffset vis off in + match off with + Field (f, o) -> + let o' = vOff o in + let f' = vis#behavior.get_fieldinfo f in + if o' != o || f' != f then Field (f', o') else off + | Index (e, o) -> + let e' = visitCilExpr vis e in + let o' = vOff o in + if e' != e || o' != o then Index (e', o') else off + | NoOffset -> off - | Const(CWStr _s) -> TPtr(theMachine.wcharType,[]) + (* sm: for offsets in initializers, the 'startvisit' will be the + * vinitoffs method, but we can re-use the childrenOffset from + * above since recursive offsets are visited by voffs. (this point + * is moot according to cil.mli which claims the offsets in + * initializers will never recursively contain offsets) + *) + and visitCilInitOffset (vis: cilVisitor) (off: offset) : offset = + doVisitCil vis id vis#vinitoffs childrenOffset off - | Const(CReal (_, fk, _)) -> TFloat(fk, []) + and visitCilInstr (vis: cilVisitor) (i: instr) : instr list = + let oldloc = CurrentLoc.get () in + CurrentLoc.set (Cil_datatype.Instr.loc i); + assertEmptyQueue vis; + let res = + doVisitListCil vis id vis#vinst childrenInstr i in + CurrentLoc.set oldloc; + (* See if we have accumulated some instructions *) + vis#unqueueInstr () @ res - | Const(CEnum {eihost = ei}) -> TEnum(ei, []) + and childrenInstr (vis: cilVisitor) (i: instr) : instr = + let fExp = visitCilExpr vis in + let fLval = visitCilLval vis in + match i with + | Skip _l -> + i + | Set(lv,e,l) -> + let lv' = fLval lv in let e' = fExp e in + if lv' != lv || e' != e then Set(lv',e',l) else i + | Call(None,f,args,l) -> + let f' = fExp f in let args' = mapNoCopy fExp args in + if f' != f || args' != args then Call(None,f',args',l) else i + | Call(Some lv,fn,args,l) -> + let lv' = fLval lv in let fn' = fExp fn in + let args' = mapNoCopy fExp args in + if lv' != lv || fn' != fn || args' != args + then Call(Some lv', fn', args', l) else i - | Lval(lv) -> typeOfLval lv - | SizeOf _ | SizeOfE _ | SizeOfStr _ -> theMachine.typeOfSizeOf - | AlignOf _ | AlignOfE _ -> theMachine.typeOfSizeOf - | UnOp (_, _, t) -> t - | BinOp (_, _, _, t) -> t - | CastE (t, _) -> t - | AddrOf (lv) -> TPtr(typeOfLval lv, []) - | StartOf (lv) -> - begin - match unrollType (typeOfLval lv) with - TArray (t,_,_, _) -> TPtr(t, []) - | _ -> fatal "typeOf: StartOf on a non-array" - end + | Asm(sl,isvol,outs,ins,clobs,l) -> + let outs' = mapNoCopy (fun ((id,s,lv) as pair) -> + let lv' = fLval lv in + if lv' != lv then (id,s,lv') else pair) outs in + let ins' = mapNoCopy (fun ((id,s,e) as pair) -> + let e' = fExp e in + if e' != e then (id,s,e') else pair) ins in + if outs' != outs || ins' != ins then + Asm(sl,isvol,outs',ins',clobs,l) else i + | Code_annot (a,l) -> + let a' = visitCilCodeAnnotation vis a in Code_annot(a',l) - and typeOfInit (i: init) : typ = - match i with - SingleInit e -> typeOf e - | CompoundInit (t, _) -> t - and typeOfLval = function - Var vi, off -> typeOffset vi.vtype off - | Mem addr, off -> begin - match unrollType (typeOf addr) with - TPtr (t, _) -> typeOffset t off - | _ -> fatal "typeOfLval: Mem on a non-pointer (%a)" !pd_exp addr - end + (* visit all nodes in a Cil statement tree in preorder *) + and visitCilStmt (vis:cilVisitor) (s: stmt) : stmt = + let oldloc = CurrentLoc.get () in + CurrentLoc.set (Stmt.loc s) ; + vis#push_stmt s; (*(vis#behavior.memo_stmt s);*) + assertEmptyQueue vis; + let toPrepend : instr list ref = ref [] in (* childrenStmt may add to this *) + let res = + doVisitCil vis + vis#behavior.memo_stmt vis#vstmt (childrenStmt toPrepend) s in + (* Now see if we have saved some instructions *) + toPrepend := !toPrepend @ vis#unqueueInstr (); + (match !toPrepend with + [] -> () (* Return the same statement *) + | _ -> + (* Make our statement contain the instructions to prepend *) + res.skind <- + Block (mkBlock + ((List.map (fun i -> mkStmt (Instr i)) !toPrepend) @ + [ mkStmt res.skind ] ))); + CurrentLoc.set oldloc; + vis#pop_stmt s; + res - and typeOffset basetyp = - let blendAttributes baseAttrs = - let (_, _, contageous) = - partitionAttributes ~default:(AttrName false) baseAttrs in - typeAddAttributes contageous + and childrenStmt (toPrepend: instr list ref) (vis:cilVisitor) (s:stmt): stmt = + let fExp e = (visitCilExpr vis e) in + let fBlock b = visitCilBlock vis b in + let fInst i = visitCilInstr vis i in + let fLoopAnnot a = mapNoCopy (visitCilCodeAnnotation vis) a in + (* Just change the statement kind *) + let skind' = + match s.skind with + Break _ | Continue _ | Return (None, _) -> s.skind + | UnspecifiedSequence seq -> + let seq' = + mapNoCopy + (function (stmt,modified,writes,reads,calls) as orig-> + let stmt' = visitCilStmt vis stmt in + (* might make sense for the default to be + to just copy the varinfo when using the copy visitor, + and not apply vvrbl, i.e. not using vis but generic_visitor ? + *) + let modified' = mapNoCopy (visitCilLval vis) modified in + let writes' = mapNoCopy (visitCilLval vis) writes in + let reads' = mapNoCopy (visitCilLval vis) reads in + let calls' = + if vis#behavior.is_copy_behavior then + (* we need new references anyway, no need for mapNoCopy *) + List.map (fun x -> ref (vis#behavior.memo_stmt !x)) calls + else calls + in + if stmt' != stmt || writes' != writes || reads' != reads || + modified != modified' || calls' != calls + then + (stmt',modified', writes',reads',calls') + else orig) + seq + in + if seq' != seq then UnspecifiedSequence seq' else s.skind + | Goto (sr,l) -> + if vis#behavior.is_copy_behavior then + Goto(ref (vis#behavior.memo_stmt !sr),l) + else s.skind + | Return (Some e, l) -> + let e' = fExp e in + if e' != e then Return (Some e', l) else s.skind + | Loop (a, b, l, s1, s2) -> + let a' = fLoopAnnot a in + let b' = fBlock b in + if a' != a || b' != b then Loop (a', b', l, s1, s2) else s.skind + | If(e, s1, s2, l) -> + let e' = fExp e in + (*if e queued any instructions, pop them here and remember them so that + they are inserted before the If stmt, not in the then block. *) + toPrepend := vis#unqueueInstr (); + let s1'= fBlock s1 in let s2'= fBlock s2 in + (* the stmts in the blocks should have cleaned up after themselves.*) + assertEmptyQueue vis; + if e' != e || s1' != s1 || s2' != s2 then + If(e', s1', s2', l) else s.skind + | Switch (e, b, stmts, l) -> + let e' = fExp e in + toPrepend := vis#unqueueInstr (); (* insert these before the switch *) + let b' = fBlock b in + (* the stmts in b should have cleaned up after themselves.*) + assertEmptyQueue vis; + let stmts' = mapNoCopy (visitCilStmt vis#plain_copy_visitor) stmts in + if e' != e || b' != b || stmts' != stmts then + Switch (e', b', stmts', l) else s.skind + | Instr i -> + begin match fInst i with + | [i'] when i' == i -> s.skind + | il -> stmt_of_instr_list ~loc:(Cil_datatype.Instr.loc i) il + end + | Block b -> + let b' = fBlock b in + if b' != b then Block b' else s.skind + | TryFinally (b, h, l) -> + let b' = fBlock b in + let h' = fBlock h in + if b' != b || h' != h then TryFinally(b', h', l) else s.skind + | TryExcept (b, (il, e), h, l) -> + let b' = fBlock b in + assertEmptyQueue vis; + (* visit the instructions *) + let il' = mapNoCopyList fInst il in + (* Visit the expression *) + let e' = fExp e in + let il'' = + let more = vis#unqueueInstr () in + if more != [] then + il' @ more + else + il' + in + let h' = fBlock h in + (* Now collect the instructions *) + if b' != b || il'' != il || e' != e || h' != h then + TryExcept(b', (il'', e'), h', l) + else s.skind in - function - NoOffset -> basetyp - | Index (_, o) -> begin - match unrollType basetyp with - TArray (t, _, _, baseAttrs) -> - let elementType = typeOffset t o in - blendAttributes baseAttrs elementType - | _ -> fatal "typeOffset: Index on a non-array" - end - | Field (fi, o) -> - match unrollType basetyp with - TComp (_, _,baseAttrs) -> - let fieldType = typeOffset fi.ftype o in - let typ = blendAttributes baseAttrs fieldType in - (match fi.fbitfield with - | Some s -> - typeAddAttributes [Attr ("FRAMA_C_BITFIELD_SIZE", [AInt s])] typ - | None -> typ) - | _ -> fatal "typeOffset: Field %s on a non-compound type '%a'" - fi.fname !pd_type basetyp - - (**** Compute the type of a term lval ****) - let rec typeOfTermLval = function - TVar vi, off -> - let ty = match vi.lv_origin with - | Some v -> Ctype v.vtype - | None -> vi.lv_type - in - typeTermOffset ty off - | TResult ty, off -> typeTermOffset (Ctype ty) off - | TMem addr, off -> begin - match addr.term_type with - | Ctype typ -> - begin match unrollType typ with - TPtr (t, _) -> typeTermOffset (Ctype t) off - | _ -> fatal "typeOfTermLval: Mem on a non-pointer" - end - | Linteger | Lreal -> fatal "typeOfTermLval: Mem on a logic type" - | Ltype (s,_) -> fatal "typeOfTermLval: Mem on a non-C type (%s)" s.lt_name - | Lvar s -> fatal "typeOfTermLval: Mem on a non-C type ('%s)" s - | Larrow _ -> fatal "typeOfTermLval: Mem on a function type" - end - - and typeTermOffset basetyp = - let blendAttributes baseAttrs = - let (_, _, contageous) = - partitionAttributes ~default:(AttrName false) baseAttrs in - function - | Ctype typ -> - Ctype (typeAddAttributes contageous typ) - | Linteger | Lreal -> fatal "typeTermOffset: Attribute on a logic type" - | Ltype (s,_) -> fatal "typeTermOffset: Attribute on a non-C type (%s)" s.lt_name - | Lvar s -> fatal "typeTermOffset: Attribute on a non-C type ('%s)" s - | Larrow _ -> fatal "typeTermOffset: Attribute on a function type" + if skind' != s.skind then s.skind <- skind'; + (* Visit the labels *) + let labels' = + let fLabel = function + Case (e, l) as lb -> + let e' = fExp e in + if e' != e then Case (e', l) else lb + | lb -> lb + in + mapNoCopy fLabel s.labels in - function - TNoOffset -> basetyp - | TIndex (_, o) -> begin - match basetyp with - | Ctype typ -> - begin match unrollType typ with - TArray (t, _, _, baseAttrs) -> - let elementType = typeTermOffset (Ctype t) o in - blendAttributes baseAttrs elementType - | _ -> fatal "typeTermOffset: Index on a non-array" - end - | Linteger | Lreal -> fatal "typeTermOffset: Index on a logic type" - | Ltype (s,_) -> fatal "typeTermOffset: Index on a non-C type (%s)" s.lt_name - | Lvar s -> fatal "typeTermOffset: Index on a non-C type ('%s)" s - | Larrow _ -> fatal "typeTermOffset: Index on a function type" - end - | TField (fi, o) -> - match basetyp with - | Ctype typ -> - begin match unrollType typ with - TComp (_, _, baseAttrs) -> - let fieldType = typeTermOffset (Ctype fi.ftype) o in - blendAttributes baseAttrs fieldType - | _ -> fatal "typeTermOffset: Field on a non-compound" - end - | Linteger | Lreal -> fatal "typeTermOffset: Field on a logic type" - | Ltype (s,_) -> fatal "typeTermOffset: Field on a non-C type (%s)" s.lt_name - | Lvar s -> fatal "typeTermOffset: Field on a non-C type ('%s)" s - | Larrow _ -> fatal "typeTermOffset: Field on a function type" - - (** - ** - ** MACHINE DEPENDENT PART - ** - **) - exception SizeOfError of string * typ - let empty_size_cache () = {scache=Not_Computed} - let find_size_in_cache s f = - match s.scache with - | Not_Computed -> - let r = - try - f () - with SizeOfError _ as e -> - s.scache <- Not_Computable e; - raise e - in - s.scache <- Computed r; - r - | Not_Computable e -> raise e - | Computed r -> r - - (* Get the minimum aligment in bytes for a given type *) - let rec alignOf_int = function - | TInt((IChar|ISChar|IUChar|IBool), _) -> 1 - | TInt((IShort|IUShort), _) -> theMachine.theMachine.alignof_short - | TInt((IInt|IUInt), _) -> theMachine.theMachine.alignof_int - | TInt((ILong|IULong), _) -> theMachine.theMachine.alignof_long - | TInt((ILongLong|IULongLong), _) -> - theMachine.theMachine.alignof_longlong - | TEnum _ -> theMachine.theMachine.alignof_enum - | TFloat(FFloat, _) -> theMachine.theMachine.alignof_float - | TFloat(FDouble, _) -> theMachine.theMachine.alignof_double - | TFloat(FLongDouble, _) -> - theMachine.theMachine.alignof_longdouble - | TNamed (t, _) -> alignOf_int t.ttype - | TArray (t, _, _, _) -> (* Be careful for char[] of Diab-C like compilers. *) - begin - match unrollType t with - | TInt((IChar|ISChar|IUChar),_) -> - theMachine.theMachine.alignof_char_array - | _ -> alignOf_int t - end + if labels' != s.labels then s.labels <- labels'; + s - | TPtr _ | TBuiltin_va_list _ -> - theMachine.theMachine.alignof_ptr - (* For composite types get the maximum alignment of any field inside *) - | TComp (c, _, _) -> - (* On GCC the zero-width fields do not contribute to the alignment. On - * MSVC only those zero-width that _do_ appear after other - * bitfields contribute to the alignment. So we drop those that - * do not occur after othe bitfields *) - (* This is not correct for Diab-C compiler. *) - let rec dropZeros (afterbitfield: bool) = function - | f :: rest when f.fbitfield = Some 0 && not afterbitfield -> - dropZeros afterbitfield rest - | f :: rest -> f :: dropZeros (f.fbitfield <> None) rest - | [] -> [] - in - let fields = dropZeros false c.cfields in - List.fold_left - (fun sofar f -> - (* Bitfields with zero width do not contribute to the alignment in - * GCC *) - if not theMachine.msvcMode && f.fbitfield = Some 0 then sofar else - max sofar (alignOf_int f.ftype)) 1 fields - (* These are some error cases *) - | TFun _ when not theMachine.msvcMode -> - theMachine.theMachine.alignof_fun - | TFun _ as t -> raise (SizeOfError ("function", t)) - | TVoid _ as t -> raise (SizeOfError ("void", t)) + and visitCilBlock (vis: cilVisitor) (b: block) : block = + doVisitCil vis vis#behavior.cblock vis#vblock childrenBlock b + and childrenBlock (vis: cilVisitor) (b: block) : block = + let fStmt s = visitCilStmt vis s in + let locals' = mapNoCopy (vis#behavior.get_varinfo) b.blocals in + let stmts' = mapNoCopy fStmt b.bstmts in + if stmts' != b.bstmts || locals' != b.blocals then + { battrs = b.battrs; bstmts = stmts'; blocals = locals' } + else b - let bitsSizeOfInt (ik: ikind): int = - match ik with - | IBool | IChar | ISChar | IUChar -> 8 - | IInt | IUInt -> 8 * theMachine.theMachine.sizeof_int - | IShort | IUShort -> 8 * theMachine.theMachine.sizeof_short - | ILong | IULong -> 8 * theMachine.theMachine.sizeof_long - | ILongLong | IULongLong -> - 8 * theMachine.theMachine.sizeof_longlong - let unsignedVersionOf (ik:ikind): ikind = - match ik with - | ISChar | IChar -> IUChar - | IShort -> IUShort - | IInt -> IUInt - | ILong -> IULong - | ILongLong -> IULongLong - | _ -> ik + and visitCilType (vis : cilVisitor) (t : typ) : typ = + doVisitCil vis id vis#vtype childrenType t + and childrenType (vis : cilVisitor) (t : typ) : typ = + (* look for types referred to inside t's definition *) + let fTyp t = visitCilType vis t in + let fAttr a = visitCilAttributes vis a in + match t with + TPtr(t1, a) -> + let t1' = fTyp t1 in + let a' = fAttr a in + if t1' != t1 || a' != a then TPtr(t1', a') else t + | TArray(t1, None, _, a) -> + let t1' = fTyp t1 in + let a' = fAttr a in + if t1' != t1 || a' != a then TArray(t1', None, empty_size_cache (), a') else t + | TArray(t1, Some e, _, a) -> + let t1' = fTyp t1 in + let e' = visitCilExpr vis e in + let a' = fAttr a in + if t1' != t1 || e' != e || a' != a then TArray(t1', Some e',empty_size_cache (), a') else t - (* Represents an integer as for a given kind. - Returns a flag saying whether the value was changed - during truncation (because it was too large to fit in k). *) - let truncateInteger64 (k: ikind) (i: int64) : int64 * bool = - let nrBits = bitsSizeOfInt k in - let signed = isSigned k in - if nrBits = 64 then - i, false - else begin - let i1 = Int64.shift_left i (64 - nrBits) in - let i2 = - if signed then Int64.shift_right i1 (64 - nrBits) - else Int64.shift_right_logical i1 (64 - nrBits) - in - let truncated = - if i2 = i then false - else - (* Examine the bits that we chopped off. If they are all zero, then - * any difference between i2 and i is due to a simple sign-extension. - * e.g. casting the constant 0x80000000 to int makes it - * 0xffffffff80000000. - * Suppress the truncation warning in this case. *) - let chopped = Int64.shift_right_logical i (64 - nrBits) - in chopped <> Int64.zero - in - i2, truncated - end + (* DON'T recurse into the compinfo, this is done in visitCilGlobal. + User can iterate over cinfo.cfields manually, if desired.*) + | TComp(cinfo, _, a) -> + let cinfo' = vis#behavior.get_compinfo cinfo in + let a' = fAttr a in + if a != a' || cinfo' != cinfo then TComp(cinfo',empty_size_cache (), a') else t - let rank : ikind -> int = function - (* these are just unique numbers representing the integer - conversion rank. *) - | IBool | IChar | ISChar | IUChar -> 1 - | IShort | IUShort -> 2 - | IInt | IUInt -> 3 - | ILong | IULong -> 4 - | ILongLong | IULongLong -> 5 - - (* Convert 2 integer constants to integers with the same type, in preparation - for a binary operation. See ISO C 6.3.1.8p1 *) - let convertInts (i1:int64) (ik1:ikind) (i2:int64) (ik2:ikind) - : int64 * int64 * ikind = - if ik1 = ik2 then (* nothing to do *) - i1, i2, ik1 - else begin - let r1 = rank ik1 in - let r2 = rank ik2 in - let ik' = - if (isSigned ik1) = (isSigned ik2) then begin - (* Both signed or both unsigned. *) - if r1 > r2 then ik1 else ik2 - end - else begin - let signedKind, unsignedKind, signedRank, unsignedRank = - if isSigned ik1 then ik1, ik2, r1, r2 else ik2, ik1, r2, r1 - in - (* The rules for signed + unsigned get hairy. - (unsigned short + long) is converted to signed long, - but (unsigned int + long) is converted to unsigned long.*) - if unsignedRank >= signedRank then unsignedKind - else if (bytesSizeOfInt signedKind) > (bytesSizeOfInt unsignedKind) then - signedKind - else - unsignedVersionOf signedKind - end - in - let i1',_ = truncateInteger64 ik' i1 in - let i2',_ = truncateInteger64 ik' i2 in - i1', i2', ik' - end + | TFun(rettype, args, isva, a) -> + let rettype' = fTyp rettype in + (* iterate over formals, as variable declarations *) + let argslist = argsToList args in + let visitArg ((an,at,aa) as arg) = + let at' = fTyp at in + let aa' = fAttr aa in + if at' != at || aa' != aa then (an,at',aa') else arg + in + let argslist' = mapNoCopy visitArg argslist in + let a' = fAttr a in + if rettype' != rettype || argslist' != argslist || a' != a then + let args' = if argslist' == argslist then args else Some argslist' in + TFun(rettype', args', isva, a') else t - type offsetAcc = - { oaFirstFree: int; (* The first free bit *) - oaLastFieldStart: int; (* Where the previous field started *) - oaLastFieldWidth: int; (* The width of the previous field. Might not - * be same as FirstFree - FieldStart because - * of internal padding *) - oaPrevBitPack: (int * ikind * int) option; (* If the previous fields - * were packed bitfields, - * the bit where packing - * has started, the ikind - * of the bitfield and the - * width of the ikind *) - } + | TNamed(t1, a) -> + let a' = fAttr a in + let t1' = vis#behavior.get_typeinfo t1 in + if a' != a || t1' != t1 then TNamed (t1', a') else t + | TEnum(enum,a) -> + let a' = fAttr a in + let enum' = vis#behavior.get_enuminfo enum in + if a' != a || enum' != enum then TEnum(enum',a') else t + | TVoid _ | TInt _ | TFloat _ | TBuiltin_va_list _ -> + (* no nested type. visit only the attributes. *) + let a = typeAttrs t in + let a' = fAttr a in + if a' != a then setTypeAttrs t a' else t + (* for declarations, we visit the types inside; but for uses, *) + (* we just visit the varinfo node *) + and visitCilVarDecl (vis : cilVisitor) (v : varinfo) : varinfo = + let oldloc = CurrentLoc.get () in + CurrentLoc.set v.vdecl; + let res = + doVisitCil vis vis#behavior.memo_varinfo + vis#vvdec childrenVarDecl v + in CurrentLoc.set oldloc; res - (* GCC version *) - (* Does not use the sofar.oaPrevBitPack *) - let rec offsetOfFieldAcc_GCC (fi: fieldinfo) - (sofar: offsetAcc) : offsetAcc = - (* field type *) - let ftype = unrollType fi.ftype in - let ftypeAlign = 8 * alignOf_int ftype in - let ftypeBits = bitsSizeOf ftype in - (* - if fi.fcomp.cname = "comp2468" || - fi.fcomp.cname = "comp2469" || - fi.fcomp.cname = "comp2470" || - fi.fcomp.cname = "comp2471" || - fi.fcomp.cname = "comp2472" || - fi.fcomp.cname = "comp2473" || - fi.fcomp.cname = "comp2474" || - fi.fcomp.cname = "comp2475" || - fi.fcomp.cname = "comp2476" || - fi.fcomp.cname = "comp2477" || - fi.fcomp.cname = "comp2478" then - - ignore (E.log "offsetOfFieldAcc_GCC(%s of %s:%a%a,firstFree=%d,pack=%a)\n" - fi.fname fi.fcomp.cname - d_type ftype - insert - (match fi.fbitfield with - None -> nil - | Some wdthis -> dprintf ":%d" wdthis) - sofar.oaFirstFree - insert - (match sofar.oaPrevBitPack with - None -> text "None" - | Some (packstart, _, wdpack) -> - dprintf "Some(packstart=%d,wd=%d)" - packstart wdpack)); - *) - match ftype, fi.fbitfield with - (* A width of 0 means that we must end the current packing. It seems that - * GCC pads only up to the alignment boundary for the type of this field. - * *) - | _, Some 0 -> - let firstFree = addTrailing sofar.oaFirstFree ftypeAlign in - { oaFirstFree = firstFree; - oaLastFieldStart = firstFree; - oaLastFieldWidth = 0; - oaPrevBitPack = None } + and childrenVarDecl (vis : cilVisitor) (v : varinfo) : varinfo = + v.vtype <- visitCilType vis v.vtype; + v.vattr <- visitCilAttributes vis v.vattr; + v.vlogic_var_assoc <- + optMapNoCopy (visitCilLogicVarDecl vis) v.vlogic_var_assoc; + v - (* A bitfield cannot span more alignment boundaries of its type than the - * type itself *) - | _, Some wdthis - when (sofar.oaFirstFree + wdthis + ftypeAlign - 1) / ftypeAlign - - sofar.oaFirstFree / ftypeAlign > ftypeBits / ftypeAlign -> - let start = addTrailing sofar.oaFirstFree ftypeAlign in - { oaFirstFree = start + wdthis; - oaLastFieldStart = start; - oaLastFieldWidth = wdthis; - oaPrevBitPack = None } + and visitCilVarUse vis v = + doVisitCil vis vis#behavior.get_varinfo vis#vvrbl alphabetabeta v - (* Try a simple method. Just put the field down *) - | _, Some wdthis -> - { oaFirstFree = sofar.oaFirstFree + wdthis; - oaLastFieldStart = sofar.oaFirstFree; - oaLastFieldWidth = wdthis; - oaPrevBitPack = None - } + and visitCilAttributes (vis: cilVisitor) (al: attribute list) : attribute list= + let al' = + mapNoCopyList + (doVisitListCil vis + id vis#vattr childrenAttribute) al in + if al' != al then + (* Must re-sort *) + addAttributes al' [] + else + al + and childrenAttribute (vis: cilVisitor) (a: attribute) : attribute = + let fAttrP a = visitCilAttrParams vis a in + match a with + | Attr (n, args) -> + let args' = mapNoCopy fAttrP args in + if args' != args then Attr(n, args') else a + | AttrAnnot _ -> + a - (* Non-bitfield *) - | _, None -> - (* Align this field *) - let newStart = addTrailing sofar.oaFirstFree ftypeAlign in - { oaFirstFree = newStart + ftypeBits; - oaLastFieldStart = newStart; - oaLastFieldWidth = ftypeBits; - oaPrevBitPack = None; - } + and visitCilAttrParams (vis: cilVisitor) (a: attrparam) : attrparam = + doVisitCil vis id vis#vattrparam childrenAttrparam a + and childrenAttrparam (vis: cilVisitor) (aa: attrparam) : attrparam = + let fTyp t = visitCilType vis t in + let fAttrP a = visitCilAttrParams vis a in + match aa with + AInt _ | AStr _ -> aa + | ACons(n, args) -> + let args' = mapNoCopy fAttrP args in + if args' != args then ACons(n, args') else aa + | ASizeOf t -> + let t' = fTyp t in + if t' != t then ASizeOf t' else aa + | ASizeOfE e -> + let e' = fAttrP e in + if e' != e then ASizeOfE e' else aa + | AAlignOf t -> + let t' = fTyp t in + if t' != t then AAlignOf t' else aa + | AAlignOfE e -> + let e' = fAttrP e in + if e' != e then AAlignOfE e' else aa + | ASizeOfS _ | AAlignOfS _ -> + Kernel.warning "Visitor inside of a type signature." ; + aa + | AUnOp (uo, e1) -> + let e1' = fAttrP e1 in + if e1' != e1 then AUnOp (uo, e1') else aa + | ABinOp (bo, e1, e2) -> + let e1' = fAttrP e1 in + let e2' = fAttrP e2 in + if e1' != e1 || e2' != e2 then ABinOp (bo, e1', e2') else aa + | ADot (ap, s) -> + let ap' = fAttrP ap in + if ap' != ap then ADot (ap', s) else aa + | AStar ap -> + let ap' = fAttrP ap in + if ap' != ap then AStar ap' else aa + | AAddrOf ap -> + let ap' = fAttrP ap in + if ap' != ap then AAddrOf ap' else aa + | AIndex (e1, e2) -> + let e1' = fAttrP e1 in + let e2' = fAttrP e2 in + if e1' != e1 || e2' != e2 then AIndex (e1', e2') else aa + | AQuestion (e1, e2, e3) -> + let e1' = fAttrP e1 in + let e2' = fAttrP e2 in + let e3' = fAttrP e3 in + if e1' != e1 || e2' != e2 || e3' != e3 + then AQuestion (e1', e2', e3') else aa - (* MSVC version *) - and offsetOfFieldAcc_MSVC (fi: fieldinfo) - (sofar: offsetAcc) : offsetAcc = - (* field type *) - let ftype = unrollType fi.ftype in - let ftypeAlign = 8 * alignOf_int ftype in - let ftypeBits = bitsSizeOf ftype in - (* - ignore (E.log "offsetOfFieldAcc_MSVC(%s of %s:%a%a,firstFree=%d, pack=%a)\n" - fi.fname fi.fcomp.cname - d_type ftype - insert - (match fi.fbitfield with - None -> nil - | Some wdthis -> dprintf ":%d" wdthis) - sofar.oaFirstFree - insert - (match sofar.oaPrevBitPack with - None -> text "None" - | Some (prevpack, _, wdpack) -> dprintf "Some(prev=%d,wd=%d)" - prevpack wdpack)); - *) - match ftype, fi.fbitfield, sofar.oaPrevBitPack with - (* Ignore zero-width bitfields that come after non-bitfields *) - | TInt (_ikthis, _), Some 0, None -> - let firstFree = sofar.oaFirstFree in - { oaFirstFree = firstFree; - oaLastFieldStart = firstFree; - oaLastFieldWidth = 0; - oaPrevBitPack = None } - (* If we are in a bitpack and we see a bitfield for a type with the - * different width than the pack, then we finish the pack and retry *) - | _, Some _, Some (packstart, _, wdpack) when wdpack != ftypeBits -> - let firstFree = - if sofar.oaFirstFree = packstart then packstart else - packstart + wdpack - in - offsetOfFieldAcc_MSVC fi - { oaFirstFree = addTrailing firstFree ftypeAlign; - oaLastFieldStart = sofar.oaLastFieldStart; - oaLastFieldWidth = sofar.oaLastFieldWidth; - oaPrevBitPack = None } + let rec fix_succs_preds_block b block = + List.iter (fix_succs_preds b) block.bstmts + and fix_succs_preds b stmt = + stmt.succs <- mapNoCopy b.get_stmt stmt.succs; + stmt.preds <- mapNoCopy b.get_stmt stmt.preds; + match stmt.skind with + If(_,bthen,belse,_) -> + fix_succs_preds_block b bthen; + fix_succs_preds_block b belse + | Switch(e,cases,stmts,l) -> + fix_succs_preds_block b cases; + stmt.skind <- Switch(e,cases,List.map b.get_stmt stmts,l) + | Loop(annot,block,loc,stmt1,stmt2) -> + fix_succs_preds_block b block; + let stmt1' = optMapNoCopy b.get_stmt stmt1 in + let stmt2' = optMapNoCopy b.get_stmt stmt2 in + stmt.skind <- Loop(annot,block,loc,stmt1',stmt2') + | Block block -> fix_succs_preds_block b block + | TryFinally(block1,block2,_) -> + fix_succs_preds_block b block1; + fix_succs_preds_block b block2 + | TryExcept(block1,_,block2,_) -> + fix_succs_preds_block b block1; + fix_succs_preds_block b block2 + | _ -> () - (* A width of 0 means that we must end the current packing. *) - | TInt (ikthis, _), Some 0, Some (packstart, _, wdpack) -> - let firstFree = - if sofar.oaFirstFree = packstart then packstart else - packstart + wdpack - in - let firstFree = addTrailing firstFree ftypeAlign in - { oaFirstFree = firstFree; - oaLastFieldStart = firstFree; - oaLastFieldWidth = 0; - oaPrevBitPack = Some (firstFree, ikthis, ftypeBits) } + let rec visitCilFunction (vis : cilVisitor) (f : fundec) : fundec = + if debugVisit then Kernel.feedback "Visiting function %s" f.svar.vname ; + assertEmptyQueue vis; + vis#set_current_func f; + let f = vis#behavior.cfundec f in + f.svar <- vis#behavior.memo_varinfo f.svar; (* hit the function name *) + let f = + doVisitCil vis id (* copy has already been done *) + vis#vfunc childrenFunction f + in + let toPrepend = vis#unqueueInstr () in + if toPrepend <> [] then + f.sbody.bstmts <- + (List.map (fun i -> mkStmt (Instr i)) toPrepend) @ f.sbody.bstmts; + if vis#behavior.is_copy_behavior then begin + fix_succs_preds_block vis#behavior f.sbody; + f.sallstmts <- List.map vis#behavior.get_stmt f.sallstmts + end; + vis#reset_current_func (); + f - (* Check for a bitfield that fits in the current pack after some other - * bitfields *) - | TInt(_ikthis, _), Some wdthis, Some (packstart, _ikprev, wdpack) - when packstart + wdpack >= sofar.oaFirstFree + wdthis -> - { oaFirstFree = sofar.oaFirstFree + wdthis; - oaLastFieldStart = sofar.oaFirstFree; - oaLastFieldWidth = wdthis; - oaPrevBitPack = sofar.oaPrevBitPack - } + and childrenFunction (vis : cilVisitor) (f : fundec) : fundec = + f.svar <- visitCilVarDecl vis f.svar; (* hit the function name *) + (* visit local declarations *) + f.slocals <- mapNoCopy (visitCilVarDecl vis) f.slocals; + (* visit the formals *) + let newformals = mapNoCopy (visitCilVarDecl vis) f.sformals in + (* Make sure the type reflects the formals *) + Queue.add (fun () -> setFormals f newformals) vis#get_filling_actions; + (* Remember any new instructions that were generated while visiting + variable declarations. *) + let toPrepend = vis#unqueueInstr () in + f.sbody <- visitCilBlock vis f.sbody; (* visit the body *) + if toPrepend <> [] then + f.sbody.bstmts <- (List.map (fun i -> mkStmt (Instr i)) toPrepend) @ f.sbody.bstmts; + if not (is_empty_funspec f.sspec) then + f.sspec <- visitCilFunspec vis f.sspec; + f + let childrenFieldInfo vis fi = + fi.fcomp <- vis#behavior.get_compinfo fi.fcomp; + fi.ftype <- visitCilType vis fi.ftype; + fi.fattr <- visitCilAttributes vis fi.fattr; + fi - | _, _, Some (packstart, _, wdpack) -> (* Finish up the bitfield pack and - * restart. *) - let firstFree = - if sofar.oaFirstFree = packstart then packstart else - packstart + wdpack - in - offsetOfFieldAcc_MSVC fi - { oaFirstFree = addTrailing firstFree ftypeAlign; - oaLastFieldStart = sofar.oaLastFieldStart; - oaLastFieldWidth = sofar.oaLastFieldWidth; - oaPrevBitPack = None } + let visitCilFieldInfo vis f = + doVisitCil vis vis#behavior.memo_fieldinfo vis#vfieldinfo childrenFieldInfo f - (* No active bitfield pack. But we are seeing a bitfield. *) - | TInt(ikthis, _), Some wdthis, None -> - let firstFree = addTrailing sofar.oaFirstFree ftypeAlign in - { oaFirstFree = firstFree + wdthis; - oaLastFieldStart = firstFree; - oaLastFieldWidth = wdthis; - oaPrevBitPack = Some (firstFree, ikthis, ftypeBits); } + let childrenCompInfo vis comp = + comp.cfields <- mapNoCopy (visitCilFieldInfo vis) comp.cfields; + comp.cattr <- visitCilAttributes vis comp.cattr; + comp - (* No active bitfield pack. Non-bitfield *) - | _, None, None -> - (* Align this field *) - let firstFree = addTrailing sofar.oaFirstFree ftypeAlign in - { oaFirstFree = firstFree + ftypeBits; - oaLastFieldStart = firstFree; - oaLastFieldWidth = ftypeBits; - oaPrevBitPack = None; - } + let visitCilCompInfo vis c = + doVisitCil vis vis#behavior.memo_compinfo vis#vcompinfo childrenCompInfo c - | _, Some _, None -> Cilmsg.fatal "offsetAcc" + let childrenEnumItem vis e = + e.eival <- visitCilExpr vis e.eival; + e.eihost <- vis#behavior.get_enuminfo e.eihost; + e + let visitCilEnumItem vis e = + doVisitCil vis vis#behavior.memo_enumitem vis#venumitem childrenEnumItem e - and offsetOfFieldAcc ~(fi: fieldinfo) - ~(sofar: offsetAcc) : offsetAcc = - if theMachine.msvcMode then offsetOfFieldAcc_MSVC fi sofar - else offsetOfFieldAcc_GCC fi sofar + let childrenEnumInfo vis e = + e.eitems <- mapNoCopy (visitCilEnumItem vis) e.eitems; + e.eattr <- visitCilAttributes vis e.eattr; + e - (* The size of a type, in bits. If struct or array then trailing padding is - * added *) - and bitsSizeOf t = - if not (TheMachine.is_computed ()) then - Cilmsg.fatal "You did not call Cil.initCIL before using the CIL library" ; - match t with - | TInt (ik,_) -> 8 * (bytesSizeOfInt ik) - | TFloat(FDouble, _) -> 8 * theMachine.theMachine.sizeof_double - | TFloat(FLongDouble, _) -> - 8 * theMachine.theMachine.sizeof_longdouble - | TFloat _ -> 8 * theMachine.theMachine.sizeof_float - | TEnum _ -> 8 * theMachine.theMachine.sizeof_enum - | TPtr _ -> 8 * theMachine.theMachine.sizeof_ptr - | TBuiltin_va_list _ -> 8 * theMachine.theMachine.sizeof_ptr - | TNamed (t, _) -> bitsSizeOf t.ttype - | TComp (comp, scache, _) when comp.cfields == [] -> - find_size_in_cache - scache - (fun () -> begin - (* Empty structs are allowed in msvc mode *) - if not comp.cdefined && not theMachine.msvcMode then - raise - (SizeOfError - (Format.sprintf - "abstract type: empty struct exist only with MSVC (comp %s)" - (compFullName comp), - t)) (*abstract type*) - else - 0 - end) + let visitCilEnumInfo vis e = + doVisitCil vis vis#behavior.memo_enuminfo vis#venuminfo childrenEnumInfo e - | TComp (comp, scache, _) when comp.cstruct -> (* Struct *) - find_size_in_cache - scache - (fun () -> - (* Go and get the last offset *) - let startAcc = - { oaFirstFree = 0; - oaLastFieldStart = 0; - oaLastFieldWidth = 0; - oaPrevBitPack = None; - } in - let lastoff = - List.fold_left (fun acc fi -> offsetOfFieldAcc ~fi ~sofar:acc) - startAcc comp.cfields - in - if theMachine.msvcMode && lastoff.oaFirstFree = 0 && comp.cfields <> [] - then - (* On MSVC if we have just a zero-width bitfields then the length - * is 32 and is not padded *) - 32 - else - addTrailing lastoff.oaFirstFree (8 * alignOf_int t)) + let rec visitCilGlobal (vis: cilVisitor) (g: global) : global list = + let oldloc = CurrentLoc.get () in + CurrentLoc.set (Global.loc g) ; + currentGlobal := g; + let res = + doVisitListCil vis id vis#vglob childrenGlobal g in + CurrentLoc.set oldloc; + res + and childrenGlobal (vis: cilVisitor) (g: global) : global = + match g with + | GFun (f, l) -> + let f' = visitCilFunction vis f in + if f' != f then GFun (f', l) else g + | GType(t, l) -> + let t' = vis#behavior.memo_typeinfo t in + t'.ttype <- visitCilType vis t'.ttype; + if t' != t then GType(t,l) else g + | GEnumTagDecl (enum,l) -> + let enum' = vis#behavior.memo_enuminfo enum in + if enum != enum' then GEnumTagDecl(enum',l) else g + (* real visit'll be done in the definition *) + | GCompTagDecl (comp,l) -> + let comp' = vis#behavior.memo_compinfo comp in + if comp != comp' then GCompTagDecl(comp',l) else g + | GEnumTag (enum, l) -> + let enum' = visitCilEnumInfo vis enum in + if enum != enum' then GEnumTag(enum',l) else g + | GCompTag (comp, l) -> + let comp' = visitCilCompInfo vis comp in + if comp != comp' then GCompTag(comp',l) else g + | GVarDecl(spec, v, l) -> + let form = + try Some (getFormalsDecl v) with Not_found -> None + in + let v' = visitCilVarDecl vis v in + let form' = optMapNoCopy (mapNoCopy (visitCilVarDecl vis)) form in + let spec' = + if isFunctionType v.vtype && not (is_empty_funspec spec) then + visitCilFunspec vis spec + else begin + assert (is_empty_funspec spec); + if is_copy_behavior vis#behavior then + empty_funspec () + else spec (* do not need to change it if it's not a copy visitor. *) + end + in + if v' != v || spec' != spec || form != form' then + begin + (match form' with None -> () + | Some form' -> + Queue.add (fun () -> unsafeSetFormalsDecl v' form') + vis#get_filling_actions); + GVarDecl (spec', v', l) + end + else g + | GVar (v, inito, l) -> + let v' = visitCilVarDecl vis v in + let inito' = vis#behavior.cinitinfo inito in + (match inito'.init with + None -> () + | Some i -> let i' = visitCilInit vis v NoOffset i in + if i' != i then inito'.init <- Some i'); + if v' != v || inito' != inito then GVar (v', inito', l) else g + | GPragma (a, l) -> begin + match visitCilAttributes vis [a] with + [a'] -> if a' != a then GPragma (a', l) else g + | _ -> Kernel.fatal "visitCilAttributes returns more than one attribute" + end + | GAnnot (a,l) -> + let a' = visitCilAnnotation vis a in + if a' != a then GAnnot(a',l) else g + | GText _ | GAsm _ -> g - | TComp (comp, scache, _) -> (* when not comp.cstruct *) - find_size_in_cache - scache - (fun () -> - (* Get the maximum of all fields *) - let startAcc = - { oaFirstFree = 0; - oaLastFieldStart = 0; - oaLastFieldWidth = 0; - oaPrevBitPack = None; - } in - let max = - List.fold_left (fun acc fi -> - let lastoff = offsetOfFieldAcc ~fi ~sofar:startAcc in - if lastoff.oaFirstFree > acc then - lastoff.oaFirstFree else acc) 0 comp.cfields in - (* Add trailing by simulating adding an extra field *) - addTrailing max (8 * alignOf_int t)) +(* sm: utility *) +let startsWith prefix s = + let prefixLen = String.length prefix in + String.length s >= prefixLen && String.sub s 0 prefixLen = prefix - | TArray(bt, Some len, scache, _) -> - find_size_in_cache - scache - (fun () -> - begin - match (constFold true len).enode with - Const(CInt64(l,_,_)) -> - let sz = Int64.mul (Int64.of_int (bitsSizeOf bt)) l in - let sz' = Int64.to_int sz in - (* Check for overflow. - There are other places in these cil.ml that overflow can occur, - but this multiplication is the most likely to be a problem. *) - if (Int64.of_int sz') <> sz then - raise (SizeOfError ("Array is so long that its size can't be " - ^"represented with an OCaml int.", t)) - else - begin - sz' (*WAS: addTrailing sz' (8 * alignOf_int t)*) - end - | _ -> raise (SizeOfError ("array non-constant length", t)) - end) - | TVoid _ -> 8 * theMachine.theMachine.sizeof_void - | TFun _ when not theMachine.msvcMode -> - (* On GCC the size of a function is defined *) - 8 * theMachine.theMachine.sizeof_fun - | TArray (_, None, _, _) -> - (* it seems that on GCC the size of such an - * array is 0 *) - 0 +(* The next compindo identifier to use. Counts up. *) +let nextCompinfoKey = + let module M = State_builder.SharedCounter(struct let name = "compinfokey" end) in + M.next - | TFun _ -> raise (SizeOfError ("function", t)) +let bytesSizeOfInt (ik: ikind): int = + match ik with + | IChar | ISChar | IUChar -> 1 + | IBool | IInt | IUInt -> theMachine.theMachine.sizeof_int + | IShort | IUShort -> theMachine.theMachine.sizeof_short + | ILong | IULong -> theMachine.theMachine.sizeof_long + | ILongLong | IULongLong -> theMachine.theMachine.sizeof_longlong - and addTrailing nrbits roundto = - (nrbits + roundto - 1) land (lnot (roundto - 1)) +let unsignedVersionOf (ik:ikind): ikind = + match ik with + | ISChar | IChar -> IUChar + | IShort -> IUShort + | IInt -> IUInt + | ILong -> IULong + | ILongLong -> IULongLong + | _ -> ik + +let intKindForSize (s:int) (unsigned:bool) : ikind = + if unsigned then + (* Test the most common sizes first *) + if s = 1 then IUChar + else if s = theMachine.theMachine.sizeof_int then IUInt + else if s = theMachine.theMachine.sizeof_long then IULong + else if s = theMachine.theMachine.sizeof_short then IUShort + else if s = theMachine.theMachine.sizeof_longlong then IULongLong + else raise Not_found + else + (* Test the most common sizes first *) + if s = 1 then ISChar + else if s = theMachine.theMachine.sizeof_int then IInt + else if s = theMachine.theMachine.sizeof_long then ILong + else if s = theMachine.theMachine.sizeof_short then IShort + else if s = theMachine.theMachine.sizeof_longlong then ILongLong + else raise Not_found + +let floatKindForSize (s:int) = + if s = theMachine.theMachine.sizeof_double then FDouble + else if s = theMachine.theMachine.sizeof_float then FFloat + else if s = theMachine.theMachine.sizeof_longdouble then FLongDouble + else raise Not_found - and sizeOf_int t = (bitsSizeOf t) lsr 3 -and sizeOf ~loc t = - try - integer ~loc ((bitsSizeOf t) lsr 3) - with SizeOfError _ -> new_exp ?loc (SizeOf(t)) +(** Returns true if and only if the given integer type is signed. *) +let isSigned = function + | IUChar | IBool + | IUShort + | IUInt + | IULong + | IULongLong -> + false + | ISChar + | IShort + | IInt + | ILong + | ILongLong -> + true + | IChar -> + not theMachine.theMachine.Cil_types.char_is_unsigned - and bitsOffset (baset: typ) (off: offset) : int * int = - let rec loopOff (baset: typ) (width: int) (start: int) = function - NoOffset -> start, width - | Index(e, off) -> begin - let ei = - match isInteger e with - Some i64 -> Int64.to_int i64 - | None -> raise (SizeOfError ("index not constant", baset)) - in - let bt = - match unrollType baset with - TArray(bt, _, _, _) -> bt - | _ -> Cilmsg.fatal "bitsOffset: Index on a non-array" - in - let bitsbt = bitsSizeOf bt in - loopOff bt bitsbt (start + ei * bitsbt) off - end - | Field(f, off) when not f.fcomp.cstruct -> - (* All union fields start at offset 0 *) - loopOff f.ftype (bitsSizeOf f.ftype) start off - | Field(f, off) -> - (* Construct a list of fields preceeding and including this one *) - let prevflds = - let rec loop = function - [] -> abort - "bitsOffset: Cannot find field %s in %s" f.fname f.fcomp.cname - | fi' :: _ when fi' == f -> [fi'] - | fi' :: rest -> fi' :: loop rest - in - loop f.fcomp.cfields - in - let lastoff = - List.fold_left (fun acc fi' -> offsetOfFieldAcc ~fi:fi' ~sofar:acc) - { oaFirstFree = 0; (* Start at 0 because each struct is done - * separately *) - oaLastFieldStart = 0; - oaLastFieldWidth = 0; - oaPrevBitPack = None } prevflds - in - (* ignore (E.log "Field %s of %s: start=%d, lastFieldStart=%d\n" - f.fname f.fcomp.cname start lastoff.oaLastFieldStart); *) - loopOff f.ftype lastoff.oaLastFieldWidth - (start + lastoff.oaLastFieldStart) off - in - loopOff baset (bitsSizeOf baset) 0 off +let max_signed_number nrBits = + let n = nrBits-1 in + My_bigint.pred (My_bigint.shift_left My_bigint.one (My_bigint.of_int n)) +let max_unsigned_number nrBits = + My_bigint.pred (My_bigint.shift_left My_bigint.one (My_bigint.of_int nrBits)) +let min_signed_number nrBits = + let n = nrBits-1 in + My_bigint.neg (My_bigint.shift_left My_bigint.one (My_bigint.of_int n)) + + +(* True if the integer fits within the kind's range *) +let fitsInInt k i = + let signed = isSigned k in + let nrBits = + let unsignedbits = 8 * (bytesSizeOfInt k) in + if signed then + unsignedbits-1 + else + unsignedbits + in + let max_strict_bound = + My_bigint.shift_left My_bigint.one (My_bigint.of_int nrBits) + in + let min_bound = if signed then My_bigint.neg max_strict_bound + else My_bigint.zero + in + let fits = My_bigint.le min_bound i && My_bigint.lt i max_strict_bound in + Kernel.debug "Fits in %a %s : %b@." !pd_ikind k (My_bigint.to_string i) fits; + fits -(** Do constant folding on an expression. If the first argument is true then - will also compute compiler-dependent expressions such as sizeof. - See also {!Cil.constFoldVisitor}, which will run constFold on all - expressions in a given AST node.*) -and constFold (machdep: bool) (e: exp) : exp = - let loc = e.eloc in - match e.enode with - BinOp(bop, e1, e2, tres) -> constFoldBinOp ~loc machdep bop e1 e2 tres - | UnOp(unop, e1, tres) -> begin - try - let tk = - match unrollType tres with - TInt(ik, _) -> ik - | TEnum _ -> IInt - | _ -> raise Not_found (* probably a float *) + + +(* Represents an integer as for a given kind. + Returns a flag saying whether the value was changed + during truncation (because it was too large to fit in k). *) +let truncateInteger64 (k: ikind) i = + Kernel.debug "Truncate to %a: %s@." !pd_ikind k (My_bigint.to_string i); + if fitsInInt k i then + i,false + else + begin + let nrBits = My_bigint.of_int (8 * (bytesSizeOfInt k)) in + let max_strict_bound = My_bigint.shift_left My_bigint.one nrBits in + let modulo = My_bigint.pos_rem i max_strict_bound in + let signed = isSigned k in + if signed + then + let max_signed_strict_bound = + My_bigint.shift_right max_strict_bound My_bigint.one in - let e1c = constFold machdep e1 in - match e1c.enode with - Const(CInt64(i,_ik,repr)) -> begin - match unop with - Neg -> - let repr = Extlib.opt_map (fun s -> "-" ^ s) repr in - kinteger64_repr ~loc tk (Int64.neg i) repr - | BNot -> kinteger64 ~loc tk (Int64.lognot i) - | LNot -> if i = Int64.zero then one ~loc else zero ~loc - end - | _ -> new_exp ~loc (UnOp(unop, e1c, tres)) - with Not_found -> e - end - (* Characters are integers *) - | Const(CChr c) -> new_exp ~loc (Const(charConstToInt c)) - | Const(CEnum {eival = v}) -> constFold machdep v - | SizeOf t when machdep -> begin - try - let bs = bitsSizeOf t in - kinteger ~loc theMachine.kindOfSizeOf (bs / 8) - with SizeOfError _ -> e - end - | SizeOfE e when machdep -> constFold machdep - (new_exp ~loc:e.eloc (SizeOf (typeOf e))) - | SizeOfStr s when machdep -> - kinteger ~loc theMachine.kindOfSizeOf (1 + String.length s) - | AlignOf t when machdep -> - kinteger ~loc theMachine.kindOfSizeOf (alignOf_int t) - | AlignOfE e when machdep -> begin - (* The alignment of an expression is not always the alignment of its - * type. I know that for strings this is not true *) - match e.enode with - Const (CStr _) when not theMachine.msvcMode -> - kinteger ~loc - theMachine.kindOfSizeOf theMachine.theMachine.alignof_str - (* For an array, it is the alignment of the array ! *) - | _ -> constFold machdep (new_exp ~loc:e.eloc (AlignOf (typeOf e))) - end + if My_bigint.ge modulo max_signed_strict_bound then + My_bigint.sub modulo max_strict_bound + else if My_bigint.lt modulo (My_bigint.neg max_signed_strict_bound) + then My_bigint.add modulo max_strict_bound + else modulo + else + if My_bigint.lt modulo My_bigint.zero then + My_bigint.add modulo max_strict_bound + else + modulo + end, + true - | CastE(it, - { enode = AddrOf (Mem ({enode = CastE(TPtr(bt, _), z)}), off)}) - when machdep && isZero z -> begin - try - let start, _width = bitsOffset bt off in - if start mod 8 <> 0 then error "Using offset of bitfield" ; - constFold machdep (new_exp ~loc (CastE(it, (integer ~loc (start / 8))))) - with SizeOfError _ -> e - end +(* Return the smallest kind that will hold the integer's value. + The kind will be unsigned if the 2nd argument is true *) +let intKindForValue i (unsigned: bool) = + if unsigned then + if fitsInInt IUChar i then IUChar + else if fitsInInt IUShort i then IUShort + else if fitsInInt IUInt i then IUInt + else if fitsInInt IULong i then IULong + else IULongLong + else + if fitsInInt ISChar i then ISChar + else if fitsInInt IShort i then IShort + else if fitsInInt IInt i then IInt + else if fitsInInt ILong i then ILong + else ILongLong - | CastE (t, e) -> begin - let e = constFold machdep e in - match e.enode, unrollType t with - (* Might truncate silently *) - Const(CInt64(i,_k,_)), TInt(nk,a) - (* It's okay to drop a cast to const. - If the cast has any other attributes, leave the cast alone. *) - when (dropAttributes ["const"] a) = [] -> - kinteger64 ~loc nk i - | _, _ -> new_exp ~loc (CastE (t, e)) - end - | Lval lv -> new_exp ~loc (Lval (constFoldLval machdep lv)) - | AddrOf lv -> new_exp ~loc (AddrOf (constFoldLval machdep lv)) - | StartOf lv -> new_exp ~loc (StartOf (constFoldLval machdep lv)) - | _ -> e +(* Construct an integer constant with possible truncation *) +let kinteger64_repr ~loc (k: ikind) i repr = + Kernel.debug "kinteger64_repr %s" (My_bigint.to_string i); + let i', truncated = truncateInteger64 k i in + if truncated then + Kernel.debug ~level:3 "Truncating integer %s to %s" + (My_bigint.to_string i) + (My_bigint.to_string i'); + new_exp ~loc (Const (CInt64(i' , k, repr))) - and constFoldLval machdep (host,offset) = - let newhost = - match host with - | Mem e -> Mem (constFold machdep e) - | Var _ -> host - in - let rec constFoldOffset machdep = function - | NoOffset -> NoOffset - | Field (fi,offset) -> Field (fi, constFoldOffset machdep offset) - | Index (exp,offset) -> Index (constFold machdep exp, - constFoldOffset machdep offset) - in - (newhost, constFoldOffset machdep offset) +let kinteger64 ~loc k i = kinteger64_repr ~loc k i None -and constFoldBinOp ~loc (machdep: bool) bop e1 e2 tres = - let e1' = constFold machdep e1 in - let e2' = constFold machdep e2 in - if isIntegralType tres then begin - let newe = - let rec mkInt e = - let loc = e.eloc in - match e.enode with - Const(CChr c) -> new_exp ~loc (Const(charConstToInt c)) - | Const(CEnum {eival = v}) -> mkInt v - | CastE(TInt (ik, ta), e) -> begin - let exp = mkInt e in - match exp.enode with - Const(CInt64(i, _, _)) -> - kinteger64 ~loc ik i - | _ -> {exp with enode = CastE(TInt(ik, ta), exp)} - end - | _ -> e - in - let tk = - match unrollType tres with - TInt(ik, _) -> ik - | TEnum _ -> IInt - | _ -> Cilmsg.fatal "constFoldBinOp" - in - (* See if the result is unsigned *) - let isunsigned typ = not (isSigned typ) in - let ge (unsigned: bool) (i1: int64) (i2: int64) : bool = - if unsigned then - let l1 = Int64.shift_right_logical i1 1 in - let l2 = Int64.shift_right_logical i2 1 in (* Both positive now *) - (l1 > l2) || (l1 = l2 && - Int64.logand i1 Int64.one >= Int64.logand i2 Int64.one) - else i1 >= i2 - in - let shiftInBounds i2 = - (* We only try to fold shifts if the second arg is positive and - less than the size of the type of the first argument. - Otherwise, the semantics are processor-dependent, - so let the compiler sort it out. *) - (* We only try to fold shifts if the second arg is positive and - less than the size of the type of the first argument. - Otherwise, the semantics are processor-dependent, so let the - compiler sort it out. *) - if machdep then - try - i2 >= Int64.zero && i2 < (Int64.of_int (bitsSizeOf (typeOf e1'))) - with SizeOfError _ -> false - else false - in - (* Assume that the necessary promotions have been done *) - let e1'' = mkInt e1' in - let e2'' = mkInt e2' in - match bop, e1''.enode, e2''.enode with - | PlusA, Const(CInt64(z,_,_)), _ when z = Int64.zero -> e2'' - | PlusA, _, Const(CInt64(z,_,_)) when z = Int64.zero -> e1'' - | PlusPI, _, Const(CInt64(z,_,_)) when z = Int64.zero -> e1'' - | IndexPI, _, Const(CInt64(z,_,_)) when z = Int64.zero -> e1'' - | MinusPI, _, Const(CInt64(z,_,_)) when z = Int64.zero -> e1'' - | PlusA, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - kinteger64 ~loc tk (Int64.add i1 i2) - | MinusA, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) - when ik1 = ik2 -> - kinteger64 ?loc tk (Int64.sub i1 i2) - | Mult, Const(CInt64(i1,ik1,_)), Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - kinteger64 ?loc tk (Int64.mul i1 i2) - | Mult, Const(CInt64(0L,_,_)), _ -> zero ~loc - | Mult, Const(CInt64(1L,_,_)), _ -> e2'' - | Mult, _, Const(CInt64(0L,_,_)) -> zero ~loc - | Mult, _, Const(CInt64(1L,_,_)) -> e1'' - | Div, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - begin - try kinteger64 ?loc tk (Int64.div i1 i2) - with Division_by_zero -> new_exp ?loc (BinOp(bop, e1', e2', tres)) - end - | Div, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) - when bytesSizeOfInt ik1 = bytesSizeOfInt ik2 -> begin - try kinteger64 ?loc tk (Int64.div i1 i2) - with Division_by_zero -> new_exp ?loc (BinOp(bop, e1', e2', tres)) - end - | Div, _, Const(CInt64(1L,_,_)) -> e1'' - | Mod, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - begin - try kinteger64 ?loc tk (Int64.rem i1 i2) - with Division_by_zero -> new_exp ?loc (BinOp(bop, e1', e2', tres)) - end - | BAnd, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - kinteger64 ?loc tk (Int64.logand i1 i2) - | BAnd, Const(CInt64(0L,_,_)), _ -> zero ~loc - | BAnd, _, Const(CInt64(0L,_,_)) -> zero ~loc - | BOr, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - kinteger64 ?loc tk (Int64.logor i1 i2) - | BOr, _, _ when isZero e1' -> e2' - | BOr, _, _ when isZero e2' -> e1' - | BXor, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> - kinteger64 ?loc tk (Int64.logxor i1 i2) - | Shiftlt, Const(CInt64(i1,_ik1,_)),Const(CInt64(i2,_,_)) - when shiftInBounds i2 -> - kinteger64 ?loc tk (Int64.shift_left i1 (Int64.to_int i2)) - | Shiftlt, Const(CInt64(0L,_,_)), _ -> zero ~loc - | Shiftlt, _, Const(CInt64(0L,_,_)) -> e1'' - | Shiftrt, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,_,_)) - when shiftInBounds i2 -> - if isunsigned ik1 then - kinteger64 ?loc tk (Int64.shift_right_logical i1 (Int64.to_int i2)) - else - kinteger64 ?loc tk (Int64.shift_right i1 (Int64.to_int i2)) - | Shiftrt, Const(CInt64(0L,_,_)), _ -> zero ~loc - | Shiftrt, _, Const(CInt64(0L,_,_)) -> e1'' - | Eq, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> - let i1', i2', _ = convertInts i1 ik1 i2 ik2 in - if i1' = i2' then one ~loc else zero ~loc - | Ne, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> - let i1', i2', _ = convertInts i1 ik1 i2 ik2 in - if i1' <> i2' then one ~loc else zero ~loc - | Le, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> - let i1', i2', ik' = convertInts i1 ik1 i2 ik2 in - if ge (isunsigned ik') i2' i1' then one ~loc else zero ~loc - - | Ge, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> - let i1', i2', ik' = convertInts i1 ik1 i2 ik2 in - if ge (isunsigned ik') i1' i2' then one ~loc else zero ~loc - - | Lt, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> - let i1', i2', ik' = convertInts i1 ik1 i2 ik2 in - if i1' <> i2' && ge (isunsigned ik') i2' i1' then - one ~loc - else zero ~loc - - | Gt, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> - let i1', i2', ik' = convertInts i1 ik1 i2 ik2 in - if i1 <> i2 && ge (isunsigned ik') i1' i2' then - one ~loc - else zero ~loc +(* Construct an integer of a given kind. *) +let kinteger ~loc (k: ikind) (i: int) = kinteger64 ~loc k (My_bigint.of_int i) - (* We rely on the fact that LAnd/LOr appear in global initializers - and should not have side effects. *) - | LAnd, _, _ when isZero e1' || isZero e2' -> zero ~loc - | LAnd, _, _ when isInteger e1' <> None -> e2' (* e1' is TRUE *) - | LAnd, _, _ when isInteger e2' <> None -> e1' (* e2' is TRUE *) - | LOr, _, _ when isZero e1' -> e2' - | LOr, _, _ when isZero e2' -> e1' - | LOr, _, _ when isInteger e1' <> None || isInteger e2' <> None -> - (* One of e1' or e2' is a nonzero constant *) - one ~loc - | _ -> new_exp ?loc (BinOp(bop, e1', e2', tres)) - in - if debugConstFold then - Cilmsg.debug ~current:true "Folded %a to %a" - (!pd_exp) (new_exp ?loc (BinOp(bop, e1', e2', tres))) - (!pd_exp) newe ; - newe - end else - new_exp ?loc (BinOp(bop, e1', e2', tres)) +(* Construct an integer. Use only for values that fit on 31 bits *) +let integer_constant i = CInt64(My_bigint.of_int i, IInt, None) +(* Construct an integer. Use only for values that fit on 31 bits *) +let integer ~loc (i: int) = new_exp ~loc (Const (integer_constant i)) - (* Moved from ext/expcompare.ml *) - let rec compareExp (e1: exp) (e2: exp) : bool = - (* log "CompareExp %a and %a.\n" d_plainexp e1 d_plainexp e2; *) - e1 == e2 || - match e1.enode, e2.enode with - | Lval lv1, Lval lv2 - | StartOf lv1, StartOf lv2 - | AddrOf lv1, AddrOf lv2 -> compareLval lv1 lv2 - | BinOp(bop1, l1, r1, _), BinOp(bop2, l2, r2, _) -> - bop1 = bop2 && compareExp l1 l2 && compareExp r1 r2 - | _ -> begin - match isInteger (constFold true e1), isInteger (constFold true e2) with - Some i1, Some i2 -> i1 = i2 - | _ -> false - end +let zero ~loc = integer ~loc 0 +let one ~loc = integer ~loc 1 +let mone ~loc = integer ~loc (-1) - and compareLval (lv1: lval) (lv2: lval) : bool = - let rec compareOffset (off1: offset) (off2: offset) : bool = - match off1, off2 with - | Field (fld1, off1'), Field (fld2, off2') -> - fld1 == fld2 && compareOffset off1' off2' - | Index (e1, off1'), Index (e2, off2') -> - compareExp e1 e2 && compareOffset off1' off2' - | NoOffset, NoOffset -> true - | _ -> false - in - lv1 == lv2 || - match lv1, lv2 with - | (Var vi1, off1), (Var vi2, off2) -> - vi1 == vi2 && compareOffset off1 off2 - | (Mem e1, off1), (Mem e2, off2) -> - compareExp e1 e2 && compareOffset off1 off2 - | _ -> false +let lconstant ?(loc=Location.unknown) v = + { term_node = TConst (CInt64(v, IInt, None)); term_loc = loc; + term_name = []; term_type = Linteger;} + +let lzero ?(loc=Location.unknown) () = lconstant ~loc My_bigint.zero +let lone ?(loc=Location.unknown) () = lconstant ~loc My_bigint.one +let lmone ?(loc=Location.unknown) () = lconstant ~loc (My_bigint.minus_one) - (* CEA: moved from cabs2cil.ml. See cil.mli for infos *) - (* Weimer - * multi-character character constants - * In MSCV, this code works: - * - * long l1 = 'abcd'; // note single quotes - * char * s = "dcba"; - * long * lptr = ( long * )s; - * long l2 = *lptr; - * assert(l1 == l2); - * - * We need to change a multi-character character literal into the - * appropriate integer constant. However, the plot sickens: we - * must also be able to handle things like 'ab\nd' (value = * "d\nba") - * and 'abc' (vale = *"cba"). - * - * First we convert 'AB\nD' into the list [ 65 ; 66 ; 10 ; 68 ], then we - * multiply and add to get the desired value. - *) + (** Given the character c in a (CChr c), sign-extend it to 32 bits. + (This is the official way of interpreting character constants, according + to ISO C 6.4.4.4.10, which says that character constants are chars cast + to ints) + Returns CInt64(sign-extened c, IInt, None) *) +let charConstToInt (c: char) : constant = + let c' = Char.code c in + let value = + if c' < 128 + then My_bigint.of_int c' + else My_bigint.of_int (c' - 256) + in + CInt64(value, IInt, None) - (* Given a character constant (like 'a' or 'abc') as a list of 64-bit - * values, turn it into a CIL constant. Multi-character constants are - * treated as multi-digit numbers with radix given by the bit width of - * the specified type (either char or wchar_t). *) - let reduce_multichar typ : int64 list -> int64 = - let radix = bitsSizeOf typ in - List.fold_left - (fun acc -> Int64.add (Int64.shift_left acc radix)) - Int64.zero - let interpret_character_constant char_list = - let value = reduce_multichar charType char_list in - if value < (Int64.of_int 256) then - (* ISO C 6.4.4.4.10: single-character constants have type int *) - (CChr(Char.chr (Int64.to_int value))), intType - else begin - let orig_rep = None (* Some("'" ^ (String.escaped str) ^ "'") *) in - if value <= (Int64.of_int32 Int32.max_int) then - (CInt64(value,IULong,orig_rep)),(TInt(IULong,[])) - else - (CInt64(value,IULongLong,orig_rep)),(TInt(IULongLong,[])) - end +let rec isInteger e = match e.enode with +| Const(CInt64 (n,_,_)) -> Some n +| Const(CChr c) -> isInteger (dummy_exp (Const (charConstToInt c))) +| Const(CEnum {eival = v}) -> isInteger v +| CastE(_, e) -> isInteger e +| _ -> None - (*/CEA*) + (** Convert a 64-bit int to an OCaml int, or raise an exception if that + can't be done. *) +let i64_to_int (i: int64) : int = + let i': int = Int64.to_int i in (* i.e. i' = i mod 2^31 *) + if i = Int64.of_int i' then i' + else Kernel.abort "Int constant too large: %Ld\n" i + +let rec isZero (e: exp) : bool = + match isInteger e with + | None -> false + | Some i -> My_bigint.equal i My_bigint.zero + +let rec isLogicZero t = match t.term_node with +| TConst (CInt64 (n,_,_)) -> My_bigint.equal n My_bigint.zero +| TConst (CChr c) -> Char.code c = 0 +| TCastE(_, t) -> isLogicZero t +| _ -> false + +let isLogicNull t = + isLogicZero t || + (let rec aux t = match t.term_node with + | Tnull -> true + | TCastE(_, t) -> aux t + | _ -> false + in aux t) +let parseInt ~loc (str: string) : exp = + let hasSuffix str = + let l = String.length str in + fun s -> + let ls = String.length s in + l >= ls && s = String.uppercase (String.sub str (l - ls) ls) + in + let l = String.length str in + (* See if it is octal or hex *) + let octalhex = (l >= 1 && String.get str 0 = '0') in + (* The length of the suffix and a list of possible kinds. See ISO + * 6.4.4.1 *) + let hasSuffix = hasSuffix str in + let suffixlen, kinds = + if hasSuffix "ULL" || hasSuffix "LLU" then + 3, [IULongLong] + else if hasSuffix "LL" then + 2, if octalhex then [ILongLong; IULongLong] else [ILongLong] + else if hasSuffix "UL" || hasSuffix "LU" then + 2, [IULong; IULongLong] + else if hasSuffix "L" then + 1, if octalhex then [ILong; IULong; ILongLong; IULongLong] + else [ILong; ILongLong] + else if hasSuffix "U" then + 1, [IUInt; IULong; IULongLong] + else + 0, if octalhex || true (* !!! This is against the ISO but it + * is what GCC and MSVC do !!! *) + then [IInt; IUInt; ILong; IULong; ILongLong; IULongLong] + else [IInt; ILong; IUInt; ILongLong] + in + (* Convert to integer. To prevent overflow we do the arithmetic + * on Big_int and we take care of overflow. We work only with + * positive integers since the lexer takes care of the sign *) + let rec toInt base (acc: My_bigint.t) (idx: int) : + My_bigint.t = + let doAcc what = + let acc' = + My_bigint.add what (My_bigint.mul base acc) in + toInt base acc' (idx + 1) + in + if idx >= l - suffixlen then begin + acc + end else + let ch = String.get str idx in + if ch >= '0' && ch <= '9' then + doAcc (My_bigint.of_int (Char.code ch - Char.code '0')) + else if ch >= 'a' && ch <= 'f' then + doAcc (My_bigint.of_int (10 + Char.code ch - Char.code 'a')) + else if ch >= 'A' && ch <= 'F' then + doAcc (My_bigint.of_int (10 + Char.code ch - Char.code 'A')) + else + fatal "Invalid integer constant: %s" str + in + try + let i = + if octalhex then + if l >= 2 && + (let c = String.get str 1 in c = 'x' || c = 'X') then + toInt My_bigint.small_nums.(16) My_bigint.zero 2 + else + toInt My_bigint.small_nums.(8) My_bigint.zero 1 + else + toInt My_bigint.small_nums.(10) My_bigint.zero 0 + in + let res = + let rec loop = function + | k::rest -> + if fitsInInt k i then (* i fits in the current type. *) + kinteger64_repr ~loc k i (Some str) + else loop rest + | [] -> + Kernel.fatal ~source:(fst loc) "Cannot represent the integer %s" str + in + loop kinds + in + res + with Failure "" as e -> + Kernel.warning "int_of_string %s (%s)\n" str (Printexc.to_string e); + zero ~loc - let d_unop fmt u = - fprintf fmt "%s" - (match u with - Neg -> "-" - | BNot -> "~" - | LNot -> "!") + let mkStmtCfg ~before ~(new_stmtkind:stmtkind) ~(ref_stmt:stmt) : stmt = + let new_ = { skind = new_stmtkind; + labels = []; + sid = -1; succs = []; preds = []; ghost = false } + in + new_.sid <- Sid.next (); + if before then begin + new_.succs <- [ref_stmt]; + let old_preds = ref_stmt.preds in + ref_stmt.preds <- [new_]; + new_.preds <- old_preds; + List.iter + (fun pred_stmt -> + pred_stmt.succs <- + (List.map + (fun a_succ -> if a_succ.sid = ref_stmt.sid then new_ else a_succ) + pred_stmt.succs)) + old_preds + end else begin + let old_succs = ref_stmt.succs in + ref_stmt.succs <- [new_]; + new_.preds <- [ref_stmt]; + new_.succs <- old_succs; + List.iter + (fun succ_stmt -> + succ_stmt.preds <- + (List.map + (fun a_pred -> if a_pred.sid = ref_stmt.sid then new_ else a_pred) + succ_stmt.preds)) + old_succs + end; + new_ - let d_binop fmt b = - fprintf fmt "%s" - (match b with - PlusA | PlusPI | IndexPI -> "+" - | MinusA | MinusPP | MinusPI -> "-" - | Mult -> "*" - | Div -> "/" - | Mod -> "%" - | Shiftlt -> "<<" - | Shiftrt -> ">>" - | Lt -> "<" - | Gt -> ">" - | Le -> "<=" - | Ge -> ">=" - | Eq -> "==" - | Ne -> "!=" - | BAnd -> "&" - | BXor -> "^" - | BOr -> "|" - | LAnd -> "&&" - | LOr -> "||") + let mkStmtCfgBlock sl = + let sid = Sid.next () in + let n = mkStmt (Block (mkBlock sl)) in + n.sid <- sid; + match sl with + | [] -> n + | s::_ -> + let old_preds = s.preds in + n.succs <- [s]; + n.preds <- s.preds; + List.iter + (fun pred_stmt -> + pred_stmt.succs <- + (List.map + (fun a_succ -> if a_succ.sid = s.sid then + n + else a_succ) + pred_stmt.succs)) + old_preds; + n - let d_term_binop fmt b = - fprintf fmt "%s" - (match b with - PlusA | PlusPI | IndexPI -> "+" - | MinusA | MinusPP | MinusPI -> "-" - | Mult -> "*" - | Div -> "/" - | Mod -> "%" - | Shiftlt -> "<<" - | Shiftrt -> ">>" - | Lt -> "<" - | Gt -> ">" - | Le -> if !print_utf8 then Utf8_logic.le else "<=" - | Ge -> if !print_utf8 then Utf8_logic.ge else ">=" - | Eq -> if !print_utf8 then Utf8_logic.eq else "==" - | Ne -> if !print_utf8 then Utf8_logic.neq else "!=" - | BAnd -> "&" - | BXor -> "^" - | BOr -> "|" - | LAnd -> if !print_utf8 then Utf8_logic.conj else "&&" - | LOr -> if !print_utf8 then Utf8_logic.disj else "||") + let mkEmptyStmt ?ghost ?(loc=Location.unknown) () = mkStmt ?ghost (Instr (Skip loc)) + let mkStmtOneInstr ?ghost ?valid_sid i = mkStmt ?ghost ?valid_sid (Instr i) - let d_relation fmt b = - fprintf fmt "%s" - (match b with - | Rlt -> "<" - | Rgt -> ">" - | Rle -> if !print_utf8 then Utf8_logic.le else "<=" - | Rge -> if !print_utf8 then Utf8_logic.ge else ">=" - | Req -> if !print_utf8 then Utf8_logic.eq else "==" - | Rneq -> if !print_utf8 then Utf8_logic.neq else "!=") + let dummyInstr = Asm([], ["dummy statement!!"], [], [], [], Location.unknown) + let dummyStmt = mkStmt (Instr dummyInstr) - let invalidStmt = mkStmt (Instr (Skip Location.unknown)) + (*** + let compactStmts (b: stmt list) : stmt list = + (* Try to compress statements. Scan the list of statements and remember + * the last instrunction statement encountered, along with a Clist of + * instructions in it. *) + let rec compress (lastinstrstmt: stmt) (* Might be dummStmt *) + (lastinstrs: instr Clist.clist) + (body: stmt list) = + let finishLast (tail: stmt list) : stmt list = + if lastinstrstmt == dummyStmt then tail + else begin + lastinstrstmt.skind <- Instr (Clist.toList lastinstrs); + lastinstrstmt :: tail + end + in + match body with + [] -> finishLast [] + | ({skind=Instr il} as s) :: rest -> + let ils = Clist.fromList il in + if lastinstrstmt != dummyStmt && s.labels == [] then + compress lastinstrstmt (Clist.append lastinstrs ils) rest + else + finishLast (compress s ils rest) - module Builtin_functions = - State_builder.Hashtbl - (Datatype.String.Hashtbl) - (Datatype.Triple(Typ)(Datatype.List(Typ))(Datatype.Bool)) - (struct - let name = "Builtin_functions" - let dependencies = [ TheMachine.self ] - let size = 49 - let kind = `Internal - end) + | s :: rest -> + let res = s :: compress dummyStmt Clist.empty rest in + finishLast res + in + compress dummyStmt Clist.empty b + ***) - (* Initialize the builtin functions after the machine has been initialized. *) - let initGccBuiltins () : unit = - if not (TheMachine.is_computed ()) then - Cilmsg.fatal "Call initCIL before initGccBuiltins" ; - if Builtin_functions.length () <> 0 then - Cilmsg.fatal "builtins already initialized." ; - (* See if we have builtin_va_list *) - let hasbva = Machdep.state.Machdep.gccHas__builtin_va_list in - let sizeType = theMachine.upointType in - let add s t l b = Builtin_functions.add ("__builtin_" ^ s) (t, l, b) in + (**** ATTRIBUTES ****) - add "__fprintf_chk" - intType - (* first argument is really FILE*, not void*, but we don't want to build in - the definition for FILE *) - [ voidPtrType; intType; charConstPtrType ] - true; - add "__memcpy_chk" - voidPtrType - [ voidPtrType; voidConstPtrType; sizeType; sizeType ] - false; - add "__memmove_chk" - voidPtrType [ voidPtrType; voidConstPtrType; sizeType; sizeType ] false; - add "__mempcpy_chk" - voidPtrType [ voidPtrType; voidConstPtrType; sizeType; sizeType ] false; - add "__memset_chk" - voidPtrType [ voidPtrType; intType; sizeType; sizeType ] false; - add "__printf_chk" intType [ intType; charConstPtrType ] true; - add "__snprintf_chk" - intType [ charPtrType; sizeType; intType; sizeType; charConstPtrType ] true; - add "__sprintf_chk" - intType [ charPtrType; intType; sizeType; charConstPtrType ] true; - add "__stpcpy_chk" - charPtrType [ charPtrType; charConstPtrType; sizeType ] false; - add "__strcat_chk" - charPtrType [ charPtrType; charConstPtrType; sizeType ] false; - add "__strcpy_chk" - charPtrType [ charPtrType; charConstPtrType; sizeType ] false; - add "__strncat_chk" - charPtrType [ charPtrType; charConstPtrType; sizeType; sizeType ] false; - add "__strncpy_chk" - charPtrType [ charPtrType; charConstPtrType; sizeType; sizeType ] false; - add "__vfprintf_chk" - intType - (* first argument is really FILE*, not void*, but we don't want to build in - the definition for FILE *) - [ voidPtrType; intType; charConstPtrType; TBuiltin_va_list [] ] - false; - add "__vprintf_chk" - intType [ intType; charConstPtrType; TBuiltin_va_list [] ] false; - add "__vsnprintf_chk" - intType - [ charPtrType; sizeType; intType; sizeType; charConstPtrType; - TBuiltin_va_list [] ] - false; - add "__vsprintf_chk" - intType - [ charPtrType; intType; sizeType; charConstPtrType; TBuiltin_va_list [] ] - false; - add "alloca" voidPtrType [ sizeType ] false; + (* JS: build an attribute annotation from [s]. *) + let mkAttrAnnot s = "/*@ " ^ s ^ " */" - add "acos" doubleType [ doubleType ] false; - add "acosf" floatType [ floatType ] false; - add "acosl" longDoubleType [ longDoubleType ] false; +(* Internal attributes. Won't be pretty-printed *) +let reserved_attributes = ref [] +let register_shallow_attribute s = reserved_attributes:=s::!reserved_attributes - add "asin" doubleType [ doubleType ] false; - add "asinf" floatType [ floatType ] false; - add "asinl" longDoubleType [ longDoubleType ] false; +let qualifier_attributes = [ "const"; "restrict"; "volatile"] + +let type_remove_qualifier_attributes = + typeRemoveAttributes qualifier_attributes + +let filter_qualifier_attributes al = + List.filter + (fun a -> List.mem (attributeName a) qualifier_attributes) al + +type attributeClass = + | AttrName of bool + (* Attribute of a name. If argument is true and we are on MSVC then + * the attribute is printed using __declspec as part of the storage + * specifier *) + | AttrFunType of bool + (* Attribute of a function type. If argument is true and we are on + * MSVC then the attribute is printed just before the function name *) - add "atan" doubleType [ doubleType ] false; - add "atanf" floatType [ floatType ] false; - add "atanl" longDoubleType [ longDoubleType ] false; + | AttrType (* Attribute of a type *) - add "atan2" doubleType [ doubleType; doubleType ] false; - add "atan2f" floatType [ floatType; floatType ] false; - add "atan2l" longDoubleType [ longDoubleType; - longDoubleType ] false; + (* This table contains the mapping of predefined attributes to classes. + * Extend this table with more attributes as you need. This table is used to + * determine how to associate attributes with names or type during cabs2cil + * conversion *) + let attributeHash: (string, attributeClass) Hashtbl.t = + let table = Hashtbl.create 13 in + List.iter (fun a -> Hashtbl.add table a (AttrName false)) + [ "section"; "constructor"; "destructor"; "unused"; "used"; "weak"; + "no_instrument_function"; "alias"; "no_check_memory_usage"; + "exception"; "model"; (* "restrict"; *) + "aconst"; "__asm__" (* Gcc uses this to specifiy the name to be used in + * assembly for a global *)]; + (* Now come the MSVC declspec attributes *) + List.iter (fun a -> Hashtbl.add table a (AttrName true)) + [ "thread"; "naked"; "dllimport"; "dllexport"; + "selectany"; "allocate"; "nothrow"; "novtable"; "property"; "noreturn"; + "uuid"; "align" ]; + List.iter (fun a -> Hashtbl.add table a (AttrFunType false)) + [ "format"; "regparm"; "longcall"; "noinline"; "always_inline" ]; + List.iter (fun a -> Hashtbl.add table a (AttrFunType true)) + [ "stdcall";"cdecl"; "fastcall" ]; + List.iter (fun a -> Hashtbl.add table a AttrType) + [ "const"; "volatile"; "restrict"; "mode" ]; + table - add "ceil" doubleType [ doubleType ] false; - add "ceilf" floatType [ floatType ] false; - add "ceill" longDoubleType [ longDoubleType ] false; + let attributeClass = Hashtbl.find attributeHash - add "cos" doubleType [ doubleType ] false; - add "cosf" floatType [ floatType ] false; - add "cosl" longDoubleType [ longDoubleType ] false; + let registerAttribute = Hashtbl.add attributeHash + let removeAttribute = Hashtbl.remove attributeHash - add "cosh" doubleType [ doubleType ] false; - add "coshf" floatType [ floatType ] false; - add "coshl" longDoubleType [ longDoubleType ] false; + (** Partition the attributes into classes *) + let partitionAttributes + ~(default:attributeClass) + (attrs: attribute list) : + attribute list * attribute list * attribute list = + let rec loop (n,f,t) = function + [] -> n, f, t + | (Attr(an, _) | AttrAnnot an as a) :: rest -> + match (try Hashtbl.find attributeHash an with Not_found -> default) with + AttrName _ -> loop (addAttribute a n, f, t) rest + | AttrFunType _ -> + loop (n, addAttribute a f, t) rest + | AttrType -> loop (n, f, addAttribute a t) rest + in + loop ([], [], []) attrs - add "clz" intType [ uintType ] false; - add "clzl" intType [ ulongType ] false; - add "clzll" intType [ ulongLongType ] false; - add "constant_p" intType [ intType ] false; - add "ctz" intType [ uintType ] false; - add "ctzl" intType [ ulongType ] false; - add "ctzll" intType [ ulongLongType ] false; - add "exp" doubleType [ doubleType ] false; - add "expf" floatType [ floatType ] false; - add "expl" longDoubleType [ longDoubleType ] false; + (** Get the full name of a comp *) + let compFullName comp = + (if comp.cstruct then "struct " else "union ") ^ comp.cname - add "expect" longType [ longType; longType ] false; - add "fabs" doubleType [ doubleType ] false; - add "fabsf" floatType [ floatType ] false; - add "fabsl" longDoubleType [ longDoubleType ] false; + let missingFieldName = "" (* "___missing_field_name"*) - add "ffs" intType [ uintType ] false; - add "ffsl" intType [ ulongType ] false; - add "ffsll" intType [ ulongLongType ] false; - add "frame_address" voidPtrType [ uintType ] false; + (** Creates a (potentially recursive) composite type. Make sure you add a + * GTag for it to the file! **) + let mkCompInfo + (isstruct: bool) + (n: string) + (* fspec is a function that when given a forward + * representation of the structure type constructs the type of + * the fields. The function can ignore this argument if not + * constructing a recursive type. *) + (mkfspec: compinfo -> (string * typ * int option * attribute list * + location) list) + (a: attribute list) : compinfo = - add "floor" doubleType [ doubleType ] false; - add "floorf" floatType [ floatType ] false; - add "floorl" longDoubleType [ longDoubleType ] false; + (* make a new name for anonymous structs *) + if n = "" then Kernel.fatal "mkCompInfo: missing structure name\n" ; + (* Make a new self cell and a forward reference *) + let comp = + { cstruct = isstruct; + corig_name = n; + cname = n; + ckey = nextCompinfoKey (); + cfields = []; (* fields will be added afterwards. *) + cattr = a; + creferenced = false; + (* Make this compinfo undefined by default *) + cdefined = false; } + in + let flds = + List.map (fun (fn, ft, fb, fa, fl) -> + { fcomp = comp; + ftype = ft; + forig_name = fn; + fname = fn; + fbitfield = fb; + fattr = fa; + floc = fl; + faddrof = false; + fsize_in_bits = None; + foffset_in_bits = None; + fpadding_in_bits = None; + }) (mkfspec comp) in + comp.cfields <- flds; + if flds <> [] then comp.cdefined <- true; + comp - add "huge_val" doubleType [] false; - add "huge_valf" floatType [] false; - add "huge_vall" longDoubleType [] false; - add "inf" doubleType [] false; - add "inff" floatType [] false; - add "infl" longDoubleType [] false; - add "memcpy" voidPtrType [ voidPtrType; voidConstPtrType; sizeType ] false; - add "mempcpy" voidPtrType [ voidPtrType; voidConstPtrType; sizeType ] false; - add "memset" voidPtrType [ voidPtrType; intType; intType ] false; + (** Make a copy of a compinfo, changing the name and the key *) + let copyCompInfo (ci: compinfo) (n: string) : compinfo = + let ci' = {ci with cname = n; ckey = nextCompinfoKey (); } in + (* Copy the fields and set the new pointers to parents *) + ci'.cfields <- List.map (fun f -> {f with fcomp = ci'}) ci'.cfields; + ci' - add "fmod" doubleType [ doubleType ] false; - add "fmodf" floatType [ floatType ] false; - add "fmodl" longDoubleType [ longDoubleType ] false; + let rec unrollTypeDeep (t: typ) : typ = + let rec withAttrs (al: attributes) (t: typ) : typ = + match t with + TNamed (r, a') -> withAttrs (addAttributes al a') r.ttype + | TPtr(t, a') -> TPtr(unrollTypeDeep t, addAttributes al a') + | TArray(t, l, s, a') -> TArray(unrollTypeDeep t, l, s, addAttributes al a') + | TFun(rt, args, isva, a') -> + TFun (unrollTypeDeep rt, + (match args with + None -> None + | Some argl -> + Some (List.map (fun (an,at,aa) -> + (an, unrollTypeDeep at, aa)) argl)), + isva, + addAttributes al a') + | x -> typeAddAttributes al x + in + withAttrs [] t - add "frexp" doubleType [ doubleType; intPtrType ] false; - add "frexpf" floatType [ floatType; intPtrType ] false; - add "frexpl" longDoubleType [ longDoubleType; intPtrType ] false; + let isVoidType t = + match unrollType t with + TVoid _ -> true + | _ -> false + let isVoidPtrType t = + match unrollType t with + TPtr(tau,_) when isVoidType tau -> true + | _ -> false - add "ldexp" doubleType [ doubleType; intType ] false; - add "ldexpf" floatType [ floatType; intType ] false; - add "ldexpl" longDoubleType [ longDoubleType; intType ] false; - - add "log" doubleType [ doubleType ] false; - add "logf" floatType [ floatType ] false; - add "logl" longDoubleType [ longDoubleType ] false; - - add "log10" doubleType [ doubleType ] false; - add "log10f" floatType [ floatType ] false; - add "log10l" longDoubleType [ longDoubleType ] false; + let isSignedInteger ty = + match unrollType ty with + | TInt(ik,_) | TEnum ({ekind=ik},_) -> isSigned ik + | _ -> false - add "modff" floatType [ floatType; TPtr(floatType,[]) ] false; - add "modfl" - longDoubleType [ longDoubleType; TPtr(longDoubleType, []) ] false; + let var vi : lval = (Var vi, NoOffset) + (* let assign vi e = Cil_datatype.Instrs(Set (var vi, e), lu) *) - add "nan" doubleType [ charConstPtrType ] false; - add "nanf" floatType [ charConstPtrType ] false; - add "nanl" longDoubleType [ charConstPtrType ] false; - add "nans" doubleType [ charConstPtrType ] false; - add "nansf" floatType [ charConstPtrType ] false; - add "nansl" longDoubleType [ charConstPtrType ] false; - add "next_arg" - (* When we parse builtin_next_arg we drop the second argument *) - (if hasbva then TBuiltin_va_list [] else voidPtrType) [] false; - add "object_size" sizeType [ voidPtrType; intType ] false; + let evar ~loc vi = new_exp ~loc (Lval (var vi)) - add "parity" intType [ uintType ] false; - add "parityl" intType [ ulongType ] false; - add "parityll" intType [ ulongLongType ] false; + let mkString ~loc s = new_exp ~loc (Const(CStr s)) - add "popcount" intType [ uintType ] false; - add "popcountl" intType [ ulongType ] false; - add "popcountll" intType [ ulongLongType ] false; + let mkWhile ~(guard:exp) ~(body: stmt list) : stmt list = + (* Do it like this so that the pretty printer recognizes it *) + [ mkStmt + (Loop ([], + mkBlock + (mkStmt + (If(guard, + mkBlock [ mkEmptyStmt () ], + mkBlock [ mkStmt (Break guard.eloc)], guard.eloc)) :: + body), guard.eloc, None, None)) ] - add "powi" doubleType [ doubleType; intType ] false; - add "powif" floatType [ floatType; intType ] false; - add "powil" longDoubleType [ longDoubleType; intType ] false; - add "prefetch" voidType [ voidConstPtrType ] true; - add "return" voidType [ voidConstPtrType ] false; - add "return_address" voidPtrType [ uintType ] false; + let mkFor ~(start: stmt list) ~(guard: exp) ~(next: stmt list) + ~(body: stmt list) : stmt list = + (start @ + (mkWhile guard (body @ next))) - add "sin" doubleType [ doubleType ] false; - add "sinf" floatType [ floatType ] false; - add "sinl" longDoubleType [ longDoubleType ] false; + let mkForIncr ~(iter : varinfo) ~(first: exp) ~stopat:(past: exp) ~(incr: exp) + ~(body: stmt list) : stmt list = + (* See what kind of operator we need *) + let compop, nextop = + match unrollType iter.vtype with + TPtr _ -> Lt, PlusPI + | _ -> Lt, PlusA + in + mkFor + [ mkStmt (Instr (Set (var iter, first, first.eloc))) ] + (new_exp ~loc:past.eloc + (BinOp(compop, new_exp ~loc:past.eloc (Lval(var iter)), past, intType))) + [ mkStmt + (Instr + (Set + (var iter, + (new_exp ~loc:incr.eloc + (BinOp(nextop, + new_exp ~loc:past.eloc (Lval(var iter)), + incr, + iter.vtype))), + incr.eloc)))] + body - add "sinh" doubleType [ doubleType ] false; - add "sinhf" floatType [ floatType ] false; - add "sinhl" longDoubleType [ longDoubleType ] false; + let block_from_unspecified_sequence us = + { battrs = []; bstmts = List.map (fun (x,_,_,_,_) ->x) us; blocals = [] } - add "sqrt" doubleType [ doubleType ] false; - add "sqrtf" floatType [ floatType ] false; - add "sqrtl" longDoubleType [ longDoubleType ] false; + let rec stripCasts (e: exp) = + match e.enode with CastE(_, e') -> stripCasts e' | _ -> e - add "stpcpy" charPtrType [ charPtrType; charConstPtrType ] false; - add "strchr" charPtrType [ charPtrType; intType ] false; - add "strcmp" intType [ charConstPtrType; charConstPtrType ] false; - add "strcpy" charPtrType [ charPtrType; charConstPtrType ] false; - add "strcspn" sizeType [ charConstPtrType; charConstPtrType ] false; - add "strncat" charPtrType [ charPtrType; charConstPtrType; sizeType ] false; - add "strncmp" intType [ charConstPtrType; charConstPtrType; sizeType ] false; - add "strncpy" charPtrType [ charPtrType; charConstPtrType; sizeType ] false; - add "strspn" sizeType [ charConstPtrType; charConstPtrType ] false; - add "strpbrk" charPtrType [ charConstPtrType; charConstPtrType ] false; - (* When we parse builtin_types_compatible_p, we change its interface *) - add "types_compatible_p" - intType - [ theMachine.typeOfSizeOf;(* Sizeof the type *) - theMachine.typeOfSizeOf (* Sizeof the type *) ] - false; - add "tan" doubleType [ doubleType ] false; - add "tanf" floatType [ floatType ] false; - add "tanl" longDoubleType [ longDoubleType ] false; + let rec stripCastsAndInfo (e: exp) = + match e.enode with Info(e',_) | CastE(_,e') -> stripCastsAndInfo e' | _ -> e - add "tanh" doubleType [ doubleType ] false; - add "tanhf" floatType [ floatType ] false; - add "tanhl" longDoubleType [ longDoubleType ] false; + let rec stripCastsButLastInfo (e: exp) = + match e.enode with + Info({enode = (Info _ | CastE _)} as e',_) + | CastE(_,e') -> + stripCastsButLastInfo e' + | _ -> e + let rec stripTermCasts (t: term) = + match t.term_node with TCastE(_, t') -> stripTermCasts t' | _ -> t - if hasbva then begin - add "va_end" voidType [ TBuiltin_va_list [] ] false; - add "varargs_start" voidType [ TBuiltin_va_list [] ] false; - (* When we parse builtin_{va,stdarg}_start, we drop the second argument *) - add "va_start" voidType [ TBuiltin_va_list [] ] false; - add "stdarg_start" voidType [ TBuiltin_va_list [] ] false; - (* When we parse builtin_va_arg we change its interface *) - add "va_arg" - voidType - [ TBuiltin_va_list []; - theMachine.typeOfSizeOf;(* Sizeof the type *) - voidPtrType (* Ptr to res *) ] - false; - add "va_copy" voidType [ TBuiltin_va_list []; TBuiltin_va_list [] ] false; - end +let exp_info_of_term t = { exp_type = t.term_type; exp_name = t.term_name;} -(* [VP] Should we projectify this ?*) -let special_builtins_table = ref Datatype.String.Set.empty -let special_builtins = Queue.create () +let term_of_exp_info loc tnode einfo = + { + term_node = tnode; term_loc = loc; + term_type = einfo.exp_type; term_name = einfo.exp_name; + } -let is_special_builtin s = - Queue.fold (fun res f -> res || f s) false special_builtins +let map_under_info f e = match e.enode with + | Info(e,einfo) -> new_exp ~loc:e.eloc (Info(f e,einfo)) + | _ -> f e -let add_special_builtin_family f = Queue.add f special_builtins + let app_under_info f e = match e.enode with + | Info(e,_) -> f e + | _ -> f e -let add_special_builtin s = - special_builtins_table := Datatype.String.Set.add s !special_builtins_table + (* the name of the C function we call to get ccgr ASTs + external parse : string -> file = "cil_main" + *) + (* + Pretty Printing + *) -let () = add_special_builtin_family - (fun s -> Datatype.String.Set.mem s !special_builtins_table) + let d_ikind fmt c = + fprintf fmt "%s" + ( match c with + | IChar -> "char" + | IBool -> "_Bool" + | ISChar -> "signed char" + | IUChar -> "unsigned char" + | IInt -> "int" + | IUInt -> "unsigned int" + | IShort -> "short" + | IUShort -> "unsigned short" + | ILong -> "long" + | IULong -> "unsigned long" + | ILongLong -> + if theMachine.msvcMode then "__int64" else "long long" + | IULongLong -> + if theMachine.msvcMode then "unsigned __int64" + else "unsigned long long") -let () = List.iter add_special_builtin - [ "__builtin_stdarg_start"; "__builtin_va_arg"; - "__builtin_va_start"; "__builtin_expect"; "__builtin_next_arg"; ] + let () = pd_ikind := d_ikind -(** Construct a hash with the builtins *) -let initMsvcBuiltins () : unit = - if not (TheMachine.is_computed ()) then - Cilmsg.fatal "Call initCIL before initMsvcBuiltins" ; - if Builtin_functions.length () <> 0 then - Cilmsg.fatal "builtins already initialized." ; - (** Take a number of wide string literals *) - Builtin_functions.add "__annotation" (voidType, [ ], true); - () + let d_fkind fmt = function + FFloat -> fprintf fmt "float" + | FDouble -> fprintf fmt "double" + | FLongDouble -> fprintf fmt "long double" - (** This is used as the location of the prototypes of builtin functions. *) - let builtinLoc: location = Location.unknown + let d_storage fmt c = + fprintf fmt "%s" + ( match c with + | NoStorage -> "" + | Static -> "static " + | Extern -> "extern " + | Register -> "register ") - let range_loc loc1 loc2 = fst loc1, snd loc2 + (* sm: need this value below *) + let mostNeg32BitInt : int64 = (Int64.of_string "-0x80000000") + let mostNeg64BitInt : int64 = (Int64.of_string "-0x8000000000000000") - let pred_body = function - | LBpred a -> a - | LBnone - | LBreads _ - | LBinductive _ - | LBterm _ -> Cilmsg.fatal "definition expected in Cil.pred_body" + let pretty_C_constant suffix k fmt i = + let nb_signed_bits = + My_bigint.pred (My_bigint.of_int (8 * (bytesSizeOfInt k))) + in + let max_strict_signed = My_bigint.shift_left My_bigint.one nb_signed_bits in + let most_neg = My_bigint.neg max_strict_signed in + if My_bigint.equal most_neg i then + (* sm: quirk here: if you print -2147483648 then this is two + tokens in C, and the second one is too large to represent in + a signed int.. + so we do what's done in limits.h, and print (-2147483467-1); *) + (* in gcc this avoids a warning, but it might avoid a real + problem on another compiler or a 64-bit architecture *) + Format.fprintf fmt "(-%a-1)" + (My_bigint.pretty ~hexa:true) (My_bigint.pred max_strict_signed) + else + Format.fprintf fmt "%a%s" + (My_bigint.pretty ~hexa:false) i + suffix + + let default_int64_printer fmt n = Format.fprintf fmt "%Ld" n + + let int64_hexa_printer fmt n = + if Kernel.BigIntsHex.is_default () then + Format.fprintf fmt "%Ld" n + else + if Int64.abs n >= Int64.of_int (Kernel.BigIntsHex.get ()) then + if n >= Int64.zero then Format.fprintf fmt "0x%Lx" n + else Format.fprintf fmt "-0x%Lx" (Int64.neg n) + else + Format.fprintf fmt "%Ld" n + let regexp_int_decimal = Str.regexp "^-?[0-9]+$" + let print_as_source source = + Kernel.BigIntsHex.is_default () || + not (Str.string_match regexp_int_decimal source 0) - (** A printer interface for CIL trees. Create instantiations of - * this type by specializing the class {!Cil.defaultCilPrinter}. *) - class type cilPrinter = object + (* constant *) + let d_const fmt c = + match c with + | CInt64(_, _, Some s) when print_as_source s -> + fprintf fmt "%s" s (* Always print the text if there is one, unless + we want to print it as hexa *) + | CInt64(i, ik, _) -> + (*fprintf fmt "/* %Lx */" i;*) + (** We must make sure to capture the type of the constant. For some + constants this is done with a suffix, for others with a cast + prefix.*) + let suffix = match ik with + | IUInt -> "U" + | ILong -> "L" + | IULong -> "UL" + | ILongLong -> if theMachine.msvcMode then "L" else "LL" + | IULongLong -> if theMachine.msvcMode then "UL" else "ULL" + | IInt | IBool | IShort | IUShort | IChar | ISChar | IUChar -> "" + in + let prefix = + if suffix <> "" then "" + else if ik = IInt then "" + else Pretty_utils.sfprintf "(%a)" d_ikind ik + in + fprintf fmt "%s%a" prefix (pretty_C_constant suffix ik) i - (** Local logical annotation (function specifications and code annotations - are printed only if [logic_printer_enabled] is set to true - *) - val mutable logic_printer_enabled : bool + | CStr(s) -> fprintf fmt "\"%s\"" (Escape.escape_string s) + | CWStr(s) -> + (* text ("L\"" ^ escape_string s ^ "\"") *) + fprintf fmt "L"; + List.iter + (fun elt -> + if (elt >= Int64.zero && + elt <= (Int64.of_int 255)) then + fprintf fmt "%S" + (Escape.escape_char (Char.chr (Int64.to_int elt))) + else + fprintf fmt "\"\\x%LX\"" elt; + fprintf fmt "@ ") + s; + (* we cannot print L"\xabcd" "feedme" as L"\xabcdfeedme" -- + * the former has 7 wide characters and the later has 3. *) - (** more info is displayed on verbose mode. *) - val mutable verbose: bool + | CChr(c) -> fprintf fmt "'%s'" (Escape.escape_char c) + | CReal(_, _, Some s) -> fprintf fmt "%s" s + | CReal(f, fsize, None) -> + fprintf fmt "%s%s" (string_of_float f) + (match fsize with + FFloat -> "f" + | FDouble -> "" + | FLongDouble -> "L") + | CEnum {einame = s} -> fprintf fmt "%s" s - method current_function: varinfo option - (** Returns the [varinfo] corresponding to the function being printed *) - method has_annot: bool - (** true if [current_stmt] has some annotations attached to it. *) + (* Parentheses/precedence level. An expression "a op b" is printed + * parenthesized if its parentheses level is >= that that of its context. + * Identifiers have the lowest level and weakly binding operators (e.g. |) + * have the largest level. The correctness criterion is that a smaller level + * MUST correspond to a stronger precedence! *) - method current_stmt: stmt option - (** Returns the stmt being printed *) + let derefStarLevel = 20 + let indexLevel = 20 + let arrowLevel = 20 + let addrOfLevel = 30 + let additiveLevel = 60 + let comparativeLevel = 70 + let bitwiseLevel = 75 + let logic_level = 77 + let binderLevel = 90 + let questionLevel = 100 + let upperLevel = 110 - method current_behavior: funbehavior option - (** Returns the [funbehavior] being pretty-printed. *) - - method may_be_skipped: stmt -> bool - - method setPrintInstrTerminator : string -> unit - method getPrintInstrTerminator : unit -> string + let getParenthLevelPred = function + | Pfalse + | Ptrue + | Papp _ + | Pvalid _ + | Pinitialized _ + | Pseparated _ + | Pat _ + | Pfresh _ + | Pvalid_index _ + | Pvalid_range _ -> 0 - method pVarName: Format.formatter -> string -> unit - (** Invoked each time an identifier name is to be printed. Allows for - various manipulation of the name, such as unmangling. *) + | Psubtype _ -> 75 - method pVDecl: Format.formatter -> varinfo -> unit - (** Invoked for each variable declaration. Note that variable - * declarations are all the [GVar], [GVarDecl], [GFun], all the [varinfo] - * in formals of function types, and the formals and locals for function - * definitions. *) + | Pnot _ -> 30 - method pVar: Format.formatter -> varinfo -> unit - (** Invoked on each variable use. *) + | Pand _ + | Por _ + | Pxor _ -> 85 - method pLval: Format.formatter -> lval -> unit - (** Invoked on each lvalue occurence *) + | Pimplies _ -> 88 + | Piff _ -> 89 + | Pif _ -> questionLevel - method pOffset: Format.formatter -> offset -> unit - (** Invoked on each offset occurence. The second argument is the base. *) + | Prel _ -> comparativeLevel - method pInstr: Format.formatter -> instr -> unit - (** Invoked on each instruction occurrence. *) + | Plet _ + | Pforall _ + | Pexists _ -> binderLevel - method pStmt: Format.formatter -> stmt -> unit - (** Control-flow statement. This is used by - * {!Cil.printGlobal} and by [Cil.dumpGlobal]. *) + let getParenthLevel e = match (stripInfo e).enode with + | Info _ -> assert false + | BinOp((LAnd | LOr), _,_,_) -> 80 + (* Bit operations. *) + | BinOp((BOr|BXor|BAnd),_,_,_) -> bitwiseLevel (* 75 *) - method pStmtNext : stmt -> Format.formatter -> stmt -> unit + (* Comparisons *) + | BinOp((Eq|Ne|Gt|Lt|Ge|Le),_,_,_) -> + comparativeLevel (* 70 *) + (* Additive. Shifts can have higher + * level than + or - but I want + * parentheses around them *) + | BinOp((MinusA|MinusPP|MinusPI|PlusA| + PlusPI|IndexPI|Shiftlt|Shiftrt),_,_,_) + -> additiveLevel (* 60 *) - method requireBraces: block -> bool (* Cf. cil.mli *) + (* Multiplicative *) + | BinOp((Div|Mod|Mult),_,_,_) -> 40 - method pBlock: - ?nobrace:bool -> ?forcenewline:bool -> Format.formatter -> block -> unit - (** Print a block. *) + (* Unary *) + | CastE(_,_) -> 30 + | AddrOf(_) -> 30 + | StartOf(_) -> 30 + | UnOp((Neg|BNot|LNot),_,_) -> 30 - method pGlobal: Format.formatter -> global -> unit - (** Global (vars, types, etc.). This can be slow and is used only by - * {!Cil.printGlobal} but by {!Cil.dumpGlobal} for everything else except - * [GVar] and [GFun]. *) + (* Lvals *) + | Lval(Mem _ , _) -> derefStarLevel (* 20 *) + | Lval(Var _, (Field _|Index _)) -> indexLevel (* 20 *) + | SizeOf _ | SizeOfE _ | SizeOfStr _ -> 20 + | AlignOf _ | AlignOfE _ -> 20 - method pFieldDecl: Format.formatter -> fieldinfo -> unit - (** A field declaration *) + | Lval(Var _, NoOffset) -> 0 (* Plain variables *) + | Const _ -> 0 (* Constants *) - method pType: ?fundecl:varinfo -> - (Format.formatter -> unit) option -> Format.formatter -> typ -> unit + let getParenthLevelLogic = function + | Tlambda _ | Trange _ | Tlet _ -> binderLevel + | TBinOp((LAnd | LOr), _,_) -> 80 + (* Bit operations. *) + | TBinOp((BOr|BXor|BAnd),_,_) -> bitwiseLevel (* 75 *) - method pAttr: Format.formatter -> attribute -> bool - (** Attribute. Also return an indication whether this attribute must be - * printed inside the __attribute__ list or not. *) + (* Comparisons *) + | TBinOp((Eq|Ne|Gt|Lt|Ge|Le),_,_) -> + comparativeLevel (* 70 *) + (* Additive. Shifts can have higher + * level than + or - but I want + * parentheses around them *) + | TBinOp((MinusA|MinusPP|MinusPI|PlusA| + PlusPI|IndexPI|Shiftlt|Shiftrt),_,_) + -> additiveLevel (* 60 *) - method pAttrParam: Format.formatter -> attrparam -> unit - (** Attribute paramter *) + (* Multiplicative *) + | TBinOp((Div|Mod|Mult),_,_) -> 40 - method pAttrs: Format.formatter -> attributes -> unit - (** Attribute lists *) + (* Unary *) + | TCastE(_,_) -> 30 + | TAddrOf(_) -> addrOfLevel + | TStartOf(_) -> 30 + | TUnOp((Neg|BNot|LNot),_) -> 30 + (* Unary post *) + | TCoerce _ | TCoerceE _ -> 25 - method pLabel: Format.formatter -> label -> unit - (** Label *) + (* Lvals *) + | TLval(TMem _ , _) -> derefStarLevel + | TLval(TVar _, (TField _|TIndex _)) -> indexLevel + | TLval(TResult _,(TField _|TIndex _)) -> indexLevel + | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ -> 20 + | TAlignOf _ | TAlignOfE _ -> 20 + (* VP: I'm not sure I understand why sizeof(x) and f(x) should + have a separated treatment wrt parentheses. *) + (* application and applications-like constructions *) + | Tapp (_, _,_)|TDataCons _ + | Tblock_length _ | Tbase_addr _ | Tat (_, _) + | Tunion _ | Tinter _ + | TUpdate _ | Ttypeof _ | Ttype _ -> 10 + | TLval(TVar _, TNoOffset) -> 0 (* Plain variables *) + (* Constructions that do not require parentheses *) + | TConst _ + | Tnull | TLval (TResult _,TNoOffset) | Tcomprehension _ | Tempty_set -> 0 + | Tif (_, _, _) -> logic_level - method pLineDirective: ?forcefile:bool -> Format.formatter -> location -> unit - (** Print a line-number. This is assumed to come always on an empty line. - * If the forcefile argument is present and is true then the file name - * will be printed always. Otherwise the file name is printed only if it - * is different from the last time time this function is called. The last - * file name is stored in a private field inside the cilPrinter object. *) + let getParenthLevelAttrParam (a: attrparam) = + (* Create an expression of the same shape, and use {!getParenthLevel} *) + match a with + AInt _ | AStr _ | ACons _ -> 0 + | ASizeOf _ | ASizeOfE _ | ASizeOfS _ -> 20 + | AAlignOf _ | AAlignOfE _ | AAlignOfS _ -> 20 + | AUnOp (uo, _) -> getParenthLevel + (dummy_exp (UnOp(uo, zero ~loc:Cil_datatype.Location.unknown, intType))) + | ABinOp (bo, _, _) -> + getParenthLevel (dummy_exp(BinOp(bo, + zero ~loc:Cil_datatype.Location.unknown, + zero ~loc:Cil_datatype.Location.unknown, + intType))) + | AAddrOf _ -> 30 + | ADot _ | AIndex _ | AStar _ -> 20 + | AQuestion _ -> questionLevel - method pStmtLabels : Format.formatter -> stmt -> unit - (** Print only the labels of the statement. Used by [pAnnotatedStmt]. *) - method pAnnotatedStmt : stmt -> Format.formatter -> stmt -> unit - (** Print an annotated statement. The code to be printed is given in the - * last {!stmt} argument. The initial {!stmt} argument - * records the statement which follows the one being printed; - * {!Cil.defaultCilPrinterClass} uses this information to prettify - * statement printing in certain special cases. *) + (* Separate out the storage-modifier name attributes *) + let separateStorageModifiers (al: attribute list) = + let isstoragemod (Attr(an, _) | AttrAnnot an : attribute) : bool = + try + match Hashtbl.find attributeHash an with + AttrName issm -> issm + | _ -> false + with Not_found -> false + in + let stom, rest = List.partition isstoragemod al in + if not theMachine.msvcMode then + stom, rest + else + (* Put back the declspec. Put it without the leading __ since these will + * be added later *) + let stom' = + List.map + (function + | Attr(an, args) -> Attr("declspec", [ACons(an, args)]) + | AttrAnnot _ -> assert false) + stom + in + stom', rest - method pStmtKind : stmt -> Format.formatter -> stmtkind -> unit - (** Print a statement kind. The code to be printed is given in the - * {!stmtkind} argument. The initial {!Cil.stmt} argument - * records the statement which follows the one being printed; - * {!Cil.defaultCilPrinterClass} uses this information to prettify - * statement printing in certain special cases. - *) - method pExp: Format.formatter -> exp -> unit - (** Print expressions *) + let isCharType t = + match unrollType t with + | TInt((IChar|ISChar|IUChar),_) -> true + | _ -> false - method pInit: Format.formatter -> init -> unit - (** Print initializers. This can be slow and is used by - * {!Cil.printGlobal} but not by {!Cil.dumpGlobal}. *) +let isShortType t = + match unrollType t with + | TInt((IUShort|IShort),_) -> true + | _ -> false - method pLogic_type: - (Format.formatter -> unit) option -> - Format.formatter -> logic_type -> unit - (** The first argument gives the name of the declared variable. see pType for more - information. *) +let isCharPtrType t = + match unrollType t with + TPtr(tau,_) when isCharType tau -> true + | _ -> false - method pTerm: Format.formatter -> term -> unit + let isIntegralType t = + match unrollType t with + (TInt _ | TEnum _) -> true + | _ -> false - method pTerm_node: Format.formatter -> term -> unit + let isLogicIntegralType t = + match t with + | Ctype t -> isIntegralType t + | Linteger -> true + | Lreal -> false + | Lvar _ | Ltype _ | Larrow _ -> false - method pTerm_lval: Format.formatter -> term_lval -> unit + let isFloatingType t = + match unrollType t with + TFloat _ -> true + | _ -> false - method pTerm_offset: Format.formatter -> term_offset -> unit + let isLogicFloatType t = + match t with + | Ctype t -> isFloatingType t + | Linteger -> false + | Lreal -> false + | Lvar _ | Ltype _ | Larrow _ -> false - method pLogic_info_use: Format.formatter -> logic_info -> unit + let isLogicRealOrFloatType t = + match t with + | Ctype t -> isFloatingType t + | Linteger -> false + | Lreal -> true + | Lvar _ | Ltype _ | Larrow _ -> false - method pLogic_type_def: Format.formatter -> logic_type_def -> unit + let isLogicRealType t = + match t with + | Ctype _ -> false + | Linteger -> false + | Lreal -> true + | Lvar _ | Ltype _ | Larrow _ -> false - method pLogic_var: Format.formatter -> logic_var -> unit + let isArithmeticType t = + match unrollType t with + (TInt _ | TEnum _ | TFloat _) -> true + | _ -> false - method pQuantifiers: Format.formatter -> quantifiers -> unit - - method pPredicate: Format.formatter -> predicate -> unit - - method pPredicate_named: Format.formatter -> predicate named -> unit - - method pIdentified_predicate: - Format.formatter -> identified_predicate -> unit + let isLogicArithmeticType t = + match t with + | Ctype t -> isArithmeticType t + | Linteger | Lreal -> true + | Lvar _ | Ltype _ | Larrow _ -> false - (* - method pPredicate_info_use: Format.formatter -> predicate_info -> unit - *) + let isPointerType t = + match unrollType t with + TPtr _ -> true + | _ -> false - method pBehavior: Format.formatter -> funbehavior -> unit + let isTypeTagType t = + match t with + Ltype({lt_name = "typetag"},[]) -> true + | _ -> false - method pRequires: Format.formatter -> identified_predicate -> unit - method pPost_cond: Format.formatter -> - (termination_kind * identified_predicate) -> unit - method pAssumes: Format.formatter -> identified_predicate -> unit + let isVariadicListType t = + match unrollType t with + | TBuiltin_va_list _ -> true + | _ -> false - method pComplete_behaviors: Format.formatter -> string list -> unit - method pDisjoint_behaviors: Format.formatter -> string list -> unit + let getReturnType t = + match unrollType t with + | TFun(rt,_,_,_) -> rt + | _ -> Kernel.fatal "getReturnType: not a function type" - method pTerminates: Format.formatter -> identified_predicate -> unit + let setReturnTypeVI (v: varinfo) (t: typ) = + match unrollType v.vtype with + | TFun (_, args, va, a) -> + v.vtype <- TFun (t, args, va, a) + | _ -> Kernel.fatal "setReturnType: not a function type" - method pSpec: Format.formatter -> funspec -> unit + let setReturnType (f:fundec) (t:typ) = + setReturnTypeVI f.svar t - method pAssigns: - string -> Format.formatter -> identified_term assigns -> unit + (** Returns the type pointed by the given type. Asserts it is a pointer type *) + let typeOf_pointed typ = + match unrollType typ with + | TPtr (typ,_) -> typ + | _ -> assert false - method pFrom: - string -> Format.formatter -> identified_term from -> unit + (** Returns the type of the elements of the array. Asserts it is an array type + *) + let typeOf_array_elem t = + match unrollType t with + | TArray (ty_elem, _, _, _) -> ty_elem + | _ -> assert false - method pStatus : Format.formatter -> Cil_types.annot_status -> unit - method pCode_annot: Format.formatter -> code_annotation -> unit + (**** Compute the type of an expression ****) + let rec typeOf (e: exp) : typ = + match (stripInfo e).enode with + | Info _ -> assert false + | Const(CInt64 (_, ik, _)) -> TInt(ik, []) - method pAnnotation: Format.formatter -> global_annotation -> unit + (* Character constants have type int. ISO/IEC 9899:1999 (E), + * section 6.4.4.4 [Character constants], paragraph 10, if you + * don't believe me. *) + | Const(CChr _) -> intType - method pDecreases: Format.formatter -> term variant -> unit + (* The type of a string is a pointer to characters ! The only case when + * you would want it to be an array is as an argument to sizeof, but we + * have SizeOfStr for that *) + | Const(CStr _s) -> theMachine.stringLiteralType - method pLoop_variant: Format.formatter -> term variant -> unit - end + | Const(CWStr _s) -> TPtr(theMachine.wcharType,[]) + | Const(CReal (_, fk, _)) -> TFloat(fk, []) - let is_skip = function Instr (Skip _) -> true | _ -> false + | Const(CEnum {eival=v}) -> typeOf v - (** [b_assumes] must be always empty for behavior named [Cil.default_behavior_name] *) - let mk_behavior ?(name=default_behavior_name) ?(assumes=[]) ?(requires=[]) - ?(post_cond=[]) ?(assigns=WritesAny) ?(extended=[]) () = - { b_name = name; - b_assumes = assumes; (* must be always empty for default_behavior_name *) - b_requires = requires; - b_assigns = assigns ; - b_post_cond = post_cond ; - b_extended = extended; - } + | Lval(lv) -> typeOfLval lv + | SizeOf _ | SizeOfE _ | SizeOfStr _ -> theMachine.typeOfSizeOf + | AlignOf _ | AlignOfE _ -> theMachine.typeOfSizeOf + | UnOp (_, _, t) -> t + | BinOp (_, _, _, t) -> t + | CastE (t, _) -> t + | AddrOf (lv) -> TPtr(typeOfLval lv, []) + | StartOf (lv) -> + begin + match unrollType (typeOfLval lv) with + TArray (t,_,_, _) -> TPtr(t, []) + | _ -> fatal "typeOf: StartOf on a non-array" + end - let empty_funspec () = - {spec_behavior = []; - spec_variant = None; - spec_terminates = None; - spec_complete_behaviors = []; - spec_disjoint_behaviors = []; - } + and typeOfInit (i: init) : typ = + match i with + SingleInit e -> typeOf e + | CompoundInit (t, _) -> t - let is_empty_funspec (spec : funspec) = - spec.spec_behavior = [] && - spec.spec_variant = None && spec.spec_terminates = None && - spec.spec_complete_behaviors = [] && spec.spec_disjoint_behaviors = [] + and typeOfLval = function + Var vi, off -> typeOffset vi.vtype off + | Mem addr, off -> begin + match unrollType (typeOf addr) with + TPtr (t, _) -> typeOffset t off + | _ -> fatal "typeOfLval: Mem on a non-pointer (%a)" !pd_exp addr + end -let is_empty_behavior b = - b.b_assumes = [] && b.b_requires = [] && b.b_post_cond = [] && - b.b_assigns = WritesAny && b.b_extended = [] + and typeOffset basetyp = + let blendAttributes baseAttrs = + let (_, _, contageous) = + partitionAttributes ~default:(AttrName false) baseAttrs in + typeAddAttributes contageous + in + function + NoOffset -> basetyp + | Index (_, o) -> begin + match unrollType basetyp with + TArray (t, _, _, baseAttrs) -> + let elementType = typeOffset t o in + blendAttributes baseAttrs elementType + | _ -> fatal "typeOffset: Index on a non-array" + end + | Field (fi, o) -> + match unrollType basetyp with + TComp (_, _,baseAttrs) -> + let fieldType = typeOffset fi.ftype o in + let typ = blendAttributes baseAttrs fieldType in + (match fi.fbitfield with + | Some s -> + typeAddAttributes [Attr ("FRAMA_C_BITFIELD_SIZE", [AInt s])] typ + | None -> typ) + | _ -> fatal "typeOffset: Field %s on a non-compound type '%a'" + fi.fname !pd_type basetyp + (**** Compute the type of a term lval ****) + let rec typeOfTermLval = function + TVar vi, off -> + let ty = match vi.lv_origin with + | Some v -> Ctype v.vtype + | None -> vi.lv_type + in + typeTermOffset ty off + | TResult ty, off -> typeTermOffset (Ctype ty) off + | TMem addr, off -> begin + let type_of_pointed t = + match t with + | Ctype typ -> + begin match unrollType typ with + TPtr (t, _) -> typeTermOffset (Ctype t) off + | _ -> fatal "typeOfTermLval: Mem on a non-pointer" + end + | Linteger | Lreal -> fatal "typeOfTermLval: Mem on a logic type" + | Ltype (s,_) -> + fatal "typeOfTermLval: Mem on a non-C type (%s)" s.lt_name + | Lvar s -> fatal "typeOfTermLval: Mem on a non-C type ('%s)" s + | Larrow _ -> fatal "typeOfTermLval: Mem on a function type" + in + Logic_const.transform_element type_of_pointed addr.term_type + end - (* Make a varinfo. Used mostly as a helper function below *) - let makeVarinfo ?(logic=false) ?(generated=true) global formal name typ = - (* Strip const from type for locals *) - let vi = - { vorig_name = name; - vname = name; - vid = -1; - vglob = global; - vdefined = false; - vformal = formal; - vgenerated = generated; - vtype = if formal || global then typ - else typeRemoveAttributes ["const"] typ; - vdecl = Location.unknown; - vinline = false; - vattr = []; - vstorage = NoStorage; - vaddrof = false; - vreferenced = false; - vdescr = None; - vdescrpure = true; - vghost = false; - vlogic = logic; - vlogic_var_assoc = None - } + and typeTermOffset basetyp = + let blendAttributes baseAttrs t = + let (_, _, contageous) = + partitionAttributes ~default:(AttrName false) baseAttrs in + let putAttributes = + function + | Ctype typ -> + Ctype (typeAddAttributes contageous typ) + | Linteger | Lreal -> + fatal "typeTermOffset: Attribute on a logic type" + | Ltype (s,_) -> + fatal "typeTermOffset: Attribute on a non-C type (%s)" s.lt_name + | Lvar s -> fatal "typeTermOffset: Attribute on a non-C type ('%s)" s + | Larrow _ -> fatal "typeTermOffset: Attribute on a function type" + in + Logic_const.transform_element putAttributes t in - set_vid vi; - vi + function + | TNoOffset -> basetyp + | TIndex (e, o) -> begin + let elt_type basetyp = + match basetyp with + | Ctype typ -> + begin match unrollType typ with + TArray (t, _, _, baseAttrs) -> + let elementType = typeTermOffset (Ctype t) o in + blendAttributes baseAttrs elementType + | _ -> fatal "typeTermOffset: Index on a non-array" + end + | Linteger | Lreal -> fatal "typeTermOffset: Index on a logic type" + | Ltype (s,_) -> + fatal "typeTermOffset: Index on a non-C type (%s)" s.lt_name + | Lvar s -> fatal "typeTermOffset: Index on a non-C type ('%s)" s + | Larrow _ -> fatal "typeTermOffset: Index on a function type" + in + Logic_const.set_conversion + (Logic_const.transform_element elt_type basetyp) e.term_type + end + | TField (fi, o) -> + let elt_type basetyp = + match basetyp with + | Ctype typ -> + begin match unrollType typ with + TComp (_, _, baseAttrs) -> + let fieldType = typeTermOffset (Ctype fi.ftype) o in + blendAttributes baseAttrs fieldType + | _ -> fatal "typeTermOffset: Field on a non-compound" + end + | Linteger | Lreal -> fatal "typeTermOffset: Field on a logic type" + | Ltype (s,_) -> + fatal "typeTermOffset: Field on a non-C type (%s)" s.lt_name + | Lvar s -> fatal "typeTermOffset: Field on a non-C type ('%s)" s + | Larrow _ -> fatal "typeTermOffset: Field on a function type" + in Logic_const.transform_element elt_type basetyp + + (**** Look at the attributes of a lval type ****) + let visitTypeAttributesOfTypeOfLval (f: attributes -> unit) (ty:typ): unit = + let rec visit (t: typ) : unit = + match t with + TNamed (r, a') -> f a' ; + visit r.ttype + | TArray(t, _, _, a') -> f a'; + visit t + | TComp (comp, _, a') -> f a'; + List.iter (fun fi -> f fi.fattr; + visit fi.ftype) comp.cfields + | TVoid a' + | TInt (_, a') + | TFloat (_, a') + | TEnum (_, a') + | TFun (_, _, _, a') + | TBuiltin_va_list a' + | TPtr(_, a') -> f a' + in visit ty + +exception VolatileFound +let hasLvalTypeSomeVolatileAttr (ty:typ) : bool = + let hasVolatileAttr attr = + if hasAttribute "volatile" attr + then raise VolatileFound + in try + visitTypeAttributesOfTypeOfLval hasVolatileAttr ty ; + false + with VolatileFound -> true - module FormalsDecl = - State_builder.Hashtbl - (Varinfo.Hashtbl) - (Datatype.List(Varinfo)) - (struct - let name = "FormalsDecl" - let dependencies = [] (* depends on file in Frama-C kernel *) - let size = 47 - let kind = `Internal - end) +let hasSomeVolatileAttr (lv:lval) : bool = + hasLvalTypeSomeVolatileAttr (typeOfLval lv) + + (** + ** + ** MACHINE DEPENDENT PART + ** + **) + exception SizeOfError of string * typ + let find_size_in_cache s f = + match s.scache with + | Not_Computed -> + let r = + try + f () + with SizeOfError _ as e -> + s.scache <- Not_Computable e; + raise e + in + s.scache <- Computed r; + r + | Not_Computable e -> raise e + | Computed r -> r - let selfFormalsDecl = FormalsDecl.self - let makeFormalsVarDecl (n,t,a) = - let vi = makeVarinfo ~generated:false false true n t in - vi.vattr <- a; - vi +(* Some basic type utilities *) + let rank : ikind -> int = function + (* these are just unique numbers representing the integer + conversion rank. *) + | IBool | IChar | ISChar | IUChar -> 1 + | IShort | IUShort -> 2 + | IInt | IUInt -> 3 + | ILong | IULong -> 4 + | ILongLong | IULongLong -> 5 - let setFormalsDecl vi typ = - match unrollType typ with - | TFun(_, Some args, _, _) -> - FormalsDecl.replace vi - (List.map makeFormalsVarDecl args) - | TFun(_,None,_,_) -> () - | _ -> error - "trying to assigns formal parameters to an object which is not a function prototype" - let getFormalsDecl vi = FormalsDecl.find vi + let unsignedVersionOf (ik:ikind): ikind = + match ik with + | ISChar | IChar -> IUChar + | IShort -> IUShort + | IInt -> IUInt + | ILong -> IULong + | ILongLong -> IULongLong + | _ -> ik - let unsafeSetFormalsDecl vi args = - FormalsDecl.replace vi args -let get_termination_kind_name = function - Normal -> "ensures" | Exits -> "exits" | Breaks -> "breaks" - | Continues -> "continue" | Returns -> "returns" + (* Convert 2 integer constants to integers with the same type, in preparation + for a binary operation. See ISO C 6.3.1.8p1 *) + let convertInts i1 ik1 i2 ik2 = + if ik1 = ik2 then (* nothing to do *) + i1, i2, ik1 + else begin + let r1 = rank ik1 in + let r2 = rank ik2 in + let ik' = + if (isSigned ik1) = (isSigned ik2) then begin + (* Both signed or both unsigned. *) + if r1 > r2 then ik1 else ik2 + end + else begin + let signedKind, unsignedKind, signedRank, unsignedRank = + if isSigned ik1 then ik1, ik2, r1, r2 else ik2, ik1, r2, r1 + in + (* The rules for signed + unsigned get hairy. + (unsigned short + long) is converted to signed long, + but (unsigned int + long) is converted to unsigned long.*) + if unsignedRank >= signedRank then unsignedKind + else if (bytesSizeOfInt signedKind) > (bytesSizeOfInt unsignedKind) then + signedKind + else + unsignedVersionOf signedKind + end + in + let i1',_ = truncateInteger64 ik' i1 in + let i2',_ = truncateInteger64 ik' i2 in + i1', i2', ik' + end -class defaultCilPrinterClass : cilPrinter = object (self) - val mutable logic_printer_enabled = true - val mutable verbose = false +(* Local type to compute alignments of struct field. *) + type offsetAcc = + { oaFirstFree: int; (* The first free bit *) + oaLastFieldStart: int; (* Where the previous field started *) + oaLastFieldWidth: int; (* The width of the previous field. Might not + * be same as FirstFree - FieldStart because + * of internal padding *) + oaPrevBitPack: (int * ikind * int) option; (* If the previous fields + * were packed bitfields, + * the bit where packing + * has started, the ikind + * of the bitfield and the + * width of the ikind *) + } - val current_stmt = Stack.create () - val mutable current_function = None - val mutable current_behavior = None - method private in_current_function vi = - assert (current_function = None); - current_function <- Some vi - method private out_current_function = - assert (current_function <> None); - current_function <- None +(* Hack to prevent infinite recursion in alignments *) +let ignoreAlignmentAttrs = ref false - val mutable has_annot = false - method has_annot = has_annot +module CoupleTypOffset = + Datatype.Pair_with_collections(Typ)(Offset) + (struct let module_name = "Cil.CopleTypOffset" end) + +module CacheBitsOffset = + State_builder.Hashtbl + (CoupleTypOffset.Hashtbl) + (Datatype.Pair(Datatype.Int)(Datatype.Int)) + (struct let size = 17 + let dependencies = [] + let name = "Cil.CacheBitsOffset" + let kind = `Correctness end) - method current_function = current_function - method current_behavior = current_behavior + (* Get the minimum aligment in bytes for a given type *) +let rec alignOf_int t = + let alignOfType () = match t with + | TInt((IChar|ISChar|IUChar|IBool), _) -> 1 + | TInt((IShort|IUShort), _) -> theMachine.theMachine.alignof_short + | TInt((IInt|IUInt), _) -> theMachine.theMachine.alignof_int + | TInt((ILong|IULong), _) -> theMachine.theMachine.alignof_long + | TInt((ILongLong|IULongLong), _) -> + theMachine.theMachine.alignof_longlong + | TEnum (ei,_) -> alignOf_int (TInt(ei.ekind, [])) + | TFloat(FFloat, _) -> theMachine.theMachine.alignof_float + | TFloat(FDouble, _) -> theMachine.theMachine.alignof_double + | TFloat(FLongDouble, _) -> + theMachine.theMachine.alignof_longdouble + | TNamed (t, _) -> alignOf_int t.ttype + | TArray (t, _, _, _) -> (* Be careful for char[] of Diab-C like compilers. *) + begin + match unrollType t with + | TInt((IChar|ISChar|IUChar),_) -> + theMachine.theMachine.alignof_char_array + | _ -> alignOf_int t + end - method private set_current_behavior b = - assert (current_behavior = None); current_behavior <- Some b + | TPtr _ | TBuiltin_va_list _ -> + theMachine.theMachine.alignof_ptr - method private reset_current_behavior () = - assert (current_behavior <> None); current_behavior <- None + (* For composite types get the maximum alignment of any field inside *) + | TComp (c, _, _) -> + (* On GCC the zero-width fields do not contribute to the alignment. On + * MSVC only those zero-width that _do_ appear after other + * bitfields contribute to the alignment. So we drop those that + * do not occur after othe bitfields *) + (* This is not correct for Diab-C compiler. *) + let rec dropZeros (afterbitfield: bool) = function + | f :: rest when f.fbitfield = Some 0 && not afterbitfield -> + dropZeros afterbitfield rest + | f :: rest -> f :: dropZeros (f.fbitfield <> None) rest + | [] -> [] + in + let fields = dropZeros false c.cfields in + List.fold_left + (fun sofar f -> + (* Bitfields with zero width do not contribute to the alignment in + * GCC *) + if not theMachine.msvcMode && f.fbitfield = Some 0 then sofar else + max sofar (alignOfField f)) 1 fields + (* These are some error cases *) + | TFun _ when not theMachine.msvcMode -> + theMachine.theMachine.alignof_fun + | TFun _ as t -> raise (SizeOfError ("function", t)) + | TVoid _ as t -> raise (SizeOfError ("void", t)) + in + match filterAttributes "aligned" (typeAttrs t) with + [] -> + (* no __aligned__ attribute, so get the default alignment *) + alignOfType () + | _ when !ignoreAlignmentAttrs -> + Kernel.warning "ignoring recursive align attributes on %a" + !pd_type t; + alignOfType () + | (Attr(_, [a]) as at)::rest -> begin + if rest <> [] then + Kernel.warning "ignoring duplicate align attributes on %a" + !pd_type t; + match intOfAttrparam a with + Some n -> n + | None -> + Kernel.warning "alignment attribute \"%a\" not understood on %a" + !pd_attr at !pd_type t; + alignOfType () + end + | Attr(_, [])::rest -> + (* aligned with no arg means a power of two at least as large as + any alignment on the system.*) + if rest <> [] then + Kernel.warning "ignoring duplicate align attributes on %a" + !pd_type t; + theMachine.theMachine.alignof_aligned + | at::_ -> + Kernel.warning "alignment attribute \"%a\" not understood on %a" + !pd_attr at !pd_type t; + alignOfType () + +(* alignment of a possibly-packed struct field. *) +and alignOfField (fi: fieldinfo) = + let fieldIsPacked = hasAttribute "packed" fi.fattr + || hasAttribute "packed" fi.fcomp.cattr in + if fieldIsPacked then 1 + else alignOf_int fi.ftype + +and intOfAttrparam (a:attrparam) : int option = + let rec doit a : int = + match a with + AInt(n) -> n + | ABinOp(Shiftlt, a1, a2) -> (doit a1) lsl (doit a2) + | ABinOp(Div, a1, a2) -> (doit a1) / (doit a2) + | ASizeOf(t) -> + let bs = bitsSizeOf t in + bs / 8 + | AAlignOf(t) -> + alignOf_int t + | _ -> raise (SizeOfError ("", voidType)) + in + (* Use ignoreAlignmentAttrs here to prevent stack overflow if a buggy + program does something like + struct s {...} __attribute__((aligned(sizeof(struct s)))) + This is too conservative, but it's often enough. + *) + assert (not !ignoreAlignmentAttrs); + ignoreAlignmentAttrs := true; + try + let n = doit a in + ignoreAlignmentAttrs := false; + Some n + with SizeOfError _ -> (* Can't compile *) + ignoreAlignmentAttrs := false; + None - method private push_stmt s = Stack.push s current_stmt - method private pop_stmt s = - ignore (Stack.pop current_stmt); has_annot<-false; s - method current_stmt = - try Some (Stack.top current_stmt) with Stack.Empty -> None +and bitsSizeOfInt (ik: ikind): int = + match ik with + | IBool | IChar | ISChar | IUChar -> 8 + | IInt | IUInt -> 8 * theMachine.theMachine.sizeof_int + | IShort | IUShort -> 8 * theMachine.theMachine.sizeof_short + | ILong | IULong -> 8 * theMachine.theMachine.sizeof_long + | ILongLong | IULongLong -> + 8 * theMachine.theMachine.sizeof_longlong - method may_be_skipped s = s.labels = [] +(* GCC version *) +(* Does not use the sofar.oaPrevBitPack *) +and offsetOfFieldAcc_GCC (fi: fieldinfo) (sofar: offsetAcc) : offsetAcc = + (* field type *) + let ftype = unrollType fi.ftype in + let ftypeAlign = 8 * alignOfField fi in + let ftypeBits = bitsSizeOf ftype in + match ftype, fi.fbitfield with + (* A width of 0 means that we must end the current packing. It seems that + * GCC pads only up to the alignment boundary for the type of this field. + * *) + | _, Some 0 -> + let firstFree = addTrailing sofar.oaFirstFree ftypeAlign in + { oaFirstFree = firstFree; + oaLastFieldStart = firstFree; + oaLastFieldWidth = 0; + oaPrevBitPack = None } - (** Returns the stmt being printed *) + (* A bitfield cannot span more alignment boundaries of its type than the + * type itself *) + | _, Some wdthis + when (sofar.oaFirstFree + wdthis + ftypeAlign - 1) / ftypeAlign + - sofar.oaFirstFree / ftypeAlign > ftypeBits / ftypeAlign -> + let start = addTrailing sofar.oaFirstFree ftypeAlign in + { oaFirstFree = start + wdthis; + oaLastFieldStart = start; + oaLastFieldWidth = wdthis; + oaPrevBitPack = None } - val mutable currentFormals : varinfo list = [] - method private getLastNamedArgument (s: string) : exp = - match List.rev currentFormals with - f :: _ -> new_exp ~loc:f.vdecl (Lval (var f)) - | [] -> abort "Cannot find the last named argument when printing call to %s" s + (* Try a simple method. Just put the field down *) + | _, Some wdthis -> + { oaFirstFree = sofar.oaFirstFree + wdthis; + oaLastFieldStart = sofar.oaFirstFree; + oaLastFieldWidth = wdthis; + oaPrevBitPack = None + } - (*** VARIABLES ***) - method pVarName fmt v = pp_print_string fmt v + (* Non-bitfield *) + | _, None -> + (* Align this field *) + let newStart = addTrailing sofar.oaFirstFree ftypeAlign in + { oaFirstFree = newStart + ftypeBits; + oaLastFieldStart = newStart; + oaLastFieldWidth = ftypeBits; + oaPrevBitPack = None; + } - method private pVarString v = - Pretty_utils.sfprintf "%a" self#pVar v + (* MSVC version *) + and offsetOfFieldAcc_MSVC (fi: fieldinfo) + (sofar: offsetAcc) : offsetAcc = + (* field type *) + let ftype = unrollType fi.ftype in + let ftypeAlign = 8 * alignOfField fi in + let ftypeBits = bitsSizeOf ftype in + match ftype, fi.fbitfield, sofar.oaPrevBitPack with + (* Ignore zero-width bitfields that come after non-bitfields *) + | TInt (_ikthis, _), Some 0, None -> + let firstFree = sofar.oaFirstFree in + { oaFirstFree = firstFree; + oaLastFieldStart = firstFree; + oaLastFieldWidth = 0; + oaPrevBitPack = None } - (* variable use *) - method pVar fmt (v:varinfo) = Format.fprintf fmt "%a" self#pVarName v.vname + (* If we are in a bitpack and we see a bitfield for a type with the + * different width than the pack, then we finish the pack and retry *) + | _, Some _, Some (packstart, _, wdpack) when wdpack != ftypeBits -> + let firstFree = + if sofar.oaFirstFree = packstart then packstart else + packstart + wdpack + in + offsetOfFieldAcc_MSVC fi + { oaFirstFree = addTrailing firstFree ftypeAlign; + oaLastFieldStart = sofar.oaLastFieldStart; + oaLastFieldWidth = sofar.oaLastFieldWidth; + oaPrevBitPack = None } - (* variable declaration *) - method pVDecl fmt (v:varinfo) = - let stom, rest = separateStorageModifiers v.vattr in - let fundecl = if isFunctionType v.vtype then Some v else None in - (* First the storage modifiers *) - fprintf fmt "%s%a%a%a %a" - (if v.vinline then "__inline " else "") - d_storage v.vstorage - self#pAttrs stom - (self#pType ?fundecl (Some (fun fmt -> self#pVar fmt v))) v.vtype - self#pAttrs rest + (* A width of 0 means that we must end the current packing. *) + | TInt (ikthis, _), Some 0, Some (packstart, _, wdpack) -> + let firstFree = + if sofar.oaFirstFree = packstart then packstart else + packstart + wdpack + in + let firstFree = addTrailing firstFree ftypeAlign in + { oaFirstFree = firstFree; + oaLastFieldStart = firstFree; + oaLastFieldWidth = 0; + oaPrevBitPack = Some (firstFree, ikthis, ftypeBits) } - (*** L-VALUES ***) - method pLval fmt (lv:lval) = (* lval (base is 1st field) *) - match lv with - Var vi, o -> fprintf fmt "%a%a" self#pVar vi self#pOffset o - | Mem e, Field(fi, o) -> - fprintf fmt "%a->%a%a" - (self#pExpPrec arrowLevel) e - self#pVarName fi.fname - self#pOffset o - | Mem e, NoOffset -> - fprintf fmt "*%a" - (self#pExpPrec derefStarLevel) e - | Mem e, o -> - fprintf fmt "(*%a)%a" - (self#pExpPrec derefStarLevel) e - self#pOffset o + (* Check for a bitfield that fits in the current pack after some other + * bitfields *) + | TInt(_ikthis, _), Some wdthis, Some (packstart, _ikprev, wdpack) + when packstart + wdpack >= sofar.oaFirstFree + wdthis -> + { oaFirstFree = sofar.oaFirstFree + wdthis; + oaLastFieldStart = sofar.oaFirstFree; + oaLastFieldWidth = wdthis; + oaPrevBitPack = sofar.oaPrevBitPack + } - (** Offsets **) - method pOffset fmt = function - | NoOffset -> () - | Field (fi, o) -> - fprintf fmt ".%a%a" - self#pVarName fi.fname - self#pOffset o - | Index (e, o) -> - fprintf fmt "[%a]%a" - self#pExp e - self#pOffset o - method private pLvalPrec (contextprec: int) fmt lv = - if getParenthLevel (dummy_exp(Lval(lv))) >= contextprec then - fprintf fmt "(%a)" self#pLval lv - else - self#pLval fmt lv + | _, _, Some (packstart, _, wdpack) -> (* Finish up the bitfield pack and + * restart. *) + let firstFree = + if sofar.oaFirstFree = packstart then packstart else + packstart + wdpack + in + offsetOfFieldAcc_MSVC fi + { oaFirstFree = addTrailing firstFree ftypeAlign; + oaLastFieldStart = sofar.oaLastFieldStart; + oaLastFieldWidth = sofar.oaLastFieldWidth; + oaPrevBitPack = None } - (*** EXPRESSIONS ***) - method pExp fmt (e: exp) = - let level = getParenthLevel e in - match (stripInfo e).enode with - | Info _ -> assert false - | Const(c) -> d_const fmt c - | Lval(l) -> self#pLval fmt l - | UnOp(u,e1,_) -> - fprintf fmt "%a %a" - d_unop u - (self#pExpPrec level) e1 - - | BinOp(b,e1,e2,_) -> - fprintf fmt "@[%a %a %a@]" - (self#pExpPrec level) e1 - d_binop b - (self#pExpPrec level) e2 - - | CastE(t,e) -> - fprintf fmt "(%a)%a" - (self#pType None) t - (self#pExpPrec level) e + (* No active bitfield pack. But we are seeing a bitfield. *) + | TInt(ikthis, _), Some wdthis, None -> + let firstFree = addTrailing sofar.oaFirstFree ftypeAlign in + { oaFirstFree = firstFree + wdthis; + oaLastFieldStart = firstFree; + oaLastFieldWidth = wdthis; + oaPrevBitPack = Some (firstFree, ikthis, ftypeBits); } - | SizeOf (t) -> - fprintf fmt "sizeof(%a)" - (self#pType None) t + (* No active bitfield pack. Non-bitfield *) + | _, None, None -> + (* Align this field *) + let firstFree = addTrailing sofar.oaFirstFree ftypeAlign in + { oaFirstFree = firstFree + ftypeBits; + oaLastFieldStart = firstFree; + oaLastFieldWidth = ftypeBits; + oaPrevBitPack = None; + } - | SizeOfE (e) -> - fprintf fmt "sizeof(%a)" - self#pExp e + | _, Some _, None -> Kernel.fatal "offsetAcc" - | SizeOfStr s -> - fprintf fmt "sizeof(%a)" - d_const (CStr s) - | AlignOf (t) -> - fprintf fmt "__alignof__(%a)" - (self#pType None) t - | AlignOfE (e) -> - fprintf fmt "__alignof__(%a)" - self#pExp e - | AddrOf(lv) -> - fprintf fmt "& %a" - (self#pLvalPrec addrOfLevel) lv + and offsetOfFieldAcc ~(fi: fieldinfo) ~(sofar: offsetAcc) : offsetAcc = + if theMachine.msvcMode then offsetOfFieldAcc_MSVC fi sofar + else offsetOfFieldAcc_GCC fi sofar - | StartOf(lv) -> self#pLval fmt lv + (* The size of a type, in bits. If struct or array then trailing padding is + * added *) + and bitsSizeOf t = + if not (TheMachine.is_computed ()) then + Kernel.fatal "You did not call Cil.initCIL before using the CIL library" ; + match t with + | TInt (ik,_) -> 8 * (bytesSizeOfInt ik) + | TFloat(FDouble, _) -> 8 * theMachine.theMachine.sizeof_double + | TFloat(FLongDouble, _) -> + 8 * theMachine.theMachine.sizeof_longdouble + | TFloat _ -> 8 * theMachine.theMachine.sizeof_float + | TEnum (ei,_) -> bitsSizeOf (TInt(ei.ekind, [])) + | TPtr _ -> 8 * theMachine.theMachine.sizeof_ptr + | TBuiltin_va_list _ -> 8 * theMachine.theMachine.sizeof_ptr + | TNamed (t, _) -> bitsSizeOf t.ttype + | TComp (comp, scache, _) when comp.cfields == [] -> + find_size_in_cache + scache + (fun () -> begin + (* Empty structs are allowed in msvc mode *) + if not comp.cdefined && not theMachine.msvcMode then begin + raise + (SizeOfError + (Format.sprintf + "abstract type: empty struct exist only with MSVC \ + (comp %s)" + (compFullName comp), + t)) (*abstract type*) + end else + 0 + end) - (* Print an expression, given the precedence of the context in which it - * appears. *) - method private pExpPrec (contextprec: int) fmt (e: exp) = - let thisLevel = getParenthLevel e in - let needParens = - if thisLevel >= contextprec then - true - else if contextprec == bitwiseLevel then - (* quiet down some GCC warnings *) - thisLevel == additiveLevel || thisLevel == comparativeLevel - else - false - in - if needParens then - fprintf fmt "(%a)" self#pExp e - else - self#pExp fmt e + | TComp (comp, scache, _) when comp.cstruct -> (* Struct *) + find_size_in_cache + scache + (fun () -> + (* Go and get the last offset *) + let startAcc = + { oaFirstFree = 0; + oaLastFieldStart = 0; + oaLastFieldWidth = 0; + oaPrevBitPack = None; + } in + let lastoff = + List.fold_left (fun acc fi -> offsetOfFieldAcc ~fi ~sofar:acc) + startAcc comp.cfields + in + if theMachine.msvcMode && lastoff.oaFirstFree = 0 && comp.cfields <> [] + then + (* On MSVC if we have just a zero-width bitfields then the length + * is 32 and is not padded *) + 32 + else + addTrailing lastoff.oaFirstFree (8 * alignOf_int t)) - method pInit fmt = function - SingleInit e -> self#pExp fmt e - | CompoundInit (t, initl) -> - (* We do not print the type of the Compound *) - (* - let dinit e = d_init () e in - dprintf "{@[%a@]}" - (docList ~sep:(chr ',' ++ break) dinit) initl - *) - let printDesignator = - if not theMachine.msvcMode then begin - (* Print only for union when we do not initialize the first field *) - match unrollType t, initl with - TComp(ci, _, _), [(Field(f, NoOffset), _)] -> - if not (ci.cstruct) && ci.cfields != [] && - (List.hd ci.cfields) != f then - true - else - false - | _ -> false - end else - false - in - let d_oneInit fmt = function - Field(f, NoOffset), i -> - if printDesignator then - fprintf fmt ".%a = " - self#pVarName f.fname; - self#pInit fmt i - | Index(e, NoOffset), i -> - if printDesignator then - fprintf fmt "[%a] = " - self#pExp e; - self#pInit fmt i - | _ -> Cilmsg.fatal "Trying to print malformed initializer" - in - fprintf fmt "{@[%a@]}" - (Pretty_utils.pp_list ~sep:",@ " d_oneInit) initl + | TComp (comp, scache, _) -> (* when not comp.cstruct *) + find_size_in_cache + scache + (fun () -> + (* Get the maximum of all fields *) + let startAcc = + { oaFirstFree = 0; + oaLastFieldStart = 0; + oaLastFieldWidth = 0; + oaPrevBitPack = None; + } in + let max = + List.fold_left (fun acc fi -> + let lastoff = offsetOfFieldAcc ~fi ~sofar:startAcc in + if lastoff.oaFirstFree > acc then + lastoff.oaFirstFree else acc) 0 comp.cfields in + (* Add trailing by simulating adding an extra field *) + addTrailing max (8 * alignOf_int t)) + | TArray(bt, Some len, scache, _) -> + find_size_in_cache + scache + (fun () -> + begin + match (constFold true len).enode with + Const(CInt64(l,_,_)) -> + let sz = My_bigint.mul (My_bigint.of_int (bitsSizeOf bt)) l in + let sz' = try + My_bigint.to_int sz + with Failure "nativeint_of_big_int" -> + raise + (SizeOfError ("Array is so long that its size can't be " + ^"represented with an OCaml int.", t)) - (** What terminator to print after an instruction. sometimes we want to - * print sequences of instructions separated by comma *) - val mutable printInstrTerminator = ";" + in + sz' (*WAS: addTrailing sz' (8 * alignOf_int t)*) + | _ -> raise (SizeOfError ("array non-constant length", t)) + end) + | TVoid _ -> 8 * theMachine.theMachine.sizeof_void + | TFun _ when not theMachine.msvcMode -> + (* On GCC the size of a function is defined *) + 8 * theMachine.theMachine.sizeof_fun - method private setPrintInstrTerminator (term : string) = - printInstrTerminator <- term + | TArray (_, None, _, _) -> + (* it seems that on GCC the size of such an + * array is 0 *) + 0 - method private getPrintInstrTerminator () = printInstrTerminator + | TFun _ -> raise (SizeOfError ("function", t)) - (*** INSTRUCTIONS ****) - method pInstr fmt (i:instr) = (* imperative instruction *) - fprintf fmt "%a" - (self#pLineDirective ~forcefile:false) (Cil_datatype.Instr.loc i); - match i with - | Skip _ -> fprintf fmt ";" - | Set(lv,e,_) -> begin - (* Be nice to some special cases *) - match e.enode with - BinOp((PlusA|PlusPI|IndexPI), - {enode = Lval(lv')}, - {enode=Const(CInt64(one,_,_))},_) - when compareLval lv lv' && one = Int64.one - && not miscState.printCilAsIs -> - fprintf fmt "%a ++%s" - (self#pLvalPrec indexLevel) lv - printInstrTerminator - | BinOp((MinusA|MinusPI), - {enode = Lval(lv')}, - {enode=Const(CInt64(one,_,_))}, _) - when compareLval lv lv' && one = Int64.one - && not miscState.printCilAsIs -> - fprintf fmt "%a --%s" - (self#pLvalPrec indexLevel) lv - printInstrTerminator - | BinOp((PlusA|PlusPI|IndexPI), - {enode = Lval(lv')}, - {enode = Const(CInt64(mone,_,_))},_) - when compareLval lv lv' && mone = Int64.minus_one - && not miscState.printCilAsIs -> - fprintf fmt "%a --%s" - (self#pLvalPrec indexLevel) lv - printInstrTerminator + and addTrailing nrbits roundto = + (nrbits + roundto - 1) land (lnot (roundto - 1)) - | BinOp((PlusA|PlusPI|IndexPI|MinusA|MinusPP|MinusPI|BAnd|BOr|BXor| - Mult|Div|Mod|Shiftlt|Shiftrt) as bop, - {enode = Lval(lv')},e,_) when compareLval lv lv' -> - fprintf fmt "%a %a= %a%s" - self#pLval lv - d_binop bop - self#pExp e - printInstrTerminator + and sizeOf_int t = (bitsSizeOf t) lsr 3 - | _ -> - fprintf fmt "%a = %a%s" - self#pLval lv - self#pExp e - printInstrTerminator +and sizeOf ~loc t = + try + integer ~loc ((bitsSizeOf t) lsr 3) + with SizeOfError _ -> new_exp ?loc (SizeOf(t)) - end - (* In cabs2cil we have turned the call to builtin_va_arg into a - * three-argument call: the last argument is the address of the - * destination *) - | Call(None, {enode = Lval(Var vi, NoOffset)}, - [dest; {enode = SizeOf t}; adest], l) - when vi.vname = "__builtin_va_arg" && not miscState.printCilAsIs -> - let destlv = match (stripCasts adest).enode with - AddrOf destlv -> destlv - (* If this fails, it's likely that an extension interfered - with the AddrOf *) - | _ -> - Cilmsg.fatal ~source:(source l) - "Encountered unexpected call to %s with dest %a" - vi.vname self#pExp adest + and bitsOffset (baset: typ) (off: offset) : int * int = + CacheBitsOffset.memo + (fun (baset, off) -> + let rec loopOff (baset: typ) (width: int) (start: int) = function + NoOffset -> start, width + | Index(e, off) -> begin + let ei = + match isInteger e with + Some i -> My_bigint.to_int i + | None -> raise (SizeOfError ("index not constant", baset)) in - fprintf fmt "%a = __builtin_va_arg (@[%a,@ %a@])%s" - self#pLval destlv - (* Now the arguments *) - self#pExp dest - (self#pType None) t - printInstrTerminator + let bt = + match unrollType baset with + TArray(bt, _, _, _) -> bt + | _ -> Kernel.fatal "bitsOffset: Index on a non-array" + in + let bitsbt = bitsSizeOf bt in + loopOff bt bitsbt (start + ei * bitsbt) off + end + | Field(f, off) when not f.fcomp.cstruct -> + (* All union fields start at offset 0 *) + loopOff f.ftype (bitsSizeOf f.ftype) start off - (* In cabs2cil we have dropped the last argument in the call to - * __builtin_va_start and __builtin_stdarg_start. *) - | Call(None, {enode = Lval(Var vi, NoOffset)}, [marker], l) - when ((vi.vname = "__builtin_stdarg_start" || - vi.vname = "__builtin_va_start") - && not miscState.printCilAsIs) -> - begin - let last = self#getLastNamedArgument vi.vname in - self#pInstr fmt (Call(None,dummy_exp(Lval(Var vi,NoOffset)), - [marker; last],l)) - end + | Field(f, off) -> + (* Construct a list of fields preceeding and including this one *) + let prevflds = + let rec loop = function + | [] -> + Kernel.abort + "bitsOffset: Cannot find field %s in %s" + f.fname + f.fcomp.cname + | fi' :: _ when fi' == f -> [ fi' ] + | fi' :: rest -> fi' :: loop rest + in + loop f.fcomp.cfields + in + let lastoff = + List.fold_left (fun acc fi' -> offsetOfFieldAcc ~fi:fi' ~sofar:acc) + { oaFirstFree = 0; (* Start at 0 because each struct is done + * separately *) + oaLastFieldStart = 0; + oaLastFieldWidth = 0; + oaPrevBitPack = None } prevflds + in + (* ignore (E.log "Field %s of %s: start=%d, lastFieldStart=%d\n" + f.fname f.fcomp.cname start lastoff.oaLastFieldStart); *) + loopOff f.ftype lastoff.oaLastFieldWidth + (start + lastoff.oaLastFieldStart) off + in + loopOff baset (bitsSizeOf baset) 0 off + ) (baset, off) - (* In cabs2cil we have dropped the last argument in the call to - * __builtin_next_arg. *) - | Call(res, {enode = Lval(Var vi, NoOffset)}, [ ], l) - when vi.vname = "__builtin_next_arg" && not miscState.printCilAsIs -> - begin - let last = self#getLastNamedArgument vi.vname in - self#pInstr fmt (Call(res,dummy_exp(Lval(Var vi,NoOffset)),[last],l)) - end +(** Do constant folding on an expression. If the first argument is true then + will also compute compiler-dependent expressions such as sizeof. + See also {!Cil.constFoldVisitor}, which will run constFold on all + expressions in a given AST node.*) +and constFold (machdep: bool) (e: exp) : exp = + Kernel.debug "ConstFold to %a@." + !pd_exp e; - (* In cparser we have turned the call to - * __builtin_types_compatible_p(t1, t2) into - * __builtin_types_compatible_p(sizeof t1, sizeof t2), so that we can - * represent the types as expressions. - * Remove the sizeofs when printing. *) - | Call(dest, {enode = Lval(Var vi, NoOffset)}, - [{enode = SizeOf t1}; {enode = SizeOf t2}], _) - when vi.vname = "__builtin_types_compatible_p" - && not miscState.printCilAsIs -> - (* Print the destination *) - (match dest with - None -> () - | Some lv -> fprintf fmt "%a = " self#pLval lv ); - (* Now the call itself *) - fprintf fmt "%a(%a, %a)%s" - self#pVarName vi.vname - (self#pType None) t1 - (self#pType None) t2 - printInstrTerminator - | Call(_, {enode = Lval(Var vi, NoOffset)}, _, l) - when vi.vname = "__builtin_types_compatible_p" - && not miscState.printCilAsIs -> - Cilmsg.fatal ~source:(source l) - "__builtin_types_compatible_p: cabs2cil should have added sizeof to the arguments." + let loc = e.eloc in + match e.enode with + BinOp(bop, e1, e2, tres) -> constFoldBinOp ~loc machdep bop e1 e2 tres + | UnOp(unop, e1, tres) -> begin + try + let tk = + match unrollType tres with + | TInt(ik, _) -> ik + | TEnum (ei,_) -> ei.ekind + | _ -> raise Not_found (* probably a float *) + in + let e1c = constFold machdep e1 in + match e1c.enode with + Const(CInt64(i,_ik,repr)) -> begin + match unop with + Neg -> + let repr = Extlib.opt_map (fun s -> "-" ^ s) repr in + kinteger64_repr ~loc tk (My_bigint.neg i) repr + | BNot -> kinteger64 ~loc tk (My_bigint.lognot i) + | LNot -> + if My_bigint.equal i My_bigint.zero then one ~loc + else zero ~loc + end + | _ -> new_exp ~loc (UnOp(unop, e1c, tres)) + with Not_found -> e + end + (* Characters are integers *) + | Const(CChr c) -> new_exp ~loc (Const(charConstToInt c)) + | Const(CEnum {eival = v}) -> constFold machdep v + | SizeOf t when machdep -> begin + try + let bs = bitsSizeOf t in + kinteger ~loc theMachine.kindOfSizeOf (bs / 8) + with SizeOfError _ -> e + end + | SizeOfE e when machdep -> constFold machdep + (new_exp ~loc:e.eloc (SizeOf (typeOf e))) + | SizeOfStr s when machdep -> + kinteger ~loc theMachine.kindOfSizeOf (1 + String.length s) + | AlignOf t when machdep -> + kinteger ~loc theMachine.kindOfSizeOf (alignOf_int t) + | AlignOfE e when machdep -> begin + (* The alignment of an expression is not always the alignment of its + * type. I know that for strings this is not true *) + match e.enode with + Const (CStr _) when not theMachine.msvcMode -> + kinteger ~loc + theMachine.kindOfSizeOf theMachine.theMachine.alignof_str + (* For an array, it is the alignment of the array ! *) + | _ -> constFold machdep (new_exp ~loc:e.eloc (AlignOf (typeOf e))) + end - | Call(dest,e,args,_) -> - (match dest with - None -> () - | Some lv -> - fprintf fmt "%a = " - self#pLval lv; - (* Maybe we need to print a cast *) - (let destt = typeOfLval lv in - match unrollType (typeOf e) with - TFun (rt, _, _, _) - when not (equals (!pTypeSig rt) - (!pTypeSig destt)) -> - fprintf fmt "(%a)" - (self#pType None) destt - | _ -> ())); - (* Now the function name *) - (match e.enode with - Lval(Var _, _) -> self#pExp fmt e - | _ -> fprintf fmt "(%a)" self#pExp e); - (* Now the arguments *) - Pretty_utils.pp_flowlist ~left:"(" ~sep:"," ~right:")" - self#pExp fmt args ; - (* Now the terminator *) - fprintf fmt "%s" printInstrTerminator + | CastE(it, + { enode = AddrOf (Mem ({enode = CastE(TPtr(bt, _), z)}), off)}) + when machdep && isZero z -> begin + try + let start, _width = bitsOffset bt off in + if start mod 8 <> 0 then error "Using offset of bitfield" ; + constFold machdep + (new_exp ~loc (CastE(it, (integer ~loc (start / 8))))) + with SizeOfError _ -> e + end - | Asm(attrs, tmpls, outs, ins, clobs, l) -> - self#pLineDirective fmt l; - if theMachine.msvcMode then - fprintf fmt "__asm {@[%a@]}%s" - (Pretty_utils.pp_list ~sep:"@\n" (fun fmt s -> fprintf fmt "%s" s)) tmpls - printInstrTerminator - else begin - fprintf fmt "__asm__ %a (@[%a" - self#pAttrs attrs - (Pretty_utils.pp_list ~sep:"@\n" (fun fmt x -> fprintf fmt "\"%s\"" (escape_string x))) tmpls; + | CastE (t, e) -> begin + Kernel.debug "ConstFold CAST to to %a@." + !pd_type t ; + let e = constFold machdep e in + match e.enode, unrollType t with + (* Might truncate silently *) + Const(CInt64(i,_k,_)), TInt(nk,a) + (* It's okay to drop a cast to const. + If the cast has any other attributes, leave the cast alone. *) + when (dropAttributes ["const"] a) = [] -> + Kernel.debug "ConstFold to %a : %s@." + !pd_ikind nk (My_bigint.to_string i); + kinteger64 ~loc nk i + | _, _ -> new_exp ~loc (CastE (t, e)) + end + | Lval lv -> new_exp ~loc (Lval (constFoldLval machdep lv)) + | AddrOf lv -> new_exp ~loc (AddrOf (constFoldLval machdep lv)) + | StartOf lv -> new_exp ~loc (StartOf (constFoldLval machdep lv)) + | _ -> e + + and constFoldLval machdep (host,offset) = + let newhost = + match host with + | Mem e -> Mem (constFold machdep e) + | Var _ -> host + in + let rec constFoldOffset machdep = function + | NoOffset -> NoOffset + | Field (fi,offset) -> Field (fi, constFoldOffset machdep offset) + | Index (exp,offset) -> Index (constFold machdep exp, + constFoldOffset machdep offset) + in + (newhost, constFoldOffset machdep offset) + +and constFoldBinOp ~loc (machdep: bool) bop e1 e2 tres = + let e1' = constFold machdep e1 in + let e2' = constFold machdep e2 in + if isIntegralType tres then begin + let newe = + let rec mkInt e = + let loc = e.eloc in + match e.enode with + Const(CChr c) -> new_exp ~loc (Const(charConstToInt c)) + | Const(CEnum {eival = v}) -> mkInt v + | CastE(TInt (ik, ta), e) -> begin + let exp = mkInt e in + match exp.enode with + Const(CInt64(i, _, _)) -> + kinteger64 ~loc ik i + | _ -> {exp with enode = CastE(TInt(ik, ta), exp)} + end + | _ -> e + in + let tk = + match unrollType tres with + TInt(ik, _) -> ik + | TEnum (ei,_) -> ei.ekind + | _ -> Kernel.fatal "constFoldBinOp" + in + (* See if the result is unsigned *) + let isunsigned typ = not (isSigned typ) in + let shiftInBounds i2 = + (* We only try to fold shifts if the second arg is positive and + less than the size of the type of the first argument. + Otherwise, the semantics are processor-dependent, so let the + compiler sort it out. *) + if machdep then + try + (My_bigint.ge i2 My_bigint.zero) + && My_bigint.lt i2 (My_bigint.of_int (bitsSizeOf (typeOf e1'))) + with SizeOfError _ -> false + else false + in + (* Assume that the necessary promotions have been done *) + let e1'' = mkInt e1' in + let e2'' = mkInt e2' in + match bop, e1''.enode, e2''.enode with + | PlusA, Const(CInt64(z,_,_)), _ + when My_bigint.equal z My_bigint.zero -> e2'' + | PlusA, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> e1'' + | PlusPI, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> e1'' + | IndexPI, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> e1'' + | MinusPI, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> e1'' + | PlusA, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + kinteger64 ~loc tk (My_bigint.add i1 i2) + | MinusA, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) + when ik1 = ik2 -> + kinteger64 ?loc tk (My_bigint.sub i1 i2) + | Mult, Const(CInt64(i1,ik1,_)), Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + kinteger64 ?loc tk (My_bigint.mul i1 i2) + | Mult, Const(CInt64(z,_,_)), _ + when My_bigint.equal z My_bigint.zero -> zero ~loc + | Mult, Const(CInt64(one,_,_)), _ + when My_bigint.equal one My_bigint.one -> e2'' + | Mult, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> zero ~loc + | Mult, _, Const(CInt64(one,_,_)) + when My_bigint.equal one My_bigint.one -> e1'' + | Div, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + begin + try kinteger64 ?loc tk (My_bigint.div i1 i2) + with Division_by_zero -> new_exp ?loc (BinOp(bop, e1', e2', tres)) + end + | Div, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) + when bytesSizeOfInt ik1 = bytesSizeOfInt ik2 -> begin + try kinteger64 ?loc tk (My_bigint.div i1 i2) + with Division_by_zero -> new_exp ?loc (BinOp(bop, e1', e2', tres)) + end + | Div, _, Const(CInt64(one,_,_)) + when My_bigint.equal one My_bigint.one -> e1'' + | Mod, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + begin + try kinteger64 ?loc tk (My_bigint.rem i1 i2) + with Division_by_zero -> new_exp ?loc (BinOp(bop, e1', e2', tres)) + end + | BAnd, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + kinteger64 ?loc tk (My_bigint.logand i1 i2) + | BAnd, Const(CInt64(z,_,_)), _ + when My_bigint.equal z My_bigint.zero -> zero ~loc + | BAnd, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> zero ~loc + | BOr, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + kinteger64 ?loc tk (My_bigint.logor i1 i2) + | BOr, _, _ when isZero e1' -> e2' + | BOr, _, _ when isZero e2' -> e1' + | BXor, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) when ik1 = ik2 -> + kinteger64 ?loc tk (My_bigint.logxor i1 i2) + | Shiftlt, Const(CInt64(i1,_ik1,_)),Const(CInt64(i2,_,_)) + when shiftInBounds i2 -> + kinteger64 ?loc tk (My_bigint.shift_left i1 i2) + | Shiftlt, Const(CInt64(z,_,_)), _ + when My_bigint.equal z My_bigint.zero -> zero ~loc + | Shiftlt, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> e1'' + | Shiftrt, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,_,_)) + when shiftInBounds i2 -> + if isunsigned ik1 then + kinteger64 ?loc tk + (My_bigint.shift_right_logical i1 i2) + else + kinteger64 ?loc tk (My_bigint.shift_right i1 i2) + | Shiftrt, Const(CInt64(z,_,_)), _ + when My_bigint.equal z My_bigint.zero -> zero ~loc + | Shiftrt, _, Const(CInt64(z,_,_)) + when My_bigint.equal z My_bigint.zero -> e1'' + | Eq, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> + let i1', i2', _ = convertInts i1 ik1 i2 ik2 in + if My_bigint.equal i1' i2' then one ~loc else zero ~loc + | Ne, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> + let i1', i2', _ = convertInts i1 ik1 i2 ik2 in + if My_bigint.equal i1' i2' then zero ~loc else one ~loc + | Le, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> + let i1', i2', _ = convertInts i1 ik1 i2 ik2 in + if My_bigint.le i1' i2' then one ~loc else zero ~loc + | Ge, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> + let i1', i2', _ = convertInts i1 ik1 i2 ik2 in + if My_bigint.ge i1' i2' then one ~loc else zero ~loc + | Lt, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> + let i1', i2', _ = convertInts i1 ik1 i2 ik2 in + if My_bigint.lt i1' i2' then one ~loc else zero ~loc + | Gt, Const(CInt64(i1,ik1,_)),Const(CInt64(i2,ik2,_)) -> + let i1', i2', _ = convertInts i1 ik1 i2 ik2 in + if My_bigint.gt i1' i2' then one ~loc else zero ~loc + + (* We rely on the fact that LAnd/LOr appear in global initializers + and should not have side effects. *) + | LAnd, _, _ when isZero e1' || isZero e2' -> zero ~loc + | LAnd, _, _ when isInteger e1' <> None -> e2' (* e1' is TRUE *) + | LAnd, _, _ when isInteger e2' <> None -> e1' (* e2' is TRUE *) + | LOr, _, _ when isZero e1' -> e2' + | LOr, _, _ when isZero e2' -> e1' + | LOr, _, _ when isInteger e1' <> None || isInteger e2' <> None -> + (* One of e1' or e2' is a nonzero constant *) + one ~loc + | _ -> new_exp ?loc (BinOp(bop, e1', e2', tres)) + in + if debugConstFold then + Format.printf "Folded %a to %a@." + (!pd_exp) (new_exp ?loc (BinOp(bop, e1', e2', tres))) + (!pd_exp) newe ; + newe + end else + new_exp ?loc (BinOp(bop, e1', e2', tres)) + +let () = pbitsSizeOf := bitsSizeOf + + (* CEA: moved from cabs2cil.ml. See cil.mli for infos *) + (* Weimer + * multi-character character constants + * In MSCV, this code works: + * + * long l1 = 'abcd'; // note single quotes + * char * s = "dcba"; + * long * lptr = ( long * )s; + * long l2 = *lptr; + * assert(l1 == l2); + * + * We need to change a multi-character character literal into the + * appropriate integer constant. However, the plot sickens: we + * must also be able to handle things like 'ab\nd' (value = * "d\nba") + * and 'abc' (vale = *"cba"). + * + * First we convert 'AB\nD' into the list [ 65 ; 66 ; 10 ; 68 ], then we + * multiply and add to get the desired value. + *) + + (* Given a character constant (like 'a' or 'abc') as a list of 64-bit + * values, turn it into a CIL constant. Multi-character constants are + * treated as multi-digit numbers with radix given by the bit width of + * the specified type (either char or wchar_t). *) + let reduce_multichar typ : int64 list -> int64 = + let radix = bitsSizeOf typ in + List.fold_left + (fun acc -> Int64.add (Int64.shift_left acc radix)) + Int64.zero + + let interpret_character_constant char_list = + let value = reduce_multichar charType char_list in + if value < (Int64.of_int 256) then + (* ISO C 6.4.4.4.10: single-character constants have type int *) + (CChr(Char.chr (Int64.to_int value))), intType + else begin + let orig_rep = None (* Some("'" ^ (String.escaped str) ^ "'") *) in + if value <= (Int64.of_int32 Int32.max_int) then + (CInt64(My_bigint.of_int64 value,IULong,orig_rep)),(TInt(IULong,[])) + else + (CInt64(My_bigint.of_int64 value,IULongLong,orig_rep)),(TInt(IULongLong,[])) + end + + (*/CEA*) + +let smallest_kind ~signed ~bits_size = + try + List.find + (fun kind -> isSigned kind=signed && bitsSizeOfInt kind = bits_size) + [IBool; (* This list is ordered by size of types *) + IChar; ISChar; IUChar; + IShort; IUShort; + IInt; IUInt; + ILong; IULong; + ILongLong; IULongLong] + with Not_found -> Kernel.fatal "Could not find a%signed type of size %d" + (if signed then " " else "n un") bits_size + +let uint64_t () = TInt(smallest_kind ~signed:false ~bits_size:64,[]) +let uint32_t () = TInt(smallest_kind ~signed:false ~bits_size:32,[]) +let uint16_t () = TInt(smallest_kind ~signed:false ~bits_size:16,[]) + +let d_unop fmt u = + fprintf fmt "%s" + (match u with + Neg -> "-" + | BNot -> "~" + | LNot -> "!") + +let d_binop fmt b = + fprintf fmt "%s" + (match b with + PlusA | PlusPI | IndexPI -> "+" + | MinusA | MinusPP | MinusPI -> "-" + | Mult -> "*" + | Div -> "/" + | Mod -> "%" + | Shiftlt -> "<<" + | Shiftrt -> ">>" + | Lt -> "<" + | Gt -> ">" + | Le -> "<=" + | Ge -> ">=" + | Eq -> "==" + | Ne -> "!=" + | BAnd -> "&" + | BXor -> "^" + | BOr -> "|" + | LAnd -> "&&" + | LOr -> "||") + + let d_term_binop fmt b = + fprintf fmt "%s" + (match b with + PlusA | PlusPI | IndexPI -> "+" + | MinusA | MinusPP | MinusPI -> "-" + | Mult -> "*" + | Div -> "/" + | Mod -> "%" + | Shiftlt -> "<<" + | Shiftrt -> ">>" + | Lt -> "<" + | Gt -> ">" + | Le -> if Kernel.Unicode.get () then Utf8_logic.le else "<=" + | Ge -> if Kernel.Unicode.get () then Utf8_logic.ge else ">=" + | Eq -> if Kernel.Unicode.get () then Utf8_logic.eq else "==" + | Ne -> if Kernel.Unicode.get () then Utf8_logic.neq else "!=" + | BAnd -> "&" + | BXor -> "^" + | BOr -> "|" + | LAnd -> if Kernel.Unicode.get () then Utf8_logic.conj else "&&" + | LOr -> if Kernel.Unicode.get () then Utf8_logic.disj else "||") + + let d_relation fmt b = + fprintf fmt "%s" + (match b with + | Rlt -> "<" + | Rgt -> ">" + | Rle -> if Kernel.Unicode.get () then Utf8_logic.le else "<=" + | Rge -> if Kernel.Unicode.get () then Utf8_logic.ge else ">=" + | Req -> if Kernel.Unicode.get () then Utf8_logic.eq else "==" + | Rneq -> if Kernel.Unicode.get () then Utf8_logic.neq else "!=") + + let invalidStmt = mkStmt (Instr (Skip Location.unknown)) + + module Builtin_functions = + State_builder.Hashtbl + (Datatype.String.Hashtbl) + (Datatype.Triple(Typ)(Datatype.List(Typ))(Datatype.Bool)) + (struct + let name = "Builtin_functions" + let dependencies = [ TheMachine.self ] + let size = 49 + let kind = `Internal + end) + + (* Initialize the builtin functions after the machine has been initialized. *) + let initGccBuiltins () : unit = + if not (TheMachine.is_computed ()) then + Kernel.fatal "Call initCIL before initGccBuiltins" ; + if Builtin_functions.length () <> 0 then + Kernel.fatal "builtins already initialized." ; + (* See if we have builtin_va_list *) + let hasbva = Machdep.state.Machdep.gccHas__builtin_va_list in + let sizeType = theMachine.upointType in + let add s t l b = Builtin_functions.add ("__builtin_" ^ s) (t, l, b) in + + add "__fprintf_chk" + intType + (* first argument is really FILE*, not void*, but we don't want to build in + the definition for FILE *) + [ voidPtrType; intType; charConstPtrType ] + true; + add "__memcpy_chk" + voidPtrType + [ voidPtrType; voidConstPtrType; sizeType; sizeType ] + false; + add "__memmove_chk" + voidPtrType [ voidPtrType; voidConstPtrType; sizeType; sizeType ] false; + add "__mempcpy_chk" + voidPtrType [ voidPtrType; voidConstPtrType; sizeType; sizeType ] false; + add "__memset_chk" + voidPtrType [ voidPtrType; intType; sizeType; sizeType ] false; + add "__printf_chk" intType [ intType; charConstPtrType ] true; + add "__snprintf_chk" + intType [ charPtrType; sizeType; intType; sizeType; charConstPtrType ] true; + add "__sprintf_chk" + intType [ charPtrType; intType; sizeType; charConstPtrType ] true; + add "__stpcpy_chk" + charPtrType [ charPtrType; charConstPtrType; sizeType ] false; + add "__strcat_chk" + charPtrType [ charPtrType; charConstPtrType; sizeType ] false; + add "__strcpy_chk" + charPtrType [ charPtrType; charConstPtrType; sizeType ] false; + add "__strncat_chk" + charPtrType [ charPtrType; charConstPtrType; sizeType; sizeType ] false; + add "__strncpy_chk" + charPtrType [ charPtrType; charConstPtrType; sizeType; sizeType ] false; + add "__vfprintf_chk" + intType + (* first argument is really FILE*, not void*, but we don't want to build in + the definition for FILE *) + [ voidPtrType; intType; charConstPtrType; TBuiltin_va_list [] ] + false; + add "__vprintf_chk" + intType [ intType; charConstPtrType; TBuiltin_va_list [] ] false; + add "__vsnprintf_chk" + intType + [ charPtrType; sizeType; intType; sizeType; charConstPtrType; + TBuiltin_va_list [] ] + false; + add "__vsprintf_chk" + intType + [ charPtrType; intType; sizeType; charConstPtrType; TBuiltin_va_list [] ] + false; + + add "alloca" voidPtrType [ sizeType ] false; + + add "acos" doubleType [ doubleType ] false; + add "acosf" floatType [ floatType ] false; + add "acosl" longDoubleType [ longDoubleType ] false; - if outs = [] && ins = [] && clobs = [] then - fprintf fmt ":" - else - fprintf fmt ": %a" - (Pretty_utils.pp_list ~sep:",@ " - (fun fmt (idopt, c, lv) -> - fprintf fmt "%s\"%s\" (%a)" - (match idopt with - None -> "" - | Some id -> "[" ^ id ^ "] " - ) - (escape_string c) - self#pLval lv - )) outs; + add "asin" doubleType [ doubleType ] false; + add "asinf" floatType [ floatType ] false; + add "asinl" longDoubleType [ longDoubleType ] false; - if ins = [] && clobs = [] then - () - else - fprintf fmt ": %a" - (Pretty_utils.pp_list ~sep:",@ " - (fun fmt (idopt, c, e) -> - fprintf fmt "%s\"%s\"(%a)" - (match idopt with - None -> "" - | Some id -> "[" ^ id ^ "] " - ) - (escape_string c) - self#pExp e)) - ins; + add "atan" doubleType [ doubleType ] false; + add "atanf" floatType [ floatType ] false; + add "atanl" longDoubleType [ longDoubleType ] false; + add "atan2" doubleType [ doubleType; doubleType ] false; + add "atan2f" floatType [ floatType; floatType ] false; + add "atan2l" longDoubleType [ longDoubleType; + longDoubleType ] false; - if clobs = [] then () - else - fprintf fmt ": %a" - (Pretty_utils.pp_list ~sep:",@ " - (fun fmt c -> fprintf fmt "\"%s\"" (escape_string c))) - clobs; + add "ceil" doubleType [ doubleType ] false; + add "ceilf" floatType [ floatType ] false; + add "ceill" longDoubleType [ longDoubleType ] false; - fprintf fmt "@])%s" printInstrTerminator - end - | Code_annot (annot, l) -> - has_annot <- true; - if logic_printer_enabled then - begin - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "/*@@ " ; - self#pCode_annot fmt annot ; - Pretty_utils.pp_close_block fmt "*/" ; - end + add "cos" doubleType [ doubleType ] false; + add "cosf" floatType [ floatType ] false; + add "cosl" longDoubleType [ longDoubleType ] false; - (**** STATEMENTS ****) - method pStmt fmt (s:stmt) = (* control-flow statement *) - self#push_stmt s; - self#pop_stmt (self#pStmtNext invalidStmt fmt s) + add "cosh" doubleType [ doubleType ] false; + add "coshf" floatType [ floatType ] false; + add "coshl" longDoubleType [ longDoubleType ] false; - method pStmtNext (next: stmt) fmt (s: stmt) = - self#push_stmt s; - self#pop_stmt (self#pAnnotatedStmt next fmt s) + add "clz" intType [ uintType ] false; + add "clzl" intType [ ulongType ] false; + add "clzll" intType [ ulongLongType ] false; + add "constant_p" intType [ intType ] false; + add "ctz" intType [ uintType ] false; + add "ctzl" intType [ ulongType ] false; + add "ctzll" intType [ ulongLongType ] false; - method pStmtLabels fmt (s:stmt) = - (* print the labels. *) - begin - let is_simple = function - | Instr(Set _ | Call _ | Skip _) -> true - | _ -> false - in - match s.labels with - | [] -> () - | [l] when is_simple s.skind -> self#pLabel fmt l - | _ -> List.iter (fprintf fmt "%a@ " self#pLabel) s.labels - end + add "exp" doubleType [ doubleType ] false; + add "expf" floatType [ floatType ] false; + add "expl" longDoubleType [ longDoubleType ] false; - method pAnnotatedStmt (next: stmt) fmt (s: stmt) = - self#pStmtLabels fmt s ; - (* print the statement. *) - if is_skip s.skind && not s.ghost then - (if verbose || s.labels <> [] then fprintf fmt ";") - else - begin - if s.ghost then Pretty_utils.pp_open_block fmt "/*@@ ghost "; - self#pStmtKind next fmt s.skind ; - if s.ghost then Pretty_utils.pp_close_block fmt "*/" ; - end + add "expect" longType [ longType; longType ] false; - method private pLabel fmt = function - Label (s, _, true) -> fprintf fmt "%s: " s - | Label (s, _, false) -> fprintf fmt "%s: /* internal */ " s - | Case (e, _) -> fprintf fmt "case %a: " self#pExp e - | Default _ -> fprintf fmt "default: " + add "fabs" doubleType [ doubleType ] false; + add "fabsf" floatType [ floatType ] false; + add "fabsl" longDoubleType [ longDoubleType ] false; - method requireBraces blk = - match blk.bstmts, blk.battrs, blk.blocals with - | ([_] | []),[],[] -> false - | _,_,_::_ -> true - | _ -> self#has_annot + add "ffs" intType [ uintType ] false; + add "ffsl" intType [ ulongType ] false; + add "ffsll" intType [ ulongLongType ] false; + add "frame_address" voidPtrType [ uintType ] false; - (* The pBlock will put the unalign itself *) - method pBlock ?(nobrace=true) ?(forcenewline=false) fmt (blk: block) = - let force_paren = (not nobrace) && (verbose || self#requireBraces blk) in - (* Let the host of the block decide on the alignment. The d_block will - * pop the alignment as well *) - let print_sep fmt = - if forcenewline then fprintf fmt "@\n" else fprintf fmt "@ " - in - let rec iterblock fmt = function - | [] -> () - | [s] -> - self#pStmtNext invalidStmt fmt s - | s_cur :: (s_next :: _ as tail) -> - self#pStmtNext s_next fmt s_cur ; - print_sep fmt; - iterblock fmt tail - in - if force_paren then fprintf fmt "@[{@[@ "; - if nobrace then print_sep fmt ; - if Cilmsg.debug_atleast 1 then fprintf fmt "@\n/* %a */@\n" - (Pretty_utils.pp_list - ~sep:("," ^^ Pretty_utils.space_sep) self#pVar) blk.blocals; - if blk.battrs <> [] then self#pAttrsGen true fmt blk.battrs ; - List.iter - (fun v -> fprintf fmt "%a;%t" self#pVDecl v print_sep) blk.blocals; - iterblock fmt blk.bstmts ; - if force_paren then fprintf fmt "@]@;}@]@\n"; + add "floor" doubleType [ doubleType ] false; + add "floorf" floatType [ floatType ] false; + add "floorl" longDoubleType [ longDoubleType ] false; - (* Store here the name of the last file printed in a line number. This is - * private to the object *) - val mutable lastFileName = "" - val mutable lastLineNumber = -1 + add "huge_val" doubleType [] false; + add "huge_valf" floatType [] false; + add "huge_vall" longDoubleType [] false; + add "inf" doubleType [] false; + add "inff" floatType [] false; + add "infl" longDoubleType [] false; + add "memcpy" voidPtrType [ voidPtrType; voidConstPtrType; sizeType ] false; + add "mempcpy" voidPtrType [ voidPtrType; voidConstPtrType; sizeType ] false; + add "memset" voidPtrType [ voidPtrType; intType; intType ] false; - (* Make sure that you only call self#pLineDirective on an empty line *) - method pLineDirective ?(forcefile=false) fmt l = - CurrentLoc.set l; - match miscState.lineDirectiveStyle with - | None -> () - | Some _ when (fst l).Lexing.pos_lnum <= 0 -> () + add "fmod" doubleType [ doubleType ] false; + add "fmodf" floatType [ floatType ] false; + add "fmodl" longDoubleType [ longDoubleType ] false; - (* Do not print lineComment if the same line as above *) - | Some LineCommentSparse when (fst l).Lexing.pos_lnum = lastLineNumber -> () + add "frexp" doubleType [ doubleType; intPtrType ] false; + add "frexpf" floatType [ floatType; intPtrType ] false; + add "frexpl" longDoubleType [ longDoubleType; intPtrType ] false; - | Some style -> - let directive = - match style with - | LineComment | LineCommentSparse -> "//#line " - | LinePreprocessorOutput when not theMachine.msvcMode -> "#" - | LinePreprocessorOutput | LinePreprocessorInput -> "#line" - in - lastLineNumber <- (fst l).Lexing.pos_lnum; - let filename = - if forcefile || (fst l).Lexing.pos_fname <> lastFileName then - begin - lastFileName <- (fst l).Lexing.pos_fname; - " \"" ^ (fst l).Lexing.pos_fname ^ "\"" - end - else - "" - in - fprintf fmt "@<0>\n@<0>%s@<0> @<0>%d@<0> @<0>%s@\n" directive (fst l).Lexing.pos_lnum filename + add "ldexp" doubleType [ doubleType; intType ] false; + add "ldexpf" floatType [ floatType; intType ] false; + add "ldexpl" longDoubleType [ longDoubleType; intType ] false; + add "log" doubleType [ doubleType ] false; + add "logf" floatType [ floatType ] false; + add "logl" longDoubleType [ longDoubleType ] false; - method pStmtKind (next: stmt) fmt kind = - match kind with - | UnspecifiedSequence seq -> - let print_stmt pstmt fmt (stmt, _, writes, reads,_) = - pstmt fmt stmt ; - if verbose then - Format.fprintf fmt "@ /*effects: @[%a@ <-@ %a@]*/" - (pretty_list (space_sep ",") self#pLval) writes - (pretty_list (space_sep ",") self#pLval) reads - in - let rec iterblock fmt = function - | [] -> () - | [srw] -> - fprintf fmt "@ " ; - print_stmt (self#pStmtNext invalidStmt) fmt srw - | srw_first :: ((s_next,_,_,_,_) :: _ as tail) -> - fprintf fmt "@ " ; - print_stmt (self#pStmtNext s_next) fmt srw_first ; - iterblock fmt tail - in - Pretty_utils.pp_open_block fmt "{ /*undefined sequence*/ " ; - iterblock fmt seq ; - Pretty_utils.pp_close_block fmt "}" + add "log10" doubleType [ doubleType ] false; + add "log10f" floatType [ floatType ] false; + add "log10l" longDoubleType [ longDoubleType ] false; - | Return(None, l) -> - self#pLineDirective fmt l; - fprintf fmt "return;" + add "modff" floatType [ floatType; TPtr(floatType,[]) ] false; + add "modfl" + longDoubleType [ longDoubleType; TPtr(longDoubleType, []) ] false; - | Return(Some e, l) -> - self#pLineDirective fmt l ; - fprintf fmt "return (%a);" self#pExp e + add "nan" doubleType [ charConstPtrType ] false; + add "nanf" floatType [ charConstPtrType ] false; + add "nanl" longDoubleType [ charConstPtrType ] false; + add "nans" doubleType [ charConstPtrType ] false; + add "nansf" floatType [ charConstPtrType ] false; + add "nansl" longDoubleType [ charConstPtrType ] false; + add "next_arg" + (* When we parse builtin_next_arg we drop the second argument *) + (if hasbva then TBuiltin_va_list [] else voidPtrType) [] false; + add "object_size" sizeType [ voidPtrType; intType ] false; - | Goto (sref, l) -> begin - (* Grab one of the labels *) - let rec pickLabel = function - [] -> None - | Label (lbl, _, _) :: _ -> Some lbl - | _ :: rest -> pickLabel rest - in - match pickLabel !sref.labels with - Some lbl -> - self#pLineDirective fmt l; - fprintf fmt "goto %s;" (* ^^ " /* %a */" *) lbl - (*self#pStmt !sref*) - | None -> - error "Cannot find label for target of goto: %a" self#pStmt !sref; - fprintf fmt "goto __invalid_label;" - end + add "parity" intType [ uintType ] false; + add "parityl" intType [ ulongType ] false; + add "parityll" intType [ ulongLongType ] false; + + add "popcount" intType [ uintType ] false; + add "popcountl" intType [ ulongType ] false; + add "popcountll" intType [ ulongLongType ] false; - | Break l -> - self#pLineDirective fmt l; - fprintf fmt "break;" + add "powi" doubleType [ doubleType; intType ] false; + add "powif" floatType [ floatType; intType ] false; + add "powil" longDoubleType [ longDoubleType; intType ] false; + add "prefetch" voidType [ voidConstPtrType ] true; + add "return" voidType [ voidConstPtrType ] false; + add "return_address" voidPtrType [ uintType ] false; - | Continue l -> - self#pLineDirective fmt l; - fprintf fmt "continue;" + add "sin" doubleType [ doubleType ] false; + add "sinf" floatType [ floatType ] false; + add "sinl" longDoubleType [ longDoubleType ] false; - | Instr i -> self#pInstr fmt i - (* fprintf fmt "@[%a@]" self#pInstr i *) + add "sinh" doubleType [ doubleType ] false; + add "sinhf" floatType [ floatType ] false; + add "sinhl" longDoubleType [ longDoubleType ] false; - | If(be,t,{bstmts=[];battrs=[]},l) when not miscState.printCilAsIs -> - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "if (%a) {" self#pExp be ; - self#pBlock fmt t ; - Pretty_utils.pp_close_block fmt "}" + add "sqrt" doubleType [ doubleType ] false; + add "sqrtf" floatType [ floatType ] false; + add "sqrtl" longDoubleType [ longDoubleType ] false; - | If(be,t,{bstmts=[{skind=Goto(gref,_);labels=[]}]; battrs=[]},l) - when !gref == next && not miscState.printCilAsIs -> - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "if (%a) {" self#pExp be ; - self#pBlock fmt t ; - Pretty_utils.pp_close_block fmt "}" + add "stpcpy" charPtrType [ charPtrType; charConstPtrType ] false; + add "strchr" charPtrType [ charPtrType; intType ] false; + add "strcmp" intType [ charConstPtrType; charConstPtrType ] false; + add "strcpy" charPtrType [ charPtrType; charConstPtrType ] false; + add "strcspn" sizeType [ charConstPtrType; charConstPtrType ] false; + add "strncat" charPtrType [ charPtrType; charConstPtrType; sizeType ] false; + add "strncmp" intType [ charConstPtrType; charConstPtrType; sizeType ] false; + add "strncpy" charPtrType [ charPtrType; charConstPtrType; sizeType ] false; + add "strspn" sizeType [ charConstPtrType; charConstPtrType ] false; + add "strpbrk" charPtrType [ charConstPtrType; charConstPtrType ] false; + (* When we parse builtin_types_compatible_p, we change its interface *) + add "types_compatible_p" + intType + [ theMachine.typeOfSizeOf;(* Sizeof the type *) + theMachine.typeOfSizeOf (* Sizeof the type *) ] + false; + add "tan" doubleType [ doubleType ] false; + add "tanf" floatType [ floatType ] false; + add "tanl" longDoubleType [ longDoubleType ] false; - | If(be,{bstmts=[];battrs=[]},e,l) when not miscState.printCilAsIs -> - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "if (%a) {" - self#pExp (dummy_exp(UnOp(LNot,be,intType))) ; - self#pBlock fmt e ; - Pretty_utils.pp_close_block fmt "}" + add "tanh" doubleType [ doubleType ] false; + add "tanhf" floatType [ floatType ] false; + add "tanhl" longDoubleType [ longDoubleType ] false; - | If(be,{bstmts=[{skind=Goto(gref,_);labels=[]}]; battrs=[]},e,l) - when !gref == next && not miscState.printCilAsIs -> - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "if (%a) {" - self#pExp (dummy_exp(UnOp(LNot,be,intType))) ; - self#pBlock fmt e ; - Pretty_utils.pp_close_block fmt "}" - | If(be,t,e,l) -> - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "if (%a) {" self#pExp be ; - self#pBlock fmt t ; - Pretty_utils.pp_close_block fmt "}" ; - fprintf fmt "@ " ; - Pretty_utils.pp_open_block fmt "else {" ; - self#pBlock fmt e ; - Pretty_utils.pp_close_block fmt "}" + if hasbva then begin + add "va_end" voidType [ TBuiltin_va_list [] ] false; + add "varargs_start" voidType [ TBuiltin_va_list [] ] false; + (* When we parse builtin_{va,stdarg}_start, we drop the second argument *) + add "va_start" voidType [ TBuiltin_va_list [] ] false; + add "stdarg_start" voidType [ TBuiltin_va_list [] ] false; + (* When we parse builtin_va_arg we change its interface *) + add "va_arg" + voidType + [ TBuiltin_va_list []; + theMachine.typeOfSizeOf;(* Sizeof the type *) + voidPtrType (* Ptr to res *) ] + false; + add "va_copy" voidType [ TBuiltin_va_list []; TBuiltin_va_list [] ] false; + end - | Switch(e,b,_,l) -> - self#pLineDirective ~forcefile:false fmt l ; - Pretty_utils.pp_open_block fmt "switch (%a) {" self#pExp e ; - self#pBlock fmt b ; - Pretty_utils.pp_close_block fmt "}" +(* [VP] Should we projectify this ?*) +let special_builtins_table = ref Datatype.String.Set.empty +let special_builtins = Queue.create () - | Loop(annot, b, l, _, _) -> - if logic_printer_enabled && annot <> [] then - begin - Pretty_utils.pp_open_block fmt "/*@@ " ; - Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep - self#pCode_annot - fmt - annot; - Pretty_utils.pp_close_block fmt "@ */@\n" ; - end ; - begin - (* Maybe the first thing is a conditional. Turn it into a WHILE *) - try - let rec skipEmpty = function - [] -> [] - | {skind=Instr (Skip _);labels=[]} as h :: rest - when self#may_be_skipped h-> skipEmpty rest - | x -> x - in - let term, bodystmts = - (* Bill McCloskey: Do not remove the If if it has labels *) - match skipEmpty b.bstmts with - {skind=If(e,tb,fb,_)} as to_skip :: rest - when - not miscState.printCilAsIs && self#may_be_skipped to_skip -> - begin - match skipEmpty tb.bstmts, skipEmpty fb.bstmts with - [], {skind=Break _; labels=[]}::_ -> e, rest - | {skind=Break _; labels=[]}::_, [] - -> dummy_exp (UnOp(LNot, e, intType)), rest - | _ -> raise Not_found - end - | _ -> raise Not_found - in - let b = match skipEmpty bodystmts with - [{ skind=Block b} as s ] when self#may_be_skipped s -> b - | _ -> { b with bstmts = bodystmts } - in - self#pLineDirective fmt l ; - Pretty_utils.pp_open_block fmt "while (%a) {" self#pExp term ; - self#pBlock fmt b ; - Pretty_utils.pp_close_block fmt "}" +let is_special_builtin s = + Queue.fold (fun res f -> res || f s) false special_builtins - with Not_found -> - self#pLineDirective fmt l ; - Pretty_utils.pp_open_block fmt "while (1) {" ; - self#pBlock fmt b ; - Pretty_utils.pp_close_block fmt "}" +let add_special_builtin_family f = Queue.add f special_builtins - end +let add_special_builtin s = + special_builtins_table := Datatype.String.Set.add s !special_builtins_table - | Block b -> - if (match b.bstmts with [] | [_] -> true | _ -> false) - then self#pBlock ~nobrace:false fmt b - else - begin - if verbose then - Pretty_utils.pp_open_block fmt "/*block:begin*/@ " ; - self#pBlock ~nobrace:false fmt b ; - if verbose then Pretty_utils.pp_close_block fmt "/*block:end*/" ; - end +let () = add_special_builtin_family + (fun s -> Datatype.String.Set.mem s !special_builtins_table) - | TryFinally (b, h, l) -> - self#pLineDirective fmt l; - fprintf fmt "__try {@[%a@]} @[<5>__finally{%a}@]" - (* NB: eta expansion needed because of optional args of pBlock. *) - (fun fmt -> self#pBlock fmt) b - (fun fmt -> self#pBlock fmt) h +let () = List.iter add_special_builtin + [ "__builtin_stdarg_start"; "__builtin_va_arg"; + "__builtin_va_start"; "__builtin_expect"; "__builtin_next_arg"; ] - | TryExcept (b, (il, e), h, l) -> - self#pLineDirective fmt l; - fprintf fmt "__try {@[%a@]} @[<5>__except(@\n@[" - (* NB: eta expansion needed because of optional args of pBlock. *) - (fun fmt -> self#pBlock fmt) b; +(** Construct a hash with the builtins *) +let initMsvcBuiltins () : unit = + if not (TheMachine.is_computed ()) then + Kernel.fatal "Call initCIL before initMsvcBuiltins" ; + if Builtin_functions.length () <> 0 then + Kernel.fatal "builtins already initialized." ; + (** Take a number of wide string literals *) + Builtin_functions.add "__annotation" (voidType, [ ], true); + () - (* Print the instructions but with a comma at the end, instead of - * semicolon *) - printInstrTerminator <- ","; - Pretty_utils.pp_list ~sep:"@\n" self#pInstr fmt il; - printInstrTerminator <- ";"; - fprintf fmt "%a) @]%a" - (* NB: eta expansion needed because of optional args of pBlock. *) - self#pExp e (fun fmt -> self#pBlock fmt) h + (** This is used as the location of the prototypes of builtin functions. *) + let builtinLoc: location = Location.unknown - (*** GLOBALS ***) - method pGlobal fmt (g:global) = (* global (vars, types, etc.) *) - match g with - | GFun (fundec, l) -> - self#in_current_function fundec.svar; - (* If the function has attributes then print a prototype because - * GCC cannot accept function attributes in a definition *) - let oldattr = fundec.svar.vattr in - (* Always pring the file name before function declarations *) - (* Prototype first *) - if oldattr <> [] then - (self#pLineDirective fmt l; - fprintf fmt "%a;@\n" - self#pVDecl fundec.svar); - (* Temporarily remove the function attributes *) - fundec.svar.vattr <- []; - (* Body now *) - self#pLineDirective ~forcefile:true fmt l; - self#pFunDecl fmt fundec; - fundec.svar.vattr <- oldattr; - fprintf fmt "@\n"; - self#out_current_function + let range_loc loc1 loc2 = fst loc1, snd loc2 + + let pred_body = function + | LBpred a -> a + | LBnone + | LBreads _ + | LBinductive _ + | LBterm _ -> Kernel.fatal "definition expected in Cil.pred_body" + (*** Type signatures ***) - | GType (typ, l) -> - self#pLineDirective ~forcefile:true fmt l; - fprintf fmt "typedef %a;@\n" - (self#pType (Some (fun fmt -> fprintf fmt "%s" typ.tname))) typ.ttype + (* Helper class for typeSig: replace any types in attributes with typsigs *) + class typeSigVisitor(typeSigConverter: typ->typsig) = object + inherit nopCilVisitor + method vattrparam ap = + match ap with + | ASizeOf t -> ChangeTo (ASizeOfS (typeSigConverter t)) + | AAlignOf t -> ChangeTo (AAlignOfS (typeSigConverter t)) + | _ -> DoChildren + end - | GEnumTag (enum, l) -> - self#pLineDirective fmt l; - fprintf fmt "enum@[ %a {@\n%a@]@\n} %a;@\n" - self#pVarName enum.ename - (Pretty_utils.pp_list ~sep:",@\n" - (fun fmt item -> - fprintf fmt "%s = %a" - item.einame - self#pExp item.eival)) - enum.eitems - self#pAttrs enum.eattr + let typeSigAddAttrs a0 t = + if a0 = [] then t else + match t with + TSBase t -> TSBase (typeAddAttributes a0 t) + | TSPtr (ts, a) -> TSPtr (ts, addAttributes a0 a) + | TSArray (ts, l, a) -> TSArray(ts, l, addAttributes a0 a) + | TSComp (iss, n, a) -> TSComp (iss, n, addAttributes a0 a) + | TSEnum (n, a) -> TSEnum (n, addAttributes a0 a) + | TSFun(ts, tsargs, isva, a) -> TSFun(ts, tsargs, isva, addAttributes a0 a) - | GEnumTagDecl (enum, l) -> (* This is a declaration of a tag *) - self#pLineDirective fmt l; - fprintf fmt "enum %a;@\n" self#pVarName enum.ename + (* Compute a type signature. + Use ~ignoreSign:true to convert all signed integer types to unsigned, + so that signed and unsigned will compare the same. *) + let rec typeSigWithAttrs ?(ignoreSign=false) doattr t = + let typeSig = typeSigWithAttrs ~ignoreSign doattr in + let attrVisitor = new typeSigVisitor typeSig in + let doattr al = visitCilAttributes attrVisitor (doattr al) in + match t with + | TInt (ik, al) -> + let ik' = + if ignoreSign then unsignedVersionOf ik else ik + in + TSBase (TInt (ik', doattr al)) + | TFloat (fk, al) -> TSBase (TFloat (fk, doattr al)) + | TVoid al -> TSBase (TVoid (doattr al)) + | TEnum (enum, a) -> TSEnum (enum.ename, doattr a) + | TPtr (t, a) -> TSPtr (typeSig t, doattr a) + | TArray (t,l,_, a) -> (* We do not want fancy expressions in array lengths. + * So constant fold the lengths *) + let l' = match l with + | None -> None + | Some l -> + match constFold true l with + | { enode = Const(CInt64(i, _, _))} -> Some (My_bigint.to_string i) + | e -> + Kernel.abort "Invalid length in array type: %a\n" !pd_exp e + in + TSArray(typeSig t, l', doattr a) - | GCompTag (comp, l) -> (* This is a definition of a tag *) - let n = comp.cname in - let su = - if comp.cstruct then "struct" - else "union" - in - let sto_mod, rest_attr = separateStorageModifiers comp.cattr in - self#pLineDirective ~forcefile:true fmt l; - fprintf fmt "@[<3>%s %a%a {@\n%a@]@\n}%a;@\n" - su - self#pAttrs sto_mod - self#pVarName n - (Pretty_utils.pp_list ~sep:"@\n" self#pFieldDecl) - comp.cfields - self#pAttrs rest_attr + | TComp (comp, _, a) -> + TSComp (comp.cstruct, comp.cname, doattr (addAttributes comp.cattr a)) + | TFun(rt,args,isva,a) -> + TSFun(typeSig rt, + List.map (fun (_, atype, _) -> (typeSig atype)) (argsToList args), + isva, doattr a) + | TNamed(t, a) -> typeSigAddAttrs (doattr a) (typeSig t.ttype) + | TBuiltin_va_list al -> TSBase (TBuiltin_va_list (doattr al)) - | GCompTagDecl (comp, l) -> (* This is a declaration of a tag *) - self#pLineDirective fmt l; - fprintf fmt "%s;@\n" (compFullName comp) + let typeSig t = + typeSigWithAttrs (fun al -> al) t - | GVar (vi, io, l) -> - self#pLineDirective ~forcefile:true fmt l; - fprintf fmt "%a" - self#pVDecl vi; - (match io.init with - None -> () - | Some i -> - fprintf fmt " = "; - let islong = - match i with - CompoundInit (_, il) when List.length il >= 8 -> true - | _ -> false - in - if islong then - begin self#pLineDirective fmt l; - fprintf fmt " @[@\n" - end; - self#pInit fmt i; - if islong then - fprintf fmt "@]"); - fprintf fmt ";@\n" + (* Remove the attribute from the top-level of the type signature *) + let setTypeSigAttrs (a: attribute list) = function + TSBase t -> TSBase (setTypeAttrs t a) + | TSPtr (ts, _) -> TSPtr (ts, a) + | TSArray (ts, l, _) -> TSArray(ts, l, a) + | TSComp (iss, n, _) -> TSComp (iss, n, a) + | TSEnum (n, _) -> TSEnum (n, a) + | TSFun (ts, tsargs, isva, _) -> TSFun (ts, tsargs, isva, a) - (* print global variable 'extern' declarations, and function prototypes *) - | GVarDecl (funspec, vi, l) -> - if isFunctionType vi.vtype then self#in_current_function vi; - self#opt_funspec fmt funspec; - if not miscState.printCilAsIs && Builtin_functions.mem vi.vname then - begin - (* Compiler builtins need no prototypes. Just print them in - comments. *) - fprintf fmt "/* compiler builtin: @\n %a; */@\n" - self#pVDecl vi - end else begin - self#pLineDirective fmt l; - fprintf fmt "%a;@\n" self#pVDecl vi - end; - if isFunctionType vi.vtype then self#out_current_function + let typeSigAttrs = function + TSBase t -> typeAttrs t + | TSPtr (_ts, a) -> a + | TSArray (_ts, _l, a) -> a + | TSComp (_iss, _n, a) -> a + | TSEnum (_n, a) -> a + | TSFun (_ts, _tsargs, _isva, a) -> a - | GAsm (s, l) -> - self#pLineDirective fmt l; - fprintf fmt "__asm__(\"%s\");@\n" (escape_string s) + let compareConstant c1 c2 = + match c1, c2 with + | CEnum e1, CEnum e2 -> + e1.einame = e2.einame && e1.eihost.ename = e2.eihost.ename && + (match + isInteger (constFold true e1.eival), + isInteger (constFold true e2.eival) + with + | Some i1, Some i2 -> My_bigint.equal i1 i2 + | _ -> false) + | CInt64 (i1,k1,_), CInt64(i2,k2,_) -> + k1 = k2 && My_bigint.equal i1 i2 + | CStr s1, CStr s2 -> s1 = s2 + | CWStr l1, CWStr l2 -> + (try List.for_all2 (fun x y -> Int64.compare x y = 0) l1 l2 + with Invalid_argument _ -> false) + | CChr c1, CChr c2 -> c1 = c2 + | CReal(f1,k1,_), CReal(f2,k2,_) -> k1 = k2 && f1 = f2 + | (CEnum _ | CInt64 _ | CStr _ | CWStr _ | CChr _ | CReal _), _ -> false - | GPragma (Attr(an, args), l) -> - (* sm: suppress printing pragmas that gcc does not understand *) - (* assume anything starting with "ccured" is ours *) - (* also don't print the 'combiner' pragma *) - (* nor 'cilnoremove' *) - let suppress = - not miscState.print_CIL_Input && - not theMachine.msvcMode && - ((startsWith "box" an) || - (startsWith "ccured" an) || - (an = "merger") || - (an = "cilnoremove")) - in - self#pLineDirective fmt l; - if suppress then fprintf fmt "/* "; - fprintf fmt "#pragma "; - begin - match an, args with - | _, [] -> - fprintf fmt "%s" an - | "weak", [ACons (varinfo, [])] -> - fprintf fmt "weak %s" varinfo - | "",_ -> - fprintf fmt "%a" - (Pretty_utils.pp_list ~sep:" " self#pAttrParam) args - | _ -> - fprintf fmt "%s(%a)" - an - (Pretty_utils.pp_list ~sep:"," self#pAttrParam) args + (* Moved from ext/expcompare.ml *) + let rec compareExp (e1: exp) (e2: exp) : bool = + (* log "CompareExp %a and %a.\n" d_plainexp e1 d_plainexp e2; *) + e1 == e2 || + match e1.enode, e2.enode with + | Const c1, Const c2 -> compareConstant c1 c2 + | Lval lv1, Lval lv2 + | StartOf lv1, StartOf lv2 + | AddrOf lv1, AddrOf lv2 -> compareLval lv1 lv2 + | BinOp(bop1, l1, r1, _), BinOp(bop2, l2, r2, _) -> + bop1 = bop2 && compareExp l1 l2 && compareExp r1 r2 + | UnOp(op1,e1,_), UnOp(op2,e2,_) -> op1 = op2 && compareExp e1 e2 + | SizeOf t1, SizeOf t2 -> Cilutil.equals (typeSig t1) (typeSig t2) + | SizeOfE e1, SizeOfE e2 -> compareExp e1 e2 + | SizeOfStr s1, SizeOfStr s2 -> s1 = s2 + | AlignOf t1, AlignOf t2 -> Cilutil.equals (typeSig t1) (typeSig t2) + | AlignOfE e1, AlignOfE e2 -> compareExp e1 e2 + | CastE(t1,e1), CastE(t2,e2) -> + Cilutil.equals (typeSig t1) (typeSig t2) && compareExp e1 e2 + | Info (e1,_), Info(e2,_) -> compareExp e1 e2 + | (Const _ | Lval _ | StartOf _ | AddrOf _ | BinOp _ | UnOp _ + | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ + | CastE _ | Info _), _ -> false - end; - if suppress then fprintf fmt " */@\n" else fprintf fmt "@\n" + and compareLval (lv1: lval) (lv2: lval) : bool = + lv1 == lv2 || + match lv1, lv2 with + | (Var vi1, off1), (Var vi2, off2) -> + vi1 == vi2 && compareOffset off1 off2 + | (Mem e1, off1), (Mem e2, off2) -> + compareExp e1 e2 && compareOffset off1 off2 + | ((Var _ | Mem _), _), _ -> false - | GPragma (AttrAnnot _, _) -> - assert false - (* self#pLineDirective fmt l; - fprintf fmt "/* #pragma %s */@\n" a*) + and compareOffset (off1: offset) (off2: offset) : bool = + off1 == off2 || + match off1, off2 with + | Field (fld1, off1'), Field (fld2, off2') -> + fld1 == fld2 && compareOffset off1' off2' + | Index (e1, off1'), Index (e2, off2') -> + compareExp e1 e2 && compareOffset off1' off2' + | NoOffset, NoOffset -> true + | (Field _ | Index _ | NoOffset), _ -> false - | GAnnot (decl,l) -> - (*if logic_printer_enabled then*) - begin - self#pLineDirective fmt l; - fprintf fmt "/*@@@ %a@ */@\n" - self#pAnnotation decl - end - | GText s -> - if s <> "//" then - fprintf fmt "%s@\n" s + (** A printer interface for CIL trees. Create instantiations of + * this type by specializing the class {!Cil.defaultCilPrinter}. *) + class type cilPrinter = object - method pFieldDecl fmt fi = - fprintf fmt "%a %s%a;" - (self#pType - (Some (fun fmt -> if fi.fname <> missingFieldName then fprintf fmt "%s" fi.fname))) - fi.ftype - (match fi.fbitfield with - | None -> "" - | Some i -> ": " ^ string_of_int i ^ " ") - self#pAttrs fi.fattr + (** Local logical annotation (function specifications and code annotations + are printed only if [logic_printer_enabled] is set to true + *) + val mutable logic_printer_enabled : bool + (** more info is displayed on verbose mode. *) + val mutable verbose: bool - method private opt_funspec fmt funspec = - if logic_printer_enabled && not (is_empty_funspec funspec) then - fprintf fmt "/*@[@@ %a@]*/@\n" self#pSpec funspec + method current_function: varinfo option + (** Returns the [varinfo] corresponding to the function being printed *) - method private pFunDecl fmt f = - (* declaration. *) - fprintf fmt "%a%a@\n@[{" self#opt_funspec f.sspec self#pVDecl f.svar ; - (* We take care of locals in blocks. *) - (*List.iter (fprintf fmt "@\n%a;" self#pVDecl) f.slocals ;*) - (* body. *) - currentFormals <- f.sformals ; - self#pBlock ~forcenewline:true fmt f.sbody ; - currentFormals <- [] ; - fprintf fmt "@]@\n}@." + method has_annot: bool + (** true if [current_stmt] has some annotations attached to it. *) - (***** PRINTING DECLARATIONS and TYPES ****) + method current_stmt: stmt option + (** Returns the stmt being printed *) - method pType ?fundecl nameOpt - fmt (t:typ) = - let name = match nameOpt with None -> (fun _ -> ()) | Some d -> d in - let printAttributes fmt (a: attributes) = - match nameOpt with - | None when not miscState.print_CIL_Input && not theMachine.msvcMode -> - (* Cannot print the attributes in this case because gcc does not - * like them here, except if we are printing for CIL, or for MSVC. - * In fact, for MSVC we MUST print attributes such as __stdcall *) - (* if pa = nil then nil else - text "/*" ++ pa ++ text "*/"*) () - | _ -> self#pAttrs fmt a - in - match t with - TVoid a -> - fprintf fmt "void%a %t" - self#pAttrs a - name + method current_behavior: funbehavior option + (** Returns the [funbehavior] being pretty-printed. *) - | TInt (ikind,a) -> - fprintf fmt "%a%a %t" - d_ikind ikind - self#pAttrs a - name + method may_be_skipped: stmt -> bool - | TFloat(fkind, a) -> - fprintf fmt "%a%a %t" - d_fkind fkind - self#pAttrs a - name + method setPrintInstrTerminator : string -> unit + method getPrintInstrTerminator : unit -> string - | TComp (comp, _, a) -> (* A reference to a struct *) - fprintf fmt - "%s %a %a%t" - (if comp.cstruct then "struct" else "union") - self#pVarName comp.cname - self#pAttrs a - name + method pVarName: Format.formatter -> string -> unit + (** Invoked each time an identifier name is to be printed. Allows for + various manipulation of the name, such as unmangling. *) - | TEnum (enum, a) -> - fprintf fmt "enum %a %a%t" - self#pVarName enum.ename - self#pAttrs a - name + method pVDecl: Format.formatter -> varinfo -> unit + (** Invoked for each variable declaration. Note that variable + * declarations are all the [GVar], [GVarDecl], [GFun], all the [varinfo] + * in formals of function types, and the formals and locals for function + * definitions. *) - | TPtr (bt, a) -> - (* Parenthesize the ( * attr name) if a pointer to a function or an - * array. However, on MSVC the __stdcall modifier must appear right - * before the pointer constructor "(__stdcall *f)". We push them into - * the parenthesis. *) - let (paren: (formatter -> unit) option), (bt': typ) = - match bt with - TFun(rt, args, isva, fa) when theMachine.msvcMode -> - let an, af', at = partitionAttributes ~default:AttrType fa in - (* We take the af' and we put them into the parentheses *) - Some - (fun fmt -> - fprintf fmt - "(%a" - printAttributes af'), - TFun(rt, args, isva, addAttributes an at) + method pVar: Format.formatter -> varinfo -> unit + (** Invoked on each variable use. *) - | TFun _ | TArray _ -> (Some (fun fmt -> fprintf fmt "(")), bt + method pLval: Format.formatter -> lval -> unit + (** Invoked on each lvalue occurence *) - | _ -> None, bt - in - let name' = fun fmt -> - fprintf fmt "*%a%t" - printAttributes a - name - in - let name'' = - fun fmt -> - (* Put the parenthesis *) - match paren with - Some p -> fprintf fmt "%t%t)" p name' - | _ -> fprintf fmt "%t" name' - in - self#pType - (Some name'') - fmt - bt' + method pOffset: Format.formatter -> offset -> unit + (** Invoked on each offset occurence. The second argument is the base. *) - | TArray (elemt, lo, _, a) -> - (* ignore the const attribute for arrays *) - let a' = dropAttributes [ "const" ] a in - let name' = fun fmt -> - if a' == [] then name fmt else - if nameOpt == None then - fprintf fmt - "%a" - printAttributes a' - else - fprintf fmt - "(%a%t)" - printAttributes a' - name - in - self#pType - (Some (fun fmt -> - fprintf fmt "%t[%t]" - name' - (fun fmt -> - match lo with - | None -> () - | Some e -> - fprintf fmt - "%a" - self#pExp e) - )) - fmt - elemt + method pInstr: Format.formatter -> instr -> unit + (** Invoked on each instruction occurrence. *) - | TFun (restyp, args, isvararg, a) -> - let name' fmt = - if a == [] then name fmt else - if nameOpt == None then - fprintf fmt - "%a" - printAttributes a - else - fprintf fmt - "(%a%t)" - printAttributes a - name - in - let module Args(A:sig type t - val args: t list option - val pp_args: Format.formatter -> t -> unit - end)= - struct - let pp_prms fmt = - fprintf fmt "%t(@[%t@])" name' - (fun fmt -> - match A.args with - | None -> () - | Some [] when isvararg -> - fprintf fmt "..." - | Some [] -> fprintf fmt "void" - | Some args -> - Pretty_utils.pp_list ~sep:",@ " A.pp_args - fmt args ; - if isvararg then fprintf fmt "@ , ..."; - ) - end - in - let pp_prms = - match fundecl with - None -> - let module Args = - Args(struct - type t = (string * typ * attributes) - let args = args - let pp_args fmt (aname,atype,aattr) = - let stom, rest = separateStorageModifiers aattr in - (* First the storage modifiers *) - fprintf fmt - "%a%a %a" - self#pAttrs stom - (self#pType - (Some (fun fmt -> fprintf fmt "%s" aname))) atype - self#pAttrs rest - end) - in Args.pp_prms - | Some fundecl -> - let module Args = - Args(struct - type t = varinfo - let args = - (try Some (getFormalsDecl fundecl) - with Not_found -> None) - let pp_args = self#pVDecl - end) - in Args.pp_prms - in - self#pType (Some pp_prms) fmt restyp - | TNamed (t, a) -> - fprintf fmt "%a%a %t" - self#pVarName t.tname - self#pAttrs a - name + method pStmt: Format.formatter -> stmt -> unit + (** Control-flow statement. This is used by + * {!Cil.printGlobal} and by [Cil.dumpGlobal]. *) - | TBuiltin_va_list a -> - fprintf fmt "__builtin_va_list%a %t" - self#pAttrs a - name + method pStmtNext : stmt -> Format.formatter -> stmt -> unit + method requireBraces: block -> bool (* Cf. cil.mli *) - (**** PRINTING ATTRIBUTES *********) - method pAttrs fmt (a: attributes) = - self#pAttrsGen false fmt a + method pBlock: + ?nobrace:bool -> ?forcenewline:bool -> Format.formatter -> block -> unit + (** Print a block. *) + method pGlobal: Format.formatter -> global -> unit + (** Global (vars, types, etc.). This can be slow and is used only by + * {!Cil.printGlobal} but by {!Cil.dumpGlobal} for everything else except + * [GVar] and [GFun]. *) - (* Print one attribute. Return also an indication whether this attribute - * should be printed inside the __attribute__ list *) - method pAttr fmt = function - Attr(an, args) -> - (* Recognize and take care of some known cases *) - (match an, args with - "const", [] -> fprintf fmt "const"; false - (* Put the aconst inside the attribute list *) - | "aconst", [] when not theMachine.msvcMode -> - fprintf fmt "__const__"; true - | "thread", [] when not theMachine.msvcMode -> - fprintf fmt "__thread"; false - (* - | "used", [] when not !msvcMode -> text "__attribute_used__", false - *) - | "volatile", [] -> fprintf fmt "volatile"; false - | "restrict", [] -> fprintf fmt "__restrict"; false - | "missingproto", [] -> fprintf fmt "/* missing proto */"; false - | "cdecl", [] when theMachine.msvcMode -> fprintf fmt "__cdecl"; false - | "stdcall", [] when theMachine.msvcMode -> - fprintf fmt "__stdcall"; false - | "fastcall", [] when theMachine.msvcMode -> fprintf fmt "__fastcall"; false - | "declspec", args when theMachine.msvcMode -> - fprintf fmt "__declspec(%a)" - (Pretty_utils.pp_list ~sep:"" self#pAttrParam) args; - false - | "w64", [] when theMachine.msvcMode -> fprintf fmt "__w64"; false - | "asm", args -> - fprintf fmt "__asm__(%a)" - (Pretty_utils.pp_list ~sep:"" self#pAttrParam) args; - false - (* we suppress printing mode(__si__) because it triggers an *) - (* internal compiler error in all current gcc versions *) - (* sm: I've now encountered a problem with mode(__hi__)... *) - (* I don't know what's going on, but let's try disabling all "mode"..*) - | "mode", [ACons(tag,[])] -> - fprintf fmt "/* mode(%s) */" tag; - false + method pFieldDecl: Format.formatter -> fieldinfo -> unit + (** A field declaration *) - (* sm: also suppress "format" because we seem to print it in *) - (* a way gcc does not like *) - | "format", _ -> fprintf fmt "/* format attribute */"; - false + method pType: ?fundecl:varinfo -> + (Format.formatter -> unit) option -> Format.formatter -> typ -> unit - (* sm: here's another one I don't want to see gcc warnings about.. *) - | "mayPointToStack", _ when not miscState.print_CIL_Input - (* [matth: may be inside another comment.] - -> text "/*mayPointToStack*/", false - *) - -> fprintf fmt ""; false + method pAttr: Format.formatter -> attribute -> bool + (** Attribute. Also return an indication whether this attribute must be + * printed inside the __attribute__ list or not. *) - | "arraylen", [a] -> - fprintf fmt "/*[%a]*/" self#pAttrParam a; - false - | "static",_ -> fprintf fmt "/* static */"; false - |"", _ -> - (fprintf fmt "%a " - (Pretty_utils.pp_list ~sep:" " self#pAttrParam) args; - true) - | _ -> (* This is the dafault case *) - (* Add underscores to the name *) - let an' = - if theMachine.msvcMode then "__" ^ an else "__" ^ an ^ "__" - in - if args = [] then - (fprintf fmt "%s" an'; - true) - else - (fprintf fmt "%s(%a)" - an' - (Pretty_utils.pp_list ~sep:"," self#pAttrParam) args; - true)) - | AttrAnnot s -> - fprintf fmt "%s" (mkAttrAnnot s); false + method pAttrParam: Format.formatter -> attrparam -> unit + (** Attribute paramter *) - method private pAttrPrec (contextprec: int) fmt (a: attrparam) = - let thisLevel = getParenthLevelAttrParam a in - let needParens = - if thisLevel >= contextprec then - true - else if contextprec == bitwiseLevel then - (* quiet down some GCC warnings *) - thisLevel == additiveLevel || thisLevel == comparativeLevel - else - false - in - if needParens then - fprintf fmt "(%a)" self#pAttrParam a - else - self#pAttrParam fmt a + method pAttrs: Format.formatter -> attributes -> unit + (** Attribute lists *) + method pLabel: Format.formatter -> label -> unit + (** Label *) - method pAttrParam fmt a = - let level = getParenthLevelAttrParam a in - match a with - | AInt n -> fprintf fmt "%d" n - | AStr s -> fprintf fmt "\"%s\"" (escape_string s) - | ACons(s, []) -> fprintf fmt "%s" s - | ACons(s,al) -> - fprintf fmt "%s(%a)" - s - (Pretty_utils.pp_list ~sep:"" self#pAttrParam) al - | ASizeOfE a -> fprintf fmt "sizeof(%a)" self#pAttrParam a - | ASizeOf t -> fprintf fmt "sizeof(%a)" (self#pType None) t - | ASizeOfS _ts -> fprintf fmt "sizeof()" - | AAlignOfE a -> fprintf fmt "__alignof__(%a)" self#pAttrParam a - | AAlignOf t -> fprintf fmt "__alignof__(%a)" (self#pType None) t - | AAlignOfS _ts -> fprintf fmt "__alignof__()" - | AUnOp(u,a1) -> - fprintf fmt "%a %a" - d_unop u - (self#pAttrPrec level) a1 + method pLineDirective: ?forcefile:bool -> Format.formatter -> location -> unit + (** Print a line-number. This is assumed to come always on an empty line. + * If the forcefile argument is present and is true then the file name + * will be printed always. Otherwise the file name is printed only if it + * is different from the last time time this function is called. The last + * file name is stored in a private field inside the cilPrinter object. *) - | ABinOp(b,a1,a2) -> - fprintf fmt "@[(%a)%a@ (%a) @]" - (self#pAttrPrec level) a1 - d_binop b - (self#pAttrPrec level) a2 + method pStmtLabels : Format.formatter -> stmt -> unit + (** Print only the labels of the statement. Used by [pAnnotatedStmt]. *) + + method pAnnotatedStmt : stmt -> Format.formatter -> stmt -> unit + (** Print an annotated statement. The code to be printed is given in the + * last {!stmt} argument. The initial {!stmt} argument + * records the statement which follows the one being printed; + * {!Cil.defaultCilPrinterClass} uses this information to prettify + * statement printing in certain special cases. *) + + method pStmtKind : stmt -> Format.formatter -> stmtkind -> unit + (** Print a statement kind. The code to be printed is given in the + * {!stmtkind} argument. The initial {!Cil.stmt} argument + * records the statement which follows the one being printed; + * {!Cil.defaultCilPrinterClass} uses this information to prettify + * statement printing in certain special cases. + *) - | ADot (ap, s) -> - fprintf fmt "%a.%s" - self#pAttrParam ap - s - | AStar a1 -> - fprintf fmt "(*%a)" - (self#pAttrPrec derefStarLevel) a1 - | AAddrOf a1 -> - fprintf fmt "& %a" (self#pAttrPrec addrOfLevel) a1 - | AIndex (a1, a2) -> - fprintf fmt "%a[%a]" - self#pAttrParam a1 - self#pAttrParam a2 - | AQuestion (a1, a2, a3) -> - fprintf fmt "%a ? %a : %a" - self#pAttrParam a1 - self#pAttrParam a2 - self#pAttrParam a3 + method pExp: Format.formatter -> exp -> unit + (** Print expressions *) + method pInit: Format.formatter -> init -> unit + (** Print initializers. This can be slow and is used by + * {!Cil.printGlobal} but not by {!Cil.dumpGlobal}. *) - (* A general way of printing lists of attributes *) - method private pAttrsGen (block: bool) fmt (a: attributes) = - (* Scan all the attributes and separate those that must be printed inside - * the __attribute__ list *) - let rec loop (in__attr__: string list) = function - [] -> begin - match in__attr__ with - [] -> () - | _ :: _-> - (* sm: added 'forgcc' calls to not comment things out - * if CIL is the consumer; this is to address a case - * Daniel ran into where blockattribute(nobox) was being - * dropped by the merger - *) - (if block then - fprintf fmt " %s __blockattribute__(" - (forgcc "/*") - else - fprintf fmt "__attribute__(("); - Pretty_utils.pp_list ~sep:",@ " - (fun fmt a -> fprintf fmt "%s" a) - fmt - in__attr__; - fprintf fmt ")%s" - (if block then forgcc "*/" else ")") - end - | x :: rest -> - let buff = Buffer.create 17 in - let local_fmt = formatter_of_buffer buff in - let ina = self#pAttr local_fmt x in - pp_print_flush local_fmt (); - let dx = Buffer.contents buff in - if ina then - loop (dx :: in__attr__) rest - else if dx = "" then - loop in__attr__ rest - else - (fprintf fmt "%s " dx; - loop in__attr__ rest) - in - let a = - List.filter (function Attr (s,_) -> not (List.mem s !reserved_attributes) - | AttrAnnot _ -> true) a - in - if a <> [] then - begin - fprintf fmt " "; - loop [] a; - fprintf fmt " " - end + method pLogic_type: + (Format.formatter -> unit) option -> + Format.formatter -> logic_type -> unit + (** The first argument gives the name of the declared variable. see pType for more + information. *) - (* Logic annotations printer *) + method pTerm: Format.formatter -> term -> unit - method pLogic_type name fmt = - let pname = match name with - | Some d -> (fun fmt -> Format.fprintf fmt "@ %t" d) - | None -> (fun _ -> ()) - in - function - | Ctype typ -> self#pType name fmt typ - | Linteger -> - let res = if !print_utf8 then Utf8_logic.integer else "integer" in - Format.fprintf fmt "%s%t" res pname - | Lreal -> - let res = if !print_utf8 then Utf8_logic.real else "real" in - Format.fprintf fmt "%s%t" res pname - | Ltype ({ lt_name = name},[]) when name = Utf8_logic.boolean-> - let res = if !print_utf8 then Utf8_logic.boolean else "boolean" in - Format.fprintf fmt "%s%t" res pname - | Ltype (s,l) -> - fprintf fmt "%a%a%t" self#pVarName s.lt_name - (pretty_list_del (fun fmt -> fprintf fmt "<@[") - (fun fmt -> fprintf fmt "@]>@ ") - (* the space avoids the issue of list> where the double > - would be read as a shift. It could be optimized away in most of - the cases. - *) - (space_sep ",") (self#pLogic_type None)) l pname - | Larrow (args,rt) -> - fprintf fmt "@[@[<2>{@ %a@]}@]%a%t" - (pretty_list (space_sep ",") (self#pLogic_type None)) args - (self#pLogic_type None) rt pname - | Lvar s -> fprintf fmt "%a%t" self#pVarName s pname + method pTerm_node: Format.formatter -> term -> unit - method private pTermPrec contextprec fmt e = - let thisLevel = getParenthLevelLogic e.term_node in - let needParens = - if thisLevel >= contextprec then - true - else if contextprec == bitwiseLevel then - (* quiet down some GCC warnings *) - thisLevel == additiveLevel || thisLevel == comparativeLevel - else - false - in - if needParens then - fprintf fmt "@[(%a)@]" self#pTerm e - else - self#pTerm fmt e + method pTerm_lval: Format.formatter -> term_lval -> unit - method pTerm fmt t = - match t.term_name with - [] -> self#pTerm_node fmt t - | _ -> - fprintf fmt "(@[%a:@ %a@])" - (pretty_list (swap fprintf ":@ ") pp_print_string) t.term_name - self#pTerm_node t + method pTerm_offset: Format.formatter -> term_offset -> unit - method pTerm_node fmt t = - let current_level = getParenthLevelLogic t.term_node in - match t.term_node with - | TConst s -> fprintf fmt "%a" d_const s - | TDataCons(ci,args) -> - fprintf fmt "%a%a" self#pVarName ci.ctor_name - (pretty_list_del (swap fprintf "(@[") (swap fprintf "@])") - (space_sep ",") self#pTerm) args - | TLval lv -> fprintf fmt "%a" (self#pTerm_lvalPrec current_level) lv - | TSizeOf t -> fprintf fmt "sizeof(%a)" (self#pType None) t - | TSizeOfE e -> fprintf fmt "sizeof(%a)" self#pTerm e - | TSizeOfStr s -> fprintf fmt "sizeof(%S)" s - | TAlignOf e -> fprintf fmt "alignof(%a)" (self#pType None) e - | TAlignOfE e -> fprintf fmt "alignof(%a)" self#pTerm e - | TUnOp (op,e) -> fprintf fmt "%a%a" - d_unop op (self#pTermPrec current_level) e - | TBinOp (op,l,r) -> - fprintf fmt "%a%a%a" - (self#pTermPrec current_level) l - d_term_binop op - (self#pTermPrec current_level) r - | TCastE (ty,e) -> - fprintf fmt "(%a)%a" (self#pType None) ty - (self#pTermPrec current_level) e - | TAddrOf lv -> fprintf fmt "&%a" (self#pTerm_lvalPrec addrOfLevel) lv - | TStartOf lv -> fprintf fmt "(%a)%a" - (self#pLogic_type None) t.term_type - (self#pTerm_lvalPrec current_level) lv - | Tapp (f, labels, tl) -> fprintf fmt "%a%a%a" - self#pLogic_info_use f - self#pLabels (List.map snd labels) - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@[(") - (fun fmt -> Format.fprintf fmt ")@]") - (space_sep ",") self#pTerm) tl - | Tif (cond,th,el) -> - fprintf fmt "@[<2>%a?@;%a:@;%a@]" - (self#pTermPrec current_level) cond - (self#pTermPrec current_level) th - (self#pTermPrec current_level) el - | Told e -> fprintf fmt "\\old(%a)" self#pTerm e - | Tat (t,lab) -> - begin - let rec pickLabel = function - | [] -> None - | Label (l, _, _) :: _ -> Some l - | _ :: rest -> pickLabel rest - in - let l = match lab with - | LogicLabel (_, s) -> s - | StmtLabel sref -> - match pickLabel !sref.labels with - Some l -> l - | None -> Cilmsg.fatal "Cannot find label for \\at@."; - in - fprintf fmt "@[\\at(@[@[%a@],@,@[%s@]@])@]" self#pTerm t l - end - | Tbase_addr t -> fprintf fmt "\\base_addr(%a)" self#pTerm t - | Tblock_length t -> fprintf fmt "\\block_length(%a)" self#pTerm t - | Tnull -> fprintf fmt "\\null" - | TCoerce (e,ty) -> - fprintf fmt "%a@ :>@ %a" - (self#pTermPrec current_level) e (self#pType None) ty - | TCoerceE (e,ce) -> - fprintf fmt "%a :> %a" - (self#pTermPrec current_level) e (self#pTermPrec current_level) ce - | TUpdate (t,toff,v) -> - fprintf fmt "{%a \\with %a = %a}" - self#pTerm t - self#pTerm_offset toff - self#pTerm v - | Tlambda(prms,expr) -> - fprintf fmt "@[<2>\\lambda@ %a;@ %a@]" - self#pQuantifiers prms (self#pTermPrec current_level) expr - | Ttypeof t -> fprintf fmt "\\typeof(%a)" self#pTerm t - | Ttype ty -> fprintf fmt "\\type(%a)" (self#pType None) ty - | Tunion locs -> - fprintf fmt "@[\\union(@,%a)@]" - (pretty_list (space_sep ",") self#pTerm) locs - | Tinter locs -> - fprintf fmt "@[\\inter(@,%a)@]" - (pretty_list (space_sep ",") self#pTerm) locs - | Tempty_set -> pp_print_string fmt "\\empty" - | Tcomprehension(lv,quant,pred) -> - fprintf fmt "{@[%a@ |@ %a%a@]}" - self#pTerm lv self#pQuantifiers quant - (pretty_opt (fun fmt p -> fprintf fmt ";@ %a" - self#identified_pred p)) - pred - | Trange(low,high) -> - fprintf fmt "@[%a..@,%a@]" - (pretty_opt (self#pTermPrec current_level)) low - (pretty_opt (self#pTermPrec current_level)) high - | Tlet(def,body) -> - assert - (Cilmsg.verify (def.l_labels = []) - "invalid logic construction: local definition with label"); - assert - (Cilmsg.verify (def.l_tparams = []) - "invalid logic construction: polymorphic local definition"); - let v = def.l_var_info in - let args = def.l_profile in - let pp_defn = match def.l_body with - | LBterm t -> fun fmt -> self#pTerm fmt t - | LBpred p -> fun fmt -> self#pPredicate_named fmt p - | LBnone - | LBreads _ | LBinductive _ -> fatal "invalid logic local definition" - in - fprintf fmt "@[\\let@ %a@ =@ %t%t;@ %a@]" - self#pLogic_var v - (fun fmt -> if args <> [] then - fprintf fmt "@[<2>\\lambda@ %a;@]@ " self#pQuantifiers args) - pp_defn - (self#pTermPrec current_level) body + method pLogic_info_use: Format.formatter -> logic_info -> unit - method private pTerm_lvalPrec contextprec fmt lv = - if getParenthLevelLogic (TLval lv) > contextprec then - fprintf fmt "(%a)" self#pTerm_lval lv - else - fprintf fmt "%a" self#pTerm_lval lv + method pLogic_type_def: Format.formatter -> logic_type_def -> unit - method pTerm_lval fmt lv = match lv with - | TVar vi, o -> fprintf fmt "%a%a" self#pLogic_var vi self#pTerm_offset o - | TResult _, o -> fprintf fmt "\\result%a" self#pTerm_offset o - | TMem ({term_node=TBinOp((PlusPI|IndexPI),base,off)}), o -> - fprintf fmt "%a[%a]%a" - (self#pTermPrec derefStarLevel) base - self#pTerm off - self#pTerm_offset o - | TMem e, TField(fi,o) -> - fprintf fmt "%a->%a%a" (self#pTermPrec arrowLevel) e - self#pVarName fi.fname self#pTerm_offset o - | TMem e, TNoOffset -> - fprintf fmt "*%a" (self#pTermPrec derefStarLevel) e - | TMem e, o -> - fprintf fmt "(*%a)%a" - (self#pTermPrec derefStarLevel) e self#pTerm_offset o + method pLogic_var: Format.formatter -> logic_var -> unit - method pTerm_offset fmt o = match o with - | TNoOffset -> () - | TField (fi,o) -> - fprintf fmt ".%a%a" self#pVarName fi.fname self#pTerm_offset o - | TIndex(e,o) -> fprintf fmt "[%a]%a" self#pTerm e self#pTerm_offset o + method pQuantifiers: Format.formatter -> quantifiers -> unit - method pLogic_info_use fmt li = self#pLogic_var fmt li.l_var_info + method pPredicate: Format.formatter -> predicate -> unit - method pLogic_var fmt v = self#pVarName fmt v.lv_name + method pPredicate_named: Format.formatter -> predicate named -> unit - method pQuantifiers fmt l = - pretty_list (space_sep ",") - (fun fmt lv -> - let pvar fmt = self#pLogic_var fmt lv in - self#pLogic_type (Some pvar) fmt lv.lv_type) - fmt l + method pIdentified_predicate: + Format.formatter -> identified_predicate -> unit + (* + method pPredicate_info_use: Format.formatter -> predicate_info -> unit + *) - method private pPredPrec fmt (contextprec,p) = - let thisLevel = getParenthLevelPred p in - let needParens = - if thisLevel >= contextprec then - true - else - false - in - if needParens then - fprintf fmt "@[(%a)@]" self#pPredicate p - else - self#pPredicate fmt p + method pBehavior: Format.formatter -> funbehavior -> unit - method private named_pred fmt (parenth,names,content) = - match names with - [] -> self#pPredPrec fmt (parenth,content) - | _ -> if parenth = upperLevel then - fprintf fmt "@[%a:@ %a@]" - (pretty_list (swap fprintf ":@ ") pp_print_string) names - self#pPredPrec (upperLevel,content) - else - fprintf fmt "(@[%a:@ %a@])" - (pretty_list (swap fprintf ":@ ") pp_print_string) names - self#pPredPrec (upperLevel,content) + method pRequires: Format.formatter -> identified_predicate -> unit + method pPost_cond: Format.formatter -> + (termination_kind * identified_predicate) -> unit + method pAssumes: Format.formatter -> identified_predicate -> unit - method private identified_pred fmt p = self#named_pred fmt (upperLevel,p.name,p.content) + method pComplete_behaviors: Format.formatter -> string list -> unit + method pDisjoint_behaviors: Format.formatter -> string list -> unit - method private pPredPrec_named fmt (parenth,p) = self#named_pred fmt (parenth,p.name,p.content) + method pTerminates: Format.formatter -> identified_predicate -> unit - method pPredicate_named fmt p = self#named_pred fmt (0,p.name,p.content) + method pSpec: Format.formatter -> funspec -> unit - method pIdentified_predicate fmt p = - if verbose then - fprintf fmt "@[//id:%d@\n%a@]" - p.ip_id self#named_pred (upperLevel,p.ip_name,p.ip_content) - else self#named_pred fmt (upperLevel,p.ip_name,p.ip_content) + method pAssigns: + string -> Format.formatter -> identified_term assigns -> unit - method private preds kw fmt l = - pretty_list_del ignore nl_sep nl_sep - (fun fmt p -> - fprintf fmt "@[%s @[%a@];@]" kw self#pIdentified_predicate p) fmt l + method pFrom: + string -> Format.formatter -> identified_term from -> unit - method pPredicate fmt p = - let current_level = getParenthLevelPred p in - let term = self#pTermPrec logic_level in - match p with - | Pfalse -> fprintf fmt "\\false" - | Ptrue -> fprintf fmt "\\true" - | Papp (p,labels,l) -> fprintf fmt "@[%a%a%a@]" - self#pLogic_info_use p - self#pLabels (List.map snd labels) - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@[(") - (fun fmt -> Format.fprintf fmt ")@]") - (space_sep ",") self#pTerm) l - | Prel (rel,l,r) -> - fprintf fmt "@[(@[%a@]@ %a@ @[%a@])@]" term l d_relation rel term r - | Pand (p1, p2) -> - fprintf fmt "@[%a@]@ %a@ @[%a@]" - self#pPredPrec_named (current_level,p1) - d_term_binop LAnd - self#pPredPrec_named (current_level,p2) - | Por (p1, p2) -> - fprintf fmt "@[%a@]@ %a@ @[%a@]" - self#pPredPrec_named (current_level,p1) - d_term_binop LOr - self#pPredPrec_named (current_level,p2) - | Pxor (p1, p2) -> - fprintf fmt "@[%a@]@ %s@ @[%a@]" - self#pPredPrec_named (current_level,p1) - (if !print_utf8 then Utf8_logic.x_or else "^^") - self#pPredPrec_named (current_level,p2) - | Pimplies (p1,p2) -> - fprintf fmt "@[%a@]@ %s@ @[%a@]" - self#pPredPrec_named (current_level,p1) - (if !print_utf8 then Utf8_logic.implies else "==>") - self#pPredPrec_named (current_level,p2) - | Piff (p1,p2) -> - fprintf fmt "@[%a@]@ %s@ @[%a@]" - self#pPredPrec_named (current_level,p1) - (if !print_utf8 then Utf8_logic.iff else "<==>") - self#pPredPrec_named (current_level,p2) - | Pnot a -> fprintf fmt "@[%s@[%a@]@]" - (if !print_utf8 then Utf8_logic.neg else "!") - self#pPredPrec_named (current_level,a) - | Pif (e, p1, p2) -> - fprintf fmt "@[<2>%a?@ %a:@ %a@]" - term e self#pPredPrec_named (current_level,p1) self#pPredPrec_named (current_level,p2) - | Plet (def, p) -> - assert - (Cilmsg.verify (def.l_labels = []) - "invalid logic construction: local definition with label"); - assert - (Cilmsg.verify (def.l_tparams = []) - "invalid logic construction: polymorphic local definition"); - let v = def.l_var_info in - let args = def.l_profile in - let pp_defn = match def.l_body with - | LBterm t -> fun fmt -> self#pTerm fmt t - | LBpred p -> fun fmt -> self#pPredPrec_named fmt (current_level,p) - | LBnone - | LBreads _ | LBinductive _ -> fatal "invalid logic local definition" - in - fprintf fmt "@[\\let@ %a@ =@ %t%t;@ %a@]" - self#pLogic_var v - (fun fmt -> - if args <> [] then - fprintf fmt "@[<2>\\lambda@ %a;@]@ " self#pQuantifiers args) - pp_defn - self#pPredPrec_named (current_level,p) - | Pforall (quant,pred) -> - fprintf fmt "@[%s %a;@]@ %a" - (if !print_utf8 then Utf8_logic.forall else "\\forall") - self#pQuantifiers quant self#pPredPrec_named (current_level,pred) - | Pexists (quant,pred) -> - fprintf fmt "@[%s %a;@]@ %a" - (if !print_utf8 then Utf8_logic.exists else "\\exists") - self#pQuantifiers quant self#pPredPrec_named (current_level,pred) - | Pold a -> fprintf fmt "@[\\old(@[%a@])@]" self#pPredPrec_named (upperLevel,a) - | Pvalid p -> fprintf fmt "@[\\valid(@[%a@])@]" self#pTerm p - | Pseparated seps -> - fprintf fmt "@[<2>\\separated(@,%a@,)@]" - (pretty_list (space_sep ",") self#pTerm) seps - | Pat (p,StmtLabel sref) -> - begin - let rec pickLabel = function - | [] -> None - | Label (l, _, _) :: _ -> Some l - | _ :: rest -> pickLabel rest - in - let l = match pickLabel !sref.labels with - Some l -> l - | None -> fatal "Cannot find label for \\at@." - in - fprintf fmt "@[\\at(@[@[%a@],@,@[%s@]@])@]" - self#pPredPrec_named (upperLevel,p) l - end - | Pat(p,LogicLabel (_, s)) -> - fprintf fmt "@[\\at(@[@[%a@],@,%s@])@]" - self#pPredPrec_named (upperLevel,p) s - | Pfresh e -> fprintf fmt "@[\\fresh(@[%a@])@]" self#pTerm e - | Pvalid_index (e1,e2) -> - fprintf fmt "@[\\valid_index(@[@[%a@],@,@[%a@]@])@]" - self#pTerm e1 self#pTerm e2 - | Pvalid_range (e1,e2,e3) -> - fprintf fmt "@[\\valid_range(@[@[%a@],@,@[%a@],@,@[%a@]@])@]" - self#pTerm e1 self#pTerm e2 self#pTerm e3 - | Psubtype (e,ce) -> - fprintf fmt "%a <: %a" term e term ce + method pCode_annot: Format.formatter -> code_annotation -> unit + method pAnnotation: Format.formatter -> global_annotation -> unit - method private pDecrement kw fmt (t, rel) = - match rel with - None -> fprintf fmt "@[<2>%s@ %a;@]" kw self#pTerm t - | Some str -> - (*TODO: replace this string with an interpreted variable*) - fprintf fmt "@[<2>%s@ %a@ for@ %s;@]" kw self#pTerm t str + method pDecreases: Format.formatter -> term variant -> unit - method pDecreases fmt v = self#pDecrement "decreases" fmt v + method pLoop_variant: Format.formatter -> term variant -> unit + end - method pLoop_variant fmt v = self#pDecrement "loop variant" fmt v - method pAssumes fmt p = - fprintf fmt "@[<2>assumes @[%a@];@]" self#pIdentified_predicate p + let is_skip = function Instr (Skip _) -> true | _ -> false - method pPost_cond fmt (k,p) = - let kw = get_termination_kind_name k in - fprintf fmt "@[<2>%s @[%a@];@]" kw self#pIdentified_predicate p + (** [b_assumes] must be always empty for behavior named [Cil.default_behavior_name] *) + let mk_behavior ?(name=default_behavior_name) ?(assumes=[]) ?(requires=[]) + ?(post_cond=[]) ?(assigns=WritesAny) ?(extended=[]) () = + { b_name = name; + b_assumes = assumes; (* must be always empty for default_behavior_name *) + b_requires = requires; + b_assigns = assigns ; + b_post_cond = post_cond ; + b_extended = extended; + } - method pBehavior fmt b = - if not (is_default_behavior b) - then begin - self#set_current_behavior b; - fprintf fmt "behavior %s:@\n @[%a%a%a%a@]" - b.b_name - (pretty_list_del ignore nl_sep nl_sep self#pAssumes) b.b_assumes - (pretty_list_del ignore nl_sep nl_sep self#pRequires) b.b_requires - (pretty_list_del ignore nl_sep nl_sep self#pPost_cond) b.b_post_cond - (self#pAssignsDeps "assigns") b.b_assigns; - self#reset_current_behavior () - end +let get_termination_kind_name = function + Normal -> "ensures" | Exits -> "exits" | Breaks -> "breaks" + | Continues -> "continue" | Returns -> "returns" - method pRequires fmt p = - fprintf fmt "@[<2>requires @[%a@];@]" - self#pIdentified_predicate p +let type_remove_attributes_for_cast = + typeRemoveAttributes ("FRAMA_C_BITFIELD_SIZE"::qualifier_attributes) + +let need_cast oldt newt = + not + (Cilutil.equals + (typeSig (type_remove_attributes_for_cast (unrollType oldt))) + (typeSig (type_remove_attributes_for_cast (unrollType newt)))) - method pTerminates fmt p = - fprintf fmt "@[<2>terminates @[%a@];@]" - self#pIdentified_predicate p +class defaultCilPrinterClass : cilPrinter = object (self) + val mutable logic_printer_enabled = true + val mutable verbose = false - method pComplete_behaviors fmt p = - fprintf fmt "@[<2>complete behaviors @[%a@];@]" - (pretty_list_del - ignore - ignore - (space_sep ",") - Format.pp_print_string) - p + val current_stmt = Stack.create () + val mutable current_function = None - method pDisjoint_behaviors fmt p = - fprintf fmt "@[<2>disjoint behaviors @[%a@];@]" - (pretty_list_del - ignore - ignore - (space_sep ",") - Format.pp_print_string) - p + val mutable current_behavior = None - method pSpec fmt ({ spec_behavior = behaviors; - spec_variant = variant; - spec_terminates = terminates; - spec_complete_behaviors = complete; - spec_disjoint_behaviors = disjoint; - } as spec) = - let default,default_requires,default_assigns,default_post_cond = - match find_default_behavior spec with - | (Some b) as db -> db, b.b_requires,b.b_assigns,b.b_post_cond - | None -> None,[],WritesAny,[] - in - let behaviors = List.filter (not $ is_default_behavior) behaviors in - let pretty_maybe_nl needs f fmt x = - if needs then nl_sep fmt; - f fmt x - in - fprintf fmt "@["; - let non_empty_default = - match default with - | None -> false - | Some b -> - self#set_current_behavior b; - let terminates_needs_nl = - default_requires <> [] && terminates <> None - in - let non_empty_prefix = - default_requires <> [] || terminates <> None - in - let variant_needs_nl = non_empty_prefix && variant <> None in - let non_empty_prefix = non_empty_prefix || variant <> None in - let post_cond_needs_nl = - non_empty_prefix && default_post_cond <> [] - in - let non_empty_prefix = non_empty_prefix || default_post_cond <> [] in - let assigns_needs_nl = - non_empty_prefix && default_assigns<>WritesAny - in - let non_empty_prefix = - non_empty_prefix || default_assigns<>WritesAny - in - fprintf fmt "%a%a%a%a%a" - (pretty_list nl_sep self#pRequires) default_requires - (pretty_opt - (pretty_maybe_nl terminates_needs_nl self#pTerminates)) - terminates - (pretty_opt - (pretty_maybe_nl variant_needs_nl self#pDecreases)) variant - (pretty_list nl_sep - (pretty_maybe_nl post_cond_needs_nl self#pPost_cond)) - default_post_cond - (pretty_maybe_nl assigns_needs_nl (self#pAssignsDeps "assigns")) - default_assigns; - self#reset_current_behavior (); - non_empty_prefix - in - let behaviors_needs_nl = non_empty_default && behaviors <> [] in - let non_empty_prefix = non_empty_default || behaviors <> [] in - let complete_needs_nl = non_empty_prefix && complete <> [] in - let non_empty_prefix = non_empty_prefix || complete <> [] in - let disjoint_needs_nl = non_empty_prefix && disjoint <> [] in - fprintf fmt "%a%a%a@]" - (pretty_maybe_nl behaviors_needs_nl (pretty_list nl_sep self#pBehavior)) - behaviors - (pretty_maybe_nl complete_needs_nl - (pretty_list nl_sep self#pComplete_behaviors)) - complete - (pretty_maybe_nl disjoint_needs_nl - (pretty_list nl_sep self#pDisjoint_behaviors)) - disjoint + method private in_current_function vi = + assert (current_function = None); + current_function <- Some vi + method private out_current_function = + assert (current_function <> None); + current_function <- None - method pAssigns kw fmt a = - match a with - | WritesAny -> () - | Writes [] -> fprintf fmt "@[%s \\nothing;@]" kw - | Writes l -> - let without_result = - List.filter - (function (a,_) -> not (Logic_const.is_result a.it_content)) l - in - pretty_list_del - (fun fmt -> fprintf fmt "%s@ " kw) - (fun fmt -> fprintf fmt ";") - (space_sep ",") - (fun fmt (x,_) -> self#pTerm fmt x.it_content) - fmt without_result + val mutable has_annot = false + method has_annot = has_annot - method private pAssignsDeps kw fmt a = - self#pAssigns kw fmt a; - match a with - WritesAny | Writes [] -> () - | Writes [(b,_ as a)] when Logic_const.is_result b.it_content -> - (* in this case, pAssigns does not write anything. *) - self#pFrom kw fmt a - | Writes l -> - pretty_list - ignore - (fun fmt f -> fprintf fmt "@\n%a" (self#pFrom kw) f) - fmt - (List.filter (fun (_,f) -> f <> FromAny) l) + method current_function = current_function + method current_behavior = current_behavior - method pFrom kw fmt (base,deps) = - match deps with - FromAny -> () - | From [] -> - fprintf fmt "%s@ %a@ \\from \\nothing;" kw - self#pTerm base.it_content - | From l -> - fprintf fmt "%s@ %a@ @[<2>\\from %a@];" - kw self#pTerm base.it_content - (pretty_list (space_sep ",") - (fun fmt x -> self#pTerm fmt x.it_content)) l + method private set_current_behavior b = + assert (current_behavior = None); current_behavior <- Some b - method private pLoop_pragma fmt = function - | Widen_hints terms -> fprintf fmt "WIDEN_HINTS @[%a@]" - (pretty_list_del - (fun _ -> ()) (fun _ -> ()) - (space_sep ",") self#pTerm) terms - | Widen_variables terms -> fprintf fmt "WIDEN_VARIABLES @[%a@]" - (pretty_list_del - (fun _ -> ()) (fun _ -> ()) - (space_sep ",") self#pTerm) terms - | Unroll_level t -> fprintf fmt "UNROLL @[%a@]" self#pTerm t + method private reset_current_behavior () = + assert (current_behavior <> None); current_behavior <- None - method private pSlice_pragma fmt = function - SPexpr t -> - fprintf fmt "expr @[%a@]" self#pTerm t - | SPctrl -> pp_print_string fmt "ctrl" - | SPstmt -> pp_print_string fmt "stmt" + method private push_stmt s = Stack.push s current_stmt + method private pop_stmt s = + ignore (Stack.pop current_stmt); has_annot<-false; s + method current_stmt = + try Some (Stack.top current_stmt) with Stack.Empty -> None - method private pImpact_pragma fmt = function - | IPexpr t -> fprintf fmt "expr @[%a@]" self#pTerm t - | IPstmt -> pp_print_string fmt "stmt" + method may_be_skipped s = s.labels = [] - method pStatus fmt s = d_annotation_status fmt s.status + (** Returns the stmt being printed *) - (* TODO: add the annot ID in debug mode?*) - method pCode_annot fmt ca = - match ca.annot_content with - | AAssert (behav,p) -> fprintf fmt "@[%aassert@ %a;@]" - (pretty_list_del - (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") - (space_sep ",") pp_print_string) - behav - self#identified_pred p - | APragma (Slice_pragma sp) -> - fprintf fmt "@[slice pragma@ %a;@]" self#pSlice_pragma sp - | APragma (Impact_pragma sp) -> - fprintf fmt "@[impact pragma@ %a;@]" self#pImpact_pragma sp - | APragma (Loop_pragma lp) -> - fprintf fmt "@[loop pragma@ %a;@]" self#pLoop_pragma lp - | AStmtSpec sp -> self#pSpec fmt sp - | AAssigns(behav,a) -> - fprintf fmt "@[<2>%a%a@]" - (pretty_list_del - (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") - (space_sep ",") pp_print_string) - behav - (self#pAssignsDeps "loop assigns") a - | AInvariant(behav,true, i) -> - fprintf fmt "@[<2>%aloop invariant@ %a;@]" - (pretty_list_del - (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") - (space_sep ",") pp_print_string) - behav - self#identified_pred i - | AInvariant(behav,false,i) -> fprintf fmt "@[<2>%ainvariant@ %a;@]" - (pretty_list_del - (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") - (space_sep ",") pp_print_string) - behav - self#identified_pred i - | AVariant v -> self#pLoop_variant fmt v + val mutable currentFormals : varinfo list = [] + method private getLastNamedArgument (s: string) : exp = + match List.rev currentFormals with + | [] -> + Kernel.abort + "Cannot find the last named argument when printing call to %s" + s + | f :: _ -> new_exp ~loc:f.vdecl (Lval (var f)) - method private pLoopInv fmt p = - fprintf fmt "@[<2>loop invariant@ %a;@]" - self#identified_pred p + (*** VARIABLES ***) + method pVarName fmt v = pp_print_string fmt v - method private pLogicPrms fmt arg = - let pvar fmt = self#pLogic_var fmt arg in - self#pLogic_type (Some pvar) fmt arg.lv_type + method private pVarString v = + Pretty_utils.sfprintf "%a" self#pVar v - method private pTypeParameters fmt tvars = - pretty_list_del - (fun fmt -> fprintf fmt "<@[") (fun fmt -> fprintf fmt "@]>") - (space_sep ",") pp_print_string fmt tvars + (* variable use *) + method pVar fmt (v:varinfo) = Format.fprintf fmt "%a" self#pVarName v.vname - method private pLogicLabel fmt lab = - let s = - match lab with - | LogicLabel (_, s) -> s - | StmtLabel sref -> - let rec pickLabel = function - [] -> None - | Label (l, _, _) :: _ -> Some l - | _ :: rest -> pickLabel rest - in - match pickLabel !sref.labels with - Some l -> l - | None -> "__invalid_label" - in pp_print_string fmt s + (* variable declaration *) + method pVDecl fmt (v:varinfo) = + let stom, rest = separateStorageModifiers v.vattr in + let fundecl = if isFunctionType v.vtype then Some v else None in + (* First the storage modifiers *) + fprintf fmt "%s%a%a%s%a%a" + (if v.vinline then "__inline " else "") + d_storage v.vstorage + self#pAttrs stom + (if stom = [] then "" else " ") + (self#pType ?fundecl + (if v.vname = "" then None else Some (fun fmt -> self#pVar fmt v))) + v.vtype + self#pAttrs rest - method private pLabels fmt labels = - pretty_list_del - (fun fmt -> fprintf fmt "{@[") (fun fmt -> fprintf fmt "@]}") - (space_sep ",") self#pLogicLabel fmt labels + (*** L-VALUES ***) + method pLval fmt (lv:lval) = (* lval (base is 1st field) *) + match lv with + Var vi, o -> fprintf fmt "%a%a" self#pVar vi self#pOffset o + | Mem e, Field(fi, o) -> + fprintf fmt "%a->%a%a" + (self#pExpPrec arrowLevel) e + self#pVarName fi.fname + self#pOffset o + | Mem e, NoOffset -> + fprintf fmt "*%a" + (self#pExpPrec derefStarLevel) e + | Mem e, o -> + fprintf fmt "(*%a)%a" + (self#pExpPrec derefStarLevel) e + self#pOffset o - method pAnnotation fmt = function - | Dtype_annot (a,_) -> - fprintf fmt "@[type invariant @[%a%a=@ %a@,;@]@]@\n" - self#pLogic_var a.l_var_info - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@[(") - (fun fmt -> Format.fprintf fmt ")@]@ ") - (space_sep ",") self#pLogicPrms) a.l_profile - self#identified_pred (pred_body a.l_body) - | Dinvariant (pred,_) -> - fprintf fmt "@[global@ invariant %a:@[@ %a;@]@]@\n" - self#pLogic_var pred.l_var_info - self#identified_pred (pred_body pred.l_body) - | Dlemma(name, is_axiom, labels, tvars, pred,_) -> - fprintf fmt "@[%s@ %a%a%a:@[@ %a;@]@]@\n" - (if is_axiom then "axiom" else "lemma") - self#pVarName name - self#pLabels labels - self#pTypeParameters tvars - self#identified_pred pred - | Dtype (ti,_) -> - fprintf fmt "@[type@ %a%a%a;@]@\n" - self#pVarName ti.lt_name self#pTypeParameters ti.lt_params - (pretty_opt - (fun fmt d -> fprintf fmt "@ =@ @[%a@]" self#pLogic_type_def d)) - ti.lt_def - | Dfun_or_pred (li,_) -> - begin - match li.l_type with - | Some rt -> - fprintf fmt "@[logic %a" - (self#pLogic_type None) rt - | None -> - fprintf fmt "@[predicate" - end; - fprintf fmt " %a%a%a%a" - self#pLogic_var li.l_var_info - self#pLabels li.l_labels - self#pTypeParameters li.l_tparams - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@[(") - (fun fmt -> Format.fprintf fmt ")@]@ ") - (space_sep ",") self#pLogicPrms) li.l_profile; - begin - match li.l_body with - | LBnone -> - fprintf fmt ";" - | LBreads reads -> - fprintf fmt "%a;" - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@\n@[reads@ ") - (fun fmt -> Format.fprintf fmt "@]") - (space_sep ",") - (fun fmt x -> self#pTerm fmt x.it_content)) reads - | LBpred def -> - fprintf fmt "=@ %a;" - self#identified_pred def - | LBinductive indcases -> - fprintf fmt "{@ %a}" - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@[") - (fun fmt -> Format.fprintf fmt "@]@\n") - nl_sep - (fun fmt (id,labels,tvars,p) -> - Format.fprintf fmt "case %s%a%a: @[%a@];" id - self#pLabels labels - self#pTypeParameters tvars - self#identified_pred p)) indcases - | LBterm def -> - fprintf fmt "=@ %a;" - self#pTerm def - end; - fprintf fmt "@]@\n" - | Daxiomatic(id,decls,_) -> - (* - Format.eprintf "cil.pAnnotation on axiomatic %s@." id; - *) - fprintf fmt "@[axiomatic@ %s {@\n%a}@]@\n" id - (pretty_list_del - (fun fmt -> Format.fprintf fmt "@[") - (fun fmt -> Format.fprintf fmt "@]@\n") - nl_sep - self#pAnnotation) - decls + (** Offsets **) + method pOffset fmt = function + | NoOffset -> () + | Field (fi, o) -> + fprintf fmt ".%a%a" + self#pVarName fi.fname + self#pOffset o + | Index (e, o) -> + fprintf fmt "[%a]%a" + self#pExp e + self#pOffset o - method pLogic_type_def fmt = function - | LTsum l -> - pretty_list (fun fmt -> fprintf fmt "@ |@ ") - (fun fmt info -> - fprintf fmt "%s@[%a@]" info.ctor_name - (pretty_list_del - (fun fmt -> fprintf fmt "@[(") - (fun fmt -> fprintf fmt ")@]") - (space_sep ",") - (self#pLogic_type None)) info.ctor_params) fmt l - | LTsyn typ -> self#pLogic_type None fmt typ + method private pLvalPrec (contextprec: int) fmt lv = + if getParenthLevel (dummy_exp(Lval(lv))) >= contextprec then + fprintf fmt "(%a)" self#pLval lv + else + self#pLval fmt lv - end (* class defaultCilPrinterClass *) + (*** EXPRESSIONS ***) + method pExp fmt (e: exp) = + let level = getParenthLevel e in + match (stripInfo e).enode with + | Info _ -> assert false + | Const(c) -> d_const fmt c + | Lval(l) -> self#pLval fmt l + | UnOp(u,e1,_) -> + fprintf fmt "%a %a" + d_unop u + (self#pExpPrec level) e1 - let defaultCilPrinter = new defaultCilPrinterClass + | BinOp(b,e1,e2,_) -> + fprintf fmt "@[%a %a %a@]" + (self#pExpPrec level) e1 + d_binop b + (self#pExpPrec level) e2 - (* Top-level printing functions *) - let printType (pp: cilPrinter) fmt (t: typ) = - pp#pType None fmt t + | CastE(t,e) -> + fprintf fmt "(%a)%a" + (self#pType None) t + (self#pExpPrec level) e - let printExp (pp: cilPrinter) fmt (e: exp) = - pp#pExp fmt e + | SizeOf (t) -> + fprintf fmt "sizeof(%a)" + (self#pType None) t - let printVar (pp:#cilPrinter) fmt v = pp#pVar fmt v + | SizeOfE (e) -> + fprintf fmt "sizeof(%a)" + self#pExp e - let printLval (pp: cilPrinter) fmt (lv: lval) = - pp#pLval fmt lv + | SizeOfStr s -> + fprintf fmt "sizeof(%a)" + d_const (CStr s) - let printGlobal (pp: cilPrinter) fmt (g: global) = - pp#pGlobal fmt g + | AlignOf (t) -> + fprintf fmt "__alignof__(%a)" + (self#pType None) t + | AlignOfE (e) -> + fprintf fmt "__alignof__(%a)" + self#pExp e + | AddrOf(lv) -> + fprintf fmt "& %a" + (self#pLvalPrec addrOfLevel) lv - let printAttr (pp: cilPrinter) fmt (a: attribute) = - ignore (pp#pAttr fmt a) + | StartOf(lv) -> self#pLval fmt lv + + (* Print an expression, given the precedence of the context in which it + * appears. *) + method private pExpPrec (contextprec: int) fmt (e: exp) = + let thisLevel = getParenthLevel e in + let needParens = + if thisLevel >= contextprec then + true + else if contextprec == bitwiseLevel then + (* quiet down some GCC warnings *) + thisLevel == additiveLevel || thisLevel == comparativeLevel + else + false + in + if needParens then + fprintf fmt "(%a)" self#pExp e + else + self#pExp fmt e + + method pInit fmt = function + SingleInit e -> self#pExp fmt e + | CompoundInit (t, initl) -> + (* We do not print the type of the Compound *) + (* + let dinit e = d_init () e in + dprintf "{@[%a@]}" + (docList ~sep:(chr ',' ++ break) dinit) initl + *) + let printDesignator = + if not theMachine.msvcMode then begin + (* Print only for union when we do not initialize the first field *) + match unrollType t, initl with + TComp(ci, _, _), [(Field(f, NoOffset), _)] -> + if not (ci.cstruct) && ci.cfields != [] && + (List.hd ci.cfields) != f then + true + else + false + | _ -> false + end else + false + in + let d_oneInit fmt = function + Field(f, NoOffset), i -> + if printDesignator then + fprintf fmt ".%a = " + self#pVarName f.fname; + self#pInit fmt i + | Index(e, NoOffset), i -> + if printDesignator then + fprintf fmt "[%a] = " + self#pExp e; + self#pInit fmt i + | _ -> Kernel.fatal "Trying to print malformed initializer" + in + fprintf fmt "{@[%a@]}" + (Pretty_utils.pp_list ~sep:",@ " d_oneInit) initl - let printAttrs (pp: cilPrinter) fmt (a: attributes) = - pp#pAttrs fmt a - let printInstr (pp: cilPrinter) fmt (i: instr) = - pp#pInstr fmt i + (** What terminator to print after an instruction. sometimes we want to + * print sequences of instructions separated by comma *) + val mutable printInstrTerminator = ";" - let printStmt (pp: cilPrinter) fmt (s: stmt) = - pp#pStmt fmt s + method private setPrintInstrTerminator (term : string) = + printInstrTerminator <- term - let printBlock (pp: cilPrinter) fmt (b: block) = - (* NB: eta expansion needed because of optional args of pBlock. *) - fprintf fmt "@[%a@]" (fun fmt -> pp#pBlock ~nobrace:false fmt) b + method private getPrintInstrTerminator () = printInstrTerminator - let printInit (pp: cilPrinter) fmt (i: init) = - pp#pInit fmt i + (*** INSTRUCTIONS ****) + method pInstr fmt (i:instr) = (* imperative instruction *) + fprintf fmt "%a" + (self#pLineDirective ~forcefile:false) (Cil_datatype.Instr.loc i); + match i with + | Skip _ -> fprintf fmt ";" + | Set(lv,e,_) -> begin + (* Be nice to some special cases *) + match e.enode with + BinOp((PlusA|PlusPI|IndexPI), + {enode = Lval(lv')}, + {enode=Const(CInt64(one,_,_))},_) + when compareLval lv lv' && My_bigint.equal one My_bigint.one + && not miscState.printCilAsIs -> + fprintf fmt "%a ++%s" + (self#pLvalPrec indexLevel) lv + printInstrTerminator + | BinOp((MinusA|MinusPI), + {enode = Lval(lv')}, + {enode=Const(CInt64(one,_,_))}, _) + when compareLval lv lv' && My_bigint.equal one My_bigint.one + && not miscState.printCilAsIs -> + fprintf fmt "%a --%s" + (self#pLvalPrec indexLevel) lv + printInstrTerminator - let printTerm_lval pp fmt lv = pp#pTerm_lval fmt lv + | BinOp((PlusA|PlusPI|IndexPI), + {enode = Lval(lv')}, + {enode = Const(CInt64(mone,_,_))},_) + when compareLval lv lv' && My_bigint.equal mone My_bigint.minus_one + && not miscState.printCilAsIs -> + fprintf fmt "%a --%s" + (self#pLvalPrec indexLevel) lv + printInstrTerminator - let printLogic_var pp fmt lv = pp#pLogic_var fmt lv + | BinOp((PlusA|PlusPI|IndexPI|MinusA|MinusPP|MinusPI|BAnd|BOr|BXor| + Mult|Div|Mod|Shiftlt|Shiftrt) as bop, + {enode = Lval(lv')},e,_) when compareLval lv lv' -> + fprintf fmt "%a %a= %a%s" + self#pLval lv + d_binop bop + self#pExp e + printInstrTerminator - let printLogic_type pp fmt lv = pp#pLogic_type None fmt lv + | _ -> + fprintf fmt "%a = %a%s" + self#pLval lv + self#pExp e + printInstrTerminator - let printTerm pp fmt t = pp#pTerm fmt t + end + (* In cabs2cil we have turned the call to builtin_va_arg into a + * three-argument call: the last argument is the address of the + * destination *) + | Call(None, {enode = Lval(Var vi, NoOffset)}, + [dest; {enode = SizeOf t}; adest], (l,_)) + when vi.vname = "__builtin_va_arg" && not miscState.printCilAsIs -> + let destlv = match (stripCasts adest).enode with + AddrOf destlv -> destlv + (* If this fails, it's likely that an extension interfered + with the AddrOf *) + | _ -> + Kernel.fatal ~source:l + "Encountered unexpected call to %s with dest %a" + vi.vname self#pExp adest + in + fprintf fmt "%a = __builtin_va_arg (@[%a,@ %a@])%s" + self#pLval destlv + (* Now the arguments *) + self#pExp dest + (self#pType None) t + printInstrTerminator - let printTerm_offset pp fmt o = pp#pTerm_offset fmt o + (* In cabs2cil we have dropped the last argument in the call to + * __builtin_va_start and __builtin_stdarg_start. *) + | Call(None, {enode = Lval(Var vi, NoOffset)}, [marker], l) + when ((vi.vname = "__builtin_stdarg_start" || + vi.vname = "__builtin_va_start") + && not miscState.printCilAsIs) -> + begin + let last = self#getLastNamedArgument vi.vname in + self#pInstr fmt (Call(None,dummy_exp(Lval(Var vi,NoOffset)), + [marker; last],l)) + end - let printPredicate_named pp fmt p = pp#pPredicate_named fmt p - let printIdentified_predicate pp fmt p = pp#pIdentified_predicate fmt p + (* In cabs2cil we have dropped the last argument in the call to + * __builtin_next_arg. *) + | Call(res, {enode = Lval(Var vi, NoOffset)}, [ ], l) + when vi.vname = "__builtin_next_arg" && not miscState.printCilAsIs -> + begin + let last = self#getLastNamedArgument vi.vname in + self#pInstr fmt (Call(res,dummy_exp(Lval(Var vi,NoOffset)),[last],l)) + end - let printCode_annotation pp fmt ca = pp#pCode_annot fmt ca - let printStatus pp fmt s = pp#pStatus fmt s + (* In cparser we have turned the call to + * __builtin_types_compatible_p(t1, t2) into + * __builtin_types_compatible_p(sizeof t1, sizeof t2), so that we can + * represent the types as expressions. + * Remove the sizeofs when printing. *) + | Call(dest, {enode = Lval(Var vi, NoOffset)}, + [{enode = SizeOf t1}; {enode = SizeOf t2}], _) + when vi.vname = "__builtin_types_compatible_p" + && not miscState.printCilAsIs -> + (* Print the destination *) + (match dest with + None -> () + | Some lv -> fprintf fmt "%a = " self#pLval lv ); + (* Now the call itself *) + fprintf fmt "%a(%a, %a)%s" + self#pVarName vi.vname + (self#pType None) t1 + (self#pType None) t2 + printInstrTerminator + | Call(_, {enode = Lval(Var vi, NoOffset)}, _, (l,_)) + when vi.vname = "__builtin_types_compatible_p" + && not miscState.printCilAsIs -> + Kernel.fatal ~source:l + "__builtin_types_compatible_p: cabs2cil should have added sizeof to the arguments." - let printFunspec pp fmt s = pp#pSpec fmt s + | Call(dest,e,args,_) -> + (match dest with + None -> () + | Some lv -> + fprintf fmt "%a = " + self#pLval lv; + (* Maybe we need to print a cast *) + (let destt = typeOfLval lv in + match unrollType (typeOf e) with + | TFun (rt, _, _, _) + when (need_cast rt destt) -> + fprintf fmt "(%a)" + (self#pType None) destt + | _ -> ())); + (* Now the function name *) + (match e.enode with + Lval(Var _, _) -> self#pExp fmt e + | _ -> fprintf fmt "(%a)" self#pExp e); + (* Now the arguments *) + Pretty_utils.pp_flowlist ~left:"(" ~sep:"," ~right:")" + self#pExp fmt args ; + (* Now the terminator *) + fprintf fmt "%s" printInstrTerminator - let printAnnotation pp fmt a = pp#pAnnotation fmt a - let printDecreases pp fmt a = pp#pDecreases fmt a - let printLoop_variant pp fmt a = pp#pLoop_variant fmt a - let printAssigns pp kw fmt a = pp#pAssigns kw fmt a - let printFrom pp kw fmt a = pp#pFrom kw fmt a - - (* Now define some short cuts *) - let d_exp fmt e = printExp defaultCilPrinter fmt e - let d_var fmt v = printVar defaultCilPrinter fmt v - let () = Cil_datatype.Varinfo.pretty_ref := d_var - let d_lval fmt lv = printLval defaultCilPrinter fmt lv - let () = Cil_datatype.Lval.pretty_ref := d_lval - let d_offset fmt off = defaultCilPrinter#pOffset fmt off - let d_init fmt i = printInit defaultCilPrinter fmt i - let d_type fmt t = printType defaultCilPrinter fmt t - let d_global fmt g = printGlobal defaultCilPrinter fmt g - let d_attrlist fmt a = printAttrs defaultCilPrinter fmt a - let d_attr fmt a = printAttr defaultCilPrinter fmt a - let d_attrparam fmt e = defaultCilPrinter#pAttrParam fmt e - let d_label fmt l = defaultCilPrinter#pLabel fmt l - let d_stmt fmt s = printStmt defaultCilPrinter fmt s - let () = Cil_datatype.Stmt.pretty_ref := d_stmt - let d_block fmt b = printBlock defaultCilPrinter fmt b - let d_instr fmt i = printInstr defaultCilPrinter fmt i + | Asm(attrs, tmpls, outs, ins, clobs, l) -> + self#pLineDirective fmt l; + if theMachine.msvcMode then + fprintf fmt "__asm {@[%a@]}%s" + (Pretty_utils.pp_list ~sep:"@\n" + (fun fmt s -> fprintf fmt "%s" s)) tmpls + printInstrTerminator + else begin + fprintf fmt "__asm__%a (@[%a" + self#pAttrs attrs + (Pretty_utils.pp_list ~sep:"@\n" + (fun fmt x -> + (* [JS 2011/03/11] isn't equivalent to [fprintf fmt "%S" x]? + *) + fprintf fmt "\"%s\"" (Escape.escape_string x))) + tmpls; - let d_term_lval fmt lv = printTerm_lval defaultCilPrinter fmt lv - let d_logic_var fmt lv = printLogic_var defaultCilPrinter fmt lv - let () = Cil_datatype.Logic_var.pretty_ref := d_logic_var - let d_logic_type fmt lv = printLogic_type defaultCilPrinter fmt lv - let () = Cil_datatype.Logic_type.pretty_ref := d_logic_type - let d_term fmt lv = printTerm defaultCilPrinter fmt lv - let () = Cil_datatype.Term.pretty_ref := d_term - let d_term_offset fmt lv = printTerm_offset defaultCilPrinter fmt lv + if outs = [] && ins = [] && clobs = [] then + fprintf fmt ":" + else + fprintf fmt ": %a" + (Pretty_utils.pp_list ~sep:",@ " + (fun fmt (idopt, c, lv) -> + fprintf fmt "%s\"%s\" (%a)" + (match idopt with + None -> "" + | Some id -> "[" ^ id ^ "] " + ) + (Escape.escape_string c) + self#pLval lv + )) outs; - let d_status fmt s = printStatus defaultCilPrinter fmt s - let d_predicate_named fmt lv = printPredicate_named defaultCilPrinter fmt lv - let d_identified_predicate fmt p = - printIdentified_predicate defaultCilPrinter fmt p - let d_code_annotation fmt lv = printCode_annotation defaultCilPrinter fmt lv - let d_funspec fmt lv = printFunspec defaultCilPrinter fmt lv - let d_annotation fmt lv = printAnnotation defaultCilPrinter fmt lv - let d_decreases fmt lv = printDecreases defaultCilPrinter fmt lv - let d_loop_variant fmt lv = printLoop_variant defaultCilPrinter fmt lv - let d_from fmt f = printFrom defaultCilPrinter "assigns" fmt f - let d_assigns fmt a = printAssigns defaultCilPrinter "assigns" fmt a - let d_loop_assigns fmt a = printAssigns defaultCilPrinter "loop assigns" fmt a - let d_loop_from fmt f = printFrom defaultCilPrinter "loop assigns" fmt f + if ins <> [] || clobs <> [] then + fprintf fmt ": %a" + (Pretty_utils.pp_list ~sep:",@ " + (fun fmt (idopt, c, e) -> + fprintf fmt "%s\"%s\"(%a)" + (match idopt with + None -> "" + | Some id -> "[" ^ id ^ "] " + ) + (Escape.escape_string c) + self#pExp e)) + ins; - let () = pd_exp := d_exp - let () = pd_global := d_global - let () = pd_type := d_type - (* sm: given an ordinary CIL object printer, yield one which - * behaves the same, except it never prints #line directives - * (this is useful for debugging printfs) *) - let dn_obj (func: formatter -> 'a -> unit) : (formatter -> 'a -> unit) = - begin - (* construct the closure to return *) - let theFunc fmt (obj:'a) = - begin - let prevStyle = miscState.lineDirectiveStyle in - miscState.lineDirectiveStyle <- None; - func fmt obj; (* call underlying printer *) - miscState.lineDirectiveStyle <- prevStyle - end in - theFunc - end + if clobs <> [] then + fprintf fmt ": %a" + (Pretty_utils.pp_list ~sep:",@ " + (fun fmt c -> fprintf fmt "\"%s\"" (Escape.escape_string c))) + clobs; - (* now define shortcuts for the non-location-printing versions, - * with the naming prefix "dn_" *) - let dn_exp = (dn_obj d_exp) - let dn_lval = (dn_obj d_lval) - (* dn_offset is missing because it has a different interface *) - let dn_init = (dn_obj d_init) - let dn_type = (dn_obj d_type) - let dn_global = (dn_obj d_global) - let dn_attrlist = (dn_obj d_attrlist) - let dn_attr = (dn_obj d_attr) - let dn_attrparam = (dn_obj d_attrparam) - let dn_stmt = (dn_obj d_stmt) - let dn_instr = (dn_obj d_instr) + fprintf fmt "@])%s" printInstrTerminator + end + | Code_annot (annot, l) -> + has_annot <- true; + if logic_printer_enabled then + begin + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "/*@@ " ; + self#pCode_annot fmt annot ; + Pretty_utils.pp_close_block fmt "*/" ; + end -(* And now some shortcuts *) -let d_plainexp fmt e = defaultCilPrinter#pExp fmt e -let d_plaintype fmt t = defaultCilPrinter#pType None fmt t -let d_plaininit fmt i = defaultCilPrinter#pInit fmt i -let d_plainlval fmt l = defaultCilPrinter#pLval fmt l -class type descriptiveCilPrinter = object - inherit cilPrinter - method startTemps: unit -> unit - method stopTemps: unit -> unit - method pTemps: Format.formatter -> unit - end + (**** STATEMENTS ****) + method pStmt fmt (s:stmt) = (* control-flow statement *) + self#push_stmt s; + self#pop_stmt (self#pStmtNext invalidStmt fmt s) - class descriptiveCilPrinterClass : descriptiveCilPrinter = object (self) - (** Like defaultCilPrinterClass, but instead of temporary variable - names it prints the description that was provided when the temp was - created. This is usually better for messages that are printed for end - users, although you may want the temporary names for debugging. *) - inherit defaultCilPrinterClass as super + method pStmtNext (next: stmt) fmt (s: stmt) = + self#push_stmt s; + self#pop_stmt (self#pAnnotatedStmt next fmt s) - val mutable temps: (varinfo * string * string option) list = [] - val mutable useTemps: bool = false + method pStmtLabels fmt (s:stmt) = + (* print the labels. *) + begin + let is_simple = function + | Instr(Set _ | Call _ | Skip _) -> true + | _ -> false + in + match s.labels with + | [] -> () + | [l] when is_simple s.skind -> self#pLabel fmt l + | _ -> List.iter (fprintf fmt "%a@ " self#pLabel) s.labels + end - method startTemps () : unit = - temps <- []; - useTemps <- true + method pAnnotatedStmt (next: stmt) fmt (s: stmt) = + self#pStmtLabels fmt s ; + (* print the statement. *) + if is_skip s.skind && not s.ghost then + (if verbose || s.labels <> [] then fprintf fmt ";") + else + begin + if s.ghost then Pretty_utils.pp_open_block fmt "/*@@ ghost "; + self#pStmtKind next fmt s.skind ; + if s.ghost then Pretty_utils.pp_close_block fmt "*/" ; + end - method stopTemps () : unit = - temps <- []; - useTemps <- false + method private pLabel fmt = function + Label (s, _, true) -> fprintf fmt "%s: " s + | Label (s, _, false) -> fprintf fmt "%s: /* internal */ " s + | Case (e, _) -> fprintf fmt "case %a: " self#pExp e + | Default _ -> fprintf fmt "default: " - method pTemps fmt = - if temps = [] then - () - else - fprintf fmt "@\nWhere:@\n %a" - (Pretty_utils.pp_list ~sep:"\n " - (let f fmt v = match v with - | (_, s, Some d) -> fprintf fmt "%s = %s" s d - |(_, s, None) -> fprintf fmt "%s = " s in f)) - (List.rev temps) + method requireBraces blk = + match blk.bstmts, blk.battrs, blk.blocals with + | ([_] | []),[],[] -> false + | _,_,_::_ -> true + | _ -> self#has_annot - method private pVarDescriptive fmt (vi: varinfo) = - match vi.vdescr with - | Some vd -> - if vi.vdescrpure || not useTemps then - fprintf fmt "%s" vd - else begin - try - let _, name, _ = List.find (fun (vi', _, _) -> vi == vi') temps in - fprintf fmt "%s" name - with Not_found -> - let name = "tmp" ^ string_of_int (List.length temps) in - temps <- (vi, name, vi.vdescr) :: temps; - fprintf fmt "%s" name - end - | None -> - super#pVar fmt vi + (* The pBlock will put the unalign itself *) + method pBlock ?(nobrace=true) ?(forcenewline=false) fmt (blk: block) = + let force_paren = (not nobrace) && (verbose || self#requireBraces blk) in + (* Let the host of the block decide on the alignment. The d_block will + * pop the alignment as well *) + let print_sep fmt = + if forcenewline then fprintf fmt "@\n" else fprintf fmt "@ " + in + let rec iterblock fmt = function + | [] -> () + | [s] -> + self#pStmtNext invalidStmt fmt s + | s_cur :: (s_next :: _ as tail) -> + self#pStmtNext s_next fmt s_cur ; + print_sep fmt; + iterblock fmt tail + in + if force_paren then fprintf fmt "@[{@[@ "; + if nobrace then print_sep fmt ; + if Kernel.debug_atleast 1 then fprintf fmt "@\n/* %a */@\n" + (Pretty_utils.pp_list + ~sep:("," ^^ Pretty_utils.space_sep) self#pVar) blk.blocals; + if blk.battrs <> [] then self#pAttrsGen true fmt blk.battrs ; + List.iter + (fun v -> fprintf fmt "%a;%t" self#pVDecl v print_sep) blk.blocals; + iterblock fmt blk.bstmts ; + if force_paren then fprintf fmt "@]@;}@]@\n"; - (* Only substitute temp vars that appear in expressions. - (Other occurrences of lvalues are the left-hand sides of assignments, - but we shouldn't substitute there since "foo(a,b) = foo(a,b)" - would make no sense to the user.) *) - method pExp fmt (e:exp) = - match e.enode with - Lval (Var vi, o) - | StartOf (Var vi, o) -> - fprintf fmt "%a%a" self#pVarDescriptive vi self#pOffset o - | AddrOf (Var vi, o) -> - (* No parens needed, since offsets have higher precedence than & *) - fprintf fmt "& %a%a" self#pVarDescriptive vi self#pOffset o - | _ -> super#pExp fmt e - end + (* Store here the name of the last file printed in a line number. This is + * private to the object *) + val mutable lastFileName = "" + val mutable lastLineNumber = -1 - let descriptiveCilPrinter: descriptiveCilPrinter = - ((new descriptiveCilPrinterClass) :> descriptiveCilPrinter) + (* Make sure that you only call self#pLineDirective on an empty line *) + method pLineDirective ?(forcefile=false) fmt l = + CurrentLoc.set l; + match miscState.lineDirectiveStyle with + | None -> () + | Some _ when (fst l).Lexing.pos_lnum <= 0 -> () - let dd_exp = descriptiveCilPrinter#pExp - let dd_lval = descriptiveCilPrinter#pLval + (* Do not print lineComment if the same line as above *) + | Some LineCommentSparse when (fst l).Lexing.pos_lnum = lastLineNumber -> () - let cvar_to_lvar vi = - match vi.vlogic_var_assoc with - None -> - let lv = - { lv_name = vi.vname; - lv_id = vi.vid; - lv_type = Ctype vi.vtype ; - lv_origin = Some vi} - in vi.vlogic_var_assoc <- Some lv; lv - | Some lv -> lv + | Some style -> + let directive = + match style with + | LineComment | LineCommentSparse -> "//#line " + | LinePreprocessorOutput when not theMachine.msvcMode -> "#" + | LinePreprocessorOutput | LinePreprocessorInput -> "#line" + in + lastLineNumber <- (fst l).Lexing.pos_lnum; + let filename = + if forcefile || (fst l).Lexing.pos_fname <> lastFileName then + begin + lastFileName <- (fst l).Lexing.pos_fname; + " \"" ^ (fst l).Lexing.pos_fname ^ "\"" + end + else + "" + in + fprintf fmt "@<0>\n@<0>%s@<0> @<0>%d@<0> @<0>%s@\n" directive (fst l).Lexing.pos_lnum filename - let copyVarinfo (vi: varinfo) (newname: string) : varinfo = - let vi' = copy_with_new_vid vi in - vi'.vname <- newname; - (match vi.vlogic_var_assoc with - None -> () - | Some _ -> - vi'.vlogic_var_assoc <- None; - ignore(cvar_to_lvar vi')); - vi' - let rec findUniqueName ?(suffix="") fdec name = - let current_name = name ^ suffix in - (* Is this check a performance problem? We could bring the old - unchecked makeTempVar back as a separate function that assumes - the prefix name does not occur in the original program. *) - if (List.exists (fun vi -> vi.vname = current_name) fdec.slocals) - || (List.exists (fun vi -> vi.vname = current_name) fdec.sformals) then begin - fdec.smaxid <- 1 + fdec.smaxid; - findUniqueName ~suffix:("_" ^ (string_of_int (1 + fdec.smaxid))) fdec name - end else - current_name + method pStmtKind (next: stmt) fmt kind = + match kind with + | UnspecifiedSequence seq -> + let print_stmt pstmt fmt (stmt, modifies, writes, reads,_) = + pstmt fmt stmt ; + if verbose then + Format.fprintf fmt "@ /*effects: @[(%a)%a@ <-@ %a@]*/" + (Cilutil.pretty_list (Cilutil.space_sep ",") self#pLval) modifies + (Cilutil.pretty_list (Cilutil.space_sep ",") self#pLval) writes + (Cilutil.pretty_list (Cilutil.space_sep ",") self#pLval) reads + in + let rec iterblock fmt = function + | [] -> () + | [srw] -> + fprintf fmt "@ " ; + print_stmt (self#pStmtNext invalidStmt) fmt srw + | srw_first :: ((s_next,_,_,_,_) :: _ as tail) -> + fprintf fmt "@ " ; + print_stmt (self#pStmtNext s_next) fmt srw_first ; + iterblock fmt tail + in + Pretty_utils.pp_open_block fmt "{ /*undefined sequence*/ " ; + iterblock fmt seq ; + Pretty_utils.pp_close_block fmt "}" - let makeLocal ?(generated=true) ?(formal=false) fdec name typ = - (* a helper function *) - let name = findUniqueName fdec name in - fdec.smaxid <- 1 + fdec.smaxid; - let vi = makeVarinfo ~generated false formal name typ in - vi + | Return(None, l) -> + self#pLineDirective fmt l; + fprintf fmt "return;" - (* Make a local variable and add it to a function *) - let makeLocalVar fdec ?scope ?(generated=true) ?(insert = true) name typ = - let vi = makeLocal ~generated fdec name typ in - if insert then - begin - fdec.slocals <- fdec.slocals @ [vi]; - let local_block = - match scope with - | None -> fdec.sbody - | Some b -> b - in - local_block.blocals <- vi::local_block.blocals - end; - vi + | Return(Some e, l) -> + self#pLineDirective fmt l ; + fprintf fmt "return (%a);" self#pExp e - let makeTempVar fdec ?insert ?(name = "__cil_tmp") ?descr ?(descrpure = true) - typ : varinfo = - let vi = makeLocalVar fdec ?insert name typ in - vi.vdescr <- descr; - vi.vdescrpure <- descrpure; - vi + | Goto (sref, l) -> begin + (* Grab one of the labels *) + let rec pickLabel = function + [] -> None + | Label (lbl, _, _) :: _ -> Some lbl + | _ :: rest -> pickLabel rest + in + match pickLabel !sref.labels with + Some lbl -> + self#pLineDirective fmt l; + fprintf fmt "goto %s;" (* ^^ " /* %a */" *) lbl + (*self#pStmt !sref*) + | None -> + Kernel.error "Cannot find label for target of goto: %a" + self#pStmt !sref; + fprintf fmt "goto __invalid_label;" + end - let makePseudoVar = - let counter = ref 0 in - function ty -> - incr counter; - let name = "@" ^ (string_of_int !counter) in - makeVarinfo ~logic:true (* global= *)false (* formal= *)false name ty + | Break l -> + self#pLineDirective fmt l; + fprintf fmt "break;" - (* Set the formals and re-create the function name based on the information*) - let setFormals (f: fundec) (forms: varinfo list) = - unsafeSetFormalsDecl f.svar forms; - List.iter (fun v -> v.vformal <- true) forms; - f.sformals <- forms; (* Set the formals *) - match unrollType f.svar.vtype with - TFun(rt, _, isva, fa) -> - f.svar.vtype <- - TFun(rt, - Some (List.map (fun a -> (a.vname, a.vtype, a.vattr)) forms), - isva, fa) - | _ -> Cilmsg.abort "Set formals. %s does not have function type" f.svar.vname + | Continue l -> + self#pLineDirective fmt l; + fprintf fmt "continue;" - (* Set the types of arguments and results as given by the function type - * passed as the second argument *) - let setFunctionType (f: fundec) (t: typ) = - match unrollType t with - TFun (_rt, Some args, _va, _a) -> - if List.length f.sformals <> List.length args then - Cilmsg.fatal "setFunctionType: number of arguments differs from the number of formals" ; - (* Change the function type. *) - f.svar.vtype <- t; - (* Change the sformals and we know that indirectly we'll change the - * function type *) - List.iter2 - (fun (_an,at,aa) f -> - f.vtype <- at; f.vattr <- aa) - args f.sformals + | Instr i -> self#pInstr fmt i + (* fprintf fmt "@[%a@]" self#pInstr i *) - | _ -> Cilmsg.fatal "setFunctionType: not a function type" + | If(be,t,{bstmts=[];battrs=[]},l) when not miscState.printCilAsIs -> + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "if (%a) {" self#pExp be ; + self#pBlock fmt t ; + Pretty_utils.pp_close_block fmt "}" + | If(be,t,{bstmts=[{skind=Goto(gref,_);labels=[]}]; battrs=[]},l) + when !gref == next && not miscState.printCilAsIs -> + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "if (%a) {" self#pExp be ; + self#pBlock fmt t ; + Pretty_utils.pp_close_block fmt "}" - (* Set the types of arguments and results as given by the function type - * passed as the second argument *) - let setFunctionTypeMakeFormals (f: fundec) (t: typ) = - match unrollType t with - TFun (_rt, Some args, _va, _a) -> - if f.sformals <> [] then - Cilmsg.fatal "setFunctionTypMakeFormals called on function %s with some formals already" - f.svar.vname ; - (* Change the function type. *) - f.svar.vtype <- t; - f.sformals <- []; + | If(be,{bstmts=[];battrs=[]},e,l) when not miscState.printCilAsIs -> + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "if (%a) {" + self#pExp (dummy_exp(UnOp(LNot,be,intType))) ; + self#pBlock fmt e ; + Pretty_utils.pp_close_block fmt "}" - f.sformals <- List.map (fun (n,t,_a) -> makeLocal ~formal:true f n t) args; + | If(be,{bstmts=[{skind=Goto(gref,_);labels=[]}]; battrs=[]},e,l) + when !gref == next && not miscState.printCilAsIs -> + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "if (%a) {" + self#pExp (dummy_exp(UnOp(LNot,be,intType))) ; + self#pBlock fmt e ; + Pretty_utils.pp_close_block fmt "}" - setFunctionType f t + | If(be,t,e,l) -> + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "if (%a) {" self#pExp be ; + self#pBlock fmt t ; + Pretty_utils.pp_close_block fmt "}" ; + fprintf fmt "@ " ; + Pretty_utils.pp_open_block fmt "else {" ; + self#pBlock fmt e ; + Pretty_utils.pp_close_block fmt "}" - | _ -> Cilmsg.fatal "setFunctionTypeMakeFormals: not a function type: %a" d_type t + | Switch(e,b,_,l) -> + self#pLineDirective ~forcefile:false fmt l ; + Pretty_utils.pp_open_block fmt "switch (%a) {" self#pExp e ; + self#pBlock fmt b ; + Pretty_utils.pp_close_block fmt "}" + | Loop(annot, b, l, _, _) -> + if logic_printer_enabled && annot <> [] then + begin + Pretty_utils.pp_open_block fmt "/*@@ " ; + Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep + self#pCode_annot + fmt + annot; + Pretty_utils.pp_close_block fmt "@ */@\n" ; + end ; + begin + (* Maybe the first thing is a conditional. Turn it into a WHILE *) + try + let rec skipEmpty = function + [] -> [] + | {skind=Instr (Skip _);labels=[]} as h :: rest + when self#may_be_skipped h-> skipEmpty rest + | x -> x + in + let term, bodystmts = + (* Bill McCloskey: Do not remove the If if it has labels *) + match skipEmpty b.bstmts with + {skind=If(e,tb,fb,_)} as to_skip :: rest + when + not miscState.printCilAsIs && self#may_be_skipped to_skip -> + begin + match skipEmpty tb.bstmts, skipEmpty fb.bstmts with + [], {skind=Break _; labels=[]}::_ -> e, rest + | {skind=Break _; labels=[]}::_, [] + -> dummy_exp (UnOp(LNot, e, intType)), rest + | _ -> raise Not_found + end + | _ -> raise Not_found + in + let b = match skipEmpty bodystmts with + [{ skind=Block b} as s ] when self#may_be_skipped s -> b + | _ -> { b with bstmts = bodystmts } + in + self#pLineDirective fmt l ; + Pretty_utils.pp_open_block fmt "while (%a) {" self#pExp term ; + self#pBlock fmt b ; + Pretty_utils.pp_close_block fmt "}" - let setMaxId (f: fundec) = - f.smaxid <- List.length f.sformals + List.length f.slocals + with Not_found -> + self#pLineDirective fmt l ; + Pretty_utils.pp_open_block fmt "while (1) {" ; + self#pBlock fmt b ; + Pretty_utils.pp_close_block fmt "}" + end - (* Make a formal variable for a function. Insert it in both the sformals - * and the type of the function. You can optionally specify where to insert - * this one. If where = "^" then it is inserted first. If where = "$" then - * it is inserted last. Otherwise where must be the name of a formal after - * which to insert this. By default it is inserted at the end. *) - let makeFormalVar fdec ?(where = "$") name typ : varinfo = - (* Search for the insertion place *) - let thenewone = ref fdec.svar in (* Just a placeholder *) - let makeit () : varinfo = - let vi = makeLocal ~formal:true fdec name typ in - thenewone := vi; - vi - in - let rec loopFormals = function - [] -> - if where = "$" then [makeit ()] - else Cilmsg.fatal "makeFormalVar: cannot find insert-after formal %s" where - | f :: rest when f.vname = where -> f :: makeit () :: rest - | f :: rest -> f :: loopFormals rest - in - let newformals = - if where = "^" then makeit () :: fdec.sformals else - loopFormals fdec.sformals in - setFormals fdec newformals; - !thenewone + | Block b -> + if (match b.bstmts with [] | [_] -> true | _ -> false) + then self#pBlock ~nobrace:false fmt b + else + begin + if verbose then + Pretty_utils.pp_open_block fmt "/*block:begin*/@ " ; + self#pBlock ~nobrace:false fmt b ; + if verbose then Pretty_utils.pp_close_block fmt "/*block:end*/" ; + end - (* Make a global variable. Your responsibility to make sure that the name - * is unique *) - let makeGlobalVar ?logic ?generated name typ = - let vi = makeVarinfo ?logic ?generated true false name typ in - vi + | TryFinally (b, h, l) -> + self#pLineDirective fmt l; + fprintf fmt "__try {@[%a@]} @[<5>__finally{%a}@]" + (* NB: eta expansion needed because of optional args of pBlock. *) + (fun fmt -> self#pBlock fmt) b + (fun fmt -> self#pBlock fmt) h - (* Make an empty function *) - let emptyFunction name = - let r = - { svar = makeGlobalVar - ~generated:false name (TFun(voidType, Some [], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - sspec = empty_funspec () - } - in - setFormalsDecl r.svar r.svar.vtype; - r + | TryExcept (b, (il, e), h, l) -> + self#pLineDirective fmt l; + fprintf fmt "__try {@[%a@]} @[<5>__except(@\n@[" + (* NB: eta expansion needed because of optional args of pBlock. *) + (fun fmt -> self#pBlock fmt) b; + + (* Print the instructions but with a comma at the end, instead of + * semicolon *) + printInstrTerminator <- ","; + Pretty_utils.pp_list ~sep:"@\n" self#pInstr fmt il; + printInstrTerminator <- ";"; + fprintf fmt "%a) @]%a" + (* NB: eta expansion needed because of optional args of pBlock. *) + self#pExp e (fun fmt -> self#pBlock fmt) h - let dummyFile = - { globals = []; - fileName = ""; - globinit = None; - globinitcalled = false;} + (*** GLOBALS ***) + method pGlobal fmt (g:global) = (* global (vars, types, etc.) *) + match g with + | GFun (fundec, l) -> + self#in_current_function fundec.svar; + (* If the function has attributes then print a prototype because + * GCC cannot accept function attributes in a definition *) + let oldattr = fundec.svar.vattr in + (* Always pring the file name before function declarations *) + (* Prototype first *) + if oldattr <> [] then + (self#pLineDirective fmt l; + fprintf fmt "%a;@\n" + self#pVDecl fundec.svar); + (* Temporarily remove the function attributes *) + fundec.svar.vattr <- []; + (* Body now *) + self#pLineDirective ~forcefile:true fmt l; + self#pFunDecl fmt fundec; + fundec.svar.vattr <- oldattr; + fprintf fmt "@\n"; + self#out_current_function - (* Take the name of a file and make a valid varinfo name out of it. There are - * a few characters that are not valid in varinfos *) - let makeValidVarinfoName (s: string) = - let s = String.copy s in (* So that we can update in place *) - let l = String.length s in - for i = 0 to l - 1 do - let c = String.get s i in - let isinvalid = - match c with - '-' | '.' -> true - | _ -> false - in - if isinvalid then - String.set s i '_'; - done; - s + | GType (typ, l) -> + self#pLineDirective ~forcefile:true fmt l; + fprintf fmt "typedef %a;@\n" + (self#pType (Some (fun fmt -> fprintf fmt "%s" typ.tname))) typ.ttype - let rec lastOffset (off: offset) : offset = - match off with - | NoOffset | Field(_,NoOffset) | Index(_,NoOffset) -> off - | Field(_,off) | Index(_,off) -> lastOffset off + | GEnumTag (enum, l) -> + self#pLineDirective fmt l; + if verbose then + fprintf fmt "/* Following enum is equivalent to %a */@\n" + (self#pType None) + (TInt(enum.ekind,[])); + fprintf fmt "enum@[ %a {@\n%a@]@\n}%a;@\n" + self#pVarName enum.ename + (Pretty_utils.pp_list ~sep:",@\n" + (fun fmt item -> + fprintf fmt "%s = %a" + item.einame + self#pExp item.eival)) + enum.eitems + self#pAttrs enum.eattr - let rec lastTermOffset (off: term_offset) : term_offset = - match off with - | TNoOffset | TField(_,TNoOffset) | TIndex(_,TNoOffset) -> off - | TField(_,off) | TIndex(_,off) -> lastTermOffset off + | GEnumTagDecl (enum, l) -> (* This is a declaration of a tag *) + self#pLineDirective fmt l; + fprintf fmt "enum %a;@\n" self#pVarName enum.ename - let rec addOffset (toadd: offset) (off: offset) : offset = - match off with - NoOffset -> toadd - | Field(fid', offset) -> Field(fid', addOffset toadd offset) - | Index(e, offset) -> Index(e, addOffset toadd offset) + | GCompTag (comp, l) -> (* This is a definition of a tag *) + let n = comp.cname in + let su = + if comp.cstruct then "struct" + else "union" + in + let sto_mod, rest_attr = separateStorageModifiers comp.cattr in + self#pLineDirective ~forcefile:true fmt l; + fprintf fmt "@[<3>%s%a %a {@\n%a@]@\n}%a;@\n" + su + self#pAttrs sto_mod + self#pVarName n + (Pretty_utils.pp_list ~sep:"@\n" self#pFieldDecl) + comp.cfields + self#pAttrs rest_attr - let rec addTermOffset (toadd: term_offset) (off: term_offset) : term_offset = - match off with - TNoOffset -> toadd - | TField(fid', offset) -> TField(fid', addTermOffset toadd offset) - | TIndex(t, offset) -> TIndex(t, addTermOffset toadd offset) + | GCompTagDecl (comp, l) -> (* This is a declaration of a tag *) + self#pLineDirective fmt l; + fprintf fmt "%s;@\n" (compFullName comp) - (* Add an offset at the end of an lv *) - let addOffsetLval toadd (b, off) : lval = - b, addOffset toadd off + | GVar (vi, io, l) -> + self#pLineDirective ~forcefile:true fmt l; + fprintf fmt "%a" + self#pVDecl vi; + (match io.init with + None -> () + | Some i -> + fprintf fmt " = "; + let islong = + match i with + CompoundInit (_, il) when List.length il >= 8 -> true + | _ -> false + in + if islong then + begin self#pLineDirective fmt l; + fprintf fmt " @[@\n" + end; + self#pInit fmt i; + if islong then + fprintf fmt "@]"); + fprintf fmt ";@\n" - let addTermOffsetLval toadd (b, off) : term_lval = - b, addTermOffset toadd off + (* print global variable 'extern' declarations, and function prototypes *) + | GVarDecl (funspec, vi, l) -> + if isFunctionType vi.vtype then self#in_current_function vi; + self#opt_funspec fmt funspec; + if not miscState.printCilAsIs && Builtin_functions.mem vi.vname then + begin + (* Compiler builtins need no prototypes. Just print them in + comments. *) + fprintf fmt "/* compiler builtin: @\n %a; */@\n" + self#pVDecl vi + end else begin + self#pLineDirective fmt l; + fprintf fmt "%a;@\n" self#pVDecl vi + end; + if isFunctionType vi.vtype then self#out_current_function - let rec removeOffset (off: offset) : offset * offset = - match off with - NoOffset -> NoOffset, NoOffset - | Field(_f, NoOffset) -> NoOffset, off - | Index(_i, NoOffset) -> NoOffset, off - | Field(f, restoff) -> - let off', last = removeOffset restoff in - Field(f, off'), last - | Index(i, restoff) -> - let off', last = removeOffset restoff in - Index(i, off'), last - let removeOffsetLval ((b, off): lval) : lval * offset = - let off', last = removeOffset off in - (b, off'), last + | GAsm (s, l) -> + self#pLineDirective fmt l; + fprintf fmt "__asm__(\"%s\");@\n" (Escape.escape_string s) + | GPragma (Attr(an, args), l) -> + (* sm: suppress printing pragmas that gcc does not understand *) + (* assume anything starting with "ccured" is ours *) + (* also don't print the 'combiner' pragma *) + (* nor 'cilnoremove' *) + let suppress = + not miscState.print_CIL_Input && + not theMachine.msvcMode && + ((startsWith "box" an) || + (startsWith "ccured" an) || + (an = "merger") || + (an = "cilnoremove")) + in + self#pLineDirective fmt l; + if suppress then fprintf fmt "/* "; + fprintf fmt "#pragma "; + begin + match an, args with + | _, [] -> + fprintf fmt "%s" an + | "weak", [ACons (varinfo, [])] -> + fprintf fmt "weak %s" varinfo + | "",_ -> + fprintf fmt "%a" + (Pretty_utils.pp_list ~sep:" " self#pAttrParam) args + | _ -> + fprintf fmt "%s(%a)" + an + (Pretty_utils.pp_list ~sep:"," self#pAttrParam) args -(*** Define the visiting engine ****) -(* visit all the nodes in a Cil expression *) -let doVisit (vis: 'visitor) - only_copy_vis - (previsit: 'a -> 'a) - (startvisit: 'a -> 'a visitAction) - (children: 'visitor -> 'a -> 'a) - (node: 'a) : 'a = - let node' = previsit node in - let action = startvisit node' in - match action with - SkipChildren -> node' - | ChangeTo node' -> node' - | ChangeToPost (node',f) -> f node' - | DoChildren | JustCopy | ChangeDoChildrenPost _ | JustCopyPost _ -> - let nodepre = match action with - ChangeDoChildrenPost (node', _) -> node' - | _ -> node' - in - let vis = match action with - JustCopy | JustCopyPost _ -> only_copy_vis - | _ -> vis - in - let nodepost = children vis nodepre in - match action with - ChangeDoChildrenPost (_, f) | JustCopyPost f -> f nodepost - | _ -> nodepost + end; + if suppress then fprintf fmt " */@\n" else fprintf fmt "@\n" - let doVisitCil vis previsit startvisit children node = - doVisit vis vis#plain_copy_visitor previsit startvisit children node + | GPragma (AttrAnnot _, _) -> + assert false + (* self#pLineDirective fmt l; + fprintf fmt "/* #pragma %s */@\n" a*) - let rev_until i l = - let rec aux acc = - function - [] -> acc - | i'::_ when i' == i -> acc - | i'::l -> aux (i'::acc) l - in aux [] l + | GAnnot (decl,l) -> + (*if logic_printer_enabled then*) + begin + self#pLineDirective fmt l; + fprintf fmt "/*@@@ %a@ */@\n" + self#pAnnotation decl + end - (* mapNoCopy is like map but avoid copying the list if the function does not - * change the elements. *) - let mapNoCopy (f: 'a -> 'a) orig = - let rec aux ((acc,has_changed) as res) l = - match l with - [] -> if has_changed then List.rev acc else orig - | i :: resti -> - let i' = f i in - if has_changed then - aux (i'::acc,true) resti - else if i' != i then - aux (i'::rev_until i orig,true) resti - else - aux res resti - in aux ([],false) orig + | GText s -> + if s <> "//" then + fprintf fmt "%s@\n" s + + method pFieldDecl fmt fi = + fprintf fmt "%a %s%a;" + (self#pType + (Some (fun fmt -> if fi.fname <> missingFieldName then fprintf fmt "%s" fi.fname))) + fi.ftype + (match fi.fbitfield with + | None -> "" + | Some i -> ": " ^ string_of_int i ^ " ") + self#pAttrs fi.fattr - let mapNoCopyList (f: 'a -> 'a list) orig = - let rec aux ((acc,has_changed) as res) l = - match l with - [] -> if has_changed then List.rev acc else orig - | i :: resti -> - let l' = f i in - if has_changed then - aux (List.rev_append l' acc,true) resti - else - (match l' with - [i'] when i' == i -> aux res resti - | _ -> aux (List.rev_append l' (rev_until i orig), true) resti) - in aux ([],false) orig -(* A visitor for lists *) -let doVisitList (vis: 'visit) - only_copy_vis - (previsit: 'a -> 'a) - (startvisit: 'a -> 'a list visitAction) - (children: 'visit -> 'a -> 'a) - (node: 'a) : 'a list = - let node' = previsit node in - let action = startvisit node' in - match action with - SkipChildren -> [node'] - | ChangeTo nodes' -> nodes' - | ChangeToPost (nodes',f) -> f nodes' - | _ -> - let nodespre = match action with - ChangeDoChildrenPost (nodespre, _) -> nodespre - | _ -> [node'] - in - let vis = match action with - JustCopy | JustCopyPost _ -> only_copy_vis - | _ -> vis - in - let nodespost = mapNoCopy (children vis) nodespre in - match action with - ChangeDoChildrenPost (_, f) | JustCopyPost f -> f nodespost - | _ -> nodespost + method private opt_funspec fmt funspec = + if logic_printer_enabled && not (is_empty_funspec funspec) then + fprintf fmt "/*@[@@ %a@]*/@\n" self#pSpec funspec - let doVisitListCil vis previsit startvisit children node = - doVisitList vis vis#plain_copy_visitor previsit startvisit children node + method private pFunDecl fmt f = + (* declaration. *) + fprintf fmt "%a%a@\n@[{" self#opt_funspec f.sspec self#pVDecl f.svar ; + (* We take care of locals in blocks. *) + (*List.iter (fprintf fmt "@\n%a;" self#pVDecl) f.slocals ;*) + (* body. *) + currentFormals <- f.sformals ; + self#pBlock ~forcenewline:true fmt f.sbody ; + currentFormals <- [] ; + fprintf fmt "@]@\n}@." - let optMapNoCopy f o = - match o with - None -> o - | Some x -> - let x' = f x in if x' != x then Some x' else o + (***** PRINTING DECLARATIONS and TYPES ****) - let opt_bind f = - function - None -> None - | Some x as o -> - match f x with - None -> None - | Some x' as o' -> if x != x' then o else o' + method pType ?fundecl nameOpt + fmt (t:typ) = + let pname fmt space = match nameOpt with + | None -> () + | Some d -> Format.fprintf fmt "%s%t" (if space then " " else "") d + in + let printAttributes fmt (a: attributes) = + match nameOpt with + | None when not miscState.print_CIL_Input && not theMachine.msvcMode -> + (* Cannot print the attributes in this case because gcc does not + * like them here, except if we are printing for CIL, or for MSVC. + * In fact, for MSVC we MUST print attributes such as __stdcall *) + (* if pa = nil then nil else + text "/*" ++ pa ++ text "*/"*) () + | _ -> self#pAttrs fmt a + in + match t with + TVoid a -> + fprintf fmt "void%a%a" + self#pAttrs a + pname true - let doVisitOption (vis: #cilVisitor as 'visit) - (previsit: 'a -> 'a) - (startvisit: 'a -> 'a option visitAction) - (children: 'visit -> 'a -> 'a) - (node: 'a) : 'a option = - let node' = previsit node in - let action = startvisit node' in - match action with - SkipChildren -> Some node' - | ChangeTo node' -> node' - | ChangeToPost (node',f) -> f node' - | _ -> - let nodepre = match action with - ChangeDoChildrenPost(nodepre,_) -> nodepre - | _ -> Some node' - in let vis = match action with - JustCopy | JustCopyPost _ -> vis#plain_copy_visitor - | _ -> vis - in let nodepost = optMapNoCopy (children vis) nodepre in - match action with - ChangeDoChildrenPost(_,f) | JustCopyPost f -> f nodepost - | _ -> nodepost + | TInt (ikind,a) -> + fprintf fmt "%a%a%a" + d_ikind ikind + self#pAttrs a + pname true - let debugVisit = false + | TFloat(fkind, a) -> + fprintf fmt "%a%a%a" + d_fkind fkind + self#pAttrs a + pname true -let rec visitCilTerm vis t = - let oldloc = CurrentLoc.get () in - CurrentLoc.set t.term_loc; - let res = doVisitCil vis (fun x-> x) vis#vterm childrenTerm t in - CurrentLoc.set oldloc; res + | TComp (comp, _, a) -> (* A reference to a struct *) + fprintf fmt + "%s %a%a%a" + (if comp.cstruct then "struct" else "union") + self#pVarName comp.cname + self#pAttrs a + pname true -and childrenTerm vis t = - let tn' = visitCilTermNode vis t.term_node in - let tt' = visitCilLogicType vis t.term_type in - if tn' != t.term_node || tt' != t.term_type then - { t with term_node = tn'; term_type = tt' } - else t -and visitCilTermNode vis tn = - doVisitCil vis (fun x -> x) vis#vterm_node childrenTermNode tn -and childrenTermNode vis tn = - let vTerm t = visitCilTerm vis t in - let vTermLval tl = visitCilTermLval vis tl in - let vTyp t = visitCilType vis t in - let vLogicInfo li = visitCilLogicInfoUse vis li in - match tn with - | TConst _ -> tn (*enum constants are visited at their declaration site*) - | TDataCons (ci,args) -> - let ci' = - doVisitCil vis (fun x -> x) vis#vlogic_ctor_info_use (fun _ x -> x) ci - in - let args' = mapNoCopy vTerm args in - if ci' != ci || args != args' then TDataCons(ci',args') else tn - | TLval tl -> - let tl' = vTermLval tl in - if tl' != tl then TLval tl' else tn - | TSizeOf t -> - let t' = vTyp t in if t' != t then TSizeOf t' else tn - | TSizeOfE t -> - let t' = vTerm t in if t' != t then TSizeOfE t' else tn - | TSizeOfStr _ -> tn - | TAlignOf t -> - let t' = vTyp t in if t' != t then TAlignOf t' else tn - | TAlignOfE t -> - let t' = vTerm t in if t' != t then TAlignOfE t' else tn - | TUnOp (op,t) -> - let t' = vTerm t in if t' != t then TUnOp (op,t') else tn - | TBinOp(op,t1,t2) -> - let t1' = vTerm t1 in - let t2' = vTerm t2 in - if t1' != t1 || t2' != t2 then TBinOp(op,t1',t2') else tn - | TCastE(ty,te) -> - let ty' = vTyp ty in - let te' = vTerm te in - if ty' != ty || te' != te then TCastE(ty',te') else tn - | TAddrOf tl -> - let tl' = vTermLval tl in - if tl' != tl then TAddrOf tl' else tn - | TStartOf tl -> - let tl' = vTermLval tl in - if tl' != tl then TStartOf tl' else tn - | Tapp(li,labels,args) -> - let li' = vLogicInfo li in -(* - Format.eprintf "Cil.children_term_node: li = %s(%d), li' = %s(%d)@." - li.l_var_info.lv_name li.l_var_info.lv_id - li'.l_var_info.lv_name li'.l_var_info.lv_id; -*) - let args' = mapNoCopy vTerm args in - if li' != li || args' != args then Tapp(li',labels,args') else tn - | Tif(test,ttrue,tfalse) -> - let test' = vTerm test in - let ttrue' = vTerm ttrue in - let tfalse' = vTerm tfalse in - if test' != test || ttrue' != ttrue || tfalse' != tfalse then - Tif(test',ttrue',tfalse') - else tn - | Told t -> - let t' = vTerm t in if t' != t then Told t' else tn - | Tat(t,s) -> - let t' = vTerm t in - let s' = visitCilLogicLabel vis s in - if t' != t || s' != s then Tat (t',s') else tn - | Tbase_addr t -> - let t' = vTerm t in if t' != t then Tbase_addr t' else tn - | Tblock_length t -> - let t' = vTerm t in if t' != t then Tblock_length t' else tn - | Tnull -> tn - | TCoerce(te,ty) -> - let ty' = vTyp ty in - let te' = vTerm te in - if ty' != ty || te' != te then TCoerce(te',ty') else tn - | TCoerceE(te,tc) -> - let tc' = vTerm tc in - let te' = vTerm te in - if tc' != tc || te' != te then TCoerceE(te',tc') else tn - | TUpdate (tc,toff,te) -> - let tc' = vTerm tc in - let te' = vTerm te in - let toff' = visitCilTermOffset vis toff in - if tc' != tc || (te' != te || toff' != toff) - then TUpdate(tc',toff',te') else tn - | Tlambda(prms,te) -> - let prms' = visitCilQuantifiers vis prms in - let te' = vTerm te in - if prms' != prms || te' != te then Tlambda(prms',te') else tn - | Ttypeof t -> - let t' = vTerm t in if t' != t then Ttypeof t' else tn - | Ttype ty -> - let ty' = vTyp ty in if ty' != ty then Ttype ty' else tn - | Tunion locs -> - let locs' = mapNoCopy (visitCilTerm vis) locs in - if locs != locs' then Tunion(locs') else tn - | Tinter locs -> - let locs' = mapNoCopy (visitCilTerm vis) locs in - if locs != locs' then Tinter(locs') else tn - | Tcomprehension(lval,quant,pred) -> - let quant' = visitCilQuantifiers vis quant in - let lval' = visitCilTerm vis lval in - let pred' = (optMapNoCopy (visitCilPredicateNamed vis)) pred in - if lval' != lval || quant' != quant || pred' != pred - then - Tcomprehension(lval',quant',pred') - else - tn - | Tempty_set -> tn - | Trange(low,high) -> - let low' = optMapNoCopy (visitCilTerm vis) low in - let high' = optMapNoCopy (visitCilTerm vis) high in - if low != low' || high != high' then Trange(low',high') - else tn - | Tlet(def,body) -> - let def'= visitCilLogicInfo vis def in - let body' = visitCilTerm vis body in - if def != def' || body != body' then - Tlet(def',body') else tn + | TEnum (enum, a) -> + fprintf fmt "enum %a%a%a" + self#pVarName enum.ename + self#pAttrs a + pname true + + | TPtr (bt, a) -> + (* Parenthesize the ( * attr name) if a pointer to a function or an + * array. However, on MSVC the __stdcall modifier must appear right + * before the pointer constructor "(__stdcall *f)". We push them into + * the parenthesis. *) + let (paren: (formatter -> unit) option), (bt': typ) = + match bt with + TFun(rt, args, isva, fa) when theMachine.msvcMode -> + let an, af', at = partitionAttributes ~default:AttrType fa in + (* We take the af' and we put them into the parentheses *) + Some + (fun fmt -> + fprintf fmt + "(%a" + printAttributes af'), + TFun(rt, args, isva, addAttributes an at) - and visitCilLogicLabel vis l = - match l with - StmtLabel s -> s := vis#behavior.get_stmt !s; l - | LogicLabel _ -> l + | TFun _ | TArray _ -> (Some (fun fmt -> fprintf fmt "(")), bt - and visitCilTermLval vis tl = - doVisitCil vis (fun x -> x) vis#vterm_lval childrenTermLval tl + | _ -> None, bt + in + let name' = fun fmt -> + fprintf fmt "*%a%a" + printAttributes a + pname (a <> []) + in + let name'' = + fun fmt -> + (* Put the parenthesis *) + match paren with + Some p -> fprintf fmt "%t%t)" p name' + | _ -> fprintf fmt "%t" name' + in + self#pType + (Some name'') + fmt + bt' - and childrenTermLval vis ((tlv,toff) as tl)= - let tlv' = visitCilTermLhost vis tlv in - let toff' = visitCilTermOffset vis toff in - if tlv' != tlv || toff' != toff then (tlv',toff') else tl + | TArray (elemt, lo, _, a) -> + (* ignore the const attribute for arrays *) + let a' = dropAttributes [ "const" ] a in + let name' fmt = + if a' = [] then pname fmt false + else if nameOpt = None then + printAttributes fmt a' + else + fprintf fmt "(%a%a)" + printAttributes a' + pname (a' <> []) + in + self#pType + (Some (fun fmt -> + fprintf fmt "%t[%t]" + name' + (fun fmt -> + match lo with + | None -> () + | Some e -> self#pExp fmt e) + )) + fmt + elemt - and visitCilTermLhost vis tl = - doVisitCil vis (fun x -> x) vis#vterm_lhost childrenTermLhost tl + | TFun (restyp, args, isvararg, a) -> + let name' fmt = + if a = [] then pname fmt false else + if nameOpt = None then + printAttributes fmt a + else + fprintf fmt "(%a%a)" + printAttributes a + pname (a <> []) + in + let module Args(A:sig type t + val args: t list option + val pp_args: Format.formatter -> t -> unit + end)= + struct + let pp_prms fmt = + fprintf fmt "%t(@[%t@])" name' + (fun fmt -> + match A.args with + | None -> () + | Some [] when isvararg -> + fprintf fmt "..." + | Some [] -> fprintf fmt "void" + | Some args -> + Pretty_utils.pp_list ~sep:",@ " A.pp_args + fmt args ; + if isvararg then fprintf fmt "@ , ..."; + ) + end + in + let pp_prms = + match fundecl with + | None -> + let module Args = + Args(struct + type t = (string * typ * attributes) + let args = args + let pp_args fmt (aname,atype,aattr) = + let stom, rest = separateStorageModifiers aattr in + (* First the storage modifiers *) + fprintf fmt + "%a%a%a" + self#pAttrs stom + (self#pType + (Some (fun fmt -> fprintf fmt "%s" aname))) atype + self#pAttrs rest + end) + in Args.pp_prms + | Some fundecl -> + let module Args = + Args(struct + type t = varinfo + let args = + (try Some (getFormalsDecl fundecl) + with Not_found -> None) + let pp_args = self#pVDecl + end) + in Args.pp_prms + in + self#pType (Some pp_prms) fmt restyp + | TNamed (t, a) -> + fprintf fmt "%a%a%a" + self#pVarName t.tname + self#pAttrs a + pname true - and childrenTermLhost vis tl = match tl with - TVar v -> - let v' = visitCilLogicVarUse vis v in if v' != v then TVar v' else tl - | TResult ty -> - let ty' = visitCilType vis ty in if ty' != ty then TResult ty' else tl - | TMem t -> - let t' = visitCilTerm vis t in if t' != t then TMem t' else tl + | TBuiltin_va_list a -> + fprintf fmt "__builtin_va_list%a%a" + self#pAttrs a + pname true - and visitCilTermOffset vis toff = - doVisitCil vis (fun x -> x) - vis#vterm_offset childrenTermOffset toff - and childrenTermOffset vis toff = - let vOffset o = visitCilTermOffset vis o in - let vTerm t = visitCilTerm vis t in - match toff with - TNoOffset -> toff - | TField (fi, t) -> - let t' = vOffset t in - let fi' = vis#behavior.get_fieldinfo fi in - if t' != t || fi != fi' then TField(fi',t') else toff - | TIndex(t,o) -> - let t' = vTerm t in let o' = vOffset o in - if t' != t || o' != o then TIndex(t',o') else toff + (**** PRINTING ATTRIBUTES *********) + method pAttrs fmt (a: attributes) = + self#pAttrsGen false fmt a - and visitCilLogicInfoUse vis li = - (* First, visit the underlying varinfo to fill the copy tables if needed. *) - let new_v = visitCilLogicVarUse vis li.l_var_info in - let new_li = - doVisitCil vis vis#behavior.get_logic_info - vis#vlogic_info_use (fun _ x -> x) li - in - new_li.l_var_info <- new_v; - new_li - and visitCilLogicInfo vis li = - (* visit first the underlying varinfo. This will fill internal tables - of copy behavior if needed. - *) - let new_v = visitCilLogicVarDecl vis li.l_var_info in - let res = - doVisitCil - vis vis#behavior.memo_logic_info - vis#vlogic_info_decl childrenLogicInfo li - in res.l_var_info <- new_v; res + (* Print one attribute. Return also an indication whether this attribute + * should be printed inside the __attribute__ list *) + method pAttr fmt = function + Attr(an, args) -> + (* Recognize and take care of some known cases *) + (match an, args with + "const", [] -> fprintf fmt "const"; false + (* Put the aconst inside the attribute list *) + | "aconst", [] when not theMachine.msvcMode -> + fprintf fmt "__const__"; true + | "thread", [] when not theMachine.msvcMode -> + fprintf fmt "__thread"; false + (* + | "used", [] when not !msvcMode -> text "__attribute_used__", false + *) + | "volatile", [] -> fprintf fmt "volatile"; false + | "restrict", [] -> fprintf fmt "__restrict"; false + | "missingproto", [] -> fprintf fmt "/* missing proto */"; false + | "cdecl", [] when theMachine.msvcMode -> fprintf fmt "__cdecl"; false + | "stdcall", [] when theMachine.msvcMode -> + fprintf fmt "__stdcall"; false + | "fastcall", [] when theMachine.msvcMode -> fprintf fmt "__fastcall"; false + | "declspec", args when theMachine.msvcMode -> + fprintf fmt "__declspec(%a)" + (Pretty_utils.pp_list ~sep:"" self#pAttrParam) args; + false + | "w64", [] when theMachine.msvcMode -> fprintf fmt "__w64"; false + | "asm", args -> + fprintf fmt "__asm__(%a)" + (Pretty_utils.pp_list ~sep:"" self#pAttrParam) args; + false + (* we suppress printing mode(__si__) because it triggers an *) + (* internal compiler error in all current gcc versions *) + (* sm: I've now encountered a problem with mode(__hi__)... *) + (* I don't know what's going on, but let's try disabling all "mode"..*) + | "mode", [ACons(tag,[])] -> + fprintf fmt "/* mode(%s) */" tag; + false - and childrenLogicInfo vis li = - (* NB: underlying varinfo has been already visited. *) - let lt = optMapNoCopy (visitCilLogicType vis) li.l_type in - let lp = mapNoCopy (visitCilLogicVarDecl vis) li.l_profile in - li.l_type <- lt; - li.l_profile <- lp; - li.l_body <- - begin - match li.l_body with - | LBnone -> li.l_body - | LBreads ol -> - let l = mapNoCopy (visitCilIdLocations vis) ol in - if l != ol then LBreads l else li.l_body - | LBterm ot -> - let t = visitCilTerm vis ot in - if t != ot then LBterm t else li.l_body - | LBinductive inddef -> - let i = - mapNoCopy - (fun (id,labs,tvars,p) -> - (id, labs, tvars, visitCilPredicateNamed vis p)) - inddef - in - if i != inddef then LBinductive i else li.l_body - | LBpred odef -> - let def = visitCilPredicateNamed vis odef in - if def != odef then LBpred def else li.l_body - end; - li + (* sm: also suppress "format" because we seem to print it in *) + (* a way gcc does not like *) + | "format", _ -> fprintf fmt "/* format attribute */"; + false - and visitCilLogicTypeInfo vis lt = - doVisitCil vis vis#behavior.memo_logic_type_info - vis#vlogic_type_info_decl childrenLogicTypeInfo lt + (* sm: here's another one I don't want to see gcc warnings about.. *) + | "mayPointToStack", _ when not miscState.print_CIL_Input + (* [matth: may be inside another comment.] + -> text "/*mayPointToStack*/", false + *) + -> fprintf fmt ""; false + + | "arraylen", [a] -> + fprintf fmt "/*[%a]*/" self#pAttrParam a; + false + | "static",_ -> fprintf fmt "/* static */"; false + |"", _ -> + (fprintf fmt "%a " + (Pretty_utils.pp_list ~sep:" " self#pAttrParam) args; + true) + | _ -> (* This is the dafault case *) + (* Add underscores to the name *) + let an' = + if theMachine.msvcMode then "__" ^ an else "__" ^ an ^ "__" + in + if args = [] then + (fprintf fmt "%s" an'; + true) + else + (fprintf fmt "%s(%a)" + an' + (Pretty_utils.pp_list ~sep:"," self#pAttrParam) args; + true)) + | AttrAnnot s -> + fprintf fmt "%s" (mkAttrAnnot s); false + + method private pAttrPrec (contextprec: int) fmt (a: attrparam) = + let thisLevel = getParenthLevelAttrParam a in + let needParens = + if thisLevel >= contextprec then + true + else if contextprec == bitwiseLevel then + (* quiet down some GCC warnings *) + thisLevel == additiveLevel || thisLevel == comparativeLevel + else + false + in + if needParens then + fprintf fmt "(%a)" self#pAttrParam a + else + self#pAttrParam fmt a - and childrenLogicTypeInfo vis lt = - let def = optMapNoCopy (visitCilLogicTypeDef vis) lt.lt_def in - lt.lt_def <- def; lt - and visitCilLogicTypeDef vis def = - doVisitCil vis (fun x -> x) vis#vlogic_type_def childrenLogicTypeDef def + method pAttrParam fmt a = + let level = getParenthLevelAttrParam a in + match a with + | AInt n -> fprintf fmt "%d" n + | AStr s -> fprintf fmt "\"%s\"" (Escape.escape_string s) + | ACons(s, []) -> fprintf fmt "%s" s + | ACons(s,al) -> + fprintf fmt "%s(%a)" + s + (Pretty_utils.pp_list ~sep:"" self#pAttrParam) al + | ASizeOfE a -> fprintf fmt "sizeof(%a)" self#pAttrParam a + | ASizeOf t -> fprintf fmt "sizeof(%a)" (self#pType None) t + | ASizeOfS _ts -> fprintf fmt "sizeof()" + | AAlignOfE a -> fprintf fmt "__alignof__(%a)" self#pAttrParam a + | AAlignOf t -> fprintf fmt "__alignof__(%a)" (self#pType None) t + | AAlignOfS _ts -> fprintf fmt "__alignof__()" + | AUnOp(u,a1) -> + fprintf fmt "%a %a" + d_unop u + (self#pAttrPrec level) a1 - and childrenLogicTypeDef vis def = - match def with - | LTsum l -> - let l' = mapNoCopy (visitCilLogicCtorInfoAddTable vis) l in - if l != l' then LTsum l' else def - | LTsyn typ -> - let typ' = visitCilLogicType vis typ in - if typ != typ' then LTsyn typ else def + | ABinOp(b,a1,a2) -> + fprintf fmt "@[(%a)%a@ (%a) @]" + (self#pAttrPrec level) a1 + d_binop b + (self#pAttrPrec level) a2 - and visitCilLogicCtorInfoAddTable vis ctor = - let ctor' = visitCilLogicCtorInfo vis ctor in - if is_copy_behavior vis#behavior then - Queue.add - (fun () -> - Logic_env.add_logic_ctor ctor'.ctor_name ctor') - vis#get_filling_actions; - ctor' + | ADot (ap, s) -> + fprintf fmt "%a.%s" + self#pAttrParam ap + s + | AStar a1 -> + fprintf fmt "(*%a)" + (self#pAttrPrec derefStarLevel) a1 + | AAddrOf a1 -> + fprintf fmt "& %a" (self#pAttrPrec addrOfLevel) a1 + | AIndex (a1, a2) -> + fprintf fmt "%a[%a]" + self#pAttrParam a1 + self#pAttrParam a2 + | AQuestion (a1, a2, a3) -> + fprintf fmt "%a ? %a : %a" + self#pAttrParam a1 + self#pAttrParam a2 + self#pAttrParam a3 - and visitCilLogicCtorInfo vis ctor = - doVisitCil vis (fun x -> x) vis#vlogic_ctor_info_decl childrenLogicCtorInfo ctor - and childrenLogicCtorInfo vis ctor = - let ctor_type = doVisitCil vis vis#behavior.get_logic_type_info - vis#vlogic_type_info_use (fun _ x -> x) ctor.ctor_type - in - let ctor_params = mapNoCopy (visitCilLogicType vis) ctor.ctor_params in - if ctor_type != ctor.ctor_type || ctor_params != ctor.ctor_params then - { ctor with ctor_type = ctor_type; ctor_params = ctor_params } - else ctor + (* A general way of printing lists of attributes *) + method private pAttrsGen (block: bool) fmt (a: attributes) = + (* Scan all the attributes and separate those that must be printed inside + * the __attribute__ list *) + let rec loop (in__attr__: string list) = function + | [] -> + if in__attr__ <> [] then + begin + (* sm: added 'forgcc' calls to not comment things out + * if CIL is the consumer; this is to address a case + * Daniel ran into where blockattribute(nobox) was being + * dropped by the merger + *) + (if block then + fprintf fmt " %s __blockattribute__(" + (forgcc "/*") + else + fprintf fmt " __attribute__(("); + Pretty_utils.pp_list ~sep:",@ " + Format.pp_print_string fmt in__attr__; + fprintf fmt ")%s" + (if block then forgcc "*/" else ")") + end + | x :: rest -> + let buff = Buffer.create 17 in + let local_fmt = formatter_of_buffer buff in + let ina = self#pAttr local_fmt x in + pp_print_flush local_fmt (); + let dx = Buffer.contents buff in + if ina then + loop (dx :: in__attr__) rest + else begin + if dx <> "" then fprintf fmt " %s" dx; + loop in__attr__ rest + end + in + let keep_attr = function + | Attr (s,_) -> not (List.mem s !reserved_attributes) + | AttrAnnot _ -> true + in + loop [] (List.filter keep_attr a); - and visitCilLogicType vis t = - doVisitCil vis (fun x -> x) vis#vlogic_type childrenLogicType t + (* Logic annotations printer *) - and childrenLogicType vis ty = - match ty with - Ctype t -> - let t' = visitCilType vis t in - if t != t' then Ctype t' else ty - | Linteger | Lreal -> ty + method pLogic_type name fmt = + let pname = match name with + | Some d -> (fun fmt -> Format.fprintf fmt "@ %t" d) + | None -> alphaunit + in + function + | Ctype typ -> self#pType name fmt typ + | Linteger -> + let res = + if Kernel.Unicode.get () then Utf8_logic.integer else "integer" + in + Format.fprintf fmt "%s%t" res pname + | Lreal -> + let res = + if Kernel.Unicode.get () then Utf8_logic.real else "real" + in + Format.fprintf fmt "%s%t" res pname + | Ltype ({ lt_name = name},[]) when name = Utf8_logic.boolean-> + let res = + if Kernel.Unicode.get () then Utf8_logic.boolean else "boolean" + in + Format.fprintf fmt "%s%t" res pname | Ltype (s,l) -> - let s' = doVisitCil vis vis#behavior.get_logic_type_info - vis#vlogic_type_info_use (fun _ x -> x) s in - let l' = mapNoCopy (visitCilLogicType vis) l in - if s' != s || l' != l then Ltype (s',l') else ty - | Larrow(args,rttyp) -> - let args' = mapNoCopy(visitCilLogicType vis) args in - let rttyp' = visitCilLogicType vis rttyp in - if args' != args || rttyp' != rttyp then Larrow(args',rttyp') else ty - | Lvar _ -> ty + fprintf fmt "%a%a%t" self#pVarName s.lt_name + (Cilutil.pretty_list_del (fun fmt -> fprintf fmt "<@[") + (fun fmt -> fprintf fmt "@]>@ ") + (* the space avoids the issue of list> where the double > + would be read as a shift. It could be optimized away in most of + the cases. + *) + (Cilutil.space_sep ",") (self#pLogic_type None)) l pname + | Larrow (args,rt) -> + fprintf fmt "@[@[<2>{@ %a@]}@]%a%t" + (Cilutil.pretty_list + (Cilutil.space_sep ",") (self#pLogic_type None)) args + (self#pLogic_type None) rt pname + | Lvar s -> fprintf fmt "%a%t" self#pVarName s pname + + method private pTermPrec contextprec fmt e = + let thisLevel = getParenthLevelLogic e.term_node in + let needParens = + if thisLevel >= contextprec then + true + else if contextprec == bitwiseLevel then + (* quiet down some GCC warnings *) + thisLevel == additiveLevel || thisLevel == comparativeLevel + else + false + in + if needParens then + fprintf fmt "@[(%a)@]" self#pTerm e + else + self#pTerm fmt e + + val mutable is_debug_type_mode = false + initializer + is_debug_type_mode <- false + + method pTerm fmt t = + if (Kernel.debug_atleast 5) && (not is_debug_type_mode) then + begin + is_debug_type_mode <- true ; + fprintf fmt "/*type:%a*/" (self#pLogic_type None) t.term_type; + is_debug_type_mode <- false ; + end ; + match t.term_name with + [] -> self#pTerm_node fmt t + | _ -> + fprintf fmt "(@[%a:@ %a@])" + (Cilutil.pretty_list + (Cilutil.swap fprintf ":@ ") pp_print_string) t.term_name + self#pTerm_node t + + method pTerm_node fmt t = + let current_level = getParenthLevelLogic t.term_node in + match t.term_node with + | TConst s -> fprintf fmt "%a" d_const s + | TDataCons(ci,args) -> + fprintf fmt "%a%a" self#pVarName ci.ctor_name + (Cilutil.pretty_list_del + (Cilutil.swap fprintf "(@[") (Cilutil.swap fprintf "@])") + (Cilutil.space_sep ",") self#pTerm) args + | TLval lv -> fprintf fmt "%a" (self#pTerm_lvalPrec current_level) lv + | TSizeOf t -> fprintf fmt "sizeof(%a)" (self#pType None) t + | TSizeOfE e -> fprintf fmt "sizeof(%a)" self#pTerm e + | TSizeOfStr s -> fprintf fmt "sizeof(%S)" s + | TAlignOf e -> fprintf fmt "alignof(%a)" (self#pType None) e + | TAlignOfE e -> fprintf fmt "alignof(%a)" self#pTerm e + | TUnOp (op,e) -> fprintf fmt "%a%a" + d_unop op (self#pTermPrec current_level) e + | TBinOp (op,l,r) -> + fprintf fmt "%a%a%a" + (self#pTermPrec current_level) l + d_term_binop op + (self#pTermPrec current_level) r + | TCastE (ty,e) -> + fprintf fmt "(%a)%a" (self#pType None) ty + (self#pTermPrec current_level) e + | TAddrOf lv -> fprintf fmt "&%a" (self#pTerm_lvalPrec addrOfLevel) lv + | TStartOf lv -> fprintf fmt "(%a)%a" + (self#pLogic_type None) t.term_type + (self#pTerm_lvalPrec current_level) lv + | Tapp (f, labels, tl) -> fprintf fmt "%a%a%a" + self#pLogic_info_use f + self#pLabels (List.map snd labels) + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@[(") + (fun fmt -> Format.fprintf fmt ")@]") + (Cilutil.space_sep ",") self#pTerm) tl + | Tif (cond,th,el) -> + fprintf fmt "@[<2>%a?@;%a:@;%a@]" + (self#pTermPrec current_level) cond + (self#pTermPrec current_level) th + (self#pTermPrec current_level) el + | Tat (t,StmtLabel sref) -> + let rec pickLabel = function + | [] -> None + | Label (l, _, _) :: _ -> Some l + | _ :: rest -> pickLabel rest + in let l = match pickLabel !sref.labels with + Some l -> l + | None -> Kernel.fatal "Cannot find label for \\at@."; + in + fprintf fmt "@[\\at(@[@[%a@],@,@[%s@]@])@]" self#pTerm t l + | Tat (t,(LogicLabel (_, l) as lab)) -> + if lab = Logic_const.old_label then + fprintf fmt "@[\\old(@[%a@])@]" self#pTerm t + else + fprintf fmt "@[\\at(@[@[%a@],@,@[%s@]@])@]" self#pTerm t l + | Tbase_addr t -> fprintf fmt "\\base_addr(%a)" self#pTerm t + | Tblock_length t -> fprintf fmt "\\block_length(%a)" self#pTerm t + | Tnull -> fprintf fmt "\\null" + | TCoerce (e,ty) -> + fprintf fmt "%a@ :>@ %a" + (self#pTermPrec current_level) e (self#pType None) ty + | TCoerceE (e,ce) -> + fprintf fmt "%a :> %a" + (self#pTermPrec current_level) e (self#pTermPrec current_level) ce + | TUpdate (t,toff,v) -> + fprintf fmt "{%a \\with %a = %a}" + self#pTerm t + self#pTerm_offset toff + self#pTerm v + | Tlambda(prms,expr) -> + fprintf fmt "@[<2>\\lambda@ %a;@ %a@]" + self#pQuantifiers prms (self#pTermPrec current_level) expr + | Ttypeof t -> fprintf fmt "\\typeof(%a)" self#pTerm t + | Ttype ty -> fprintf fmt "\\type(%a)" (self#pType None) ty + | Tunion locs -> + fprintf fmt "@[\\union(@,%a)@]" + (Cilutil.pretty_list (Cilutil.space_sep ",") self#pTerm) locs + | Tinter locs -> + fprintf fmt "@[\\inter(@,%a)@]" + (Cilutil.pretty_list (Cilutil.space_sep ",") self#pTerm) locs + | Tempty_set -> pp_print_string fmt "\\empty" + | Tcomprehension(lv,quant,pred) -> + fprintf fmt "{@[%a@ |@ %a%a@]}" + self#pTerm lv self#pQuantifiers quant + (Cilutil.pretty_opt (fun fmt p -> fprintf fmt ";@ %a" + self#identified_pred p)) + pred + | Trange(low,high) -> + fprintf fmt "@[%a..@,%a@]" + (Cilutil.pretty_opt (self#pTermPrec current_level)) low + (Cilutil.pretty_opt (self#pTermPrec current_level)) high + | Tlet(def,body) -> + assert + (Kernel.verify (def.l_labels = []) + "invalid logic construction: local definition with label"); + assert + (Kernel.verify (def.l_tparams = []) + "invalid logic construction: polymorphic local definition"); + let v = def.l_var_info in + let args = def.l_profile in + let pp_defn = match def.l_body with + | LBterm t -> fun fmt -> self#pTerm fmt t + | LBpred p -> fun fmt -> self#pPredicate_named fmt p + | LBnone + | LBreads _ | LBinductive _ -> fatal "invalid logic local definition" + in + fprintf fmt "@[\\let@ %a@ =@ %t%t;@ %a@]" + self#pLogic_var v + (fun fmt -> if args <> [] then + fprintf fmt "@[<2>\\lambda@ %a;@]@ " self#pQuantifiers args) + pp_defn + (self#pTermPrec current_level) body - and visitCilLogicVarDecl vis lv = - (* keep names in C and logic worlds in sync *) - (match lv.lv_origin with - None -> () - | Some cv -> lv.lv_name <- cv.vname); - doVisitCil vis vis#behavior.memo_logic_var vis#vlogic_var_decl - childrenLogicVarDecl lv + method private pTerm_lvalPrec contextprec fmt lv = + if getParenthLevelLogic (TLval lv) > contextprec then + fprintf fmt "(%a)" self#pTerm_lval lv + else + fprintf fmt "%a" self#pTerm_lval lv - and childrenLogicVarDecl vis lv = - lv.lv_type <- visitCilLogicType vis lv.lv_type; - lv.lv_origin <- - optMapNoCopy (visitCilVarUse vis) lv.lv_origin; - lv + method pTerm_lval fmt lv = match lv with + | TVar vi, o -> fprintf fmt "%a%a" self#pLogic_var vi self#pTerm_offset o + | TResult _, o -> fprintf fmt "\\result%a" self#pTerm_offset o + | TMem e, TField(fi,o) -> + fprintf fmt "%a->%a%a" (self#pTermPrec arrowLevel) e + self#pVarName fi.fname self#pTerm_offset o + | TMem e, TNoOffset -> + fprintf fmt "*%a" (self#pTermPrec derefStarLevel) e + | TMem e, o -> + fprintf fmt "(*%a)%a" + (self#pTermPrec derefStarLevel) e self#pTerm_offset o - and visitCilLogicVarUse vis lv = - if vis#behavior.is_copy_behavior && - Logic_env.is_builtin_logic_function lv.lv_name then begin - (* Do as if the variable has been declared. - We'll fill the logic info table of the new project at the end. - Behavior's logic_var table is filled as a side effect. - *) - let siblings = Logic_env.find_all_logic_functions lv.lv_name in - let siblings' = List.map (visitCilLogicInfo vis) siblings in - (*Format.printf "new vars:@."; - List.iter (fun x -> Format.printf "%s#%d@." x.l_var_info.lv_name x.l_var_info.lv_id) siblings'; - *) - Queue.add - (fun () -> - (* Add them to env only once *) - List.iter - (fun x -> - if not (Logic_env.Logic_builtin_used.mem x) then begin - (* Format.printf - "Adding info for %s#%d@." - x.l_var_info.lv_name x.l_var_info.lv_id; *) - Logic_env.Logic_builtin_used.add x; - Logic_env.Logic_info.add x.l_var_info.lv_name x - end) - siblings') - vis#get_filling_actions; - end; - doVisitCil vis vis#behavior.get_logic_var vis#vlogic_var_use - childrenLogicVarUse lv + method pTerm_offset fmt o = match o with + | TNoOffset -> () + | TField (fi,o) -> + fprintf fmt ".%a%a" self#pVarName fi.fname self#pTerm_offset o + | TIndex(e,o) -> fprintf fmt "[%a]%a" self#pTerm e self#pTerm_offset o - and childrenLogicVarUse vis lv = - lv.lv_origin <- optMapNoCopy (visitCilVarUse vis) lv.lv_origin; lv + method pLogic_info_use fmt li = self#pLogic_var fmt li.l_var_info - and visitCilQuantifiers vis lv = - doVisitCil vis (fun x -> x) vis#vquantifiers - (fun vis l -> mapNoCopy (visitCilLogicVarDecl vis) l) lv + method pLogic_var fmt v = self#pVarName fmt v.lv_name - and visitCilPredicate vis p = - doVisitCil vis (fun x -> x) vis#vpredicate childrenPredicate p + method pQuantifiers fmt l = + Cilutil.pretty_list (Cilutil.space_sep ",") + (fun fmt lv -> + let pvar fmt = self#pLogic_var fmt lv in + self#pLogic_type (Some pvar) fmt lv.lv_type) + fmt l - and visitCilPredicateNamed vis p = - doVisitCil vis - (fun x -> x) vis#vpredicate_named childrenPredicateNamed p - and childrenPredicateNamed vis p = - let content = visitCilPredicate vis p.content in - if content != p.content then { p with content = content} else p + method private pPredPrec fmt (contextprec,p) = + let thisLevel = getParenthLevelPred p in + let needParens = thisLevel >= contextprec in + if needParens then fprintf fmt "@[(%a)@]" self#pPredicate p + else self#pPredicate fmt p - and childrenPredicate vis p = - let vPred p = visitCilPredicateNamed vis p in - let vLogicInfo li = visitCilLogicInfoUse vis li in - let vTerm t = visitCilTerm vis t in - match p with - Pfalse | Ptrue -> p - | Papp (pred,labels,args) -> - let pred' = vLogicInfo pred in - let args' = mapNoCopy vTerm args in - if pred' != pred || args' != args then - Papp(pred',labels,args') - else p - | Prel(rel,t1,t2) -> - let t1' = vTerm t1 in - let t2' = vTerm t2 in - if t1' != t1 || t2' != t2 then - Prel(rel,t1',t2') - else p - | Pand(p1,p2) -> - let p1' = vPred p1 in - let p2' = vPred p2 in - if p1' != p1 || p2' != p2 then - Pand(p1',p2') - else p - | Por(p1,p2) -> - let p1' = vPred p1 in - let p2' = vPred p2 in - if p1' != p1 || p2' != p2 then - Por(p1',p2') - else p - | Pxor(p1,p2) -> - let p1' = vPred p1 in - let p2' = vPred p2 in - if p1' != p1 || p2' != p2 then - Pxor(p1',p2') - else p - | Pimplies(p1,p2) -> - let p1' = vPred p1 in - let p2' = vPred p2 in - if p1' != p1 || p2' != p2 then - Pimplies(p1',p2') - else p - | Piff(p1,p2) -> - let p1' = vPred p1 in - let p2' = vPred p2 in - if p1' != p1 || p2' != p2 then - Piff(p1',p2') - else p - | Pnot p1 -> - let p1' = vPred p1 in - if p1' != p1 then Pnot p1' else p - | Pif(t,ptrue,pfalse) -> - let t' = vTerm t in - let ptrue' = vPred ptrue in - let pfalse' = vPred pfalse in - if t' != t || ptrue' != ptrue || pfalse' != pfalse then - Pif(t', ptrue',pfalse') - else p - | Plet(def,p1) -> - let def' = visitCilLogicInfo vis def in - let p1' = vPred p1 in - if def' != def || p1' != p1 then - Plet(def',p1') - else p - | Pforall(quant,p1) -> - let quant' = visitCilQuantifiers vis quant in - let p1' = vPred p1 in - if quant' != quant || p1' != p1 then - Pforall(quant', p1') - else p - | Pexists(quant,p1) -> - let quant' = visitCilQuantifiers vis quant in - let p1' = vPred p1 in - if quant' != quant || p1' != p1 then - Pexists(quant', p1') - else p - | Pold p1 -> - let p1' = vPred p1 in if p1' != p1 then Pold p1' else p - | Pat(p1,s) -> - let p1' = vPred p1 in - let s' = visitCilLogicLabel vis s in - if p1' != p1 then Pat(p1',s') else p - | Pvalid t -> - let t' = vTerm t in if t' != t then Pvalid t' else p - | Pvalid_index (t1,t2) -> - let t1' = vTerm t1 in - let t2' = vTerm t2 in - if t1' != t1 || t2' != t2 then Pvalid_index (t1',t2') else p - | Pvalid_range(t1,t2,t3) -> - let t1' = vTerm t1 in - let t2' = vTerm t2 in - let t3' = vTerm t3 in - if t1' != t1 || t2' != t2 || t3' != t3 then - Pvalid_range (t1',t2',t3') else p - | Pseparated seps -> - let seps' = mapNoCopy vTerm seps in - if seps' != seps then Pseparated seps' else p - | Pfresh t -> - let t' = vTerm t in if t' != t then Pfresh t' else p - | Psubtype(te,tc) -> - let tc' = vTerm tc in - let te' = vTerm te in - if tc' != tc || te' != te then Psubtype(te',tc') else p + method private named_pred fmt (parenth, names, content) = + match names with + | [] -> self#pPredPrec fmt (parenth,content) + | _ :: _ -> + if parenth = upperLevel then + fprintf fmt "@[%a:@ %a@]" + (Cilutil.pretty_list + (Cilutil.swap fprintf ":@ ") pp_print_string) names + self#pPredPrec (upperLevel,content) + else + fprintf fmt "(@[%a:@ %a@])" + (Cilutil.pretty_list + (Cilutil.swap fprintf ":@ ") pp_print_string) names + self#pPredPrec (upperLevel,content) - and visitCilIdLocations vis loc = - let loc' = visitCilTerm vis loc.it_content in - if loc' != loc.it_content then { loc with it_content = loc' } else loc + method private identified_pred fmt p = + self#named_pred fmt (upperLevel,p.name,p.content) - and visitCilAssigns vis a = - doVisitCil vis (fun x -> x) vis#vassigns childrenAssigns a - and childrenAssigns vis a = - match a with - WritesAny -> a - | Writes l -> - let l' = mapNoCopy (visitCilFrom vis) l in - if l' != l then Writes l' else a + method private pPredPrec_named fmt (parenth,p) = + self#named_pred fmt (parenth,p.name,p.content) -and visitCilFrom vis f = - doVisitCil vis (fun x -> x) vis#vfrom childrenFrom f -and childrenFrom vis ((b,f) as a) = - let b' = visitCilIdLocations vis b in - let f' = visitCilDeps vis f in - if b!=b' || f!=f' then (b',f') else a + method pPredicate_named fmt p = self#named_pred fmt (0,p.name,p.content) -and visitCilDeps vis d = - doVisitCil vis (fun x -> x) vis#vdeps childrenDeps d -and childrenDeps vis d = - match d with - FromAny -> d - | From l -> - let l' = mapNoCopy (visitCilIdLocations vis) l in - if l !=l' then From l' else d + method pIdentified_predicate fmt p = + (*fprintf fmt "@[IP_LOC:%a@\n@]" Extlib.pretty_position (fst p.ip_loc);*) + if verbose then + fprintf fmt "@[//id:%d@\n%a@]" + p.ip_id self#named_pred (upperLevel,p.ip_name,p.ip_content) + else self#named_pred fmt (upperLevel,p.ip_name,p.ip_content) -and visitCilBehavior vis b = - doVisitCil vis vis#behavior.cfunbehavior - vis#vbehavior childrenBehavior b + method private preds kw fmt l = + Cilutil.pretty_list_del ignore Cilutil.nl_sep Cilutil.nl_sep + (fun fmt p -> + fprintf fmt "@[%s @[%a@];@]" kw self#pIdentified_predicate p) fmt l + + method pPredicate fmt p = + let current_level = getParenthLevelPred p in + let term = self#pTermPrec current_level in + match p with + | Pfalse -> fprintf fmt "\\false" + | Ptrue -> fprintf fmt "\\true" + | Papp (p,labels,l) -> fprintf fmt "@[%a%a%a@]" + self#pLogic_info_use p + self#pLabels (List.map snd labels) + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@[(") + (fun fmt -> Format.fprintf fmt ")@]") + (Cilutil.space_sep ",") self#pTerm) l + | Prel (rel,l,r) -> + fprintf fmt "@[@[%a@]@ %a@ @[%a@]@]" term l d_relation rel term r + | Pand (p1, p2) -> + fprintf fmt "@[%a@]@ %a@ @[%a@]" + self#pPredPrec_named (current_level,p1) + d_term_binop LAnd + self#pPredPrec_named (current_level,p2) + | Por (p1, p2) -> + fprintf fmt "@[%a@]@ %a@ @[%a@]" + self#pPredPrec_named (current_level,p1) + d_term_binop LOr + self#pPredPrec_named (current_level,p2) + | Pxor (p1, p2) -> + fprintf fmt "@[%a@]@ %s@ @[%a@]" + self#pPredPrec_named (current_level,p1) + (if Kernel.Unicode.get () then Utf8_logic.x_or else "^^") + self#pPredPrec_named (current_level,p2) + | Pimplies (p1,p2) -> + fprintf fmt "@[%a@]@ %s@ @[%a@]" + self#pPredPrec_named (current_level,p1) + (if Kernel.Unicode.get () then Utf8_logic.implies else "==>") + self#pPredPrec_named (current_level,p2) + | Piff (p1,p2) -> + fprintf fmt "@[%a@]@ %s@ @[%a@]" + self#pPredPrec_named (current_level,p1) + (if Kernel.Unicode.get () then Utf8_logic.iff else "<==>") + self#pPredPrec_named (current_level,p2) + | Pnot a -> fprintf fmt "@[%s@[%a@]@]" + (if Kernel.Unicode.get () then Utf8_logic.neg else "!") + self#pPredPrec_named (current_level,a) + | Pif (e, p1, p2) -> + fprintf fmt "@[<2>%a?@ %a:@ %a@]" + term e + self#pPredPrec_named (current_level, p1) + self#pPredPrec_named (current_level, p2) + | Plet (def, p) -> + assert + (Kernel.verify (def.l_labels = []) + "invalid logic construction: local definition with label"); + assert + (Kernel.verify (def.l_tparams = []) + "invalid logic construction: polymorphic local definition"); + let v = def.l_var_info in + let args = def.l_profile in + let pp_defn = match def.l_body with + | LBterm t -> fun fmt -> self#pTerm fmt t + | LBpred p -> fun fmt -> self#pPredPrec_named fmt (current_level,p) + | LBnone + | LBreads _ | LBinductive _ -> fatal "invalid logic local definition" + in + fprintf fmt "@[\\let@ %a@ =@ %t%t;@ %a@]" + self#pLogic_var v + (fun fmt -> + if args <> [] then + fprintf fmt "@[<2>\\lambda@ %a;@]@ " self#pQuantifiers args) + pp_defn + self#pPredPrec_named (current_level,p) + | Pforall (quant,pred) -> + fprintf fmt "@[%s %a;@]@ %a" + (if Kernel.Unicode.get () then Utf8_logic.forall else "\\forall") + self#pQuantifiers quant self#pPredPrec_named (current_level,pred) + | Pexists (quant,pred) -> + fprintf fmt "@[%s %a;@]@ %a" + (if Kernel.Unicode.get () then Utf8_logic.exists else "\\exists") + self#pQuantifiers quant self#pPredPrec_named (current_level,pred) + | Pvalid p -> fprintf fmt "@[\\valid(@[%a@])@]" self#pTerm p + | Pinitialized p -> fprintf fmt "@[\\initialized(@[%a@])@]" self#pTerm p + | Pseparated seps -> + fprintf fmt "@[<2>\\separated(@,%a@,)@]" + (Cilutil.pretty_list (Cilutil.space_sep ",") self#pTerm) seps + | Pat (p,StmtLabel sref) -> + let rec pickLabel = function + | [] -> fatal "Cannot find label for \\at@." + | Label (l, _, _) :: _ -> l + | _ :: rest -> pickLabel rest + in + let l = pickLabel !sref.labels in + fprintf fmt "@[\\at(@[@[%a@],@,@[%s@]@])@]" + self#pPredPrec_named (upperLevel, p) l + | Pat(p,(LogicLabel (_, s) as lab)) -> + if lab = Logic_const.old_label then + fprintf fmt "@[\\old(@[%a@])@]" + self#pPredPrec_named (upperLevel,p) + else + fprintf fmt "@[\\at(@[@[%a@],@,%s@])@]" + self#pPredPrec_named (upperLevel,p) s + | Pfresh e -> fprintf fmt "@[\\fresh(@[%a@])@]" self#pTerm e + | Pvalid_index (e1,e2) -> + fprintf fmt "@[\\valid_index(@[@[%a@],@,@[%a@]@])@]" + self#pTerm e1 self#pTerm e2 + | Pvalid_range (e1,e2,e3) -> + fprintf fmt "@[\\valid_range(@[@[%a@],@,@[%a@],@,@[%a@]@])@]" + self#pTerm e1 self#pTerm e2 self#pTerm e3 + | Psubtype (e,ce) -> + fprintf fmt "%a <: %a" term e term ce -and childrenBehavior vis b = - b.b_assumes <- visitCilPredicates vis b.b_assumes; - b.b_requires <- visitCilPredicates vis b.b_requires; - b.b_post_cond <- - mapNoCopy - (function ((k,p) as pc) -> - let p' = visitCilIdPredicate vis p in if p != p' then (k,p') else pc) - b.b_post_cond; - b.b_assigns <- visitCilAssigns vis b.b_assigns; - b.b_extended <- mapNoCopy - (fun (s,id,p as orig) -> - let r = mapNoCopy (visitCilIdPredicate vis) p in - if r == p then orig - else (s,id,r)) - b.b_extended; - b + method private pDecrement kw fmt (t, rel) = + match rel with + None -> fprintf fmt "@[<2>%s@ %a;@]" kw self#pTerm t + | Some str -> + (*TODO: replace this string with an interpreted variable*) + fprintf fmt "@[<2>%s@ %a@ for@ %s;@]" kw self#pTerm t str - and visitCilPredicates vis ps = mapNoCopy (visitCilIdPredicate vis) ps + method pDecreases fmt v = self#pDecrement "decreases" fmt v - and visitCilIdPredicate vis ps = - let p' = visitCilPredicate vis ps.ip_content in - if p' != ps.ip_content then { ps with ip_content = p' } else ps + method pLoop_variant fmt v = self#pDecrement "loop variant" fmt v - and visitCilBehaviors vis bs = mapNoCopy (visitCilBehavior vis) bs + method pAssumes fmt p = + fprintf fmt "@[<2>assumes @[%a@];@]" self#pIdentified_predicate p - and visitCilFunspec vis s = - doVisitCil vis vis#behavior.cfunspec vis#vspec childrenSpec s + method pPost_cond fmt (k,p) = + let kw = get_termination_kind_name k in + fprintf fmt "@[<2>%s @[%a@];@]" kw self#pIdentified_predicate p - and childrenSpec vis s = - s.spec_behavior <- visitCilBehaviors vis s.spec_behavior; - s.spec_variant <- - optMapNoCopy (fun x -> (visitCilTerm vis (fst x), snd x)) s.spec_variant; - s.spec_terminates <- - optMapNoCopy (visitCilIdPredicate vis) s.spec_terminates; - (* nothing is done now for behaviors names, no need to visit complete and - disjoint behaviors clauses - *) - s + method pBehavior fmt b = + if not (is_default_behavior b) + then begin + self#set_current_behavior b; + fprintf fmt "behavior %s:@\n @[%a%a%a%a@]" + b.b_name + (Cilutil.pretty_list_del ignore Cilutil.nl_sep Cilutil.nl_sep + self#pAssumes) + b.b_assumes + (Cilutil.pretty_list_del ignore Cilutil.nl_sep Cilutil.nl_sep + self#pRequires) + b.b_requires + (Cilutil.pretty_list_del ignore Cilutil.nl_sep Cilutil.nl_sep + self#pPost_cond) + b.b_post_cond + (self#pAssignsDeps "assigns") b.b_assigns; + self#reset_current_behavior () + end - and visitCilSlicePragma vis p = - doVisitCil vis (fun x -> x) vis#vslice_pragma childrenSlicePragma p + method pRequires fmt p = + fprintf fmt "@[<2>requires @[%a@];@]" + self#pIdentified_predicate p - and childrenSlicePragma vis p = - match p with - | SPexpr t -> - let t' = visitCilTerm vis t in if t' != t then SPexpr t' else p - | SPctrl | SPstmt -> p + method pTerminates fmt p = + fprintf fmt "@[<2>terminates @[%a@];@]" + self#pIdentified_predicate p - and visitCilImpactPragma vis p = - doVisitCil vis (fun x -> x) vis#vimpact_pragma childrenImpactPragma p + method pComplete_behaviors fmt p = + fprintf fmt "@[<2>complete behaviors @[%a@];@]" + (Cilutil.pretty_list_del + ignore + ignore + (Cilutil.space_sep ",") + pp_print_string) + p - and childrenImpactPragma vis p = match p with - | IPexpr t -> let t' = visitCilTerm vis t in if t' != t then IPexpr t' else p - | IPstmt -> p + method pDisjoint_behaviors fmt p = + fprintf fmt "@[<2>disjoint behaviors @[%a@];@]" + (Cilutil.pretty_list_del + ignore + ignore + (Cilutil.space_sep ",") + pp_print_string) + p - and visitCilLoopPragma vis p = - doVisitCil vis - (fun x -> x) vis#vloop_pragma childrenLoopPragma p + method pSpec fmt ({ spec_behavior = behaviors; + spec_variant = variant; + spec_terminates = terminates; + spec_complete_behaviors = complete; + spec_disjoint_behaviors = disjoint; + } as spec) = + let default,default_requires,default_assigns,default_post_cond = + match find_default_behavior spec with + | (Some b) as db -> db, b.b_requires,b.b_assigns,b.b_post_cond + | None -> None,[],WritesAny,[] + in + let behaviors = + List.filter (fun b -> not (is_default_behavior b)) behaviors + in + let pretty_maybe_nl needs f fmt x = + if needs then Cilutil.nl_sep fmt; + f fmt x + in + fprintf fmt "@["; + let non_empty_default = + match default with + | None -> false + | Some b -> + self#set_current_behavior b; + let terminates_needs_nl = + default_requires <> [] && terminates <> None + in + let non_empty_prefix = + default_requires <> [] || terminates <> None + in + let variant_needs_nl = non_empty_prefix && variant <> None in + let non_empty_prefix = non_empty_prefix || variant <> None in + let post_cond_needs_nl = + non_empty_prefix && default_post_cond <> [] + in + let non_empty_prefix = non_empty_prefix || default_post_cond <> [] in + let assigns_needs_nl = + non_empty_prefix && default_assigns<>WritesAny + in + let non_empty_prefix = + non_empty_prefix || default_assigns<>WritesAny + in + fprintf fmt "%a%a%a%a%a" + (Cilutil.pretty_list Cilutil.nl_sep self#pRequires) + default_requires + (Cilutil.pretty_opt + (pretty_maybe_nl terminates_needs_nl self#pTerminates)) + terminates + (Cilutil.pretty_opt + (pretty_maybe_nl variant_needs_nl self#pDecreases)) variant + (Cilutil.pretty_list Cilutil.nl_sep + (pretty_maybe_nl post_cond_needs_nl self#pPost_cond)) + default_post_cond + (pretty_maybe_nl assigns_needs_nl (self#pAssignsDeps "assigns")) + default_assigns; + self#reset_current_behavior (); + non_empty_prefix + in + let behaviors_needs_nl = non_empty_default && behaviors <> [] in + let non_empty_prefix = non_empty_default || behaviors <> [] in + let complete_needs_nl = non_empty_prefix && complete <> [] in + let non_empty_prefix = non_empty_prefix || complete <> [] in + let disjoint_needs_nl = non_empty_prefix && disjoint <> [] in + fprintf fmt "%a%a%a@]" + (pretty_maybe_nl behaviors_needs_nl + (Cilutil.pretty_list Cilutil.nl_sep self#pBehavior)) + behaviors + (pretty_maybe_nl complete_needs_nl + (Cilutil.pretty_list Cilutil.nl_sep self#pComplete_behaviors)) + complete + (pretty_maybe_nl disjoint_needs_nl + (Cilutil.pretty_list Cilutil.nl_sep self#pDisjoint_behaviors)) + disjoint - and childrenLoopPragma vis p = - match p with - | Unroll_level t -> let t' = visitCilTerm vis t in - if t' != t then Unroll_level t' else p - | Widen_hints lt -> let lt' = List.map (visitCilTerm vis) lt in - if lt' != lt then Widen_hints lt' else p - | Widen_variables lt -> let lt' = List.map (visitCilTerm vis) lt in - if lt' != lt then Widen_variables lt' else p + method pAssigns kw fmt a = + match a with + | WritesAny -> () + | Writes [] -> fprintf fmt "@[%s \\nothing;@]" kw + | Writes l -> + let without_result = + List.filter + (function (a,_) -> + not (Logic_const.is_result a.it_content || + Logic_const.is_exit_status a.it_content)) + l + in + Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "%s@ " kw) + (fun fmt -> fprintf fmt ";") + (Cilutil.space_sep ",") + (fun fmt (x,_) -> self#pTerm fmt x.it_content) + fmt without_result - and visitCilAnnotation vis a = - let oldloc = CurrentLoc.get () in - CurrentLoc.set (Global_annotation.loc a); - let res = doVisitCil vis (fun x -> x) vis#vannotation childrenAnnotation a in - CurrentLoc.set oldloc; - res + method private pAssignsDeps kw fmt a = + self#pAssigns kw fmt a; + match a with + WritesAny | Writes [] -> () + | Writes [(b,_ as a)] when Logic_const.is_result b.it_content -> + (* in this case, pAssigns does not write anything. *) + self#pFrom kw fmt a + | Writes l -> + Cilutil.pretty_list + ignore + (fun fmt f -> fprintf fmt "@\n%a" (self#pFrom kw) f) + fmt + (List.filter (fun (_,f) -> f <> FromAny) l) - and visitCilAxiom vis ((id,p) as a) = - let p' = visitCilPredicateNamed vis p in - if p' != p then (id,p') else a + method pFrom kw fmt (base,deps) = + match deps with + FromAny -> () + | From [] -> + fprintf fmt "%s@ %a@ \\from \\nothing;" kw + self#pTerm base.it_content + | From l -> + fprintf fmt "%s@ %a@ @[<2>\\from %a@];" + kw self#pTerm base.it_content + (Cilutil.pretty_list (Cilutil.space_sep ",") + (fun fmt x -> self#pTerm fmt x.it_content)) l - and childrenAnnotation vis a = - match a with - | Dfun_or_pred (li,loc) -> - let li' = visitCilLogicInfo vis li in - if vis#behavior.is_copy_behavior then - Queue.add - (fun () -> - Logic_env.add_logic_function_gen (fun _ _ -> false) li') - vis#get_filling_actions; - if li' != li then Dfun_or_pred (li',loc) else a - | Dtype (ti,loc) -> - let ti' = visitCilLogicTypeInfo vis ti in - if vis#behavior.is_copy_behavior then - Queue.add - (fun () -> - Logic_env.add_logic_type ti'.lt_name ti') - vis#get_filling_actions; - if ti' != ti then Dtype (ti',loc) else a - | Dlemma(s,is_axiom,labels,tvars,p,loc) -> - let p' = visitCilPredicateNamed vis p in - if p' != p then Dlemma(s,is_axiom,labels,tvars,p',loc) else a - | Dinvariant (p,loc) -> - let p' = visitCilLogicInfo vis p in - if vis#behavior.is_copy_behavior then - Queue.add - (fun () -> Logic_env.add_logic_function_gen (fun _ _ -> false) p') - vis#get_filling_actions; - if p' != p then Dinvariant (p',loc) else a - | Dtype_annot (ta,loc) -> - let ta' = visitCilLogicInfo vis ta in - if vis#behavior.is_copy_behavior then - Queue.add - (fun () -> Logic_env.add_logic_function_gen (fun _ _ -> false) ta') - vis#get_filling_actions; - if ta' != ta then Dtype_annot (ta',loc) else a - | Daxiomatic(id,l,loc) -> - (* - Format.eprintf "cil.visitCilAnnotation on axiomatic %s@." id; - *) - let l' = mapNoCopy (visitCilAnnotation vis) l in - if l' != l then Daxiomatic(id,l',loc) else a + method private pLoop_pragma fmt = function + | Widen_hints terms -> fprintf fmt "WIDEN_HINTS @[%a@]" + (Cilutil.pretty_list_del + alphaunit alphaunit + (Cilutil.space_sep ",") self#pTerm) terms + | Widen_variables terms -> fprintf fmt "WIDEN_VARIABLES @[%a@]" + (Cilutil.pretty_list_del + alphaunit alphaunit + (Cilutil.space_sep ",") self#pTerm) terms + | Unroll_level t -> fprintf fmt "UNROLL @[%a@]" self#pTerm t - and visitCilCodeAnnotation vis ca = - doVisitCil vis (fun x -> x) vis#vcode_annot childrenCodeAnnot ca + method private pSlice_pragma fmt = function + SPexpr t -> + fprintf fmt "expr @[%a@]" self#pTerm t + | SPctrl -> pp_print_string fmt "ctrl" + | SPstmt -> pp_print_string fmt "stmt" - and childrenCodeAnnot vis ca = - let vPred p = visitCilPredicateNamed vis p in - let vTerm t = visitCilTerm vis t in - let vSpec s = visitCilFunspec vis s in - let change_content annot = { ca with annot_content = annot } in - match ca.annot_content with - AAssert (behav,p) -> - let p' = vPred p in if p' != p then - change_content (AAssert (behav,p')) - else ca - | APragma (Impact_pragma t) -> - let t' = visitCilImpactPragma vis t in - if t' != t then change_content (APragma (Impact_pragma t')) else ca - | APragma (Slice_pragma t) -> - let t' = visitCilSlicePragma vis t in - if t' != t then change_content (APragma (Slice_pragma t')) else ca - | APragma (Loop_pragma p) -> - let p' = visitCilLoopPragma vis p in - if p' != p then change_content (APragma (Loop_pragma p')) else ca - | AStmtSpec s -> - let s' = vSpec s in - if s' != s then change_content (AStmtSpec s') else ca - | AInvariant(behav,f,p) -> - let p' = vPred p in - if p' != p then change_content (AInvariant (behav,f,p')) else ca - | AVariant ((t,s)) -> - let t' = vTerm t in - if t != t' then change_content (AVariant ((t',s))) else ca - | AAssigns(behav, a) -> - let a' = visitCilAssigns vis a in - if a != a' then change_content (AAssigns (behav,a')) else ca - (* - | ALoopBehavior(behav,p,a) -> - let p' = mapNoCopy vPred p in - let a' = mapNoCopy (visitCilAssigns vis) a in - if p' != p || a' != a then - change_content (ALoopBehavior(behav,p',a')) else ca - *) + method private pImpact_pragma fmt = function + | IPexpr t -> fprintf fmt "expr @[%a@]" self#pTerm t + | IPstmt -> pp_print_string fmt "stmt" -and visitCilExpr (vis: cilVisitor) (e: exp) : exp = - let oldLoc = CurrentLoc.get () in - CurrentLoc.set e.eloc; - let res = doVisitCil vis (fun x -> x) vis#vexpr childrenExp e in - CurrentLoc.set oldLoc; res + (* TODO: add the annot ID in debug mode?*) + method pCode_annot fmt ca = + match ca.annot_content with + | AAssert (behav,p) -> + fprintf fmt "@[%aassert@ %a;@]" + (Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") + (Cilutil.space_sep ",") pp_print_string) + behav + self#identified_pred p + | APragma (Slice_pragma sp) -> + fprintf fmt "@[slice pragma@ %a;@]" self#pSlice_pragma sp + | APragma (Impact_pragma sp) -> + fprintf fmt "@[impact pragma@ %a;@]" self#pImpact_pragma sp + | APragma (Loop_pragma lp) -> + fprintf fmt "@[loop pragma@ %a;@]" self#pLoop_pragma lp + | AStmtSpec (behav,sp) -> + fprintf fmt "@[<2>%a%a@]" + (Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") + (Cilutil.space_sep ",") pp_print_string) + behav + self#pSpec sp + | AAssigns(behav,a) -> + fprintf fmt "@[<2>%a%a@]" + (Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") + (Cilutil.space_sep ",") pp_print_string) + behav + (self#pAssignsDeps "loop assigns") a + | AInvariant(behav,true, i) -> + fprintf fmt "@[<2>%aloop invariant@ %a;@]" + (Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") + (Cilutil.space_sep ",") pp_print_string) + behav + self#identified_pred i + | AInvariant(behav,false,i) -> fprintf fmt "@[<2>%ainvariant@ %a;@]" + (Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "for ") (fun fmt -> fprintf fmt ": ") + (Cilutil.space_sep ",") pp_print_string) + behav + self#identified_pred i + | AVariant v -> self#pLoop_variant fmt v -and childrenExp (vis: cilVisitor) (e: exp) : exp = - let vExp e = visitCilExpr vis e in - let vTyp t = visitCilType vis t in - let vLval lv = visitCilLval vis lv in - let new_exp e' = { e with enode = e' } in - match (stripInfo e).enode with - | Info _ -> assert false - | Const (CEnum ei) -> (* In case of deep copy, we must change the enumitem*) - let ei' = vis#behavior.get_enumitem ei in - if ei' != ei then new_exp (Const(CEnum ei')) else e - | Const _ -> e - | SizeOf t -> - let t'= vTyp t in - if t' != t then new_exp (SizeOf t') else e - | SizeOfE e1 -> - let e1' = vExp e1 in - if e1' != e1 then new_exp (SizeOfE e1') else e - | SizeOfStr _s -> e + method private pLoopInv fmt p = + fprintf fmt "@[<2>loop invariant@ %a;@]" + self#identified_pred p - | AlignOf t -> - let t' = vTyp t in - if t' != t then new_exp (AlignOf t') else e - | AlignOfE e1 -> - let e1' = vExp e1 in - if e1' != e1 then new_exp (AlignOfE e1') else e - | Lval lv -> - let lv' = vLval lv in - if lv' != lv then new_exp (Lval lv') else e - | UnOp (uo, e1, t) -> - let e1' = vExp e1 in let t' = vTyp t in - if e1' != e1 || t' != t then new_exp (UnOp(uo, e1', t')) else e - | BinOp (bo, e1, e2, t) -> - let e1' = vExp e1 in let e2' = vExp e2 in let t' = vTyp t in - if e1' != e1 || e2' != e2 || t' != t then - new_exp (BinOp(bo, e1',e2',t')) - else e - | CastE (t, e1) -> - let t' = vTyp t in let e1' = vExp e1 in - if t' != t || e1' != e1 then new_exp (CastE(t', e1')) else e - | AddrOf lv -> - let lv' = vLval lv in - if lv' != lv then new_exp (AddrOf lv') else e - | StartOf lv -> - let lv' = vLval lv in - if lv' != lv then new_exp (StartOf lv') else e + method private pLogicPrms fmt arg = + let pvar fmt = self#pLogic_var fmt arg in + self#pLogic_type (Some pvar) fmt arg.lv_type - and visitCilInit (vis: cilVisitor) (forglob: varinfo) - (atoff: offset) (i: init) : init = - let rec childrenInit (vis: cilVisitor) (i: init) : init = - let fExp e = visitCilExpr vis e in - let fTyp t = visitCilType vis t in - match i with - | SingleInit e -> - let e' = fExp e in - if e' != e then SingleInit e' else i - | CompoundInit (t, initl) -> - let t' = fTyp t in - (* Collect the new initializer list, in reverse. We prefer two - * traversals to ensure tail-recursion. *) - let newinitl : (offset * init) list ref = ref [] in - (* Keep track whether the list has changed *) - let hasChanged = ref false in - let doOneInit ((o, i) as oi) = - let o' = visitCilInitOffset vis o in (* use initializer version *) - let i' = visitCilInit vis forglob (addOffset o' atoff) i in - let newio = - if o' != o || i' != i then - begin hasChanged := true; (o', i') end else oi - in - newinitl := newio :: !newinitl - in - List.iter doOneInit initl; - let initl' = if !hasChanged then List.rev !newinitl else initl in - if t' != t || initl' != initl then CompoundInit (t', initl') else i - in - doVisitCil vis (fun x -> x) (vis#vinit forglob atoff) childrenInit i + method private pTypeKernel fmt tvars = + Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "<@[") (fun fmt -> fprintf fmt "@]>") + (Cilutil.space_sep ",") pp_print_string fmt tvars - and visitCilLval (vis: cilVisitor) (lv: lval) : lval = - doVisitCil vis (fun x -> x) vis#vlval childrenLval lv - and childrenLval (vis: cilVisitor) (lv: lval) : lval = - (* and visit its subexpressions *) - let vExp e = visitCilExpr vis e in - let vOff off = visitCilOffset vis off in - match lv with - Var v, off -> - let v'= visitCilVarUse vis v in - let off' = vOff off in - if v' != v || off' != off then Var v', off' else lv - | Mem e, off -> - let e' = vExp e in - let off' = vOff off in - if e' != e || off' != off then Mem e', off' else lv + method private pLogicLabel fmt lab = + let s = + match lab with + | LogicLabel (_, s) -> s + | StmtLabel sref -> + let rec pickLabel = function + [] -> None + | Label (l, _, _) :: _ -> Some l + | _ :: rest -> pickLabel rest + in + match pickLabel !sref.labels with + Some l -> l + | None -> "__invalid_label" + in pp_print_string fmt s - and visitCilOffset (vis: cilVisitor) (off: offset) : offset = - doVisitCil vis (fun x -> x) vis#voffs childrenOffset off - and childrenOffset (vis: cilVisitor) (off: offset) : offset = - let vOff off = visitCilOffset vis off in - match off with - Field (f, o) -> - let o' = vOff o in - let f' = vis#behavior.get_fieldinfo f in - if o' != o || f' != f then Field (f', o') else off - | Index (e, o) -> - let e' = visitCilExpr vis e in - let o' = vOff o in - if e' != e || o' != o then Index (e', o') else off - | NoOffset -> off + method private pLabels fmt labels = + Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "{@[") (fun fmt -> fprintf fmt "@]}") + (Cilutil.space_sep ",") self#pLogicLabel fmt labels - (* sm: for offsets in initializers, the 'startvisit' will be the - * vinitoffs method, but we can re-use the childrenOffset from - * above since recursive offsets are visited by voffs. (this point - * is moot according to cil.mli which claims the offsets in - * initializers will never recursively contain offsets) - *) - and visitCilInitOffset (vis: cilVisitor) (off: offset) : offset = - doVisitCil vis (fun x -> x) vis#vinitoffs childrenOffset off + method pAnnotation fmt = function + | Dtype_annot (a,_) -> + fprintf fmt "@[type invariant @[%a%a=@ %a@,;@]@]@\n" + self#pLogic_var a.l_var_info + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@[(") + (fun fmt -> Format.fprintf fmt ")@]@ ") + (Cilutil.space_sep ",") self#pLogicPrms) a.l_profile + self#identified_pred (pred_body a.l_body) + | Dmodel_annot (mfi,_) -> + begin + match mfi.l_profile,mfi.l_type with + | [v],Some t -> + fprintf fmt "@[model %a { %a %s }@]@\n" + (self#pLogic_type None) v.lv_type + (self#pLogic_type None) t + mfi.l_var_info.lv_name + | _ -> assert false + end + | Dinvariant (pred,_) -> + fprintf fmt "@[global@ invariant %a:@[@ %a;@]@]@\n" + self#pLogic_var pred.l_var_info + self#identified_pred (pred_body pred.l_body) + | Dlemma(name, is_axiom, labels, tvars, pred,_) -> + fprintf fmt "@[%s@ %a%a%a:@[@ %a;@]@]@\n" + (if is_axiom then "axiom" else "lemma") + self#pVarName name + self#pLabels labels + self#pTypeKernel tvars + self#identified_pred pred + | Dtype (ti,_) -> + fprintf fmt "@[type@ %a%a%a;@]@\n" + self#pVarName ti.lt_name self#pTypeKernel ti.lt_params + (Cilutil.pretty_opt + (fun fmt d -> fprintf fmt "@ =@ @[%a@]" self#pLogic_type_def d)) + ti.lt_def + | Dfun_or_pred (li,_) -> + begin + match li.l_type with + | Some rt -> + fprintf fmt "@[logic %a" + (self#pLogic_type None) rt + | None -> + (match li.l_body with + LBinductive _ -> fprintf fmt "@[inductive" + | _ -> fprintf fmt "@[predicate") + end; + fprintf fmt " %a%a%a%a" + self#pLogic_var li.l_var_info + self#pLabels li.l_labels + self#pTypeKernel li.l_tparams + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@[(") + (fun fmt -> Format.fprintf fmt ")@]@ ") + (Cilutil.space_sep ",") self#pLogicPrms) li.l_profile; + begin + match li.l_body with + | LBnone -> + fprintf fmt ";" + | LBreads reads -> + fprintf fmt "%a;" + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@\n@[reads@ ") + (fun fmt -> Format.fprintf fmt "@]") + (Cilutil.space_sep ",") + (fun fmt x -> self#pTerm fmt x.it_content)) reads + | LBpred def -> + fprintf fmt "=@ %a;" + self#identified_pred def + | LBinductive indcases -> + fprintf fmt "{@ %a}" + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@[") + (fun fmt -> Format.fprintf fmt "@]@\n") + Cilutil.nl_sep + (fun fmt (id,labels,tvars,p) -> + Format.fprintf fmt "case %s%a%a: @[%a@];" id + self#pLabels labels + self#pTypeKernel tvars + self#identified_pred p)) indcases + | LBterm def -> + fprintf fmt "=@ %a;" + self#pTerm def + end; + fprintf fmt "@]@\n" + | Dvolatile(tsets,rvi_opt,wvi_opt,_) -> + let pp_vol txt fmt = function + | None -> () ; + | Some vi -> fprintf fmt "@ %s %a" txt self#pVar vi + in + fprintf fmt "@[volatile@ %a%a%a;@]" + (Cilutil.pretty_list (Cilutil.space_sep ",") + (fun fmt x -> self#pTerm fmt x.it_content)) tsets + (pp_vol "reads") rvi_opt + (pp_vol "writes") wvi_opt ; + | Daxiomatic(id,decls,_) -> + (* + Format.eprintf "cil.pAnnotation on axiomatic %s@." id; + *) + fprintf fmt "@[axiomatic@ %s {@\n%a}@]@\n" id + (Cilutil.pretty_list_del + (fun fmt -> Format.fprintf fmt "@[") + (fun fmt -> Format.fprintf fmt "@]@\n") + Cilutil.nl_sep + self#pAnnotation) + decls - and visitCilInstr (vis: cilVisitor) (i: instr) : instr list = - let oldloc = CurrentLoc.get () in - CurrentLoc.set (Cil_datatype.Instr.loc i); - assertEmptyQueue vis; - let res = - doVisitListCil vis (fun x -> x) vis#vinst childrenInstr i in - CurrentLoc.set oldloc; - (* See if we have accumulated some instructions *) - vis#unqueueInstr () @ res + method pLogic_type_def fmt = function + | LTsum l -> + Cilutil.pretty_list (fun fmt -> fprintf fmt "@ |@ ") + (fun fmt info -> + fprintf fmt "%s@[%a@]" info.ctor_name + (Cilutil.pretty_list_del + (fun fmt -> fprintf fmt "@[(") + (fun fmt -> fprintf fmt ")@]") + (Cilutil.space_sep ",") + (self#pLogic_type None)) info.ctor_params) fmt l + | LTsyn typ -> self#pLogic_type None fmt typ - and childrenInstr (vis: cilVisitor) (i: instr) : instr = - let fExp = visitCilExpr vis in - let fLval = visitCilLval vis in - match i with - | Skip _l -> - i - | Set(lv,e,l) -> - let lv' = fLval lv in let e' = fExp e in - if lv' != lv || e' != e then Set(lv',e',l) else i - | Call(None,f,args,l) -> - let f' = fExp f in let args' = mapNoCopy fExp args in - if f' != f || args' != args then Call(None,f',args',l) else i - | Call(Some lv,fn,args,l) -> - let lv' = fLval lv in let fn' = fExp fn in - let args' = mapNoCopy fExp args in - if lv' != lv || fn' != fn || args' != args - then Call(Some lv', fn', args', l) else i + end (* class defaultCilPrinterClass *) - | Asm(sl,isvol,outs,ins,clobs,l) -> - let outs' = mapNoCopy (fun ((id,s,lv) as pair) -> - let lv' = fLval lv in - if lv' != lv then (id,s,lv') else pair) outs in - let ins' = mapNoCopy (fun ((id,s,e) as pair) -> - let e' = fExp e in - if e' != e then (id,s,e') else pair) ins in - if outs' != outs || ins' != ins then - Asm(sl,isvol,outs',ins',clobs,l) else i - | Code_annot (a,l) -> - let a' = visitCilCodeAnnotation vis a in Code_annot(a',l) + let defaultCilPrinter = new defaultCilPrinterClass + (* Top-level printing functions *) + let printType (pp: cilPrinter) fmt (t: typ) = + pp#pType None fmt t - (* visit all nodes in a Cil statement tree in preorder *) - and visitCilStmt (vis:cilVisitor) (s: stmt) : stmt = - let oldloc = CurrentLoc.get () in - CurrentLoc.set (Stmt.loc s) ; - vis#push_stmt s; (*(vis#behavior.memo_stmt s);*) - assertEmptyQueue vis; - let toPrepend : instr list ref = ref [] in (* childrenStmt may add to this *) - let res = - doVisitCil vis - vis#behavior.memo_stmt vis#vstmt (childrenStmt toPrepend) s in - (* Now see if we have saved some instructions *) - toPrepend := !toPrepend @ vis#unqueueInstr (); - (match !toPrepend with - [] -> () (* Return the same statement *) - | _ -> - (* Make our statement contain the instructions to prepend *) - res.skind <- - Block (mkBlock - ((List.map (fun i -> mkStmt (Instr i)) !toPrepend) @ - [ mkStmt res.skind ] ))); - CurrentLoc.set oldloc; - vis#pop_stmt s; - res + let printExp (pp: cilPrinter) fmt (e: exp) = + pp#pExp fmt e - and childrenStmt (toPrepend: instr list ref) (vis:cilVisitor) (s:stmt): stmt = - let fExp e = (visitCilExpr vis e) in - let fBlock b = visitCilBlock vis b in - let fInst i = visitCilInstr vis i in - let fLoopAnnot a = mapNoCopy (visitCilCodeAnnotation vis) a in - (* Just change the statement kind *) - let skind' = - match s.skind with - Break _ | Continue _ | Return (None, _) -> s.skind - | UnspecifiedSequence seq -> - let seq' = - mapNoCopy - (function (stmt,modified,writes,reads,calls) as orig-> - let stmt' = visitCilStmt vis stmt in - (* might make sense for the default to be - to just copy the varinfo when using the copy visitor, - and not apply vvrbl, i.e. not using vis but generic_visitor ? - *) - let modified' = mapNoCopy (visitCilLval vis) modified in - let writes' = mapNoCopy (visitCilLval vis) writes in - let reads' = mapNoCopy (visitCilLval vis) reads in - let calls' = - if vis#behavior.is_copy_behavior then - (* we need new references anyway, no need for mapNoCopy *) - List.map (fun x -> ref (vis#behavior.memo_stmt !x)) calls - else calls - in - if stmt' != stmt || writes' != writes || reads' != reads || - modified != modified' || calls' != calls - then - (stmt',modified', writes',reads',calls') - else orig) - seq - in - if seq' != seq then UnspecifiedSequence seq' else s.skind - | Goto (sr,l) -> - if vis#behavior.is_copy_behavior then - Goto(ref (vis#behavior.memo_stmt !sr),l) - else s.skind - | Return (Some e, l) -> - let e' = fExp e in - if e' != e then Return (Some e', l) else s.skind - | Loop (a, b, l, s1, s2) -> - let a' = fLoopAnnot a in - let b' = fBlock b in - if a' != a || b' != b then Loop (a', b', l, s1, s2) else s.skind - | If(e, s1, s2, l) -> - let e' = fExp e in - (*if e queued any instructions, pop them here and remember them so that - they are inserted before the If stmt, not in the then block. *) - toPrepend := vis#unqueueInstr (); - let s1'= fBlock s1 in let s2'= fBlock s2 in - (* the stmts in the blocks should have cleaned up after themselves.*) - assertEmptyQueue vis; - if e' != e || s1' != s1 || s2' != s2 then - If(e', s1', s2', l) else s.skind - | Switch (e, b, stmts, l) -> - let e' = fExp e in - toPrepend := vis#unqueueInstr (); (* insert these before the switch *) - let b' = fBlock b in - (* the stmts in b should have cleaned up after themselves.*) - assertEmptyQueue vis; - let stmts' = mapNoCopy (visitCilStmt vis#plain_copy_visitor) stmts in - if e' != e || b' != b || stmts' != stmts then - Switch (e', b', stmts', l) else s.skind - | Instr i -> - begin match fInst i with - | [i'] when i' == i -> s.skind - | il -> stmt_of_instr_list ~loc:(Cil_datatype.Instr.loc i) il - end - | Block b -> - let b' = fBlock b in - if b' != b then Block b' else s.skind - | TryFinally (b, h, l) -> - let b' = fBlock b in - let h' = fBlock h in - if b' != b || h' != h then TryFinally(b', h', l) else s.skind - | TryExcept (b, (il, e), h, l) -> - let b' = fBlock b in - assertEmptyQueue vis; - (* visit the instructions *) - let il' = mapNoCopyList fInst il in - (* Visit the expression *) - let e' = fExp e in - let il'' = - let more = vis#unqueueInstr () in - if more != [] then - il' @ more - else - il' - in - let h' = fBlock h in - (* Now collect the instructions *) - if b' != b || il'' != il || e' != e || h' != h then - TryExcept(b', (il'', e'), h', l) - else s.skind - in - if skind' != s.skind then s.skind <- skind'; - (* Visit the labels *) - let labels' = - let fLabel = function - Case (e, l) as lb -> - let e' = fExp e in - if e' != e then Case (e', l) else lb - | lb -> lb - in - mapNoCopy fLabel s.labels - in - if labels' != s.labels then s.labels <- labels'; - s + let printVar (pp:#cilPrinter) fmt v = pp#pVar fmt v + let printLval (pp: cilPrinter) fmt (lv: lval) = + pp#pLval fmt lv + let printGlobal (pp: cilPrinter) fmt (g: global) = + pp#pGlobal fmt g - and visitCilBlock (vis: cilVisitor) (b: block) : block = - doVisitCil vis vis#behavior.cblock vis#vblock childrenBlock b - and childrenBlock (vis: cilVisitor) (b: block) : block = - let fStmt s = visitCilStmt vis s in - let locals' = mapNoCopy (vis#behavior.get_varinfo) b.blocals in - let stmts' = mapNoCopy fStmt b.bstmts in - if stmts' != b.bstmts then - { battrs = b.battrs; bstmts = stmts'; blocals = locals' } - else b + let printAttr (pp: cilPrinter) fmt (a: attribute) = + ignore (pp#pAttr fmt a) + let printAttrs (pp: cilPrinter) fmt (a: attributes) = + pp#pAttrs fmt a - and visitCilType (vis : cilVisitor) (t : typ) : typ = - doVisitCil vis (fun x -> x) vis#vtype childrenType t - and childrenType (vis : cilVisitor) (t : typ) : typ = - (* look for types referred to inside t's definition *) - let fTyp t = visitCilType vis t in - let fAttr a = visitCilAttributes vis a in - match t with - TPtr(t1, a) -> - let t1' = fTyp t1 in - let a' = fAttr a in - if t1' != t1 || a' != a then TPtr(t1', a') else t - | TArray(t1, None, _, a) -> - let t1' = fTyp t1 in - let a' = fAttr a in - if t1' != t1 || a' != a then TArray(t1', None, empty_size_cache (), a') else t - | TArray(t1, Some e, _, a) -> - let t1' = fTyp t1 in - let e' = visitCilExpr vis e in - let a' = fAttr a in - if t1' != t1 || e' != e || a' != a then TArray(t1', Some e',empty_size_cache (), a') else t + let printInstr (pp: cilPrinter) fmt (i: instr) = + pp#pInstr fmt i - (* DON'T recurse into the compinfo, this is done in visitCilGlobal. - User can iterate over cinfo.cfields manually, if desired.*) - | TComp(cinfo, _, a) -> - let cinfo' = vis#behavior.get_compinfo cinfo in - let a' = fAttr a in - if a != a' || cinfo' != cinfo then TComp(cinfo',empty_size_cache (), a') else t + let printStmt (pp: cilPrinter) fmt (s: stmt) = + pp#pStmt fmt s - | TFun(rettype, args, isva, a) -> - let rettype' = fTyp rettype in - (* iterate over formals, as variable declarations *) - let argslist = argsToList args in - let visitArg ((an,at,aa) as arg) = - let at' = fTyp at in - let aa' = fAttr aa in - if at' != at || aa' != aa then (an,at',aa') else arg - in - let argslist' = mapNoCopy visitArg argslist in - let a' = fAttr a in - if rettype' != rettype || argslist' != argslist || a' != a then - let args' = if argslist' == argslist then args else Some argslist' in - TFun(rettype', args', isva, a') else t + let printBlock (pp: cilPrinter) fmt (b: block) = + (* NB: eta expansion needed because of optional args of pBlock. *) + fprintf fmt "@[%a@]" (fun fmt -> pp#pBlock ~nobrace:false fmt) b - | TNamed(t1, a) -> - let a' = fAttr a in - let t1' = vis#behavior.get_typeinfo t1 in - if a' != a || t1' != t1 then TNamed (t1', a') else t - | TEnum(enum,a) -> - let a' = fAttr a in - let enum' = vis#behavior.get_enuminfo enum in - if a' != a || enum' != enum then TEnum(enum',a') else t - | TVoid _ | TInt _ | TFloat _ | TBuiltin_va_list _ -> - (* no nested type. visit only the attributes. *) - let a = typeAttrs t in - let a' = fAttr a in - if a' != a then setTypeAttrs t a' else t + let printInit (pp: cilPrinter) fmt (i: init) = + pp#pInit fmt i - (* for declarations, we visit the types inside; but for uses, *) - (* we just visit the varinfo node *) - and visitCilVarDecl (vis : cilVisitor) (v : varinfo) : varinfo = - let oldloc = CurrentLoc.get () in - CurrentLoc.set v.vdecl; - let res = - doVisitCil vis vis#behavior.memo_varinfo - vis#vvdec childrenVarDecl v - in CurrentLoc.set oldloc; res + let printTerm_lval pp fmt lv = pp#pTerm_lval fmt lv - and childrenVarDecl (vis : cilVisitor) (v : varinfo) : varinfo = - v.vtype <- visitCilType vis v.vtype; - v.vattr <- visitCilAttributes vis v.vattr; - v.vlogic_var_assoc <- - optMapNoCopy (visitCilLogicVarDecl vis) v.vlogic_var_assoc; - v + let printLogic_var pp fmt lv = pp#pLogic_var fmt lv - and visitCilVarUse vis v = - doVisitCil vis vis#behavior.get_varinfo vis#vvrbl (fun _ x -> x) v + let printLogic_type pp fmt lv = pp#pLogic_type None fmt lv - and visitCilAttributes (vis: cilVisitor) (al: attribute list) : attribute list= - let al' = - mapNoCopyList - (doVisitListCil vis - (fun x -> x) vis#vattr childrenAttribute) al in - if al' != al then - (* Must re-sort *) - addAttributes al' [] - else - al - and childrenAttribute (vis: cilVisitor) (a: attribute) : attribute = - let fAttrP a = visitCilAttrParams vis a in - match a with - | Attr (n, args) -> - let args' = mapNoCopy fAttrP args in - if args' != args then Attr(n, args') else a - | AttrAnnot _ -> - a + let printTerm pp fmt t = pp#pTerm fmt t - and visitCilAttrParams (vis: cilVisitor) (a: attrparam) : attrparam = - doVisitCil vis (fun x -> x) vis#vattrparam childrenAttrparam a - and childrenAttrparam (vis: cilVisitor) (aa: attrparam) : attrparam = - let fTyp t = visitCilType vis t in - let fAttrP a = visitCilAttrParams vis a in - match aa with - AInt _ | AStr _ -> aa - | ACons(n, args) -> - let args' = mapNoCopy fAttrP args in - if args' != args then ACons(n, args') else aa - | ASizeOf t -> - let t' = fTyp t in - if t' != t then ASizeOf t' else aa - | ASizeOfE e -> - let e' = fAttrP e in - if e' != e then ASizeOfE e' else aa - | AAlignOf t -> - let t' = fTyp t in - if t' != t then AAlignOf t' else aa - | AAlignOfE e -> - let e' = fAttrP e in - if e' != e then AAlignOfE e' else aa - | ASizeOfS _ | AAlignOfS _ -> - warning "Visitor inside of a type signature." ; - aa - | AUnOp (uo, e1) -> - let e1' = fAttrP e1 in - if e1' != e1 then AUnOp (uo, e1') else aa - | ABinOp (bo, e1, e2) -> - let e1' = fAttrP e1 in - let e2' = fAttrP e2 in - if e1' != e1 || e2' != e2 then ABinOp (bo, e1', e2') else aa - | ADot (ap, s) -> - let ap' = fAttrP ap in - if ap' != ap then ADot (ap', s) else aa - | AStar ap -> - let ap' = fAttrP ap in - if ap' != ap then AStar ap' else aa - | AAddrOf ap -> - let ap' = fAttrP ap in - if ap' != ap then AAddrOf ap' else aa - | AIndex (e1, e2) -> - let e1' = fAttrP e1 in - let e2' = fAttrP e2 in - if e1' != e1 || e2' != e2 then AIndex (e1', e2') else aa - | AQuestion (e1, e2, e3) -> - let e1' = fAttrP e1 in - let e2' = fAttrP e2 in - let e3' = fAttrP e3 in - if e1' != e1 || e2' != e2 || e3' != e3 - then AQuestion (e1', e2', e3') else aa + let printTerm_offset pp fmt o = pp#pTerm_offset fmt o + let printPredicate_named pp fmt p = pp#pPredicate_named fmt p + let printIdentified_predicate pp fmt p = pp#pIdentified_predicate fmt p - let rec fix_succs_preds_block b block = - List.iter (fix_succs_preds b) block.bstmts - and fix_succs_preds b stmt = - stmt.succs <- mapNoCopy b.get_stmt stmt.succs; - stmt.preds <- mapNoCopy b.get_stmt stmt.preds; - match stmt.skind with - If(_,bthen,belse,_) -> - fix_succs_preds_block b bthen; - fix_succs_preds_block b belse - | Switch(e,cases,stmts,l) -> - fix_succs_preds_block b cases; - stmt.skind <- Switch(e,cases,List.map b.get_stmt stmts,l) - | Loop(annot,block,loc,stmt1,stmt2) -> - fix_succs_preds_block b block; - let stmt1' = optMapNoCopy b.get_stmt stmt1 in - let stmt2' = optMapNoCopy b.get_stmt stmt2 in - stmt.skind <- Loop(annot,block,loc,stmt1',stmt2') - | Block block -> fix_succs_preds_block b block - | TryFinally(block1,block2,_) -> - fix_succs_preds_block b block1; - fix_succs_preds_block b block2 - | TryExcept(block1,_,block2,_) -> - fix_succs_preds_block b block1; - fix_succs_preds_block b block2 - | _ -> () + let printCode_annotation pp fmt ca = pp#pCode_annot fmt ca + let printStatus pp fmt s = pp#pStatus fmt s - let rec visitCilFunction (vis : cilVisitor) (f : fundec) : fundec = - if debugVisit then Cilmsg.feedback "Visiting function %s" f.svar.vname ; - assertEmptyQueue vis; - vis#set_current_func f; - let f = vis#behavior.cfundec f in - f.svar <- vis#behavior.memo_varinfo f.svar; (* hit the function name *) - let f = - doVisitCil vis (fun x -> x) (* copy has already been done *) - vis#vfunc childrenFunction f - in - let toPrepend = vis#unqueueInstr () in - if toPrepend <> [] then - f.sbody.bstmts <- - (List.map (fun i -> mkStmt (Instr i)) toPrepend) @ f.sbody.bstmts; - if vis#behavior.is_copy_behavior then begin - fix_succs_preds_block vis#behavior f.sbody; - f.sallstmts <- List.map vis#behavior.get_stmt f.sallstmts - end; - vis#reset_current_func (); - f + let printFunspec pp fmt s = pp#pSpec fmt s - and childrenFunction (vis : cilVisitor) (f : fundec) : fundec = - f.svar <- visitCilVarDecl vis f.svar; (* hit the function name *) - (* visit local declarations *) - f.slocals <- mapNoCopy (visitCilVarDecl vis) f.slocals; - (* visit the formals *) - let newformals = mapNoCopy (visitCilVarDecl vis) f.sformals in - (* Make sure the type reflects the formals *) - setFormals f newformals; - (* Remember any new instructions that were generated while visiting - variable declarations. *) - let toPrepend = vis#unqueueInstr () in - f.sbody <- visitCilBlock vis f.sbody; (* visit the body *) - if toPrepend <> [] then - f.sbody.bstmts <- (List.map (fun i -> mkStmt (Instr i)) toPrepend) @ f.sbody.bstmts; - f.sspec <- visitCilFunspec vis f.sspec; - f + let printAnnotation pp fmt a = pp#pAnnotation fmt a + let printDecreases pp fmt a = pp#pDecreases fmt a + let printLoop_variant pp fmt a = pp#pLoop_variant fmt a + let printAssigns pp kw fmt a = pp#pAssigns kw fmt a + let printFrom pp kw fmt a = pp#pFrom kw fmt a - let childrenFieldInfo vis fi = - fi.fcomp <- vis#behavior.get_compinfo fi.fcomp; - fi.ftype <- visitCilType vis fi.ftype; - fi.fattr <- visitCilAttributes vis fi.fattr; - fi + (* Now define some short cuts *) + let d_exp fmt e = printExp defaultCilPrinter fmt e + let d_var fmt v = printVar defaultCilPrinter fmt v + let () = Cil_datatype.Varinfo.pretty_ref := d_var + let d_lval fmt lv = printLval defaultCilPrinter fmt lv + let () = Cil_datatype.Lval.pretty_ref := d_lval + let d_offset fmt off = defaultCilPrinter#pOffset fmt off + let () = Cil_datatype.Offset.pretty_ref := d_offset + let d_init fmt i = printInit defaultCilPrinter fmt i + let d_type fmt t = printType defaultCilPrinter fmt t + let () = Cil_datatype.Typ.pretty_ref := d_type + let d_global fmt g = printGlobal defaultCilPrinter fmt g + let d_attrlist fmt a = printAttrs defaultCilPrinter fmt a + let d_attr fmt a = printAttr defaultCilPrinter fmt a + let () = pd_attr:=d_attr + let d_attrparam fmt e = defaultCilPrinter#pAttrParam fmt e + let d_label fmt l = defaultCilPrinter#pLabel fmt l + let d_stmt fmt s = printStmt defaultCilPrinter fmt s + let () = Cil_datatype.Stmt.pretty_ref := d_stmt + let d_block fmt b = printBlock defaultCilPrinter fmt b + let d_instr fmt i = printInstr defaultCilPrinter fmt i - let visitCilFieldInfo vis f = - doVisitCil vis vis#behavior.memo_fieldinfo vis#vfieldinfo childrenFieldInfo f + let d_term_lval fmt lv = printTerm_lval defaultCilPrinter fmt lv + let d_logic_var fmt lv = printLogic_var defaultCilPrinter fmt lv + let () = Cil_datatype.Logic_var.pretty_ref := d_logic_var + let d_logic_type fmt lv = printLogic_type defaultCilPrinter fmt lv + let () = Cil_datatype.Logic_type.pretty_ref := d_logic_type + let d_term fmt lv = printTerm defaultCilPrinter fmt lv + let () = Cil_datatype.Term.pretty_ref := d_term + let d_term_offset fmt lv = printTerm_offset defaultCilPrinter fmt lv - let childrenCompInfo vis comp = - comp.cfields <- mapNoCopy (visitCilFieldInfo vis) comp.cfields; - comp.cattr <- visitCilAttributes vis comp.cattr; - comp + let d_predicate_named fmt lv = printPredicate_named defaultCilPrinter fmt lv + let d_identified_predicate fmt p = + printIdentified_predicate defaultCilPrinter fmt p + let d_code_annotation fmt lv = printCode_annotation defaultCilPrinter fmt lv + let d_funspec fmt lv = printFunspec defaultCilPrinter fmt lv + let d_annotation fmt lv = printAnnotation defaultCilPrinter fmt lv + let d_decreases fmt lv = printDecreases defaultCilPrinter fmt lv + let d_loop_variant fmt lv = printLoop_variant defaultCilPrinter fmt lv + let d_from fmt f = printFrom defaultCilPrinter "assigns" fmt f + let d_assigns fmt a = printAssigns defaultCilPrinter "assigns" fmt a + let d_loop_assigns fmt a = printAssigns defaultCilPrinter "loop assigns" fmt a + let d_loop_from fmt f = printFrom defaultCilPrinter "loop assigns" fmt f - let visitCilCompInfo vis c = - doVisitCil vis vis#behavior.memo_compinfo vis#vcompinfo childrenCompInfo c + let () = pd_exp := d_exp + let () = pd_global := d_global + let () = pd_type := d_type + + (* sm: given an ordinary CIL object printer, yield one which + * behaves the same, except it never prints #line directives + * (this is useful for debugging printfs) *) + let dn_obj (func: formatter -> 'a -> unit) : (formatter -> 'a -> unit) = + begin + (* construct the closure to return *) + let theFunc fmt (obj:'a) = + begin + let prevStyle = miscState.lineDirectiveStyle in + miscState.lineDirectiveStyle <- None; + func fmt obj; (* call underlying printer *) + miscState.lineDirectiveStyle <- prevStyle + end in + theFunc + end + + (* now define shortcuts for the non-location-printing versions, + * with the naming prefix "dn_" *) + let dn_exp = (dn_obj d_exp) + let dn_lval = (dn_obj d_lval) + (* dn_offset is missing because it has a different interface *) + let dn_init = (dn_obj d_init) + let dn_type = (dn_obj d_type) + let dn_global = (dn_obj d_global) + let dn_attrlist = (dn_obj d_attrlist) + let dn_attr = (dn_obj d_attr) + let dn_attrparam = (dn_obj d_attrparam) + let dn_stmt = (dn_obj d_stmt) + let dn_instr = (dn_obj d_instr) + + + +(* Strip the "const" from the type. It is unfortunate that const variables + * can only be set in initialization. Once we decided to move all + * declarations to the top of the functions, we have no way of setting a + * "const" variable. Furthermore, if the type of the variable is an array or + * a struct we must recursively strip the "const" from fields and array + * elements. *) +let rec stripConstLocalType (t: typ) : typ = + let dc a = + if hasAttribute "const" a then + dropAttribute "const" a + else a + in + match t with + | TPtr (bt, a) -> + (* We want to be able to detect by pointer equality if the type has + * changed. So, don't realloc the type unless necessary. *) + let a' = dc a in if a != a' then TPtr(bt, a') else t + | TInt (ik, a) -> + let a' = dc a in if a != a' then TInt(ik, a') else t + | TFloat(fk, a) -> + let a' = dc a in if a != a' then TFloat(fk, a') else t + | TNamed (ti, a) -> + (* We must go and drop the consts from the typeinfo as well ! *) + let t' = stripConstLocalType ti.ttype in + if t != t' then begin + (* ignore (warn "Stripping \"const\" from typedef %s\n" ti.tname); *) + ti.ttype <- t' + end; + let a' = dc a in if a != a' then TNamed(ti, a') else t - let childrenEnumItem vis e = - e.eival <- visitCilExpr vis e.eival; - e.eihost <- vis#behavior.get_enuminfo e.eihost; - e + | TEnum (ei, a) -> + let a' = dc a in if a != a' then TEnum(ei, a') else t - let visitCilEnumItem vis e = - doVisitCil vis vis#behavior.memo_enumitem vis#venumitem childrenEnumItem e + | TArray(bt, leno, _, a) -> + (* We never assign to the array. So, no need to change the const. But + * we must change it on the base type *) + let bt' = stripConstLocalType bt in + if bt' != bt then TArray(bt', leno, empty_size_cache (), a) else t + + | TComp(ci, _, a) -> + (* Must change both this structure as well as its fields *) + List.iter + (fun f -> + let t' = stripConstLocalType f.ftype in + if t' != f.ftype then begin + Kernel.debug ~level:3 "Stripping \"const\" from field %s of %s\n" + f.fname (compFullName ci) ; + f.ftype <- t' + end) + ci.cfields; + let a' = dc a in if a != a' then TComp(ci, empty_size_cache (), a') else t + + (* We never assign functions either *) + | TFun(_rt, _args, _va, _a) -> t + | TVoid _ -> (* this may happen with temporary used only for their sizeof. *) + t + | TBuiltin_va_list a -> + let a' = dc a in if a != a' then TBuiltin_va_list a' else t - let childrenEnumInfo vis e = - e.eitems <- mapNoCopy (visitCilEnumItem vis) e.eitems; - e.eattr <- visitCilAttributes vis e.eattr; - e - let visitCilEnumInfo vis e = - doVisitCil vis vis#behavior.memo_enuminfo vis#venuminfo childrenEnumInfo e +(* And now some shortcuts *) +let d_plainexp fmt e = defaultCilPrinter#pExp fmt e +let d_plaintype fmt t = defaultCilPrinter#pType None fmt t +let d_plaininit fmt i = defaultCilPrinter#pInit fmt i +let d_plainlval fmt l = defaultCilPrinter#pLval fmt l +class type descriptiveCilPrinter = object + inherit cilPrinter + method startTemps: unit -> unit + method stopTemps: unit -> unit + method pTemps: Format.formatter -> unit + end - let rec visitCilGlobal (vis: cilVisitor) (g: global) : global list = - let oldloc = CurrentLoc.get () in - CurrentLoc.set (Global.loc g) ; - currentGlobal := g; - let res = - doVisitListCil vis (fun x -> x) vis#vglob childrenGlobal g in - CurrentLoc.set oldloc; - res - and childrenGlobal (vis: cilVisitor) (g: global) : global = - match g with - | GFun (f, l) -> - let f' = visitCilFunction vis f in - if f' != f then GFun (f', l) else g - | GType(t, l) -> - let t' = vis#behavior.memo_typeinfo t in - t'.ttype <- visitCilType vis t'.ttype; - if t' != t then GType(t,l) else g - | GEnumTagDecl (enum,l) -> - let enum' = vis#behavior.memo_enuminfo enum in - if enum != enum' then GEnumTagDecl(enum',l) else g - (* real visit'll be done in the definition *) - | GCompTagDecl (comp,l) -> - let comp' = vis#behavior.memo_compinfo comp in - if comp != comp' then GCompTagDecl(comp',l) else g - | GEnumTag (enum, l) -> - let enum' = visitCilEnumInfo vis enum in - if enum != enum' then GEnumTag(enum',l) else g - | GCompTag (comp, l) -> - let comp' = visitCilCompInfo vis comp in - if comp != comp' then GCompTag(comp',l) else g - | GVarDecl(spec, v, l) -> - let form = - try Some (getFormalsDecl v) with Not_found -> None - in - let v' = visitCilVarDecl vis v in - let form' = optMapNoCopy (mapNoCopy (visitCilVarDecl vis)) form in - let spec' = - if isFunctionType v.vtype then - visitCilFunspec vis spec - else begin - assert (is_empty_funspec spec); - empty_funspec () - end - in - if v' != v || spec' != spec || form != form' then - begin - (match form' with None -> () - | Some form' -> - Queue.add (fun () -> unsafeSetFormalsDecl v' form') - vis#get_filling_actions); - GVarDecl (spec', v', l) - end - else g - | GVar (v, inito, l) -> - let v' = visitCilVarDecl vis v in - let inito' = vis#behavior.cinitinfo inito in - (match inito'.init with - None -> () - | Some i -> let i' = visitCilInit vis v NoOffset i in - if i' != i then inito'.init <- Some i'); - if v' != v || inito' != inito then GVar (v', inito', l) else g - | GPragma (a, l) -> begin - match visitCilAttributes vis [a] with - [a'] -> if a' != a then GPragma (a', l) else g - | _ -> Cilmsg.fatal "visitCilAttributes returns more than one attribute" - end - | GAnnot (a,l) -> - let a' = visitCilAnnotation vis a in - if a' != a then GAnnot(a',l) else g - | GText _ | GAsm _ -> g + class descriptiveCilPrinterClass : descriptiveCilPrinter = object (self) + (** Like defaultCilPrinterClass, but instead of temporary variable + names it prints the description that was provided when the temp was + created. This is usually better for messages that are printed for end + users, although you may want the temporary names for debugging. *) + inherit defaultCilPrinterClass as super - (* the default visitor does nothing at each node, but does *) - (* not stop; hence they return true *) - class genericCilVisitor ?prj behavior: cilVisitor = - object - method behavior = behavior + val mutable temps: (varinfo * string * string option) list = [] + val mutable useTemps: bool = false - method plain_copy_visitor = - match prj with - None -> new genericCilVisitor behavior - | Some prj -> new genericCilVisitor ~prj behavior + method startTemps () : unit = + temps <- []; + useTemps <- true - (* list of things to perform on the new project. Done at the end - of the analysis in order to minimize the number of project changes. - *) - val global_tables_action = Queue.create () + method stopTemps () : unit = + temps <- []; + useTemps <- false - method fill_global_tables = - let action () = Queue.iter (fun f -> f()) global_tables_action in - (match prj with - None -> action () - | Some prj -> Project.on prj action ()); - Queue.clear global_tables_action + method pTemps fmt = + if temps = [] then + () + else + fprintf fmt "@\nWhere:@\n %a" + (Pretty_utils.pp_list ~sep:"\n " + (let f fmt v = match v with + | (_, s, Some d) -> fprintf fmt "%s = %s" s d + |(_, s, None) -> fprintf fmt "%s = " s in f)) + (List.rev temps) - method get_filling_actions = global_tables_action + method private pVarDescriptive fmt (vi: varinfo) = + match vi.vdescr with + | Some vd -> + if vi.vdescrpure || not useTemps then + fprintf fmt "%s" vd + else begin + try + let _, name, _ = List.find (fun (vi', _, _) -> vi == vi') temps in + fprintf fmt "%s" name + with Not_found -> + let name = "tmp" ^ string_of_int (List.length temps) in + temps <- (vi, name, vi.vdescr) :: temps; + fprintf fmt "%s" name + end + | None -> + super#pVar fmt vi - method vfile _f = DoChildren - val current_stmt = Stack.create () - method push_stmt s = Stack.push s current_stmt - method pop_stmt _s = ignore (Stack.pop current_stmt) - method current_stmt = - try Some (Stack.top current_stmt) with Stack.Empty -> None + (* Only substitute temp vars that appear in expressions. + (Other occurrences of lvalues are the left-hand sides of assignments, + but we shouldn't substitute there since "foo(a,b) = foo(a,b)" + would make no sense to the user.) *) + method pExp fmt (e:exp) = + match e.enode with + Lval (Var vi, o) + | StartOf (Var vi, o) -> + fprintf fmt "%a%a" self#pVarDescriptive vi self#pOffset o + | AddrOf (Var vi, o) -> + (* No parens needed, since offsets have higher precedence than & *) + fprintf fmt "& %a%a" self#pVarDescriptive vi self#pOffset o + | _ -> super#pExp fmt e + end - method current_kinstr = - try Kstmt (Stack.top current_stmt) with Stack.Empty -> Kglobal + let descriptiveCilPrinter: descriptiveCilPrinter = + ((new descriptiveCilPrinterClass) :> descriptiveCilPrinter) - val mutable current_func = None - method current_func = current_func - method set_current_func f = current_func <- Some f - method reset_current_func () = current_func <- None + let dd_exp = descriptiveCilPrinter#pExp + let dd_lval = descriptiveCilPrinter#pLval - method vvrbl (_v:varinfo) = DoChildren - method vvdec (_v:varinfo) = DoChildren - method vexpr (_e:exp) = DoChildren - method vlval (_l:lval) = DoChildren - method voffs (_o:offset) = DoChildren - method vinitoffs (_o:offset) = DoChildren - method vinst (_i:instr) = DoChildren - method vstmt (_s:stmt) = DoChildren - method vblock (_b: block) = DoChildren - method vfunc (_f:fundec) = DoChildren - method vglob (_g:global) = DoChildren - method vinit (_forg: varinfo) (_off: offset) (_i:init) = DoChildren - method vtype (_t:typ) = DoChildren - method vcompinfo _ = DoChildren - method venuminfo _ = DoChildren - method vfieldinfo _ = DoChildren - method venumitem _ = DoChildren - method vattr (_a: attribute) = DoChildren - method vattrparam (_a: attrparam) = DoChildren + let cvar_to_lvar vi = + match vi.vlogic_var_assoc with + None -> + let lv = + { lv_name = vi.vname; + lv_id = vi.vid; + lv_type = Ctype vi.vtype ; + lv_origin = Some vi} + in vi.vlogic_var_assoc <- Some lv; lv + | Some lv -> lv - val mutable instrQueue = [] + let copyVarinfo (vi: varinfo) (newname: string) : varinfo = + let vi' = copy_with_new_vid vi in + vi'.vname <- newname; + (match vi.vlogic_var_assoc with + None -> () + | Some _ -> + vi'.vlogic_var_assoc <- None; + ignore(cvar_to_lvar vi')); + vi' - method queueInstr (il: instr list) = - List.iter (fun i -> instrQueue <- i :: instrQueue) il + let rec findUniqueName ?(suffix="") fdec name = + let current_name = name ^ suffix in + (* Is this check a performance problem? We could bring the old + unchecked makeTempVar back as a separate function that assumes + the prefix name does not occur in the original program. *) + if (List.exists (fun vi -> vi.vname = current_name) fdec.slocals) + || (List.exists (fun vi -> vi.vname = current_name) fdec.sformals) then begin + fdec.smaxid <- 1 + fdec.smaxid; + findUniqueName ~suffix:("_" ^ (string_of_int (1 + fdec.smaxid))) fdec name + end else + current_name - method unqueueInstr () = - let res = List.rev instrQueue in - instrQueue <- []; - res + let makeLocal ?(generated=true) ?(formal=false) fdec name typ = + (* a helper function *) + let name = findUniqueName fdec name in + fdec.smaxid <- 1 + fdec.smaxid; + let vi = makeVarinfo ~generated false formal name typ in + vi - method vlogic_type _lt = DoChildren + (* Make a local variable and add it to a function *) + let makeLocalVar fdec ?scope ?(generated=true) ?(insert = true) name typ = + let typ = stripConstLocalType typ in + let vi = makeLocal ~generated fdec name typ in + if insert then + begin + fdec.slocals <- fdec.slocals @ [vi]; + let local_block = + match scope with + | None -> fdec.sbody + | Some b -> b + in + local_block.blocals <- vi::local_block.blocals + end; + vi - method vterm _t = DoChildren + let makeTempVar fdec ?insert ?(name = "__cil_tmp") ?descr ?(descrpure = true) + typ : varinfo = + let vi = makeLocalVar fdec ?insert name typ in + vi.vdescr <- descr; + vi.vdescrpure <- descrpure; + vi - method vterm_node _tn = DoChildren + let makePseudoVar = + let counter = ref 0 in + function ty -> + incr counter; + let name = "@" ^ (string_of_int !counter) in + makeVarinfo ~logic:true (* global= *)false (* formal= *)false name ty - method vterm_lval _tl = DoChildren + (* Set the types of arguments and results as given by the function type + * passed as the second argument *) + let setFunctionType (f: fundec) (t: typ) = + match unrollType t with + TFun (_rt, Some args, _va, _a) -> + if List.length f.sformals <> List.length args then + Kernel.fatal "setFunctionType: number of arguments differs from the number of formals" ; + (* Change the function type. *) + f.svar.vtype <- t; + (* Change the sformals and we know that indirectly we'll change the + * function type *) + List.iter2 + (fun (_an,at,aa) f -> + f.vtype <- at; f.vattr <- aa) + args f.sformals - method vterm_lhost _tl = DoChildren + | _ -> Kernel.fatal "setFunctionType: not a function type" - method vterm_offset _vo = DoChildren - method vlogic_info_decl _li = DoChildren + (* Set the types of arguments and results as given by the function type + * passed as the second argument *) + let setFunctionTypeMakeFormals (f: fundec) (t: typ) = + match unrollType t with + TFun (_rt, Some args, _va, _a) -> + if f.sformals <> [] then + Kernel.fatal "setFunctionTypMakeFormals called on function %s with some formals already" + f.svar.vname ; + (* Change the function type. *) + f.svar.vtype <- t; + f.sformals <- []; - method vlogic_info_use _li = DoChildren + f.sformals <- List.map (fun (n,t,_a) -> makeLocal ~formal:true f n t) args; - method vlogic_type_info_decl _ = DoChildren + setFunctionType f t - method vlogic_type_info_use _ = DoChildren + | _ -> Kernel.fatal "setFunctionTypeMakeFormals: not a function type: %a" d_type t - method vlogic_type_def _ = DoChildren - method vlogic_ctor_info_decl _ = DoChildren + let setMaxId (f: fundec) = + f.smaxid <- List.length f.sformals + List.length f.slocals - method vlogic_ctor_info_use _ = DoChildren - method vlogic_var_decl _lv = DoChildren + (* Make a formal variable for a function. Insert it in both the sformals + * and the type of the function. You can optionally specify where to insert + * this one. If where = "^" then it is inserted first. If where = "$" then + * it is inserted last. Otherwise where must be the name of a formal after + * which to insert this. By default it is inserted at the end. *) + let makeFormalVar fdec ?(where = "$") name typ : varinfo = + (* Search for the insertion place *) + let thenewone = ref fdec.svar in (* Just a placeholder *) + let makeit () : varinfo = + let vi = makeLocal ~formal:true fdec name typ in + thenewone := vi; + vi + in + let rec loopFormals = function + [] -> + if where = "$" then [makeit ()] + else Kernel.fatal "makeFormalVar: cannot find insert-after formal %s" where + | f :: rest when f.vname = where -> f :: makeit () :: rest + | f :: rest -> f :: loopFormals rest + in + let newformals = + if where = "^" then makeit () :: fdec.sformals else + loopFormals fdec.sformals in + setFormals fdec newformals; + !thenewone - method vlogic_var_use _lv = DoChildren + (* Make a global variable. Your responsibility to make sure that the name + * is unique *) + let makeGlobalVar ?logic ?generated name typ = + let vi = makeVarinfo ?logic ?generated true false name typ in + vi - method vquantifiers _q = DoChildren + let emptyFunctionFromVI vi = + let r = + { svar = vi; + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + sspec = empty_funspec () + } + in + setFormalsDecl r.svar r.svar.vtype; + r - method vpredicate _p = DoChildren + (* Make an empty function *) + let emptyFunction name = + let vi = + makeGlobalVar ~generated:false name (TFun(voidType, Some [], false,[])) + in emptyFunctionFromVI vi - method vpredicate_named _p = DoChildren + let dummyFile = + { globals = []; + fileName = ""; + globinit = None; + globinitcalled = false;} - method vbehavior _b = DoChildren - method vspec _s = DoChildren + (* Take the name of a file and make a valid varinfo name out of it. There are + * a few characters that are not valid in varinfos *) + let makeValidVarinfoName (s: string) = + let s = String.copy s in (* So that we can update in place *) + let l = String.length s in + for i = 0 to l - 1 do + let c = String.get s i in + let isinvalid = + match c with + '-' | '.' -> true + | _ -> false + in + if isinvalid then + String.set s i '_'; + done; + s - method vassigns _s = DoChildren + let rec lastOffset (off: offset) : offset = + match off with + | NoOffset | Field(_,NoOffset) | Index(_,NoOffset) -> off + | Field(_,off) | Index(_,off) -> lastOffset off - method vloop_pragma _ = DoChildren + let isBitfield lval = + match lval with + | _, off -> + let off = lastOffset off in + match off with + Field({fbitfield=Some _}, _) -> true + | _ -> false - method vslice_pragma _ = DoChildren - method vimpact_pragma _ = DoChildren + let rec lastTermOffset (off: term_offset) : term_offset = + match off with + | TNoOffset | TField(_,TNoOffset) | TIndex(_,TNoOffset) -> off + | TField(_,off) | TIndex(_,off) -> lastTermOffset off - method vdeps _ = DoChildren + (* Add an offset at the end of an lv *) + let addOffsetLval toadd (b, off) : lval = + b, addOffset toadd off - method vfrom _ = DoChildren + let addTermOffsetLval toadd (b, off) : term_lval = + b, addTermOffset toadd off - method vcode_annot _ca = DoChildren + let rec removeOffset (off: offset) : offset * offset = + match off with + NoOffset -> NoOffset, NoOffset + | Field(_f, NoOffset) -> NoOffset, off + | Index(_i, NoOffset) -> NoOffset, off + | Field(f, restoff) -> + let off', last = removeOffset restoff in + Field(f, off'), last + | Index(i, restoff) -> + let off', last = removeOffset restoff in + Index(i, off'), last - method vannotation _a = DoChildren + let removeOffsetLval ((b, off): lval) : lval * offset = + let off', last = removeOffset off in + (b, off'), last + class copyVisitExpr = object + inherit genericCilVisitor (copy_visit()) + method vexpr e = + ChangeDoChildrenPost ({e with eid = Eid.next ()}, fun x -> x) end - class nopCilVisitor = object - inherit genericCilVisitor (inplace_visit ()) - end + let copy_exp e = visitCilExpr (new copyVisitExpr) e (** A visitor that does constant folding. If "machdep" is true then we do * machine dependent simplification (e.g., sizeof) *) @@ -7844,7 +8379,7 @@ iterGlobals f (fun g -> match fGlob g with - [g'] when g' == g || equals g' g -> () + [g'] when g' == g || Cilutil.equals g' g -> () (* Try to do the pointer check first *) | gl -> fatal @@ -7859,17 +8394,17 @@ match res with SkipChildren -> ChangeToPost(f, post_action) | JustCopy -> JustCopyPost post_action - | JustCopyPost f -> JustCopyPost (f $ post_action) + | JustCopyPost f -> JustCopyPost (fun x -> f (post_action x)) | ChangeTo res -> ChangeToPost(res, post_action) - | ChangeToPost (res, f) -> ChangeToPost (res, f $ post_action) + | ChangeToPost (res, f) -> ChangeToPost (res, fun x -> f (post_action x)) | DoChildren -> ChangeDoChildrenPost(f, post_action) | ChangeDoChildrenPost(f,post) -> - ChangeDoChildrenPost(f, post $ post_action) + ChangeDoChildrenPost(f, fun x -> post (post_action x)) (* A visitor for the whole file that does not change the globals *) let visitCilFileSameGlobals (vis : cilVisitor) (f : file) : unit = if vis#behavior.is_copy_behavior then - Cilmsg.fatal "You used visitCilFileSameGlobals with a copy visitor. Nothing is done" + Kernel.fatal "You used visitCilFileSameGlobals with a copy visitor. Nothing is done" else ignore (doVisitCil vis vis#behavior.cfile (post_file vis) childrenFileSameGlobals f) @@ -7898,7 +8433,7 @@ let visitCilFile vis f = if vis#behavior.is_copy_behavior then - Cilmsg.fatal "You used visitCilFile with a copy visitor. Nothing is done" + Kernel.fatal "You used visitCilFile with a copy visitor. Nothing is done" else ignore (visitCilFileCopy vis f) @@ -7959,7 +8494,7 @@ [], Location.unknown))) :: m.sbody.bstmts; inserted := true; - Cilmsg.feedback ~level:2 "Inserted the globinit" ; + Kernel.feedback ~level:2 "Inserted the globinit" ; fl.globinitcalled <- true; | _ -> ()) fl.globals; @@ -7983,7 +8518,7 @@ | Some g -> begin match doone (GFun(g, Location.unknown)) with GFun(g', _) -> fl.globinit <- Some g' - | _ -> Cilmsg.fatal "mapGlobals: globinit is not a function" + | _ -> Kernel.fatal "mapGlobals: globinit is not a function" end) @@ -7994,7 +8529,7 @@ pp_set_max_boxes fmt max_int; (* We don't want ... in the output *) pp_set_margin fmt 79; - Cilmsg.feedback ~level:2 "printing file %s" outfile ; + Kernel.feedback ~level:2 "printing file %s" outfile ; fprintf fmt "/* Generated by Frama-C */@." ; iterGlobals file (fun g -> printGlobal pp fmt g); @@ -8019,6 +8554,7 @@ match e.enode with Const(CInt64(i,k,_)) -> let i', trunc = truncateInteger64 k i in + let i' = My_bigint.to_int64 i' in if trunc then raise (NotAnAttrParam e); let i2 = Int64.to_int i' in @@ -8075,15 +8611,19 @@ (* Process two statements and possibly replace them both *) let rec peepHole2 ~agressive (dotwo: stmt * stmt -> stmt list option) (ss: stmt list) = - let rec doStmtList (il: stmt list) : stmt list = + let rec doStmtList acc (il: stmt list) : stmt list = match il with - [] -> [] - | [i] -> process i; il + [] -> List.rev acc + | [i] -> process i; List.rev (i::acc) | (i1 :: ((i2 :: rest) as rest2)) -> begin match dotwo (i1,i2) with - None -> process i1; i1 :: doStmtList rest2 - | Some sl -> if agressive then doStmtList (sl @ rest) else sl @ doStmtList rest + None -> process i1; doStmtList (i1::acc) rest2 + | Some sl -> + if agressive then + doStmtList acc (sl @ rest) + else + doStmtList (List.rev_append sl acc) rest end and doUnspecifiedStmtList il = match il with @@ -8114,9 +8654,11 @@ eb.bstmts <- peepHole2 ~agressive dotwo eb.bstmts | Switch (_e, b, _, _) -> b.bstmts <- peepHole2 ~agressive dotwo b.bstmts | Loop (_, b, _l, _, _) -> b.bstmts <- peepHole2 ~agressive dotwo b.bstmts - | Block b -> b.bstmts <- doStmtList b.bstmts - | TryFinally (b, h, _l) -> b.bstmts <- peepHole2 ~agressive dotwo b.bstmts; - b.bstmts <- peepHole2 ~agressive dotwo h.bstmts + | Block b -> b.bstmts <- doStmtList [] b.bstmts + | TryFinally (b, h, _l) -> + b.bstmts <- + peepHole2 ~agressive dotwo b.bstmts; + b.bstmts <- peepHole2 ~agressive dotwo h.bstmts | TryExcept (b, (_il, _e), h, _l) -> b.bstmts <- peepHole2 ~agressive dotwo b.bstmts; h.bstmts <- peepHole2 ~agressive dotwo h.bstmts; @@ -8127,94 +8669,7 @@ | Return _ | Goto _ | Break _ | Continue _ -> () in if agressive then List.iter process ss; - doStmtList ss - - (*** Type signatures ***) - - (* Helper class for typeSig: replace any types in attributes with typsigs *) - class typeSigVisitor(typeSigConverter: typ->typsig) = object - inherit nopCilVisitor - method vattrparam ap = - match ap with - | ASizeOf t -> ChangeTo (ASizeOfS (typeSigConverter t)) - | AAlignOf t -> ChangeTo (AAlignOfS (typeSigConverter t)) - | _ -> DoChildren - end - - let typeSigAddAttrs a0 t = - if a0 = [] then t else - match t with - TSBase t -> TSBase (typeAddAttributes a0 t) - | TSPtr (ts, a) -> TSPtr (ts, addAttributes a0 a) - | TSArray (ts, l, a) -> TSArray(ts, l, addAttributes a0 a) - | TSComp (iss, n, a) -> TSComp (iss, n, addAttributes a0 a) - | TSEnum (n, a) -> TSEnum (n, addAttributes a0 a) - | TSFun(ts, tsargs, isva, a) -> TSFun(ts, tsargs, isva, addAttributes a0 a) - - (* Compute a type signature. - Use ~ignoreSign:true to convert all signed integer types to unsigned, - so that signed and unsigned will compare the same. *) - let rec typeSigWithAttrs ?(ignoreSign=false) doattr t = - let typeSig = typeSigWithAttrs ~ignoreSign doattr in - let attrVisitor = new typeSigVisitor typeSig in - let doattr al = visitCilAttributes attrVisitor (doattr al) in - match t with - | TInt (ik, al) -> - let ik' = - if ignoreSign then unsignedVersionOf ik else ik - in - TSBase (TInt (ik', doattr al)) - | TFloat (fk, al) -> TSBase (TFloat (fk, doattr al)) - | TVoid al -> TSBase (TVoid (doattr al)) - | TEnum (enum, a) -> TSEnum (enum.ename, doattr a) - | TPtr (t, a) -> TSPtr (typeSig t, doattr a) - | TArray (t,l,_, a) -> (* We do not want fancy expressions in array lengths. - * So constant fold the lengths *) - let l' = - match l with - | Some l -> begin - match constFold true l with - { enode = Const(CInt64(i, _, _))} -> Some i - | e -> abort "Invalid length in array type: %a\n" - (!pd_exp) e - end - | None -> None - in - TSArray(typeSig t, l', doattr a) - - | TComp (comp, _, a) -> - TSComp (comp.cstruct, comp.cname, doattr (addAttributes comp.cattr a)) - | TFun(rt,args,isva,a) -> - TSFun(typeSig rt, - List.map (fun (_, atype, _) -> (typeSig atype)) (argsToList args), - isva, doattr a) - | TNamed(t, a) -> typeSigAddAttrs (doattr a) (typeSig t.ttype) - | TBuiltin_va_list al -> TSBase (TBuiltin_va_list (doattr al)) - - let typeSig t = - typeSigWithAttrs (fun al -> al) t - - let () = pTypeSig := typeSig - - (* Remove the attribute from the top-level of the type signature *) - let setTypeSigAttrs (a: attribute list) = function - TSBase t -> TSBase (setTypeAttrs t a) - | TSPtr (ts, _) -> TSPtr (ts, a) - | TSArray (ts, l, _) -> TSArray(ts, l, a) - | TSComp (iss, n, _) -> TSComp (iss, n, a) - | TSEnum (n, _) -> TSEnum (n, a) - | TSFun (ts, tsargs, isva, _) -> TSFun (ts, tsargs, isva, a) - - - let typeSigAttrs = function - TSBase t -> typeAttrs t - | TSPtr (_ts, a) -> a - | TSArray (_ts, _l, a) -> a - | TSComp (_iss, _n, a) -> a - | TSEnum (_n, a) -> a - | TSFun (_ts, _tsargs, _isva, a) -> a - - + doStmtList [] ss let dExp: string -> exp = fun d -> new_exp ~loc:Cil_datatype.Location.unknown (Const(CStr(d))) @@ -8259,6 +8714,7 @@ d_plainexp addr d_plainoffset off d_plainexp res); *) res + let mkTermMem ~(addr: term) ~(off: term_offset) : term_lval = let loc = addr.term_loc in let res = @@ -8283,9 +8739,86 @@ : typ * (string * typ * attributes) list option * bool * attributes = match unrollType fvi.vtype with TFun (rt, args, isva, a) -> rt, args, isva, a - | _ -> abort "Function %s invoked on a non function type" fvi.vname + | _ -> Kernel.abort "Function %s invoked on a non function type" fvi.vname + + let rec integralPromotion (t : typ) : typ = (* c.f. ISO 6.3.1.1 *) + match unrollType t with + | TInt ((IShort|ISChar|IBool), a) -> TInt(IInt, a) + | TInt (IChar,a) when isSigned IChar -> TInt(IInt, a) + | TInt (IUChar|IUShort as k, a) -> + if bitsSizeOfInt k < bitsSizeOf intType then + TInt(IInt, a) + else + TInt(IUInt,a) + | TInt (k,a) -> + begin match findAttribute "FRAMA_C_BITFIELD_SIZE" a with + | [AInt size] -> + let sizeofint = bitsSizeOf intType in + let attrs = dropAttribute "FRAMA_C_BITFIELD_SIZE" a in + let kind = + if size < sizeofint then IInt + else if size = sizeofint then + if isSigned k then IInt + else IUInt + else k + in + TInt(kind,attrs) + | [] -> t + | _ -> assert false + end + | TEnum (ei, a) -> integralPromotion (TInt(ei.ekind, a)) + (* gcc packed enums can be < int *) + | t -> fatal "integralPromotion: not expecting %a" d_type t + + let arithmeticConversion t1 t2 = (* c.f. ISO 6.3.1.8 *) + let checkToInt _ = () in (* dummies for now *) + let checkToFloat _ = () in + match unrollType t1, unrollType t2 with + TFloat(FLongDouble, _), _ -> checkToFloat t2; t1 + | _, TFloat(FLongDouble, _) -> checkToFloat t1; t2 + | TFloat(FDouble, _), _ -> checkToFloat t2; t1 + | _, TFloat (FDouble, _) -> checkToFloat t1; t2 + | TFloat(FFloat, _), _ -> checkToFloat t2; t1 + | _, TFloat (FFloat, _) -> checkToFloat t1; t2 + | _, _ -> begin + let t1' = integralPromotion t1 in + let t2' = integralPromotion t2 in + match unrollType t1', unrollType t2' with + TInt(IULongLong, _), _ -> checkToInt t2'; t1' + | _, TInt(IULongLong, _) -> checkToInt t1'; t2' + + | TInt(ILongLong,_), _ + when bitsSizeOf t1' <= bitsSizeOf t2' && + (not (isSignedInteger t2')) -> TInt(IULongLong,[]) + | _, TInt(ILongLong,_) + when bitsSizeOf t2' <= bitsSizeOf t1' && + (not (isSignedInteger t1')) -> TInt(IULongLong,[]) + + | TInt(ILongLong, _), _ -> checkToInt t2'; t1' + | _, TInt(ILongLong, _) -> checkToInt t1'; t2' + + | TInt(IULong, _), _ -> checkToInt t2'; t1' + | _, TInt(IULong, _) -> checkToInt t1'; t2' + + + | TInt(ILong,_), TInt(IUInt,_) + when bitsSizeOf t1' <= bitsSizeOf t2' -> TInt(IULong,[]) + | TInt(IUInt,_), TInt(ILong,_) + when bitsSizeOf t2' <= bitsSizeOf t1' -> TInt(IULong,[]) + + | TInt(ILong, _), _ -> checkToInt t2'; t1' + | _, TInt(ILong, _) -> checkToInt t1'; t2' - let isArrayType t = + | TInt(IUInt, _), _ -> checkToInt t2'; t1' + | _, TInt(IUInt, _) -> checkToInt t1'; t2' + + | TInt(IInt, _), TInt (IInt, _) -> t1' + + | t1, t2 -> + fatal "arithmeticConversion %a -> %a@." d_type t1 d_type t2 + end + +let isArrayType t = match unrollType t with TArray _ -> true | _ -> false @@ -8300,6 +8833,10 @@ TComp _ -> true | _ -> false + let isVariadicListType t = + match unrollType t with + | TBuiltin_va_list _ -> true + | _ -> false let rec isConstantGen f e = match (stripInfo e).enode with | Info _ -> assert false @@ -8323,8 +8860,8 @@ | Field(_fi, off) -> isConstantOffsetGen f off | Index(e, off) -> isConstantGen f e && isConstantOffsetGen f off - let isConstant e = isConstantGen (fun _ -> true) e - let isConstantOffset o = isConstantOffsetGen (fun _ -> true) o + let isConstant e = isConstantGen alphatrue e + let isConstantOffset o = isConstantOffsetGen alphatrue o let isIntegerConstant e = isConstantGen @@ -8335,12 +8872,6 @@ let getCompField (cinfo:compinfo) (fieldName:string) : fieldinfo = (List.find (fun fi -> fi.fname = fieldName) cinfo.cfields) - let need_cast oldt newt = - not - (equals - (typeSig (typeRemoveAttributes ["const"; "FRAMA_C_BITFIELD_SIZE"] oldt)) - (typeSig (typeRemoveAttributes ["const"; "FRAMA_C_BITFIELD_SIZE"] newt))) - let rec mkCastT ~(e: exp) ~(oldt: typ) ~(newt: typ) = let loc = e.eloc in (* Do not remove old casts because they are conversions !!! *) @@ -8354,12 +8885,85 @@ | _ -> new_exp ~loc - (CastE((typeRemoveAttributes ["FRAMA_C_BITFIELD_SIZE"] newt),e)) + (CastE((type_remove_attributes_for_cast newt),e)) end let mkCast ~(e: exp) ~(newt: typ) = mkCastT e (typeOf e) newt +(* TODO: unify this with doBinOp in Cabs2cil. *) + let mkBinOp ~loc op e1 e2 = + let t1 = typeOf e1 in + let t2 = typeOf e2 in + let machdep = false in + let make_expr common_type res_type = + constFoldBinOp ~loc machdep op + (mkCastT e1 t1 common_type) + (mkCastT e2 t2 common_type) + res_type + in + let doArithmetic () = + let tres = arithmeticConversion t1 t2 in + make_expr tres tres + in + let doArithmeticComp () = + let tres = arithmeticConversion t1 t2 in + make_expr tres intType + in + let doIntegralArithmetic () = + let tres = arithmeticConversion t1 t2 in + if isIntegralType tres then + make_expr tres tres + else fatal "mkBinOp: %a" + d_plainexp (dummy_exp(BinOp(op,e1,e2,intType))) + in + match op with + (Mult|Div) -> doArithmetic () + | (Mod|BAnd|BOr|BXor|LAnd|LOr) -> doIntegralArithmetic () + | (Shiftlt|Shiftrt) -> (* ISO 6.5.7. Only integral promotions. The result + * has the same type as the left hand side *) + if theMachine.msvcMode then + (* MSVC has a bug. We duplicate it here *) + doIntegralArithmetic () + else + let t1' = integralPromotion t1 in + let t2' = integralPromotion t2 in + constFoldBinOp ~loc machdep op + (mkCastT e1 t1 t1') (mkCastT e2 t2 t2') t1' + | (PlusA|MinusA) + when isArithmeticType t1 && isArithmeticType t2 -> doArithmetic () + | (PlusPI|MinusPI|IndexPI) when isPointerType t1 && isIntegralType t2 -> + constFoldBinOp ~loc machdep op e1 e2 t1 + | MinusPP when isPointerType t1 && isPointerType t2 -> + (* NB: Same as cabs2cil. Check if this is really what the standard says*) + constFoldBinOp ~loc machdep op e1 (mkCastT e2 t2 t1) intType + | (Eq|Ne|Lt|Le|Ge|Gt) + when isArithmeticType t1 && isArithmeticType t2 -> + doArithmeticComp () + | (Le|Lt|Ge|Gt|Eq|Ne) when isPointerType t1 && isPointerType t2 -> + constFoldBinOp ~loc machdep op + (mkCastT e1 t1 theMachine.upointType) + (mkCastT e2 t2 theMachine.upointType) + intType + | (Eq|Ne) when isPointerType t1 && isZero e2 -> + constFoldBinOp ~loc machdep op + e1 (mkCastT (zero ~loc)theMachine.upointType t1) intType + | (Eq|Ne) when isPointerType t2 && isZero e1 -> + constFoldBinOp ~loc machdep op + (mkCastT (zero ~loc)theMachine.upointType t2) e2 intType + | (Eq|Ne) when isVariadicListType t1 && isZero e2 -> + Kernel.debug ~level:3 "Comparison of va_list and zero"; + constFoldBinOp ~loc machdep op e1 + (mkCastT (zero ~loc)theMachine.upointType t1) intType + | (Eq|Ne) when isVariadicListType t2 && isZero e1 -> + Kernel.debug ~level:3 "Comparison of zero and va_list"; + constFoldBinOp ~loc machdep op + (mkCastT (zero ~loc)theMachine.upointType t2) e2 intType + | _ -> + Kernel.fatal "mkBinOp: %a" + d_plainexp (dummy_exp(BinOp(op,e1,e2,intType))) + + type existsAction = ExistsTrue (* We have found it *) | ExistsFalse (* Stop processing this branch *) @@ -8396,17 +9000,21 @@ (* Try to do an increment, with constant folding *) let increm (e: exp) (i: int) = - let et = typeOf e in + let e' = constFold false e in + let et = typeOf e' in let bop = if isPointerType et then PlusPI else PlusA in - constFold false - (new_exp ~loc:e.eloc (BinOp(bop, e, integer ~loc:e.eloc i, et))) + let i = match et with + | TInt (k, _) | TEnum ({ekind = k },_) -> kinteger k ~loc:e.eloc i + | _ -> integer ~loc:e.eloc i + in + constFoldBinOp ~loc:e.eloc false bop e' i et (* Try to do an increment, with constant folding *) - let increm64 (e: exp) (i: int64) = + let increm64 (e: exp) i = let et = typeOf e in let bop = if isPointerType et then PlusPI else PlusA in - constFold - false + constFold + false (new_exp ~loc:e.eloc (BinOp(bop, e, kinteger64 ~loc:e.eloc IULongLong i, et))) @@ -8416,17 +9024,17 @@ None -> raise LenOfArray | Some e -> begin match (constFold true e).enode with - | Const(CInt64(ni, _, _)) when ni >= Int64.zero -> + | Const(CInt64(ni, _, _)) when My_bigint.ge ni My_bigint.zero -> ni | _ -> raise LenOfArray end - let lenOfArray eo = Int64.to_int (lenOfArray64 eo) + let lenOfArray eo = My_bigint.to_int (lenOfArray64 eo) (*** Make an initializer for zeroe-ing a data type ***) let rec makeZeroInit ~loc (t: typ) : init = match unrollType t with TInt (ik, _) -> - SingleInit (new_exp ~loc (Const(CInt64(Int64.zero, ik, None)))) + SingleInit (new_exp ~loc (Const(CInt64(My_bigint.zero, ik, None)))) | TFloat(fk, _) -> SingleInit(new_exp ~loc (Const(CReal(0.0, fk, None)))) | TEnum _ -> SingleInit (zero ~loc) | TComp (comp, _, _) as t' when comp.cstruct -> @@ -8476,7 +9084,7 @@ | TArray(bt, Some len, _, _) as t' -> let n = match (constFold true len).enode with - Const(CInt64(n, _, _)) -> Int64.to_int n + Const(CInt64(n, _, _)) -> My_bigint.to_int n | _ -> fatal "Cannot understand length of array" in let initbt = makeZeroInit ~loc bt in @@ -8521,7 +9129,7 @@ Some lene when implicit -> begin match (constFold true lene).enode with Const(CInt64(i, _, _)) -> - let len_array = Int64.to_int i in + let len_array = My_bigint.to_int i in let len_init = List.length initl in if len_array > len_init then (*TODO : find a proper loc*) @@ -8589,7 +9197,7 @@ (try let oldid = Hashtbl.find globalNames vi.vname in if oldid <> vi.vid && not vi.vinline then - warning + Kernel.warning "The name %s is used for two distinct globals" vi.vname (* Here if we have used this name already. Go ahead *) with Not_found -> begin @@ -8615,8 +9223,9 @@ (CurrentLoc.get ()) in if false && newname <> v.vname then (* Disable this warning *) - warning - "Changing the name of local %s in %s to %s (due to duplicate at %a)\n" + Kernel.warning + "Changing the name of local %s in %s to %s \ +(due to duplicate at %a)" v.vname fdec.svar.vname newname d_loc oldloc ; @@ -8757,17 +9366,14 @@ let initCIL initLogicBuiltins = if not (TheMachine.is_computed ()) then begin - (* Set the machine *) theMachine.theMachine <- if theMachine.msvcMode then Machdep.state.Machdep.msvc else Machdep.state.Machdep.gcc; (* Pick type for string literals *) theMachine.stringLiteralType <- - if theMachine.theMachine.const_string_literals then - charConstPtrType - else - charPtrType; + if theMachine.theMachine.const_string_literals then charConstPtrType + else charPtrType; (* Find the right ikind given the size *) let findIkindSz (unsigned: bool) (sz: int) : ikind = (* Test the most common sizes first *) @@ -8782,7 +9388,7 @@ else if sz = theMachine.theMachine.sizeof_longlong then if unsigned then IULongLong else ILongLong else - Cilmsg.fatal "initCIL: cannot find the right ikind for size %d\n" sz + Kernel.fatal "initCIL: cannot find the right ikind for size %d\n" sz in (* Find the right ikind given the name *) let findIkindName (name: string) : ikind = @@ -8796,7 +9402,7 @@ else if name = "char" then IChar else if name = "unsigned char" then IUChar else - Cilmsg.fatal "initCIL: cannot find the right ikind for type %s\n" name + Kernel.fatal "initCIL: cannot find the right ikind for type %s\n" name in theMachine.upointType <- TInt(findIkindSz true theMachine.theMachine.sizeof_ptr, []); @@ -8812,8 +9418,6 @@ theMachine.little_endian <- theMachine.theMachine.Cil_types.little_endian; theMachine.underscore_name <- theMachine.theMachine.Cil_types.underscore_name; - theMachine.enum_are_signed <- - theMachine.theMachine.Cil_types.enum_are_signed; (* do not use lazy LAND and LOR *) theMachine.useLogicalOperators <- false; (*nextGlobalVID <- 1 ; @@ -9010,7 +9614,6 @@ | TAlignOfE t | TUnOp (_,t) | TCastE (_,t) - | Told t | Tat (t,_) | Tbase_addr t | Tblock_length t @@ -9076,7 +9679,7 @@ | LBpred p -> free_vars_predicate bound_vars p | LBnone | LBreads _ | LBinductive _ -> - Cilmsg.fatal + Kernel.fatal "definition of local variable %s is not a term or a predicate" d.l_var_info.lv_name in @@ -9113,8 +9716,7 @@ (fun acc t -> Logic_var.Set.union (free_vars_term bound_vars t) acc) Logic_var.Set.empty tl - | Pfresh t -> free_vars_term bound_vars t - | Pvalid(t) -> free_vars_term bound_vars t + | Pfresh t | Pvalid t | Pinitialized t -> free_vars_term bound_vars t | Pseparated seps -> List.fold_left (fun free_vars tset -> @@ -9144,7 +9746,6 @@ (free_vars_predicate bound_vars p1) (free_vars_predicate bound_vars p2) | Pnot p - | Pold p | Pat (p,_) (* | Pnamed (_,p) *) -> free_vars_predicate bound_vars p @@ -9161,7 +9762,7 @@ | LBpred p -> free_vars_predicate bound_vars p | LBnone | LBreads _ | LBinductive _ -> - Cilmsg.fatal + Kernel.fatal "Local logic var %s is not a defined term or predicate" d.l_var_info.lv_name in @@ -9257,6 +9858,42 @@ with Got l -> Some (List.rev l) +(** Provided [s] is a switch, [separate_switch_succs s] returns the + subset of [s.succs] that correspond to the labels of [s], and an + optional statement that is [None] if the switch has a default label, + or [Some s'] where [s'] is the syntactic successor of [s] otherwise *) +let separate_switch_succs s = + match s.skind with + | Switch (_, _, cases, _) -> + let to_set = + List.fold_left (fun s stmt -> Stmt.Set.add stmt s) Stmt.Set.empty in + let s_succs = to_set s.succs in + let s_cases = to_set cases in + let diff = Stmt.Set.diff s_succs s_cases in + let cases = Stmt.Set.elements (Stmt.Set.inter s_succs s_cases) in + (match Stmt.Set.elements diff with + | [] -> cases, None + | [s] -> cases, Some s + | _ :: _ :: _ -> + fatal "Bad CFG: switch with multiple non-case successors." + ) + | _ -> raise (Invalid_argument "separate_switch_succs") + + +module Switch_cases = + State_builder.Hashtbl + (Stmt.Hashtbl) + (Datatype.Pair(Datatype.List(Stmt))(Datatype.Option(Stmt))) + (struct + let name = "Switch_cases" + let dependencies = [] + let size = 49 + let kind = `Internal + end) +let () = add_ast_dependency Switch_cases.self +let () = add_ast_dependency CacheBitsOffset.self +let separate_switch_succs = Switch_cases.memo separate_switch_succs + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil.mli frama-c-20111001+nitrogen+dfsg/cil/src/cil.mli --- frama-c-20110201+carbon+dfsg/cil/src/cil.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil.mli 2011-10-10 08:40:09.000000000 +0000 @@ -39,41 +39,17 @@ (* énergies alternatives). *) (**************************************************************************) -(* ************************************************************************* *) -(* Lithitum-Compatibility Logs *) -(* ************************************************************************* *) +(** CIL main API. -val info : ('a,Format.formatter,unit) format -> 'a -val err : ('a,Format.formatter,unit) format -> 'a -val log : ?once:bool -> ('a,Format.formatter,unit) format -> 'a -val warn : ?once:bool -> ('a,Format.formatter,unit) format -> 'a + CIL original API documentation is available as + an html version at http://manju.cs.berkeley.edu/cil. + + @plugin development guide *) (* ************************************************************************* *) -(* Localized Cilmsg logging functions *) +(** {2 Localized logging functions} *) (* ************************************************************************* *) -val source : Cil_types.location -> Log.source - -val warnOpt : ('a, Format.formatter, unit, unit) format4 -> 'a -val warning : ('a, Format.formatter, unit, unit) format4 -> 'a -val error : ('a, Format.formatter, unit, unit) format4 -> 'a -val abort : ('a, Format.formatter, unit, 'b) format4 -> 'a -val fatal : ('a, Format.formatter, unit, 'b) format4 -> 'a - -val error_loc : (string*int) -> ('a, Format.formatter, unit, unit) format4 -> 'a -val abort_loc : (string*int) -> ('a, Format.formatter, unit, 'b) format4 -> 'a - -(* - * CIL: An intermediate language for analyzing C programs. - * - * George Necula - * - *) - -(** CIL original API documentation is available as - * an html version at http://manju.cs.berkeley.edu/cil. - @plugin development guide *) - (** returns [true] if the given name refers to a special built-in function. A special built-in function can have any number of arguments. It is up to the plug-ins to know what to do with it. @@ -85,7 +61,7 @@ val add_special_builtin: string -> unit (** register a new family of special built-in functions. - @since Boron-20100401-dev + @since Carbon-20101201 *) val add_special_builtin_family: (string -> bool) -> unit @@ -132,8 +108,6 @@ the identifier. That is, will function foo() have the label "foo", or "_foo"? *) mutable underscore_name: bool; - (** Wether enum are signed or not. *) - mutable enum_are_signed: bool; mutable stringLiteralType: typ; (** An unsigned integer type that fits pointers. Depends on [Cil.msvcMode] *) @@ -225,6 +199,11 @@ (** {b Values for manipulating globals} *) +(** Make an empty function from an existing global varinfo. + @since Nitrogen-20111001 +*) +val emptyFunctionFromVI: varinfo -> fundec + (** Make an empty function *) val emptyFunction: string -> fundec @@ -254,6 +233,13 @@ * {!Cil.makeTempVar}. *) val setMaxId: fundec -> unit +(** Strip const attribute from the type. This is useful for + any type used as the type of a local variable which may be assigned. + Note that the type attributes are mutated in place. + @since Nitrogen-20111001 +*) +val stripConstLocalType : Cil_types.typ -> Cil_types.typ + val selfFormalsDecl: State.t (** state of the table associating formals to each prototype. *) @@ -311,20 +297,20 @@ module Sid: sig val next: unit -> int - val get: unit -> int - val self: State.t - val reset: unit -> unit end module Eid: sig val next: unit -> int - val get: unit -> int - val self: State.t end (** creates an expression with a fresh id *) val new_exp: loc:location -> exp_node -> exp +(** performs a deep copy of an expression (especially, avoid eid sharing). + @since Nitrogen-20111001 +*) +val copy_exp: exp -> exp + (** creates an expression with a dummy id. Use with caution, {i i.e.} not on expressions that may be put in the AST. *) @@ -428,6 +414,30 @@ (** unsigned long long *) val ulongLongType: typ +(** Any unsigned integer type of size 16 bits. + It is equivalent to the ISO C uint16_t type but without using the + corresponding header. + Shall not be called if not such type exists in the current architecture. + @since Nitrogen-20111001 +*) +val uint16_t: unit -> typ + +(** Any unsigned integer type of size 32 bits. + It is equivalent to the ISO C uint32_t type but without using the + corresponding header. + Shall not be called if not such type exists in the current architecture. + @since Nitrogen-20111001 +*) +val uint32_t: unit -> typ + +(** Any unsigned integer type of size 64 bits. + It is equivalent to the ISO C uint64_t type but without using the + corresponding header. + Shall not be called if not such type exists in the current architecture. + @since Nitrogen-20111001 +*) +val uint64_t: unit -> typ + (** char *) val charType: typ @@ -511,6 +521,17 @@ (** Separate out the storage-modifier name attributes *) val separateStorageModifiers: attribute list -> attribute list * attribute list +(** returns the type of the result of an arithmetic operator applied to + values of the corresponding input types. + @since Nitrogen-20111001 (moved from Cabs2cil) +*) +val arithmeticConversion : Cil_types.typ -> Cil_types.typ -> Cil_types.typ + +(** performs the usual integral promotions mentioned in C reference manual. + @since Nitrogen-20111001 (moved from Cabs2cil) +*) +val integralPromotion : Cil_types.typ -> Cil_types.typ + (** True if the argument is a character type (i.e. plain, signed or unsigned) *) val isCharType: typ -> bool @@ -525,7 +546,7 @@ (i.e. plain, signed or unsigned) *) val isCharArrayType: typ -> bool -(** True if the argument is a logic integral type (i.e. integer or enum) *) +(** True if the argument is an integral type (i.e. integer or enum) *) val isIntegralType: typ -> bool (** True if the argument is an integral type (i.e. integer or enum), either @@ -562,6 +583,11 @@ @plugin development guide *) val isFunctionType: typ -> bool +(** True if the argument denotes the type of ... in a variadic function. + @since Nitrogen-20111001 moved from cabs2cil +*) +val isVariadicListType: typ -> bool + (** Obtain the argument list ([] if None) *) val argsToList: (string * typ * attributes) list option -> (string * typ * attributes) list @@ -569,6 +595,11 @@ (** True if the argument is an array type *) val isArrayType: typ -> bool +(** True if the argument is a variadic list. + @since Nitrogen-20111001 +*) +val isVariadicListType: typ -> bool + (** True if the argument is a struct of union type *) val isStructOrUnionType: typ -> bool @@ -580,7 +611,7 @@ * integer. Raises {!Cil.LenOfArray} if not able to compute the length, such * as when there is no length or the length is not a constant. *) val lenOfArray: exp option -> int -val lenOfArray64: exp option -> Int64.t +val lenOfArray64: exp option -> My_bigint.t (** Return a named fieldinfo in compinfo, or raise Not_found *) val getCompField: compinfo -> string -> fieldinfo @@ -672,7 +703,11 @@ Make sure you know what you are doing if you set insert=false. [generated] is passed to {!Cil.makeVarinfo}. The variable is attached to the toplevel block if [scope] is not specified. - *) + + @since Nitrogen-20111001 This function will strip const attributes + of its type in place in order for local variable to be assignable at + least once. +*) val makeLocalVar: fundec -> ?scope:block -> ?generated:bool -> ?insert:bool -> string -> typ -> varinfo @@ -710,6 +745,9 @@ (** Equivalent to [lastOffset] for terms. *) val lastTermOffset: term_offset -> term_offset +(** Is an lvalue a bitfield? *) +val isBitfield: lval -> bool + (** Add an offset at the end of an lvalue. Make sure the type of the lvalue * and the offset are compatible. *) val addOffsetLval: offset -> lval -> lval @@ -745,6 +783,16 @@ (** Equivalent to [typeOffset] for terms. *) val typeTermOffset: logic_type -> term_offset -> logic_type +(** Returns true when some part of the lvalue has volatile attributes. + @since Nitrogen-20111001 +*) +val hasSomeVolatileAttr:lval -> bool + +(** Returns true when some part of the type of an lvalue has volatile attributes. + @since Nitrogen-20111001 +*) +val hasLvalTypeSomeVolatileAttr:typ -> bool + (*******************************************************) (** {b Values for manipulating expressions} *) @@ -764,10 +812,10 @@ (** Construct an integer of a given kind, using OCaml's int64 type. If needed * it will truncate the integer to be within the representable range for the * given kind. The integer can have an optional literal representation. *) -val kinteger64_repr: loc:location -> ikind -> int64 -> string option -> exp +val kinteger64_repr: loc:location -> ikind -> My_bigint.t -> string option -> exp (** Construct an integer of a given kind without literal representation. *) -val kinteger64: loc:location -> ikind -> int64 -> exp +val kinteger64: loc:location -> ikind -> My_bigint.t -> exp (** Construct an integer of a given kind. Converts the integer to int64 and * then uses kinteger64. This might truncate the value if you use a kind @@ -782,7 +830,7 @@ (** True if the given expression is a (possibly cast'ed) character or an integer constant *) -val isInteger: exp -> int64 option +val isInteger: exp -> My_bigint.t option (** Convert a 64-bit int to an OCaml int, or raise an exception if that can't be done. *) @@ -842,26 +890,38 @@ will also compute compiler-dependent expressions such as [sizeof]. *) val constFoldBinOp: loc:location -> bool -> binop -> exp -> exp -> typ -> exp +(** [true] if the two constant are equal. + @since Nitrogen-20111001 +*) +val compareConstant: constant -> constant -> bool + (** [true] if the two expressions are syntactically the same. *) val compareExp: exp -> exp -> bool (** [true] if the two lval are syntactically the same. *) val compareLval: lval -> lval -> bool +(** [true] if the two offsets are syntactically the same. *) +val compareOffset: offset -> offset -> bool + (** Increment an expression. Can be arithmetic or pointer type *) val increm: exp -> int -> exp (** Increment an expression. Can be arithmetic or pointer type *) -val increm64: exp -> int64 -> exp +val increm64: exp -> My_bigint.t -> exp (** Makes an lvalue out of a given variable *) val var: varinfo -> lval +(** Creates an expr representing the variable. + @since Nitrogen-20111001 + *) +val evar: loc:location -> varinfo -> exp + (** Make an AddrOf. Given an lvalue of type T will give back an expression of type ptr(T). It optimizes somewhat expressions like "& v" and "& v[0]" *) val mkAddrOf: loc:location -> lval -> exp - (** Like mkAddrOf except if the type of lval is an array then it uses StartOf. This is the right operation for getting a pointer to the start of the storage denoted by lval. *) @@ -874,6 +934,12 @@ StartOf *) val mkMem: addr:exp -> off:offset -> lval +(** makes a binary operation and performs const folding. Inserts + casts between arithmetic types as needed, or between pointer + types, but do not attempt to cast pointer to int or + vice-versa. Use appropriate binop (PlusPI & friends) for that. *) +val mkBinOp: loc:location -> binop -> exp -> exp -> exp + (** Equivalent to [mkMem] for terms. *) val mkTermMem: addr:term -> off:term_offset -> term_lval @@ -961,8 +1027,10 @@ wrap it into the Cfg. *) val mkStmtCfgBlock: stmt list -> stmt -(** Construct a statement consisting of just one instruction *) -val mkStmtOneInstr: ?ghost:bool -> instr -> stmt +(** Construct a statement consisting of just one instruction + See {!Cil.mkStmt} for the signification of the optional args. + *) +val mkStmtOneInstr: ?ghost:bool -> ?valid_sid:bool -> instr -> stmt (** Try to compress statements so as to get maximal basic blocks. * use this instead of List.@ because you get fewer basic blocks *) @@ -1083,6 +1151,11 @@ their uses *) val typeRemoveAttributes: string list -> typ -> typ +(** Remove all attributes relative to const, volatile and restrict attributes + @since Nitrogen-20111001 + *) +val type_remove_qualifier_attributes: typ -> typ + (** Convert an expression into an attrparam, if possible. Otherwise raise NotAnAttrParam with the offending subexpression *) val expToAttrParam: exp -> attrparam @@ -1130,14 +1203,14 @@ function on the node *) -val mk_behavior : - ?name:string -> - ?assumes:('a list) -> - ?requires:('a list) -> - ?post_cond:((termination_kind * 'a) list) -> +val mk_behavior : + ?name:string -> + ?assumes:('a list) -> + ?requires:('a list) -> + ?post_cond:((termination_kind * 'a) list) -> ?assigns:('b Cil_types.assigns ) -> - ?extended:((string * int * 'a list) list) -> - unit -> + ?extended:((string * int * 'a list) list) -> + unit -> ('a, 'b) Cil_types.behavior (** @since Carbon-20101201 returns a dummy behavior with the default name [Cil.default_behavior_name]. @@ -1154,7 +1227,6 @@ val find_default_requires: ('a, 'b) behavior list -> 'a list (** @since Carbon-20101201 *) - type visitor_behavior (** How the visitor should behave in front of mutable fields: in place modification or copy of the structure. This type is abstract. @@ -1190,6 +1262,7 @@ val reset_behavior_stmt: visitor_behavior -> unit val reset_behavior_logic_info: visitor_behavior -> unit val reset_behavior_fieldinfo: visitor_behavior -> unit +val reset_behavior_kernel_function: visitor_behavior -> unit val get_varinfo: visitor_behavior -> varinfo -> varinfo (** retrieve the representative of a given varinfo in the current @@ -1203,6 +1276,7 @@ val get_logic_info: visitor_behavior -> logic_info -> logic_info val get_fieldinfo: visitor_behavior -> fieldinfo -> fieldinfo val get_logic_var: visitor_behavior -> logic_var -> logic_var +val get_kernel_function: visitor_behavior -> kernel_function -> kernel_function val get_original_varinfo: visitor_behavior -> varinfo -> varinfo (** retrieve the original representative of a given copy of a varinfo @@ -1216,6 +1290,8 @@ val get_original_logic_info: visitor_behavior -> logic_info -> logic_info val get_original_fieldinfo: visitor_behavior -> fieldinfo -> fieldinfo val get_original_logic_var: visitor_behavior -> logic_var -> logic_var +val get_original_kernel_function: + visitor_behavior -> kernel_function -> kernel_function val set_varinfo: visitor_behavior -> varinfo -> varinfo -> unit (** change the representative of a given varinfo in the current @@ -1230,6 +1306,8 @@ val set_logic_info: visitor_behavior -> logic_info -> logic_info -> unit val set_fieldinfo: visitor_behavior -> fieldinfo -> fieldinfo -> unit val set_logic_var: visitor_behavior -> logic_var -> logic_var -> unit +val set_kernel_function: + visitor_behavior -> kernel_function -> kernel_function -> unit val set_orig_varinfo: visitor_behavior -> varinfo -> varinfo -> unit (** change the reference of a given new varinfo in the current @@ -1243,6 +1321,11 @@ val set_orig_logic_info: visitor_behavior -> logic_info -> logic_info -> unit val set_orig_fieldinfo: visitor_behavior -> fieldinfo -> fieldinfo -> unit val set_orig_logic_var: visitor_behavior -> logic_var -> logic_var -> unit +val set_orig_kernel_function: + visitor_behavior -> kernel_function -> kernel_function -> unit + +val memo_kernel_function: + visitor_behavior -> kernel_function -> kernel_function (** A visitor interface for traversing CIL trees. Create instantiations of * this type by specializing the class {!nopCilVisitor}. Each of the @@ -1269,20 +1352,20 @@ method vvdec: varinfo -> varinfo visitAction (** Invoked for each variable declaration. The subtrees to be traversed - * are those corresponding to the type and attributes of the variable. - * Note that variable declarations are all the [GVar], [GVarDecl], [GFun], - * all the [varinfo] in formals of function types, and the formals and - * locals for function definitions. This means that the list of formals - * in a function definition will be traversed twice, once as part of the - * function type and second as part of the formals in a function - * definition. + are those corresponding to the type and attributes of the variable. + Note that variable declarations are all the [GVar], [GVarDecl], [GFun], + all the [varinfo] in formals of function types, and the formals and + locals for function definitions. This means that the list of formals + in a function definition will be traversed twice, once as part of the + function type and second as part of the formals in a function + definition. @plugin development guide *) method vvrbl: varinfo -> varinfo visitAction (** Invoked on each variable use. Here only the [SkipChildren] and - * [ChangeTo] actions make sense since there are no subtrees. Note that - * the type and attributes of the variable are not traversed for a - * variable use. + [ChangeTo] actions make sense since there are no subtrees. Note that + the type and attributes of the variable are not traversed for a + variable use. @plugin development guide *) method vexpr: exp -> exp visitAction @@ -1399,6 +1482,8 @@ method vterm_offset: term_offset -> term_offset visitAction + method vlogic_label: logic_label -> logic_label visitAction + method vlogic_info_decl: logic_info -> logic_info visitAction method vlogic_info_use: logic_info -> logic_info visitAction @@ -1572,6 +1657,13 @@ val visitCilBehavior: cilVisitor -> funbehavior -> funbehavior val visitCilBehaviors: cilVisitor -> funbehavior list -> funbehavior list +(** visit an extended clause of a behavior. + @since Nitrogen-20111001 + *) +val visitCilExtended: + cilVisitor -> (string * int * identified_predicate list) + -> (string * int * identified_predicate list) + val visitCilLogicType: cilVisitor -> logic_type -> logic_type val visitCilPredicate: cilVisitor -> predicate -> predicate @@ -1586,6 +1678,11 @@ val visitCilTerm: cilVisitor -> term -> term +(** visit term_lval. + @since Nitrogen-20111001 + *) +val visitCilTermLval: cilVisitor -> term_lval -> term_lval + val visitCilTermLhost: cilVisitor -> term_lhost -> term_lhost val visitCilTermOffset: cilVisitor -> term_offset -> term_offset @@ -1890,8 +1987,6 @@ method pFrom: string -> Format.formatter -> identified_term from -> unit - method pStatus : Format.formatter -> Cil_types.annot_status -> unit - method pCode_annot: Format.formatter -> code_annotation -> unit method pAnnotation: Format.formatter -> global_annotation -> unit @@ -1972,13 +2067,13 @@ (** pretty prints an assigns clause. The string is the keyword used ([assigns] or [loop assigns]) *) -val printAssigns: +val printAssigns: cilPrinter -> string -> Format.formatter -> identified_term assigns -> unit -(** pretty prints a functional dependencies clause. +(** pretty prints a functional dependencies clause. The string is the keyword used ([assigns] or [loop assigns]) *) -val printFrom: +val printFrom: cilPrinter -> string -> Format.formatter -> identified_term from -> unit (** Pretty-print a type using {!Cil.defaultCilPrinter} *) @@ -2034,16 +2129,14 @@ * stack) for huge globals (such as arrays with lots of initializers). *) val d_global: Format.formatter -> global -> unit +val d_relation: Format.formatter -> relation -> unit + val d_term_lval: Format.formatter -> term_lval -> unit val d_logic_var: Format.formatter -> logic_var -> unit val d_logic_type: Format.formatter -> logic_type -> unit val d_term: Format.formatter -> term -> unit val d_term_offset: Format.formatter -> term_offset -> unit -val d_annotation_status: Format.formatter -> annotation_status -> unit - (** @since Beryllium-20090901 *) - -val d_status: Format.formatter -> annot_status -> unit val d_predicate_named: Format.formatter -> predicate named -> unit val d_identified_predicate: Format.formatter -> identified_predicate -> unit val d_code_annotation: Format.formatter -> code_annotation -> unit @@ -2148,25 +2241,50 @@ (** Create a fresh size cache with [Not_Computed] *) val empty_size_cache : unit -> bitsSizeofTypCache +(** Give the unsigned kind corresponding to any integer kind *) +val unsignedVersionOf : ikind -> ikind + +(** The signed integer kind for a given size (unsigned if second argument + * is true). Raises Not_found if no such kind exists *) +val intKindForSize : int -> bool -> ikind + +(** The float kind for a given size. Raises Not_found + * if no such kind exists *) +val floatKindForSize : int-> fkind + (** The size of a type, in bits. Trailing padding is added for structs and * arrays. Raises {!Cil.SizeOfError} when it cannot compute the size. This * function is architecture dependent, so you should only call this after you * call {!Cil.initCIL}. Remember that on GCC sizeof(void) is 1! *) val bitsSizeOf: typ -> int -(* Returns the number of bytes to represent the given integer kind depending +(** Returns the number of bytes to represent the given integer kind depending on the curretn machdep. *) val bytesSizeOfInt: ikind -> int -(* Returns the signedness of the given integer kind depending +(** Returns the signedness of the given integer kind depending on the curretn machdep. *) val isSigned: ikind -> bool -(* Returns a unique number representing the integer +(** Returns a unique number representing the integer conversion rank. *) val rank: ikind -> int -val truncateInteger64: ikind -> int64 -> int64 * bool +(** Represents an integer as for a given kind. + * Returns a flag saying whether the value was changed + * during truncation (because it was too large to fit in k). *) +val truncateInteger64: ikind -> My_bigint.t -> My_bigint.t * bool + +val max_signed_number: int -> My_bigint.t +val min_signed_number: int -> My_bigint.t +val max_unsigned_number: int -> My_bigint.t + +(** True if the integer fits within the kind's range *) +val fitsInInt: ikind -> My_bigint.t -> bool + +(** Return the smallest kind that will hold the integer's value. + * The kind will be unsigned if the 2nd argument is true *) +val intKindForValue: My_bigint.t -> bool -> ikind (** The size of a type, in bytes. Returns a constant expression or a "sizeof" * expression if it cannot compute the size. This function is architecture @@ -2248,6 +2366,8 @@ val d_formatarg : Format.formatter -> formatArg -> unit +(** {b Misc} *) + val stmt_of_instr_list : ?loc:location -> instr list -> stmtkind val pretty_loc : Format.formatter -> kinstr -> unit @@ -2267,7 +2387,7 @@ val lzero : ?loc:location -> unit -> term (** The given constant logic term *) -val lconstant : ?loc:location -> Int64.t -> term +val lconstant : ?loc:location -> My_bigint.t -> term (** Bind all free variables with an universal quantifier *) val close_predicate : predicate named -> predicate named @@ -2290,7 +2410,21 @@ @raise Invalid_argument if the lists have different lengths. *) val create_alpha_renaming: varinfo list -> varinfo list -> cilVisitor -val print_utf8 : bool ref + +(** Provided [s] is a switch, [separate_switch_succs s] returns the + subset of [s.succs] that correspond to the labels of [s], and an + optional statement that is [None] if the switch has a default label, + or [Some s'] where [s'] is the syntactic successor of [s] otherwise *) +val separate_switch_succs: stmt -> stmt list * stmt option + + +(**/**) + +val register_ast_dependencies : State.t -> unit + (** Used to postpone some dependencies on [Ast.self], which is initialized + afterwards. *) + + (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cilmsg.ml frama-c-20111001+nitrogen+dfsg/cil/src/cilmsg.ml --- frama-c-20110201+carbon+dfsg/cil/src/cilmsg.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cilmsg.ml 2011-10-10 08:40:09.000000000 +0000 @@ -39,43 +39,25 @@ (* énergies alternatives). *) (**************************************************************************) -(* -------------------------------------------------------------------------- *) -(* --- Cil Messages --- *) -(* -------------------------------------------------------------------------- *) - -include Log.Register - (struct - let channel = Log.kernel_channel_name - let label = Log.kernel_label_name - let verbose_atleast n = !Cmdline.kernel_verbose_atleast_ref n - let debug_atleast n = !Cmdline.kernel_debug_atleast_ref n - end) - let hadErrors = ref false let errorstack = ref [] let had_errors () = !hadErrors let clear_errors () = hadErrors := false let set_error (_:Log.event) = hadErrors := true -let push_errors () = errorstack := !hadErrors :: !errorstack ; hadErrors := false -let pop_errors () = - match !errorstack with - | [] -> fatal "Error stack is inconsistent. Please report bug." - | old::stack -> errorstack := stack ; hadErrors := old +let push_errors () = + errorstack := !hadErrors :: !errorstack ; + hadErrors := false + +let pop_errors () = match !errorstack with + | [] -> Kernel.fatal "Error stack is inconsistent." + | old :: stack -> + errorstack := stack; + hadErrors := old let () = - begin - register Log.Error set_error ; - register Log.Failure set_error ; - end - -let on_errors_abort fmt = - if !hadErrors - then abort fmt - else Log.nullprintf fmt - -let warnFlag = false -let warnOpt fmt = if warnFlag then warning fmt else Log.nullprintf fmt + Kernel.register Log.Error set_error; + Kernel.register Log.Failure set_error (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cilmsg.mli frama-c-20111001+nitrogen+dfsg/cil/src/cilmsg.mli --- frama-c-20110201+carbon+dfsg/cil/src/cilmsg.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cilmsg.mli 2011-10-10 08:40:09.000000000 +0000 @@ -39,35 +39,15 @@ (* énergies alternatives). *) (**************************************************************************) -(* -------------------------------------------------------------------------- *) -(* --- Cil Messages --- *) -(* -------------------------------------------------------------------------- *) -(* Candidate replacement for both ocamlutil/Pretty and ocamlutil/Errormsg *) -(* module E = Errormsg *) -(* module M = Cilmsg *) -(* !E.hadErrors => M.had_errors () *) -(* E.s(E.bug s) => M.fatal s *) -(* E.s(E.error s) => M.error s *) -(* E.warn s => M.warning s *) -(* -------------------------------------------------------------------------- *) - -include Log.Messages - -val warnFlag : bool -val warnOpt : ('a, Format.formatter, unit, unit) format4 -> 'a +(** CIL's internal stack of errors. The module name [Cilmsg] is misleading, + but historical. *) val had_errors : unit -> bool -val clear_errors : unit -> unit +val clear_errors : unit -> unit val push_errors : unit -> unit val pop_errors : unit -> unit -val on_errors_abort : ('a,Format.formatter,unit) format -> 'a - (** Same as: [if had_errors () then abort ... ;] *) - -val set_error : Log.event -> unit - (** Should not be used directly. Use error, abort or fatal instead. *) - (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/cil/src/cil_types.mli frama-c-20111001+nitrogen+dfsg/cil/src/cil_types.mli --- frama-c-20110201+carbon+dfsg/cil/src/cil_types.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/cil_types.mli 2011-10-10 08:40:09.000000000 +0000 @@ -59,32 +59,40 @@ (** kind of termination a post-condition applies to. See ACSL manual. *) type termination_kind = Normal | Exits | Breaks | Continues | Returns +(* ************************************************************************* *) +(** {2 Root of the AST} *) +(* ************************************************************************* *) + +(** In Frama-C, the whole AST is accessible through {!Ast.get}. *) + (** The top-level representation of a CIL source file (and the result of the - * parsing and elaboration). Its main contents is the list of global - * declarations and definitions. You can iterate over the globals in a - * {!Cil_types.file} using the following iterators: {!Cil.mapGlobals}, - * {!Cil.iterGlobals} and {!Cil.foldGlobals}. You can also use the - * {!Cil.dummyFile} when you need a {!Cil_types.file} as a placeholder. For each - * global item CIL stores the source location where it appears (using the - * type {!Cil_types.location}) *) -type file = - { mutable fileName: string; (** The complete file name *) - mutable globals: global list; (** List of globals as they will appear - in the printed file *) - mutable globinit: fundec option; - (** An optional global initializer function. This is a function where - * you can put stuff that must be executed before the program is - * started. This function, is conceptually at the end of the file, - * although it is not part of the globals list. Use {!Cil.getGlobInit} - * to create/get one. *) - mutable globinitcalled: bool; - (** Whether the global initialization function is called in main. This - should always be false if there is no global initializer. When - you create a global initialization CIL will try to insert code in - main to call it. *) - } -(** Top-level representation of a C source file. - @plugin development guide *) + parsing and elaboration). Its main contents is the list of global + declarations and definitions. You can iterate over the globals in a + {!Cil_types.file} using the following iterators: {!Cil.mapGlobals}, + {!Cil.iterGlobals} and {!Cil.foldGlobals}. You can also use the + {!Cil.dummyFile} when you need a {!Cil_types.file} as a placeholder. For + each global item CIL stores the source location where it appears (using the + type {!Cil_types.location}) + @plugin development guide *) +type file = { + mutable fileName: string; (** The complete file name *) + + mutable globals: global list; + (** List of globals as they will appear in the printed file *) + + mutable globinit: fundec option; + (** An optional global initializer function. This is a function where you + can put stuff that must be executed before the program is + started. This function, is conceptually at the end of the file, + although it is not part of the globals list. Use {!Cil.getGlobInit} to + create/get one. *) + + mutable globinitcalled: bool; +(** Whether the global initialization function is called in main. This + should always be false if there is no global initializer. When you + create a global initialization CIL will try to insert code in main to + call it. *) +} (** The main type for representing global declarations and definitions. A list of these form a CIL file. The order of globals in the file is generally @@ -92,144 +100,146 @@ @plugin development guide *) and global = | GType of typeinfo * location - (** A typedef. All uses of type names (through the [TNamed] constructor) - must be preceeded in the file by a definition of the name. The string - is the defined name and always not-empty. *) + (** A typedef. All uses of type names (through the [TNamed] constructor) + must be preceeded in the file by a definition of the name. The string + is the defined name and always not-empty. *) | GCompTag of compinfo * location - (** Defines a struct/union tag with some fields. There must be one of - these for each struct/union tag that you use (through the [TComp] - constructor) since this is the only context in which the fields are - printed. Consequently nested structure tag definitions must be - broken into individual definitions with the innermost structure - defined first. *) + (** Defines a struct/union tag with some fields. There must be one of + these for each struct/union tag that you use (through the [TComp] + constructor) since this is the only context in which the fields are + printed. Consequently nested structure tag definitions must be + broken into individual definitions with the innermost structure + defined first. *) | GCompTagDecl of compinfo * location - (** Declares a struct/union tag. Use as a forward declaration. This is - * printed without the fields. *) + (** Declares a struct/union tag. Use as a forward declaration. This is + printed without the fields. *) | GEnumTag of enuminfo * location - (** Declares an enumeration tag with some fields. There must be one of + (** Declares an enumeration tag with some fields. There must be one of these for each enumeration tag that you use (through the [TEnum] constructor) since this is the only context in which the items are printed. *) | GEnumTagDecl of enuminfo * location - (** Declares an enumeration tag. Use as a forward declaration. This is - * printed without the items. *) + (** Declares an enumeration tag. Use as a forward declaration. This is + printed without the items. *) | GVarDecl of funspec * varinfo * location - (** A variable declaration (not a definition). If the variable has a - function type then this is a prototype. There can be several - declarations and at most one definition for a given variable. If both - forms appear then they must share the same varinfo structure. A - prototype shares the varinfo with the fundec of the definition. Either - has storage Extern or there must be a definition in this file *) + (** A variable declaration (not a definition). If the variable has a + function type then this is a prototype. There can be several + declarations and at most one definition for a given variable. If both + forms appear then they must share the same varinfo structure. A + prototype shares the varinfo with the fundec of the definition. Either + has storage Extern or there must be a definition in this file *) | GVar of varinfo * initinfo * location - (** A variable definition. Can have an initializer. The initializer is - * updateable so that you can change it without requiring to recreate - * the list of globals. There can be at most one definition for a - * variable in an entire program. Cannot have storage Extern or function - * type. *) - + (** A variable definition. Can have an initializer. The initializer is + updateable so that you can change it without requiring to recreate the + list of globals. There can be at most one definition for a variable in an + entire program. Cannot have storage Extern or function type. *) | GFun of fundec * location - (** A function definition. *) + (** A function definition. *) + + | GAsm of string * location + (** Global asm statement. These ones can contain only a template *) + + | GPragma of attribute * location + (** Pragmas at top level. Use the same syntax as attributes *) + + | GText of string + (** Some text (printed verbatim) at top level. E.g., this way you can put + comments in the output. *) - | GAsm of string * location (** Global asm statement. These ones - can contain only a template *) - | GPragma of attribute * location (** Pragmas at top level. Use the same - syntax as attributes *) - | GText of string (** Some text (printed verbatim) at - top level. E.g., this way you can - put comments in the output. *) | GAnnot of global_annotation * location - (** a global annotation. Can be - - an axiom or a lemma - - a predicate declaration or definition - - a global type invariant - - a global invariant - - a logic function declaration or definition. - *) - -(** {b Types}. A C type is represented in CIL using the type {!Cil_types.typ}. - * Among types we differentiate the integral types (with different kinds - * denoting the sign and precision), floating point types, enumeration types, - * array and pointer types, and function types. Every type is associated with - * a list of attributes, which are always kept in sorted order. Use - * {!Cil.addAttribute} and {!Cil.addAttributes} to construct list of - * attributes. If you want to inspect a type, you should use - * {!Cil.unrollType} or {!Cil.unrollTypeDeep} to see through the uses of - * named types. *) -(** CIL is configured at build-time with the sizes and alignments of the - * underlying compiler (GCC or MSVC). CIL contains functions that can compute - * the size of a type (in bits) {!Cil.bitsSizeOf}, the alignment of a type - * (in bytes) {!Cil.alignOf_int}, and can convert an offset into a start and - * width (both in bits) using the function {!Cil.bitsOffset}. At the moment - * these functions do not take into account the [packed] attributes and - * pragmas. *) +(** a global annotation. Can be + - an axiom or a lemma + - a predicate declaration or definition + - a global type invariant + - a global invariant + - a logic function declaration or definition. *) + +(* ************************************************************************* *) +(** {2 Types} *) +(* ************************************************************************* *) + +(** A C type is represented in CIL using the type {!Cil_types.typ}. Among types + we differentiate the integral types (with different kinds denoting the sign + and precision), floating point types, enumeration types, array and pointer + types, and function types. Every type is associated with a list of + attributes, which are always kept in sorted order. Use {!Cil.addAttribute} + and {!Cil.addAttributes} to construct list of attributes. If you want to + inspect a type, you should use {!Cil.unrollType} or {!Cil.unrollTypeDeep} to + see through the uses of named types. + + CIL is configured at build-time with the sizes and alignments of the + underlying compiler (GCC or MSVC). CIL contains functions that can compute + the size of a type (in bits) {!Cil.bitsSizeOf}, the alignment of a type (in + bytes) {!Cil.alignOf_int}, and can convert an offset into a start and width + (both in bits) using the function {!Cil.bitsOffset}. At the moment these + functions do not take into account the [packed] attributes and pragmas. *) and typ = - TVoid of attributes (** Void type. Also predefined as {!Cil.voidType} *) + | TVoid of attributes (** Void type. Also predefined as {!Cil.voidType} *) + | TInt of ikind * attributes - (** An integer type. The kind specifies the sign and width. Several - * useful variants are predefined as {!Cil.intType}, {!Cil.uintType}, - * {!Cil.longType}, {!Cil.charType}. *) + (** An integer type. The kind specifies the sign and width. Several useful + variants are predefined as {!Cil.intType}, {!Cil.uintType}, + {!Cil.longType}, {!Cil.charType}. *) | TFloat of fkind * attributes - (** A floating-point type. The kind specifies the precision. You can - * also use the predefined constant {!Cil.doubleType}. *) + (** A floating-point type. The kind specifies the precision. You can also use + the predefined constant {!Cil.doubleType}. *) | TPtr of typ * attributes - (** Pointer type. Several useful variants are predefined as - * {!Cil.charPtrType}, {!Cil.charConstPtrType} (pointer to a - * constant character), {!Cil.voidPtrType}, - * {!Cil.intPtrType} *) + (** Pointer type. Several useful variants are predefined as + {!Cil.charPtrType}, {!Cil.charConstPtrType} (pointer to a constant + character), {!Cil.voidPtrType}, {!Cil.intPtrType} *) | TArray of typ * exp option * bitsSizeofTypCache * attributes - (** Array type. It indicates the base type and the array length. *) + (** Array type. It indicates the base type and the array length. *) | TFun of typ * (string * typ * attributes) list option * bool * attributes - (** Function type. Indicates the type of the result, the name, type - * and name attributes of the formal arguments ([None] if no - * arguments were specified, as in a function whose definition or - * prototype we have not seen; [Some \[\]] means void). Use - * {!Cil.argsToList} to obtain a list of arguments. The boolean - * indicates if it is a variable-argument function. If this is the - * type of a varinfo for which we have a function declaration then - * the information for the formals must match that in the - * function's sformals. Use {!Cil.setFormals}, or - * {!Cil.setFunctionType}, or {!Cil.makeFormalVar} for this - * purpose. *) + (** Function type. Indicates the type of the result, the name, type + and name attributes of the formal arguments ([None] if no arguments + were specified, as in a function whose definition or prototype we + have not seen; [Some \[\]] means void). Use {!Cil.argsToList} to + obtain a list of arguments. The boolean indicates if it is a + variable-argument function. If this is the type of a varinfo for + which we have a function declaration then the information for the + formals must match that in the function's sformals. Use + {!Cil.setFormals}, or {!Cil.setFunctionType}, or + {!Cil.makeFormalVar} for this purpose. *) | TNamed of typeinfo * attributes - (** The use of a named type. All uses of the same type name must - * share the typeinfo. Each such type name must be preceeded - * in the file by a [GType] global. This is printed as just the - * type name. The actual referred type is not printed here and is - * carried only to simplify processing. To see through a sequence - * of named type references, use {!Cil.unrollType}. The attributes - * are in addition to those given when the type name was defined. *) + (** The use of a named type. All uses of the same type name must share the + typeinfo. Each such type name must be preceeded in the file by a [GType] + global. This is printed as just the type name. The actual referred type + is not printed here and is carried only to simplify processing. To see + through a sequence of named type references, use {!Cil.unrollType}. The + attributes are in addition to those given when the type name was + defined. *) | TComp of compinfo * bitsSizeofTypCache * attributes - (** A reference to a struct or a union type. All references to the - same struct or union must share the same compinfo among them and - with a [GCompTag] global that preceeds all uses (except maybe - those that are pointers to the composite type). The attributes - given are those pertaining to this use of the type and are in - addition to the attributes that were given at the definition of - the type and which are stored in the compinfo. *) + (** A reference to a struct or a union type. All references to the + same struct or union must share the same compinfo among them and + with a [GCompTag] global that preceeds all uses (except maybe + those that are pointers to the composite type). The attributes + given are those pertaining to this use of the type and are in + addition to the attributes that were given at the definition of + the type and which are stored in the compinfo. *) | TEnum of enuminfo * attributes - (** A reference to an enumeration type. All such references must - share the enuminfo among them and with a [GEnumTag] global that - preceeds all uses. The attributes refer to this use of the - enumeration and are in addition to the attributes of the - enumeration itself, which are stored inside the enuminfo *) + (** A reference to an enumeration type. All such references must + share the enuminfo among them and with a [GEnumTag] global that + preceeds all uses. The attributes refer to this use of the + enumeration and are in addition to the attributes of the + enumeration itself, which are stored inside the enuminfo *) | TBuiltin_va_list of attributes - (** This is the same as the gcc's type with the same name *) +(** This is the same as the gcc's type with the same name *) (** Various kinds of integers *) and ikind = @@ -253,35 +263,38 @@ | FDouble (** [double] *) | FLongDouble (** [long double] *) -(** {b Attributes.} *) +(* ************************************************************************* *) +(** {2 Attributes} *) +(* ************************************************************************* *) and attribute = | Attr of string * attrparam list -(** An attribute has a name and some optional parameters. The name should not - * start or end with underscore. When CIL parses attribute names it will - * strip leading and ending underscores (to ensure that the multitude of GCC - * attributes such as const, __const and __const__ all mean the same thing.) *) + (** An attribute has a name and some optional parameters. The name should not + start or end with underscore. When CIL parses attribute names it will + strip leading and ending underscores (to ensure that the multitude of GCC + attributes such as const, __const and __const__ all mean the same + thing.) *) + | AttrAnnot of string (** Attributes are lists sorted by the attribute name. Use the functions - * {!Cil.addAttribute} and {!Cil.addAttributes} to insert attributes in an - * attribute list and maintain the sortedness. *) + {!Cil.addAttribute} and {!Cil.addAttributes} to insert attributes in an + attribute list and maintain the sortedness. *) and attributes = attribute list (** The type of parameters of attributes *) and attrparam = | AInt of int (** An integer constant *) | AStr of string (** A string constant *) - | ACons of string * attrparam list (** Constructed attributes. These - are printed [foo(a1,a2,...,an)]. - The list of parameters can be - empty and in that case the - parentheses are not printed. *) + | ACons of string * attrparam list + (** Constructed attributes. These are printed [foo(a1,a2,...,an)]. The list + of parameters can be empty and in that case the parentheses are not + printed. *) | ASizeOf of typ (** A way to talk about types *) | ASizeOfE of attrparam - | ASizeOfS of typsig (** Replacement for ASizeOf in type - signatures. Only used for - attributes inside typsigs.*) + | ASizeOfS of typsig + (** Replacement for ASizeOf in type signatures. Only used for attributes + inside typsigs.*) | AAlignOf of typ | AAlignOfE of attrparam | AAlignOfS of typsig @@ -293,257 +306,282 @@ | AIndex of attrparam * attrparam (** a1[a2] *) | AQuestion of attrparam * attrparam * attrparam (** a1 ? a2 : a3 **) - -(** {b Structures.} The {!Cil_types.compinfo} describes the definition of a - * structure or union type. Each such {!Cil_types.compinfo} must be defined at the - * top-level using the [GCompTag] constructor and must be shared by all - * references to this type (using either the [TComp] type constructor or from - * the definition of the fields. - - If all you need is to scan the definition of each - * composite type once, you can do that by scanning all top-level [GCompTag]. - - * Constructing a {!Cil_types.compinfo} can be tricky since it must contain fields - * that might refer to the host {!Cil_types.compinfo} and furthermore the type of - * the field might need to refer to the {!Cil_types.compinfo} for recursive types. - * Use the {!Cil.mkCompInfo} function to create a {!Cil_types.compinfo}. You can - * easily fetch the {!Cil_types.fieldinfo} for a given field in a structure with - * {!Cil.getCompField}. *) - -(** The definition of a structure or union type. Use {!Cil.mkCompInfo} to - * make one and use {!Cil.copyCompInfo} to copy one (this ensures that a new - * key is assigned and that the fields have the right pointers to parents.). +(* ************************************************************************* *) +(** {2 Structures} *) +(* ************************************************************************* *) + +(** The {!Cil_types.compinfo} describes the definition of a structure or union + type. Each such {!Cil_types.compinfo} must be defined at the top-level using + the [GCompTag] constructor and must be shared by all references to this type + (using either the [TComp] type constructor or from the definition of the + fields. + + If all you need is to scan the definition of each composite type once, you + can do that by scanning all top-level [GCompTag]. + + Constructing a {!Cil_types.compinfo} can be tricky since it must contain + fields that might refer to the host {!Cil_types.compinfo} and furthermore + the type of the field might need to refer to the {!Cil_types.compinfo} for + recursive types. Use the {!Cil.mkCompInfo} function to create a + {!Cil_types.compinfo}. You can easily fetch the {!Cil_types.fieldinfo} for a + given field in a structure with {!Cil.getCompField}. *) + +(** The definition of a structure or union type. Use {!Cil.mkCompInfo} to make + one and use {!Cil.copyCompInfo} to copy one (this ensures that a new key is + assigned and that the fields have the right pointers to parents.). @plugin development guide *) and compinfo = { - mutable cstruct: bool; - (** True if struct, False if union *) - corig_name: string; - (** Original name as found in C file. Will never be changed *) - mutable cname: string; - (** The name. Always non-empty. Use {!Cil.compFullName} to get the full - * name of a comp (along with the struct or union) *) - mutable ckey: int; - (** A unique integer. This is assigned by {!Cil.mkCompInfo} using a - * global variable in the Cil module. Thus two identical structs in two - * different files might have different keys. Use {!Cil.copyCompInfo} to - * copy structures so that a new key is assigned. *) - mutable cfields: fieldinfo list; - (** Information about the fields. Notice that each fieldinfo has a - * pointer back to the host compinfo. This means that you should not - * share fieldinfo's between two compinfo's *) - mutable cattr: attributes; - (** The attributes that are defined at the same time as the composite - * type. These attributes can be supplemented individually at each - * reference to this [compinfo] using the [TComp] type constructor. *) - mutable cdefined: bool; - (** This boolean flag can be used to distinguish between structures - that have not been defined and those that have been defined but have - no fields (such things are allowed in gcc). *) - mutable creferenced: bool; - (** True if used. Initially set to false. *) - } - -(** {b Structure fields.} The {!Cil_types.fieldinfo} structure is used to describe - * a structure or union field. Fields, just like variables, can have - * attributes associated with the field itself or associated with the type of - * the field (stored along with the type of the field). *) + mutable cstruct: bool; + (** [true] if struct, [false] if union *) + + corig_name: string; + (** Original name as found in C file. Will never be changed *) + + mutable cname: string; + (** The name. Always non-empty. Use {!Cil.compFullName} to get the full name + of a comp (along with the struct or union) *) + + mutable ckey: int; + (** A unique integer. This is assigned by {!Cil.mkCompInfo} using a global + variable in the Cil module. Thus two identical structs in two different + files might have different keys. Use {!Cil.copyCompInfo} to copy + structures so that a new key is assigned. *) + + mutable cfields: fieldinfo list; + (** Information about the fields. Notice that each fieldinfo has a pointer + back to the host compinfo. This means that you should not share + fieldinfo's between two compinfo's *) + + mutable cattr: attributes; + (** The attributes that are defined at the same time as the composite + type. These attributes can be supplemented individually at each + reference to this [compinfo] using the [TComp] type constructor. *) + + mutable cdefined: bool; + (** This boolean flag can be used to distinguish between structures + that have not been defined and those that have been defined but have + no fields (such things are allowed in gcc). *) + + mutable creferenced: bool; +(** [true] if used. Initially set to [false]. *) +} + +(* ************************************************************************* *) +(** {2 Structure fields} *) +(* ************************************************************************* *) + +(** The {!Cil_types.fieldinfo} structure is used to describe a structure or + union field. Fields, just like variables, can have attributes associated + with the field itself or associated with the type of the field (stored along + with the type of the field). *) (** Information about a struct/union field. @plugin development guide *) and fieldinfo = { - mutable fcomp: compinfo; - (** The host structure that contains this field. There can be only one - * [compinfo] that contains the field. *) - forig_name: string; - (** original name as found in C file. *) - mutable fname: string; - (** The name of the field. Might be the value of {!Cil.missingFieldName} - * in which case it must be a bitfield and is not printed and it does not - * participate in initialization *) - mutable ftype: typ; - (** The type *) - mutable fbitfield: int option; - (** If a bitfield then ftype should be an integer type and the width of - * the bitfield must be 0 or a positive integer smaller or equal to the - * width of the integer type. A field of width 0 is used in C to control - * the alignment of fields. *) - mutable fattr: attributes; - (** The attributes for this field (not for its type) *) - mutable floc: location; - (** The location where this field is defined *) - mutable faddrof: bool; - (** Adapted from CIL [vaddrof] field for variables. Only set for - * non-array fields. Variable whose field address is taken is not marked - * anymore as having its own address taken. - * True if the address of this field is taken. CIL will set these - * flags when it parses C, but you should make sure to set the flag - * whenever your transformation create [AddrOf] expression. *) - mutable fsize_in_bits: int option; - (** Similar to [fbitfield] for all types of fields. Useful when - * the type of the field is changed in the analyzer, to recall the size - * of the original field. - @deprecated only Jessie uses this - *) - mutable foffset_in_bits: int option; - (** Store the offset at which the field starts in the structure. - @deprecated only Jessie uses this *) - mutable fpadding_in_bits: int option; - (** Store the size of the padding that follows the field, if any. - @deprecated only Jessie uses this *) + mutable fcomp: compinfo; + (** The host structure that contains this field. There can be only one + [compinfo] that contains the field. *) + + forig_name: string; + (** original name as found in C file. *) + + mutable fname: string; + (** The name of the field. Might be the value of {!Cil.missingFieldName} in + which case it must be a bitfield and is not printed and it does not + participate in initialization *) + + mutable ftype: typ; + (** The type *) + + mutable fbitfield: int option; + (** If a bitfield then ftype should be an integer type and the width of the + bitfield must be 0 or a positive integer smaller or equal to the width of + the integer type. A field of width 0 is used in C to control the alignment + of fields. *) + + mutable fattr: attributes; + (** The attributes for this field (not for its type) *) + + mutable floc: location; + (** The location where this field is defined *) + + mutable faddrof: bool; + (** Adapted from CIL [vaddrof] field for variables. Only set for non-array + fields. Variable whose field address is taken is not marked anymore as + having its own address taken. True if the address of this field is + taken. CIL will set these flags when it parses C, but you should make + sure to set the flag whenever your transformation create [AddrOf] + expression. *) + + mutable fsize_in_bits: int option; + (** Similar to [fbitfield] for all types of fields. Useful when the type of + the field is changed in the analyzer, to recall the size of the original + field. @deprecated only Jessie uses this *) + + mutable foffset_in_bits: int option; + (** Store the offset at which the field starts in the structure. + @deprecated only Jessie uses this *) + + mutable fpadding_in_bits: int option; +(** Store the size of the padding that follows the field, if any. + @deprecated only Jessie uses this *) } +(* ************************************************************************* *) +(** {2 Enumerations} *) +(* ************************************************************************* *) - -(** {b Enumerations.} Information about an enumeration. This is shared by all - * references to an enumeration. Make sure you have a [GEnumTag] for each - * of these. *) +(** Information about an enumeration. This is shared by all references to an + enumeration. Make sure you have a [GEnumTag] for each of these. *) (** Information about an enumeration. @plugin development guide *) and enuminfo = { - eorig_name: string; (** original name as found in C file. *) - mutable ename: string; - (** The name. Always non-empty. *) - mutable eitems: enumitem list; - (** Items. The list must be non-empty *) - mutable eattr: attributes; - (** The attributes that are defined at the same time as the enumeration - * type. These attributes can be supplemented individually at each - * reference to this [enuminfo] using the [TEnum] type constructor. *) - mutable ereferenced: bool; - (** True if used. Initially set to false*) -} - -and enumitem = - { eiorig_name: string; (** original name as found in C file. *) - mutable einame: string; (** the name, always non-empty. *) - mutable eival: exp; (** value of the item. - Must be a compile-time constant *) - mutable eihost: enuminfo; (** the host enumeration in which the - item is declared. *) - eiloc: location; - } + eorig_name: string; (** original name as found in C file. *) + + mutable ename: string; (** The name. Always non-empty. *) + + mutable eitems: enumitem list; (** Items. The list must be non-empty *) + + mutable eattr: attributes; + (** The attributes that are defined at the same time as the enumeration + type. These attributes can be supplemented individually at each + reference to this [enuminfo] using the [TEnum] type constructor. *) + + mutable ereferenced: bool; (** [true] if used. Initially set to [false]. *) + mutable ekind: ikind (** The integer kind used to represent this enum. MSVC + always assumes IInt but this is not the case + for gcc. See ISO C 6.7.2.2 *) +} + +and enumitem = { + eiorig_name: string; (** original name as found in C file. *) + mutable einame: string; (** the name, always non-empty. *) + mutable eival: exp; (** value of the item. Must be a compile-time constant *) + mutable eihost: enuminfo; (** the host enumeration in which the item is + declared. *) + eiloc: location; +} (** Information about a defined type. @plugin development guide *) and typeinfo = { - torig_name: string; (** original name as found in C file. *) - mutable tname: string; - (** The name. Can be empty only in a [GType] when introducing a composite - * or enumeration tag. If empty cannot be refered to from the file *) - mutable ttype: typ; - (** The actual type. This includes the attributes that were present in - * the typedef *) - mutable treferenced: bool; - (** True if used. Initially set to false*) -} - -(** {b Variables.} - Each local or global variable is represented by a unique {!Cil_types.varinfo} -structure. A global {!Cil_types.varinfo} can be introduced with the [GVarDecl] or -[GVar] or [GFun] globals. A local varinfo can be introduced as part of a -function definition {!Cil_types.fundec}. - - All references to a given global or local variable must refer to the same -copy of the [varinfo]. Each [varinfo] has a globally unique identifier that -can be used to index maps and hashtables (the name can also be used for this -purpose, except for locals from different functions). This identifier is -constructor using a global counter. - - It is very important that you construct [varinfo] structures using only one - of the following functions: -- {!Cil.makeGlobalVar} : to make a global variable -- {!Cil.makeTempVar} : to make a temporary local variable whose name -will be generated so that to avoid conflict with other locals. -- {!Cil.makeLocalVar} : like {!Cil.makeTempVar} but you can specify the -exact name to be used. -- {!Cil.copyVarinfo}: make a shallow copy of a varinfo assigning a new name -and a new unique identifier + torig_name: string; (** original name as found in C file. *) - A [varinfo] is also used in a function type to denote the list of formals. + mutable tname: string; + (** The name. Can be empty only in a [GType] when introducing a composite or + enumeration tag. If empty cannot be refered to from the file *) -*) + mutable ttype: typ; + (** The actual type. This includes the attributes that were present in the + typedef *) + + mutable treferenced: bool; (** [true] if used. Initially set to [false]. *) +} + +(* ************************************************************************* *) +(** {2 Variables} *) +(* ************************************************************************* *) + +(** Each local or global variable is represented by a unique + {!Cil_types.varinfo} structure. A global {!Cil_types.varinfo} can be + introduced with the [GVarDecl] or [GVar] or [GFun] globals. A local varinfo + can be introduced as part of a function definition {!Cil_types.fundec}. + + All references to a given global or local variable must refer to the same + copy of the [varinfo]. Each [varinfo] has a globally unique identifier that + can be used to index maps and hashtables (the name can also be used for this + purpose, except for locals from different functions). This identifier is + constructor using a global counter. + + It is very important that you construct [varinfo] structures using only one + of the following functions: + - {!Cil.makeGlobalVar} : to make a global variable + - {!Cil.makeTempVar} : to make a temporary local variable whose name + will be generated so that to avoid conflict with other locals. + - {!Cil.makeLocalVar} : like {!Cil.makeTempVar} but you can specify the + exact name to be used. + - {!Cil.copyVarinfo}: make a shallow copy of a varinfo assigning a new name + and a new unique identifier + + A [varinfo] is also used in a function type to denote the list of + formals. *) (** Information about a variable. @plugin development guide *) and varinfo = { - mutable vname: string; - (** The name of the variable. Cannot be empty. It is primarily your - * responsibility to ensure the uniqueness of a variable name. For local - * variables {!Cil.makeTempVar} helps you ensure that the name is unique. - *) - - vorig_name: string; - (** the original name of the variable. Need not be unique. *) - - mutable vtype: typ; - (** The declared type of the variable. *) - - mutable vattr: attributes; - (** A list of attributes associated with the variable.*) - mutable vstorage: storage; - (** The storage-class *) - - mutable vglob: bool; - (** True if this is a global variable*) - - mutable vdefined: bool; - (** True if the variable or function is defined in the file. - * Only relevant for functions and global variables. - * Not used in particular for local variables and logic variables. *) - - mutable vformal: bool; - (** True if the variable is a formal parameter of a function. *) - - mutable vinline: bool; - (** Whether this varinfo is for an inline function. *) - - mutable vdecl: location; - (** Location of variable declaration. *) - - mutable vid: int; - (** A unique integer identifier. This field will be - * set for you if you use one of the {!Cil.makeFormalVar}, - * {!Cil.makeLocalVar}, {!Cil.makeTempVar}, {!Cil.makeGlobalVar}, or - * {!Cil.copyVarinfo}. *) - - mutable vaddrof: bool; - (** True if the address of this variable is taken. CIL will set these - * flags when it parses C, but you should make sure to set the flag - * whenever your transformation create [AddrOf] expression. *) - - mutable vreferenced: bool; - (** True if this variable is ever referenced. This is computed by - * [removeUnusedVars]. It is safe to just initialize this to False *) - - vgenerated: bool; - (** true for temporary variables generated by CIL normalization. - false for variables coming directly from user input. - *) - - mutable vdescr: string option; (** For most temporary variables, a - description of what the var holds. - (e.g. for temporaries used for - function call results, this string - is a representation of the function - call.) *) - - mutable vdescrpure: bool; (** Indicates whether the vdescr above - is a pure expression or call. - True for all CIL expressions and - Lvals, but false for e.g. function - calls. - Printing a non-pure vdescr more - than once may yield incorrect - results. *) + mutable vname: string; + (** The name of the variable. Cannot be empty. It is primarily your + responsibility to ensure the uniqueness of a variable name. For local + variables {!Cil.makeTempVar} helps you ensure that the name is + unique. *) + + vorig_name: string; + (** the original name of the variable. Need not be unique. *) + + mutable vtype: typ; + (** The declared type of the variable. *) + + mutable vattr: attributes; + (** A list of attributes associated with the variable.*) + + mutable vstorage: storage; + (** The storage-class *) + + mutable vglob: bool; + (** True if this is a global variable*) + + mutable vdefined: bool; + (** True if the variable or function is defined in the file. Only relevant + for functions and global variables. Not used in particular for local + variables and logic variables. *) + + mutable vformal: bool; + (** True if the variable is a formal parameter of a function. *) + + mutable vinline: bool; + (** Whether this varinfo is for an inline function. *) + + mutable vdecl: location; + (** Location of variable declaration. *) + + mutable vid: int; + (** A unique integer identifier. This field will be set for you if you use + one of the {!Cil.makeFormalVar}, {!Cil.makeLocalVar}, + {!Cil.makeTempVar}, {!Cil.makeGlobalVar}, or {!Cil.copyVarinfo}. *) + + mutable vaddrof: bool; + (** [true] if the address of this variable is taken. CIL will set these + flags when it parses C, but you should make sure to set the flag + whenever your transformation create [AddrOf] expression. *) + + mutable vreferenced: bool; + (** [true] if this variable is ever referenced. This is computed by + [removeUnusedVars]. It is safe to just initialize this to [false]. *) + + vgenerated: bool; + (** [true] for temporary variables generated by CIL normalization. [false] + for variables coming directly from user input. *) + + mutable vdescr: string option; + (** For most temporary variables, a description of what the var holds. + (e.g. for temporaries used for function call results, this string is a + representation of the function call.) *) + + mutable vdescrpure: bool; + (** Indicates whether the vdescr above is a pure expression or call. True + for all CIL expressions and Lvals, but false for e.g. function calls. + Printing a non-pure vdescr more than once may yield incorrect + results. *) - mutable vghost: bool; (** Indicates if the variable is declared in ghost code *) + mutable vghost: bool; + (** Indicates if the variable is declared in ghost code *) - vlogic: bool; - (** False if this variable is a C variable. *) + vlogic: bool; + (** [false] iff this variable is a C variable. *) - mutable vlogic_var_assoc: logic_var option - (** logic variable representing this variable in the logic world*) + mutable vlogic_var_assoc: logic_var option +(** logic variable representing this variable in the logic world*) } (** Storage-class information *) @@ -553,91 +591,91 @@ | Register | Extern +(* ************************************************************************* *) +(** {2 Expressions} *) +(* ************************************************************************* *) + +(** The CIL expression language contains only the side-effect free expressions + of C. They are represented as the type {!Cil_types.exp}. There are several + interesting aspects of CIL expressions: + + Integer and floating point constants can carry their textual representation. + This way the integer 15 can be printed as 0xF if that is how it occurred in + the source. + + CIL uses 64 bits to represent the integer constants and also stores the + width of the integer type. Care must be taken to ensure that the constant is + representable with the given width. Use the functions {!Cil.kinteger}, + {!Cil.kinteger64} and {!Cil.integer} to construct constant expressions. CIL + predefines the constants {!Cil.zero}, {!Cil.one} and {!Cil.mone} (for -1). + + Use the functions {!Cil.isConstant} and {!Cil.isInteger} to test if an + expression is a constant and a constant integer respectively. + + CIL keeps the type of all unary and binary expressions. You can think of + that type qualifying the operator. Furthermore there are different operators + for arithmetic and comparisons on arithmetic types and on pointers. + + Another unusual aspect of CIL is that the implicit conversion between an + expression of array type and one of pointer type is made explicit, using the + [StartOf] expression constructor (which is not printed). If you apply the + [AddrOf}]constructor to an lvalue of type [T] then you will be getting an + expression of type [TPtr(T)]. -(** {b Expressions.} The CIL expression language contains only the side-effect free expressions of -C. They are represented as the type {!Cil_types.exp}. There are several -interesting aspects of CIL expressions: - - Integer and floating point constants can carry their textual representation. -This way the integer 15 can be printed as 0xF if that is how it occurred in the -source. - - CIL uses 64 bits to represent the integer constants and also stores the width -of the integer type. Care must be taken to ensure that the constant is -representable with the given width. Use the functions {!Cil.kinteger}, -{!Cil.kinteger64} and {!Cil.integer} to construct constant -expressions. CIL predefines the constants {!Cil.zero}, -{!Cil.one} and {!Cil.mone} (for -1). - - Use the functions {!Cil.isConstant} and {!Cil.isInteger} to test if -an expression is a constant and a constant integer respectively. - - CIL keeps the type of all unary and binary expressions. You can think of that -type qualifying the operator. Furthermore there are different operators for -arithmetic and comparisons on arithmetic types and on pointers. - - Another unusual aspect of CIL is that the implicit conversion between an -expression of array type and one of pointer type is made explicit, using the -[StartOf] expression constructor (which is not printed). If you apply the -[AddrOf}]constructor to an lvalue of type [T] then you will be getting an -expression of type [TPtr(T)]. + You can find the type of an expression with {!Cil.typeOf}. - You can find the type of an expression with {!Cil.typeOf}. - - You can perform constant folding on expressions using the function -{!Cil.constFold}. -*) + You can perform constant folding on expressions using the function + {!Cil.constFold}. *) (** Expressions (Side-effect free)*) -and exp = { eid: int; (** unique identifier *) - enode: exp_node; (** the expression itself *) - eloc: location; (** location of the expression. *) - } +and exp = { + eid: int; (** unique identifier *) + enode: exp_node; (** the expression itself *) + eloc: location; (** location of the expression. *) +} and exp_node = - Const of constant (** Constant *) + | Const of constant (** Constant *) | Lval of lval (** Lvalue *) | SizeOf of typ - (** sizeof(). Has [unsigned int] type (ISO 6.5.3.4). This is not - * turned into a constant because some transformations might want to - * change types *) + (** sizeof(). Has [unsigned int] type (ISO 6.5.3.4). This is not + turned into a constant because some transformations might want to change + types *) - | SizeOfE of exp - (** sizeof() *) + | SizeOfE of exp (** sizeof() *) | SizeOfStr of string - (** sizeof(string_literal). We separate this case out because this is the - * only instance in which a string literal should not be treated as - * having type pointer to character. *) + (** sizeof(string_literal). We separate this case out because this is the + only instance in which a string literal should not be treated as having + type pointer to character. *) | AlignOf of typ - (** This corresponds to the GCC __alignof_. Has [unsigned int] type *) - | AlignOfE of exp + (** This corresponds to the GCC __alignof_. Has [unsigned int] type *) + | AlignOfE of exp | UnOp of unop * exp * typ - (** Unary operation. Includes the type of the result. *) + (** Unary operation. Includes the type of the result. *) | BinOp of binop * exp * exp * typ - (** Binary operation. Includes the type of the result. The arithmetic - * conversions are made explicit for the arguments. *) + (** Binary operation. Includes the type of the result. The arithmetic + conversions are made explicit for the arguments. *) | CastE of typ * exp - (** Use {!Cil.mkCast} to make casts. *) + (** Use {!Cil.mkCast} to make casts. *) | AddrOf of lval - (** Always use {!Cil.mkAddrOf} to construct one of these. Apply to an - * lvalue of type [T] yields an expression of type [TPtr(T)] *) + (** Always use {!Cil.mkAddrOf} to construct one of these. Apply to an lvalue + of type [T] yields an expression of type [TPtr(T)] *) | StartOf of lval - (** Conversion from an array to a pointer to the beginning of the array. - * Given an lval of type [TArray(T)] produces an expression of type - * [TPtr(T)]. In C this operation is implicit, the [StartOf] operator is - * not printed. We have it in CIL because it makes the typing rules - * simpler. *) + (** Conversion from an array to a pointer to the beginning of the array. + Given an lval of type [TArray(T)] produces an expression of type + [TPtr(T)]. In C this operation is implicit, the [StartOf] operator is not + printed. We have it in CIL because it makes the typing rules simpler. *) | Info of exp * exp_info - (** Additional information on the underlying expression *) +(** Additional information on the underlying expression *) (** Additional information on an expression *) and exp_info = { @@ -645,468 +683,466 @@ exp_name: string list; } -(** {b Constants.} *) +(* ************************************************************************* *) +(** {2 Constants} *) +(* ************************************************************************* *) (** Literal constants *) and constant = - | CInt64 of int64 * ikind * string option - (** Integer constant. Give the ikind (see ISO9899 6.1.3.2) and the - * textual representation. Textual representation is always set to Some s - * when it comes from user code. This allows us to print a - * constant as it was represented in the code, for example, - * 0xF instead of 15. It is usually None for constant generated by Cil - * itself. Use {!Cil.integer} or {!Cil.kinteger} to create these. - * TODO: Use big integers, as int64 can not handle all possible constant - * (128 bit long long or 64 bit unsigned long) - *) + | CInt64 of My_bigint.t * ikind * string option + (** Integer constant. Give the ikind (see ISO9899 6.1.3.2) and the + textual representation. Textual representation is always set to Some s + when it comes from user code. This allows us to print a + constant as it was represented in the code, for example, + 0xF instead of 15. It is usually None for constant generated by Cil + itself. Use {!Cil.integer} or {!Cil.kinteger} to create these. *) + | CStr of string - (** String constant. The escape characters inside the string have been - * already interpreted. This constant has pointer to character type! The - * only case when you would like a string literal to have an array type - * is when it is an argument to sizeof. In that case you should use - * SizeOfStr. *) + (** String constant. The escape characters inside the string have been already + interpreted. This constant has pointer to character type! The only case + when you would like a string literal to have an array type is when it is + an argument to sizeof. In that case you should use SizeOfStr. *) + | CWStr of int64 list - (** Wide character string constant. Note that the local interpretation - * of such a literal depends on {!Cil.theMachine.wcharType} and - * {!Cil.theMachine.wcharKind}. - * Such a constant has type pointer to {!Cil.theMachine.wcharType}. The - * escape characters in the string have not been "interpreted" in - * the sense that L"A\xabcd" remains "A\xabcd" rather than being - * represented as the wide character list with two elements: 65 and - * 43981. That "interpretation" depends on the underlying wide - * character type. *) + (** Wide character string constant. Note that the local interpretation of such + a literal depends on {!Cil.theMachine.wcharType} and + {!Cil.theMachine.wcharKind}. Such a constant has type pointer to + {!Cil.theMachine.wcharType}. The escape characters in the string have not + been "interpreted" in the sense that L"A\xabcd" remains "A\xabcd" rather + than being represented as the wide character list with two elements: 65 + and 43981. That "interpretation" depends on the underlying wide character + type. *) + | CChr of char - (** Character constant. This has type int, so use charConstToInt - * to read the value in case sign-extension is needed. *) + (** Character constant. This has type int, so use charConstToInt to read the + value in case sign-extension is needed. *) + | CReal of float * fkind * string option - (** Floating point constant. Give the fkind (see ISO 6.4.4.2) and also - * the textual representation, if available. *) + (** Floating point constant. Give the fkind (see ISO 6.4.4.2) and also the + textual representation, if available. *) + | CEnum of enumitem - (** An enumeration constant - * Use [Cillower.lowerEnumVisitor] to replace these with integer - * constants. *) +(** An enumeration constant. Use [Cillower.lowerEnumVisitor] to replace these + with integer constants. *) (** Unary operators *) and unop = - Neg (** Unary minus *) - | BNot (** Bitwise complement (~) *) - | LNot (** Logical Not (!) *) + Neg (** Unary minus *) + | BNot (** Bitwise complement (~) *) + | LNot (** Logical Not (!) *) (** Binary operations *) and binop = - PlusA (** arithmetic + *) - | PlusPI (** pointer + integer *) - | IndexPI (** pointer + integer but only when - * it arises from an expression - * [e\[i\]] when [e] is a pointer and - * not an array. This is semantically - * the same as PlusPI but CCured uses - * this as a hint that the integer is - * probably positive. *) - | MinusA (** arithmetic - *) - | MinusPI (** pointer - integer *) - | MinusPP (** pointer - pointer *) - | Mult (** * *) - | Div (** / *) - | Mod (** % *) - | Shiftlt (** shift left *) - | Shiftrt (** shift right *) - - | Lt (** < (arithmetic comparison) *) - | Gt (** > (arithmetic comparison) *) - | Le (** <= (arithmetic comparison) *) - | Ge (** >= (arithmetic comparison) *) - | Eq (** == (arithmetic comparison) *) - | Ne (** != (arithmetic comparison) *) - | BAnd (** bitwise and *) - | BXor (** exclusive-or *) - | BOr (** inclusive-or *) - - | LAnd (** logical and. Unlike other - * expressions this one does not - * always evaluate both operands. If - * you want to use these, you must - * set {!Cil.useLogicalOperators}. *) - | LOr (** logical or. Unlike other - * expressions this one does not - * always evaluate both operands. If - * you want to use these, you must - * set {!Cil.useLogicalOperators}. *) - -(** {b Lvalues.} Lvalues are the sublanguage of expressions that can appear at the left of an assignment or as operand to the address-of operator. -In C the syntax for lvalues is not always a good indication of the meaning -of the lvalue. For example the C value -{v -a[0][1][2] - v} - might involve 1, 2 or 3 memory reads when used in an expression context, -depending on the declared type of the variable [a]. If [a] has type [int -\[4\]\[4\]\[4\]] then we have one memory read from somewhere inside the area -that stores the array [a]. On the other hand if [a] has type [int ***] then -the expression really means [* ( * ( * (a + 0) + 1) + 2)], in which case it is -clear that it involves three separate memory operations. - -An lvalue denotes the contents of a range of memory addresses. This range -is denoted as a host object along with an offset within the object. The -host object can be of two kinds: a local or global variable, or an object -whose address is in a pointer expression. We distinguish the two cases so -that we can tell quickly whether we are accessing some component of a -variable directly or we are accessing a memory location through a pointer. -To make it easy to -tell what an lvalue means CIL represents lvalues as a host object and an -offset (see {!Cil_types.lval}). The host object (represented as -{!Cil_types.lhost}) can be a local or global variable or can be the object -pointed-to by a pointer expression. The offset (represented as -{!Cil_types.offset}) is a sequence of field or array index designators. - - Both the typing rules and the meaning of an lvalue is very precisely -specified in CIL. - - The following are a few useful function for operating on lvalues: -- {!Cil.mkMem} - makes an lvalue of [Mem] kind. Use this to ensure -that certain equivalent forms of lvalues are canonized. -For example, [*&x = x]. -- {!Cil.typeOfLval} - the type of an lvalue -- {!Cil.typeOffset} - the type of an offset, given the type of the -host. -- {!Cil.addOffset} and {!Cil.addOffsetLval} - extend sequences -of offsets. -- {!Cil.removeOffset} and {!Cil.removeOffsetLval} - shrink sequences -of offsets. - -The following equivalences hold {v -Mem(AddrOf(Mem a, aoff)), off = Mem a, aoff + off -Mem(AddrOf(Var v, aoff)), off = Var v, aoff + off -AddrOf (Mem a, NoOffset) = a - v} *) + PlusA (** arithmetic + *) + | PlusPI (** pointer + integer *) + | IndexPI (** pointer + integer but only when it arises from an expression + [e\[i\]] when [e] is a pointer and + not an array. This is semantically + the same as PlusPI but CCured uses + this as a hint that the integer is + probably positive. *) + | MinusA (** arithmetic - *) + | MinusPI (** pointer - integer *) + | MinusPP (** pointer - pointer *) + | Mult (** * *) + | Div (** / *) + | Mod (** % *) + | Shiftlt (** shift left *) + | Shiftrt (** shift right *) + + | Lt (** < (arithmetic comparison) *) + | Gt (** > (arithmetic comparison) *) + | Le (** <= (arithmetic comparison) *) + | Ge (** >= (arithmetic comparison) *) + | Eq (** == (arithmetic comparison) *) + | Ne (** != (arithmetic comparison) *) + | BAnd (** bitwise and *) + | BXor (** exclusive-or *) + | BOr (** inclusive-or *) + + | LAnd (** logical and. Unlike other expressions this one does not always + evaluate both operands. If you want + to use these, you must set + {!Cil.useLogicalOperators}. *) + | LOr (** logical or. Unlike other expressions this one does not always + evaluate both operands. If you + want to use these, you must set + {!Cil.useLogicalOperators}. *) + +(* ************************************************************************* *) +(** {2 Left values} *) +(* ************************************************************************* *) + +(** Left values (aka Lvalues) are the sublanguage of expressions that can appear + at the left of an assignment or as operand to the address-of operator. In C + the syntax for lvalues is not always a good indication of the meaning of the + lvalue. For example the C value {v a[0][1][2] v} might involve 1, 2 or 3 + memory reads when used in an expression context, depending on the declared + type of the variable [a]. If [a] has type [int \[4\]\[4\]\[4\]] then we have + one memory read from somewhere inside the area that stores the array [a]. On + the other hand if [a] has type [int ***] then the expression really means [* + ( * ( * (a + 0) + 1) + 2)], in which case it is clear that it involves three + separate memory operations. + + An lvalue denotes the contents of a range of memory addresses. This range is + denoted as a host object along with an offset within the object. The host + object can be of two kinds: a local or global variable, or an object whose + address is in a pointer expression. We distinguish the two cases so that we + can tell quickly whether we are accessing some component of a variable + directly or we are accessing a memory location through a pointer. To make + it easy to tell what an lvalue means CIL represents lvalues as a host object + and an offset (see {!Cil_types.lval}). The host object (represented as + {!Cil_types.lhost}) can be a local or global variable or can be the object + pointed-to by a pointer expression. The offset (represented as + {!Cil_types.offset}) is a sequence of field or array index designators. + + Both the typing rules and the meaning of an lvalue is very precisely + specified in CIL. + + The following are a few useful function for operating on lvalues: + - {!Cil.mkMem} - makes an lvalue of [Mem] kind. Use this to ensure + that certain equivalent forms of lvalues are canonized. + For example, [*&x = x]. + - {!Cil.typeOfLval} - the type of an lvalue + - {!Cil.typeOffset} - the type of an offset, given the type of the + host. + - {!Cil.addOffset} and {!Cil.addOffsetLval} - extend sequences + of offsets. + - {!Cil.removeOffset} and {!Cil.removeOffsetLval} - shrink sequences + of offsets. + + The following equivalences hold {v + Mem(AddrOf(Mem a, aoff)), off = Mem a, aoff + off + Mem(AddrOf(Var v, aoff)), off = Var v, aoff + off + AddrOf (Mem a, NoOffset) = a + v} *) -and lval = - lhost * offset +and lval = lhost * offset (** The host part of an {!Cil_types.lval}. *) and lhost = | Var of varinfo - (** The host is a variable. *) + (** The host is a variable. *) | Mem of exp - (** The host is an object of type [T] when the expression has pointer - * [TPtr(T)]. *) +(** The host is an object of type [T] when the expression has pointer + [TPtr(T)]. *) -(** The offset part of an {!Cil_types.lval}. Each offset can be applied to certain - * kinds of lvalues and its effect is that it advances the starting address - * of the lvalue and changes the denoted type, essentially focussing to some - * smaller lvalue that is contained in the original one. +(** The offset part of an {!Cil_types.lval}. Each offset can be applied to + certain kinds of lvalues and its effect is that it advances the starting + address of the lvalue and changes the denoted type, essentially focussing + to some smaller lvalue that is contained in the original one. @plugin development guide *) and offset = - | NoOffset (** No offset. Can be applied to any lvalue and does - * not change either the starting address or the type. - * This is used when the lval consists of just a host - * or as a terminator in a list of other kinds of - * offsets. *) + | NoOffset + (** No offset. Can be applied to any lvalue and does not change either the + starting address or the type. This is used when the lval consists of just + a host or as a terminator in a list of other kinds of offsets. *) | Field of fieldinfo * offset - (** A field offset. Can be applied only to an lvalue - * that denotes a structure or a union that contains - * the mentioned field. This advances the offset to the - * beginning of the mentioned field and changes the - * type to the type of the mentioned field. *) + (** A field offset. Can be applied only to an lvalue that denotes a structure + or a union that contains the mentioned field. This advances the offset to + the beginning of the mentioned field and changes the type to the type of + the mentioned field. *) | Index of exp * offset - (** An array index offset. Can be applied only to an - * lvalue that denotes an array. This advances the - * starting address of the lval to the beginning of the - * mentioned array element and changes the denoted type - * to be the type of the array element *) - +(** An array index offset. Can be applied only to an lvalue that denotes an + array. This advances the starting address of the lval to the beginning of + the mentioned array element and changes the denoted type to be the type of + the array element *) + +(* ************************************************************************* *) +(** {2 Initializers} *) +(* ************************************************************************* *) + +(** A special kind of expressions are those that can appear as initializers for + global variables (initialization of local variables is turned into + assignments). The initializers are represented as type + {!Cil_types.init}. You can create initializers with {!Cil.makeZeroInit} and + you can conveniently scan compound initializers them with + {!Cil.foldLeftCompound}. *) -(** {b Initializers.} -A special kind of expressions are those that can appear as initializers for -global variables (initialization of local variables is turned into -assignments). The initializers are represented as type {!Cil_types.init}. You -can create initializers with {!Cil.makeZeroInit} and you can conveniently -scan compound initializers them with {!Cil.foldLeftCompound}. -*) (** Initializers for global variables. *) and init = | SingleInit of exp (** A single initializer *) | CompoundInit of typ * (offset * init) list - (** Used only for initializers of structures, unions and arrays. - * The offsets are all of the form [Field(f, NoOffset)] or - * [Index(i, NoOffset)] and specify the field or the index being - * initialized. For structures all fields - * must have an initializer (except the unnamed bitfields), in - * the proper order. This is necessary since the offsets are not - * printed. For arrays the list must contain a prefix of the - * initializers; the rest are 0-initialized. - * For unions there must be exactly one initializer. If - * the initializer is not for the first field then a field - * designator is printed, so you better be on GCC since MSVC does - * not understand this. You can scan an initializer list with - * {!Cil.foldLeftCompound}. *) +(** Used only for initializers of structures, unions and arrays. The offsets + are all of the form [Field(f, NoOffset)] or [Index(i, NoOffset)] and + specify the field or the index being initialized. For structures all fields + must have an initializer (except the unnamed bitfields), in the proper + order. This is necessary since the offsets are not printed. For arrays the + list must contain a prefix of the initializers; the rest are 0-initialized. + For unions there must be exactly one initializer. If the initializer is not + for the first field then a field designator is printed, so you better be on + GCC since MSVC does not understand this. You can scan an initializer list + with {!Cil.foldLeftCompound}. *) (** We want to be able to update an initializer in a global variable, so we - * define it as a mutable field *) -and initinfo = { - mutable init : init option; - } - -(** {b Function definitions.} -A function definition is always introduced with a [GFun] constructor at the -top level. All the information about the function is stored into a -{!Cil_types.fundec}. Some of the information (e.g. its name, type, -storage, attributes) is stored as a {!Cil_types.varinfo} that is a field of the -[fundec]. To refer to the function from the expression language you must use -the [varinfo]. - - The function definition contains, in addition to the body, a list of all the -local variables and separately a list of the formals. Both kind of variables -can be referred to in the body of the function. The formals must also be shared -with the formals that appear in the function type. For that reason, to -manipulate formals you should use the provided functions -{!Cil.makeFormalVar} and {!Cil.setFormals}. -*) + define it as a mutable field *) +and initinfo = { mutable init : init option } + +(* ************************************************************************* *) +(** {2 Function definitions} *) +(* ************************************************************************* *) + +(** A function definition is always introduced with a [GFun] constructor at the + top level. All the information about the function is stored into a + {!Cil_types.fundec}. Some of the information (e.g. its name, type, storage, + attributes) is stored as a {!Cil_types.varinfo} that is a field of the + [fundec]. To refer to the function from the expression language you must use + the [varinfo]. + + The function definition contains, in addition to the body, a list of all the + local variables and separately a list of the formals. Both kind of variables + can be referred to in the body of the function. The formals must also be + shared with the formals that appear in the function type. For that reason, + to manipulate formals you should use the provided functions + {!Cil.makeFormalVar} and {!Cil.setFormals}. *) + (** Function definitions. @plugin development guide *) -and fundec = - { mutable svar: varinfo; - (** Holds the name and type as a variable, so we can refer to it - * easily from the program. All references to this function either - * in a function call or in a prototype must point to the same - * [varinfo]. *) - mutable sformals: varinfo list; - (** Formals. These must be in the same order and with the same - * information as the formal information in the type of the function. - * Use {!Cil.setFormals} or - * {!Cil.setFunctionType} to set these formals and ensure that they - * are reflected in the function type. Do not make copies of these - * because the body refers to them. *) - mutable slocals: varinfo list; - (** Locals. Does NOT include the sformals. Do not make copies of - * these because the body refers to them. *) - mutable smaxid: int; (** Max local id. Starts at 0. Used for - * creating the names of new temporary - * variables. Updated by - * {!Cil.makeLocalVar} and - * {!Cil.makeTempVar}. You can also use - * {!Cil.setMaxId} to set it after you - * have added the formals and locals. *) - mutable sbody: block; (** The function body. *) - mutable smaxstmtid: int option; (** max id of a (reachable) statement - * in this function, if we have - * computed it. range = 0 ... - * (smaxstmtid-1). This is computed by - * {!Cil.computeCFGInfo}. *) - mutable sallstmts: stmt list; (** After you call {!Cil.computeCFGInfo} - * this field is set to contain all - * statements in the function *) - mutable sspec: funspec; - } +and fundec = { + mutable svar: varinfo; + (** Holds the name and type as a variable, so we can refer to it easily + from the program. All references to this function either in a function + call or in a prototype must point to the same [varinfo]. *) + + mutable sformals: varinfo list; + (** Formals. These must be in the same order and with the same information + as the formal information in the type of the function. Use + {!Cil.setFormals} or {!Cil.setFunctionType} to set these formals and + ensure that they are reflected in the function type. Do not make + copies of these because the body refers to them. *) + + mutable slocals: varinfo list; + (** Locals. Does NOT include the sformals. Do not make copies of these + because the body refers to them. *) + + mutable smaxid: int; + (** Max local id. Starts at 0. Used for creating the names of new + temporary variables. Updated by {!Cil.makeLocalVar} and + {!Cil.makeTempVar}. You can also use {!Cil.setMaxId} to set it after + you have added the formals and locals. *) + + mutable sbody: block; (** The function body. *) + + mutable smaxstmtid: int option; + (** max id of a (reachable) statement in this function, if we have + computed it. range = 0 ... (smaxstmtid-1). This is computed by + {!Cfg.computeCFGInfo}. *) + + mutable sallstmts: stmt list; + (** After you call {!Cfg.computeCFGInfo} this field is set to contain all + statements in the function. *) + mutable sspec: funspec; +} (** A block is a sequence of statements with the control falling through from one element to the next *) -and block = - { mutable battrs: attributes; (** Attributes for the block *) - mutable blocals: varinfo list; (** variables that are local to - the block. It is a subset of the - slocals of the enclosing function. - *) - mutable bstmts: stmt list; (** The statements comprising the block*) - } - -(** {b Statements}. -CIL statements are the structural elements that make the CFG. They are -represented using the type {!Cil_types.stmt}. Every -statement has a (possibly empty) list of labels. The -{!Cil_types.stmtkind} field of a statement indicates what kind of statement it -is. - - Use {!Cil.mkStmt} to make a statement and the fill-in the fields. - -CIL also comes with support for control-flow graphs. The [sid] field in -[stmt] can be used to give unique numbers to statements, and the [succs] -and [preds] fields can be used to maintain a list of successors and -predecessors for every statement. The CFG information is not computed by -default. Instead you must explicitly use the functions -{!Cil.prepareCFG} and {!Cil.computeCFGInfo} to do it. +and block = { + mutable battrs: attributes; (** Attributes for the block *) + + mutable blocals: varinfo list; + (** variables that are local to the block. It is a subset of the slocals of + the enclosing function. *) + + mutable bstmts: stmt list; (** The statements comprising the block. *) +} + +(* ************************************************************************* *) +(** {2 Statements} *) +(* ************************************************************************* *) + +(** CIL statements are the structural elements that make the CFG. They are + represented using the type {!Cil_types.stmt}. Every statement has a + (possibly empty) list of labels. The {!Cil_types.stmtkind} field of a + statement indicates what kind of statement it is. + + Use {!Cil.mkStmt} to make a statement and the fill-in the fields. + + CIL also comes with support for control-flow graphs. The [sid] field in + [stmt] can be used to give unique numbers to statements, and the [succs] and + [preds] fields can be used to maintain a list of successors and predecessors + for every statement. The CFG information is not computed by default. Instead + you must explicitly use the functions {!Cfg.prepareCFG} and + {!Cfg.computeCFGInfo} to do it. *) -*) (** Statements. @plugin development guide *) and stmt = { - mutable labels: label list; - (** Whether the statement starts with some labels, case statements or - * default statements. *) - - mutable skind: stmtkind; - (** The kind of statement *) - - mutable sid: int; - (** A number (>= 0) that is unique in a function. Filled in only after - * the CFG is computed. *) - mutable succs: stmt list; - (** The successor statements. They can always be computed from the skind - * and the context in which this statement appears. Filled in only after - * the CFG is computed. *) - mutable preds: stmt list; - (** The inverse of the succs function. *) + mutable labels: label list; + (** Whether the statement starts with some labels, case statements or + default statements. *) + + mutable skind: stmtkind; + (** The kind of statement *) + + mutable sid: int; + (** A number (>= 0) that is unique in a function. Filled in only after the + CFG is computed. *) + + mutable succs: stmt list; + (** The successor statements. They can always be computed from the skind and + the context in which this statement appears. Filled in only after the CFG + is computed. *) - mutable ghost : bool - } + mutable preds: stmt list; + (** The inverse of the succs function. *) + + mutable ghost : bool +} (** Labels *) and label = - Label of string * location * bool - (** A real label. If the bool is "true", the label is from the - * input source program. If the bool is "false", the label was - * created by CIL or some other transformation *) - | Case of exp * location (** A case statement. This expression - * is lowered into a constant if - * {!Cil.lowerConstants} is set to - * true. *) - | Default of location (** A default statement *) - + | Label of string * location * bool + (** A real label. If the bool is "true", the label is from the input source + program. If the bool is "false", the label was created by CIL or some + other transformation *) + + | Case of exp * location + (** A case statement. This expression is lowered into a constant if + {!Cil.lowerConstants} is set to [true]. *) + | Default of location (** A default statement *) (* The various kinds of statements *) and stmtkind = | Instr of instr - (** An instruction that does not contain control flow. Control - * implicitly falls through. *) + (** An instruction that does not contain control flow. Control implicitly + falls through. *) | Return of exp option * location - (** The return statement. This is a leaf in the CFG. *) + (** The return statement. This is a leaf in the CFG. *) | Goto of stmt ref * location - (** A goto statement. Appears from actual goto's in the code or from - * goto's that have been inserted during elaboration. The reference - * points to the statement that is the target of the Goto. This means that - * you have to update the reference whenever you replace the target - * statement. The target statement MUST have at least a label. *) + (** A goto statement. Appears from actual goto's in the code or from goto's + that have been inserted during elaboration. The reference points to the + statement that is the target of the Goto. This means that you have to + update the reference whenever you replace the target statement. The + target statement MUST have at least a label. *) | Break of location - (** A break to the end of the nearest enclosing Loop or Switch *) + (** A break to the end of the nearest enclosing Loop or Switch *) | Continue of location - (** A continue to the start of the nearest enclosing [Loop] *) + (** A continue to the start of the nearest enclosing [Loop] *) + | If of exp * block * block * location - (** A conditional. Two successors, the "then" and the "else" branches. - * Both branches fall-through to the successor of the If statement. *) + (** A conditional. Two successors, the "then" and the "else" branches. Both + branches fall-through to the successor of the If statement. *) | Switch of exp * block * (stmt list) * location - (** A switch statement. The statements that implement the cases can be - * reached through the provided list. For each such target you can find - * among its labels what cases it implements. The statements that - * implement the cases are somewhere within the provided [block]. *) - - | Loop of code_annotation list * - block * location * (stmt option) * (stmt option) - (** A [while(1)] loop. The termination test is implemented in the body of - * a loop using a [Break] statement. If prepareCFG has been called, - * the first stmt option will point to the stmt containing the continue - * label for this loop and the second will point to the stmt containing - * the break label for this loop. *) + (** A switch statement. The statements that implement the cases can be reached + through the provided list. For each such target you can find among its + labels what cases it implements. The statements that implement the cases + are somewhere within the provided [block]. *) + + | Loop of + code_annotation list * block * location * (stmt option) * (stmt option) + (** A [while(1)] loop. The termination test is implemented in the body of a + loop using a [Break] statement. If {!Cfg.prepareCFG} has been called, the + first stmt option will point to the stmt containing the continue label + for this loop and the second will point to the stmt containing the break + label for this loop. *) | Block of block - (** Just a block of statements. Use it as a way to keep some block - * attributes local *) + (** Just a block of statements. Use it as a way to keep some block attributes + local *) | UnspecifiedSequence of (stmt * lval list * lval list * lval list * stmt ref list) list - (** statements whose order of execution is not specified by - ISO/C. This is important for the order of side effects - during evaluation of expressions. Each statement comes - together with three list of lval - - lvals that are written during the sequence and whose future - value depends upon the statement (it is legal to read from them) - - lvals that are written during the evaluation of the statement itself - - lval that are read. - - Function calls in the corresponding statement - Note that this include only a subset of the affectations - of the statement. Namely, the - temporary variables generated by cil are excluded (i.e. it - is assumed that the "compilation" is correct). In addition, - side effects caused by function applications are not taken - into account in the list. For a single statement, the written lvals - are supposed to be ordered (or their order of evaluation doesn't - matter), so that an alarm should be emitted only if the lvals read by - a statement overlap with the lvals written (or read) by another - statement of the sequence. + (** statements whose order of execution is not specified by + ISO/C. This is important for the order of side effects + during evaluation of expressions. Each statement comes + together with three list of lval + - lvals that are written during the sequence and whose future + value depends upon the statement (it is legal to read from them) + - lvals that are written during the evaluation of the statement itself + - lval that are read. + - Function calls in the corresponding statement + Note that this include only a subset of the affectations + of the statement. Namely, the + temporary variables generated by cil are excluded (i.e. it + is assumed that the "compilation" is correct). In addition, + side effects caused by function applications are not taken + into account in the list. For a single statement, the written lvals + are supposed to be ordered (or their order of evaluation doesn't + matter), so that an alarm should be emitted only if the lvals read by + a statement overlap with the lvals written (or read) by another + statement of the sequence. - At this time this feature is - experimental and may miss some unspecified sequences. + At this time this feature is + experimental and may miss some unspecified sequences. + + In case you do not care about this feature just handle it + like a block (see {!Cil.block_from_unspecified_sequence}) *) - In case you do not care about this feature just handle it - like a block (see {!Cil.block_from_unspecified_sequence}) *) | TryFinally of block * block * location - (** On MSVC we support structured exception handling. This is what you - * might expect. Control can get into the finally block either from the - * end of the body block, or if an exception is thrown. *) + (** On MSVC we support structured exception handling. This is what you might + expect. Control can get into the finally block either from the end of the + body block, or if an exception is thrown. *) | TryExcept of block * (instr list * exp) * block * location - (** On MSVC we support structured exception handling. The try/except - * statement is a bit tricky: -{v __try \{ blk \} - __except (e) \{ - handler - \} -v} - - The argument to __except must be an expression. However, we keep a - list of instructions AND an expression in case you need to make - function calls. We'll print those as a comma expression. The control - can get to the __except expression only if an exception is thrown. - After that, depending on the value of the expression the control - goes to the handler, propagates the exception, or retries the - exception !!! The location corresponds to the try keyword. - *) - +(** On MSVC we support structured exception handling. The try/except + statement is a bit tricky: + {v __try \{ blk \} + __except (e) \{ + handler + \} + v} + + The argument to __except must be an expression. However, we keep a + list of instructions AND an expression in case you need to make + function calls. We'll print those as a comma expression. The control + can get to the __except expression only if an exception is thrown. + After that, depending on the value of the expression the control + goes to the handler, propagates the exception, or retries the + exception. The location corresponds to the try keyword. *) (** Instructions. They may cause effects directly but may not have control flow.*) and instr = - Set of lval * exp * location (** An assignment. A cast is present - if the exp has different type - from lval *) - | Call of lval option * exp * exp list * location - (** optional: result is an lval. A cast might be - necessary if the declared result type of the - function is not the same as that of the - destination. If the function is declared then - casts are inserted for those arguments that - correspond to declared formals. (The actual - number of arguments might be smaller or larger - than the declared number of arguments. C allows - this.) If the type of the result variable is not - the same as the declared type of the function - result then an implicit cast exists. *) - - (* See the GCC specification for the meaning of ASM. - * If the source is MS VC then only the templates - * are used *) - (* sm: I've added a notes.txt file which contains more - * information on interpreting Asm instructions *) - | Asm of attributes * (* Really only const and volatile can appear - * here *) - string list * (* templates (CR-separated) *) - (string option * string * lval) list * - (* outputs must be lvals with - * optional names and constraints. - * I would like these - * to be actually variables, but I - * run into some trouble with ASMs - * in the Linux sources *) - (string option * string * exp) list * - (* inputs with optional names and constraints *) - string list * (* register clobbers *) - location - (** An inline assembly instruction. The arguments are (1) a list of - attributes (only const and volatile can appear here and only for - GCC), (2) templates (CR-separated), (3) a list of - outputs, each of which is an lvalue with a constraint, (4) a list - of input expressions along with constraints, (5) clobbered - registers, and (5) location information *) + | Set of lval * exp * location + (** An assignment. A cast is present if the exp has different type from + lval *) + + | Call of lval option * exp * exp list * location + (** optional: result is an lval. A cast might be necessary if the declared + result type of the function is not the same as that of the destination. If + the function is declared then casts are inserted for those arguments that + correspond to declared formals. (The actual number of arguments might be + smaller or larger than the declared number of arguments. C allows this.) + If the type of the result variable is not the same as the declared type of + the function result then an implicit cast exists. *) + + (* See the GCC specification for the meaning of ASM. + If the source is MS VC then only the templates + are used. + + [sm] I've added a notes.txt file which contains more + information on interpreting Asm instructions *) + | Asm of + attributes (* Really only const and volatile can appear here *) + * string list (* templates (CR-separated) *) + * (string option * string * lval) list + (* outputs must be lvals with optional names and constraints. I would + like these to be actually variables, but I run into some trouble with + ASMs in the Linux sources *) + * (string option * string * exp) list + (* inputs with optional names and constraints *) + * string list (* register clobbers *) + * location + (** An inline assembly instruction. The arguments are + (1) a list of attributes (only const and volatile can appear here and only + for GCC) + (2) templates (CR-separated) + (3) a list of outputs, each of which is an lvalue with optional names and + constraints. + (4) a list of input expressions along with constraints + (5) clobbered registers + (6) location information *) | Skip of location @@ -1118,14 +1154,14 @@ (** Type signatures. Two types are identical iff they have identical signatures *) and typsig = - TSArray of typsig * int64 option * attribute list + | TSArray of typsig * string option (* stands for the size *) * attribute list | TSPtr of typsig * attribute list | TSComp of bool * string * attribute list | TSFun of typsig * typsig list * bool * attribute list | TSEnum of string * attribute list | TSBase of typ -(** Abstract syntax trees for annotations *) +(** {1 Abstract syntax trees for annotations} *) (** Types of logic terms. *) and logic_type = @@ -1139,17 +1175,22 @@ (** tsets with an unique identifier. Use [Logic_const.new_location] to generate a new id. *) -and identified_term = - { it_id: int; (** the identifier. *) - it_content: term (** the term *) - } +and identified_term = { + it_id: int; (** the identifier. *) + it_content: term (** the term *) +} (** logic label referring to a particular program point. *) and logic_label = | StmtLabel of stmt ref (** label of a C statement. *) - | LogicLabel of (stmt option * string) (** builtin logic label ({t Here, Pre}, ...) *) + | LogicLabel of (stmt option * string) (* [JS 2011/05/13] why a tuple here? *) +(** builtin logic label ({t Here, Pre}, ...) *) + +(* ************************************************************************* *) +(** {2 Terms} *) +(* ************************************************************************* *) -(* Expressions follow CIL constructs (with prefix T) *) +(** C Expressions as logic terms follow C constructs (with prefix T) *) (** Logic terms. *) and term = { @@ -1175,6 +1216,7 @@ | TCastE of typ * term (** cast to a C type. *) | TAddrOf of term_lval (** address of a term. *) | TStartOf of term_lval (** beginning of an array. *) + (* additional constructs *) | Tapp of logic_info * (logic_label * logic_label) list * term list (** application of a logic function. *) @@ -1183,7 +1225,6 @@ (** constructor of logic sum-type. *) | Tif of term * term * term (** conditional operator*) - | Told of term (** term refers to the pre-state of the function. *) | Tat of term * logic_label (** term refers to a particular program point. *) | Tbase_addr of term (** base address of a pointer. *) @@ -1200,8 +1241,7 @@ | Tinter of term list (** intersection of terms. *) | Tcomprehension of term * quantifiers * predicate named option - (** set defined in comprehension ({t \{ t[i] | integer i; 0 <= i < 5\}}) - *) + (** set defined in comprehension ({t \{ t[i] | integer i; 0 <= i < 5\}}) *) | Trange of term option * term option (** range of integers. *) | Tlet of logic_info * term (** local binding *) @@ -1241,19 +1281,18 @@ mutable l_body : logic_body; (** body of the function. *) } -and builtin_logic_info = - { mutable bl_name: string; - mutable bl_labels: logic_label list; - mutable bl_params: string list; - mutable bl_type: logic_type option; - mutable bl_profile: (string * logic_type) list; - } +and builtin_logic_info = { + mutable bl_name: string; + mutable bl_labels: logic_label list; + mutable bl_params: string list; + mutable bl_type: logic_type option; + mutable bl_profile: (string * logic_type) list; +} and logic_body = - | LBnone - (** no definition and no reads clause *) + | LBnone (** no definition and no reads clause *) | LBreads of identified_term list - (** read accesses performed by a function. *) + (** read accesses performed by a function. *) | LBterm of term (** direct definition of a function. *) | LBpred of predicate named (** direct definition of a predicate. *) | LBinductive of @@ -1261,13 +1300,13 @@ (** inductive definition *) (** description of a logic type*) -and logic_type_info = - { lt_name: string; - lt_params : string list; (** type parameters*) - mutable lt_def: logic_type_def option - (** definition of the type. None for abstract types. *) - } - (* will be expanded when dealing with concrete types *) +and logic_type_info = { + lt_name: string; + lt_params : string list; (** type parameters*) + mutable lt_def: logic_type_def option + (** definition of the type. None for abstract types. *) +} +(* will be expanded when dealing with concrete types *) and logic_type_def = | LTsum of logic_ctor_info list (** sum type with its constructors. *) @@ -1279,9 +1318,9 @@ mutable lv_name : string; (** name of the variable. *) mutable lv_id : int; (** unique identifier *) mutable lv_type : logic_type; (** type of the variable. *) - mutable lv_origin : varinfo option (** when the logic variable stems from a - C variable, set to the original C variable. - *) + mutable lv_origin : varinfo option +(** when the logic variable stems from a C variable, set to the original C + variable. *) } (** description of a constructor of a logic sum-type*) @@ -1289,10 +1328,12 @@ { ctor_name: string; (** name of the constructor. *) ctor_type: logic_type_info; (** type to which the constructor belongs. *) ctor_params: logic_type list - (** types of the parameters of the constructor. *) + (** types of the parameters of the constructor. *) } -(* Predicates *) +(* ************************************************************************* *) +(** {2 Predicates} *) +(* ************************************************************************* *) (** variables bound by a quantifier. *) and quantifiers = logic_var list @@ -1307,52 +1348,38 @@ | Papp of logic_info * (logic_label * logic_label) list * term list (** application of a predicate. *) | Pseparated of term list - | Prel of relation * term * term - (** comparison of two terms. *) - | Pand of predicate named * predicate named - (** conjunction *) - | Por of predicate named * predicate named - (** disjunction. *) - | Pxor of predicate named * predicate named - (** logical xor. *) - | Pimplies of predicate named * predicate named - (** implication. *) - | Piff of predicate named * predicate named - (** equivalence. *) - | Pnot of predicate named - (** negation. *) - | Pif of term * predicate named * predicate named - (** conditional *) - | Plet of logic_info * predicate named - (** definition of a local variable *) - | Pforall of quantifiers * predicate named - (** universal quantification. *) - | Pexists of quantifiers * predicate named - (** existential quantification. *) - | Pold of predicate named - (** predicate refers to the pre-state of a function. *) + | Prel of relation * term * term (** comparison of two terms. *) + | Pand of predicate named * predicate named (** conjunction *) + | Por of predicate named * predicate named (** disjunction. *) + | Pxor of predicate named * predicate named (** logical xor. *) + | Pimplies of predicate named * predicate named (** implication. *) + | Piff of predicate named * predicate named (** equivalence. *) + | Pnot of predicate named (** negation. *) + | Pif of term * predicate named * predicate named (** conditional *) + | Plet of logic_info * predicate named (** definition of a local variable *) + | Pforall of quantifiers * predicate named (** universal quantification. *) + | Pexists of quantifiers * predicate named (** existential quantification. *) | Pat of predicate named * logic_label - (** predicate refers to a particular program point. *) - | Pvalid of term - (** the given locations are valid. *) + (** predicate refers to a particular program point. *) + | Pvalid of term (** the given locations are valid. *) | Pvalid_index of term * term - (** {b deprecated:} Use [Pvalid(TLval(TBinOp(PlusPI,p,i)))] instead + (** {b deprecated:} Use [Pvalid(TLval(TBinOp(PlusPI,p,i)))] instead. [Pvalid_index(p,i)] indicates that accessing the [i]th element - of [p] is valid. - *) + of [p] is valid. *) | Pvalid_range of term * term * term (** {b deprecated:} Use [Pvalid(TLVal(TBinOp(PlusPI(p,Trange(i1,i2)))))] - instead + instead. similar to [Pvalid_index] but for a range of indices.*) + | Pinitialized of term (** the given locations are initialized. *) | Pfresh of term (** The given term is newly allocated in the post-state of a function.*) | Psubtype of term * term (** First term is a type tag that is a subtype of the second. *) -(** predicate with an unique identifier. -Use [Logic_const.new_predicate] to create fresh predicates *) +(** predicate with an unique identifier. Use [Logic_const.new_predicate] to + create fresh predicates *) and identified_predicate = { ip_name: string list; (** names given to the predicate if any.*) ip_loc: location; (** location in the source code. *) @@ -1364,9 +1391,9 @@ (** variant of a loop or a recursive function. Type shared with Logic_ptree. *) and 'term variant = 'term * string option -(** dependencies of an assigned location. Shared with Logic_ptree. *) +(** dependencies of an assigned location. Shared with Logic_ptree. *) and 'locs deps = - From of 'locs list (** tsets. Empty list means \nothing. *) + | From of 'locs list (** tsets. Empty list means \nothing. *) | FromAny (** Nothing specified. Any location can be involved. *) and 'locs from = ('locs * 'locs deps) @@ -1378,32 +1405,36 @@ (** list of locations that can be written. Empty list means \nothing. *) (** object that can be named (in particular predicates). *) -and 'a named = { name : string list; (** list of given names *) - loc : location; (** position in the source code. *) - content : 'a; (** content *) - } +and 'a named = { + name : string list; (** list of given names *) + loc : location; (** position in the source code. *) + content : 'a; (** content *) +} -(** function contract. Type shared with Logic_ptree. *) +(** Function contract. Type shared with Logic_ptree. *) and ('term,'pred,'locs) spec = { mutable spec_behavior : ('pred,'locs) behavior list; (** behaviors *) + mutable spec_variant : 'term variant option; (** variant for recursive functions. *) + mutable spec_terminates: 'pred option; (** termination condition. *) + mutable spec_complete_behaviors: string list list; (** list of complete behaviors. It is possible to have more than one set of complete behaviors *) + mutable spec_disjoint_behaviors: string list list; (** list of disjoint behaviors. It is possible to have more than one set of disjoint behaviors *) } -(** behavior of a function. Type shared with Logic_ptree. +(** Behavior of a function. Type shared with Logic_ptree. @since Carbon-20101201 [b_requires] has been added. @modify Boron-20100401 [b_ensures] is replaced by [b_post_cond]. - Old [b_ensures] represent the [Normal] case of [b_post_cond]. - *) + Old [b_ensures] represent the [Normal] case of [b_post_cond]. *) and ('pred,'locs) behavior = { mutable b_name : string; (** name of the behavior. *) mutable b_requires : 'pred list; (** require clauses. *) @@ -1411,68 +1442,59 @@ mutable b_post_cond : (termination_kind * 'pred) list; (** post-condition. *) mutable b_assigns : 'locs assigns; (** assignments. *) mutable b_extended : (string * int * 'pred list) list - (** Grammar extensions *) +(** Grammar extensions *) } -(** pragmas for the value analysis plugin of Frama-C. -Type shared with Logic_ptree.*) +(** Pragmas for the value analysis plugin of Frama-C. + Type shared with Logic_ptree.*) and 'term loop_pragma = | Unroll_level of 'term | Widen_hints of 'term list | Widen_variables of 'term list -(** pragmas for the slicing plugin of Frama-C. Type shared with Logic_ptree.*) +(** Pragmas for the slicing plugin of Frama-C. Type shared with Logic_ptree.*) and 'term slice_pragma = | SPexpr of 'term | SPctrl | SPstmt -(** pragmas for the impact plugin of Frama-C. Type shared with Logic_ptree.*) +(** Pragmas for the impact plugin of Frama-C. Type shared with Logic_ptree.*) and 'term impact_pragma = | IPexpr of 'term | IPstmt -(** the various kinds of pragmas. Type shared with Logic_ptree. *) +(** The various kinds of pragmas. Type shared with Logic_ptree. *) and 'term pragma = | Loop_pragma of 'term loop_pragma | Slice_pragma of 'term slice_pragma | Impact_pragma of 'term impact_pragma -(** Annotation status *) -and validity = True | False | Maybe -and annot_checked_status = { mutable emitter : string; - mutable valid : validity } -and annotation_status = | Unknown (* Nothing was ever tried to check it *) - | Checked of annot_checked_status (* Something was tried *) -and annot_status = { mutable status : annotation_status } (** all annotations that can be found in the code. Type shared with Logic_ptree. *) and ('term, 'pred, 'spec_pred, 'locs) code_annot = | AAssert of string list * 'pred - (** assertion to be checked. The list of strings is the list of - behaviors to which this assertion applies. - @deprecated since Beryllium-20090902, the annot_status - field is no longer updated by anyone. Use {!Db.Annotations.Status} - functions to access the true status. *) + (** assertion to be checked. The list of strings is the list of + behaviors to which this assertion applies. + @deprecated since Beryllium-20090902, the annot_status + field is no longer updated by anyone. Use {!Db.Annotations.Status} + functions to access the true status. *) + + | AStmtSpec of string list * ('term, 'spec_pred, 'locs) spec + (** statement contract eventualy for some behaviors. *) - | AStmtSpec of ('term, 'spec_pred, 'locs) spec (** statement contract. *) | AInvariant of string list * bool * 'pred - (** code invariant. The list of strings is the list of - behaviors to which this invariant applies. - The boolean flag is true for normal loop invariants - and false for invariant-as-assertions. - TODO: remove this constructor: - - normal loop invariants are now under constructor ALoopBehavior - - invariant-as-assertions should be just one variant of AAssert - *) - | AVariant of 'term variant (** loop variant. Note that - there can be at most one variant - associated to a given statement - *) + (** loop/code invariant. The list of strings is the list of behaviors to which + this invariant applies. The boolean flag is true for normal loop + invariants and false for invariant-as-assertions. *) + + | AVariant of 'term variant + (** loop variant. Note that there can be at most one variant associated to a + given statement *) + | AAssigns of string list * 'locs assigns - (** loop assigns. (see [b_assigns] in the behaviors for other assigns). - At most one clause associated to a given (statement, behavior) couple. - *) + (** loop assigns. (see [b_assigns] in the behaviors for other assigns). At + most one clause associated to a given (statement, behavior) couple. *) + | APragma of 'term pragma (** pragma. *) (** function contract. *) @@ -1481,11 +1503,12 @@ (** code annotation with an unique identifier. Use [Logic_const.new_code_annotation] to create new code annotations with a fresh id. *) -and code_annotation = - { annot_content : - (term, predicate named, identified_predicate, identified_term) - code_annot; (** content of the annotation. *) - annot_id: int (** identifier. *) } +and code_annotation = { + annot_id: int; (** identifier. *) + annot_content : + (term, predicate named, identified_predicate, identified_term) code_annot; + (** content of the annotation. *) +} (** behavior of a function. *) and funbehavior = (identified_predicate,identified_term) behavior @@ -1493,23 +1516,71 @@ (** global annotations, not attached to a statement or a function. *) and global_annotation = | Dfun_or_pred of logic_info * location + | Dvolatile of + identified_term list * varinfo option * varinfo option * location + (** associated terms, reading function, writing function *) | Daxiomatic of string * global_annotation list * location | Dtype of logic_type_info * location (** declaration of a logic type. *) | Dlemma of string * bool * logic_label list * string list * predicate named * location - (** definition of a lemma. The boolean flag is true if the property. - should be taken as an axiom and false if it must be proved. - *) + (** definition of a lemma. The boolean flag is [true] if the property should + be taken as an axiom and [false] if it must be proved. *) | Dinvariant of logic_info * location - (** global invariant. The predicate does not have any argument. *) + (** global invariant. The predicate does not have any argument. *) | Dtype_annot of logic_info * location - (** type invariant. The predicate has exactly one argument. *) + (** type invariant. The predicate has exactly one argument. *) + | Dmodel_annot of logic_info * location + (** Model field for a type t, seen as a logic function with one + argument of type t *) type kinstr = | Kstmt of stmt | Kglobal +(** Internal representation of decorated C functions *) +type cil_function = + | Definition of (fundec * location) (** defined function *) + | Declaration of (funspec * varinfo * varinfo list option * location) + (** Declaration(spec,f,args,loc) represents a leaf function [f] with + specification [spec] and arguments [args], at location [loc]. As + with the [TFun] constructor of {!Cil_types.typ}, the arg list is + optional, to distinguish [void f()] ([None]) from + [void f(void)] ([Some []]). *) + +type alarm = + | Division_alarm + | Memory_alarm + | Index_alarm + | Shift_alarm + | Pointer_compare_alarm + | Signed_overflow_alarm + | Using_nan_or_infinite_alarm + | Result_is_nan_or_infinite_alarm + | Separation_alarm + | Other_alarm + +type rooted_code_annotation = + | User of code_annotation + | AI of alarm*code_annotation + +(** Except field [fundec], do not use the other fields directly. + Prefer to use {!Kernel_function.find_return}, {!Kernel_function.get_spec} + or {!Kernel_function.set_spec}. + @plugin development guide *) +type kernel_function = { + mutable fundec : cil_function; + mutable return_stmt : stmt option; + mutable spec : funspec; +} + +(* [VP] TODO: VLocal should be attached to a particular block, not a whole + function. *) +type localisation = + | VGlobal + | VLocal of kernel_function + | VFormal of kernel_function + type mach = { version_major: int; (* Major version number *) version_minor: int; (* Minor version number *) @@ -1520,7 +1591,6 @@ sizeof_long: int ; (* Size of "long" *) sizeof_longlong: int; (* Size of "long long" *) sizeof_ptr: int; (* Size of pointers *) - sizeof_enum: int; (* Size of enum types *) sizeof_float: int; (* Size of "float" *) sizeof_double: int; (* Size of "double" *) sizeof_longdouble: int; (* Size of "long double" *) @@ -1529,13 +1599,11 @@ size_t: string; (* Type of "sizeof(T)" *) wchar_t: string; (* Type of "wchar_t" *) ptrdiff_t: string; (* Type of "ptrdiff_t" *) - enum_are_signed: bool; (* Sign of enum types *) alignof_short: int; (* Alignment of "short" *) alignof_int: int; (* Alignment of "int" *) alignof_long: int; (* Alignment of "long" *) alignof_longlong: int; (* Alignment of "long long" *) alignof_ptr: int; (* Alignment of pointers *) - alignof_enum: int; (* Alignment of enum types *) alignof_float: int; (* Alignment of "float" *) alignof_double: int; (* Alignment of "double" *) alignof_longdouble: int; (* Alignment of "long double" *) @@ -1545,10 +1613,11 @@ char_is_unsigned: bool; (* Whether "char" is unsigned *) const_string_literals: bool; (* Whether string literals have const chars *) little_endian: bool; (* whether the machine is little endian *) + alignof_aligned: int (* Alignment of a type with aligned attribute *) } (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/availexpslv.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/availexpslv.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/availexpslv.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/availexpslv.ml 2011-10-10 08:40:08.000000000 +0000 @@ -56,7 +56,7 @@ let time _ f c = f c end (*Stats*) -let debug = ref (Cilmsg.debug_atleast 2) +let debug = ref (Kernel.debug_atleast 2) let doTime = ref false @@ -114,7 +114,7 @@ (* the result must be the intersection of eh1 and eh2 *) (* exp IH.t -> exp IH.t -> exp IH.t *) let lvh_combine lvh1 lvh2 = - if !debug then Cilmsg.debug ~level:2 "lvh_combine: combining %a\n and\n %a" + if !debug then Kernel.debug ~level:2 "lvh_combine: combining %a\n and\n %a" lvh_pretty lvh1 lvh_pretty lvh2; let lvh' = LvExpHash.copy lvh1 in (* eh' gets all of eh1 *) LvExpHash.iter (fun lv e1 -> @@ -127,7 +127,7 @@ List.iter (fun e -> LvExpHash.add lvh' lv e) e1l' with Not_found -> LvExpHash.remove lvh' lv) lvh1; - if !debug then Cilmsg.debug "with result %a" lvh_pretty lvh'; + if !debug then Kernel.debug "with result %a" lvh_pretty lvh'; lvh' @@ -297,7 +297,7 @@ end | _ -> begin (* e is volatile *) (* must remove mapping for lv *) - if !debug then Cilmsg.debug "lvh_handle_inst: %a is volatile. killing %a" + if !debug then Kernel.debug "lvh_handle_inst: %a is volatile. killing %a" d_exp e d_lval lv; LvExpHash.remove lvh lv; lvh_kill_lval lvh lv; @@ -339,7 +339,7 @@ type t = exp LvExpHash.t module StmtStartData = - DF.StmtStartData(struct type t = exp LvExpHash.t let size = 64 end) + Dataflow.StartData(struct type t = exp LvExpHash.t let size = 64 end) let copy = LvExpHash.copy @@ -367,7 +367,7 @@ end -module AE = DF.ForwardsDataFlow(AvailableExps) +module AE = Dataflow.Forwards(AvailableExps) (* @@ -380,10 +380,10 @@ let first_stm = List.hd slst in (*time "make_var_hash" make_var_hash fd;*) AvailableExps.StmtStartData.clear (); - AvailableExps.StmtStartData.add first_stm.sid (LvExpHash.create 4); + AvailableExps.StmtStartData.add first_stm (LvExpHash.create 4); time "compute" AE.compute [first_stm] - with Failure "hd" -> if !debug then Cilmsg.debug "fn w/ no stmts?" - | Not_found -> if !debug then Cilmsg.debug "no data for first_stm?" + with Failure "hd" -> if !debug then Kernel.debug "fn w/ no stmts?" + | Not_found -> if !debug then Kernel.debug "no data for first_stm?" (* get the AE data for a statement *) @@ -393,7 +393,7 @@ (* get the AE data for an instruction list *) let instrAEs il _sid lvh _out = - if !debug then Cilmsg.debug "instrAEs" ; + if !debug then Kernel.debug "instrAEs" ; let proc_one hil i = match hil with [] -> let lvh' = LvExpHash.copy lvh in @@ -408,49 +408,46 @@ let foldednotout = List.rev (List.tl folded) in foldednotout -class aeVisitorClass = object +class aeVisitorClass = object (self) inherit nopCilVisitor - val mutable sid = -1 - val mutable ae_dat_lst = [] val mutable cur_ae_dat = None method vstmt stm = - sid <- stm.sid; - match getAEs sid with - None -> - if !debug then Cilmsg.debug "aeVis: stm %d has no data" sid ; + match getAEs stm with + | None -> + if !debug then Kernel.debug "aeVis: stm %d has no data" stm.sid ; cur_ae_dat <- None; DoChildren | Some eh -> match stm.skind with Instr il -> - if !debug then Cilmsg.debug "aeVist: visit il" ; + if !debug then Kernel.debug "aeVist: visit il" ; ae_dat_lst <- time "instrAEs" (instrAEs [il] stm.sid eh) false; DoChildren | _ -> - if !debug then Cilmsg.debug "aeVisit: visit non-il" ; + if !debug then Kernel.debug "aeVisit: visit non-il" ; cur_ae_dat <- None; DoChildren method vinst i = - if !debug then Cilmsg.debug "aeVist: before %a, ae_dat_lst is %d long" + if !debug then Kernel.debug "aeVist: before %a, ae_dat_lst is %d long" d_instr i (List.length ae_dat_lst); try let data = List.hd ae_dat_lst in cur_ae_dat <- Some(data); ae_dat_lst <- List.tl ae_dat_lst; - if !debug then Cilmsg.debug "aeVisit: data is %a" lvh_pretty data; + if !debug then Kernel.debug "aeVisit: data is %a" lvh_pretty data; DoChildren with Failure "hd" -> - if !debug then Cilmsg.debug "aeVis: il ae_dat_lst mismatch"; + if !debug then Kernel.debug "aeVis: il ae_dat_lst mismatch"; DoChildren method get_cur_eh () = match cur_ae_dat with - None -> getAEs sid + | None -> getAEs (Extlib.the self#current_stmt) | Some eh -> Some eh end diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/callgraph.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/callgraph.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/callgraph.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/callgraph.ml 2011-10-10 08:40:08.000000000 +0000 @@ -144,7 +144,7 @@ (* begin visiting a function definition *) method vfunc (f:fundec) : fundec visitAction = begin - Cilmsg.feedback ~level:2 "Callgraph for function %s" f.svar.vname ; + Kernel.feedback ~level:2 "Callgraph for function %s" f.svar.vname ; let node = getNodeForVar graph f.svar in (match node.cnInfo with NIVar (_v, r) -> r := true diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/cfg.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/cfg.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/cfg.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/cfg.ml 2011-10-10 08:40:08.000000000 +0000 @@ -113,7 +113,7 @@ let rec cfgFun (fd : fundec) = nodeList := []; cfgBlock fd.sbody None None None; - fd.smaxstmtid <- Some(Cil.Sid.get ()); + fd.smaxstmtid <- Some(Cil.Sid.next ()); fd.sallstmts <- List.rev !nodeList; nodeList := [] @@ -139,8 +139,10 @@ if s.sid = -1 then s.sid <- Cil.Sid.next (); nodeList := s :: !nodeList; (* Future traversals can be made in linear time. e.g. *) if s.succs <> [] then - Cilmsg.fatal "CFG must be cleared before being computed! '%a' of %d" d_stmt s - (List.length s.succs); + Kernel.fatal + "CFG must be cleared before being computed! Stmt %d (%d) '%a' \ + has %d successors" + s.sid (Obj.magic s) d_stmt s (List.length s.succs); let addSucc (n: stmt) = if not (List.memq n s.succs) then s.succs <- n::s.succs; if not (List.memq s n.preds) then n.preds <- s::n.preds @@ -211,7 +213,7 @@ (* Since all loops have terminating condition true, we don't put any direct successor to stmt following the loop *) | TryExcept _ | TryFinally _ -> - Cilmsg.fatal "try/except/finally" + Kernel.fatal "try/except/finally" (*------------------------------------------------------------*) @@ -422,7 +424,7 @@ let assert_of_clause f ca = match ca.annot_content with | AAssert _ | AInvariant _ | AVariant _ | AAssigns _ | APragma _ -> ptrue - | AStmtSpec s -> + | AStmtSpec (_bhv,s) -> List.fold_left (fun acc bhv -> pand @@ -459,7 +461,7 @@ let cont_clause = Logic_utils.translate_old_label s cont_clause in Stack.push cont_clause old_clause; end else begin - Cilmsg.fatal "No stack where to put continues clause" + Kernel.fatal "No stack where to put continues clause" end; if not (Stack.is_empty breaks_stack) then begin let old_clause = Stack.top breaks_stack in @@ -467,7 +469,7 @@ in Stack.push break_clause old_clause; end else begin - Cilmsg.fatal "No stack where to put breaks clause" + Kernel.fatal "No stack where to put breaks clause" end in let rec popn n = @@ -500,10 +502,10 @@ let suffix = match isInteger e with | Some value -> - if value < Int64.zero then - "neg_" ^ Int64.to_string (Int64.neg value) + if My_bigint.lt value My_bigint.zero then + "neg_" ^ My_bigint.to_string (My_bigint.neg value) else - Int64.to_string value + My_bigint.to_string value | None -> "exp" in @@ -527,42 +529,42 @@ rest break_dest cont_dest label_index 0 | Break(l) -> if Stack.is_empty breaks_stack then - Cilmsg.fatal "empty breaks stack"; - let goto_stmt = mkStmt (Goto(break_dest (),l)) in + Kernel.fatal "empty breaks stack"; + s.skind <- Goto(break_dest (),l); let breaks = Stack.top breaks_stack in let assertion = ref ptrue in Stack.iter (fun p -> assertion := pand (p,!assertion)) breaks; (match !assertion with { content = Ptrue } -> popn popstack; - goto_stmt :: + s :: xform_switch_stmt rest break_dest cont_dest label_index 0 | p -> let a = Logic_const.new_code_annotation (AAssert ([],p)) in let assertion = mkStmt (Instr(Code_annot(a,l))) in popn popstack; - assertion::goto_stmt:: + assertion:: s :: xform_switch_stmt rest break_dest cont_dest label_index 0) | Continue(l) -> if Stack.is_empty continues_stack then - Cilmsg.fatal "empty continues stack"; - let goto_stmt = mkStmt (Goto(cont_dest (),l)) in + Kernel.fatal "empty continues stack"; + s.skind <- Goto(cont_dest (),l); let continues = Stack.top continues_stack in let assertion = ref ptrue in Stack.iter (fun p -> assertion := pand(p,!assertion)) continues; (match !assertion with { content = Ptrue } -> popn popstack; - goto_stmt :: + s :: xform_switch_stmt rest break_dest cont_dest label_index 0 | p -> let a = Logic_const.new_code_annotation (AAssert([],p)) in let assertion = mkStmt (Instr(Code_annot(a,l))) in popn popstack; - assertion::goto_stmt:: + assertion :: s :: xform_switch_stmt rest break_dest cont_dest label_index 0) | If(e,b1,b2,l) -> @@ -644,7 +646,9 @@ (* begin replacement: *) let pred = match ce.enode with - Const (CInt64 (0L,_,_)) -> + Const (CInt64 (z,_,_)) + when My_bigint.equal z My_bigint.zero + -> new_exp ~loc:ce.eloc (UnOp(LNot,e,intType)) | _ -> new_exp ~loc:ce.eloc (BinOp(Eq,e,ce,intType)) @@ -732,7 +736,7 @@ s.skind <- UnspecifiedSequence seq; s :: xform_switch_stmt rest break_dest cont_dest label_index 0 | TryExcept _ | TryFinally _ -> - Cilmsg.fatal + Kernel.fatal "xform_switch_statement: \ structured exception handling not implemented" end @@ -759,8 +763,8 @@ (List.concat (List.map treat_one seq)) in xform_switch_block b - (fun () -> Cilmsg.abort "break outside of loop or switch") - (fun () -> Cilmsg.abort "continues outside of loop") + (fun () -> Kernel.abort "break outside of loop or switch") + (fun () -> Kernel.abort "continues outside of loop") (-1) (* Enter all the labels in a function into an alpha renaming table to @@ -794,12 +798,11 @@ fd.sbody <- b (* make the cfg and return a list of statements *) -let computeCFGInfo (f : fundec) (global_numbering : bool) : unit = - if not global_numbering then Sid.reset (); +let computeCFGInfo (f : fundec) (_global_numbering : bool) : unit = statements := []; let clear_it = new clear in ignore (visitCilBlock clear_it f.sbody) ; - f.smaxstmtid <- Some (Sid.get ()) ; + f.smaxstmtid <- Some (Sid.next ()) ; succpred_block f.sbody (None); let res = List.rev !statements in statements := []; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/ciltools.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/ciltools.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/ciltools.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/ciltools.ml 2011-10-10 08:40:08.000000000 +0000 @@ -43,10 +43,10 @@ open Cil (* Contributed by Nathan Cooprider *) - +(* let isOne e = isInteger e = Some Int64.one - +*) (* written by Zach *) let is_volatile_tp tp = @@ -88,23 +88,6 @@ | _ -> raise Not_an_integer in (bitsSizeOf tp), s - -(* depricated. Use isInteger directly instead *) -let unbox_int_exp (e : exp) : int64 = - match isInteger e with - None -> raise Not_an_integer - | Some (x) -> x - -let box_int_to_exp (n : int64) (ye : typ) : exp = - let tp = unrollType ye in - match tp with - TInt (i, _) -> - kinteger64 ~loc:Cil_datatype.Location.unknown i n - | _ -> raise Not_an_integer - -let cil_to_ocaml_int (e : exp) : (int64 * int * sign) = - let v, s = unbox_int_type (typeOf e) in - unbox_int_exp (e), v, s exception Weird_bitwidth diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/dataflow.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/dataflow.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/dataflow.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/dataflow.ml 2011-10-10 08:40:08.000000000 +0000 @@ -69,17 +69,19 @@ module type StmtStartData = sig type data + type key val clear: unit -> unit - val mem: int -> bool - val find: int -> data - val replace: int -> data -> unit - val add: int -> data -> unit - val iter: (int -> data -> unit) -> unit + val mem: key -> bool + val find: key -> data + val replace: key -> data -> unit + val add: key -> data -> unit + val iter: (key -> data -> unit) -> unit val length: unit -> int end module StmtStartData(X: sig type t val size: int end) = struct type data = X.t + type key = int open Inthash let stmtStartData = create X.size let clear () = clear stmtStartData @@ -91,6 +93,40 @@ let length () = length stmtStartData end +module StartData(X: sig type t val size: int end) = struct + type data = X.t + type key = stmt + open Cil_datatype.Stmt.Hashtbl + let stmtStartData = create X.size + let clear () = clear stmtStartData + let mem = mem stmtStartData + let find = find stmtStartData + let replace = replace stmtStartData + let add = add stmtStartData + let iter f = iter f stmtStartData + let length () = length stmtStartData +end + +let stmt_of_sid = Extlib.mk_fun "Dataflow.stmt_of_sid" + +(* Conversion from an initial state indexed by statements sids to + an initial state indexed by statements. Not used in code called + with the current dataflows *) +module ConvertStartData(SSD: StmtStartData with type key = int) : + StmtStartData with type data = SSD.data and type key = stmt = +struct + type data = SSD.data + type key = stmt + let stmt_of_sid sid = !stmt_of_sid sid + let clear () = SSD.clear () + let mem stmt = SSD.mem stmt.sid + let find stmt = SSD.find stmt.sid + let replace stmt data = SSD.replace stmt.sid data + let add stmt data = SSD.add stmt.sid data + let iter f = SSD.iter (fun sid -> f (stmt_of_sid sid)) + let length () = SSD.length () +end + (****************************************************************** ********** @@ -98,18 +134,13 @@ ********** ********************************************************************) -module type ForwardsTransfer = sig +module type ForwardsTransferAux = sig val name: string (** For debugging purposes, the name of the analysis *) val debug: bool ref (** Whether to turn on debugging *) type t (** The type of the data we compute for each block start. May be * imperative. *) - module StmtStartData: StmtStartData with type data = t - (** For each statement id, the data at the start. Not found in the hash - * table means nothing is known about the state at this point. At the end - * of the analysis this means that the block is not reachable. *) - val copy: t -> t (** Make a deep copy of the data *) @@ -132,9 +163,9 @@ * [stmt] is the englobing statement *) val doGuard: stmt -> exp -> t -> t guardaction * t guardaction - (** Generate the successors [th, el] to an + (** Generate the successors [th, el] to an * If statement assuming the given expression - * is respectively nonzero and zero. + * is respectively nonzero and zero. * Analyses that don't need guard information can return * GDefault, GDefault; this is equivalent to returning GUse of the input. * A return value of GUnreachable indicates that this half of the branch @@ -161,7 +192,17 @@ *) end -module ForwardsDataFlow(T : ForwardsTransfer) = struct +module type ForwardsTransfer = sig + include ForwardsTransferAux + + module StmtStartData: StmtStartData with type data = t + (** For each statement id, the data at the start. Not found in the hash + * table means nothing is known about the state at this point. At the end + * of the analysis this means that the block is not reachable. *) + +end + +module Forwards(T : ForwardsTransfer with type StmtStartData.key = stmt) = struct (** Keep a worklist of statements to process. It is best to keep a queue, * because this way it is more likely that we are going to process all @@ -177,31 +218,31 @@ let d = T.doEdge pred s d in let newdata: T.t option = try - let old = T.StmtStartData.find s.sid in + let old = T.StmtStartData.find s in match T.combinePredecessors s ~old:old d with None -> (* We are done here *) if !T.debug then - Cilmsg.debug "FF(%s): reached stmt %d with %a\n implies the old state %a\n" + Kernel.debug "FF(%s): reached stmt %d with %a\n implies the old state %a\n" T.name s.sid T.pretty d T.pretty old; None | Some d' -> begin (* We have changed the data *) if !T.debug then - Cilmsg.debug "FF(%s): weaken data for block %d: %a\n" + Kernel.debug "FF(%s): weaken data for block %d: %a\n" T.name s.sid T.pretty d'; Some d' end with Not_found -> (* was bottom before *) let d' = T.computeFirstPredecessor s d in if !T.debug then - Cilmsg.debug "FF(%s): set data for block %d: %a\n" + Kernel.debug "FF(%s): set data for block %d: %a\n" T.name s.sid T.pretty d'; Some d' in match newdata with None -> () | Some d' -> - T.StmtStartData.replace s.sid d'; + T.StmtStartData.replace s d'; if T.filterStmt s && not (Queue.fold (fun exists s' -> exists || s'.sid = s.sid) false @@ -226,9 +267,12 @@ s.succs in match fallthrough with - [] -> Cil.fatal "Bad CFG: missing fallthrough for If." + [] -> + Kernel.fatal ~current:true + "Bad CFG: missing fallthrough for If." | [s'] -> s' - | _ -> Cil.fatal "Bad CFG: multiple fallthrough for If." + | _ -> + Kernel.fatal ~current:true "Bad CFG: multiple fallthrough for If." in (* If thenSucc or elseSucc is Cil.dummyStmt, it's an empty block. So the successor is the statement after the if *) @@ -241,99 +285,148 @@ (stmtOrFallthrough thenSucc, stmtOrFallthrough elseSucc) - | _-> Cil.fatal "ifSuccs on a non-If Statement." + | _-> Kernel.fatal ~current:true "ifSuccs on a non-If Statement." (** Process a statement *) let processStmt (s: stmt) : unit = CurrentLoc.set (Cil_datatype.Stmt.loc s); if !T.debug then - Cilmsg.debug "FF(%s).stmt %d at %t@\n" T.name s.sid d_thisloc; + Kernel.debug "FF(%s).stmt %d at %t@\n" T.name s.sid d_thisloc; (* It must be the case that the block has some data *) let init: T.t = - try T.copy (T.StmtStartData.find s.sid) - with Not_found -> - (Cil.fatal "FF(%s): processing block without data" T.name) + try T.copy (T.StmtStartData.find s) + with Not_found -> + Kernel.fatal ~current:true + "FF(%s): processing block without data" T.name in (** See what the custom says *) match T.doStmt s init with - SDone -> () + | SDone -> () | (SDefault | SUse _) as act -> begin let curr = match act with - SDefault -> init + | SDefault -> init | SUse d -> d - | SDone -> (Cil.fatal "SDone") - in - (* Do the instructions in order *) - let handleInstruction (state: T.t) (i: instr) : T.t = - CurrentLoc.set (Cil_datatype.Instr.loc i); - - (* Now handle the instruction itself *) - let s' = - let action = T.doInstr s i state in - match action with - | Done s' -> s' - | Default -> state (* do nothing *) - | Post f -> f state - in - s' + | SDone -> assert false + and do_succs state = + List.iter (fun s' -> reachedStatement s s' state) s.succs in - let after: T.t = - match s.skind with - Instr i -> - (* Handle instructions starting with the first one *) - handleInstruction curr i + CurrentLoc.set (Cil_datatype.Stmt.loc s); + match s.skind with + | Instr i -> + CurrentLoc.set (Cil_datatype.Instr.loc i); + let action = T.doInstr s i curr in + let after = match action with + | Done s' -> s' + | Default -> curr (* do nothing *) + | Post f -> f curr + in + do_succs after + | UnspecifiedSequence _ - | Goto _ | Break _ | Continue _ | If _ + | Goto _ | Break _ | Continue _ | TryExcept _ | TryFinally _ - | Switch _ | Loop _ | Return _ | Block _ -> curr - in - CurrentLoc.set (Cil_datatype.Stmt.loc s); + | Loop _ | Return _ | Block _ -> + do_succs curr - (* Handle If guards *) - let succsToReach = match s.skind with - If (e, _, _, _) -> begin - let thenGuard, elseGuard = T.doGuard s e after in + | If (e, _, _, _) -> + let thenGuard, elseGuard = T.doGuard s e curr in if thenGuard = GDefault && elseGuard = GDefault then (* this is the common case *) - s.succs + do_succs curr else begin let doBranch succ guard = match guard with - GDefault -> reachedStatement s succ after + GDefault -> reachedStatement s succ curr | GUse d -> reachedStatement s succ d | GUnreachable -> if !T.debug then - (Cilmsg.debug "FF(%s): Not exploring branch to %d\n" + (Kernel.debug "FF(%s): Not exploring branch to %d\n" T.name succ.sid) in let thenSucc, elseSucc = ifSuccs s in doBranch thenSucc thenGuard; doBranch elseSucc elseGuard; - [] end - end - | Switch _ -> - List.iter - (fun succ -> - match T.doGuard s (Cil.one ~loc:(Cil_datatype.Stmt.loc s)) - after - with - GDefault, _ -> reachedStatement s succ after - | GUse d, _ -> reachedStatement s succ d - | GUnreachable, _ -> - if !T.debug then - Cilmsg.debug "FF(%s): Not exploring branch to %d\n" - T.name succ.sid) - s.succs; - [] - | _ -> s.succs - in - (* Reach the successors *) - List.iter (fun s' -> reachedStatement s s' after) succsToReach; + | Switch (exp_sw, _, _, _) -> + let cases, next_sw = Cil.separate_switch_succs s in + (* Auxiliary function that iters on all the labels of + the switch. The accumulator is the state after the + evaluation of the label, and the default case *) + let iter_all_labels f = + List.fold_left + (fun (rem_state, _default as acc) succ -> + if rem_state = None then acc + else + List.fold_left + (fun (rem_state, default as acc) label -> + match rem_state with + | None -> acc + | Some state -> f succ label state default + ) acc succ.labels + ) (Some curr, next_sw) cases + in + (* Compute a successor of the switch, starting with the state + [before], supposing we are considering the label [exp] *) + let explore_succ before succ exp_case = + let exp = match exp_case.enode with + | Const (CInt64 (z,_,_)) + when My_bigint.equal z My_bigint.zero -> + new_exp ~loc:exp_sw.eloc (UnOp(LNot,exp_sw,intType)) + | _ -> + Cil.new_exp exp_case.eloc + (BinOp (Eq, exp_sw, exp_case, Cil.intType)) + in + let branch_case, branch_not_case = T.doGuard s exp before in + (match branch_case with + | GDefault -> reachedStatement s succ before; + | GUse d -> reachedStatement s succ d; + | GUnreachable -> + if !T.debug then + Kernel.debug "FF(%s): Not exploring branch to %d\n" + T.name succ.sid; + ); + (* State corresponding to the negation of [exp], to + be used for the remaining labels *) + match branch_not_case with + | GDefault -> Some before + | GUse d -> Some d + | GUnreachable -> None + in + (* Evaluate all of the labels one after the other, refining + the state after each case *) + let after, default = iter_all_labels + (fun succ label before default -> + match label with + | Label _ -> (* Label not related to the switch *) + (Some before, default) + + | Cil_types.Default _loc -> + if default <> None then + Kernel.fatal ~current:true + "Bad CFG: switch with multiple \ + successors or default cases."; + (Some before, Some succ) + + | Case (exp_case, _) -> + let after = explore_succ before succ exp_case in + (after, default) + ) in + (* If [after] is different from [None], we must evaluate + the default case, be it a default label, or the + successor of the switch *) + (match after with + | None -> () + | Some state -> + match default with + | None -> + Kernel.fatal ~current:true + "Bad CFG: switch without \ + successor or default case." + | Some succ -> reachedStatement s succ state) end @@ -384,16 +477,18 @@ List.iter (fun s -> Queue.add s worklist) sources; (** All initial stmts must have non-bottom data *) - List.iter (fun s -> - if not (T.StmtStartData.mem s.sid) then - (Cil.fatal "FF(%s): initial stmt %d does not have data" - T.name s.sid)) - sources; + List.iter + (fun s -> + if not (T.StmtStartData.mem s) then + Kernel.fatal ~current:true + "FF(%s): initial stmt %d does not have data" + T.name s.sid) + sources; if !T.debug then - (Cilmsg.debug "FF(%s): processing" T.name); + (Kernel.debug "FF(%s): processing" T.name); let rec fixedpoint () = if !T.debug && not (Queue.is_empty worklist) then - (Cilmsg.debug "FF(%s): worklist= %a" + (Kernel.debug "FF(%s): worklist= %a" T.name (Pretty_utils.pp_list (fun fmt s -> Format.fprintf fmt "%d" s.sid)) (List.rev @@ -406,10 +501,20 @@ fixedpoint () with Queue.Empty -> if !T.debug then - (Cilmsg.debug "FF(%s): done" T.name)) + (Kernel.debug "FF(%s): done" T.name)) end +(* Old interface, deprecated *) +module ForwardsDataFlow + (T : ForwardsTransfer with type StmtStartData.key = int) = +struct + include Forwards( + struct + include (T : ForwardsTransferAux with type t = T.t) + module StmtStartData = ConvertStartData(T.StmtStartData) + end) +end (****************************************************************** @@ -417,7 +522,7 @@ ********** BACKWARDS ********** ********************************************************************) -module type BackwardsTransfer = sig +module type BackwardsTransferAux = sig val name: string (* For debugging purposes, the name of the analysis *) val debug: bool ref (** Whether to turn on debugging *) @@ -428,10 +533,6 @@ * a block has many exceptional ends. So we maintain the data for * the statement start. *) - module StmtStartData: StmtStartData with type data = t - (** For each block id, the data at the start. This data structure must be - * initialized with the initial data for each block *) - val pretty: Format.formatter -> t -> unit (** Pretty-print the state *) val funcExitData: t @@ -471,19 +572,29 @@ end -module BackwardsDataFlow(T : BackwardsTransfer) = struct +module type BackwardsTransfer = sig + include BackwardsTransferAux + + module StmtStartData: StmtStartData with type data = t + (** For each block id, the data at the start. This data structure must be + * initialized with the initial data for each block *) +end + +module Backwards(T : BackwardsTransfer with type StmtStartData.key = stmt) = +struct let getStmtStartData (s: stmt) : T.t = - try T.StmtStartData.find s.sid + try T.StmtStartData.find s with Not_found -> - (Cil.fatal "BF(%s): stmtStartData is not initialized for %d" - T.name s.sid) + Kernel.fatal ~current:true + "BF(%s): stmtStartData is not initialized for %d" + T.name s.sid (** Process a statement and return true if the set of live return * addresses on its entry has changed. *) let processStmt (s: stmt) : bool = if !T.debug then - (Cilmsg.debug "FF(%s).stmt %d\n" T.name s.sid); + (Kernel.debug "FF(%s).stmt %d\n" T.name s.sid); (* Find the state before the branch *) @@ -492,10 +603,14 @@ match T.doStmt s with Done d -> d | (Default | Post _) as action -> begin - (* Do the default one. Combine the successors *) + (* Compute the default state, by combining the successors *) let res = - match s.succs with - [] -> T.funcExitData + (* We restrict ourselves to the successors we are interested in. + If T.filterStmt is deterministic, this should not make the + list empty if s.succs is not empty, as we would not have + reached s otherwise *) + match List.filter (T.filterStmt s) s.succs with + | [] -> T.funcExitData | fst :: rest -> List.fold_left (fun acc succ -> T.combineSuccessors acc (getStmtStartData succ)) @@ -536,9 +651,9 @@ | Some d' -> (* We have changed the data *) if !T.debug then - Cilmsg.debug "BF(%s): set data for block %d: %a\n" + Kernel.debug "BF(%s): set data for block %d: %a\n" T.name s.sid T.pretty d'; - T.StmtStartData.replace s.sid d'; + T.StmtStartData.replace s d'; true @@ -547,11 +662,11 @@ let worklist: stmt Queue.t = Queue.create () in List.iter (fun s -> Queue.add s worklist) sinks; if !T.debug && not (Queue.is_empty worklist) then - (Cilmsg.debug "\nBF(%s): processing\n" + (Kernel.debug "\nBF(%s): processing\n" T.name); let rec fixedpoint () = if !T.debug && not (Queue.is_empty worklist) then - (Cilmsg.debug "BF(%s): worklist= %a\n" + (Kernel.debug "BF(%s): worklist= %a\n" T.name (Pretty_utils.pp_list (fun fmt s -> Format.fprintf fmt "%d" s.sid)) (List.rev @@ -578,9 +693,21 @@ fixedpoint () with Queue.Empty -> if !T.debug then - (Cilmsg.debug "BF(%s): done\n\n" T.name) + (Kernel.debug "BF(%s): done\n\n" T.name) end +(* Old interface, deprecated *) +module BackwardsDataFlow + (T : BackwardsTransfer with type StmtStartData.key = int) = +struct + include Backwards( + struct + include (T: BackwardsTransferAux with type t = T.t) + module StmtStartData = ConvertStartData(T.StmtStartData) + end) +end + + (** Helper utility that finds all of the statements of a function. It also lists the return statments (including statements that @@ -604,3 +731,10 @@ and all_stmts = ref [] in ignore(visitCilFunction (sinkFinder sink_stmts all_stmts) fdec); !all_stmts, !sink_stmts + + +(* +Local Variables: +compile-command: "make -C ../../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/dataflow.mli frama-c-20111001+nitrogen+dfsg/cil/src/ext/dataflow.mli --- frama-c-20110201+carbon+dfsg/cil/src/ext/dataflow.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/dataflow.mli 2011-10-10 08:40:08.000000000 +0000 @@ -65,17 +65,21 @@ module type StmtStartData = sig type data + type key val clear: unit -> unit - val mem: int -> bool - val find: int -> data - val replace: int -> data -> unit - val add: int -> data -> unit - val iter: (int -> data -> unit) -> unit + val mem: key -> bool + val find: key -> data + val replace: key -> data -> unit + val add: key -> data -> unit + val iter: (key -> data -> unit) -> unit val length: unit -> int end module StmtStartData(X:sig type t val size: int end) : - StmtStartData with type data = X.t + StmtStartData with type data = X.t and type key = int + +module StartData(X:sig type t val size: int end) : + StmtStartData with type data = X.t and type key = Cil_types.stmt (****************************************************************** ********** @@ -91,11 +95,6 @@ type t (** The type of the data we compute for each block start. May be * imperative. *) - module StmtStartData: StmtStartData with type data = t - (** For each statement id, the data at the start. Not found in the hash - * table means nothing is known about the state at this point. At the end - * of the analysis this means that the block is not reachable. *) - val copy: t -> t (** Make a deep copy of the data *) @@ -140,14 +139,21 @@ val stmt_can_reach : Cil_types.stmt -> Cil_types.stmt -> bool - val doEdge: Cil_types.stmt -> Cil_types.stmt -> t -> t + val doEdge: Cil_types.stmt -> Cil_types.stmt -> t -> t (** what to do when following the edge between the two given statements. Can default to identity if nothing special is required. *) + module StmtStartData: StmtStartData with type data = t + (** For each statement id, the data at the start. Not found in the hash + * table means nothing is known about the state at this point. At the end + * of the analysis this means that the block is not reachable. *) + end -module ForwardsDataFlow(T : ForwardsTransfer) : sig +module Forwards( + T : ForwardsTransfer with type StmtStartData.key = Cil_types.stmt) : +sig val reachedStatement : Cil_types.stmt -> Cil_types.stmt -> T.t -> unit val compute: Cil_types.stmt list -> unit (** Fill in the T.stmtStartData, given a number of initial statements to @@ -155,6 +161,16 @@ * T.stmtStartData (i.e., the initial data should not be bottom) *) end +(** Same dataflow as above, but with initial states indexed by statements + sids. Do not use. + @deprecated Nitrogen-20111001 *) +module ForwardsDataFlow( + T : ForwardsTransfer with type StmtStartData.key = int) : +sig + val reachedStatement : Cil_types.stmt -> Cil_types.stmt -> T.t -> unit + val compute: Cil_types.stmt list -> unit +end + (****************************************************************** ********** ********** BACKWARDS @@ -171,10 +187,6 @@ * a block has many exceptional ends. So we maintain the data for * the statement start. *) - module StmtStartData: StmtStartData with type data = t - (** For each block id, the data at the start. This data structure must be - * initialized with the initial data for each block *) - val pretty: Format.formatter -> t -> unit (** Pretty-print the state *) val funcExitData: t @@ -212,9 +224,15 @@ * predecessor and the block whose predecessor we are (and whose data has * changed) *) + module StmtStartData: StmtStartData with type data = t + (** For each block id, the data at the start. This data structure must be + * initialized with the initial data for each block *) + end -module BackwardsDataFlow(T : BackwardsTransfer) : sig +module Backwards( + T : BackwardsTransfer with type StmtStartData.key = Cil_types.stmt) : +sig val compute: Cil_types.stmt list -> unit (** Fill in the T.stmtStartData, given a number of initial statements to * start from (the sinks for the backwards data flow). All of the statements @@ -224,9 +242,29 @@ * {!find_stmts} may be useful here. *) end +(** Same dataflow as above, but with initial states indexed by statements + sids. Do not use. + @deprecated Nitrogen-20111001 *) +module BackwardsDataFlow( + T : BackwardsTransfer with type StmtStartData.key = int) : +sig + val compute: Cil_types.stmt list -> unit +end + + (** Returns (all_stmts, sink_stmts), where all_stmts is a list of the statements in a function, and sink_stmts is a list of the return statments (including statements that fall through the end of a void function). Useful when you need an initial set of statements for BackwardsDataFlow.compute. *) val find_stmts: Cil_types.fundec -> (Cil_types.stmt list * Cil_types.stmt list) + +(**/**) + +val stmt_of_sid: (int -> Cil_types.stmt) ref + +(* +Local Variables: +compile-command: "LC_ALL=C make -C ../../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/deadcodeelim.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/deadcodeelim.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/deadcodeelim.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/deadcodeelim.ml 2011-10-10 08:40:08.000000000 +0000 @@ -101,24 +101,27 @@ UD.VS.iter (fun vi -> if IH.mem iosh vi.vid then let ios = IH.find iosh vi.vid in - if !debug then (Cilmsg.debug "DCE: IOS size for vname=%s at stmt=%d: %d\n" + if !debug then (Kernel.debug "DCE: IOS size for vname=%s at stmt=%d: %d\n" vi.vname - sid (RD.IOS.cardinal ios)); + (Extlib.the self#current_stmt).sid + (RD.IOS.cardinal ios)); RD.IOS.iter (function Some(i) -> - if !debug then Cilmsg.debug "DCE: def %d used: %a\n" i d_plainexp e; + if !debug then Kernel.debug "DCE: def %d used: %a\n" i d_plainexp e; usedDefsSet := IS.add i (!usedDefsSet) | None -> ()) ios - else if !debug then Cilmsg.debug "DCE: vid %d:%s not in stm:%d iosh at %a\n" + else if !debug then Kernel.debug "DCE: vid %d:%s not in stm:%d iosh at %a\n" vi.vid vi.vname - sid d_plainexp e) u + (Extlib.the self#current_stmt).sid + d_plainexp e + ) u method vexpr e = let u = UD.computeUseExp e in match self#get_cur_iosh() with Some(iosh) -> self#add_defids iosh e u; DoChildren | None -> - if !debug then Cilmsg.debug "DCE: use but no rd data: %a\n" d_plainexp e; + if !debug then Kernel.debug "DCE: use but no rd data: %a\n" d_plainexp e; DoChildren method vstmt s = @@ -146,6 +149,7 @@ end method vinst i = + let cstmt = Extlib.the self#current_stmt in let handle_inst iosh i = match i with | Asm(_,_,slvl,_,_,_) -> List.iter (fun (_,s,lv) -> match lv with (Var v, off) -> @@ -163,9 +167,9 @@ | Some i -> begin (* add sid to set for i *) try let set = IH.find sidUseSetHash i in - IH.replace sidUseSetHash i (IS.add sid set) + IH.replace sidUseSetHash i (IS.add cstmt.sid set) with Not_found -> - IH.add sidUseSetHash i (IS.singleton sid) + IH.add sidUseSetHash i (IS.singleton cstmt.sid) end | None -> ()) ios) u) (ce::el) | Set((Mem _,_) as lh, rhs,_l) -> @@ -178,9 +182,9 @@ | Some i -> begin (* add sid to set for i *) try let set = IH.find sidUseSetHash i in - IH.replace sidUseSetHash i (IS.add sid set) + IH.replace sidUseSetHash i (IS.add cstmt.sid set) with Not_found -> - IH.add sidUseSetHash i (IS.singleton sid) + IH.add sidUseSetHash i (IS.singleton cstmt.sid) end | None -> ()) ios) u) ([new_exp ~loc:Cil_datatype.Location.unknown @@ -190,7 +194,7 @@ ignore(super#vinst i); match cur_rd_dat with | None -> begin - if !debug then (Cilmsg.debug "DCE: instr with no cur_rd_dat\n"); + if !debug then (Kernel.debug "DCE: instr with no cur_rd_dat\n"); (* handle_inst *) DoChildren end @@ -331,7 +335,7 @@ let defuses = IH.find defUseSetHash defid in (*let siduses = IH.find sidUseSetHash defid in*) if IH.mem sidUseSetHash defid then begin - if !debug then Cilmsg.debug "siduses not empty: %a\n" d_instr i; + if !debug then Kernel.debug "siduses not empty: %a\n" d_instr i; true end else begin (* true if there is something in defuses not in instruses or when @@ -339,7 +343,7 @@ let instruses = viSetToDefIdSet iosh instruses in IS.fold (fun i' b -> if not(IS.mem i' instruses) then begin - if !debug then Cilmsg.debug "i not in instruses: %a\n" d_instr i; + if !debug then Kernel.debug "i not in instruses: %a\n" d_instr i; true end else (* can only use the definition i' at the definition defid *) @@ -348,10 +352,10 @@ if not(IS.equal i'_uses (IS.singleton defid)) then begin IS.iter (fun iu -> match RD.getSimpRhs iu with | Some(RD.RDExp e) -> - if !debug then Cilmsg.debug "i' had other than one use: %d: %a\n" + if !debug then Kernel.debug "i' had other than one use: %d: %a\n" (IS.cardinal i'_uses) d_exp e | Some(RD.RDCall i) -> - if !debug then Cilmsg.debug "i' had other than one use: %d: %a\n" + if !debug then Kernel.debug "i' had other than one use: %d: %a\n" (IS.cardinal i'_uses) d_instr i | None -> ()) i'_uses; true @@ -364,10 +368,10 @@ match i with | Call(Some(Var vi,NoOffset),{enode = Lval(Var _vf,NoOffset)},el,_l) -> if not(!callHasNoSideEffects i) then begin - if !debug then Cilmsg.debug "found call w/ side effects: %a\n" d_instr i; + if !debug then Kernel.debug "found call w/ side effects: %a\n" d_instr i; true end else begin - if !debug then Cilmsg.debug "found call w/o side effects: %a\n" d_instr i; + if !debug then Kernel.debug "found call w/o side effects: %a\n" d_instr i; (vi.vglob || (Ciltools.is_volatile_vi vi) || (el_has_volatile el) || let uses, defd = UD.computeUseDefInstr i in let rec loop n = @@ -403,7 +407,7 @@ | _ :: _ :: _ -> assert false in - match RD.getRDs stm.sid with + match RD.getRDs stm with None -> DoChildren | Some(_,s,iosh) -> match stm.skind with @@ -438,10 +442,10 @@ IH.clear sidUseSetHash; removedCount := 0; time "reaching definitions" RD.computeRDs fd; - if !debug then (Cilmsg.debug "DCE: collecting used definitions\n"); + if !debug then (Kernel.debug "DCE: collecting used definitions\n"); ignore(time "ud-collector" (visitCilFunction (new usedDefsCollectorClass :> cilVisitor)) fd); - if !debug then (Cilmsg.debug "DCE: eliminating useless instructions\n"); + if !debug then (Kernel.debug "DCE: eliminating useless instructions\n"); let fd' = time "useless-elim" (visitCilFunction (new uselessInstrElim)) fd in fd' @@ -455,5 +459,5 @@ end let dce f = - if !debug then (Cilmsg.debug "DCE: starting dead code elimination\n"); + if !debug then (Kernel.debug "DCE: starting dead code elimination\n"); visitCilFile (new deadCodeElimClass) f diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/dominators.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/dominators.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/dominators.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/dominators.ml 2011-10-10 08:40:08.000000000 +0000 @@ -39,43 +39,6 @@ (* énergies alternatives). *) (**************************************************************************) -(* - * - * Copyright (c) 2001-2002, - * George C. Necula - * Scott McPeak - * Wes Weimer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The names of the contributors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *) - (** Compute dominator information for the statements in a function *) open Cil_types open Cil @@ -88,7 +51,7 @@ let debug = false (* For each statement we maintain a set of statements that dominate it *) -module BS = Cil_datatype.Stmt.Set +module BS = Cil_datatype.Stmt.Hptset (** Customization module for dominators *) module DT = struct @@ -99,7 +62,7 @@ type t = BS.t module StmtStartData = - DF.StmtStartData(struct type t = BS.t let size = 17 end) + Dataflow.StartData(struct type t = BS.t let size = 17 end) (** For each statement in a function we keep the set of dominator blocks. * Indexed by statement id *) @@ -139,19 +102,19 @@ -module Dom = DF.ForwardsDataFlow(DT) +module Dom = Dataflow.Forwards(DT) let clear () = DT.StmtStartData.clear() let getStmtDominators (s: stmt) : BS.t = - try DT.StmtStartData.find s.sid + try DT.StmtStartData.find s with Not_found -> BS.empty (* Not reachable *) let getIdom (idomInfo: stmt option IH.t) (s: stmt) = try IH.find idomInfo s.sid with Not_found -> - Cilmsg.fatal "Immediate dominator information not set for statement %d" s.sid + Kernel.fatal "Immediate dominator information not set for statement %d" s.sid (** Check whether one block dominates another. This assumes that the "idom" * field has been computed. *) @@ -210,7 +173,7 @@ [] -> () (* function has no body *) | start :: _ -> begin (* We start with only the start block *) - DT.StmtStartData.add start.sid (BS.singleton start); + DT.StmtStartData.add start (BS.singleton start); Dom.compute [start]; (* Dump the dominators information *) @@ -221,10 +184,10 @@ if not (BS.mem s sdoms) then begin (* It can be that the block is not reachable *) if s.preds <> [] then - (Cilmsg.error "Statement %d is not in its list of dominators" + (Kernel.error "Statement %d is not in its list of dominators" s.sid); end; - Cilmsg.debug "Dominators for %d: %a\n" s.sid + Kernel.debug "Dominators for %d: %a\n" s.sid DT.pretty (BS.remove s sdoms)) f.sallstmts; (* Scan all blocks and compute the idom *) @@ -271,7 +234,7 @@ let pp_loop fmt (s,backs) = Format.fprintf fmt "Start:%d, backs:%a" s.sid (Pretty_utils.pp_list pp_back) backs in - Cilmsg.debug + Kernel.debug "Natural loops:\n%a" (Pretty_utils.pp_list ~sep:"@\n" pp_loop) loops diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/liveness.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/liveness.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/liveness.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/liveness.ml 2011-10-10 08:40:08.000000000 +0000 @@ -84,7 +84,7 @@ let debug = debug type t = VS.t module StmtStartData = - DF.StmtStartData(struct type t = VS.t let size = 32 end) + Dataflow.StartData(struct type t = VS.t let size = 32 end) let pretty fmt vs = let fn = !printer in @@ -100,10 +100,10 @@ let combineSuccessors = VS.union let doStmt stmt = - if !debug then Cilmsg.debug "looking at: %a\n" d_stmt stmt; + if !debug then Kernel.debug "looking at: %a\n" d_stmt stmt; match stmt.succs with [] -> let u,_d = UD.computeUseDefStmtKind stmt.skind in - if !debug then (Cilmsg.debug "doStmt: no succs %d\n" stmt.sid); + if !debug then (Kernel.debug "doStmt: no succs %d\n" stmt.sid); DF.Done u | _ -> let handle_stm vs = match stmt.skind with @@ -124,7 +124,7 @@ end -module L = DF.BackwardsDataFlow(LiveFlow) +module L = Dataflow.Backwards(LiveFlow) (* XXX: This does not compute the best ordering to * give to the work-list algorithm. @@ -135,7 +135,7 @@ method vstmt s = all_stmts := s :: (!all_stmts); - LiveFlow.StmtStartData.add s.sid VS.empty; + LiveFlow.StmtStartData.add s VS.empty; DoChildren end @@ -156,12 +156,12 @@ with Not_found -> None let print_everything () = - LiveFlow.StmtStartData.iter (fun i vs -> - Format.printf "%d: %a" i LiveFlow.pretty vs) + LiveFlow.StmtStartData.iter (fun s vs -> + Format.printf "%d: %a" s.sid LiveFlow.pretty vs) let match_label lbl = match lbl with Label(str,_,_b) -> - if !debug then (Cilmsg.debug "Liveness: label seen: %s\n" str); + if !debug then (Kernel.debug "Liveness: label seen: %s\n" str); (*b && *)(String.compare str (!live_label) = 0) | _ -> false @@ -182,16 +182,16 @@ method vstmt s = if List.exists match_label s.labels then try - let vs = LiveFlow.StmtStartData.find s.sid in + let vs = LiveFlow.StmtStartData.find s in (printer := min_print; Format.printf "%a" LiveFlow.pretty vs; SkipChildren) with Not_found -> - if !debug then (Cilmsg.debug "Liveness: stmt: %d not found\n" s.sid); + if !debug then (Kernel.debug "Liveness: stmt: %d not found\n" s.sid); DoChildren else (if List.length s.labels = 0 then - if !debug then (Cilmsg.debug "Liveness: no label at sid=%d\n" s.sid); + if !debug then (Kernel.debug "Liveness: no label at sid=%d\n" s.sid); DoChildren) end diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/oneret.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/oneret.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/oneret.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/oneret.ml 2011-10-10 08:40:08.000000000 +0000 @@ -95,7 +95,7 @@ match f.svar.vtype with TFun(rt, _, _, _) -> rt | _ -> - Cilmsg.abort "Function %s does not have a function type" f.svar.vname + Kernel.abort "Function %s does not have a function type" f.svar.vname in (* Does it return anything ? *) let hasRet = match unrollType retTyp with TVoid _ -> false | _ -> true in @@ -118,34 +118,34 @@ inherit Cil.nopCilVisitor method vterm_lhost = function | TResult _ -> - let v = getRetVar () in + let v = getRetVar () in ChangeTo (TVar (cvar_to_lvar v)) | TMem _ | TVar _ -> DoChildren end in visitCilPredicateNamed vis p in - let assert_of_returns ca = + let assert_of_returns ca = match ca.annot_content with | AAssert _ | AInvariant _ | AVariant _ | AAssigns _ | APragma _ -> ptrue - | AStmtSpec s -> + | AStmtSpec (_bhvs,s) -> let res = - List.fold_left + List.fold_left (fun acc bhv -> - pand + pand (acc, - pimplies - (pands - (List.map - (fun p -> - pold ~loc:p.ip_loc + pimplies + (pands + (List.map + (fun p -> + pold ~loc:p.ip_loc (Logic_utils.named_of_identified_predicate p)) bhv.b_assumes), - pands - (List.fold_left + pands + (List.fold_left (fun acc (kind,p) -> match kind with - Returns -> - Logic_utils.named_of_identified_predicate p + Returns -> + Logic_utils.named_of_identified_predicate p :: acc | Normal | Exits | Breaks | Continues -> acc) [ptrue] bhv.b_post_cond) @@ -168,13 +168,13 @@ setLastLoc (List.map (fun (x,_,_,_,_) -> x) seq) | {skind= _} as s :: [] -> lastloc := Cil_datatype.Stmt.loc s | {skind=_s} :: l -> setLastLoc l - in + in setLastLoc f.sbody.bstmts; !lastloc in let loc = getLastLoc () in (* Must create a statement *) let rv = - if hasRet then + if hasRet then Some (new_exp ~loc (Lval(Var (getRetVar ()), NoOffset))) else None in @@ -204,23 +204,23 @@ multiple statement contracts on top of each other before finding an actual statement... *) - let rec scanStmts (mainbody: bool) popstack = function + let rec scanStmts acc (mainbody: bool) popstack = function | [] when mainbody -> (* We are at the end of the function. Now it is * time to add the return statement *) let rs = getRetStmt () in if !haveGoto then rs.labels <- (Label("return_label", !lastloc, false)) :: rs.labels; - [rs] - - | [] -> [] - + List.rev (rs :: acc) + + | [] -> List.rev acc + | [{skind=Return (Some ({enode = Lval(Var _,NoOffset)}), _l)} as s] when mainbody && not !haveGoto -> - (* We're not changing the return into goto, so returns clause will still - have effect. - *) + (* We're not changing the return into goto, so returns clause will still + have effect. + *) popn popstack; - [s] + List.rev (s::acc) | ({skind=Return (retval, l)} as s) :: rests -> (*CEA currentLoc := l; *) @@ -232,9 +232,10 @@ d_loc l); *) if hasRet && retval = None then - (Cil.error "Found return without value in function %s" fname) ; + Kernel.error ~current:true + "Found return without value in function %s" fname; if not hasRet && retval <> None then - (Cil.error "Found return in subroutine %s" fname); + Kernel.error ~current:true "Found return in subroutine %s" fname; (* Keep this statement because it might have labels. But change it to * an instruction that sets the return value (if any). *) s.skind <- begin @@ -249,7 +250,7 @@ match !returns_assert with { content = Ptrue } -> res | p -> - let a = + let a = Logic_const.new_code_annotation (AAssert ([],p)) in mkStmt (Instr(Code_annot (a,l))) :: res @@ -257,76 +258,75 @@ (* See if this is the last statement in function *) if mainbody && rests == [] then begin popn popstack; - let res = scanStmts mainbody 0 rests in - s :: add_assert res + scanStmts (add_assert (s::acc)) mainbody 0 rests end else begin (* Add a Goto *) let sgref = ref (getRetStmt ()) in let sg = mkStmt (Goto (sgref, l)) in haveGoto := true; popn popstack; - s :: add_assert (sg :: (scanStmts mainbody 0 rests)) + scanStmts (sg :: (add_assert (s::acc))) mainbody 0 rests end | ({skind=If(eb,t,e,l)} as s) :: rests -> (*CEA currentLoc := l;*) s.skind <- If(eb, scanBlock false t, scanBlock false e, l); popn popstack; - s :: scanStmts mainbody 0 rests + scanStmts (s::acc) mainbody 0 rests | ({skind=Loop(a,b,l,lb1,lb2)} as s) :: rests -> (*CEA currentLoc := l;*) s.skind <- Loop(a,scanBlock false b, l,lb1,lb2); popn popstack; - s :: scanStmts mainbody 0 rests + scanStmts (s::acc) mainbody 0 rests | ({skind=Switch(e, b, cases, l)} as s) :: rests -> (*CEA currentLoc := l;*) s.skind <- Switch(e, scanBlock false b, cases, l); popn popstack; - s :: scanStmts mainbody 0 rests + scanStmts (s::acc) mainbody 0 rests | [{skind=Block b} as s] -> - s.skind <- Block (scanBlock mainbody b); + s.skind <- Block (scanBlock mainbody b); popn popstack; - [s] + List.rev (s::acc) | ({skind=Block b} as s) :: rests -> s.skind <- Block (scanBlock false b); popn popstack; - s :: scanStmts mainbody 0 rests + scanStmts (s::acc) mainbody 0 rests | [{skind = UnspecifiedSequence seq} as s] -> s.skind <- UnspecifiedSequence (List.concat (List.map (fun (s,m,w,r,c) -> - let res = scanStmts mainbody 0 [s] in + let res = scanStmts [] mainbody 0 [s] in (List.hd res,m,w,r,c):: (List.map (fun x -> x,[],[],[],[]) (List.tl res))) seq)); popn popstack; - [s] + List.rev (s::acc) | ({skind = UnspecifiedSequence seq} as s) :: rests -> s.skind <- UnspecifiedSequence (List.concat (List.map (fun (s,m,w,r,c) -> - let res = scanStmts false 0 [s] in + let res = scanStmts [] false 0 [s] in (List.hd res,m,w,r,c):: (List.map (fun x -> x,[],[],[],[]) (List.tl res))) seq)); popn popstack; - s::scanStmts mainbody 0 rests + scanStmts (s::acc) mainbody 0 rests | {skind=Instr(Code_annot (ca,_))} as s :: rests -> let returns = assert_of_returns ca in let returns = Logic_utils.translate_old_label s returns in Stack.push returns returns_clause_stack; - s::scanStmts mainbody (popstack + 1) rests - + scanStmts (s::acc) mainbody (popstack + 1) rests + | ({skind=(Goto _ | Instr _ | Continue _ | Break _ | TryExcept _ | TryFinally _)} as s) - :: rests -> + :: rests -> popn popstack; - s :: scanStmts mainbody 0 rests + scanStmts (s::acc) mainbody 0 rests and scanBlock (mainbody: bool) (b: block) = - { b with bstmts = scanStmts mainbody 0 b.bstmts;} + { b with bstmts = scanStmts [] mainbody 0 b.bstmts;} in (*CEA since CurrentLoc isn't set diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/reachingdefs.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/reachingdefs.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/reachingdefs.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/reachingdefs.ml 2011-10-10 08:40:08.000000000 +0000 @@ -171,16 +171,16 @@ IH.length iosh2 = 0 && not(IH.length iosh1 = 0)*) if not(IH.length iosh1 = IH.length iosh2) then - (Cilmsg.debug "iosh_equals: length not same" ; false) + (Kernel.debug "iosh_equals: length not same" ; false) else IH.fold (fun vid ios b -> if not b then b else try let ios2 = IH.find iosh2 vid in if not(IOS.compare ios ios2 = 0) then - (Cilmsg.debug "iosh_equals: sets for vid %d not equal\n" vid ; false) + (Kernel.debug "iosh_equals: sets for vid %d not equal\n" vid ; false) else true with Not_found -> - (Cilmsg.debug "iosh_equals: vid %d not in iosh2\n" vid ; false)) + (Kernel.debug "iosh_equals: vid %d not in iosh2\n" vid ; false)) iosh1 true (* replace an entire set with a singleton. @@ -299,7 +299,7 @@ type t = (unit * int * IOS.t IH.t) module StmtStartData = - DF.StmtStartData + Dataflow.StartData (struct type t = (unit * int * IOS.t IH.t) let size = 32 end) (* entries for starting statements must be added before calling compute *) @@ -342,7 +342,7 @@ if n < 0 then () else - (Cilmsg.debug "RD: defId %d -> stm %d\n" (startDefId + n) stm.sid ; + (Kernel.debug "RD: defId %d -> stm %d\n" (startDefId + n) stm.sid ; Inthash.add defIdStmtHash (startDefId + n) stm; loop (n-1)) in @@ -373,8 +373,8 @@ let doStmt stm (_, _s, iosh) = if not(Inthash.mem sidStmtHash stm.sid) then Inthash.add sidStmtHash stm.sid stm; - if !debug then Cilmsg.debug "RD: looking at %a\n" d_stmt stm; - match L.getLiveSet stm.sid with + if !debug then Kernel.debug "RD: looking at %a\n" d_stmt stm; + match L.getLiveSet stm with | None -> DF.SDefault | Some vs -> begin iosh_filter_dead iosh vs; @@ -392,7 +392,7 @@ end -module RD = DF.ForwardsDataFlow(ReachingDef) +module RD = Dataflow.Forwards(ReachingDef) (* take the id number of a definition and return the rhs of the definition if there is one. @@ -404,10 +404,10 @@ if IH.mem rhsHtbl defId then IH.find rhsHtbl defId else let stm = try IH.find didstmh defId - with Not_found -> Cilmsg.fatal "getDefRhs: defId %d not found\n" defId in + with Not_found -> Kernel.fatal "getDefRhs: defId %d not found\n" defId in let (_,s,iosh) = - try ReachingDef.StmtStartData.find stm.sid - with Not_found -> Cilmsg.fatal "getDefRhs: sid %d not found \n" stm.sid in + try ReachingDef.StmtStartData.find stm + with Not_found -> Kernel.fatal "getDefRhs: sid %d not found \n" stm.sid in match stm.skind with Instr il -> let ivihl = instrRDs il stm.sid ((),s,iosh) true in (* defs that reach out of each instr *) @@ -431,18 +431,18 @@ Var _vi' -> (IH.add rhsHtbl defId (Some(RDExp(e),stm.sid,iosh_in)); Some(RDExp(e), stm.sid, iosh_in)) - | _ -> Cilmsg.fatal "Reaching Defs getDefRhs: right vi not first") + | _ -> Kernel.fatal "Reaching Defs getDefRhs: right vi not first") | Call(_lvo,_e,_el,_) -> (IH.add rhsHtbl defId (Some(RDCall(i),stm.sid,iosh_in)); Some(RDCall(i), stm.sid, iosh_in)) | Skip _ | Code_annot _ -> None | Asm(_a,_sl,_slvl,_sel,_sl',_) -> None) (* ? *) with Not_found -> - (if !debug then (Cilmsg.debug "getDefRhs: No instruction defines %d" defId); + (if !debug then (Kernel.debug "getDefRhs: No instruction defines %d" defId); IH.add rhsHtbl defId None; None)) with Invalid_argument _ -> None end - | _ -> Cilmsg.fatal "getDefRhs: defining statement not an instruction list %d" defId + | _ -> Kernel.fatal "getDefRhs: defining statement not an instruction list %d" defId (*None*) let prettyprint _fmt _didstmh _stmdat () (_,_s,_iosh) = () @@ -481,7 +481,7 @@ try if String.compare fdec.svar.vname (!debug_fn) = 0 then (debug := true; - Cilmsg.debug "%s =\n%a\n" (!debug_fn) d_block fdec.sbody); + Kernel.debug "%s =\n%a\n" (!debug_fn) d_block fdec.sbody); let bdy = fdec.sbody in let slst = bdy.bstmts in ReachingDef.StmtStartData.clear (); @@ -492,10 +492,10 @@ let fst_stm = List.hd slst in let fst_iosh = IH.create 32 in UD.onlyNoOffsetsAreDefs := false; - ReachingDef.StmtStartData.add fst_stm.sid ((), 0, fst_iosh); + ReachingDef.StmtStartData.add fst_stm ((), 0, fst_iosh); time "liveness" L.computeLiveness fdec; ignore(ReachingDef.computeFirstPredecessor fst_stm ((), 0, fst_iosh)); - if !debug then Cilmsg.debug "computeRDs: fst_stm.sid=%d\n" fst_stm.sid ; + if !debug then Kernel.debug "computeRDs: fst_stm.sid=%d\n" fst_stm.sid ; RD.compute [fst_stm]; if String.compare fdec.svar.vname (!debug_fn) = 0 then debug := false @@ -546,12 +546,9 @@ *) (* If this class is extended with a visitor on expressions, then the current rd data is available at each expression *) -class rdVisitorClass = object +class rdVisitorClass = object (self) inherit nopCilVisitor - (* the statement being worked on *) - val mutable sid = -1 - (* if a list of instructions is being processed, then this is the corresponding list of reaching definitions *) @@ -562,37 +559,36 @@ val mutable cur_rd_dat = None method vstmt stm = - sid <- stm.sid; - match getRDs sid with - None -> - if !debug then (Cilmsg.debug "rdVis: stm %d had no data\n" sid); + match getRDs stm with + | None -> + if !debug then (Kernel.debug "rdVis: stm %d had no data\n" stm.sid); cur_rd_dat <- None; DoChildren | Some(_,s,iosh) -> match stm.skind with Instr il -> - if !debug then (Cilmsg.debug "rdVis: visit il\n"); + if !debug then (Kernel.debug "rdVis: visit il\n"); rd_dat_lst <- instrRDs il stm.sid ((),s,iosh) false; DoChildren | _ -> - if !debug then (Cilmsg.debug "rdVis: visit non-il\n"); + if !debug then (Kernel.debug "rdVis: visit non-il\n"); cur_rd_dat <- None; DoChildren method vinst i = - if !debug then Cilmsg.debug "rdVis: before %a, rd_dat_lst is %d long\n" + if !debug then Kernel.debug "rdVis: before %a, rd_dat_lst is %d long\n" d_instr i (List.length rd_dat_lst); try cur_rd_dat <- Some(List.hd rd_dat_lst); rd_dat_lst <- List.tl rd_dat_lst; DoChildren with Failure "hd" -> - if !debug then (Cilmsg.debug "rdVis: il rd_dat_lst mismatch\n"); + if !debug then (Kernel.debug "rdVis: il rd_dat_lst mismatch\n"); DoChildren method get_cur_iosh () = match cur_rd_dat with - None -> (match getRDs sid with + None -> (match getRDs (Extlib.the self#current_stmt) with None -> None | Some(_,_,iosh) -> Some iosh) | Some(_,_,iosh) -> Some iosh diff -Nru frama-c-20110201+carbon+dfsg/cil/src/ext/rmciltmps.ml frama-c-20111001+nitrogen+dfsg/cil/src/ext/rmciltmps.ml --- frama-c-20110201+carbon+dfsg/cil/src/ext/rmciltmps.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/ext/rmciltmps.ml 2011-10-10 08:40:08.000000000 +0000 @@ -98,17 +98,17 @@ method vvrbl vi = if vi.vglob then - (if !debug then (Cilmsg.debug "memReadOrAddrOfFinder: %s is a global\n" + (if !debug then (Kernel.debug "memReadOrAddrOfFinder: %s is a global\n" vi.vname); exp_ok := false; SkipChildren) else if vi.vaddrof then (if !debug then - (Cilmsg.debug "memReadOrAddrOfFinder: %s has its address taken\n" + (Kernel.debug "memReadOrAddrOfFinder: %s has its address taken\n" vi.vname); exp_ok := false; SkipChildren) - else (if !debug then (Cilmsg.debug "memReadOrAddrOfFinder: %s does not have its address taken\n" + else (if !debug then (Kernel.debug "memReadOrAddrOfFinder: %s does not have its address taken\n" vi.vname); DoChildren) @@ -118,7 +118,7 @@ (* exp -> bool *) let exp_is_ok_replacement e = - if !debug then Cilmsg.debug "exp_is_ok_replacement: in exp_is_ok_replacement with %a\n" + if !debug then Kernel.debug "exp_is_ok_replacement: in exp_is_ok_replacement with %a\n" d_exp e; exp_ok := true; ignore(visitCilExpr memReadOrAddrOfFinder e); @@ -159,19 +159,19 @@ instruction that writes to memory? Do a dfs *) let visited_sid_isr = ref IS.empty in let rec dfs goal b start = - if !debug then Cilmsg.debug "writes_between: dfs visiting %a\n" d_stmt start; + if !debug then Kernel.debug "writes_between: dfs visiting %a\n" d_stmt start; if start.sid = goal.sid then let wh = find_write start in - (if !debug && b then (Cilmsg.debug "writes_between: start=goal and found a write\n"); - if !debug && (not b) then (Cilmsg.debug "writes_between: start=goal and no write\n"); - if !debug && wh then (Cilmsg.debug "writes_between: start=goal and write here\n"); - if !debug && (not wh) then (Cilmsg.debug "writes_between: start=goal and no write here\n"); + (if !debug && b then (Kernel.debug "writes_between: start=goal and found a write\n"); + if !debug && (not b) then (Kernel.debug "writes_between: start=goal and no write\n"); + if !debug && wh then (Kernel.debug "writes_between: start=goal and write here\n"); + if !debug && (not wh) then (Kernel.debug "writes_between: start=goal and no write here\n"); b || (find_write start)) else (* if time "List.mem1" (List.mem start.sid) (!visited_sid_lr) then false else *) if IS.mem start.sid (!visited_sid_isr) then false else let w = find_write start in - if !debug && w then Cilmsg.debug "writes_between: found write %a" d_stmt start; + if !debug && w then Kernel.debug "writes_between: found write %a" d_stmt start; visited_sid_isr := IS.add start.sid (!visited_sid_isr); let rec proc_succs sl = match sl with [] -> false | s::rest -> if dfs goal (w || b) s then true else proc_succs rest @@ -179,7 +179,7 @@ proc_succs start.succs in match stmo, dstmo with - None, _ | _, None -> Cilmsg.fatal "writes_between: defining stmt not an instr" + None, _ | _, None -> Kernel.fatal "writes_between: defining stmt not an instr" | Some stm, Some dstm -> let _ = visited_sid_isr := IS.singleton stm.sid in let from_stm = List.fold_left (dfs stm) false stm.succs in @@ -198,11 +198,11 @@ let defido = RD.iosh_singleton_lookup defiosh vi in match curido, defido with Some(curid), Some(defid) -> - (if !debug then (Cilmsg.debug "verify_unmodified: curido: %d defido: %d" curid defid); + (if !debug then (Kernel.debug "verify_unmodified: curido: %d defido: %d" curid defid); curid = defid && b) | None, None -> if not(UD.VS.mem vi fdefs) then - (if !debug then (Cilmsg.debug "verify_unmodified: %s not defined in function" vi.vname); + (if !debug then (Kernel.debug "verify_unmodified: %s not defined in function" vi.vname); b) else (* if the same set of definitions reaches, we can replace, also *) let curios = try IH.find curiosh vi.vid @@ -211,7 +211,7 @@ with Not_found -> RD.IOS.empty in RD.IOS.compare curios defios == 0 && b | _, _ -> - (if !debug then Cilmsg.debug "verify_unmodified: %s has conflicting definitions. cur: %a\n def: %a" + (if !debug then Kernel.debug "verify_unmodified: %s has conflicting definitions. cur: %a\n def: %a" vi.vname RD.ReachingDef.pretty ((),0,curiosh) RD.ReachingDef.pretty ((),0,defiosh); false)) @@ -267,21 +267,21 @@ (exp_is_ok_replacement e) && b) true el in let u,_d = UD.computeUseDefInstr i in u, safe - | _ -> Cilmsg.fatal "ok_to_replace: got non Call in RDCall." + | _ -> Kernel.fatal "ok_to_replace: got non Call in RDCall." in let target_addrof = if vi.vaddrof || vi.vglob then - (if !debug then (Cilmsg.debug "ok_to_replace: target %s had its address taken or is a global" vi.vname); + (if !debug then (Kernel.debug "ok_to_replace: target %s had its address taken or is a global" vi.vname); true) - else (if !debug then (Cilmsg.debug "ok_to_replace: target %s does not have its address taken" vi.vname); + else (if !debug then (Kernel.debug "ok_to_replace: target %s does not have its address taken" vi.vname); false) in let writes = if safe && not(target_addrof) then false else (time "writes_between" (writes_between f dsid) sid) in if (not safe || target_addrof) && writes then - (if !debug then (Cilmsg.debug "ok_to_replace: replacement not safe because of pointers or addrOf"); + (if !debug then (Kernel.debug "ok_to_replace: replacement not safe because of pointers or addrOf"); false) else let fdefs = collect_fun_defs f in - let _ = if !debug then (Cilmsg.debug "ok_to_replace: card fdefs = %d" (UD.VS.cardinal fdefs)) in - let _ = if !debug then (Cilmsg.debug "ok_to_replace: card uses = %d" (UD.VS.cardinal uses)) in + let _ = if !debug then (Kernel.debug "ok_to_replace: card fdefs = %d" (UD.VS.cardinal fdefs)) in + let _ = if !debug then (Kernel.debug "ok_to_replace: card uses = %d" (UD.VS.cardinal uses)) in verify_unmodified uses fdefs curiosh defiosh let useList = ref [] @@ -297,9 +297,10 @@ let vido = RD.iosh_defId_find iosh defid in let exists = match vido with Some _ -> true | None -> false in if vi.vid = vi'.vid && exists - then (useList := sid::(!useList); DoChildren) + then (useList := + (Extlib.the self#current_stmt)::(!useList); DoChildren) else DoChildren - | _ -> Cilmsg.fatal "useLister: no data for statement") + | _ -> Kernel.fatal "useLister: no data for statement") | _ -> DoChildren end @@ -330,15 +331,16 @@ BinOp((PlusA|PlusPI|IndexPI), {enode = Lval(Var vi', NoOffset)}, {enode = Const(CInt64(one,_,_))},_) -> - if vi.vid = vi'.vid && one = Int64.one + if vi.vid = vi'.vid && My_bigint.equal one My_bigint.one then Some(PlusA) - else if vi.vid = vi'.vid && one = Int64.minus_one + else if vi.vid = vi'.vid && + My_bigint.equal one My_bigint.minus_one then Some(MinusA) else None | BinOp((MinusA|MinusPI), {enode = Lval(Var vi', NoOffset)}, {enode = Const(CInt64(one,_,_))},_) -> - if vi.vid = vi'.vid && one = Int64.one + if vi.vid = vi'.vid && My_bigint.equal one My_bigint.one then Some(MinusA) else None | _ -> None @@ -354,26 +356,26 @@ with Not_found -> RD.IOS.empty in let redefrhso = getDefRhs curid in (match redefrhso with - None -> (if !debug then (Cilmsg.debug "ok_to_replace: couldn't get rhs for redef: %d" curid); + None -> (if !debug then (Kernel.debug "ok_to_replace: couldn't get rhs for redef: %d" curid); None) | Some(redefrhs, _, redefiosh) -> let tmprdido = RD.iosh_singleton_lookup redefiosh vi in match tmprdido with - None -> (if !debug then (Cilmsg.debug "ok_to_replace: conflicting defs of %s reach redef of %s" vi.vname rhsvi.vname); + None -> (if !debug then (Kernel.debug "ok_to_replace: conflicting defs of %s reach redef of %s" vi.vname rhsvi.vname); None) | Some tmprdid -> if not (tmprdid = id) then - (if !debug then (Cilmsg.debug "ok_to_replace: initial def of %s doesn't reach redef of %s" vi.vname rhsvi.vname); + (if !debug then (Kernel.debug "ok_to_replace: initial def of %s doesn't reach redef of %s" vi.vname rhsvi.vname); None) else let redefios = try IH.find redefiosh rhsvi.vid with Not_found -> RD.IOS.empty in let curdef_stmt = try IH.find RD.ReachingDef.defIdStmtHash curid with Not_found -> - Cilmsg.fatal "ok_to_replace: couldn't find statement defining %d" curid in + Kernel.fatal "ok_to_replace: couldn't find statement defining %d" curid in if not (RD.IOS.compare defios redefios = 0) then (if !debug then - (Cilmsg.debug + (Kernel.debug "ok_to_replace: different sets of definitions of %s reach the def of %s and the redef of %s" rhsvi.vname vi.vname @@ -385,22 +387,22 @@ Some(PlusA) -> if num_uses () = 1 then Some(curdef_stmt.sid, curid, rhsvi, PlusA) - else (if !debug then (Cilmsg.debug "ok_to_replace: tmp used more than once"); + else (if !debug then (Kernel.debug "ok_to_replace: tmp used more than once"); None) | Some(MinusA) -> if num_uses () = 1 then Some(curdef_stmt.sid, curid, rhsvi, MinusA) - else (if !debug then (Cilmsg.debug "ok_to_replace: tmp used more than once"); + else (if !debug then (Kernel.debug "ok_to_replace: tmp used more than once"); None) | None -> - (if !debug then (Cilmsg.debug "ok_to_replace: redef isn't adding or subtracting one from itself"); + (if !debug then (Kernel.debug "ok_to_replace: redef isn't adding or subtracting one from itself"); None) - | _ -> (Cilmsg.fatal "ok_to_replace: unexpected op in inc/dec info.")) - | _ -> (if !debug then (Cilmsg.debug "ok_to_replace: redef a call"); + | _ -> (Kernel.fatal "ok_to_replace: unexpected op in inc/dec info.")) + | _ -> (if !debug then (Kernel.debug "ok_to_replace: redef a call"); None))) - | _ -> (if !debug then (Cilmsg.debug "ok_to_replace: %s has conflicting definitions" rhsvi.vname); + | _ -> (if !debug then (Kernel.debug "ok_to_replace: %s has conflicting definitions" rhsvi.vname); None)) - | _ -> (if !debug then (Cilmsg.debug "ok_to_replace: rhs not of correct form"); + | _ -> (if !debug then (Kernel.debug "ok_to_replace: rhs not of correct form"); None) (* A hash from variable ids to Call instruction @@ -552,11 +554,11 @@ | _ -> true) ios in if not(RD.IOS.cardinal ios' = 1) - then (if !debug then (Cilmsg.debug "iosh_get_useful_def: multiple different defs of %d:%s(%d)" + then (if !debug then (Kernel.debug "iosh_get_useful_def: multiple different defs of %d:%s(%d)" vi.vid vi.vname (RD.IOS.cardinal ios')); None) else RD.IOS.choose ios' - else (if !debug then (Cilmsg.debug "iosh_get_useful_def: no def of %s reaches here" vi.vname); + else (if !debug then (Kernel.debug "iosh_get_useful_def: no def of %s reaches here" vi.vname); None) let ae_tmp_to_exp_change = ref false @@ -564,7 +566,7 @@ if nofrm || (check_forms vi.vname forms) then try begin let e = IH.find eh vi.vid in - if !debug then Cilmsg.debug "tmp_to_exp: changing %s to %a" + if !debug then Kernel.debug "tmp_to_exp: changing %s to %a" vi.vname d_plainexp e; match e.enode with | Const(CStr _) @@ -590,7 +592,7 @@ | Const(CWStr _) -> None | _ -> begin ae_lval_to_exp_change := true; - if !debug then Cilmsg.debug "ae: replacing %a with %a" + if !debug then Kernel.debug "ae: replacing %a with %a" d_lval lv d_exp e; Some e end @@ -605,7 +607,7 @@ | Const(CWStr _) -> None | _ -> begin ae_lval_to_exp_change := true; - Cilmsg.debug "ae: replacing %a with %a" + Kernel.debug "ae: replacing %a with %a" d_lval lv d_exp e; Some e end @@ -624,18 +626,18 @@ if nofrm || (check_forms vi.vname forms) then let ido = iosh_get_useful_def iosh vi in match ido with None -> - if !debug then (Cilmsg.debug "tmp_to_exp: non-single def: %s" + if !debug then (Kernel.debug "tmp_to_exp: non-single def: %s" vi.vname); None | Some(id) -> let defrhs = time "getDefRhs" getDefRhs id in match defrhs with None -> if !debug then - (Cilmsg.debug "tmp_to_exp: no def of %s" vi.vname); + (Kernel.debug "tmp_to_exp: no def of %s" vi.vname); None | Some(RD.RDExp(e) as r, dsid , defiosh) -> if time "ok_to_replace" (ok_to_replace vi iosh sid defiosh dsid fd) r then - (if !debug then Cilmsg.debug "tmp_to_exp: changing %s to %a" + (if !debug then Kernel.debug "tmp_to_exp: changing %s to %a" vi.vname d_plainexp e; match e.enode with | Const(CStr _) @@ -645,13 +647,13 @@ Some e end) else - (if !debug then (Cilmsg.debug "tmp_to_exp: not ok to replace %s" vi.vname); + (if !debug then (Kernel.debug "tmp_to_exp: not ok to replace %s" vi.vname); None) | _ -> - if !debug then (Cilmsg.debug "tmp_to_exp: rhs is call %s" vi.vname); + if !debug then (Kernel.debug "tmp_to_exp: rhs is call %s" vi.vname); None else - (if !debug then (Cilmsg.debug "tmp_to_exp: %s didn't match form or nofrm" vi.vname); + (if !debug then (Kernel.debug "tmp_to_exp: %s didn't match form or nofrm" vi.vname); None) let rd_fwd_subst data sid e fd nofrm = @@ -700,7 +702,7 @@ None -> None | Some(RD.RDExp({enode = Const c;eloc=loc}), _, defiosh) -> (match RD.getDefIdStmt defid with - None -> (Cilmsg.fatal "tmp_to_const: defid has no statement") + None -> (Kernel.fatal "tmp_to_const: defid has no statement") | Some(stm) -> if ok_to_replace vi iosh sid defiosh stm.sid fd (RD.RDExp(dummy_exp (Const c))) @@ -712,7 +714,7 @@ | Some(RD.RDExp({enode = Const c'}),_,defiosh) -> if Cilutil.equals c c' then match RD.getDefIdStmt defid with - None -> (Cilmsg.fatal "tmp_to_const: defid has no statement") + None -> (Kernel.fatal "tmp_to_const: defid has no statement") | Some(stm) -> ok_to_replace vi iosh sid defiosh stm.sid fd (RD.RDExp(dummy_exp (Const c'))) @@ -737,7 +739,7 @@ let e' = visitCilExpr (varXformClass ae_tmp_to_const eh sid fd nofrm) e in (e', !ae_tmp_to_const_change) -class expTempElimClass (fd:fundec) = object +class expTempElimClass (fd:fundec) = object (self) inherit RD.rdVisitorClass method vexpr e = @@ -749,13 +751,14 @@ let riviho = getDefRhs id in (match riviho with Some(RD.RDExp(e) as r, dsid, defiosh) -> - if !debug then Cilmsg.debug "Can I replace %s with %a?" + if !debug then Kernel.debug "Can I replace %s with %a?" vi.vname d_exp e; - if ok_to_replace vi iosh sid defiosh dsid fd r + if ok_to_replace + vi iosh (Extlib.the self#current_stmt).sid defiosh dsid fd r then - (if !debug then (Cilmsg.debug "Yes."); + (if !debug then (Kernel.debug "Yes."); ChangeTo(e)) - else (if !debug then (Cilmsg.debug "No."); + else (if !debug then (Kernel.debug "No."); DoChildren) | _ -> DoChildren) | _ -> DoChildren) @@ -767,15 +770,15 @@ (* only allowed to replace a tmp with a function call once *) (match cur_rd_dat with Some(_,_s,iosh) -> do_change iosh vi - | None -> let iviho = RD.getRDs sid in + | None -> let iviho = RD.getRDs (Extlib.the self#current_stmt) in match iviho with Some(_,_s,iosh) -> (if !debug then - (Cilmsg.debug "Try to change %s outside of instruction." vi.vname); + (Kernel.debug "Try to change %s outside of instruction." vi.vname); do_change iosh vi) | None -> (if !debug then - (Cilmsg.debug "%s in statement w/o RD info" vi.vname); + (Kernel.debug "%s in statement w/o RD info" vi.vname); DoChildren)) else DoChildren) | _ -> DoChildren @@ -789,13 +792,14 @@ match self#get_cur_eh () with | None -> DoChildren | Some eh -> begin - let e', _ = ae_lv_fwd_subst eh sid e fd false in + let e', _ = + ae_lv_fwd_subst eh (Extlib.the self#current_stmt).sid e fd false in ChangeTo e' end end -class incdecTempElimClass (fd:fundec) = object +class incdecTempElimClass (fd:fundec) = object (self) inherit RD.rdVisitorClass method vexpr e = @@ -809,15 +813,15 @@ Some(RD.RDExp _e as r, _, defiosh) -> (match ok_to_replace_with_incdec iosh defiosh fd id vi r with Some(curdef_stmt_id,redefid, rhsvi, b) -> - (if !debug then (Cilmsg.debug "No, but I can replace it with a post-inc/dec"); - if !debug then (Cilmsg.debug "cdsi: %d redefid: %d name: %s" + (if !debug then (Kernel.debug "No, but I can replace it with a post-inc/dec"); + if !debug then (Kernel.debug "cdsi: %d redefid: %d name: %s" curdef_stmt_id redefid rhsvi.vname); IH.add incdecHash vi.vid (redefid, rhsvi, b); id_dh_add rhsvi.vid (curdef_stmt_id, redefid); DoChildren) | None -> - (if !debug then (Cilmsg.debug "No."); + (if !debug then (Kernel.debug "No."); DoChildren)) | _ -> DoChildren) | _ -> DoChildren) @@ -829,20 +833,20 @@ (* only allowed to replace a tmp with an inc/dec if there is only one use *) (match cur_rd_dat with Some(_,_s,iosh) -> do_change iosh vi - | None -> let iviho = RD.getRDs sid in + | None -> let iviho = RD.getRDs (Extlib.the self#current_stmt) in match iviho with Some(_,_s,iosh) -> - (if !debug then (Cilmsg.debug "Try to change %s outside of instruction." vi.vname); + (if !debug then (Kernel.debug "Try to change %s outside of instruction." vi.vname); do_change iosh vi) | None -> - (if !debug then (Cilmsg.debug "%s in statement w/o RD info" vi.vname); + (if !debug then (Kernel.debug "%s in statement w/o RD info" vi.vname); DoChildren)) else DoChildren) | _ -> DoChildren end -class callTempElimClass (fd:fundec) = object +class callTempElimClass (fd:fundec) = object (self) inherit RD.rdVisitorClass method vexpr e = @@ -854,12 +858,13 @@ let riviho = getDefRhs id in (match riviho with Some(RD.RDCall(i) as r, dsid, defiosh) -> - if !debug then Cilmsg.debug "Can I replace %s with %a?" vi.vname d_instr i; - if ok_to_replace vi iosh sid defiosh dsid fd r - then (if !debug then (Cilmsg.debug "Yes."); + if !debug then Kernel.debug "Can I replace %s with %a?" vi.vname d_instr i; + if ok_to_replace + vi iosh (Extlib.the self#current_stmt).sid defiosh dsid fd r + then (if !debug then (Kernel.debug "Yes."); IH.add iioh vi.vid (Some(i)); DoChildren) - else (if !debug then (Cilmsg.debug "No."); + else (if !debug then (Kernel.debug "No."); DoChildren) | _ -> DoChildren) | _ -> DoChildren) @@ -874,13 +879,13 @@ else (match cur_rd_dat with Some(_,_s,iosh) -> do_change iosh vi - | None -> let iviho = RD.getRDs sid in + | None -> let iviho = RD.getRDs (Extlib.the self#current_stmt) in match iviho with Some(_,_s,iosh) -> - (if !debug then (Cilmsg.debug "Try to change %s:%d outside of instruction." vi.vname vi.vid); + (if !debug then (Kernel.debug "Try to change %s:%d outside of instruction." vi.vname vi.vid); do_change iosh vi) | None -> - (if !debug then (Cilmsg.debug "%s in statement w/o RD info" vi.vname); + (if !debug then (Kernel.debug "%s in statement w/o RD info" vi.vname); DoChildren)) else DoChildren) | _ -> DoChildren @@ -891,13 +896,13 @@ code elimination is performed before printing. *) method vinst i = (* Need to copy this from rdVisitorClass because we are overriding *) - if !debug then Cilmsg.debug "rdVis: before %a, rd_dat_lst is %d long" + if !debug then Kernel.debug "rdVis: before %a, rd_dat_lst is %d long" d_instr i (List.length rd_dat_lst); (try cur_rd_dat <- Some(List.hd rd_dat_lst); rd_dat_lst <- List.tl rd_dat_lst with Failure "hd" -> - if !debug then (Cilmsg.debug "rdVis: il rd_dat_lst mismatch")); + if !debug then (Kernel.debug "rdVis: il rd_dat_lst mismatch")); match i with Set((Var vi,_off),_,_) -> if IH.mem iioh vi.vid @@ -942,9 +947,9 @@ List.exists (function (Attr("volatile",_)) -> true | _ -> false) (typeAttrs vi.vtype) in if !debug && (vi_vol || typ_vol) then - (Cilmsg.debug "unusedRemover: %s is volatile" vi.vname); + (Kernel.debug "unusedRemover: %s is volatile" vi.vname); if !debug && not(vi_vol || typ_vol) then - (Cilmsg.debug "unusedRemover: %s is not volatile" vi.vname); + (Kernel.debug "unusedRemover: %s is not volatile" vi.vname); vi_vol || typ_vol @@ -981,7 +986,7 @@ let unused = List.fold_left (fun un vi -> if UD.VS.mem vi used then un - else (if !debug then (Cilmsg.debug "unusedRemoverClass: %s is unused" vi.vname); + else (if !debug then (Kernel.debug "unusedRemoverClass: %s is unused" vi.vname); UD.VS.add vi un)) UD.VS.empty f.slocals in unused_set <- unused; let good_locals = List.filter self#good_var f.slocals in @@ -1009,23 +1014,23 @@ match findf_in_pl stm.sid pl with (_sid,redefid)::_l -> let rhso = getDefRhs redefid in (match rhso with - None -> (if !debug then (Cilmsg.debug "check_incdec: couldn't find rhs for def %d" redefid); + None -> (if !debug then (Kernel.debug "check_incdec: couldn't find rhs for def %d" redefid); false) | Some(rhs, _, _indiosh) -> (match rhs with - RD.RDCall _ -> (if !debug then Cilmsg.debug "check_incdec: rhs not an expression"; + RD.RDCall _ -> (if !debug then Kernel.debug "check_incdec: rhs not an expression"; false) | RD.RDExp e' -> if compareExp e e' then true - else (if !debug then Cilmsg.debug "check_incdec: rhs of %d: %a, and needed redef %a not equal" + else (if !debug then Kernel.debug "check_incdec: rhs of %d: %a, and needed redef %a not equal" redefid d_plainexp e' d_plainexp e; false))) - | [] -> (if !debug then Cilmsg.debug "check_incdec: current statement not in list: %d. %s = %a" + | [] -> (if !debug then Kernel.debug "check_incdec: current statement not in list: %d. %s = %a" stm.sid vi.vname d_exp e; false) - else (if !debug then Cilmsg.debug "check_incdec: %s not in idDefHash" + else (if !debug then Kernel.debug "check_incdec: %s not in idDefHash" vi.vname; false) in diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cabs2cil.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabs2cil.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cabs2cil.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabs2cil.ml 2011-10-10 08:40:08.000000000 +0000 @@ -46,8 +46,9 @@ module C = Cabshelper module V = Cabsvisit module H = Hashtbl -module IH = Inthash +module IH = Datatype.Int.Hashtbl module AL = Alpha +module Global_machdep = Machdep open Pretty_utils open Cabs @@ -57,38 +58,18 @@ open Cil_datatype open Cilutil open Lexing +open Kernel let debugGlobal = true let continueOnError = false +let frama_c_keep_block = "FRAMA_C_KEEP_BLOCK" +let () = Cil.register_shallow_attribute frama_c_keep_block + (** Leave a certain global alone. Use a negative number to disable. *) let nocil: int ref = ref (-1) -(* NB: The three flags below are controlled by Frama-C parameters. Do not - change their default value here, but in parameters.ml. *) - -(** Turn on tranformation that forces right to left - parameter evaluation order *) -let forceRLArgEval = ref false - -(** Indicates whether we're allowed to duplicate small chunks. *) -let allowDuplication: bool ref = ref true - -(** If false, the destination of a Call instruction should always have the - same type as the function's return type. Where needed, CIL will insert - a temporary to make this happen. - - If true, the destination type may differ from the return type, so there - is an implicit cast. This is useful for analyses involving [malloc], - because the instruction "T* x = malloc(...);" won't be broken into - two instructions, so it's easy to find the allocation type. - - This is false by default. Set to true to replicate the behavior - of CIL 1.3.5 and earlier. -*) -let doCollapseCallCast: bool ref = ref true - (** A hook into the code that creates temporary local vars. By default this is the identity function, but you can overwrite it if you need to change the types of cabs2cil-introduced temp variables. *) @@ -169,10 +150,37 @@ Var _, o -> is_dangerous_offset o | Mem _,_ -> true + +class check_no_locals = object + inherit nopCilVisitor + method vlval (h,_) = + (match h with + | Var v -> + if not v.vglob then + Kernel.error ~current:true + "Forbidden access to local variable %a in static initializer" + d_var v + | _ -> ()); + DoChildren +end + +let rec check_no_locals_in_initializer i = + match i with + | SingleInit e -> + ignore (visitCilExpr (new check_no_locals) e) + | CompoundInit (ct, initl) -> + foldLeftCompound ~implicit:false + ~doinit:(fun _off' i' _ () -> + check_no_locals_in_initializer i') + ~ct:ct + ~initl:initl + ~acc:() + + (* ---------- source error message handling ------------- *) -let cabslu = - {Lexing.dummy_pos with pos_fname="Cabs2cil_start"}, - {Lexing.dummy_pos with pos_fname="Cabs2cil_end"} +let cabslu s = + {Lexing.dummy_pos with pos_fname="Cabs2cil_start"^s}, + {Lexing.dummy_pos with pos_fname="Cabs2cil_end"^s} exception NoReturn @@ -191,6 +199,119 @@ lp <= ls && String.sub s 0 lp = p +(***** PROCESS PRAGMAS **********) + +(* ICC align/noalign pragmas (not supported by GCC/MSVC with this syntax). + Implemented by translating them to 'aligned' attributes. Currently, + only default and noalign are supported, not explicit alignment values. + Cf. www.slac.stanford.edu/grp/cd/soft/rmx/manuals/IC_386.PDF *) +let current_pragma_align = ref (None : bool option) +let pragma_align_by_struct = H.create 17 + +let process_align_pragma name args = + let aux pname v = + (if theMachine.msvcMode + then Kernel.warning else Kernel.debug ~level:1 ?dkey:None) + ~current:true "Parsing ICC '%s' pragma." pname; + match args with + | [] -> current_pragma_align := Some v + | l -> + List.iter + (function + | AStr s | ACons (s, _) -> H.replace pragma_align_by_struct s v + | _ -> Kernel.warning ~current:true + "Unsupported '%s' pragma not honored by Frama-C." pname + ) l + in + match name with + | "align" -> aux "align" true + | "noalign" -> aux "noalign" false + | _ -> () + +let align_pragma_for_struct sname = + try Some (H.find pragma_align_by_struct sname) + with Not_found -> !current_pragma_align + +(* The syntax and semantics for the pack pragmas are GCC's. + The MSVC ones seems quite different and specific code should + be written so support it. *) + +(* The pack pragma stack *) +let packing_pragma_stack = Stack.create () + +(* The current pack pragma *) +let current_packing_pragma = ref None +let process_pack_pragma name args = + begin match name with + | "pack" -> begin + if theMachine.msvcMode then + Kernel.warning ~current:true + "'pack' pragmas are probably incorrect in MSVC mode. \ + Using GCC like pragmas."; + match args with + | [] (* #pragma pack() *) -> + current_packing_pragma := None; None + | [AInt n] (* #pragma pack(n) *) -> + current_packing_pragma := Some n; None + | [ACons ("push",[])] (* #pragma pack(push) *) -> + Stack.push !current_packing_pragma packing_pragma_stack; None + | [ACons ("push",[AInt n])] (* #pragma pack(push,n) *) -> + Stack.push !current_packing_pragma packing_pragma_stack; + current_packing_pragma:= Some n; None + | [ACons ("pop",[])] (* #pragma pack(pop) *) -> + begin try + current_packing_pragma := Stack.pop packing_pragma_stack; + None + with Stack.Empty -> + Kernel.warning ~current:true + "Inconsistent #pragma pack(pop). Using default packing."; + current_packing_pragma := None; None + end + | [ACons ("show",[])] (* #pragma pack(show) *) -> + Some (Attr (name, args)) + | _ -> + Kernel.warning ~current:true + "Unsupported packing pragma not honored by Frama-C."; + Some (Attr (name, args)) + end + | _ -> Some (Attr (name, args)) + end + +let force_packed_attribute a = + if hasAttribute "packed" a then a + else addAttribute (Attr("packed",[])) a + +let add_packing_attributes s a = + match !current_packing_pragma, align_pragma_for_struct s.corig_name with + | None, None -> a + | Some n, _ -> (* ignore 'align' pragma if some 'pack' pragmas are present + (no known compiler support both syntaxes) *) + let with_aligned_attributes = + match filterAttributes "aligned" a with + | [] (* no aligned attributes yet. Add the global one. *) -> + addAttribute (Attr("aligned",[AInt n])) a + | [Attr("aligned",[AInt local])] + (* The largest aligned wins with GCC. Don't know + with other compilers. *) -> + addAttribute (Attr("aligned",[AInt (max local n)])) + (dropAttribute "aligned" a) + | [Attr("aligned",[])] -> (* This one always wins as it is the + biggest available on the plateform. *) + a + | _ -> Kernel.warning ~current:true + "Unknown aligned attribute syntax: keeping it as is and \ + adding new one."; + addAttribute (Attr("aligned",[AInt n])) a + in + force_packed_attribute with_aligned_attributes + + | None, Some true -> + dropAttribute "aligned" a + | None, Some false -> + force_packed_attribute + (addAttribute (Attr("aligned",[AInt 1])) (dropAttribute "aligned" a)) + + (***** COMPUTED GOTO ************) (* The address of labels are small integers (starting from 0). A computed @@ -213,15 +334,16 @@ * is *) let isTransparentUnion (t: typ) : fieldinfo option = match unrollType t with - TComp (comp, _, _) when not comp.cstruct -> + | TComp (comp, _, _) when not comp.cstruct -> (* Turn transparent unions into the type of their first field *) - if hasAttribute "transparent_union" (typeAttrs t) then begin - match comp.cfields with - f :: _ -> Some f - | _ -> - Cil.abort "Empty transparent union: %s" (compFullName comp) - end else - None + if hasAttribute "transparent_union" (typeAttrs t) then begin + match comp.cfields with + | [] -> + Kernel.abort ~current:true + "Empty transparent union: %s" (compFullName comp) + | f :: _ -> Some f + end else + None | _ -> None (* When we process an argument list, remember the argument index which has a @@ -232,7 +354,7 @@ let debugLoc = false let convLoc (l : cabsloc) = if debugLoc then - Cilmsg.debug "convLoc at %s: line %d, btye %d\n" + Kernel.debug "convLoc at %s: line %d, btye %d\n" (fst l).Lexing.pos_fname (fst l).Lexing.pos_lnum (fst l).Lexing.pos_bol; l @@ -244,15 +366,9 @@ if theMachine.msvcMode then n = "va_list" || n = "__ccured_va_list" else n = "__builtin_va_alist_t" -let isVariadicListType t = - match unrollType t with - | TBuiltin_va_list _ -> true - | _ -> false - - (*** EXPRESSIONS *************) - (* We collect here the program *) +(* We collect here the program *) let theFile : global list ref = ref [] let theFileTypes : global list ref = ref [] @@ -383,8 +499,9 @@ (match !scopes with [] -> begin match d with - EnvVar _ -> - Cil.fatal "addLocalToEnv: not in a scope when adding %s!" n + | EnvVar _ -> + Kernel.fatal ~current:true + "addLocalToEnv: not in a scope when adding %s!" n | _ -> () (* We might add types *) end | s :: _ -> @@ -462,7 +579,7 @@ (*** In order to process GNU_BODY expressions we must record that a given *** COMPUTATION is interesting *) let gnu_body_result : (A.statement * ((exp * typ) option ref)) ref - = ref ({stmt_ghost = false; stmt_node = A.NOP cabslu}, ref None) + = ref ({stmt_ghost = false; stmt_node = A.NOP (cabslu "_NOP")}, ref None) (*** When we do statements we need to know the current return type *) let currentReturnType : typ ref = ref (TVoid([])) @@ -550,8 +667,9 @@ (* And continue using the last name *) vi with Not_found -> - Cil.abort - "It seems that we would need to rename global %s (to %s) because of previous occurrence at %a" + Kernel.abort ~current:true + "It seems that we would need to rename global %s (to %s) \ +because of previous occurrence at %a" vi.vname newname d_loc oldloc; end end else begin @@ -579,67 +697,6 @@ newvi.vname docAlphaTable alphaTable); *) newvi - -(* Strip the "const" from the type. It is unfortunate that const variables - * can only be set in initialization. Once we decided to move all - * declarations to the top of the functions, we have no way of setting a - * "const" variable. Furthermore, if the type of the variable is an array or - * a struct we must recursively strip the "const" from fields and array - * elements. *) -let rec stripConstLocalType (t: typ) : typ = - let dc a = - if hasAttribute "const" a then - dropAttribute "const" a - else a - in - match t with - | TPtr (bt, a) -> - (* We want to be able to detect by pointer equality if the type has - * changed. So, don't realloc the type unless necessary. *) - let a' = dc a in if a != a' then TPtr(bt, a') else t - | TInt (ik, a) -> - let a' = dc a in if a != a' then TInt(ik, a') else t - | TFloat(fk, a) -> - let a' = dc a in if a != a' then TFloat(fk, a') else t - | TNamed (ti, a) -> - (* We must go and drop the consts from the typeinfo as well ! *) - let t' = stripConstLocalType ti.ttype in - if t != t' then begin - (* ignore (warn "Stripping \"const\" from typedef %s\n" ti.tname); *) - ti.ttype <- t' - end; - let a' = dc a in if a != a' then TNamed(ti, a') else t - - | TEnum (ei, a) -> - let a' = dc a in if a != a' then TEnum(ei, a') else t - - | TArray(bt, leno, _, a) -> - (* We never assign to the array. So, no need to change the const. But - * we must change it on the base type *) - let bt' = stripConstLocalType bt in - if bt' != bt then TArray(bt', leno, empty_size_cache (), a) else t - - | TComp(ci, _, a) -> - (* Must change both this structure as well as its fields *) - List.iter - (fun f -> - let t' = stripConstLocalType f.ftype in - if t' != f.ftype then begin - Cil.warnOpt "Stripping \"const\" from field %s of %s\n" - f.fname (compFullName ci) ; - f.ftype <- t' - end) - ci.cfields; - let a' = dc a in if a != a' then TComp(ci, empty_size_cache (), a') else t - - (* We never assign functions either *) - | TFun(_rt, _args, _va, _a) -> t - | TVoid _ -> (* this may happen with temporary used only for their sizeof. *) - t - | TBuiltin_va_list a -> - let a' = dc a in if a != a' then TBuiltin_va_list a' else t - - let constFoldTypeVisitor = object inherit nopCilVisitor method vtype t: typ visitAction = @@ -662,9 +719,9 @@ (* Create a new temporary variable *) let newTempVar descr (descrpure:bool) typ = if !currentFunctionFDEC.svar.vname == "@dummy@" then - Cil.fatal "newTempVar called outside a function" ; + Kernel.fatal ~current:true "newTempVar called outside a function" ; (* ignore (E.log "stripConstLocalType(%a) for temporary\n" d_type typ); *) - let t' = (!typeForInsertedVar) (stripConstLocalType typ) in + let t' = (!typeForInsertedVar) (Cil.stripConstLocalType typ) in (* Start with the name "tmp". The alpha converter will fix it *) let vi = makeVarinfo false false "tmp" t' in vi.vdescr <- descr; @@ -725,7 +782,7 @@ try lookupTypeNoError kind n with Not_found -> - Cil.fatal "Cannot find type %s (kind:%s)\n" n kind + Kernel.fatal ~current:true "Cannot find type %s (kind:%s)" n kind (* Create the self ref cell and add it to the map. Return also an indication * if this is a new one. *) @@ -750,7 +807,8 @@ with Not_found -> begin (* Create a enuminfo *) let enum = { eorig_name = n; ename = n; eitems = []; - eattr = []; ereferenced = false; } in + eattr = []; ereferenced = false; ekind = IInt ; } + in H.add enumInfoNameEnv n enum; enum, true end @@ -801,11 +859,280 @@ ignore (visitCilStmt vis s); !pRes + +(******** CASTS *********) + +let arithmeticConversion = Cil.arithmeticConversion + +let integralPromotion = Cil.integralPromotion + +let rec check_strict_attributes ~direct ot nt = + let w ?name () = + let s = (match name with + | None -> "" + | Some n -> "through fields " ^ n) + in + if direct then + Kernel.warning ~current:true + "cannot drop strict attributes from %a to %a %s" d_type ot d_type nt s + else + Kernel.warning ~current:true + "cannot add strict attributes of %a to %a %s" d_type ot d_type nt s; + false + in + let is_strict_attr a = attributeName a = "address_space" in + let strict_attr a = List.filter is_strict_attr a in + let check oa na = + if (List.for_all + (fun x -> List.exists (Cilutil.equals x) (strict_attr na)) (strict_attr oa)) + then true else w () + in + let exists_strict_attribute_deep ?name ty = + match exists_attribute_deep is_strict_attr ty with + | None -> true + | Some l -> let n = Pretty_utils.sfprintf "%a%a" + (Cilutil.pretty_opt (fun fmt -> Format.fprintf fmt "%s, ")) name + (Cilutil.pretty_list (fun fmt -> Format.fprintf fmt ", ") + Format.pp_print_string) + l + in + w ~name:n () + in + let check_comp_fields l = + List.fold_left + (fun acc fi -> + acc + && + (List.for_all (fun x -> (if is_strict_attr x then w ~name:fi.fname () else true)) fi.fattr) + && + (exists_strict_attribute_deep ~name:fi.fname fi.ftype) + ) + true + l + in + match unrollType ot, unrollType nt with + | TNamed _, _ | _, TNamed _ -> assert false + + | (TVoid o|TInt(_,o)|TEnum (_,o)|TFloat(_,o)|TBuiltin_va_list (o)), + (TVoid n|TInt(_,n)|TEnum (_,n)|TFloat(_,n)|TBuiltin_va_list (n)) + -> check o n + | (TArray (ot,_,_,o)|TPtr (ot, o)), (TArray (nt,_,_,n)|TPtr(nt, n)) -> + check o n && check_strict_attributes ~direct ot nt + | ((TVoid o|TInt(_,o)|TEnum (_,o)|TFloat(_,o)|TBuiltin_va_list (o)), + (TArray (_,_,_,n)|TPtr(_, n))) -> + check o n + | ((TArray (ot,_,_,o)|TPtr (ot, o)), + (TVoid n|TInt(_,n)|TEnum (_,n)|TFloat(_,n)|TBuiltin_va_list (n))) -> + check o n && (exists_strict_attribute_deep ot) + | TComp ({ckey=ok; cattr=oia; cfields=l}, _, oa), TComp ({ckey=nk; cattr=nia}, _, na) -> + ok=nk || (check (addAttributes oa oia) (addAttributes na nia) + && check_comp_fields l) + | TComp ({cattr=co; cfields=l}, _, o),nt -> + check (addAttributes o co) (typeAttr nt) && + check_comp_fields l + + | (TVoid o|TInt(_,o)|TEnum (_,o)|TFloat(_,o)|TBuiltin_va_list (o)) ,TComp ({cattr=no},_,n)-> + check o (addAttributes no n) + + | (TArray (ot,_,_,o)|TPtr (ot, o)),TComp ({cattr=no},_,n)-> + check o (addAttributes no n) + && + (exists_strict_attribute_deep ot) + | TFun (_, _, _, _),_ + | _,TFun (_, _, _, _) -> (exists_strict_attribute_deep ot) + +(* true if the expression is known to be a boolean result, i.e. 0 or 1. *) +let rec is_boolean_result e = + match e.enode with + | Const _ -> + (match Cil.isInteger e with + | Some i -> + My_bigint.equal i My_bigint.zero || My_bigint.equal i My_bigint.one + | None -> false) + | CastE (_,e) -> is_boolean_result e + | BinOp((Lt | Gt | Le | Ge | Eq | Ne | LAnd | LOr),_,_,_) -> true + | BinOp((PlusA | PlusPI | IndexPI | MinusA | MinusPI | MinusPP | Mult + | Div | Mod | Shiftlt | Shiftrt | BAnd | BXor | BOr),_,_,_) -> false + | UnOp(LNot,_,_) -> true + | UnOp ((Neg | BNot),_,_) -> false + | Lval _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ + | AlignOfE _ | AddrOf _ | StartOf _ | Info _ -> false + +(* Specify whether the cast is from the source code *) +let rec castTo ?(fromsource=false) + (ot : typ) (nt : typ) (e : exp) : (typ * exp ) = + let debugCast = true in + if debugCast then + Kernel.debug "@[%t: castTo:%s %a->%a@\n@]" + d_thisloc (if fromsource then "(source)" else "") + d_type ot d_type nt; + + let ot' = unrollType ot in + let nt' = unrollType nt in + if not fromsource && not (need_cast ot' nt') then + (* Do not put the cast if it is not necessary, unless it is from the + * source. *) + (if debugCast then Kernel.debug "no cast to perform"; + (ot, e)) + else begin + let nt' = if fromsource then nt' else !typeForInsertedCast e ot' nt' in + let result = (nt', if theMachine.insertImplicitCasts || fromsource then + Cil.mkCastT e ot nt' else e) + in +(* [BM] uncomment the following line to enable attributes static typing + ignore (check_strict_attributes true ot nt && check_strict_attributes false nt ot);*) + if debugCast then + Kernel.debug "@[castTo: ot=%a nt=%a\n result is %a@\n@]" + d_type ot d_type nt' + d_plainexp (snd result); + + (* Now see if we can have a cast here *) + match ot', nt' with + TNamed _, _ + | _, TNamed _ -> Kernel.fatal ~current:true "unrollType failed in castTo" + | _, TInt(IBool,_) -> + if is_boolean_result e then result + else + nt, + Cil.mkCastT + (constFold true + (new_exp ~loc:e.eloc + (BinOp(Ne,e,Cil.integer ~loc:e.eloc 0,intType)))) + ot nt' + | TInt(_,_), TInt(_,_) -> + (* We used to ignore attributes on integer-integer casts. Not anymore *) + (* if ikindo = ikindn then (nt, e) else *) + result + | TPtr (_, _), TPtr(_, _) -> result + + | TInt _, TPtr _ -> result + + | TPtr _, TInt _ -> result + + | TArray _, TPtr _ -> result + + | TArray(t1,_,_,_), TArray(t2,None,_,_) + when Cilutil.equals (typeSig t1) (typeSig t2) -> (nt', e) + + | TPtr _, TArray(_,_,_,_) -> (nt', e) + + | TEnum _, TInt _ -> result + | TFloat _, (TInt _|TEnum _) -> result + | (TInt _|TEnum _), TFloat _ -> result + | TFloat _, TFloat _ -> result + | TInt (ik,_), TEnum (ei,[]) -> + (match e.enode with + | Const (CEnum { eihost = ei'}) + when + ei.ename = ei'.ename && + Cil.bytesSizeOfInt ik = Cil.bytesSizeOfInt ei'.ekind + -> (nt',e) + | _ -> result) + | TInt _, TEnum _ -> result + | TEnum _, TEnum _ -> result + + | TEnum _, TPtr _ -> result + | TBuiltin_va_list _, (TInt _ | TPtr _) -> + result + + | (TInt _ | TPtr _), TBuiltin_va_list _ -> + Kernel.debug ~level:3 "Casting %a to __builtin_va_list" d_type ot ; + result + + | TPtr _, TEnum _ -> + Kernel.debug ~level:3 "Casting a pointer into an enumeration type" ; + result + + (* The expression is evaluated for its effects *) + | (TInt _ | TEnum _ | TPtr _ ), TVoid _ -> + (ot, e) + + (* Even casts between structs are allowed when we are only + * modifying some attributes *) + | TComp (comp1, _, _), TComp (comp2, _, _) when comp1.ckey = comp2.ckey -> + result + + (** If we try to pass a transparent union value to a function + * expecting a transparent union argument, the argument type would + * have been changed to the type of the first argument, and we'll + * see a cast from a union to the type of the first argument. Turn + * that into a field access *) + | TComp(_, _, _), _ -> begin + match isTransparentUnion ot with + | None -> + Kernel.fatal ~current:true "castTo %a -> %a" d_type ot d_type nt' + | Some fstfield -> begin + (* We do it now only if the expression is an lval *) + let e' = + match e.enode with + | Lval lv -> + new_exp ~loc:e.eloc + (Lval (addOffsetLval (Field(fstfield, NoOffset)) lv)) + | _ -> + Kernel.fatal ~current:true + "castTo: transparent union expression is not an lval: %a\n" + d_exp e + in + (* Continue casting *) + castTo ~fromsource:fromsource fstfield.ftype nt' e' + end + end + | _ -> + Kernel.fatal ~current:true + "cabs2cil: castTo %a -> %a@\n" d_type ot d_type nt' + end + +(* Like Cil.mkCastT, but it calls typeForInsertedCast *) +let makeCastT ~(e: exp) ~(oldt: typ) ~(newt: typ) = + if need_cast oldt newt then + Cil.mkCastT e oldt (!typeForInsertedCast e oldt newt) + else e + +let makeCast ~(e: exp) ~(newt: typ) = + makeCastT e (typeOf e) newt + +(* A cast that is used for conditional expressions. Pointers are Ok. + Abort if invalid *) +let checkBool (ot : typ) (_ : exp) = + match unrollType ot with + | TInt _ + | TPtr _ + | TEnum _ + | TFloat _ -> () + | _ -> Kernel.fatal ~current:true "castToBool %a" d_type ot + +(* Given an expression that is being coerced to bool, + is it a nonzero constant? *) +let rec isConstTrue (e:exp): bool = + match e.enode with + | Const(CInt64 (n,_,_)) -> not (My_bigint.equal n My_bigint.zero) + | Const(CChr c) -> 0 <> Char.code c + | Const(CStr _ | CWStr _) -> true + | Const(CReal(f, _, _)) -> f <> 0.0; + | CastE(_, e) -> isConstTrue e + | _ -> false + +(* Given an expression that is being coerced to bool, is it zero? + This is a more general version of Cil.isZero, which only handles integers. + On constant expressions, either isConstTrue or isConstFalse will hold. *) +let rec isConstFalse (e:exp): bool = + match e.enode with + | Const(CInt64 (n,_,_)) -> My_bigint.equal n My_bigint.zero + | Const(CChr c) -> 0 = Char.code c + | Const(CReal(f, _, _)) -> f = 0.0; + | CastE(_, e) -> isConstFalse e + | _ -> false + + module BlockChunk = struct type chunk = { stmts: (stmt * lval list * lval list * lval list * stmt ref list) list; - (* statements of the chunk. Each statements comes with the list of + (* statements of the chunk. + + This list is built on reverse order. + + Each statements comes with the list of pending modified, written and read values. The first category represents values which are to be modified during the execution of the chunk and whose new value depends on the @@ -823,8 +1150,6 @@ chunk is unspecified. *) locals: varinfo list; (* variables that are local to the chunk. *) - postins: (stmt * lval list * lval list * lval list * stmt ref list) list; - (* Some statements to append at the ends of stmts (in reverse order) *) cases: stmt list; (* A list of case statements * (statements with Case labels) * visible at the outer level *) @@ -845,32 +1170,29 @@ unspecified let d_chunk fmt (c: chunk) = - Format.fprintf fmt "@[%a%a{ @[%a@] };@?%a@]" + Format.fprintf fmt "@[%a%a{ @[%a@] }@]" (fun fmt b -> if b then Format.fprintf fmt "/* UNDEFINED ORDER */@\n") c.unspecified_order (Pretty_utils.pp_list ~sep:";" defaultCilPrinter#pVar) c.locals - (Pretty_utils.pp_list ~sep:";" (d_stmt_chunk c.unspecified_order)) c.stmts - (Pretty_utils.pp_list ~sep:";" (d_stmt_chunk c.unspecified_order)) - (List.rev c.postins) + (Pretty_utils.pp_list ~sep:";" (d_stmt_chunk c.unspecified_order)) + (List.rev c.stmts) let empty = - { stmts = []; postins = []; cases = []; locals = []; + { stmts = []; cases = []; locals = []; unspecified_order = false; } - + let empty_stmts l = let rec is_empty_stmt s = match s.skind with Instr (Skip _) -> true - | Block b -> - b.battrs = [] && - List.for_all is_empty_stmt b.bstmts + | Block b -> b.battrs = [] && List.for_all is_empty_stmt b.bstmts | UnspecifiedSequence seq -> - List.for_all is_empty_stmt (List.map (fun (x,_,_,_,_) -> x) seq) + List.for_all is_empty_stmt (List.map (fun (x,_,_,_,_) -> x) seq) | _ -> false in List.for_all is_empty_stmt (List.map (fun (x,_,_,_,_) -> x) l) - let isEmpty c = empty_stmts c.stmts && empty_stmts c.postins + let isEmpty c = empty_stmts c.stmts let isNotEmpty c = not (isEmpty c) @@ -879,7 +1201,7 @@ Instr(Call _) -> [ref i] | _ -> [] in - { empty with postins = [i,m,w,r,c]; } + { empty with stmts = [i,m,w,r,c]; } (* Keep track of the gotos *) let backPatchGotos : (string, stmt ref list ref) H.t = H.create 17 @@ -909,7 +1231,7 @@ List.iter (fun gref -> gref := dest) !gotos; (* Format.eprintf "Label %s associated to %a@." lname d_stmt dest*) with Not_found -> begin - Cil.error "Label %s not found" lname + Kernel.error ~current:true "Label %s not found" lname end) backPatchGotos @@ -943,7 +1265,7 @@ try ref (H.find labels s) with Not_found when List.mem s !label_current -> - let my_ref = ref (mkEmptyStmt ~loc:cabslu ()) in + let my_ref = ref (mkEmptyStmt ~loc:(cabslu "_find_label") ()) in addGoto s my_ref; my_ref let remove_label l = @@ -964,33 +1286,6 @@ H.replace labelStmt s labstmt | Case _ | Default _ -> () - let pushPostIns c = - let stmts = - match c.stmts with - [ { skind = Block b; labels = []},modified,writes,reads,calls] - when not c.unspecified_order && b.blocals = [] && b.battrs = [] - -> - (* we can't map the effects on every statement of - the block (otherwise, we'd end up multiplying them). - *) - (match b.bstmts,writes,reads with - [],[],[] -> [] - | [],_,_ -> [Cil.mkEmptyStmt ~loc:cabslu (), - modified,writes,reads,calls] - | hd::tl,_,_ -> - (hd,modified,writes,reads,calls):: - (List.map (fun x->x,modified,[],[],[]) tl)) - - | [ { skind = UnspecifiedSequence seq ; labels = []},_,_,_,_] - (* the effects are also present in the sequence itself, no - need to consider them. *) - when c.unspecified_order - -> - seq - | _ -> c.stmts - in - stmts @ (List.rev c.postins) - (* transforms a chunk into a block. Note that if the chunk has its unspecified_order flag set, the resulting block contains a single UnspecifiedSequence statement. @@ -1002,23 +1297,25 @@ { battrs = []; blocals = c.locals; bstmts = - [mkStmt (UnspecifiedSequence (pushPostIns c))]; } + [mkStmt (UnspecifiedSequence (List.rev c.stmts))]; } else - let block = block_from_unspecified_sequence (pushPostIns c) in - match block.bstmts with - [{ skind = Block b } as s] when collapse_block && s.labels = [] -> + match c.stmts with + | [{ skind = Block b } as s,_,_,_,_] when + collapse_block && s.labels = [] -> b.blocals <- c.locals @ b.blocals; b - | _ -> + | stmts -> (* block has no locals by itself. We must add them now *) - block.blocals <- c.locals; - block + { blocals = c.locals; + battrs = []; + bstmts = List.rev_map (fun (s,_,_,_,_) -> s) stmts; + } (* converts a chunk into a statement. *) let c2stmt c = let kind = if c.unspecified_order then - let kind = UnspecifiedSequence (pushPostIns c) in + let kind = UnspecifiedSequence (List.rev c.stmts) in if c.locals <> [] then Block { battrs = []; blocals = c.locals; bstmts = [ mkStmt kind] } else kind @@ -1037,9 +1334,8 @@ c1 @ c2 let get_chunk_effects c = - List.fold_left merge_effects ([],[],[],[]) - (List.map (fun (_,x,y,z,t) ->(x,y,z,t)) c.stmts @ - List.map (fun (_,x,y,z,t) -> (x,y,z,t)) c.postins) + List.fold_left + (fun c (_,x,y,z,t) -> merge_effects c (x,y,z,t)) ([],[],[],[]) c.stmts let c2stmt_effect c = let modified, writes, reads, calls = get_chunk_effects c @@ -1061,7 +1357,7 @@ Instr (Call _) -> [ref i] | _ -> [] in - {c with postins = (i,m,w,r,call) :: c.postins; } + {c with stmts = (i,m,w,r,call) :: c.stmts; } (* Append two chunks. Never refer to the original chunks after you call * this. And especially never share c2 with somebody else *) @@ -1070,18 +1366,16 @@ if (c1.unspecified_order && c2.unspecified_order) || (not c1.unspecified_order && not c2.unspecified_order) then - { stmts = (pushPostIns c1) @ c2.stmts; - postins = c2.postins; + { stmts = c2.stmts @ c1.stmts; cases = c1.cases @ c2.cases; locals = c1.locals @ c2.locals; unspecified_order = c1.unspecified_order; } else - match c2.stmts, c2.postins with - [],[] -> c1 - | [s],[] | [],[s] (*when not c1.unspecified_order*) -> - { stmts = (pushPostIns c1) @ [ s ]; - postins = []; + match c2.stmts with + [] -> c1 + | [s] -> + { stmts = s :: c1.stmts; cases = c1.cases @ c2.cases; locals = c1.locals @ c2.locals; unspecified_order = c1.unspecified_order; @@ -1092,28 +1386,31 @@ in a block at this point. *) let c2 = { c2 with locals = [] } in - { stmts = (pushPostIns c1) @ [c2stmt_effect c2]; - postins = []; + { stmts = c2stmt_effect c2 :: c1.stmts; cases = c1.cases @ c2.cases; locals = locals; unspecified_order = c1.unspecified_order; } in -(* - Format.eprintf "Concat:@\n%a@\nWITH@\n%a@\nLEADS TO@\n%a@." + +(* Format.eprintf "Concat:@\n%a@\nWITH@\n%a@\nLEADS TO@\n%a@." d_chunk c1 d_chunk c2 d_chunk r; *) r let remove_reads lv c = + (* Format.eprintf "Removing %a from chunk@\n%a@." + d_lval lv d_chunk c; *) let remove_list = - List.filter (fun x -> not (Lval.equal lv x)) + List.filter (fun x -> not (Cil.compareLval lv x)) in let remove_from_reads = List.map (fun (s,m,w,r,c) -> (s,lv::m,w,remove_list r,c)) in - { c with - stmts = remove_from_reads c.stmts; - postins = remove_from_reads c.postins } + let res = + { c with stmts = remove_from_reads c.stmts; } + in + (* Format.eprintf "Result is@\n%a@." d_chunk res; *) + res (* the chunks below are used in statements translation. Hence, their order of evaluation is always specified, and we can forget their @@ -1124,7 +1421,6 @@ let returnChunk e (l: location) : chunk = { stmts = [ mkStmt (Return(e, l)),[],[],[],[] ]; - postins = []; cases = []; locals = []; unspecified_order = false; @@ -1136,7 +1432,6 @@ let (m,r,w,c) = merge_effects effects_t effects_e in let stmt = mkStmt(If(be, c2block t, c2block e, l)) in { stmts = [ stmt ,m,r,w,c ]; - postins = []; cases = t.cases @ e.cases; locals = []; unspecified_order = false; @@ -1148,36 +1443,39 @@ * it does not have cases *) let duplicateChunk (c: chunk) = (* raises Failure if you should not * duplicate this chunk *) - if not !allowDuplication then + if not (AllowDuplication.get ()) then raise (Failure "cannot duplicate: disallowed by user"); if c.cases != [] then raise (Failure "cannot duplicate: has cases") else - let pCount = ref (List.length c.postins) in - let duplicate_stmt (s,m,w,r,c) = - if s.labels != [] then - raise (Failure "cannot duplicate: has labels"); - (match s.skind with - If _ | Switch _ | Loop _ | Block _ | UnspecifiedSequence _ - | TryFinally _ | TryExcept _ - -> - raise (Failure "cannot duplicate: complex stmt") - | Instr _ | Goto _ | Return _ | Break _ | Continue _ -> - incr pCount); - if !pCount > 5 then raise - (Failure ("cannot duplicate: too many instr")); + let pCount = ref 0 in + let duplicate_stmt (s,m,w,r,c) = + if s.labels != [] then + raise (Failure "cannot duplicate: has labels"); + (match s.skind with + If _ | Switch _ | Loop _ | Block _ | UnspecifiedSequence _ + | TryFinally _ | TryExcept _ + -> + raise (Failure "cannot duplicate: complex stmt") + | Instr _ | Goto _ | Return _ | Break _ | Continue _ -> + incr pCount); + if !pCount > 5 then raise + (Failure ("cannot duplicate: too many instr")); (* We can just copy it because there is nothing to share here. * Except maybe for the ref cell in Goto but it is Ok to share * that, I think *) - let s' = { s with sid = s.sid} in - let c = match s.skind with - Instr (Call _) -> [ref s'] - | _ -> assert (c = []); [] - in (s',m,w,r,c) - in - { stmts = List.map duplicate_stmt c.stmts; - postins = List.map duplicate_stmt c.postins; - cases = []; unspecified_order = c.unspecified_order; - locals = c.locals; (* varinfos must be shared anyway. *) - } + let s' = { s with sid = s.sid} in + let c = match s.skind with + | Instr (Call _) -> [ref s'] + | Instr _ | TryExcept (_, _, _, _)| TryFinally (_, _, _) + | UnspecifiedSequence _| Block _| Loop (_, _, _, _, _) + | Switch (_, _, _, _)| If (_, _, _, _)| Continue _| Break _ + | Goto (_, _)| Return (_, _) -> assert (c = []); [] + in + (s',m,w,r,c) + in + { stmts = List.map duplicate_stmt c.stmts; + cases = []; unspecified_order = c.unspecified_order; + locals = c.locals; (* varinfos must be shared anyway. *) + } (* We can drop a chunk if it does not have labels inside *) let canDrop (c: chunk) = @@ -1189,7 +1487,6 @@ mkStmt (Loop (a,c2block body, CurrentLoc.get (), None, None)) in { stmts = [ loop,[],[],[],[] ]; - postins = []; cases = body.cases; unspecified_order = false; locals = []; @@ -1197,7 +1494,6 @@ let breakChunk (l: location) : chunk = { stmts = [ mkStmt (Break l),[],[],[],[] ]; - postins = []; cases = []; unspecified_order = false; locals = []; @@ -1205,7 +1501,6 @@ let continueChunk (l: location) : chunk = { stmts = [ mkStmt (Continue l),[],[],[],[] ]; - postins = []; cases = []; unspecified_order = false; locals = []; @@ -1216,46 +1511,16 @@ let getFirstInChunk ~loc c = (* Get the first statement and add the label to it *) match c.stmts with - (*| [ ({skind = Block {bstmts = []; - blocals = []; - battrs = []}; - labels = [] }, - m,w,r)] -> - let n = mkEmptyStmt ~loc () in - n, [n,m,w,r] - |[ ({skind = Block {bstmts = [stmt]; - blocals = []; - battrs = []}; - labels = [] }, - m,w,r)] -> - stmt, [stmt,m,w,r] - |[ ({skind = Block {bstmts = stmt::stmts; - blocals = []; - battrs = []}; - labels = [] }, - m,w,r)] when not c.unspecified_order -> - stmt, (stmt,m,w,r)::(List.map (fun x -> (x,[],[],[])) stmts) - | [{skind = UnspecifiedSequence []; labels = []}, m,w,r] -> - let n = mkEmptyStmt ~loc () in - n, [n,m,w,r] - | [ {skind = UnspecifiedSequence [stmt,_,_,_]; labels = []}, - m,w,r ] -> - stmt, [stmt,m,w,r] - | [ { skind = UnspecifiedSequence (((stmt,_,_,_)::_) as stmts); - labels = [] }, - _,_,_] when c.unspecified_order -> - stmt, stmts *) - | (s,_,_,_,_) :: _ -> s, c.stmts | [] -> (* Add a statement *) let n = mkEmptyStmt ~loc () in n, [n,[],[],[],[]] + | s -> let (st,_,_,_,_) = Extlib.last s in st,s (* s2c must not be used during expression translation, as it does not take care of the effects of the statement. Use i2c instead. *) let s2c (s:stmt) : chunk = { stmts = [ s,[],[],[],[] ]; - postins = []; cases = []; unspecified_order = false; locals = []; @@ -1265,7 +1530,6 @@ let gref = ref dummyStmt in addGoto ln gref; { stmts = [ mkStmt (Goto (gref, l)),[],[],[],[] ]; - postins = []; cases = []; locals = []; unspecified_order = false; @@ -1287,34 +1551,50 @@ unspecified_order = false } - let switchChunk (e: exp) (body: chunk) (l: location) = (* Make the statement *) let defaultSeen = ref false in - let checkForDefault lb : unit = + let t = typeOf e in + let checkForDefaultAndCast lb = match lb with - Default _ -> if !defaultSeen then - Cil.error "Switch statement at %a has duplicate default entries." - d_loc l; - defaultSeen := true - | _ -> () + | Default _ as d -> + if !defaultSeen then + Kernel.error ~current:true + "Switch statement at %a has duplicate default entries." + d_loc l; + defaultSeen := true; + d + | Label _ as l -> l + | Case (e, loc) -> + (* If needed, convert e to type t, and check in case the label + was too big *) + let e' = makeCast ~e ~newt:t in + let constFold = constFold false in + let e'' = if theMachine.lowerConstants then constFold e' else e' in + (match (constFold e).enode, (constFold e'').enode with + | Const(CInt64(i1, _, _)), Const(CInt64(i2, _, _)) + when not (My_bigint.equal i1 i2) -> + Kernel.warning ~source:(fst e.eloc) + "Case label %a exceeds range for switch expression" d_exp e; + | _ -> () + ); + Case (e'', loc) in let block = c2block body in - let cases = (* eliminate duplicate entries from body.cases. - A statement is added to body.cases for each case label - it has. *) - List.fold_right (fun s acc -> - if List.memq s acc then acc - else begin - List.iter checkForDefault s.labels; - s::acc - end) + let cases = (* eliminate duplicate entries from body.cases. A statement + is added to body.cases for each case label it has. *) + List.fold_right + (fun s acc -> + if List.memq s acc then acc + else begin + s.labels <- List.map checkForDefaultAndCast s.labels; + s::acc + end) body.cases [] in let switch = mkStmt (Switch (e, block, cases, l)) in { stmts = [ switch,[],[],[],[] ]; - postins = []; cases = []; locals = []; unspecified_order = false; @@ -1333,7 +1613,8 @@ end in try ignore (visitCilBlock find b); - Cil.warn "Inconsistent AST: Statement %a,@ with label %s is not in the AST" + Kernel.warning ~current:true + "Inconsistent AST: Statement %a,@ with label %s is not in the AST" d_stmt s l; with Found -> () @@ -1341,7 +1622,7 @@ inherit nopCilVisitor val unspecified_stack = Stack.create () - val replace_table = Stmt.Hashtbl.create 17 + val mutable replace_table = [] (* we start in a deterministic block. *) initializer Stack.push false unspecified_stack @@ -1355,34 +1636,34 @@ method vblock b = b.bstmts <- - List.fold_right( - fun s res -> + List.rev + (List.fold_left( + fun res s -> match s.skind with - Block b when - (not (Stack.top unspecified_stack)) && - b.battrs = [] && b.blocals = [] && - s.labels = [] - -> b.bstmts @ res - | _ -> s ::res) - b.bstmts []; + Block b when + (not (Stack.top unspecified_stack)) && + b.battrs = [] && b.blocals = [] && + s.labels = [] + -> List.rev_append b.bstmts res + | _ -> s ::res) + [] b.bstmts); DoChildren method vstmt s = let change_label_stmt s s' = List.iter (function - | Label (x,_,_) -> H.replace labelStmt x s' - | Case _ | Default _ -> - Stmt.Hashtbl.add replace_table s s') - s.labels; + | Label (x,_,_) -> H.replace labelStmt x s' + | Case _ | Default _ -> replace_table <- (s, s') :: replace_table + ) s.labels; s'.labels <- s.labels @ s'.labels in match s.skind with UnspecifiedSequence [s',_,_,_,_] -> change_label_stmt s s'; - ChangeDoChildrenPost(s', fun x ->x) + ChangeDoChildrenPost(s', fun x -> x) | UnspecifiedSequence [] -> - let s' = mkEmptyStmt ~loc:cabslu () in + let s' = mkEmptyStmt ~loc:(cabslu "_useq") () in change_label_stmt s s'; ChangeTo s'; | UnspecifiedSequence _ -> self#push true s @@ -1399,7 +1680,7 @@ let newcases = List.map (fun s -> - try Stmt.Hashtbl.find replace_table s + try List.assq s replace_table with Not_found -> s) cases in @@ -1415,19 +1696,17 @@ let mkFunctionBody (c: chunk) : block = if c.cases <> [] then - Cil.error "Switch cases not inside a switch statement\n"; + Kernel.error ~current:true + "Switch cases not inside a switch statement\n"; (* cleanup empty blocks and unspecified sequences. This can change some labels (the one attached to removed blocks), - so it has to be done before resolveGotos. - *) + so it has to be done before resolveGotos. *) let res = visitCilBlock (new cleanUnspecified) (c2block c) in H.iter (find_stmt res) labelStmt; resolveGotos (); initLabels (); res - - let add_reads r c = - match r with - [] -> c - | _ -> c +++ (mkEmptyStmt ~loc:cabslu (), [],[], r) + let add_reads loc r c = match r with + | [] -> c + | _ :: _ -> c +++ (mkEmptyStmt ~loc (), [],[], r) end @@ -1462,7 +1741,7 @@ let continueOrLabelChunk (l: location) : chunk = match !continues with - [] -> Cil.abort "continue not in a loop" + | [] -> Kernel.abort ~current:true "continue not in a loop" | While lr :: _ -> if !doTransformWhile then begin @@ -1485,12 +1764,13 @@ let breakChunk l = if Stack.is_empty break_env then - Cil.abort "break outside of a loop or switch"; + Kernel.abort ~current:true "break outside of a loop or switch"; breakChunk l let exit_break_env () = if Stack.is_empty break_env then - Cil.fatal "trying to exit a breakable env without having entered it"; + Kernel.fatal ~current:true + "trying to exit a breakable env without having entered it"; ignore (Stack.pop break_env) let startLoop iswhile = @@ -1501,7 +1781,7 @@ let exitLoop () = exit_break_env (); match !continues with - [] -> Cil.error "exit Loop not in a loop" + [] -> Kernel.error ~current:true "exit Loop not in a loop" | _ :: rest -> continues := rest (* In GCC we can have locally declared labels. *) @@ -1540,8 +1820,9 @@ method private removeLocalLabels blk = List.iter (fun lbl -> - if H.find localLabels lbl = None - then ignore (warn "Local label %s declared but not defined" lbl); + if H.find localLabels lbl = None then + Kernel.warning ~current:true + "Local label %s declared but not defined" lbl; H.remove localLabels lbl) blk.blabels @@ -1557,14 +1838,18 @@ (try (match H.find localLabels lbl with | Some oldloc -> - Cil.error "Duplicate local label '%s' (previous definition was at %a)" lbl d_loc oldloc + Kernel.error ~current:true + "Duplicate local label '%s' (previous definition was at %a)" + lbl d_loc oldloc | None -> (* Mark this label as defined *) H.replace localLabels lbl (Some (CurrentLoc.get()))) with Not_found -> (* lbl is not a local label *) let newname, oldloc = newAlphaName false "label" lbl in - if newname <> lbl - then Cil.error "Duplicate label '%s' (previous definition was at %a)" lbl d_loc oldloc) + if newname <> lbl then + Kernel.error ~current:true + "Duplicate label '%s' (previous definition was at %a)" + lbl d_loc oldloc) | _ -> ()); DoChildren end @@ -1649,282 +1934,6 @@ | CEOr of condExpRes * condExpRes | CENot of condExpRes -(******** CASTS *********) -let integralPromotion (t : typ) : typ = (* c.f. ISO 6.3.1.1 *) - match unrollType t with - (* We assume that an IInt can hold even an IUShort *) - TInt ((IShort|IUShort|IChar|ISChar|IUChar|IBool), a) -> TInt(IInt, a) - | TInt (_,a) -> - begin match findAttribute "FRAMA_C_BITFIELD_SIZE" a with - | [AInt size] when size < (bitsSizeOf intType) -> - TInt(IInt, dropAttribute "FRAMA_C_BITFIELD_SIZE" a) - | [] -> t - | _ -> assert false - end - | TEnum (_, a) -> TInt(IInt, a) - | t -> Cil.fatal "integralPromotion: not expecting %a" d_type t - - -let arithmeticConversion (* c.f. ISO 6.3.1.8 *) - (t1: typ) - (t2: typ) : typ = - let checkToInt _ = () in (* dummies for now *) - let checkToFloat _ = () in - match unrollType t1, unrollType t2 with - TFloat(FLongDouble, _), _ -> checkToFloat t2; t1 - | _, TFloat(FLongDouble, _) -> checkToFloat t1; t2 - | TFloat(FDouble, _), _ -> checkToFloat t2; t1 - | _, TFloat (FDouble, _) -> checkToFloat t1; t2 - | TFloat(FFloat, _), _ -> checkToFloat t2; t1 - | _, TFloat (FFloat, _) -> checkToFloat t1; t2 - | _, _ -> begin - let t1' = integralPromotion t1 in - let t2' = integralPromotion t2 in - match unrollType t1', unrollType t2' with - TInt(IULongLong, _), _ -> checkToInt t2'; t1' - | _, TInt(IULongLong, _) -> checkToInt t1'; t2' - - (* We assume a long long is always larger than a long *) - | TInt(ILongLong, _), _ -> checkToInt t2'; t1' - | _, TInt(ILongLong, _) -> checkToInt t1'; t2' - - | TInt(IULong, _), _ -> checkToInt t2'; t1' - | _, TInt(IULong, _) -> checkToInt t1'; t2' - - - | TInt(ILong,_), TInt(IUInt,_) - when bitsSizeOf t1' <= bitsSizeOf t2' -> TInt(IULong,[]) - | TInt(IUInt,_), TInt(ILong,_) - when bitsSizeOf t2' <= bitsSizeOf t1' -> TInt(IULong,[]) - - | TInt(ILong, _), _ -> checkToInt t2'; t1' - | _, TInt(ILong, _) -> checkToInt t1'; t2' - - | TInt(IUInt, _), _ -> checkToInt t2'; t1' - | _, TInt(IUInt, _) -> checkToInt t1'; t2' - - | TInt(IInt, _), TInt (IInt, _) -> t1' - - | t1, t2 -> Cil.fatal "arithmeticConversion %a -> %a@." d_type t1 d_type t2 - end - - -let rec check_strict_attributes ~direct ot nt = - let w ?name () = - let s = (match name with - | None -> "" - | Some n -> "through fields " ^ n) - in - if direct then - Cil.warning "cannot drop strict attributes from %a to %a %s" d_type ot d_type nt s - else - Cil.warning "cannot add strict attributes of %a to %a %s" d_type ot d_type nt s - ; false - in - let is_strict_attr a = attributeName a = "address_space" in - let strict_attr a = List.filter is_strict_attr a in - let check oa na = - if (List.for_all - (fun x -> List.exists (Cilutil.equals x) (strict_attr na)) (strict_attr oa)) - then true else w () - in - let exists_strict_attribute_deep ?name ty = - match exists_attribute_deep is_strict_attr ty with - | None -> true - | Some l -> let n = Pretty_utils.sfprintf "%a%a" - (Cilutil.pretty_opt (fun fmt -> Format.fprintf fmt "%s, ")) name - (Cilutil.pretty_list (fun fmt -> Format.fprintf fmt ", ") - Format.pp_print_string) - l - in - w ~name:n () - in - let check_comp_fields l = - List.fold_left - (fun acc fi -> - acc - && - (List.for_all (fun x -> (if is_strict_attr x then w ~name:fi.fname () else true)) fi.fattr) - && - (exists_strict_attribute_deep ~name:fi.fname fi.ftype) - ) - true - l - in - match unrollType ot, unrollType nt with - | TNamed _, _ | _, TNamed _ -> assert false - - | (TVoid o|TInt(_,o)|TEnum (_,o)|TFloat(_,o)|TBuiltin_va_list (o)), - (TVoid n|TInt(_,n)|TEnum (_,n)|TFloat(_,n)|TBuiltin_va_list (n)) - -> check o n - | (TArray (ot,_,_,o)|TPtr (ot, o)), (TArray (nt,_,_,n)|TPtr(nt, n)) -> - check o n && check_strict_attributes ~direct ot nt - | ((TVoid o|TInt(_,o)|TEnum (_,o)|TFloat(_,o)|TBuiltin_va_list (o)), - (TArray (_,_,_,n)|TPtr(_, n))) -> - check o n - | ((TArray (ot,_,_,o)|TPtr (ot, o)), - (TVoid n|TInt(_,n)|TEnum (_,n)|TFloat(_,n)|TBuiltin_va_list (n))) -> - check o n && (exists_strict_attribute_deep ot) - | TComp ({ckey=ok; cattr=oia; cfields=l}, _, oa), TComp ({ckey=nk; cattr=nia}, _, na) -> - ok=nk || (check (addAttributes oa oia) (addAttributes na nia) - && check_comp_fields l) - | TComp ({cattr=co; cfields=l}, _, o),nt -> - check (addAttributes o co) (typeAttr nt) && - check_comp_fields l - - | (TVoid o|TInt(_,o)|TEnum (_,o)|TFloat(_,o)|TBuiltin_va_list (o)) ,TComp ({cattr=no},_,n)-> - check o (addAttributes no n) - - | (TArray (ot,_,_,o)|TPtr (ot, o)),TComp ({cattr=no},_,n)-> - check o (addAttributes no n) - && - (exists_strict_attribute_deep ot) - | TFun (_, _, _, _),_ - | _,TFun (_, _, _, _) -> (exists_strict_attribute_deep ot) - -(* Specify whether the cast is from the source code *) -let rec castTo ?(fromsource=false) - (ot : typ) (nt : typ) (e : exp) : (typ * exp ) = - let debugCast = false in - if debugCast then - Cilmsg.debug "@[%t: castTo:%s %a->%a@\n@]" - d_thisloc (if fromsource then "(source)" else "") - d_type ot d_type nt; - - let ot' = unrollType ot in - let nt' = unrollType nt in - if not fromsource && not (need_cast ot' nt') then - (* Do not put the cast if it is not necessary, unless it is from the - * source. *) - (ot, e) - else begin - let nt' = if fromsource then nt' else !typeForInsertedCast e ot' nt' in - let result = (nt', if theMachine.insertImplicitCasts || fromsource then - Cil.mkCastT e ot nt' else e) - in -(* [BM] uncomment the following line to enable attributes static typing - ignore (check_strict_attributes true ot nt && check_strict_attributes false nt ot);*) - if debugCast then - Cilmsg.debug "@[castTo: ot=%a nt=%a\n result is %a@\n@]" - d_type ot d_type nt' - d_plainexp (snd result); - - (* Now see if we can have a cast here *) - match ot', nt' with - TNamed _, _ - | _, TNamed _ -> Cil.fatal "unrollType failed in castTo" - | _, TInt(IBool,_) -> - nt,(constFold true - (new_exp ~loc:e.eloc (BinOp(Ne,e,Cil.integer ~loc:e.eloc 0,nt)))) - | TInt(_,_), TInt(_,_) -> - (* We used to ignore attributes on integer-integer casts. Not anymore *) - (* if ikindo = ikindn then (nt, e) else *) - result - | TPtr (_, _), TPtr(_, _) -> result - - | TInt _, TPtr _ -> result - - | TPtr _, TInt _ -> result - - | TArray _, TPtr _ -> result - - | TArray(t1,_,_,_), TArray(t2,None,_,_) - when Cilutil.equals (typeSig t1) (typeSig t2) -> (nt', e) - - | TPtr _, TArray(_,_,_,_) -> (nt', e) - - | TEnum _, TInt _ -> result - | TFloat _, (TInt _|TEnum _) -> result - | (TInt _|TEnum _), TFloat _ -> result - | TFloat _, TFloat _ -> result - | TInt _, TEnum _ -> result - | TEnum _, TEnum _ -> result - - | TEnum _, TPtr _ -> result - | TBuiltin_va_list _, (TInt _ | TPtr _) -> - result - - | (TInt _ | TPtr _), TBuiltin_va_list _ -> - Cil.warnOpt "Casting %a to __builtin_va_list" d_type ot ; - result - - | TPtr _, TEnum _ -> - Cil.warnOpt "Casting a pointer into an enumeration type" ; - result - - (* The expression is evaluated for its effects *) - | (TInt _ | TEnum _ | TPtr _ ), TVoid _ -> - (ot, e) - - (* Even casts between structs are allowed when we are only - * modifying some attributes *) - | TComp (comp1, _, _), TComp (comp2, _, _) when comp1.ckey = comp2.ckey -> - result - - (** If we try to pass a transparent union value to a function - * expecting a transparent union argument, the argument type would - * have been changed to the type of the first argument, and we'll - * see a cast from a union to the type of the first argument. Turn - * that into a field access *) - | TComp(_, _, _), _ -> begin - match isTransparentUnion ot with - None -> Cil.fatal "castTo %a -> %a" d_type ot d_type nt' - | Some fstfield -> begin - (* We do it now only if the expression is an lval *) - let e' = - match e.enode with - Lval lv -> - new_exp ~loc:e.eloc - (Lval (addOffsetLval (Field(fstfield, NoOffset)) lv)) - | _ -> Cil.fatal "castTo: transparent union expression is not an lval: %a\n" d_exp e - in - (* Continue casting *) - castTo ~fromsource:fromsource fstfield.ftype nt' e' - end - end - | _ -> Cil.fatal "cabs2cil: castTo %a -> %a@\n" d_type ot d_type nt' - end - -(* Like Cil.mkCastT, but it calls typeForInsertedCast *) -let makeCastT ~(e: exp) ~(oldt: typ) ~(newt: typ) = - if need_cast oldt newt then - Cil.mkCastT e oldt (!typeForInsertedCast e oldt newt) - else e - -let makeCast ~(e: exp) ~(newt: typ) = - makeCastT e (typeOf e) newt - -(* A cast that is used for conditional expressions. Pointers are Ok *) -let checkBool (ot : typ) (_ : exp) : bool = - match unrollType ot with - TInt _ -> true - | TPtr _ -> true - | TEnum _ -> true - | TFloat _ -> true - | _ -> Cil.fatal "castToBool %a" d_type ot - -(* Given an expression that is being coerced to bool, - is it a nonzero constant? *) -let rec isConstTrue (e:exp): bool = - match e.enode with - | Const(CInt64 (n,_,_)) -> n <> Int64.zero - | Const(CChr c) -> 0 <> Char.code c - | Const(CStr _ | CWStr _) -> true - | Const(CReal(f, _, _)) -> f <> 0.0; - | CastE(_, e) -> isConstTrue e - | _ -> false - -(* Given an expression that is being coerced to bool, is it zero? - This is a more general version of Cil.isZero, which only handles integers. - On constant expressions, either isConstTrue or isConstFalse will hold. *) -let rec isConstFalse (e:exp): bool = - match e.enode with - | Const(CInt64 (n,_,_)) -> n = Int64.zero - | Const(CChr c) -> 0 = Char.code c - | Const(CReal(f, _, _)) -> f = 0.0; - | CastE(_, e) -> isConstFalse e - | _ -> false - (* We have our own version of addAttributes that does not allow duplicates *) @@ -1939,7 +1948,7 @@ if Cilutil.equals a a' then acc (* Already in *) else begin - Cil.warnOpt + Kernel.debug ~level:3 "Duplicate attribute %a along with %a" d_attr a d_attr a' ; (* let acc' = dropAttribute an acc in *) @@ -2000,9 +2009,11 @@ | (IUInt, "__DI__") -> (IULongLong, a0') | _ -> - (ignore (error "GCC width mode %s applied to unexpected type, or unexpected mode" - mode)); - (ik', a0one :: a0') + Kernel.error ~current:true + "GCC width mode %s applied to unexpected type, \ +or unexpected mode" + mode; + (ik', a0one :: a0') end | _ -> (ik', a0one :: a0')) @@ -2047,8 +2058,9 @@ if oldk = k then oldk else (* GCC allows a function definition to have a more precise integer * type than a prototype that says "int" *) - if not theMachine.msvcMode && oldk = IInt && bitsSizeOf t <= 32 - && (what = CombineFunarg || what = CombineFunret) then + if not theMachine.msvcMode && oldk = IInt + && sizeOf_int t <= (bytesSizeOfInt IInt) + && (what = CombineFunarg || what = CombineFunret) then k else raise (Failure "different integer types") @@ -2121,7 +2133,7 @@ ) oldci.cfields ci.cfields with Failure _ as e -> begin (* Our assumption was wrong. Forget the isomorphism *) - Cilmsg.debug "Failed in our assumption that %s and %s are isomorphic" + Kernel.debug "Failed in our assumption that %s and %s are isomorphic" oldci.cname ci.cname ; H.remove isomorphicStructs (oldci.cname, ci.cname); H.remove isomorphicStructs (ci.cname, oldci.cname); @@ -2150,8 +2162,9 @@ if checkEqualSize false then oldsz else if checkEqualSize true then begin - Cil.warning - "Array type comparison succeeds only based on machine-dependent constant evaluation: %a and %a\n" + Kernel.warning ~current:true + "Array type comparison succeeds only based on machine-dependent \ +constant evaluation: %a and %a\n" d_exp oldsz' d_exp sz' ; oldsz end else @@ -2166,7 +2179,7 @@ | TFun (_, _, _, [Attr("missingproto",_)]), TFun _ -> t | TFun (oldrt, oldargs, oldva, olda), TFun (rt, args, va, a) -> - let newrt = combineTypes + let newrt = combineTypes (if what = CombineFundef then CombineFunret else CombineOther) oldrt rt in @@ -2257,13 +2270,13 @@ else vi.vname in - Cilmsg.debug + Kernel.debug "makeGlobalVarinfo isadef=%b vi.vname=%s (lookup = %s)" isadef vi.vname lookupname; (* This may throw an exception Not_found *) let oldvi, oldloc = lookupGlobalVar lookupname in - Cilmsg.debug " %s(%d) already in the env at loc %a" + Kernel.debug " %s(%d) already in the env at loc %a" vi.vname oldvi.vid d_loc oldloc; (* It was already defined. We must reuse the varinfo. But clean up the * storage. *) @@ -2278,11 +2291,12 @@ | _ -> - if vi.vstorage != oldvi.vstorage then - (Cil.warning - "Inconsistent storage specification for %s. Previous declaration: %a" - vi.vname d_loc oldloc); - vi.vstorage + if vi.vstorage != oldvi.vstorage then + Kernel.warning ~current:true + "Inconsistent storage specification for %s. \ +Previous declaration: %a" + vi.vname d_loc oldloc; + vi.vstorage in oldvi.vinline <- oldvi.vinline || vi.vinline; oldvi.vstorage <- newstorage; @@ -2304,12 +2318,13 @@ then DifferentDeclHook.apply (oldvi,vi); oldvi.vtype <- mytype; with Failure reason -> - Cilmsg.debug "old type = %a\nnew type = %a\n" + Kernel.debug "old type = %a\nnew type = %a\n" d_plaintype oldvi.vtype d_plaintype vi.vtype ; - Cil.error "Declaration of %s does not match previous declaration from %a (%s)." + Kernel.error ~current:true + "Declaration of %s does not match previous declaration from %a (%s)." vi.vname d_loc oldloc reason; - IncompatibleDeclHook.apply (oldvi,vi,reason) + IncompatibleDeclHook.apply (oldvi,vi,reason) end; (* Found an old one. Keep the location always from the definition *) @@ -2327,7 +2342,7 @@ List.iter2 (fun old (name,typ,attr) -> if name <> "" then begin - Cilmsg.debug "replacing formal %s with %s" old.vname name; + Kernel.debug "replacing formal %s with %s" old.vname name; old.vname <- name; old.vtype <- typ; old.vattr <- attr; @@ -2342,7 +2357,7 @@ with | Invalid_argument "List.iter2" -> if not (Cilmsg.had_errors ()) then begin - Cilmsg.abort "Inconsistent formals" ; + Kernel.abort "Inconsistent formals" ; end | Not_found -> ()) | _ -> () @@ -2351,7 +2366,7 @@ if isadef then oldvi.vdefined <- true; oldvi, true with Not_found -> begin (* A new one. *) - Cilmsg.debug " %s not in the env already" vi.vname; + Kernel.debug " %s not in the env already" vi.vname; (* Announce the name to the alpha conversion table. This will not * actually change the name of the vi. See the definition of * alphaConvertVarAndAddToEnv *) @@ -2381,27 +2396,27 @@ | (TPtr _) as t2', (TPtr _ as t3') -> begin try combineTypes CombineOther t2' t3' with Failure msg -> begin - (Cil.warning "A.QUESTION: %a does not match %a (%s)" - d_type (unrollType t2) d_type (unrollType t3) msg); + Kernel.warning ~current:true "A.QUESTION: %a does not match %a (%s)" + d_type (unrollType t2) d_type (unrollType t3) msg; t2 (* Just pick one *) end end | _, _ -> - Cil.fatal "invalid implicit conversion from %a to %a" + Kernel.fatal ~current:true "invalid implicit conversion from %a to %a" Cil.d_type t2 Cil.d_type t3 in tresult let logicConditionalConversion t1 t2 = match unrollType t1, unrollType t2 with - TPtr _ , TInt _ | TInt _, TPtr _ -> - Cil.fatal "invalid implicit conversion from %a to %a" - Cil.d_type t2 Cil.d_type t1 - | _ -> conditionalConversion t1 t2 + | TPtr _ , TInt _ | TInt _, TPtr _ -> + Kernel.fatal ~current:true "invalid implicit conversion from %a to %a" + Cil.d_type t2 Cil.d_type t1 + | _ -> conditionalConversion t1 t2 (* Some utilitites for doing initializers *) -let debugInit = false +let debugInit = true type preInit = | NoInitPre @@ -2426,16 +2441,16 @@ let idx, (* Index in the current comp *) restoff (* Rest offset *) = match o with - | Index({enode = Const(CInt64(i,_,_))}, off) -> Int64.to_int i, off + | Index({enode = Const(CInt64(i,_,_))}, off) -> My_bigint.to_int i, off | Field (f, off) -> (* Find the index of the field *) let rec loop (idx: int) = function - [] -> Cil.abort "Cannot find field %s" f.fname + | [] -> Kernel.abort ~current:true "Cannot find field %s" f.fname | f' :: _ when f'.fname = f.fname -> idx | _ :: restf -> loop (idx + 1) restf in loop 0 f.fcomp.cfields, off - | _ -> Cil.abort "setOneInit: non-constant index" + | _ -> Kernel.abort ~current:true "setOneInit: non-constant index" in let pMaxIdx, pArray = match this with @@ -2456,7 +2471,7 @@ end; pMaxIdx, pArray | SinglePre _ -> - Cil.fatal "Index %d is already initialized" idx + Kernel.fatal ~current:true "Index %d is already initialized" idx in assert (idx >= 0 && idx < Array.length !pArray); let this' = setOneInit !pArray.(idx) restoff e in @@ -2471,7 +2486,7 @@ let rec collectInitializer (this: preInit) (thistype: typ) : (init * typ) = - let loc = CurrentLoc.get() in + let loc = CurrentLoc.get() in if this = NoInitPre then (makeZeroInit ~loc thistype), thistype else match unrollType thistype, this with @@ -2482,25 +2497,26 @@ match leno with Some len -> begin match (constFold true len).enode with - Const(CInt64(ni, _, _)) when ni >= 0L -> - (Int64.to_int ni), TArray(bt,leno, empty_size_cache (),at) + | Const(CInt64(ni, _, _)) when My_bigint.ge ni My_bigint.zero -> + (My_bigint.to_int ni), TArray(bt,leno, empty_size_cache (),at) | _ -> - Cil.fatal - "Array length is not a constant expression %a" - d_exp len + Kernel.fatal ~current:true + "Array length is not a constant expression %a" + d_exp len end | _ -> (* unsized array case, length comes from initializers *) (!pMaxIdx + 1, - TArray (bt, + TArray (bt, Some (integer ~loc (!pMaxIdx + 1)), empty_size_cache (), at)) in if !pMaxIdx >= len then - Cil.abort "collectInitializer: too many initializers(%d >= %d)" - !pMaxIdx len; + Kernel.abort ~current:true + "collectInitializer: too many initializers(%d >= %d)" + !pMaxIdx len; (* len could be extremely big. So omit the last initializers, if they * are many (more than 16) *) (* @@ -2546,19 +2562,21 @@ | TComp (comp, _, _), CompoundPre (pMaxIdx, pArray) when not comp.cstruct -> (* Find the field to initialize *) let rec findField (idx: int) = function - [] -> Cil.abort "collectInitializer: union" + | [] -> Kernel.abort ~current:true "collectInitializer: union" | _ :: rest when idx < !pMaxIdx && !pArray.(idx) = NoInitPre -> findField (idx + 1) rest | f :: _ when idx = !pMaxIdx -> Field(f, NoOffset), collectFieldInitializer !pArray.(idx) f - | _ -> Cil.fatal "Can initialize only one field for union" + | _ -> + Kernel.fatal ~current:true "Can initialize only one field for union" in if theMachine.msvcMode && !pMaxIdx != 0 then - (Cil.warning "On MSVC we can initialize only the first field of a union"); + Kernel.warning ~current:true + "On MSVC we can initialize only the first field of a union"; CompoundInit (thistype, [ findField 0 comp.cfields ]), thistype - | _ -> Cil.fatal "collectInitializer" + | _ -> Kernel.fatal ~current:true "collectInitializer" and collectFieldInitializer (this: preInit) @@ -2603,6 +2621,14 @@ *) let alpha_renaming = Hashtbl.create 59 +let rename_spec = function + GVarDecl(spec,v,_) -> + (try + let alpha = Hashtbl.find alpha_renaming v.vid in + ignore (Cil.visitCilFunspec alpha spec) + with Not_found -> ()) + | _ -> () + (* Make a subobject iterator *) let rec makeSubobj (host: varinfo) @@ -2624,21 +2650,21 @@ (* The array is over *) | InArray (parOff, bt, leno, current) :: rest -> if leno = !current then begin (* The array is over *) - if debugInit then Cilmsg.debug "Past the end of array"; + if debugInit then Kernel.debug "Past the end of array"; so.stack <- rest; advanceSubobj so end else begin so.soTyp <- bt; - so.soOff <- - addOffset - (Index(integer ~loc:(CurrentLoc.get()) !current, NoOffset)) + so.soOff <- + addOffset + (Index(integer ~loc:(CurrentLoc.get()) !current, NoOffset)) parOff end (* The fields are over *) | InComp (parOff, _, nextflds) :: rest -> if nextflds == [] then begin (* No more fields here *) - if debugInit then Cilmsg.debug "Past the end of structure"; + if debugInit then Kernel.debug "Past the end of structure"; so.stack <- rest; advanceSubobj so end else begin @@ -2649,12 +2675,12 @@ (* Advance to the next subobject. Always apply to a normalized object *) and advanceSubobj (so: subobj) : unit = - if so.eof then Cil.abort "advanceSubobj past end"; + if so.eof then Kernel.abort ~current:true "advanceSubobj past end"; match so.stack with - | [] -> if debugInit then Cilmsg.debug "Setting eof to true"; + | [] -> if debugInit then Kernel.debug "Setting eof to true"; so.eof <- true | InArray (_, _, _, current) :: _ -> - if debugInit then Cilmsg.debug " Advancing to [%d]" (!current + 1); + if debugInit then Kernel.debug " Advancing to [%d]" (!current + 1); (* so.stack <- InArray (parOff, bt, leno, current + 1) :: rest; *) incr current; normalSubobj so @@ -2662,9 +2688,10 @@ (* The fields are over *) | InComp (parOff, comp, nextflds) :: rest -> if debugInit then - Cilmsg.debug "Advancing past .%s" (List.hd nextflds).fname; + Kernel.debug "Advancing past .%s" (List.hd nextflds).fname; let flds' = - try List.tl nextflds with Failure _ -> Cil.abort "advanceSubobj" + try List.tl nextflds + with Failure _ -> Kernel.abort ~current:true "advanceSubobj" in so.stack <- InComp(parOff, comp, flds') :: rest; normalSubobj so @@ -2684,7 +2711,8 @@ None -> flds1 | Some fn -> let rec loop = function - [] -> Cil.fatal "Cannot find designated field %s" fn + | [] -> + Kernel.fatal ~current:true "Cannot find designated field %s" fn | (f :: _) as nextflds when f.fname = fn -> nextflds | _ :: rest -> loop rest in @@ -2699,13 +2727,13 @@ let integerArrayLength (leno: exp option) : int = match leno with - None -> max_int - | Some len -> begin - try lenOfArray leno - with LenOfArray -> - Cil.fatal "Initializing non-constant-length array with length=%a" - d_exp len - end + | None -> max_int + | Some len -> + try lenOfArray leno + with LenOfArray -> + Kernel.fatal ~current:true + "Initializing non-constant-length array with length=%a" + d_exp len (* sm: I'm sure something like this already exists, but ... *) let isNone (o : 'a option) : bool = @@ -2714,8 +2742,8 @@ | Some _ -> false -let annonCompFieldNameId = ref 0 -let annonCompFieldName = "__annonCompField" +let anonCompFieldNameId = ref 0 +let anonCompFieldName = "__anonCompField" let find_field_offset cond (fidlist: fieldinfo list) : offset = (* Depth first search for the field. This appears to be what GCC does. @@ -2723,14 +2751,15 @@ * matter how we search *) let rec search = function [] -> raise Not_found - | fid :: _ when cond fid -> Field(fid, NoOffset) - | fid :: rest when prefix annonCompFieldName fid.fname -> begin + | fid :: _ when cond fid -> + Field(fid, NoOffset) + | fid :: rest when prefix anonCompFieldName fid.fname -> begin match unrollType fid.ftype with - TComp (ci, _, _) -> - (try let off = search ci.cfields in Field(fid,off) - with Not_found -> - search rest (* Continue searching *)) - | _ -> Cil.abort "unnamed field type is not a struct/union" + | TComp (ci, _, _) -> + (try let off = search ci.cfields in Field(fid,off) + with Not_found -> search rest (* Continue searching *)) + | _ -> + Kernel.abort ~current:true "unnamed field type is not a struct/union" end | _ :: rest -> search rest in @@ -2740,7 +2769,7 @@ try find_field_offset (fun x -> x.fname = n) fidlist with Not_found -> - Cil.error "Cannot find field %s" n; NoOffset + Kernel.error ~current:true "Cannot find field %s" n; NoOffset (* Utility ***) let rec replaceLastInList @@ -2773,7 +2802,7 @@ | A.LE -> Le | A.GT -> Gt | A.GE -> Ge - | _ -> Cil.fatal "convBinOp" + | _ -> Kernel.fatal ~current:true "convBinOp" (**** PEEP-HOLE optimizations ***) let afterConversion (c: chunk) : chunk = @@ -2793,8 +2822,9 @@ * the call *) (let tcallres = match unrollType (typeOf f) with - TFun (rt, _, _, _) -> rt - | _ -> Cil.abort "Function call to a non-function" + | TFun (rt, _, _, _) -> rt + | _ -> + Kernel.abort ~current:true "Function call to a non-function" in Cilutil.equals (typeSig tcallres) (typeSig vi.vtype) && Cilutil.equals (typeSig newt) (typeSig (typeOfLval destlv))) && @@ -2819,17 +2849,16 @@ end else None | _ -> None in - (* First add in the postins *) let block = c2block ~collapse_block:false c in let sl = - if !doCollapseCallCast then + if DoCollapseCallCast.get () then peepHole2 ~agressive:false collapseCallCast block.bstmts else block.bstmts in (* the call to c2block has taken care of a possible unspecified sequence. We do not need to keep track of effects at this level. *) let res = - { c with stmts = (List.map (fun x -> x,[],[],[],[]) sl); postins = [] } + { c with stmts = (List.rev_map (fun x -> x,[],[],[],[]) sl); } in (* Format.eprintf "Before conversion@\n%a@\nAfter conversion@\n%a@\n@." d_chunk c d_chunk res; @@ -2850,16 +2879,23 @@ else new_exp ~loc (BinOp(bop, e1, e2, t)) +let integral_cast ty t = + raise + (Failure + (Pretty_utils.sfprintf "term %a has type %a, but %a is expected." + Cil.d_term t Cil.d_logic_type Linteger Cil.d_type ty)) + module C_logic_env = struct - let annonCompFieldName = annonCompFieldName + let anonCompFieldName = anonCompFieldName let conditionalConversion = logicConditionalConversion let find_macro _ = raise Not_found let find_var x = match H.find env x with | EnvVar vi, _ -> cvar_to_lvar vi | _ -> raise Not_found let find_enum_tag x = match H.find env x with - | EnvEnum item,_ -> item.eival, TEnum (item.eihost,[]) + | EnvEnum item,_ -> + dummy_exp (Const (CEnum item)), typeOf item.eival | _ -> raise Not_found let find_comp_type ~kind s = findCompType kind s [] @@ -2874,6 +2910,8 @@ let add_logic_function = add_logic_function_gen Logic_utils.is_same_logic_profile + let integral_cast = integral_cast + end module Ltyping = Logic_typing.Make (C_logic_env) @@ -2885,10 +2923,9 @@ (* Exit a scope and clean the environment. We do not yet delete from * the name table *) let exitScope () = - let this, rest = - match !scopes with - car :: cdr -> car, cdr - | [] -> Cil.fatal "Not in a scope" + let this, rest = match !scopes with + | [] -> Kernel.fatal ~current:true "Not in a scope" + | car :: cdr -> car, cdr in scopes := rest; let rec loop = function @@ -2915,7 +2952,7 @@ let consLabContinue (c: chunk) = match !continues with - [] -> Cil.fatal "labContinue not in a loop" + | [] -> Kernel.fatal ~current:true "labContinue not in a loop" | While lr :: _ -> begin assert (!doTransformWhile); @@ -2963,7 +3000,7 @@ (* We have a label, perhaps we can jump here *) | s :: rest when s.labels <> [] -> - Cilmsg.debug ~level:4 "computeFromRoot call f from stmt %a" + Kernel.debug ~level:4 "computeFromRoot call f from stmt %a" Cil.d_loc (Stmt.loc s); f (s :: rest) @@ -2982,7 +3019,7 @@ | Code_annot _ -> true let rec stmtFallsThrough (s: stmt) : bool = - Cilmsg.debug ~level:4 "stmtFallsThrough stmt %a" + Kernel.debug ~level:4 "stmtFallsThrough stmt %a" Cil.d_loc (Stmt.loc s); match s.skind with Instr(il) -> @@ -3029,7 +3066,7 @@ (* will we leave this statement or block with a break command? *) and stmtCanBreak (s: stmt) : bool = - Cilmsg.debug ~level:4 "stmtCanBreak stmt %a" + Kernel.debug ~level:4 "stmtCanBreak stmt %a" Cil.d_loc (Stmt.loc s); match s.skind with Instr _ | Return _ | Continue _ | Goto _ -> false @@ -3048,7 +3085,7 @@ let rec aux = function [] -> false | s::tl -> - Cilmsg.debug ~level:4 "blockCanBreak from stmt %a" + Kernel.debug ~level:4 "blockCanBreak from stmt %a" Cil.d_loc (Stmt.loc s); stmtCanBreak s || (if stmtFallsThrough s then aux tl @@ -3057,7 +3094,7 @@ let chunkFallsThrough c = let get_stmt (s,_,_,_,_) = s in - let stmts = List.map get_stmt c.stmts @ List.map get_stmt c.postins in + let stmts = List.rev_map get_stmt c.stmts in stmtListFallsThrough stmts let rec doSpecList ghost (suggestedAnonName: string) @@ -3089,23 +3126,24 @@ A.SpecTypedef -> acc | A.SpecInline -> isinline := true; acc | A.SpecStorage st -> - if !storage <> NoStorage then - Cil.error "Multiple storage specifiers"; - let sto' = - match st with - A.NO_STORAGE -> NoStorage - | A.AUTO -> NoStorage - | A.REGISTER -> Register - | A.STATIC -> Static - | A.EXTERN -> Extern - in - storage := sto'; - acc + if !storage <> NoStorage then + Kernel.error ~current:true "Multiple storage specifiers"; + let sto' = + match st with + A.NO_STORAGE -> NoStorage + | A.AUTO -> NoStorage + | A.REGISTER -> Register + | A.STATIC -> Static + | A.EXTERN -> Extern + in + storage := sto'; + acc | A.SpecCV cv -> cvattrs := cv :: !cvattrs; acc | A.SpecAttr a -> attrs := a :: !attrs; acc | A.SpecType ts -> ts :: acc - | A.SpecPattern _ -> Cil.abort "SpecPattern in cabs2cil input" + | A.SpecPattern _ -> + Kernel.abort ~current:true "SpecPattern in cabs2cil input" in (* Now scan the list and collect the type specifiers. Preserve the order *) let tspecs = List.fold_right doSpecElem specs [] in @@ -3117,7 +3155,7 @@ A.Tnamed _ :: (_ :: _ as rest) when not theMachine.msvcMode -> (* If rest contains "short" or "long" then drop the Tnamed *) if List.exists (function A.Tshort -> true - | A.Tlong -> true | _ -> false) rest then + | A.Tlong -> true | _ -> false) rest then rest else tspecs @@ -3127,9 +3165,9 @@ let tspecs'' = match specs, List.rev tspecs' with | A.SpecTypedef :: _, A.Tnamed _ :: [] -> - tspecs' + tspecs' | A.SpecTypedef :: _, A.Tnamed _ :: rest -> - List.rev rest + List.rev rest | _ -> tspecs' in (* Sort the type specifiers *) @@ -3148,7 +3186,7 @@ | _ -> 10 (* There should be at most one of the others *) in List.stable_sort (fun ts1 ts2 -> - Datatype.Int.compare (order ts1) (order ts2)) tspecs'' + Datatype.Int.compare (order ts1) (order ts2)) tspecs'' in let getTypeAttrs () : A.attribute list = (* Partitions the attributes in !attrs. @@ -3160,7 +3198,8 @@ let an, af, at = cabsPartitionAttributes ghost ~default:AttrType !attrs in attrs := an; (* Save the name attributes for later *) if af <> [] then - Cil.error "Invalid position for function type attributes."; + Kernel.error ~current:true + "Invalid position for function type attributes."; at in @@ -3217,146 +3256,191 @@ | [A.Tlong; A.Tdouble] -> TFloat(FLongDouble, []) (* Now the other type specifiers *) - | [A.Tnamed n] -> begin - if n = "__builtin_va_list" && - Machdep.state.Machdep.gccHas__builtin_va_list then begin - TBuiltin_va_list [] - end else - let t = - match lookupType "type" n with - (TNamed _) as x, _ -> x - | _ -> Cil.fatal - "Named type %s is not mapped correctly" n - in - t - end + | [A.Tnamed n] -> + if n = "__builtin_va_list" && + Global_machdep.state.Global_machdep.gccHas__builtin_va_list + then + TBuiltin_va_list [] + else + (match lookupType "type" n with + | (TNamed _) as x, _ -> x + | _ -> + Kernel.fatal ~current:true "Named type %s is not mapped correctly" n) | [A.Tstruct (n, None, _)] -> (* A reference to a struct *) - if n = "" then Cil.error "Missing struct tag on incomplete struct"; - findCompType "struct" n [] + if n = "" then + Kernel.error ~current:true "Missing struct tag on incomplete struct"; + findCompType "struct" n [] | [A.Tstruct (n, Some nglist, extraAttrs)] -> (* A definition of a struct *) - let n' = - if n <> "" then n else anonStructName "struct" suggestedAnonName in - (* Use the (non-cv, non-name) attributes in !attrs now *) - let a = extraAttrs @ (getTypeAttrs ()) in - makeCompType ghost true n' nglist (doAttributes ghost a) + let n' = + if n <> "" then n else anonStructName "struct" suggestedAnonName in + (* Use the (non-cv, non-name) attributes in !attrs now *) + let a = extraAttrs @ (getTypeAttrs ()) in + makeCompType ghost true n' nglist (doAttributes ghost a) | [A.Tunion (n, None, _)] -> (* A reference to a union *) - if n = "" then Cil.error "Missing union tag on incomplete union"; - findCompType "union" n [] + if n = "" then + Kernel.error ~current:true "Missing union tag on incomplete union"; + findCompType "union" n [] | [A.Tunion (n, Some nglist, extraAttrs)] -> (* A definition of a union *) - let n' = - if n <> "" then n else anonStructName "union" suggestedAnonName in - (* Use the attributes now *) - let a = extraAttrs @ (getTypeAttrs ()) in - makeCompType ghost false n' nglist (doAttributes ghost a) + let n' = + if n <> "" then n else anonStructName "union" suggestedAnonName in + (* Use the attributes now *) + let a = extraAttrs @ (getTypeAttrs ()) in + makeCompType ghost false n' nglist (doAttributes ghost a) | [A.Tenum (n, None, _)] -> (* Just a reference to an enum *) - if n = "" then Cil.error "Missing enum tag on incomplete enum"; - findCompType "enum" n [] + if n = "" then + Kernel.error ~current:true "Missing enum tag on incomplete enum"; + findCompType "enum" n [] | [A.Tenum (n, Some eil, extraAttrs)] -> (* A definition of an enum *) - let n' = - if n <> "" then n else anonStructName "enum" suggestedAnonName in - (* make a new name for this enumeration *) - let n'', _ = newAlphaName true "enum" n' in - - (* Create the enuminfo, or use one that was created already for a - * forward reference *) - let enum, _ = createEnumInfo n'' in - let a = extraAttrs @ (getTypeAttrs ()) in - enum.eattr <- doAttributes ghost a; - let res = TEnum (enum, []) in - - (* sm: start a scope for the enum tag values, since they * - * can refer to earlier tags *) - enterScope (); - - (* as each name,value pair is determined, this is called *) - let rec processName kname (i: exp) loc rest = begin - (* add the name to the environment, but with a faked 'typ' field; - * we don't know the full type yet (since that includes all of the - * tag values), but we won't need them in here *) - - (* add this tag to the list so that it ends up in the real - * environment when we're finished *) - let newname, _ = newAlphaName true "" kname in - let item = { eiorig_name = kname; - einame = newname; - eival = i; - eiloc = loc; - eihost = enum } - in - addLocalToEnv kname (EnvEnum item); - (kname, item) :: loop (increm i 1) rest - end - - and loop i = function - [] -> [] - | (kname, { expr_node = A.NOTHING}, cloc) :: rest -> - (* use the passed-in 'i' as the value, since none specified *) - processName kname i (convLoc cloc) rest - - | (kname, e, cloc) :: rest -> - (* constant-eval 'e' to determine tag value *) - let e' = getIntConstExp ghost e in - let e' = - match isInteger (constFold true e') with - Some i -> - if theMachine.lowerConstants then - kinteger64 ~loc:e.expr_loc IInt i - else e' - | _ -> Cil.fatal - "Constant initializer %a not an integer" - d_exp e' - in - processName kname e' (convLoc cloc) rest + let n' = + if n <> "" then n else anonStructName "enum" suggestedAnonName in + (* make a new name for this enumeration *) + let n'', _ = newAlphaName true "enum" n' in + + (* Create the enuminfo, or use one that was created already for a + * forward reference *) + let enum, _ = createEnumInfo n'' in + let a = extraAttrs @ (getTypeAttrs ()) in + enum.eattr <- doAttributes ghost a; + let res = TEnum (enum, []) in + let smallest = ref My_bigint.zero in + let largest = ref My_bigint.zero in + + (* Life is fun here. ANSI says: enum constants are ints, + and there's an implementation-dependent underlying integer + type for the enum, which must be capable of holding all the + enum's values. + For MSVC, we follow these rules and assume the enum's + underlying type is int. + GCC allows enum constants that don't fit in int: the enum + constant's type is the smallest type (but at least int) that + will hold the value, with a preference for signed types. + The underlying type EI of the enum is picked as follows: + - let T be the smallest integer type that holds all the enum's + values; T is signed if any enum value is negative, unsigned otherwise + - if the enum is packed or sizeof(T) >= sizeof(int), then EI = T + - otherwise EI = int if T is signed and unsigned int otherwise + Note that these rules make the enum unsigned if possible *) + let updateEnum i : ikind = + if My_bigint.lt i !smallest then + smallest := i; + if My_bigint.gt i !largest then + largest := i; + if theMachine.msvcMode then + IInt + else + (* This matches gcc's behaviour *) + if fitsInInt IInt i then IInt + else if fitsInInt IUInt i then IUInt + else if fitsInInt ILongLong i then ILongLong + else IULongLong + in + (* as each name,value pair is determined, this is called *) + let rec processName kname (i: exp) loc rest = begin + (* add the name to the environment, but with a faked 'typ' field; + * we don't know the full type yet (since that includes all of the + * tag values), but we won't need them in here *) + + (* add this tag to the list so that it ends up in the real + * environment when we're finished *) + let newname, _ = newAlphaName true "" kname in + let item = { eiorig_name = kname; + einame = newname; + eival = i; + eiloc = loc; + eihost = enum } in + addLocalToEnv kname (EnvEnum item); + (kname, item) :: loop (increm i 1) rest + end - (* sm: now throw away the environment we built for eval'ing the enum - * tags, so we can add to the new one properly *) - exitScope (); - - (*TODO: find a better loc*) - let fields = loop (zero ~loc:(CurrentLoc.get())) eil in - (* Now set the right set of items *) - enum.eitems <- List.map (fun (_, x) -> x) fields; - (* Record the enum name in the environment *) - addLocalToEnv (kindPlusName "enum" n'') (EnvTyp res); - (* And define the tag *) - cabsPushGlobal (GEnumTag (enum, CurrentLoc.get ())); - res + and loop i = function + [] -> [] + | (kname, { expr_node = A.NOTHING}, cloc) :: rest -> + (* use the passed-in 'i' as the value, since none specified *) + processName kname i (convLoc cloc) rest + + | (kname, e, cloc) :: rest -> + (* constant-eval 'e' to determine tag value *) + let e' = getIntConstExp ghost e in + let e' = match isInteger (constFold true e') with + | None -> + Kernel.fatal ~current:true + "Constant initializer %a not an integer" + d_exp e' + | Some i -> + let ik = updateEnum i in + if theMachine.lowerConstants then + kinteger64 ~loc:e.expr_loc ik i + else e' + in + processName kname e' (convLoc cloc) rest + in + (*TODO: find a better loc*) + let fields = loop (zero ~loc:(CurrentLoc.get())) eil in + (* Now set the right set of items *) + enum.eitems <- List.map (fun (_, x) -> x) fields; + (* Pick the enum's kind - see discussion above *) + if not theMachine.msvcMode then begin + let unsigned = My_bigint.ge !smallest My_bigint.zero in + let smallKind = intKindForValue !smallest unsigned in + let largeKind = intKindForValue !largest unsigned in + let ekind = + if (bytesSizeOfInt smallKind) > (bytesSizeOfInt largeKind) then + smallKind + else + largeKind + in + enum.ekind <- + if bytesSizeOfInt ekind < bytesSizeOfInt IInt then + if hasAttribute "packed" enum.eattr then + ekind + else + if unsigned then IUInt else IInt + else + ekind + end; + (* Record the enum name in the environment *) + addLocalToEnv (kindPlusName "enum" n'') (EnvTyp res); + (* And define the tag *) + cabsPushGlobal (GEnumTag (enum, CurrentLoc.get ())); + res | [A.TtypeofE e] -> - let (_, _, e', t) = doExp (ghost_local_env ghost) false e AType in - let t' = - match e'.enode with - StartOf(lv) -> typeOfLval lv - (* If this is a string literal, then we treat it as in sizeof*) - | Const (CStr s) -> begin - match typeOf e' with - TPtr(bt, _) -> (* This is the type of array elements *) - TArray(bt, - Some (new_exp ~loc:e'.eloc (SizeOfStr s)), - empty_size_cache (), - []) - | _ -> Cil.abort "The typeOf a string is not a pointer type" - end - | _ -> t - in - (* - ignore (E.log "typeof(%a) = %a\n" d_exp e' d_plaintype t'); - *) - t' + let (_, _, e', t) = doExp (ghost_local_env ghost) false e AType in + let t' = + match e'.enode with + StartOf(lv) -> typeOfLval lv + (* If this is a string literal, then we treat it as in sizeof*) + | Const (CStr s) -> begin + match typeOf e' with + | TPtr(bt, _) -> (* This is the type of array elements *) + TArray(bt, + Some (new_exp ~loc:e'.eloc (SizeOfStr s)), + empty_size_cache (), + []) + | _ -> + Kernel.abort ~current:true + "The typeOf a string is not a pointer type" + end + | _ -> t + in + (* + ignore (E.log "typeof(%a) = %a\n" d_exp e' d_plaintype t'); + *) + t' | [A.TtypeofT (specs, dt)] -> - let typ = doOnlyType ghost specs dt in - typ + doOnlyType ghost specs dt | l -> - Cil.fatal "Invalid combination of type specifiers:@ %a" - (pp_list ~sep:"@ " Cprint.print_type_spec) l; + Kernel.fatal ~current:true + "Invalid combination of type specifiers:@ %a" + (pp_list ~sep:"@ " Cprint.print_type_spec) l; in bt,!storage,!isinline,List.rev (!attrs @ (convertCVtoAttr !cvattrs)) @@ -3386,7 +3470,7 @@ bt (A.PARENTYPE(attrs, ndt, a)) in (* log "Got yp:%a->%a(%a)@." d_type bt d_type vtype d_attrlist nattr;*) if inline && not (isFunctionType vtype) then - ignore (error "inline for a non-function: %s" n); + Kernel.error ~current:true "inline for a non-function: %s" n; let t = if not isglobal && not isformal then begin (* Sometimes we call this on the formal argument of a function with no @@ -3422,9 +3506,9 @@ ~isglobal:false ldecl spec_res (n,ndt,a), empty, zero ~loc:ldecl, false | Some (ndt', se, len) -> - makeVarInfoCabs ~ghost ~isformal:false - ~isglobal:false - ldecl spec_res (n,ndt',a), se, len, true + makeVarInfoCabs ~ghost ~isformal:false + ~isglobal:false + ldecl spec_res (n,ndt',a), se, len, true else makeVarInfoCabs ~ghost ~isformal:false ~isglobal:false @@ -3436,7 +3520,7 @@ let l = String.length n in let rec start i = if i >= l then - Cil.error "Invalid attribute name %s" n; + Kernel.error ~current:true "Invalid attribute name %s" n; if String.get n i = '_' then start (i + 1) else i in let st = start 0 in @@ -3450,86 +3534,88 @@ match a with | ("__attribute__", []) -> [] (* An empty list of gcc attributes *) | (s, []) -> - let s = stripUnderscore s in - [ match attrAnnot s with None -> Attr(s, []) | Some s -> AttrAnnot s ] + let s = stripUnderscore s in + [ match attrAnnot s with None -> Attr(s, []) | Some s -> AttrAnnot s ] | (s, el) -> - let rec attrOfExp (strip: bool) - ?(foldenum=true) - (a: A.expression) : attrparam = - let loc = a.expr_loc in - match a.expr_node with - A.VARIABLE n -> begin - let n' = if strip then stripUnderscore n else n in - (** See if this is an enumeration *) - try - if not foldenum then raise Not_found; + let rec attrOfExp (strip: bool) + ?(foldenum=true) + (a: A.expression) : attrparam = + let loc = a.expr_loc in + match a.expr_node with + A.VARIABLE n -> begin + let n' = if strip then stripUnderscore n else n in + (** See if this is an enumeration *) + try + if not foldenum then raise Not_found; - match H.find env n' with - EnvEnum item, _ -> begin - match isInteger (constFold true item.eival) with - Some i64 when theMachine.lowerConstants -> - AInt (Int64.to_int i64) - | _ -> ACons(n', []) - end - | _ -> ACons (n', []) - with Not_found -> ACons(n', []) - end - | A.CONSTANT (A.CONST_STRING s) -> AStr s - | A.CONSTANT (A.CONST_INT str) -> begin - match (parseInt ~loc str).enode with - Const (CInt64 (v64,_,_)) -> - AInt (i64_to_int v64) - | _ -> - Cil.fatal "Invalid attribute constant: %s" str - end - | A.CALL({expr_node = A.VARIABLE n}, args) -> begin - let n' = if strip then stripUnderscore n else n in - let ae' = List.map ae args in - ACons(n', ae') - end - | A.EXPR_SIZEOF e -> ASizeOfE (ae e) - | A.TYPE_SIZEOF (bt, dt) -> ASizeOf (doOnlyType ghost bt dt) - | A.EXPR_ALIGNOF e -> AAlignOfE (ae e) - | A.TYPE_ALIGNOF (bt, dt) -> AAlignOf (doOnlyType ghost bt dt) - | A.BINARY(A.AND, aa1, aa2) -> - ABinOp(LAnd, ae aa1, ae aa2) - | A.BINARY(A.OR, aa1, aa2) -> - ABinOp(LOr, ae aa1, ae aa2) - | A.BINARY(abop, aa1, aa2) -> - ABinOp (convBinOp abop, ae aa1, ae aa2) - | A.UNARY(A.PLUS, aa) -> ae aa - | A.UNARY(A.MINUS, aa) -> AUnOp (Neg, ae aa) - | A.UNARY(A.BNOT, aa) -> AUnOp(BNot, ae aa) - | A.UNARY(A.NOT, aa) -> AUnOp(LNot, ae aa) - | A.MEMBEROF (e, s) -> ADot (ae e, s) - | A.PAREN(e) -> attrOfExp strip ~foldenum:foldenum e - | A.UNARY(A.MEMOF, aa) -> AStar (ae aa) - | A.UNARY(A.ADDROF, aa) -> AAddrOf (ae aa) - | A.MEMBEROFPTR (aa1, s) -> ADot(AStar(ae aa1), s) - | A.INDEX(aa1, aa2) -> AIndex(ae aa1, ae aa2) - | A.QUESTION(aa1, aa2, aa3) -> AQuestion(ae aa1, ae aa2, ae aa3) + match H.find env n' with + EnvEnum item, _ -> begin + match isInteger (constFold true item.eival) with + Some i64 when theMachine.lowerConstants -> + AInt (My_bigint.to_int i64) + | _ -> ACons(n', []) + end + | _ -> ACons (n', []) + with Not_found -> ACons(n', []) + end + | A.CONSTANT (A.CONST_STRING s) -> AStr s + | A.CONSTANT (A.CONST_INT str) -> begin + match (parseInt ~loc str).enode with + | Const (CInt64 (v64,_,_)) -> + AInt (My_bigint.to_int v64) | _ -> - Cil.fatal "cabs2cil: invalid expression in attribute: %a" - Cprint.print_expression a - - and ae (e: A.expression) = attrOfExp false e in - - (* Sometimes we need to convert attrarg into attr *) - let arg2attr = function - | ACons (s, args) -> Attr (s, args) - | a -> - Cil.fatal "Invalid form of attribute: %a" - d_attrparam a; - in - if s = "__attribute__" then (* Just a wrapper for many attributes*) - List.map (fun e -> arg2attr (attrOfExp true ~foldenum:false e)) el - else if s = "__blockattribute__" then (* Another wrapper *) - List.map (fun e -> arg2attr (attrOfExp true ~foldenum:false e)) el - else if s = "__declspec" then - List.map (fun e -> arg2attr (attrOfExp false ~foldenum:false e)) el - else - [Attr(stripUnderscore s, List.map (attrOfExp ~foldenum:false false) el)] + Kernel.fatal ~current:true "Invalid attribute constant: %s" str + end + | A.CALL({expr_node = A.VARIABLE n}, args) -> begin + let n' = if strip then stripUnderscore n else n in + let ae' = List.map ae args in + ACons(n', ae') + end + | A.EXPR_SIZEOF e -> ASizeOfE (ae e) + | A.TYPE_SIZEOF (bt, dt) -> ASizeOf (doOnlyType ghost bt dt) + | A.EXPR_ALIGNOF e -> AAlignOfE (ae e) + | A.TYPE_ALIGNOF (bt, dt) -> AAlignOf (doOnlyType ghost bt dt) + | A.BINARY(A.AND, aa1, aa2) -> + ABinOp(LAnd, ae aa1, ae aa2) + | A.BINARY(A.OR, aa1, aa2) -> + ABinOp(LOr, ae aa1, ae aa2) + | A.BINARY(abop, aa1, aa2) -> + ABinOp (convBinOp abop, ae aa1, ae aa2) + | A.UNARY(A.PLUS, aa) -> ae aa + | A.UNARY(A.MINUS, aa) -> AUnOp (Neg, ae aa) + | A.UNARY(A.BNOT, aa) -> AUnOp(BNot, ae aa) + | A.UNARY(A.NOT, aa) -> AUnOp(LNot, ae aa) + | A.MEMBEROF (e, s) -> ADot (ae e, s) + | A.PAREN(e) -> attrOfExp strip ~foldenum:foldenum e + | A.UNARY(A.MEMOF, aa) -> AStar (ae aa) + | A.UNARY(A.ADDROF, aa) -> AAddrOf (ae aa) + | A.MEMBEROFPTR (aa1, s) -> ADot(AStar(ae aa1), s) + | A.INDEX(aa1, aa2) -> AIndex(ae aa1, ae aa2) + | A.QUESTION(aa1, aa2, aa3) -> AQuestion(ae aa1, ae aa2, ae aa3) + | _ -> + Kernel.fatal ~current:true + "cabs2cil: invalid expression in attribute: %a" + Cprint.print_expression a + + and ae (e: A.expression) = attrOfExp false e in + + (* Sometimes we need to convert attrarg into attr *) + let arg2attr = function + | ACons (s, args) -> Attr (s, args) + | a -> + Kernel.fatal ~current:true + "Invalid form of attribute: %a" + d_attrparam a; + in + if s = "__attribute__" then (* Just a wrapper for many attributes*) + List.map (fun e -> arg2attr (attrOfExp true ~foldenum:false e)) el + else if s = "__blockattribute__" then (* Another wrapper *) + List.map (fun e -> arg2attr (attrOfExp true ~foldenum:false e)) el + else if s = "__declspec" then + List.map (fun e -> arg2attr (attrOfExp false ~foldenum:false e)) el + else + [Attr(stripUnderscore s, List.map (attrOfExp ~foldenum:false false) el)] and doAttributes (ghost:bool) (al: A.attribute list) : attribute list = List.fold_left (fun acc a -> cabsAddAttributes (doAttr ghost a) acc) [] al @@ -3543,18 +3629,18 @@ (attrs: A.attribute list) : A.attribute list * A.attribute list * A.attribute list = let rec loop (n,f,t) = function - [] -> n, f, t + [] -> n, f, t | a :: rest -> - let kind = match doAttr ghost a with + let kind = match doAttr ghost a with [] -> default | (Attr(an, _) | AttrAnnot an)::_ -> - (try attributeClass an with Not_found -> default) - in - match kind with - AttrName _ -> loop (a::n, f, t) rest - | AttrFunType _ -> - loop (n, a::f, t) rest - | AttrType -> loop (n, f, a::t) rest + (try attributeClass an with Not_found -> default) + in + match kind with + AttrName _ -> loop (a::n, f, t) rest + | AttrFunType _ -> + loop (n, a::f, t) rest + | AttrType -> loop (n, f, a::t) rest in loop ([], [], []) attrs @@ -3576,236 +3662,233 @@ * declarator type is as printed, meaning that it is the reverse of the * right one *) let rec doDeclType (bt: typ) (acc: attribute list) = function - A.JUSTBASE -> bt, acc + | A.JUSTBASE -> bt, acc | A.PARENTYPE (a1, d, a2) -> - let a1' = doAttributes ghost a1 in - let a1n, a1f, a1t = partitionAttributes AttrType a1' in - let a2' = doAttributes ghost a2 in - let a2n, a2f, a2t = partitionAttributes nameortype a2' in - (* log "doType: %a @[a1n=%a@\na1f=%a@\na1t=%a@\na2n=%a@\na2f=%a@\na2t=%a@]@\n" d_loc !currentLoc d_attrlist a1n d_attrlist a1f d_attrlist a1t d_attrlist a2n d_attrlist a2f d_attrlist a2t;*) - let bt' = cabsTypeAddAttributes a1t bt in - (* log "bt' = %a@." d_type bt';*) - - let bt'', a1fadded = - match unrollType bt with - TFun _ -> cabsTypeAddAttributes a1f bt', true - | _ -> bt', false - in - (* Now recurse *) - let restyp, nattr = doDeclType bt'' acc d in - (* Add some more type attributes *) - let restyp = cabsTypeAddAttributes a2t restyp in - (* See if we can add some more type attributes *) - let restyp' = - match unrollType restyp with - TFun _ -> - if a1fadded then - cabsTypeAddAttributes a2f restyp - else - cabsTypeAddAttributes a2f - (cabsTypeAddAttributes a1f restyp) - | TPtr ((TFun _ as tf), ap) when not theMachine.msvcMode -> - if a1fadded then - TPtr(cabsTypeAddAttributes a2f tf, ap) - else - TPtr(cabsTypeAddAttributes a2f - (cabsTypeAddAttributes a1f tf), ap) - | _ -> - if a1f <> [] && not a1fadded then - Cil.error "Invalid position for (prefix) function type attributes:%a" - d_attrlist a1f; - if a2f <> [] then - Cil.error "Invalid position for (post) function type attributes:%a" - d_attrlist a2f; - restyp - in - (* log "restyp' = %a@." d_type restyp';*) + let a1' = doAttributes ghost a1 in + let a1n, a1f, a1t = partitionAttributes AttrType a1' in + let a2' = doAttributes ghost a2 in + let a2n, a2f, a2t = partitionAttributes nameortype a2' in + (* log "doType: %a @[a1n=%a@\na1f=%a@\na1t=%a@\na2n=%a@\na2f=%a@\na2t=%a@]@\n" d_loc !currentLoc d_attrlist a1n d_attrlist a1f d_attrlist a1t d_attrlist a2n d_attrlist a2f d_attrlist a2t;*) + let bt' = cabsTypeAddAttributes a1t bt in + (* log "bt' = %a@." d_type bt';*) + + let bt'', a1fadded = + match unrollType bt with + TFun _ -> cabsTypeAddAttributes a1f bt', true + | _ -> bt', false + in + (* Now recurse *) + let restyp, nattr = doDeclType bt'' acc d in + (* Add some more type attributes *) + let restyp = cabsTypeAddAttributes a2t restyp in + (* See if we can add some more type attributes *) + let restyp' = + match unrollType restyp with + TFun _ -> + if a1fadded then + cabsTypeAddAttributes a2f restyp + else + cabsTypeAddAttributes a2f + (cabsTypeAddAttributes a1f restyp) + | TPtr ((TFun _ as tf), ap) when not theMachine.msvcMode -> + if a1fadded then + TPtr(cabsTypeAddAttributes a2f tf, ap) + else + TPtr(cabsTypeAddAttributes a2f + (cabsTypeAddAttributes a1f tf), ap) + | _ -> + if a1f <> [] && not a1fadded then + Kernel.error ~current:true + "Invalid position for (prefix) function type attributes:%a" + d_attrlist a1f; + if a2f <> [] then + Kernel.error ~current:true + "Invalid position for (post) function type attributes:%a" + d_attrlist a2f; + restyp + in + (* log "restyp' = %a@." d_type restyp';*) - (* Now add the name attributes and return *) - restyp', cabsAddAttributes a1n (cabsAddAttributes a2n nattr) + (* Now add the name attributes and return *) + restyp', cabsAddAttributes a1n (cabsAddAttributes a2n nattr) | A.PTR (al, d) -> - let al' = doAttributes ghost al in - let an, af, at = partitionAttributes AttrType al' in - (* Now recurse *) - let restyp, nattr = doDeclType (TPtr(bt, at)) acc d in - (* See if we can do anything with function type attributes *) - let restyp' = - match unrollType restyp with - TFun _ -> cabsTypeAddAttributes af restyp - | TPtr((TFun _ as tf), ap) -> - TPtr(cabsTypeAddAttributes af tf, ap) - | _ -> - if af <> [] then - Cil.error "Invalid position for function type attributes:%a" - d_attrlist af; - restyp - in - (* Now add the name attributes and return *) - restyp', cabsAddAttributes an nattr + let al' = doAttributes ghost al in + let an, af, at = partitionAttributes AttrType al' in + (* Now recurse *) + let restyp, nattr = doDeclType (TPtr(bt, at)) acc d in + (* See if we can do anything with function type attributes *) + let restyp' = + match unrollType restyp with + TFun _ -> cabsTypeAddAttributes af restyp + | TPtr((TFun _ as tf), ap) -> + TPtr(cabsTypeAddAttributes af tf, ap) + | _ -> + if af <> [] then + Kernel.error ~current:true + "Invalid position for function type attributes:%a" + d_attrlist af; + restyp + in + (* Now add the name attributes and return *) + restyp', cabsAddAttributes an nattr | A.ARRAY (d, al, len) -> - let lo = - match len.expr_node with - A.NOTHING -> None - | _ -> - (* Check that len is a constant expression. - We used to also cast the length to int here, but that's - theoretically too restrictive on 64-bit machines. *) - let len' = doPureExp (ghost_local_env ghost) len in - if not (isIntegralType (typeOf len')) then - Cil.error "Array length %a does not have an integral type." - d_exp len'; - if not allowVarSizeArrays then begin - (* Assert that len' is a constant *) - let elsz = - try (bitsSizeOf bt + 7) / 8 - with SizeOfError _ -> 1 - (** We get this if we cannot compute the size of - one element. This can happen, when we define - an extern, for example. - We use 1 for now *) - in - let cst = constFold true len' in - (match cst.enode with - Const(CInt64(i, _, _)) -> - if i < 0L then - Cil.error "Length of array is negative"; - if Int64.mul i (Int64.of_int elsz) >= 0x80000000L then - Cil.error "Length of array is too large" + let lo = + match len.expr_node with + A.NOTHING -> None + | _ -> + (* Check that len is a constant expression. + We used to also cast the length to int here, but that's + theoretically too restrictive on 64-bit machines. *) + let len' = doPureExp (ghost_local_env ghost) len in + if not (isIntegralType (typeOf len')) then + Kernel.error ~current:true + "Array length %a does not have an integral type." + d_exp len'; + if not allowVarSizeArrays then begin + (* Assert that len' is a constant *) + let cst = constFold true len' in + (match cst.enode with + | Const(CInt64(i, _, _)) -> + if My_bigint.lt i My_bigint.zero then + Kernel.error ~current:true "Length of array is negative"; - | _ -> - if isConstant cst then - (* e.g., there may be a float constant involved. - * We'll leave it to the user to ensure the length is - * non-negative, etc.*) - (Cil.warning "Unable to do constant-folding on array length %a. Some CIL operations on this array may fail." - d_exp cst) - else - Cil.error "Length of array is not a constant: %a" - d_exp cst) - end; - Some len' - in - let al' = doAttributes ghost al in - if not isFuncArg && hasAttribute "static" al' then - Cil.error - "static specifier inside array argument is allowed only in \ + | _ -> + if isConstant cst then + (* e.g., there may be a float constant involved. + * We'll leave it to the user to ensure the length is + * non-negative, etc.*) + Kernel.warning ~current:true + "Unable to do constant-folding on array length %a. \ + Some CIL operations on this array may fail." + d_exp cst + else + Kernel.error ~current:true + "Length of array is not a constant: %a" + d_exp cst) + end; + Some len' + in + let al' = doAttributes ghost al in + if not isFuncArg && hasAttribute "static" al' then + Kernel.error ~current:true + "static specifier inside array argument is allowed only in \ function argument"; - doDeclType (TArray(bt, lo, empty_size_cache (), al')) acc d + doDeclType (TArray(bt, lo, empty_size_cache (), al')) acc d | A.PROTO (d, args, isva) -> - (* Start a scope for the parameter names *) - enterScope (); - (* Intercept the old-style use of varargs.h. On GCC this means that - * we have ellipsis and a last argument "builtin_va_alist: - * builtin_va_alist_t". On MSVC we do not have the ellipsis and we - * have a last argument "va_alist: va_list" *) - let args', isva' = - if args != [] && theMachine.msvcMode = not isva then begin - let newisva = ref isva in - let rec doLast = function - [([A.SpecType (A.Tnamed atn)], (an, A.JUSTBASE, [], _))] - when isOldStyleVarArgTypeName atn && - isOldStyleVarArgName an -> begin - (* Turn it into a vararg *) - newisva := true; - (* And forget about this argument *) - [] - end + (* Start a scope for the parameter names *) + enterScope (); + (* Intercept the old-style use of varargs.h. On GCC this means that + * we have ellipsis and a last argument "builtin_va_alist: + * builtin_va_alist_t". On MSVC we do not have the ellipsis and we + * have a last argument "va_alist: va_list" *) + let args', isva' = + if args != [] && theMachine.msvcMode = not isva then begin + let newisva = ref isva in + let rec doLast = function + [([A.SpecType (A.Tnamed atn)], (an, A.JUSTBASE, [], _))] + when isOldStyleVarArgTypeName atn && + isOldStyleVarArgName an -> begin + (* Turn it into a vararg *) + newisva := true; + (* And forget about this argument *) + [] + end - | a :: rest -> a :: doLast rest - | [] -> [] + | a :: rest -> a :: doLast rest + | [] -> [] + in + let args' = doLast args in + (args', !newisva) + end else (args, isva) + in + (* Make the argument as for a formal *) + let doOneArg (s, (n, ndt, a, cloc)) : varinfo = + let s' = doSpecList ghost n s in + let vi = makeVarInfoCabs ~ghost ~isformal:true ~isglobal:false + (convLoc cloc) s' (n,ndt,a) in + (* Add the formal to the environment, so it can be referenced by + other formals (e.g. in an array type, although that will be + changed to a pointer later, or though typeof). *) + addLocalToEnv vi.vname (EnvVar vi); + vi + in + let targs : varinfo list option = + match List.map doOneArg args' with + | [] -> None (* No argument list *) + | [t] when isVoidType t.vtype -> + Some [] + | l -> + Some l + in + exitScope (); + (* Turn [] types into pointers in the arguments and the result type. + * Turn function types into pointers to respective. This simplifies + * our life a lot, and is what the standard requires. *) + let turnArrayIntoPointer (bt: typ) + (lo: exp option) (a: attributes) : typ = + let real_a = dropAttribute "static" a in + let a' : attributes = + match lo with + None -> [] + | Some l -> begin + let static = if hasAttribute "static" a then + [Attr ("static",[])] + else [] in - let args' = doLast args in - (args', !newisva) - end else (args, isva) - in - (* Make the argument as for a formal *) - let doOneArg (s, (n, ndt, a, cloc)) : varinfo = - let s' = doSpecList ghost n s in - let vi = makeVarInfoCabs ~ghost ~isformal:true ~isglobal:false - (convLoc cloc) s' (n,ndt,a) in - (* Add the formal to the environment, so it can be referenced by - other formals (e.g. in an array type, although that will be - changed to a pointer later, or though typeof). *) - addLocalToEnv vi.vname (EnvVar vi); - vi - in - let targs : varinfo list option = - match List.map doOneArg args' with - | [] -> None (* No argument list *) - | [t] when isVoidType t.vtype -> - Some [] - | l -> - Some l + (* Transform the length into an attribute expression *) + try + let la : attrparam = expToAttrParam l in + Attr("arraylen", [ la ]) :: static + with NotAnAttrParam _ -> begin + Kernel.warning ~current:true + "Cannot represent the length of array as an attribute"; + static (* Leave unchanged *) + end + end in - exitScope (); - (* Turn [] types into pointers in the arguments and the result type. - * Turn function types into pointers to respective. This simplifies - * our life a lot, and is what the standard requires. *) - let turnArrayIntoPointer (bt: typ) - (lo: exp option) (a: attributes) : typ = - let real_a = dropAttribute "static" a in - let a' : attributes = - match lo with - None -> [] - | Some l -> begin - let static = if hasAttribute "static" a then - [Attr ("static",[])] - else [] - in - (* Transform the length into an attribute expression *) - try - let la : attrparam = expToAttrParam l in - Attr("arraylen", [ la ]) :: static - with NotAnAttrParam _ -> begin - (Cil.warning "Cannot represent the length of array as an attribute"); - - static (* Leave unchanged *) - end - end - in - let rec downwardAttrInArray bt = match bt with + let rec downwardAttrInArray bt = match bt with | TArray(bt,lo,s,attr) -> TArray(downwardAttrInArray bt, lo, s, attr) | _ -> typeAddAttributes real_a bt - in - TPtr(downwardAttrInArray bt, a') - in - let rec fixupArgumentTypes (argidx: int) (args: varinfo list) : unit = - match args with - [] -> () - | a :: args' -> - (match unrollType a.vtype with - TArray(bt,lo,_,attr) -> - (* Note that for multi-dimensional arrays we strip off only - the first TArray and leave bt alone. *) - a.vtype <- turnArrayIntoPointer bt lo attr - | TFun _ -> a.vtype <- TPtr(a.vtype, []) - | TComp (_, _,_) -> begin - match isTransparentUnion a.vtype with - None -> () - | Some fstfield -> - transparentUnionArgs := - (argidx, a.vtype) :: !transparentUnionArgs; - a.vtype <- fstfield.ftype; - end - | _ -> ()); - fixupArgumentTypes (argidx + 1) args' - in - let args = - match targs with - None -> None - | Some argl -> - fixupArgumentTypes 0 argl; - Some (List.map (fun a -> (a.vname, a.vtype, a.vattr)) argl) - in - let tres = - match unrollType bt with - TArray(t,lo,_,attr) -> turnArrayIntoPointer t lo attr - | _ -> bt - in - doDeclType (TFun (tres, args, isva', [])) acc d + in + TPtr(downwardAttrInArray bt, a') + in + let rec fixupArgumentTypes (argidx: int) (args: varinfo list) : unit = + match args with + [] -> () + | a :: args' -> + (match unrollType a.vtype with + TArray(bt,lo,_,attr) -> + (* Note that for multi-dimensional arrays we strip off only + the first TArray and leave bt alone. *) + a.vtype <- turnArrayIntoPointer bt lo attr + | TFun _ -> a.vtype <- TPtr(a.vtype, []) + | TComp (_, _,_) -> begin + match isTransparentUnion a.vtype with + None -> () + | Some fstfield -> + transparentUnionArgs := + (argidx, a.vtype) :: !transparentUnionArgs; + a.vtype <- fstfield.ftype; + end + | _ -> ()); + fixupArgumentTypes (argidx + 1) args' + in + let args = + match targs with + None -> None + | Some argl -> + fixupArgumentTypes 0 argl; + Some (List.map (fun a -> (a.vname, a.vtype, a.vattr)) argl) + in + let tres = + match unrollType bt with + TArray(t,lo,_,attr) -> turnArrayIntoPointer t lo attr + | _ -> bt + in + doDeclType (TFun (tres, args, isva', [])) acc d in doDeclType bt [] dt @@ -3816,15 +3899,15 @@ : (A.decl_type * chunk * exp) option = let res = ref None in let rec findArray = function - ARRAY (JUSTBASE, al, lo) when lo.expr_node != A.NOTHING -> - (* Try to compile the expression to a constant *) - let (_, se, e', _) = - doExp (ghost_local_env ghost) true lo (AExp (Some intType)) in - if isNotEmpty se || not (isConstant e') then begin - res := Some (se, e'); - PTR (al, JUSTBASE) - end else - ARRAY (JUSTBASE, al, lo) + ARRAY (JUSTBASE, al, lo) when lo.expr_node != A.NOTHING -> + (* Try to compile the expression to a constant *) + let (_, se, e', _) = + doExp (ghost_local_env ghost) true lo (AExp (Some intType)) in + if isNotEmpty se || not (isConstant e') then begin + res := Some (se, e'); + PTR (al, JUSTBASE) + end else + ARRAY (JUSTBASE, al, lo) | ARRAY (dt, al, lo) -> ARRAY (findArray dt, al, lo) | PTR (al, dt) -> PTR (al, findArray dt) | JUSTBASE -> JUSTBASE @@ -3839,11 +3922,12 @@ and doOnlyType ghost (specs: A.spec_elem list) (dt: A.decl_type) : typ = let bt',sto,inl,attrs = doSpecList ghost "" specs in if sto <> NoStorage || inl then - Cil.error "Storage or inline specifier in type only"; + Kernel.error ~current:true "Storage or inline specifier in type only"; let tres, nattr = doType ghost false AttrType bt' (A.PARENTYPE(attrs, dt, [])) in if nattr <> [] then - Cil.error "Name attributes in only_type: %a" d_attrlist nattr; + Kernel.error ~current:true + "Name attributes in only_type: %a" d_attrlist nattr; tres @@ -3861,8 +3945,8 @@ (nl: (A.name * A.expression option) list)) = (* Do the specifiers exactly once *) let sugg = match nl with - [] -> "" - | ((n, _, _, _), _) :: _ -> n + [] -> "" + | ((n, _, _, _), _) :: _ -> n in let bt, sto, inl, attrs = doSpecList ghost sugg s in (* Do the fields *) @@ -3870,30 +3954,34 @@ (((n,ndt,a,cloc) : A.name), (widtho : A.expression option)) : fieldinfo = if sto <> NoStorage || inl then - Cil.error "Storage or inline not allowed for fields"; + Kernel.error ~current:true "Storage or inline not allowed for fields"; let ftype, nattr = doType ghost false (AttrName false) bt (A.PARENTYPE(attrs, ndt, a)) in (* check for fields whose type is an undefined struct. This rules out circularity: struct C1 { struct C2 c2; }; //This line is now an error. struct C2 { struct C1 c1; int dummy; }; - *) + *) (match unrollType ftype with - TComp (ci',_,_) when not ci'.cdefined -> - Cil.error "Type of field %s is an undefined struct" n - | _ -> ()); + | TComp (ci',_,_) when not ci'.cdefined -> + Kernel.error ~current:true "Type of field %s is an undefined struct" n + | _ -> ()); let width = match widtho with None -> None | Some w -> begin - (match unrollType ftype with - TInt (_, _) -> () - | TEnum _ -> () - | _ -> Cil.error "Base type for bitfield is not an integer type"); - match isIntegerConstant ghost w with - Some n -> Some n - | None -> Cil.fatal "bitfield width is not an integer constant" - end + (match unrollType ftype with + | TInt (_, _) -> () + | TEnum _ -> () + | _ -> + Kernel.error ~current:true + "Base type for bitfield is not an integer type"); + match isIntegerConstant ghost w with + | None -> + Kernel.fatal ~current:true + "bitfield width is not an integer constant" + | Some n -> Some n + end in (* If the field is unnamed and its type is a structure of union type * then give it a distinguished name *) @@ -3901,8 +3989,8 @@ if n = missingFieldName then begin match unrollType ftype with TComp _ -> begin - incr annonCompFieldNameId; - annonCompFieldName ^ (string_of_int !annonCompFieldNameId) + incr anonCompFieldNameId; + anonCompFieldName ^ (string_of_int !anonCompFieldNameId) end | _ -> n end else @@ -3935,17 +4023,18 @@ (* This appears to be a multiply defined structure. This can happen from * a construct like "typedef struct foo { ... } A, B;". This is dangerous * because at the time B is processed some forward references in { ... } - * appear as backward references, which coild lead to circularity in + * appear as backward references, which could lead to circularity in * the type structure. We do a thourough check and then we reuse the type * for A *) let fieldsSig fs = List.map (fun f -> typeSig f.ftype) fs in if not (Cilutil.equals (fieldsSig comp.cfields) (fieldsSig flds)) then - ignore (error "%s seems to be multiply defined" (compFullName comp)) + Kernel.error ~current:true + "%s seems to be multiply defined" (compFullName comp) end else comp.cfields <- flds; (* ignore (E.log "makeComp: %s: %a\n" comp.cname d_attrlist a); *) - comp.cattr <- a; + comp.cattr <- add_packing_attributes comp a; let res = TComp (comp,empty_size_cache (), []) in (* This compinfo is defined, even if there are no fields *) comp.cdefined <- true; @@ -3965,6 +4054,8 @@ (* If we are casting to a union type then we have to treat this as a * constructor expression. This is to handle the gcc extension that allows * cast from a type of a field to the type of the union *) + (* However, it may just be casting of a whole union to its own type. We + * will resolve this later, when we'll convert casts to unions. *) let ie' = match unrollType typ, ie with TComp (c, _, _), A.SINGLE_INIT _ when not c.cstruct -> @@ -3980,11 +4071,11 @@ TComp (ci, _, _) -> List.map (function - A.SpecType (A.Tstruct ("", _, [])) -> - A.SpecType (A.Tstruct (ci.cname, None, [])) - | A.SpecType (A.Tunion ("", _, [])) -> - A.SpecType (A.Tunion (ci.cname, None, [])) - | s -> s) specs + A.SpecType (A.Tstruct ("", _, [])) -> + A.SpecType (A.Tstruct (ci.cname, None, [])) + | A.SpecType (A.Tunion ("", _, [])) -> + A.SpecType (A.Tunion (ci.cname, None, [])) + | s -> s) specs | _ -> specs in specs1, dt, ie' @@ -3993,15 +4084,16 @@ let loc = aexp.expr_loc in let _, c, e, _ = doExp (ghost_local_env ghost) true aexp (AExp None) in if not (isEmpty c) then - Cil.error "Constant expression %a has effects" d_exp e; + Kernel.error ~current:true "Constant expression %a has effects" d_exp e; match e.enode with - (* first, filter for those Const exps that are integers *) + (* first, filter for those Const exps that are integers *) | Const (CInt64 _ ) -> e | Const (CEnum _) -> e | Const (CChr i) -> new_exp ~loc (Const(charConstToInt i)) (* other Const expressions are not ok *) - | Const _ -> Cil.fatal "Expected integer constant and got %a" d_exp e + | Const _ -> + Kernel.fatal ~current:true "Expected integer constant and got %a" d_exp e (* now, anything else that 'doExp true' returned is ok (provided that it didn't yield side effects); this includes, in particular, @@ -4019,7 +4111,7 @@ match doExp (ghost_local_env ghost) true aexp (AExp None) with (_, c, e, _) when isEmpty c -> begin match isInteger (Cil.constFold true e) with - Some i64 -> Some (Int64.to_int i64) + Some i64 -> Some (My_bigint.to_int i64) | _ -> None end | _ -> None @@ -4047,13 +4139,14 @@ let processArrayFun e t = let loc = e.eloc in match e.enode, unrollType t with - (Lval(lv) | CastE(_, {enode = Lval lv})), TArray(tbase, _, _, a) -> - mkStartOfAndMark loc lv, TPtr(tbase, a) + | (Lval(lv) | CastE(_, {enode = Lval lv})), TArray(tbase, _, _, a) -> + mkStartOfAndMark loc lv, TPtr(tbase, a) | (Lval(lv) | CastE(_, {enode = Lval lv})), TFun _ -> - mkAddrOfAndMark loc lv, TPtr(t, []) + mkAddrOfAndMark loc lv, TPtr(t, []) | _, (TArray _ | TFun _) -> - Cil.fatal "Array or function expression is not lval: %a@\n" - d_plainexp e + Kernel.fatal ~current:true + "Array or function expression is not lval: %a@\n" + d_plainexp e | _ -> e, t in (* Before we return we call finishExp *) @@ -4061,302 +4154,314 @@ match newWhat with ADrop | AType -> - (reads, se, e, t) + (reads, se, e, t) | AExpLeaveArrayFun -> - (reads, se, e, t) - (* It is important that we do not do "processArrayFun" in - * this case. We exploit this when we process the typeOf construct *) + (reads, se, e, t) + (* It is important that we do not do "processArrayFun" in + * this case. We exploit this when we process the typeOf construct *) | AExp _ -> - let (e', t') = processArrayFun e t in - (* - ignore (E.log "finishExp: e'=%a, t'=%a\n" - d_exp e' d_type t'); - *) - (reads, se, e', t') + let (e', t') = processArrayFun e t in + (* + ignore (E.log "finishExp: e'=%a, t'=%a\n" + d_exp e' d_type t'); + *) + (reads, se, e', t') | ASet (is_real_write,lv, r, lvt) -> begin - (* See if the set was done already *) - match e.enode with - Lval(lv') when lv == lv' -> - (reads,se, e, t) (* if this is the case, the effects have also been - taken into account in the chunk. *) - | _ -> - let (e', t') = processArrayFun e t in - let (t'', e'') = castTo t' lvt e' in - (*log "finishExp: e = %a\n e'' = %a\n" d_plainexp e d_plainexp e'';*) - let writes = if is_real_write then [lv] else [] in - ([], (* the reads are incorporated in the chunk. *) - (remove_reads lv se) +++ - (mkStmtOneInstr ~ghost:local_env.is_ghost - (Set(lv, e'', CurrentLoc.get ())),[],writes,r @ reads), - e'', t'') + (* See if the set was done already *) + match e.enode with + Lval(lv') when lv == lv' -> + (reads,se, e, t) (* if this is the case, the effects have also been + taken into account in the chunk. *) + | _ -> + let (e', t') = processArrayFun e t in + let (t'', e'') = castTo t' lvt e' in + (*Kernel.debug "finishExp: e = %a\n e'' = %a\n" d_exp e d_exp e'';*) + let writes = if is_real_write then [lv] else [] in + ([], (* the reads are incorporated in the chunk. *) + (remove_reads lv se) +++ + (mkStmtOneInstr ~ghost:local_env.is_ghost + (Set(lv, e'', CurrentLoc.get ())), + writes,writes, + List.filter (fun x -> not (Cil.compareLval x lv)) r @ reads), + e'', t'') - end + end in - let result = try - match e.expr_node with - | A.PAREN _ -> Cil.fatal "stripParen" - | A.NOTHING when what = ADrop -> - finishExp [] (unspecified_chunk empty) (integer ~loc 0) intType - | A.NOTHING -> - let res = new_exp ~loc (Const(CStr "exp_nothing")) in - finishExp [] (unspecified_chunk empty) res (typeOf res) - - (* Do the potential lvalues first *) - | A.VARIABLE n -> begin - (* Look up in the environment *) - try - let envdata = H.find env n in - match envdata with - EnvVar vi, _ -> - let lval = var vi in - let reads = - if Lval.Set.mem lval local_env.authorized_reads + let result = + try + match e.expr_node with + | A.PAREN _ -> Kernel.fatal ~current:true "stripParen" + | A.NOTHING when what = ADrop -> + finishExp [] (unspecified_chunk empty) (integer ~loc 0) intType + | A.NOTHING -> + let res = new_exp ~loc (Const(CStr "exp_nothing")) in + finishExp [] (unspecified_chunk empty) res (typeOf res) + (* Do the potential lvalues first *) + | A.VARIABLE n -> begin + (* Look up in the environment *) + try + let envdata = H.find env n in + match envdata with + EnvVar vi, _ -> + let lval = var vi in + let reads = + if Lval.Set.mem lval local_env.authorized_reads then [] - else [ lval ] - in - (* if isconst && - not (isFunctionType vi.vtype) && - not (isArrayType vi.vtype)then + else [ lval ] + in + (* if isconst && + not (isFunctionType vi.vtype) && + not (isArrayType vi.vtype)then Cil.error "variable appears in constant"; *) - finishExp - reads (unspecified_chunk empty) - (new_exp ~loc (Lval lval)) vi.vtype - | EnvEnum item, _ -> - let typ = TEnum (item.eihost,[]) in - if Cil.theMachine.Cil.lowerConstants then - finishExp [] (unspecified_chunk empty) item.eival typ - else - finishExp [] - (unspecified_chunk empty) - (new_exp ~loc (Const (CEnum item))) - typ - | _ -> raise Not_found - with Not_found -> begin - if isOldStyleVarArgName n then - Cil.fatal "Cannot resolve variable %s. This could be a CIL bug due to the handling of old-style variable argument functions" n - else - Cil.fatal "Cannot resolve variable %s" n - end + finishExp + reads (unspecified_chunk empty) + (new_exp ~loc (Lval lval)) vi.vtype + | EnvEnum item, _ -> + let typ = Cil.typeOf item.eival in + Kernel.debug "Looking for %s got enum %s : %a of type %a" + n item.einame d_exp item.eival d_type typ; + if Cil.theMachine.Cil.lowerConstants then + finishExp [] (unspecified_chunk empty) item.eival typ + else + finishExp [] + (unspecified_chunk empty) + (new_exp ~loc (Const (CEnum item))) + typ + | _ -> raise Not_found + with Not_found -> begin + if isOldStyleVarArgName n then + Kernel.fatal ~current:true + "Cannot resolve variable %s. \ +This could be a CIL bug due to the handling of old-style variable argument \ +functions" + n + else + Kernel.fatal ~current:true "Cannot resolve variable %s" n + end end - | A.INDEX (e1, e2) -> begin - (* Recall that doExp turns arrays into StartOf pointers *) - let (r1, se1, e1', t1) = - doExp local_env false e1 (AExp None) in - let (r2,se2, e2', t2) = - doExp local_env false e2 (AExp None) in - let se = se1 @@ se2 in - let (e1'', t1, e2'', tresult) = - (* Either e1 or e2 can be the pointer *) - match unrollType t1, unrollType t2 with - TPtr(t1e,_), (TInt _|TEnum _) -> e1', t1, e2', t1e - | (TInt _|TEnum _), TPtr(t2e,_) -> e2', t2, e1', t2e - | _ -> - Cil.fatal - "Expecting a pointer type in index:@\n t1=%a@\nt2=%a" - d_plaintype t1 d_plaintype t2 - in - (* We have to distinguish the construction based on the type of e1'' *) - let res = - match e1''.enode with - StartOf array -> (* A real array indexing operation *) - addOffsetLval (Index(e2'', NoOffset)) array - | _ -> (* Turn into *(e1 + e2) *) - mkMem - (new_exp ~loc:e1''.eloc (BinOp(IndexPI, e1'', e2'', t1))) - NoOffset - in - (* Do some optimization of StartOf *) - let reads = + | A.INDEX (e1, e2) -> begin + (* Recall that doExp turns arrays into StartOf pointers *) + let (r1, se1, e1', t1) = + doExp local_env false e1 (AExp None) in + let (r2,se2, e2', t2) = + doExp local_env false e2 (AExp None) in + let se = se1 @@ se2 in + let (e1'', t1, e2'', tresult) = + (* Either e1 or e2 can be the pointer *) + match unrollType t1, unrollType t2 with + TPtr(t1e,_), (TInt _|TEnum _) -> e1', t1, e2', t1e + | (TInt _|TEnum _), TPtr(t2e,_) -> e2', t2, e1', t2e + | _ -> + Kernel.fatal ~current:true + "Expecting a pointer type in index:@\n t1=%a@\nt2=%a" + d_plaintype t1 d_plaintype t2 + in + (* We have to distinguish the construction based on the type of e1'' *) + let res = + match e1''.enode with + StartOf array -> (* A real array indexing operation *) + addOffsetLval (Index(e2'', NoOffset)) array + | _ -> (* Turn into *(e1 + e2) *) + mkMem + (new_exp ~loc:e1''.eloc (BinOp(IndexPI, e1'', e2'', t1))) + NoOffset + in + (* Do some optimization of StartOf *) + let reads = let l = r1 @ r2 in - if Lval.Set.mem res local_env.authorized_reads + if Lval.Set.mem res local_env.authorized_reads then l - else res :: l - in - finishExp reads se (new_exp ~loc (Lval res)) tresult + else res :: l + in + finishExp reads se (new_exp ~loc (Lval res)) tresult end - | A.UNARY (A.MEMOF, e) -> - if asconst then - (Cil.warning "MEMOF in constant"); - let (r,se, e', t) = doExp local_env false e (AExp None) in - let tresult = - match unrollType t with - | TPtr(te, _) -> te - | _ -> Cil.fatal "Expecting a pointer type in *. Got %a." - d_plaintype t - in - let res = mkMem e' NoOffset in - let reads = - if Lval.Set.mem res local_env.authorized_reads + | A.UNARY (A.MEMOF, e) -> + if asconst then + Kernel.warning ~current:true "MEMOF in constant"; + let (r,se, e', t) = doExp local_env false e (AExp None) in + let tresult = + match unrollType t with + | TPtr(te, _) -> te + | _ -> + Kernel.fatal ~current:true + "Expecting a pointer type in *. Got %a." + d_plaintype t + in + let res = mkMem e' NoOffset in + let reads = + if Lval.Set.mem res local_env.authorized_reads then r else res :: r in - finishExp reads se (new_exp ~loc (Lval res)) tresult + finishExp reads se (new_exp ~loc (Lval res)) tresult - (* e.str = (& e + off(str)). If e = (be + beoff) then e.str = (be - * + beoff + off(str)) *) - | A.MEMBEROF (e, str) -> - (* member of is actually allowed if we only take the address *) - (* if isconst then - Cil.error "MEMBEROF in constant"; *) - let (r,se, e', t') = doExp local_env false e (AExp None) in - let lv = - match e'.enode with - Lval x -> x - | CastE(_, { enode = Lval x}) -> x - | _ -> Cil.fatal "Expected an lval in MEMBEROF (field %s)" str - in - (* We're not reading the whole lval, just a chunk of it. *) - let r = - List.filter (fun x -> not (Lval.equal x lv)) r - in - let field_offset = - match unrollType t' with - TComp (comp, _, _) -> findField str comp.cfields - | _ -> Cil.fatal "expecting a struct with field %s" str - in - let lv' = addOffsetLval field_offset lv in + (* e.str = (& e + off(str)). If e = (be + beoff) then e.str = (be + * + beoff + off(str)) *) + | A.MEMBEROF (e, str) -> + (* member of is actually allowed if we only take the address *) + (* if isconst then Cil.error "MEMBEROF in constant"; *) + let (r,se, e', t') = doExp local_env false e (AExp None) in + let lv = + match e'.enode with + Lval x -> x + | CastE(_, { enode = Lval x}) -> x + | _ -> + Kernel.fatal ~current:true + "Expected an lval in MEMBEROF (field %s)" + str + in + (* We're not reading the whole lval, just a chunk of it. *) + let r = + List.filter (fun x -> not (Lval.equal x lv)) r + in + let field_offset = + match unrollType t' with + TComp (comp, _, _) -> findField str comp.cfields + | _ -> + Kernel.fatal ~current:true "expecting a struct with field %s" str + in + let lv' = addOffsetLval field_offset lv in let field_type = typeOf (dummy_exp (Lval lv')) in - let reads = - if Lval.Set.mem lv' local_env.authorized_reads + let reads = + if Lval.Set.mem lv' local_env.authorized_reads then r else lv':: r in - finishExp reads se (new_exp ~loc (Lval lv')) field_type + finishExp reads se (new_exp ~loc (Lval lv')) field_type - (* e->str = * (e + off(str)) *) - | A.MEMBEROFPTR (e, str) -> - if asconst then - (Cil.warning "MEMBEROFPTR in constant"); - let (r,se, e', t') = doExp local_env false e (AExp None) in - let pointedt = - match unrollType t' with - TPtr(t1, _) -> t1 - | TArray(t1,_,_,_) -> t1 - | _ -> Cil.fatal "expecting a pointer to a struct" - in - let field_offset = - match unrollType pointedt with - TComp (comp, _, _) -> findField str comp.cfields - | x -> - Cil.fatal - "expecting a struct with field %s. Found %a. t1 is %a" - str d_type x d_type t' - in + (* e->str = * (e + off(str)) *) + | A.MEMBEROFPTR (e, str) -> + if asconst then Kernel.warning ~current:true "MEMBEROFPTR in constant"; + let (r,se, e', t') = doExp local_env false e (AExp None) in + let pointedt = match unrollType t' with + | TPtr(t1, _) -> t1 + | TArray(t1,_,_,_) -> t1 + | _ -> Kernel.fatal ~current:true "expecting a pointer to a struct" + in + let field_offset = match unrollType pointedt with + | TComp (comp, _, _) -> findField str comp.cfields + | x -> + Kernel.fatal ~current:true + "expecting a struct with field %s. Found %a. t1 is %a" + str d_type x d_type t' + in let lv' = mkMem e' field_offset in let field_type = typeOf (dummy_exp (Lval lv')) in - let reads = - if Lval.Set.mem lv' local_env.authorized_reads + let reads = + if Lval.Set.mem lv' local_env.authorized_reads then r else lv' :: r - in - finishExp reads se (new_exp ~loc (Lval lv')) field_type + in + finishExp reads se (new_exp ~loc (Lval lv')) field_type - | A.CONSTANT ct -> begin - let hasSuffix str = - let l = String.length str in - fun s -> - let ls = String.length s in - l >= ls && s = String.uppercase (String.sub str (l - ls) ls) - in - match ct with - A.CONST_INT str -> begin - let res = parseInt ~loc str in - finishExp [] (unspecified_chunk empty) res (typeOf res) - end + | A.CONSTANT ct -> begin + let hasSuffix str = + let l = String.length str in + fun s -> + let ls = String.length s in + l >= ls && s = String.uppercase (String.sub str (l - ls) ls) + in + match ct with + A.CONST_INT str -> begin + let res = parseInt ~loc str in + finishExp [] (unspecified_chunk empty) res (typeOf res) + end - | A.CONST_WSTRING (ws: int64 list) -> - let res = - new_exp ~loc - (Const(CWStr ((* intlist_to_wstring *) ws))) - in - finishExp [] (unspecified_chunk empty) res (typeOf res) + | A.CONST_WSTRING (ws: int64 list) -> + let res = + new_exp ~loc + (Const(CWStr ((* intlist_to_wstring *) ws))) + in + finishExp [] (unspecified_chunk empty) res (typeOf res) - | A.CONST_STRING s -> - (* Maybe we burried __FUNCTION__ in there *) - let s' = - try - let start = String.index s (Char.chr 0) in - let l = String.length s in - let tofind = (String.make 1 (Char.chr 0)) ^ "__FUNCTION__" in - let past = start + String.length tofind in - if past <= l && - String.sub s start (String.length tofind) = tofind then - (if start > 0 then String.sub s 0 start else "") ^ - !currentFunctionFDEC.svar.vname ^ - (if past < l then String.sub s past (l - past) else "") - else - s - with Not_found -> s - in - let res = new_exp ~loc (Const(CStr s')) in - finishExp [] (unspecified_chunk empty) res (typeOf res) + | A.CONST_STRING s -> + (* Maybe we burried __FUNCTION__ in there *) + let s' = + try + let start = String.index s (Char.chr 0) in + let l = String.length s in + let tofind = (String.make 1 (Char.chr 0)) ^ "__FUNCTION__" in + let past = start + String.length tofind in + if past <= l && + String.sub s start (String.length tofind) = tofind then + (if start > 0 then String.sub s 0 start else "") ^ + !currentFunctionFDEC.svar.vname ^ + (if past < l then String.sub s past (l - past) else "") + else + s + with Not_found -> s + in + let res = new_exp ~loc (Const(CStr s')) in + finishExp [] (unspecified_chunk empty) res (typeOf res) - | A.CONST_CHAR char_list -> - let a, b = (interpret_character_constant char_list) in - finishExp [] (unspecified_chunk empty) (new_exp ~loc (Const a)) b - - | A.CONST_WCHAR char_list -> - (* matth: I can't see a reason for a list of more than one char - * here, since the kinteger64 below will take only the lower 16 - * bits of value. ('abc' makes sense, because CHAR constants have - * type int, and so more than one char may be needed to represent - * the value. But L'abc' has type wchar, and so is equivalent to - * L'c'). But gcc allows L'abc', so I'll leave this here in case - * I'm missing some architecture dependent behavior. *) - let value = reduce_multichar theMachine.wcharType char_list in - let result = kinteger64 ~loc theMachine.wcharKind value in - finishExp [] (unspecified_chunk empty) result (typeOf result) - - | A.CONST_FLOAT str -> begin - (* Maybe it ends in U or UL. Strip those *) - let l = String.length str in - let hasSuffix = hasSuffix str in - let baseint, kind = - if hasSuffix "L" then - String.sub str 0 (l - 1), FLongDouble - else if hasSuffix "F" then - String.sub str 0 (l - 1), FFloat - else if hasSuffix "D" then - String.sub str 0 (l - 1), FDouble - else - str, FDouble - in - try - finishExp [] (unspecified_chunk empty) - (new_exp ~loc - (Const(CReal(float_of_string baseint, kind, Some str)))) - (TFloat(kind,[])) - with Failure s -> begin - Cil.error "float_of_string %s (%s)\n" str s; - let res = new_exp ~loc (Const(CStr "booo CONS_FLOAT")) in - finishExp [] (unspecified_chunk empty) res (typeOf res) - end - end + | A.CONST_CHAR char_list -> + let a, b = (interpret_character_constant char_list) in + finishExp [] (unspecified_chunk empty) (new_exp ~loc (Const a)) b + + | A.CONST_WCHAR char_list -> + (* matth: I can't see a reason for a list of more than one char + * here, since the kinteger64 below will take only the lower 16 + * bits of value. ('abc' makes sense, because CHAR constants have + * type int, and so more than one char may be needed to represent + * the value. But L'abc' has type wchar, and so is equivalent to + * L'c'). But gcc allows L'abc', so I'll leave this here in case + * I'm missing some architecture dependent behavior. *) + let value = reduce_multichar theMachine.wcharType char_list in + let result = kinteger64 ~loc theMachine.wcharKind + (My_bigint.of_int64 value) + in + finishExp [] (unspecified_chunk empty) result (typeOf result) + + | A.CONST_FLOAT str -> begin + (* Maybe it ends in U or UL. Strip those *) + let l = String.length str in + let hasSuffix = hasSuffix str in + let baseint, kind = + if hasSuffix "L" then + String.sub str 0 (l - 1), FLongDouble + else if hasSuffix "F" then + String.sub str 0 (l - 1), FFloat + else if hasSuffix "D" then + String.sub str 0 (l - 1), FDouble + else + str, FDouble + in + try + finishExp [] (unspecified_chunk empty) + (new_exp ~loc + (Const(CReal(float_of_string baseint, kind, Some str)))) + (TFloat(kind,[])) + with Failure s -> begin + Kernel.error ~current:true "float_of_string %s (%s)\n" str s; + let res = new_exp ~loc (Const(CStr "booo CONS_FLOAT")) in + finishExp [] (unspecified_chunk empty) res (typeOf res) + end + end end - | A.TYPE_SIZEOF (bt, dt) -> - let typ = doOnlyType local_env.is_ghost bt dt in - finishExp [] (unspecified_chunk empty) (new_exp ~loc (SizeOf(typ))) + | A.TYPE_SIZEOF (bt, dt) -> + let typ = doOnlyType local_env.is_ghost bt dt in + finishExp [] (unspecified_chunk empty) (new_exp ~loc (SizeOf(typ))) theMachine.typeOfSizeOf - (* Intercept the sizeof("string") *) - | A.EXPR_SIZEOF ({ expr_node = A.CONSTANT (A.CONST_STRING _)} as e) -> - begin - (* Process the string first *) - match doExp local_env asconst e (AExp None) with - _, _, {enode = Const(CStr s)}, _ -> - finishExp [] (unspecified_chunk empty) - (new_exp ~loc (SizeOfStr s)) - theMachine.typeOfSizeOf - | _ -> Cil.abort "cabs2cil: sizeOfStr" - end + (* Intercept the sizeof("string") *) + | A.EXPR_SIZEOF ({ expr_node = A.CONSTANT (A.CONST_STRING _)} as e) -> + begin + (* Process the string first *) + match doExp local_env asconst e (AExp None) with + _, _, {enode = Const(CStr s)}, _ -> + finishExp [] (unspecified_chunk empty) + (new_exp ~loc (SizeOfStr s)) + theMachine.typeOfSizeOf + | _ -> Kernel.abort ~current:true "cabs2cil: sizeOfStr" + end - | A.EXPR_SIZEOF e -> - (* Allow non-constants in sizeof *) - (* Do not convert arrays and functions into pointers. *) - let (_, se, e', _) = - doExp local_env false e AExpLeaveArrayFun in + | A.EXPR_SIZEOF e -> + (* Allow non-constants in sizeof *) + (* Do not convert arrays and functions into pointers. *) + let (_, se, e', _) = + doExp local_env false e AExpLeaveArrayFun in (* ignore (E.log "sizeof: %a e'=%a, t=%a\n" d_loc !currentLoc d_plainexp e' d_type t); @@ -4365,7 +4470,8 @@ * drop the potential side-effects *) let scope_chunk = if isNotEmpty se then begin - Cil.warning "Warning: Dropping side-effect in sizeof"; + Kernel.warning ~current:true + "Warning: Dropping side-effect in sizeof"; IgnoreSideEffectHook.apply (e, e'); let vars = List.filter (fun x -> Cil.appears_in_expr x e') se.locals @@ -4399,7 +4505,8 @@ (* !!!! The book says that the expression is not evaluated, so we * drop the potential side-effects *) if isNotEmpty se then begin - Cil.warning "Warning: Dropping side-effect in sizeof"; + Kernel.warning ~current:true + "Warning: Dropping side-effect in sizeof"; IgnoreSideEffectHook.apply (e, e') end; let e'' = @@ -4435,7 +4542,7 @@ A.SINGLE_INIT e -> doExp local_env asconst e what', true - | A.NO_INIT -> Cil.fatal "missing expression in cast" + | A.NO_INIT -> Kernel.fatal ~current:true "missing expression in cast" | A.COMPOUND_INIT _ -> begin (* Pretend that we are declaring and initializing a brand new @@ -4500,7 +4607,8 @@ match e'.enode with | Const(CInt64(i, ik, repr)) -> let repr = Extlib.opt_map (fun s -> "-" ^ s) repr in - kinteger64_repr ~loc ik (Int64.neg i) repr + kinteger64_repr ~loc ik + (My_bigint.neg i) repr | _ -> new_exp ~loc (UnOp(Neg, makeCastT e' t tres, tres)) in finishExp r se e'' tres @@ -4508,7 +4616,7 @@ if isArithmeticType t then finishExp r se (new_exp ~loc:e'.eloc (UnOp(Neg,e',t))) t else - Cil.fatal "Unary - on a non-arithmetic type" + Kernel.fatal ~current:true "Unary - on a non-arithmetic type" | A.UNARY(A.BNOT, e) -> let (r, se, e', t) = doExp local_env asconst e (AExp None) in @@ -4517,7 +4625,7 @@ let e'' = new_exp ~loc (UnOp(BNot, makeCastT e' t tres, tres)) in finishExp r se e'' tres else - Cil.fatal "Unary ~ on a non-integral type" + Kernel.fatal ~current:true "Unary ~ on a non-integral type" | A.UNARY(A.PLUS, e) -> doExp local_env asconst e what @@ -4551,9 +4659,11 @@ * the address of the last real argument *) if theMachine.msvcMode then begin let rec getLast = function - [] -> Cil.fatal - "old-style variable argument function without real arguments" - | [a] -> a + | [] -> + Kernel.fatal ~current:true + "old-style variable argument function without real \ +arguments" + | [ a ] -> a | _ :: rest -> getLast rest in let last = getLast !currentFunctionFDEC.sformals in @@ -4588,9 +4698,11 @@ what end - | (A.VARIABLE _ | A.UNARY (A.MEMOF, _) | (* Regular lvalues *) - A.INDEX _ | A.MEMBEROF _ | A.MEMBEROFPTR _ | - A.CAST (_, A.COMPOUND_INIT _)) -> begin + | A.VARIABLE _ | A.UNARY (A.MEMOF, _) (* Regular lvalues *) + | A.CONSTANT (A.CONST_STRING _) | A.CONSTANT (A.CONST_WSTRING _) + | A.INDEX _ | A.MEMBEROF _ | A.MEMBEROFPTR _ + | A.CAST (_, A.COMPOUND_INIT _) -> + begin let (r, se, e', t) = doExp local_env false e (AExp None) in (* ignore (E.log "ADDROF on %a : %a\n" d_plainexp e' d_plaintype t); *) @@ -4620,15 +4732,20 @@ in finishExp reads se (mkAddrOfAndMark loc lv) tres + | Const (CStr _ | CWStr _) -> + (* string to array *) + finishExp r se e' (TPtr(t, [])) + (* Function names are converted into pointers to the function. * Taking the address-of again does not change things *) | AddrOf (Var v, NoOffset) when isFunctionType v.vtype -> finishExp r se e' t - | _ -> Cil.fatal "Expected lval for ADDROF. Got %a@" + | _ -> + Kernel.fatal ~current:true "Expected lval for ADDROF. Got %a" d_plainexp e' end - | _ -> Cil.fatal "Unexpected operand for addrof" + | _ -> Kernel.fatal ~current:true "Unexpected operand for addrof" end | A.UNARY((A.PREINCR|A.PREDECR) as uop, e) -> begin match e.expr_node with @@ -4654,7 +4771,7 @@ A.CAST _ (* A GCC extension *)) -> begin let uop' = if uop = A.PREINCR then PlusA else MinusA in if asconst then - (Cil.warning "PREINCR or PREDECR in constant"); + Kernel.warning ~current:true "PREINCR or PREDECR in constant"; let (r, se, e', t) = doExp local_env false e (AExp None) in let lv = match e'.enode with @@ -4663,14 +4780,14 @@ (* A GCC extension. The operation is * done at the cast type. The result * is also of the cast type *) - | _ -> Cil.fatal "Expected lval for ++ or --" + | _ -> Kernel.fatal ~current:true "Expected lval for ++ or --" in let se' = remove_reads lv se in let r' = List.filter (fun x -> not (Lval.equal x lv)) r in - let tresult, result = - doBinOp loc uop' e' t (one ~loc:e'.eloc) intType + let tresult, result = + doBinOp loc uop' e' t (one ~loc:e'.eloc) intType in finishExp [] (se' +++ @@ -4678,9 +4795,10 @@ (Set(lv, makeCastT result tresult t, CurrentLoc.get ())),[],[lv],r')) e' - tresult (* Should this be t instead ??? *) + t end - | _ -> Cil.fatal "Unexpected operand for prefix -- or ++" + | _ -> + Kernel.fatal ~current:true "Unexpected operand for prefix -- or ++" end | A.UNARY((A.POSINCR|A.POSDECR) as uop, e) -> begin @@ -4707,7 +4825,7 @@ A.INDEX _ | A.MEMBEROF _ | A.MEMBEROFPTR _ | A.CAST _ (* A GCC extension *) ) -> begin if asconst then - (Cil.warning "POSTINCR or POSTDECR in constant"); + Kernel.warning ~current:true "POSTINCR or POSTDECR in constant"; (* If we do not drop the result then we must save the value *) let uop' = if uop = A.POSINCR then PlusA else MinusA in let (r,se, e', t) = doExp local_env false e (AExp None) in @@ -4719,15 +4837,15 @@ * be be done at the cast type. The * result of this is also of the cast * type *) - | _ -> Cil.fatal "Expected lval for ++ or --" + | _ -> Kernel.fatal ~current:true "Expected lval for ++ or --" in let se' = remove_reads lv se in let r' = List.filter (fun x -> not (Lval.equal x lv)) r in - let tresult, opresult = + let tresult, opresult = doBinOp loc uop' e' t (one ~loc:e'.eloc) - intType + intType in let reads, se', result = if what <> ADrop && what <> AType then @@ -4749,16 +4867,17 @@ [],se, e' in finishExp reads - (se' +++ + (se' +++ (mkStmtOneInstr ~ghost:local_env.is_ghost (Set(lv, makeCastT opresult tresult (typeOfLval lv), CurrentLoc.get ())), [],[lv], r')) result - tresult (* Should this be t instead ??? *) + t end - | _ -> Cil.fatal "Unexpected operand for suffix ++ or --" + | _ -> + Kernel.fatal ~current:true "Unexpected operand for suffix ++ or --" end | A.BINARY(A.ASSIGN, e1, e2) -> begin @@ -4798,37 +4917,39 @@ (cabs_exp loc (A.BINARY(A.ASSIGN,e1,e2))) what | (A.VARIABLE _ | A.UNARY (A.MEMOF, _) | (* Regular lvalues *) A.INDEX _ | A.MEMBEROF _ | A.MEMBEROFPTR _ ) -> begin - if asconst then Cil.warning "ASSIGN in constant"; - let se0 = unspecified_chunk empty in - let (r1,se1, e1', lvt) = doExp local_env false e1 (AExp None) in - let lv = - match e1'.enode with - Lval x -> x - | _ -> Cil.fatal "Expected lval for assignment. Got %a" - d_plainexp e1' - in - let se1' = remove_reads lv se1 in - let r1' = - List.filter (fun x -> not (Lval.equal x lv)) r1 - in - let local_env = - { local_env with - authorized_reads = - Lval.Set.add lv local_env.authorized_reads } - in - (*[BM]: is this useful? - let (_, _, _) = doExp ghost false e2 (ASet(lv, lvt)) in*) - (* Catch the case of an lval that might depend on itself, - e.g. p[p[0]] when p[0] == 0. We need to use a temporary - here if the result of the expression will be used: - tmp := e2; lv := tmp; use tmp as the result - Test: small1/assign.c *) - let needsTemp = match what, lv with + if asconst then Kernel.warning ~current:true "ASSIGN in constant"; + let se0 = unspecified_chunk empty in + let (r1,se1, e1', lvt) = doExp local_env false e1 (AExp None) in + let lv = + match e1'.enode with + | Lval x -> x + | _ -> + Kernel.fatal ~current:true + "Expected lval for assignment. Got %a" + d_plainexp e1' + in + let se1' = remove_reads lv se1 in + let r1' = List.filter (fun x -> not (Lval.equal x lv)) r1 in + let local_env = + { local_env with + authorized_reads = + Lval.Set.add lv local_env.authorized_reads } + in + (*[BM]: is this useful? + let (_, _, _) = doExp ghost false e2 (ASet(lv, lvt)) in*) + (* Catch the case of an lval that might depend on itself, + e.g. p[p[0]] when p[0] == 0. We need to use a temporary + here if the result of the expression will be used: + tmp := e2; lv := tmp; use tmp as the result + Test: small1/assign.c *) + let needsTemp = + not (isBitfield lv) && (* PC: BTS 933, 968 *) + match what, lv with (ADrop|AType), _ -> false - | _, (Mem e, off) -> not (isConstant e) - || not (isConstantOffset off) + | _, (Mem e, off) -> + not (isConstant e) || not (isConstantOffset off) | _, (Var _, off) -> not (isConstantOffset off) - in + in let r1, tmplv, se3 = if needsTemp then let descr = Some (Pretty_utils.sfprintf "%a" dd_lval lv) in @@ -4845,11 +4966,12 @@ let (r2,se2, _, _) = doExp local_env false e2 (ASet(not needsTemp,tmplv, r1, lvt)) in + (* Format.eprintf "chunk for assigns is %a@." d_chunk se2; *) (* r1 is read in the assignment part itself *) finishExp r2 (((se0 @@ se1') @@ se2) @@ se3) (new_exp ~loc (Lval tmplv)) lvt end - | _ -> Cil.fatal "Invalid left operand for ASSIGN" + | _ -> Kernel.fatal ~current:true "Invalid left operand for ASSIGN" end | A.BINARY((A.ADD|A.SUB|A.MUL|A.DIV|A.MOD|A.BAND|A.BOR|A.XOR| A.SHL|A.SHR|A.EQ|A.NE|A.LT|A.GT|A.GE|A.LE) as bop, @@ -4890,7 +5012,7 @@ A.INDEX _ | A.MEMBEROF _ | A.MEMBEROFPTR _ | A.CAST _ (* GCC extension *) ) -> begin if asconst then - (Cil.warning "op_ASSIGN in constant"); + Kernel.warning ~current:true "op_ASSIGN in constant"; let bop' = match bop with A.ADD_ASSIGN -> PlusA | A.SUB_ASSIGN -> MinusA @@ -4902,7 +5024,7 @@ | A.XOR_ASSIGN -> BXor | A.SHL_ASSIGN -> Shiftlt | A.SHR_ASSIGN -> Shiftrt - | _ -> Cil.fatal "binary +=" + | _ -> Kernel.fatal ~current:true "binary +=" in let (r1,se1, e1', t1) = doExp local_env false e1 (AExp None) in let lv1 = @@ -4911,12 +5033,12 @@ | CastE (_, {enode = Lval x}) -> x (* GCC extension. The operation and * the result are at the cast type *) - | _ -> Cil.fatal "Expected lval for assignment with arith" + | _ -> + Kernel.fatal ~current:true + "Expected lval for assignment with arith" in let se1' = remove_reads lv1 se1 in - let r1' = - List.filter (fun x -> not (Lval.equal x lv1)) r1 - in + let r1' = List.filter (fun x -> not (Lval.equal x lv1)) r1 in let local_env = { local_env with authorized_reads = @@ -4938,7 +5060,9 @@ e1' t1 end - | _ -> Cil.fatal "Unexpected left operand for assignment with arith" + | _ -> + Kernel.fatal ~current:true + "Unexpected left operand for assignment with arith" end | A.BINARY((A.AND|A.OR), _, _) | A.UNARY(A.NOT, _) -> begin @@ -4946,8 +5070,8 @@ (* We must normalize the result to 0 or 1 *) match ce with CEExp (se, ({enode = Const _;eloc=loc} as c)) -> - finishExp [] se - (if isConstTrue c then one ~loc else zero ~loc) + finishExp [] se + (if isConstTrue c then one ~loc else zero ~loc) intType | CEExp (se, ({enode = UnOp(LNot, _, _)} as e)) -> (* already normalized to 0 or 1 *) @@ -4956,7 +5080,7 @@ let e' = let te = typeOf e in let _, zte = castTo intType te (zero ~loc:e.eloc) in - new_exp ~loc (BinOp(Ne, e, zte, te)) + new_exp ~loc (BinOp(Ne, e, zte, intType)) in finishExp [] se e' intType | _ -> @@ -4979,7 +5103,7 @@ end | A.CALL(f, args) -> - if asconst then Cil.warning "CALL in constant"; + if asconst then Kernel.warning ~current:true "CALL in constant"; let (rf,sf, f', ft') = match f.expr_node with (* Treat the VARIABLE case separate because we might be calling a @@ -5000,7 +5124,8 @@ new_exp ~loc:f.expr_loc (Lval(var vi)), vi.vtype) (* Found. Do not use finishExp. Simulate what = AExp None *) with Not_found -> begin - Cil.warnOpt "Calling function %s without prototype." n ; + Kernel.debug ~level:3 + "Calling function %s without prototype." n ; let ftype = TFun(intType, None, false, [Attr("missingproto",[])]) in (* Add a prototype to the environment *) @@ -5036,12 +5161,14 @@ in (rt,at,isvar, f'') | x -> - Cil.fatal "Unexpected type of the called function %a: %a" - d_exp f' d_type x + Kernel.fatal ~current:true + "Unexpected type of the called function %a: %a" + d_exp f' d_type x end | x -> - Cil.fatal "Unexpected type of the called function %a: %a" - d_exp f' d_type x + Kernel.fatal ~current:true + "Unexpected type of the called function %a: %a" + d_exp f' d_type x in let argTypesList = argsToList argTypes in (* Drop certain qualifiers from the result type *) @@ -5056,14 +5183,12 @@ | _ -> false in - (** If the "--forceRLArgEval" flag was used, make sure - we evaluate args right-to-left. - Added by Nathan Cooprider. **) + let force_rlarg_eval = ForceRLArgEval.get () in + (** If [force_rlarg_eval], make sure we evaluate args right-to-left. *) let force_right_to_left_evaluation (r,c, e, t) = (* If chunk is empty then it is not already evaluated *) (* constants don't need to be pulled out *) - if ((!forceRLArgEval && (not (isConstant e)))) - && (not isSpecialBuiltin) + if force_rlarg_eval && (not (isConstant e)) && not isSpecialBuiltin then (* create a temporary *) let tmp = @@ -5073,24 +5198,26 @@ let c = local_var_chunk c tmp in (* create an instruction to give the e to the temporary *) let i = mkStmtOneInstr ~ghost:local_env.is_ghost - (Set(var tmp, e, loc)) in + (Set(var tmp, e, loc)) + in (* add the instruction to the chunk *) (* change the expression to be the temporary *) (c +++ (i,[],[],[]), new_exp ~loc (Lval(var tmp)), t) else - (add_reads r c, e, t) + (add_reads loc r c, e, t) in let init_chunk = - if !forceRLArgEval then empty else unspecified_chunk empty + if force_rlarg_eval then empty else unspecified_chunk empty in (* Do the arguments. In REVERSE order !!! Both GCC and MSVC do this *) let rec loopArgs = function | ([], []) -> (init_chunk, []) | _, [] -> - if not isSpecialBuiltin then - Cil.error "Too few arguments in call to %a." d_exp f' ; - (init_chunk, []) + if not isSpecialBuiltin then + Kernel.error ~current:true + "Too few arguments in call to %a." d_exp f' ; + (init_chunk, []) | ((_, at, _) :: atypes, a :: args) -> let (ss, args') = loopArgs (atypes, args) in @@ -5106,7 +5233,8 @@ | ([], args) -> (* No more types *) if not isvar && argTypes != None && not isSpecialBuiltin then (* Do not give a warning for functions without a prototype*) - Cil.error "Too many arguments in call to %a" d_exp f'; + Kernel.error ~current:true + "Too many arguments in call to %a" d_exp f'; let rec loop = function [] -> (init_chunk, []) | a :: args -> @@ -5182,7 +5310,7 @@ pis__builtin_va_arg := true; end | _ -> - (Cil.warning "Invalid call to %s\n" fv.vname); + Kernel.warning ~current:true "Invalid call to %s\n" fv.vname; end else if fv.vname = "__builtin_stdarg_start" || fv.vname = "__builtin_va_start" then begin match !pargs with @@ -5194,16 +5322,16 @@ | _ -> false in if not isOk then - (Cil.warning - "The second argument in call to %s \ - should be the last formal argument" fv.vname); + Kernel.warning ~current:true + "The second argument in call to %s \ + should be the last formal argument" fv.vname; (* Check that "lastv" is indeed the last variable in the * prototype and then drop it *) pargs := [ marker ] end | _ -> - (Cil.warning "Invalid call to %s\n" fv.vname); + Kernel.warning ~current:true "Invalid call to %s\n" fv.vname; (* We have to turn uses of __builtin_varargs_start into uses * of __builtin_stdarg_start (because we have dropped the @@ -5214,8 +5342,9 @@ let v, _ = try lookupGlobalVar "__builtin_stdarg_start" with Not_found -> - Cil.abort "Cannot find __builtin_stdarg_start \ - to replace %s" fv.vname + Kernel.abort ~current:true + "Cannot find __builtin_stdarg_start to replace %s" + fv.vname in pf := new_exp ~loc (Lval (var v)) end else if fv.vname = "__builtin_next_arg" then begin @@ -5228,14 +5357,14 @@ | _ -> false in if not isOk then - (Cil.warning - "The argument in call to %s should be \ - the last formal argument\n" fv.vname); + Kernel.warning ~current:true + "The argument in call to %s should be \ + the last formal argument\n" fv.vname; pargs := [ ] end | _ -> - (Cil.warning "Invalid call to %s\n" fv.vname); + Kernel.warning ~current:true "Invalid call to %s\n" fv.vname; end else if fv.vname = "__builtin_constant_p" then begin (* Drop the side-effects *) prechunk := empty; @@ -5253,7 +5382,8 @@ prestype := intType end | _ -> - (Cil.warning "Invalid call to builtin_constant_p")); + Kernel.warning ~current:true + "Invalid call to builtin_constant_p"); end end | _ -> ()); @@ -5262,14 +5392,14 @@ (* Now we must finish the call *) if !piscall then begin let addCall ?(is_real_var=true) calldest res t = - let my_write = + let my_write, chunk = match calldest with - None -> [] - | Some c when is_real_var -> [c] - | Some _ -> [] + None -> [], !prechunk + | Some c when is_real_var -> [c], remove_reads c !prechunk + | Some _ -> [], !prechunk in prechunk := - !prechunk +++ + chunk +++ (mkStmtOneInstr ~ghost:local_env.is_ghost (Call(calldest,!pf,!pargs,loc)), [],my_write, rf); @@ -5281,26 +5411,26 @@ | AType -> prestype := resType' | ASet(is_real_var, lv, _, vtype) when !pis__builtin_va_arg -> (* Make an exception here for __builtin_va_arg *) - addCall + addCall ~is_real_var - None - (new_exp ~loc:e.expr_loc (Lval(lv))) + None + (new_exp ~loc:e.expr_loc (Lval(lv))) vtype - | ASet(is_real_var, lv, _, vtype) when !doCollapseCallCast || - (Cilutil.equals (typeSig vtype) (typeSig resType')) + | ASet(is_real_var, lv, _, vtype) + when DoCollapseCallCast.get () || + Cilutil.equals (typeSig vtype) (typeSig resType') -> (* We can assign the result directly to lv *) - addCall + addCall ~is_real_var - (Some lv) - (new_exp ~loc:e.expr_loc (Lval(lv))) + (Some lv) + (new_exp ~loc:e.expr_loc (Lval(lv))) vtype | _ -> begin - let restype'' = - match !pwhat with - AExp (Some t) when !doCollapseCallCast -> t + let restype'' = match !pwhat with + | AExp (Some t) when DoCollapseCallCast.get () -> t | _ -> resType' in let descr = @@ -5313,10 +5443,10 @@ (* Remember that this variable has been created for this * specific call. We will use this in collapseCallCast. *) IH.add callTempVars tmp.vid (); - addCall + addCall ~is_real_var:false - (Some (var tmp)) - (new_exp ~loc:e.expr_loc (Lval(var tmp))) + (Some (var tmp)) + (new_exp ~loc:e.expr_loc (Lval(var tmp))) restype'' end end; @@ -5324,22 +5454,22 @@ finishExp [] !prechunk !pres !prestype | A.COMMA el -> - if asconst then Cil.warning "COMMA in constant"; - let rec loop sofar = function - [e] -> - let (r, se, e', t') = doExp local_env false e what - in (* Pass on the action *) - (r, sofar @@ se, e', t') - | e :: rest -> - let (_, se, _, _) = doExp local_env false e ADrop in - loop (sofar @@ se) rest - | [] -> Cil.fatal "empty COMMA expression" - in - loop empty el + if asconst then Kernel.warning ~current:true "COMMA in constant"; + let rec loop sofar = function + [e] -> + let (r, se, e', t') = doExp local_env false e what + in (* Pass on the action *) + (r, sofar @@ se, e', t') + | e :: rest -> + let (_, se, _, _) = doExp local_env false e ADrop in + loop (sofar @@ se) rest + | [] -> Kernel.fatal ~current:true "empty COMMA expression" + in + loop empty el | A.QUESTION (e1,e2,e3) when what = ADrop -> if asconst then - (Cil.warning "QUESTION with ADrop in constant"); + Kernel.warning ~current:true "QUESTION with ADrop in constant"; let (r3,se3,_,_) = doExp local_env false e3 ADrop in let r2,se2 = match e2.expr_node with @@ -5352,7 +5482,7 @@ ConditionalSideEffectHook.apply (e,e3); finishExp [] (doCondition local_env asconst - e1 (add_reads r2 se2) (add_reads r3 se3)) + e1 (add_reads e2.expr_loc r2 se2) (add_reads e3.expr_loc r3 se3)) (zero ~loc:e.expr_loc) intType | A.QUESTION (e1, e2, e3) -> begin (* what is not ADrop *) @@ -5473,7 +5603,7 @@ | _ -> try findLastComputation (List.rev b.A.bstmts), false with Not_found -> - Cil.fatal "Cannot find COMPUTATION in GNU.body" + Kernel.fatal ~current:true "Cannot find COMPUTATION in GNU.body" (* A.NOP cabslu, true *) in let loc = Cabshelper.get_statementloc lastComp in @@ -5483,13 +5613,14 @@ let se = doBody local_env b in - (*Cilmsg.debug "Body inside expression: %a@." d_chunk se;*) + (*Kernel.debug "Body inside expression: %a@." d_chunk se;*) gnu_body_result := old_gnu; match !data with - None when isvoidbody -> + None when isvoidbody -> finishExp [] se (zero ~loc:e.expr_loc) voidType - | None -> Cil.abort "Cannot find COMPUTATION in GNU.body" + | None -> + Kernel.abort ~current:true "Cannot find COMPUTATION in GNU.body" | Some (e, t) -> let se, e = match se.stmts with @@ -5520,10 +5651,11 @@ (makeCast (integer ~loc addrval) voidPtrType) voidPtrType end - | A.EXPR_PATTERN _ -> Cil.abort "EXPR_PATTERN in cabs2cil input" + | A.EXPR_PATTERN _ -> + Kernel.abort ~current:true "EXPR_PATTERN in cabs2cil input" with _ when Cilmsg.had_errors () && continueOnError -> begin - Cil.error "ignoring expression"; + Kernel.error ~current:true "ignoring expression"; ([], i2c (mkStmtOneInstr ~ghost:local_env.is_ghost (dInstr (Pretty_utils.sfprintf "booo_exp(%t)" d_thisloc) loc), @@ -5563,7 +5695,8 @@ tres, optConstFoldBinOp loc false bop (makeCastT e1 t1 tres) (makeCastT e2 t2 tres) tres - | _ -> Cil.fatal "%a operator on a non-integer type" d_binop bop + | _ -> + Kernel.fatal ~current:true "%a operator on a non-integer type" d_binop bop in let pointerComparison e1 t1 e2 t2 = (* Cast both sides to an integer *) @@ -5578,7 +5711,14 @@ intType, optConstFoldBinOp loc false bop e1' e2' intType in - + let do_shift e1 t1 e2 t2 = + match e1.enode with + StartOf lv -> + { e1 with enode = AddrOf (addOffsetLval (Index (e2,NoOffset)) lv) } + | _ -> + optConstFoldBinOp loc false PlusPI e1 + (makeCastT e2 t2 (integralPromotion t2)) t1 + in match bop with (Mult|Div) -> doArithmetic () | (Mod|BAnd|BOr|BXor) -> doIntegralArithmetic () @@ -5599,13 +5739,9 @@ when isArithmeticType t1 && isArithmeticType t2 -> doArithmeticComp () | PlusA when isPointerType t1 && isIntegralType t2 -> - t1, - optConstFoldBinOp loc false PlusPI e1 - (makeCastT e2 t2 (integralPromotion t2)) t1 + t1, do_shift e1 t1 e2 t2 | PlusA when isIntegralType t1 && isPointerType t2 -> - t2, - optConstFoldBinOp loc false PlusPI e2 - (makeCastT e1 t1 (integralPromotion t1)) t2 + t2, do_shift e2 t2 e1 t1 | MinusA when isPointerType t1 && isIntegralType t2 -> t1, optConstFoldBinOp loc false MinusPI e1 @@ -5623,28 +5759,29 @@ pointerComparison (makeCastT (zero ~loc)theMachine.upointType t2) t2 e2 t2 | (Eq|Ne) when isVariadicListType t1 && isZero e2 -> - (Cil.warnOpt "Comparison of va_list and zero"); - pointerComparison e1 t1 (makeCastT (zero ~loc)theMachine.upointType t1) t1 + Kernel.debug ~level:3 "Comparison of va_list and zero"; + pointerComparison e1 t1 (makeCastT (zero ~loc)theMachine.upointType t1) t1 | (Eq|Ne) when isVariadicListType t2 && isZero e1 -> - (Cil.warnOpt "Comparison of zero and va_list"); - pointerComparison (makeCastT (zero ~loc)theMachine.upointType t2) t2 e2 t2 + Kernel.debug ~level:3 "Comparison of zero and va_list"; + pointerComparison (makeCastT (zero ~loc)theMachine.upointType t2) t2 e2 t2 | (Eq|Ne|Le|Lt|Ge|Gt) when isPointerType t1 && isArithmeticType t2 -> - (Cil.warnOpt "Comparison of pointer and non-pointer"); - (* Cast both values to upointType *) - doBinOp loc bop - (makeCastT e1 t1 theMachine.upointType) theMachine.upointType - (makeCastT e2 t2 theMachine.upointType) theMachine.upointType + Kernel.debug ~level:3 "Comparison of pointer and non-pointer"; + (* Cast both values to upointType *) + doBinOp loc bop + (makeCastT e1 t1 theMachine.upointType) theMachine.upointType + (makeCastT e2 t2 theMachine.upointType) theMachine.upointType | (Eq|Ne|Le|Lt|Ge|Gt) when isArithmeticType t1 && isPointerType t2 -> - (Cil.warnOpt "Comparison of pointer and non-pointer"); - (* Cast both values to upointType *) - doBinOp loc - bop (makeCastT e1 t1 theMachine.upointType) theMachine.upointType - (makeCastT e2 t2 theMachine.upointType) theMachine.upointType + Kernel.debug ~level:3 "Comparison of pointer and non-pointer"; + (* Cast both values to upointType *) + doBinOp loc + bop (makeCastT e1 t1 theMachine.upointType) theMachine.upointType + (makeCastT e2 t2 theMachine.upointType) theMachine.upointType | _ -> - Cil.fatal "doBinOp: %a" - d_plainexp (dummy_exp(BinOp(bop,e1,e2,intType))) + Kernel.fatal ~current:true + "doBinOp: %a" + d_plainexp (dummy_exp(BinOp(bop,e1,e2,intType))) (* Constant fold a conditional. This is because we want to avoid having * conditionals in the initializers. So, we try very hard to avoid creating @@ -5718,7 +5855,7 @@ | CEExp (se1, e) when isEmpty se1 -> let t = typeOf e in if not ((isPointerType t) || (isArithmeticType t))then - Cil.error "Bad operand to !"; + Kernel.error ~current:true "Bad operand to !"; CEExp (empty, new_exp ~loc (UnOp(LNot, e, intType))) | ce1 -> CENot ce1 end @@ -5732,7 +5869,7 @@ ConditionalSideEffectHook.apply (orig,e)); ignore (checkBool t e'); Cabscond.bind e e' ; - CEExp (add_reads r se, + CEExp (add_reads e.expr_loc r se, if asconst || theMachine.lowerConstants then constFold asconst e' else e') @@ -5805,8 +5942,12 @@ | CEExp (se, e) -> begin match e.enode with - Const(CInt64(i,_,_)) when i <> Int64.zero && canDrop sf -> se @@ st - | Const(CInt64(z,_,_)) when z = Int64.zero && canDrop st -> se @@ sf + | Const(CInt64(i,_,_)) + when (not (My_bigint.equal i My_bigint.zero)) && canDrop sf -> + se @@ st + | Const(CInt64(z,_,_)) + when (My_bigint.equal z My_bigint.zero) && canDrop st -> + se @@ sf | _ -> (empty @@ se) @@ ifChunk e e.eloc st sf end @@ -5818,18 +5959,24 @@ (st: chunk) (sf: chunk) : chunk = let cabscond = match info with - | Some (descr,loc) -> Cabscond.push_condition descr loc e - | None -> false in - let ce = doCondExp local_env isconst e in - if cabscond then Cabscond.pop_condition () ; - let chunk = compileCondExp cabscond ce st sf in + | Some (descr,loc) -> Cabscond.push_condition descr loc e + | None -> false + in + if isEmpty st && isEmpty sf(*TODO: ignore attribute FRAMA_C_KEEP_BLOCK*) then + let (_, se,_,_) = doExp local_env cabscond e ADrop in + if cabscond then Cabscond.pop_condition (); + se + else + let ce = doCondExp local_env isconst e in + if cabscond then Cabscond.pop_condition () ; + let chunk = compileCondExp cabscond ce st sf in chunk and doPureExp local_env (e : A.expression) : exp = let (_,se, e', _) = doExp local_env true e (AExp None) in if isNotEmpty se then - Cil.error "%a has side-effects" Cprint.print_expression e; + Kernel.error ~current:true "%a has side-effects" Cprint.print_expression e; e' and doFullExp local_env const e what = @@ -5845,10 +5992,10 @@ (* Setup the pre-initializer *) let topPreInit = ref NoInitPre in if debugInit then - Cilmsg.debug "@\nStarting a new initializer for %s : %a@\n" vi.vname d_type vi.vtype; + Kernel.debug "@\nStarting a new initializer for %s : %a@\n" vi.vname d_type vi.vtype; let topSetupInit (o: offset) (e: exp) = if debugInit then - Cilmsg.debug " set %a := %a@\n" d_lval (Var vi, o) d_exp e; + Kernel.debug " set %a := %a@\n" d_lval (Var vi, o) d_exp e; let newinit = setOneInit !topPreInit o e in if newinit != !topPreInit then topPreInit := newinit in @@ -5858,16 +6005,16 @@ (unspecified_chunk empty) [ (A.NEXT_INIT, inite) ] in if restl <> [] then - Cil.warning "Ignoring some initializers"; + Kernel.warning ~current:true "Ignoring some initializers"; (* sm: we used to do array-size fixups here, but they only worked * for toplevel array types; now, collectInitializer does the job, * including for nested array types *) let typ' = unrollType vi.vtype in if debugInit then - Cilmsg.debug "Collecting the initializer for %s@\n" vi.vname; + Kernel.debug "Collecting the initializer for %s@\n" vi.vname; let (init, typ'') = collectInitializer !topPreInit typ' in if debugInit then - Cilmsg.debug "Finished the initializer for %s@\n init=%a@\n typ=%a@\n acc=%a@\n" + Kernel.debug "Finished the initializer for %s@\n init=%a@\n typ=%a@\n acc=%a@\n" vi.vname d_init init d_type typ' d_chunk acc; empty @@ acc, init, typ'' @@ -5922,7 +6069,7 @@ let allinitl = initl2 in if debugInit then begin - Cilmsg.debug "doInit for %t %s (current %a). Looking at: %t" whoami + Kernel.debug "doInit for %t %s (current %a). Looking at: %t" whoami (if so.eof then "(eof)" else "") d_lval (Var so.host, so.curOff) (fun fmt -> @@ -5952,48 +6099,50 @@ (A.CONST_STRING s)} as e))])) :: restil when (match unrollType bt with - TInt((IChar|IUChar|ISChar), _) -> true - | TInt _ -> - (*Base type is a scalar other than char. Maybe a wchar_t?*) - Cil.fatal "Using a string literal to initialize something other than a character array" - | _ -> false (* OK, this is probably an array of strings. Handle *) - ) (* it with the other arrays below.*) + | TInt((IChar|IUChar|ISChar), _) -> true + | TInt _ -> + (*Base type is a scalar other than char. Maybe a wchar_t?*) + Kernel.fatal ~current:true + "Using a string literal to initialize something other than \ +a character array" + | _ -> false (* OK, this is probably an array of strings. Handle *) + ) (* it with the other arrays below.*) -> - let charinits = - let init c = - A.NEXT_INIT, - A.SINGLE_INIT - { expr_node = A.CONSTANT (A.CONST_CHAR [c]); - expr_loc = e.expr_loc } - in - let collector = - (* ISO 6.7.8 para 14: final NUL added only if no size specified, or - * if there is room for it; btw, we can't rely on zero-init of - * globals, since this array might be a local variable *) - if ((isNone leno) or ((String.length s) < (integerArrayLength leno))) - then ref [init Int64.zero] - else ref [] - in - for pos = String.length s - 1 downto 0 do - collector := init (Int64.of_int (Char.code (s.[pos]))) :: !collector - done; - !collector + let charinits = + let init c = + A.NEXT_INIT, + A.SINGLE_INIT + { expr_node = A.CONSTANT (A.CONST_CHAR [c]); + expr_loc = e.expr_loc } in - (* Create a separate object for the array *) - let so' = makeSubobj so.host so.soTyp so.soOff in - (* Go inside the array *) - let leno = integerArrayLength leno in - so'.stack <- [InArray(so'.curOff, bt, leno, ref 0)]; - normalSubobj so'; - let acc', initl' = - doInit local_env isconst setone so' acc charinits in - if initl' <> [] then - (Cil.warning "Too many initializers for character array %t" whoami); - (* Advance past the array *) - advanceSubobj so; - (* Continue *) - let res = doInit local_env isconst setone so acc' restil in - res + let collector = + (* ISO 6.7.8 para 14: final NUL added only if no size specified, or + * if there is room for it; btw, we can't rely on zero-init of + * globals, since this array might be a local variable *) + if ((isNone leno) or ((String.length s) < (integerArrayLength leno))) + then ref [init Int64.zero] + else ref [] + in + for pos = String.length s - 1 downto 0 do + collector := init (Int64.of_int (Char.code (s.[pos]))) :: !collector + done; + !collector + in + (* Create a separate object for the array *) + let so' = makeSubobj so.host so.soTyp so.soOff in + (* Go inside the array *) + let leno = integerArrayLength leno in + so'.stack <- [InArray(so'.curOff, bt, leno, ref 0)]; + normalSubobj so'; + let acc', initl' = + doInit local_env isconst setone so' acc charinits in + if initl' <> [] then + Kernel.warning ~current:true + "Too many initializers for character array %t" whoami; + (* Advance past the array *) + advanceSubobj so; + (* Continue *) + doInit local_env isconst setone so acc' restil (* If we are at an array of WIDE characters and the initializer is a * WIDE string literal (optionally enclosed in braces) then explore @@ -6021,7 +6170,8 @@ | TInt _ -> (*Base type is a scalar other than wchar_t. Maybe a char?*) - Cil.fatal "Using a wide string literal to initialize \ + Kernel.fatal ~current:true + "Using a wide string literal to initialize \ something other than a wchar_t array" | _ -> false (* OK, this is probably an array of strings. Handle @@ -6033,8 +6183,9 @@ Int64.one in let charinits = let init c = - if (Int64.compare c maxWChar > 0) then (* if c > maxWChar *) - Cil.error "cab2cil:doInit:character 0x%Lx too big." c; + if Int64.compare c maxWChar > 0 then (* if c > maxWChar *) + Kernel.error ~current:true + "cab2cil:doInit:character 0x%Lx too big." c; A.NEXT_INIT, A.SINGLE_INIT { expr_node = A.CONSTANT (A.CONST_INT (Int64.to_string c)); @@ -6062,7 +6213,8 @@ (* sm: see above regarding ISO 6.7.8 para 14, which is not implemented * for wchar_t because, as far as I can tell, we don't even put in * the automatic NUL (!) *) - (Cil.warning "Too many initializers for wchar_t array %t" whoami); + Kernel.warning ~current:true + "Too many initializers for wchar_t array %t" whoami; (* Advance past the array *) advanceSubobj so; (* Continue *) @@ -6085,7 +6237,7 @@ let r,se, oneinit', t' = doExp local_env isconst oneinit (AExp None) in - let se = add_reads r se in + let se = add_reads oneinit'.eloc r se in if (match unrollType t' with TComp (comp', _, _) when comp'.ckey = comp.ckey -> true | _ -> false) @@ -6106,11 +6258,11 @@ | _, (A.NEXT_INIT, A.SINGLE_INIT oneinit) :: restil -> let r, se, oneinit', t' = doExp local_env isconst oneinit (AExp(Some so.soTyp)) in - let se = add_reads r se in - (* ignore (E.log "oneinit'=%a, t'=%a, so.soTyp=%a\n" - d_exp oneinit' d_type t' d_type so.soTyp);*) + let se = add_reads oneinit'.eloc r se in + Kernel.debug "oneinit'=%a, t'=%a, so.soTyp=%a" + d_exp oneinit' d_type t' d_type so.soTyp; setone so.soOff (if theMachine.insertImplicitCasts then - makeCastT oneinit' t' so.soTyp + snd (castTo t' so.soTyp oneinit') else oneinit'); (* Move on *) advanceSubobj so; @@ -6128,7 +6280,8 @@ normalSubobj so'; let acc', initl' = doInit local_env isconst setone so' acc initl in if initl' <> [] then - (Cil.warning "Too many initializers for array %t" whoami); + Kernel.warning ~current:true + "Too many initializers for array %t" whoami; (* Advance past the array *) advanceSubobj so; (* Continue *) @@ -6137,7 +6290,7 @@ (* We have a designator that tells us to select the matching union field. * This is to support a GCC extension *) - | TComp(ci, _, _), [(A.NEXT_INIT, + | TComp(ci, _, _) as targ, [(A.NEXT_INIT, A.COMPOUND_INIT [(A.INFIELD_INIT ("___matching_field", A.NEXT_INIT), A.SINGLE_INIT oneinit)])] @@ -6146,14 +6299,21 @@ let _, _, _, t' = doExp local_env isconst oneinit (AExp None) in let tsig = typeSigNoAttrs t' in let rec findField = function - [] -> Cil.fatal "Cannot find matching union field in cast" + | [] -> + Kernel.fatal ~current:true "Cannot find matching union field in cast" | fi :: _rest when Cilutil.equals (typeSigNoAttrs fi.ftype) tsig -> fi | _ :: rest -> findField rest in - let fi = findField ci.cfields in - (* Change the designator and redo *) - doInit local_env isconst setone so acc - [(A.INFIELD_INIT (fi.fname, A.NEXT_INIT), A.SINGLE_INIT oneinit)] + (* If this is a cast from union X to union X *) + if Cilutil.equals tsig (typeSigNoAttrs targ) then + doInit local_env isconst setone so acc + [(A.NEXT_INIT, A.SINGLE_INIT oneinit)] + else + (* If this is a GNU extension with field-to-union cast find the field *) + let fi = findField ci.cfields in + (* Change the designator and redo *) + doInit local_env isconst setone so acc + [A.INFIELD_INIT (fi.fname, A.NEXT_INIT), A.SINGLE_INIT oneinit] (* A structure with a composite initializer. We initialize the fields*) | TComp (comp, _, _), (A.NEXT_INIT, A.COMPOUND_INIT initl) :: restil -> @@ -6166,7 +6326,7 @@ doInit local_env isconst setone so' acc initl in if initl' <> [] then - (Cil.warning "Too many initializers for structure"); + Kernel.warning ~current:true "Too many initializers for structure"; (* Advance past the structure *) advanceSubobj so; (* Continue *) @@ -6187,13 +6347,14 @@ let r,se, oneinit', t' = doExp local_env isconst oneinit (AExp(Some so.soTyp)) in - let se = add_reads r se in + let se = add_reads oneinit'.eloc r se in setone so.soOff (makeCastT oneinit' t' so.soTyp); (* Move on *) advanceSubobj so; doInit local_env isconst setone so (acc @@ se) restil with Not_found -> - Cil.fatal "doInit: unexpected NEXT_INIT for %a\n" d_type t + Kernel.fatal ~current:true + "doInit: unexpected NEXT_INIT for %a\n" d_type t end (* We have a designator *) @@ -6216,7 +6377,9 @@ so.stack <- InComp(so.soOff, comp, toinit) :: so.stack; normalSubobj so; address whatnext acc - | _ -> Cil.fatal "Field designator %s not in a struct " fn + | _ -> + Kernel.fatal ~current:true + "Field designator %s not in a struct " fn end | A.ATINDEX_INIT(idx, whatnext) -> begin @@ -6227,24 +6390,27 @@ let (r,doidx, idxe', _) = doExp local_env true idx (AExp(Some intType)) in - let doidx = add_reads r doidx in + let doidx = add_reads idxe'.eloc r doidx in match (constFold true idxe').enode, isNotEmpty doidx with - Const(CInt64(x, _, _)), false -> Int64.to_int x, doidx - | _ -> Cil.fatal + Const(CInt64(x, _, _)), false -> My_bigint.to_int x, doidx + | _ -> + Kernel.fatal ~current:true "INDEX initialization designator is not a constant" in if nextidx' < 0 || nextidx' >= ilen then - Cil.fatal "INDEX designator is outside bounds"; + Kernel.fatal ~current:true + "INDEX designator is outside bounds"; so.stack <- InArray(so.soOff, bt, ilen, ref nextidx') :: so.stack; normalSubobj so; address whatnext (acc @@ doidx) - | _ -> Cil.fatal "INDEX designator for a non-array" + | _ -> + Kernel.fatal ~current:true "INDEX designator for a non-array" end | A.ATINDEXRANGE_INIT _ -> - Cil.abort "addressSubobj: INDEXRANGE" + Kernel.abort ~current:true "addressSubobj: INDEXRANGE" in address what acc in @@ -6260,21 +6426,22 @@ doExp local_env true idxs (AExp(Some intType)) in let (re, doidxe, idxe', _) = doExp local_env true idxe (AExp(Some intType)) in - let doidxs = add_reads rs doidxs in - let doidxe = add_reads re doidxe in + let doidxs = add_reads idxs'.eloc rs doidxs in + let doidxe = add_reads idxe'.eloc re doidxe in if isNotEmpty doidxs || isNotEmpty doidxe then - Cil.fatal "Range designators are not constants"; + Kernel.fatal ~current:true "Range designators are not constants"; let first, last = match (constFold true idxs').enode, (constFold true idxe').enode with Const(CInt64(s, _, _)), Const(CInt64(e, _, _)) -> - Int64.to_int s, Int64.to_int e - | _ -> Cil.fatal + My_bigint.to_int s, My_bigint.to_int e + | _ -> + Kernel.fatal ~current:true "INDEX_RANGE initialization designator is not a constant" in if first < 0 || first > last then - Cil.error + Kernel.error ~current:true "start index larger than end index in range initializer"; let rec loop (i: int) = if i > last then restil @@ -6295,7 +6462,7 @@ expandRange (fun x -> x) what | t, (_what, _ie) :: _ -> - Cil.abort "doInit: cases for t=%a" d_type t + Kernel.abort ~current:true "doInit: cases for t=%a" d_type t (* Create and add to the file (if not already added) a global. Return the @@ -6304,7 +6471,7 @@ (((n,ndt,a,cloc), inite) : A.init_name) : varinfo = try if debugGlobal then - Cilmsg.debug "createGlobal: %s" n; + Kernel.debug "createGlobal: %s" n; (* Make a first version of the varinfo *) let vi = makeVarInfoCabs ~ghost ~isformal:false ~isglobal:true (convLoc cloc) specs (n,ndt,a) in @@ -6312,7 +6479,8 @@ * because it might refer to the variable itself *) if isFunctionType vi.vtype then begin if inite != A.NO_INIT then - error "Function declaration with initializer (%s)\n" vi.vname; + Kernel.error ~current:true + "Function declaration with initializer (%s)\n" vi.vname; (* sm: if it's a function prototype, and the storage class *) (* isn't specified, make it 'extern'; this fixes a problem *) (* with no-storage prototype and static definition *) @@ -6337,7 +6505,8 @@ if unrollType vi.vtype != unrollType et then vi.vtype <- et; if isNotEmpty se then begin - Cil.error "invalid global initializer @[%a@]" d_chunk se; + Kernel.error ~current:true + "invalid global initializer @[%a@]" d_chunk se; end; Some ie' in @@ -6346,10 +6515,11 @@ let oldloc = H.find alreadyDefined vi.vname in if init != None then begin (* function redefinition is taken care of elsewhere. *) - Cil.error "Global %s was already defined at %a" vi.vname d_loc oldloc; + Kernel.error ~current:true + "Global %s was already defined at %a" vi.vname d_loc oldloc; end; if debugGlobal then - Cilmsg.debug " global %s was already defined" vi.vname; + Kernel.debug " global %s was already defined" vi.vname; (* Do not declare it again, but update the spec if any *) if isFunctionType vi.vtype then begin @@ -6361,7 +6531,7 @@ List.iter2 (fun x y -> if x != y then - Cilmsg.fatal + Kernel.fatal "Function %s: formals are not shared between AST and \ FormalDecls table" vi.vname) l1 l2; @@ -6381,7 +6551,7 @@ with Not_found -> begin (* Not already defined *) if debugGlobal then - Cilmsg.debug " first definition for %s(%d)\n" vi.vname + Kernel.debug " first definition for %s(%d)\n" vi.vname vi.vid; if init != None then begin (* weimer: Sat Dec 8 17:43:34 2001 @@ -6435,7 +6605,7 @@ vi end else begin if debugGlobal then - Cilmsg.debug " already in env %s" vi.vname; + Kernel.debug " already in env %s" vi.vname; (match logic_spec with | None -> () | Some (spec,loc) -> @@ -6461,7 +6631,7 @@ end end with _ when Cilmsg.had_errors () && continueOnError -> begin - Cil.error "skipping global %s" n; + Kernel.error ~current:true "skipping global %s" n; cabsPushGlobal (dGlobal (Pretty_utils.sfprintf "booo - error in global %s (%t)" n d_thisloc) (CurrentLoc.get ())); @@ -6502,7 +6672,7 @@ | _ when sto = Static -> if debugGlobal then - Cilmsg.debug "createGlobal (local static): %s" n; + Kernel.debug "createGlobal (local static): %s" n; (* Now alpha convert it to make sure that it does not conflict with * existing globals or locals from this function. *) @@ -6535,10 +6705,11 @@ if unrollType vi.vtype != unrollType et then vi.vtype <- et; if isNotEmpty se then - Cil.error "global static initializer"; + Kernel.error ~current:true "global static initializer"; + (* Check that no locals are refered by the initializer *) + check_no_locals_in_initializer ie'; (* Maybe the initializer refers to the function itself. - Push a prototype for the function, just in case. Hopefully, - if does not refer to the locals *) + Push a prototype for the function, just in case. *) cabsPushGlobal (GVarDecl (empty_funspec (), !currentFunctionFDEC.svar, CurrentLoc.get ())); @@ -6567,7 +6738,8 @@ let vi = alphaConvertVarAndAddToEnv true vi in (* Replace vi *) let se1 = if isvarsize then begin (* Variable-sized array *) - (Cil.warning "Variable-sized local variable %s" vi.vname); + Kernel.warning ~current:true + "Variable-sized local variable %s" vi.vname; (* Make a local variable to keep the length *) let savelen = makeVarInfoCabs @@ -6597,7 +6769,8 @@ IH.add varSizeArrays vi.vid sizeof; (* There can be no initializer for this *) if inite != A.NO_INIT then - Cil.error "Variable-sized array cannot have initializer"; + Kernel.error ~current:true + "Variable-sized array cannot have initializer"; let setlen = se0 +++ (mkStmtOneInstr ~ghost (Set(var savelen, makeCast len savelen.vtype, @@ -6606,7 +6779,7 @@ in (* Initialize the variable *) let alloca: varinfo = allocaFun () in - if !doCollapseCallCast then + if DoCollapseCallCast.get () then (* do it in one step *) setlen +++ (mkStmtOneInstr ~ghost @@ -6662,7 +6835,7 @@ (* E.log "%s is alias for %s at %a\n" thisname othername *) (* d_loc !currentLoc; *) let rt, formals, isva, _ = splitFunctionType vtype in - if isva then Cil.error "alias unsupported with varargs"; + if isva then Kernel.error ~current:true "alias unsupported with varargs"; let args = List.map (fun (n,_,_) -> { expr_loc = loc; expr_node = A.VARIABLE n}) (argsToList formals) in @@ -6677,8 +6850,10 @@ let fdef = A.FUNDEF (None, sname, body, loc, loc) in ignore (doDecl false true fdef); (* get the new function *) - let v,_ = try lookupGlobalVar thisname - with Not_found -> Cil.abort "error in doDecl" in + let v,_ = + try lookupGlobalVar thisname + with Not_found -> Kernel.abort ~current:true "error in doDecl" + in v.vattr <- dropAttribute "alias" v.vattr @@ -6707,13 +6882,15 @@ (* E.log "%s is not aliased\n" name *) | [Attr("alias", [AStr othername])] -> if not (isFunctionType vtype) || ghost then begin - Cil.warning - "%a: CIL only supports attribute((alias)) for C functions.\n" + Kernel.warning ~current:true + "%a: CIL only supports attribute((alias)) for C functions." d_loc (CurrentLoc.get ()); ignore (createGlobal ghost logic_spec spec_res name) end else doAliasFun vtype n othername (s, (n,ndt,a,l)) loc - | _ -> Cil.error "Bad alias attribute at %a" d_loc (CurrentLoc.get())); + | _ -> + Kernel.error ~current:true + "Bad alias attribute at %a" d_loc (CurrentLoc.get())); acc end else acc @@ createLocal ghost spec_res name @@ -6743,19 +6920,25 @@ [Attr("dummy", [a'])] -> let a'' = match a' with - | ACons (s, args) -> Attr (s, args) + | ACons (s, args) -> + process_align_pragma s args; + process_pack_pragma s args | _ -> (* Cil.fatal "Unexpected attribute in #pragma" *) - Cil.warning "Unexpected attribute in #pragma"; - Attr ("", [a']) + Kernel.warning ~current:true "Unexpected attribute in #pragma"; + Some (Attr ("", [a'])) in - cabsPushGlobal (GPragma (a'', CurrentLoc.get ())); + Extlib.may + (fun a'' -> + cabsPushGlobal (GPragma (a'', CurrentLoc.get ()))) + a''; empty - | _ -> Cil.fatal "Too many attributes in pragma" + | _ -> Kernel.fatal ~current:true "Too many attributes in pragma" end - | A.TRANSFORMER (_, _, _) -> Cil.abort "TRANSFORMER in cabs2cil input" + | A.TRANSFORMER (_, _, _) -> + Kernel.abort ~current:true "TRANSFORMER in cabs2cil input" | A.EXPRTRANSFORMER (_, _, _) -> - Cil.abort "EXPRTRANSFORMER in cabs2cil input" + Kernel.abort ~current:true "EXPRTRANSFORMER in cabs2cil input" (* If there are multiple definitions of extern inline, turn all but the * first into a prototype *) @@ -6768,12 +6951,13 @@ if othervi.vname = n then (* The previous entry in the env is also an extern inline version of n. *) - (Cil.warning "Duplicate extern inline definition for %s ignored" n) + Kernel.warning ~current:true + "Duplicate extern inline definition for %s ignored" n else begin (* Otherwise, the previous entry is an ordinary function that happens to be named __extinline. Renaming n to n__extinline would confict with other, so report an error. *) - Cil.fatal + Kernel.fatal ~current:true ("Trying to rename %s to\n %s__extinline, but %s__extinline" ^^ " already exists in the env.\n \"__extinline\" is" ^^ " reserved for CIL.\n") n n n @@ -6785,11 +6969,12 @@ | A.FUNDEF (spec,((specs,(n,dt,a, _)) : A.single_name), (body : A.block), loc1, loc2) when isglobal -> begin - let funloc = convLoc loc1 in - let endloc = convLoc loc2 in + let idloc = loc1 in + let funloc = fst loc1, snd loc2 in + let endloc = loc2 in if debugGlobal then - Cilmsg.debug "Definition of %s at %a\n" n d_loc funloc; - CurrentLoc.set funloc; + Kernel.debug "Definition of %s at %a\n" n d_loc idloc; + CurrentLoc.set idloc; try IH.clear callTempVars; @@ -6807,19 +6992,19 @@ sallstmts = []; sspec = empty_funspec () }; - !currentFunctionFDEC.svar.vdecl <- funloc; + !currentFunctionFDEC.svar.vdecl <- idloc; constrExprId := 0; (* Setup the environment. Add the formals to the locals. Maybe * they need alpha-conv *) enterScope (); (* Start the scope *) ignore (V.visitCabsBlock (new gatherLabelsClass) body); - CurrentLoc.set funloc; + CurrentLoc.set idloc; IH.clear varSizeArrays; (* Enter all the function's labels into the alpha conversion table *) ignore (V.visitCabsBlock (new registerLabelsVisitor) body); - CurrentLoc.set funloc; + CurrentLoc.set idloc; (* Do not process transparent unions in function definitions. * We'll do it later *) @@ -6891,9 +7076,9 @@ * function *) addGlobalToEnv n (EnvVar !currentFunctionFDEC.svar); if H.mem alreadyDefined !currentFunctionFDEC.svar.vname then - Cil.error "There is a definition already for %s" n; + Kernel.error ~current:true "There is a definition already for %s" n; - H.add alreadyDefined !currentFunctionFDEC.svar.vname funloc; + H.add alreadyDefined !currentFunctionFDEC.svar.vname idloc; (* @@ -6998,19 +7183,34 @@ (******* Now do the spec *******) begin match spec with - | Some (spec,loc) -> - Cabshelper.continue_annot loc + | Some (spec,loc) -> + Cabshelper.continue_annot loc (fun () -> - !currentFunctionFDEC.sspec <- - Ltyping.funspec behaviors - !currentFunctionFDEC.svar - (Some !currentFunctionFDEC.sformals) - !currentFunctionFDEC.svar.vtype spec) + !currentFunctionFDEC.sspec <- + Ltyping.funspec behaviors + !currentFunctionFDEC.svar + (Some !currentFunctionFDEC.sformals) + !currentFunctionFDEC.svar.vtype spec) (fun () -> ()) "ignoring logic specification of function %s" !currentFunctionFDEC.svar.vname | None -> () end; + (* Merge pre-existing spec if needed. *) + if has_decl then begin + let merge_spec = function + | GVarDecl(old_spec,_,_) as g -> + if not (Cil.is_empty_funspec old_spec) then begin + rename_spec g; + Logic_utils.merge_funspec + !currentFunctionFDEC.sspec old_spec; + Logic_utils.clear_funspec old_spec; + end + | _ -> assert false + in + update_global_fundec_in_theFile + !currentFunctionFDEC.svar merge_spec + end; (********** Now do the BODY *************) let _ = let stmts = @@ -7031,8 +7231,10 @@ Some (_switchv, switch) -> let switche, loc = match switch.skind with - Switch (switche, _, _, l) -> switche, l - | _ -> Cil.fatal "the computed goto statement not a switch" + | Switch (switche, _, _, l) -> switche, l + | _ -> + Kernel.fatal ~current:true + "the computed goto statement not a switch" in (* Build a default chunk that segfaults *) let default = @@ -7056,10 +7258,10 @@ * have already inserted the goto's *) let newswitchkind = match newswitch.stmts with - [ s, _, _,_,_] - when newswitch.postins == [] && newswitch.cases == []-> - s.skind - | _ -> Cil.fatal "Unexpected result from switchChunk" + [ s, _, _,_,_] when newswitch.cases == []-> s.skind + | _ -> + Kernel.fatal ~current:true + "Unexpected result from switchChunk" in switch.skind <- newswitchkind @@ -7083,11 +7285,12 @@ [], l -> l | f :: formals, l :: locals -> if f != l then - Cil.abort "formal %s is not in locals (found instead %s)" + Kernel.abort ~current:true + "formal %s is not in locals (found instead %s)" f.vname l.vname; dropFormals formals locals - | _ -> Cil.abort "Too few locals" + | _ -> Kernel.abort ~current:true "Too few locals" in !currentFunctionFDEC.slocals <- dropFormals !currentFunctionFDEC.sformals @@ -7137,20 +7340,19 @@ match unrollType !currentReturnType with TVoid _ -> None | (TInt _ | TEnum _ | TFloat _ | TPtr _) as rt -> - (Cil.warn - "Body of function %s falls-through. \ + Kernel.warning ~current:true + "Body of function %s falls-through. \ Adding a return statement" - !currentFunctionFDEC.svar.vname); - Some (makeCastT (zero ~loc:endloc) intType rt) + !currentFunctionFDEC.svar.vname; + Some (makeCastT (zero ~loc:endloc) intType rt) | _ -> - (Cil.warn - "Body of function %s falls-through and \ + Kernel.warning ~current:true + "Body of function %s falls-through and \ cannot find an appropriate return value" - !currentFunctionFDEC.svar.vname); - raise NoReturn + !currentFunctionFDEC.svar.vname; + raise NoReturn in - if not (hasAttribute "noreturn" - !currentFunctionFDEC.svar.vattr) + if not (hasAttribute "noreturn" !currentFunctionFDEC.svar.vattr) then !currentFunctionFDEC.sbody.bstmts <- !currentFunctionFDEC.sbody.bstmts @@ -7163,7 +7365,8 @@ cabsPushGlobal (GFun (!currentFunctionFDEC, funloc)); empty with _ when Cilmsg.had_errors () && continueOnError -> begin - Cil.error "skipping function %s in collectFunction" n; + Kernel.error ~current:true + "skipping function %s in collectFunction" n; cabsPushGlobal (GAsm("error in function " ^ n, CurrentLoc.get ())); empty end @@ -7172,15 +7375,18 @@ | LINKAGE (n, loc, dl) -> CurrentLoc.set (convLoc loc); if n <> "C" then - (Cil.warning "Encountered linkage specification \"%s\"" n); + Kernel.warning ~current:true + "Encountered linkage specification \"%s\"" n; if not isglobal then - Cil.error "Encountered linkage specification in local scope"; + Kernel.error ~current:true + "Encountered linkage specification in local scope"; (* For now drop the linkage on the floor !!! *) List.iter (fun d -> let s = doDecl ghost isglobal d in if isNotEmpty s then - Cil.abort "doDecl returns non-empty statement for global") + Kernel.abort ~current:true + "doDecl returns non-empty statement for global") dl; empty @@ -7200,14 +7406,15 @@ end; empty - | _ -> Cil.fatal "unexpected form of declaration" + | _ -> Kernel.fatal ~current:true "unexpected form of declaration" and doTypedef ghost ((specs, nl): A.name_group) = try (* Do the specifiers exactly once *) let bt, sto, inl, attrs = doSpecList ghost (suggestAnonName nl) specs in if sto <> NoStorage || inl then - Cil.error "Storage or inline specifier not allowed in typedef"; + Kernel.error ~current:true + "Storage or inline specifier not allowed in typedef"; let createTypedef ((n,ndt,a,_) : A.name) = (* E.s (error "doTypeDef") *) try @@ -7233,13 +7440,13 @@ addLocalToEnv (kindPlusName "type" n) (EnvTyp namedTyp); cabsPushGlobal (GType (ti, CurrentLoc.get ())) with _ when Cilmsg.had_errors () && continueOnError -> begin - Cil.error "skipping typedef"; + Kernel.error ~current:true "skipping typedef"; cabsPushGlobal (GAsm ("booo_typedef:" ^ n, CurrentLoc.get ())) end in List.iter createTypedef nl with _ when Cilmsg.had_errors () && continueOnError -> begin - Cil.error "skipping typedef"; + Kernel.error ~current:true "skipping typedef"; let fstname = match nl with [] -> "" @@ -7252,12 +7459,13 @@ try let bt, sto, inl, attrs = doSpecList ghost "" specs in if sto <> NoStorage || inl then - Cil.error "Storage or inline specifier not allowed in typedef"; + Kernel.error ~current:true + "Storage or inline specifier not allowed in typedef"; let restyp, nattr = doType ghost false AttrType bt (A.PARENTYPE(attrs, A.JUSTBASE, [])) in if nattr <> [] then - (Cil.warning "Ignoring identifier attribute"); + Kernel.warning ~current:true "Ignoring identifier attribute"; (* doSpec will register the type. *) (* See if we are defining a composite or enumeration type, and in that * case move the attributes from the defined type into the composite type @@ -7283,10 +7491,12 @@ end else cabsPushGlobal (GEnumTagDecl(ei, CurrentLoc.get ())) | _ -> - (Cil.warning "Ignoring un-named typedef that does not introduce a struct or enumeration type\n") + Kernel.warning ~current:true + "Ignoring un-named typedef that does not introduce a struct or \ +enumeration type" with _ when Cilmsg.had_errors () && continueOnError -> begin - Cil.error "skipping A.ONLYTYPEDEF"; + Kernel.error ~current:true "skipping A.ONLYTYPEDEF"; cabsPushGlobal (GAsm ("booo_typedef", CurrentLoc.get ())) end @@ -7329,7 +7539,7 @@ new_behaviors @ local_env.known_behaviors } in -(* Format.eprintf "Considering statement: %a@." +(* Format.eprintf "Considering statement: %a@." Cprint.print_statement s; *) let res = doStatement local_env s in @@ -7349,39 +7559,32 @@ (* Format.eprintf "Done statement %a@." d_chunk res; *) let chunk = if keep_block then - match res.stmts, res.postins with - | [],[] -> prev + match res.stmts with + | [] -> prev (* if we have a single statement, we can avoid enclosing it into a block. *) - | [ (_s,_,_,_,_) ], [] | [], [ (_s,_,_,_,_) ] -> + | [ (_s,_,_,_,_) ] -> (* Format.eprintf "Statement is: %a@." d_stmt _s; *) prev @@ res (* Make a block, and put labels of the first statement on the block itself, so as to respect scoping rules for \at in further annotations. *) - | _::_,_ | _, _::_ - -> - let b = c2block res in - (* The statement may contain some local variable - declarations coming from userland. We have to shift - them from the inner block, otherwise they will not - be accessible in the next statements. - *) - let locals = b.blocals in - b.blocals <- []; - b.battrs <- - addAttributes - [Attr("FRAMA_C_KEEP_BLOCK",[])] b.battrs; - let block = mkStmt (Block b) in -(* block.labels <- s.labels; - List.iter - (fun x -> replace_string_label x block) - s.labels; - s.labels <- []; *) - let chunk = s2c block in - let chunk = { chunk with cases = res.cases } in - List.fold_left - local_var_chunk (prev @@ chunk) locals + | _ -> + let b = c2block res in + (* The statement may contain some local variable + declarations coming from userland. We have to shift + them from the inner block, otherwise they will not + be accessible in the next statements. + *) + let locals = b.blocals in + b.blocals <- []; + b.battrs <- + addAttributes [Attr(frama_c_keep_block,[])] b.battrs; + let block = mkStmt (Block b) in + let chunk = s2c block in + let chunk = { chunk with cases = res.cases } in + List.fold_left + local_var_chunk (prev @@ chunk) locals else prev @@ res in ((new_behaviors, keep_next), chunk)) (([],false),empty) @@ -7447,7 +7650,7 @@ CurrentLoc.set (convLoc loc); let c = doBody local_env b in let b = c2block c in - b.battrs <- addAttributes [Attr("FRAMA_C_KEEP_BLOCK",[])] b.battrs; + b.battrs <- addAttributes [Attr(frama_c_keep_block,[])] b.battrs; let res = s2c (mkStmt (Block b)) in { res with cases = c.cases } @@ -7508,7 +7711,7 @@ let (se3, _, _) = doFullExp local_env false e3 ADrop in startLoop false; let s' = doStatement local_env s in - (*Cilmsg.debug "Loop body : %a" d_chunk s';*) + (*Kernel.debug "Loop body : %a" d_chunk s';*) CurrentLoc.set loc'; let s'' = consLabContinue se3 in let break_cond = breakChunk loc' in @@ -7547,9 +7750,9 @@ let loc' = convLoc loc in CurrentLoc.set loc'; if not (isVoidType !currentReturnType) then - (Cil.warn - "Return statement without a value in function returning %a\n" - d_type !currentReturnType); + Kernel.warning ~current:true + "Return statement without a value in function returning %a\n" + d_type !currentReturnType; returnChunk None loc' | A.RETURN (e, loc) -> @@ -7557,7 +7760,8 @@ CurrentLoc.set loc'; (* Sometimes we return the result of a void function call *) if isVoidType !currentReturnType then begin - (Cil.warn "Return statement with a value in function returning void"); + Kernel.warning ~current:true + "Return statement with a value in function returning void"; let (se, _, _) = doFullExp local_env false e ADrop in se @@ returnChunk None loc' end else begin @@ -7573,22 +7777,22 @@ | A.SWITCH (e, s, loc) -> let loc' = convLoc loc in CurrentLoc.set loc'; - let (se, e', et) = - doFullExp local_env false e (AExp (Some intType)) in - let (_, e'') = castTo et intType e' in + let (se, e', et) = doFullExp local_env false e (AExp None) in + if not (Cil.isIntegralType et) then + Kernel.error ~current:true "Switch on a non-integer expression."; + let et' = Cil.integralPromotion et in + let e' = makeCastT ~e:e' ~oldt:et ~newt:et' in enter_break_env (); let s' = doStatement local_env s in exit_break_env (); - se @@ (switchChunk e'' s' loc') + se @@ (switchChunk e' s' loc') | A.CASE (e, s, loc) -> let loc' = convLoc loc in CurrentLoc.set loc'; let (se, e', _) = doFullExp local_env true e (AExp None) in - if isNotEmpty se || - (not (Cil.isIntegerConstant e')) - then - Cil.error "Case statement with a non-constant"; + if isNotEmpty se || not (Cil.isIntegerConstant e') then + Kernel.error ~current:true "Case statement with a non-constant"; caseRangeChunk [if theMachine.lowerConstants then constFold false e' else e'] loc' (doStatement local_env s) @@ -7599,15 +7803,16 @@ let (sel, el', _) = doFullExp local_env false el (AExp None) in let (seh, eh', _) = doFullExp local_env false eh (AExp None) in if isNotEmpty sel || isNotEmpty seh then - Cil.error "Case statement with a non-constant"; + Kernel.error ~current:true "Case statement with a non-constant"; let il, ih = match (constFold true el').enode, (constFold true eh').enode with Const(CInt64(il, _, _)), Const(CInt64(ih, _, _)) -> - Int64.to_int il, Int64.to_int ih - | _ -> Cil.fatal "Cannot understand the constants in case range" + My_bigint.to_int il, My_bigint.to_int ih + | _ -> + Kernel.fatal ~current:true + "Cannot understand the constants in case range" in - if il > ih then - Cil.error "Empty case range"; + if il > ih then Kernel.error ~current:true "Empty case range"; let rec mkAll (i: int) = if i > ih then [] else integer ~loc i :: mkAll (i + 1) in @@ -7655,10 +7860,12 @@ (("__compgoto", A.JUSTBASE, [], loc), A.NO_INIT) in if not (isEmpty vchunk) then - Cil.fatal "Non-empty chunk in creating temporary for goto *"; + Kernel.fatal ~current:true + "Non-empty chunk in creating temporary for goto *"; let switchv, _ = try lookupVar "__compgoto" - with Not_found -> Cil.abort "Cannot find temporary for goto *"; + with Not_found -> + Kernel.abort ~current:true "Cannot find temporary for goto *"; in (* Make a switch statement. We'll fill in the statements at the * end of the function *) @@ -7678,7 +7885,7 @@ | A.DEFINITION d -> let s = doDecl local_env.is_ghost false d in (* - Cilmsg.debug "Def at %a: %a\n" d_loc (currentLoc()) d_chunk s; + Kernel.debug "Def at %a: %a\n" d_loc (currentLoc()) d_chunk s; *) s @@ -7710,7 +7917,9 @@ match e'.enode with | Lval lval | StartOf lval -> lval - | _ -> Cil.fatal "Expected lval for ASM outputs" + | _ -> + Kernel.fatal ~current:true + "Expected lval for ASM outputs" in stmts := !stmts @@ se; (id, c, lv)) outs @@ -7722,7 +7931,7 @@ let (r, se, e', _) = doExp local_env false e (AExp None) in - let se = add_reads r se in + let se = add_reads e'.eloc r se in stmts := !stmts @@ se; (id, c, e')) ins @@ -7739,8 +7948,8 @@ let b': chunk = doBody local_env b in let h': chunk = doBody local_env h in if b'.cases <> [] || h'.cases <> [] then - Cil.error "Try statements cannot contain switch cases"; - + Kernel.error ~current:true + "Try statements cannot contain switch cases"; s2c (mkStmt (TryFinally (c2block b', c2block h', loc'))) | TRY_EXCEPT (b, e, h, loc) -> @@ -7752,31 +7961,20 @@ doFullExp local_env false e (AExp None) in let h': chunk = doBody local_env h in if b'.cases <> [] || h'.cases <> [] || se.cases <> [] then - Cil.error "Try statements cannot contain switch cases"; + Kernel.error ~current:true + "Try statements cannot contain switch cases"; (* Now take se and try to convert it to a list of instructions. This * might not be always possible *) let stmt_to_instrs s = - List.map - (function s -> match s.skind with - | Instr s -> s - | _ -> - Cil.fatal - "Except expression contains unexpected statement") + List.rev_map + (function (s,_,_,_,_) -> match s.skind with + | Instr s -> s + | _ -> + Kernel.fatal ~current:true + "Except expression contains unexpected statement") s in - let il' = - match se.stmts with - [] -> stmt_to_instrs (List.map(fun (x,_,_,_,_)->x) se.postins) - | [ s,_,_,_,_ ] -> begin - match s.skind with - Instr i -> - i :: (stmt_to_instrs (List.map (fun (x,_,_,_,_)->x) - se.postins)) - | _ -> Cil.fatal "Except expression contains unexpected statement" - end - | _ -> Cil.fatal - "Except expression contains too many statements" - in + let il' = stmt_to_instrs se.stmts in s2c (mkStmt (TryExcept (c2block b', (il', e'), c2block h', loc'))) | CODE_ANNOT (a, loc) -> let loc' = convLoc loc in @@ -7799,14 +7997,14 @@ (fun () -> let spec = Ltyping.code_annot loc' local_env.known_behaviors - (Ctype !currentReturnType) (AStmtSpec a) + (Ctype !currentReturnType) (AStmtSpec ([],a)) in s2c (mkStmtOneInstr ~ghost:local_env.is_ghost (Code_annot (spec,loc')))) (fun () -> BlockChunk.empty) "Ignoring logic code specification" ; end with _ when Cilmsg.had_errors () && continueOnError -> begin - Cilmsg.error "Ignoring statement" ; + Kernel.error "Ignoring statement" ; consLabel "booo_statement" empty (convLoc (C.get_statementloc s)) false end @@ -7825,14 +8023,6 @@ let stripParenFile file = V.visitCabsFile (new stripParenClass) file -let rename_spec = function - GVarDecl(spec,v,_) -> - (try - let alpha = Hashtbl.find alpha_renaming v.vid in - ignore (Cil.visitCilFunspec alpha spec) - with Not_found -> ()) - | _ -> () - (* Translate a file *) let convFile (f : A.file) : Cil_types.file = @@ -7852,9 +8042,13 @@ H.clear typedefs; H.clear isomorphicStructs; H.clear alpha_renaming; + Stack.clear packing_pragma_stack; + current_packing_pragma := None; + H.clear pragma_align_by_struct; + current_pragma_align := None; Logic_env.prepare_tables (); - annonCompFieldNameId := 0; - Cilmsg.debug ~level:2 "Converting CABS->CIL" ; + anonCompFieldNameId := 0; + Kernel.debug ~level:2 "Converting CABS->CIL" ; (* Setup the built-ins, but do not add their prototypes to the file *) let setupBuiltin name (resTyp, argTypes, isva) = let v = @@ -7873,7 +8067,8 @@ let doOneGlobal (ghost,(d: A.definition)) = let s = doDecl ghost true d in if isNotEmpty s then - Cil.abort "doDecl returns non-empty statement for global"; + Kernel.abort ~current:true + "doDecl returns non-empty statement for global"; (* See if this is one of the globals which we can leave alone. Increment * globalidx and see if we must leave this alone. *) if @@ -7920,7 +8115,7 @@ IH.clear callTempVars; H.clear alpha_renaming; - if false then Cilmsg.debug "Cabs2cil converted %d globals" !globalidx; + if false then Kernel.debug "Cabs2cil converted %d globals" !globalidx; (* We are done *) { fileName = fname; globals = !globals; @@ -7930,6 +8125,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../../.." +compile-command: "make -C ../../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cabs2cil.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabs2cil.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cabs2cil.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabs2cil.mli 2011-10-10 08:40:08.000000000 +0000 @@ -96,25 +96,16 @@ val convFile: Cabs.file -> Cil_types.file + +(** Name of the attribute inserted by the elaboration to prevent user blocks + from disappearing. It can be removed whenever block contracts have been + processed. *) +val frama_c_keep_block: string + (** Set this integer to the index of the global to be left in CABS form. Use -1 to disable *) val nocil: int ref -(* NB: The three flags below are controlled by Frama-C parameters. Do not - change their default value here, but in parameters.ml. *) - -(** Turn on tranformation that forces right to left - parameter evaluation order *) -val forceRLArgEval: bool ref - -(** Indicates whether we're allowed to duplicate small chunks of code. *) -val allowDuplication: bool ref - -(** Allows to have implicit cast between value returned by a function and - the lval it is assigned to. - *) -val doCollapseCallCast: bool ref - (** A hook into the code that creates temporary local vars. By default this is the identity function, but you can overwrite it if you need to change the types of cabs2cil-introduced temp variables. *) @@ -136,12 +127,10 @@ globals and starting with [prefix] *) val fresh_global : string -> string -(** CEA-LRI: exports for logic typing *) - (** Check that [s] starts with the prefix [p]. *) val prefix : string -> string -> bool -val annonCompFieldName : string +val anonCompFieldName : string val find_field_offset: (Cil_types.fieldinfo -> bool) -> Cil_types.fieldinfo list -> Cil_types.offset @@ -150,8 +139,20 @@ @raise Not_found if no such field exists. *) +(** returns the type of the result of a logic operator applied to values of + the corresponding input types. + *) val logicConditionalConversion: Cil_types.typ -> Cil_types.typ -> Cil_types.typ + +(** returns the type of the result of an arithmetic operator applied to + values of the corresponding input types. + @deprecated Nitrogen-20111001 moved to Cil module +*) val arithmeticConversion : Cil_types.typ -> Cil_types.typ -> Cil_types.typ + +(** performs the usual integral promotions mentioned in C reference manual. + @deprecated Nitrogen-20111001 moved to Cil module. +*) val integralPromotion : Cil_types.typ -> Cil_types.typ (** local information needed to typecheck expressions and statements *) @@ -198,6 +199,9 @@ in forward ingoing gotos (from the if-branch to the else-branch). *) val setDoAlternateConditional : unit -> unit +(** Raise Failure *) +val integral_cast: Cil_types.typ -> Cil_types.term -> Cil_types.term + (* Local Variables: compile-command: "make -C ../../.." diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cabscond.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabscond.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cabscond.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabscond.ml 2011-10-10 08:40:08.000000000 +0000 @@ -91,12 +91,12 @@ let inconsistent from = match !c_stack with | (_,_,loc)::_ -> - Cilmsg.warning + Kernel.warning "[%s] Inconsistent state when binding condition at %a" from Cabshelper.d_cabsloc loc ; active := false | _ -> - Cilmsg.warning + Kernel.warning "[%s] Inconsistent condition stack (no condition expression stacked)" from ; active := false diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cabshelper.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabshelper.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cabshelper.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabshelper.ml 2011-10-10 08:40:08.000000000 +0000 @@ -48,33 +48,77 @@ let currentLoc () = Errorloc.getPosition () -(* TODO: use Parameters directly as soon as dependencies issues are resolved*) - -let continueOnAnnotError = ref false - -let continue_annot_error_set () = continueOnAnnotError:=true -let continue_annot_error_unset () = continueOnAnnotError :=false let cabslu = Lexing.dummy_pos,Lexing.dummy_pos -let continue_annot l job default msg = +let continue_annot (l,_) job default msg = try Cilmsg.push_errors () ; let result = job () in if Cilmsg.had_errors () then failwith "Annotation has errors" ; Cilmsg.pop_errors () ; Log.with_null (fun _ -> result) msg ; - with exn when !continueOnAnnotError -> - Cilmsg.debug "Continue on annotation error (%s)" (Printexc.to_string exn) ; + with exn when Kernel.ContinueOnAnnotError.get () -> + Kernel.debug "Continue on annotation error (%s)" (Printexc.to_string exn) ; Cilmsg.pop_errors () ; - Cilmsg.with_warning (fun _ -> default ()) - ~source:{ - Log.src_file= (fst l).Lexing.pos_fname ; - Log.src_line= (fst l).Lexing.pos_lnum ; - } msg - -(* clexer puts comments here *) -let commentsGA = GrowArray.make 100 (GrowArray.Elem(cabslu,"",false)) + Kernel.with_warning (fun _ -> default ()) ~source:l msg +module Comments = + struct + module MyTable = + Rangemap.Make + (Cil_datatype.Position) + (Datatype.List(Datatype.Pair(Cil_datatype.Position)(Datatype.String))) + module MyState = + State_builder.Ref + (MyTable) + (struct + let name = "Cabshelper.Comments" + let dependencies = [ ] + (* depends from File.self and Ast.self which add + the dependency themselves. *) + let kind = `Internal + let default () = MyTable.empty + end) + let self = MyState.self + + (* What matters is the beginning of the comment. *) + let add (first,last) comment = + let state = MyState.get () in + let acc = try MyTable.find first state with Not_found -> [] in + MyState.set ((MyTable.add first ((last,comment)::acc)) state) + + let get (first,last) = + Kernel.debug "Searching for comments between positions %a and %a@." + Cil_datatype.Position.pretty first + Cil_datatype.Position.pretty last; + MyTable.fold_range + (fun pos -> + match Cil_datatype.Position.compare first pos with + | n when n > 0 -> Rangemap.Below + | 0 -> Rangemap.Match + | _ -> + if Cil_datatype.Position.compare pos last <= 0 then + Rangemap.Match + else + Rangemap.Above) + (fun _ comments acc -> acc @ List.rev_map snd comments) + (MyState.get ()) + [] + + let iter f = + MyTable.iter + (fun first comments -> + List.iter (fun (last,comment) -> f (first,last) comment) comments) + (MyState.get()) + + let fold f acc = + MyTable.fold + (fun first comments acc -> + List.fold_left + (fun acc (last,comment) -> f (first,last) comment acc) acc comments) + (MyState.get()) acc + +end (*********** HELPER FUNCTIONS **********) @@ -157,7 +201,7 @@ '0'..'9' -> (Char.code chr) - (Char.code '0') | 'a'..'z' -> (Char.code chr) - (Char.code 'a') + 10 | 'A'..'Z' -> (Char.code chr) - (Char.code 'A') + 10 - | _ -> Cilmsg.fatal "not a digit" + | _ -> Kernel.fatal "not a digit" in Int64.of_int int_value @@ -166,3 +210,9 @@ Format.fprintf fmt "%s:%d" (fst cl).Lexing.pos_fname (fst cl).Lexing.pos_lnum + +(* +Local Variables: +compile-command: "make -C ../../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cabshelper.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabshelper.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cabshelper.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabshelper.mli 2011-10-10 08:40:08.000000000 +0000 @@ -39,27 +39,35 @@ (* énergies alternatives). *) (**************************************************************************) -val nextident : int ref +(** Helper functions for Cabs *) -(* the three functions below should be replaced by direct calls to - Parameters.ContinueOnAnnotError but there are still dependencies issues. *) +val nextident : int ref -val continue_annot_error_set: unit -> unit -val continue_annot_error_unset: unit -> unit +(** Try do do the job. If exception and continue on error is set, catch it and + to the fallback with proper warning. -(** Try do do the job. If exception and continue on error is set, catch it and to - the fallback with proper warning. - - Usage: [continue_annot job backtrack "Ignoring foo"] -*) -val continue_annot : Cabs.cabsloc -> - (unit -> 'a) -> (unit -> 'a) -> + Usage: [continue_annot job backtrack "Ignoring foo"] *) +val continue_annot : Cabs.cabsloc -> + (unit -> 'a) -> (unit -> 'a) -> ('b,Format.formatter,unit,'a) format4 -> 'b val getident : unit -> int val currentLoc : unit -> Cabs.cabsloc val cabslu : Cabs.cabsloc -val commentsGA : (Cabs.cabsloc * string * bool) GrowArray.t + +(* List of comments together with the location where they are found. *) +module Comments: sig + val self: State.t + (* adds a comment at a given location. *) + val add: Cabs.cabsloc -> string -> unit + (* gets all the comment located between the two positions. *) + val get: Cabs.cabsloc -> string list + (* iter over all registered comments. *) + val iter: (Cabs.cabsloc -> string -> unit) -> unit + (* fold over all registered comments. *) + val fold: (Cabs.cabsloc -> string -> 'a -> 'a) -> 'a -> 'a +end + val missingFieldDecl : string * Cabs.decl_type * 'a list * Cabs.cabsloc val isStatic : Cabs.spec_elem list -> bool val isExtern : Cabs.spec_elem list -> bool diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cabsvisit.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabsvisit.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cabsvisit.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cabsvisit.ml 2011-10-10 08:40:08.000000000 +0000 @@ -160,7 +160,7 @@ match al' with [a''] when a'' == a -> se | [a''] -> SpecAttr a'' - | _ -> Cilmsg.fatal "childrenSpecElem: visitCabsAttribute returned a list" + | _ -> Kernel.fatal "childrenSpecElem: visitCabsAttribute returned a list" end | SpecType ts -> let ts' = visitCabsTypeSpecifier vis ts in @@ -321,7 +321,7 @@ let d1' = match visitCabsDefinition vis d1 with [d1'] -> d1' - | _ -> Cilmsg.fatal "visitCabs: for can have only one definition" + | _ -> Kernel.fatal "visitCabs: for can have only one definition" in if d1' != d1 then FC_DECL d1' else fc1 in diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/clexer.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/clexer.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/clexer.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/clexer.ml 2011-10-10 08:48:48.000000000 +0000 @@ -20,13 +20,7 @@ let enter_ghost_code () = ghost_code := true let exit_ghost_code () = ghost_code := false -let keepComments = ref false - -(* string -> unit *) -let addComment c = - let l = currentLoc() in - let i = GrowArray.max_init_index Cabshelper.commentsGA in - GrowArray.setg Cabshelper.commentsGA (i+1) (l,c,false) +let addComment c = Cabshelper.Comments.add (currentLoc()) c (* track whitespace for the current token *) let white = ref "" @@ -66,7 +60,7 @@ (* Some debugging support for line numbers *) let dbgToken (t: token) = if false then begin - let dprintf fmt = Cilmsg.debug fmt in + let dprintf fmt = Kernel.debug fmt in (match t with IDENT n -> dprintf "IDENT(%s)\n" n | LBRACE l -> dprintf "LBRACE(%d)\n" (fst l).Lexing.pos_lnum @@ -193,6 +187,9 @@ IDENT "__thread"); ] + +let is_c_keyword s = Hashtbl.mem lexicon s + (* Mark an identifier as a type name. The old mapping is preserved and will * be reinstated when we exit this context *) let add_type name = @@ -206,7 +203,7 @@ let pop_context _ = match !context with - [] -> Cilmsg.fatal "Empty context stack" + [] -> Kernel.fatal "Empty context stack" | con::sub -> (context := sub; List.iter (fun name -> @@ -220,7 +217,7 @@ * will be reinstated when we exit this context *) let add_identifier name = match !context with - [] -> Cilmsg.fatal "Empty context stack" + [] -> Kernel.fatal "Empty context stack" | con::sub -> (context := (name::con)::sub; (*Format.eprintf "adding IDENT for %s@." name;*) @@ -330,9 +327,15 @@ (match buffer with None -> () | Some b -> Buffer.add_char b ch) ; remainder buffer lexbuf -let do_lex_comment remainder lexbuf = +let do_lex_comment ?first_char remainder lexbuf = let buffer = - if !keepComments then Some(Buffer.create 80) else None + if Kernel.PrintComments.get () then + Some(let b = Buffer.create 80 in + (match first_char with Some c -> + Buffer.add_char b c + | None -> ()); + b) + else None in remainder buffer lexbuf ; match buffer with | Some b -> addComment (Buffer.contents b) @@ -379,6 +382,13 @@ let pragmaLine = ref false let annot_char = ref '@' + +let () = + Kernel.ReadAnnot.add_set_hook + (fun _ x -> + (* prevent the C lexer interpretation of comments *) + annot_char := if x then '@' else '\000') + let annot_start_pos = ref Cabshelper.cabslu let buf = Buffer.create 1024 @@ -389,7 +399,6 @@ let start = snd !annot_start_pos in match Logic_lexer.annot (start, s) with | Logic_ptree.Adecl d -> DECL d - | Logic_ptree.Afor_spec for_spec-> FOR_SPEC for_spec | Logic_ptree.Aspec -> SPEC (start,s) (* At this point, we only have identified a function spec. Complete parsing of the annotation will only occur in the cparser.mly rule. @@ -398,7 +407,7 @@ | Logic_ptree.Aloop_annot (loc,a) -> LOOP_ANNOT (a,loc) | Logic_ptree.Aattribute_annot (loc,a) -> ATTRIBUTE_ANNOT (a, loc) -# 402 "cil/src/frontc/clexer.ml" +# 411 "cil/src/frontc/clexer.ml" let __ocaml_lex_tables = { Lexing.lex_base = "\000\000\180\255\181\255\091\000\113\000\194\000\193\255\194\255\ @@ -1873,25 +1882,25 @@ } let rec initial lexbuf = - __ocaml_lex_initial_rec lexbuf 0 + __ocaml_lex_initial_rec lexbuf 0 and __ocaml_lex_initial_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 501 "cil/src/frontc/clexer.mll" +# 510 "cil/src/frontc/clexer.mll" ( do_lex_comment comment lexbuf ; addWhite lexbuf ; initial lexbuf ) -# 1887 "cil/src/frontc/clexer.ml" +# 1896 "cil/src/frontc/clexer.ml" | 1 -> let -# 507 "cil/src/frontc/clexer.mll" +# 516 "cil/src/frontc/clexer.mll" c -# 1893 "cil/src/frontc/clexer.ml" +# 1902 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme_char lexbuf (lexbuf.Lexing.lex_start_pos + 2) in -# 508 "cil/src/frontc/clexer.mll" +# 517 "cil/src/frontc/clexer.mll" ( if c = !annot_char then begin Cabshelper.continue_annot (currentLoc ()) @@ -1904,15 +1913,15 @@ "Skipping annotation" end else begin - do_lex_comment comment lexbuf ; + do_lex_comment ~first_char:c comment lexbuf ; addWhite lexbuf; initial lexbuf end ) -# 1913 "cil/src/frontc/clexer.ml" +# 1922 "cil/src/frontc/clexer.ml" | 2 -> -# 527 "cil/src/frontc/clexer.mll" +# 536 "cil/src/frontc/clexer.mll" ( do_lex_comment onelinecomment lexbuf ; E.newline(); if is_oneline_ghost () then begin @@ -1923,15 +1932,15 @@ initial lexbuf end ) -# 1927 "cil/src/frontc/clexer.ml" +# 1936 "cil/src/frontc/clexer.ml" | 3 -> let -# 538 "cil/src/frontc/clexer.mll" +# 547 "cil/src/frontc/clexer.mll" c -# 1933 "cil/src/frontc/clexer.ml" +# 1942 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme_char lexbuf (lexbuf.Lexing.lex_start_pos + 2) in -# 539 "cil/src/frontc/clexer.mll" +# 548 "cil/src/frontc/clexer.mll" ( if c = !annot_char then begin Cabshelper.continue_annot (currentLoc()) @@ -1943,7 +1952,7 @@ "Skipping annotation" end else begin - do_lex_comment onelinecomment lexbuf ; + do_lex_comment ~first_char:c onelinecomment lexbuf ; E.newline(); if is_oneline_ghost () then begin @@ -1957,15 +1966,15 @@ end end ) -# 1961 "cil/src/frontc/clexer.ml" +# 1970 "cil/src/frontc/clexer.ml" | 4 -> -# 564 "cil/src/frontc/clexer.mll" +# 573 "cil/src/frontc/clexer.mll" (addWhite lexbuf; initial lexbuf) -# 1966 "cil/src/frontc/clexer.ml" +# 1975 "cil/src/frontc/clexer.ml" | 5 -> -# 565 "cil/src/frontc/clexer.mll" +# 574 "cil/src/frontc/clexer.mll" ( E.newline (); if !pragmaLine then begin @@ -1981,38 +1990,38 @@ addWhite lexbuf; initial lexbuf end ) -# 1985 "cil/src/frontc/clexer.ml" +# 1994 "cil/src/frontc/clexer.ml" | 6 -> -# 580 "cil/src/frontc/clexer.mll" +# 589 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; E.newline (); initial lexbuf ) -# 1993 "cil/src/frontc/clexer.ml" +# 2002 "cil/src/frontc/clexer.ml" | 7 -> -# 584 "cil/src/frontc/clexer.mll" +# 593 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; hash lexbuf) -# 1998 "cil/src/frontc/clexer.ml" +# 2007 "cil/src/frontc/clexer.ml" | 8 -> -# 585 "cil/src/frontc/clexer.mll" +# 594 "cil/src/frontc/clexer.mll" ( PRAGMA (currentLoc ()) ) -# 2003 "cil/src/frontc/clexer.ml" +# 2012 "cil/src/frontc/clexer.ml" | 9 -> -# 586 "cil/src/frontc/clexer.mll" +# 595 "cil/src/frontc/clexer.mll" ( CST_CHAR (chr lexbuf, currentLoc ())) -# 2008 "cil/src/frontc/clexer.ml" +# 2017 "cil/src/frontc/clexer.ml" | 10 -> -# 587 "cil/src/frontc/clexer.mll" +# 596 "cil/src/frontc/clexer.mll" ( CST_WCHAR (chr lexbuf, currentLoc ()) ) -# 2013 "cil/src/frontc/clexer.ml" +# 2022 "cil/src/frontc/clexer.ml" | 11 -> -# 588 "cil/src/frontc/clexer.mll" +# 597 "cil/src/frontc/clexer.mll" ( addLexeme lexbuf; (* '"' *) (* matth: BUG: this could be either a regular string or a wide string. * e.g. if it's the "world" in @@ -2024,461 +2033,461 @@ raise (InternalError ("str: " ^ Printexc.to_string e))) -# 2028 "cil/src/frontc/clexer.ml" +# 2037 "cil/src/frontc/clexer.ml" | 12 -> -# 599 "cil/src/frontc/clexer.mll" +# 608 "cil/src/frontc/clexer.mll" ( (* weimer: wchar_t string literal *) try CST_WSTRING(str lexbuf, currentLoc ()) with e -> raise (InternalError ("wide string: " ^ Printexc.to_string e))) -# 2038 "cil/src/frontc/clexer.ml" +# 2047 "cil/src/frontc/clexer.ml" | 13 -> -# 605 "cil/src/frontc/clexer.mll" +# 614 "cil/src/frontc/clexer.mll" (CST_FLOAT (Lexing.lexeme lexbuf, currentLoc ())) -# 2043 "cil/src/frontc/clexer.ml" +# 2052 "cil/src/frontc/clexer.ml" | 14 -> -# 606 "cil/src/frontc/clexer.mll" +# 615 "cil/src/frontc/clexer.mll" (CST_INT (Lexing.lexeme lexbuf, currentLoc ())) -# 2048 "cil/src/frontc/clexer.ml" +# 2057 "cil/src/frontc/clexer.ml" | 15 -> -# 607 "cil/src/frontc/clexer.mll" +# 616 "cil/src/frontc/clexer.mll" (CST_INT (Lexing.lexeme lexbuf, currentLoc ())) -# 2053 "cil/src/frontc/clexer.ml" +# 2062 "cil/src/frontc/clexer.ml" | 16 -> -# 608 "cil/src/frontc/clexer.mll" +# 617 "cil/src/frontc/clexer.mll" (CST_INT (Lexing.lexeme lexbuf, currentLoc ())) -# 2058 "cil/src/frontc/clexer.ml" +# 2067 "cil/src/frontc/clexer.ml" | 17 -> -# 609 "cil/src/frontc/clexer.mll" +# 618 "cil/src/frontc/clexer.mll" (EOF) -# 2063 "cil/src/frontc/clexer.ml" +# 2072 "cil/src/frontc/clexer.ml" | 18 -> -# 610 "cil/src/frontc/clexer.mll" +# 619 "cil/src/frontc/clexer.mll" (ELLIPSIS) -# 2068 "cil/src/frontc/clexer.ml" +# 2077 "cil/src/frontc/clexer.ml" | 19 -> -# 611 "cil/src/frontc/clexer.mll" +# 620 "cil/src/frontc/clexer.mll" (PLUS_EQ) -# 2073 "cil/src/frontc/clexer.ml" +# 2082 "cil/src/frontc/clexer.ml" | 20 -> -# 612 "cil/src/frontc/clexer.mll" +# 621 "cil/src/frontc/clexer.mll" (MINUS_EQ) -# 2078 "cil/src/frontc/clexer.ml" +# 2087 "cil/src/frontc/clexer.ml" | 21 -> -# 613 "cil/src/frontc/clexer.mll" +# 622 "cil/src/frontc/clexer.mll" (STAR_EQ) -# 2083 "cil/src/frontc/clexer.ml" +# 2092 "cil/src/frontc/clexer.ml" | 22 -> -# 614 "cil/src/frontc/clexer.mll" +# 623 "cil/src/frontc/clexer.mll" (SLASH_EQ) -# 2088 "cil/src/frontc/clexer.ml" +# 2097 "cil/src/frontc/clexer.ml" | 23 -> -# 615 "cil/src/frontc/clexer.mll" +# 624 "cil/src/frontc/clexer.mll" (PERCENT_EQ) -# 2093 "cil/src/frontc/clexer.ml" +# 2102 "cil/src/frontc/clexer.ml" | 24 -> -# 616 "cil/src/frontc/clexer.mll" +# 625 "cil/src/frontc/clexer.mll" (PIPE_EQ) -# 2098 "cil/src/frontc/clexer.ml" +# 2107 "cil/src/frontc/clexer.ml" | 25 -> -# 617 "cil/src/frontc/clexer.mll" +# 626 "cil/src/frontc/clexer.mll" (AND_EQ) -# 2103 "cil/src/frontc/clexer.ml" +# 2112 "cil/src/frontc/clexer.ml" | 26 -> -# 618 "cil/src/frontc/clexer.mll" +# 627 "cil/src/frontc/clexer.mll" (CIRC_EQ) -# 2108 "cil/src/frontc/clexer.ml" +# 2117 "cil/src/frontc/clexer.ml" | 27 -> -# 619 "cil/src/frontc/clexer.mll" +# 628 "cil/src/frontc/clexer.mll" (INF_INF_EQ) -# 2113 "cil/src/frontc/clexer.ml" +# 2122 "cil/src/frontc/clexer.ml" | 28 -> -# 620 "cil/src/frontc/clexer.mll" +# 629 "cil/src/frontc/clexer.mll" (SUP_SUP_EQ) -# 2118 "cil/src/frontc/clexer.ml" +# 2127 "cil/src/frontc/clexer.ml" | 29 -> -# 621 "cil/src/frontc/clexer.mll" +# 630 "cil/src/frontc/clexer.mll" (INF_INF) -# 2123 "cil/src/frontc/clexer.ml" +# 2132 "cil/src/frontc/clexer.ml" | 30 -> -# 622 "cil/src/frontc/clexer.mll" +# 631 "cil/src/frontc/clexer.mll" (SUP_SUP) -# 2128 "cil/src/frontc/clexer.ml" +# 2137 "cil/src/frontc/clexer.ml" | 31 -> -# 623 "cil/src/frontc/clexer.mll" +# 632 "cil/src/frontc/clexer.mll" (EQ_EQ) -# 2133 "cil/src/frontc/clexer.ml" +# 2142 "cil/src/frontc/clexer.ml" | 32 -> -# 624 "cil/src/frontc/clexer.mll" +# 633 "cil/src/frontc/clexer.mll" (EXCLAM_EQ) -# 2138 "cil/src/frontc/clexer.ml" +# 2147 "cil/src/frontc/clexer.ml" | 33 -> -# 625 "cil/src/frontc/clexer.mll" +# 634 "cil/src/frontc/clexer.mll" (INF_EQ) -# 2143 "cil/src/frontc/clexer.ml" +# 2152 "cil/src/frontc/clexer.ml" | 34 -> -# 626 "cil/src/frontc/clexer.mll" +# 635 "cil/src/frontc/clexer.mll" (SUP_EQ) -# 2148 "cil/src/frontc/clexer.ml" +# 2157 "cil/src/frontc/clexer.ml" | 35 -> -# 627 "cil/src/frontc/clexer.mll" +# 636 "cil/src/frontc/clexer.mll" (EQ) -# 2153 "cil/src/frontc/clexer.ml" +# 2162 "cil/src/frontc/clexer.ml" | 36 -> -# 628 "cil/src/frontc/clexer.mll" +# 637 "cil/src/frontc/clexer.mll" (INF) -# 2158 "cil/src/frontc/clexer.ml" +# 2167 "cil/src/frontc/clexer.ml" | 37 -> -# 629 "cil/src/frontc/clexer.mll" +# 638 "cil/src/frontc/clexer.mll" (SUP) -# 2163 "cil/src/frontc/clexer.ml" +# 2172 "cil/src/frontc/clexer.ml" | 38 -> -# 630 "cil/src/frontc/clexer.mll" +# 639 "cil/src/frontc/clexer.mll" (PLUS_PLUS (currentLoc ())) -# 2168 "cil/src/frontc/clexer.ml" +# 2177 "cil/src/frontc/clexer.ml" | 39 -> -# 631 "cil/src/frontc/clexer.mll" +# 640 "cil/src/frontc/clexer.mll" (MINUS_MINUS (currentLoc ())) -# 2173 "cil/src/frontc/clexer.ml" +# 2182 "cil/src/frontc/clexer.ml" | 40 -> -# 632 "cil/src/frontc/clexer.mll" +# 641 "cil/src/frontc/clexer.mll" (ARROW) -# 2178 "cil/src/frontc/clexer.ml" +# 2187 "cil/src/frontc/clexer.ml" | 41 -> -# 633 "cil/src/frontc/clexer.mll" +# 642 "cil/src/frontc/clexer.mll" (PLUS (currentLoc ())) -# 2183 "cil/src/frontc/clexer.ml" +# 2192 "cil/src/frontc/clexer.ml" | 42 -> -# 634 "cil/src/frontc/clexer.mll" +# 643 "cil/src/frontc/clexer.mll" (MINUS (currentLoc ())) -# 2188 "cil/src/frontc/clexer.ml" +# 2197 "cil/src/frontc/clexer.ml" | 43 -> -# 636 "cil/src/frontc/clexer.mll" +# 645 "cil/src/frontc/clexer.mll" ( if is_ghost_code () then might_end_ghost lexbuf else STAR (currentLoc ())) -# 2195 "cil/src/frontc/clexer.ml" +# 2204 "cil/src/frontc/clexer.ml" | 44 -> -# 639 "cil/src/frontc/clexer.mll" +# 648 "cil/src/frontc/clexer.mll" (SLASH) -# 2200 "cil/src/frontc/clexer.ml" +# 2209 "cil/src/frontc/clexer.ml" | 45 -> -# 640 "cil/src/frontc/clexer.mll" +# 649 "cil/src/frontc/clexer.mll" (PERCENT) -# 2205 "cil/src/frontc/clexer.ml" +# 2214 "cil/src/frontc/clexer.ml" | 46 -> -# 641 "cil/src/frontc/clexer.mll" +# 650 "cil/src/frontc/clexer.mll" (EXCLAM (currentLoc ())) -# 2210 "cil/src/frontc/clexer.ml" +# 2219 "cil/src/frontc/clexer.ml" | 47 -> -# 642 "cil/src/frontc/clexer.mll" +# 651 "cil/src/frontc/clexer.mll" (AND_AND (currentLoc ())) -# 2215 "cil/src/frontc/clexer.ml" +# 2224 "cil/src/frontc/clexer.ml" | 48 -> -# 643 "cil/src/frontc/clexer.mll" +# 652 "cil/src/frontc/clexer.mll" (PIPE_PIPE) -# 2220 "cil/src/frontc/clexer.ml" +# 2229 "cil/src/frontc/clexer.ml" | 49 -> -# 644 "cil/src/frontc/clexer.mll" +# 653 "cil/src/frontc/clexer.mll" (AND (currentLoc ())) -# 2225 "cil/src/frontc/clexer.ml" +# 2234 "cil/src/frontc/clexer.ml" | 50 -> -# 645 "cil/src/frontc/clexer.mll" +# 654 "cil/src/frontc/clexer.mll" (PIPE) -# 2230 "cil/src/frontc/clexer.ml" +# 2239 "cil/src/frontc/clexer.ml" | 51 -> -# 646 "cil/src/frontc/clexer.mll" +# 655 "cil/src/frontc/clexer.mll" (CIRC) -# 2235 "cil/src/frontc/clexer.ml" +# 2244 "cil/src/frontc/clexer.ml" | 52 -> -# 647 "cil/src/frontc/clexer.mll" +# 656 "cil/src/frontc/clexer.mll" (QUEST) -# 2240 "cil/src/frontc/clexer.ml" +# 2249 "cil/src/frontc/clexer.ml" | 53 -> -# 648 "cil/src/frontc/clexer.mll" +# 657 "cil/src/frontc/clexer.mll" (COLON) -# 2245 "cil/src/frontc/clexer.ml" +# 2254 "cil/src/frontc/clexer.ml" | 54 -> -# 649 "cil/src/frontc/clexer.mll" +# 658 "cil/src/frontc/clexer.mll" (TILDE (currentLoc ())) -# 2250 "cil/src/frontc/clexer.ml" +# 2259 "cil/src/frontc/clexer.ml" | 55 -> -# 651 "cil/src/frontc/clexer.mll" +# 660 "cil/src/frontc/clexer.mll" (dbgToken (LBRACE (currentLoc ()))) -# 2255 "cil/src/frontc/clexer.ml" +# 2264 "cil/src/frontc/clexer.ml" | 56 -> -# 652 "cil/src/frontc/clexer.mll" +# 661 "cil/src/frontc/clexer.mll" (dbgToken (RBRACE (currentLoc ()))) -# 2260 "cil/src/frontc/clexer.ml" +# 2269 "cil/src/frontc/clexer.ml" | 57 -> -# 653 "cil/src/frontc/clexer.mll" +# 662 "cil/src/frontc/clexer.mll" (LBRACKET) -# 2265 "cil/src/frontc/clexer.ml" +# 2274 "cil/src/frontc/clexer.ml" | 58 -> -# 654 "cil/src/frontc/clexer.mll" +# 663 "cil/src/frontc/clexer.mll" (RBRACKET) -# 2270 "cil/src/frontc/clexer.ml" +# 2279 "cil/src/frontc/clexer.ml" | 59 -> -# 655 "cil/src/frontc/clexer.mll" +# 664 "cil/src/frontc/clexer.mll" (dbgToken (LPAREN (currentLoc ())) ) -# 2275 "cil/src/frontc/clexer.ml" +# 2284 "cil/src/frontc/clexer.ml" | 60 -> -# 656 "cil/src/frontc/clexer.mll" +# 665 "cil/src/frontc/clexer.mll" (RPAREN) -# 2280 "cil/src/frontc/clexer.ml" +# 2289 "cil/src/frontc/clexer.ml" | 61 -> -# 657 "cil/src/frontc/clexer.mll" +# 666 "cil/src/frontc/clexer.mll" (dbgToken (SEMICOLON (currentLoc ())) ) -# 2285 "cil/src/frontc/clexer.ml" +# 2294 "cil/src/frontc/clexer.ml" | 62 -> -# 658 "cil/src/frontc/clexer.mll" +# 667 "cil/src/frontc/clexer.mll" (COMMA) -# 2290 "cil/src/frontc/clexer.ml" +# 2299 "cil/src/frontc/clexer.ml" | 63 -> -# 659 "cil/src/frontc/clexer.mll" +# 668 "cil/src/frontc/clexer.mll" (DOT) -# 2295 "cil/src/frontc/clexer.ml" +# 2304 "cil/src/frontc/clexer.ml" | 64 -> -# 660 "cil/src/frontc/clexer.mll" +# 669 "cil/src/frontc/clexer.mll" (SIZEOF (currentLoc ())) -# 2300 "cil/src/frontc/clexer.ml" +# 2309 "cil/src/frontc/clexer.ml" | 65 -> -# 661 "cil/src/frontc/clexer.mll" +# 670 "cil/src/frontc/clexer.mll" ( if !Cprint.msvcMode then MSASM (msasm lexbuf, currentLoc ()) else (ASM (currentLoc ())) ) -# 2307 "cil/src/frontc/clexer.ml" +# 2316 "cil/src/frontc/clexer.ml" | 66 -> -# 666 "cil/src/frontc/clexer.mll" +# 675 "cil/src/frontc/clexer.mll" ( matchingParsOpen := 0; let _ = matchingpars lexbuf in addWhite lexbuf; initial lexbuf ) -# 2316 "cil/src/frontc/clexer.ml" +# 2325 "cil/src/frontc/clexer.ml" | 67 -> -# 673 "cil/src/frontc/clexer.mll" +# 682 "cil/src/frontc/clexer.mll" (AT_TRANSFORM (currentLoc ())) -# 2321 "cil/src/frontc/clexer.ml" +# 2330 "cil/src/frontc/clexer.ml" | 68 -> -# 674 "cil/src/frontc/clexer.mll" +# 683 "cil/src/frontc/clexer.mll" (AT_TRANSFORMEXPR (currentLoc ())) -# 2326 "cil/src/frontc/clexer.ml" +# 2335 "cil/src/frontc/clexer.ml" | 69 -> -# 675 "cil/src/frontc/clexer.mll" +# 684 "cil/src/frontc/clexer.mll" (AT_SPECIFIER (currentLoc ())) -# 2331 "cil/src/frontc/clexer.ml" +# 2340 "cil/src/frontc/clexer.ml" | 70 -> -# 676 "cil/src/frontc/clexer.mll" +# 685 "cil/src/frontc/clexer.mll" (AT_EXPR (currentLoc ())) -# 2336 "cil/src/frontc/clexer.ml" +# 2345 "cil/src/frontc/clexer.ml" | 71 -> -# 677 "cil/src/frontc/clexer.mll" +# 686 "cil/src/frontc/clexer.mll" (AT_NAME) -# 2341 "cil/src/frontc/clexer.ml" +# 2350 "cil/src/frontc/clexer.ml" | 72 -> -# 681 "cil/src/frontc/clexer.mll" +# 690 "cil/src/frontc/clexer.mll" (addWhite lexbuf; initial lexbuf ) -# 2346 "cil/src/frontc/clexer.ml" +# 2355 "cil/src/frontc/clexer.ml" | 73 -> -# 682 "cil/src/frontc/clexer.mll" +# 691 "cil/src/frontc/clexer.mll" (scan_ident (Lexing.lexeme lexbuf)) -# 2351 "cil/src/frontc/clexer.ml" +# 2360 "cil/src/frontc/clexer.ml" | 74 -> -# 684 "cil/src/frontc/clexer.mll" +# 693 "cil/src/frontc/clexer.mll" ( if is_oneline_ghost() then begin exit_oneline_ghost (); RGHOST end else EOF ) -# 2360 "cil/src/frontc/clexer.ml" +# 2369 "cil/src/frontc/clexer.ml" | 75 -> -# 689 "cil/src/frontc/clexer.mll" +# 698 "cil/src/frontc/clexer.mll" (E.parse_error "Invalid symbol") -# 2365 "cil/src/frontc/clexer.ml" +# 2374 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_initial_rec lexbuf __ocaml_lex_state and might_end_ghost lexbuf = - __ocaml_lex_might_end_ghost_rec lexbuf 188 + __ocaml_lex_might_end_ghost_rec lexbuf 188 and __ocaml_lex_might_end_ghost_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 692 "cil/src/frontc/clexer.mll" +# 701 "cil/src/frontc/clexer.mll" ( exit_ghost_code(); RGHOST ) -# 2376 "cil/src/frontc/clexer.ml" +# 2385 "cil/src/frontc/clexer.ml" | 1 -> -# 693 "cil/src/frontc/clexer.mll" +# 702 "cil/src/frontc/clexer.mll" ( STAR (currentLoc()) ) -# 2381 "cil/src/frontc/clexer.ml" +# 2390 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_might_end_ghost_rec lexbuf __ocaml_lex_state and comment buffer lexbuf = - __ocaml_lex_comment_rec buffer lexbuf 190 + __ocaml_lex_comment_rec buffer lexbuf 190 and __ocaml_lex_comment_rec buffer lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 696 "cil/src/frontc/clexer.mll" +# 705 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; ) -# 2392 "cil/src/frontc/clexer.ml" +# 2401 "cil/src/frontc/clexer.ml" | 1 -> -# 697 "cil/src/frontc/clexer.mll" +# 706 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; lex_comment comment buffer lexbuf ) -# 2397 "cil/src/frontc/clexer.ml" +# 2406 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_comment_rec buffer lexbuf __ocaml_lex_state and onelinecomment buffer lexbuf = - __ocaml_lex_onelinecomment_rec buffer lexbuf 194 + __ocaml_lex_onelinecomment_rec buffer lexbuf 194 and __ocaml_lex_onelinecomment_rec buffer lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 700 "cil/src/frontc/clexer.mll" +# 709 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; ) -# 2408 "cil/src/frontc/clexer.ml" +# 2417 "cil/src/frontc/clexer.ml" | 1 -> -# 701 "cil/src/frontc/clexer.mll" +# 710 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; lex_comment onelinecomment buffer lexbuf ) -# 2413 "cil/src/frontc/clexer.ml" +# 2422 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_onelinecomment_rec buffer lexbuf __ocaml_lex_state and matchingpars lexbuf = - __ocaml_lex_matchingpars_rec lexbuf 197 + __ocaml_lex_matchingpars_rec lexbuf 197 and __ocaml_lex_matchingpars_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 704 "cil/src/frontc/clexer.mll" +# 713 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; E.newline (); matchingpars lexbuf ) -# 2424 "cil/src/frontc/clexer.ml" +# 2433 "cil/src/frontc/clexer.ml" | 1 -> -# 705 "cil/src/frontc/clexer.mll" +# 714 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; matchingpars lexbuf ) -# 2429 "cil/src/frontc/clexer.ml" +# 2438 "cil/src/frontc/clexer.ml" | 2 -> -# 706 "cil/src/frontc/clexer.mll" +# 715 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; incr matchingParsOpen; matchingpars lexbuf ) -# 2434 "cil/src/frontc/clexer.ml" +# 2443 "cil/src/frontc/clexer.ml" | 3 -> -# 707 "cil/src/frontc/clexer.mll" +# 716 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; decr matchingParsOpen; if !matchingParsOpen = 0 then () else matchingpars lexbuf ) -# 2444 "cil/src/frontc/clexer.ml" +# 2453 "cil/src/frontc/clexer.ml" | 4 -> -# 713 "cil/src/frontc/clexer.mll" +# 722 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; do_lex_comment comment lexbuf ; matchingpars lexbuf ) -# 2451 "cil/src/frontc/clexer.ml" +# 2460 "cil/src/frontc/clexer.ml" | 5 -> -# 716 "cil/src/frontc/clexer.mll" +# 725 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; (* '"' *) let _ = str lexbuf in matchingpars lexbuf ) -# 2458 "cil/src/frontc/clexer.ml" +# 2467 "cil/src/frontc/clexer.ml" | 6 -> -# 719 "cil/src/frontc/clexer.mll" +# 728 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; matchingpars lexbuf ) -# 2463 "cil/src/frontc/clexer.ml" +# 2472 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_matchingpars_rec lexbuf __ocaml_lex_state and hash lexbuf = -lexbuf.Lexing.lex_mem <- Array.create 2 (-1) ; __ocaml_lex_hash_rec lexbuf 206 + lexbuf.Lexing.lex_mem <- Array.create 2 (-1) ; __ocaml_lex_hash_rec lexbuf 206 and __ocaml_lex_hash_rec lexbuf __ocaml_lex_state = match Lexing.new_engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 723 "cil/src/frontc/clexer.mll" +# 732 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; E.newline (); initial lexbuf) -# 2474 "cil/src/frontc/clexer.ml" +# 2483 "cil/src/frontc/clexer.ml" | 1 -> -# 724 "cil/src/frontc/clexer.mll" +# 733 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; hash lexbuf) -# 2479 "cil/src/frontc/clexer.ml" +# 2488 "cil/src/frontc/clexer.ml" | 2 -> -# 725 "cil/src/frontc/clexer.mll" +# 734 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; (* We are seeing a line number. This is the number for the * next line *) let s = Lexing.lexeme lexbuf in @@ -2486,372 +2495,372 @@ int_of_string s with Failure ("int_of_string") -> (* the int is too big. *) - Cilmsg.warning "Bad line number in preprocessed file: %s" s; + Kernel.warning "Bad line number in preprocessed file: %s" s; (-1) in E.setCurrentLine (lineno - 1); (* A file name may follow *) file lexbuf ) -# 2496 "cil/src/frontc/clexer.ml" +# 2505 "cil/src/frontc/clexer.ml" | 3 -> -# 738 "cil/src/frontc/clexer.mll" +# 747 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; hash lexbuf ) -# 2501 "cil/src/frontc/clexer.ml" +# 2510 "cil/src/frontc/clexer.ml" | 4 -> let -# 741 "cil/src/frontc/clexer.mll" +# 750 "cil/src/frontc/clexer.mll" pragmaName -# 2507 "cil/src/frontc/clexer.ml" +# 2516 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_mem.(0) lexbuf.Lexing.lex_curr_pos in -# 742 "cil/src/frontc/clexer.mll" +# 751 "cil/src/frontc/clexer.mll" ( let here = currentLoc () in PRAGMA_LINE (pragmaName ^ pragma lexbuf, here) ) -# 2513 "cil/src/frontc/clexer.ml" +# 2522 "cil/src/frontc/clexer.ml" | 5 -> -# 745 "cil/src/frontc/clexer.mll" +# 754 "cil/src/frontc/clexer.mll" ( pragmaLine := true; PRAGMA (currentLoc ()) ) -# 2518 "cil/src/frontc/clexer.ml" +# 2527 "cil/src/frontc/clexer.ml" | 6 -> -# 746 "cil/src/frontc/clexer.mll" +# 755 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; endline lexbuf) -# 2523 "cil/src/frontc/clexer.ml" +# 2532 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_hash_rec lexbuf __ocaml_lex_state and file lexbuf = - __ocaml_lex_file_rec lexbuf 313 + __ocaml_lex_file_rec lexbuf 313 and __ocaml_lex_file_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 749 "cil/src/frontc/clexer.mll" +# 758 "cil/src/frontc/clexer.mll" (addWhite lexbuf; E.newline (); initial lexbuf) -# 2534 "cil/src/frontc/clexer.ml" +# 2543 "cil/src/frontc/clexer.ml" | 1 -> -# 750 "cil/src/frontc/clexer.mll" +# 759 "cil/src/frontc/clexer.mll" (addWhite lexbuf; file lexbuf) -# 2539 "cil/src/frontc/clexer.ml" +# 2548 "cil/src/frontc/clexer.ml" | 2 -> -# 751 "cil/src/frontc/clexer.mll" +# 760 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; (* '"' *) let n = Lexing.lexeme lexbuf in let n1 = String.sub n 1 ((String.length n) - 2) in E.setCurrentFile n1; endline lexbuf) -# 2549 "cil/src/frontc/clexer.ml" +# 2558 "cil/src/frontc/clexer.ml" | 3 -> -# 758 "cil/src/frontc/clexer.mll" +# 767 "cil/src/frontc/clexer.mll" (addWhite lexbuf; endline lexbuf) -# 2554 "cil/src/frontc/clexer.ml" +# 2563 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_file_rec lexbuf __ocaml_lex_state and endline lexbuf = - __ocaml_lex_endline_rec lexbuf 320 + __ocaml_lex_endline_rec lexbuf 320 and __ocaml_lex_endline_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 761 "cil/src/frontc/clexer.mll" +# 770 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; E.newline (); initial lexbuf) -# 2565 "cil/src/frontc/clexer.ml" +# 2574 "cil/src/frontc/clexer.ml" | 1 -> -# 762 "cil/src/frontc/clexer.mll" +# 771 "cil/src/frontc/clexer.mll" ( EOF ) -# 2570 "cil/src/frontc/clexer.ml" +# 2579 "cil/src/frontc/clexer.ml" | 2 -> -# 763 "cil/src/frontc/clexer.mll" +# 772 "cil/src/frontc/clexer.mll" ( addWhite lexbuf; endline lexbuf) -# 2575 "cil/src/frontc/clexer.ml" +# 2584 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_endline_rec lexbuf __ocaml_lex_state and pragma lexbuf = - __ocaml_lex_pragma_rec lexbuf 324 + __ocaml_lex_pragma_rec lexbuf 324 and __ocaml_lex_pragma_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 766 "cil/src/frontc/clexer.mll" +# 775 "cil/src/frontc/clexer.mll" ( E.newline (); "" ) -# 2586 "cil/src/frontc/clexer.ml" +# 2595 "cil/src/frontc/clexer.ml" | 1 -> -# 767 "cil/src/frontc/clexer.mll" +# 776 "cil/src/frontc/clexer.mll" ( let cur = Lexing.lexeme lexbuf in cur ^ (pragma lexbuf) ) -# 2592 "cil/src/frontc/clexer.ml" +# 2601 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_pragma_rec lexbuf __ocaml_lex_state and str lexbuf = - __ocaml_lex_str_rec lexbuf 327 + __ocaml_lex_str_rec lexbuf 327 and __ocaml_lex_str_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 771 "cil/src/frontc/clexer.mll" +# 780 "cil/src/frontc/clexer.mll" ([]) -# 2603 "cil/src/frontc/clexer.ml" +# 2612 "cil/src/frontc/clexer.ml" | 1 -> -# 772 "cil/src/frontc/clexer.mll" +# 781 "cil/src/frontc/clexer.mll" (addLexeme lexbuf; lex_hex_escape str lexbuf) -# 2608 "cil/src/frontc/clexer.ml" +# 2617 "cil/src/frontc/clexer.ml" | 2 -> -# 773 "cil/src/frontc/clexer.mll" +# 782 "cil/src/frontc/clexer.mll" (addLexeme lexbuf; lex_oct_escape str lexbuf) -# 2613 "cil/src/frontc/clexer.ml" +# 2622 "cil/src/frontc/clexer.ml" | 3 -> -# 774 "cil/src/frontc/clexer.mll" +# 783 "cil/src/frontc/clexer.mll" (addLexeme lexbuf; lex_simple_escape str lexbuf) -# 2618 "cil/src/frontc/clexer.ml" +# 2627 "cil/src/frontc/clexer.ml" | 4 -> -# 775 "cil/src/frontc/clexer.mll" +# 784 "cil/src/frontc/clexer.mll" (E.parse_error "unterminated string" ) -# 2623 "cil/src/frontc/clexer.ml" +# 2632 "cil/src/frontc/clexer.ml" | 5 -> -# 776 "cil/src/frontc/clexer.mll" +# 785 "cil/src/frontc/clexer.mll" (addLexeme lexbuf; lex_unescaped str lexbuf) -# 2628 "cil/src/frontc/clexer.ml" +# 2637 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_str_rec lexbuf __ocaml_lex_state and chr lexbuf = - __ocaml_lex_chr_rec lexbuf 338 + __ocaml_lex_chr_rec lexbuf 338 and __ocaml_lex_chr_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 779 "cil/src/frontc/clexer.mll" +# 788 "cil/src/frontc/clexer.mll" ([]) -# 2639 "cil/src/frontc/clexer.ml" +# 2648 "cil/src/frontc/clexer.ml" | 1 -> -# 780 "cil/src/frontc/clexer.mll" +# 789 "cil/src/frontc/clexer.mll" (lex_hex_escape chr lexbuf) -# 2644 "cil/src/frontc/clexer.ml" +# 2653 "cil/src/frontc/clexer.ml" | 2 -> -# 781 "cil/src/frontc/clexer.mll" +# 790 "cil/src/frontc/clexer.mll" (lex_oct_escape chr lexbuf) -# 2649 "cil/src/frontc/clexer.ml" +# 2658 "cil/src/frontc/clexer.ml" | 3 -> -# 782 "cil/src/frontc/clexer.mll" +# 791 "cil/src/frontc/clexer.mll" (lex_simple_escape chr lexbuf) -# 2654 "cil/src/frontc/clexer.ml" +# 2663 "cil/src/frontc/clexer.ml" | 4 -> -# 783 "cil/src/frontc/clexer.mll" +# 792 "cil/src/frontc/clexer.mll" ( E.parse_error "unterminated char" ) -# 2659 "cil/src/frontc/clexer.ml" +# 2668 "cil/src/frontc/clexer.ml" | 5 -> -# 784 "cil/src/frontc/clexer.mll" +# 793 "cil/src/frontc/clexer.mll" (lex_unescaped chr lexbuf) -# 2664 "cil/src/frontc/clexer.ml" +# 2673 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_chr_rec lexbuf __ocaml_lex_state and msasm lexbuf = - __ocaml_lex_msasm_rec lexbuf 349 + __ocaml_lex_msasm_rec lexbuf 349 and __ocaml_lex_msasm_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 787 "cil/src/frontc/clexer.mll" +# 796 "cil/src/frontc/clexer.mll" ( msasm lexbuf ) -# 2675 "cil/src/frontc/clexer.ml" +# 2684 "cil/src/frontc/clexer.ml" | 1 -> -# 788 "cil/src/frontc/clexer.mll" +# 797 "cil/src/frontc/clexer.mll" ( msasminbrace lexbuf ) -# 2680 "cil/src/frontc/clexer.ml" +# 2689 "cil/src/frontc/clexer.ml" | 2 -> -# 789 "cil/src/frontc/clexer.mll" +# 798 "cil/src/frontc/clexer.mll" ( let cur = Lexing.lexeme lexbuf in cur ^ (msasmnobrace lexbuf) ) -# 2686 "cil/src/frontc/clexer.ml" +# 2695 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_msasm_rec lexbuf __ocaml_lex_state and msasminbrace lexbuf = - __ocaml_lex_msasminbrace_rec lexbuf 353 + __ocaml_lex_msasminbrace_rec lexbuf 353 and __ocaml_lex_msasminbrace_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 793 "cil/src/frontc/clexer.mll" +# 802 "cil/src/frontc/clexer.mll" ( "" ) -# 2697 "cil/src/frontc/clexer.ml" +# 2706 "cil/src/frontc/clexer.ml" | 1 -> -# 794 "cil/src/frontc/clexer.mll" +# 803 "cil/src/frontc/clexer.mll" ( let cur = Lexing.lexeme lexbuf in cur ^ (msasminbrace lexbuf) ) -# 2703 "cil/src/frontc/clexer.ml" +# 2712 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_msasminbrace_rec lexbuf __ocaml_lex_state and msasmnobrace lexbuf = - __ocaml_lex_msasmnobrace_rec lexbuf 356 + __ocaml_lex_msasmnobrace_rec lexbuf 356 and __ocaml_lex_msasmnobrace_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 797 "cil/src/frontc/clexer.mll" +# 806 "cil/src/frontc/clexer.mll" ( lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - 1; "" ) -# 2716 "cil/src/frontc/clexer.ml" +# 2725 "cil/src/frontc/clexer.ml" | 1 -> -# 800 "cil/src/frontc/clexer.mll" +# 809 "cil/src/frontc/clexer.mll" ( lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - 5; "" ) -# 2723 "cil/src/frontc/clexer.ml" +# 2732 "cil/src/frontc/clexer.ml" | 2 -> -# 803 "cil/src/frontc/clexer.mll" +# 812 "cil/src/frontc/clexer.mll" ( let cur = Lexing.lexeme lexbuf in cur ^ (msasmnobrace lexbuf) ) -# 2730 "cil/src/frontc/clexer.ml" +# 2739 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_msasmnobrace_rec lexbuf __ocaml_lex_state and annot_first_token lexbuf = - __ocaml_lex_annot_first_token_rec lexbuf 364 + __ocaml_lex_annot_first_token_rec lexbuf 364 and __ocaml_lex_annot_first_token_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 808 "cil/src/frontc/clexer.mll" +# 817 "cil/src/frontc/clexer.mll" ( if is_oneline_ghost () then E.parse_error "nested ghost code"; Buffer.clear buf; enter_ghost_code (); LGHOST ) -# 2746 "cil/src/frontc/clexer.ml" +# 2755 "cil/src/frontc/clexer.ml" | 1 -> let -# 814 "cil/src/frontc/clexer.mll" +# 823 "cil/src/frontc/clexer.mll" c -# 2752 "cil/src/frontc/clexer.ml" +# 2761 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 814 "cil/src/frontc/clexer.mll" +# 823 "cil/src/frontc/clexer.mll" ( Buffer.add_char buf c; annot_first_token lexbuf ) -# 2756 "cil/src/frontc/clexer.ml" +# 2765 "cil/src/frontc/clexer.ml" | 2 -> -# 815 "cil/src/frontc/clexer.mll" +# 824 "cil/src/frontc/clexer.mll" ( E.newline(); Buffer.add_char buf '\n'; annot_first_token lexbuf ) -# 2761 "cil/src/frontc/clexer.ml" +# 2770 "cil/src/frontc/clexer.ml" | 3 -> -# 816 "cil/src/frontc/clexer.mll" +# 825 "cil/src/frontc/clexer.mll" ( annot_token lexbuf ) -# 2766 "cil/src/frontc/clexer.ml" +# 2775 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_annot_first_token_rec lexbuf __ocaml_lex_state and annot_token lexbuf = - __ocaml_lex_annot_token_rec lexbuf 372 + __ocaml_lex_annot_token_rec lexbuf 372 and __ocaml_lex_annot_token_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 818 "cil/src/frontc/clexer.mll" +# 827 "cil/src/frontc/clexer.mll" ( let s = Buffer.contents buf in make_annot s ) -# 2778 "cil/src/frontc/clexer.ml" +# 2787 "cil/src/frontc/clexer.ml" | 1 -> -# 820 "cil/src/frontc/clexer.mll" +# 829 "cil/src/frontc/clexer.mll" ( E.parse_error "Unterminated annotation" ) -# 2783 "cil/src/frontc/clexer.ml" +# 2792 "cil/src/frontc/clexer.ml" | 2 -> -# 821 "cil/src/frontc/clexer.mll" +# 830 "cil/src/frontc/clexer.mll" (E.newline(); Buffer.add_char buf '\n'; annot_token lexbuf ) -# 2788 "cil/src/frontc/clexer.ml" +# 2797 "cil/src/frontc/clexer.ml" | 3 -> let -# 822 "cil/src/frontc/clexer.mll" +# 831 "cil/src/frontc/clexer.mll" c -# 2794 "cil/src/frontc/clexer.ml" +# 2803 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 822 "cil/src/frontc/clexer.mll" +# 831 "cil/src/frontc/clexer.mll" ( Buffer.add_char buf c; annot_token lexbuf ) -# 2798 "cil/src/frontc/clexer.ml" +# 2807 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_annot_token_rec lexbuf __ocaml_lex_state and annot_one_line lexbuf = - __ocaml_lex_annot_one_line_rec lexbuf 378 + __ocaml_lex_annot_one_line_rec lexbuf 378 and __ocaml_lex_annot_one_line_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 825 "cil/src/frontc/clexer.mll" +# 834 "cil/src/frontc/clexer.mll" ( if is_oneline_ghost () then E.parse_error "nested ghost code"; enter_oneline_ghost (); LGHOST ) -# 2812 "cil/src/frontc/clexer.ml" +# 2821 "cil/src/frontc/clexer.ml" | 1 -> let -# 829 "cil/src/frontc/clexer.mll" +# 838 "cil/src/frontc/clexer.mll" c -# 2818 "cil/src/frontc/clexer.ml" +# 2827 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 829 "cil/src/frontc/clexer.mll" +# 838 "cil/src/frontc/clexer.mll" ( Buffer.add_char buf c; annot_one_line lexbuf ) -# 2822 "cil/src/frontc/clexer.ml" +# 2831 "cil/src/frontc/clexer.ml" | 2 -> -# 830 "cil/src/frontc/clexer.mll" +# 839 "cil/src/frontc/clexer.mll" ( annot_one_line_logic lexbuf ) -# 2827 "cil/src/frontc/clexer.ml" +# 2836 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_annot_one_line_rec lexbuf __ocaml_lex_state and annot_one_line_logic lexbuf = - __ocaml_lex_annot_one_line_logic_rec lexbuf 385 + __ocaml_lex_annot_one_line_logic_rec lexbuf 385 and __ocaml_lex_annot_one_line_logic_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 832 "cil/src/frontc/clexer.mll" +# 841 "cil/src/frontc/clexer.mll" ( E.newline (); make_annot (Buffer.contents buf) ) -# 2838 "cil/src/frontc/clexer.ml" +# 2847 "cil/src/frontc/clexer.ml" | 1 -> let -# 833 "cil/src/frontc/clexer.mll" +# 842 "cil/src/frontc/clexer.mll" c -# 2844 "cil/src/frontc/clexer.ml" +# 2853 "cil/src/frontc/clexer.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 833 "cil/src/frontc/clexer.mll" +# 842 "cil/src/frontc/clexer.mll" ( Buffer.add_char buf c; annot_one_line_logic lexbuf ) -# 2848 "cil/src/frontc/clexer.ml" +# 2857 "cil/src/frontc/clexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_annot_one_line_logic_rec lexbuf __ocaml_lex_state ;; -# 835 "cil/src/frontc/clexer.mll" +# 844 "cil/src/frontc/clexer.mll" -# 2858 "cil/src/frontc/clexer.ml" +# 2867 "cil/src/frontc/clexer.ml" diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/clexer.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/clexer.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/clexer.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/clexer.mli 2011-10-10 08:40:08.000000000 +0000 @@ -39,24 +39,35 @@ (* énergies alternatives). *) (**************************************************************************) -val keepComments : bool ref +(** The C Lexer. *) val init: filename:string -> Lexing.lexbuf val finish: unit -> unit -(* This is the main parser function *) val initial: Lexing.lexbuf -> Cparser.token +(** This is the main lexing function *) +val push_context: unit -> unit +(** Start a context *) -val push_context: unit -> unit (* Start a context *) -val add_type: string -> unit (* Add a new string as a type name *) -val add_identifier: string -> unit (* Add a new string as a variable name *) -val pop_context: unit -> unit (* Remove all names added in this context *) +val add_type: string -> unit +(** Add a new string as a type name *) -val annot_char : char ref (* The character to recognize logic formulae in comments *) +val add_identifier: string -> unit +(** Add a new string as a variable name *) + +val pop_context: unit -> unit +(** Remove all names added in this context *) + +val annot_char : char ref +(** The character to recognize logic formulae in comments *) val get_white: unit -> string val get_extra_lexeme: unit -> string val clear_white: unit -> unit val clear_lexeme: unit -> unit val currentLoc : unit -> Cabs.cabsloc + +val is_c_keyword: string -> bool +(** [true] if the given string is a C keyword. + @since Nitrogen-20111001 *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/clexer.mll frama-c-20111001+nitrogen+dfsg/cil/src/frontc/clexer.mll --- frama-c-20110201+carbon+dfsg/cil/src/frontc/clexer.mll 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/clexer.mll 2011-10-10 08:40:08.000000000 +0000 @@ -65,13 +65,7 @@ let enter_ghost_code () = ghost_code := true let exit_ghost_code () = ghost_code := false -let keepComments = ref false - -(* string -> unit *) -let addComment c = - let l = currentLoc() in - let i = GrowArray.max_init_index Cabshelper.commentsGA in - GrowArray.setg Cabshelper.commentsGA (i+1) (l,c,false) +let addComment c = Cabshelper.Comments.add (currentLoc()) c (* track whitespace for the current token *) let white = ref "" @@ -111,7 +105,7 @@ (* Some debugging support for line numbers *) let dbgToken (t: token) = if false then begin - let dprintf fmt = Cilmsg.debug fmt in + let dprintf fmt = Kernel.debug fmt in (match t with IDENT n -> dprintf "IDENT(%s)\n" n | LBRACE l -> dprintf "LBRACE(%d)\n" (fst l).Lexing.pos_lnum @@ -238,6 +232,9 @@ IDENT "__thread"); ] + +let is_c_keyword s = Hashtbl.mem lexicon s + (* Mark an identifier as a type name. The old mapping is preserved and will * be reinstated when we exit this context *) let add_type name = @@ -251,7 +248,7 @@ let pop_context _ = match !context with - [] -> Cilmsg.fatal "Empty context stack" + [] -> Kernel.fatal "Empty context stack" | con::sub -> (context := sub; List.iter (fun name -> @@ -265,7 +262,7 @@ * will be reinstated when we exit this context *) let add_identifier name = match !context with - [] -> Cilmsg.fatal "Empty context stack" + [] -> Kernel.fatal "Empty context stack" | con::sub -> (context := (name::con)::sub; (*Format.eprintf "adding IDENT for %s@." name;*) @@ -375,9 +372,15 @@ (match buffer with None -> () | Some b -> Buffer.add_char b ch) ; remainder buffer lexbuf -let do_lex_comment remainder lexbuf = +let do_lex_comment ?first_char remainder lexbuf = let buffer = - if !keepComments then Some(Buffer.create 80) else None + if Kernel.PrintComments.get () then + Some(let b = Buffer.create 80 in + (match first_char with Some c -> + Buffer.add_char b c + | None -> ()); + b) + else None in remainder buffer lexbuf ; match buffer with | Some b -> addComment (Buffer.contents b) @@ -424,6 +427,13 @@ let pragmaLine = ref false let annot_char = ref '@' + +let () = + Kernel.ReadAnnot.add_set_hook + (fun _ x -> + (* prevent the C lexer interpretation of comments *) + annot_char := if x then '@' else '\000') + let annot_start_pos = ref Cabshelper.cabslu let buf = Buffer.create 1024 @@ -434,7 +444,6 @@ let start = snd !annot_start_pos in match Logic_lexer.annot (start, s) with | Logic_ptree.Adecl d -> DECL d - | Logic_ptree.Afor_spec for_spec-> FOR_SPEC for_spec | Logic_ptree.Aspec -> SPEC (start,s) (* At this point, we only have identified a function spec. Complete parsing of the annotation will only occur in the cparser.mly rule. @@ -517,7 +526,7 @@ "Skipping annotation" end else begin - do_lex_comment comment lexbuf ; + do_lex_comment ~first_char:c comment lexbuf ; addWhite lexbuf; initial lexbuf end @@ -547,7 +556,7 @@ "Skipping annotation" end else begin - do_lex_comment onelinecomment lexbuf ; + do_lex_comment ~first_char:c onelinecomment lexbuf ; E.newline(); if is_oneline_ghost () then begin @@ -729,7 +738,7 @@ int_of_string s with Failure ("int_of_string") -> (* the int is too big. *) - Cilmsg.warning "Bad line number in preprocessed file: %s" s; + Kernel.warning "Bad line number in preprocessed file: %s" s; (-1) in E.setCurrentLine (lineno - 1); diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cparser.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cparser.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cparser.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cparser.ml 2011-10-10 08:48:48.000000000 +0000 @@ -1,5 +1,4 @@ type token = - | FOR_SPEC of (Cabs.cabsloc * string list * Logic_ptree.spec) | SPEC of (Lexing.position * string) | DECL of (Logic_ptree.decl list) | CODE_ANNOT of (Logic_ptree.code_annot * Cabs.cabsloc) @@ -179,20 +178,19 @@ parse_error "Cannot find the prototype in a function definition"); currentFunctionName := n - let check_funspec_abrupt_clauses fname (spec,_) = List.iter - (fun bhv -> List.iter - (function - (Cil_types.Normal | Cil_types.Exits),_ -> () - | (Cil_types.Breaks | Cil_types.Continues | - Cil_types.Returns), {Logic_ptree.lexpr_loc = (loc,_)} -> - Cil.error_loc (loc.Lexing.pos_fname, loc.Lexing.pos_lnum) - "Specification of function %s can only contain ensures or \ + (fun bhv -> + List.iter + (function + | (Cil_types.Normal | Cil_types.Exits),_ -> () + | (Cil_types.Breaks | Cil_types.Continues | + Cil_types.Returns), {Logic_ptree.lexpr_loc = (loc,_)} -> + Kernel.error ~source:loc + "Specification of function %s can only contain ensures or \ exits post-conditions" fname; - raise Parsing.Parse_error - ) - bhv.Cil_types.b_post_cond) + raise Parsing.Parse_error) + bhv.Cil_types.b_post_cond) spec.Cil_types.spec_behavior let applyPointer (ptspecs: attribute list list) (dt: decl_type) @@ -365,139 +363,138 @@ get_statementloc (List.hd l), get_statementloc (Cilutil.list_last l))) -# 369 "cil/src/frontc/cparser.ml" +# 367 "cil/src/frontc/cparser.ml" let yytransl_const = [| 0 (* EOF *); - 297 (* EQ *); - 298 (* PLUS_EQ *); - 299 (* MINUS_EQ *); - 300 (* STAR_EQ *); - 301 (* SLASH_EQ *); - 302 (* PERCENT_EQ *); - 303 (* AND_EQ *); - 304 (* PIPE_EQ *); - 305 (* CIRC_EQ *); - 306 (* INF_INF_EQ *); - 307 (* SUP_SUP_EQ *); - 308 (* ARROW *); - 309 (* DOT *); - 310 (* EQ_EQ *); - 311 (* EXCLAM_EQ *); - 312 (* INF *); - 313 (* SUP *); - 314 (* INF_EQ *); - 315 (* SUP_EQ *); - 319 (* SLASH *); - 320 (* PERCENT *); - 323 (* PIPE *); - 324 (* CIRC *); - 327 (* PIPE_PIPE *); - 328 (* INF_INF *); - 329 (* SUP_SUP *); - 332 (* RPAREN *); - 336 (* LBRACKET *); - 337 (* RBRACKET *); - 338 (* COLON *); - 340 (* COMMA *); - 341 (* ELLIPSIS *); - 342 (* QUEST *); - 357 (* ELSE *); - 364 (* LABEL__ *); - 367 (* BUILTIN_VA_LIST *); - 368 (* BLOCKATTRIBUTE *); - 376 (* PRAGMA_EOL *); - 381 (* AT_NAME *); - 382 (* LGHOST *); - 383 (* RGHOST *); + 296 (* EQ *); + 297 (* PLUS_EQ *); + 298 (* MINUS_EQ *); + 299 (* STAR_EQ *); + 300 (* SLASH_EQ *); + 301 (* PERCENT_EQ *); + 302 (* AND_EQ *); + 303 (* PIPE_EQ *); + 304 (* CIRC_EQ *); + 305 (* INF_INF_EQ *); + 306 (* SUP_SUP_EQ *); + 307 (* ARROW *); + 308 (* DOT *); + 309 (* EQ_EQ *); + 310 (* EXCLAM_EQ *); + 311 (* INF *); + 312 (* SUP *); + 313 (* INF_EQ *); + 314 (* SUP_EQ *); + 318 (* SLASH *); + 319 (* PERCENT *); + 322 (* PIPE *); + 323 (* CIRC *); + 326 (* PIPE_PIPE *); + 327 (* INF_INF *); + 328 (* SUP_SUP *); + 331 (* RPAREN *); + 335 (* LBRACKET *); + 336 (* RBRACKET *); + 337 (* COLON *); + 339 (* COMMA *); + 340 (* ELLIPSIS *); + 341 (* QUEST *); + 356 (* ELSE *); + 363 (* LABEL__ *); + 366 (* BUILTIN_VA_LIST *); + 367 (* BLOCKATTRIBUTE *); + 375 (* PRAGMA_EOL *); + 380 (* AT_NAME *); + 381 (* LGHOST *); + 382 (* RGHOST *); 0|] let yytransl_block = [| - 257 (* FOR_SPEC *); - 258 (* SPEC *); - 259 (* DECL *); - 260 (* CODE_ANNOT *); - 261 (* LOOP_ANNOT *); - 262 (* ATTRIBUTE_ANNOT *); - 263 (* IDENT *); - 264 (* CST_CHAR *); - 265 (* CST_WCHAR *); - 266 (* CST_INT *); - 267 (* CST_FLOAT *); - 268 (* NAMED_TYPE *); - 269 (* CST_STRING *); - 270 (* CST_WSTRING *); - 271 (* BOOL *); - 272 (* CHAR *); - 273 (* INT *); - 274 (* DOUBLE *); - 275 (* FLOAT *); - 276 (* VOID *); - 277 (* INT64 *); - 278 (* INT32 *); - 279 (* ENUM *); - 280 (* STRUCT *); - 281 (* TYPEDEF *); - 282 (* UNION *); - 283 (* SIGNED *); - 284 (* UNSIGNED *); - 285 (* LONG *); - 286 (* SHORT *); - 287 (* VOLATILE *); - 288 (* EXTERN *); - 289 (* STATIC *); - 290 (* CONST *); - 291 (* RESTRICT *); - 292 (* AUTO *); - 293 (* REGISTER *); - 294 (* THREAD *); - 295 (* SIZEOF *); - 296 (* ALIGNOF *); - 316 (* PLUS *); - 317 (* MINUS *); - 318 (* STAR *); - 321 (* TILDE *); - 322 (* AND *); - 325 (* EXCLAM *); - 326 (* AND_AND *); - 330 (* PLUS_PLUS *); - 331 (* MINUS_MINUS *); - 333 (* LPAREN *); - 334 (* RBRACE *); - 335 (* LBRACE *); - 339 (* SEMICOLON *); - 343 (* BREAK *); - 344 (* CONTINUE *); - 345 (* GOTO *); - 346 (* RETURN *); - 347 (* SWITCH *); - 348 (* CASE *); - 349 (* DEFAULT *); - 350 (* WHILE *); - 351 (* DO *); - 352 (* FOR *); - 353 (* IF *); - 354 (* TRY *); - 355 (* EXCEPT *); - 356 (* FINALLY *); - 358 (* ATTRIBUTE *); - 359 (* INLINE *); - 360 (* ASM *); - 361 (* TYPEOF *); - 362 (* FUNCTION__ *); - 363 (* PRETTY_FUNCTION__ *); - 365 (* BUILTIN_VA_ARG *); - 366 (* ATTRIBUTE_USED *); - 369 (* BUILTIN_TYPES_COMPAT *); - 370 (* BUILTIN_OFFSETOF *); - 371 (* DECLSPEC *); - 372 (* MSASM *); - 373 (* MSATTR *); - 374 (* PRAGMA_LINE *); - 375 (* PRAGMA *); - 377 (* AT_TRANSFORM *); - 378 (* AT_TRANSFORMEXPR *); - 379 (* AT_SPECIFIER *); - 380 (* AT_EXPR *); + 257 (* SPEC *); + 258 (* DECL *); + 259 (* CODE_ANNOT *); + 260 (* LOOP_ANNOT *); + 261 (* ATTRIBUTE_ANNOT *); + 262 (* IDENT *); + 263 (* CST_CHAR *); + 264 (* CST_WCHAR *); + 265 (* CST_INT *); + 266 (* CST_FLOAT *); + 267 (* NAMED_TYPE *); + 268 (* CST_STRING *); + 269 (* CST_WSTRING *); + 270 (* BOOL *); + 271 (* CHAR *); + 272 (* INT *); + 273 (* DOUBLE *); + 274 (* FLOAT *); + 275 (* VOID *); + 276 (* INT64 *); + 277 (* INT32 *); + 278 (* ENUM *); + 279 (* STRUCT *); + 280 (* TYPEDEF *); + 281 (* UNION *); + 282 (* SIGNED *); + 283 (* UNSIGNED *); + 284 (* LONG *); + 285 (* SHORT *); + 286 (* VOLATILE *); + 287 (* EXTERN *); + 288 (* STATIC *); + 289 (* CONST *); + 290 (* RESTRICT *); + 291 (* AUTO *); + 292 (* REGISTER *); + 293 (* THREAD *); + 294 (* SIZEOF *); + 295 (* ALIGNOF *); + 315 (* PLUS *); + 316 (* MINUS *); + 317 (* STAR *); + 320 (* TILDE *); + 321 (* AND *); + 324 (* EXCLAM *); + 325 (* AND_AND *); + 329 (* PLUS_PLUS *); + 330 (* MINUS_MINUS *); + 332 (* LPAREN *); + 333 (* RBRACE *); + 334 (* LBRACE *); + 338 (* SEMICOLON *); + 342 (* BREAK *); + 343 (* CONTINUE *); + 344 (* GOTO *); + 345 (* RETURN *); + 346 (* SWITCH *); + 347 (* CASE *); + 348 (* DEFAULT *); + 349 (* WHILE *); + 350 (* DO *); + 351 (* FOR *); + 352 (* IF *); + 353 (* TRY *); + 354 (* EXCEPT *); + 355 (* FINALLY *); + 357 (* ATTRIBUTE *); + 358 (* INLINE *); + 359 (* ASM *); + 360 (* TYPEOF *); + 361 (* FUNCTION__ *); + 362 (* PRETTY_FUNCTION__ *); + 364 (* BUILTIN_VA_ARG *); + 365 (* ATTRIBUTE_USED *); + 368 (* BUILTIN_TYPES_COMPAT *); + 369 (* BUILTIN_OFFSETOF *); + 370 (* DECLSPEC *); + 371 (* MSASM *); + 372 (* MSATTR *); + 373 (* PRAGMA_LINE *); + 374 (* PRAGMA *); + 376 (* AT_TRANSFORM *); + 377 (* AT_TRANSFORMEXPR *); + 378 (* AT_SPECIFIER *); + 379 (* AT_EXPR *); 0|] let yylhs = "\255\255\ @@ -525,39 +522,39 @@ \037\000\037\000\087\000\087\000\085\000\085\000\085\000\085\000\ \085\000\085\000\085\000\085\000\085\000\085\000\085\000\085\000\ \085\000\085\000\085\000\085\000\085\000\085\000\085\000\085\000\ -\085\000\085\000\085\000\085\000\085\000\085\000\088\000\088\000\ -\093\000\094\000\089\000\089\000\030\000\030\000\030\000\030\000\ -\040\000\040\000\039\000\039\000\023\000\023\000\023\000\023\000\ -\023\000\023\000\023\000\023\000\023\000\023\000\095\000\095\000\ -\096\000\096\000\024\000\024\000\024\000\024\000\024\000\024\000\ -\024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\ +\085\000\085\000\085\000\085\000\085\000\088\000\088\000\093\000\ +\094\000\089\000\089\000\030\000\030\000\030\000\030\000\040\000\ +\040\000\039\000\039\000\023\000\023\000\023\000\023\000\023\000\ +\023\000\023\000\023\000\023\000\023\000\095\000\095\000\096\000\ +\096\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\ \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\ \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\ -\025\000\025\000\025\000\025\000\025\000\025\000\043\000\043\000\ -\042\000\042\000\042\000\029\000\029\000\029\000\028\000\028\000\ -\041\000\099\000\099\000\099\000\044\000\044\000\044\000\044\000\ -\101\000\102\000\102\000\103\000\103\000\103\000\027\000\027\000\ -\027\000\027\000\026\000\104\000\104\000\038\000\038\000\054\000\ -\054\000\054\000\105\000\105\000\105\000\048\000\049\000\049\000\ -\033\000\033\000\047\000\047\000\045\000\045\000\045\000\045\000\ -\046\000\046\000\031\000\031\000\032\000\032\000\032\000\032\000\ -\032\000\051\000\051\000\051\000\051\000\005\000\005\000\006\000\ -\006\000\006\000\097\000\097\000\097\000\097\000\090\000\090\000\ -\100\000\100\000\100\000\100\000\100\000\107\000\107\000\098\000\ -\098\000\053\000\053\000\053\000\053\000\109\000\109\000\109\000\ -\109\000\109\000\109\000\109\000\109\000\110\000\110\000\111\000\ -\111\000\112\000\112\000\112\000\113\000\113\000\114\000\114\000\ -\114\000\115\000\115\000\115\000\115\000\115\000\115\000\115\000\ +\024\000\024\000\024\000\024\000\024\000\024\000\024\000\025\000\ +\025\000\025\000\025\000\025\000\025\000\043\000\043\000\042\000\ +\042\000\042\000\029\000\029\000\029\000\028\000\028\000\041\000\ +\099\000\099\000\099\000\044\000\044\000\044\000\044\000\101\000\ +\102\000\102\000\103\000\103\000\103\000\027\000\027\000\027\000\ +\027\000\026\000\104\000\104\000\038\000\038\000\054\000\054\000\ +\054\000\105\000\105\000\105\000\048\000\049\000\049\000\033\000\ +\033\000\047\000\047\000\045\000\045\000\045\000\045\000\046\000\ +\046\000\031\000\031\000\032\000\032\000\032\000\032\000\032\000\ +\051\000\051\000\051\000\051\000\005\000\005\000\006\000\006\000\ +\006\000\097\000\097\000\097\000\097\000\090\000\090\000\100\000\ +\100\000\100\000\100\000\100\000\107\000\107\000\098\000\098\000\ +\053\000\053\000\053\000\053\000\109\000\109\000\109\000\109\000\ +\109\000\109\000\109\000\109\000\110\000\110\000\111\000\111\000\ +\112\000\112\000\112\000\113\000\113\000\114\000\114\000\114\000\ +\115\000\115\000\115\000\115\000\115\000\115\000\115\000\116\000\ \116\000\116\000\116\000\116\000\116\000\116\000\116\000\116\000\ -\116\000\116\000\116\000\117\000\118\000\118\000\118\000\118\000\ -\119\000\119\000\119\000\120\000\120\000\120\000\121\000\121\000\ -\121\000\121\000\121\000\122\000\122\000\122\000\123\000\123\000\ -\124\000\124\000\125\000\125\000\126\000\126\000\127\000\127\000\ -\128\000\128\000\108\000\129\000\129\000\129\000\130\000\130\000\ -\083\000\083\000\106\000\106\000\007\000\007\000\007\000\091\000\ -\091\000\092\000\092\000\131\000\131\000\133\000\133\000\134\000\ -\134\000\132\000\132\000\135\000\135\000\136\000\136\000\137\000\ -\137\000\000\000\000\000" +\116\000\116\000\117\000\118\000\118\000\118\000\118\000\119\000\ +\119\000\119\000\120\000\120\000\120\000\121\000\121\000\121\000\ +\121\000\121\000\122\000\122\000\122\000\123\000\123\000\124\000\ +\124\000\125\000\125\000\126\000\126\000\127\000\127\000\128\000\ +\128\000\108\000\129\000\129\000\129\000\130\000\130\000\083\000\ +\083\000\106\000\106\000\007\000\007\000\007\000\091\000\091\000\ +\092\000\092\000\131\000\131\000\133\000\133\000\134\000\134\000\ +\132\000\132\000\135\000\135\000\136\000\136\000\137\000\137\000\ +\000\000\000\000" let yylen = "\002\000\ \002\000\001\000\000\000\002\000\003\000\002\000\000\000\002\000\ @@ -581,67 +578,67 @@ \003\000\003\000\000\000\001\000\003\000\003\000\003\000\003\000\ \005\000\003\000\001\000\000\000\002\000\001\000\003\000\003\000\ \003\000\003\000\000\000\001\000\002\000\004\000\000\000\004\000\ -\001\000\003\000\001\000\002\000\001\000\002\000\002\000\002\000\ -\001\000\003\000\005\000\003\000\004\000\006\000\009\000\004\000\ -\004\000\006\000\002\000\002\000\003\000\002\000\002\000\003\000\ -\004\000\007\000\001\000\005\000\004\000\003\000\000\000\001\000\ -\001\000\001\000\002\000\001\000\003\000\002\000\004\000\003\000\ -\001\000\003\000\001\000\003\000\002\000\002\000\002\000\002\000\ -\002\000\002\000\002\000\002\000\002\000\004\000\000\000\001\000\ -\000\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\001\000\001\000\002\000\003\000\005\000\ -\004\000\006\000\005\000\002\000\005\000\004\000\006\000\005\000\ -\002\000\006\000\005\000\007\000\006\000\001\000\004\000\004\000\ -\000\000\003\000\002\000\004\000\002\000\003\000\001\000\003\000\ -\001\000\004\000\002\000\001\000\003\000\003\000\001\000\003\000\ -\003\000\002\000\004\000\003\000\001\000\004\000\004\000\004\000\ -\001\000\000\000\002\000\000\000\002\000\003\000\002\000\002\000\ -\001\000\003\000\002\000\005\000\003\000\001\000\003\000\000\000\ -\004\000\004\000\001\000\003\000\001\000\003\000\000\000\001\000\ -\002\000\001\000\003\000\001\000\004\000\003\000\004\000\004\000\ -\001\000\000\000\003\000\002\000\002\000\002\000\004\000\005\000\ -\003\000\001\000\001\000\001\000\001\000\000\000\002\000\000\000\ -\002\000\005\000\004\000\002\000\001\000\001\000\000\000\002\000\ -\001\000\001\000\001\000\001\000\001\000\004\000\002\000\001\000\ -\002\000\002\000\003\000\004\000\001\000\001\000\001\000\003\000\ -\001\000\001\000\003\000\003\000\003\000\001\000\001\000\001\000\ -\002\000\001\000\002\000\003\000\001\000\001\000\001\000\003\000\ -\001\000\001\000\002\000\003\000\002\000\003\000\003\000\004\000\ -\001\000\002\000\004\000\002\000\004\000\002\000\002\000\002\000\ -\002\000\002\000\002\000\001\000\001\000\003\000\003\000\003\000\ -\001\000\003\000\003\000\001\000\003\000\003\000\001\000\003\000\ -\003\000\003\000\003\000\001\000\003\000\003\000\001\000\003\000\ -\001\000\003\000\001\000\003\000\001\000\003\000\001\000\003\000\ -\001\000\005\000\001\000\001\000\003\000\003\000\000\000\001\000\ -\003\000\003\000\003\000\003\000\000\000\002\000\002\000\001\000\ -\002\000\000\000\003\000\000\000\001\000\001\000\003\000\005\000\ -\005\000\000\000\003\000\000\000\003\000\000\000\002\000\001\000\ -\003\000\002\000\002\000" +\001\000\003\000\001\000\002\000\001\000\002\000\002\000\001\000\ +\003\000\005\000\003\000\004\000\006\000\009\000\004\000\004\000\ +\006\000\002\000\002\000\003\000\002\000\002\000\003\000\004\000\ +\007\000\001\000\005\000\004\000\003\000\000\000\001\000\001\000\ +\001\000\002\000\001\000\003\000\002\000\004\000\003\000\001\000\ +\003\000\001\000\003\000\002\000\002\000\002\000\002\000\002\000\ +\002\000\002\000\002\000\002\000\004\000\000\000\001\000\000\000\ +\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ +\001\000\001\000\001\000\001\000\002\000\003\000\005\000\004\000\ +\006\000\005\000\002\000\005\000\004\000\006\000\005\000\002\000\ +\006\000\005\000\007\000\006\000\001\000\004\000\004\000\000\000\ +\003\000\002\000\004\000\002\000\003\000\001\000\003\000\001\000\ +\004\000\002\000\001\000\003\000\003\000\001\000\003\000\003\000\ +\002\000\004\000\003\000\001\000\004\000\004\000\004\000\001\000\ +\000\000\002\000\000\000\002\000\003\000\002\000\002\000\001\000\ +\003\000\002\000\005\000\003\000\001\000\003\000\000\000\004\000\ +\004\000\001\000\003\000\001\000\003\000\000\000\001\000\002\000\ +\001\000\003\000\001\000\004\000\003\000\004\000\004\000\001\000\ +\000\000\003\000\002\000\002\000\002\000\004\000\005\000\003\000\ +\001\000\001\000\001\000\001\000\000\000\002\000\000\000\002\000\ +\005\000\004\000\002\000\001\000\001\000\000\000\002\000\001\000\ +\001\000\001\000\001\000\001\000\004\000\002\000\001\000\002\000\ +\002\000\003\000\004\000\001\000\001\000\001\000\003\000\001\000\ +\001\000\003\000\003\000\003\000\001\000\001\000\001\000\002\000\ +\001\000\002\000\003\000\001\000\001\000\001\000\003\000\001\000\ +\001\000\002\000\003\000\002\000\003\000\003\000\004\000\001\000\ +\002\000\004\000\002\000\004\000\002\000\002\000\002\000\002\000\ +\002\000\002\000\001\000\001\000\003\000\003\000\003\000\001\000\ +\003\000\003\000\001\000\003\000\003\000\001\000\003\000\003\000\ +\003\000\003\000\001\000\003\000\003\000\001\000\003\000\001\000\ +\003\000\001\000\003\000\001\000\003\000\001\000\003\000\001\000\ +\005\000\001\000\001\000\003\000\003\000\000\000\001\000\003\000\ +\003\000\003\000\003\000\000\000\002\000\002\000\001\000\002\000\ +\000\000\003\000\000\000\001\000\001\000\003\000\005\000\005\000\ +\000\000\003\000\000\000\003\000\000\000\002\000\001\000\003\000\ +\002\000\002\000" let yydefred = "\000\000\ -\000\000\000\000\000\000\000\000\011\000\069\001\000\000\254\000\ -\229\000\228\000\231\000\235\000\234\000\227\000\233\000\000\000\ -\000\000\000\000\000\000\236\000\237\000\232\000\230\000\067\001\ -\000\000\000\000\066\001\068\001\000\000\000\000\078\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\077\001\093\001\000\000\ -\000\000\000\000\000\000\000\000\194\001\000\000\002\000\000\000\ +\000\000\000\000\000\000\000\000\011\000\068\001\000\000\253\000\ +\228\000\227\000\230\000\234\000\233\000\226\000\232\000\000\000\ +\000\000\000\000\000\000\235\000\236\000\231\000\229\000\066\001\ +\000\000\000\000\065\001\067\001\000\000\000\000\077\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\076\001\092\001\000\000\ +\000\000\000\000\000\000\000\000\193\001\000\000\002\000\000\000\ \000\000\000\000\012\000\013\000\000\000\000\000\000\000\017\000\ -\000\000\195\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\194\001\000\000\000\000\000\000\000\000\000\000\000\000\ \023\000\024\000\000\000\000\000\000\000\000\000\025\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\224\000\213\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\223\000\212\000\000\000\ \000\000\000\000\120\000\121\000\122\000\000\000\000\000\115\000\ -\214\000\215\000\216\000\217\000\006\000\000\000\219\000\000\000\ -\000\000\000\000\076\001\000\000\000\000\000\000\098\001\097\001\ +\213\000\214\000\215\000\216\000\006\000\000\000\218\000\000\000\ +\000\000\000\000\075\001\000\000\000\000\000\000\097\001\096\001\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\090\001\113\001\000\000\000\000\103\001\000\000\ -\114\001\000\000\132\001\133\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\163\001\000\000\ +\000\000\000\000\089\001\112\001\000\000\000\000\102\001\000\000\ +\113\001\000\000\131\001\132\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\162\001\000\000\ \000\000\000\000\010\000\000\000\000\000\000\000\001\000\004\000\ -\000\000\206\000\062\001\000\000\000\000\000\000\048\001\000\000\ -\226\000\218\000\007\000\155\000\060\001\000\000\000\000\220\000\ -\221\000\000\000\208\000\000\000\059\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\012\001\000\000\000\000\ -\087\001\000\000\000\000\000\000\000\000\089\001\000\000\000\000\ +\000\000\205\000\061\001\000\000\000\000\000\000\047\001\000\000\ +\225\000\217\000\007\000\155\000\059\001\000\000\000\000\219\000\ +\220\000\000\000\207\000\000\000\058\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\011\001\000\000\000\000\ +\086\001\000\000\000\000\000\000\000\000\088\001\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\014\000\116\000\000\000\ \000\000\000\000\029\000\109\000\110\000\107\000\108\000\117\000\ @@ -650,2426 +647,2434 @@ \030\000\111\000\000\000\031\000\000\000\000\000\000\000\034\000\ \000\000\062\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\094\000\106\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\122\001\000\000\ -\124\001\126\001\127\001\128\001\131\001\129\001\130\001\000\000\ -\000\000\000\000\115\001\000\000\091\001\094\001\095\001\110\001\ -\000\000\000\000\109\001\117\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\121\001\000\000\ +\123\001\125\001\126\001\127\001\130\001\128\001\129\001\000\000\ +\000\000\000\000\114\001\000\000\090\001\093\001\094\001\109\001\ +\000\000\000\000\108\001\116\001\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\008\000\009\000\005\000\ -\085\001\084\001\082\001\083\001\000\000\081\001\000\000\000\000\ -\205\000\000\000\000\000\000\000\021\001\035\001\000\000\000\000\ -\000\000\022\000\065\001\000\000\207\000\000\000\019\000\000\000\ -\000\000\031\001\032\001\000\000\000\000\000\000\027\001\063\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\003\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\241\000\005\001\000\000\000\000\000\000\246\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\168\001\000\000\075\001\ +\084\001\083\001\081\001\082\001\000\000\080\001\000\000\000\000\ +\204\000\000\000\000\000\000\000\020\001\034\001\000\000\000\000\ +\000\000\022\000\064\001\000\000\206\000\000\000\019\000\000\000\ +\000\000\030\001\031\001\000\000\000\000\000\000\026\001\062\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\240\000\004\001\000\000\000\000\000\000\245\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\167\001\000\000\074\001\ \000\000\000\000\051\000\000\000\053\000\055\000\056\000\057\000\ \060\000\058\000\059\000\061\000\000\000\049\000\050\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\255\000\119\000\118\000\049\001\000\000\000\001\000\000\000\000\ +\254\000\119\000\118\000\048\001\000\000\255\000\000\000\000\000\ \042\000\043\000\000\000\000\000\035\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\170\001\000\000\000\000\169\001\099\001\ -\101\001\100\001\000\000\000\000\112\001\096\001\116\001\092\001\ -\105\001\000\000\118\001\119\001\000\000\134\001\135\001\136\001\ +\000\000\000\000\000\000\169\001\000\000\000\000\168\001\098\001\ +\100\001\099\001\000\000\000\000\111\001\095\001\115\001\091\001\ +\104\001\000\000\117\001\118\001\000\000\133\001\134\001\135\001\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\222\000\046\001\071\001\210\000\000\000\123\000\ -\212\000\000\000\000\000\000\000\000\000\017\001\000\000\000\000\ -\154\000\000\000\000\000\000\000\000\000\000\000\039\001\000\000\ -\000\000\034\001\000\000\000\000\000\000\000\000\029\001\000\000\ -\016\001\014\001\013\001\251\000\086\001\026\000\000\000\000\000\ -\000\000\006\001\011\001\002\001\000\000\000\000\000\000\240\000\ -\243\000\000\000\245\000\248\000\000\000\015\000\172\001\171\001\ +\000\000\000\000\221\000\045\001\070\001\209\000\000\000\123\000\ +\211\000\000\000\000\000\000\000\000\000\016\001\000\000\000\000\ +\154\000\000\000\000\000\000\000\000\000\000\000\038\001\000\000\ +\000\000\033\001\000\000\000\000\000\000\000\000\028\001\000\000\ +\015\001\013\001\012\001\250\000\085\001\026\000\000\000\000\000\ +\000\000\005\001\010\001\001\001\000\000\000\000\000\000\239\000\ +\242\000\000\000\244\000\247\000\000\000\015\000\171\001\170\001\ \016\000\000\000\000\000\000\000\150\000\000\000\000\000\149\000\ \000\000\032\000\000\000\000\000\000\000\000\000\000\000\041\000\ \040\000\000\000\141\000\000\000\000\000\000\000\095\000\096\000\ \097\000\098\000\099\000\100\000\101\000\102\000\103\000\104\000\ \105\000\065\000\066\000\067\000\064\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\143\000\000\000\166\001\ -\165\001\000\000\000\000\108\001\120\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\143\000\000\000\165\001\ +\164\001\000\000\000\000\107\001\119\001\000\000\000\000\000\000\ \000\000\000\000\000\000\131\000\000\000\128\000\000\000\000\000\ -\000\000\000\000\000\000\037\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\073\001\000\000\000\000\000\000\157\000\000\000\ -\000\000\000\000\000\000\164\000\064\001\045\001\000\000\000\000\ -\018\000\000\000\000\000\025\001\051\001\000\000\000\000\030\001\ -\250\000\253\000\000\000\000\000\008\001\004\001\242\000\247\000\ +\000\000\000\000\000\000\036\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\072\001\000\000\000\000\000\000\157\000\000\000\ +\000\000\000\000\000\000\164\000\063\001\044\001\000\000\000\000\ +\018\000\000\000\000\000\024\001\050\001\000\000\000\000\029\001\ +\249\000\252\000\000\000\000\000\007\001\003\001\241\000\246\000\ \000\000\000\000\000\000\146\000\145\000\000\000\063\000\000\000\ \000\000\000\000\033\000\000\000\036\000\152\000\151\000\000\000\ -\162\001\000\000\000\000\000\000\000\000\000\000\132\000\000\000\ -\139\000\124\000\130\000\022\001\000\000\000\000\148\000\018\001\ -\023\001\000\000\000\000\024\001\168\000\170\000\165\000\000\000\ -\153\000\000\000\000\000\000\000\202\000\000\000\173\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\195\000\000\000\000\000\177\000\000\000\000\000\000\000\ -\000\000\200\000\201\000\000\000\000\000\054\001\000\000\000\000\ -\000\000\252\000\010\001\000\000\000\000\000\000\045\000\000\000\ -\093\000\000\000\000\000\138\000\134\000\000\000\000\000\126\000\ -\129\000\036\001\020\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\171\000\000\000\174\000\175\000\190\000\191\000\000\000\ -\000\000\188\000\000\000\000\000\000\000\000\000\187\000\000\000\ -\000\000\000\000\000\000\000\000\176\000\159\000\161\000\000\000\ -\160\000\000\000\000\000\000\000\044\001\041\001\042\001\053\001\ -\056\001\055\001\044\000\037\000\038\000\000\000\039\000\047\000\ -\020\000\021\000\135\000\000\000\019\001\074\001\166\000\198\000\ -\000\000\172\000\000\000\192\000\189\000\000\000\180\000\000\000\ -\000\000\000\000\000\000\000\000\174\001\175\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\046\000\136\000\193\000\185\000\ -\000\000\000\000\000\000\197\000\114\000\000\000\000\000\184\000\ -\080\001\181\000\000\000\000\000\204\000\000\000\000\000\179\000\ -\196\000\177\001\000\000\000\000\000\000\203\000\000\000\186\000\ -\000\000\000\000\000\000\182\001\000\000\000\000\182\000\000\000\ -\000\000\000\000\179\001\000\000\000\000\194\000\000\000\189\001\ -\000\000\183\001\000\000\000\000\000\000\187\001\000\000\000\000\ -\183\000\000\000\191\001\185\001\184\001\000\000\193\001" +\161\001\000\000\000\000\000\000\000\000\000\000\132\000\000\000\ +\139\000\124\000\130\000\021\001\000\000\000\000\148\000\017\001\ +\022\001\000\000\000\000\023\001\168\000\170\000\165\000\000\000\ +\153\000\000\000\000\000\201\000\000\000\173\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\194\000\000\000\000\000\176\000\000\000\000\000\000\000\000\000\ +\199\000\200\000\000\000\000\000\053\001\000\000\000\000\000\000\ +\251\000\009\001\000\000\000\000\000\000\045\000\000\000\093\000\ +\000\000\000\000\138\000\134\000\000\000\000\000\126\000\129\000\ +\035\001\019\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\171\000\000\000\174\000\189\000\190\000\000\000\000\000\187\000\ +\000\000\000\000\000\000\000\000\186\000\000\000\000\000\000\000\ +\000\000\000\000\175\000\159\000\161\000\000\000\160\000\000\000\ +\000\000\000\000\043\001\040\001\041\001\052\001\055\001\054\001\ +\044\000\037\000\038\000\000\000\039\000\047\000\020\000\021\000\ +\135\000\000\000\018\001\073\001\166\000\197\000\000\000\172\000\ +\000\000\191\000\188\000\000\000\179\000\000\000\000\000\000\000\ +\000\000\000\000\173\001\174\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\046\000\136\000\192\000\184\000\000\000\000\000\ +\000\000\196\000\114\000\000\000\000\000\183\000\079\001\180\000\ +\000\000\000\000\203\000\000\000\000\000\178\000\195\000\176\001\ +\000\000\000\000\000\000\202\000\000\000\185\000\000\000\000\000\ +\000\000\181\001\000\000\000\000\181\000\000\000\000\000\000\000\ +\178\001\000\000\000\000\193\000\000\000\188\001\000\000\182\001\ +\000\000\000\000\000\000\186\001\000\000\000\000\182\000\000\000\ +\190\001\184\001\183\001\000\000\192\001" let yydgoto = "\003\000\ -\045\000\046\000\047\000\048\000\053\001\230\001\244\002\225\000\ -\226\000\129\001\069\002\084\002\187\002\228\000\036\002\149\001\ -\087\000\229\000\085\002\086\002\087\002\213\002\185\000\050\000\ +\045\000\046\000\047\000\048\000\053\001\230\001\242\002\225\000\ +\226\000\129\001\069\002\084\002\186\002\228\000\036\002\149\001\ +\087\000\229\000\085\002\086\002\087\002\212\002\185\000\050\000\ \186\000\147\000\171\000\174\000\175\000\051\000\052\000\053\000\ -\231\000\189\002\106\002\065\001\234\001\168\000\148\000\149\000\ -\108\001\094\001\095\001\244\001\245\001\246\001\199\002\151\000\ +\231\000\188\002\106\002\065\001\234\001\168\000\148\000\149\000\ +\108\001\094\001\095\001\244\001\245\001\246\001\198\002\151\000\ \096\001\054\000\055\000\142\000\187\000\241\001\117\000\061\001\ -\083\001\232\000\233\000\208\002\089\002\234\000\235\000\236\000\ +\083\001\232\000\233\000\207\002\089\002\234\000\235\000\236\000\ \237\000\238\000\239\000\240\000\241\000\242\000\243\000\244\000\ -\245\000\246\000\247\000\046\003\088\000\152\002\090\002\160\002\ -\158\000\237\001\099\000\107\002\226\002\227\002\229\002\193\002\ -\054\003\032\003\047\003\060\003\194\002\195\002\089\000\154\000\ +\245\000\246\000\247\000\044\003\088\000\152\002\090\002\160\002\ +\158\000\237\001\099\000\107\002\225\002\226\002\227\002\192\002\ +\052\003\030\003\045\003\058\003\193\002\194\002\089\000\154\000\ \057\000\073\000\096\002\055\001\064\000\172\000\079\001\062\001\ \112\002\201\000\074\000\249\000\119\000\120\000\018\001\019\001\ \020\001\121\000\122\000\123\000\124\000\125\000\126\000\127\000\ \128\000\129\000\130\000\131\000\132\000\133\000\134\000\135\000\ -\250\000\111\001\066\003\075\003\067\003\068\003\069\003\086\003\ -\091\003" +\250\000\111\001\064\003\073\003\065\003\066\003\067\003\084\003\ +\089\003" -let yysindex = "\247\000\ -\063\011\063\011\000\000\056\017\000\000\000\000\041\255\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\255\ -\058\255\053\018\109\000\000\000\000\000\000\000\000\000\000\000\ -\136\016\053\018\000\000\000\000\053\018\053\018\000\000\063\011\ -\112\255\053\018\146\255\148\255\181\255\000\000\000\000\087\023\ -\009\255\236\255\016\000\086\002\000\000\113\001\000\000\063\011\ -\048\000\086\018\000\000\000\000\044\255\115\000\053\018\000\000\ -\053\018\000\000\047\000\053\018\120\000\044\255\137\000\166\017\ -\000\000\000\000\147\000\091\000\181\255\099\000\000\000\106\000\ -\107\255\191\255\216\013\119\000\040\000\000\000\000\000\216\013\ -\123\000\093\000\000\000\000\000\000\000\230\014\063\255\000\000\ -\000\000\000\000\000\000\000\000\000\000\129\000\000\000\063\255\ -\206\015\102\029\000\000\000\000\145\000\000\000\000\000\000\000\ -\201\019\016\020\095\011\095\011\095\011\095\011\095\011\095\011\ -\095\011\158\000\000\000\000\000\152\000\001\255\000\000\192\001\ -\000\000\011\255\000\000\000\000\123\001\201\000\175\000\021\002\ -\058\001\205\000\230\000\220\000\232\000\174\255\000\000\193\014\ -\035\020\048\001\000\000\086\002\086\002\063\011\000\000\000\000\ -\198\003\000\000\000\000\240\000\244\000\032\001\000\000\101\255\ -\000\000\000\000\000\000\000\000\000\000\226\000\254\000\000\000\ -\000\000\137\000\000\000\001\001\000\000\003\001\012\001\022\001\ -\166\017\039\001\024\001\055\001\092\001\000\000\056\001\129\000\ -\000\000\135\001\147\000\147\000\066\001\000\000\069\001\216\013\ -\079\000\080\001\216\013\216\013\216\013\082\001\087\001\216\013\ -\216\013\091\001\053\018\063\011\048\000\000\000\000\000\165\029\ -\117\001\127\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\106\020\125\020\035\020\035\020\035\020\035\020\035\020\035\020\ -\180\255\196\020\196\020\014\010\112\001\133\001\138\001\148\001\ -\000\000\000\000\131\001\000\000\121\255\039\001\151\001\000\000\ -\040\001\000\000\152\003\175\001\064\001\065\001\140\002\141\001\ -\168\001\161\001\178\001\172\001\013\000\000\000\000\000\006\255\ -\166\001\180\001\253\001\005\002\013\002\014\010\000\000\014\010\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\205\001\ -\031\002\031\029\000\000\184\001\000\000\000\000\000\000\000\000\ -\046\001\063\255\000\000\000\000\131\255\131\255\095\011\095\011\ -\095\011\095\011\095\011\095\011\095\011\095\011\095\011\095\011\ -\095\011\095\011\095\011\095\011\095\011\095\011\095\011\095\011\ -\095\011\095\011\222\001\234\001\247\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\039\001\000\000\198\003\039\001\ -\000\000\229\018\198\003\163\001\000\000\000\000\251\001\180\255\ -\215\001\000\000\000\000\006\002\000\000\137\000\000\000\053\018\ -\008\002\000\000\000\000\000\000\119\255\169\016\000\000\000\000\ -\035\020\118\000\011\002\019\002\032\002\056\001\056\001\147\000\ -\216\013\000\000\035\020\216\013\015\002\041\002\061\002\101\255\ -\000\000\000\000\070\002\089\002\216\013\000\000\112\002\122\002\ -\216\013\120\000\124\002\032\001\064\255\000\000\128\002\000\000\ -\125\002\014\010\000\000\014\010\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\014\010\000\000\000\000\221\255\ -\134\002\136\002\151\002\169\002\035\020\053\018\053\018\214\002\ -\000\000\000\000\000\000\000\000\167\002\000\000\131\255\131\255\ -\000\000\000\000\173\012\244\012\000\000\035\020\035\020\035\020\ -\035\020\035\020\035\020\035\020\035\020\035\020\035\020\035\020\ -\035\020\035\020\035\020\035\020\035\020\035\020\035\020\035\020\ -\035\020\035\020\035\020\035\020\035\020\035\020\035\020\035\020\ -\035\020\035\020\173\012\000\000\228\029\228\029\000\000\000\000\ -\000\000\000\000\177\002\179\002\000\000\000\000\000\000\000\000\ -\000\000\046\001\000\000\000\000\175\002\000\000\000\000\000\000\ -\123\001\123\001\201\000\201\000\175\000\175\000\175\000\175\000\ -\021\002\021\002\058\001\205\000\230\000\220\000\232\000\183\002\ -\250\002\003\003\000\000\000\000\000\000\000\000\022\016\000\000\ -\000\000\039\001\137\000\243\000\190\002\000\000\224\001\166\017\ -\000\000\187\002\193\002\181\255\020\255\053\018\000\000\048\255\ -\195\002\000\000\129\001\152\008\116\011\202\002\000\000\024\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\205\002\223\002\ -\056\001\000\000\000\000\000\000\035\020\017\255\216\013\000\000\ -\000\000\242\002\000\000\000\000\243\002\000\000\000\000\000\000\ -\000\000\251\002\252\002\253\002\000\000\173\012\173\012\000\000\ -\049\019\000\000\247\002\248\002\002\003\004\003\129\001\000\000\ -\000\000\006\003\000\000\005\003\045\000\254\002\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\175\001\175\001\064\001\ -\064\001\065\001\065\001\065\001\065\001\140\002\140\002\141\001\ -\168\001\161\001\178\001\172\001\009\003\000\000\010\003\000\000\ -\000\000\008\003\008\003\000\000\000\000\095\011\016\003\017\003\ -\000\000\131\255\035\020\000\000\015\003\000\000\063\003\025\003\ -\030\003\229\018\046\003\000\000\047\003\198\003\173\012\043\003\ -\198\003\063\255\000\000\055\003\226\000\180\255\000\000\020\255\ -\020\255\056\003\150\009\000\000\000\000\000\000\049\003\052\003\ -\000\000\067\003\039\001\000\000\000\000\166\017\173\012\000\000\ -\000\000\000\000\066\003\198\003\000\000\000\000\000\000\000\000\ -\008\003\008\003\008\003\000\000\000\000\022\016\000\000\053\018\ -\053\018\131\255\000\000\039\001\000\000\000\000\000\000\035\020\ -\000\000\063\011\035\020\011\000\004\255\022\016\000\000\229\018\ -\000\000\000\000\000\000\000\000\053\018\173\012\000\000\000\000\ -\000\000\112\003\072\003\000\000\000\000\000\000\000\000\022\003\ -\000\000\006\003\147\006\149\005\000\000\000\000\000\000\071\003\ -\090\003\046\000\206\011\078\003\035\020\110\003\078\003\044\255\ -\153\000\000\000\122\003\020\255\000\000\020\255\124\003\020\255\ -\121\000\000\000\000\000\048\255\199\017\000\000\131\003\132\003\ -\128\003\000\000\000\000\136\003\134\003\139\003\000\000\049\255\ -\000\000\140\003\141\003\000\000\000\000\011\000\035\020\000\000\ -\000\000\000\000\000\000\173\012\198\003\020\255\187\000\147\006\ -\142\003\000\000\204\010\000\000\000\000\000\000\000\000\173\012\ -\144\003\000\000\148\003\007\013\147\006\198\000\000\000\147\006\ -\120\001\153\000\153\000\146\003\000\000\000\000\000\000\250\000\ -\000\000\078\003\147\006\158\003\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\230\003\000\000\000\000\ -\000\000\000\000\000\000\169\003\000\000\000\000\000\000\000\000\ -\250\000\000\000\168\003\000\000\000\000\221\255\000\000\147\006\ -\035\020\160\003\078\003\044\255\000\000\000\000\239\003\147\006\ -\250\000\147\006\165\003\133\010\000\000\000\000\000\000\000\000\ -\180\003\147\006\044\255\000\000\000\000\239\003\189\003\000\000\ -\000\000\000\000\078\003\190\003\000\000\173\012\147\006\000\000\ -\000\000\000\000\192\003\200\003\194\003\000\000\199\003\000\000\ -\022\004\212\003\213\003\000\000\063\255\216\003\000\000\173\012\ -\221\003\192\003\000\000\192\003\226\003\000\000\234\003\000\000\ -\232\003\000\000\078\013\147\006\239\003\000\000\240\003\244\003\ -\000\000\237\003\000\000\000\000\000\000\239\003\000\000" +let yysindex = "\057\001\ +\038\007\038\007\000\000\141\017\000\000\000\000\232\254\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\146\000\ +\211\000\138\018\230\000\000\000\000\000\000\000\000\000\000\000\ +\221\016\138\018\000\000\000\000\138\018\138\018\000\000\038\007\ +\255\254\138\018\006\255\039\255\094\255\000\000\000\000\211\011\ +\118\255\153\255\218\255\001\007\000\000\040\001\000\000\038\007\ +\141\255\171\018\000\000\000\000\055\255\042\000\138\018\000\000\ +\138\018\000\000\229\255\138\018\181\255\055\255\088\000\251\017\ +\000\000\000\000\111\000\048\000\094\255\069\000\000\000\065\000\ +\065\255\247\255\045\014\075\000\061\000\000\000\000\000\045\014\ +\094\000\062\000\000\000\000\000\000\000\059\015\128\255\000\000\ +\000\000\000\000\000\000\000\000\000\000\100\000\000\000\128\255\ +\035\016\106\029\000\000\000\000\145\000\000\000\000\000\000\000\ +\030\020\101\020\249\029\249\029\249\029\249\029\249\029\249\029\ +\249\029\153\000\000\000\000\000\169\000\002\000\000\000\110\002\ +\000\000\007\255\000\000\000\000\048\001\005\001\001\001\181\001\ +\028\001\208\000\215\000\220\000\241\000\251\254\000\000\022\015\ +\120\020\033\001\000\000\001\007\001\007\038\007\000\000\000\000\ +\195\005\000\000\000\000\216\000\233\000\030\001\000\000\164\000\ +\000\000\000\000\000\000\000\000\000\000\225\000\252\000\000\000\ +\000\000\088\000\000\000\003\001\000\000\006\001\019\001\012\001\ +\251\017\043\001\037\001\060\001\083\001\000\000\050\001\100\000\ +\000\000\133\001\111\000\111\000\049\001\000\000\081\001\045\014\ +\018\000\088\001\045\014\045\014\045\014\089\001\094\001\045\014\ +\045\014\110\001\138\018\038\007\141\255\000\000\000\000\142\029\ +\131\001\136\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\191\020\210\020\120\020\120\020\120\020\120\020\120\020\120\020\ +\079\000\025\021\025\021\169\010\142\001\147\001\151\001\154\001\ +\000\000\000\000\159\001\000\000\203\255\043\001\165\001\000\000\ +\008\002\000\000\158\003\052\001\070\001\066\001\226\001\100\001\ +\180\001\188\001\194\001\204\001\159\255\000\000\000\000\021\000\ +\196\001\212\001\027\002\029\002\032\002\169\010\000\000\169\010\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\225\001\ +\040\002\035\029\000\000\191\001\000\000\000\000\000\000\000\000\ +\044\001\128\255\000\000\000\000\234\255\234\255\249\029\249\029\ +\249\029\249\029\249\029\249\029\249\029\249\029\249\029\249\029\ +\249\029\249\029\249\029\249\029\249\029\249\029\249\029\249\029\ +\249\029\249\029\230\001\235\001\239\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\043\001\000\000\195\005\043\001\ +\000\000\058\019\195\005\187\001\000\000\000\000\244\001\079\000\ +\214\001\000\000\000\000\248\001\000\000\088\000\000\000\138\018\ +\255\001\000\000\000\000\000\000\226\000\254\016\000\000\000\000\ +\120\020\142\000\006\002\013\002\036\002\050\001\050\001\111\000\ +\045\014\000\000\120\020\045\014\033\002\051\002\054\002\164\000\ +\000\000\000\000\056\002\060\002\045\014\000\000\061\002\064\002\ +\045\014\181\255\065\002\030\001\026\000\000\000\074\002\000\000\ +\068\002\169\010\000\000\169\010\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\169\010\000\000\000\000\040\000\ +\072\002\076\002\081\002\083\002\120\020\138\018\138\018\109\002\ +\000\000\000\000\000\000\000\000\084\002\000\000\234\255\234\255\ +\000\000\000\000\011\013\082\013\000\000\120\020\120\020\120\020\ +\120\020\120\020\120\020\120\020\120\020\120\020\120\020\120\020\ +\120\020\120\020\120\020\120\020\120\020\120\020\120\020\120\020\ +\120\020\120\020\120\020\120\020\120\020\120\020\120\020\120\020\ +\120\020\120\020\011\013\000\000\213\029\213\029\000\000\000\000\ +\000\000\000\000\086\002\089\002\000\000\000\000\000\000\000\000\ +\000\000\044\001\000\000\000\000\123\002\000\000\000\000\000\000\ +\048\001\048\001\005\001\005\001\001\001\001\001\001\001\001\001\ +\181\001\181\001\028\001\208\000\215\000\220\000\241\000\124\002\ +\198\002\200\002\000\000\000\000\000\000\000\000\107\016\000\000\ +\000\000\043\001\088\000\038\002\131\002\000\000\063\001\251\017\ +\000\000\126\002\128\002\094\255\024\255\138\018\000\000\041\255\ +\127\002\000\000\175\001\195\001\051\009\133\002\000\000\037\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\136\002\137\002\ +\050\001\000\000\000\000\000\000\120\020\151\255\045\014\000\000\ +\000\000\140\002\000\000\000\000\141\002\000\000\000\000\000\000\ +\000\000\144\002\145\002\149\002\000\000\011\013\011\013\000\000\ +\134\019\000\000\142\002\146\002\150\002\153\002\175\001\000\000\ +\000\000\151\002\000\000\157\002\078\000\161\002\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\052\001\052\001\070\001\ +\070\001\066\001\066\001\066\001\066\001\226\001\226\001\100\001\ +\180\001\188\001\194\001\204\001\156\002\000\000\159\002\000\000\ +\000\000\165\002\165\002\000\000\000\000\249\029\167\002\168\002\ +\000\000\234\255\120\020\000\000\164\002\000\000\220\002\180\002\ +\185\002\058\019\194\002\000\000\196\002\195\005\011\013\192\002\ +\195\005\128\255\000\000\206\002\225\000\079\000\000\000\024\255\ +\024\255\205\002\050\010\000\000\000\000\000\000\190\002\201\002\ +\000\000\211\002\043\001\000\000\000\000\251\017\011\013\000\000\ +\000\000\000\000\214\002\195\005\000\000\000\000\000\000\000\000\ +\165\002\165\002\165\002\000\000\000\000\107\016\000\000\138\018\ +\138\018\234\255\000\000\043\001\000\000\000\000\000\000\120\020\ +\000\000\038\007\120\020\011\255\093\255\107\016\000\000\058\019\ +\000\000\000\000\000\000\000\000\138\018\011\013\000\000\000\000\ +\000\000\004\003\235\002\000\000\000\000\000\000\000\000\207\002\ +\000\000\151\002\148\005\000\000\000\000\000\000\250\002\252\002\ +\123\255\042\012\008\003\120\020\007\003\008\003\055\255\160\000\ +\000\000\003\003\024\255\000\000\024\255\009\003\024\255\055\001\ +\000\000\000\000\041\255\028\018\000\000\014\003\020\003\016\003\ +\000\000\000\000\022\003\025\003\028\003\000\000\201\000\000\000\ +\027\003\031\003\000\000\000\000\011\255\120\020\000\000\000\000\ +\000\000\000\000\011\013\195\005\024\255\049\000\144\006\024\003\ +\000\000\103\011\000\000\000\000\000\000\011\013\034\003\000\000\ +\035\003\101\013\144\006\191\000\000\000\144\006\058\001\160\000\ +\160\000\037\003\000\000\000\000\000\000\005\255\000\000\008\003\ +\144\006\055\003\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\126\003\000\000\000\000\000\000\000\000\ +\000\000\053\003\000\000\000\000\000\000\000\000\005\255\000\000\ +\058\003\000\000\000\000\040\000\000\000\144\006\120\020\042\003\ +\008\003\055\255\000\000\000\000\131\003\144\006\005\255\144\006\ +\051\003\032\011\000\000\000\000\000\000\000\000\071\003\144\006\ +\055\255\000\000\000\000\131\003\072\003\000\000\000\000\000\000\ +\008\003\078\003\000\000\011\013\144\006\000\000\000\000\000\000\ +\075\003\103\003\115\003\000\000\127\003\000\000\204\003\130\003\ +\129\003\000\000\128\255\132\003\000\000\011\013\133\003\075\003\ +\000\000\075\003\139\003\000\000\144\003\000\000\142\003\000\000\ +\172\013\144\006\131\003\000\000\145\003\149\003\000\000\146\003\ +\000\000\000\000\000\000\131\003\000\000" let yyrindex = "\000\000\ -\029\000\031\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\032\000\036\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\076\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\087\000\076\000\000\000\000\000\076\000\076\000\000\000\033\000\ -\000\000\076\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\033\000\ -\080\000\023\001\000\000\000\000\000\000\000\000\076\000\000\000\ -\076\000\000\000\000\000\076\000\080\000\000\000\023\017\250\003\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\007\ -\000\000\167\000\008\004\118\007\000\000\000\000\000\000\008\004\ -\230\007\000\000\000\000\000\000\000\000\000\000\074\014\000\000\ +\000\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\042\255\130\000\000\000\000\000\130\000\130\000\000\000\031\000\ +\000\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\000\ +\004\001\056\255\000\000\000\000\000\000\000\000\130\000\000\000\ +\130\000\000\000\000\000\130\000\004\001\000\000\108\017\152\003\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\161\007\ +\000\000\076\000\151\003\017\008\000\000\000\000\000\000\151\003\ +\129\008\000\000\000\000\000\000\000\000\000\000\159\014\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\194\022\094\023\016\023\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\246\003\ +\000\000\004\008\000\000\000\000\031\014\133\017\054\030\116\001\ +\053\014\222\005\188\013\140\010\240\005\255\002\000\000\232\003\ +\000\000\000\000\000\000\000\000\000\000\031\000\000\000\000\000\ +\080\000\000\000\000\000\154\003\000\000\025\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\152\004\000\000\000\000\ +\000\000\108\017\000\000\000\000\000\000\159\003\074\255\000\000\ +\000\000\105\000\162\003\000\000\067\000\000\000\161\003\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\151\003\ +\004\001\000\000\151\003\151\003\151\003\241\008\000\000\151\003\ +\151\003\000\000\000\000\043\255\004\001\000\000\000\000\165\003\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\109\022\009\023\187\022\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\241\005\ -\000\000\217\007\000\000\000\000\218\014\191\017\064\029\241\003\ -\038\016\225\011\058\018\137\008\020\007\111\002\000\000\087\004\ -\000\000\000\000\000\000\000\000\000\000\033\000\000\000\000\000\ -\183\000\000\000\000\000\007\004\000\000\237\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\151\004\000\000\000\000\ -\000\000\023\017\000\000\000\000\000\000\015\004\045\255\000\000\ -\000\000\213\000\018\004\000\000\253\255\000\000\017\004\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\004\ -\080\000\000\000\008\004\008\004\008\004\086\008\000\000\008\004\ -\008\004\000\000\000\000\034\255\080\000\000\000\000\000\020\004\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\109\021\218\000\000\000\000\000\ +\196\021\000\000\173\023\242\023\193\024\144\025\208\026\043\002\ +\176\027\032\028\144\028\208\012\052\012\000\000\000\000\000\000\ +\166\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\029\007\109\006\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\024\021\174\000\000\000\000\000\ -\111\021\000\000\154\023\223\023\174\024\235\001\123\026\035\027\ -\147\027\003\028\115\028\038\012\112\012\000\000\000\000\000\000\ -\027\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\140\000\000\000\065\009\004\001\ +\000\000\000\000\183\000\045\255\000\000\000\000\000\000\000\000\ +\022\005\000\000\000\000\000\000\000\000\000\000\000\000\238\255\ +\000\000\000\000\000\000\163\000\163\003\000\000\000\000\000\000\ +\000\000\178\003\000\000\000\000\000\000\161\003\161\003\000\000\ +\151\003\000\000\000\000\151\003\077\001\174\003\000\000\000\000\ +\000\000\000\000\000\000\000\000\151\003\000\000\000\000\000\000\ +\151\003\004\001\000\000\091\001\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\112\006\249\006\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\219\000\000\000\165\008\080\000\ -\000\000\000\000\179\000\149\001\000\000\000\000\000\000\000\000\ -\022\005\000\000\000\000\000\000\000\000\000\000\000\000\078\255\ -\000\000\000\000\000\000\067\001\019\004\000\000\000\000\000\000\ -\000\000\026\004\000\000\000\000\000\000\017\004\017\004\000\000\ -\008\004\000\000\000\000\008\004\164\001\024\004\000\000\000\000\ -\000\000\000\000\000\000\000\000\008\004\000\000\000\000\000\000\ -\008\004\080\000\000\000\170\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\004\ -\249\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\019\004\000\000\000\000\000\000\ -\000\000\000\000\033\004\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\180\003\ +\223\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\163\003\000\000\000\000\000\000\ +\000\000\000\000\189\003\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\040\004\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\185\003\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\105\007\000\000\000\000\000\000\000\000\000\000\000\000\ -\073\015\048\017\244\029\028\030\061\030\096\030\129\030\164\030\ -\187\030\210\030\142\016\097\013\114\018\241\009\132\007\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\045\004\000\000\ -\000\000\080\000\023\017\021\012\000\000\000\000\130\001\250\003\ -\000\000\000\000\041\004\000\000\030\009\080\255\000\000\080\000\ -\086\255\000\000\055\000\019\000\116\000\000\000\000\000\018\004\ +\000\000\148\007\000\000\000\000\000\000\000\000\000\000\000\000\ +\047\015\158\015\020\018\021\030\089\030\122\030\157\030\190\030\ +\213\030\236\030\123\016\226\016\143\018\171\010\175\007\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\190\003\000\000\ +\000\000\004\001\108\017\113\012\000\000\000\000\112\001\152\003\ +\000\000\000\000\186\003\000\000\186\009\077\255\000\000\004\001\ +\079\255\000\000\023\001\120\000\104\000\000\000\000\000\162\003\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\017\004\000\000\000\000\000\000\000\000\080\000\008\004\000\000\ +\161\003\000\000\000\000\000\000\000\000\004\001\151\003\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\159\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\053\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\036\024\105\024\243\024\ -\056\025\125\025\191\025\001\026\067\026\179\026\235\026\091\027\ -\203\027\059\028\171\028\227\028\000\000\000\000\000\000\000\000\ -\000\000\073\008\221\013\000\000\000\000\000\000\000\000\000\000\ -\034\031\000\000\000\000\000\000\047\004\000\000\125\019\000\000\ -\000\000\000\000\000\000\000\000\000\000\149\013\050\004\000\000\ -\130\011\000\000\000\000\000\000\151\004\000\000\000\000\023\003\ -\151\003\000\000\122\001\000\000\000\000\000\000\043\004\000\000\ -\000\000\000\000\192\000\000\000\000\000\250\003\050\004\000\000\ -\000\000\000\000\000\000\177\001\000\000\000\000\000\000\000\000\ -\198\021\029\022\000\000\000\000\000\000\045\004\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\055\024\124\024\006\025\ +\075\025\210\025\020\026\086\026\152\026\008\027\064\027\120\027\ +\232\027\088\028\200\028\000\029\000\000\000\000\000\000\000\000\ +\000\000\116\008\228\008\000\000\000\000\000\000\000\000\000\000\ +\060\031\000\000\000\000\000\000\199\003\000\000\210\019\000\000\ +\000\000\000\000\000\000\000\000\000\000\191\013\197\003\000\000\ +\221\011\000\000\000\000\000\000\152\004\000\000\000\000\033\003\ +\157\003\000\000\149\001\000\000\000\000\000\000\196\003\000\000\ +\000\000\000\000\119\255\000\000\000\000\152\003\197\003\000\000\ +\000\000\000\000\000\000\121\001\000\000\000\000\000\000\000\000\ +\027\022\114\022\000\000\000\000\000\000\190\003\000\000\000\000\ \000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\ -\000\000\034\255\000\000\153\018\000\000\045\004\000\000\000\000\ -\000\000\000\000\000\000\000\000\080\255\000\000\000\000\000\000\ -\000\000\097\012\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\222\000\181\001\181\001\000\000\086\015\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\051\004\000\000\000\000\023\003\000\000\023\003\000\000\023\003\ -\000\000\000\000\000\000\080\000\078\255\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\153\018\000\000\000\000\ -\000\000\000\000\000\000\000\000\222\003\023\003\000\000\181\001\ -\000\000\000\000\181\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\181\001\000\000\000\000\181\001\ -\000\000\051\004\051\004\000\000\000\000\000\000\000\000\023\004\ -\000\000\000\000\181\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\020\006\000\000\000\000\000\000\000\000\000\000\000\000\181\001\ -\000\000\145\002\000\000\000\000\000\000\000\000\000\000\181\001\ -\020\006\181\001\000\000\052\004\000\000\000\000\000\000\000\000\ -\000\000\181\001\000\000\000\000\000\000\065\255\057\004\000\000\ -\000\000\000\000\000\000\000\000\000\000\052\004\181\001\000\000\ -\000\000\000\000\225\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\058\004\061\000\000\000\000\000\000\000\000\000\062\004\ -\000\000\225\000\000\000\228\255\000\000\000\000\000\000\000\000\ -\064\004\000\000\000\000\181\001\000\000\000\000\000\000\000\000\ -\000\000\065\004\000\000\000\000\000\000\000\000\000\000" +\000\000\043\255\000\000\238\018\000\000\190\003\000\000\000\000\ +\000\000\000\000\000\000\000\000\077\255\000\000\000\000\000\000\ +\000\000\190\012\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\166\000\120\001\000\000\171\015\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\210\003\ +\000\000\000\000\033\003\000\000\033\003\000\000\033\003\000\000\ +\000\000\000\000\004\001\238\255\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\238\018\000\000\000\000\000\000\ +\000\000\000\000\000\000\176\001\033\003\000\000\120\001\000\000\ +\000\000\120\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\120\001\000\000\000\000\120\001\000\000\210\003\ +\210\003\000\000\000\000\000\000\000\000\025\004\000\000\000\000\ +\120\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\018\006\000\000\ +\000\000\000\000\000\000\000\000\000\000\120\001\000\000\162\002\ +\000\000\000\000\000\000\000\000\000\000\120\001\018\006\120\001\ +\000\000\213\003\000\000\000\000\000\000\000\000\000\000\120\001\ +\000\000\000\000\000\000\139\000\221\003\000\000\000\000\000\000\ +\000\000\000\000\000\000\213\003\120\001\000\000\000\000\000\000\ +\186\000\000\000\000\000\000\000\000\000\000\000\000\000\235\003\ +\177\000\000\000\000\000\000\000\000\000\239\003\000\000\186\000\ +\000\000\248\255\000\000\000\000\000\000\000\000\225\001\000\000\ +\000\000\120\001\000\000\000\000\000\000\000\000\000\000\247\003\ +\000\000\000\000\000\000\000\000\000\000" let yygindex = "\000\000\ -\000\000\140\005\231\255\007\005\012\255\170\003\041\000\000\000\ -\241\255\007\000\050\254\211\254\074\255\112\253\000\000\192\002\ -\000\000\000\000\000\000\000\000\157\253\188\002\150\000\000\000\ -\050\000\000\000\141\255\066\004\136\255\216\255\068\001\150\005\ -\077\255\208\255\110\254\091\003\092\003\111\255\000\000\207\255\ -\213\255\000\000\167\003\041\005\000\000\000\000\159\255\095\255\ -\235\255\103\255\000\000\168\002\020\000\038\254\240\255\034\000\ -\196\254\000\000\000\000\000\000\209\253\220\001\221\001\150\001\ -\176\001\105\002\183\001\021\004\025\004\028\004\029\004\031\004\ -\000\000\053\003\178\003\135\253\185\255\000\000\000\000\077\003\ -\000\000\000\000\195\255\187\253\179\253\062\254\139\254\000\000\ -\000\000\165\002\153\002\000\000\000\000\000\000\048\004\000\000\ -\158\255\103\000\000\000\002\255\215\254\056\254\209\003\000\000\ -\007\003\026\005\000\000\015\000\000\000\147\255\188\004\013\004\ -\000\000\000\000\000\000\000\000\218\000\189\002\196\002\036\003\ -\194\002\171\004\172\004\175\004\178\004\174\004\000\000\229\254\ -\114\255\000\000\148\002\000\000\000\000\143\002\000\000\000\000\ -\129\002" +\000\000\065\005\236\255\188\004\013\255\099\003\008\000\000\000\ +\241\255\166\255\039\253\216\254\083\000\143\254\000\000\125\002\ +\000\000\000\000\000\000\000\000\207\253\120\002\149\000\000\000\ +\033\000\000\000\122\255\252\003\100\255\216\255\005\000\075\005\ +\114\255\205\255\063\254\236\002\234\002\124\255\000\000\228\255\ +\212\255\000\000\076\003\187\004\000\000\000\000\170\255\095\255\ +\233\255\109\255\000\000\112\002\012\000\057\254\240\255\034\000\ +\191\254\000\000\000\000\000\000\210\253\059\001\185\001\104\001\ +\098\001\217\001\105\001\169\003\172\003\168\003\171\003\173\003\ +\000\000\208\002\042\004\144\253\198\255\000\000\000\000\237\002\ +\000\000\000\000\193\255\222\253\186\253\106\254\020\004\000\000\ +\000\000\066\002\062\002\000\000\000\000\000\000\057\004\000\000\ +\131\255\091\000\000\000\082\255\230\254\064\254\112\003\000\000\ +\166\002\190\004\000\000\232\255\000\000\155\255\091\004\187\003\ +\000\000\000\000\000\000\000\000\051\000\035\002\049\002\114\002\ +\050\002\086\004\088\004\085\004\087\004\093\004\000\000\229\254\ +\120\255\000\000\057\002\000\000\000\000\058\002\000\000\000\000\ +\044\002" -let yytablesize = 8312 +let yytablesize = 8337 let yytable = "\071\000\ -\071\000\063\001\071\000\140\000\157\000\150\000\093\000\177\000\ -\076\001\086\000\017\001\164\000\225\001\165\000\216\001\199\000\ -\068\001\150\000\232\001\109\002\056\000\056\000\144\000\104\002\ -\116\000\255\001\000\002\152\000\003\000\192\002\003\000\100\002\ -\003\000\007\000\167\002\237\002\065\000\130\001\240\002\152\000\ -\131\001\066\000\108\002\155\000\065\001\198\000\054\001\110\002\ -\212\002\072\000\076\000\056\000\081\000\073\001\118\000\011\001\ -\071\000\110\001\086\001\087\001\071\000\231\001\021\001\022\001\ -\065\000\071\000\221\001\056\000\076\001\066\000\226\001\130\001\ -\075\001\130\001\187\001\083\000\188\001\040\001\145\000\040\001\ -\202\000\180\001\116\000\012\001\214\002\064\001\204\002\136\000\ -\215\002\181\001\023\001\116\000\116\000\116\000\116\000\116\000\ -\116\000\116\000\091\001\140\000\140\000\006\003\216\002\227\000\ -\016\001\034\003\181\000\065\000\067\000\145\000\190\000\003\000\ -\066\000\065\000\212\002\194\000\048\001\063\000\066\000\077\000\ -\013\001\082\000\156\000\065\001\007\003\065\000\074\001\008\001\ -\148\001\191\000\066\000\068\000\140\001\083\000\138\001\071\000\ -\075\000\065\000\043\003\015\002\176\001\093\001\066\000\044\001\ -\069\000\105\002\176\001\181\001\077\001\018\003\049\000\049\000\ -\015\003\061\000\070\000\056\000\040\001\139\001\040\001\068\000\ -\040\001\056\000\061\003\017\001\064\001\108\002\108\002\078\000\ -\084\000\085\000\107\001\132\001\069\000\200\002\078\000\078\000\ -\182\000\059\001\078\000\078\000\239\001\049\000\070\000\078\000\ -\116\000\180\000\065\000\130\001\094\000\130\001\018\002\066\000\ -\019\002\049\000\218\002\243\001\123\002\049\000\130\001\153\000\ -\124\001\020\002\232\001\118\002\078\000\132\001\078\000\132\001\ -\141\001\078\000\028\002\029\002\054\001\170\000\168\002\056\000\ -\054\001\054\001\248\001\090\003\035\002\038\002\096\000\001\002\ -\097\000\070\000\084\000\085\000\090\003\097\002\063\001\070\000\ -\231\001\090\001\255\002\197\000\098\001\099\001\100\001\095\002\ -\188\001\103\001\104\001\070\000\041\001\231\001\230\000\001\000\ -\002\000\108\002\116\000\108\002\070\002\108\002\115\002\070\000\ -\117\002\098\000\194\001\042\001\071\000\071\000\222\001\116\000\ +\071\000\157\000\071\000\140\000\150\000\177\000\227\000\063\001\ +\076\001\086\000\165\000\093\000\056\000\056\000\216\001\118\000\ +\150\000\225\001\017\001\054\001\255\001\000\002\086\001\087\001\ +\116\000\152\000\104\002\144\000\199\000\068\001\003\000\003\000\ +\164\000\232\001\073\001\003\000\191\002\152\000\109\002\100\002\ +\110\002\031\000\007\000\056\000\071\001\198\000\044\001\222\000\ +\141\000\072\000\076\000\063\000\081\000\011\001\155\000\224\000\ +\071\000\021\001\022\001\056\000\071\000\224\000\082\002\110\001\ +\041\001\071\000\224\000\221\001\076\001\167\002\065\000\226\001\ +\050\003\064\001\094\000\066\000\039\001\131\001\063\001\042\001\ +\202\000\096\000\116\000\075\001\071\001\023\001\108\002\203\002\ +\008\001\083\002\061\003\116\000\116\000\116\000\116\000\116\000\ +\116\000\116\000\211\002\140\000\140\000\145\000\222\000\215\002\ +\016\001\033\000\181\000\077\000\077\003\082\000\190\000\187\001\ +\191\000\188\001\097\000\194\000\224\000\222\000\037\000\003\000\ +\038\000\048\001\071\001\222\000\046\001\074\001\071\001\071\001\ +\065\000\046\001\224\000\224\000\156\000\066\000\224\000\071\000\ +\224\000\224\000\224\000\083\000\093\001\231\001\180\000\140\001\ +\141\000\141\000\077\001\056\000\105\002\049\000\049\000\064\001\ +\061\000\056\000\039\001\016\003\063\001\002\001\003\001\004\001\ +\005\001\006\001\007\001\211\002\182\000\222\000\078\000\168\002\ +\132\001\098\000\139\001\017\001\213\002\078\000\078\000\107\001\ +\214\002\078\000\078\000\224\000\049\000\199\002\078\000\230\002\ +\116\000\054\001\013\003\001\002\070\000\054\001\054\001\123\002\ +\049\000\239\001\046\001\136\000\049\000\046\001\153\000\248\001\ +\124\001\145\000\132\001\078\000\132\001\078\000\141\001\056\000\ +\078\000\108\002\108\002\145\000\170\000\217\002\083\000\138\001\ +\090\001\232\001\118\002\098\001\099\001\100\001\146\000\224\001\ +\103\001\104\001\088\003\018\002\178\001\019\002\137\000\091\001\ +\084\000\085\000\197\000\088\003\063\001\039\001\020\002\065\000\ +\095\002\145\000\046\001\179\001\066\000\230\000\249\001\028\002\ +\029\002\244\002\116\000\245\002\253\002\247\002\197\001\115\002\ +\003\002\117\002\194\001\187\001\071\000\071\000\163\000\116\000\ \116\000\116\000\116\000\116\000\116\000\116\000\116\000\116\000\ \116\000\116\000\116\000\116\000\116\000\116\000\116\000\116\000\ -\116\000\116\000\116\000\108\002\007\000\049\000\007\000\220\001\ -\007\000\049\000\049\000\049\000\068\000\197\001\072\002\073\002\ -\021\002\246\002\140\002\247\002\155\002\249\002\065\000\235\001\ -\022\002\069\000\145\002\066\000\065\000\228\002\195\001\196\001\ -\164\000\066\000\137\000\072\001\071\000\070\001\170\000\082\002\ -\224\001\132\001\070\001\132\001\002\001\003\001\004\001\005\001\ -\006\001\007\001\015\001\223\000\132\001\188\001\188\001\071\000\ -\015\001\093\002\223\000\178\001\017\001\052\003\047\001\249\001\ -\106\001\049\000\083\002\047\001\138\000\223\000\072\001\132\002\ -\133\002\003\002\179\001\065\000\072\001\072\001\072\001\063\003\ -\066\000\158\002\217\002\232\002\162\002\145\000\003\000\141\000\ -\143\000\230\000\159\000\065\000\070\001\250\001\189\000\023\003\ -\066\000\079\003\026\003\162\000\173\000\142\002\071\000\071\000\ -\022\002\054\001\146\000\070\001\054\001\035\003\070\001\203\002\ -\181\001\223\000\002\002\027\002\145\000\004\002\181\001\166\000\ -\054\001\054\001\054\001\230\000\223\000\230\000\010\002\223\000\ -\223\000\173\000\013\002\223\000\047\001\223\000\223\000\223\000\ -\091\001\092\001\040\003\223\000\070\000\116\000\116\000\176\000\ -\159\002\223\000\048\003\193\000\050\003\088\001\103\002\178\000\ -\032\002\033\002\088\001\070\001\056\003\145\000\091\002\242\002\ -\179\000\070\001\243\002\080\000\054\001\070\001\070\001\070\001\ -\159\002\064\003\070\001\057\001\111\002\188\000\047\001\070\001\ -\223\000\192\000\163\000\047\001\047\001\200\000\071\000\141\000\ -\141\000\076\001\068\000\223\000\205\002\206\002\250\002\251\002\ -\252\002\070\000\093\001\047\001\070\001\240\001\089\003\069\000\ -\047\001\047\001\252\000\170\000\010\001\224\001\047\001\219\002\ -\014\003\070\000\076\001\070\001\061\001\188\001\070\001\009\001\ -\070\001\198\001\199\001\200\001\070\001\088\001\029\001\030\001\ -\049\001\050\001\047\001\054\001\235\002\047\001\054\001\070\001\ -\088\002\050\001\070\001\070\001\027\001\028\001\070\001\230\000\ -\233\001\230\000\070\001\124\002\047\001\016\003\037\001\047\001\ -\223\002\050\001\230\000\094\002\051\001\052\001\225\000\024\003\ -\031\000\054\001\025\003\230\000\230\000\225\000\039\001\031\000\ -\033\001\047\001\225\000\088\001\047\001\013\003\047\001\047\001\ -\033\001\038\001\047\001\007\000\180\001\040\001\047\001\070\001\ -\007\000\019\003\180\001\070\001\014\001\130\001\045\001\101\000\ -\126\002\015\001\047\001\061\001\047\001\047\001\116\000\211\000\ -\211\000\071\000\188\002\056\001\255\000\001\001\057\001\091\002\ -\058\001\048\001\188\001\188\001\103\000\064\001\048\001\104\000\ -\066\001\047\001\163\002\069\001\225\000\235\001\070\001\047\001\ -\033\000\149\002\191\002\143\001\144\001\077\001\071\001\033\000\ -\224\001\072\001\225\000\225\000\145\000\037\000\225\000\038\000\ -\225\000\225\000\225\000\078\001\037\000\070\002\038\000\035\001\ -\036\001\145\001\146\001\148\002\147\001\071\000\141\001\148\001\ -\210\002\071\000\054\001\164\001\165\001\170\000\190\002\070\002\ -\114\002\072\001\080\001\240\001\081\001\071\000\049\001\241\002\ -\166\001\167\001\114\000\082\001\224\001\085\001\052\001\048\001\ -\088\001\070\002\048\001\225\000\072\001\033\003\052\001\089\001\ -\111\002\211\002\225\002\225\002\224\001\097\001\224\001\050\001\ -\101\001\233\002\051\001\052\001\102\001\056\000\031\000\088\002\ -\049\001\105\001\072\001\207\002\115\001\117\001\033\003\118\001\ -\119\001\120\001\121\001\122\001\123\001\126\001\127\001\088\002\ -\024\001\025\001\026\001\238\002\133\001\072\001\033\003\048\001\ -\112\001\050\001\172\001\173\001\051\001\052\001\014\001\158\000\ -\031\000\101\000\113\001\015\001\083\000\072\001\137\001\225\002\ -\072\001\134\001\225\002\072\001\072\001\072\001\135\001\199\000\ -\199\000\199\000\027\003\028\003\225\002\012\003\103\000\225\002\ -\136\001\104\000\142\001\072\001\175\001\049\001\033\000\072\001\ -\072\001\174\001\225\002\044\003\161\001\162\001\163\001\227\001\ -\074\000\177\001\228\001\037\000\176\001\038\000\009\001\009\001\ -\158\000\182\001\057\003\053\003\211\000\211\000\050\001\183\001\ -\197\000\051\001\052\001\070\001\070\001\031\000\184\001\225\002\ -\033\000\074\000\229\001\170\000\074\000\074\000\185\001\225\002\ -\074\000\225\002\199\000\199\000\199\000\037\000\186\001\038\000\ -\189\001\225\002\029\003\030\003\114\000\230\000\230\000\041\003\ -\074\000\074\000\074\000\074\000\074\000\074\000\225\002\049\000\ -\190\001\084\000\085\000\217\001\074\000\074\000\074\000\192\001\ -\074\000\074\000\240\001\046\001\047\001\077\003\074\000\218\001\ -\074\000\054\002\055\002\074\000\074\000\074\000\074\000\074\000\ -\074\000\106\001\219\001\225\002\144\000\033\000\236\001\229\001\ -\233\001\144\000\144\000\144\000\031\001\032\001\033\001\034\001\ -\074\000\238\001\037\000\242\001\038\000\056\002\057\002\004\000\ -\252\001\088\003\240\001\006\000\059\000\074\000\253\001\074\000\ -\005\002\008\000\062\002\063\002\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\254\001\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\006\002\050\002\051\002\052\002\ +\116\000\116\000\116\000\222\001\049\000\220\001\007\000\007\000\ +\049\000\049\000\049\000\007\000\108\002\138\000\108\002\143\000\ +\108\002\159\000\027\002\140\002\072\002\073\002\130\001\235\001\ +\162\000\155\002\145\002\084\000\085\000\097\002\195\001\196\001\ +\231\001\001\000\002\000\039\001\071\000\170\000\132\001\039\001\ +\132\001\235\002\065\000\065\000\238\002\231\001\108\002\066\000\ +\066\000\132\001\198\001\199\001\200\001\164\000\145\000\071\000\ +\130\001\087\001\130\001\012\001\065\000\069\001\087\001\106\001\ +\049\000\066\000\069\001\068\000\017\001\166\000\093\002\180\001\ +\187\001\187\001\091\001\092\001\015\002\070\000\054\001\181\001\ +\069\000\054\001\158\002\003\000\181\001\162\002\046\001\216\002\ +\230\000\069\001\021\002\046\001\173\000\054\001\054\001\054\001\ +\013\001\002\002\022\002\176\000\004\002\233\001\071\000\071\000\ +\069\001\222\000\014\003\069\001\224\001\010\002\032\003\222\000\ +\202\002\013\002\189\000\193\000\069\001\250\001\179\000\014\001\ +\178\000\046\001\230\000\173\000\230\000\014\001\046\001\065\000\ +\188\000\087\001\069\001\069\001\066\000\142\002\069\001\071\001\ +\022\002\054\001\069\001\255\000\001\001\116\000\116\000\041\003\ +\047\001\065\000\124\002\192\000\103\002\047\001\066\000\200\000\ +\032\002\033\002\069\001\032\001\046\001\091\002\056\001\046\001\ +\070\000\070\000\069\001\032\001\069\001\240\002\222\000\059\003\ +\241\002\069\001\071\001\111\002\130\001\187\001\130\001\087\001\ +\071\001\071\001\071\001\069\001\222\000\222\000\071\000\130\001\ +\222\000\076\001\222\000\222\000\222\000\175\001\046\001\046\001\ +\065\000\093\001\046\001\175\001\240\001\066\000\046\001\067\000\ +\054\001\252\000\170\000\054\001\046\001\035\002\038\002\065\000\ +\012\003\009\001\076\001\065\000\066\000\051\001\047\001\059\001\ +\066\000\047\001\007\000\069\001\010\001\051\001\068\000\007\000\ +\149\002\204\002\205\002\180\001\004\003\222\000\054\001\224\001\ +\088\002\180\001\069\001\069\000\179\001\070\002\230\000\046\001\ +\230\000\046\001\179\001\115\001\117\001\070\000\046\001\022\003\ +\037\001\230\000\023\003\005\003\126\001\127\001\222\002\148\001\ +\060\001\038\001\230\000\230\000\069\001\039\001\047\001\070\000\ +\075\000\069\001\187\001\187\001\049\001\046\001\045\001\126\002\ +\046\001\144\000\056\001\224\001\049\001\243\001\144\000\144\000\ +\144\000\014\001\069\001\080\000\101\000\040\001\015\001\068\000\ +\210\002\046\001\057\001\224\001\046\001\224\001\116\000\027\001\ +\028\001\071\000\187\002\049\001\069\000\058\001\091\002\029\001\ +\030\001\103\000\068\000\064\001\104\000\066\001\070\000\046\001\ +\035\001\036\001\163\002\069\001\069\001\235\001\072\001\069\000\ +\070\001\236\002\190\002\077\001\050\001\070\000\054\001\051\001\ +\052\001\070\000\069\001\031\000\071\001\069\001\060\001\145\000\ +\132\002\133\002\210\000\210\000\024\001\025\001\026\001\071\001\ +\161\001\162\001\163\001\148\002\141\001\071\000\189\002\078\001\ +\031\003\071\000\081\001\010\003\170\000\209\002\088\001\046\001\ +\164\001\165\001\240\001\239\002\082\001\071\000\080\001\114\000\ +\166\001\167\001\085\001\118\001\119\001\120\001\121\001\122\001\ +\123\001\031\003\069\001\248\002\249\002\250\002\111\002\071\001\ +\172\001\173\001\224\002\025\003\026\003\056\000\008\001\008\001\ +\231\002\031\003\089\001\033\000\097\001\229\001\101\001\088\002\ +\147\001\147\001\102\001\206\002\210\000\210\000\114\002\069\001\ +\037\000\159\002\038\000\049\001\147\001\147\001\147\001\088\002\ +\147\001\147\001\071\001\105\001\039\003\071\001\147\001\049\001\ +\071\001\071\001\071\001\147\001\147\001\147\001\147\001\049\001\ +\147\001\159\002\069\001\069\001\050\001\112\001\224\002\051\001\ +\052\001\224\002\113\001\031\000\198\000\198\000\198\000\069\001\ +\050\001\133\001\224\002\051\001\052\001\224\002\134\001\031\000\ +\050\001\158\000\135\001\051\001\052\001\136\001\042\003\031\000\ +\224\002\137\001\147\001\031\001\032\001\033\001\034\001\142\001\ +\218\002\198\000\198\000\198\000\174\001\055\003\086\003\027\003\ +\028\003\051\003\069\001\046\001\047\001\069\001\175\001\197\000\ +\069\001\069\001\069\001\176\001\233\002\224\002\227\001\056\002\ +\057\002\228\001\170\000\054\002\055\002\224\002\116\002\224\002\ +\177\001\228\001\158\000\033\000\062\002\063\002\182\001\224\002\ +\168\001\169\001\170\001\171\001\230\000\230\000\183\001\033\000\ +\037\000\229\001\038\000\184\001\224\002\185\001\049\000\033\000\ +\186\001\229\001\049\001\189\001\037\000\011\003\038\000\082\000\ +\190\001\240\001\217\001\075\003\037\000\192\001\038\000\218\001\ +\017\003\219\001\143\001\144\001\130\001\201\001\202\001\106\001\ +\233\001\224\002\238\001\050\001\236\001\094\002\051\001\052\001\ +\082\000\242\001\031\000\082\000\082\000\203\001\204\001\082\000\ +\145\001\146\001\252\001\147\001\209\001\210\001\148\001\253\001\ +\240\001\050\002\051\002\052\002\053\002\053\002\053\002\053\002\ \053\002\053\002\053\002\053\002\053\002\053\002\053\002\053\002\ -\053\002\053\002\053\002\053\002\053\002\053\002\053\002\007\002\ -\178\000\178\000\178\000\008\002\178\000\178\000\178\000\178\000\ -\178\000\178\000\178\000\178\000\178\000\178\000\178\000\178\000\ -\178\000\178\000\178\000\178\000\178\000\178\000\009\002\178\000\ -\178\000\178\000\178\000\178\000\178\000\178\000\178\000\178\000\ -\178\000\178\000\178\000\178\000\178\000\178\000\178\000\178\000\ -\178\000\197\000\161\001\033\000\034\000\011\002\036\000\161\001\ -\161\001\161\001\161\001\168\001\169\001\170\001\171\001\012\002\ -\037\000\014\002\038\000\016\002\178\000\178\000\178\000\017\002\ -\043\000\178\000\178\000\024\002\139\000\178\000\178\000\201\001\ -\202\001\023\002\178\000\178\000\030\002\178\000\178\000\178\000\ -\203\001\204\001\025\002\178\000\209\001\210\001\161\001\178\000\ -\178\000\178\000\178\000\178\000\178\000\178\000\178\000\178\000\ -\178\000\178\000\178\000\031\002\026\002\135\002\178\000\178\000\ -\178\000\178\000\178\000\178\000\074\002\178\000\075\002\077\002\ -\079\002\178\000\178\000\178\000\178\000\178\000\178\000\178\000\ -\078\002\080\002\098\002\178\000\178\000\101\002\178\000\178\000\ -\058\002\059\002\060\002\061\002\102\002\113\002\163\000\163\000\ -\163\000\119\002\121\002\163\000\163\000\163\000\163\000\163\000\ +\053\002\053\002\053\002\082\000\082\000\082\000\254\001\082\000\ +\082\000\005\002\030\002\014\001\070\002\082\000\101\000\082\000\ +\015\001\083\000\082\000\082\000\082\000\082\000\082\000\082\000\ +\058\002\059\002\060\002\061\002\008\002\006\002\070\002\007\002\ +\009\002\011\002\033\000\103\000\012\002\014\002\104\000\082\000\ +\205\001\206\001\207\001\208\001\016\002\017\002\024\002\037\000\ +\070\002\038\000\023\002\025\002\082\000\026\002\082\000\031\002\ +\074\002\177\000\177\000\075\002\177\000\177\000\177\000\177\000\ +\177\000\177\000\177\000\177\000\177\000\177\000\177\000\177\000\ +\177\000\177\000\177\000\177\000\177\000\177\000\197\000\177\000\ +\177\000\177\000\177\000\177\000\177\000\177\000\177\000\177\000\ +\177\000\177\000\177\000\177\000\177\000\177\000\177\000\177\000\ +\177\000\114\000\077\002\079\002\078\002\080\002\098\002\101\002\ +\113\002\135\002\102\002\119\002\121\002\122\002\084\000\085\000\ +\127\002\128\002\129\002\130\002\177\000\177\000\177\000\131\002\ +\136\002\177\000\177\000\139\002\137\002\177\000\177\000\141\002\ +\138\002\022\002\177\000\177\000\144\002\177\000\177\000\177\000\ +\143\002\181\001\134\002\177\000\146\002\147\002\150\002\177\000\ +\177\000\177\000\177\000\177\000\177\000\177\000\177\000\177\000\ +\177\000\177\000\177\000\151\002\153\002\154\002\177\000\177\000\ +\177\000\177\000\177\000\177\000\156\002\177\000\157\002\161\002\ +\195\002\177\000\177\000\177\000\177\000\177\000\177\000\177\000\ +\164\002\169\002\196\002\177\000\177\000\197\002\177\000\177\000\ +\163\000\163\000\201\002\219\002\163\000\163\000\163\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\122\002\163\000\163\000\163\000\ +\163\000\163\000\163\000\163\000\163\000\220\002\163\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\163\000\163\000\163\000\127\002\ -\128\002\079\000\205\001\206\001\207\001\208\001\129\002\130\002\ -\131\002\090\000\136\002\137\002\091\000\092\000\143\002\139\002\ -\141\002\095\000\163\000\163\000\163\000\138\002\134\002\163\000\ -\163\000\022\002\144\002\163\000\163\000\181\001\146\002\147\002\ -\163\000\163\000\150\002\163\000\163\000\163\000\160\000\151\002\ -\161\000\163\000\153\002\154\002\053\002\163\000\163\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\156\002\157\002\161\002\163\000\163\000\163\000\163\000\ -\163\000\163\000\164\002\163\000\196\002\169\002\197\002\163\000\ -\163\000\163\000\163\000\163\000\163\000\163\000\198\002\202\002\ -\220\002\163\000\163\000\221\002\222\002\163\000\163\000\163\000\ -\163\000\230\002\236\002\163\000\163\000\163\000\163\000\163\000\ +\053\002\160\001\079\000\228\002\221\002\229\002\160\001\160\001\ +\160\001\160\001\090\000\234\002\243\002\091\000\092\000\237\002\ +\254\002\246\002\095\000\163\000\163\000\163\000\255\002\000\003\ +\163\000\163\000\001\003\002\003\163\000\163\000\003\003\007\003\ +\015\003\163\000\163\000\008\003\163\000\163\000\163\000\160\000\ +\029\003\161\000\163\000\018\003\019\003\160\001\163\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\231\002\163\000\163\000\163\000\ +\163\000\163\000\034\003\035\003\036\003\163\000\163\000\163\000\ +\163\000\163\000\163\000\037\003\163\000\040\003\043\003\049\003\ +\163\000\163\000\163\000\163\000\163\000\163\000\163\000\053\003\ +\057\003\063\003\163\000\163\000\163\000\163\000\163\000\060\003\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\163\000\163\000\163\000\239\002\ -\150\001\151\001\152\001\153\001\154\001\155\001\156\001\157\001\ -\158\001\159\001\160\001\049\001\245\002\248\002\000\003\001\003\ -\002\003\004\003\163\000\163\000\163\000\003\003\005\003\163\000\ -\163\000\009\003\010\003\163\000\163\000\070\001\031\003\017\003\ -\163\000\163\000\020\003\163\000\050\001\163\000\021\003\051\001\ -\052\001\163\000\036\003\031\000\037\003\163\000\163\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\038\003\039\003\045\003\163\000\163\000\163\000\163\000\ -\163\000\163\000\051\003\163\000\042\003\055\003\070\001\163\000\ -\163\000\163\000\163\000\163\000\163\000\163\000\059\003\065\003\ -\062\003\163\000\163\000\070\003\071\003\163\000\079\001\079\001\ -\079\001\072\003\079\001\079\001\073\003\079\001\079\001\079\001\ -\079\001\079\001\079\001\079\001\079\001\074\003\148\001\148\001\ -\076\003\070\001\078\003\033\000\070\001\080\003\083\003\070\001\ -\070\001\070\001\148\001\148\001\148\001\084\003\148\001\148\001\ -\037\000\085\003\038\000\092\003\148\001\079\001\079\001\093\003\ -\094\003\148\001\148\001\148\001\148\001\026\001\148\001\039\002\ -\040\002\041\002\042\002\043\002\044\002\045\002\046\002\047\002\ -\048\002\049\002\079\001\079\001\079\001\001\001\007\000\079\001\ -\079\001\209\000\038\001\079\001\079\001\028\001\027\000\167\001\ -\079\001\079\001\058\001\079\001\162\000\079\001\164\001\028\000\ -\148\001\079\001\007\001\007\000\140\000\079\001\079\001\079\001\ -\079\001\079\001\079\001\079\001\079\001\079\001\079\001\079\001\ -\079\001\142\000\127\000\169\000\125\000\043\001\079\001\173\001\ -\079\001\079\001\147\000\079\001\178\001\186\001\142\000\079\001\ -\079\001\142\000\079\001\190\001\192\001\058\000\043\001\008\003\ -\099\002\011\003\079\001\251\001\079\001\162\000\167\000\167\000\ -\167\000\062\000\167\000\167\000\167\000\167\000\167\000\167\000\ +\163\000\068\003\163\000\163\000\163\000\163\000\163\000\163\000\ +\163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ +\163\000\163\000\163\000\163\000\069\003\150\001\151\001\152\001\ +\153\001\154\001\155\001\156\001\157\001\158\001\159\001\160\001\ +\070\003\071\003\072\003\074\003\078\003\076\003\081\003\163\000\ +\163\000\163\000\082\003\090\003\163\000\163\000\083\003\091\003\ +\163\000\163\000\025\001\000\001\092\003\163\000\163\000\007\000\ +\163\000\037\001\163\000\208\000\027\001\027\000\163\000\166\001\ +\163\001\057\001\163\000\163\000\163\000\163\000\163\000\163\000\ +\163\000\163\000\163\000\163\000\163\000\163\000\028\000\006\001\ +\007\000\163\000\163\000\163\000\163\000\163\000\163\000\140\000\ +\163\000\142\000\127\000\169\000\163\000\163\000\163\000\163\000\ +\163\000\163\000\163\000\125\000\147\000\042\001\163\000\163\000\ +\078\001\078\001\163\000\078\001\078\001\172\001\078\001\078\001\ +\078\001\078\001\078\001\078\001\078\001\078\001\142\000\177\001\ +\110\001\110\001\110\001\110\001\110\001\110\001\110\001\110\001\ +\110\001\110\001\110\001\110\001\110\001\185\001\110\001\110\001\ +\110\001\142\000\110\001\110\001\110\001\110\001\078\001\078\001\ +\110\001\191\001\058\000\043\001\110\001\110\001\110\001\110\001\ +\110\001\099\002\110\001\006\003\009\003\251\001\062\000\166\002\ +\165\002\125\002\060\001\078\001\078\001\078\001\064\002\066\002\ +\078\001\078\001\065\002\067\002\078\001\078\001\068\002\208\002\ +\047\003\078\001\078\001\200\002\078\001\162\000\078\001\120\002\ +\251\002\056\003\078\001\193\001\110\001\084\001\078\001\078\001\ +\078\001\078\001\078\001\078\001\078\001\078\001\078\001\078\001\ +\078\001\078\001\211\001\213\001\076\002\212\001\214\001\078\001\ +\079\003\078\001\078\001\080\003\078\001\215\001\000\000\093\003\ +\078\001\078\001\000\000\078\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\078\001\000\000\078\001\162\000\167\000\ +\167\000\000\000\167\000\167\000\167\000\167\000\167\000\167\000\ \167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\125\002\167\000\167\000\167\000\ +\167\000\167\000\167\000\167\000\000\000\167\000\167\000\167\000\ \167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\165\002\ -\060\001\166\002\064\002\201\002\209\002\049\003\058\003\065\002\ -\120\002\084\001\253\002\066\002\193\001\067\002\076\002\211\001\ -\068\002\212\001\167\000\167\000\167\000\213\001\215\001\167\000\ -\167\000\214\001\082\003\167\000\167\000\081\003\095\003\000\000\ +\167\000\167\000\167\000\167\000\167\000\167\000\167\000\039\002\ +\040\002\041\002\042\002\043\002\044\002\045\002\046\002\047\002\ +\048\002\049\002\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\167\000\167\000\167\000\000\000\000\000\167\000\ +\167\000\000\000\000\000\167\000\167\000\000\000\000\000\000\000\ \167\000\167\000\000\000\167\000\167\000\167\000\000\000\000\000\ \000\000\167\000\000\000\000\000\000\000\167\000\167\000\167\000\ \167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ \167\000\000\000\000\000\000\000\167\000\167\000\167\000\167\000\ \167\000\167\000\000\000\167\000\000\000\000\000\167\000\167\000\ \167\000\167\000\167\000\167\000\167\000\167\000\000\000\000\000\ -\000\000\167\000\167\000\000\000\167\000\156\000\156\000\156\000\ -\000\000\156\000\156\000\156\000\156\000\156\000\156\000\156\000\ +\000\000\167\000\167\000\000\000\167\000\156\000\156\000\000\000\ \156\000\156\000\156\000\156\000\156\000\156\000\156\000\156\000\ -\156\000\156\000\156\000\000\000\156\000\156\000\156\000\156\000\ \156\000\156\000\156\000\156\000\156\000\156\000\156\000\156\000\ -\156\000\156\000\156\000\156\000\156\000\156\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\156\000\156\000\156\000\000\000\000\000\156\000\156\000\ -\000\000\000\000\156\000\156\000\000\000\000\000\000\000\156\000\ -\156\000\000\000\156\000\156\000\156\000\000\000\000\000\000\000\ -\156\000\000\000\000\000\000\000\156\000\156\000\156\000\156\000\ +\156\000\156\000\000\000\156\000\156\000\156\000\156\000\156\000\ \156\000\156\000\156\000\156\000\156\000\156\000\156\000\156\000\ -\000\000\000\000\000\000\156\000\156\000\156\000\156\000\156\000\ -\156\000\000\000\156\000\000\000\000\000\000\000\156\000\156\000\ \156\000\156\000\156\000\156\000\156\000\000\000\000\000\000\000\ -\156\000\156\000\000\000\156\000\170\002\171\002\224\002\000\000\ -\104\002\173\002\006\000\081\002\204\000\205\000\206\000\207\000\ -\174\002\083\000\208\000\009\000\010\000\011\000\012\000\013\000\ -\014\000\015\000\000\000\016\000\017\000\018\000\019\000\020\000\ -\021\000\022\000\023\000\024\000\060\000\026\000\027\000\028\000\ -\029\000\030\000\031\000\209\000\210\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\211\000\212\000\213\000\000\000\000\000\214\000\215\000\000\000\ -\000\000\216\000\217\000\000\000\000\000\000\000\218\000\219\000\ -\000\000\220\000\000\000\156\000\000\000\000\000\000\000\175\002\ -\000\000\000\000\000\000\176\002\177\002\178\002\179\002\180\002\ -\181\002\182\002\000\000\000\000\000\000\183\002\184\002\000\000\ -\000\000\000\000\033\000\034\000\185\002\036\000\084\000\085\000\ -\000\000\221\000\000\000\000\000\000\000\222\000\223\000\037\000\ -\186\002\038\000\000\000\000\000\000\000\000\000\000\000\043\000\ -\224\000\000\000\105\002\079\001\079\001\079\001\000\000\079\001\ -\079\001\000\000\079\001\079\001\079\001\079\001\079\001\079\001\ -\079\001\079\001\000\000\000\000\111\001\111\001\111\001\111\001\ -\111\001\111\001\111\001\111\001\111\001\111\001\111\001\111\001\ -\111\001\000\000\111\001\111\001\111\001\000\000\111\001\111\001\ -\111\001\111\001\079\001\079\001\111\001\000\000\000\000\000\000\ -\111\001\111\001\111\001\111\001\111\001\000\000\111\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\079\001\ -\079\001\079\001\000\000\000\000\079\001\079\001\000\000\000\000\ -\079\001\079\001\000\000\000\000\000\000\079\001\079\001\000\000\ -\079\001\000\000\079\001\000\000\000\000\000\000\079\001\000\000\ -\111\001\000\000\079\001\079\001\079\001\079\001\079\001\079\001\ -\079\001\079\001\079\001\079\001\079\001\079\001\000\000\000\000\ -\000\000\000\000\000\000\079\001\104\001\079\001\079\001\000\000\ -\079\001\000\000\000\000\000\000\079\001\079\001\000\000\079\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\079\001\ -\000\000\079\001\170\002\171\002\224\002\000\000\104\002\173\002\ -\000\000\081\002\204\000\205\000\206\000\207\000\066\000\083\000\ -\208\000\000\000\000\000\104\001\104\001\104\001\104\001\104\001\ -\104\001\104\001\104\001\104\001\104\001\104\001\104\001\104\001\ -\000\000\104\001\104\001\104\001\000\000\104\001\104\001\104\001\ -\104\001\209\000\210\000\104\001\000\000\000\000\000\000\104\001\ -\104\001\104\001\104\001\104\001\000\000\104\001\000\000\000\000\ +\156\000\156\000\156\000\000\000\000\000\156\000\156\000\000\000\ +\000\000\156\000\156\000\000\000\000\000\000\000\156\000\156\000\ +\000\000\156\000\156\000\156\000\000\000\000\000\000\000\156\000\ +\000\000\000\000\000\000\156\000\156\000\156\000\156\000\156\000\ +\156\000\156\000\156\000\156\000\156\000\156\000\156\000\000\000\ +\000\000\000\000\156\000\156\000\156\000\156\000\156\000\156\000\ +\000\000\156\000\000\000\000\000\000\000\156\000\156\000\156\000\ +\156\000\156\000\156\000\156\000\000\000\000\000\000\000\156\000\ +\156\000\000\000\156\000\170\002\223\002\000\000\104\002\172\002\ +\006\000\081\002\204\000\205\000\206\000\207\000\173\002\083\000\ +\208\000\009\000\010\000\011\000\012\000\013\000\014\000\015\000\ +\000\000\016\000\017\000\018\000\019\000\020\000\021\000\022\000\ +\023\000\024\000\060\000\026\000\027\000\028\000\029\000\030\000\ +\031\000\209\000\210\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\049\001\ \000\000\000\000\000\000\000\000\000\000\000\000\211\000\212\000\ \213\000\000\000\000\000\214\000\215\000\000\000\000\000\216\000\ -\217\000\104\001\104\001\000\000\218\000\219\000\000\000\220\000\ -\000\000\156\000\000\000\000\000\000\000\175\002\000\000\104\001\ -\000\000\176\002\177\002\178\002\179\002\180\002\181\002\182\002\ -\000\000\000\000\000\000\183\002\184\002\000\000\000\000\000\000\ -\000\000\000\000\185\002\000\000\084\000\085\000\000\000\221\000\ -\000\000\000\000\000\000\222\000\223\000\249\000\186\002\000\000\ -\000\000\000\000\000\000\249\000\249\000\000\000\224\000\000\000\ -\105\002\249\000\000\000\000\000\249\000\249\000\249\000\249\000\ -\249\000\249\000\249\000\000\000\249\000\249\000\249\000\249\000\ -\249\000\249\000\249\000\249\000\249\000\249\000\249\000\249\000\ -\249\000\249\000\249\000\249\000\106\001\106\001\106\001\106\001\ +\217\000\000\000\000\000\000\000\218\000\219\000\000\000\220\000\ +\050\001\156\000\000\000\051\001\052\001\174\002\000\000\031\000\ +\000\000\175\002\176\002\177\002\178\002\179\002\180\002\181\002\ +\000\000\000\000\000\000\182\002\183\002\000\000\000\000\000\000\ +\033\000\034\000\184\002\036\000\084\000\085\000\021\003\221\000\ +\000\000\024\003\000\000\222\000\223\000\037\000\185\002\038\000\ +\000\000\000\000\000\000\000\000\033\003\043\000\224\000\000\000\ +\105\002\078\001\078\001\000\000\078\001\078\001\000\000\078\001\ +\078\001\078\001\078\001\078\001\078\001\078\001\078\001\152\001\ +\152\001\000\000\152\001\152\001\000\000\000\000\000\000\033\000\ +\152\001\038\003\000\000\000\000\000\000\152\001\152\001\152\001\ +\152\001\046\003\152\001\048\003\037\000\158\001\038\000\078\001\ +\078\001\000\000\158\001\054\003\000\000\000\000\000\000\158\001\ +\158\001\158\001\158\001\000\000\158\001\000\000\000\000\000\000\ +\062\003\000\000\000\000\000\000\078\001\078\001\078\001\000\000\ +\000\000\078\001\078\001\000\000\152\001\078\001\078\001\000\000\ +\000\000\000\000\078\001\078\001\000\000\078\001\000\000\078\001\ +\000\000\000\000\000\000\078\001\000\000\087\003\158\001\078\001\ +\078\001\078\001\078\001\078\001\078\001\078\001\078\001\078\001\ +\078\001\078\001\078\001\000\000\000\000\000\000\000\000\000\000\ +\078\001\000\000\078\001\078\001\000\000\078\001\000\000\000\000\ +\000\000\078\001\078\001\000\000\078\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\078\001\000\000\078\001\170\002\ +\223\002\000\000\104\002\172\002\000\000\081\002\204\000\205\000\ +\206\000\207\000\066\000\083\000\208\000\000\000\000\000\105\001\ +\105\001\105\001\105\001\105\001\105\001\105\001\105\001\105\001\ +\105\001\105\001\105\001\105\001\000\000\105\001\105\001\105\001\ +\000\000\105\001\105\001\105\001\105\001\209\000\210\000\105\001\ +\000\000\000\000\000\000\105\001\105\001\105\001\105\001\105\001\ +\000\000\105\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\211\000\212\000\213\000\000\000\000\000\214\000\ +\215\000\000\000\000\000\216\000\217\000\000\000\000\000\000\000\ +\218\000\219\000\000\000\220\000\000\000\156\000\000\000\000\000\ +\000\000\174\002\000\000\105\001\000\000\175\002\176\002\177\002\ +\178\002\179\002\180\002\181\002\000\000\000\000\000\000\182\002\ +\183\002\000\000\000\000\000\000\000\000\000\000\184\002\000\000\ +\084\000\085\000\000\000\221\000\000\000\000\000\000\000\222\000\ +\223\000\004\000\185\002\000\000\000\000\006\000\059\000\000\000\ +\000\000\000\000\224\000\008\000\105\002\000\000\009\000\010\000\ +\011\000\012\000\013\000\014\000\015\000\000\000\016\000\017\000\ +\018\000\019\000\020\000\021\000\022\000\023\000\024\000\060\000\ +\026\000\027\000\028\000\029\000\030\000\031\000\004\000\005\000\ +\103\001\000\000\006\000\007\000\000\000\000\000\000\000\000\000\ +\008\000\000\000\000\000\009\000\010\000\011\000\012\000\013\000\ +\014\000\015\000\000\000\016\000\017\000\018\000\019\000\020\000\ +\021\000\022\000\023\000\024\000\025\000\026\000\027\000\028\000\ +\029\000\030\000\031\000\000\000\000\000\000\000\000\000\103\001\ +\103\001\103\001\103\001\103\001\103\001\103\001\103\001\103\001\ +\103\001\103\001\103\001\103\001\000\000\103\001\103\001\103\001\ +\000\000\103\001\103\001\103\001\103\001\033\000\034\000\103\001\ +\036\000\000\000\000\000\103\001\103\001\103\001\103\001\103\001\ +\000\000\103\001\037\000\000\000\038\000\000\000\000\000\032\000\ +\000\000\000\000\043\000\000\000\000\000\000\000\139\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\103\001\103\001\000\000\ +\000\000\000\000\033\000\034\000\035\000\036\000\000\000\000\000\ +\000\000\000\000\000\000\103\001\000\000\000\000\000\000\037\000\ +\000\000\038\000\039\000\040\000\000\000\041\000\042\000\043\000\ +\248\000\000\000\044\000\000\000\000\000\248\000\248\000\000\000\ +\000\000\000\000\000\000\248\000\000\000\000\000\248\000\248\000\ +\248\000\248\000\248\000\248\000\248\000\000\000\248\000\248\000\ +\248\000\248\000\248\000\248\000\248\000\248\000\248\000\248\000\ +\248\000\248\000\248\000\248\000\248\000\248\000\106\001\106\001\ \106\001\106\001\106\001\106\001\106\001\106\001\106\001\106\001\ -\106\001\000\000\106\001\106\001\106\001\000\000\106\001\106\001\ -\106\001\106\001\000\000\249\000\106\001\000\000\000\000\000\000\ -\106\001\106\001\106\001\106\001\106\001\000\000\106\001\000\000\ -\000\000\249\000\249\000\000\000\000\000\249\000\000\000\249\000\ -\249\000\249\000\159\001\000\000\000\000\000\000\000\000\159\001\ -\000\000\000\000\000\000\000\000\159\001\159\001\159\001\159\001\ -\000\000\159\001\000\000\249\000\249\000\000\000\249\000\000\000\ -\106\001\000\000\000\000\000\000\000\000\238\000\000\000\000\000\ -\249\000\000\000\249\000\238\000\238\000\000\000\000\000\000\000\ -\249\000\238\000\249\000\000\000\238\000\238\000\238\000\238\000\ -\238\000\238\000\238\000\159\001\238\000\238\000\238\000\238\000\ +\106\001\106\001\106\001\000\000\106\001\106\001\106\001\000\000\ +\106\001\106\001\106\001\106\001\000\000\248\000\106\001\000\000\ +\000\000\000\000\106\001\106\001\106\001\106\001\106\001\000\000\ +\106\001\000\000\000\000\248\000\248\000\000\000\000\000\248\000\ +\000\000\248\000\248\000\248\000\159\001\000\000\000\000\000\000\ +\000\000\159\001\000\000\000\000\000\000\000\000\159\001\159\001\ +\159\001\159\001\000\000\159\001\000\000\248\000\248\000\000\000\ +\248\000\000\000\106\001\000\000\000\000\000\000\000\000\000\000\ +\237\000\000\000\248\000\000\000\248\000\237\000\237\000\000\000\ +\000\000\000\000\248\000\237\000\248\000\000\000\237\000\237\000\ +\237\000\237\000\237\000\237\000\237\000\159\001\237\000\237\000\ +\237\000\237\000\237\000\237\000\237\000\237\000\237\000\237\000\ +\237\000\237\000\237\000\237\000\237\000\237\000\000\000\000\000\ +\120\001\120\001\120\001\120\001\120\001\120\001\120\001\120\001\ +\120\001\120\001\120\001\000\000\120\001\120\001\120\001\000\000\ +\120\001\120\001\120\001\120\001\000\000\237\000\120\001\000\000\ +\000\000\000\000\000\000\120\001\120\001\120\001\120\001\000\000\ +\120\001\000\000\000\000\237\000\237\000\000\000\000\000\237\000\ +\000\000\237\000\237\000\237\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\237\000\237\000\000\000\ +\237\000\000\000\120\001\000\000\000\000\000\000\000\000\000\000\ +\243\000\000\000\237\000\000\000\237\000\243\000\243\000\000\000\ +\000\000\000\000\237\000\243\000\237\000\000\000\243\000\243\000\ +\243\000\243\000\243\000\243\000\243\000\000\000\243\000\243\000\ +\243\000\243\000\243\000\243\000\243\000\243\000\243\000\243\000\ +\243\000\243\000\243\000\243\000\243\000\243\000\000\000\000\000\ +\122\001\122\001\122\001\122\001\122\001\122\001\122\001\122\001\ +\122\001\122\001\122\001\000\000\122\001\122\001\122\001\000\000\ +\122\001\122\001\122\001\122\001\000\000\243\000\122\001\000\000\ +\000\000\000\000\000\000\122\001\122\001\122\001\122\001\000\000\ +\122\001\000\000\000\000\243\000\243\000\000\000\000\000\243\000\ +\000\000\243\000\243\000\243\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\243\000\243\000\000\000\ +\243\000\000\000\122\001\000\000\000\000\000\000\000\000\000\000\ +\238\000\000\000\243\000\000\000\243\000\238\000\238\000\000\000\ +\000\000\000\000\243\000\238\000\243\000\000\000\238\000\238\000\ +\238\000\238\000\238\000\238\000\238\000\000\000\238\000\238\000\ \238\000\238\000\238\000\238\000\238\000\238\000\238\000\238\000\ -\238\000\238\000\238\000\238\000\107\001\107\001\107\001\107\001\ -\107\001\107\001\107\001\107\001\107\001\107\001\107\001\107\001\ -\107\001\000\000\107\001\107\001\107\001\000\000\107\001\107\001\ -\107\001\107\001\000\000\238\000\107\001\000\000\000\000\000\000\ -\107\001\107\001\107\001\107\001\107\001\000\000\107\001\000\000\ -\000\000\238\000\238\000\000\000\000\000\238\000\000\000\238\000\ -\238\000\238\000\160\001\000\000\000\000\000\000\000\000\160\001\ -\000\000\000\000\000\000\000\000\160\001\160\001\160\001\160\001\ -\000\000\160\001\000\000\238\000\238\000\000\000\238\000\000\000\ -\107\001\000\000\000\000\000\000\000\000\244\000\000\000\000\000\ -\238\000\000\000\238\000\244\000\244\000\000\000\000\000\000\000\ -\238\000\244\000\238\000\000\000\244\000\244\000\244\000\244\000\ -\244\000\244\000\244\000\160\001\244\000\244\000\244\000\244\000\ -\244\000\244\000\244\000\244\000\244\000\244\000\244\000\244\000\ -\244\000\244\000\244\000\244\000\000\000\000\000\121\001\121\001\ -\121\001\121\001\121\001\121\001\121\001\121\001\121\001\121\001\ -\121\001\000\000\121\001\121\001\121\001\000\000\121\001\121\001\ -\121\001\121\001\000\000\244\000\121\001\000\000\000\000\000\000\ -\000\000\121\001\121\001\121\001\121\001\000\000\121\001\000\000\ -\000\000\244\000\244\000\000\000\000\000\244\000\000\000\244\000\ -\244\000\244\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\244\000\244\000\000\000\244\000\000\000\ -\121\001\000\000\000\000\000\000\000\000\239\000\000\000\000\000\ -\244\000\000\000\244\000\239\000\239\000\000\000\000\000\000\000\ -\244\000\239\000\244\000\000\000\239\000\239\000\239\000\239\000\ -\239\000\239\000\239\000\000\000\239\000\239\000\239\000\239\000\ -\239\000\239\000\239\000\239\000\239\000\239\000\239\000\239\000\ -\239\000\239\000\239\000\239\000\000\000\000\000\123\001\123\001\ -\123\001\123\001\123\001\123\001\123\001\123\001\123\001\123\001\ -\123\001\000\000\123\001\123\001\123\001\000\000\123\001\123\001\ -\123\001\123\001\000\000\239\000\123\001\000\000\000\000\000\000\ -\000\000\123\001\123\001\123\001\123\001\049\001\123\001\000\000\ -\000\000\239\000\239\000\000\000\070\001\239\000\000\000\239\000\ -\239\000\239\000\000\000\070\001\070\001\070\001\070\001\070\001\ -\070\001\070\001\070\001\000\000\000\000\000\000\050\001\000\000\ -\000\000\051\001\052\001\239\000\239\000\031\000\239\000\000\000\ -\123\001\000\000\000\000\000\000\000\000\070\001\000\000\000\000\ -\239\000\000\000\239\000\070\001\070\001\070\001\157\001\157\001\ -\239\000\000\000\239\000\000\000\157\001\000\000\000\000\000\000\ -\000\000\157\001\157\001\157\001\157\001\000\000\157\001\000\000\ -\070\001\070\001\070\001\000\000\116\002\070\001\070\001\228\001\ -\000\000\070\001\070\001\000\000\000\000\000\000\070\001\070\001\ -\070\001\070\001\000\000\070\001\070\001\070\001\070\001\070\001\ -\070\001\000\000\000\000\000\000\000\000\033\000\000\000\229\001\ -\157\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\037\000\000\000\038\000\000\000\070\001\070\001\ -\000\000\070\001\000\000\000\000\000\000\070\001\070\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\163\000\163\000\163\000\ -\070\001\070\001\163\000\163\000\163\000\163\000\163\000\163\000\ +\238\000\238\000\238\000\238\000\238\000\238\000\000\000\000\000\ +\124\001\124\001\124\001\124\001\124\001\124\001\124\001\124\001\ +\124\001\124\001\124\001\000\000\124\001\124\001\124\001\000\000\ +\124\001\124\001\124\001\124\001\000\000\238\000\124\001\000\000\ +\000\000\000\000\000\000\124\001\124\001\124\001\124\001\049\001\ +\124\001\000\000\000\000\238\000\238\000\000\000\000\000\238\000\ +\069\001\238\000\238\000\238\000\000\000\000\000\069\001\069\001\ +\069\001\069\001\069\001\069\001\069\001\069\001\000\000\000\000\ +\050\001\000\000\000\000\051\001\052\001\238\000\238\000\031\000\ +\238\000\000\000\124\001\000\000\000\000\000\000\000\000\000\000\ +\069\001\000\000\238\000\000\000\238\000\000\000\069\001\069\001\ +\069\001\000\000\238\000\000\000\238\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\069\001\069\001\069\001\116\002\000\000\ +\069\001\069\001\000\000\000\000\069\001\069\001\000\000\000\000\ +\000\000\069\001\069\001\069\001\069\001\000\000\069\001\069\001\ +\069\001\069\001\069\001\069\001\000\000\000\000\000\000\033\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\037\000\000\000\038\000\000\000\ +\000\000\069\001\069\001\000\000\069\001\000\000\000\000\000\000\ +\069\001\069\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\163\000\163\000\069\001\069\001\163\000\163\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\000\000\163\000\163\000\163\000\163\000\ +\163\000\163\000\163\000\163\000\163\000\163\000\000\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\163\000\163\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ +\163\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\163\000\163\000\163\000\000\000\000\000\163\000\163\000\ -\000\000\000\000\163\000\163\000\000\000\000\000\000\000\163\000\ -\163\000\000\000\163\000\163\000\163\000\000\000\000\000\000\000\ -\163\000\000\000\000\000\000\000\163\000\163\000\163\000\163\000\ +\000\000\000\000\000\000\000\000\163\000\163\000\163\000\000\000\ +\000\000\163\000\163\000\000\000\000\000\163\000\163\000\000\000\ +\000\000\000\000\163\000\163\000\000\000\163\000\163\000\163\000\ +\000\000\000\000\000\000\163\000\000\000\000\000\000\000\163\000\ \163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\000\000\000\000\000\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\000\000\163\000\000\000\000\000\000\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\163\000\170\002\171\002\172\002\ -\163\000\163\000\173\002\006\000\081\002\204\000\205\000\206\000\ -\207\000\174\002\083\000\208\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\000\000\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\209\000\210\000\000\000\000\000\ +\163\000\163\000\163\000\000\000\000\000\000\000\163\000\163\000\ +\163\000\163\000\163\000\163\000\000\000\163\000\000\000\000\000\ +\000\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ +\000\000\170\002\171\002\163\000\163\000\172\002\006\000\081\002\ +\204\000\205\000\206\000\207\000\173\002\083\000\208\000\009\000\ +\010\000\011\000\012\000\013\000\014\000\015\000\000\000\016\000\ +\017\000\018\000\019\000\020\000\021\000\022\000\023\000\024\000\ +\060\000\026\000\027\000\028\000\029\000\030\000\031\000\209\000\ +\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\211\000\212\000\213\000\000\000\ +\000\000\214\000\215\000\000\000\000\000\216\000\217\000\000\000\ +\000\000\000\000\218\000\219\000\000\000\220\000\000\000\156\000\ +\000\000\000\000\000\000\174\002\000\000\000\000\000\000\175\002\ +\176\002\177\002\178\002\179\002\180\002\181\002\000\000\000\000\ +\000\000\182\002\183\002\000\000\000\000\000\000\033\000\034\000\ +\184\002\036\000\084\000\085\000\000\000\221\000\000\000\000\000\ +\000\000\222\000\223\000\037\000\185\002\038\000\039\000\040\000\ +\128\001\000\000\000\000\043\000\224\000\006\000\203\000\204\000\ +\205\000\206\000\207\000\008\000\083\000\208\000\009\000\010\000\ +\011\000\012\000\013\000\014\000\015\000\000\000\016\000\017\000\ +\018\000\019\000\020\000\021\000\022\000\023\000\024\000\060\000\ +\026\000\027\000\028\000\029\000\030\000\031\000\209\000\210\000\ +\156\001\156\001\000\000\000\000\000\000\000\000\156\001\000\000\ +\000\000\000\000\000\000\156\001\156\001\156\001\156\001\000\000\ +\156\001\000\000\000\000\211\000\212\000\213\000\000\000\000\000\ +\214\000\215\000\000\000\000\000\216\000\217\000\000\000\157\001\ +\157\001\218\000\219\000\000\000\220\000\157\001\156\000\000\000\ +\000\000\000\000\157\001\157\001\157\001\157\001\000\000\157\001\ +\000\000\000\000\156\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\033\000\034\000\000\000\ +\036\000\084\000\085\000\000\000\221\000\000\000\000\000\000\000\ +\222\000\223\000\037\000\000\000\038\000\000\000\000\000\034\002\ +\195\000\157\001\043\000\224\000\006\000\203\000\204\000\205\000\ +\206\000\207\000\008\000\083\000\208\000\009\000\010\000\011\000\ +\012\000\013\000\014\000\015\000\000\000\016\000\017\000\018\000\ +\019\000\020\000\021\000\022\000\023\000\024\000\060\000\026\000\ +\027\000\028\000\029\000\030\000\031\000\209\000\210\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\211\000\212\000\213\000\000\000\000\000\214\000\ +\215\000\000\000\000\000\216\000\217\000\000\000\170\002\223\002\ +\218\000\219\000\172\002\220\000\081\002\204\000\205\000\206\000\ +\207\000\066\000\083\000\208\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\033\000\034\000\000\000\036\000\ +\084\000\085\000\000\000\221\000\209\000\210\000\000\000\222\000\ +\223\000\037\000\000\000\038\000\000\000\000\000\000\000\000\000\ +\000\000\043\000\224\000\000\000\000\000\000\000\000\000\000\000\ \000\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ \000\000\000\000\216\000\217\000\000\000\000\000\000\000\218\000\ \219\000\000\000\220\000\000\000\156\000\000\000\000\000\000\000\ -\175\002\000\000\000\000\000\000\176\002\177\002\178\002\179\002\ -\180\002\181\002\182\002\000\000\000\000\000\000\183\002\184\002\ -\000\000\000\000\000\000\033\000\034\000\185\002\036\000\084\000\ -\085\000\000\000\221\000\000\000\000\000\000\000\222\000\223\000\ -\037\000\186\002\038\000\039\000\040\000\128\001\000\000\000\000\ -\043\000\224\000\000\000\006\000\203\000\204\000\205\000\206\000\ -\207\000\008\000\083\000\208\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\000\000\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\209\000\210\000\158\001\158\001\ -\000\000\000\000\000\000\000\000\158\001\000\000\000\000\000\000\ -\000\000\158\001\158\001\158\001\158\001\000\000\158\001\000\000\ -\000\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ -\000\000\000\000\216\000\217\000\000\000\000\000\000\000\218\000\ -\219\000\000\000\220\000\000\000\156\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\158\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\033\000\034\000\000\000\036\000\084\000\ +\174\002\000\000\000\000\000\000\175\002\176\002\177\002\178\002\ +\179\002\180\002\181\002\000\000\000\000\000\000\182\002\183\002\ +\000\000\000\000\000\000\000\000\000\000\184\002\000\000\084\000\ \085\000\000\000\221\000\000\000\000\000\000\000\222\000\223\000\ -\037\000\000\000\038\000\000\000\034\002\000\000\195\000\000\000\ -\043\000\224\000\006\000\203\000\204\000\205\000\206\000\207\000\ -\008\000\083\000\208\000\009\000\010\000\011\000\012\000\013\000\ -\014\000\015\000\000\000\016\000\017\000\018\000\019\000\020\000\ -\021\000\022\000\023\000\024\000\060\000\026\000\027\000\028\000\ -\029\000\030\000\031\000\209\000\210\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\211\000\212\000\213\000\000\000\000\000\214\000\215\000\000\000\ -\000\000\216\000\217\000\170\002\171\002\224\002\218\000\219\000\ -\173\002\220\000\081\002\204\000\205\000\206\000\207\000\066\000\ -\083\000\208\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\033\000\034\000\000\000\036\000\084\000\085\000\ -\000\000\221\000\209\000\210\000\000\000\222\000\223\000\037\000\ -\000\000\038\000\000\000\000\000\000\000\000\000\000\000\043\000\ -\224\000\000\000\000\000\000\000\000\000\000\000\000\000\211\000\ -\212\000\213\000\000\000\000\000\214\000\215\000\000\000\000\000\ -\216\000\217\000\000\000\000\000\000\000\218\000\219\000\000\000\ -\220\000\000\000\156\000\000\000\000\000\000\000\175\002\000\000\ -\000\000\000\000\176\002\177\002\178\002\179\002\180\002\181\002\ -\182\002\000\000\000\000\000\000\183\002\184\002\000\000\000\000\ -\000\000\000\000\000\000\185\002\000\000\084\000\085\000\000\000\ -\221\000\000\000\000\000\000\000\222\000\223\000\000\000\186\002\ -\004\000\005\000\000\000\000\000\006\000\007\000\000\000\224\000\ -\000\000\000\000\008\000\000\000\000\000\009\000\010\000\011\000\ -\012\000\013\000\014\000\015\000\000\000\016\000\017\000\018\000\ -\019\000\020\000\021\000\022\000\023\000\024\000\025\000\026\000\ -\027\000\028\000\029\000\030\000\031\000\100\000\000\000\000\000\ -\101\000\000\000\102\000\083\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\049\001\000\000\000\000\000\000\103\000\000\000\000\000\ -\104\000\070\001\000\000\000\000\000\000\105\000\106\000\000\000\ -\070\001\070\001\070\001\070\001\070\001\000\000\070\001\070\001\ -\000\000\032\000\050\001\000\000\000\000\051\001\052\001\000\000\ -\000\000\031\000\107\000\108\000\109\000\000\000\000\000\110\000\ -\111\000\000\000\070\001\112\000\033\000\034\000\035\000\036\000\ -\070\001\070\001\000\000\113\000\000\000\000\000\000\000\000\000\ -\000\000\037\000\000\000\038\000\039\000\040\000\000\000\041\000\ -\042\000\043\000\000\000\114\000\044\000\070\001\070\001\070\001\ -\116\002\000\000\070\001\070\001\000\000\000\000\070\001\070\001\ -\084\000\085\000\000\000\070\001\070\001\034\002\070\001\000\000\ -\000\000\000\000\070\001\000\000\203\000\204\000\205\000\206\000\ -\207\000\033\000\083\000\208\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\037\000\000\000\ -\038\000\000\000\000\000\070\001\070\001\000\000\070\001\000\000\ -\000\000\000\000\070\001\070\001\209\000\210\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\070\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ -\000\000\000\000\216\000\217\000\070\001\000\000\000\000\218\000\ -\219\000\000\000\220\000\070\001\070\001\070\001\070\001\070\001\ -\234\002\070\001\070\001\153\001\153\001\000\000\153\001\153\001\ -\000\000\000\000\000\000\090\000\153\001\000\000\000\000\000\000\ -\000\000\153\001\153\001\153\001\153\001\000\000\153\001\084\000\ -\085\000\000\000\221\000\070\001\070\001\000\000\222\000\223\000\ -\000\000\000\000\000\000\000\000\090\000\000\000\000\000\090\000\ -\090\000\224\000\000\000\090\000\000\000\000\000\000\000\000\000\ +\100\000\185\002\000\000\101\000\069\001\102\000\083\000\000\000\ +\000\000\224\000\069\001\069\001\069\001\069\001\069\001\000\000\ +\069\001\069\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\103\000\000\000\000\000\104\000\000\000\000\000\000\000\000\000\ +\105\000\106\000\000\000\000\000\069\001\000\000\000\000\000\000\ +\000\000\000\000\069\001\069\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\107\000\108\000\109\000\ +\000\000\000\000\110\000\111\000\000\000\000\000\112\000\069\001\ +\069\001\069\001\000\000\000\000\069\001\069\001\113\000\000\000\ +\069\001\069\001\000\000\000\000\000\000\069\001\069\001\000\000\ +\069\001\034\002\000\000\000\000\069\001\000\000\114\000\203\000\ +\204\000\205\000\206\000\207\000\000\000\083\000\208\000\000\000\ +\092\000\000\000\000\000\084\000\085\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\069\001\069\001\000\000\ +\069\001\115\000\000\000\000\000\069\001\069\001\000\000\209\000\ +\210\000\092\000\000\000\000\000\092\000\092\000\000\000\069\001\ +\092\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\211\000\212\000\213\000\000\000\ +\000\000\214\000\215\000\000\000\000\000\216\000\217\000\000\000\ +\069\001\000\000\218\000\219\000\000\000\220\000\069\001\069\001\ +\069\001\069\001\069\001\232\002\069\001\069\001\092\000\000\000\ +\092\000\000\000\000\000\092\000\092\000\092\000\092\000\092\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\084\000\085\000\000\000\221\000\069\001\069\001\ +\092\000\222\000\223\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\224\000\092\000\000\000\092\000\ +\000\000\000\000\000\000\069\001\069\001\069\001\000\000\000\000\ +\069\001\069\001\000\000\000\000\069\001\069\001\000\000\000\000\ +\000\000\069\001\069\001\000\000\069\001\070\001\000\000\000\000\ +\069\001\000\000\000\000\070\001\070\001\070\001\070\001\070\001\ +\000\000\070\001\070\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\090\000\000\000\000\000\000\000\ +\000\000\069\001\069\001\000\000\069\001\000\000\000\000\000\000\ +\069\001\069\001\000\000\070\001\070\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\069\001\000\000\090\000\000\000\000\000\ +\090\000\090\000\000\000\000\000\090\000\000\000\000\000\000\000\ \070\001\070\001\070\001\000\000\000\000\070\001\070\001\000\000\ -\153\001\070\001\070\001\000\000\000\000\000\000\070\001\070\001\ -\071\001\070\001\000\000\000\000\000\000\070\001\000\000\071\001\ -\071\001\071\001\071\001\071\001\090\000\071\001\071\001\000\000\ -\000\000\090\000\000\000\090\000\000\000\092\000\090\000\090\000\ -\090\000\090\000\090\000\090\000\000\000\000\000\070\001\070\001\ -\000\000\070\001\000\000\000\000\000\000\070\001\070\001\071\001\ -\071\001\000\000\000\000\090\000\000\000\000\000\092\000\000\000\ -\070\001\092\000\092\000\000\000\000\000\092\000\000\000\000\000\ -\090\000\000\000\090\000\000\000\071\001\071\001\071\001\000\000\ -\000\000\071\001\071\001\000\000\000\000\071\001\071\001\000\000\ -\000\000\000\000\071\001\071\001\034\002\071\001\000\000\000\000\ -\000\000\071\001\000\000\203\000\204\000\205\000\206\000\207\000\ -\000\000\083\000\208\000\092\000\000\000\092\000\000\000\000\000\ -\092\000\092\000\092\000\092\000\092\000\000\000\000\000\000\000\ -\000\000\000\000\071\001\071\001\000\000\071\001\000\000\000\000\ -\000\000\071\001\071\001\209\000\210\000\092\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\071\001\000\000\000\000\000\000\ -\000\000\000\000\092\000\000\000\092\000\000\000\000\000\000\000\ -\211\000\212\000\213\000\000\000\000\000\214\000\215\000\000\000\ -\000\000\216\000\217\000\037\002\000\000\000\000\218\000\219\000\ -\000\000\220\000\203\000\204\000\205\000\206\000\207\000\000\000\ -\083\000\208\000\000\000\000\000\000\000\000\000\022\003\000\000\ -\000\000\000\000\000\000\000\000\000\000\203\000\204\000\205\000\ -\206\000\207\000\000\000\083\000\208\000\000\000\084\000\085\000\ -\000\000\221\000\209\000\210\000\000\000\222\000\223\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\224\000\000\000\000\000\000\000\000\000\209\000\210\000\211\000\ +\000\000\070\001\070\001\000\000\000\000\000\000\070\001\070\001\ +\000\000\070\001\034\002\000\000\000\000\070\001\000\000\000\000\ +\203\000\204\000\205\000\206\000\207\000\090\000\083\000\208\000\ +\000\000\000\000\090\000\000\000\090\000\000\000\000\000\090\000\ +\090\000\090\000\090\000\090\000\090\000\000\000\070\001\070\001\ +\000\000\070\001\000\000\000\000\000\000\070\001\070\001\000\000\ +\209\000\210\000\000\000\000\000\090\000\000\000\000\000\000\000\ +\070\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\090\000\000\000\090\000\000\000\211\000\212\000\213\000\ +\000\000\000\000\214\000\215\000\000\000\000\000\216\000\217\000\ +\000\000\037\002\000\000\218\000\219\000\000\000\220\000\203\000\ +\204\000\205\000\206\000\207\000\000\000\083\000\208\000\000\000\ +\000\000\000\000\000\000\000\000\020\003\000\000\000\000\000\000\ +\000\000\000\000\203\000\204\000\205\000\206\000\207\000\000\000\ +\083\000\208\000\000\000\084\000\085\000\000\000\221\000\209\000\ +\210\000\000\000\222\000\223\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\224\000\000\000\000\000\ +\000\000\000\000\209\000\210\000\211\000\212\000\213\000\000\000\ +\000\000\214\000\215\000\000\000\000\000\216\000\217\000\000\000\ +\000\000\000\000\218\000\219\000\000\000\220\000\000\000\211\000\ \212\000\213\000\000\000\000\000\214\000\215\000\000\000\000\000\ -\216\000\217\000\000\000\000\000\000\000\218\000\219\000\000\000\ -\220\000\000\000\211\000\212\000\213\000\000\000\000\000\214\000\ -\215\000\000\000\000\000\216\000\217\000\087\003\000\000\000\000\ -\218\000\219\000\000\000\220\000\203\000\204\000\205\000\206\000\ -\207\000\000\000\083\000\208\000\000\000\084\000\085\000\000\000\ -\221\000\000\000\000\000\000\000\222\000\223\000\000\000\000\000\ +\216\000\217\000\000\000\085\003\000\000\218\000\219\000\000\000\ +\220\000\203\000\204\000\205\000\206\000\207\000\000\000\083\000\ +\208\000\000\000\084\000\085\000\000\000\221\000\069\001\000\000\ +\000\000\222\000\223\000\000\000\069\001\069\001\069\001\069\001\ +\069\001\000\000\069\001\069\001\224\000\084\000\085\000\000\000\ +\221\000\209\000\210\000\000\000\222\000\223\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\224\000\ -\084\000\085\000\000\000\221\000\209\000\210\000\000\000\222\000\ -\223\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\224\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ -\000\000\000\000\216\000\217\000\070\001\000\000\000\000\218\000\ -\219\000\000\000\220\000\070\001\070\001\070\001\070\001\070\001\ -\000\000\070\001\070\001\154\001\154\001\000\000\154\001\154\001\ -\000\000\000\000\000\000\000\000\154\001\000\000\000\000\000\000\ -\000\000\154\001\154\001\154\001\154\001\000\000\154\001\084\000\ -\085\000\000\000\221\000\070\001\070\001\000\000\222\000\223\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\224\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\070\001\070\001\070\001\000\000\000\000\070\001\070\001\183\000\ -\154\001\070\001\070\001\000\000\000\000\006\000\070\001\070\001\ -\000\000\070\001\000\000\008\000\000\000\000\000\009\000\010\000\ -\011\000\012\000\013\000\014\000\015\000\000\000\016\000\017\000\ -\018\000\019\000\020\000\021\000\022\000\023\000\024\000\060\000\ -\026\000\027\000\028\000\029\000\030\000\031\000\070\001\070\001\ -\000\000\070\001\000\000\000\000\000\000\070\001\070\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\070\001\000\000\125\001\125\001\125\001\125\001\125\001\125\001\ -\125\001\125\001\125\001\125\001\125\001\000\000\125\001\125\001\ -\125\001\000\000\125\001\125\001\125\001\125\001\000\000\000\000\ -\125\001\000\000\184\000\000\000\000\000\125\001\125\001\125\001\ -\125\001\000\000\125\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\033\000\034\000\000\000\ -\036\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\037\000\113\000\038\000\039\000\040\000\113\000\ -\113\000\000\000\043\000\113\000\125\001\113\000\000\000\000\000\ -\113\000\113\000\113\000\113\000\113\000\113\000\113\000\000\000\ -\113\000\113\000\113\000\113\000\113\000\113\000\113\000\113\000\ -\113\000\113\000\113\000\113\000\113\000\113\000\113\000\113\000\ -\000\000\000\000\113\000\113\000\113\000\113\000\113\000\113\000\ +\000\000\000\000\000\000\000\000\069\001\069\001\211\000\212\000\ +\213\000\000\000\000\000\214\000\215\000\000\000\000\000\216\000\ +\217\000\000\000\000\000\000\000\218\000\219\000\000\000\220\000\ +\000\000\069\001\069\001\069\001\000\000\154\001\069\001\069\001\ +\154\001\154\001\069\001\069\001\000\000\000\000\154\001\069\001\ +\069\001\000\000\069\001\154\001\154\001\154\001\154\001\000\000\ +\154\001\000\000\000\000\000\000\084\000\085\000\000\000\221\000\ +\000\000\000\000\000\000\222\000\223\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\224\000\069\001\ +\069\001\000\000\069\001\000\000\183\000\000\000\069\001\069\001\ +\000\000\006\000\154\001\000\000\000\000\000\000\000\000\008\000\ +\000\000\069\001\009\000\010\000\011\000\012\000\013\000\014\000\ +\015\000\000\000\016\000\017\000\018\000\019\000\020\000\021\000\ +\022\000\023\000\024\000\060\000\026\000\027\000\028\000\029\000\ +\030\000\031\000\000\000\136\001\136\001\136\001\136\001\136\001\ +\136\001\136\001\136\001\000\000\000\000\000\000\000\000\136\001\ +\136\001\136\001\000\000\136\001\136\001\136\001\136\001\000\000\ +\000\000\136\001\000\000\000\000\000\000\000\000\136\001\136\001\ +\136\001\136\001\000\000\136\001\000\000\150\001\150\001\150\001\ +\000\000\150\001\150\001\000\000\000\000\000\000\184\000\150\001\ +\000\000\000\000\000\000\000\000\150\001\150\001\150\001\150\001\ +\000\000\150\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\033\000\034\000\000\000\036\000\136\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\037\000\113\000\ +\038\000\039\000\040\000\113\000\113\000\000\000\043\000\113\000\ +\000\000\113\000\000\000\150\001\113\000\113\000\113\000\113\000\ +\113\000\113\000\113\000\000\000\113\000\113\000\113\000\113\000\ \113\000\113\000\113\000\113\000\113\000\113\000\113\000\113\000\ +\113\000\113\000\113\000\113\000\000\000\000\000\113\000\113\000\ \113\000\113\000\113\000\113\000\113\000\113\000\113\000\113\000\ -\113\000\113\000\000\000\113\000\113\000\113\000\000\000\113\000\ \113\000\113\000\113\000\113\000\113\000\113\000\113\000\113\000\ +\113\000\113\000\113\000\113\000\113\000\113\000\000\000\113\000\ +\113\000\113\000\000\000\113\000\113\000\113\000\113\000\113\000\ \113\000\113\000\113\000\113\000\113\000\113\000\113\000\113\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\113\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\113\000\ -\113\000\000\000\113\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\113\000\000\000\113\000\000\000\ -\000\000\113\000\004\000\005\000\113\000\000\000\006\000\007\000\ -\000\000\000\000\000\000\000\000\008\000\000\000\000\000\009\000\ -\010\000\011\000\012\000\013\000\014\000\015\000\000\000\016\000\ -\017\000\018\000\019\000\020\000\021\000\022\000\023\000\024\000\ -\025\000\026\000\027\000\028\000\029\000\030\000\031\000\195\000\ -\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\ -\000\000\008\000\000\000\000\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\000\000\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\000\000\000\000\000\000\137\001\ -\137\001\137\001\137\001\137\001\137\001\137\001\137\001\000\000\ -\000\000\000\000\000\000\137\001\137\001\137\001\000\000\137\001\ -\137\001\137\001\137\001\000\000\000\000\137\001\033\000\034\000\ -\035\000\036\000\137\001\137\001\137\001\137\001\000\000\137\001\ -\000\000\000\000\000\000\037\000\196\000\038\000\039\000\040\000\ -\000\000\041\000\042\000\043\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\033\000\034\000\000\000\036\000\000\000\ -\000\000\137\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\037\000\000\000\038\000\254\000\254\000\000\000\000\000\000\000\ -\043\000\254\000\000\000\000\000\254\000\254\000\254\000\254\000\ -\254\000\254\000\254\000\000\000\254\000\254\000\254\000\254\000\ -\254\000\254\000\254\000\254\000\254\000\254\000\254\000\254\000\ -\254\000\254\000\254\000\254\000\000\000\000\000\138\001\138\001\ -\138\001\138\001\138\001\138\001\138\001\138\001\000\000\000\000\ -\000\000\000\000\138\001\138\001\138\001\000\000\138\001\138\001\ -\138\001\138\001\000\000\254\000\138\001\000\000\000\000\000\000\ -\000\000\138\001\138\001\138\001\138\001\000\000\138\001\000\000\ -\000\000\000\000\254\000\000\000\000\000\000\000\000\000\024\000\ -\254\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\254\000\254\000\000\000\254\000\000\000\ -\138\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\254\000\000\000\254\000\000\000\000\000\000\000\000\000\000\000\ -\254\000\000\000\254\000\006\000\203\000\204\000\205\000\206\000\ -\207\000\008\000\083\000\208\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\000\000\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\209\000\210\000\000\000\000\000\ +\113\000\113\000\113\000\113\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\113\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\113\000\113\000\000\000\113\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\113\000\000\000\113\000\000\000\000\000\113\000\004\000\005\000\ +\113\000\000\000\006\000\007\000\000\000\000\000\000\000\000\000\ +\008\000\000\000\000\000\009\000\010\000\011\000\012\000\013\000\ +\014\000\015\000\000\000\016\000\017\000\018\000\019\000\020\000\ +\021\000\022\000\023\000\024\000\025\000\026\000\027\000\028\000\ +\029\000\030\000\031\000\195\000\000\000\000\000\000\000\006\000\ +\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\ +\009\000\010\000\011\000\012\000\013\000\014\000\015\000\000\000\ +\016\000\017\000\018\000\019\000\020\000\021\000\022\000\023\000\ +\024\000\060\000\026\000\027\000\028\000\029\000\030\000\031\000\ +\000\000\000\000\000\000\137\001\137\001\137\001\137\001\137\001\ +\137\001\137\001\137\001\000\000\000\000\000\000\000\000\137\001\ +\137\001\137\001\000\000\137\001\137\001\137\001\137\001\000\000\ +\000\000\137\001\033\000\034\000\035\000\036\000\137\001\137\001\ +\137\001\137\001\000\000\137\001\000\000\000\000\000\000\037\000\ +\196\000\038\000\039\000\040\000\000\000\041\000\042\000\043\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\033\000\ +\034\000\000\000\036\000\000\000\000\000\137\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\037\000\000\000\038\000\253\000\ +\253\000\000\000\000\000\000\000\043\000\253\000\000\000\000\000\ +\253\000\253\000\253\000\253\000\253\000\253\000\253\000\000\000\ +\253\000\253\000\253\000\253\000\253\000\253\000\253\000\253\000\ +\253\000\253\000\253\000\253\000\253\000\253\000\253\000\253\000\ +\000\000\000\000\138\001\138\001\138\001\138\001\138\001\138\001\ +\138\001\138\001\000\000\000\000\000\000\000\000\138\001\138\001\ +\138\001\000\000\138\001\138\001\138\001\138\001\000\000\253\000\ +\138\001\000\000\000\000\000\000\000\000\138\001\138\001\138\001\ +\138\001\000\000\138\001\000\000\000\000\000\000\253\000\000\000\ +\000\000\000\000\000\000\024\000\253\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\253\000\ +\253\000\000\000\253\000\000\000\138\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\253\000\000\000\253\000\000\000\ +\000\000\000\000\000\000\000\000\253\000\000\000\253\000\006\000\ +\203\000\204\000\205\000\206\000\207\000\008\000\083\000\208\000\ +\009\000\010\000\011\000\012\000\013\000\014\000\015\000\000\000\ +\016\000\017\000\018\000\019\000\020\000\021\000\022\000\023\000\ +\024\000\060\000\026\000\027\000\028\000\029\000\030\000\031\000\ +\209\000\210\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ -\000\000\000\000\216\000\217\000\000\000\000\000\000\000\218\000\ -\219\000\000\000\220\000\000\000\081\002\204\000\205\000\206\000\ -\207\000\066\000\083\000\208\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\211\000\212\000\213\000\ +\000\000\000\000\214\000\215\000\000\000\000\000\216\000\217\000\ +\000\000\000\000\000\000\218\000\219\000\000\000\220\000\000\000\ +\081\002\204\000\205\000\206\000\207\000\066\000\083\000\208\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\033\000\034\000\000\000\036\000\084\000\ -\085\000\000\000\221\000\000\000\209\000\210\000\222\000\223\000\ -\037\000\000\000\038\000\000\000\000\000\000\000\000\000\000\000\ -\043\000\224\000\082\002\000\000\000\000\000\000\000\000\000\000\ -\000\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ -\000\000\000\000\216\000\217\000\000\000\000\000\000\000\218\000\ -\219\000\000\000\220\000\000\000\223\001\083\002\000\000\151\001\ -\151\001\151\001\000\000\151\001\151\001\000\000\000\000\000\000\ -\000\000\151\001\000\000\000\000\000\000\000\000\151\001\151\001\ -\151\001\151\001\000\000\151\001\000\000\000\000\000\000\084\000\ -\085\000\000\000\221\000\000\000\000\000\000\000\222\000\223\000\ -\000\000\000\000\000\000\000\000\000\000\006\000\000\000\000\000\ -\000\000\224\000\070\000\008\000\083\000\000\000\009\000\010\000\ -\011\000\012\000\013\000\014\000\015\000\151\001\016\000\017\000\ -\018\000\019\000\020\000\021\000\022\000\023\000\024\000\060\000\ -\026\000\027\000\028\000\029\000\030\000\031\000\006\000\000\000\ -\000\000\000\000\000\000\000\000\008\000\000\000\000\000\009\000\ -\010\000\011\000\012\000\013\000\014\000\015\000\000\000\016\000\ -\017\000\018\000\019\000\020\000\021\000\022\000\023\000\024\000\ -\060\000\026\000\027\000\028\000\029\000\030\000\031\000\152\001\ -\152\001\152\001\000\000\152\001\152\001\000\000\000\000\000\000\ -\000\000\152\001\000\000\000\000\000\000\000\000\152\001\152\001\ -\152\001\152\001\000\000\152\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\033\000\034\000\000\000\ -\036\000\084\000\085\000\000\000\000\000\169\000\000\000\000\000\ -\000\000\000\000\037\000\000\000\038\000\247\001\000\000\000\000\ -\000\000\000\000\043\000\000\000\000\000\152\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\033\000\034\000\ -\000\000\036\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\037\000\025\001\038\000\000\000\000\000\ -\000\000\000\000\025\001\043\000\000\000\025\001\025\001\025\001\ -\025\001\025\001\025\001\025\001\000\000\025\001\025\001\025\001\ -\025\001\025\001\025\001\025\001\025\001\025\001\025\001\025\001\ -\025\001\025\001\025\001\025\001\025\001\006\000\059\000\000\000\ -\000\000\000\000\000\000\008\000\000\000\000\000\009\000\010\000\ -\011\000\012\000\013\000\014\000\015\000\000\000\016\000\017\000\ -\018\000\019\000\020\000\021\000\022\000\023\000\024\000\060\000\ -\026\000\027\000\028\000\029\000\030\000\031\000\000\000\000\000\ -\000\000\000\000\025\001\025\001\000\000\139\001\139\001\139\001\ -\139\001\139\001\139\001\139\001\139\001\000\000\000\000\000\000\ -\000\000\139\001\139\001\139\001\000\000\139\001\139\001\139\001\ -\139\001\000\000\000\000\139\001\025\001\025\001\000\000\025\001\ -\139\001\139\001\139\001\139\001\000\000\139\001\000\000\000\000\ -\000\000\025\001\000\000\025\001\000\000\000\000\000\000\000\000\ -\000\000\025\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\033\000\034\000\000\000\ -\036\000\000\000\000\000\000\000\000\000\000\000\000\000\139\001\ -\000\000\000\000\037\000\006\000\038\000\000\000\000\000\000\000\ -\000\000\008\000\043\000\000\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\000\000\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\006\000\000\000\000\000\000\000\ -\000\000\000\000\008\000\000\000\000\000\009\000\010\000\011\000\ -\012\000\013\000\014\000\015\000\000\000\016\000\017\000\018\000\ -\019\000\020\000\021\000\022\000\023\000\024\000\060\000\026\000\ -\027\000\028\000\029\000\030\000\031\000\000\000\000\000\000\000\ -\000\000\000\000\169\000\000\000\140\001\140\001\140\001\140\001\ -\140\001\140\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\140\001\140\001\140\001\000\000\140\001\140\001\140\001\140\001\ -\000\000\000\000\140\001\033\000\034\000\000\000\036\000\140\001\ -\140\001\140\001\140\001\000\000\140\001\000\000\000\000\000\000\ -\037\000\000\000\038\000\254\002\000\000\000\000\000\000\000\000\ -\043\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\033\000\034\000\000\000\036\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\140\001\000\000\ -\000\000\037\000\006\000\038\000\000\000\000\000\000\000\000\000\ -\008\000\043\000\000\000\009\000\010\000\011\000\012\000\013\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\033\000\ +\034\000\000\000\036\000\084\000\085\000\000\000\221\000\000\000\ +\209\000\210\000\222\000\223\000\037\000\000\000\038\000\000\000\ +\000\000\000\000\000\000\000\000\043\000\224\000\082\002\000\000\ +\000\000\000\000\000\000\000\000\000\000\211\000\212\000\213\000\ +\000\000\000\000\214\000\215\000\000\000\000\000\216\000\217\000\ +\000\000\000\000\000\000\218\000\219\000\000\000\220\000\000\000\ +\223\001\083\002\000\000\151\001\151\001\151\001\000\000\151\001\ +\151\001\000\000\000\000\000\000\000\000\151\001\000\000\000\000\ +\000\000\000\000\151\001\151\001\151\001\151\001\000\000\151\001\ +\000\000\000\000\000\000\084\000\085\000\000\000\221\000\000\000\ +\000\000\000\000\222\000\223\000\000\000\000\000\000\000\000\000\ +\000\000\006\000\000\000\000\000\000\000\224\000\070\000\008\000\ +\083\000\000\000\009\000\010\000\011\000\012\000\013\000\014\000\ +\015\000\151\001\016\000\017\000\018\000\019\000\020\000\021\000\ +\022\000\023\000\024\000\060\000\026\000\027\000\028\000\029\000\ +\030\000\031\000\006\000\000\000\000\000\000\000\000\000\000\000\ +\008\000\000\000\000\000\009\000\010\000\011\000\012\000\013\000\ \014\000\015\000\000\000\016\000\017\000\018\000\019\000\020\000\ \021\000\022\000\023\000\024\000\060\000\026\000\027\000\028\000\ -\029\000\030\000\031\000\006\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\000\000\016\000\017\000\018\000\019\000\ -\020\000\021\000\022\000\023\000\024\000\060\000\026\000\027\000\ -\028\000\029\000\030\000\031\000\155\001\000\000\000\000\155\001\ -\155\001\000\000\000\000\000\000\000\000\155\001\000\000\000\000\ -\000\000\000\000\155\001\155\001\155\001\155\001\000\000\155\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\033\000\034\000\000\000\036\000\000\000\137\000\ -\137\000\137\000\137\000\137\000\000\000\137\000\137\000\037\000\ -\000\000\038\000\000\000\000\000\000\000\000\000\000\000\043\000\ -\000\000\155\001\000\000\000\000\156\001\000\000\000\000\156\001\ -\156\001\000\000\000\000\033\000\034\000\156\001\036\000\137\000\ -\137\000\137\000\156\001\156\001\156\001\156\001\000\000\156\001\ -\037\000\000\000\038\000\000\000\000\000\000\000\000\000\000\000\ -\043\000\000\000\000\000\000\000\137\000\137\000\137\000\000\000\ -\000\000\137\000\137\000\000\000\000\000\137\000\137\000\000\000\ -\000\000\000\000\137\000\137\000\000\000\137\000\000\000\137\000\ -\000\000\156\001\000\000\203\000\204\000\205\000\206\000\207\000\ -\000\000\083\000\208\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\137\000\137\000\000\000\137\000\000\000\000\000\ -\000\000\137\000\137\000\209\000\210\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\137\000\000\000\000\000\000\000\ +\029\000\030\000\031\000\153\001\153\001\000\000\153\001\153\001\ +\000\000\000\000\000\000\000\000\153\001\000\000\000\000\000\000\ +\000\000\153\001\153\001\153\001\153\001\000\000\153\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\033\000\034\000\000\000\036\000\084\000\085\000\000\000\ +\000\000\169\000\000\000\000\000\000\000\000\000\037\000\000\000\ +\038\000\247\001\000\000\000\000\000\000\000\000\043\000\000\000\ +\153\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\033\000\034\000\000\000\036\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\037\000\ +\024\001\038\000\000\000\000\000\000\000\000\000\024\001\043\000\ +\000\000\024\001\024\001\024\001\024\001\024\001\024\001\024\001\ +\000\000\024\001\024\001\024\001\024\001\024\001\024\001\024\001\ +\024\001\024\001\024\001\024\001\024\001\024\001\024\001\024\001\ +\024\001\006\000\059\000\000\000\000\000\000\000\000\000\008\000\ +\000\000\000\000\009\000\010\000\011\000\012\000\013\000\014\000\ +\015\000\000\000\016\000\017\000\018\000\019\000\020\000\021\000\ +\022\000\023\000\024\000\060\000\026\000\027\000\028\000\029\000\ +\030\000\031\000\000\000\000\000\000\000\000\000\024\001\024\001\ +\000\000\139\001\139\001\139\001\139\001\139\001\139\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\139\001\139\001\139\001\ +\000\000\139\001\139\001\139\001\139\001\000\000\000\000\139\001\ +\024\001\024\001\000\000\024\001\139\001\139\001\139\001\139\001\ +\000\000\139\001\000\000\000\000\000\000\024\001\000\000\024\001\ +\000\000\000\000\000\000\000\000\000\000\024\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\033\000\034\000\000\000\036\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\139\001\000\000\000\000\037\000\006\000\ +\038\000\000\000\000\000\000\000\000\000\008\000\043\000\000\000\ +\009\000\010\000\011\000\012\000\013\000\014\000\015\000\000\000\ +\016\000\017\000\018\000\019\000\020\000\021\000\022\000\023\000\ +\024\000\060\000\026\000\027\000\028\000\029\000\030\000\031\000\ +\006\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\ +\000\000\009\000\010\000\011\000\012\000\013\000\014\000\015\000\ +\000\000\016\000\017\000\018\000\019\000\020\000\021\000\022\000\ +\023\000\024\000\060\000\026\000\027\000\028\000\029\000\030\000\ +\031\000\000\000\000\000\000\000\000\000\000\000\169\000\000\000\ +\140\001\140\001\140\001\140\001\140\001\140\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\140\001\140\001\140\001\000\000\ +\140\001\140\001\140\001\140\001\000\000\000\000\140\001\033\000\ +\034\000\000\000\036\000\140\001\140\001\140\001\140\001\000\000\ +\140\001\000\000\000\000\000\000\037\000\000\000\038\000\252\002\ +\000\000\000\000\000\000\000\000\043\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\033\000\034\000\000\000\036\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\140\001\000\000\000\000\037\000\006\000\038\000\ +\000\000\000\000\000\000\000\000\008\000\043\000\000\000\009\000\ +\010\000\011\000\012\000\013\000\014\000\015\000\000\000\016\000\ +\017\000\018\000\019\000\020\000\021\000\022\000\023\000\024\000\ +\060\000\026\000\027\000\028\000\029\000\030\000\031\000\006\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\211\000\212\000\213\000\000\000\000\000\214\000\215\000\000\000\ -\000\000\216\000\217\000\000\000\000\000\000\000\218\000\219\000\ -\000\000\220\000\000\000\223\001\000\000\000\000\000\000\203\000\ +\009\000\010\000\011\000\012\000\013\000\014\000\015\000\000\000\ +\016\000\017\000\018\000\019\000\020\000\021\000\022\000\023\000\ +\024\000\060\000\026\000\027\000\028\000\029\000\030\000\031\000\ +\155\001\000\000\000\000\155\001\155\001\000\000\000\000\000\000\ +\000\000\155\001\000\000\000\000\000\000\000\000\155\001\155\001\ +\155\001\155\001\000\000\155\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\033\000\034\000\ +\000\000\036\000\000\000\137\000\137\000\137\000\137\000\137\000\ +\000\000\137\000\137\000\037\000\000\000\038\000\000\000\000\000\ +\000\000\000\000\000\000\043\000\000\000\155\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\033\000\ +\034\000\000\000\036\000\137\000\137\000\137\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\037\000\000\000\038\000\000\000\ +\000\000\000\000\000\000\000\000\043\000\000\000\000\000\000\000\ +\137\000\137\000\137\000\000\000\000\000\137\000\137\000\000\000\ +\000\000\137\000\137\000\000\000\000\000\000\000\137\000\137\000\ +\000\000\137\000\000\000\137\000\000\000\000\000\000\000\203\000\ \204\000\205\000\206\000\207\000\000\000\083\000\208\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\084\000\085\000\ -\000\000\221\000\000\000\000\000\000\000\222\000\223\000\209\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\137\000\137\000\ +\000\000\137\000\000\000\000\000\000\000\137\000\137\000\209\000\ \210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\137\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\211\000\212\000\213\000\000\000\ \000\000\214\000\215\000\000\000\000\000\216\000\217\000\000\000\ -\000\000\000\000\218\000\219\000\000\000\220\000\000\000\134\002\ -\000\000\000\000\000\000\133\000\133\000\133\000\133\000\133\000\ -\000\000\133\000\133\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\218\000\219\000\000\000\220\000\000\000\223\001\ +\000\000\000\000\000\000\203\000\204\000\205\000\206\000\207\000\ +\000\000\083\000\208\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\084\000\085\000\000\000\221\000\000\000\000\000\ -\000\000\222\000\223\000\133\000\133\000\000\000\000\000\000\000\ +\000\000\222\000\223\000\209\000\210\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\224\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\133\000\133\000\133\000\000\000\000\000\133\000\133\000\000\000\ -\000\000\133\000\133\000\000\000\000\000\000\000\133\000\133\000\ -\000\000\133\000\000\000\133\000\000\000\000\000\000\000\203\000\ -\204\000\205\000\206\000\207\000\000\000\083\000\208\000\000\000\ +\211\000\212\000\213\000\000\000\000\000\214\000\215\000\000\000\ +\000\000\216\000\217\000\000\000\000\000\000\000\218\000\219\000\ +\000\000\220\000\000\000\134\002\000\000\000\000\000\000\133\000\ +\133\000\133\000\133\000\133\000\000\000\133\000\133\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\133\000\133\000\ -\000\000\133\000\000\000\000\000\000\000\133\000\133\000\209\000\ -\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\084\000\085\000\ +\000\000\221\000\000\000\000\000\000\000\222\000\223\000\133\000\ \133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\211\000\212\000\213\000\000\000\ -\000\000\214\000\215\000\000\000\000\000\216\000\217\000\000\000\ -\000\000\000\000\218\000\219\000\000\000\254\000\203\000\204\000\ -\205\000\206\000\207\000\000\000\083\000\208\000\000\000\000\000\ +\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\133\000\133\000\133\000\000\000\ +\000\000\133\000\133\000\000\000\000\000\133\000\133\000\000\000\ +\000\000\000\000\133\000\133\000\000\000\133\000\000\000\133\000\ +\000\000\000\000\000\000\203\000\204\000\205\000\206\000\207\000\ +\000\000\083\000\208\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\133\000\133\000\000\000\133\000\000\000\000\000\ +\000\000\133\000\133\000\209\000\210\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\133\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\203\000\204\000\205\000\206\000\207\000\000\000\083\000\ -\208\000\000\000\084\000\085\000\000\000\221\000\209\000\210\000\ -\000\000\222\000\223\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\224\000\000\000\000\000\000\000\ -\000\000\209\000\210\000\211\000\212\000\213\000\000\000\000\000\ -\214\000\215\000\000\000\000\000\216\000\217\000\000\000\000\000\ -\000\000\218\000\219\000\000\000\000\001\000\000\211\000\212\000\ -\213\000\000\000\000\000\214\000\215\000\000\000\000\000\216\000\ -\217\000\000\000\000\000\000\000\218\000\219\000\000\000\220\000\ -\203\000\204\000\205\000\206\000\207\000\000\000\083\000\208\000\ -\000\000\084\000\085\000\000\000\221\000\000\000\000\000\000\000\ -\222\000\223\000\000\000\203\000\204\000\205\000\206\000\207\000\ -\000\000\083\000\208\000\224\000\084\000\085\000\000\000\221\000\ -\209\000\210\000\000\000\222\000\223\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\224\000\000\000\ -\000\000\000\000\000\000\209\000\210\000\211\000\212\000\213\000\ -\000\000\000\000\214\000\215\000\000\000\000\000\216\000\217\000\ -\000\000\000\000\000\000\218\000\219\000\000\000\114\001\000\000\ \211\000\212\000\213\000\000\000\000\000\214\000\215\000\000\000\ \000\000\216\000\217\000\000\000\000\000\000\000\218\000\219\000\ -\000\000\116\001\203\000\204\000\205\000\206\000\207\000\000\000\ -\083\000\208\000\000\000\084\000\085\000\000\000\221\000\000\000\ -\000\000\000\000\222\000\223\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\224\000\084\000\085\000\ +\000\000\254\000\203\000\204\000\205\000\206\000\207\000\000\000\ +\083\000\208\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\203\000\204\000\205\000\ +\206\000\207\000\000\000\083\000\208\000\000\000\084\000\085\000\ \000\000\221\000\209\000\210\000\000\000\222\000\223\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\224\000\000\000\000\000\000\000\000\000\000\000\000\000\211\000\ +\224\000\000\000\000\000\000\000\000\000\209\000\210\000\211\000\ \212\000\213\000\000\000\000\000\214\000\215\000\000\000\000\000\ \216\000\217\000\000\000\000\000\000\000\218\000\219\000\000\000\ -\125\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\112\000\000\000\000\000\ +\000\001\000\000\211\000\212\000\213\000\000\000\000\000\214\000\ +\215\000\000\000\000\000\216\000\217\000\000\000\000\000\000\000\ +\218\000\219\000\000\000\220\000\203\000\204\000\205\000\206\000\ +\207\000\000\000\083\000\208\000\000\000\084\000\085\000\000\000\ +\221\000\000\000\000\000\000\000\222\000\223\000\000\000\203\000\ +\204\000\205\000\206\000\207\000\000\000\083\000\208\000\224\000\ +\084\000\085\000\000\000\221\000\209\000\210\000\000\000\222\000\ +\223\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\224\000\000\000\000\000\000\000\000\000\209\000\ +\210\000\211\000\212\000\213\000\000\000\000\000\214\000\215\000\ +\000\000\000\000\216\000\217\000\000\000\000\000\000\000\218\000\ +\219\000\000\000\114\001\000\000\211\000\212\000\213\000\000\000\ +\000\000\214\000\215\000\000\000\000\000\216\000\217\000\000\000\ +\000\000\000\000\218\000\219\000\000\000\116\001\203\000\204\000\ +\205\000\206\000\207\000\000\000\083\000\208\000\000\000\084\000\ +\085\000\000\000\221\000\000\000\000\000\000\000\222\000\223\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\084\000\085\000\000\000\ -\221\000\000\000\000\000\000\000\222\000\223\000\112\000\000\000\ -\000\000\112\000\112\000\000\000\000\000\112\000\000\000\224\000\ -\112\000\112\000\112\000\112\000\112\000\112\000\112\000\112\000\ +\000\000\224\000\084\000\085\000\000\000\221\000\209\000\210\000\ +\000\000\222\000\223\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\224\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\211\000\212\000\213\000\000\000\000\000\ +\214\000\215\000\000\000\000\000\216\000\217\000\000\000\000\000\ +\000\000\218\000\219\000\000\000\125\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\112\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\084\000\085\000\000\000\221\000\000\000\000\000\000\000\ +\222\000\223\000\112\000\000\000\000\000\112\000\112\000\000\000\ +\000\000\112\000\000\000\224\000\112\000\112\000\112\000\112\000\ \112\000\112\000\112\000\112\000\112\000\112\000\112\000\112\000\ \112\000\112\000\112\000\112\000\112\000\112\000\112\000\112\000\ -\000\000\112\000\112\000\112\000\000\000\112\000\112\000\112\000\ -\112\000\112\000\112\000\112\000\112\000\112\000\000\000\112\000\ -\112\000\112\000\112\000\112\000\112\000\112\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\048\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\112\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\112\000\000\000\112\000\048\000\000\000\112\000\ -\048\000\048\000\000\000\000\000\048\000\000\000\000\000\048\000\ +\112\000\112\000\112\000\112\000\000\000\112\000\112\000\112\000\ +\000\000\112\000\112\000\112\000\112\000\112\000\112\000\112\000\ +\112\000\112\000\000\000\112\000\112\000\112\000\112\000\112\000\ +\112\000\112\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\048\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\112\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\112\000\000\000\ +\112\000\048\000\000\000\112\000\048\000\048\000\000\000\000\000\ +\048\000\000\000\000\000\048\000\048\000\048\000\048\000\048\000\ +\048\000\048\000\048\000\048\000\048\000\048\000\000\000\000\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ -\048\000\048\000\000\000\000\000\048\000\048\000\048\000\048\000\ -\048\000\048\000\048\000\048\000\048\000\048\000\048\000\000\000\ -\048\000\048\000\048\000\000\000\048\000\048\000\048\000\048\000\ -\000\000\000\000\048\000\000\000\048\000\000\000\000\000\048\000\ -\048\000\048\000\048\000\048\000\048\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\052\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\048\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\048\000\000\000\048\000\052\000\000\000\048\000\052\000\ -\052\000\000\000\000\000\052\000\000\000\000\000\052\000\052\000\ +\048\000\048\000\048\000\000\000\048\000\048\000\048\000\000\000\ +\048\000\048\000\048\000\048\000\000\000\000\000\048\000\000\000\ +\048\000\000\000\000\000\048\000\048\000\048\000\048\000\048\000\ +\048\000\000\000\000\000\000\000\000\000\000\000\000\000\052\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\048\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\048\000\000\000\048\000\ +\052\000\000\000\048\000\052\000\052\000\000\000\000\000\052\000\ +\000\000\000\000\052\000\052\000\052\000\052\000\052\000\052\000\ +\052\000\052\000\052\000\052\000\052\000\000\000\000\000\052\000\ \052\000\052\000\052\000\052\000\052\000\052\000\052\000\052\000\ -\052\000\000\000\000\000\052\000\052\000\052\000\052\000\052\000\ -\052\000\052\000\052\000\052\000\052\000\052\000\000\000\052\000\ -\052\000\052\000\000\000\052\000\052\000\052\000\052\000\000\000\ -\000\000\052\000\000\000\052\000\000\000\000\000\052\000\052\000\ -\052\000\052\000\052\000\052\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\054\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\052\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\052\000\000\000\052\000\054\000\000\000\052\000\054\000\054\000\ -\000\000\000\000\054\000\000\000\000\000\054\000\054\000\054\000\ +\052\000\052\000\000\000\052\000\052\000\052\000\000\000\052\000\ +\052\000\052\000\052\000\000\000\000\000\052\000\000\000\052\000\ +\000\000\000\000\052\000\052\000\052\000\052\000\052\000\052\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\054\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\052\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\052\000\000\000\052\000\054\000\ +\000\000\052\000\054\000\054\000\000\000\000\000\054\000\000\000\ +\000\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ +\054\000\054\000\054\000\054\000\000\000\000\000\054\000\054\000\ \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ -\000\000\000\000\054\000\054\000\054\000\054\000\054\000\054\000\ -\054\000\054\000\054\000\054\000\054\000\000\000\054\000\054\000\ -\054\000\000\000\054\000\054\000\054\000\054\000\000\000\000\000\ -\054\000\000\000\054\000\000\000\000\000\054\000\054\000\054\000\ -\054\000\054\000\054\000\094\001\000\000\000\000\094\001\000\000\ -\094\001\094\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\054\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\094\001\000\000\000\000\094\001\054\000\ -\000\000\054\000\000\000\000\000\054\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\094\001\094\001\094\001\094\001\094\001\094\001\094\001\094\001\ -\094\001\094\001\094\001\094\001\094\001\000\000\094\001\094\001\ -\094\001\000\000\094\001\094\001\094\001\094\001\000\000\000\000\ -\094\001\023\000\000\000\000\000\094\001\094\001\094\001\094\001\ -\094\001\095\001\094\001\000\000\095\001\000\000\095\001\095\001\ -\000\000\094\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\094\001\094\001\ -\000\000\095\001\000\000\000\000\095\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\094\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\095\001\095\001\ -\095\001\095\001\095\001\095\001\095\001\095\001\095\001\095\001\ -\095\001\095\001\095\001\000\000\095\001\095\001\095\001\000\000\ -\095\001\095\001\095\001\095\001\000\000\000\000\095\001\024\000\ -\000\000\000\000\095\001\095\001\095\001\095\001\095\001\102\001\ -\095\001\000\000\102\001\000\000\102\001\102\001\000\000\095\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\095\001\095\001\000\000\102\001\ -\000\000\000\000\102\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\095\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\102\001\102\001\102\001\102\001\ -\102\001\102\001\102\001\102\001\102\001\102\001\102\001\102\001\ -\102\001\000\000\102\001\102\001\102\001\000\000\102\001\102\001\ -\102\001\102\001\000\000\000\000\102\001\000\000\000\000\000\000\ -\102\001\102\001\000\000\102\001\102\001\100\000\102\001\000\000\ -\101\000\000\000\102\000\083\000\000\000\102\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\102\001\102\001\000\000\103\000\000\000\000\000\ -\104\000\000\000\000\000\000\000\000\000\105\000\106\000\000\000\ -\102\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\107\000\108\000\109\000\000\000\000\000\110\000\ -\111\000\000\000\000\000\112\000\000\000\000\000\000\000\064\000\ -\000\000\000\000\000\000\113\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\114\000\000\000\000\000\000\000\000\000\ -\064\000\000\000\000\000\064\000\064\000\000\000\000\000\064\000\ -\084\000\085\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\115\000\064\000\ -\064\000\064\000\064\000\064\000\064\000\064\000\064\000\064\000\ -\064\000\064\000\000\000\064\000\064\000\064\000\000\000\064\000\ -\064\000\064\000\064\000\000\000\068\000\064\000\000\000\064\000\ -\000\000\000\000\064\000\064\000\064\000\064\000\064\000\064\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\068\000\000\000\064\000\ -\068\000\068\000\000\000\000\000\068\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\064\000\000\000\064\000\000\000\ -\000\000\000\000\000\000\000\000\068\000\068\000\068\000\068\000\ -\068\000\068\000\068\000\068\000\000\000\000\000\000\000\000\000\ -\068\000\068\000\068\000\000\000\068\000\068\000\068\000\068\000\ -\000\000\069\000\068\000\000\000\068\000\000\000\000\000\068\000\ -\068\000\068\000\068\000\068\000\068\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\069\000\000\000\068\000\069\000\069\000\000\000\ -\000\000\069\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\068\000\000\000\068\000\000\000\000\000\000\000\000\000\ -\000\000\069\000\069\000\069\000\069\000\069\000\069\000\069\000\ -\069\000\000\000\000\000\000\000\000\000\069\000\069\000\069\000\ -\000\000\069\000\069\000\069\000\069\000\000\000\070\000\069\000\ -\000\000\069\000\000\000\000\000\069\000\069\000\069\000\069\000\ -\069\000\069\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\070\000\ -\000\000\069\000\070\000\070\000\000\000\000\000\070\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\069\000\000\000\ -\069\000\000\000\000\000\000\000\000\000\000\000\070\000\070\000\ -\070\000\070\000\070\000\070\000\070\000\070\000\000\000\000\000\ -\000\000\000\000\070\000\070\000\070\000\000\000\070\000\070\000\ -\070\000\070\000\000\000\071\000\070\000\000\000\070\000\000\000\ -\000\000\070\000\070\000\070\000\070\000\070\000\070\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\071\000\000\000\070\000\071\000\ -\071\000\000\000\000\000\071\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\070\000\000\000\070\000\000\000\000\000\ -\000\000\000\000\000\000\071\000\071\000\071\000\071\000\071\000\ -\071\000\000\000\000\000\000\000\000\000\000\000\000\000\071\000\ -\071\000\071\000\000\000\071\000\071\000\071\000\071\000\000\000\ -\072\000\071\000\000\000\071\000\000\000\000\000\071\000\071\000\ -\071\000\071\000\071\000\071\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\072\000\000\000\071\000\072\000\072\000\000\000\000\000\ -\072\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\071\000\000\000\071\000\000\000\000\000\000\000\000\000\000\000\ -\072\000\072\000\072\000\072\000\072\000\072\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\072\000\072\000\072\000\000\000\ -\072\000\072\000\072\000\072\000\000\000\073\000\072\000\000\000\ -\072\000\000\000\000\000\072\000\072\000\072\000\072\000\072\000\ -\072\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\073\000\000\000\ -\072\000\073\000\073\000\000\000\000\000\073\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\072\000\000\000\072\000\ -\000\000\000\000\000\000\000\000\000\000\073\000\073\000\073\000\ -\073\000\073\000\073\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\073\000\073\000\073\000\000\000\073\000\073\000\073\000\ -\073\000\000\000\075\000\073\000\000\000\073\000\000\000\000\000\ -\073\000\073\000\073\000\073\000\073\000\073\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\075\000\000\000\073\000\075\000\075\000\ -\000\000\000\000\075\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\073\000\000\000\073\000\000\000\000\000\000\000\ -\000\000\000\000\075\000\075\000\075\000\075\000\075\000\075\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\075\000\075\000\ -\075\000\000\000\075\000\075\000\076\000\000\000\000\000\000\000\ -\075\000\000\000\075\000\000\000\000\000\075\000\075\000\075\000\ -\075\000\075\000\075\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\076\000\000\000\000\000\ -\076\000\076\000\075\000\000\000\076\000\000\000\000\000\000\000\ +\054\000\000\000\054\000\054\000\054\000\000\000\054\000\054\000\ +\054\000\054\000\000\000\000\000\054\000\000\000\054\000\000\000\ +\000\000\054\000\054\000\054\000\054\000\054\000\054\000\093\001\ +\000\000\000\000\093\001\000\000\093\001\093\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\054\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\093\001\ +\000\000\000\000\093\001\054\000\000\000\054\000\000\000\000\000\ +\054\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\093\001\093\001\093\001\093\001\ +\093\001\093\001\093\001\093\001\093\001\093\001\093\001\093\001\ +\093\001\000\000\093\001\093\001\093\001\000\000\093\001\093\001\ +\093\001\093\001\000\000\000\000\093\001\023\000\000\000\000\000\ +\093\001\093\001\093\001\093\001\093\001\094\001\093\001\000\000\ +\094\001\000\000\094\001\094\001\000\000\093\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\093\001\093\001\000\000\094\001\000\000\000\000\ +\094\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\093\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\094\001\094\001\094\001\094\001\094\001\094\001\ +\094\001\094\001\094\001\094\001\094\001\094\001\094\001\000\000\ +\094\001\094\001\094\001\000\000\094\001\094\001\094\001\094\001\ +\000\000\000\000\094\001\024\000\000\000\000\000\094\001\094\001\ +\094\001\094\001\094\001\101\001\094\001\000\000\101\001\000\000\ +\101\001\101\001\000\000\094\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\094\001\094\001\000\000\101\001\000\000\000\000\101\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\094\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\101\001\101\001\101\001\101\001\101\001\101\001\101\001\101\001\ +\101\001\101\001\101\001\101\001\101\001\000\000\101\001\101\001\ +\101\001\000\000\101\001\101\001\101\001\101\001\000\000\000\000\ +\101\001\000\000\000\000\000\000\101\001\101\001\000\000\101\001\ +\101\001\064\000\101\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\101\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\101\001\101\001\ +\000\000\000\000\064\000\000\000\000\000\064\000\064\000\000\000\ +\000\000\064\000\000\000\000\000\101\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\064\000\064\000\064\000\064\000\064\000\064\000\064\000\ +\064\000\064\000\064\000\064\000\000\000\064\000\064\000\064\000\ +\000\000\064\000\064\000\064\000\064\000\000\000\068\000\064\000\ +\000\000\064\000\000\000\000\000\064\000\064\000\064\000\064\000\ +\064\000\064\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\068\000\ +\000\000\064\000\068\000\068\000\000\000\000\000\068\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\064\000\000\000\ +\064\000\000\000\000\000\000\000\000\000\000\000\068\000\068\000\ +\068\000\068\000\068\000\068\000\068\000\068\000\000\000\000\000\ +\000\000\000\000\068\000\068\000\068\000\000\000\068\000\068\000\ +\068\000\068\000\000\000\069\000\068\000\000\000\068\000\000\000\ +\000\000\068\000\068\000\068\000\068\000\068\000\068\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\069\000\000\000\068\000\069\000\ +\069\000\000\000\000\000\069\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\068\000\000\000\068\000\000\000\000\000\ +\000\000\000\000\000\000\069\000\069\000\069\000\069\000\069\000\ +\069\000\069\000\069\000\000\000\000\000\000\000\000\000\069\000\ +\069\000\069\000\000\000\069\000\069\000\069\000\069\000\000\000\ +\070\000\069\000\000\000\069\000\000\000\000\000\069\000\069\000\ +\069\000\069\000\069\000\069\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\070\000\000\000\069\000\070\000\070\000\000\000\000\000\ +\070\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\069\000\000\000\069\000\000\000\000\000\000\000\000\000\000\000\ +\070\000\070\000\070\000\070\000\070\000\070\000\070\000\070\000\ +\000\000\000\000\000\000\000\000\070\000\070\000\070\000\000\000\ +\070\000\070\000\070\000\070\000\000\000\071\000\070\000\000\000\ +\070\000\000\000\000\000\070\000\070\000\070\000\070\000\070\000\ +\070\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\071\000\000\000\ +\070\000\071\000\071\000\000\000\000\000\071\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\070\000\000\000\070\000\ +\000\000\000\000\000\000\000\000\000\000\071\000\071\000\071\000\ +\071\000\071\000\071\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\071\000\071\000\071\000\000\000\071\000\071\000\071\000\ +\071\000\000\000\072\000\071\000\000\000\071\000\000\000\000\000\ +\071\000\071\000\071\000\071\000\071\000\071\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\072\000\000\000\071\000\072\000\072\000\ +\000\000\000\000\072\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\071\000\000\000\071\000\000\000\000\000\000\000\ +\000\000\000\000\072\000\072\000\072\000\072\000\072\000\072\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\072\000\072\000\ +\072\000\000\000\072\000\072\000\072\000\072\000\000\000\073\000\ +\072\000\000\000\072\000\000\000\000\000\072\000\072\000\072\000\ +\072\000\072\000\072\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\073\000\000\000\072\000\073\000\073\000\000\000\000\000\073\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\072\000\ +\000\000\072\000\000\000\000\000\000\000\000\000\000\000\073\000\ +\073\000\073\000\073\000\073\000\073\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\073\000\073\000\073\000\000\000\073\000\ +\073\000\073\000\073\000\000\000\074\000\073\000\000\000\073\000\ +\000\000\000\000\073\000\073\000\073\000\073\000\073\000\073\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\074\000\000\000\073\000\ +\074\000\074\000\000\000\000\000\074\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\073\000\000\000\073\000\000\000\ +\000\000\000\000\000\000\000\000\074\000\074\000\074\000\074\000\ +\074\000\074\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\074\000\074\000\074\000\000\000\074\000\074\000\075\000\000\000\ +\000\000\000\000\074\000\000\000\074\000\000\000\000\000\074\000\ +\074\000\074\000\074\000\074\000\074\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\075\000\ -\000\000\075\000\000\000\000\000\076\000\076\000\076\000\076\000\ -\076\000\076\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\076\000\076\000\076\000\000\000\076\000\076\000\077\000\000\000\ -\000\000\000\000\076\000\000\000\076\000\000\000\000\000\076\000\ -\076\000\076\000\076\000\076\000\076\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\077\000\ -\000\000\000\000\077\000\077\000\076\000\000\000\077\000\000\000\ +\000\000\000\000\075\000\075\000\074\000\000\000\075\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\076\000\000\000\076\000\000\000\000\000\077\000\077\000\ -\077\000\077\000\077\000\077\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\077\000\077\000\077\000\000\000\077\000\077\000\ -\078\000\000\000\000\000\000\000\077\000\000\000\077\000\000\000\ -\000\000\077\000\077\000\077\000\077\000\077\000\077\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\078\000\000\000\000\000\078\000\078\000\077\000\000\000\ -\078\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\077\000\000\000\077\000\000\000\000\000\ -\078\000\078\000\078\000\078\000\078\000\078\000\000\000\000\000\ -\079\000\000\000\000\000\000\000\078\000\078\000\078\000\000\000\ -\078\000\078\000\000\000\000\000\000\000\000\000\078\000\000\000\ -\078\000\000\000\000\000\078\000\078\000\078\000\078\000\078\000\ -\078\000\079\000\000\000\000\000\079\000\079\000\000\000\000\000\ -\079\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\078\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\079\000\079\000\000\000\000\000\000\000\078\000\000\000\078\000\ -\080\000\000\000\000\000\000\000\079\000\079\000\079\000\000\000\ -\079\000\079\000\000\000\000\000\000\000\000\000\079\000\000\000\ -\079\000\000\000\000\000\079\000\079\000\079\000\079\000\079\000\ -\079\000\080\000\000\000\000\000\080\000\080\000\000\000\000\000\ -\080\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\079\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\080\000\080\000\000\000\000\000\000\000\079\000\000\000\079\000\ -\081\000\000\000\000\000\000\000\080\000\080\000\080\000\000\000\ -\080\000\080\000\000\000\000\000\000\000\000\000\080\000\000\000\ -\080\000\000\000\000\000\080\000\080\000\080\000\080\000\080\000\ -\080\000\081\000\000\000\000\000\081\000\081\000\000\000\000\000\ -\081\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\080\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\081\000\081\000\000\000\000\000\000\000\080\000\000\000\080\000\ -\082\000\000\000\000\000\000\000\081\000\081\000\081\000\000\000\ -\081\000\081\000\000\000\000\000\000\000\000\000\081\000\000\000\ -\081\000\000\000\000\000\081\000\081\000\081\000\081\000\081\000\ -\081\000\082\000\000\000\000\000\082\000\082\000\000\000\000\000\ -\082\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\081\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\081\000\000\000\081\000\ -\083\000\000\000\000\000\000\000\082\000\082\000\082\000\000\000\ -\082\000\082\000\000\000\000\000\000\000\000\000\082\000\000\000\ -\082\000\000\000\000\000\082\000\082\000\082\000\082\000\082\000\ -\082\000\083\000\000\000\000\000\083\000\083\000\000\000\000\000\ -\083\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\082\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\082\000\000\000\082\000\ -\084\000\000\000\000\000\000\000\083\000\083\000\083\000\000\000\ -\083\000\083\000\000\000\000\000\000\000\000\000\083\000\000\000\ -\083\000\000\000\000\000\083\000\083\000\083\000\083\000\083\000\ -\083\000\084\000\000\000\000\000\084\000\084\000\000\000\000\000\ -\084\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\074\000\000\000\074\000\000\000\000\000\075\000\075\000\ +\075\000\075\000\075\000\075\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\075\000\075\000\075\000\000\000\075\000\075\000\ +\076\000\000\000\000\000\000\000\075\000\000\000\075\000\000\000\ +\000\000\075\000\075\000\075\000\075\000\075\000\075\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\076\000\000\000\000\000\076\000\076\000\075\000\000\000\ +\076\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\075\000\000\000\075\000\000\000\000\000\ +\076\000\076\000\076\000\076\000\076\000\076\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\076\000\076\000\076\000\000\000\ +\076\000\076\000\077\000\000\000\000\000\000\000\076\000\000\000\ +\076\000\000\000\000\000\076\000\076\000\076\000\076\000\076\000\ +\076\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\077\000\000\000\000\000\077\000\077\000\ +\076\000\000\000\077\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\076\000\000\000\076\000\ +\000\000\000\000\077\000\077\000\077\000\077\000\077\000\077\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\077\000\077\000\ +\077\000\000\000\077\000\077\000\078\000\000\000\000\000\000\000\ +\077\000\000\000\077\000\000\000\000\000\077\000\077\000\077\000\ +\077\000\077\000\077\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\078\000\000\000\000\000\ +\078\000\078\000\077\000\000\000\078\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\077\000\ +\000\000\077\000\000\000\000\000\078\000\078\000\078\000\078\000\ +\078\000\078\000\000\000\000\000\079\000\000\000\000\000\000\000\ +\078\000\078\000\078\000\000\000\078\000\078\000\000\000\000\000\ +\000\000\000\000\078\000\000\000\078\000\000\000\000\000\078\000\ +\078\000\078\000\078\000\078\000\078\000\079\000\000\000\000\000\ +\079\000\079\000\000\000\000\000\079\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\078\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\079\000\079\000\000\000\000\000\ +\000\000\078\000\000\000\078\000\080\000\000\000\000\000\000\000\ +\079\000\079\000\079\000\000\000\079\000\079\000\000\000\000\000\ +\000\000\000\000\079\000\000\000\079\000\000\000\000\000\079\000\ +\079\000\079\000\079\000\079\000\079\000\080\000\000\000\000\000\ +\080\000\080\000\000\000\000\000\080\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\079\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\080\000\080\000\000\000\000\000\ +\000\000\079\000\000\000\079\000\081\000\000\000\000\000\000\000\ +\080\000\080\000\080\000\000\000\080\000\080\000\000\000\000\000\ +\000\000\000\000\080\000\000\000\080\000\000\000\000\000\080\000\ +\080\000\080\000\080\000\080\000\080\000\081\000\000\000\000\000\ +\081\000\081\000\000\000\000\000\081\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\080\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\081\000\081\000\000\000\000\000\ +\000\000\080\000\000\000\080\000\083\000\000\000\000\000\000\000\ +\081\000\081\000\081\000\000\000\081\000\081\000\000\000\000\000\ +\000\000\000\000\081\000\000\000\081\000\000\000\000\000\081\000\ +\081\000\081\000\081\000\081\000\081\000\083\000\000\000\000\000\ +\083\000\083\000\000\000\000\000\083\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\081\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\081\000\000\000\081\000\084\000\000\000\000\000\000\000\ +\083\000\083\000\083\000\000\000\083\000\083\000\000\000\000\000\ +\000\000\000\000\083\000\000\000\083\000\000\000\000\000\083\000\ +\083\000\083\000\083\000\083\000\083\000\084\000\000\000\000\000\ +\084\000\084\000\000\000\000\000\084\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\083\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\083\000\000\000\083\000\085\000\000\000\000\000\000\000\ +\000\000\084\000\084\000\000\000\084\000\084\000\000\000\000\000\ +\000\000\000\000\084\000\000\000\084\000\000\000\000\000\084\000\ +\084\000\084\000\084\000\084\000\084\000\085\000\000\000\000\000\ +\085\000\085\000\000\000\000\000\085\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\084\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\084\000\000\000\084\000\086\000\000\000\000\000\000\000\ +\000\000\085\000\085\000\000\000\085\000\085\000\000\000\000\000\ +\000\000\000\000\085\000\000\000\085\000\000\000\000\000\085\000\ +\085\000\085\000\085\000\085\000\085\000\086\000\000\000\000\000\ +\086\000\086\000\000\000\000\000\086\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\085\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\085\000\000\000\085\000\087\000\000\000\000\000\000\000\ +\000\000\086\000\000\000\000\000\086\000\086\000\000\000\000\000\ +\000\000\000\000\086\000\000\000\086\000\000\000\000\000\086\000\ +\086\000\086\000\086\000\086\000\086\000\087\000\000\000\000\000\ +\087\000\087\000\000\000\000\000\087\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\086\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\086\000\000\000\086\000\088\000\000\000\000\000\000\000\ +\000\000\087\000\000\000\000\000\087\000\087\000\000\000\000\000\ +\000\000\000\000\087\000\000\000\087\000\000\000\000\000\087\000\ +\087\000\087\000\087\000\087\000\087\000\088\000\000\000\000\000\ +\088\000\088\000\000\000\000\000\088\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\087\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\087\000\000\000\087\000\089\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\088\000\088\000\000\000\000\000\ +\000\000\000\000\088\000\000\000\088\000\000\000\000\000\088\000\ +\088\000\088\000\088\000\088\000\088\000\089\000\000\000\000\000\ +\089\000\089\000\000\000\000\000\089\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\088\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\088\000\000\000\088\000\091\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\089\000\089\000\000\000\000\000\ +\000\000\000\000\089\000\000\000\089\000\000\000\000\000\089\000\ +\089\000\089\000\089\000\089\000\089\000\091\000\000\000\000\000\ +\091\000\091\000\248\000\000\000\091\000\000\000\000\000\000\000\ +\100\000\000\000\000\000\101\000\089\000\102\000\083\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\089\000\000\000\089\000\000\000\000\000\000\000\000\000\ +\103\000\000\000\000\000\104\000\000\000\091\000\000\000\000\000\ +\105\000\106\000\091\000\000\000\091\000\000\000\000\000\091\000\ +\091\000\091\000\091\000\091\000\091\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\107\000\108\000\109\000\ +\000\000\000\000\110\000\111\000\091\000\000\000\112\000\000\000\ +\000\000\248\000\000\000\000\000\000\000\191\001\113\000\100\000\ +\000\000\091\000\101\000\091\000\102\000\083\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\114\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\103\000\ +\000\000\000\000\104\000\084\000\085\000\109\001\000\000\105\000\ +\106\000\000\000\000\000\100\000\000\000\000\000\101\000\000\000\ +\102\000\083\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\107\000\108\000\109\000\000\000\ +\000\000\110\000\111\000\103\000\000\000\112\000\104\000\000\000\ +\000\000\000\000\000\000\105\000\106\000\113\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\114\000\000\000\000\000\ +\107\000\108\000\109\000\000\000\000\000\110\000\111\000\000\000\ +\000\000\112\000\084\000\085\000\071\002\000\000\000\000\000\000\ +\000\000\113\000\100\000\000\000\000\000\101\000\000\000\102\000\ \083\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\083\000\000\000\083\000\ -\085\000\000\000\000\000\000\000\000\000\084\000\084\000\000\000\ -\084\000\084\000\000\000\000\000\000\000\000\000\084\000\000\000\ -\084\000\000\000\000\000\084\000\084\000\084\000\084\000\084\000\ -\084\000\085\000\000\000\000\000\085\000\085\000\000\000\000\000\ -\085\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\084\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\084\000\000\000\084\000\ -\086\000\000\000\000\000\000\000\000\000\085\000\085\000\000\000\ -\085\000\085\000\000\000\000\000\000\000\000\000\085\000\000\000\ -\085\000\000\000\000\000\085\000\085\000\085\000\085\000\085\000\ -\085\000\086\000\000\000\000\000\086\000\086\000\000\000\000\000\ -\086\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\085\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\085\000\000\000\085\000\ -\087\000\000\000\000\000\000\000\000\000\086\000\000\000\000\000\ -\086\000\086\000\000\000\000\000\000\000\000\000\086\000\000\000\ -\086\000\000\000\000\000\086\000\086\000\086\000\086\000\086\000\ -\086\000\087\000\000\000\000\000\087\000\087\000\000\000\000\000\ -\087\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\086\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\086\000\000\000\086\000\ -\088\000\000\000\000\000\000\000\000\000\087\000\000\000\000\000\ -\087\000\087\000\000\000\000\000\000\000\000\000\087\000\000\000\ -\087\000\000\000\000\000\087\000\087\000\087\000\087\000\087\000\ -\087\000\088\000\000\000\000\000\088\000\088\000\000\000\000\000\ -\088\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\087\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\087\000\000\000\087\000\ -\089\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\088\000\088\000\000\000\000\000\000\000\000\000\088\000\000\000\ -\088\000\000\000\000\000\088\000\088\000\088\000\088\000\088\000\ -\088\000\089\000\000\000\000\000\089\000\089\000\000\000\000\000\ -\089\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\088\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\088\000\000\000\088\000\ -\091\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\089\000\089\000\000\000\000\000\000\000\000\000\089\000\000\000\ -\089\000\000\000\000\000\089\000\089\000\089\000\089\000\089\000\ -\089\000\091\000\000\000\000\000\091\000\091\000\000\000\000\000\ -\091\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\089\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\089\000\248\000\089\000\ -\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\ -\101\000\091\000\102\000\083\000\000\000\000\000\091\000\000\000\ -\091\000\000\000\000\000\091\000\091\000\091\000\091\000\091\000\ -\091\000\000\000\000\000\000\000\000\000\103\000\000\000\000\000\ -\104\000\000\000\000\000\000\000\000\000\105\000\106\000\000\000\ -\091\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\091\000\000\000\091\000\ -\000\000\000\000\107\000\108\000\109\000\000\000\000\000\110\000\ -\111\000\000\000\000\000\112\000\000\000\248\000\000\000\000\000\ -\000\000\000\000\191\001\113\000\100\000\000\000\000\000\101\000\ -\000\000\102\000\083\000\000\000\000\000\143\001\143\001\143\001\ -\143\001\143\001\143\001\114\000\000\000\000\000\000\000\000\000\ -\000\000\143\001\143\001\143\001\103\000\143\001\143\001\104\000\ -\084\000\085\000\000\000\143\001\105\000\106\000\000\000\000\000\ -\143\001\143\001\143\001\143\001\000\000\143\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\107\000\108\000\109\000\109\001\000\000\110\000\111\000\ -\000\000\000\000\112\000\100\000\000\000\000\000\101\000\000\000\ -\102\000\083\000\113\000\000\000\000\000\000\000\000\000\143\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\114\000\103\000\000\000\000\000\104\000\000\000\ -\000\000\000\000\000\000\105\000\106\000\000\000\000\000\084\000\ -\085\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\107\000\108\000\109\000\071\002\000\000\110\000\111\000\000\000\ -\000\000\112\000\100\000\000\000\000\000\101\000\000\000\102\000\ -\083\000\113\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\114\000\103\000\000\000\000\000\104\000\000\000\000\000\ -\000\000\000\000\105\000\106\000\000\000\000\000\084\000\085\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\114\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\103\000\000\000\000\000\104\000\084\000\085\000\ +\000\000\000\000\105\000\106\000\000\000\000\000\100\000\000\000\ +\000\000\101\000\000\000\102\000\083\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\107\000\ -\108\000\109\000\000\000\000\000\110\000\111\000\000\000\000\000\ -\112\000\141\001\141\001\141\001\141\001\141\001\141\001\000\000\ -\113\000\000\000\000\000\000\000\000\000\141\001\141\001\141\001\ +\108\000\109\000\000\000\000\000\110\000\111\000\103\000\000\000\ +\112\000\104\000\000\000\000\000\000\000\000\000\105\000\106\000\ +\113\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\114\000\000\000\000\000\107\000\108\000\109\000\000\000\000\000\ +\110\000\111\000\000\000\000\000\112\000\084\000\085\000\000\000\ +\000\000\000\000\000\000\000\000\113\000\000\000\000\000\000\000\ +\000\000\141\001\141\001\141\001\141\001\141\001\141\001\000\000\ +\000\000\000\000\000\000\000\000\114\000\141\001\141\001\141\001\ \000\000\141\001\141\001\141\001\141\001\000\000\000\000\141\001\ -\114\000\000\000\000\000\000\000\141\001\141\001\141\001\141\001\ -\000\000\141\001\000\000\000\000\000\000\084\000\085\000\000\000\ -\000\000\142\001\142\001\142\001\142\001\142\001\142\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\142\001\142\001\142\001\ -\000\000\142\001\142\001\142\001\142\001\000\000\000\000\142\001\ -\000\000\000\000\000\000\141\001\142\001\142\001\142\001\142\001\ -\000\000\142\001\144\001\144\001\144\001\144\001\144\001\144\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\144\001\144\001\ -\144\001\000\000\144\001\144\001\000\000\000\000\000\000\000\000\ -\144\001\000\000\000\000\000\000\000\000\144\001\144\001\144\001\ -\144\001\000\000\144\001\142\001\000\000\145\001\145\001\145\001\ -\145\001\145\001\145\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\145\001\145\001\145\001\000\000\145\001\145\001\000\000\ -\000\000\000\000\000\000\145\001\000\000\000\000\000\000\000\000\ -\145\001\145\001\145\001\145\001\144\001\145\001\146\001\146\001\ -\146\001\146\001\146\001\146\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\146\001\146\001\146\001\000\000\146\001\146\001\ -\000\000\000\000\000\000\000\000\146\001\000\000\000\000\000\000\ -\000\000\146\001\146\001\146\001\146\001\000\000\146\001\145\001\ -\000\000\147\001\147\001\147\001\147\001\147\001\147\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\147\001\147\001\147\001\ -\000\000\147\001\147\001\000\000\000\000\000\000\000\000\147\001\ -\149\001\149\001\000\000\000\000\147\001\147\001\147\001\147\001\ -\146\001\147\001\000\000\000\000\149\001\149\001\149\001\000\000\ -\149\001\149\001\000\000\000\000\000\000\000\000\149\001\150\001\ -\150\001\000\000\000\000\149\001\149\001\149\001\149\001\000\000\ -\149\001\000\000\000\000\150\001\150\001\150\001\000\000\150\001\ -\150\001\000\000\000\000\147\001\000\000\150\001\000\000\000\000\ -\000\000\000\000\150\001\150\001\150\001\150\001\000\000\150\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\149\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\084\000\085\000\000\000\141\001\141\001\141\001\141\001\ +\000\000\141\001\142\001\142\001\142\001\142\001\142\001\142\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\142\001\142\001\ +\142\001\000\000\142\001\142\001\000\000\000\000\000\000\000\000\ +\142\001\000\000\000\000\000\000\000\000\142\001\142\001\142\001\ +\142\001\000\000\142\001\141\001\000\000\143\001\143\001\143\001\ +\143\001\143\001\143\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\143\001\143\001\143\001\000\000\143\001\143\001\000\000\ +\000\000\000\000\000\000\143\001\000\000\000\000\000\000\000\000\ +\143\001\143\001\143\001\143\001\142\001\143\001\144\001\144\001\ +\144\001\144\001\144\001\144\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\144\001\144\001\144\001\000\000\144\001\144\001\ +\000\000\000\000\000\000\000\000\144\001\000\000\000\000\000\000\ +\000\000\144\001\144\001\144\001\144\001\000\000\144\001\143\001\ +\000\000\145\001\145\001\145\001\145\001\145\001\145\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\145\001\145\001\145\001\ +\000\000\145\001\145\001\000\000\000\000\000\000\000\000\145\001\ +\000\000\000\000\000\000\000\000\145\001\145\001\145\001\145\001\ +\144\001\145\001\146\001\146\001\146\001\146\001\146\001\146\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\146\001\146\001\ +\146\001\000\000\146\001\146\001\000\000\000\000\000\000\000\000\ +\146\001\148\001\148\001\000\000\000\000\146\001\146\001\146\001\ +\146\001\000\000\146\001\145\001\000\000\148\001\148\001\148\001\ +\000\000\148\001\148\001\000\000\000\000\000\000\000\000\148\001\ +\149\001\149\001\000\000\000\000\148\001\148\001\148\001\148\001\ +\000\000\148\001\000\000\000\000\149\001\149\001\149\001\000\000\ +\149\001\149\001\000\000\000\000\146\001\000\000\149\001\000\000\ +\000\000\000\000\000\000\149\001\149\001\149\001\149\001\000\000\ +\149\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\148\001\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\150\001\029\000\029\000\029\000\029\000\029\000\029\000\ +\000\000\000\000\149\001\029\000\029\000\029\000\029\000\029\000\ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ -\029\000\029\000\000\000\029\000\029\000\029\000\000\000\029\000\ -\029\000\029\000\029\000\029\000\029\000\000\000\029\000\029\000\ -\000\000\029\000\000\000\023\000\029\000\029\000\000\000\029\000" +\029\000\029\000\029\000\000\000\029\000\029\000\029\000\000\000\ +\029\000\029\000\029\000\029\000\029\000\029\000\000\000\029\000\ +\029\000\000\000\029\000\000\000\023\000\029\000\029\000\000\000\ +\029\000" let yycheck = "\016\000\ -\017\000\155\000\019\000\044\000\053\000\049\000\032\000\069\000\ -\170\000\025\000\120\000\061\000\058\001\062\000\042\001\087\000\ -\162\000\061\000\060\001\238\001\001\000\002\000\048\000\004\001\ -\040\000\086\001\087\001\049\000\000\000\107\002\000\000\232\001\ -\000\000\000\001\104\002\180\002\007\001\220\000\183\002\061\000\ -\220\000\012\001\237\001\000\001\000\001\086\000\145\000\000\001\ -\148\002\016\000\017\000\032\000\019\000\169\000\040\000\117\000\ -\073\000\200\000\179\000\180\000\077\000\060\001\052\001\053\001\ -\007\001\082\000\055\001\048\000\230\000\012\001\059\001\254\000\ -\170\000\000\001\254\000\013\001\000\001\000\001\062\001\000\001\ -\096\000\076\001\098\000\083\001\081\001\000\001\134\002\079\001\ -\085\001\084\001\080\001\107\000\108\000\109\000\110\000\111\000\ -\112\000\113\000\082\001\140\000\141\000\053\001\150\002\097\000\ -\120\000\250\002\073\000\007\001\079\001\062\001\077\000\078\001\ -\012\001\007\001\214\002\082\000\142\000\077\001\012\001\017\000\ -\120\001\019\000\079\001\079\001\076\001\007\001\170\000\113\000\ -\080\001\080\000\012\001\102\001\230\000\013\001\014\001\152\000\ -\079\001\007\001\027\003\076\001\076\001\185\000\012\001\137\000\ -\115\001\126\001\082\001\084\001\170\000\227\002\001\000\002\000\ -\222\002\004\000\125\001\136\000\079\001\229\000\079\001\102\001\ -\083\001\142\000\051\003\017\001\079\001\104\002\105\002\018\000\ -\106\001\107\001\196\000\220\000\115\001\118\002\025\000\026\000\ -\074\000\077\001\029\000\030\000\070\001\032\000\125\001\034\000\ -\200\000\079\001\007\001\114\001\077\001\116\001\114\001\012\001\ -\116\001\044\000\157\002\077\001\001\002\048\000\125\001\050\000\ -\217\000\125\001\244\001\245\001\055\000\254\000\057\000\000\001\ -\230\000\060\000\134\001\135\001\055\001\064\000\105\002\196\000\ -\059\001\060\001\078\001\085\003\147\001\148\001\077\001\088\001\ -\077\001\125\001\106\001\107\001\094\003\228\001\128\001\125\001\ -\231\001\184\000\197\002\086\000\187\000\188\000\189\000\228\001\ -\013\001\192\000\193\000\125\001\071\001\244\001\097\000\001\000\ -\002\000\188\002\010\001\190\002\179\001\192\002\243\001\125\001\ -\245\001\077\001\018\001\086\001\021\001\022\001\056\001\023\001\ +\017\000\053\000\019\000\044\000\049\000\069\000\097\000\155\000\ +\170\000\025\000\062\000\032\000\001\000\002\000\042\001\040\000\ +\061\000\058\001\120\000\145\000\086\001\087\001\179\000\180\000\ +\040\000\049\000\003\001\048\000\087\000\162\000\000\000\000\000\ +\061\000\060\001\169\000\000\000\107\002\061\000\238\001\232\001\ +\000\001\037\001\000\001\032\000\000\001\086\000\137\000\006\001\ +\044\000\016\000\017\000\076\001\019\000\117\000\000\001\000\001\ +\073\000\051\001\052\001\048\000\077\000\006\001\052\001\200\000\ +\070\001\082\000\011\001\055\001\230\000\104\002\006\001\059\001\ +\034\003\000\001\076\001\011\001\000\001\220\000\000\001\085\001\ +\096\000\076\001\098\000\170\000\040\001\079\001\237\001\134\002\ +\113\000\079\001\052\003\107\000\108\000\109\000\110\000\111\000\ +\112\000\113\000\148\002\140\000\141\000\061\001\061\001\150\002\ +\120\000\101\001\073\000\017\000\070\003\019\000\077\000\254\000\ +\080\000\000\001\076\001\082\000\061\001\076\001\114\001\077\001\ +\116\001\142\000\078\001\082\001\006\001\170\000\082\001\083\001\ +\006\001\011\001\075\001\076\001\078\001\011\001\079\001\152\000\ +\081\001\082\001\083\001\012\001\185\000\060\001\078\001\230\000\ +\140\000\141\000\170\000\136\000\125\001\001\000\002\000\078\001\ +\004\000\142\000\078\001\226\002\078\001\107\000\108\000\109\000\ +\110\000\111\000\112\000\213\002\074\000\124\001\018\000\105\002\ +\220\000\076\001\229\000\017\001\080\001\025\000\026\000\196\000\ +\084\001\029\000\030\000\124\001\032\000\118\002\034\000\061\001\ +\200\000\055\001\221\002\088\001\124\001\059\001\060\001\001\002\ +\044\000\070\001\076\001\078\001\048\000\079\001\050\000\078\001\ +\217\000\061\001\254\000\055\000\000\001\057\000\230\000\196\000\ +\060\000\104\002\105\002\061\001\064\000\157\002\012\001\013\001\ +\184\000\244\001\245\001\187\000\188\000\189\000\082\001\058\001\ +\192\000\193\000\083\003\114\001\070\001\116\001\078\001\081\001\ +\105\001\106\001\086\000\092\003\128\001\000\001\125\001\006\001\ +\228\001\061\001\124\001\085\001\011\001\097\000\081\001\134\001\ +\135\001\187\002\010\001\189\002\196\002\191\002\023\001\243\001\ +\091\001\245\001\018\001\012\001\021\001\022\001\082\001\023\001\ \024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ \032\001\033\001\034\001\035\001\036\001\037\001\038\001\039\001\ -\040\001\041\001\042\001\222\002\000\001\136\000\000\001\053\001\ -\000\001\140\000\141\000\142\000\102\001\023\001\181\001\182\001\ -\076\001\188\002\031\002\190\002\090\002\192\002\007\001\064\001\ -\084\001\115\001\078\002\012\001\007\001\171\002\021\001\022\001\ -\106\001\012\001\079\001\041\001\077\001\007\001\169\000\053\001\ -\058\001\114\001\012\001\116\001\107\000\108\000\109\000\110\000\ -\111\000\112\000\078\001\000\001\125\001\106\001\107\001\096\001\ -\084\001\227\001\007\001\071\001\194\001\036\003\007\001\081\001\ -\195\000\196\000\080\001\012\001\077\001\007\001\076\001\022\002\ -\023\002\091\001\086\001\007\001\082\001\083\001\084\001\054\003\ -\012\001\094\002\152\002\062\001\097\002\062\001\078\001\044\000\ -\000\000\220\000\000\001\007\001\062\001\000\001\079\001\237\002\ -\012\001\072\003\240\002\077\001\007\001\081\001\143\001\144\001\ -\084\001\228\001\083\001\077\001\231\001\251\002\080\001\124\002\ -\076\001\062\001\089\001\133\001\062\001\092\001\082\001\007\001\ -\243\001\244\001\245\001\254\000\062\001\000\001\101\001\076\001\ -\077\001\007\001\105\001\080\001\077\001\082\001\083\001\084\001\ -\082\001\083\001\024\003\077\001\125\001\181\001\182\001\077\001\ -\095\002\083\001\032\003\079\001\034\003\007\001\236\001\077\001\ -\143\001\144\001\012\001\125\001\042\003\062\001\226\001\031\001\ -\079\001\007\001\034\001\079\001\031\002\007\001\012\001\076\001\ -\119\002\055\003\012\001\080\001\240\001\079\001\007\001\084\001\ -\125\001\079\001\083\001\012\001\125\001\077\001\223\001\140\000\ -\141\000\115\002\102\001\125\001\136\002\137\002\094\001\095\001\ -\096\001\125\001\006\002\007\001\062\001\072\001\084\003\115\001\ -\012\001\007\001\082\001\078\001\077\001\223\001\012\001\158\002\ -\221\002\125\001\140\002\077\001\000\001\013\001\080\001\082\001\ -\062\001\024\001\025\001\026\001\062\001\079\001\072\001\073\001\ -\006\001\076\001\077\001\094\002\179\002\080\001\097\002\077\001\ -\223\001\084\001\076\001\077\001\060\001\061\001\080\001\114\001\ -\078\001\116\001\084\001\005\002\077\001\083\001\066\001\080\001\ -\170\002\031\001\125\001\033\001\034\001\035\001\000\001\082\001\ -\038\001\124\002\085\001\134\001\135\001\007\001\067\001\038\001\ -\076\001\077\001\012\001\125\001\080\001\220\002\076\001\077\001\ -\084\001\068\001\080\001\078\001\076\001\070\001\084\001\125\001\ -\083\001\232\002\082\001\125\001\007\001\236\002\007\001\010\001\ -\007\002\012\001\077\001\079\001\125\001\080\001\078\002\083\001\ -\084\001\082\002\107\002\084\001\105\000\106\000\083\001\115\002\ -\041\001\007\001\106\001\107\001\031\001\108\001\012\001\034\001\ -\083\001\125\001\098\002\083\001\062\001\102\002\084\001\125\001\ -\102\001\083\002\107\002\052\001\053\001\115\002\083\001\102\001\ -\090\002\076\001\076\001\077\001\062\001\115\001\080\001\117\001\ -\082\001\083\001\084\001\084\001\115\001\036\003\117\001\054\001\ -\055\001\074\001\075\001\082\002\077\001\134\002\140\002\080\001\ -\146\002\138\002\221\002\060\001\061\001\232\001\107\002\054\003\ -\000\001\000\001\076\001\238\001\041\001\150\002\006\001\184\002\ -\072\001\073\001\093\001\084\001\134\002\007\001\076\001\077\001\ -\079\001\072\003\080\001\125\001\000\001\248\002\084\001\083\001\ -\196\002\147\002\171\002\172\002\150\002\078\001\152\002\031\001\ -\079\001\178\002\034\001\035\001\078\001\146\002\038\001\134\002\ -\006\001\079\001\041\001\138\002\209\000\210\000\017\003\211\000\ -\212\000\213\000\214\000\215\000\216\000\218\000\219\000\150\002\ -\062\001\063\001\064\001\181\002\077\001\041\001\033\003\125\001\ -\076\001\031\001\054\001\055\001\034\001\035\001\007\001\078\001\ -\038\001\010\001\076\001\012\001\013\001\076\001\076\001\224\002\ -\079\001\077\001\227\002\082\001\083\001\084\001\077\001\094\001\ -\095\001\096\001\099\001\100\001\237\002\215\002\031\001\240\002\ -\077\001\034\001\076\001\079\001\068\001\006\001\102\001\083\001\ -\084\001\066\001\251\002\028\003\062\001\063\001\064\001\077\001\ -\006\001\070\001\080\001\115\001\067\001\117\001\083\001\084\001\ -\127\001\084\001\043\003\036\003\083\001\084\001\031\001\076\001\ -\107\002\034\001\035\001\083\001\084\001\038\001\010\001\024\003\ -\102\001\031\001\104\001\118\002\034\001\035\001\010\001\032\003\ -\038\001\034\003\094\001\095\001\096\001\115\001\010\001\117\001\ -\076\001\042\003\242\002\243\002\093\001\136\002\137\002\025\003\ -\054\001\055\001\056\001\057\001\058\001\059\001\055\003\146\002\ -\010\001\106\001\107\001\078\001\066\001\067\001\068\001\120\001\ -\070\001\071\001\157\002\140\000\141\000\069\003\076\001\078\001\ -\078\001\164\001\165\001\081\001\082\001\083\001\084\001\085\001\ -\086\001\172\002\076\001\084\003\076\001\102\001\112\001\104\001\ -\078\001\081\001\082\001\083\001\056\001\057\001\058\001\059\001\ -\102\001\076\001\115\001\076\001\117\001\166\001\167\001\002\001\ -\078\001\083\003\197\002\006\001\007\001\115\001\076\001\117\001\ -\082\001\012\001\172\001\173\001\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\076\001\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\084\001\161\001\162\001\163\001\ -\164\001\165\001\166\001\167\001\168\001\169\001\170\001\171\001\ -\172\001\173\001\174\001\175\001\176\001\177\001\178\001\083\001\ -\000\001\001\001\002\001\078\001\004\001\005\001\006\001\007\001\ +\040\001\041\001\042\001\056\001\136\000\053\001\000\001\000\001\ +\140\000\141\000\142\000\000\001\187\002\076\001\189\002\000\000\ +\191\002\000\001\133\001\031\002\181\001\182\001\220\000\064\001\ +\076\001\090\002\078\002\105\001\106\001\228\001\021\001\022\001\ +\231\001\001\000\002\000\078\001\077\001\169\000\114\001\082\001\ +\116\001\179\002\006\001\006\001\182\002\244\001\221\002\011\001\ +\011\001\125\001\024\001\025\001\026\001\106\001\061\001\096\001\ +\254\000\006\001\000\001\082\001\006\001\006\001\011\001\195\000\ +\196\000\011\001\011\001\101\001\194\001\006\001\227\001\075\001\ +\105\001\106\001\081\001\082\001\075\001\124\001\228\001\083\001\ +\114\001\231\001\094\002\077\001\083\001\097\002\006\001\152\002\ +\220\000\061\001\075\001\011\001\006\001\243\001\244\001\245\001\ +\119\001\089\001\083\001\076\001\092\001\077\001\143\001\144\001\ +\076\001\000\001\082\001\079\001\223\001\101\001\248\002\006\001\ +\124\002\105\001\078\001\078\001\061\001\000\001\078\001\077\001\ +\076\001\006\001\254\000\006\001\000\001\083\001\011\001\006\001\ +\078\001\078\001\075\001\076\001\011\001\080\001\079\001\040\001\ +\083\001\031\002\083\001\105\000\106\000\181\001\182\001\025\003\ +\006\001\006\001\005\002\078\001\236\001\011\001\011\001\076\001\ +\143\001\144\001\075\001\075\001\076\001\226\001\079\001\079\001\ +\124\001\124\001\083\001\083\001\006\001\030\001\061\001\049\003\ +\033\001\011\001\075\001\240\001\114\001\012\001\116\001\124\001\ +\081\001\082\001\083\001\124\001\075\001\076\001\223\001\125\001\ +\079\001\115\002\081\001\082\001\083\001\075\001\075\001\076\001\ +\006\001\006\002\079\001\081\001\072\001\011\001\083\001\078\001\ +\094\002\081\001\078\001\097\002\124\001\147\001\148\001\006\001\ +\220\002\081\001\140\002\006\001\011\001\075\001\076\001\076\001\ +\011\001\079\001\077\001\061\001\076\001\083\001\101\001\082\001\ +\083\002\136\002\137\002\075\001\052\001\124\001\124\002\090\002\ +\223\001\081\001\076\001\114\001\075\001\179\001\114\001\124\001\ +\116\001\006\001\081\001\209\000\210\000\124\001\011\001\081\001\ +\065\001\125\001\084\001\075\001\218\000\219\000\170\002\079\001\ +\000\001\067\001\134\001\135\001\006\001\066\001\124\001\124\001\ +\078\001\011\001\105\001\106\001\075\001\076\001\006\001\007\002\ +\079\001\075\001\083\001\134\002\083\001\076\001\080\001\081\001\ +\082\001\006\001\124\001\078\001\009\001\069\001\011\001\101\001\ +\147\002\076\001\082\001\150\002\079\001\152\002\078\002\059\001\ +\060\001\082\002\107\002\005\001\114\001\040\001\115\002\071\001\ +\072\001\030\001\101\001\107\001\033\001\082\001\124\001\076\001\ +\053\001\054\001\098\002\061\001\082\001\102\002\075\001\114\001\ +\083\001\180\002\107\002\115\002\030\001\124\001\220\002\033\001\ +\034\001\124\001\076\001\037\001\082\001\079\001\078\001\061\001\ +\022\002\023\002\082\001\083\001\061\001\062\001\063\001\000\001\ +\061\001\062\001\063\001\082\002\140\002\134\002\107\002\083\001\ +\246\002\138\002\040\001\214\002\232\001\146\002\078\001\124\001\ +\059\001\060\001\238\001\183\002\083\001\150\002\075\001\092\001\ +\071\001\072\001\006\001\211\000\212\000\213\000\214\000\215\000\ +\216\000\015\003\124\001\093\001\094\001\095\001\195\002\040\001\ +\053\001\054\001\171\002\098\001\099\001\146\002\082\001\083\001\ +\177\002\031\003\082\001\101\001\077\001\103\001\078\001\134\002\ +\053\001\054\001\077\001\138\002\082\001\083\001\000\001\000\001\ +\114\001\095\002\116\001\005\001\065\001\066\001\067\001\150\002\ +\069\001\070\001\075\001\078\001\023\003\078\001\075\001\005\001\ +\081\001\082\001\083\001\080\001\081\001\082\001\083\001\005\001\ +\085\001\119\002\082\001\083\001\030\001\075\001\223\002\033\001\ +\034\001\226\002\075\001\037\001\093\001\094\001\095\001\040\001\ +\030\001\076\001\235\002\033\001\034\001\238\002\076\001\037\001\ +\030\001\077\001\076\001\033\001\034\001\076\001\026\003\037\001\ +\249\002\075\001\119\001\055\001\056\001\057\001\058\001\075\001\ +\158\002\093\001\094\001\095\001\065\001\041\003\081\003\240\002\ +\241\002\034\003\075\001\140\000\141\000\078\001\067\001\107\002\ +\081\001\082\001\083\001\066\001\178\002\022\003\076\001\166\001\ +\167\001\079\001\118\002\164\001\165\001\030\003\076\001\032\003\ +\069\001\079\001\126\001\101\001\172\001\173\001\083\001\040\003\ +\055\001\056\001\057\001\058\001\136\002\137\002\075\001\101\001\ +\114\001\103\001\116\001\009\001\053\003\009\001\146\002\101\001\ +\009\001\103\001\005\001\075\001\114\001\219\002\116\001\005\001\ +\009\001\157\002\077\001\067\003\114\001\119\001\116\001\077\001\ +\230\002\075\001\051\001\052\001\234\002\027\001\028\001\171\002\ +\077\001\082\003\075\001\030\001\111\001\032\001\033\001\034\001\ +\030\001\075\001\037\001\033\001\034\001\029\001\030\001\037\001\ +\073\001\074\001\077\001\076\001\035\001\036\001\079\001\075\001\ +\196\002\161\001\162\001\163\001\164\001\165\001\166\001\167\001\ +\168\001\169\001\170\001\171\001\172\001\173\001\174\001\175\001\ +\176\001\177\001\178\001\065\001\066\001\067\001\075\001\069\001\ +\070\001\081\001\006\001\006\001\034\003\075\001\009\001\077\001\ +\011\001\012\001\080\001\081\001\082\001\083\001\084\001\085\001\ +\168\001\169\001\170\001\171\001\077\001\083\001\052\003\082\001\ +\077\001\077\001\101\001\030\001\077\001\077\001\033\001\101\001\ +\031\001\032\001\033\001\034\001\075\001\082\001\075\001\114\001\ +\070\003\116\001\083\001\075\001\114\001\075\001\116\001\076\001\ +\075\001\000\001\001\001\075\001\003\001\004\001\005\001\006\001\ +\007\001\008\001\009\001\010\001\011\001\012\001\013\001\014\001\ +\015\001\016\001\017\001\018\001\019\001\020\001\034\003\022\001\ +\023\001\024\001\025\001\026\001\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\036\001\037\001\038\001\ +\039\001\092\001\080\001\006\001\081\001\006\001\076\001\082\001\ +\082\001\025\002\083\001\079\001\077\001\077\001\105\001\106\001\ +\077\001\077\001\075\001\075\001\059\001\060\001\061\001\075\001\ +\083\001\064\001\065\001\075\001\083\001\068\001\069\001\075\001\ +\083\001\083\001\073\001\074\001\081\001\076\001\077\001\078\001\ +\080\001\083\001\078\001\082\001\078\001\078\001\083\001\086\001\ +\087\001\088\001\089\001\090\001\091\001\092\001\093\001\094\001\ +\095\001\096\001\097\001\040\001\081\001\077\001\101\001\102\001\ +\103\001\104\001\105\001\106\001\075\001\108\001\075\001\080\001\ +\083\001\112\001\113\001\114\001\115\001\116\001\117\001\118\001\ +\075\001\077\001\082\001\122\001\123\001\075\001\125\001\126\001\ +\000\001\001\001\077\001\032\001\004\001\005\001\006\001\007\001\ \008\001\009\001\010\001\011\001\012\001\013\001\014\001\015\001\ -\016\001\017\001\018\001\019\001\020\001\021\001\078\001\023\001\ +\016\001\017\001\018\001\019\001\020\001\075\001\022\001\023\001\ \024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ \032\001\033\001\034\001\035\001\036\001\037\001\038\001\039\001\ -\040\001\036\003\076\001\102\001\103\001\078\001\105\001\081\001\ -\082\001\083\001\084\001\056\001\057\001\058\001\059\001\078\001\ -\115\001\078\001\117\001\076\001\060\001\061\001\062\001\083\001\ -\123\001\065\001\066\001\076\001\127\001\069\001\070\001\027\001\ -\028\001\084\001\074\001\075\001\007\001\077\001\078\001\079\001\ -\029\001\030\001\076\001\083\001\035\001\036\001\120\001\087\001\ +\144\002\075\001\018\000\082\001\126\001\082\001\080\001\081\001\ +\082\001\083\001\026\000\076\001\082\001\029\000\030\000\081\001\ +\075\001\081\001\034\000\059\001\060\001\061\001\075\001\080\001\ +\064\001\065\001\077\001\075\001\068\001\069\001\075\001\077\001\ +\081\001\073\001\074\001\077\001\076\001\077\001\078\001\055\000\ +\076\001\057\000\082\001\082\001\082\001\119\001\086\001\087\001\ \088\001\089\001\090\001\091\001\092\001\093\001\094\001\095\001\ -\096\001\097\001\098\001\077\001\076\001\025\002\102\001\103\001\ -\104\001\105\001\106\001\107\001\076\001\109\001\076\001\081\001\ -\007\001\113\001\114\001\115\001\116\001\117\001\118\001\119\001\ -\082\001\007\001\077\001\123\001\124\001\083\001\126\001\127\001\ -\168\001\169\001\170\001\171\001\084\001\083\001\000\001\001\001\ -\002\001\080\001\078\001\005\001\006\001\007\001\008\001\009\001\ -\010\001\011\001\012\001\013\001\014\001\015\001\016\001\017\001\ -\018\001\019\001\020\001\021\001\078\001\023\001\024\001\025\001\ -\026\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\036\001\037\001\038\001\039\001\040\001\078\001\ -\078\001\018\000\031\001\032\001\033\001\034\001\076\001\076\001\ -\076\001\026\000\084\001\084\001\029\000\030\000\081\001\076\001\ -\076\001\034\000\060\001\061\001\062\001\084\001\079\001\065\001\ -\066\001\084\001\082\001\069\001\070\001\084\001\079\001\079\001\ -\074\001\075\001\084\001\077\001\078\001\079\001\055\000\041\001\ -\057\000\083\001\082\001\078\001\144\002\087\001\088\001\089\001\ -\090\001\091\001\092\001\093\001\094\001\095\001\096\001\097\001\ -\098\001\076\001\076\001\081\001\102\001\103\001\104\001\105\001\ -\106\001\107\001\076\001\109\001\084\001\078\001\083\001\113\001\ -\114\001\115\001\116\001\117\001\118\001\119\001\076\001\078\001\ -\033\001\123\001\124\001\076\001\127\001\127\001\000\001\001\001\ -\002\001\083\001\077\001\005\001\006\001\007\001\008\001\009\001\ -\010\001\011\001\012\001\013\001\014\001\015\001\016\001\017\001\ -\018\001\019\001\020\001\021\001\083\001\023\001\024\001\025\001\ -\026\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\036\001\037\001\038\001\039\001\040\001\082\001\ -\041\001\042\001\043\001\044\001\045\001\046\001\047\001\048\001\ -\049\001\050\001\051\001\006\001\083\001\082\001\076\001\076\001\ -\081\001\076\001\060\001\061\001\062\001\078\001\076\001\065\001\ -\066\001\078\001\078\001\069\001\070\001\000\001\077\001\082\001\ -\074\001\075\001\083\001\077\001\031\001\079\001\083\001\034\001\ -\035\001\083\001\077\001\038\001\007\001\087\001\088\001\089\001\ -\090\001\091\001\092\001\093\001\094\001\095\001\096\001\097\001\ -\098\001\081\001\083\001\013\001\102\001\103\001\104\001\105\001\ -\106\001\107\001\094\001\109\001\101\001\082\001\041\001\113\001\ -\114\001\115\001\116\001\117\001\118\001\119\001\082\001\080\001\ -\083\001\123\001\124\001\076\001\083\001\127\001\000\001\001\001\ -\002\001\083\001\004\001\005\001\007\001\007\001\008\001\009\001\ -\010\001\011\001\012\001\013\001\014\001\082\001\054\001\055\001\ -\084\001\076\001\083\001\102\001\079\001\081\001\077\001\082\001\ -\083\001\084\001\066\001\067\001\068\001\076\001\070\001\071\001\ -\115\001\082\001\117\001\076\001\076\001\039\001\040\001\076\001\ -\084\001\081\001\082\001\083\001\084\001\076\001\086\001\150\001\ -\151\001\152\001\153\001\154\001\155\001\156\001\157\001\158\001\ -\159\001\160\001\060\001\061\001\062\001\078\001\000\001\065\001\ -\066\001\083\001\076\001\069\001\070\001\076\001\078\001\076\001\ -\074\001\075\001\080\001\077\001\078\001\079\001\076\001\078\001\ -\120\001\083\001\083\001\078\001\076\001\087\001\088\001\089\001\ -\090\001\091\001\092\001\093\001\094\001\095\001\096\001\097\001\ -\098\001\082\001\078\001\083\001\078\001\083\001\104\001\077\001\ -\106\001\107\001\081\001\109\001\076\001\076\001\083\001\113\001\ -\114\001\076\001\116\001\076\001\076\001\002\000\136\000\208\002\ -\231\001\214\002\124\001\082\001\126\001\127\001\000\001\001\001\ -\002\001\004\000\004\001\005\001\006\001\007\001\008\001\009\001\ -\010\001\011\001\012\001\013\001\014\001\015\001\016\001\017\001\ -\018\001\019\001\020\001\021\001\006\002\023\001\024\001\025\001\ -\026\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\036\001\037\001\038\001\039\001\040\001\101\002\ -\152\000\102\002\174\001\119\002\144\002\033\003\046\003\175\001\ -\248\001\176\000\196\002\176\001\017\001\177\001\194\001\037\001\ -\178\001\038\001\060\001\061\001\062\001\039\001\041\001\065\001\ -\066\001\040\001\076\003\069\001\070\001\074\003\094\003\255\255\ -\074\001\075\001\255\255\077\001\078\001\079\001\255\255\255\255\ -\255\255\083\001\255\255\255\255\255\255\087\001\088\001\089\001\ -\090\001\091\001\092\001\093\001\094\001\095\001\096\001\097\001\ -\098\001\255\255\255\255\255\255\102\001\103\001\104\001\105\001\ -\106\001\107\001\255\255\109\001\255\255\255\255\112\001\113\001\ -\114\001\115\001\116\001\117\001\118\001\119\001\255\255\255\255\ -\255\255\123\001\124\001\255\255\126\001\000\001\001\001\002\001\ -\255\255\004\001\005\001\006\001\007\001\008\001\009\001\010\001\ -\011\001\012\001\013\001\014\001\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\039\001\040\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\255\255\255\255\255\255\074\001\ -\075\001\255\255\077\001\078\001\079\001\255\255\255\255\255\255\ -\083\001\255\255\255\255\255\255\087\001\088\001\089\001\090\001\ -\091\001\092\001\093\001\094\001\095\001\096\001\097\001\098\001\ -\255\255\255\255\255\255\102\001\103\001\104\001\105\001\106\001\ -\107\001\255\255\109\001\255\255\255\255\255\255\113\001\114\001\ -\115\001\116\001\117\001\118\001\119\001\255\255\255\255\255\255\ -\123\001\124\001\255\255\126\001\000\001\001\001\002\001\255\255\ +\096\001\097\001\076\001\006\001\080\001\101\001\102\001\103\001\ +\104\001\105\001\106\001\082\001\108\001\100\001\012\001\093\001\ +\112\001\113\001\114\001\115\001\116\001\117\001\118\001\081\001\ +\081\001\079\001\122\001\123\001\000\001\001\001\126\001\082\001\ \004\001\005\001\006\001\007\001\008\001\009\001\010\001\011\001\ \012\001\013\001\014\001\015\001\016\001\017\001\018\001\019\001\ -\020\001\021\001\255\255\023\001\024\001\025\001\026\001\027\001\ +\020\001\075\001\022\001\023\001\024\001\025\001\026\001\027\001\ \028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ -\036\001\037\001\038\001\039\001\040\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\255\255\069\001\070\001\255\255\255\255\255\255\074\001\075\001\ -\255\255\077\001\255\255\079\001\255\255\255\255\255\255\083\001\ -\255\255\255\255\255\255\087\001\088\001\089\001\090\001\091\001\ -\092\001\093\001\255\255\255\255\255\255\097\001\098\001\255\255\ -\255\255\255\255\102\001\103\001\104\001\105\001\106\001\107\001\ -\255\255\109\001\255\255\255\255\255\255\113\001\114\001\115\001\ -\116\001\117\001\255\255\255\255\255\255\255\255\255\255\123\001\ -\124\001\255\255\126\001\000\001\001\001\002\001\255\255\004\001\ -\005\001\255\255\007\001\008\001\009\001\010\001\011\001\012\001\ -\013\001\014\001\255\255\255\255\052\001\053\001\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\039\001\040\001\076\001\255\255\255\255\255\255\ -\080\001\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\060\001\ -\061\001\062\001\255\255\255\255\065\001\066\001\255\255\255\255\ -\069\001\070\001\255\255\255\255\255\255\074\001\075\001\255\255\ -\077\001\255\255\079\001\255\255\255\255\255\255\083\001\255\255\ -\120\001\255\255\087\001\088\001\089\001\090\001\091\001\092\001\ -\093\001\094\001\095\001\096\001\097\001\098\001\255\255\255\255\ -\255\255\255\255\255\255\104\001\013\001\106\001\107\001\255\255\ -\109\001\255\255\255\255\255\255\113\001\114\001\255\255\116\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\124\001\ -\255\255\126\001\000\001\001\001\002\001\255\255\004\001\005\001\ -\255\255\007\001\008\001\009\001\010\001\011\001\012\001\013\001\ -\014\001\255\255\255\255\052\001\053\001\054\001\055\001\056\001\ -\057\001\058\001\059\001\060\001\061\001\062\001\063\001\064\001\ -\255\255\066\001\067\001\068\001\255\255\070\001\071\001\072\001\ -\073\001\039\001\040\001\076\001\255\255\255\255\255\255\080\001\ -\081\001\082\001\083\001\084\001\255\255\086\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\060\001\061\001\ -\062\001\255\255\255\255\065\001\066\001\255\255\255\255\069\001\ -\070\001\106\001\107\001\255\255\074\001\075\001\255\255\077\001\ -\255\255\079\001\255\255\255\255\255\255\083\001\255\255\120\001\ -\255\255\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ -\255\255\255\255\255\255\097\001\098\001\255\255\255\255\255\255\ -\255\255\255\255\104\001\255\255\106\001\107\001\255\255\109\001\ -\255\255\255\255\255\255\113\001\114\001\000\001\116\001\255\255\ -\255\255\255\255\255\255\006\001\007\001\255\255\124\001\255\255\ -\126\001\012\001\255\255\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\052\001\053\001\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\062\001\076\001\255\255\255\255\255\255\ -\080\001\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\255\255\076\001\077\001\255\255\255\255\080\001\255\255\082\001\ -\083\001\084\001\071\001\255\255\255\255\255\255\255\255\076\001\ -\255\255\255\255\255\255\255\255\081\001\082\001\083\001\084\001\ -\255\255\086\001\255\255\102\001\103\001\255\255\105\001\255\255\ -\120\001\255\255\255\255\255\255\255\255\000\001\255\255\255\255\ -\115\001\255\255\117\001\006\001\007\001\255\255\255\255\255\255\ -\123\001\012\001\125\001\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\120\001\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\052\001\053\001\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\062\001\076\001\255\255\255\255\255\255\ -\080\001\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\255\255\076\001\077\001\255\255\255\255\080\001\255\255\082\001\ -\083\001\084\001\071\001\255\255\255\255\255\255\255\255\076\001\ -\255\255\255\255\255\255\255\255\081\001\082\001\083\001\084\001\ -\255\255\086\001\255\255\102\001\103\001\255\255\105\001\255\255\ -\120\001\255\255\255\255\255\255\255\255\000\001\255\255\255\255\ -\115\001\255\255\117\001\006\001\007\001\255\255\255\255\255\255\ -\123\001\012\001\125\001\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\120\001\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\255\255\255\255\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\062\001\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\255\255\076\001\077\001\255\255\255\255\080\001\255\255\082\001\ -\083\001\084\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\102\001\103\001\255\255\105\001\255\255\ -\120\001\255\255\255\255\255\255\255\255\000\001\255\255\255\255\ -\115\001\255\255\117\001\006\001\007\001\255\255\255\255\255\255\ -\123\001\012\001\125\001\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\255\255\255\255\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\062\001\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\006\001\086\001\255\255\ -\255\255\076\001\077\001\255\255\000\001\080\001\255\255\082\001\ -\083\001\084\001\255\255\007\001\008\001\009\001\010\001\011\001\ -\012\001\013\001\014\001\255\255\255\255\255\255\031\001\255\255\ -\255\255\034\001\035\001\102\001\103\001\038\001\105\001\255\255\ -\120\001\255\255\255\255\255\255\255\255\033\001\255\255\255\255\ -\115\001\255\255\117\001\039\001\040\001\041\001\070\001\071\001\ -\123\001\255\255\125\001\255\255\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\060\001\061\001\062\001\255\255\077\001\065\001\066\001\080\001\ -\255\255\069\001\070\001\255\255\255\255\255\255\074\001\075\001\ -\076\001\077\001\255\255\079\001\080\001\081\001\082\001\083\001\ -\084\001\255\255\255\255\255\255\255\255\102\001\255\255\104\001\ -\120\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\115\001\255\255\117\001\255\255\106\001\107\001\ -\255\255\109\001\255\255\255\255\255\255\113\001\114\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\000\001\001\001\002\001\ -\124\001\125\001\005\001\006\001\007\001\008\001\009\001\010\001\ -\011\001\012\001\013\001\014\001\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\039\001\040\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\255\255\255\255\255\255\074\001\ -\075\001\255\255\077\001\078\001\079\001\255\255\255\255\255\255\ -\083\001\255\255\255\255\255\255\087\001\088\001\089\001\090\001\ -\091\001\092\001\093\001\094\001\095\001\096\001\097\001\098\001\ -\255\255\255\255\255\255\102\001\103\001\104\001\105\001\106\001\ -\107\001\255\255\109\001\255\255\255\255\255\255\113\001\114\001\ -\115\001\116\001\117\001\118\001\119\001\000\001\001\001\002\001\ -\123\001\124\001\005\001\006\001\007\001\008\001\009\001\010\001\ +\036\001\037\001\038\001\039\001\082\001\040\001\041\001\042\001\ +\043\001\044\001\045\001\046\001\047\001\048\001\049\001\050\001\ +\082\001\006\001\081\001\083\001\080\001\082\001\076\001\059\001\ +\060\001\061\001\075\001\075\001\064\001\065\001\081\001\075\001\ +\068\001\069\001\075\001\077\001\083\001\073\001\074\001\000\001\ +\076\001\075\001\078\001\082\001\075\001\077\001\082\001\075\001\ +\075\001\079\001\086\001\087\001\088\001\089\001\090\001\091\001\ +\092\001\093\001\094\001\095\001\096\001\097\001\077\001\082\001\ +\077\001\101\001\102\001\103\001\104\001\105\001\106\001\075\001\ +\108\001\081\001\077\001\082\001\112\001\113\001\114\001\115\001\ +\116\001\117\001\118\001\077\001\080\001\082\001\122\001\123\001\ +\000\001\001\001\126\001\003\001\004\001\076\001\006\001\007\001\ +\008\001\009\001\010\001\011\001\012\001\013\001\082\001\075\001\ +\051\001\052\001\053\001\054\001\055\001\056\001\057\001\058\001\ +\059\001\060\001\061\001\062\001\063\001\075\001\065\001\066\001\ +\067\001\075\001\069\001\070\001\071\001\072\001\038\001\039\001\ +\075\001\075\001\002\000\136\000\079\001\080\001\081\001\082\001\ +\083\001\231\001\085\001\207\002\213\002\082\001\004\000\102\002\ +\101\002\006\002\152\000\059\001\060\001\061\001\174\001\176\001\ +\064\001\065\001\175\001\177\001\068\001\069\001\178\001\144\002\ +\031\003\073\001\074\001\119\002\076\001\077\001\078\001\248\001\ +\195\002\044\003\082\001\017\001\119\001\176\000\086\001\087\001\ +\088\001\089\001\090\001\091\001\092\001\093\001\094\001\095\001\ +\096\001\097\001\037\001\039\001\194\001\038\001\040\001\103\001\ +\072\003\105\001\106\001\074\003\108\001\041\001\255\255\092\003\ +\112\001\113\001\255\255\115\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\123\001\255\255\125\001\126\001\000\001\ +\001\001\255\255\003\001\004\001\005\001\006\001\007\001\008\001\ +\009\001\010\001\011\001\012\001\013\001\014\001\015\001\016\001\ +\017\001\018\001\019\001\020\001\255\255\022\001\023\001\024\001\ +\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ +\033\001\034\001\035\001\036\001\037\001\038\001\039\001\150\001\ +\151\001\152\001\153\001\154\001\155\001\156\001\157\001\158\001\ +\159\001\160\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\059\001\060\001\061\001\255\255\255\255\064\001\ +\065\001\255\255\255\255\068\001\069\001\255\255\255\255\255\255\ +\073\001\074\001\255\255\076\001\077\001\078\001\255\255\255\255\ +\255\255\082\001\255\255\255\255\255\255\086\001\087\001\088\001\ +\089\001\090\001\091\001\092\001\093\001\094\001\095\001\096\001\ +\097\001\255\255\255\255\255\255\101\001\102\001\103\001\104\001\ +\105\001\106\001\255\255\108\001\255\255\255\255\111\001\112\001\ +\113\001\114\001\115\001\116\001\117\001\118\001\255\255\255\255\ +\255\255\122\001\123\001\255\255\125\001\000\001\001\001\255\255\ +\003\001\004\001\005\001\006\001\007\001\008\001\009\001\010\001\ \011\001\012\001\013\001\014\001\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ +\019\001\020\001\255\255\022\001\023\001\024\001\025\001\026\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\039\001\040\001\255\255\255\255\ +\035\001\036\001\037\001\038\001\039\001\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\255\255\255\255\255\255\074\001\ -\075\001\255\255\077\001\255\255\079\001\255\255\255\255\255\255\ -\083\001\255\255\255\255\255\255\087\001\088\001\089\001\090\001\ -\091\001\092\001\093\001\255\255\255\255\255\255\097\001\098\001\ -\255\255\255\255\255\255\102\001\103\001\104\001\105\001\106\001\ -\107\001\255\255\109\001\255\255\255\255\255\255\113\001\114\001\ -\115\001\116\001\117\001\118\001\119\001\000\001\255\255\255\255\ -\123\001\124\001\255\255\006\001\007\001\008\001\009\001\010\001\ -\011\001\012\001\013\001\014\001\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ +\059\001\060\001\061\001\255\255\255\255\064\001\065\001\255\255\ +\255\255\068\001\069\001\255\255\255\255\255\255\073\001\074\001\ +\255\255\076\001\077\001\078\001\255\255\255\255\255\255\082\001\ +\255\255\255\255\255\255\086\001\087\001\088\001\089\001\090\001\ +\091\001\092\001\093\001\094\001\095\001\096\001\097\001\255\255\ +\255\255\255\255\101\001\102\001\103\001\104\001\105\001\106\001\ +\255\255\108\001\255\255\255\255\255\255\112\001\113\001\114\001\ +\115\001\116\001\117\001\118\001\255\255\255\255\255\255\122\001\ +\123\001\255\255\125\001\000\001\001\001\255\255\003\001\004\001\ +\005\001\006\001\007\001\008\001\009\001\010\001\011\001\012\001\ +\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\ +\255\255\022\001\023\001\024\001\025\001\026\001\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\034\001\035\001\036\001\ +\037\001\038\001\039\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\005\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\059\001\060\001\ +\061\001\255\255\255\255\064\001\065\001\255\255\255\255\068\001\ +\069\001\255\255\255\255\255\255\073\001\074\001\255\255\076\001\ +\030\001\078\001\255\255\033\001\034\001\082\001\255\255\037\001\ +\255\255\086\001\087\001\088\001\089\001\090\001\091\001\092\001\ +\255\255\255\255\255\255\096\001\097\001\255\255\255\255\255\255\ +\101\001\102\001\103\001\104\001\105\001\106\001\235\002\108\001\ +\255\255\238\002\255\255\112\001\113\001\114\001\115\001\116\001\ +\255\255\255\255\255\255\255\255\249\002\122\001\123\001\255\255\ +\125\001\000\001\001\001\255\255\003\001\004\001\255\255\006\001\ +\007\001\008\001\009\001\010\001\011\001\012\001\013\001\066\001\ +\067\001\255\255\069\001\070\001\255\255\255\255\255\255\101\001\ +\075\001\022\003\255\255\255\255\255\255\080\001\081\001\082\001\ +\083\001\030\003\085\001\032\003\114\001\070\001\116\001\038\001\ +\039\001\255\255\075\001\040\003\255\255\255\255\255\255\080\001\ +\081\001\082\001\083\001\255\255\085\001\255\255\255\255\255\255\ +\053\003\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\119\001\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\255\255\078\001\ +\255\255\255\255\255\255\082\001\255\255\082\003\119\001\086\001\ +\087\001\088\001\089\001\090\001\091\001\092\001\093\001\094\001\ +\095\001\096\001\097\001\255\255\255\255\255\255\255\255\255\255\ +\103\001\255\255\105\001\106\001\255\255\108\001\255\255\255\255\ +\255\255\112\001\113\001\255\255\115\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\255\255\125\001\000\001\ +\001\001\255\255\003\001\004\001\255\255\006\001\007\001\008\001\ +\009\001\010\001\011\001\012\001\013\001\255\255\255\255\051\001\ +\052\001\053\001\054\001\055\001\056\001\057\001\058\001\059\001\ +\060\001\061\001\062\001\063\001\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\071\001\072\001\038\001\039\001\075\001\ +\255\255\255\255\255\255\079\001\080\001\081\001\082\001\083\001\ +\255\255\085\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\059\001\060\001\061\001\255\255\255\255\064\001\ +\065\001\255\255\255\255\068\001\069\001\255\255\255\255\255\255\ +\073\001\074\001\255\255\076\001\255\255\078\001\255\255\255\255\ +\255\255\082\001\255\255\119\001\255\255\086\001\087\001\088\001\ +\089\001\090\001\091\001\092\001\255\255\255\255\255\255\096\001\ +\097\001\255\255\255\255\255\255\255\255\255\255\103\001\255\255\ +\105\001\106\001\255\255\108\001\255\255\255\255\255\255\112\001\ +\113\001\001\001\115\001\255\255\255\255\005\001\006\001\255\255\ +\255\255\255\255\123\001\011\001\125\001\255\255\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\255\255\022\001\023\001\ +\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\001\001\002\001\ +\012\001\255\255\005\001\006\001\255\255\255\255\255\255\255\255\ +\011\001\255\255\255\255\014\001\015\001\016\001\017\001\018\001\ +\019\001\020\001\255\255\022\001\023\001\024\001\025\001\026\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\039\001\040\001\070\001\071\001\ -\255\255\255\255\255\255\255\255\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\255\255\255\255\255\255\074\001\ -\075\001\255\255\077\001\255\255\079\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\120\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\102\001\103\001\255\255\105\001\106\001\ -\107\001\255\255\109\001\255\255\255\255\255\255\113\001\114\001\ -\115\001\255\255\117\001\255\255\000\001\255\255\002\001\255\255\ -\123\001\124\001\006\001\007\001\008\001\009\001\010\001\011\001\ -\012\001\013\001\014\001\015\001\016\001\017\001\018\001\019\001\ -\020\001\021\001\255\255\023\001\024\001\025\001\026\001\027\001\ -\028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ -\036\001\037\001\038\001\039\001\040\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\255\255\069\001\070\001\000\001\001\001\002\001\074\001\075\001\ -\005\001\077\001\007\001\008\001\009\001\010\001\011\001\012\001\ -\013\001\014\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\102\001\103\001\255\255\105\001\106\001\107\001\ -\255\255\109\001\039\001\040\001\255\255\113\001\114\001\115\001\ -\255\255\117\001\255\255\255\255\255\255\255\255\255\255\123\001\ -\124\001\255\255\255\255\255\255\255\255\255\255\255\255\060\001\ -\061\001\062\001\255\255\255\255\065\001\066\001\255\255\255\255\ -\069\001\070\001\255\255\255\255\255\255\074\001\075\001\255\255\ -\077\001\255\255\079\001\255\255\255\255\255\255\083\001\255\255\ -\255\255\255\255\087\001\088\001\089\001\090\001\091\001\092\001\ -\093\001\255\255\255\255\255\255\097\001\098\001\255\255\255\255\ -\255\255\255\255\255\255\104\001\255\255\106\001\107\001\255\255\ -\109\001\255\255\255\255\255\255\113\001\114\001\255\255\116\001\ -\002\001\003\001\255\255\255\255\006\001\007\001\255\255\124\001\ -\255\255\255\255\012\001\255\255\255\255\015\001\016\001\017\001\ -\018\001\019\001\020\001\021\001\255\255\023\001\024\001\025\001\ -\026\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\036\001\037\001\038\001\007\001\255\255\255\255\ -\010\001\255\255\012\001\013\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\006\001\255\255\255\255\255\255\031\001\255\255\255\255\ -\034\001\000\001\255\255\255\255\255\255\039\001\040\001\255\255\ -\007\001\008\001\009\001\010\001\011\001\255\255\013\001\014\001\ -\255\255\083\001\031\001\255\255\255\255\034\001\035\001\255\255\ -\255\255\038\001\060\001\061\001\062\001\255\255\255\255\065\001\ -\066\001\255\255\033\001\069\001\102\001\103\001\104\001\105\001\ -\039\001\040\001\255\255\077\001\255\255\255\255\255\255\255\255\ -\255\255\115\001\255\255\117\001\118\001\119\001\255\255\121\001\ -\122\001\123\001\255\255\093\001\126\001\060\001\061\001\062\001\ -\077\001\255\255\065\001\066\001\255\255\255\255\069\001\070\001\ -\106\001\107\001\255\255\074\001\075\001\000\001\077\001\255\255\ -\255\255\255\255\081\001\255\255\007\001\008\001\009\001\010\001\ -\011\001\102\001\013\001\014\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\115\001\255\255\ -\117\001\255\255\255\255\106\001\107\001\255\255\109\001\255\255\ -\255\255\255\255\113\001\114\001\039\001\040\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\124\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\000\001\255\255\255\255\074\001\ -\075\001\255\255\077\001\007\001\008\001\009\001\010\001\011\001\ -\083\001\013\001\014\001\067\001\068\001\255\255\070\001\071\001\ -\255\255\255\255\255\255\006\001\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\106\001\ -\107\001\255\255\109\001\039\001\040\001\255\255\113\001\114\001\ -\255\255\255\255\255\255\255\255\031\001\255\255\255\255\034\001\ -\035\001\124\001\255\255\038\001\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\120\001\069\001\070\001\255\255\255\255\255\255\074\001\075\001\ -\000\001\077\001\255\255\255\255\255\255\081\001\255\255\007\001\ -\008\001\009\001\010\001\011\001\071\001\013\001\014\001\255\255\ -\255\255\076\001\255\255\078\001\255\255\006\001\081\001\082\001\ -\083\001\084\001\085\001\086\001\255\255\255\255\106\001\107\001\ -\255\255\109\001\255\255\255\255\255\255\113\001\114\001\039\001\ -\040\001\255\255\255\255\102\001\255\255\255\255\031\001\255\255\ -\124\001\034\001\035\001\255\255\255\255\038\001\255\255\255\255\ -\115\001\255\255\117\001\255\255\060\001\061\001\062\001\255\255\ -\255\255\065\001\066\001\255\255\255\255\069\001\070\001\255\255\ -\255\255\255\255\074\001\075\001\000\001\077\001\255\255\255\255\ -\255\255\081\001\255\255\007\001\008\001\009\001\010\001\011\001\ -\255\255\013\001\014\001\076\001\255\255\078\001\255\255\255\255\ -\081\001\082\001\083\001\084\001\085\001\255\255\255\255\255\255\ -\255\255\255\255\106\001\107\001\255\255\109\001\255\255\255\255\ -\255\255\113\001\114\001\039\001\040\001\102\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\124\001\255\255\255\255\255\255\ -\255\255\255\255\115\001\255\255\117\001\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\255\255\069\001\070\001\000\001\255\255\255\255\074\001\075\001\ -\255\255\077\001\007\001\008\001\009\001\010\001\011\001\255\255\ -\013\001\014\001\255\255\255\255\255\255\255\255\000\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\007\001\008\001\009\001\ -\010\001\011\001\255\255\013\001\014\001\255\255\106\001\107\001\ -\255\255\109\001\039\001\040\001\255\255\113\001\114\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\124\001\255\255\255\255\255\255\255\255\039\001\040\001\060\001\ -\061\001\062\001\255\255\255\255\065\001\066\001\255\255\255\255\ -\069\001\070\001\255\255\255\255\255\255\074\001\075\001\255\255\ -\077\001\255\255\060\001\061\001\062\001\255\255\255\255\065\001\ -\066\001\255\255\255\255\069\001\070\001\000\001\255\255\255\255\ -\074\001\075\001\255\255\077\001\007\001\008\001\009\001\010\001\ -\011\001\255\255\013\001\014\001\255\255\106\001\107\001\255\255\ -\109\001\255\255\255\255\255\255\113\001\114\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\124\001\ -\106\001\107\001\255\255\109\001\039\001\040\001\255\255\113\001\ -\114\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\124\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\000\001\255\255\255\255\074\001\ -\075\001\255\255\077\001\007\001\008\001\009\001\010\001\011\001\ -\255\255\013\001\014\001\067\001\068\001\255\255\070\001\071\001\ -\255\255\255\255\255\255\255\255\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\106\001\ -\107\001\255\255\109\001\039\001\040\001\255\255\113\001\114\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\124\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\000\001\ -\120\001\069\001\070\001\255\255\255\255\006\001\074\001\075\001\ -\255\255\077\001\255\255\012\001\255\255\255\255\015\001\016\001\ -\017\001\018\001\019\001\020\001\021\001\255\255\023\001\024\001\ -\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\034\001\035\001\036\001\037\001\038\001\106\001\107\001\ -\255\255\109\001\255\255\255\255\255\255\113\001\114\001\255\255\ +\035\001\036\001\037\001\255\255\255\255\255\255\255\255\051\001\ +\052\001\053\001\054\001\055\001\056\001\057\001\058\001\059\001\ +\060\001\061\001\062\001\063\001\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\071\001\072\001\101\001\102\001\075\001\ +\104\001\255\255\255\255\079\001\080\001\081\001\082\001\083\001\ +\255\255\085\001\114\001\255\255\116\001\255\255\255\255\082\001\ +\255\255\255\255\122\001\255\255\255\255\255\255\126\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\105\001\106\001\255\255\ +\255\255\255\255\101\001\102\001\103\001\104\001\255\255\255\255\ +\255\255\255\255\255\255\119\001\255\255\255\255\255\255\114\001\ +\255\255\116\001\117\001\118\001\255\255\120\001\121\001\122\001\ +\000\001\255\255\125\001\255\255\255\255\005\001\006\001\255\255\ +\255\255\255\255\255\255\011\001\255\255\255\255\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\255\255\022\001\023\001\ +\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\051\001\052\001\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\061\001\075\001\255\255\ +\255\255\255\255\079\001\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\075\001\076\001\255\255\255\255\079\001\ +\255\255\081\001\082\001\083\001\070\001\255\255\255\255\255\255\ +\255\255\075\001\255\255\255\255\255\255\255\255\080\001\081\001\ +\082\001\083\001\255\255\085\001\255\255\101\001\102\001\255\255\ +\104\001\255\255\119\001\255\255\255\255\255\255\255\255\255\255\ +\000\001\255\255\114\001\255\255\116\001\005\001\006\001\255\255\ +\255\255\255\255\122\001\011\001\124\001\255\255\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\119\001\022\001\023\001\ +\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\255\255\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\061\001\075\001\255\255\ +\255\255\255\255\255\255\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\075\001\076\001\255\255\255\255\079\001\ +\255\255\081\001\082\001\083\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\101\001\102\001\255\255\ +\104\001\255\255\119\001\255\255\255\255\255\255\255\255\255\255\ +\000\001\255\255\114\001\255\255\116\001\005\001\006\001\255\255\ +\255\255\255\255\122\001\011\001\124\001\255\255\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\255\255\022\001\023\001\ +\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\255\255\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\061\001\075\001\255\255\ +\255\255\255\255\255\255\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\075\001\076\001\255\255\255\255\079\001\ +\255\255\081\001\082\001\083\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\101\001\102\001\255\255\ +\104\001\255\255\119\001\255\255\255\255\255\255\255\255\255\255\ +\000\001\255\255\114\001\255\255\116\001\005\001\006\001\255\255\ +\255\255\255\255\122\001\011\001\124\001\255\255\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\255\255\022\001\023\001\ +\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\255\255\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\061\001\075\001\255\255\ +\255\255\255\255\255\255\080\001\081\001\082\001\083\001\005\001\ +\085\001\255\255\255\255\075\001\076\001\255\255\255\255\079\001\ +\000\001\081\001\082\001\083\001\255\255\255\255\006\001\007\001\ +\008\001\009\001\010\001\011\001\012\001\013\001\255\255\255\255\ +\030\001\255\255\255\255\033\001\034\001\101\001\102\001\037\001\ +\104\001\255\255\119\001\255\255\255\255\255\255\255\255\255\255\ +\032\001\255\255\114\001\255\255\116\001\255\255\038\001\039\001\ +\040\001\255\255\122\001\255\255\124\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\059\001\060\001\061\001\076\001\255\255\ +\064\001\065\001\255\255\255\255\068\001\069\001\255\255\255\255\ +\255\255\073\001\074\001\075\001\076\001\255\255\078\001\079\001\ +\080\001\081\001\082\001\083\001\255\255\255\255\255\255\101\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\114\001\255\255\116\001\255\255\ +\255\255\105\001\106\001\255\255\108\001\255\255\255\255\255\255\ +\112\001\113\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\000\001\001\001\123\001\124\001\004\001\005\001\006\001\ +\007\001\008\001\009\001\010\001\011\001\012\001\013\001\014\001\ +\015\001\016\001\017\001\018\001\019\001\020\001\255\255\022\001\ +\023\001\024\001\025\001\026\001\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\036\001\037\001\038\001\ +\039\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\124\001\255\255\054\001\055\001\056\001\057\001\058\001\059\001\ -\060\001\061\001\062\001\063\001\064\001\255\255\066\001\067\001\ -\068\001\255\255\070\001\071\001\072\001\073\001\255\255\255\255\ -\076\001\255\255\083\001\255\255\255\255\081\001\082\001\083\001\ -\084\001\255\255\086\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\102\001\103\001\255\255\ -\105\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\115\001\002\001\117\001\118\001\119\001\006\001\ -\007\001\255\255\123\001\010\001\120\001\012\001\255\255\255\255\ -\015\001\016\001\017\001\018\001\019\001\020\001\021\001\255\255\ +\255\255\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\077\001\078\001\ +\255\255\255\255\255\255\082\001\255\255\255\255\255\255\086\001\ +\087\001\088\001\089\001\090\001\091\001\092\001\093\001\094\001\ +\095\001\096\001\097\001\255\255\255\255\255\255\101\001\102\001\ +\103\001\104\001\105\001\106\001\255\255\108\001\255\255\255\255\ +\255\255\112\001\113\001\114\001\115\001\116\001\117\001\118\001\ +\255\255\000\001\001\001\122\001\123\001\004\001\005\001\006\001\ +\007\001\008\001\009\001\010\001\011\001\012\001\013\001\014\001\ +\015\001\016\001\017\001\018\001\019\001\020\001\255\255\022\001\ \023\001\024\001\025\001\026\001\027\001\028\001\029\001\030\001\ \031\001\032\001\033\001\034\001\035\001\036\001\037\001\038\001\ -\255\255\255\255\041\001\042\001\043\001\044\001\045\001\046\001\ -\047\001\048\001\049\001\050\001\051\001\052\001\053\001\054\001\ -\055\001\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ -\063\001\064\001\255\255\066\001\067\001\068\001\255\255\070\001\ -\071\001\072\001\073\001\074\001\075\001\076\001\077\001\078\001\ -\079\001\080\001\081\001\082\001\083\001\084\001\085\001\086\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\093\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\102\001\ -\103\001\255\255\105\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\115\001\255\255\117\001\255\255\ -\255\255\120\001\002\001\003\001\123\001\255\255\006\001\007\001\ -\255\255\255\255\255\255\255\255\012\001\255\255\255\255\015\001\ -\016\001\017\001\018\001\019\001\020\001\021\001\255\255\023\001\ +\039\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\255\255\078\001\ +\255\255\255\255\255\255\082\001\255\255\255\255\255\255\086\001\ +\087\001\088\001\089\001\090\001\091\001\092\001\255\255\255\255\ +\255\255\096\001\097\001\255\255\255\255\255\255\101\001\102\001\ +\103\001\104\001\105\001\106\001\255\255\108\001\255\255\255\255\ +\255\255\112\001\113\001\114\001\115\001\116\001\117\001\118\001\ +\000\001\255\255\255\255\122\001\123\001\005\001\006\001\007\001\ +\008\001\009\001\010\001\011\001\012\001\013\001\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\255\255\022\001\023\001\ \024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ -\032\001\033\001\034\001\035\001\036\001\037\001\038\001\002\001\ -\255\255\255\255\255\255\006\001\255\255\255\255\255\255\255\255\ -\255\255\012\001\255\255\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\255\255\255\255\255\255\054\001\ -\055\001\056\001\057\001\058\001\059\001\060\001\061\001\255\255\ -\255\255\255\255\255\255\066\001\067\001\068\001\255\255\070\001\ -\071\001\072\001\073\001\255\255\255\255\076\001\102\001\103\001\ -\104\001\105\001\081\001\082\001\083\001\084\001\255\255\086\001\ -\255\255\255\255\255\255\115\001\079\001\117\001\118\001\119\001\ -\255\255\121\001\122\001\123\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\102\001\103\001\255\255\105\001\255\255\ -\255\255\120\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\115\001\255\255\117\001\006\001\007\001\255\255\255\255\255\255\ -\123\001\012\001\255\255\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\255\255\255\255\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\255\255\255\255\ -\255\255\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\062\001\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\255\255\ -\255\255\255\255\077\001\255\255\255\255\255\255\255\255\082\001\ -\083\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\102\001\103\001\255\255\105\001\255\255\ -\120\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\115\001\255\255\117\001\255\255\255\255\255\255\255\255\255\255\ -\123\001\255\255\125\001\006\001\007\001\008\001\009\001\010\001\ -\011\001\012\001\013\001\014\001\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\039\001\040\001\255\255\255\255\ +\032\001\033\001\034\001\035\001\036\001\037\001\038\001\039\001\ +\069\001\070\001\255\255\255\255\255\255\255\255\075\001\255\255\ +\255\255\255\255\255\255\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\059\001\060\001\061\001\255\255\255\255\ +\064\001\065\001\255\255\255\255\068\001\069\001\255\255\069\001\ +\070\001\073\001\074\001\255\255\076\001\075\001\078\001\255\255\ +\255\255\255\255\080\001\081\001\082\001\083\001\255\255\085\001\ +\255\255\255\255\119\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\101\001\102\001\255\255\ +\104\001\105\001\106\001\255\255\108\001\255\255\255\255\255\255\ +\112\001\113\001\114\001\255\255\116\001\255\255\255\255\000\001\ +\001\001\119\001\122\001\123\001\005\001\006\001\007\001\008\001\ +\009\001\010\001\011\001\012\001\013\001\014\001\015\001\016\001\ +\017\001\018\001\019\001\020\001\255\255\022\001\023\001\024\001\ +\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ +\033\001\034\001\035\001\036\001\037\001\038\001\039\001\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\255\255\255\255\255\255\074\001\ -\075\001\255\255\077\001\255\255\007\001\008\001\009\001\010\001\ -\011\001\012\001\013\001\014\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\102\001\103\001\255\255\105\001\106\001\ -\107\001\255\255\109\001\255\255\039\001\040\001\113\001\114\001\ -\115\001\255\255\117\001\255\255\255\255\255\255\255\255\255\255\ -\123\001\124\001\053\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\255\255\255\255\065\001\066\001\ -\255\255\255\255\069\001\070\001\255\255\255\255\255\255\074\001\ -\075\001\255\255\077\001\255\255\079\001\080\001\255\255\066\001\ -\067\001\068\001\255\255\070\001\071\001\255\255\255\255\255\255\ -\255\255\076\001\255\255\255\255\255\255\255\255\081\001\082\001\ -\083\001\084\001\255\255\086\001\255\255\255\255\255\255\106\001\ -\107\001\255\255\109\001\255\255\255\255\255\255\113\001\114\001\ -\255\255\255\255\255\255\255\255\255\255\006\001\255\255\255\255\ -\255\255\124\001\125\001\012\001\013\001\255\255\015\001\016\001\ -\017\001\018\001\019\001\020\001\021\001\120\001\023\001\024\001\ -\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\034\001\035\001\036\001\037\001\038\001\006\001\255\255\ -\255\255\255\255\255\255\255\255\012\001\255\255\255\255\015\001\ -\016\001\017\001\018\001\019\001\020\001\021\001\255\255\023\001\ -\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ -\032\001\033\001\034\001\035\001\036\001\037\001\038\001\066\001\ -\067\001\068\001\255\255\070\001\071\001\255\255\255\255\255\255\ -\255\255\076\001\255\255\255\255\255\255\255\255\081\001\082\001\ -\083\001\084\001\255\255\086\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\102\001\103\001\255\255\ -\105\001\106\001\107\001\255\255\255\255\077\001\255\255\255\255\ -\255\255\255\255\115\001\255\255\117\001\085\001\255\255\255\255\ -\255\255\255\255\123\001\255\255\255\255\120\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\102\001\103\001\ -\255\255\105\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\115\001\006\001\117\001\255\255\255\255\ -\255\255\255\255\012\001\123\001\255\255\015\001\016\001\017\001\ -\018\001\019\001\020\001\021\001\255\255\023\001\024\001\025\001\ +\255\255\255\255\059\001\060\001\061\001\255\255\255\255\064\001\ +\065\001\255\255\255\255\068\001\069\001\255\255\000\001\001\001\ +\073\001\074\001\004\001\076\001\006\001\007\001\008\001\009\001\ +\010\001\011\001\012\001\013\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\102\001\255\255\104\001\ +\105\001\106\001\255\255\108\001\038\001\039\001\255\255\112\001\ +\113\001\114\001\255\255\116\001\255\255\255\255\255\255\255\255\ +\255\255\122\001\123\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\059\001\060\001\061\001\255\255\255\255\064\001\065\001\ +\255\255\255\255\068\001\069\001\255\255\255\255\255\255\073\001\ +\074\001\255\255\076\001\255\255\078\001\255\255\255\255\255\255\ +\082\001\255\255\255\255\255\255\086\001\087\001\088\001\089\001\ +\090\001\091\001\092\001\255\255\255\255\255\255\096\001\097\001\ +\255\255\255\255\255\255\255\255\255\255\103\001\255\255\105\001\ +\106\001\255\255\108\001\255\255\255\255\255\255\112\001\113\001\ +\006\001\115\001\255\255\009\001\000\001\011\001\012\001\255\255\ +\255\255\123\001\006\001\007\001\008\001\009\001\010\001\255\255\ +\012\001\013\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\030\001\255\255\255\255\033\001\255\255\255\255\255\255\255\255\ +\038\001\039\001\255\255\255\255\032\001\255\255\255\255\255\255\ +\255\255\255\255\038\001\039\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\059\001\060\001\061\001\ +\255\255\255\255\064\001\065\001\255\255\255\255\068\001\059\001\ +\060\001\061\001\255\255\255\255\064\001\065\001\076\001\255\255\ +\068\001\069\001\255\255\255\255\255\255\073\001\074\001\255\255\ +\076\001\000\001\255\255\255\255\080\001\255\255\092\001\006\001\ +\007\001\008\001\009\001\010\001\255\255\012\001\013\001\255\255\ +\005\001\255\255\255\255\105\001\106\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\105\001\106\001\255\255\ +\108\001\119\001\255\255\255\255\112\001\113\001\255\255\038\001\ +\039\001\030\001\255\255\255\255\033\001\034\001\255\255\123\001\ +\037\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\000\001\255\255\073\001\074\001\255\255\076\001\006\001\007\001\ +\008\001\009\001\010\001\082\001\012\001\013\001\075\001\255\255\ +\077\001\255\255\255\255\080\001\081\001\082\001\083\001\084\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\105\001\106\001\255\255\108\001\038\001\039\001\ +\101\001\112\001\113\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\114\001\255\255\116\001\ +\255\255\255\255\255\255\059\001\060\001\061\001\255\255\255\255\ +\064\001\065\001\255\255\255\255\068\001\069\001\255\255\255\255\ +\255\255\073\001\074\001\255\255\076\001\000\001\255\255\255\255\ +\080\001\255\255\255\255\006\001\007\001\008\001\009\001\010\001\ +\255\255\012\001\013\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\005\001\255\255\255\255\255\255\ +\255\255\105\001\106\001\255\255\108\001\255\255\255\255\255\255\ +\112\001\113\001\255\255\038\001\039\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\123\001\255\255\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\059\001\060\001\061\001\255\255\255\255\064\001\065\001\255\255\ +\255\255\068\001\069\001\255\255\255\255\255\255\073\001\074\001\ +\255\255\076\001\000\001\255\255\255\255\080\001\255\255\255\255\ +\006\001\007\001\008\001\009\001\010\001\070\001\012\001\013\001\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\255\255\105\001\106\001\ +\255\255\108\001\255\255\255\255\255\255\112\001\113\001\255\255\ +\038\001\039\001\255\255\255\255\101\001\255\255\255\255\255\255\ +\123\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\255\255\059\001\060\001\061\001\ +\255\255\255\255\064\001\065\001\255\255\255\255\068\001\069\001\ +\255\255\000\001\255\255\073\001\074\001\255\255\076\001\006\001\ +\007\001\008\001\009\001\010\001\255\255\012\001\013\001\255\255\ +\255\255\255\255\255\255\255\255\000\001\255\255\255\255\255\255\ +\255\255\255\255\006\001\007\001\008\001\009\001\010\001\255\255\ +\012\001\013\001\255\255\105\001\106\001\255\255\108\001\038\001\ +\039\001\255\255\112\001\113\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\123\001\255\255\255\255\ +\255\255\255\255\038\001\039\001\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\255\255\059\001\ +\060\001\061\001\255\255\255\255\064\001\065\001\255\255\255\255\ +\068\001\069\001\255\255\000\001\255\255\073\001\074\001\255\255\ +\076\001\006\001\007\001\008\001\009\001\010\001\255\255\012\001\ +\013\001\255\255\105\001\106\001\255\255\108\001\000\001\255\255\ +\255\255\112\001\113\001\255\255\006\001\007\001\008\001\009\001\ +\010\001\255\255\012\001\013\001\123\001\105\001\106\001\255\255\ +\108\001\038\001\039\001\255\255\112\001\113\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\123\001\ +\255\255\255\255\255\255\255\255\038\001\039\001\059\001\060\001\ +\061\001\255\255\255\255\064\001\065\001\255\255\255\255\068\001\ +\069\001\255\255\255\255\255\255\073\001\074\001\255\255\076\001\ +\255\255\059\001\060\001\061\001\255\255\066\001\064\001\065\001\ +\069\001\070\001\068\001\069\001\255\255\255\255\075\001\073\001\ +\074\001\255\255\076\001\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\255\255\105\001\106\001\255\255\108\001\ +\255\255\255\255\255\255\112\001\113\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\123\001\105\001\ +\106\001\255\255\108\001\255\255\000\001\255\255\112\001\113\001\ +\255\255\005\001\119\001\255\255\255\255\255\255\255\255\011\001\ +\255\255\123\001\014\001\015\001\016\001\017\001\018\001\019\001\ +\020\001\255\255\022\001\023\001\024\001\025\001\026\001\027\001\ +\028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ +\036\001\037\001\255\255\053\001\054\001\055\001\056\001\057\001\ +\058\001\059\001\060\001\255\255\255\255\255\255\255\255\065\001\ +\066\001\067\001\255\255\069\001\070\001\071\001\072\001\255\255\ +\255\255\075\001\255\255\255\255\255\255\255\255\080\001\081\001\ +\082\001\083\001\255\255\085\001\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\255\255\255\255\255\255\082\001\075\001\ +\255\255\255\255\255\255\255\255\080\001\081\001\082\001\083\001\ +\255\255\085\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\101\001\102\001\255\255\104\001\119\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\114\001\001\001\ +\116\001\117\001\118\001\005\001\006\001\255\255\122\001\009\001\ +\255\255\011\001\255\255\119\001\014\001\015\001\016\001\017\001\ +\018\001\019\001\020\001\255\255\022\001\023\001\024\001\025\001\ \026\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\036\001\037\001\038\001\006\001\007\001\255\255\ -\255\255\255\255\255\255\012\001\255\255\255\255\015\001\016\001\ -\017\001\018\001\019\001\020\001\021\001\255\255\023\001\024\001\ -\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\034\001\035\001\036\001\037\001\038\001\255\255\255\255\ -\255\255\255\255\076\001\077\001\255\255\054\001\055\001\056\001\ -\057\001\058\001\059\001\060\001\061\001\255\255\255\255\255\255\ -\255\255\066\001\067\001\068\001\255\255\070\001\071\001\072\001\ -\073\001\255\255\255\255\076\001\102\001\103\001\255\255\105\001\ -\081\001\082\001\083\001\084\001\255\255\086\001\255\255\255\255\ -\255\255\115\001\255\255\117\001\255\255\255\255\255\255\255\255\ -\255\255\123\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\102\001\103\001\255\255\ -\105\001\255\255\255\255\255\255\255\255\255\255\255\255\120\001\ -\255\255\255\255\115\001\006\001\117\001\255\255\255\255\255\255\ -\255\255\012\001\123\001\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ +\034\001\035\001\036\001\037\001\255\255\255\255\040\001\041\001\ +\042\001\043\001\044\001\045\001\046\001\047\001\048\001\049\001\ +\050\001\051\001\052\001\053\001\054\001\055\001\056\001\057\001\ +\058\001\059\001\060\001\061\001\062\001\063\001\255\255\065\001\ +\066\001\067\001\255\255\069\001\070\001\071\001\072\001\073\001\ +\074\001\075\001\076\001\077\001\078\001\079\001\080\001\081\001\ +\082\001\083\001\084\001\085\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\092\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\101\001\102\001\255\255\104\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\114\001\255\255\116\001\255\255\255\255\119\001\001\001\002\001\ +\122\001\255\255\005\001\006\001\255\255\255\255\255\255\255\255\ +\011\001\255\255\255\255\014\001\015\001\016\001\017\001\018\001\ +\019\001\020\001\255\255\022\001\023\001\024\001\025\001\026\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\006\001\255\255\255\255\255\255\ -\255\255\255\255\012\001\255\255\255\255\015\001\016\001\017\001\ -\018\001\019\001\020\001\021\001\255\255\023\001\024\001\025\001\ -\026\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\036\001\037\001\038\001\255\255\255\255\255\255\ -\255\255\255\255\077\001\255\255\054\001\055\001\056\001\057\001\ -\058\001\059\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\066\001\067\001\068\001\255\255\070\001\071\001\072\001\073\001\ -\255\255\255\255\076\001\102\001\103\001\255\255\105\001\081\001\ -\082\001\083\001\084\001\255\255\086\001\255\255\255\255\255\255\ -\115\001\255\255\117\001\085\001\255\255\255\255\255\255\255\255\ -\123\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\102\001\103\001\255\255\105\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\120\001\255\255\ -\255\255\115\001\006\001\117\001\255\255\255\255\255\255\255\255\ -\012\001\123\001\255\255\015\001\016\001\017\001\018\001\019\001\ -\020\001\021\001\255\255\023\001\024\001\025\001\026\001\027\001\ +\035\001\036\001\037\001\001\001\255\255\255\255\255\255\005\001\ +\255\255\255\255\255\255\255\255\255\255\011\001\255\255\255\255\ +\014\001\015\001\016\001\017\001\018\001\019\001\020\001\255\255\ +\022\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ +\255\255\255\255\255\255\053\001\054\001\055\001\056\001\057\001\ +\058\001\059\001\060\001\255\255\255\255\255\255\255\255\065\001\ +\066\001\067\001\255\255\069\001\070\001\071\001\072\001\255\255\ +\255\255\075\001\101\001\102\001\103\001\104\001\080\001\081\001\ +\082\001\083\001\255\255\085\001\255\255\255\255\255\255\114\001\ +\078\001\116\001\117\001\118\001\255\255\120\001\121\001\122\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\101\001\ +\102\001\255\255\104\001\255\255\255\255\119\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\114\001\255\255\116\001\005\001\ +\006\001\255\255\255\255\255\255\122\001\011\001\255\255\255\255\ +\014\001\015\001\016\001\017\001\018\001\019\001\020\001\255\255\ +\022\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ +\255\255\255\255\053\001\054\001\055\001\056\001\057\001\058\001\ +\059\001\060\001\255\255\255\255\255\255\255\255\065\001\066\001\ +\067\001\255\255\069\001\070\001\071\001\072\001\255\255\061\001\ +\075\001\255\255\255\255\255\255\255\255\080\001\081\001\082\001\ +\083\001\255\255\085\001\255\255\255\255\255\255\076\001\255\255\ +\255\255\255\255\255\255\081\001\082\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\101\001\ +\102\001\255\255\104\001\255\255\119\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\114\001\255\255\116\001\255\255\ +\255\255\255\255\255\255\255\255\122\001\255\255\124\001\005\001\ +\006\001\007\001\008\001\009\001\010\001\011\001\012\001\013\001\ +\014\001\015\001\016\001\017\001\018\001\019\001\020\001\255\255\ +\022\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ +\038\001\039\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\059\001\060\001\061\001\ +\255\255\255\255\064\001\065\001\255\255\255\255\068\001\069\001\ +\255\255\255\255\255\255\073\001\074\001\255\255\076\001\255\255\ +\006\001\007\001\008\001\009\001\010\001\011\001\012\001\013\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\101\001\ +\102\001\255\255\104\001\105\001\106\001\255\255\108\001\255\255\ +\038\001\039\001\112\001\113\001\114\001\255\255\116\001\255\255\ +\255\255\255\255\255\255\255\255\122\001\123\001\052\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\059\001\060\001\061\001\ +\255\255\255\255\064\001\065\001\255\255\255\255\068\001\069\001\ +\255\255\255\255\255\255\073\001\074\001\255\255\076\001\255\255\ +\078\001\079\001\255\255\065\001\066\001\067\001\255\255\069\001\ +\070\001\255\255\255\255\255\255\255\255\075\001\255\255\255\255\ +\255\255\255\255\080\001\081\001\082\001\083\001\255\255\085\001\ +\255\255\255\255\255\255\105\001\106\001\255\255\108\001\255\255\ +\255\255\255\255\112\001\113\001\255\255\255\255\255\255\255\255\ +\255\255\005\001\255\255\255\255\255\255\123\001\124\001\011\001\ +\012\001\255\255\014\001\015\001\016\001\017\001\018\001\019\001\ +\020\001\119\001\022\001\023\001\024\001\025\001\026\001\027\001\ \028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ -\036\001\037\001\038\001\006\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\015\001\016\001\017\001\018\001\ -\019\001\020\001\021\001\255\255\023\001\024\001\025\001\026\001\ +\036\001\037\001\005\001\255\255\255\255\255\255\255\255\255\255\ +\011\001\255\255\255\255\014\001\015\001\016\001\017\001\018\001\ +\019\001\020\001\255\255\022\001\023\001\024\001\025\001\026\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\036\001\037\001\038\001\067\001\255\255\255\255\070\001\ -\071\001\255\255\255\255\255\255\255\255\076\001\255\255\255\255\ -\255\255\255\255\081\001\082\001\083\001\084\001\255\255\086\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\102\001\103\001\255\255\105\001\255\255\007\001\ -\008\001\009\001\010\001\011\001\255\255\013\001\014\001\115\001\ -\255\255\117\001\255\255\255\255\255\255\255\255\255\255\123\001\ -\255\255\120\001\255\255\255\255\067\001\255\255\255\255\070\001\ -\071\001\255\255\255\255\102\001\103\001\076\001\105\001\039\001\ -\040\001\041\001\081\001\082\001\083\001\084\001\255\255\086\001\ -\115\001\255\255\117\001\255\255\255\255\255\255\255\255\255\255\ -\123\001\255\255\255\255\255\255\060\001\061\001\062\001\255\255\ -\255\255\065\001\066\001\255\255\255\255\069\001\070\001\255\255\ -\255\255\255\255\074\001\075\001\255\255\077\001\255\255\079\001\ -\255\255\120\001\255\255\007\001\008\001\009\001\010\001\011\001\ -\255\255\013\001\014\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\106\001\107\001\255\255\109\001\255\255\255\255\ -\255\255\113\001\114\001\039\001\040\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\124\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\255\255\069\001\070\001\255\255\255\255\255\255\074\001\075\001\ -\255\255\077\001\255\255\079\001\255\255\255\255\255\255\007\001\ -\008\001\009\001\010\001\011\001\255\255\013\001\014\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\106\001\107\001\ -\255\255\109\001\255\255\255\255\255\255\113\001\114\001\039\001\ -\040\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\124\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\060\001\061\001\062\001\255\255\ -\255\255\065\001\066\001\255\255\255\255\069\001\070\001\255\255\ -\255\255\255\255\074\001\075\001\255\255\077\001\255\255\079\001\ -\255\255\255\255\255\255\007\001\008\001\009\001\010\001\011\001\ -\255\255\013\001\014\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\106\001\107\001\255\255\109\001\255\255\255\255\ -\255\255\113\001\114\001\039\001\040\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\124\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\255\255\069\001\070\001\255\255\255\255\255\255\074\001\075\001\ -\255\255\077\001\255\255\079\001\255\255\255\255\255\255\007\001\ -\008\001\009\001\010\001\011\001\255\255\013\001\014\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\106\001\107\001\ -\255\255\109\001\255\255\255\255\255\255\113\001\114\001\039\001\ -\040\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\124\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\060\001\061\001\062\001\255\255\ -\255\255\065\001\066\001\255\255\255\255\069\001\070\001\255\255\ -\255\255\255\255\074\001\075\001\255\255\077\001\007\001\008\001\ -\009\001\010\001\011\001\255\255\013\001\014\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\007\001\008\001\009\001\010\001\011\001\255\255\013\001\ -\014\001\255\255\106\001\107\001\255\255\109\001\039\001\040\001\ -\255\255\113\001\114\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\124\001\255\255\255\255\255\255\ -\255\255\039\001\040\001\060\001\061\001\062\001\255\255\255\255\ -\065\001\066\001\255\255\255\255\069\001\070\001\255\255\255\255\ -\255\255\074\001\075\001\255\255\077\001\255\255\060\001\061\001\ -\062\001\255\255\255\255\065\001\066\001\255\255\255\255\069\001\ -\070\001\255\255\255\255\255\255\074\001\075\001\255\255\077\001\ -\007\001\008\001\009\001\010\001\011\001\255\255\013\001\014\001\ -\255\255\106\001\107\001\255\255\109\001\255\255\255\255\255\255\ -\113\001\114\001\255\255\007\001\008\001\009\001\010\001\011\001\ -\255\255\013\001\014\001\124\001\106\001\107\001\255\255\109\001\ -\039\001\040\001\255\255\113\001\114\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\124\001\255\255\ -\255\255\255\255\255\255\039\001\040\001\060\001\061\001\062\001\ -\255\255\255\255\065\001\066\001\255\255\255\255\069\001\070\001\ -\255\255\255\255\255\255\074\001\075\001\255\255\077\001\255\255\ -\060\001\061\001\062\001\255\255\255\255\065\001\066\001\255\255\ -\255\255\069\001\070\001\255\255\255\255\255\255\074\001\075\001\ -\255\255\077\001\007\001\008\001\009\001\010\001\011\001\255\255\ -\013\001\014\001\255\255\106\001\107\001\255\255\109\001\255\255\ -\255\255\255\255\113\001\114\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\124\001\106\001\107\001\ -\255\255\109\001\039\001\040\001\255\255\113\001\114\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\124\001\255\255\255\255\255\255\255\255\255\255\255\255\060\001\ -\061\001\062\001\255\255\255\255\065\001\066\001\255\255\255\255\ -\069\001\070\001\255\255\255\255\255\255\074\001\075\001\255\255\ -\077\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\006\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\106\001\107\001\255\255\ -\109\001\255\255\255\255\255\255\113\001\114\001\031\001\255\255\ -\255\255\034\001\035\001\255\255\255\255\038\001\255\255\124\001\ -\041\001\042\001\043\001\044\001\045\001\046\001\047\001\048\001\ -\049\001\050\001\051\001\052\001\053\001\054\001\055\001\056\001\ -\057\001\058\001\059\001\060\001\061\001\062\001\063\001\064\001\ -\255\255\066\001\067\001\068\001\255\255\070\001\071\001\072\001\ -\073\001\074\001\075\001\076\001\077\001\078\001\255\255\080\001\ -\081\001\082\001\083\001\084\001\085\001\086\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\006\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\102\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\115\001\255\255\117\001\031\001\255\255\120\001\ -\034\001\035\001\255\255\255\255\038\001\255\255\255\255\041\001\ -\042\001\043\001\044\001\045\001\046\001\047\001\048\001\049\001\ -\050\001\051\001\255\255\255\255\054\001\055\001\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ -\066\001\067\001\068\001\255\255\070\001\071\001\072\001\073\001\ -\255\255\255\255\076\001\255\255\078\001\255\255\255\255\081\001\ -\082\001\083\001\084\001\085\001\086\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\006\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\102\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\115\001\255\255\117\001\031\001\255\255\120\001\034\001\ -\035\001\255\255\255\255\038\001\255\255\255\255\041\001\042\001\ -\043\001\044\001\045\001\046\001\047\001\048\001\049\001\050\001\ -\051\001\255\255\255\255\054\001\055\001\056\001\057\001\058\001\ -\059\001\060\001\061\001\062\001\063\001\064\001\255\255\066\001\ -\067\001\068\001\255\255\070\001\071\001\072\001\073\001\255\255\ -\255\255\076\001\255\255\078\001\255\255\255\255\081\001\082\001\ -\083\001\084\001\085\001\086\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\006\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\102\001\255\255\255\255\255\255\255\255\ +\035\001\036\001\037\001\066\001\067\001\255\255\069\001\070\001\ +\255\255\255\255\255\255\255\255\075\001\255\255\255\255\255\255\ +\255\255\080\001\081\001\082\001\083\001\255\255\085\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\101\001\102\001\255\255\104\001\105\001\106\001\255\255\ +\255\255\076\001\255\255\255\255\255\255\255\255\114\001\255\255\ +\116\001\084\001\255\255\255\255\255\255\255\255\122\001\255\255\ +\119\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\101\001\102\001\255\255\104\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\114\001\ +\005\001\116\001\255\255\255\255\255\255\255\255\011\001\122\001\ +\255\255\014\001\015\001\016\001\017\001\018\001\019\001\020\001\ +\255\255\022\001\023\001\024\001\025\001\026\001\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\034\001\035\001\036\001\ +\037\001\005\001\006\001\255\255\255\255\255\255\255\255\011\001\ +\255\255\255\255\014\001\015\001\016\001\017\001\018\001\019\001\ +\020\001\255\255\022\001\023\001\024\001\025\001\026\001\027\001\ +\028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ +\036\001\037\001\255\255\255\255\255\255\255\255\075\001\076\001\ +\255\255\053\001\054\001\055\001\056\001\057\001\058\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\071\001\072\001\255\255\255\255\075\001\ +\101\001\102\001\255\255\104\001\080\001\081\001\082\001\083\001\ +\255\255\085\001\255\255\255\255\255\255\114\001\255\255\116\001\ +\255\255\255\255\255\255\255\255\255\255\122\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\101\001\102\001\255\255\104\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\119\001\255\255\255\255\114\001\005\001\ +\116\001\255\255\255\255\255\255\255\255\011\001\122\001\255\255\ +\014\001\015\001\016\001\017\001\018\001\019\001\020\001\255\255\ +\022\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ +\005\001\255\255\255\255\255\255\255\255\255\255\011\001\255\255\ +\255\255\014\001\015\001\016\001\017\001\018\001\019\001\020\001\ +\255\255\022\001\023\001\024\001\025\001\026\001\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\034\001\035\001\036\001\ +\037\001\255\255\255\255\255\255\255\255\255\255\076\001\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\255\255\075\001\101\001\ +\102\001\255\255\104\001\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\255\255\114\001\255\255\116\001\084\001\ +\255\255\255\255\255\255\255\255\122\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\101\001\102\001\255\255\104\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\119\001\255\255\255\255\114\001\005\001\116\001\ +\255\255\255\255\255\255\255\255\011\001\122\001\255\255\014\001\ +\015\001\016\001\017\001\018\001\019\001\020\001\255\255\022\001\ +\023\001\024\001\025\001\026\001\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\036\001\037\001\005\001\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\115\001\255\255\117\001\031\001\255\255\120\001\034\001\035\001\ -\255\255\255\255\038\001\255\255\255\255\041\001\042\001\043\001\ -\044\001\045\001\046\001\047\001\048\001\049\001\050\001\051\001\ -\255\255\255\255\054\001\055\001\056\001\057\001\058\001\059\001\ -\060\001\061\001\062\001\063\001\064\001\255\255\066\001\067\001\ -\068\001\255\255\070\001\071\001\072\001\073\001\255\255\255\255\ -\076\001\255\255\078\001\255\255\255\255\081\001\082\001\083\001\ -\084\001\085\001\086\001\007\001\255\255\255\255\010\001\255\255\ +\014\001\015\001\016\001\017\001\018\001\019\001\020\001\255\255\ +\022\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ +\066\001\255\255\255\255\069\001\070\001\255\255\255\255\255\255\ +\255\255\075\001\255\255\255\255\255\255\255\255\080\001\081\001\ +\082\001\083\001\255\255\085\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\101\001\102\001\ +\255\255\104\001\255\255\006\001\007\001\008\001\009\001\010\001\ +\255\255\012\001\013\001\114\001\255\255\116\001\255\255\255\255\ +\255\255\255\255\255\255\122\001\255\255\119\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\101\001\ +\102\001\255\255\104\001\038\001\039\001\040\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\114\001\255\255\116\001\255\255\ +\255\255\255\255\255\255\255\255\122\001\255\255\255\255\255\255\ +\059\001\060\001\061\001\255\255\255\255\064\001\065\001\255\255\ +\255\255\068\001\069\001\255\255\255\255\255\255\073\001\074\001\ +\255\255\076\001\255\255\078\001\255\255\255\255\255\255\006\001\ +\007\001\008\001\009\001\010\001\255\255\012\001\013\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\105\001\106\001\ +\255\255\108\001\255\255\255\255\255\255\112\001\113\001\038\001\ +\039\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\255\255\078\001\ +\255\255\255\255\255\255\006\001\007\001\008\001\009\001\010\001\ +\255\255\012\001\013\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\105\001\106\001\255\255\108\001\255\255\255\255\ +\255\255\112\001\113\001\038\001\039\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\059\001\060\001\061\001\255\255\255\255\064\001\065\001\255\255\ +\255\255\068\001\069\001\255\255\255\255\255\255\073\001\074\001\ +\255\255\076\001\255\255\078\001\255\255\255\255\255\255\006\001\ +\007\001\008\001\009\001\010\001\255\255\012\001\013\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\105\001\106\001\ +\255\255\108\001\255\255\255\255\255\255\112\001\113\001\038\001\ +\039\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\255\255\078\001\ +\255\255\255\255\255\255\006\001\007\001\008\001\009\001\010\001\ +\255\255\012\001\013\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\105\001\106\001\255\255\108\001\255\255\255\255\ +\255\255\112\001\113\001\038\001\039\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\059\001\060\001\061\001\255\255\255\255\064\001\065\001\255\255\ +\255\255\068\001\069\001\255\255\255\255\255\255\073\001\074\001\ +\255\255\076\001\006\001\007\001\008\001\009\001\010\001\255\255\ \012\001\013\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\102\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\031\001\255\255\255\255\034\001\115\001\ -\255\255\117\001\255\255\255\255\120\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\006\001\007\001\008\001\ +\009\001\010\001\255\255\012\001\013\001\255\255\105\001\106\001\ +\255\255\108\001\038\001\039\001\255\255\112\001\113\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\255\255\255\255\255\255\255\255\038\001\039\001\059\001\ +\060\001\061\001\255\255\255\255\064\001\065\001\255\255\255\255\ +\068\001\069\001\255\255\255\255\255\255\073\001\074\001\255\255\ +\076\001\255\255\059\001\060\001\061\001\255\255\255\255\064\001\ +\065\001\255\255\255\255\068\001\069\001\255\255\255\255\255\255\ +\073\001\074\001\255\255\076\001\006\001\007\001\008\001\009\001\ +\010\001\255\255\012\001\013\001\255\255\105\001\106\001\255\255\ +\108\001\255\255\255\255\255\255\112\001\113\001\255\255\006\001\ +\007\001\008\001\009\001\010\001\255\255\012\001\013\001\123\001\ +\105\001\106\001\255\255\108\001\038\001\039\001\255\255\112\001\ +\113\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\123\001\255\255\255\255\255\255\255\255\038\001\ +\039\001\059\001\060\001\061\001\255\255\255\255\064\001\065\001\ +\255\255\255\255\068\001\069\001\255\255\255\255\255\255\073\001\ +\074\001\255\255\076\001\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\255\255\255\255\068\001\069\001\255\255\ +\255\255\255\255\073\001\074\001\255\255\076\001\006\001\007\001\ +\008\001\009\001\010\001\255\255\012\001\013\001\255\255\105\001\ +\106\001\255\255\108\001\255\255\255\255\255\255\112\001\113\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\123\001\105\001\106\001\255\255\108\001\038\001\039\001\ +\255\255\112\001\113\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\059\001\060\001\061\001\255\255\255\255\ +\064\001\065\001\255\255\255\255\068\001\069\001\255\255\255\255\ +\255\255\073\001\074\001\255\255\076\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\005\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\105\001\106\001\255\255\108\001\255\255\255\255\255\255\ +\112\001\113\001\030\001\255\255\255\255\033\001\034\001\255\255\ +\255\255\037\001\255\255\123\001\040\001\041\001\042\001\043\001\ +\044\001\045\001\046\001\047\001\048\001\049\001\050\001\051\001\ \052\001\053\001\054\001\055\001\056\001\057\001\058\001\059\001\ -\060\001\061\001\062\001\063\001\064\001\255\255\066\001\067\001\ -\068\001\255\255\070\001\071\001\072\001\073\001\255\255\255\255\ -\076\001\077\001\255\255\255\255\080\001\081\001\082\001\083\001\ -\084\001\007\001\086\001\255\255\010\001\255\255\012\001\013\001\ -\255\255\093\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\106\001\107\001\ -\255\255\031\001\255\255\255\255\034\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\120\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\052\001\053\001\ +\060\001\061\001\062\001\063\001\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\071\001\072\001\073\001\074\001\075\001\ +\076\001\077\001\255\255\079\001\080\001\081\001\082\001\083\001\ +\084\001\085\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\005\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\101\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\114\001\255\255\ +\116\001\030\001\255\255\119\001\033\001\034\001\255\255\255\255\ +\037\001\255\255\255\255\040\001\041\001\042\001\043\001\044\001\ +\045\001\046\001\047\001\048\001\049\001\050\001\255\255\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\255\255\075\001\255\255\ +\077\001\255\255\255\255\080\001\081\001\082\001\083\001\084\001\ +\085\001\255\255\255\255\255\255\255\255\255\255\255\255\005\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\101\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\114\001\255\255\116\001\ +\030\001\255\255\119\001\033\001\034\001\255\255\255\255\037\001\ +\255\255\255\255\040\001\041\001\042\001\043\001\044\001\045\001\ +\046\001\047\001\048\001\049\001\050\001\255\255\255\255\053\001\ \054\001\055\001\056\001\057\001\058\001\059\001\060\001\061\001\ -\062\001\063\001\064\001\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\072\001\073\001\255\255\255\255\076\001\077\001\ -\255\255\255\255\080\001\081\001\082\001\083\001\084\001\007\001\ -\086\001\255\255\010\001\255\255\012\001\013\001\255\255\093\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\106\001\107\001\255\255\031\001\ -\255\255\255\255\034\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\120\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\052\001\053\001\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\255\255\076\001\255\255\255\255\255\255\ -\080\001\081\001\255\255\083\001\084\001\007\001\086\001\255\255\ -\010\001\255\255\012\001\013\001\255\255\093\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\106\001\107\001\255\255\031\001\255\255\255\255\ -\034\001\255\255\255\255\255\255\255\255\039\001\040\001\255\255\ -\120\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\060\001\061\001\062\001\255\255\255\255\065\001\ -\066\001\255\255\255\255\069\001\255\255\255\255\255\255\006\001\ -\255\255\255\255\255\255\077\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\093\001\255\255\255\255\255\255\255\255\ -\031\001\255\255\255\255\034\001\035\001\255\255\255\255\038\001\ -\106\001\107\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\120\001\054\001\ +\062\001\063\001\255\255\065\001\066\001\067\001\255\255\069\001\ +\070\001\071\001\072\001\255\255\255\255\075\001\255\255\077\001\ +\255\255\255\255\080\001\081\001\082\001\083\001\084\001\085\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\005\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\101\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\114\001\255\255\116\001\030\001\ +\255\255\119\001\033\001\034\001\255\255\255\255\037\001\255\255\ +\255\255\040\001\041\001\042\001\043\001\044\001\045\001\046\001\ +\047\001\048\001\049\001\050\001\255\255\255\255\053\001\054\001\ \055\001\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ -\063\001\064\001\255\255\066\001\067\001\068\001\255\255\070\001\ -\071\001\072\001\073\001\255\255\006\001\076\001\255\255\078\001\ -\255\255\255\255\081\001\082\001\083\001\084\001\085\001\086\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\031\001\255\255\102\001\ -\034\001\035\001\255\255\255\255\038\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\115\001\255\255\117\001\255\255\ -\255\255\255\255\255\255\255\255\054\001\055\001\056\001\057\001\ -\058\001\059\001\060\001\061\001\255\255\255\255\255\255\255\255\ -\066\001\067\001\068\001\255\255\070\001\071\001\072\001\073\001\ -\255\255\006\001\076\001\255\255\078\001\255\255\255\255\081\001\ -\082\001\083\001\084\001\085\001\086\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\031\001\255\255\102\001\034\001\035\001\255\255\ -\255\255\038\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\115\001\255\255\117\001\255\255\255\255\255\255\255\255\ -\255\255\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ -\061\001\255\255\255\255\255\255\255\255\066\001\067\001\068\001\ -\255\255\070\001\071\001\072\001\073\001\255\255\006\001\076\001\ -\255\255\078\001\255\255\255\255\081\001\082\001\083\001\084\001\ -\085\001\086\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\031\001\ -\255\255\102\001\034\001\035\001\255\255\255\255\038\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\115\001\255\255\ -\117\001\255\255\255\255\255\255\255\255\255\255\054\001\055\001\ -\056\001\057\001\058\001\059\001\060\001\061\001\255\255\255\255\ -\255\255\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\072\001\073\001\255\255\006\001\076\001\255\255\078\001\255\255\ -\255\255\081\001\082\001\083\001\084\001\085\001\086\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\031\001\255\255\102\001\034\001\ -\035\001\255\255\255\255\038\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\115\001\255\255\117\001\255\255\255\255\ -\255\255\255\255\255\255\054\001\055\001\056\001\057\001\058\001\ -\059\001\255\255\255\255\255\255\255\255\255\255\255\255\066\001\ -\067\001\068\001\255\255\070\001\071\001\072\001\073\001\255\255\ -\006\001\076\001\255\255\078\001\255\255\255\255\081\001\082\001\ -\083\001\084\001\085\001\086\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\031\001\255\255\102\001\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\115\001\255\255\117\001\255\255\255\255\255\255\255\255\255\255\ -\054\001\055\001\056\001\057\001\058\001\059\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\072\001\073\001\255\255\006\001\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\031\001\255\255\ -\102\001\034\001\035\001\255\255\255\255\038\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\255\255\255\255\255\255\255\255\255\255\054\001\055\001\056\001\ -\057\001\058\001\059\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\066\001\067\001\068\001\255\255\070\001\071\001\072\001\ -\073\001\255\255\006\001\076\001\255\255\078\001\255\255\255\255\ -\081\001\082\001\083\001\084\001\085\001\086\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\031\001\255\255\102\001\034\001\035\001\ -\255\255\255\255\038\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\115\001\255\255\117\001\255\255\255\255\255\255\ -\255\255\255\255\054\001\055\001\056\001\057\001\058\001\059\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\066\001\067\001\ -\068\001\255\255\070\001\071\001\006\001\255\255\255\255\255\255\ -\076\001\255\255\078\001\255\255\255\255\081\001\082\001\083\001\ -\084\001\085\001\086\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\031\001\255\255\255\255\ -\034\001\035\001\102\001\255\255\038\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\115\001\ -\255\255\117\001\255\255\255\255\054\001\055\001\056\001\057\001\ -\058\001\059\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\066\001\067\001\068\001\255\255\070\001\071\001\006\001\255\255\ -\255\255\255\255\076\001\255\255\078\001\255\255\255\255\081\001\ -\082\001\083\001\084\001\085\001\086\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\031\001\ -\255\255\255\255\034\001\035\001\102\001\255\255\038\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\115\001\255\255\117\001\255\255\255\255\054\001\055\001\ -\056\001\057\001\058\001\059\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\006\001\255\255\255\255\255\255\076\001\255\255\078\001\255\255\ -\255\255\081\001\082\001\083\001\084\001\085\001\086\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\031\001\255\255\255\255\034\001\035\001\102\001\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\115\001\255\255\117\001\255\255\255\255\ -\054\001\055\001\056\001\057\001\058\001\059\001\255\255\255\255\ -\006\001\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\054\001\055\001\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\054\001\055\001\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\054\001\055\001\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\255\255\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\255\255\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\255\255\067\001\255\255\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\255\255\067\001\255\255\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\006\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\031\001\255\255\255\255\034\001\035\001\255\255\255\255\ -\038\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\000\001\117\001\ -\255\255\255\255\255\255\255\255\255\255\007\001\255\255\255\255\ -\010\001\071\001\012\001\013\001\255\255\255\255\076\001\255\255\ -\078\001\255\255\255\255\081\001\082\001\083\001\084\001\085\001\ -\086\001\255\255\255\255\255\255\255\255\031\001\255\255\255\255\ -\034\001\255\255\255\255\255\255\255\255\039\001\040\001\255\255\ -\102\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\115\001\255\255\117\001\ -\255\255\255\255\060\001\061\001\062\001\255\255\255\255\065\001\ -\066\001\255\255\255\255\069\001\255\255\000\001\255\255\255\255\ -\255\255\255\255\076\001\077\001\007\001\255\255\255\255\010\001\ -\255\255\012\001\013\001\255\255\255\255\054\001\055\001\056\001\ -\057\001\058\001\059\001\093\001\255\255\255\255\255\255\255\255\ -\255\255\066\001\067\001\068\001\031\001\070\001\071\001\034\001\ -\106\001\107\001\255\255\076\001\039\001\040\001\255\255\255\255\ -\081\001\082\001\083\001\084\001\255\255\086\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\060\001\061\001\062\001\000\001\255\255\065\001\066\001\ -\255\255\255\255\069\001\007\001\255\255\255\255\010\001\255\255\ -\012\001\013\001\077\001\255\255\255\255\255\255\255\255\120\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\093\001\031\001\255\255\255\255\034\001\255\255\ -\255\255\255\255\255\255\039\001\040\001\255\255\255\255\106\001\ -\107\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\060\001\061\001\062\001\000\001\255\255\065\001\066\001\255\255\ -\255\255\069\001\007\001\255\255\255\255\010\001\255\255\012\001\ -\013\001\077\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\093\001\031\001\255\255\255\255\034\001\255\255\255\255\ -\255\255\255\255\039\001\040\001\255\255\255\255\106\001\107\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\060\001\ -\061\001\062\001\255\255\255\255\065\001\066\001\255\255\255\255\ -\069\001\054\001\055\001\056\001\057\001\058\001\059\001\255\255\ -\077\001\255\255\255\255\255\255\255\255\066\001\067\001\068\001\ -\255\255\070\001\071\001\072\001\073\001\255\255\255\255\076\001\ -\093\001\255\255\255\255\255\255\081\001\082\001\083\001\084\001\ -\255\255\086\001\255\255\255\255\255\255\106\001\107\001\255\255\ -\255\255\054\001\055\001\056\001\057\001\058\001\059\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\066\001\067\001\068\001\ -\255\255\070\001\071\001\072\001\073\001\255\255\255\255\076\001\ -\255\255\255\255\255\255\120\001\081\001\082\001\083\001\084\001\ -\255\255\086\001\054\001\055\001\056\001\057\001\058\001\059\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\066\001\067\001\ -\068\001\255\255\070\001\071\001\255\255\255\255\255\255\255\255\ -\076\001\255\255\255\255\255\255\255\255\081\001\082\001\083\001\ -\084\001\255\255\086\001\120\001\255\255\054\001\055\001\056\001\ -\057\001\058\001\059\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\066\001\067\001\068\001\255\255\070\001\071\001\255\255\ -\255\255\255\255\255\255\076\001\255\255\255\255\255\255\255\255\ -\081\001\082\001\083\001\084\001\120\001\086\001\054\001\055\001\ -\056\001\057\001\058\001\059\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\066\001\067\001\068\001\255\255\070\001\071\001\ -\255\255\255\255\255\255\255\255\076\001\255\255\255\255\255\255\ -\255\255\081\001\082\001\083\001\084\001\255\255\086\001\120\001\ -\255\255\054\001\055\001\056\001\057\001\058\001\059\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\066\001\067\001\068\001\ -\255\255\070\001\071\001\255\255\255\255\255\255\255\255\076\001\ -\054\001\055\001\255\255\255\255\081\001\082\001\083\001\084\001\ -\120\001\086\001\255\255\255\255\066\001\067\001\068\001\255\255\ -\070\001\071\001\255\255\255\255\255\255\255\255\076\001\054\001\ -\055\001\255\255\255\255\081\001\082\001\083\001\084\001\255\255\ -\086\001\255\255\255\255\066\001\067\001\068\001\255\255\070\001\ -\071\001\255\255\255\255\120\001\255\255\076\001\255\255\255\255\ -\255\255\255\255\081\001\082\001\083\001\084\001\255\255\086\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\120\001\255\255\255\255\255\255\255\255\255\255\ +\063\001\255\255\065\001\066\001\067\001\255\255\069\001\070\001\ +\071\001\072\001\255\255\255\255\075\001\255\255\077\001\255\255\ +\255\255\080\001\081\001\082\001\083\001\084\001\085\001\006\001\ +\255\255\255\255\009\001\255\255\011\001\012\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\101\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\030\001\ +\255\255\255\255\033\001\114\001\255\255\116\001\255\255\255\255\ +\119\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\051\001\052\001\053\001\054\001\ +\055\001\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ +\063\001\255\255\065\001\066\001\067\001\255\255\069\001\070\001\ +\071\001\072\001\255\255\255\255\075\001\076\001\255\255\255\255\ +\079\001\080\001\081\001\082\001\083\001\006\001\085\001\255\255\ +\009\001\255\255\011\001\012\001\255\255\092\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\105\001\106\001\255\255\030\001\255\255\255\255\ +\033\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\119\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\051\001\052\001\053\001\054\001\055\001\056\001\ +\057\001\058\001\059\001\060\001\061\001\062\001\063\001\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\071\001\072\001\ +\255\255\255\255\075\001\076\001\255\255\255\255\079\001\080\001\ +\081\001\082\001\083\001\006\001\085\001\255\255\009\001\255\255\ +\011\001\012\001\255\255\092\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\105\001\106\001\255\255\030\001\255\255\255\255\033\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\119\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\051\001\052\001\053\001\054\001\055\001\056\001\057\001\058\001\ +\059\001\060\001\061\001\062\001\063\001\255\255\065\001\066\001\ +\067\001\255\255\069\001\070\001\071\001\072\001\255\255\255\255\ +\075\001\255\255\255\255\255\255\079\001\080\001\255\255\082\001\ +\083\001\005\001\085\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\092\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\105\001\106\001\ +\255\255\255\255\030\001\255\255\255\255\033\001\034\001\255\255\ +\255\255\037\001\255\255\255\255\119\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\053\001\054\001\055\001\056\001\057\001\058\001\059\001\ +\060\001\061\001\062\001\063\001\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\071\001\072\001\255\255\005\001\075\001\ +\255\255\077\001\255\255\255\255\080\001\081\001\082\001\083\001\ +\084\001\085\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\030\001\ +\255\255\101\001\033\001\034\001\255\255\255\255\037\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\114\001\255\255\ +\116\001\255\255\255\255\255\255\255\255\255\255\053\001\054\001\ +\055\001\056\001\057\001\058\001\059\001\060\001\255\255\255\255\ +\255\255\255\255\065\001\066\001\067\001\255\255\069\001\070\001\ +\071\001\072\001\255\255\005\001\075\001\255\255\077\001\255\255\ +\255\255\080\001\081\001\082\001\083\001\084\001\085\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\030\001\255\255\101\001\033\001\ +\034\001\255\255\255\255\037\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\114\001\255\255\116\001\255\255\255\255\ +\255\255\255\255\255\255\053\001\054\001\055\001\056\001\057\001\ +\058\001\059\001\060\001\255\255\255\255\255\255\255\255\065\001\ +\066\001\067\001\255\255\069\001\070\001\071\001\072\001\255\255\ +\005\001\075\001\255\255\077\001\255\255\255\255\080\001\081\001\ +\082\001\083\001\084\001\085\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\030\001\255\255\101\001\033\001\034\001\255\255\255\255\ +\037\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\114\001\255\255\116\001\255\255\255\255\255\255\255\255\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\255\255\255\255\255\255\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\255\255\005\001\075\001\255\255\ +\077\001\255\255\255\255\080\001\081\001\082\001\083\001\084\001\ +\085\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\030\001\255\255\ +\101\001\033\001\034\001\255\255\255\255\037\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\114\001\255\255\116\001\ +\255\255\255\255\255\255\255\255\255\255\053\001\054\001\055\001\ +\056\001\057\001\058\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\065\001\066\001\067\001\255\255\069\001\070\001\071\001\ +\072\001\255\255\005\001\075\001\255\255\077\001\255\255\255\255\ +\080\001\081\001\082\001\083\001\084\001\085\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\030\001\255\255\101\001\033\001\034\001\ +\255\255\255\255\037\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\114\001\255\255\116\001\255\255\255\255\255\255\ +\255\255\255\255\053\001\054\001\055\001\056\001\057\001\058\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\065\001\066\001\ +\067\001\255\255\069\001\070\001\071\001\072\001\255\255\005\001\ +\075\001\255\255\077\001\255\255\255\255\080\001\081\001\082\001\ +\083\001\084\001\085\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\030\001\255\255\101\001\033\001\034\001\255\255\255\255\037\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\114\001\ +\255\255\116\001\255\255\255\255\255\255\255\255\255\255\053\001\ +\054\001\055\001\056\001\057\001\058\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\065\001\066\001\067\001\255\255\069\001\ +\070\001\071\001\072\001\255\255\005\001\075\001\255\255\077\001\ +\255\255\255\255\080\001\081\001\082\001\083\001\084\001\085\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\030\001\255\255\101\001\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\114\001\255\255\116\001\255\255\ +\255\255\255\255\255\255\255\255\053\001\054\001\055\001\056\001\ +\057\001\058\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\005\001\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\030\001\ +\255\255\255\255\033\001\034\001\101\001\255\255\037\001\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\255\255\255\255\053\001\054\001\ +\055\001\056\001\057\001\058\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\065\001\066\001\067\001\255\255\069\001\070\001\ +\005\001\255\255\255\255\255\255\075\001\255\255\077\001\255\255\ +\255\255\080\001\081\001\082\001\083\001\084\001\085\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\030\001\255\255\255\255\033\001\034\001\101\001\255\255\ +\037\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\114\001\255\255\116\001\255\255\255\255\ +\053\001\054\001\055\001\056\001\057\001\058\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\005\001\255\255\255\255\255\255\075\001\255\255\ +\077\001\255\255\255\255\080\001\081\001\082\001\083\001\084\001\ +\085\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\030\001\255\255\255\255\033\001\034\001\ +\101\001\255\255\037\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\114\001\255\255\116\001\ +\255\255\255\255\053\001\054\001\055\001\056\001\057\001\058\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\065\001\066\001\ +\067\001\255\255\069\001\070\001\005\001\255\255\255\255\255\255\ +\075\001\255\255\077\001\255\255\255\255\080\001\081\001\082\001\ +\083\001\084\001\085\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\030\001\255\255\255\255\ +\033\001\034\001\101\001\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\114\001\ +\255\255\116\001\255\255\255\255\053\001\054\001\055\001\056\001\ +\057\001\058\001\255\255\255\255\005\001\255\255\255\255\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\053\001\054\001\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\053\001\054\001\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\053\001\054\001\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\065\001\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\255\255\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\255\255\066\001\067\001\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\255\255\066\001\255\255\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\255\255\066\001\255\255\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\255\255\255\255\037\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\101\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\005\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\069\001\070\001\255\255\255\255\ +\255\255\255\255\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\030\001\255\255\255\255\ +\033\001\034\001\000\001\255\255\037\001\255\255\255\255\255\255\ +\006\001\255\255\255\255\009\001\101\001\011\001\012\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\114\001\255\255\116\001\255\255\255\255\255\255\255\255\ +\030\001\255\255\255\255\033\001\255\255\070\001\255\255\255\255\ +\038\001\039\001\075\001\255\255\077\001\255\255\255\255\080\001\ +\081\001\082\001\083\001\084\001\085\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\059\001\060\001\061\001\ +\255\255\255\255\064\001\065\001\101\001\255\255\068\001\255\255\ +\255\255\000\001\255\255\255\255\255\255\075\001\076\001\006\001\ +\255\255\114\001\009\001\116\001\011\001\012\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\092\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\030\001\ +\255\255\255\255\033\001\105\001\106\001\000\001\255\255\038\001\ +\039\001\255\255\255\255\006\001\255\255\255\255\009\001\255\255\ +\011\001\012\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\059\001\060\001\061\001\255\255\ +\255\255\064\001\065\001\030\001\255\255\068\001\033\001\255\255\ +\255\255\255\255\255\255\038\001\039\001\076\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\092\001\255\255\255\255\ +\059\001\060\001\061\001\255\255\255\255\064\001\065\001\255\255\ +\255\255\068\001\105\001\106\001\000\001\255\255\255\255\255\255\ +\255\255\076\001\006\001\255\255\255\255\009\001\255\255\011\001\ +\012\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\092\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\030\001\255\255\255\255\033\001\105\001\106\001\ +\255\255\255\255\038\001\039\001\255\255\255\255\006\001\255\255\ +\255\255\009\001\255\255\011\001\012\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\059\001\ +\060\001\061\001\255\255\255\255\064\001\065\001\030\001\255\255\ +\068\001\033\001\255\255\255\255\255\255\255\255\038\001\039\001\ +\076\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\120\001\041\001\042\001\043\001\044\001\045\001\046\001\ -\047\001\048\001\049\001\050\001\051\001\052\001\053\001\054\001\ -\055\001\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ -\063\001\064\001\255\255\066\001\067\001\068\001\255\255\070\001\ -\071\001\072\001\073\001\074\001\075\001\255\255\077\001\078\001\ -\255\255\080\001\255\255\082\001\083\001\084\001\255\255\086\001" +\092\001\255\255\255\255\059\001\060\001\061\001\255\255\255\255\ +\064\001\065\001\255\255\255\255\068\001\105\001\106\001\255\255\ +\255\255\255\255\255\255\255\255\076\001\255\255\255\255\255\255\ +\255\255\053\001\054\001\055\001\056\001\057\001\058\001\255\255\ +\255\255\255\255\255\255\255\255\092\001\065\001\066\001\067\001\ +\255\255\069\001\070\001\071\001\072\001\255\255\255\255\075\001\ +\255\255\105\001\106\001\255\255\080\001\081\001\082\001\083\001\ +\255\255\085\001\053\001\054\001\055\001\056\001\057\001\058\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\065\001\066\001\ +\067\001\255\255\069\001\070\001\255\255\255\255\255\255\255\255\ +\075\001\255\255\255\255\255\255\255\255\080\001\081\001\082\001\ +\083\001\255\255\085\001\119\001\255\255\053\001\054\001\055\001\ +\056\001\057\001\058\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\065\001\066\001\067\001\255\255\069\001\070\001\255\255\ +\255\255\255\255\255\255\075\001\255\255\255\255\255\255\255\255\ +\080\001\081\001\082\001\083\001\119\001\085\001\053\001\054\001\ +\055\001\056\001\057\001\058\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\065\001\066\001\067\001\255\255\069\001\070\001\ +\255\255\255\255\255\255\255\255\075\001\255\255\255\255\255\255\ +\255\255\080\001\081\001\082\001\083\001\255\255\085\001\119\001\ +\255\255\053\001\054\001\055\001\056\001\057\001\058\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\255\255\255\255\255\255\255\255\075\001\ +\255\255\255\255\255\255\255\255\080\001\081\001\082\001\083\001\ +\119\001\085\001\053\001\054\001\055\001\056\001\057\001\058\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\065\001\066\001\ +\067\001\255\255\069\001\070\001\255\255\255\255\255\255\255\255\ +\075\001\053\001\054\001\255\255\255\255\080\001\081\001\082\001\ +\083\001\255\255\085\001\119\001\255\255\065\001\066\001\067\001\ +\255\255\069\001\070\001\255\255\255\255\255\255\255\255\075\001\ +\053\001\054\001\255\255\255\255\080\001\081\001\082\001\083\001\ +\255\255\085\001\255\255\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\255\255\255\255\119\001\255\255\075\001\255\255\ +\255\255\255\255\255\255\080\001\081\001\082\001\083\001\255\255\ +\085\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\119\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\119\001\040\001\041\001\042\001\043\001\044\001\ +\045\001\046\001\047\001\048\001\049\001\050\001\051\001\052\001\ +\053\001\054\001\055\001\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\255\255\065\001\066\001\067\001\255\255\ +\069\001\070\001\071\001\072\001\073\001\074\001\255\255\076\001\ +\077\001\255\255\079\001\255\255\081\001\082\001\083\001\255\255\ +\085\001" let yynames_const = "\ EOF\000\ @@ -3117,7 +3122,6 @@ " let yynames_block = "\ - FOR_SPEC\000\ SPEC\000\ DECL\000\ CODE_ANNOT\000\ @@ -3210,104 +3214,104 @@ ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : (bool*Cabs.definition) list) in Obj.repr( -# 443 "cil/src/frontc/cparser.mly" +# 441 "cil/src/frontc/cparser.mly" (_1) -# 3216 "cil/src/frontc/cparser.ml" +# 3220 "cil/src/frontc/cparser.ml" : (bool*Cabs.definition) list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : (bool*Cabs.definition) list) in Obj.repr( -# 445 "cil/src/frontc/cparser.mly" +# 443 "cil/src/frontc/cparser.mly" (_1) -# 3223 "cil/src/frontc/cparser.ml" +# 3227 "cil/src/frontc/cparser.ml" : (bool*Cabs.definition) list)) ; (fun __caml_parser_env -> Obj.repr( -# 448 "cil/src/frontc/cparser.mly" +# 446 "cil/src/frontc/cparser.mly" ( [] ) -# 3229 "cil/src/frontc/cparser.ml" +# 3233 "cil/src/frontc/cparser.ml" : (bool*Cabs.definition) list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.definition) in let _2 = (Parsing.peek_val __caml_parser_env 0 : (bool*Cabs.definition) list) in Obj.repr( -# 449 "cil/src/frontc/cparser.mly" +# 447 "cil/src/frontc/cparser.mly" ( (false,_1) :: _2 ) -# 3237 "cil/src/frontc/cparser.ml" +# 3241 "cil/src/frontc/cparser.ml" : (bool*Cabs.definition) list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ghost_globals) in let _3 = (Parsing.peek_val __caml_parser_env 0 : (bool*Cabs.definition) list) in Obj.repr( -# 450 "cil/src/frontc/cparser.mly" +# 448 "cil/src/frontc/cparser.mly" ( _2 @ _3 ) -# 3245 "cil/src/frontc/cparser.ml" +# 3249 "cil/src/frontc/cparser.ml" : (bool*Cabs.definition) list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : (bool*Cabs.definition) list) in Obj.repr( -# 451 "cil/src/frontc/cparser.mly" +# 449 "cil/src/frontc/cparser.mly" ( _2 ) -# 3253 "cil/src/frontc/cparser.ml" +# 3257 "cil/src/frontc/cparser.ml" : (bool*Cabs.definition) list)) ; (fun __caml_parser_env -> Obj.repr( -# 455 "cil/src/frontc/cparser.mly" +# 453 "cil/src/frontc/cparser.mly" ( currentLoc () ) -# 3259 "cil/src/frontc/cparser.ml" +# 3263 "cil/src/frontc/cparser.ml" : Cabs.cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.definition) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ghost_globals) in Obj.repr( -# 460 "cil/src/frontc/cparser.mly" +# 458 "cil/src/frontc/cparser.mly" ( (true,_1)::_2 ) -# 3267 "cil/src/frontc/cparser.ml" +# 3271 "cil/src/frontc/cparser.ml" : 'ghost_globals)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.definition) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ghost_globals) in Obj.repr( -# 461 "cil/src/frontc/cparser.mly" +# 459 "cil/src/frontc/cparser.mly" ( (true,_1)::_2 ) -# 3275 "cil/src/frontc/cparser.ml" +# 3279 "cil/src/frontc/cparser.ml" : 'ghost_globals)) ; (fun __caml_parser_env -> Obj.repr( -# 462 "cil/src/frontc/cparser.mly" +# 460 "cil/src/frontc/cparser.mly" ( [] ) -# 3281 "cil/src/frontc/cparser.ml" +# 3285 "cil/src/frontc/cparser.ml" : 'ghost_globals)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Logic_ptree.decl list) in Obj.repr( -# 467 "cil/src/frontc/cparser.mly" +# 465 "cil/src/frontc/cparser.mly" ( GLOBANNOT _1 ) -# 3288 "cil/src/frontc/cparser.ml" +# 3292 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.definition) in Obj.repr( -# 468 "cil/src/frontc/cparser.mly" +# 466 "cil/src/frontc/cparser.mly" ( _1 ) -# 3295 "cil/src/frontc/cparser.ml" +# 3299 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.definition) in Obj.repr( -# 469 "cil/src/frontc/cparser.mly" +# 467 "cil/src/frontc/cparser.mly" ( _1 ) -# 3302 "cil/src/frontc/cparser.ml" +# 3306 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : string * cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.definition) in Obj.repr( -# 473 "cil/src/frontc/cparser.mly" +# 471 "cil/src/frontc/cparser.mly" ( LINKAGE (fst _2, (*handleLoc*) (snd _2), [ _3 ]) ) -# 3311 "cil/src/frontc/cparser.ml" +# 3315 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -3316,14 +3320,14 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : (bool*Cabs.definition) list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 475 "cil/src/frontc/cparser.mly" +# 473 "cil/src/frontc/cparser.mly" ( LINKAGE (fst _2, (*handleLoc*) (snd _2), List.map (fun (x,y) -> if x then parse_error "invalid ghost in extern linkage specification" else y) _4) ) -# 3327 "cil/src/frontc/cparser.ml" +# 3331 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -3331,16 +3335,16 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : string * cabsloc) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 482 "cil/src/frontc/cparser.mly" +# 480 "cil/src/frontc/cparser.mly" ( GLOBASM (fst _3, (*handleLoc*) _1) ) -# 3337 "cil/src/frontc/cparser.ml" +# 3341 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'pragma) in Obj.repr( -# 483 "cil/src/frontc/cparser.mly" +# 481 "cil/src/frontc/cparser.mly" ( _1 ) -# 3344 "cil/src/frontc/cparser.ml" +# 3348 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : string) in @@ -3349,7 +3353,7 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : 'old_pardef_list) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 488 "cil/src/frontc/cparser.mly" +# 486 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in (* Convert pardecl to new style *) @@ -3358,20 +3362,20 @@ doDeclaration None loc [] [((_1, PROTO(JUSTBASE, pardecl,isva), [], loc), NO_INIT)] ) -# 3362 "cil/src/frontc/cparser.ml" +# 3366 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : string) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 498 "cil/src/frontc/cparser.mly" +# 496 "cil/src/frontc/cparser.mly" ( (* Make the function declarator *) let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in doDeclaration None loc [] [((_1, PROTO(JUSTBASE,[],false), [], loc), NO_INIT)] ) -# 3375 "cil/src/frontc/cparser.ml" +# 3379 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 7 : Cabs.cabsloc) in @@ -3383,7 +3387,7 @@ let _7 = (Parsing.peek_val __caml_parser_env 1 : (bool*Cabs.definition) list) in let _8 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 504 "cil/src/frontc/cparser.mly" +# 502 "cil/src/frontc/cparser.mly" ( checkConnective _5; TRANSFORMER(_3, @@ -3394,7 +3398,7 @@ _7, _1) ) -# 3398 "cil/src/frontc/cparser.ml" +# 3402 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 7 : Cabs.cabsloc) in @@ -3406,123 +3410,123 @@ let _7 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression) in let _8 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 515 "cil/src/frontc/cparser.mly" +# 513 "cil/src/frontc/cparser.mly" ( checkConnective _5; EXPRTRANSFORMER(_3, _7, _1) ) -# 3415 "cil/src/frontc/cparser.ml" +# 3419 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 519 "cil/src/frontc/cparser.mly" +# 517 "cil/src/frontc/cparser.mly" ( PRAGMA (make_expr (VARIABLE "parse_error"), _1) ) -# 3423 "cil/src/frontc/cparser.ml" +# 3427 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 523 "cil/src/frontc/cparser.mly" +# 521 "cil/src/frontc/cparser.mly" ( _1 ) -# 3430 "cil/src/frontc/cparser.ml" +# 3434 "cil/src/frontc/cparser.ml" : 'id_or_typename_as_id)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 524 "cil/src/frontc/cparser.mly" +# 522 "cil/src/frontc/cparser.mly" ( _1 ) -# 3437 "cil/src/frontc/cparser.ml" +# 3441 "cil/src/frontc/cparser.ml" : 'id_or_typename_as_id)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename_as_id) in Obj.repr( -# 528 "cil/src/frontc/cparser.mly" +# 526 "cil/src/frontc/cparser.mly" ( _1 ) -# 3444 "cil/src/frontc/cparser.ml" +# 3448 "cil/src/frontc/cparser.ml" : 'id_or_typename)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 529 "cil/src/frontc/cparser.mly" +# 527 "cil/src/frontc/cparser.mly" ( "@name(" ^ _3 ^ ")" ) -# 3452 "cil/src/frontc/cparser.ml" +# 3456 "cil/src/frontc/cparser.ml" : 'id_or_typename)) ; (fun __caml_parser_env -> Obj.repr( -# 534 "cil/src/frontc/cparser.mly" +# 532 "cil/src/frontc/cparser.mly" ( () ) -# 3458 "cil/src/frontc/cparser.ml" +# 3462 "cil/src/frontc/cparser.ml" : 'maybecomma)) ; (fun __caml_parser_env -> Obj.repr( -# 535 "cil/src/frontc/cparser.mly" +# 533 "cil/src/frontc/cparser.mly" ( () ) -# 3464 "cil/src/frontc/cparser.ml" +# 3468 "cil/src/frontc/cparser.ml" : 'maybecomma)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 541 "cil/src/frontc/cparser.mly" +# 539 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE _1) ) -# 3471 "cil/src/frontc/cparser.ml" +# 3475 "cil/src/frontc/cparser.ml" : 'primary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.constant * cabsloc) in Obj.repr( -# 542 "cil/src/frontc/cparser.mly" +# 540 "cil/src/frontc/cparser.mly" ( make_expr (CONSTANT (fst _1)) ) -# 3478 "cil/src/frontc/cparser.ml" +# 3482 "cil/src/frontc/cparser.ml" : 'primary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 544 "cil/src/frontc/cparser.mly" +# 542 "cil/src/frontc/cparser.mly" ( make_expr (PAREN (smooth_expression _1)) ) -# 3485 "cil/src/frontc/cparser.ml" +# 3489 "cil/src/frontc/cparser.ml" : 'primary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.block * cabsloc * cabsloc) in Obj.repr( -# 545 "cil/src/frontc/cparser.mly" +# 543 "cil/src/frontc/cparser.mly" ( make_expr (GNU_BODY (fst3 _2)) ) -# 3493 "cil/src/frontc/cparser.ml" +# 3497 "cil/src/frontc/cparser.ml" : 'primary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 547 "cil/src/frontc/cparser.mly" +# 545 "cil/src/frontc/cparser.mly" ( make_expr (EXPR_PATTERN _3) ) -# 3502 "cil/src/frontc/cparser.ml" +# 3506 "cil/src/frontc/cparser.ml" : 'primary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'primary_expression) in Obj.repr( -# 551 "cil/src/frontc/cparser.mly" +# 549 "cil/src/frontc/cparser.mly" ( _1 ) -# 3509 "cil/src/frontc/cparser.ml" +# 3513 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'postfix_expression) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 553 "cil/src/frontc/cparser.mly" +# 551 "cil/src/frontc/cparser.mly" (make_expr (INDEX (_1, smooth_expression _2))) -# 3517 "cil/src/frontc/cparser.ml" +# 3521 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'postfix_expression) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in Obj.repr( -# 554 "cil/src/frontc/cparser.mly" +# 552 "cil/src/frontc/cparser.mly" (make_expr (CALL (_1, _3))) -# 3526 "cil/src/frontc/cparser.ml" +# 3530 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -3530,7 +3534,7 @@ let _3 = (Parsing.peek_val __caml_parser_env 3 : Cabs.expression) in let _5 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 556 "cil/src/frontc/cparser.mly" +# 554 "cil/src/frontc/cparser.mly" ( let b, d = _5 in let loc = Parsing.rhs_start_pos 5, Parsing.rhs_end_pos 5 in let loc_f = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in @@ -3541,7 +3545,7 @@ [_3; { expr_loc = loc; expr_node = TYPE_SIZEOF (b, d)}])) ) -# 3545 "cil/src/frontc/cparser.ml" +# 3549 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -3549,7 +3553,7 @@ let _3 = (Parsing.peek_val __caml_parser_env 3 : Cabs.spec_elem list * Cabs.decl_type) in let _5 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 567 "cil/src/frontc/cparser.mly" +# 565 "cil/src/frontc/cparser.mly" ( let b1,d1 = _3 in let b2,d2 = _5 in let loc_f = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in @@ -3562,7 +3566,7 @@ [ { expr_loc = loc1; expr_node = TYPE_SIZEOF(b1,d1)}; { expr_loc = loc2; expr_node = TYPE_SIZEOF(b2,d2)}])) ) -# 3566 "cil/src/frontc/cparser.ml" +# 3570 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -3570,41 +3574,41 @@ let _3 = (Parsing.peek_val __caml_parser_env 3 : Cabs.spec_elem list * Cabs.decl_type) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'offsetof_member_designator) in Obj.repr( -# 580 "cil/src/frontc/cparser.mly" +# 578 "cil/src/frontc/cparser.mly" ( transformOffsetOf _3 _5 ) -# 3576 "cil/src/frontc/cparser.ml" +# 3580 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'postfix_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 581 "cil/src/frontc/cparser.mly" +# 579 "cil/src/frontc/cparser.mly" ( make_expr (MEMBEROF (_1, _3))) -# 3584 "cil/src/frontc/cparser.ml" +# 3588 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'postfix_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 582 "cil/src/frontc/cparser.mly" +# 580 "cil/src/frontc/cparser.mly" ( make_expr (MEMBEROFPTR (_1, _3)) ) -# 3592 "cil/src/frontc/cparser.ml" +# 3596 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'postfix_expression) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 583 "cil/src/frontc/cparser.mly" +# 581 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (POSINCR, _1)) ) -# 3600 "cil/src/frontc/cparser.ml" +# 3604 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'postfix_expression) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 584 "cil/src/frontc/cparser.mly" +# 582 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (POSDECR, _1)) ) -# 3608 "cil/src/frontc/cparser.ml" +# 3612 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -3613,545 +3617,545 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : 'initializer_list_opt) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 587 "cil/src/frontc/cparser.mly" +# 585 "cil/src/frontc/cparser.mly" ( make_expr (CAST(_2, COMPOUND_INIT _5)) ) -# 3619 "cil/src/frontc/cparser.ml" +# 3623 "cil/src/frontc/cparser.ml" : 'postfix_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 591 "cil/src/frontc/cparser.mly" +# 589 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE _1) ) -# 3626 "cil/src/frontc/cparser.ml" +# 3630 "cil/src/frontc/cparser.ml" : 'offsetof_member_designator)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'offsetof_member_designator) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 593 "cil/src/frontc/cparser.mly" +# 591 "cil/src/frontc/cparser.mly" ( make_expr (MEMBEROF (_1, _3)) ) -# 3634 "cil/src/frontc/cparser.ml" +# 3638 "cil/src/frontc/cparser.ml" : 'offsetof_member_designator)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'offsetof_member_designator) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 595 "cil/src/frontc/cparser.mly" +# 593 "cil/src/frontc/cparser.mly" ( make_expr (INDEX (_1, smooth_expression _2)) ) -# 3642 "cil/src/frontc/cparser.ml" +# 3646 "cil/src/frontc/cparser.ml" : 'offsetof_member_designator)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'postfix_expression) in Obj.repr( -# 600 "cil/src/frontc/cparser.mly" +# 598 "cil/src/frontc/cparser.mly" ( _1 ) -# 3649 "cil/src/frontc/cparser.ml" +# 3653 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 602 "cil/src/frontc/cparser.mly" +# 600 "cil/src/frontc/cparser.mly" (make_expr (UNARY (PREINCR, _2))) -# 3657 "cil/src/frontc/cparser.ml" +# 3661 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 604 "cil/src/frontc/cparser.mly" +# 602 "cil/src/frontc/cparser.mly" (make_expr (UNARY (PREDECR, _2))) -# 3665 "cil/src/frontc/cparser.ml" +# 3669 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 606 "cil/src/frontc/cparser.mly" +# 604 "cil/src/frontc/cparser.mly" (make_expr (EXPR_SIZEOF _2)) -# 3673 "cil/src/frontc/cparser.ml" +# 3677 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 608 "cil/src/frontc/cparser.mly" +# 606 "cil/src/frontc/cparser.mly" (let b, d = _3 in make_expr (TYPE_SIZEOF (b, d)) ) -# 3682 "cil/src/frontc/cparser.ml" +# 3686 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 610 "cil/src/frontc/cparser.mly" +# 608 "cil/src/frontc/cparser.mly" ( make_expr (EXPR_ALIGNOF _2) ) -# 3690 "cil/src/frontc/cparser.ml" +# 3694 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 612 "cil/src/frontc/cparser.mly" +# 610 "cil/src/frontc/cparser.mly" (let b, d = _3 in make_expr (TYPE_ALIGNOF (b, d)) ) -# 3699 "cil/src/frontc/cparser.ml" +# 3703 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 614 "cil/src/frontc/cparser.mly" +# 612 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (PLUS, _2)) ) -# 3707 "cil/src/frontc/cparser.ml" +# 3711 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 616 "cil/src/frontc/cparser.mly" +# 614 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (MINUS, _2)) ) -# 3715 "cil/src/frontc/cparser.ml" +# 3719 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 618 "cil/src/frontc/cparser.mly" +# 616 "cil/src/frontc/cparser.mly" (make_expr (UNARY (MEMOF, _2)) ) -# 3723 "cil/src/frontc/cparser.ml" +# 3727 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 620 "cil/src/frontc/cparser.mly" +# 618 "cil/src/frontc/cparser.mly" (make_expr (UNARY (ADDROF, _2))) -# 3731 "cil/src/frontc/cparser.ml" +# 3735 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 622 "cil/src/frontc/cparser.mly" +# 620 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (NOT, _2)) ) -# 3739 "cil/src/frontc/cparser.ml" +# 3743 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 624 "cil/src/frontc/cparser.mly" +# 622 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (BNOT, _2)) ) -# 3747 "cil/src/frontc/cparser.ml" +# 3751 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename_as_id) in Obj.repr( -# 626 "cil/src/frontc/cparser.mly" +# 624 "cil/src/frontc/cparser.mly" ( make_expr (LABELADDR _2) ) -# 3755 "cil/src/frontc/cparser.ml" +# 3759 "cil/src/frontc/cparser.ml" : 'unary_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 630 "cil/src/frontc/cparser.mly" +# 628 "cil/src/frontc/cparser.mly" ( _1 ) -# 3762 "cil/src/frontc/cparser.ml" +# 3766 "cil/src/frontc/cparser.ml" : 'cast_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.spec_elem list * Cabs.decl_type) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 632 "cil/src/frontc/cparser.mly" +# 630 "cil/src/frontc/cparser.mly" ( make_expr (CAST(_2, SINGLE_INIT _4)) ) -# 3771 "cil/src/frontc/cparser.ml" +# 3775 "cil/src/frontc/cparser.ml" : 'cast_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 636 "cil/src/frontc/cparser.mly" +# 634 "cil/src/frontc/cparser.mly" ( _1 ) -# 3778 "cil/src/frontc/cparser.ml" +# 3782 "cil/src/frontc/cparser.ml" : 'multiplicative_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'multiplicative_expression) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 638 "cil/src/frontc/cparser.mly" +# 636 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(MUL, _1, _3)) ) -# 3787 "cil/src/frontc/cparser.ml" +# 3791 "cil/src/frontc/cparser.ml" : 'multiplicative_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'multiplicative_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 640 "cil/src/frontc/cparser.mly" +# 638 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(DIV, _1, _3)) ) -# 3795 "cil/src/frontc/cparser.ml" +# 3799 "cil/src/frontc/cparser.ml" : 'multiplicative_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'multiplicative_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cast_expression) in Obj.repr( -# 642 "cil/src/frontc/cparser.mly" +# 640 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(MOD, _1, _3)) ) -# 3803 "cil/src/frontc/cparser.ml" +# 3807 "cil/src/frontc/cparser.ml" : 'multiplicative_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'multiplicative_expression) in Obj.repr( -# 646 "cil/src/frontc/cparser.mly" +# 644 "cil/src/frontc/cparser.mly" ( _1 ) -# 3810 "cil/src/frontc/cparser.ml" +# 3814 "cil/src/frontc/cparser.ml" : 'additive_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'additive_expression) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'multiplicative_expression) in Obj.repr( -# 648 "cil/src/frontc/cparser.mly" +# 646 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(ADD, _1, _3)) ) -# 3819 "cil/src/frontc/cparser.ml" +# 3823 "cil/src/frontc/cparser.ml" : 'additive_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'additive_expression) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'multiplicative_expression) in Obj.repr( -# 650 "cil/src/frontc/cparser.mly" +# 648 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(SUB, _1, _3)) ) -# 3828 "cil/src/frontc/cparser.ml" +# 3832 "cil/src/frontc/cparser.ml" : 'additive_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'additive_expression) in Obj.repr( -# 654 "cil/src/frontc/cparser.mly" +# 652 "cil/src/frontc/cparser.mly" ( _1 ) -# 3835 "cil/src/frontc/cparser.ml" +# 3839 "cil/src/frontc/cparser.ml" : 'shift_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'shift_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'additive_expression) in Obj.repr( -# 656 "cil/src/frontc/cparser.mly" +# 654 "cil/src/frontc/cparser.mly" (make_expr (BINARY(SHL, _1, _3)) ) -# 3843 "cil/src/frontc/cparser.ml" +# 3847 "cil/src/frontc/cparser.ml" : 'shift_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'shift_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'additive_expression) in Obj.repr( -# 658 "cil/src/frontc/cparser.mly" +# 656 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(SHR, _1, _3)) ) -# 3851 "cil/src/frontc/cparser.ml" +# 3855 "cil/src/frontc/cparser.ml" : 'shift_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'shift_expression) in Obj.repr( -# 663 "cil/src/frontc/cparser.mly" +# 661 "cil/src/frontc/cparser.mly" ( _1 ) -# 3858 "cil/src/frontc/cparser.ml" +# 3862 "cil/src/frontc/cparser.ml" : 'relational_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_expression) in Obj.repr( -# 665 "cil/src/frontc/cparser.mly" +# 663 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(LT, _1, _3)) ) -# 3866 "cil/src/frontc/cparser.ml" +# 3870 "cil/src/frontc/cparser.ml" : 'relational_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_expression) in Obj.repr( -# 667 "cil/src/frontc/cparser.mly" +# 665 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(GT, _1, _3)) ) -# 3874 "cil/src/frontc/cparser.ml" +# 3878 "cil/src/frontc/cparser.ml" : 'relational_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_expression) in Obj.repr( -# 669 "cil/src/frontc/cparser.mly" +# 667 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(LE, _1, _3)) ) -# 3882 "cil/src/frontc/cparser.ml" +# 3886 "cil/src/frontc/cparser.ml" : 'relational_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_expression) in Obj.repr( -# 671 "cil/src/frontc/cparser.mly" +# 669 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(GE, _1, _3)) ) -# 3890 "cil/src/frontc/cparser.ml" +# 3894 "cil/src/frontc/cparser.ml" : 'relational_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'relational_expression) in Obj.repr( -# 675 "cil/src/frontc/cparser.mly" +# 673 "cil/src/frontc/cparser.mly" ( _1 ) -# 3897 "cil/src/frontc/cparser.ml" +# 3901 "cil/src/frontc/cparser.ml" : 'equality_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'equality_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'relational_expression) in Obj.repr( -# 677 "cil/src/frontc/cparser.mly" +# 675 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(EQ, _1, _3)) ) -# 3905 "cil/src/frontc/cparser.ml" +# 3909 "cil/src/frontc/cparser.ml" : 'equality_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'equality_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'relational_expression) in Obj.repr( -# 679 "cil/src/frontc/cparser.mly" +# 677 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(NE, _1, _3)) ) -# 3913 "cil/src/frontc/cparser.ml" +# 3917 "cil/src/frontc/cparser.ml" : 'equality_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'equality_expression) in Obj.repr( -# 683 "cil/src/frontc/cparser.mly" +# 681 "cil/src/frontc/cparser.mly" ( _1 ) -# 3920 "cil/src/frontc/cparser.ml" +# 3924 "cil/src/frontc/cparser.ml" : 'bitwise_and_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'bitwise_and_expression) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'equality_expression) in Obj.repr( -# 685 "cil/src/frontc/cparser.mly" +# 683 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(BAND, _1, _3)) ) -# 3929 "cil/src/frontc/cparser.ml" +# 3933 "cil/src/frontc/cparser.ml" : 'bitwise_and_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_and_expression) in Obj.repr( -# 689 "cil/src/frontc/cparser.mly" +# 687 "cil/src/frontc/cparser.mly" ( _1 ) -# 3936 "cil/src/frontc/cparser.ml" +# 3940 "cil/src/frontc/cparser.ml" : 'bitwise_xor_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'bitwise_xor_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_and_expression) in Obj.repr( -# 691 "cil/src/frontc/cparser.mly" +# 689 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(XOR, _1, _3)) ) -# 3944 "cil/src/frontc/cparser.ml" +# 3948 "cil/src/frontc/cparser.ml" : 'bitwise_xor_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_xor_expression) in Obj.repr( -# 695 "cil/src/frontc/cparser.mly" +# 693 "cil/src/frontc/cparser.mly" ( _1 ) -# 3951 "cil/src/frontc/cparser.ml" +# 3955 "cil/src/frontc/cparser.ml" : 'bitwise_or_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'bitwise_or_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_xor_expression) in Obj.repr( -# 697 "cil/src/frontc/cparser.mly" +# 695 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(BOR, _1, _3)) ) -# 3959 "cil/src/frontc/cparser.ml" +# 3963 "cil/src/frontc/cparser.ml" : 'bitwise_or_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_or_expression) in Obj.repr( -# 701 "cil/src/frontc/cparser.mly" +# 699 "cil/src/frontc/cparser.mly" ( _1 ) -# 3966 "cil/src/frontc/cparser.ml" +# 3970 "cil/src/frontc/cparser.ml" : 'logical_and_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'logical_and_expression) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_or_expression) in Obj.repr( -# 703 "cil/src/frontc/cparser.mly" +# 701 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(AND, _1, _3)) ) -# 3975 "cil/src/frontc/cparser.ml" +# 3979 "cil/src/frontc/cparser.ml" : 'logical_and_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logical_and_expression) in Obj.repr( -# 707 "cil/src/frontc/cparser.mly" +# 705 "cil/src/frontc/cparser.mly" ( _1 ) -# 3982 "cil/src/frontc/cparser.ml" +# 3986 "cil/src/frontc/cparser.ml" : 'logical_or_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'logical_or_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'logical_and_expression) in Obj.repr( -# 709 "cil/src/frontc/cparser.mly" +# 707 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(OR, _1, _3)) ) -# 3990 "cil/src/frontc/cparser.ml" +# 3994 "cil/src/frontc/cparser.ml" : 'logical_or_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logical_or_expression) in Obj.repr( -# 713 "cil/src/frontc/cparser.mly" +# 711 "cil/src/frontc/cparser.mly" ( _1 ) -# 3997 "cil/src/frontc/cparser.ml" +# 4001 "cil/src/frontc/cparser.ml" : 'conditional_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'logical_or_expression) in let _3 = (Parsing.peek_val __caml_parser_env 2 : Cabs.expression) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'conditional_expression) in Obj.repr( -# 715 "cil/src/frontc/cparser.mly" +# 713 "cil/src/frontc/cparser.mly" ( make_expr (QUESTION (_1, _3, _5)) ) -# 4006 "cil/src/frontc/cparser.ml" +# 4010 "cil/src/frontc/cparser.ml" : 'conditional_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'conditional_expression) in Obj.repr( -# 722 "cil/src/frontc/cparser.mly" +# 720 "cil/src/frontc/cparser.mly" ( _1 ) -# 4013 "cil/src/frontc/cparser.ml" +# 4017 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 724 "cil/src/frontc/cparser.mly" +# 722 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(ASSIGN, _1, _3)) ) -# 4021 "cil/src/frontc/cparser.ml" +# 4025 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 726 "cil/src/frontc/cparser.mly" +# 724 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(ADD_ASSIGN, _1, _3)) ) -# 4029 "cil/src/frontc/cparser.ml" +# 4033 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 728 "cil/src/frontc/cparser.mly" +# 726 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(SUB_ASSIGN, _1, _3)) ) -# 4037 "cil/src/frontc/cparser.ml" +# 4041 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 730 "cil/src/frontc/cparser.mly" +# 728 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(MUL_ASSIGN, _1, _3)) ) -# 4045 "cil/src/frontc/cparser.ml" +# 4049 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 732 "cil/src/frontc/cparser.mly" +# 730 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(DIV_ASSIGN, _1, _3)) ) -# 4053 "cil/src/frontc/cparser.ml" +# 4057 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 734 "cil/src/frontc/cparser.mly" +# 732 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(MOD_ASSIGN, _1, _3)) ) -# 4061 "cil/src/frontc/cparser.ml" +# 4065 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 736 "cil/src/frontc/cparser.mly" +# 734 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(BAND_ASSIGN, _1, _3)) ) -# 4069 "cil/src/frontc/cparser.ml" +# 4073 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 738 "cil/src/frontc/cparser.mly" +# 736 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(BOR_ASSIGN, _1, _3)) ) -# 4077 "cil/src/frontc/cparser.ml" +# 4081 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 740 "cil/src/frontc/cparser.mly" +# 738 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(XOR_ASSIGN, _1, _3)) ) -# 4085 "cil/src/frontc/cparser.ml" +# 4089 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 742 "cil/src/frontc/cparser.mly" +# 740 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(SHL_ASSIGN, _1, _3)) ) -# 4093 "cil/src/frontc/cparser.ml" +# 4097 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'cast_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 744 "cil/src/frontc/cparser.mly" +# 742 "cil/src/frontc/cparser.mly" ( make_expr (BINARY(SHR_ASSIGN, _1, _3))) -# 4101 "cil/src/frontc/cparser.ml" +# 4105 "cil/src/frontc/cparser.ml" : 'assignment_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'assignment_expression) in Obj.repr( -# 748 "cil/src/frontc/cparser.mly" +# 746 "cil/src/frontc/cparser.mly" ( _1 ) -# 4108 "cil/src/frontc/cparser.ml" +# 4112 "cil/src/frontc/cparser.ml" : Cabs.expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 753 "cil/src/frontc/cparser.mly" +# 751 "cil/src/frontc/cparser.mly" (CONST_INT (fst _1), snd _1) -# 4115 "cil/src/frontc/cparser.ml" +# 4119 "cil/src/frontc/cparser.ml" : Cabs.constant * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 754 "cil/src/frontc/cparser.mly" +# 752 "cil/src/frontc/cparser.mly" (CONST_FLOAT (fst _1), snd _1) -# 4122 "cil/src/frontc/cparser.ml" +# 4126 "cil/src/frontc/cparser.ml" : Cabs.constant * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list * Cabs.cabsloc) in Obj.repr( -# 755 "cil/src/frontc/cparser.mly" +# 753 "cil/src/frontc/cparser.mly" (CONST_CHAR (fst _1), snd _1) -# 4129 "cil/src/frontc/cparser.ml" +# 4133 "cil/src/frontc/cparser.ml" : Cabs.constant * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list * Cabs.cabsloc) in Obj.repr( -# 756 "cil/src/frontc/cparser.mly" +# 754 "cil/src/frontc/cparser.mly" (CONST_WCHAR (fst _1), snd _1) -# 4136 "cil/src/frontc/cparser.ml" +# 4140 "cil/src/frontc/cparser.ml" : Cabs.constant * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * cabsloc) in Obj.repr( -# 757 "cil/src/frontc/cparser.mly" +# 755 "cil/src/frontc/cparser.mly" (CONST_STRING (fst _1), snd _1) -# 4143 "cil/src/frontc/cparser.ml" +# 4147 "cil/src/frontc/cparser.ml" : Cabs.constant * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list * cabsloc) in Obj.repr( -# 758 "cil/src/frontc/cparser.mly" +# 756 "cil/src/frontc/cparser.mly" (CONST_WSTRING (fst _1), snd _1) -# 4150 "cil/src/frontc/cparser.ml" +# 4154 "cil/src/frontc/cparser.ml" : Cabs.constant * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list Queue.t * cabsloc) in Obj.repr( -# 764 "cil/src/frontc/cparser.mly" +# 762 "cil/src/frontc/cparser.mly" ( let queue, location = _1 in let buffer = Buffer.create (Queue.length queue) in @@ -4163,295 +4167,295 @@ queue; Buffer.contents buffer, location ) -# 4167 "cil/src/frontc/cparser.ml" +# 4171 "cil/src/frontc/cparser.ml" : string * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list * Cabs.cabsloc) in Obj.repr( -# 778 "cil/src/frontc/cparser.mly" +# 776 "cil/src/frontc/cparser.mly" (intlist_to_string (fst _1) ) -# 4174 "cil/src/frontc/cparser.ml" +# 4178 "cil/src/frontc/cparser.ml" : 'one_string_constant)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'one_string) in Obj.repr( -# 781 "cil/src/frontc/cparser.mly" +# 779 "cil/src/frontc/cparser.mly" ( let queue = Queue.create () in Queue.add (fst _1) queue; queue, snd _1 ) -# 4185 "cil/src/frontc/cparser.ml" +# 4189 "cil/src/frontc/cparser.ml" : int64 list Queue.t * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : int64 list Queue.t * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'one_string) in Obj.repr( -# 786 "cil/src/frontc/cparser.mly" +# 784 "cil/src/frontc/cparser.mly" ( Queue.add (fst _2) (fst _1); _1 ) -# 4196 "cil/src/frontc/cparser.ml" +# 4200 "cil/src/frontc/cparser.ml" : int64 list Queue.t * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list * Cabs.cabsloc) in Obj.repr( -# 793 "cil/src/frontc/cparser.mly" +# 791 "cil/src/frontc/cparser.mly" ( _1 ) -# 4203 "cil/src/frontc/cparser.ml" +# 4207 "cil/src/frontc/cparser.ml" : int64 list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : int64 list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'one_string) in Obj.repr( -# 794 "cil/src/frontc/cparser.mly" +# 792 "cil/src/frontc/cparser.mly" ( (fst _1) @ (fst _2), snd _1 ) -# 4211 "cil/src/frontc/cparser.ml" +# 4215 "cil/src/frontc/cparser.ml" : int64 list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : int64 list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : int64 list * Cabs.cabsloc) in Obj.repr( -# 795 "cil/src/frontc/cparser.mly" +# 793 "cil/src/frontc/cparser.mly" ( (fst _1) @ (fst _2), snd _1 ) -# 4219 "cil/src/frontc/cparser.ml" +# 4223 "cil/src/frontc/cparser.ml" : int64 list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : int64 list * Cabs.cabsloc) in Obj.repr( -# 800 "cil/src/frontc/cparser.mly" +# 798 "cil/src/frontc/cparser.mly" (_1) -# 4226 "cil/src/frontc/cparser.ml" +# 4230 "cil/src/frontc/cparser.ml" : 'one_string)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 801 "cil/src/frontc/cparser.mly" +# 799 "cil/src/frontc/cparser.mly" ((Cabshelper.explodeStringToInts !currentFunctionName), _1) -# 4234 "cil/src/frontc/cparser.ml" +# 4238 "cil/src/frontc/cparser.ml" : 'one_string)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 803 "cil/src/frontc/cparser.mly" +# 801 "cil/src/frontc/cparser.mly" ((Cabshelper.explodeStringToInts !currentFunctionName), _1) -# 4242 "cil/src/frontc/cparser.ml" +# 4246 "cil/src/frontc/cparser.ml" : 'one_string)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression) in Obj.repr( -# 808 "cil/src/frontc/cparser.mly" +# 806 "cil/src/frontc/cparser.mly" ( SINGLE_INIT _1 ) -# 4249 "cil/src/frontc/cparser.ml" +# 4253 "cil/src/frontc/cparser.ml" : Cabs.init_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'initializer_list_opt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 810 "cil/src/frontc/cparser.mly" +# 808 "cil/src/frontc/cparser.mly" ( COMPOUND_INIT _2) -# 4258 "cil/src/frontc/cparser.ml" +# 4262 "cil/src/frontc/cparser.ml" : Cabs.init_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.initwhat * Cabs.init_expression) in Obj.repr( -# 813 "cil/src/frontc/cparser.mly" +# 811 "cil/src/frontc/cparser.mly" ( [_1] ) -# 4265 "cil/src/frontc/cparser.ml" +# 4269 "cil/src/frontc/cparser.ml" : (Cabs.initwhat * Cabs.init_expression) list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.initwhat * Cabs.init_expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'initializer_list_opt) in Obj.repr( -# 814 "cil/src/frontc/cparser.mly" +# 812 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 4273 "cil/src/frontc/cparser.ml" +# 4277 "cil/src/frontc/cparser.ml" : (Cabs.initwhat * Cabs.init_expression) list)) ; (fun __caml_parser_env -> Obj.repr( -# 817 "cil/src/frontc/cparser.mly" +# 815 "cil/src/frontc/cparser.mly" ( [] ) -# 4279 "cil/src/frontc/cparser.ml" +# 4283 "cil/src/frontc/cparser.ml" : 'initializer_list_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : (Cabs.initwhat * Cabs.init_expression) list) in Obj.repr( -# 818 "cil/src/frontc/cparser.mly" +# 816 "cil/src/frontc/cparser.mly" ( _1 ) -# 4286 "cil/src/frontc/cparser.ml" +# 4290 "cil/src/frontc/cparser.ml" : 'initializer_list_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.initwhat) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'eq_opt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.init_expression) in Obj.repr( -# 821 "cil/src/frontc/cparser.mly" +# 819 "cil/src/frontc/cparser.mly" ( (_1, _3) ) -# 4295 "cil/src/frontc/cparser.ml" +# 4299 "cil/src/frontc/cparser.ml" : Cabs.initwhat * Cabs.init_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'gcc_init_designators) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.init_expression) in Obj.repr( -# 822 "cil/src/frontc/cparser.mly" +# 820 "cil/src/frontc/cparser.mly" ( (_1, _2) ) -# 4303 "cil/src/frontc/cparser.ml" +# 4307 "cil/src/frontc/cparser.ml" : Cabs.initwhat * Cabs.init_expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.init_expression) in Obj.repr( -# 823 "cil/src/frontc/cparser.mly" +# 821 "cil/src/frontc/cparser.mly" ( (NEXT_INIT, _1) ) -# 4310 "cil/src/frontc/cparser.ml" +# 4314 "cil/src/frontc/cparser.ml" : Cabs.initwhat * Cabs.init_expression)) ; (fun __caml_parser_env -> Obj.repr( -# 826 "cil/src/frontc/cparser.mly" +# 824 "cil/src/frontc/cparser.mly" ( () ) -# 4316 "cil/src/frontc/cparser.ml" +# 4320 "cil/src/frontc/cparser.ml" : 'eq_opt)) ; (fun __caml_parser_env -> Obj.repr( -# 828 "cil/src/frontc/cparser.mly" +# 826 "cil/src/frontc/cparser.mly" ( () ) -# 4322 "cil/src/frontc/cparser.ml" +# 4326 "cil/src/frontc/cparser.ml" : 'eq_opt)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'id_or_typename) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.initwhat) in Obj.repr( -# 831 "cil/src/frontc/cparser.mly" +# 829 "cil/src/frontc/cparser.mly" ( INFIELD_INIT(_2, _3) ) -# 4330 "cil/src/frontc/cparser.ml" +# 4334 "cil/src/frontc/cparser.ml" : Cabs.initwhat)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.expression) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.initwhat) in Obj.repr( -# 832 "cil/src/frontc/cparser.mly" +# 830 "cil/src/frontc/cparser.mly" ( ATINDEX_INIT(_2, _4) ) -# 4338 "cil/src/frontc/cparser.ml" +# 4342 "cil/src/frontc/cparser.ml" : Cabs.initwhat)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : Cabs.expression) in let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression) in Obj.repr( -# 834 "cil/src/frontc/cparser.mly" +# 832 "cil/src/frontc/cparser.mly" ( ATINDEXRANGE_INIT(_2, _4) ) -# 4346 "cil/src/frontc/cparser.ml" +# 4350 "cil/src/frontc/cparser.ml" : Cabs.initwhat)) ; (fun __caml_parser_env -> Obj.repr( -# 837 "cil/src/frontc/cparser.mly" +# 835 "cil/src/frontc/cparser.mly" ( NEXT_INIT ) -# 4352 "cil/src/frontc/cparser.ml" +# 4356 "cil/src/frontc/cparser.ml" : Cabs.initwhat)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.initwhat) in Obj.repr( -# 838 "cil/src/frontc/cparser.mly" +# 836 "cil/src/frontc/cparser.mly" ( _1 ) -# 4359 "cil/src/frontc/cparser.ml" +# 4363 "cil/src/frontc/cparser.ml" : Cabs.initwhat)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'id_or_typename) in Obj.repr( -# 842 "cil/src/frontc/cparser.mly" +# 840 "cil/src/frontc/cparser.mly" ( INFIELD_INIT(_1, NEXT_INIT) ) -# 4366 "cil/src/frontc/cparser.ml" +# 4370 "cil/src/frontc/cparser.ml" : 'gcc_init_designators)) ; (fun __caml_parser_env -> Obj.repr( -# 846 "cil/src/frontc/cparser.mly" +# 844 "cil/src/frontc/cparser.mly" ( [] ) -# 4372 "cil/src/frontc/cparser.ml" +# 4376 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 847 "cil/src/frontc/cparser.mly" +# 845 "cil/src/frontc/cparser.mly" ( _1 ) -# 4379 "cil/src/frontc/cparser.ml" +# 4383 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> Obj.repr( -# 851 "cil/src/frontc/cparser.mly" +# 849 "cil/src/frontc/cparser.mly" (make_expr NOTHING) -# 4385 "cil/src/frontc/cparser.ml" +# 4389 "cil/src/frontc/cparser.ml" : Cabs.expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 852 "cil/src/frontc/cparser.mly" +# 850 "cil/src/frontc/cparser.mly" (smooth_expression _1 ) -# 4392 "cil/src/frontc/cparser.ml" +# 4396 "cil/src/frontc/cparser.ml" : Cabs.expression)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression) in Obj.repr( -# 856 "cil/src/frontc/cparser.mly" +# 854 "cil/src/frontc/cparser.mly" ( [_1] ) -# 4399 "cil/src/frontc/cparser.ml" +# 4403 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.expression) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 857 "cil/src/frontc/cparser.mly" +# 855 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 4407 "cil/src/frontc/cparser.ml" +# 4411 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 858 "cil/src/frontc/cparser.mly" +# 856 "cil/src/frontc/cparser.mly" ( _3 ) -# 4414 "cil/src/frontc/cparser.ml" +# 4418 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> Obj.repr( -# 862 "cil/src/frontc/cparser.mly" +# 860 "cil/src/frontc/cparser.mly" ( make_expr NOTHING ) -# 4420 "cil/src/frontc/cparser.ml" +# 4424 "cil/src/frontc/cparser.ml" : 'comma_expression_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 863 "cil/src/frontc/cparser.mly" +# 861 "cil/src/frontc/cparser.mly" ( smooth_expression _1 ) -# 4427 "cil/src/frontc/cparser.ml" +# 4431 "cil/src/frontc/cparser.ml" : 'comma_expression_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in Obj.repr( -# 867 "cil/src/frontc/cparser.mly" +# 865 "cil/src/frontc/cparser.mly" ( _2 ) -# 4435 "cil/src/frontc/cparser.ml" +# 4439 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in Obj.repr( -# 868 "cil/src/frontc/cparser.mly" +# 866 "cil/src/frontc/cparser.mly" ( [] ) -# 4442 "cil/src/frontc/cparser.ml" +# 4446 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in Obj.repr( -# 872 "cil/src/frontc/cparser.mly" +# 870 "cil/src/frontc/cparser.mly" ( _2 ) -# 4449 "cil/src/frontc/cparser.ml" +# 4453 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> Obj.repr( -# 873 "cil/src/frontc/cparser.mly" +# 871 "cil/src/frontc/cparser.mly" ( [] ) -# 4455 "cil/src/frontc/cparser.ml" +# 4459 "cil/src/frontc/cparser.ml" : Cabs.expression list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'block_begin) in @@ -4460,185 +4464,176 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.statement list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 880 "cil/src/frontc/cparser.mly" +# 878 "cil/src/frontc/cparser.mly" (!Lexerhack.pop_context(); { blabels = _2; battrs = _3; bstmts = _4 }, _1, _5 ) -# 4471 "cil/src/frontc/cparser.ml" +# 4475 "cil/src/frontc/cparser.ml" : Cabs.block * cabsloc * cabsloc)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 886 "cil/src/frontc/cparser.mly" +# 884 "cil/src/frontc/cparser.mly" ( { blabels = []; battrs = []; bstmts = [] }, _2, _3 ) -# 4483 "cil/src/frontc/cparser.ml" +# 4487 "cil/src/frontc/cparser.ml" : Cabs.block * cabsloc * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 893 "cil/src/frontc/cparser.mly" +# 891 "cil/src/frontc/cparser.mly" (!Lexerhack.push_context (); _1) -# 4490 "cil/src/frontc/cparser.ml" +# 4494 "cil/src/frontc/cparser.ml" : 'block_begin)) ; (fun __caml_parser_env -> Obj.repr( -# 897 "cil/src/frontc/cparser.mly" +# 895 "cil/src/frontc/cparser.mly" ( [] ) -# 4496 "cil/src/frontc/cparser.ml" +# 4500 "cil/src/frontc/cparser.ml" : 'block_attrs)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'paren_attr_list_ne) in Obj.repr( -# 899 "cil/src/frontc/cparser.mly" +# 897 "cil/src/frontc/cparser.mly" ( [("__blockattribute__", _2)] ) -# 4503 "cil/src/frontc/cparser.ml" +# 4507 "cil/src/frontc/cparser.ml" : 'block_attrs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'annot_list_opt) in Obj.repr( -# 904 "cil/src/frontc/cparser.mly" +# 902 "cil/src/frontc/cparser.mly" ( _1 ) -# 4510 "cil/src/frontc/cparser.ml" +# 4514 "cil/src/frontc/cparser.ml" : Cabs.statement list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'annot_list_opt) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.definition) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.statement list) in Obj.repr( -# 906 "cil/src/frontc/cparser.mly" +# 904 "cil/src/frontc/cparser.mly" ( _1 @ no_ghost_stmt (DEFINITION(_2)) :: _3 ) -# 4519 "cil/src/frontc/cparser.ml" +# 4523 "cil/src/frontc/cparser.ml" : Cabs.statement list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'annot_list_opt) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'statement) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.statement list) in Obj.repr( -# 908 "cil/src/frontc/cparser.mly" +# 906 "cil/src/frontc/cparser.mly" ( _1 @ _2 @ _3 ) -# 4528 "cil/src/frontc/cparser.ml" +# 4532 "cil/src/frontc/cparser.ml" : Cabs.statement list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'annot_list_opt) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'pragma) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.statement list) in Obj.repr( -# 909 "cil/src/frontc/cparser.mly" +# 907 "cil/src/frontc/cparser.mly" ( _1 @ _3 ) -# 4537 "cil/src/frontc/cparser.ml" +# 4541 "cil/src/frontc/cparser.ml" : Cabs.statement list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'annot_list_opt) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'id_or_typename_as_id) in Obj.repr( -# 912 "cil/src/frontc/cparser.mly" +# 910 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 2, Parsing.rhs_end_pos 3 in _1 @ no_ghost [LABEL (_2, no_ghost_stmt (NOP loc), loc)] ) -# 4546 "cil/src/frontc/cparser.ml" +# 4550 "cil/src/frontc/cparser.ml" : Cabs.statement list)) ; (fun __caml_parser_env -> Obj.repr( -# 917 "cil/src/frontc/cparser.mly" +# 915 "cil/src/frontc/cparser.mly" ( [] ) -# 4552 "cil/src/frontc/cparser.ml" +# 4556 "cil/src/frontc/cparser.ml" : 'annot_list_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'annot_list) in Obj.repr( -# 918 "cil/src/frontc/cparser.mly" +# 916 "cil/src/frontc/cparser.mly" ( _1 ) -# 4559 "cil/src/frontc/cparser.ml" +# 4563 "cil/src/frontc/cparser.ml" : 'annot_list_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Logic_ptree.code_annot * Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'annot_list_opt) in Obj.repr( -# 922 "cil/src/frontc/cparser.mly" +# 920 "cil/src/frontc/cparser.mly" ( no_ghost [Cabs.CODE_ANNOT _1] @ _2) -# 4567 "cil/src/frontc/cparser.ml" +# 4571 "cil/src/frontc/cparser.ml" : 'annot_list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.statement list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'annot_list_opt) in Obj.repr( -# 924 "cil/src/frontc/cparser.mly" +# 922 "cil/src/frontc/cparser.mly" ( (in_ghost _2) @ _4 ) -# 4575 "cil/src/frontc/cparser.ml" +# 4579 "cil/src/frontc/cparser.ml" : 'annot_list)) ; (fun __caml_parser_env -> Obj.repr( -# 928 "cil/src/frontc/cparser.mly" +# 926 "cil/src/frontc/cparser.mly" ( [] ) -# 4581 "cil/src/frontc/cparser.ml" +# 4585 "cil/src/frontc/cparser.ml" : string list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : string list) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 0 : string list) in Obj.repr( -# 929 "cil/src/frontc/cparser.mly" +# 927 "cil/src/frontc/cparser.mly" ( _2 @ _4 ) -# 4590 "cil/src/frontc/cparser.ml" +# 4594 "cil/src/frontc/cparser.ml" : string list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename_as_id) in Obj.repr( -# 932 "cil/src/frontc/cparser.mly" +# 930 "cil/src/frontc/cparser.mly" ( [ _1 ] ) -# 4597 "cil/src/frontc/cparser.ml" +# 4601 "cil/src/frontc/cparser.ml" : string list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'id_or_typename_as_id) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string list) in Obj.repr( -# 933 "cil/src/frontc/cparser.mly" +# 931 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 4605 "cil/src/frontc/cparser.ml" +# 4609 "cil/src/frontc/cparser.ml" : string list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'statement) in Obj.repr( -# 938 "cil/src/frontc/cparser.mly" +# 936 "cil/src/frontc/cparser.mly" ( _1 ) -# 4612 "cil/src/frontc/cparser.ml" +# 4616 "cil/src/frontc/cparser.ml" : 'annotated_statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'annot_list) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'statement) in Obj.repr( -# 939 "cil/src/frontc/cparser.mly" +# 937 "cil/src/frontc/cparser.mly" ( _1 @ _2 ) -# 4620 "cil/src/frontc/cparser.ml" +# 4624 "cil/src/frontc/cparser.ml" : 'annotated_statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 943 "cil/src/frontc/cparser.mly" +# 941 "cil/src/frontc/cparser.mly" ( no_ghost [NOP _1] ) -# 4627 "cil/src/frontc/cparser.ml" - : 'statement)) -; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc * string list * Logic_ptree.spec) in - let _2 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in - Obj.repr( -# 945 "cil/src/frontc/cparser.mly" - ( (* TODO: Do not forget behavior list. *) - let loc,_bhv,spec = _1 in no_ghost [Cabs.CODE_SPEC (spec,loc)] @ _2) -# 4636 "cil/src/frontc/cparser.ml" +# 4631 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Lexing.position * string) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 948 "cil/src/frontc/cparser.mly" +# 943 "cil/src/frontc/cparser.mly" ( let bs = _2 in Cabshelper.continue_annot @@ -4650,34 +4645,34 @@ (fun () -> bs) "Skipping annotation" ) -# 4654 "cil/src/frontc/cparser.ml" +# 4649 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 960 "cil/src/frontc/cparser.mly" +# 955 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [COMPUTATION (smooth_expression _1,loc)]) -# 4663 "cil/src/frontc/cparser.ml" +# 4658 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.block * cabsloc * cabsloc) in Obj.repr( -# 962 "cil/src/frontc/cparser.mly" +# 957 "cil/src/frontc/cparser.mly" ( let (x,y,z) = _1 in no_ghost [BLOCK (x, y, z)]) -# 4670 "cil/src/frontc/cparser.ml" +# 4665 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 964 "cil/src/frontc/cparser.mly" +# 959 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [IF (smooth_expression _2, in_block _3, no_ghost_stmt (NOP loc), loc)]) -# 4681 "cil/src/frontc/cparser.ml" +# 4676 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -4685,21 +4680,21 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : 'annotated_statement) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 968 "cil/src/frontc/cparser.mly" +# 963 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [IF (smooth_expression _2, in_block _3, in_block _5, loc)]) -# 4693 "cil/src/frontc/cparser.ml" +# 4688 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 972 "cil/src/frontc/cparser.mly" +# 967 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [SWITCH (smooth_expression _2, in_block _3, loc)]) -# 4703 "cil/src/frontc/cparser.ml" +# 4698 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'opt_loop_annotations) in @@ -4707,10 +4702,10 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 976 "cil/src/frontc/cparser.mly" +# 971 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 2, Parsing.symbol_end_pos () in no_ghost [WHILE (_1, smooth_expression _3, in_block _4, loc)] ) -# 4714 "cil/src/frontc/cparser.ml" +# 4709 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : 'opt_loop_annotations) in @@ -4720,10 +4715,10 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 980 "cil/src/frontc/cparser.mly" +# 975 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 2, Parsing.symbol_end_pos () in no_ghost [DOWHILE (_1, smooth_expression _5, in_block _3, loc)]) -# 4727 "cil/src/frontc/cparser.ml" +# 4722 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 8 : 'opt_loop_annotations) in @@ -4735,34 +4730,34 @@ let _7 = (Parsing.peek_val __caml_parser_env 2 : Cabs.expression) in let _9 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 985 "cil/src/frontc/cparser.mly" +# 980 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 2, Parsing.symbol_end_pos () in no_ghost [FOR (_1, _4, _5, _7, in_block _9, loc)]) -# 4742 "cil/src/frontc/cparser.ml" +# 4737 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'id_or_typename_as_id) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'attribute_nocv_list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 988 "cil/src/frontc/cparser.mly" +# 983 "cil/src/frontc/cparser.mly" ((* The only attribute that should appear here is "unused". For now, we drop this on the floor, since unused labels are usually removed anyways by Rmtmps. *) let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 2 in no_ghost [LABEL (_1, in_block _4, loc)]) -# 4756 "cil/src/frontc/cparser.ml" +# 4751 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.expression) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 995 "cil/src/frontc/cparser.mly" +# 990 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.rhs_end_pos 3 in no_ghost [CASE (_2, in_block _4, loc)]) -# 4766 "cil/src/frontc/cparser.ml" +# 4761 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -4770,75 +4765,75 @@ let _4 = (Parsing.peek_val __caml_parser_env 2 : Cabs.expression) in let _6 = (Parsing.peek_val __caml_parser_env 0 : 'annotated_statement) in Obj.repr( -# 998 "cil/src/frontc/cparser.mly" +# 993 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.rhs_end_pos 5 in no_ghost [CASERANGE (_2, _4, in_block _6, loc)]) -# 4777 "cil/src/frontc/cparser.ml" +# 4772 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1001 "cil/src/frontc/cparser.mly" +# 996 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos(), Parsing.symbol_end_pos () in no_ghost [DEFAULT (no_ghost_stmt (NOP loc), loc)]) -# 4785 "cil/src/frontc/cparser.ml" +# 4780 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1003 "cil/src/frontc/cparser.mly" +# 998 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [RETURN ({ expr_loc = loc; expr_node = NOTHING}, loc)] ) -# 4796 "cil/src/frontc/cparser.ml" +# 4791 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1007 "cil/src/frontc/cparser.mly" +# 1002 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [RETURN (smooth_expression _2, loc)] ) -# 4808 "cil/src/frontc/cparser.ml" +# 4803 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1011 "cil/src/frontc/cparser.mly" +# 1006 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [BREAK loc] ) -# 4819 "cil/src/frontc/cparser.ml" +# 4814 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1015 "cil/src/frontc/cparser.mly" +# 1010 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [CONTINUE loc] ) -# 4830 "cil/src/frontc/cparser.ml" +# 4825 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'id_or_typename_as_id) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1019 "cil/src/frontc/cparser.mly" +# 1014 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [GOTO (_2, loc)] ) -# 4842 "cil/src/frontc/cparser.ml" +# 4837 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in @@ -4846,12 +4841,12 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1023 "cil/src/frontc/cparser.mly" +# 1018 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [COMPGOTO (smooth_expression _3, loc) ] ) -# 4855 "cil/src/frontc/cparser.ml" +# 4850 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : Cabs.cabsloc) in @@ -4861,19 +4856,19 @@ let _5 = (Parsing.peek_val __caml_parser_env 2 : 'asmoutputs) in let _7 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1027 "cil/src/frontc/cparser.mly" +# 1022 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in no_ghost [ASM (_2, _4, _5, loc)] ) -# 4870 "cil/src/frontc/cparser.ml" +# 4865 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1031 "cil/src/frontc/cparser.mly" +# 1026 "cil/src/frontc/cparser.mly" ( no_ghost [ASM ([], [fst _1], None, snd _1)]) -# 4877 "cil/src/frontc/cparser.ml" +# 4872 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -4882,7 +4877,7 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.block * cabsloc * cabsloc) in Obj.repr( -# 1032 "cil/src/frontc/cparser.mly" +# 1027 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in let loc_e = Parsing.rhs_start_pos 4, Parsing.rhs_end_pos 4 in @@ -4892,7 +4887,7 @@ no_ghost [TRY_EXCEPT (b, {expr_loc = loc_e; expr_node = COMMA _4}, h, loc)] ) -# 4896 "cil/src/frontc/cparser.ml" +# 4891 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in @@ -4900,7 +4895,7 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.block * cabsloc * cabsloc) in Obj.repr( -# 1041 "cil/src/frontc/cparser.mly" +# 1036 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos () in let b, _, _ = _2 in @@ -4908,74 +4903,74 @@ if not !Cprint.msvcMode then parse_error "try/finally in GCC code"; no_ghost [TRY_FINALLY (b, h, loc)] ) -# 4912 "cil/src/frontc/cparser.ml" +# 4907 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1048 "cil/src/frontc/cparser.mly" +# 1043 "cil/src/frontc/cparser.mly" ( no_ghost [NOP _2]) -# 4920 "cil/src/frontc/cparser.ml" +# 4915 "cil/src/frontc/cparser.ml" : 'statement)) ; (fun __caml_parser_env -> Obj.repr( -# 1052 "cil/src/frontc/cparser.mly" +# 1047 "cil/src/frontc/cparser.mly" ( [] ) -# 4926 "cil/src/frontc/cparser.ml" +# 4921 "cil/src/frontc/cparser.ml" : 'opt_loop_annotations)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annotations) in Obj.repr( -# 1053 "cil/src/frontc/cparser.mly" +# 1048 "cil/src/frontc/cparser.mly" ( _1 ) -# 4933 "cil/src/frontc/cparser.ml" +# 4928 "cil/src/frontc/cparser.ml" : 'opt_loop_annotations)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annotation) in Obj.repr( -# 1057 "cil/src/frontc/cparser.mly" +# 1052 "cil/src/frontc/cparser.mly" ( _1 ) -# 4940 "cil/src/frontc/cparser.ml" +# 4935 "cil/src/frontc/cparser.ml" : 'loop_annotations)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Logic_ptree.code_annot list * Cabs.cabsloc) in Obj.repr( -# 1069 "cil/src/frontc/cparser.mly" +# 1064 "cil/src/frontc/cparser.mly" ( fst _1 ) -# 4947 "cil/src/frontc/cparser.ml" +# 4942 "cil/src/frontc/cparser.ml" : 'loop_annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1073 "cil/src/frontc/cparser.mly" +# 1068 "cil/src/frontc/cparser.mly" ( FC_EXP _1 ) -# 4955 "cil/src/frontc/cparser.ml" +# 4950 "cil/src/frontc/cparser.ml" : 'for_clause)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.definition) in Obj.repr( -# 1074 "cil/src/frontc/cparser.mly" +# 1069 "cil/src/frontc/cparser.mly" ( FC_DECL _1 ) -# 4962 "cil/src/frontc/cparser.ml" +# 4957 "cil/src/frontc/cparser.ml" : 'for_clause)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.init_name list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1079 "cil/src/frontc/cparser.mly" +# 1074 "cil/src/frontc/cparser.mly" ( doDeclaration None ((snd _1)) (fst _1) _2 ) -# 4971 "cil/src/frontc/cparser.ml" +# 4966 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1081 "cil/src/frontc/cparser.mly" +# 1076 "cil/src/frontc/cparser.mly" ( doDeclaration None ((snd _1)) (fst _1) [] ) -# 4979 "cil/src/frontc/cparser.ml" +# 4974 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Lexing.position * string) in @@ -4983,249 +4978,249 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.init_name list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1083 "cil/src/frontc/cparser.mly" +# 1078 "cil/src/frontc/cparser.mly" ( doDeclaration (Some _1) ((snd _2)) (fst _2) _3 ) -# 4989 "cil/src/frontc/cparser.ml" +# 4984 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Lexing.position * string) in let _2 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1085 "cil/src/frontc/cparser.mly" +# 1080 "cil/src/frontc/cparser.mly" ( doDeclaration (Some _1) ((snd _2)) (fst _2) [] ) -# 4998 "cil/src/frontc/cparser.ml" +# 4993 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.init_name) in Obj.repr( -# 1088 "cil/src/frontc/cparser.mly" +# 1083 "cil/src/frontc/cparser.mly" ( [_1] ) -# 5005 "cil/src/frontc/cparser.ml" +# 5000 "cil/src/frontc/cparser.ml" : Cabs.init_name list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.init_name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.init_name list) in Obj.repr( -# 1089 "cil/src/frontc/cparser.mly" +# 1084 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 5013 "cil/src/frontc/cparser.ml" +# 5008 "cil/src/frontc/cparser.ml" : Cabs.init_name list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name) in Obj.repr( -# 1093 "cil/src/frontc/cparser.mly" +# 1088 "cil/src/frontc/cparser.mly" ( (_1, NO_INIT) ) -# 5020 "cil/src/frontc/cparser.ml" +# 5015 "cil/src/frontc/cparser.ml" : Cabs.init_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.init_expression) in Obj.repr( -# 1095 "cil/src/frontc/cparser.mly" +# 1090 "cil/src/frontc/cparser.mly" ( (_1, _3) ) -# 5028 "cil/src/frontc/cparser.ml" +# 5023 "cil/src/frontc/cparser.ml" : Cabs.init_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1100 "cil/src/frontc/cparser.mly" +# 1095 "cil/src/frontc/cparser.mly" ( SpecTypedef :: _2, _1 ) -# 5036 "cil/src/frontc/cparser.ml" +# 5031 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1101 "cil/src/frontc/cparser.mly" +# 1096 "cil/src/frontc/cparser.mly" ( SpecStorage EXTERN :: _2, _1 ) -# 5044 "cil/src/frontc/cparser.ml" +# 5039 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1102 "cil/src/frontc/cparser.mly" +# 1097 "cil/src/frontc/cparser.mly" ( SpecStorage STATIC :: _2, _1 ) -# 5052 "cil/src/frontc/cparser.ml" +# 5047 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1103 "cil/src/frontc/cparser.mly" +# 1098 "cil/src/frontc/cparser.mly" ( SpecStorage AUTO :: _2, _1 ) -# 5060 "cil/src/frontc/cparser.ml" +# 5055 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1104 "cil/src/frontc/cparser.mly" +# 1099 "cil/src/frontc/cparser.mly" ( SpecStorage REGISTER :: _2, _1) -# 5068 "cil/src/frontc/cparser.ml" +# 5063 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : typeSpecifier * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt_no_named) in Obj.repr( -# 1106 "cil/src/frontc/cparser.mly" +# 1101 "cil/src/frontc/cparser.mly" ( SpecType (fst _1) :: _2, snd _1 ) -# 5076 "cil/src/frontc/cparser.ml" +# 5071 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1108 "cil/src/frontc/cparser.mly" +# 1103 "cil/src/frontc/cparser.mly" ( SpecInline :: _2, _1 ) -# 5084 "cil/src/frontc/cparser.ml" +# 5079 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1109 "cil/src/frontc/cparser.mly" +# 1104 "cil/src/frontc/cparser.mly" ( (fst _1) :: _2, snd _1 ) -# 5092 "cil/src/frontc/cparser.ml" +# 5087 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'attribute_nocv) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec_list_opt) in Obj.repr( -# 1110 "cil/src/frontc/cparser.mly" +# 1105 "cil/src/frontc/cparser.mly" ( SpecAttr (fst _1) :: _2, snd _1 ) -# 5100 "cil/src/frontc/cparser.ml" +# 5095 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 1112 "cil/src/frontc/cparser.mly" +# 1107 "cil/src/frontc/cparser.mly" ( [ SpecPattern _3 ], _1 ) -# 5109 "cil/src/frontc/cparser.ml" +# 5104 "cil/src/frontc/cparser.ml" : spec_elem list * cabsloc)) ; (fun __caml_parser_env -> Obj.repr( -# 1117 "cil/src/frontc/cparser.mly" +# 1112 "cil/src/frontc/cparser.mly" ( [] ) -# 5115 "cil/src/frontc/cparser.ml" +# 5110 "cil/src/frontc/cparser.ml" : 'decl_spec_list_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : spec_elem list * cabsloc) in Obj.repr( -# 1118 "cil/src/frontc/cparser.mly" +# 1113 "cil/src/frontc/cparser.mly" ( fst _1 ) -# 5122 "cil/src/frontc/cparser.ml" +# 5117 "cil/src/frontc/cparser.ml" : 'decl_spec_list_opt)) ; (fun __caml_parser_env -> Obj.repr( -# 1125 "cil/src/frontc/cparser.mly" +# 1120 "cil/src/frontc/cparser.mly" ( [] ) -# 5128 "cil/src/frontc/cparser.ml" +# 5123 "cil/src/frontc/cparser.ml" : 'decl_spec_list_opt_no_named)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : spec_elem list * cabsloc) in Obj.repr( -# 1126 "cil/src/frontc/cparser.mly" +# 1121 "cil/src/frontc/cparser.mly" ( fst _1 ) -# 5135 "cil/src/frontc/cparser.ml" +# 5130 "cil/src/frontc/cparser.ml" : 'decl_spec_list_opt_no_named)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1129 "cil/src/frontc/cparser.mly" +# 1124 "cil/src/frontc/cparser.mly" ( Tvoid, _1) -# 5142 "cil/src/frontc/cparser.ml" +# 5137 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1130 "cil/src/frontc/cparser.mly" +# 1125 "cil/src/frontc/cparser.mly" ( Tchar, _1 ) -# 5149 "cil/src/frontc/cparser.ml" +# 5144 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1131 "cil/src/frontc/cparser.mly" +# 1126 "cil/src/frontc/cparser.mly" ( Tbool, _1 ) -# 5156 "cil/src/frontc/cparser.ml" +# 5151 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1132 "cil/src/frontc/cparser.mly" +# 1127 "cil/src/frontc/cparser.mly" ( Tshort, _1 ) -# 5163 "cil/src/frontc/cparser.ml" +# 5158 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1133 "cil/src/frontc/cparser.mly" +# 1128 "cil/src/frontc/cparser.mly" ( Tint, _1 ) -# 5170 "cil/src/frontc/cparser.ml" +# 5165 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1134 "cil/src/frontc/cparser.mly" +# 1129 "cil/src/frontc/cparser.mly" ( Tlong, _1 ) -# 5177 "cil/src/frontc/cparser.ml" +# 5172 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1135 "cil/src/frontc/cparser.mly" +# 1130 "cil/src/frontc/cparser.mly" ( Tint64, _1 ) -# 5184 "cil/src/frontc/cparser.ml" +# 5179 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1136 "cil/src/frontc/cparser.mly" +# 1131 "cil/src/frontc/cparser.mly" ( Tfloat, _1 ) -# 5191 "cil/src/frontc/cparser.ml" +# 5186 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1137 "cil/src/frontc/cparser.mly" +# 1132 "cil/src/frontc/cparser.mly" ( Tdouble, _1 ) -# 5198 "cil/src/frontc/cparser.ml" +# 5193 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1138 "cil/src/frontc/cparser.mly" +# 1133 "cil/src/frontc/cparser.mly" ( Tsigned, _1 ) -# 5205 "cil/src/frontc/cparser.ml" +# 5200 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1139 "cil/src/frontc/cparser.mly" +# 1134 "cil/src/frontc/cparser.mly" ( Tunsigned, _1 ) -# 5212 "cil/src/frontc/cparser.ml" +# 5207 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1141 "cil/src/frontc/cparser.mly" +# 1136 "cil/src/frontc/cparser.mly" ( Tstruct (_2, None, []), _1 ) -# 5220 "cil/src/frontc/cparser.ml" +# 5215 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'just_attributes) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1143 "cil/src/frontc/cparser.mly" +# 1138 "cil/src/frontc/cparser.mly" ( Tstruct (_3, None, _2), _1 ) -# 5229 "cil/src/frontc/cparser.ml" +# 5224 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -5234,9 +5229,9 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1145 "cil/src/frontc/cparser.mly" +# 1140 "cil/src/frontc/cparser.mly" ( Tstruct (_2, Some _4, []), _1 ) -# 5240 "cil/src/frontc/cparser.ml" +# 5235 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in @@ -5244,9 +5239,9 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1147 "cil/src/frontc/cparser.mly" +# 1142 "cil/src/frontc/cparser.mly" ( Tstruct ("", Some _3, []), _1 ) -# 5250 "cil/src/frontc/cparser.ml" +# 5245 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -5256,9 +5251,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1149 "cil/src/frontc/cparser.mly" +# 1144 "cil/src/frontc/cparser.mly" ( Tstruct (_3, Some _5, _2), _1 ) -# 5262 "cil/src/frontc/cparser.ml" +# 5257 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -5267,17 +5262,17 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1151 "cil/src/frontc/cparser.mly" +# 1146 "cil/src/frontc/cparser.mly" ( Tstruct ("", Some _4, _2), _1 ) -# 5273 "cil/src/frontc/cparser.ml" +# 5268 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1153 "cil/src/frontc/cparser.mly" +# 1148 "cil/src/frontc/cparser.mly" ( Tunion (_2, None, []), _1 ) -# 5281 "cil/src/frontc/cparser.ml" +# 5276 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -5286,9 +5281,9 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1155 "cil/src/frontc/cparser.mly" +# 1150 "cil/src/frontc/cparser.mly" ( Tunion (_2, Some _4, []), _1 ) -# 5292 "cil/src/frontc/cparser.ml" +# 5287 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in @@ -5296,9 +5291,9 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1157 "cil/src/frontc/cparser.mly" +# 1152 "cil/src/frontc/cparser.mly" ( Tunion ("", Some _3, []), _1 ) -# 5302 "cil/src/frontc/cparser.ml" +# 5297 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -5308,9 +5303,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1159 "cil/src/frontc/cparser.mly" +# 1154 "cil/src/frontc/cparser.mly" ( Tunion (_3, Some _5, _2), _1 ) -# 5314 "cil/src/frontc/cparser.ml" +# 5309 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -5319,17 +5314,17 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.field_group list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1161 "cil/src/frontc/cparser.mly" +# 1156 "cil/src/frontc/cparser.mly" ( Tunion ("", Some _4, _2), _1 ) -# 5325 "cil/src/frontc/cparser.ml" +# 5320 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1163 "cil/src/frontc/cparser.mly" +# 1158 "cil/src/frontc/cparser.mly" ( Tenum (_2, None, []), _1 ) -# 5333 "cil/src/frontc/cparser.ml" +# 5328 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -5339,9 +5334,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : 'maybecomma) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1165 "cil/src/frontc/cparser.mly" +# 1160 "cil/src/frontc/cparser.mly" ( Tenum (_2, Some _4, []), _1 ) -# 5345 "cil/src/frontc/cparser.ml" +# 5340 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -5350,9 +5345,9 @@ let _4 = (Parsing.peek_val __caml_parser_env 1 : 'maybecomma) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1167 "cil/src/frontc/cparser.mly" +# 1162 "cil/src/frontc/cparser.mly" ( Tenum ("", Some _3, []), _1 ) -# 5356 "cil/src/frontc/cparser.ml" +# 5351 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : Cabs.cabsloc) in @@ -5363,9 +5358,9 @@ let _6 = (Parsing.peek_val __caml_parser_env 1 : 'maybecomma) in let _7 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1169 "cil/src/frontc/cparser.mly" +# 1164 "cil/src/frontc/cparser.mly" ( Tenum (_3, Some _5, _2), _1 ) -# 5369 "cil/src/frontc/cparser.ml" +# 5364 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : Cabs.cabsloc) in @@ -5375,61 +5370,61 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : 'maybecomma) in let _6 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1171 "cil/src/frontc/cparser.mly" +# 1166 "cil/src/frontc/cparser.mly" ( Tenum ("", Some _4, _2), _1 ) -# 5381 "cil/src/frontc/cparser.ml" +# 5376 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1172 "cil/src/frontc/cparser.mly" +# 1167 "cil/src/frontc/cparser.mly" ( (Tnamed _1, (Parsing.symbol_start_pos (), Parsing.symbol_end_pos())) ) -# 5390 "cil/src/frontc/cparser.ml" +# 5385 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression) in Obj.repr( -# 1175 "cil/src/frontc/cparser.mly" +# 1170 "cil/src/frontc/cparser.mly" ( TtypeofE _3, _1 ) -# 5399 "cil/src/frontc/cparser.ml" +# 5394 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 1176 "cil/src/frontc/cparser.mly" +# 1171 "cil/src/frontc/cparser.mly" ( let s, d = _3 in TtypeofT (s, d), _1 ) -# 5409 "cil/src/frontc/cparser.ml" +# 5404 "cil/src/frontc/cparser.ml" : typeSpecifier * cabsloc)) ; (fun __caml_parser_env -> Obj.repr( -# 1182 "cil/src/frontc/cparser.mly" +# 1177 "cil/src/frontc/cparser.mly" ( [] ) -# 5415 "cil/src/frontc/cparser.ml" +# 5410 "cil/src/frontc/cparser.ml" : Cabs.field_group list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.field_group list) in Obj.repr( -# 1184 "cil/src/frontc/cparser.mly" +# 1179 "cil/src/frontc/cparser.mly" ( FIELD (fst _1, [(missingFieldDecl, None)]) :: _3 ) -# 5425 "cil/src/frontc/cparser.ml" +# 5420 "cil/src/frontc/cparser.ml" : Cabs.field_group list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.field_group list) in Obj.repr( -# 1188 "cil/src/frontc/cparser.mly" +# 1183 "cil/src/frontc/cparser.mly" ( _2 ) -# 5433 "cil/src/frontc/cparser.ml" +# 5428 "cil/src/frontc/cparser.ml" : Cabs.field_group list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : spec_elem list * cabsloc) in @@ -5437,127 +5432,127 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.field_group list) in Obj.repr( -# 1190 "cil/src/frontc/cparser.mly" +# 1185 "cil/src/frontc/cparser.mly" ( FIELD (fst _1, _2) :: _4 ) -# 5444 "cil/src/frontc/cparser.ml" +# 5439 "cil/src/frontc/cparser.ml" : Cabs.field_group list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'pragma) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.field_group list) in Obj.repr( -# 1193 "cil/src/frontc/cparser.mly" +# 1188 "cil/src/frontc/cparser.mly" ( _2 ) -# 5452 "cil/src/frontc/cparser.ml" +# 5447 "cil/src/frontc/cparser.ml" : Cabs.field_group list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.field_group list) in Obj.repr( -# 1196 "cil/src/frontc/cparser.mly" +# 1191 "cil/src/frontc/cparser.mly" ( _3 ) -# 5460 "cil/src/frontc/cparser.ml" +# 5455 "cil/src/frontc/cparser.ml" : Cabs.field_group list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name * expression option) in Obj.repr( -# 1199 "cil/src/frontc/cparser.mly" +# 1194 "cil/src/frontc/cparser.mly" ( [_1] ) -# 5467 "cil/src/frontc/cparser.ml" +# 5462 "cil/src/frontc/cparser.ml" : (Cabs.name * expression option) list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.name * expression option) in let _3 = (Parsing.peek_val __caml_parser_env 0 : (Cabs.name * expression option) list) in Obj.repr( -# 1200 "cil/src/frontc/cparser.mly" +# 1195 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 5475 "cil/src/frontc/cparser.ml" +# 5470 "cil/src/frontc/cparser.ml" : (Cabs.name * expression option) list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name) in Obj.repr( -# 1203 "cil/src/frontc/cparser.mly" +# 1198 "cil/src/frontc/cparser.mly" ( (_1, None) ) -# 5482 "cil/src/frontc/cparser.ml" +# 5477 "cil/src/frontc/cparser.ml" : Cabs.name * expression option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.name) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1205 "cil/src/frontc/cparser.mly" +# 1200 "cil/src/frontc/cparser.mly" ( let (n,decl,al,loc) = _1 in let al' = al @ _4 in ((n,decl,al',loc), Some _3) ) -# 5493 "cil/src/frontc/cparser.ml" +# 5488 "cil/src/frontc/cparser.ml" : Cabs.name * expression option)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression) in Obj.repr( -# 1208 "cil/src/frontc/cparser.mly" +# 1203 "cil/src/frontc/cparser.mly" ( (missingFieldDecl, Some _2) ) -# 5500 "cil/src/frontc/cparser.ml" +# 5495 "cil/src/frontc/cparser.ml" : Cabs.name * expression option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.enum_item) in Obj.repr( -# 1212 "cil/src/frontc/cparser.mly" +# 1207 "cil/src/frontc/cparser.mly" ([_1]) -# 5507 "cil/src/frontc/cparser.ml" +# 5502 "cil/src/frontc/cparser.ml" : Cabs.enum_item list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.enum_item list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.enum_item) in Obj.repr( -# 1213 "cil/src/frontc/cparser.mly" +# 1208 "cil/src/frontc/cparser.mly" (_1 @ [_3]) -# 5515 "cil/src/frontc/cparser.ml" +# 5510 "cil/src/frontc/cparser.ml" : Cabs.enum_item list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.enum_item list) in Obj.repr( -# 1214 "cil/src/frontc/cparser.mly" +# 1209 "cil/src/frontc/cparser.mly" ( _1 ) -# 5522 "cil/src/frontc/cparser.ml" +# 5517 "cil/src/frontc/cparser.ml" : Cabs.enum_item list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1217 "cil/src/frontc/cparser.mly" +# 1212 "cil/src/frontc/cparser.mly" ( let loc = Parsing.symbol_start_pos (), Parsing.symbol_end_pos() in (_1, { expr_node = NOTHING; expr_loc = loc }, loc) ) -# 5532 "cil/src/frontc/cparser.ml" +# 5527 "cil/src/frontc/cparser.ml" : Cabs.enum_item)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression) in Obj.repr( -# 1221 "cil/src/frontc/cparser.mly" +# 1216 "cil/src/frontc/cparser.mly" ( (_1, _3, (Parsing.symbol_start_pos (),Parsing.symbol_end_pos())) ) -# 5542 "cil/src/frontc/cparser.ml" +# 5537 "cil/src/frontc/cparser.ml" : Cabs.enum_item)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : attribute list list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : string * Cabs.decl_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1228 "cil/src/frontc/cparser.mly" +# 1223 "cil/src/frontc/cparser.mly" ( let (n, decl) = _2 in (n, applyPointer (fst _1) decl, _3, (snd _1)) ) -# 5553 "cil/src/frontc/cparser.ml" +# 5548 "cil/src/frontc/cparser.ml" : Cabs.name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.attribute list) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'comma_expression_opt) in Obj.repr( -# 1235 "cil/src/frontc/cparser.mly" +# 1230 "cil/src/frontc/cparser.mly" ( _1,_2 ) -# 5561 "cil/src/frontc/cparser.ml" +# 5556 "cil/src/frontc/cparser.ml" : 'attributes_or_static)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'attribute) in @@ -5565,150 +5560,150 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 1236 "cil/src/frontc/cparser.mly" +# 1231 "cil/src/frontc/cparser.mly" ( fst _1::_2 @ ["static",[]], smooth_expression _4 ) -# 5573 "cil/src/frontc/cparser.ml" +# 5568 "cil/src/frontc/cparser.ml" : 'attributes_or_static)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.attribute list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.expression list) in Obj.repr( -# 1239 "cil/src/frontc/cparser.mly" +# 1234 "cil/src/frontc/cparser.mly" ( ("static",[]) :: _2, smooth_expression _3 ) -# 5584 "cil/src/frontc/cparser.ml" +# 5579 "cil/src/frontc/cparser.ml" : 'attributes_or_static)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1247 "cil/src/frontc/cparser.mly" +# 1242 "cil/src/frontc/cparser.mly" ( (_1, JUSTBASE) ) -# 5591 "cil/src/frontc/cparser.ml" +# 5586 "cil/src/frontc/cparser.ml" : string * Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.attribute list) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.name) in Obj.repr( -# 1250 "cil/src/frontc/cparser.mly" +# 1245 "cil/src/frontc/cparser.mly" ( let (n,decl,al,_) = _3 in (n, PARENTYPE(_2,decl,al)) ) -# 5601 "cil/src/frontc/cparser.ml" +# 5596 "cil/src/frontc/cparser.ml" : string * Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : string * Cabs.decl_type) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'attributes_or_static) in Obj.repr( -# 1254 "cil/src/frontc/cparser.mly" +# 1249 "cil/src/frontc/cparser.mly" ( let (n, decl) = _1 in let (attrs, size) = _3 in (n, ARRAY(decl, attrs, size)) ) -# 5611 "cil/src/frontc/cparser.ml" +# 5606 "cil/src/frontc/cparser.ml" : string * Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : string * Cabs.decl_type) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'parameter_list_startscope) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'rest_par_list) in Obj.repr( -# 1258 "cil/src/frontc/cparser.mly" +# 1253 "cil/src/frontc/cparser.mly" ( let (n, decl) = _1 in let (params, isva) = _3 in !Lexerhack.pop_context (); (n, PROTO(decl, params, isva)) ) -# 5624 "cil/src/frontc/cparser.ml" +# 5619 "cil/src/frontc/cparser.ml" : string * Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1265 "cil/src/frontc/cparser.mly" +# 1260 "cil/src/frontc/cparser.mly" ( !Lexerhack.push_context () ) -# 5631 "cil/src/frontc/cparser.ml" +# 5626 "cil/src/frontc/cparser.ml" : 'parameter_list_startscope)) ; (fun __caml_parser_env -> Obj.repr( -# 1268 "cil/src/frontc/cparser.mly" +# 1263 "cil/src/frontc/cparser.mly" ( ([], false) ) -# 5637 "cil/src/frontc/cparser.ml" +# 5632 "cil/src/frontc/cparser.ml" : 'rest_par_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.single_name) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'rest_par_list1) in Obj.repr( -# 1269 "cil/src/frontc/cparser.mly" +# 1264 "cil/src/frontc/cparser.mly" ( let (params, isva) = _2 in (_1 :: params, isva) ) -# 5647 "cil/src/frontc/cparser.ml" +# 5642 "cil/src/frontc/cparser.ml" : 'rest_par_list)) ; (fun __caml_parser_env -> Obj.repr( -# 1274 "cil/src/frontc/cparser.mly" +# 1269 "cil/src/frontc/cparser.mly" ( ([], false) ) -# 5653 "cil/src/frontc/cparser.ml" +# 5648 "cil/src/frontc/cparser.ml" : 'rest_par_list1)) ; (fun __caml_parser_env -> Obj.repr( -# 1275 "cil/src/frontc/cparser.mly" +# 1270 "cil/src/frontc/cparser.mly" ( ([], true) ) -# 5659 "cil/src/frontc/cparser.ml" +# 5654 "cil/src/frontc/cparser.ml" : 'rest_par_list1)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.single_name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'rest_par_list1) in Obj.repr( -# 1276 "cil/src/frontc/cparser.mly" +# 1271 "cil/src/frontc/cparser.mly" ( let (params, isva) = _3 in (_2 :: params, isva) ) -# 5669 "cil/src/frontc/cparser.ml" +# 5664 "cil/src/frontc/cparser.ml" : 'rest_par_list1)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name) in Obj.repr( -# 1283 "cil/src/frontc/cparser.mly" +# 1278 "cil/src/frontc/cparser.mly" ( (fst _1, _2) ) -# 5677 "cil/src/frontc/cparser.ml" +# 5672 "cil/src/frontc/cparser.ml" : Cabs.single_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.decl_type * Cabs.attribute list) in Obj.repr( -# 1284 "cil/src/frontc/cparser.mly" +# 1279 "cil/src/frontc/cparser.mly" ( let d, a = _2 in (fst _1, ("", d, a, (*CEA*) cabslu)) ) -# 5686 "cil/src/frontc/cparser.ml" +# 5681 "cil/src/frontc/cparser.ml" : Cabs.single_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : spec_elem list * cabsloc) in Obj.repr( -# 1286 "cil/src/frontc/cparser.mly" +# 1281 "cil/src/frontc/cparser.mly" ( (fst _1, ("", JUSTBASE, [], (*CEA*) cabslu)) ) -# 5693 "cil/src/frontc/cparser.ml" +# 5688 "cil/src/frontc/cparser.ml" : Cabs.single_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.single_name) in Obj.repr( -# 1287 "cil/src/frontc/cparser.mly" +# 1282 "cil/src/frontc/cparser.mly" ( _2 ) -# 5701 "cil/src/frontc/cparser.ml" +# 5696 "cil/src/frontc/cparser.ml" : Cabs.single_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : attribute list list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'direct_old_proto_decl) in Obj.repr( -# 1292 "cil/src/frontc/cparser.mly" +# 1287 "cil/src/frontc/cparser.mly" ( let (n, decl, a) = _2 in (n, applyPointer (fst _1) decl, a, snd _1) ) -# 5712 "cil/src/frontc/cparser.ml" +# 5707 "cil/src/frontc/cparser.ml" : Cabs.name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : string * Cabs.decl_type) in @@ -5716,53 +5711,53 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : string list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'old_pardef_list) in Obj.repr( -# 1300 "cil/src/frontc/cparser.mly" +# 1295 "cil/src/frontc/cparser.mly" ( let par_decl, isva = doOldParDecl _3 _5 in let n, decl = _1 in (n, PROTO(decl, par_decl, isva), []) ) -# 5726 "cil/src/frontc/cparser.ml" +# 5721 "cil/src/frontc/cparser.ml" : 'direct_old_proto_decl)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string * Cabs.decl_type) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1305 "cil/src/frontc/cparser.mly" +# 1300 "cil/src/frontc/cparser.mly" ( let n, decl = _1 in (n, PROTO(decl, [], false), []) ) -# 5736 "cil/src/frontc/cparser.ml" +# 5731 "cil/src/frontc/cparser.ml" : 'direct_old_proto_decl)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1319 "cil/src/frontc/cparser.mly" +# 1314 "cil/src/frontc/cparser.mly" ( [_1] ) -# 5743 "cil/src/frontc/cparser.ml" +# 5738 "cil/src/frontc/cparser.ml" : string list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string list) in Obj.repr( -# 1320 "cil/src/frontc/cparser.mly" +# 1315 "cil/src/frontc/cparser.mly" ( _1::_3 ) -# 5751 "cil/src/frontc/cparser.ml" +# 5746 "cil/src/frontc/cparser.ml" : string list)) ; (fun __caml_parser_env -> Obj.repr( -# 1324 "cil/src/frontc/cparser.mly" +# 1319 "cil/src/frontc/cparser.mly" ( ([], false) ) -# 5757 "cil/src/frontc/cparser.ml" +# 5752 "cil/src/frontc/cparser.ml" : 'old_pardef_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'old_pardef) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1326 "cil/src/frontc/cparser.mly" +# 1321 "cil/src/frontc/cparser.mly" ( ([(fst _1, _2)], true) ) -# 5766 "cil/src/frontc/cparser.ml" +# 5761 "cil/src/frontc/cparser.ml" : 'old_pardef_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : spec_elem list * cabsloc) in @@ -5770,147 +5765,147 @@ let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'old_pardef_list) in Obj.repr( -# 1328 "cil/src/frontc/cparser.mly" +# 1323 "cil/src/frontc/cparser.mly" ( let rest, isva = _4 in ((fst _1, _2) :: rest, isva) ) -# 5778 "cil/src/frontc/cparser.ml" +# 5773 "cil/src/frontc/cparser.ml" : 'old_pardef_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name) in Obj.repr( -# 1334 "cil/src/frontc/cparser.mly" +# 1329 "cil/src/frontc/cparser.mly" ( [_1] ) -# 5785 "cil/src/frontc/cparser.ml" +# 5780 "cil/src/frontc/cparser.ml" : 'old_pardef)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'old_pardef) in Obj.repr( -# 1335 "cil/src/frontc/cparser.mly" +# 1330 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 5793 "cil/src/frontc/cparser.ml" +# 5788 "cil/src/frontc/cparser.ml" : 'old_pardef)) ; (fun __caml_parser_env -> Obj.repr( -# 1336 "cil/src/frontc/cparser.mly" +# 1331 "cil/src/frontc/cparser.mly" ( [] ) -# 5799 "cil/src/frontc/cparser.ml" +# 5794 "cil/src/frontc/cparser.ml" : 'old_pardef)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.attribute list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : attribute list list * cabsloc) in Obj.repr( -# 1341 "cil/src/frontc/cparser.mly" +# 1336 "cil/src/frontc/cparser.mly" ( _2 :: fst _3, _1 ) -# 5808 "cil/src/frontc/cparser.ml" +# 5803 "cil/src/frontc/cparser.ml" : attribute list list * cabsloc)) ; (fun __caml_parser_env -> Obj.repr( -# 1344 "cil/src/frontc/cparser.mly" +# 1339 "cil/src/frontc/cparser.mly" ( let l = currentLoc () in ([], l) ) -# 5815 "cil/src/frontc/cparser.ml" +# 5810 "cil/src/frontc/cparser.ml" : attribute list list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : attribute list list * cabsloc) in Obj.repr( -# 1346 "cil/src/frontc/cparser.mly" +# 1341 "cil/src/frontc/cparser.mly" ( _1 ) -# 5822 "cil/src/frontc/cparser.ml" +# 5817 "cil/src/frontc/cparser.ml" : attribute list list * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.decl_type * Cabs.attribute list) in Obj.repr( -# 1350 "cil/src/frontc/cparser.mly" +# 1345 "cil/src/frontc/cparser.mly" ( let d, a = _2 in if a <> [] then parse_error "attributes in type name" ; (fst _1, d) ) -# 5833 "cil/src/frontc/cparser.ml" +# 5828 "cil/src/frontc/cparser.ml" : Cabs.spec_elem list * Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : spec_elem list * cabsloc) in Obj.repr( -# 1354 "cil/src/frontc/cparser.mly" +# 1349 "cil/src/frontc/cparser.mly" ( (fst _1, JUSTBASE) ) -# 5840 "cil/src/frontc/cparser.ml" +# 5835 "cil/src/frontc/cparser.ml" : Cabs.spec_elem list * Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : attribute list list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.decl_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1357 "cil/src/frontc/cparser.mly" +# 1352 "cil/src/frontc/cparser.mly" ( applyPointer (fst _1) _2, _3 ) -# 5849 "cil/src/frontc/cparser.ml" +# 5844 "cil/src/frontc/cparser.ml" : Cabs.decl_type * Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : attribute list list * cabsloc) in Obj.repr( -# 1358 "cil/src/frontc/cparser.mly" +# 1353 "cil/src/frontc/cparser.mly" ( applyPointer (fst _1) JUSTBASE, [] ) -# 5856 "cil/src/frontc/cparser.ml" +# 5851 "cil/src/frontc/cparser.ml" : Cabs.decl_type * Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.attribute list) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.decl_type * Cabs.attribute list) in Obj.repr( -# 1365 "cil/src/frontc/cparser.mly" +# 1360 "cil/src/frontc/cparser.mly" ( let d, a = _3 in PARENTYPE (_2, d, a) ) -# 5867 "cil/src/frontc/cparser.ml" +# 5862 "cil/src/frontc/cparser.ml" : Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in Obj.repr( -# 1370 "cil/src/frontc/cparser.mly" +# 1365 "cil/src/frontc/cparser.mly" ( JUSTBASE ) -# 5874 "cil/src/frontc/cparser.ml" +# 5869 "cil/src/frontc/cparser.ml" : Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.decl_type) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'comma_expression_opt) in Obj.repr( -# 1373 "cil/src/frontc/cparser.mly" +# 1368 "cil/src/frontc/cparser.mly" ( ARRAY(_1, [], _3) ) -# 5882 "cil/src/frontc/cparser.ml" +# 5877 "cil/src/frontc/cparser.ml" : Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.decl_type) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'parameter_list_startscope) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'rest_par_list) in Obj.repr( -# 1376 "cil/src/frontc/cparser.mly" +# 1371 "cil/src/frontc/cparser.mly" ( let (params, isva) = _3 in !Lexerhack.pop_context (); PROTO (_1, params, isva) ) -# 5894 "cil/src/frontc/cparser.ml" +# 5889 "cil/src/frontc/cparser.ml" : Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.decl_type) in Obj.repr( -# 1382 "cil/src/frontc/cparser.mly" +# 1377 "cil/src/frontc/cparser.mly" ( _1 ) -# 5901 "cil/src/frontc/cparser.ml" +# 5896 "cil/src/frontc/cparser.ml" : Cabs.decl_type)) ; (fun __caml_parser_env -> Obj.repr( -# 1383 "cil/src/frontc/cparser.mly" +# 1378 "cil/src/frontc/cparser.mly" ( JUSTBASE ) -# 5907 "cil/src/frontc/cparser.ml" +# 5902 "cil/src/frontc/cparser.ml" : Cabs.decl_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Lexing.position * string) in let _2 = (Parsing.peek_val __caml_parser_env 1 : cabsloc * spec_elem list * name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : Cabs.block * cabsloc * cabsloc) in Obj.repr( -# 1387 "cil/src/frontc/cparser.mly" +# 1382 "cil/src/frontc/cparser.mly" ( let (loc, specs, decl) = _2 in let spec = @@ -5924,13 +5919,13 @@ * announceFunctionName *) doFunctionDef spec loc (trd3 _3) specs decl (fst3 _3) ) -# 5928 "cil/src/frontc/cparser.ml" +# 5923 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : cabsloc * spec_elem list * name) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.block * cabsloc * cabsloc) in Obj.repr( -# 1401 "cil/src/frontc/cparser.mly" +# 1396 "cil/src/frontc/cparser.mly" ( let (loc, specs, decl) = _1 in currentFunctionName := "<__FUNCTION__ used outside any functions>"; !Lexerhack.pop_context (); (* The context pushed by @@ -5938,34 +5933,34 @@ (*OCAMLYACC BUG??? Format.printf "%a@." d_cabsloc (trd3 $2);*) doFunctionDef None ((*handleLoc*) loc) (trd3 _2) specs decl (fst3 _2) ) -# 5942 "cil/src/frontc/cparser.ml" +# 5937 "cil/src/frontc/cparser.ml" : Cabs.definition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name) in Obj.repr( -# 1412 "cil/src/frontc/cparser.mly" +# 1407 "cil/src/frontc/cparser.mly" ( announceFunctionName _2; (fourth4 _2, fst _1, _2) ) -# 5952 "cil/src/frontc/cparser.ml" +# 5947 "cil/src/frontc/cparser.ml" : cabsloc * spec_elem list * name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : spec_elem list * cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.name) in Obj.repr( -# 1418 "cil/src/frontc/cparser.mly" +# 1413 "cil/src/frontc/cparser.mly" ( announceFunctionName _2; (snd _1, fst _1, _2) ) -# 5962 "cil/src/frontc/cparser.ml" +# 5957 "cil/src/frontc/cparser.ml" : cabsloc * spec_elem list * name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : string) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'parameter_list_startscope) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'rest_par_list) in Obj.repr( -# 1423 "cil/src/frontc/cparser.mly" +# 1418 "cil/src/frontc/cparser.mly" ( let (params, isva) = _3 in let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in let fdec = @@ -5974,7 +5969,7 @@ (* Default is int type *) let defSpec = [SpecType Tint] in (loc, defSpec, fdec) ) -# 5978 "cil/src/frontc/cparser.ml" +# 5973 "cil/src/frontc/cparser.ml" : cabsloc * spec_elem list * name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : string) in @@ -5982,7 +5977,7 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : string list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'old_pardef_list) in Obj.repr( -# 1434 "cil/src/frontc/cparser.mly" +# 1429 "cil/src/frontc/cparser.mly" ( (* Convert pardecl to new style *) let pardecl, isva = doOldParDecl _3 _5 in let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in @@ -5992,13 +5987,13 @@ (* Default is int type *) let defSpec = [SpecType Tint] in (loc, defSpec, fdec) ) -# 5996 "cil/src/frontc/cparser.ml" +# 5991 "cil/src/frontc/cparser.ml" : cabsloc * spec_elem list * name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1445 "cil/src/frontc/cparser.mly" +# 1440 "cil/src/frontc/cparser.mly" ( (* Make the function declarator *) let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in let fdec = (_1, PROTO(JUSTBASE, [], false), [], loc) in @@ -6006,64 +6001,64 @@ (* Default is int type *) let defSpec = [SpecType Tint] in (loc, defSpec, fdec) ) -# 6010 "cil/src/frontc/cparser.ml" +# 6005 "cil/src/frontc/cparser.ml" : cabsloc * spec_elem list * name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1456 "cil/src/frontc/cparser.mly" +# 1451 "cil/src/frontc/cparser.mly" ( SpecCV(CV_CONST), _1 ) -# 6017 "cil/src/frontc/cparser.ml" +# 6012 "cil/src/frontc/cparser.ml" : Cabs.spec_elem * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1457 "cil/src/frontc/cparser.mly" +# 1452 "cil/src/frontc/cparser.mly" ( SpecCV(CV_VOLATILE), _1 ) -# 6024 "cil/src/frontc/cparser.ml" +# 6019 "cil/src/frontc/cparser.ml" : Cabs.spec_elem * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1458 "cil/src/frontc/cparser.mly" +# 1453 "cil/src/frontc/cparser.mly" ( SpecCV(CV_RESTRICT), _1 ) -# 6031 "cil/src/frontc/cparser.ml" +# 6026 "cil/src/frontc/cparser.ml" : Cabs.spec_elem * cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1459 "cil/src/frontc/cparser.mly" +# 1454 "cil/src/frontc/cparser.mly" ( let annot, loc = _1 in SpecCV(CV_ATTRIBUTE_ANNOT annot), loc ) -# 6039 "cil/src/frontc/cparser.ml" +# 6034 "cil/src/frontc/cparser.ml" : Cabs.spec_elem * cabsloc)) ; (fun __caml_parser_env -> Obj.repr( -# 1465 "cil/src/frontc/cparser.mly" +# 1460 "cil/src/frontc/cparser.mly" ( []) -# 6045 "cil/src/frontc/cparser.ml" +# 6040 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'attribute) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1466 "cil/src/frontc/cparser.mly" +# 1461 "cil/src/frontc/cparser.mly" ( fst _1 :: _2 ) -# 6053 "cil/src/frontc/cparser.ml" +# 6048 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> Obj.repr( -# 1472 "cil/src/frontc/cparser.mly" +# 1467 "cil/src/frontc/cparser.mly" ( [] ) -# 6059 "cil/src/frontc/cparser.ml" +# 6054 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'attribute) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1473 "cil/src/frontc/cparser.mly" +# 1468 "cil/src/frontc/cparser.mly" ( fst _1 :: _2 ) -# 6067 "cil/src/frontc/cparser.ml" +# 6062 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : Cabs.cabsloc) in @@ -6071,338 +6066,338 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : string * cabsloc) in let _5 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1474 "cil/src/frontc/cparser.mly" +# 1469 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 3, Parsing.rhs_end_pos 3 in ("__asm__", [{ expr_node = CONSTANT(CONST_STRING (fst _3)); expr_loc = loc}]) :: _5 ) -# 6082 "cil/src/frontc/cparser.ml" +# 6077 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'paren_attr_list) in Obj.repr( -# 1485 "cil/src/frontc/cparser.mly" +# 1480 "cil/src/frontc/cparser.mly" ( ("__attribute__", _3), _1 ) -# 6091 "cil/src/frontc/cparser.ml" +# 6086 "cil/src/frontc/cparser.ml" : 'attribute_nocv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'paren_attr_list_ne) in Obj.repr( -# 1490 "cil/src/frontc/cparser.mly" +# 1485 "cil/src/frontc/cparser.mly" ( ("__declspec", _2), _1 ) -# 6099 "cil/src/frontc/cparser.ml" +# 6094 "cil/src/frontc/cparser.ml" : 'attribute_nocv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1491 "cil/src/frontc/cparser.mly" +# 1486 "cil/src/frontc/cparser.mly" ( (fst _1, []), snd _1 ) -# 6106 "cil/src/frontc/cparser.ml" +# 6101 "cil/src/frontc/cparser.ml" : 'attribute_nocv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1493 "cil/src/frontc/cparser.mly" +# 1488 "cil/src/frontc/cparser.mly" ( ("__thread",[]), _1 ) -# 6113 "cil/src/frontc/cparser.ml" +# 6108 "cil/src/frontc/cparser.ml" : 'attribute_nocv)) ; (fun __caml_parser_env -> Obj.repr( -# 1497 "cil/src/frontc/cparser.mly" +# 1492 "cil/src/frontc/cparser.mly" ( []) -# 6119 "cil/src/frontc/cparser.ml" +# 6114 "cil/src/frontc/cparser.ml" : 'attribute_nocv_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'attribute_nocv) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'attribute_nocv_list) in Obj.repr( -# 1498 "cil/src/frontc/cparser.mly" +# 1493 "cil/src/frontc/cparser.mly" ( fst _1 :: _2 ) -# 6127 "cil/src/frontc/cparser.ml" +# 6122 "cil/src/frontc/cparser.ml" : 'attribute_nocv_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'attribute_nocv) in Obj.repr( -# 1503 "cil/src/frontc/cparser.mly" +# 1498 "cil/src/frontc/cparser.mly" ( _1 ) -# 6134 "cil/src/frontc/cparser.ml" +# 6129 "cil/src/frontc/cparser.ml" : 'attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1504 "cil/src/frontc/cparser.mly" +# 1499 "cil/src/frontc/cparser.mly" ( ("const", []), _1 ) -# 6141 "cil/src/frontc/cparser.ml" +# 6136 "cil/src/frontc/cparser.ml" : 'attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1505 "cil/src/frontc/cparser.mly" +# 1500 "cil/src/frontc/cparser.mly" ( ("restrict",[]), _1 ) -# 6148 "cil/src/frontc/cparser.ml" +# 6143 "cil/src/frontc/cparser.ml" : 'attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1506 "cil/src/frontc/cparser.mly" +# 1501 "cil/src/frontc/cparser.mly" ( ("volatile",[]), _1 ) -# 6155 "cil/src/frontc/cparser.ml" +# 6150 "cil/src/frontc/cparser.ml" : 'attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1507 "cil/src/frontc/cparser.mly" +# 1502 "cil/src/frontc/cparser.mly" ( let annot, loc = _1 in ("$annot:" ^ annot, []), loc ) -# 6163 "cil/src/frontc/cparser.ml" +# 6158 "cil/src/frontc/cparser.ml" : 'attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'paren_attr_list) in Obj.repr( -# 1516 "cil/src/frontc/cparser.mly" +# 1511 "cil/src/frontc/cparser.mly" ( ("__attribute__", _3) ) -# 6172 "cil/src/frontc/cparser.ml" +# 6167 "cil/src/frontc/cparser.ml" : 'just_attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'paren_attr_list_ne) in Obj.repr( -# 1517 "cil/src/frontc/cparser.mly" +# 1512 "cil/src/frontc/cparser.mly" ( ("__declspec", _2) ) -# 6180 "cil/src/frontc/cparser.ml" +# 6175 "cil/src/frontc/cparser.ml" : 'just_attribute)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'just_attribute) in Obj.repr( -# 1523 "cil/src/frontc/cparser.mly" +# 1518 "cil/src/frontc/cparser.mly" ( [_1] ) -# 6187 "cil/src/frontc/cparser.ml" +# 6182 "cil/src/frontc/cparser.ml" : 'just_attributes)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'just_attribute) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'just_attributes) in Obj.repr( -# 1524 "cil/src/frontc/cparser.mly" +# 1519 "cil/src/frontc/cparser.mly" ( _1 :: _2 ) -# 6195 "cil/src/frontc/cparser.ml" +# 6190 "cil/src/frontc/cparser.ml" : 'just_attributes)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1529 "cil/src/frontc/cparser.mly" +# 1524 "cil/src/frontc/cparser.mly" ( PRAGMA (make_expr (VARIABLE ("")), _1) ) -# 6204 "cil/src/frontc/cparser.ml" +# 6199 "cil/src/frontc/cparser.ml" : 'pragma)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'attr) in Obj.repr( -# 1532 "cil/src/frontc/cparser.mly" +# 1527 "cil/src/frontc/cparser.mly" ( PRAGMA (_2, _1) ) -# 6212 "cil/src/frontc/cparser.ml" +# 6207 "cil/src/frontc/cparser.ml" : 'pragma)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'attr) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1533 "cil/src/frontc/cparser.mly" +# 1528 "cil/src/frontc/cparser.mly" ( PRAGMA (_2, _1) ) -# 6221 "cil/src/frontc/cparser.ml" +# 6216 "cil/src/frontc/cparser.ml" : 'pragma)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1534 "cil/src/frontc/cparser.mly" +# 1529 "cil/src/frontc/cparser.mly" ( PRAGMA (make_expr (VARIABLE (fst _1)), snd _1) ) -# 6230 "cil/src/frontc/cparser.ml" +# 6225 "cil/src/frontc/cparser.ml" : 'pragma)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1542 "cil/src/frontc/cparser.mly" +# 1537 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE _1) ) -# 6237 "cil/src/frontc/cparser.ml" +# 6232 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1543 "cil/src/frontc/cparser.mly" +# 1538 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE _1) ) -# 6244 "cil/src/frontc/cparser.ml" +# 6239 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1544 "cil/src/frontc/cparser.mly" +# 1539 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE ("default:" ^ fst _3)) ) -# 6252 "cil/src/frontc/cparser.ml" +# 6247 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1546 "cil/src/frontc/cparser.mly" +# 1541 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE "aconst") ) -# 6259 "cil/src/frontc/cparser.ml" +# 6254 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Cabs.cabsloc) in Obj.repr( -# 1548 "cil/src/frontc/cparser.mly" +# 1543 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE ("__noreturn__")) ) -# 6266 "cil/src/frontc/cparser.ml" +# 6261 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1549 "cil/src/frontc/cparser.mly" +# 1544 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE (_1 ^ ":" ^ fst _3)) ) -# 6274 "cil/src/frontc/cparser.ml" +# 6269 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1550 "cil/src/frontc/cparser.mly" +# 1545 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE (_1 ^ ":" ^ fst _3)) ) -# 6282 "cil/src/frontc/cparser.ml" +# 6277 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : string * Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1553 "cil/src/frontc/cparser.mly" +# 1548 "cil/src/frontc/cparser.mly" ( make_expr (VARIABLE (fst _1 ^ ":" ^ fst _3)) ) -# 6290 "cil/src/frontc/cparser.ml" +# 6285 "cil/src/frontc/cparser.ml" : 'var_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * Cabs.cabsloc) in Obj.repr( -# 1557 "cil/src/frontc/cparser.mly" +# 1552 "cil/src/frontc/cparser.mly" ( make_expr (CONSTANT(CONST_INT (fst _1))) ) -# 6297 "cil/src/frontc/cparser.ml" +# 6292 "cil/src/frontc/cparser.ml" : 'basic_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'var_attr) in Obj.repr( -# 1558 "cil/src/frontc/cparser.mly" +# 1553 "cil/src/frontc/cparser.mly" ( _1 ) -# 6304 "cil/src/frontc/cparser.ml" +# 6299 "cil/src/frontc/cparser.ml" : 'basic_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'basic_attr) in Obj.repr( -# 1561 "cil/src/frontc/cparser.mly" +# 1556 "cil/src/frontc/cparser.mly" ( [_1] ) -# 6311 "cil/src/frontc/cparser.ml" +# 6306 "cil/src/frontc/cparser.ml" : 'basic_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'basic_attr) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'basic_attr_list_ne) in Obj.repr( -# 1562 "cil/src/frontc/cparser.mly" +# 1557 "cil/src/frontc/cparser.mly" ( _1::_2 ) -# 6319 "cil/src/frontc/cparser.ml" +# 6314 "cil/src/frontc/cparser.ml" : 'basic_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'basic_attr_list_ne) in Obj.repr( -# 1566 "cil/src/frontc/cparser.mly" +# 1561 "cil/src/frontc/cparser.mly" ( _1 ) -# 6326 "cil/src/frontc/cparser.ml" +# 6321 "cil/src/frontc/cparser.ml" : 'parameter_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'basic_attr_list_ne) in let _2 = (Parsing.peek_val __caml_parser_env 0 : string * cabsloc) in Obj.repr( -# 1567 "cil/src/frontc/cparser.mly" +# 1562 "cil/src/frontc/cparser.mly" ( _1 @ [make_expr (CONSTANT(CONST_STRING (fst _2)))] ) -# 6336 "cil/src/frontc/cparser.ml" +# 6331 "cil/src/frontc/cparser.ml" : 'parameter_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'basic_attr_list_ne) in let _2 = (Parsing.peek_val __caml_parser_env 1 : string * cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'parameter_attr_list_ne) in Obj.repr( -# 1570 "cil/src/frontc/cparser.mly" +# 1565 "cil/src/frontc/cparser.mly" ( _1 @ ([make_expr (CONSTANT(CONST_STRING (fst _2)))] @ _3) ) -# 6347 "cil/src/frontc/cparser.ml" +# 6342 "cil/src/frontc/cparser.ml" : 'parameter_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'parameter_attr_list_ne) in Obj.repr( -# 1575 "cil/src/frontc/cparser.mly" +# 1570 "cil/src/frontc/cparser.mly" ( _1 ) -# 6354 "cil/src/frontc/cparser.ml" +# 6349 "cil/src/frontc/cparser.ml" : 'param_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * cabsloc) in Obj.repr( -# 1576 "cil/src/frontc/cparser.mly" +# 1571 "cil/src/frontc/cparser.mly" ( [make_expr (CONSTANT(CONST_STRING (fst _1)))] ) -# 6361 "cil/src/frontc/cparser.ml" +# 6356 "cil/src/frontc/cparser.ml" : 'param_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'basic_attr) in Obj.repr( -# 1579 "cil/src/frontc/cparser.mly" +# 1574 "cil/src/frontc/cparser.mly" ( _1 ) -# 6368 "cil/src/frontc/cparser.ml" +# 6363 "cil/src/frontc/cparser.ml" : 'primary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'attr) in Obj.repr( -# 1580 "cil/src/frontc/cparser.mly" +# 1575 "cil/src/frontc/cparser.mly" ( _2 ) -# 6376 "cil/src/frontc/cparser.ml" +# 6371 "cil/src/frontc/cparser.ml" : 'primary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string * cabsloc) in Obj.repr( -# 1581 "cil/src/frontc/cparser.mly" +# 1576 "cil/src/frontc/cparser.mly" ( make_expr (CONSTANT(CONST_STRING (fst _1))) ) -# 6383 "cil/src/frontc/cparser.ml" +# 6378 "cil/src/frontc/cparser.ml" : 'primary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'primary_attr) in Obj.repr( -# 1584 "cil/src/frontc/cparser.mly" +# 1579 "cil/src/frontc/cparser.mly" ( _1 ) -# 6390 "cil/src/frontc/cparser.ml" +# 6385 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'id_or_typename_as_id) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'paren_attr_list_ne) in Obj.repr( -# 1585 "cil/src/frontc/cparser.mly" +# 1580 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in make_expr (CALL({ expr_loc = loc; expr_node = VARIABLE _1}, _2)) ) -# 6400 "cil/src/frontc/cparser.ml" +# 6395 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'id_or_typename_as_id) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in Obj.repr( -# 1589 "cil/src/frontc/cparser.mly" +# 1584 "cil/src/frontc/cparser.mly" ( let loc1 = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in let loc2 = Parsing.rhs_start_pos 2, Parsing.rhs_end_pos 3 in @@ -6410,526 +6405,526 @@ let arg = { expr_node = VARIABLE ""; expr_loc = loc2 } in make_expr (CALL(f, [arg])) ) -# 6414 "cil/src/frontc/cparser.ml" +# 6409 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'basic_attr) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'param_attr_list_ne) in Obj.repr( -# 1598 "cil/src/frontc/cparser.mly" +# 1593 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1 in make_expr (CALL({ expr_node = VARIABLE ""; expr_loc = loc}, _1::_2)) ) -# 6424 "cil/src/frontc/cparser.ml" +# 6419 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'postfix_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1602 "cil/src/frontc/cparser.mly" +# 1597 "cil/src/frontc/cparser.mly" ( make_expr (MEMBEROFPTR (_1, _3))) -# 6432 "cil/src/frontc/cparser.ml" +# 6427 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'postfix_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'id_or_typename) in Obj.repr( -# 1603 "cil/src/frontc/cparser.mly" +# 1598 "cil/src/frontc/cparser.mly" ( make_expr (MEMBEROF (_1, _3)) ) -# 6440 "cil/src/frontc/cparser.ml" +# 6435 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'postfix_attr) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'attr) in Obj.repr( -# 1604 "cil/src/frontc/cparser.mly" +# 1599 "cil/src/frontc/cparser.mly" ( make_expr (INDEX (_1, _3)) ) -# 6448 "cil/src/frontc/cparser.ml" +# 6443 "cil/src/frontc/cparser.ml" : 'postfix_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'postfix_attr) in Obj.repr( -# 1611 "cil/src/frontc/cparser.mly" +# 1606 "cil/src/frontc/cparser.mly" ( _1 ) -# 6455 "cil/src/frontc/cparser.ml" +# 6450 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 1612 "cil/src/frontc/cparser.mly" +# 1607 "cil/src/frontc/cparser.mly" ( make_expr (EXPR_SIZEOF _2) ) -# 6463 "cil/src/frontc/cparser.ml" +# 6458 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 1614 "cil/src/frontc/cparser.mly" +# 1609 "cil/src/frontc/cparser.mly" (let b, d = _3 in make_expr (TYPE_SIZEOF (b, d)) ) -# 6473 "cil/src/frontc/cparser.ml" +# 6468 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'unary_expression) in Obj.repr( -# 1617 "cil/src/frontc/cparser.mly" +# 1612 "cil/src/frontc/cparser.mly" (make_expr (EXPR_ALIGNOF _2) ) -# 6481 "cil/src/frontc/cparser.ml" +# 6476 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 1 : Cabs.spec_elem list * Cabs.decl_type) in Obj.repr( -# 1618 "cil/src/frontc/cparser.mly" +# 1613 "cil/src/frontc/cparser.mly" (let b, d = _3 in make_expr (TYPE_ALIGNOF (b, d)) ) -# 6491 "cil/src/frontc/cparser.ml" +# 6486 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1620 "cil/src/frontc/cparser.mly" +# 1615 "cil/src/frontc/cparser.mly" (make_expr (UNARY (PLUS, _2))) -# 6499 "cil/src/frontc/cparser.ml" +# 6494 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1621 "cil/src/frontc/cparser.mly" +# 1616 "cil/src/frontc/cparser.mly" (make_expr (UNARY (MINUS, _2)) ) -# 6507 "cil/src/frontc/cparser.ml" +# 6502 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1622 "cil/src/frontc/cparser.mly" +# 1617 "cil/src/frontc/cparser.mly" (make_expr (UNARY (MEMOF, _2)) ) -# 6515 "cil/src/frontc/cparser.ml" +# 6510 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1624 "cil/src/frontc/cparser.mly" +# 1619 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (ADDROF, _2)) ) -# 6523 "cil/src/frontc/cparser.ml" +# 6518 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1625 "cil/src/frontc/cparser.mly" +# 1620 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (NOT, _2)) ) -# 6531 "cil/src/frontc/cparser.ml" +# 6526 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1626 "cil/src/frontc/cparser.mly" +# 1621 "cil/src/frontc/cparser.mly" ( make_expr (UNARY (BNOT, _2)) ) -# 6539 "cil/src/frontc/cparser.ml" +# 6534 "cil/src/frontc/cparser.ml" : 'unary_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'unary_attr) in Obj.repr( -# 1630 "cil/src/frontc/cparser.mly" +# 1625 "cil/src/frontc/cparser.mly" ( _1 ) -# 6546 "cil/src/frontc/cparser.ml" +# 6541 "cil/src/frontc/cparser.ml" : 'cast_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1634 "cil/src/frontc/cparser.mly" +# 1629 "cil/src/frontc/cparser.mly" ( _1 ) -# 6553 "cil/src/frontc/cparser.ml" +# 6548 "cil/src/frontc/cparser.ml" : 'multiplicative_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'multiplicative_attr) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1635 "cil/src/frontc/cparser.mly" +# 1630 "cil/src/frontc/cparser.mly" (make_expr (BINARY(MUL ,_1 , _3))) -# 6562 "cil/src/frontc/cparser.ml" +# 6557 "cil/src/frontc/cparser.ml" : 'multiplicative_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'multiplicative_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1636 "cil/src/frontc/cparser.mly" +# 1631 "cil/src/frontc/cparser.mly" (make_expr (BINARY(DIV ,_1 , _3))) -# 6570 "cil/src/frontc/cparser.ml" +# 6565 "cil/src/frontc/cparser.ml" : 'multiplicative_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'multiplicative_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cast_attr) in Obj.repr( -# 1637 "cil/src/frontc/cparser.mly" +# 1632 "cil/src/frontc/cparser.mly" (make_expr (BINARY(MOD ,_1 , _3))) -# 6578 "cil/src/frontc/cparser.ml" +# 6573 "cil/src/frontc/cparser.ml" : 'multiplicative_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'multiplicative_attr) in Obj.repr( -# 1642 "cil/src/frontc/cparser.mly" +# 1637 "cil/src/frontc/cparser.mly" ( _1 ) -# 6585 "cil/src/frontc/cparser.ml" +# 6580 "cil/src/frontc/cparser.ml" : 'additive_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'additive_attr) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'multiplicative_attr) in Obj.repr( -# 1643 "cil/src/frontc/cparser.mly" +# 1638 "cil/src/frontc/cparser.mly" (make_expr (BINARY(ADD ,_1 , _3))) -# 6594 "cil/src/frontc/cparser.ml" +# 6589 "cil/src/frontc/cparser.ml" : 'additive_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'additive_attr) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'multiplicative_attr) in Obj.repr( -# 1644 "cil/src/frontc/cparser.mly" +# 1639 "cil/src/frontc/cparser.mly" (make_expr (BINARY(SUB ,_1 , _3))) -# 6603 "cil/src/frontc/cparser.ml" +# 6598 "cil/src/frontc/cparser.ml" : 'additive_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'additive_attr) in Obj.repr( -# 1648 "cil/src/frontc/cparser.mly" +# 1643 "cil/src/frontc/cparser.mly" ( _1 ) -# 6610 "cil/src/frontc/cparser.ml" +# 6605 "cil/src/frontc/cparser.ml" : 'shift_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'shift_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'additive_attr) in Obj.repr( -# 1649 "cil/src/frontc/cparser.mly" +# 1644 "cil/src/frontc/cparser.mly" (make_expr (BINARY(SHL ,_1 , _3))) -# 6618 "cil/src/frontc/cparser.ml" +# 6613 "cil/src/frontc/cparser.ml" : 'shift_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'shift_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'additive_attr) in Obj.repr( -# 1650 "cil/src/frontc/cparser.mly" +# 1645 "cil/src/frontc/cparser.mly" (make_expr (BINARY(SHR ,_1 , _3))) -# 6626 "cil/src/frontc/cparser.ml" +# 6621 "cil/src/frontc/cparser.ml" : 'shift_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'shift_attr) in Obj.repr( -# 1654 "cil/src/frontc/cparser.mly" +# 1649 "cil/src/frontc/cparser.mly" ( _1 ) -# 6633 "cil/src/frontc/cparser.ml" +# 6628 "cil/src/frontc/cparser.ml" : 'relational_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_attr) in Obj.repr( -# 1655 "cil/src/frontc/cparser.mly" +# 1650 "cil/src/frontc/cparser.mly" (make_expr (BINARY(LT ,_1 , _3))) -# 6641 "cil/src/frontc/cparser.ml" +# 6636 "cil/src/frontc/cparser.ml" : 'relational_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_attr) in Obj.repr( -# 1656 "cil/src/frontc/cparser.mly" +# 1651 "cil/src/frontc/cparser.mly" (make_expr (BINARY(GT ,_1 , _3))) -# 6649 "cil/src/frontc/cparser.ml" +# 6644 "cil/src/frontc/cparser.ml" : 'relational_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_attr) in Obj.repr( -# 1657 "cil/src/frontc/cparser.mly" +# 1652 "cil/src/frontc/cparser.mly" (make_expr (BINARY(LE ,_1 , _3))) -# 6657 "cil/src/frontc/cparser.ml" +# 6652 "cil/src/frontc/cparser.ml" : 'relational_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relational_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'shift_attr) in Obj.repr( -# 1658 "cil/src/frontc/cparser.mly" +# 1653 "cil/src/frontc/cparser.mly" (make_expr (BINARY(GE ,_1 , _3))) -# 6665 "cil/src/frontc/cparser.ml" +# 6660 "cil/src/frontc/cparser.ml" : 'relational_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'relational_attr) in Obj.repr( -# 1662 "cil/src/frontc/cparser.mly" +# 1657 "cil/src/frontc/cparser.mly" ( _1 ) -# 6672 "cil/src/frontc/cparser.ml" +# 6667 "cil/src/frontc/cparser.ml" : 'equality_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'equality_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'relational_attr) in Obj.repr( -# 1663 "cil/src/frontc/cparser.mly" +# 1658 "cil/src/frontc/cparser.mly" (make_expr (BINARY(EQ ,_1 , _3))) -# 6680 "cil/src/frontc/cparser.ml" +# 6675 "cil/src/frontc/cparser.ml" : 'equality_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'equality_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'relational_attr) in Obj.repr( -# 1664 "cil/src/frontc/cparser.mly" +# 1659 "cil/src/frontc/cparser.mly" (make_expr (BINARY(NE ,_1 , _3))) -# 6688 "cil/src/frontc/cparser.ml" +# 6683 "cil/src/frontc/cparser.ml" : 'equality_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'equality_attr) in Obj.repr( -# 1669 "cil/src/frontc/cparser.mly" +# 1664 "cil/src/frontc/cparser.mly" ( _1 ) -# 6695 "cil/src/frontc/cparser.ml" +# 6690 "cil/src/frontc/cparser.ml" : 'bitwise_and_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'bitwise_and_attr) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'equality_attr) in Obj.repr( -# 1670 "cil/src/frontc/cparser.mly" +# 1665 "cil/src/frontc/cparser.mly" (make_expr (BINARY(BAND ,_1 , _3))) -# 6704 "cil/src/frontc/cparser.ml" +# 6699 "cil/src/frontc/cparser.ml" : 'bitwise_and_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_and_attr) in Obj.repr( -# 1674 "cil/src/frontc/cparser.mly" +# 1669 "cil/src/frontc/cparser.mly" ( _1 ) -# 6711 "cil/src/frontc/cparser.ml" +# 6706 "cil/src/frontc/cparser.ml" : 'bitwise_xor_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'bitwise_xor_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_and_attr) in Obj.repr( -# 1675 "cil/src/frontc/cparser.mly" +# 1670 "cil/src/frontc/cparser.mly" (make_expr (BINARY(XOR ,_1 , _3))) -# 6719 "cil/src/frontc/cparser.ml" +# 6714 "cil/src/frontc/cparser.ml" : 'bitwise_xor_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_xor_attr) in Obj.repr( -# 1679 "cil/src/frontc/cparser.mly" +# 1674 "cil/src/frontc/cparser.mly" ( _1 ) -# 6726 "cil/src/frontc/cparser.ml" +# 6721 "cil/src/frontc/cparser.ml" : 'bitwise_or_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'bitwise_or_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_xor_attr) in Obj.repr( -# 1680 "cil/src/frontc/cparser.mly" +# 1675 "cil/src/frontc/cparser.mly" (make_expr (BINARY(BOR ,_1 , _3))) -# 6734 "cil/src/frontc/cparser.ml" +# 6729 "cil/src/frontc/cparser.ml" : 'bitwise_or_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_or_attr) in Obj.repr( -# 1684 "cil/src/frontc/cparser.mly" +# 1679 "cil/src/frontc/cparser.mly" ( _1 ) -# 6741 "cil/src/frontc/cparser.ml" +# 6736 "cil/src/frontc/cparser.ml" : 'logical_and_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'logical_and_attr) in let _2 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'bitwise_or_attr) in Obj.repr( -# 1686 "cil/src/frontc/cparser.mly" +# 1681 "cil/src/frontc/cparser.mly" (make_expr (BINARY(AND ,_1 , _3))) -# 6750 "cil/src/frontc/cparser.ml" +# 6745 "cil/src/frontc/cparser.ml" : 'logical_and_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logical_and_attr) in Obj.repr( -# 1690 "cil/src/frontc/cparser.mly" +# 1685 "cil/src/frontc/cparser.mly" ( _1 ) -# 6757 "cil/src/frontc/cparser.ml" +# 6752 "cil/src/frontc/cparser.ml" : 'logical_or_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'logical_or_attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'logical_and_attr) in Obj.repr( -# 1692 "cil/src/frontc/cparser.mly" +# 1687 "cil/src/frontc/cparser.mly" (make_expr (BINARY(OR ,_1 , _3))) -# 6765 "cil/src/frontc/cparser.ml" +# 6760 "cil/src/frontc/cparser.ml" : 'logical_or_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logical_or_attr) in Obj.repr( -# 1696 "cil/src/frontc/cparser.mly" +# 1691 "cil/src/frontc/cparser.mly" ( _1 ) -# 6772 "cil/src/frontc/cparser.ml" +# 6767 "cil/src/frontc/cparser.ml" : 'conditional_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'logical_or_attr) in let _3 = (Parsing.peek_val __caml_parser_env 2 : 'conditional_attr) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'conditional_attr) in Obj.repr( -# 1699 "cil/src/frontc/cparser.mly" +# 1694 "cil/src/frontc/cparser.mly" ( make_expr (QUESTION(_1, _3, _5)) ) -# 6781 "cil/src/frontc/cparser.ml" +# 6776 "cil/src/frontc/cparser.ml" : 'conditional_attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'conditional_attr) in Obj.repr( -# 1702 "cil/src/frontc/cparser.mly" +# 1697 "cil/src/frontc/cparser.mly" ( _1 ) -# 6788 "cil/src/frontc/cparser.ml" +# 6783 "cil/src/frontc/cparser.ml" : 'attr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'attr) in Obj.repr( -# 1706 "cil/src/frontc/cparser.mly" +# 1701 "cil/src/frontc/cparser.mly" ( [_1] ) -# 6795 "cil/src/frontc/cparser.ml" +# 6790 "cil/src/frontc/cparser.ml" : 'attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'attr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'attr_list_ne) in Obj.repr( -# 1707 "cil/src/frontc/cparser.mly" +# 1702 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 6803 "cil/src/frontc/cparser.ml" +# 6798 "cil/src/frontc/cparser.ml" : 'attr_list_ne)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 0 : 'attr_list_ne) in Obj.repr( -# 1708 "cil/src/frontc/cparser.mly" +# 1703 "cil/src/frontc/cparser.mly" ( _3 ) -# 6810 "cil/src/frontc/cparser.ml" +# 6805 "cil/src/frontc/cparser.ml" : 'attr_list_ne)) ; (fun __caml_parser_env -> Obj.repr( -# 1711 "cil/src/frontc/cparser.mly" +# 1706 "cil/src/frontc/cparser.mly" ( [] ) -# 6816 "cil/src/frontc/cparser.ml" +# 6811 "cil/src/frontc/cparser.ml" : 'attr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'attr_list_ne) in Obj.repr( -# 1712 "cil/src/frontc/cparser.mly" +# 1707 "cil/src/frontc/cparser.mly" ( _1 ) -# 6823 "cil/src/frontc/cparser.ml" +# 6818 "cil/src/frontc/cparser.ml" : 'attr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'attr_list_ne) in Obj.repr( -# 1715 "cil/src/frontc/cparser.mly" +# 1710 "cil/src/frontc/cparser.mly" ( _2 ) -# 6831 "cil/src/frontc/cparser.ml" +# 6826 "cil/src/frontc/cparser.ml" : 'paren_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in Obj.repr( -# 1716 "cil/src/frontc/cparser.mly" +# 1711 "cil/src/frontc/cparser.mly" ( [] ) -# 6838 "cil/src/frontc/cparser.ml" +# 6833 "cil/src/frontc/cparser.ml" : 'paren_attr_list_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'attr_list) in Obj.repr( -# 1719 "cil/src/frontc/cparser.mly" +# 1714 "cil/src/frontc/cparser.mly" ( _2 ) -# 6846 "cil/src/frontc/cparser.ml" +# 6841 "cil/src/frontc/cparser.ml" : 'paren_attr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in Obj.repr( -# 1720 "cil/src/frontc/cparser.mly" +# 1715 "cil/src/frontc/cparser.mly" ( [] ) -# 6853 "cil/src/frontc/cparser.ml" +# 6848 "cil/src/frontc/cparser.ml" : 'paren_attr_list)) ; (fun __caml_parser_env -> Obj.repr( -# 1724 "cil/src/frontc/cparser.mly" +# 1719 "cil/src/frontc/cparser.mly" ( [] ) -# 6859 "cil/src/frontc/cparser.ml" +# 6854 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1725 "cil/src/frontc/cparser.mly" +# 1720 "cil/src/frontc/cparser.mly" ( ("volatile", []) :: _2 ) -# 6867 "cil/src/frontc/cparser.ml" +# 6862 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : Cabs.cabsloc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : Cabs.attribute list) in Obj.repr( -# 1726 "cil/src/frontc/cparser.mly" +# 1721 "cil/src/frontc/cparser.mly" ( ("const", []) :: _2 ) -# 6875 "cil/src/frontc/cparser.ml" +# 6870 "cil/src/frontc/cparser.ml" : Cabs.attribute list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'one_string_constant) in Obj.repr( -# 1729 "cil/src/frontc/cparser.mly" +# 1724 "cil/src/frontc/cparser.mly" ( [_1] ) -# 6882 "cil/src/frontc/cparser.ml" +# 6877 "cil/src/frontc/cparser.ml" : 'asmtemplate)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'one_string_constant) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'asmtemplate) in Obj.repr( -# 1730 "cil/src/frontc/cparser.mly" +# 1725 "cil/src/frontc/cparser.mly" ( _1 :: _2 ) -# 6890 "cil/src/frontc/cparser.ml" +# 6885 "cil/src/frontc/cparser.ml" : 'asmtemplate)) ; (fun __caml_parser_env -> Obj.repr( -# 1733 "cil/src/frontc/cparser.mly" +# 1728 "cil/src/frontc/cparser.mly" ( None ) -# 6896 "cil/src/frontc/cparser.ml" +# 6891 "cil/src/frontc/cparser.ml" : 'asmoutputs)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'asmoperands) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'asminputs) in Obj.repr( -# 1735 "cil/src/frontc/cparser.mly" +# 1730 "cil/src/frontc/cparser.mly" ( let (ins, clobs) = _3 in Some {aoutputs = _2; ainputs = ins; aclobbers = clobs} ) -# 6905 "cil/src/frontc/cparser.ml" +# 6900 "cil/src/frontc/cparser.ml" : 'asmoutputs)) ; (fun __caml_parser_env -> Obj.repr( -# 1739 "cil/src/frontc/cparser.mly" +# 1734 "cil/src/frontc/cparser.mly" ( [] ) -# 6911 "cil/src/frontc/cparser.ml" +# 6906 "cil/src/frontc/cparser.ml" : 'asmoperands)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'asmoperandsne) in Obj.repr( -# 1740 "cil/src/frontc/cparser.mly" +# 1735 "cil/src/frontc/cparser.mly" ( List.rev _1 ) -# 6918 "cil/src/frontc/cparser.ml" +# 6913 "cil/src/frontc/cparser.ml" : 'asmoperands)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'asmoperand) in Obj.repr( -# 1743 "cil/src/frontc/cparser.mly" +# 1738 "cil/src/frontc/cparser.mly" ( [_1] ) -# 6925 "cil/src/frontc/cparser.ml" +# 6920 "cil/src/frontc/cparser.ml" : 'asmoperandsne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'asmoperandsne) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'asmoperand) in Obj.repr( -# 1744 "cil/src/frontc/cparser.mly" +# 1739 "cil/src/frontc/cparser.mly" ( _3 :: _1 ) -# 6933 "cil/src/frontc/cparser.ml" +# 6928 "cil/src/frontc/cparser.ml" : 'asmoperandsne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'asmopname) in @@ -6937,76 +6932,76 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in let _4 = (Parsing.peek_val __caml_parser_env 1 : Cabs.expression) in Obj.repr( -# 1747 "cil/src/frontc/cparser.mly" +# 1742 "cil/src/frontc/cparser.mly" ( (_1, fst _2, _4) ) -# 6943 "cil/src/frontc/cparser.ml" +# 6938 "cil/src/frontc/cparser.ml" : 'asmoperand)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'asmopname) in let _2 = (Parsing.peek_val __caml_parser_env 3 : string * cabsloc) in let _3 = (Parsing.peek_val __caml_parser_env 2 : Cabs.cabsloc) in Obj.repr( -# 1748 "cil/src/frontc/cparser.mly" +# 1743 "cil/src/frontc/cparser.mly" ( let loc = Parsing.rhs_start_pos 4, Parsing.rhs_end_pos 4 in (_1, fst _2, { expr_loc = loc; expr_node = NOTHING} ) ) -# 6955 "cil/src/frontc/cparser.ml" +# 6950 "cil/src/frontc/cparser.ml" : 'asmoperand)) ; (fun __caml_parser_env -> Obj.repr( -# 1754 "cil/src/frontc/cparser.mly" +# 1749 "cil/src/frontc/cparser.mly" ( ([], []) ) -# 6961 "cil/src/frontc/cparser.ml" +# 6956 "cil/src/frontc/cparser.ml" : 'asminputs)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'asmoperands) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'asmclobber) in Obj.repr( -# 1756 "cil/src/frontc/cparser.mly" +# 1751 "cil/src/frontc/cparser.mly" ( (_2, _3) ) -# 6969 "cil/src/frontc/cparser.ml" +# 6964 "cil/src/frontc/cparser.ml" : 'asminputs)) ; (fun __caml_parser_env -> Obj.repr( -# 1759 "cil/src/frontc/cparser.mly" +# 1754 "cil/src/frontc/cparser.mly" ( None ) -# 6975 "cil/src/frontc/cparser.ml" +# 6970 "cil/src/frontc/cparser.ml" : 'asmopname)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 1760 "cil/src/frontc/cparser.mly" +# 1755 "cil/src/frontc/cparser.mly" ( Some _2 ) -# 6982 "cil/src/frontc/cparser.ml" +# 6977 "cil/src/frontc/cparser.ml" : 'asmopname)) ; (fun __caml_parser_env -> Obj.repr( -# 1764 "cil/src/frontc/cparser.mly" +# 1759 "cil/src/frontc/cparser.mly" ( [] ) -# 6988 "cil/src/frontc/cparser.ml" +# 6983 "cil/src/frontc/cparser.ml" : 'asmclobber)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'asmcloberlst_ne) in Obj.repr( -# 1765 "cil/src/frontc/cparser.mly" +# 1760 "cil/src/frontc/cparser.mly" ( _2 ) -# 6995 "cil/src/frontc/cparser.ml" +# 6990 "cil/src/frontc/cparser.ml" : 'asmclobber)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'one_string_constant) in Obj.repr( -# 1768 "cil/src/frontc/cparser.mly" +# 1763 "cil/src/frontc/cparser.mly" ( [_1] ) -# 7002 "cil/src/frontc/cparser.ml" +# 6997 "cil/src/frontc/cparser.ml" : 'asmcloberlst_ne)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'one_string_constant) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'asmcloberlst_ne) in Obj.repr( -# 1769 "cil/src/frontc/cparser.mly" +# 1764 "cil/src/frontc/cparser.mly" ( _1 :: _3 ) -# 7010 "cil/src/frontc/cparser.ml" +# 7005 "cil/src/frontc/cparser.ml" : 'asmcloberlst_ne)) (* Entry interpret *) ; (fun __caml_parser_env -> raise (Parsing.YYexit (Parsing.peek_val __caml_parser_env 0))) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cparser.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cparser.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cparser.mli 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cparser.mli 2011-10-10 08:48:48.000000000 +0000 @@ -1,5 +1,4 @@ type token = - | FOR_SPEC of (Cabs.cabsloc * string list * Logic_ptree.spec) | SPEC of (Lexing.position * string) | DECL of (Logic_ptree.decl list) | CODE_ANNOT of (Logic_ptree.code_annot * Cabs.cabsloc) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cparser.mly frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cparser.mly --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cparser.mly 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cparser.mly 2011-10-10 08:40:08.000000000 +0000 @@ -94,20 +94,19 @@ parse_error "Cannot find the prototype in a function definition"); currentFunctionName := n - let check_funspec_abrupt_clauses fname (spec,_) = List.iter - (fun bhv -> List.iter - (function - (Cil_types.Normal | Cil_types.Exits),_ -> () - | (Cil_types.Breaks | Cil_types.Continues | - Cil_types.Returns), {Logic_ptree.lexpr_loc = (loc,_)} -> - Cil.error_loc (loc.Lexing.pos_fname, loc.Lexing.pos_lnum) - "Specification of function %s can only contain ensures or \ + (fun bhv -> + List.iter + (function + | (Cil_types.Normal | Cil_types.Exits),_ -> () + | (Cil_types.Breaks | Cil_types.Continues | + Cil_types.Returns), {Logic_ptree.lexpr_loc = (loc,_)} -> + Kernel.error ~source:loc + "Specification of function %s can only contain ensures or \ exits post-conditions" fname; - raise Parsing.Parse_error - ) - bhv.Cil_types.b_post_cond) + raise Parsing.Parse_error) + bhv.Cil_types.b_post_cond) spec.Cil_types.spec_behavior let applyPointer (ptspecs: attribute list list) (dt: decl_type) @@ -282,7 +281,6 @@ %} -%token FOR_SPEC %token SPEC %token DECL %token CODE_ANNOT @@ -941,9 +939,6 @@ statement: SEMICOLON { no_ghost [NOP $1] } -| FOR_SPEC annotated_statement - { (* TODO: Do not forget behavior list. *) - let loc,_bhv,spec = $1 in no_ghost [Cabs.CODE_SPEC (spec,loc)] @ $2} | SPEC annotated_statement { let bs = $2 in diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cprint.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cprint.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cprint.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cprint.ml 2011-10-10 08:40:08.000000000 +0000 @@ -230,7 +230,10 @@ (* print "struct foo", but with specified keyword and a list of * attributes to put between keyword and name *) and print_struct_name_attr keyword fmt (name, extraAttrs) = - fprintf fmt "%s%a%s" keyword print_attributes extraAttrs name + fprintf fmt "%s%a%a@ %s" + keyword + (pp_cond (extraAttrs <> [])) space_sep + print_attributes extraAttrs name (* This is the main printer for declarations. It is easy bacause the * declarations are laid out as they need to be printed. *) @@ -247,7 +250,7 @@ fprintf fmt "%a[@[%a%a@]]" (print_decl n) d print_attributes al print_expression e | PROTO(d, args, isva) -> - fprintf fmt "@[(@[%a@])@;(%a)@]" + fprintf fmt "@[%a@;(%a)@]" (print_decl n) d print_params (args,isva) and print_fields fmt (flds : field_group list) = @@ -277,7 +280,7 @@ and print_field_group fmt fld = match fld with | FIELD (specs, fields) -> - fprintf fmt "%a%a;" + fprintf fmt "%a@ %a;" print_specifiers specs (pp_list ~sep:(","^^space_sep) print_field) fields | TYPE_ANNOT annot -> @@ -331,7 +334,7 @@ (pp_list ~sep:(","^^space_sep) doinitexp) initexps and print_cast_expression fmt = function - NO_INIT -> Cilmsg.fatal "no init in cast" + NO_INIT -> Kernel.fatal "no init in cast" | COMPOUND_INIT _ as ie -> fprintf fmt "(@[%a@])" print_init_expression ie | SINGLE_INIT e -> print_expression_level cast_level fmt e @@ -409,7 +412,7 @@ and print_statement fmt stat = let loc = Cabshelper.get_statementloc stat in Cil_const.CurrentLoc.set loc; - if Cilmsg.debug_atleast 2 then fprintf fmt "@\n/* %a */@\n" Cil.d_loc loc; + if Kernel.debug_atleast 2 then fprintf fmt "@\n/* %a */@\n" Cil.d_loc loc; match stat.stmt_node with NOP _ -> pp_print_string fmt ";" | COMPUTATION (exp,_) -> fprintf fmt "%a;" print_expression exp @@ -443,9 +446,13 @@ | BREAK _ -> pp_print_string fmt "break;" | CONTINUE _ -> pp_print_string fmt "continue;" | RETURN (exp, _) -> - fprintf fmt "return%a%a;" - (pp_cond (exp.expr_node = NOTHING)) space_sep - print_expression exp + let has_paren exp = + match exp.expr_node with + | PAREN _ -> true + | _ -> false in + fprintf fmt "return%a%a;" + (pp_cond (not (exp.expr_node = NOTHING || has_paren exp))) space_sep + print_expression exp | SWITCH (exp, stat,_) -> fprintf fmt "@[switch@ (@[%a@])@ %a@]" print_expression exp print_substatement stat diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/cprint.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cprint.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/cprint.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/cprint.mli 2011-10-10 08:40:08.000000000 +0000 @@ -39,6 +39,7 @@ (* énergies alternatives). *) (**************************************************************************) +(** Printers for the Cabs AST *) val version : string val msvcMode : bool ref @@ -47,6 +48,8 @@ val printCounters : bool ref val printComments : bool ref +val get_operator : Cabs.expression -> (string * int) + val print_specifiers : Format.formatter -> Cabs.specifier -> unit val print_type_spec : Format.formatter -> Cabs.typeSpecifier -> unit val print_struct_name_attr : diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/errorloc.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/errorloc.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/errorloc.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/errorloc.ml 2011-10-10 08:40:08.000000000 +0000 @@ -105,60 +105,39 @@ let current = ref dummyinfo let first_filename_encountered = ref None -let setHLine (l: int) : unit = - !current.hline <- l -let setHFile (f: string) : unit = - !current.hfile <- f - -let rem_quotes str = String.sub str 1 ((String.length str) - 2) - -(* Change \ into / in file names. To avoid complications with escapes - [BM] DO NOT USE this function. It mutates [str] and does not take care of its length. *) -(*let cleanFileName str = - let str1 = - if str <> "" && String.get str 0 = '"' (* '"' ( *) - then rem_quotes str else str in - let l = String.length str1 in - let rec loop (copyto: int) (i: int) = - if i >= l then - String.sub str1 0 copyto - else - let c = String.get str1 i in - if c <> '\\' then begin - String.set str1 copyto c; loop (copyto + 1) (i + 1) - end else begin - String.set str1 copyto '/'; - if i < l - 2 && String.get str1 (i + 1) = '\\' then - loop (copyto + 1) (i + 2) - else - loop (copyto + 1) (i + 1) - end - in - loop 0 0 -*) +let setHLine l = !current.hline <- l +let setHFile f = !current.hfile <- f + +let rem_quotes str = String.sub str 1 (String.length str - 2) let readingFromStdin = ref false -let startParsing ?(useBasename=true) (fname: string) = +let startParsing ?(useBasename=true) fname = (* We only support one open file at a time *) if !current != dummyinfo then begin - (Cilmsg.abort "Errormsg.startParsing supports only one open file: You want to open %s and %s is still open@\n" fname !current.fileName); + Kernel.fatal + "[Errorloc.startParsing] supports only one open file: \ +You want to open %S and %S is still open" + fname !current.fileName; end; let inchan = - try if fname = "-" then begin - readingFromStdin := true; - stdin - end else begin - readingFromStdin := false; - open_in_bin fname - end - with e -> (Cilmsg.abort "Cannot find input file %s (exception %s" - fname (Printexc.to_string e)) in + try + if fname = "-" then begin + readingFromStdin := true; + stdin + end else begin + readingFromStdin := false; + open_in_bin fname + end + with Sys_error s -> + Kernel.abort "Cannot find input file %S: %s" fname s + in let lexbuf = Lexing.from_channel inchan in let i = { linenum = 1; linestart = 0; fileName = - (*cleanFileName*) (if useBasename then Filename.basename fname else fname); + (*cleanFileName*) + (if useBasename then Filename.basename fname else fname); lexbuf = lexbuf; inchan = Some inchan; hfile = ""; hline = 0; num_errors = 0 } in @@ -173,20 +152,6 @@ first_filename_encountered := None; lexbuf -let startParsingFromString ?(file="") ?(line=1) (str: string) = - let lexbuf = Lexing.from_string str in - let i = - { linenum = line; linestart = line - 1; - fileName = file; - hfile = ""; hline = 0; - lexbuf = lexbuf; - inchan = None; - num_errors = 0 } - in - current := i; - first_filename_encountered := None; - lexbuf - let finishParsing () = let i = !current in (match i.inchan with Some c -> close_in c | _ -> ()); @@ -250,14 +215,15 @@ let i = !current in i.num_errors <- i.num_errors + 1; if i.num_errors > max_errors then - Cilmsg.abort "Too many errors." + Kernel.abort "Too many errors." else - Cilmsg.with_error + Kernel.with_error (fun _ -> raise Parsing.Parse_error) - ~source:{ - Log.src_file = i.fileName ; - Log.src_line = i.linenum ; - } "%s" msg + ~source:{Lexing.pos_fname= i.fileName ; + pos_lnum = i.linenum; + pos_bol = i.linestart; + pos_cnum = 0;} + "%s" msg (* More parsing support functions: line, file, char count *) let getPosition () : Lexing.position * Lexing.position = @@ -277,7 +243,7 @@ let d_loc fmt l = Format.fprintf fmt "%s:%d" l.file l.line -let d_hloc fmt l = +let d_hloc fmt l = Format.fprintf fmt "%s:%d:" l.file l.line ; if l.hline > 0 then Format.fprintf fmt " (%s:%d)" l.hfile l.hline diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/errorloc.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/errorloc.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/errorloc.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/errorloc.mli 2011-10-10 08:40:08.000000000 +0000 @@ -41,12 +41,12 @@ (* * - * Copyright (c) 2001-2002, + * Copyright (c) 2001-2002, * George C. Necula * Scott McPeak * Wes Weimer * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: @@ -79,7 +79,7 @@ (* Copied and modified from [cil/src/errormsg.mli] *) val newline: unit -> unit (* Call this function to announce a new line *) -val newHline: unit -> unit +val newHline: unit -> unit val getPosition: unit -> Lexing.position * Lexing.position val getHPosition: unit -> int * string (** high-level position *) @@ -91,16 +91,16 @@ val setCurrentFile: string -> unit (** Type for source-file locations *) -type location = +type location = { file: string; (** The file name *) line: int; (** The line number *) hfile: string; (** The high-level file name, or "" if not present *) hline: int; (** The high-level line number, or 0 if not present *) - } + } val d_loc: location Pretty_utils.formatter val d_hloc: location Pretty_utils.formatter - + val getLocation: unit -> location val parse_error: string (* A message *) -> 'a @@ -109,20 +109,13 @@ val locUnknown: location -(** Records whether the stdin is open for reading the goal **) -val readingFromStdin: bool ref - - -(* Call this function to start parsing. useBasename is by default "true", - * meaning that the error information maintains only the basename. If the +(* Call this function to start parsing. useBasename is by default "true", + * meaning that the error information maintains only the basename. If the * file name is - then it reads from stdin. *) -val startParsing: ?useBasename:bool -> string -> - Lexing.lexbuf - -val startParsingFromString: ?file:string -> ?line:int -> string - -> Lexing.lexbuf +val startParsing: ?useBasename:bool -> string -> + Lexing.lexbuf -val finishParsing: unit -> unit (* Call this function to finish parsing and +val finishParsing: unit -> unit (* Call this function to finish parsing and * close the input channel *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/frontc.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/frontc.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/frontc.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/frontc.ml 2011-10-10 08:40:08.000000000 +0000 @@ -39,9 +39,6 @@ (* énergies alternatives). *) (**************************************************************************) -module Stats = struct - let time _ x y = x y -end (* Output management *) let out : out_channel option ref = ref None let close_me = ref false @@ -68,25 +65,13 @@ let setMSVCMode () = Cprint.msvcMode := true -(* filename for patching *) -let patchFileName : string ref = ref "" (* by default do no patching *) - -(* patching file contents *) -let patchFile : Cabs.file option ref = ref None - -(* whether to print the patched CABS files *) -let printPatchedFiles : bool ref = ref false - (* whether to print a file of prototypes after parsing *) let doPrintProtos : bool ref = ref false (* this seems like something that should be built-in.. *) -let isNone (o : 'a option) : bool = -begin - match o with +let isNone (o : 'a option) : bool = match o with | Some _ -> false | None -> true -end let printNotice = ref false @@ -110,73 +95,43 @@ exception CabsOnly -(* parse, and apply patching *) +(* parse *) let rec parse_to_cabs fname = - begin - (* parse the patch file if it isn't parsed already *) - if ((!patchFileName <> "") && (isNone !patchFile)) then ( - (* parse the patch file *) - patchFile := Some(parse_to_cabs_inner !patchFileName); - Cilmsg.on_errors_abort "There were parsing errors in the patch file" - ); - (* now parse the file we came here to parse *) let cabs = parse_to_cabs_inner fname in - if Cilmsg.had_errors () then - ( Cilmsg.debug "There were parsing errors in %s" fname ; - raise Parsing.Parse_error ) ; - (* and apply the patch file, return transformed file *) - let patched = match !patchFile with - - | Some(pf) -> - if Patch.verbose then Format.eprintf "newpatching %s\n" fname; - let result = (Stats.time "newpatch" (Patch.applyPatch pf) cabs) in - - if (!printPatchedFiles) then begin - let outFname:string = fname ^ ".patched" in - Format.eprintf "Printing patched version of %s to %s\n" - fname outFname; - let o = open_out outFname in - Cprint.printFile (Format.formatter_of_out_channel o) result; - close_out o - end; - - result - | None -> cabs - in + if Cilmsg.had_errors () then begin + Kernel.debug "There were parsing errors in %s" fname ; + raise Parsing.Parse_error + end; (* print it ... *) (match !out with - Some o -> begin - if !printNotice then output_string o ("/* Generated by Frontc */\n"); - Stats.time "printCABS" - (Cprint.printFile (Format.formatter_of_out_channel o)) patched; - close_output (); - raise CabsOnly - end - | None -> ()); - if Cilmsg.had_errors () then - raise Parsing.Parse_error; - + | None -> (); + | Some o -> begin + if !printNotice then output_string o ("/* Generated by Frontc */\n"); + Cprint.printFile (Format.formatter_of_out_channel o) cabs; + close_output (); + raise CabsOnly + end); + if Cilmsg.had_errors () then raise Parsing.Parse_error; (* and return the patched source *) - patched -end + cabs and clexer lexbuf = - Clexer.clear_white (); - Clexer.clear_lexeme (); - let token = Clexer.initial lexbuf in - let white = Clexer.get_white () in - let cabsloc = Clexer.currentLoc () in - let lexeme = Clexer.get_extra_lexeme () ^ Lexing.lexeme lexbuf in - white,lexeme,token,cabsloc + Clexer.clear_white (); + Clexer.clear_lexeme (); + let token = Clexer.initial lexbuf in + let white = Clexer.get_white () in + let cabsloc = Clexer.currentLoc () in + let lexeme = Clexer.get_extra_lexeme () ^ Lexing.lexeme lexbuf in + white,lexeme,token,cabsloc (* just parse *) and parse_to_cabs_inner (fname : string) = try - Cilmsg.feedback ~level:2 "Parsing %s" fname ; + Kernel.feedback ~level:2 "Parsing %s" fname ; Cilmsg.clear_errors () ; let lexbuf = Clexer.init fname in - let cabs = Stats.time "parse" (Cparser.file (Whitetrack.wraplexer clexer)) lexbuf in + let cabs = Cparser.file (Whitetrack.wraplexer clexer) lexbuf in (* Cprint.print_defs cabs;*) Whitetrack.setFinalWhite (Clexer.get_white ()); Clexer.finish (); @@ -187,77 +142,33 @@ in*) (fname, cabs) with - | Sys_error msg -> - begin - Clexer.finish () ; - close_output () ; - Cilmsg.abort "Cannot open %s : %s" fname msg ; - end - | Parsing.Parse_error -> - begin - Clexer.finish (); - close_output (); - raise Parsing.Parse_error ; - end + | Sys_error msg -> + Clexer.finish () ; + close_output () ; + Kernel.abort "Cannot open %s : %s" fname msg ; + | Parsing.Parse_error -> + Clexer.finish (); + close_output (); + raise Parsing.Parse_error ; (*| e -> begin ignore (E.log "Caught %s while parsing\n" (Printexc.to_string e)); Clexer.finish (); raise e end *) -(*TODO:remove -(* print to safec.proto.h the prototypes of all functions that are defined *) -let printPrototypes ((_fname, file) : Cabs.file) : unit = -begin - (*ignore (E.log "file has %d defns\n" (List.length file));*) - - let chan = open_out "safec.proto.h" in - ignore (fprintf chan "/* generated prototypes file, %d defs */\n" (List.length file)); - Cprint.out := chan; - - let counter : int ref = ref 0 in - - let rec loop (_ghost,(d : Cabs.definition)) = begin - match d with - | Cabs.FUNDEF(_,name, _, loc, _) -> ( - match name with - | (_, (funcname, Cabs.PROTO(_,_,_), _, _)) -> ( - incr counter; - ignore (fprintf chan "\n/* %s from %s:%d */\n" - funcname (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum); - flush chan; - Cprint.print_single_name name; - Cprint.print_unescaped_string ";"; - Cprint.force_new_line (); - Cprint.flush () - ) - | _ -> () - ) - - | _ -> () - end in - (List.iter loop file); - - ignore (fprintf chan "\n/* wrote %d prototypes */\n" !counter); - close_out chan; - ignore (E.log "printed %d prototypes from %d defns to safec.proto.h\n" - !counter (List.length file)) -end -*) module Syntactic_transformations = Hook.Fold(struct type t = Cabs.file end) - let add_syntactic_transformation = Syntactic_transformations.extend let parse fname = - Cilmsg.feedback ~level:2 "Parsing %s to Cabs" fname ; + Kernel.feedback ~level:2 "Parsing %s to Cabs" fname ; let cabs = parse_to_cabs fname in let cabs = Syntactic_transformations.apply cabs in (*Cprint.printFile stdout cabs;*) (* Now (return a function that will) convert to CIL *) fun _ -> - Cilmsg.feedback ~level:2 "Converting %s from Cabs to CIL" fname ; - let cil = Stats.time "conv" Cabs2cil.convFile cabs in + Kernel.feedback ~level:2 "Converting %s from Cabs to CIL" fname ; + let cil = Cabs2cil.convFile cabs in (*if !doPrintProtos then (printPrototypes cabs);*) (*Cil.dumpFile Cil.defaultCilPrinter stdout "behue" cil;*) cil,cabs diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/frontc.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/frontc.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/frontc.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/frontc.mli 2011-10-10 08:40:08.000000000 +0000 @@ -39,16 +39,16 @@ (* énergies alternatives). *) (**************************************************************************) -(* Signal that we are in MS VC mode *) +(** Signals that we are in MS VC mode *) val setMSVCMode: unit -> unit -(* Raised when the front-end is requested to print the CABS and return *) +(** Raised when the front-end is requested to print the CABS and return *) exception CabsOnly (** add a syntactic transformation that will be applied to all freshly parsed C files. *) val add_syntactic_transformation: (Cabs.file -> Cabs.file) -> unit -(* the main command to parse a file. Return a thunk that can be used to - * convert the AST to CIL. *) +(** the main command to parse a file. Return a thunk that can be used to + convert the AST to CIL. *) val parse: string -> (unit -> Cil_types.file*Cabs.file) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/lexerhack.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/lexerhack.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/lexerhack.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/lexerhack.ml 2011-10-10 08:40:08.000000000 +0000 @@ -43,16 +43,16 @@ * used by the parser. In Ocaml lexers depend on parsers, so we we have put * such functions in a separate module. *) let add_identifier: (string -> unit) ref = - ref (fun _ -> Cilmsg.fatal "Uninitialized add_identifier") + ref (fun _ -> Kernel.fatal "Uninitialized add_identifier") let add_type: (string -> unit) ref = - ref (fun _ -> Cilmsg.fatal "Uninitialized add_type") + ref (fun _ -> Kernel.fatal "Uninitialized add_type") let push_context: (unit -> unit) ref = - ref (fun _ -> Cilmsg.fatal "Uninitialized push_context") + ref (fun _ -> Kernel.fatal "Uninitialized push_context") let pop_context: (unit -> unit) ref = - ref (fun _ -> Cilmsg.fatal "You called an uninitialized pop_context") + ref (fun _ -> Kernel.fatal "You called an uninitialized pop_context") (* Keep here the current pattern for formatparse *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/patch.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/patch.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/patch.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/patch.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,786 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - - -(* patch.ml *) -(* CABS file patching *) - -open Cabs -open Cabshelper -open Cabsvisit -open Cil - -(* binding of a unification variable to a syntactic construct *) -type binding = - | BSpecifier of string * spec_elem list - | BName of string * string - | BExpr of string * expression - -(* thrown when unification fails *) -exception NoMatch - -(* thrown when an attempt to find the associated binding fails *) -exception BadBind of string - -(* trying to isolate performance problems; will hide all the *) -(* potentially expensive debugging output behind "if verbose .." *) -let verbose : bool = false - - -(* raise NoMatch if x and y are not equal *) -let mustEq (x : 'a) (y : 'a) : unit = -begin - if (x <> y) then ( - if verbose then - Format.eprintf "mismatch by structural disequality\n" ; - raise NoMatch - ) -end - -(* why isn't this in the core Ocaml library? *) -let identity x = x - - -let isPatternVar (s : string) : bool = -begin - ((String.length s) >= 1) && ((String.get s 0) = '@') -end - -(* 's' is actually "@name(blah)"; extract the 'blah' *) -let extractPatternVar (s : string) : string = - (*(trace "patch" (dprintf "extractPatternVar %s\n" s));*) - (String.sub s 6 ((String.length s) - 7)) - - -(* a few debugging printers.. *) -let printExpr fmt (e : expression) = - if verbose then Format.fprintf fmt "%a@." Cprint.print_expression e - -let printSpec fmt (spec: spec_elem list) = - if verbose then - Format.fprintf fmt "%a@." Cprint.print_specifiers spec - -let printSpecs fmt (pat,tgt) = - printSpec fmt pat; printSpec fmt tgt - -let printDecl fmt (pat,tgt) = - if verbose then - Format.fprintf fmt "%a@\n%a@." Cprint.print_name pat Cprint.print_name tgt - -let printDeclType fmt (pat,tgt) = - if verbose then - Format.fprintf fmt "%a@\n%a@." - (Cprint.print_decl "__missing_field_name") pat - (Cprint.print_decl "__missing_field_name") tgt - -let printDefn fmt (d : definition) = - if verbose then Format.fprintf fmt "%a@." Cprint.print_def d - -(* class to describe how to modify the tree for subtitution *) -class substitutor (bindings : binding list) = object(self) - inherit nopCabsVisitor as super - - (* look in the binding list for a given name *) - method findBinding (name : string) : binding = - begin - try - (List.find - (fun b -> - match b with - | BSpecifier(n, _) -> n=name - | BName(n, _) -> n=name - | BExpr(n, _) -> n=name) - bindings) - with - Not_found -> raise (BadBind ("name not found: " ^ name)) - end - - method vexpr (e:expression) : expression visitAction = - begin - match e.expr_node with - | EXPR_PATTERN(name) -> ( - match (self#findBinding name) with - | BExpr(_, expr) -> ChangeTo(expr) (* substitute bound expression *) - | _ -> raise (BadBind ("wrong type: " ^ name)) - ) - | _ -> DoChildren - end - - (* use of a name *) - method vvar (s:string) : string = - begin - if (isPatternVar s) then ( - let nameString = (extractPatternVar s) in - match (self#findBinding nameString) with - | BName(_, str) -> str (* substitute *) - | _ -> raise (BadBind ("wrong type: " ^ nameString)) - ) - else - s - end - - (* binding introduction of a name *) - method vname (_k: nameKind) (_spec: specifier) (n: name) : name visitAction = - begin - match n with (s (*variable name*), dtype, attrs, loc) -> ( - let replacement = (self#vvar s) in (* use replacer from above *) - if (s <> replacement) then - ChangeTo(replacement, dtype, attrs, loc) - else - DoChildren (* no replacement *) - ) - end - - method vspec (specList: specifier) : specifier visitAction = - begin - if verbose then - Format.eprintf "@[substitutor: vspec@\n%a" printSpec specList; - - (* are any of the specifiers SpecPatterns? we have to check the entire *) - (* list, not just the head, because e.g. "typedef @specifier(foo)" has *) - (* "typedef" as the head of the specifier list *) - if (List.exists (fun elt -> match elt with - | SpecPattern(_) -> true - | _ -> false) - specList) then begin - (* yes, replace the existing list with one got by *) - (* replacing all occurrences of SpecPatterns *) - if verbose then Format.eprintf "at least one spec pattern\n" ; - ChangeTo - (List.flatten - (List.map - (* for each specifier element, yield the specifier list *) - (* to which it maps; then we'll flatten the final result *) - (fun elt -> - match elt with - | SpecPattern(name) -> ( - match (self#findBinding name) with - | BSpecifier(_, replacement) -> ( - if verbose then - Format.eprintf "replacing pattern %s\n" name ; - replacement - ) - | _ -> raise (BadBind ("wrong type: " ^ name)) - ) - | _ -> [elt] (* leave this one alone *) - ) - specList - ) - ) - end - else - (* none of the specifiers in specList are patterns *) - DoChildren - end - - method vtypespec (tspec: typeSpecifier) : typeSpecifier visitAction = - begin - match tspec with - | Tnamed(str) when (isPatternVar str) -> - ChangeTo(Tnamed(self#vvar str)) - | Tstruct(str, fields, extraAttrs) when (isPatternVar str) -> ( - ((if verbose then Format.eprintf "substituting %s\n" str)); - ChangeDoChildrenPost(Tstruct((self#vvar str), fields, extraAttrs), identity) - ) - | Tunion(str, fields, extraAttrs) when (isPatternVar str) -> - ((if verbose then Format.eprintf "substituting %s\n" str)); - ChangeDoChildrenPost(Tunion((self#vvar str), fields, extraAttrs), identity) - | _ -> DoChildren - end - -end - - -(* why can't I have forward declarations in the language?!! *) -let unifyExprFwd : (expression -> expression -> binding list) ref - = ref (fun _e _e -> []) - - -(* substitution for expressions *) -let substExpr (bindings : binding list) (expr : expression) : expression = - if verbose then - Format.eprintf "substExpr with %d bindings@\n%a" - (List.length bindings) printExpr expr; - - (* apply the transformation *) - let result = - (visitCabsExpression (new substitutor bindings :> cabsVisitor) expr) - in - printExpr Format.err_formatter result; - result - -let d_loc fmt loc = - Format.fprintf fmt "%s:%d" - (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum - -(* class to describe how to modify the tree when looking for places *) -(* to apply expression transformers *) -class exprTransformer (srcpattern : expression) (destpattern : expression) - (patchline : int) (srcloc : cabsloc) = object - inherit nopCabsVisitor as super - - method vexpr (e:expression) : expression visitAction = - begin - (* see if the source pattern matches this subexpression *) - try ( - let bindings = (!unifyExprFwd srcpattern e) in - - (* match! *) - if verbose then - Format.eprintf "expr match: patch line %d, src %a" - patchline d_loc srcloc ; - ChangeTo(substExpr bindings destpattern) - ) - - with NoMatch -> ( - (* doesn't apply *) - DoChildren - ) - end - - (* other constructs left unchanged *) -end - - -let unifyList (pat : 'a list) (tgt : 'a list) - (unifyElement : 'a -> 'a -> binding list) : binding list = -begin - (if verbose then (Format.eprintf "unifyList (pat len %d, tgt len %d)\n" - (List.length pat) (List.length tgt))); - - (* walk down the lists *) - let rec loop pat tgt : binding list = - match pat, tgt with - | [], [] -> [] - | (pelt :: prest), (telt :: trest) -> - (unifyElement pelt telt) @ - (loop prest trest) - | _,_ -> ( - (* no match *) - if verbose then ( - ((Format.eprintf "mismatching list length\n")); - ); - raise NoMatch - ) - in - (loop pat tgt) -end - - -let gettime () : float = - (Unix.times ()).Unix.tms_utime - -let rec applyPatch (patchFile : file) (srcFile : file) : file = -begin - let patch : definition list = List.map snd (snd patchFile) in - let srcFname : string = (fst srcFile) in - let src : definition list = List.map snd (snd srcFile) in - - (* trace "patchTime" (dprintf "applyPatch start: %f\n" (gettime ()))); *) - - (* more hackery *) - unifyExprFwd := unifyExpr; - - (* patch a single source definition, yield transformed *) - let rec patchDefn (patch : definition list) (d : definition) : definition list = - begin - match patch with - | TRANSFORMER(srcpattern, destpattern, loc) :: rest -> ( - if verbose then - Format.eprintf "considering applying defn pattern at line %d to src at %a\n" - (fst loc).Lexing.pos_lnum d_loc (get_definitionloc d); - - (* see if the source pattern matches the definition 'd' we have *) - try ( - let bindings = (unifyDefn srcpattern d) in - - (* we have a match! apply the substitutions *) - (if verbose then Format.eprintf "defn match: patch line %d, src %a\n" - (fst loc).Lexing.pos_lnum d_loc (get_definitionloc d)); - - (List.map (fun destElt -> (substDefn bindings destElt)) destpattern) - ) - - with NoMatch -> ( - (* no match, continue down list *) - (*(trace "patch" (dprintf "no match\n"));*) - (patchDefn rest d) - ) - ) - - | EXPRTRANSFORMER(srcpattern, destpattern, loc) :: rest -> ( - if verbose then - ((Format.eprintf "considering applying expr pattern at line %d to src at %a\n" - (fst loc).Lexing.pos_lnum d_loc (get_definitionloc d))); - - (* walk around in 'd' looking for expressions to modify *) - let dList = (visitCabsDefinition - ((new exprTransformer srcpattern destpattern - (fst loc).Lexing.pos_lnum (get_definitionloc d)) - :> cabsVisitor) - d - ) in - - (* recursively invoke myself to try additional patches *) - (* since visitCabsDefinition might return a list, I'll try my *) - (* addtional patches on every yielded definition, then collapse *) - (* all of them into a single list *) - (List.flatten (List.map (fun d -> (patchDefn rest d)) dList)) - ) - - | _ :: rest -> ( - (* not a transformer; just keep going *) - (patchDefn rest d) - ) - | [] -> ( - (* reached the end of the patch file with no match *) - [d] (* have to wrap it in a list ... *) - ) - end in - - (* transform all the definitions *) - let result : definition list = - (List.flatten (List.map (fun d -> (patchDefn patch d)) src)) in - - (if verbose then Format.eprintf "applyPatch finish: %f\n" (gettime ())); - (srcFname, List.map (fun x -> false,x) result) -end - - -(* given a definition pattern 'pat', and a target concrete defintion 'tgt', *) -(* determine if they can be unified; if so, return the list of bindings of *) -(* unification variables in pat; otherwise raise NoMatch *) -and unifyDefn (pat : definition) (tgt : definition) : binding list = -begin - match pat, tgt with - | DECDEF(_,(pspecifiers, pdeclarators), _), - DECDEF(_,(tspecifiers, tdeclarators), _) -> ( - if verbose then - ((Format.eprintf "unifyDefn of DECDEFs\n")); - (unifySpecifiers pspecifiers tspecifiers) @ - (unifyInitDeclarators pdeclarators tdeclarators) - ) - - | TYPEDEF((pspec, pdecl), _), - TYPEDEF((tspec, tdecl), _) -> ( - if verbose then - ((Format.eprintf "unifyDefn of TYPEDEFs\n")); - (unifySpecifiers pspec tspec) @ - (unifyDeclarators pdecl tdecl) - ) - - | ONLYTYPEDEF(pspec, _), - ONLYTYPEDEF(tspec, _) -> ( - if verbose then - ((Format.eprintf "unifyDefn of ONLYTYPEDEFs\n")); - (unifySpecifiers pspec tspec) - ) - - | _, _ -> ( - if verbose then - ((Format.eprintf "mismatching definitions\n")); - raise NoMatch - ) -end - -and unifySpecifier (pat : spec_elem) (tgt : spec_elem) : binding list = - if verbose then - Format.eprintf "@[unifySpecifier@\n%a@]" printSpecs ([pat], [tgt]); - - if (pat = tgt) then [] else - begin - match pat, tgt with - | SpecType(tspec1), SpecType(tspec2) -> - (unifyTypeSpecifier tspec1 tspec2) - | SpecPattern(name), _ -> - (* record that future occurrances of @specifier(name) will yield this specifier *) - if verbose then - ((Format.eprintf "found specifier match for %s\n" name)); - [BSpecifier(name, [tgt])] - | _,_ -> ( - (* no match *) - if verbose then ( - ((Format.eprintf "mismatching specifiers\n")); - ); - raise NoMatch - ) - end - -and unifySpecifiers (pat : spec_elem list) (tgt : spec_elem list) : binding list = - if verbose then - Format.eprintf "@[unifySpecifiers@\n%a@]" printSpecs (pat, tgt); - - (* canonicalize the specifiers by sorting them *) - let pat' = (List.stable_sort Extlib.compare_basic pat) in - let tgt' = (List.stable_sort Extlib.compare_basic tgt) in - - (* if they are equal, they match with no further checking *) - if (pat' = tgt') then [] else - - (* walk down the lists; don't walk the sorted lists because the *) - (* pattern must always be last, if it occurs *) - let rec loop pat tgt : binding list = - match pat, tgt with - | [], [] -> [] - | [SpecPattern(name)], _ -> - (* final SpecPattern matches anything which comes after *) - (* record that future occurrences of @specifier(name) will yield this specifier *) - if verbose then - ((Format.eprintf "found specifier match for %s\n" name)); - [BSpecifier(name, tgt)] - | (pspec :: prest), (tspec :: trest) -> - (unifySpecifier pspec tspec) @ - (loop prest trest) - | _,_ -> ( - (* no match *) - if verbose then ( - ((Format.eprintf "mismatching specifier list length\n")); - ); - raise NoMatch - ) - in - (loop pat tgt) - -and unifyTypeSpecifier (pat: typeSpecifier) (tgt: typeSpecifier) : binding list = -begin - (if verbose then (Format.eprintf "unifyTypeSpecifier\n")); - - if (pat = tgt) then [] else - - match pat, tgt with - | Tnamed(s1), Tnamed(s2) -> (unifyString s1 s2) - | Tstruct(name1, None, _), Tstruct(name2, None, _) -> - (unifyString name1 name2) - | Tstruct(name1, Some(fields1), _), Tstruct(name2, Some(fields2), _) -> - (* ignoring extraAttrs b/c we're just trying to come up with a list - * of substitutions, and there's no unify_attributes function, and - * I don't care at this time about checking that they are equal .. *) - (unifyString name1 name2) @ - (unifyList fields1 fields2 unifyField) - | Tunion(name1, None, _), Tstruct(name2, None, _) -> - (unifyString name1 name2) - | Tunion(name1, Some(fields1), _), Tunion(name2, Some(fields2), _) -> - (unifyString name1 name2) @ - (unifyList fields1 fields2 unifyField) - | Tenum(name1, None, _), Tenum(name2, None, _) -> - (unifyString name1 name2) - | Tenum(name1, Some(items1), _), Tenum(name2, Some(items2), _) -> - (mustEq items1 items2); (* enum items *) - (unifyString name1 name2) - | TtypeofE(exp1), TtypeofE(exp2) -> - (unifyExpr exp1 exp2) - | TtypeofT(spec1, dtype1), TtypeofT(spec2, dtype2) -> - (unifySpecifiers spec1 spec2) @ - (unifyDeclType dtype1 dtype2) - | _ -> ( - if verbose then ((Format.eprintf "mismatching typeSpecifiers\n")); - raise NoMatch - ) -end - -and unifyField (pat : field_group) (tgt : field_group) : binding list = -begin - match pat,tgt with FIELD (spec1, list1), FIELD (spec2, list2) -> ( - (unifySpecifiers spec1 spec2) @ - (unifyList list1 list2 unifyNameExprOpt) - ) - | _ -> - (* no match *) - if verbose then ( - ((Format.eprintf "mismatching during type annotation\n")); - ); - raise NoMatch -end - -and unifyNameExprOpt (pat : name * expression option) - (tgt : name * expression option) : binding list = -begin - match pat,tgt with - | (name1, None), (name2, None) -> (unifyName name1 name2) - | (name1, Some(exp1)), (name2, Some(exp2)) -> - (unifyName name1 name2) @ - (unifyExpr exp1 exp2) - | _,_ -> [] -end - -and unifyName (pat : name) (tgt : name) : binding list = -begin - match pat,tgt with (pstr, pdtype, pattrs, _ploc), (tstr, tdtype, tattrs, _tloc) -> - (mustEq pattrs tattrs); - (unifyString pstr tstr) @ - (unifyDeclType pdtype tdtype) -end - -and unifyInitDeclarators (pat : init_name list) (tgt : init_name list) : binding list = -begin - (* - if verbose then - ((Format.eprintf "unifyInitDeclarators, pat %d, tgt %d\n" - (List.length pat) (List.length tgt))); - *) - - match pat, tgt with - | ((pdecl, piexpr) :: prest), - ((tdecl, tiexpr) :: trest) -> - (unifyDeclarator pdecl tdecl) @ - (unifyInitExpr piexpr tiexpr) @ - (unifyInitDeclarators prest trest) - | [], [] -> [] - | _, _ -> ( - if verbose then - ((Format.eprintf "mismatching init declarators\n")); - raise NoMatch - ) -end - -and unifyDeclarators (pat : name list) (tgt : name list) : binding list = - (unifyList pat tgt unifyDeclarator) - -and unifyDeclarator (pat : name) (tgt : name) : binding list = - if verbose then - Format.eprintf "@[unifyDeclarator@\n%a@]" printDecl (pat, tgt); - - match pat, tgt with - | (pname, pdtype, pattr, _ploc), - (tname, tdtype, tattr, _tloc) -> - (mustEq pattr tattr); - (unifyDeclType pdtype tdtype) @ - (unifyString pname tname) - -and unifyDeclType (pat : decl_type) (tgt : decl_type) : binding list = - if verbose then - Format.eprintf "@[unifyDeclType@\n%a@]" printDeclType (pat, tgt); - - match pat, tgt with - | JUSTBASE, JUSTBASE -> [] - | PARENTYPE(pattr1, ptype, pattr2), - PARENTYPE(tattr1, ttype, tattr2) -> - (mustEq pattr1 tattr1); - (mustEq pattr2 tattr2); - (unifyDeclType ptype ttype) - | ARRAY(ptype, pattr, psz), - ARRAY(ttype, tattr, tsz) -> - (mustEq pattr tattr); - (unifyDeclType ptype ttype) @ - (unifyExpr psz tsz) - | PTR(pattr, ptype), - PTR(tattr, ttype) -> - (mustEq pattr tattr); - (unifyDeclType ptype ttype) - | PROTO(ptype, pformals, pva), - PROTO(ttype, tformals, tva) -> - (mustEq pva tva); - (unifyDeclType ptype ttype) @ - (unifySingleNames pformals tformals) - | _ -> ( - if verbose then - ((Format.eprintf "mismatching decl_types\n")); - raise NoMatch - ) - -and unifySingleNames (pat : single_name list) (tgt : single_name list) : binding list = -begin - (if verbose then (Format.eprintf "unifySingleNames, pat %d, tgt %d\n" - (List.length pat) (List.length tgt))); - - match pat, tgt with - | [], [] -> [] - | (pspec, pdecl) :: prest, - (tspec, tdecl) :: trest -> - (unifySpecifiers pspec tspec) @ - (unifyDeclarator pdecl tdecl) @ - (unifySingleNames prest trest) - | _, _ -> ( - if verbose then - ((Format.eprintf "mismatching single_name lists\n")); - raise NoMatch - ) -end - -and unifyString (pat : string) (tgt : string) : binding list = -begin - (* equal? match with no further ado *) - if (pat = tgt) then [] else - - (* is the pattern a variable? *) - if (isPatternVar pat) then - (* pat is actually "@name(blah)"; extract the 'blah' *) - let varname = (extractPatternVar pat) in - - (* when substituted, this name becomes 'tgt' *) - if verbose then - ((Format.eprintf "found name match for %s\n" varname)); - [BName(varname, tgt)] - - else ( - if verbose then - ((Format.eprintf "mismatching names: %s and %s\n" pat tgt)); - raise NoMatch - ) -end - -and unifyExpr (pat : expression) (tgt : expression) : binding list = - (* if they're equal, that's good enough *) - if (pat = tgt) then [] else - - (* shorter name *) - let ue = unifyExpr in - - (* because of the equality check above, I can omit some cases *) - match pat.expr_node, tgt.expr_node with - | UNARY(pop, pexpr), - UNARY(top, texpr) -> - (mustEq pop top); - (ue pexpr texpr) - | BINARY(pop, pexp1, pexp2), - BINARY(top, texp1, texp2) -> - (mustEq pop top); - (ue pexp1 texp1) @ - (ue pexp2 texp2) - | QUESTION(p1, p2, p3), - QUESTION(t1, t2, t3) -> - (ue p1 t1) @ - (ue p2 t2) @ - (ue p3 t3) - | CAST((pspec, ptype), piexpr), - CAST((tspec, ttype), tiexpr) -> - (mustEq ptype ttype); - (unifySpecifiers pspec tspec) @ - (unifyInitExpr piexpr tiexpr) - | CALL(pfunc, pargs), - CALL(tfunc, targs) -> - (ue pfunc tfunc) @ - (unifyExprs pargs targs) - | COMMA(pexprs), - COMMA(texprs) -> - (unifyExprs pexprs texprs) - | EXPR_SIZEOF(pexpr), - EXPR_SIZEOF(texpr) -> - (ue pexpr texpr) - | TYPE_SIZEOF(pspec, ptype), - TYPE_SIZEOF(tspec, ttype) -> - (mustEq ptype ttype); - (unifySpecifiers pspec tspec) - | EXPR_ALIGNOF(pexpr), - EXPR_ALIGNOF(texpr) -> - (ue pexpr texpr) - | TYPE_ALIGNOF(pspec, ptype), - TYPE_ALIGNOF(tspec, ttype) -> - (mustEq ptype ttype); - (unifySpecifiers pspec tspec) - | INDEX(parr, pindex), - INDEX(tarr, tindex) -> - (ue parr tarr) @ - (ue pindex tindex) - | MEMBEROF(pexpr, pfield), - MEMBEROF(texpr, tfield) -> - (mustEq pfield tfield); - (ue pexpr texpr) - | MEMBEROFPTR(pexpr, pfield), - MEMBEROFPTR(texpr, tfield) -> - (mustEq pfield tfield); - (ue pexpr texpr) - | GNU_BODY(pblock), - GNU_BODY(tblock) -> - (mustEq pblock tblock); - [] - | EXPR_PATTERN(name), _ -> - (* match, and contribute binding *) - if verbose then - ((Format.eprintf "found expr match for %s\n" name)); - [BExpr(name, tgt)] - | _ -> - if verbose then - Format.eprintf "@[mismatching expression@\n%a%a@]" - printExpr pat printExpr tgt; - raise NoMatch - -and unifyInitExpr (pat : init_expression) (tgt : init_expression) : binding list = -begin - (* - Cprint.print_init_expression pat; Cprint.force_new_line (); - Cprint.print_init_expression tgt; Cprint.force_new_line (); - Cprint.flush (); - *) - - match pat, tgt with - | NO_INIT, NO_INIT -> [] - | SINGLE_INIT(pe), SINGLE_INIT(te) -> - (unifyExpr pe te) - | COMPOUND_INIT(plist), - COMPOUND_INIT(tlist) -> ( - let rec loop plist tlist = - match plist, tlist with - | ((pwhat, piexpr) :: prest), - ((twhat, tiexpr) :: trest) -> - (mustEq pwhat twhat); - (unifyInitExpr piexpr tiexpr) @ - (loop prest trest) - | [], [] -> [] - | _, _ -> ( - if verbose then - ((Format.eprintf "mismatching compound init exprs\n")); - raise NoMatch - ) - in - (loop plist tlist) - ) - | _,_ -> ( - if verbose then - ((Format.eprintf "mismatching init exprs\n")); - raise NoMatch - ) -end - -and unifyExprs (pat : expression list) (tgt : expression list) : binding list = - (unifyList pat tgt unifyExpr) - - -(* given the list of bindings 'b', substitute them into 'd' to yield a new definition *) -and substDefn (bindings : binding list) (defn : definition) : definition = - if verbose then - Format.eprintf "@[substDefn with %d bindings@\n%a@]" - (List.length bindings) printDefn defn; - - (* apply the transformation *) - match (visitCabsDefinition (new substitutor bindings :> cabsVisitor) defn) with - | [d] -> d (* expect a singleton list *) - | _ -> (failwith "didn't get a singleton list where I expected one") diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/patch.mli frama-c-20111001+nitrogen+dfsg/cil/src/frontc/patch.mli --- frama-c-20110201+carbon+dfsg/cil/src/frontc/patch.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/patch.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - - -(* patch.mli *) -(* interface for patch.ml *) - -val verbose : bool -val applyPatch : Cabs.file -> Cabs.file -> Cabs.file diff -Nru frama-c-20110201+carbon+dfsg/cil/src/frontc/whitetrack.ml frama-c-20111001+nitrogen+dfsg/cil/src/frontc/whitetrack.ml --- frama-c-20110201+carbon+dfsg/cil/src/frontc/whitetrack.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/frontc/whitetrack.ml 2011-10-10 08:40:08.000000000 +0000 @@ -45,7 +45,7 @@ (* This isn't the most efficient way to do things. * It would probably be better to not reparse rather * than keep the tokens in memory *) - + (* In particular, most of the tokens we hold will be header files that we don't need *) @@ -54,7 +54,7 @@ (* TODO: gather until end of line, then decide where to split *) (* NOTE: If you find yourself getting lots of nomatch errors with - * parens in them, then that may mean you are printing + * parens in them, then that may mean you are printing * a cabs file that has had it's parens removed *) let tokenmap : ((string * int),int) Hashtbl.t = Hashtbl.create 1000 @@ -66,107 +66,110 @@ let tokens = GrowArray.make 0 (GrowArray.Elem ("","")) let cabsloc_to_str cabsloc = - (fst cabsloc).Lexing.pos_fname ^ ":" ^ - string_of_int (fst cabsloc).Lexing.pos_lnum ^ ":" ^ + (fst cabsloc).Lexing.pos_fname ^ ":" ^ + string_of_int (fst cabsloc).Lexing.pos_lnum ^ ":" ^ string_of_int (fst cabsloc).Lexing.pos_cnum let lastline = ref 0 -let wraplexer_enabled lexer lexbuf = +let wraplexer_enabled lexer lexbuf = let white,lexeme,token,cabsloc = lexer lexbuf in GrowArray.setg tokens !nextidx (white,lexeme); Hashtbl.add tokenmap ((fst cabsloc).Lexing.pos_fname,(fst cabsloc).Lexing.pos_cnum) !nextidx; nextidx := !nextidx + 1; token -let wraplexer_disabled lexer lexbuf = +let wraplexer_disabled lexer lexbuf = let _white,_lexeme,token,_cabsloc = lexer lexbuf in token let enabled = ref false let wraplexer lexer = - if !enabled then wraplexer_enabled lexer + if !enabled then wraplexer_enabled lexer else wraplexer_disabled lexer - -let finalwhite = ref "\n" - -let setFinalWhite w = finalwhite := w - -let curidx = ref 0 -let noidx = -1 + +let finalwhite = ref "\n" + +let setFinalWhite w = finalwhite := w + +let curidx = ref 0 +let noidx = -1 let out = ref stdout - + let setLoc cabsloc = if cabsloc != cabslu && !enabled then begin - try + try curidx := Hashtbl.find tokenmap ((fst cabsloc).Lexing.pos_fname,(fst cabsloc).Lexing.pos_cnum) with - Not_found -> - Cilmsg.fatal "setLoc with location for non-lexed token: %s" (cabsloc_to_str cabsloc) + Not_found -> + Kernel.fatal "setLoc with location for non-lexed token: %s" (cabsloc_to_str cabsloc) end else begin curidx := noidx; () end - -let setOutput out_chan = + +let setOutput out_chan = out := out_chan (* TODO: do this properly *) let invent_white () = " " let rec chopwhite str = - if String.length str = 0 then str + if String.length str = 0 then str else if String.get str (String.length str - 1) = ' ' then chopwhite (String.sub str 0 (String.length str - 1)) else if String.get str 0 = ' ' then - chopwhite (String.sub str 1 (String.length str - 1)) + chopwhite (String.sub str 1 (String.length str - 1)) else str - -let last_was_maybe = ref false + +let last_was_maybe = ref false let last_str = ref "" - + let print str = - let str = chopwhite str in - if str = "" then () - else if !curidx == noidx || not !enabled then - output_string !out (invent_white() ^ str) + let str = chopwhite str in + if str <> "" then + if !curidx == noidx || not !enabled then + output_string !out (invent_white() ^ str) else begin - let srcwhite,srctok = GrowArray.getg tokens !curidx in - let white = if str = srctok - then srcwhite - else if !gonebad then invent_white () - else begin - Cilmsg.warnOpt "nomatch:[%s] expected:[%s] - NOTE: cpp not supported" - (String.escaped str) (String.escaped srctok) ; - gonebad := true; - invent_white () - end in - if !last_was_maybe && str = !last_str then () else begin - output_string !out (white ^ str); - curidx := !curidx + 1 - end + let srcwhite,srctok = GrowArray.getg tokens !curidx in + let white = + if str = srctok then srcwhite + else if !gonebad then invent_white () + else begin + Kernel.debug ~level:3 + "nomatch:[%s] expected:[%s] - NOTE: cpp not supported" + (String.escaped str) + (String.escaped srctok) ; + gonebad := true; + invent_white () + end + in + if !last_was_maybe && str = !last_str then () else begin + output_string !out (white ^ str); + curidx := !curidx + 1 + end end; - last_was_maybe := false + last_was_maybe := false + +let printl strs = + List.iter print strs -let printl strs = - List.iter print strs - let printu str = if not !enabled then print str else let _srcwhite,srctok = GrowArray.getg tokens !curidx in - if chopwhite str = "" then () - else if srctok = str - || srctok = str ^ "__" + if chopwhite str = "" then () + else if srctok = str + || srctok = str ^ "__" || srctok = "__" ^ str || srctok = "__" ^ str ^ "__" then print srctok else (print_endline ("u-nomatch:["^str^"]"); print str) - + let print_maybe str = if not !enabled then print str else let _srcwhite,srctok = GrowArray.getg tokens !curidx in - if str = srctok then begin + if str = srctok then begin print str; last_was_maybe := true; last_str := str diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/cillower.ml frama-c-20111001+nitrogen+dfsg/cil/src/legacy/cillower.ml --- frama-c-20110201+carbon+dfsg/cil/src/legacy/cillower.ml 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/cillower.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(** A number of lowering passes over CIL *) -open Cil - -(** Lower CEnum constants *) -class lowerEnumVisitorClass : cilVisitor = object (self) - inherit nopCilVisitor - - method vexpr (e: exp) = - match e with - Const (CEnum(v, s, ei)) -> - ChangeTo (visitCilExpr (self :>cilVisitor) v) - - | _ -> DoChildren - -end - -let lowerEnumVisitor = new lowerEnumVisitorClass diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/cillower.mli frama-c-20111001+nitrogen+dfsg/cil/src/legacy/cillower.mli --- frama-c-20110201+carbon+dfsg/cil/src/legacy/cillower.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/cillower.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* - * - * Copyright (c) 2001-2003, - * George C. Necula - * Scott McPeak - * Wes Weimer - * Ben Liblit - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The names of the contributors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *) - -(** A number of lowering passes over CIL *) - -(** Replace enumeration constants with integer constants *) -val lowerEnumVisitor : Cil.cilVisitor diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/ciloptions.ml frama-c-20111001+nitrogen+dfsg/cil/src/legacy/ciloptions.ml --- frama-c-20110201+carbon+dfsg/cil/src/legacy/ciloptions.ml 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/ciloptions.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,203 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - - -module E = Errormsg - -let setDebugFlag v name = - E.debugFlag := v; - if v then Pretty.flushOften := true - -type outfile = - { fname: string; - fchan: out_channel } - -let setTraceDepth n = - Pretty.printDepth := n - - - (* Processign of output file arguments *) -let openFile (what: string) (takeit: outfile -> unit) (fl: string) = - if !E.verboseFlag then - ignore (Printf.printf "Setting %s to %s\n" what fl); - (try takeit { fname = fl; - fchan = open_out fl } - with _ -> - raise (Arg.Bad ("Cannot open " ^ what ^ " file " ^ fl))) - - -let fileNames : string list ref = ref [] -let recordFile fname = - fileNames := fname :: (!fileNames) - - (* Parsing of files with additional names *) -let parseExtraFile (s: string) = - try - let sfile = open_in s in - while true do - let line = try input_line sfile with e -> (close_in sfile; raise e) in - let linelen = String.length line in - let rec scan (pos: int) (* next char to look at *) - (start: int) : unit (* start of the word, - or -1 if none *) = - if pos >= linelen then - if start >= 0 then - recordFile (String.sub line start (pos - start)) - else - () (* Just move on to the next line *) - else - let c = String.get line pos in - match c with - ' ' | '\n' | '\r' | '\t' -> - (* whitespace *) - if start >= 0 then begin - recordFile (String.sub line start (pos - start)); - end; - scan (pos + 1) (-1) - - | _ -> (* non-whitespace *) - if start >= 0 then - scan (pos + 1) start - else - scan (pos + 1) pos - in - scan 0 (-1) - done - with Sys_error _ -> E.s (E.error "Cannot find extra file: %s\n" s) - | End_of_file -> () - - -let options : (string * Arg.spec * string) list = - [ - (* General Options *) - "", Arg.Unit (fun () -> ()), "\n\t\tGeneral Options\n" ; - - "--version", Arg.Unit - (fun _ -> print_endline ("CIL version " ^ Cil.cilVersion ^ - "\nMore information at http://cil.sourceforge.net/\n"); - exit 0), - "output version information and exit"; - "--verbose", Arg.Unit (fun _ -> E.verboseFlag := true), - "Print lots of random stuff. This is passed on from cilly."; - "--warnall", Arg.Unit (fun _ -> E.warnFlag := true), "Show all warnings"; - "--debug", Arg.String (setDebugFlag true), - " turns on debugging flag xxx"; - "--nodebug", Arg.String (setDebugFlag false), - " turns off debugging flag xxx"; - - "--flush", Arg.Unit (fun _ -> Pretty.flushOften := true), - "Flush the output streams often (aids debugging)" ; - "--check", Arg.Unit (fun _ -> Cilutil.doCheck := true), - "Run a consistency check over the CIL after every operation."; - "--nocheck", Arg.Unit (fun _ -> Cilutil.doCheck := false), - "turns off consistency checking of CIL"; - "--noPrintLn", Arg.Unit (fun _ -> Cil.lineDirectiveStyle := None; - Cprint.printLn := false), - "Don't output #line directives in the output."; - "--commPrintLn", Arg.Unit (fun _ -> Cil.lineDirectiveStyle := Some Cil.LineComment; - Cprint.printLnComment := true), - "Print #line directives in the output, but put them in comments."; - "--commPrintLnSparse", Arg.Unit (fun _ -> Cil.lineDirectiveStyle := Some Cil.LineCommentSparse; - Cprint.printLnComment := true), - "Print #line directives in the output, but put them in comments."; - "--stats", Arg.Unit (fun _ -> Cilutil.printStats := true), - "Print statistics about running times and memory usage."; - - - "--log", Arg.String (openFile "log" (fun oc -> E.logChannel := oc.fchan)), - "Set the name of the log file. By default stderr is used"; - - "--MSVC", Arg.Unit (fun _ -> Cil.msvcMode := true; - Frontc.setMSVCMode (); - if not Machdep.hasMSVC then - ignore (E.warn "Will work in MSVC mode but will be using machine-dependent parameters for GCC since you do not have the MSVC compiler installed\n") - ), "Enable MSVC compatibility. Default is GNU."; - - "--testcil", Arg.String (fun s -> Cilutil.testcil := s), - "test CIL using the given compiler"; - - "--ignore-merge-conflicts", - Arg.Unit (fun _ -> Mergecil.ignore_merge_conflicts := true), - "ignore merging conflicts"; - "--sliceGlobal", Arg.Unit (fun _ -> Cilutil.sliceGlobal := true), - "output is the slice of #pragma cilnoremove(sym) varinfos"; - - (* sm: some more debugging options *) - "--tr", Arg.String Trace.traceAddMulti, - ": subsystem to show debug printfs for"; - "--pdepth", Arg.Int setTraceDepth, - ": set max print depth (default: 5)"; - - "--extrafiles", Arg.String parseExtraFile, - ": the name of a file that contains a list of additional files to process, separated by whitespace of newlines"; - - (* Lowering Options *) - "", Arg.Unit (fun () -> ()), "\n\t\tLowering Options\n" ; - - "--noLowerConstants", Arg.Unit (fun _ -> Cil.lowerConstants := false), - "do not lower constant expressions"; - - "--noInsertImplicitCasts", Arg.Unit (fun _ -> Cil.insertImplicitCasts := false), - "do not insert implicit casts"; - - "--forceRLArgEval", - Arg.Unit (fun n -> Cabs2cil.forceRLArgEval := true), - "Forces right to left evaluation of function arguments"; - "--nocil", Arg.Int (fun n -> Cabs2cil.nocil := n), - "Do not compile to CIL the global with the given index"; - "--disallowDuplication", Arg.Unit (fun n -> Cabs2cil.allowDuplication := false), - "Prevent small chunks of code from being duplicated"; - "--keepunused", Arg.Set Rmtmps.keepUnused, - "Do not remove the unused variables and types"; - "--rmUnusedInlines", Arg.Set Rmtmps.rmUnusedInlines, - "Delete any unused inline functions. This is the default in MSVC mode"; - - - - "", Arg.Unit (fun () -> ()), "\n\t\tOutput Options\n" ; - "--printCilAsIs", Arg.Unit (fun _ -> Cil.printCilAsIs := true), - "do not try to simplify the CIL when printing. Without this flag, CIL will attempt to produce prettier output by e.g. changing while(1) into more meaningful loops."; - "--noWrap", Arg.Unit (fun _ -> Cil.lineLength := 100000), - "do not wrap long lines when printing"; - "--noTruncateWarning", Arg.Unit (fun _ -> Cil.warnTruncate := false), - "suppress warning about truncating integer constants"; - - ] - diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/libmaincil.ml frama-c-20111001+nitrogen+dfsg/cil/src/legacy/libmaincil.ml --- frama-c-20110201+carbon+dfsg/cil/src/legacy/libmaincil.ml 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/libmaincil.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* libmaincil *) -(* this is a replacement for maincil.ml, for the case when we're - * creating a C-callable library (libcil.a); all it does is register - * a couple of functions and initialize CIL *) - - -module E = Errormsg - -open Cil - - -(* print a Cil 'file' to stdout *) -let unparseToStdout (cil : file) : unit = -begin - dumpFile defaultCilPrinter stdout cil -end;; - -(* a visitor to unroll all types - may need to do some magic to keep attributes *) -class unrollVisitorClass = object (self) - inherit nopCilVisitor - - (* variable declaration *) - method vvdec (vi : varinfo) : varinfo visitAction = - begin - vi.vtype <- unrollTypeDeep vi.vtype; - (*ignore (E.log "varinfo for %s in file '%s' line %d byte %d\n" vi.vname vi.vdecl.file vi.vdecl.line vi.vdecl.byte);*) - SkipChildren - end - - (* global: need to unroll fields of compinfo *) - method vglob (g : global) : global list visitAction = - begin - match g with - GCompTag(ci, loc) as g -> - let doFieldinfo (fi : fieldinfo) : unit = - fi.ftype <- unrollTypeDeep fi.ftype - in begin - ignore(List.map doFieldinfo ci.cfields); - (*ChangeTo [g]*) - SkipChildren - end - | _ -> DoChildren - end -end;; - - -let unrollVisitor = new unrollVisitorClass;; - -(* open and parse a C file into a Cil 'file', unroll all typedefs *) -let parseOneFile (fname: string) : file = - let ast : file = Frontc.parse fname () in - begin - visitCilFile unrollVisitor ast; - ast - end -;; - -let getDummyTypes () : typ * typ = - ( TPtr(TVoid [], []), TInt(IInt, []) ) -;; - -(* register some functions - these may be called from C code *) -Callback.register "cil_parse" parseOneFile; -Callback.register "cil_unparse" unparseToStdout; -(* Callback.register "unroll_type_deep" unrollTypeDeep; *) -Callback.register "get_dummy_types" getDummyTypes; - -(* initalize CIL *) -initCIL (); - - diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/maincil.ml frama-c-20111001+nitrogen+dfsg/cil/src/legacy/maincil.ml --- frama-c-20110201+carbon+dfsg/cil/src/legacy/maincil.ml 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/maincil.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,289 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* maincil *) -(* this module is the program entry point for the 'cilly' program, *) -(* which reads a C program file, parses it, translates it to the CIL *) -(* intermediate language, and then renders that back into C *) - - -module F = Frontc -module C = Cil_types -module CK = Check -module E = Errormsg -open Pretty -open Trace - -type outfile = - { fname: string; - fchan: out_channel } -let outChannel : outfile option ref = ref None -let mergedChannel : outfile option ref = ref None - - -let parseOneFile (fname: string) : C.file = - (* PARSE and convert to CIL *) - if !Cilutil.printStages then ignore (E.log "Parsing %s\n" fname); - let cil = F.parse fname () in - - if (not !Epicenter.doEpicenter) then ( - (* sm: remove unused temps to cut down on gcc warnings *) - (* (Stats.time "usedVar" Rmtmps.removeUnusedTemps cil); *) - (trace "sm" (dprintf "removing unused temporaries\n")); - (Rmtmps.removeUnusedTemps cil) - ); - cil - -(** These are the statically-configured features. To these we append the - * features defined in Feature_config.ml (from Makefile) *) - -let makeCFGFeature : Cil.featureDescr = - { Cil.fd_name = "makeCFG"; - Cil.fd_enabled = Cilutil.makeCFG; - Cil.fd_description = "make the program look more like a CFG" ; - Cil.fd_extraopt = []; - Cil.fd_doit = (fun f -> - ignore (Partial.calls_end_basic_blocks f) ; - ignore (Partial.globally_unique_vids f) ; - Cil.iterGlobals f (fun glob -> match glob with - C.GFun(fd,_) -> Cfg.prepareCFG fd ; - (* jc: blockinggraph depends on this "true" arg *) - ignore (Cfg.computeCFGInfo fd true) - | _ -> ()) - ); - Cil.fd_post_check = true; - } - -let features : Cil.featureDescr list = - [ Epicenter.feature; - Simplify.feature; - Canonicalize.feature; - Callgraph.feature; - Logwrites.feature; - Heapify.feature1; - Heapify.feature2; - Oneret.feature; - makeCFGFeature; (* ww: make CFG *must* come before Partial *) - Partial.feature; - Simplemem.feature; - Sfi.feature; - Dataslicing.feature; - Logcalls.feature; - Ptranal.feature; - Liveness.feature; - ] - @ Feature_config.features - -let rec processOneFile (cil: C.file) = - begin - - if !Cilutil.doCheck then begin - ignore (E.log "First CIL check\n"); - ignore (CK.checkFile [] cil); - end; - - (* Scan all the features configured from the Makefile and, if they are - * enabled then run them on the current file *) - List.iter - (fun fdesc -> - if ! (fdesc.Cil.fd_enabled) then begin - if !E.verboseFlag then - ignore (E.log "Running CIL feature %s (%s)\n" - fdesc.Cil.fd_name fdesc.Cil.fd_description); - fdesc.Cil.fd_doit cil; - (* See if we need to do some checking *) - if !Cilutil.doCheck && fdesc.Cil.fd_post_check then begin - ignore (E.log "CIL check after %s\n" fdesc.Cil.fd_name); - ignore (CK.checkFile [] cil); - end - end) - features; - - - (match !outChannel with - None -> () - | Some c -> Stats.time "printCIL" - (Cil.dumpFile (!Cil.printerForMaincil) c.fchan c.fname) cil); - - if !E.hadErrors then - E.s (E.error "Error while processing file; see above for details."); - - end - -(***** MAIN *****) -let rec theMain () = - let usageMsg = "Usage: cilly [options] source-files" in - (* Processign of output file arguments *) - let openFile (what: string) (takeit: outfile -> unit) (fl: string) = - if !E.verboseFlag then - ignore (Printf.printf "Setting %s to %s\n" what fl); - (try takeit { fname = fl; - fchan = open_out fl } - with _ -> - raise (Arg.Bad ("Cannot open " ^ what ^ " file " ^ fl))) - in - let outName = ref "" in - (* sm: enabling this by default, since I think usually we - * want 'cilly' transformations to preserve annotations; I - * can easily add a command-line flag if someone sometimes - * wants these suppressed *) - Cil.print_CIL_Input := true; - - (*********** COMMAND LINE ARGUMENTS *****************) - (* Construct the arguments for the features configured from the Makefile *) - let blankLine = ("", Arg.Unit (fun _ -> ()), "") in - let featureArgs = - List.fold_right - (fun fdesc acc -> - if !(fdesc.Cil.fd_enabled) then - (* The feature is enabled by default *) - blankLine :: - ("--dont" ^ fdesc.Cil.fd_name, Arg.Clear(fdesc.Cil.fd_enabled), - " Disable " ^ fdesc.Cil.fd_description) :: - fdesc.Cil.fd_extraopt @ acc - else - (* Disabled by default *) - blankLine :: - ("--do" ^ fdesc.Cil.fd_name, Arg.Set(fdesc.Cil.fd_enabled), - " Enable " ^ fdesc.Cil.fd_description) :: - fdesc.Cil.fd_extraopt @ acc - ) - features - [blankLine] - in - let featureArgs = - ("", Arg.Unit (fun () -> ()), "\n\t\tCIL Features") :: featureArgs - in - - let argDescr = Ciloptions.options @ - [ - "--out", Arg.String (openFile "output" - (fun oc -> outChannel := Some oc)), - "the name of the output CIL file. The cilly script sets this for you."; - "--mergedout", Arg.String (openFile "merged output" - (fun oc -> mergedChannel := Some oc)), - "specify the name of the merged file"; - ] - @ F.args @ featureArgs in - begin - (* this point in the code is the program entry point *) - - Stats.reset (Stats.has_performance_counters ()); - - (* parse the command-line arguments *) - Arg.parse argDescr Ciloptions.recordFile usageMsg; - Cil.initCIL (); - - Ciloptions.fileNames := List.rev !Ciloptions.fileNames; - - if !Cilutil.testcil <> "" then begin - Testcil.doit !Cilutil.testcil - end else - (* parse each of the files named on the command line, to CIL *) - let files = List.map parseOneFile !Ciloptions.fileNames in - - (* if there's more than one source file, merge them together; *) - (* now we have just one CIL "file" to deal with *) - let one = - match files with - [one] -> one - | [] -> E.s (E.error "No arguments for CIL\n") - | _ -> - let merged = - Stats.time "merge" (Mergecil.merge files) - (if !outName = "" then "stdout" else !outName) in - if !E.hadErrors then - E.s (E.error "There were errors during merging\n"); - (* See if we must save the merged file *) - (match !mergedChannel with - None -> () - | Some mc -> begin - let oldpci = !Cil.print_CIL_Input in - Cil.print_CIL_Input := true; - Stats.time "printMerged" - (Cil.dumpFile !Cil.printerForMaincil mc.fchan mc.fname) merged; - Cil.print_CIL_Input := oldpci - end); - merged - in - - if !E.hadErrors then - E.s (E.error "Cabs2cil had some errors"); - - (* process the CIL file (merged if necessary) *) - processOneFile one - end -;; - (* Define a wrapper for main to - * intercept the exit *) -let failed = ref false - -let cleanup () = - if !E.verboseFlag || !Cilutil.printStats then - Stats.print stderr "Timings:\n"; - if !E.logChannel != stderr then - close_out (! E.logChannel); - (match ! outChannel with Some c -> close_out c.fchan | _ -> ()) - - -(* Without this handler, cilly.asm.exe will quit silently with return code 0 - when a segfault happens. *) -let handleSEGV code = - if !Cil.currentLoc == Cil.locUnknown then - E.log "**** Segmentation fault (possibly a stack overflow)\n" - else begin - E.log ("**** Segmentation fault (possibly a stack overflow) "^^ - "while processing %a\n") - Cil.d_loc !Cil.currentLoc - end; - exit code - -let _ = Sys.set_signal Sys.sigsegv (Sys.Signal_handle handleSEGV); - -;; - -begin - try - theMain (); - with F.CabsOnly -> (* this is OK *) () -end; -cleanup (); -exit (if !failed then 1 else 0) - diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/pretty.ml frama-c-20111001+nitrogen+dfsg/cil/src/legacy/pretty.ml --- frama-c-20110201+carbon+dfsg/cil/src/legacy/pretty.ml 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/pretty.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,922 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* - * - * Copyright (c) 2001-2002, - * George C. Necula - * Scott McPeak - * Wes Weimer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The names of the contributors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *) - -(******************************************************************************) -(* Pretty printer - This module contains several fast, but sub-optimal heuristics to pretty-print - structured text. -*) - -let debug = false - -(* Choose an algorithm *) -type algo = George | Aman | Gap -let algo = George -let fastMode = ref false - - -(** Whether to print identation or not (for faster printing and smaller - * output) *) -let printIndent = ref true - -(******************************************************************************) -(* The doc type and constructors *) - -type doc = - Nil - | Text of string - | Concat of doc * doc - | CText of doc * string - | Break - | Line - | LeftFlush - | Align - | Unalign - | Mark - | Unmark - | Tag of string - -(* Break a string at \n *) -let rec breakString (acc: doc) (str: string) : doc = - try - (* Printf.printf "breaking string %s\n" str; *) - let r = String.index str '\n' in - (* Printf.printf "r=%d\n" r; *) - let len = String.length str in - if r > 0 then begin - (* Printf.printf "Taking %s\n" (String.sub str 0 r); *) - let acc' = Concat(CText (acc, String.sub str 0 r), Line) in - if r = len - 1 then (* The last one *) - acc' - else begin - (* Printf.printf "Continuing with %s\n" (String.sub str (r + 1) (len - r - 1)); *) - breakString acc' - (String.sub str (r + 1) (len - r - 1)) - end - end else (* The first is a newline *) - breakString (Concat(acc, Line)) - (String.sub str (r + 1) (len - r - 1)) - with Not_found -> - if acc = Nil then Text str else CText (acc, str) - -let nil = Nil -let text s = breakString nil s -let num i = text (string_of_int i) -let real f = text (string_of_float f) -let chr c = text (String.make 1 c) -let align = Align -let unalign = Unalign -let line = Line -let leftflush = LeftFlush -let break = Break -let mark = Mark -let unmark = Unmark - -let d_int32 (i: int32) = text (Int32.to_string i) -let f_int32 () i = d_int32 i - -let d_int64 (i: int64) = text (Int64.to_string i) -let f_int64 () i = d_int64 i - -let tag s = Tag s - -(* Note that the ++ operator in Ocaml are left-associative. This means - * that if you have a long list of ++ then the whole thing is very unbalanced - * towards the left side. This is the worst possible case since scanning the - * left side of a Concat is the non-tail recursive case. *) - -let (++) d1 d2 = Concat (d1, d2) -let concat d1 d2 = Concat (d1, d2) - -(* Ben Liblit fix *) -let indent n d = text (String.make n ' ') ++ (align ++ (d ++ unalign)) - -let markup d = mark ++ d ++ unmark - -(* Format a sequence. The first argument is a separator *) -let seq ~(sep:doc) ~(doit:'a -> doc) ~(elements: 'a list) = - let rec loop (acc: doc) = function - [] -> acc - | h :: t -> - let fh = doit h in (* Make sure this is done first *) - loop (acc ++ sep ++ fh) t - in - (match elements with - [] -> nil - | h :: t -> - let fh = doit h in loop fh t) - - -let docArray ?(sep=chr ',') (doit:int -> 'a -> doc) () (elements:'a array) = - let len = Array.length elements in - if len = 0 then - nil - else - let rec loop (acc: doc) i = - if i >= len then acc else - let fi = doit i elements.(i) in (* Make sure this is done first *) - loop (acc ++ sep ++ fi) (i + 1) - in - let f0 = doit 0 elements.(0) in - loop f0 1 - -let docOpt delem () = function - None -> text "None" - | Some e -> text "Some(" ++ (delem e) ++ chr ')' - - - -let docList ?(sep=chr ',') (doit:'a -> doc) () (elements:'a list) = - seq sep doit elements - -let insert () d = d - - -let d_list (sep:string) (doit:unit -> 'a -> doc) () (elts:'a list) : doc = - (* thunk 'doit' to match docList's interface *) - let internalDoit (elt:'a) = - (doit () elt) in - (docList ~sep:(text sep) internalDoit () elts) - -(** Format maps *) -module MakeMapPrinter = - functor (Map: sig - type key - type 'a t - val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b - end) -> -struct - let docMap ?(sep=chr ',') - (doit: Map.key -> 'a -> doc) () (maplets: 'a Map.t) : doc = - Map.fold - (fun k d acc -> - (if acc==nil then acc else acc ++ sep) - ++ (doit k d)) - maplets - nil - - let dmaplet d0 d1 = d0 ++ (text " |-> ") ++ d1 - - let d_map ?(dmaplet=dmaplet) (sep:string) dkey dval = - let doit = fun k d -> dmaplet (dkey () k) (dval () d) in - docMap ~sep:(text sep) doit -end - -(** Format sets *) -module MakeSetPrinter = - functor (Set: sig - type elt - type t - val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a - end) -> -struct - let docSet ?(sep=chr ',') (doit: Set.elt -> doc) () (set: Set.t) : doc = - Set.fold - (fun elt acc -> - (if acc==nil then acc else acc ++ sep) - ++ (doit elt)) - set - nil - - let d_set (sep:string) delt = - docSet ~sep:(text sep) (delt ()) -end - - -(******************************************************************************) -(* Some debugging stuff *) - -let dbgprintf x = Printf.fprintf stderr x - -let rec dbgPrintDoc = function - Nil -> dbgprintf "(Nil)" - | Text s -> dbgprintf "(Text %s)" s - | Concat (d1,d2) -> dbgprintf ""; dbgPrintDoc d1; dbgprintf " ++\n "; - dbgPrintDoc d2; dbgprintf "" - | CText (d,s) -> dbgPrintDoc d; dbgprintf " ++ \"%s\"" s; - | Break -> dbgprintf "(Break)" - | Line -> dbgprintf "(Line)" - | LeftFlush -> dbgprintf "(LeftFlush)" - | Align -> dbgprintf "(Align)" - | Unalign -> dbgprintf "(Unalign)" - | Mark -> dbgprintf "(Mark)" - | Unmark -> dbgprintf "(Unmark)" - | Tag s -> dbgprintf "(Tag %s)" s - -(******************************************************************************) -(* The "george" algorithm *) - -(* When we construct documents, most of the time they are heavily unbalanced - * towards the left. This is due to the left-associativity of ++ and also to - * the fact that constructors such as docList construct from the let of a - * sequence. We would prefer to shift the imbalance to the right to avoid - * consuming a lot of stack when we traverse the document *) -let rec flatten (acc: doc) = function - | Concat (d1, d2) -> flatten (flatten acc d2) d1 - | CText (d, s) -> flatten (Concat(Text s, acc)) d - | Nil -> acc (* Get rid of Nil *) - | d -> Concat(d, acc) - -(* We keep a stack of active aligns. *) -type align = - { mutable gainBreak: int; (* This is the gain that is associated with - * taking the break associated with this - * alignment mark. If this is 0, then there - * is no break associated with the mark *) - mutable isTaken: bool ref; (* If breakGain is > 0 then this is a ref - * cell that must be set to true when the - * break is taken. These ref cells are also - * int the "breaks" list *) - deltaFromPrev: int ref; (* The column of this alignment mark - - * the column of the previous mark. - * Shared with the deltaToNext of the - * previous active align *) - deltaToNext: int ref (* The column of the next alignment mark - - * the columns of this one. Shared with - * deltaFromPrev of the next active align *) - } - -(* We use references to avoid the need to pass data around all the time *) -let aligns: align list ref = (* The current stack of active alignment marks, - * with the top at the head. Never empty. *) - ref [{ gainBreak = 0; isTaken = ref false; - deltaFromPrev = ref 0; deltaToNext = ref 0; }] - -let topAlignAbsCol = ref 0 (* The absolute column of the top alignment *) - -let pushAlign (abscol: int) = - let topalign = List.hd !aligns in - let res = - { gainBreak = 0; isTaken = ref false; - deltaFromPrev = topalign.deltaToNext; (* Share with the previous *) - deltaToNext = ref 0; (* Allocate a new ref *)} in - aligns := res :: !aligns; - res.deltaFromPrev := abscol - !topAlignAbsCol; - topAlignAbsCol := abscol - -let popAlign () = - match !aligns with - top :: t when t != [] -> - aligns := t; - topAlignAbsCol := !topAlignAbsCol - !(top.deltaFromPrev) - | _ -> failwith "Unmatched unalign\n" - -(** We keep a list of active markup sections. For each one we keep the column - * we are in *) -let activeMarkups: int list ref = ref [] - - -(* Keep a list of ref cells for the breaks, in the same order that we see - * them in the document *) -let breaks: bool ref list ref = ref [] - -(* The maximum column that we should use *) -let maxCol = ref 0 - -(* Sometimes we take all the optional breaks *) -let breakAllMode = ref false - -(* We are taking a newline and moving left *) -let newline () = - let topalign = List.hd !aligns in (* aligns is never empty *) - if debug then - dbgprintf "Taking a newline: reseting gain of %d\n" topalign.gainBreak; - topalign.gainBreak <- 0; (* Erase the current break info *) - if !breakAllMode && !topAlignAbsCol < !maxCol then - breakAllMode := false; - !topAlignAbsCol (* This is the new column *) - - - -(* Choose the align with the best gain. We outght to find a better way to - * keep the aligns sorted, especially since they gain never changes (when the - * align is the top align) *) -let chooseBestGain () : align option = - let bestGain = ref 0 in - let rec loop (breakingAlign: align option) = function - [] -> breakingAlign - | a :: resta -> - if debug then dbgprintf "Looking at align with gain %d\n" a.gainBreak; - if a.gainBreak > !bestGain then begin - bestGain := a.gainBreak; - loop (Some a) resta - end else - loop breakingAlign resta - in - loop None !aligns - - -(* Another one that chooses the break associated with the current align only *) -let chooseLastGain () : align option = - let topalign = List.hd !aligns in - if topalign.gainBreak > 0 then Some topalign else None - -(* We have just advanced to a new column. See if we must take a line break *) -let movingRight (abscol: int) : int = - (* Keep taking the best break until we get back to the left of maxCol or no - * more are left *) - let rec tryAgain abscol = - if abscol <= !maxCol then abscol else - begin - if debug then - dbgprintf "Looking for a break to take in column %d\n" abscol; - (* Find the best gain there is out there *) - match if !fastMode then None else chooseBestGain () with - None -> begin - (* No breaks are available. Take all breaks from now on *) - breakAllMode := true; - if debug then - dbgprintf "Can't find any breaks\n"; - abscol - end - | Some breakingAlign -> begin - let topalign = List.hd !aligns in - let theGain = breakingAlign.gainBreak in - assert (theGain > 0); - if debug then dbgprintf "Taking break at %d. gain=%d\n" abscol theGain; - breakingAlign.isTaken := true; - breakingAlign.gainBreak <- 0; - if breakingAlign != topalign then begin - breakingAlign.deltaToNext := - !(breakingAlign.deltaToNext) - theGain; - topAlignAbsCol := !topAlignAbsCol - theGain - end; - tryAgain (abscol - theGain) - end - end - in - tryAgain abscol - - -(* Keep track of nested align in gprintf. Each gprintf format string must - * have properly nested align/unalign pairs. When the nesting depth surpasses - * !printDepth then we print ... and we skip until the matching unalign *) -let printDepth = ref 10000000 (* WRW: must see whole thing *) -let alignDepth = ref 0 - -let useAlignDepth = true - -(** Start an align. Return true if we ahve just passed the threshhold *) -let enterAlign () = - incr alignDepth; - useAlignDepth && !alignDepth = !printDepth + 1 - -(** Exit an align *) -let exitAlign () = - decr alignDepth - -(** See if we are at a low-enough align level (and we should be printing - * normally) *) -let shallowAlign () = - not useAlignDepth || !alignDepth <= !printDepth - - -(* Pass the current absolute column and compute the new column *) -let rec scan (abscol: int) (d: doc) : int = - match d with - Nil -> abscol - | Concat (d1, d2) -> scan (scan abscol d1) d2 - | Text s when shallowAlign () -> - let sl = String.length s in - if debug then - dbgprintf "Done string: %s from %d to %d\n" s abscol (abscol + sl); - movingRight (abscol + sl) - | CText (d, s) -> - let abscol' = scan abscol d in - if shallowAlign () then begin - let sl = String.length s in - if debug then - dbgprintf "Done string: %s from %d to %d\n" s abscol' (abscol' + sl); - movingRight (abscol' + sl) - end else - abscol' - - | Align -> - pushAlign abscol; - if enterAlign () then - movingRight (abscol + 3) (* "..." *) - else - abscol - - | Unalign -> exitAlign (); popAlign (); abscol - - | Line when shallowAlign () -> (* A forced line break *) - if !activeMarkups != [] then - failwith "Line breaks inside markup sections"; - newline () - - | LeftFlush when shallowAlign () -> (* Keep cursor left-flushed *) 0 - - | Break when shallowAlign () -> (* An optional line break. Always a space - * followed by an optional line break *) - if !activeMarkups != [] then - failwith "Line breaks inside markup sections"; - let takenref = ref false in - breaks := takenref :: !breaks; - let topalign = List.hd !aligns in (* aligns is never empty *) - if !breakAllMode then begin - takenref := true; - newline () - end else begin - (* If there was a previous break there it stays not taken, forever. - * So we overwrite it. *) - topalign.isTaken <- takenref; - topalign.gainBreak <- 1 + abscol - !topAlignAbsCol; - if debug then - dbgprintf "Registering a break at %d with gain %d\n" - (1 + abscol) topalign.gainBreak; - movingRight (1 + abscol) - end - - | Mark -> activeMarkups := abscol :: !activeMarkups; - abscol - - | Unmark -> begin - match !activeMarkups with - old :: rest -> activeMarkups := rest; - old - | [] -> failwith "Too many unmark" - end - - | _ -> (* Align level is too deep *) abscol - - -(** Keep a running counter of the newlines we are taking. You can read and - * reset this from user code, if you want *) -let countNewLines = ref 0 - -(* The actual function that takes a document and prints it *) -let emitDoc - (emitString: string -> int -> unit) (* emit a number of copies of a - * string *) - ?(tag=fun _ -> ()) - (d: doc) = - let aligns: int list ref = ref [0] in (* A stack of alignment columns *) - - let wantIndent = ref false in - (* Use this function to take a newline *) - (* AB: modified it to flag wantIndent. The actual indentation is done only - if leftflush is not encountered *) - let newline () = - match !aligns with - [] -> failwith "Ran out of aligns" - | x :: _ -> - emitString "\n" 1; - incr countNewLines; - wantIndent := true; - x - in - (* Print indentation if wantIndent was previously flagged ; reset this flag *) - let indentIfNeeded () = - if !printIndent && !wantIndent then ignore ( - match !aligns with - [] -> failwith "Ran out of aligns" - | x :: _ -> - if x > 0 then emitString " " x; - x); - wantIndent := false - in - (* A continuation passing style loop *) - let rec loopCont (abscol: int) (d: doc) (cont: int -> unit) : unit - (* the new column *) = - match d with - Nil -> cont abscol - | Concat (d1, d2) -> - loopCont abscol d1 (fun abscol' -> loopCont abscol' d2 cont) - - | Text s when shallowAlign () -> - let sl = String.length s in - indentIfNeeded (); - emitString s 1; - cont (abscol + sl) - - | CText (d, s) -> - loopCont abscol d - (fun abscol' -> - if shallowAlign () then - let sl = String.length s in - indentIfNeeded (); - emitString s 1; - cont (abscol' + sl) - else - cont abscol') - - | Align -> - aligns := abscol :: !aligns; - if enterAlign () then begin - indentIfNeeded (); - emitString "..." 1; - cont (abscol + 3) - end else - cont abscol - - | Unalign -> begin - match !aligns with - [] -> failwith "Unmatched unalign" - | _ :: rest -> - exitAlign (); - aligns := rest; cont abscol - end - | Line when shallowAlign () -> cont (newline ()) - | LeftFlush when shallowAlign () -> wantIndent := false; cont (0) - | Break when shallowAlign () -> begin - match !breaks with - [] -> failwith "Break without a takenref" - | istaken :: rest -> - breaks := rest; (* Consume the break *) - if !istaken then cont (newline ()) - else begin - indentIfNeeded (); - emitString " " 1; - cont (abscol + 1) - end - end - - | Mark -> - activeMarkups := abscol :: !activeMarkups; - cont abscol - - | Unmark -> begin - match !activeMarkups with - old :: rest -> activeMarkups := rest; - cont old - | [] -> failwith "Unmark without a mark" - end - - | Tag s -> - tag s; - cont abscol - - | _ -> (* Align is too deep *) - cont abscol - in - - loopCont 0 d (fun _ -> ()) - - -(* Print a document on a channel *) -let fprint (chn: out_channel) ~(width: int) doc = - (* Save some parameters, to allow for nested calls of these routines. *) - maxCol := width; - let old_breaks = !breaks in - breaks := []; - let old_alignDepth = !alignDepth in - alignDepth := 0; - let old_activeMarkups = !activeMarkups in - activeMarkups := []; - ignore (scan 0 doc); - breaks := List.rev !breaks; - ignore (emitDoc - (fun s nrcopies -> - for i = 1 to nrcopies do - output_string chn s - done) doc); - activeMarkups := old_activeMarkups; - alignDepth := old_alignDepth; - breaks := old_breaks (* We must do this especially if we don't do emit - * (which consumes breaks) because otherwise we waste - * memory *) - -(* Print the document to a string *) -let sprint ~(width : int) doc : string = - maxCol := width; - let old_breaks = !breaks in - breaks := []; - let old_activeMarkups = !activeMarkups in - activeMarkups := []; - let old_alignDepth = !alignDepth in - alignDepth := 0; - ignore (scan 0 doc); - breaks := List.rev !breaks; - let buf = Buffer.create 1024 in - let rec add_n_strings str num = - if num <= 0 then () - else begin Buffer.add_string buf str; add_n_strings str (num - 1) end - in - emitDoc add_n_strings doc; - breaks := old_breaks; - activeMarkups := old_activeMarkups; - alignDepth := old_alignDepth; - Buffer.contents buf - -let pretty fmt doc = - let s = sprint ~width:80 doc in - Format.fprintf fmt "%s" s - (* The rest is based on printf.ml *) -external format_int: string -> int -> string = "caml_format_int" -external format_float: string -> float -> string = "caml_format_float" - - - -let gprintf (finish : doc -> 'b) - (format : ('a, unit, doc, 'b) format4) : 'a = - let format = (Obj.magic format : string) in - - (* Record the starting align depth *) - let startAlignDepth = !alignDepth in - (* Special concatenation functions *) - let dconcat (acc: doc) (another: doc) = - if !alignDepth > !printDepth then acc else acc ++ another in - let dctext1 (acc: doc) (str: string) = - if !alignDepth > !printDepth then acc else - CText(acc, str) - in - (* Special finish function *) - let dfinish (dc: doc) : 'b = - if !alignDepth <> startAlignDepth then - prerr_string ("Unmatched align/unalign in " ^ format ^ "\n"); - finish dc - in - let flen = String.length format in - (* Reading a format character *) - let fget = String.unsafe_get format in - (* Output a literal sequence of - * characters, starting at i. The - * character at i does not need to be - * checked. *) - let rec literal acc i = - let rec skipChars j = - if j >= flen || - (match fget j with - '%' -> true - | '@' -> true - | '\n' -> true - | _ -> false) then - collect (dctext1 acc (String.sub format i (j-i))) j - else - skipChars (succ j) - in - skipChars (succ i) - (* the main collection function *) - and collect (acc: doc) (i: int) = - if i >= flen then begin - Obj.magic (dfinish acc) - end else begin - let c = fget i in - if c = '%' then begin - let j = skip_args (succ i) in - match fget j with - '%' -> literal acc j - | 's' -> - Obj.magic(fun s -> - let str = - if j <= i+1 then - s - else - let sl = String.length s in - let p = - try - int_of_string (String.sub format (i+1) (j-i-1)) - with _ -> - invalid_arg "fprintf: bad %s format" in - if p > 0 && sl < p then - (String.make (p - sl) ' ') ^ s - else if p < 0 && sl < -p then - s ^ (String.make (-p - sl) ' ') - else - s - in - collect (breakString acc str) (succ j)) - | 'c' -> - Obj.magic(fun c -> - collect (dctext1 acc (String.make 1 c)) (succ j)) - | 'd' | 'i' | 'o' | 'x' | 'X' | 'u' -> - Obj.magic(fun n -> - collect (dctext1 acc - (format_int (String.sub format i - (j-i+1)) n)) - (succ j)) - (* L, l, and n are the Int64, Int32, and Nativeint modifiers to the integer - formats d,i,o,x,X,u. For example, %Lo means print an Int64 in octal.*) - | 'L' -> - if j != i + 1 then (*Int64.format handles simple formats like %d. - * Any special flags eaten by skip_args will confuse it. *) - invalid_arg ("dprintf: unimplemented format " - ^ (String.sub format i (j-i+1))); - let j' = succ j in (* eat the d,i,x etc. *) - let format_spec = "% " in - String.set format_spec 1 (fget j'); (* format_spec = "%x", etc. *) - Obj.magic(fun n -> - collect (dctext1 acc - (Int64.format format_spec n)) - (succ j')) - | 'l' -> - if j != i + 1 then invalid_arg ("dprintf: unimplemented format " - ^ (String.sub format i (j-i+1))); - let j' = succ j in (* eat the d,i,x etc. *) - let format_spec = "% " in - String.set format_spec 1 (fget j'); (* format_spec = "%x", etc. *) - Obj.magic(fun n -> - collect (dctext1 acc - (Int32.format format_spec n)) - (succ j')) - | 'n' -> - if j != i + 1 then invalid_arg ("dprintf: unimplemented format " - ^ (String.sub format i (j-i+1))); - let j' = succ j in (* eat the d,i,x etc. *) - let format_spec = "% " in - String.set format_spec 1 (fget j'); (* format_spec = "%x", etc. *) - Obj.magic(fun n -> - collect (dctext1 acc - (Nativeint.format format_spec n)) - (succ j')) - | 'f' | 'e' | 'E' | 'g' | 'G' -> - Obj.magic(fun f -> - collect (dctext1 acc - (format_float (String.sub format i (j-i+1)) f)) - (succ j)) - | 'b' | 'B' -> - Obj.magic(fun b -> - collect (dctext1 acc (string_of_bool b)) (succ j)) - | 'a' -> - Obj.magic(fun pprinter arg -> - collect (dconcat acc (pprinter () arg)) (succ j)) - | 't' -> - Obj.magic(fun pprinter -> - collect (dconcat acc (pprinter ())) (succ j)) - | c -> - invalid_arg ("dprintf: unknown format %s" ^ String.make 1 c) - - end else if c = '@' then begin - if i + 1 < flen then begin - match fget (succ i) with - - (* Now the special format characters *) - '[' -> (* align *) - let newacc = - if !alignDepth > !printDepth then - acc - else if !alignDepth = !printDepth then - CText(acc, "...") - else - acc ++ align - in - incr alignDepth; - collect newacc (i + 2) - - | ']' -> (* unalign *) - decr alignDepth; - let newacc = - if !alignDepth >= !printDepth then - acc - else - acc ++ unalign - in - collect newacc (i + 2) - | '!' | '\n' -> (* hard-line break *) - collect (dconcat acc line) (i + 2) - | '?' -> (* soft line break *) - collect (dconcat acc (break)) (i + 2) - | '<' -> - collect (dconcat acc mark) (i +1) - | '>' -> - collect (dconcat acc unmark) (i +1) - | '^' -> (* left-flushed *) - collect (dconcat acc (leftflush)) (i + 2) - | '@' -> - collect (dctext1 acc "@") (i + 2) - | c -> - invalid_arg ("dprintf: unknown format @" ^ String.make 1 c) - end else - invalid_arg "dprintf: incomplete format @" - end else if c = '\n' then begin - collect (dconcat acc line) (i + 1) - end else - literal acc i - end - - and skip_args j = - match String.unsafe_get format j with - '0' .. '9' | ' ' | '.' | '-' -> skip_args (succ j) - | _ -> j - - in - collect Nil 0 - -let withPrintDepth dp thunk = - let opd = !printDepth in - printDepth := dp; - thunk (); - printDepth := opd - - - -let flushOften = ref false - -let dprintf format = gprintf (fun x -> x) format -let fprintf chn format = - let f d = fprint chn 80 d; d in - (* weimeric hack begins -- flush output to streams *) - let res = gprintf f format in - (* save the value we would have returned, flush the channel and then - * return it -- this allows us to see debug input near infinite loops - * *) - if !flushOften then flush chn; - res - (* weimeric hack ends *) - -let printf format = fprintf stdout format -let eprintf format = fprintf stderr format - - - -(******************************************************************************) -let getAlgoName = function - George -> "George" - | Aman -> "Aman" - | Gap -> "Gap" - -let getAboutString () : string = - "(Pretty: ALGO=" ^ (getAlgoName algo) ^ ")" - - -(************************************************) -let auto_printer (typ: string) = - failwith ("Pretty.auto_printer \"" ^ typ ^ "\" only works with you use -pp \"camlp4o pa_prtype.cmo\" when you compile") - - -let emit_doc emit ?tag ~width doc = - maxCol := width; - breaks := []; - activeMarkups := []; - alignDepth := 0; - ignore (scan 0 doc); - breaks := List.rev !breaks; - alignDepth := 0; - emitDoc emit ?tag doc; - breaks := []; - activeMarkups := [] diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/pretty.mli frama-c-20111001+nitrogen+dfsg/cil/src/legacy/pretty.mli --- frama-c-20110201+carbon+dfsg/cil/src/legacy/pretty.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/pretty.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,369 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* - * - * Copyright (c) 2001 by - * George C. Necula necula@cs.berkeley.edu - * Scott McPeak smcpeak@cs.berkeley.edu - * Wes Weimer weimer@cs.berkeley.edu - * - * All rights reserved. Permission to use, copy, modify and distribute - * this software for research purposes only is hereby granted, - * provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * DISCLAIMER: - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *) - -(** Utility functions for pretty-printing. The major features provided by - this module are -- An [fprintf]-style interface with support for user-defined printers -- The printout is fit to a width by selecting some of the optional newlines -- Constructs for alignment and indentation -- Print ellipsis starting at a certain nesting depth -- Constructs for printing lists and arrays - - Pretty-printing occurs in two stages: -- Construct a {!Pretty.doc} object that encodes all of the elements to be - printed - along with alignment specifiers and optional and mandatory newlines -- Format the {!Pretty.doc} to a certain width and emit it as a string, to an - output stream or pass it to a user-defined function - - The formatting algorithm is not optimal but it does a pretty good job while - still operating in linear time. The original version was based on a pretty - printer by Philip Wadler which turned out to not scale to large jobs. -*) - -(** API *) - -(** The type of unformated documents. Elements of this type can be - * constructed in two ways. Either with a number of constructor shown below, - * or using the {!Pretty.dprintf} function with a [printf]-like interface. - * The {!Pretty.dprintf} method is slightly slower so we do not use it for - * large jobs such as the output routines for a compiler. But we use it for - * small jobs such as logging and error messages. *) -type doc - - - -(** Constructors for the doc type. *) - - - - -(** Constructs an empty document *) -val nil : doc - - -(** Concatenates two documents. This is an infix operator that associates to - the left. *) -val (++) : doc -> doc -> doc -val concat : doc -> doc -> doc - -(** A document that prints the given string *) -val text : string -> doc - - -(** A document that prints an integer in decimal form *) -val num : int -> doc - - -(** A document that prints a real number *) -val real : float -> doc - -(** A document that prints a character. This is just like {!Pretty.text} - with a one-character string. *) -val chr : char -> doc - - -(** A document that consists of a mandatory newline. This is just like [(text - "\n")]. The new line will be indented to the current indentation level, - unless you use {!Pretty.leftflush} right after this. *) -val line : doc - -(** Use after a {!Pretty.line} to prevent the indentation. Whatever follows - * next will be flushed left. Indentation resumes on the next line. *) -val leftflush : doc - - -(** A document that consists of either a space or a line break. Also called - an optional line break. Such a break will be - taken only if necessary to fit the document in a given width. If the break - is not taken a space is printed instead. *) -val break: doc - -(** Mark the current column as the current indentation level. Does not print - anything. All taken line breaks will align to this column. The previous - alignment level is saved on a stack. *) -val align: doc - -(** Reverts to the last saved indentation level. *) -val unalign: doc - - -(** Mark the beginning of a markup section. The width of a markup section is - * considered 0 for the purpose of computing identation *) -val mark: doc - -(** The end of a markup section *) -val unmark: doc - -(************* Now some syntactic sugar *****************) -(** Syntactic sugar *) - -(** Indents the document. Same as [((text " ") ++ align ++ doc ++ unalign)], - with the specified number of spaces. *) -val indent: int -> doc -> doc - -(** Prints a document as markup. The marked document cannot contain line - * breaks or alignment constructs. *) -val markup: doc -> doc - -(** Formats a sequence. [sep] is a separator, [doit] is a function that - * converts an element to a document. *) -val seq: sep:doc -> doit:('a ->doc) -> elements:'a list -> doc - - -(** An alternative function for printing a list. The [unit] argument is there - * to make this function more easily usable with the {!Pretty.dprintf} - * interface. The first argument is a separator, by default a comma. *) -val docList: ?sep:doc -> ('a -> doc) -> unit -> 'a list -> doc - -(** sm: Yet another list printer. This one accepts the same kind of - * printing function that {!Pretty.dprintf} does, and itself works - * in the dprintf context. Also accepts - * a string as the separator since that's by far the most common. *) -val d_list: string -> (unit -> 'a -> doc) -> unit -> 'a list -> doc - -(** Formats an array. A separator and a function that prints an array - element. The default separator is a comma. *) -val docArray: ?sep:doc -> (int -> 'a -> doc) -> unit -> 'a array -> doc - -(** Prints an ['a option] with [None] or [Some] *) -val docOpt: ('a -> doc) -> unit -> 'a option -> doc - - -(** Print an int32 *) -val d_int32: int32 -> doc -val f_int32: unit -> int32 -> doc - -val d_int64: int64 -> doc -val f_int64: unit -> int64 -> doc - -(** Format maps. *) -module MakeMapPrinter : - functor (Map: sig - type key - type 'a t - val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b - end) -> -sig - (** Format a map, analogous to docList. *) - val docMap: ?sep:doc -> (Map.key -> 'a -> doc) -> unit -> 'a Map.t -> doc - - (** Format a map, analogous to d_list. *) - val d_map: ?dmaplet:(doc -> doc -> doc) - -> string - -> (unit -> Map.key -> doc) - -> (unit -> 'a -> doc) - -> unit - -> 'a Map.t - -> doc - end - -(** Format sets. *) -module MakeSetPrinter : - functor (Set: sig - type elt - type t - val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a - end) -> -sig - (** Format a set, analogous to docList. *) - val docSet: ?sep:doc -> (Set.elt -> doc) -> unit -> Set.t -> doc - - (** Format a set, analogous to d_list. *) - val d_set: string - -> (unit -> Set.elt -> doc) - -> unit - -> Set.t - -> doc -end - -(** A function that is useful with the [printf]-like interface *) -val insert: unit -> doc -> doc - -val dprintf: ('a, unit, doc, doc) format4 -> 'a -(** This function provides an alternative method for constructing - [doc] objects. The first argument for this function is a format string - argument (of type [('a, unit, doc) format]; if you insist on - understanding what that means see the module [Printf]). The format string - is like that for the [printf] function in C, except that it understands a - few more formatting controls, all starting with the @ character. - - See the gprintf function if you want to pipe the result of dprintf into - some other functions. - - The following special formatting characters are understood (these do not - correspond to arguments of the function): -- @\[ Inserts an {!Pretty.align}. Every format string must have matching - {!Pretty.align} and {!Pretty.unalign}. -- @\] Inserts an {!Pretty.unalign}. -- @! Inserts a {!Pretty.line}. Just like "\n" -- @? Inserts a {!Pretty.break}. -- @< Inserts a {!Pretty.mark}. -- @> Inserts a {!Pretty.unmark}. -- @^ Inserts a {!Pretty.leftflush} - Should be used immediately after @! or "\n". -- @@ : inserts a @ character - - In addition to the usual [printf] % formatting characters the following two - new characters are supported: -- %t Corresponds to an argument of type [unit -> doc]. This argument is - invoked to produce a document -- %a Corresponds to {b two} arguments. The first of type [unit -> 'a -> doc] - and the second of type ['a]. (The extra [unit] is do to the - peculiarities of the built-in support for format strings in Ocaml. It - turns out that it is not a major problem.) Here is an example of how - you use this: - -{v dprintf "Name=%s, SSN=%7d, Children=\@\[%a\@\]\n" - pers.name pers.ssn (docList (chr ',' ++ break) text) - pers.children v} - - The result of [dprintf] is a {!Pretty.doc}. You can format the document and - emit it using the functions {!Pretty.fprint} and {!Pretty.sprint}. - -*) - -(** Like {!Pretty.dprintf} but more general. It also takes a function that is - * invoked on the constructed document but before any formatting is done. The - * type of the format argument means that 'a is the type of the parameters of - * this function, unit is the type of the first argument to %a and %t - * formats, doc is the type of the intermediate result, and 'b is the type of - * the result of gprintf. *) -val gprintf: (doc -> 'b) -> ('a, unit, doc, 'b) format4 -> 'a - -(** Format the document to the given width and emit it to the given channel *) -val fprint: out_channel -> width:int -> doc -> unit - -(** Format the document to the given width and emit it as a string *) -val sprint: width:int -> doc -> string - -(** Like {!Pretty.dprintf} followed by {!Pretty.fprint} *) -val fprintf: out_channel -> ('a, unit, doc) format -> 'a - -(** Like {!Pretty.fprintf} applied to [stdout] *) -val printf: ('a, unit, doc) format -> 'a - -(** Like {!Pretty.fprintf} applied to [stderr] *) -val eprintf: ('a, unit, doc) format -> 'a - - -(* sm: arg! why can't I write this function?! *) -(* * Like {!Pretty.dprintf} but yielding a string with no newlines *) -(*val sprintf: (doc, unit, doc) format -> string*) - -(* sm: different tack.. *) -(* doesn't work either. well f it anyway *) -(*val failwithf: ('a, unit, doc) format -> 'a*) - - -(** Invokes a thunk, with printDepth temporarily set to the specified value *) -val withPrintDepth : int -> (unit -> unit) -> unit - -(** The following variables can be used to control the operation of the printer *) - -(** Specifies the nesting depth of the [align]/[unalign] pairs at which - everything is replaced with ellipsis *) -val printDepth : int ref - -val printIndent : bool ref (** If false then does not indent *) - - -(** If set to [true] then optional breaks are taken only when the document - has exceeded the given width. This means that the printout will looked - more ragged but it will be faster *) -val fastMode : bool ref - -val flushOften : bool ref (** If true the it flushes after every print *) - - -(** Keep a running count of the taken newlines. You can read and write this - * from the client code if you want *) -val countNewLines : int ref - - -(** A function that when used at top-level in a module will direct - * the pa_prtype module generate automatically the printing functions for a - * type *) -val auto_printer: string -> 'b - -(** CEA-LRI *) - -val pretty : Format.formatter -> doc -> unit - -val tag : string -> doc - -val emit_doc : - (string -> int -> unit) (* emit a number of copies of a string *) -> - ?tag:(string -> unit) (* emit a tag *) -> - width:int -> - doc -> - unit diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/trace.ml frama-c-20111001+nitrogen+dfsg/cil/src/legacy/trace.ml --- frama-c-20110201+carbon+dfsg/cil/src/legacy/trace.ml 2011-02-07 13:42:19.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/trace.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,209 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* - * - * Copyright (c) 2001-2002, - * George C. Necula - * Scott McPeak - * Wes Weimer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The names of the contributors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *) - -(* Trace module implementation - * see trace.mli - *) - -open Pretty;; - - -(* --------- traceSubsystems --------- *) -(* this is the list of tags (usually subsystem names) for which - * trace output will appear *) -let traceSubsystems : string list ref = ref [];; - - -let traceAddSys (subsys : string) : unit = - (* (ignore (printf "traceAddSys %s\n" subsys)); *) - traceSubsystems := subsys :: !traceSubsystems -;; - - -let traceActive (subsys : string) : bool = - (* (List.mem elt list) returns true if something in list equals ('=') elt *) - (List.mem subsys !traceSubsystems) -;; - - -let rec parseString (str : string) (delim : char) : string list = -begin - if (not (String.contains str delim)) then - if ((String.length str) = 0) then - [] - else - [str] - - else - let d = ((String.index str delim) + 1) in - if (d = 1) then - (* leading delims are eaten *) - (parseString (String.sub str d ((String.length str) - d)) delim) - else - (String.sub str 0 (d-1)) :: - (parseString (String.sub str d ((String.length str) - d)) delim) -end;; - -let traceAddMulti (systems : string) : unit = -begin - let syslist = (parseString systems ',') in - (List.iter traceAddSys syslist) -end;; - - - -(* --------- traceIndent --------- *) -let traceIndentLevel : int ref = ref 0;; - - -let traceIndent (sys : string) : unit = - if (traceActive sys) then - traceIndentLevel := !traceIndentLevel + 2 -;; - -let traceOutdent (sys : string) : unit = - if ((traceActive sys) && - (!traceIndentLevel >= 2)) then - traceIndentLevel := !traceIndentLevel - 2 -;; - - -(* --------- trace --------- *) -(* return a tag to prepend to a trace output - * e.g. " %%% mysys: " - *) -let traceTag (sys : string) : Pretty.doc = - (* return string of 'i' spaces *) - let rec ind (i : int) : string = - if (i <= 0) then - "" - else - " " ^ (ind (i-1)) - - in - (text ((ind !traceIndentLevel) ^ "%%% " ^ sys ^ ": ")) -;; - - -(* this is the trace function; its first argument is a string - * tag, and subsequent arguments are like printf formatting - * strings ("%a" and whatnot) *) -let trace - (subsys : string) (* subsystem identifier for enabling tracing *) - (d : Pretty.doc) (* something made by 'dprintf' *) - : unit = (* no return value *) - (* (ignore (printf "trace %s\n" subsys)); *) - - (* see if the subsystem's tracing is turned on *) - if (traceActive subsys) then - begin - (fprint stderr 80 (* print it *) - ((traceTag subsys) ++ d)); (* with prepended subsys tag *) - (* mb: flush after every message; useful if the program hangs in an - infinite loop... *) - (flush stderr) - end - else - () (* eat it *) -;; - - -let tracei (sys : string) (d : Pretty.doc) : unit = - (* trace before indent *) - (trace sys d); - (traceIndent sys) -;; - -let traceu (sys : string) (d : Pretty.doc) : unit = - (* trace after outdent *) - (* no -- I changed my mind -- I want trace *then* outdent *) - (trace sys d); - (traceOutdent sys) -;; - - - - -(* -------------------------- trash --------------------- *) -(* TRASH START - -(* sm: more experimenting *) -(trace "no" (dprintf "no %d\n" 5)); -(trace "yes" (dprintf "yes %d\n" 6)); -(trace "maybe" (dprintf "maybe %d\n" 7)); - -TRASH END *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/legacy/trace.mli frama-c-20111001+nitrogen+dfsg/cil/src/legacy/trace.mli --- frama-c-20110201+carbon+dfsg/cil/src/legacy/trace.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/legacy/trace.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003, *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'Énergie Atomique). *) -(**************************************************************************) - -(* - * - * Copyright (c) 2001-2002, - * George C. Necula - * Scott McPeak - * Wes Weimer - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The names of the contributors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *) - -(* Trace module - * Scott McPeak, 5/4/00 - * - * The idea is to pepper the source with debugging printfs, - * and be able to select which ones to actually display at - * runtime. - * - * It is built on top of the Pretty module for printing data - * structures. - * - * To a first approximation, this is needed to compensate for - * the lack of a debugger that does what I want... - *) - - -(* this is the list of tags (usually subsystem names) for which - * trace output will appear *) -val traceSubsystems : string list ref - -(* interface to add a new subsystem to trace (slightly more - * convenient than direclty changing 'tracingSubsystems') *) -val traceAddSys : string -> unit - -(* query whether a particular subsystem is being traced *) -val traceActive : string -> bool - -(* add several systems, separated by commas *) -val traceAddMulti : string -> unit - - -(* current indentation level for tracing *) -val traceIndentLevel : int ref - -(* bump up or down the indentation level, if the given subsys - * is being traced *) -val traceIndent : string -> unit -val traceOutdent : string -> unit - - -(* this is the trace function; its first argument is a string - * tag, and second argument is a 'doc' (which is what 'dprintf' - * returns). - * - * so a sample usage might be - * (trace "mysubsys" (dprintf "something neat happened %d times\n" counter)) - *) -val trace : string -> Pretty.doc -> unit - - -(* special flavors that indent/outdent as well. the indent version - * indents *after* printing, while the outdent version outdents - * *before* printing. thus, a sequence like - * - * (tracei "foo" (dprintf "beginning razzle-dazzle\n")) - * ..razzle.. - * ..dazzle.. - * (traceu "foo" (dprintf "done with razzle-dazzle\n")) - * - * will do the right thing - * - * update -- I changed my mind! I decided I prefer it like this - * %%% sys: (myfunc args) - * %%% ...inner stuff... - * %%% sys: myfunc returning 56 - * - * so now they both print before in/outdenting - *) -val tracei : string -> Pretty.doc -> unit -val traceu : string -> Pretty.doc -> unit diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_builtin.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_builtin.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_builtin.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_builtin.ml 2011-10-10 08:40:07.000000000 +0000 @@ -30,6 +30,8 @@ let float_type = Ctype Cil.floatType let double_type = Ctype Cil.doubleType let long_double_type = Ctype Cil.longDoubleType +let object_ptr = Ctype Cil.voidPtrType +let fun_ptr = Ctype (TPtr(TFun(Cil.voidType,None,false,[]),[])) let init = let called = ref false in @@ -38,7 +40,7 @@ the same name. *) fun () -> - if ! called then (fun () -> ()) + if !called then (fun () -> ()) else begin called:=true; fun () -> @@ -119,13 +121,21 @@ "\\no_overflow_double", [], ["m", rounding_mode; "x", Lreal] ; "\\subset", ["a"], ["s1", Ltype (set, [Lvar "a"]); "s2", Ltype (set, [Lvar "a"])]; + "\\pointer_comparable", [], [("p1", object_ptr); + ("p2", object_ptr)]; + "\\pointer_comparable", [], [("p1", fun_ptr); + ("p2", fun_ptr)]; + "\\pointer_comparable", [], [("p1", fun_ptr); + ("p2", object_ptr)]; + "\\pointer_comparable", [], [("p1", object_ptr); + ("p2", fun_ptr)]; ]; (* functions *) List.iter (fun (f,params,ret_type) -> add { bl_name = f; bl_params = []; bl_profile = params; bl_type = Some ret_type; bl_labels = []}) - [ "\\exit_status", [], Linteger; + [ "\\min", ["x",Linteger;"y",Linteger], Linteger ; "\\max", ["x",Linteger;"y",Linteger], Linteger ; "\\min", ["x",Lreal;"y",Lreal], Lreal ; @@ -232,7 +242,6 @@ ] end - (* Local Variables: compile-command: "make -j -C ../../.." diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_const.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_const.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_const.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_const.ml 2011-10-10 08:40:07.000000000 +0000 @@ -29,36 +29,77 @@ (** {1 Identification Numbers} *) -(**/**) -let __annot_count = ref 0 -let __pred_count = ref 0 -let __term_count = ref 0 -(**/**) +module AnnotId = + State_builder.SharedCounter(struct let name = "annot_counter" end) +module PredicateId = + State_builder.SharedCounter(struct let name = "predicate_counter" end) +module TermId = + State_builder.SharedCounter(struct let name = "term_counter" end) -let new_code_annotation annot = - incr __annot_count; { annot_content = annot ; annot_id = !__annot_count } -let fresh_code_annotation () = - incr __annot_count; !__annot_count +let new_code_annotation annot = + { annot_content = annot ; annot_id = AnnotId.next () } -let refresh_code_annotation annot = new_code_annotation annot.annot_content +let fresh_code_annotation = AnnotId.next let new_predicate p = - incr __pred_count; - { ip_id = !__pred_count; + { ip_id = PredicateId.next (); ip_content = p.content; ip_loc = p.loc; ip_name = p.name } -let fresh_predicate_id () = - incr __pred_count; !__pred_count +let fresh_predicate_id = PredicateId.next let pred_of_id_pred p = { name = p.ip_name; loc = p.ip_loc; content = p.ip_content } +let refresh_predicate p = { p with ip_id = PredicateId.next () } + let new_identified_term t = - incr __term_count; { it_id = !__term_count; it_content = t } + { it_id = TermId.next (); it_content = t } -let fresh_term_id () = - incr __term_count; !__term_count +let fresh_term_id = TermId.next + +let refresh_deps = function + | FromAny -> FromAny + | From l -> + From (List.map (fun d -> new_identified_term d.it_content) l) + +let refresh_from (a,d) = (new_identified_term a.it_content, refresh_deps d) + +let refresh_assigns a = + match a with + WritesAny -> WritesAny + | Writes l -> + Writes(List.map refresh_from l) + +let refresh_behavior b = + { b with + b_requires = List.map refresh_predicate b.b_requires; + b_assumes = List.map refresh_predicate b.b_assumes; + b_post_cond = + List.map (fun (k,p) -> (k, refresh_predicate p)) b.b_post_cond; + b_assigns = refresh_assigns b.b_assigns; + b_extended = + List.map (fun (s,n,p) -> (s,n,List.map refresh_predicate p)) b.b_extended + } + +let refresh_variant (t,s) = (new_identified_term t.it_content,s) + +let refresh_spec s = + { spec_behavior = List.map refresh_behavior s.spec_behavior; + spec_variant = s.spec_variant; + spec_terminates = Extlib.opt_map refresh_predicate s.spec_terminates; + spec_complete_behaviors = s.spec_complete_behaviors; + spec_disjoint_behaviors = s.spec_disjoint_behaviors; + } + +let refresh_code_annotation annot = + let content = + match annot.annot_content with + | AAssert _ | AInvariant _ | AVariant _ | APragma _ as c -> c + | AStmtSpec(l,spec) -> AStmtSpec(l, refresh_spec spec) + | AAssigns(l,a) -> AAssigns(l, refresh_assigns a) + in + new_code_annotation content (** {1 Smart constructors} *) @@ -80,89 +121,88 @@ {content = p ; loc = loc; name = [] } let ptrue = unamed Ptrue - let pfalse = unamed Pfalse let pold ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) p = match p.content with -| Ptrue | Pfalse -> p -| _ -> {p with content = Pold p; loc = loc} + | Ptrue | Pfalse -> p + | _ -> {p with content = Pat(p, old_label); loc = loc} let papp ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p,lab,a) = unamed ~loc (Papp(p,lab,a)) let pand ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p1, p2) = match p1.content, p2.content with -| Ptrue, _ -> p2 -| _, Ptrue -> p1 -| Pfalse, _ -> p1 -| _, Pfalse -> p2 -| _, _ -> unamed ~loc (Pand (p1, p2)) + | Ptrue, _ -> p2 + | _, Ptrue -> p1 + | Pfalse, _ -> p1 + | _, Pfalse -> p2 + | _, _ -> unamed ~loc (Pand (p1, p2)) let por ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p1, p2) = -match p1.content, p2.content with -| Ptrue, _ -> p1 -| _, Ptrue -> p2 -| Pfalse, _ -> p2 -| _, Pfalse -> p1 -| _, _ -> unamed ~loc (Por (p1, p2)) + match p1.content, p2.content with + | Ptrue, _ -> p1 + | _, Ptrue -> p2 + | Pfalse, _ -> p2 + | _, Pfalse -> p1 + | _, _ -> unamed ~loc (Por (p1, p2)) let pxor ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p1, p2) = match p1.content, p2.content with - Ptrue, Ptrue -> unamed ~loc Pfalse - | Ptrue, _ -> p1 - | _, Ptrue -> p2 - | Pfalse, _ -> p2 - | _, Pfalse -> p1 - | _,_ -> unamed ~loc (Pxor (p1,p2)) + | Ptrue, Ptrue -> unamed ~loc Pfalse + | Ptrue, _ -> p1 + | _, Ptrue -> p2 + | Pfalse, _ -> p2 + | _, Pfalse -> p1 + | _,_ -> unamed ~loc (Pxor (p1,p2)) let pnot ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) p2 = match p2.content with -| Ptrue -> {p2 with content = Pfalse; loc = loc } -| Pfalse -> {p2 with content = Ptrue; loc = loc } -| _ -> unamed ~loc (Pnot p2) + | Ptrue -> {p2 with content = Pfalse; loc = loc } + | Pfalse -> {p2 with content = Ptrue; loc = loc } + | Pnot p -> p + | _ -> unamed ~loc (Pnot p2) let pands l = List.fold_right (fun p1 p2 -> pand (p1, p2)) l ptrue - let pors l = List.fold_right (fun p1 p2 -> por (p1, p2)) l pfalse let plet ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) p = match p.content with -| (_, ({content = Ptrue} as p)) -> p -| (v, p) -> unamed ~loc (Plet (v, p)) + | (_, ({content = Ptrue} as p)) -> p + | (v, p) -> unamed ~loc (Plet (v, p)) let pimplies ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p1,p2) = -match p1.content,p2.content with -| Ptrue, _ | _, Ptrue -> p2 -| Pfalse, _ -> - {name = p1.name ; loc = loc; content = Ptrue } -| _, _ -> unamed ~loc (Pimplies (p1, p2)) + match p1.content, p2.content with + | Ptrue, _ | _, Ptrue -> p2 + | Pfalse, _ -> { name = p1.name; loc = loc; content = Ptrue } + | _, _ -> unamed ~loc (Pimplies (p1, p2)) let pif ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (t,p2,p3) = -match (p2.content,p3.content) with -| Ptrue, Ptrue -> ptrue -| Pfalse, Pfalse -> pfalse -| _,_ -> unamed ~loc (Pif (t,p2,p3)) + match (p2.content, p3.content) with + | Ptrue, Ptrue -> ptrue + | Pfalse, Pfalse -> pfalse + | _,_ -> unamed ~loc (Pif (t,p2,p3)) let piff ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p2,p3) = -match (p2.content,p3.content) with -| Pfalse, Pfalse -> ptrue -| Ptrue, _ -> p3 -| _, Ptrue -> p2 -| _,_ -> unamed ~loc (Piff (p2,p3)) + match p2.content, p3.content with + | Pfalse, Pfalse -> ptrue + | Ptrue, _ -> p3 + | _, Ptrue -> p2 + | _,_ -> unamed ~loc (Piff (p2,p3)) (** @plugin development guide *) let prel ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (a,b,c) = unamed ~loc (Prel(a,b,c)) let pforall ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (l,p) = match l with -| [] -> p -| _ -> match p.content with - | Ptrue -> p - | _ -> unamed ~loc (Pforall (l,p)) + | [] -> p + | _ :: _ -> + match p.content with + | Ptrue -> p + | _ -> unamed ~loc (Pforall (l,p)) let pexists ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (l,p) = match l with -| [] -> p -| _ -> match p.content with - | Pfalse -> p - | _ -> unamed ~loc (Pexists (l,p)) + | [] -> p + | _ :: _ -> match p.content with + | Pfalse -> p + | _ -> unamed ~loc (Pexists (l,p)) let pfresh ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) p = unamed ~loc (Pfresh p) let pvalid ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) p = unamed ~loc (Pvalid p) @@ -171,6 +211,8 @@ unamed ~loc (Pvalid_index (p,q)) let pvalid_range ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p,q,r) = unamed ~loc (Pvalid_range (p,q,r)) +let pinitialized ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) p = + unamed ~loc (Pinitialized p) let psubtype ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (p,q) = unamed ~loc (Psubtype (p,q)) @@ -181,47 +223,42 @@ (** [set_conversion ty1 ty2] returns a set type as soon as [ty1] and/or [ty2] is a set. Elements have type [ty1], or the type of the elements of [ty1] if - it is itself a set-type ({i.e.} we do not build set of sets that way). -*) + it is itself a set-type ({i.e.} we do not build set of sets that way).*) let set_conversion ty1 ty2 = match ty1,ty2 with - Ltype ({lt_name = "set"},[_]),_ -> ty1 - | ty1,Ltype({lt_name = "set"} as lt,[_]) -> Ltype(lt,[ty1]) - | _ -> ty1 + | Ltype ({lt_name = "set"},[_]),_ -> ty1 + | ty1, Ltype({lt_name = "set"} as lt,[_]) -> Ltype(lt,[ty1]) + | _ -> ty1 (** converts a type into the corresponding set type if needed. *) let make_set_type ty = - set_conversion ty - (Ltype(Logic_env.find_logic_type "set",[Lvar "_"])) + set_conversion ty (Ltype(Logic_env.find_logic_type "set",[Lvar "_"])) (** returns the type of elements of a set type. - @raise Failure if the input type is not a set type. - *) + @raise Failure if the input type is not a set type. *) let type_of_element ty = match ty with | Ltype ({lt_name = "set"},[t]) -> t | _ -> failwith "not a set type" (** [plain_or_set f t] applies [f] to [t] or to the type of elements of [t] - if it is a set type - *) + if it is a set type *) let plain_or_set f = function - | Ltype ({lt_name = "set"},[t]) -> f t - | t -> f t + | Ltype ({lt_name = "set"},[t]) -> f t + | t -> f t + +let transform_element f t = set_conversion (plain_or_set f t) t let is_plain_type = function - | Ltype ({lt_name = "set"},[_]) -> false - | _ -> true + | Ltype ({lt_name = "set"},[_]) -> false + | _ -> true + +let is_boolean_type = function + | Ltype ({ lt_name = s }, []) when s = Utf8_logic.boolean -> true + | _ -> false (** {2 Terms} *) (* empty line for ocamldoc *) -let taddrof ?(loc=Lexing.dummy_pos, Lexing.dummy_pos) lv typ = - match lv with - | TMem h, TNoOffset -> h - | _ -> { term_node = TAddrOf lv; - term_type = typ; - term_name = []; - term_loc = loc} (** @plugin development guide *) let term ?(loc=Lexing.dummy_pos, Lexing.dummy_pos) term typ = @@ -230,22 +267,30 @@ term_name = []; term_loc = loc } +let taddrof ?(loc=Lexing.dummy_pos, Lexing.dummy_pos) lv typ = + match lv with + | TMem h, TNoOffset -> h + | _ -> term ~loc (TAddrOf lv) typ + (** range of integers *) let trange ?(loc=Lexing.dummy_pos, Lexing.dummy_pos) (low,high) = term ~loc (Trange(low,high)) (Ltype(Logic_env.find_logic_type "set",[Linteger])) (** An integer constant (of type integer). *) -let tinteger ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) i = - term ~loc (TConst (CInt64 (Int64.of_int i,IUInt,None))) Linteger +let tinteger ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) ?(ikind=ILongLong) i = + term ~loc (TConst (CInt64 (My_bigint.of_int i,ikind,None))) Linteger (** An integer constant (of type integer) from an int64 . *) -let tinteger_s64 ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) i64 = - term ~loc (TConst (CInt64 (i64,IInt,None))) Linteger +let tinteger_s64 + ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) ?(ikind=ILongLong) i64 = + term ~loc (TConst (CInt64 (My_bigint.of_int64 i64,ikind,None))) Linteger let tat ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) (t,label) = term ~loc (Tat(t,label)) t.term_type +let told ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) t = tat ~loc (t,old_label) + let tvar ?(loc=Lexing.dummy_pos,Lexing.dummy_pos) lv = term ~loc (TLval(TVar lv,TNoOffset)) lv.lv_type @@ -256,9 +301,13 @@ TODO: some refactoring of these two files *) (** true if the given term is a lvalue denoting result or part of it *) let rec is_result t = match t.term_node with - TLval (TResult _,_) -> true + | TLval (TResult _,_) -> true | Tat(t,_) -> is_result t - | Told t -> is_result t + | _ -> false + +let rec is_exit_status t = match t.term_node with + | TLval (TVar n,_) when n.lv_name = "\\exit_status" -> true + | Tat(t,_) -> is_exit_status t | _ -> false (* diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_const.mli frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_const.mli --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_const.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_const.mli 2011-10-10 08:40:07.000000000 +0000 @@ -0,0 +1,236 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* INRIA (Institut National de Recherche en Informatique et en *) +(* Automatique) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version v2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Smart contructors for logic annotations. + @plugin development guide *) + +open Cil_types +open Cil_datatype + +(* ************************************************************************** *) +(** {2 Nodes with a unique ID} *) +(* ************************************************************************** *) + +(** creates a code annotation with a fresh id. *) +val new_code_annotation : + (term, predicate named, identified_predicate, identified_term) code_annot -> + code_annotation + +(** @return a fresh id for a code annotation. *) +val fresh_code_annotation: unit -> int + +(** set a fresh id to an existing code annotation*) +val refresh_code_annotation: code_annotation -> code_annotation + +(** creates a new identified predicate with a fresh id. *) +val new_predicate: predicate named -> identified_predicate + +(** @return a fresh id for predicates *) +val fresh_predicate_id: unit -> int + +(** extract a named predicate for an identified predicate. *) +val pred_of_id_pred: identified_predicate -> predicate named + +(** creates a new identified term with a fresh id*) +val new_identified_term: term -> identified_term + +(** @return a fresh id from an identified term*) +val fresh_term_id: unit -> int + +(* ************************************************************************** *) +(** {2 Logic labels} *) +(* ************************************************************************** *) + +val pre_label: logic_label +val post_label: logic_label +val here_label: logic_label +val old_label: logic_label + +(* ************************************************************************** *) +(** {2 Predicates} *) +(* ************************************************************************** *) + +(** makes a predicate with no name. Default location is unknown.*) +val unamed: ?loc:location -> 'a -> 'a named + +(** \true *) +val ptrue: predicate named + +(** \false *) +val pfalse: predicate named + +(** \old *) +val pold: ?loc:location -> predicate named -> predicate named + +(** application of predicate*) +val papp: + ?loc:location -> + logic_info * (logic_label * logic_label) list * term list -> + predicate named + +(** && *) +val pand: ?loc:location -> predicate named * predicate named -> predicate named + +(** || *) +val por: ?loc:location -> predicate named * predicate named -> predicate named + +(** ^^ *) +val pxor: ?loc:location -> predicate named * predicate named -> predicate named +(** ! *) +val pnot: ?loc:location -> predicate named -> predicate named + +(** Folds && over a list of predicates. *) +val pands: predicate named list -> predicate named + +(** Folds || over a list of predicates. *) +val pors: predicate named list -> predicate named + +(** local binding *) +val plet: + ?loc:location -> (logic_info * predicate named) named -> predicate named + +(** ==> *) +val pimplies : + ?loc:location -> predicate named * predicate named -> predicate named + +(** ? : *) +val pif: + ?loc:location -> term * predicate named * predicate named -> predicate named + +(** <==> *) +val piff: ?loc:location -> predicate named * predicate named -> predicate named + +(** binary relation*) +val prel: ?loc:location -> relation * term * term -> predicate named + +(** \forall *) +val pforall: ?loc:location -> quantifiers * predicate named -> predicate named + +(** \exists *) +val pexists: ?loc:location -> quantifiers * predicate named -> predicate named + +(** \fresh *) +val pfresh: ?loc:location -> term -> predicate named + +(** \valid *) +val pvalid: ?loc:location -> term -> predicate named + +(** \initialized *) +val pinitialized: ?loc:location -> term -> predicate named + +(** \at *) +val pat: ?loc:location -> predicate named * logic_label -> predicate named + +(** \valid_index *) +val pvalid_index: ?loc:location -> term * term -> predicate named + +(** \valid_range *) +val pvalid_range: ?loc:location -> term * term * term -> predicate named + +(** subtype relation *) +val psubtype: ?loc:location -> term * term -> predicate named + +(** \separated *) +val pseparated: ?loc:location -> term list -> predicate named + +(* ************************************************************************** *) +(** {2 Logic types} *) +(* ************************************************************************** *) + +(** [set_conversion ty1 ty2] returns a set type as soon as [ty1] and/or [ty2] + is a set. Elements have type [ty1], or the type of the elements of [ty1] if + it is itself a set-type ({i.e.} we do not build set of sets that way). *) +val set_conversion: logic_type -> logic_type -> logic_type + +(** converts a type into the corresponding set type if needed. Does nothing + if the argument is already a set type. *) +val make_set_type: logic_type -> logic_type + +(** returns the type of elements of a set type. + @raise Failure if the input type is not a set type. *) +val type_of_element: logic_type -> logic_type + +(** [plain_or_set f t] applies [f] to [t] or to the type of elements of [t] + if it is a set type *) +val plain_or_set: (logic_type -> 'a) -> logic_type -> 'a + +(** [transform_element f t] is the same as + [set_conversion (plain_or_set f t) t] + @since Nitrogen-20111001 +*) +val transform_element: (logic_type -> logic_type) -> logic_type -> logic_type + +(** [true] if the argument is not a set type *) +val is_plain_type: logic_type -> bool + +val is_boolean_type: logic_type -> bool +(** @return true if the argument is the boolean type *) + +(* ************************************************************************** *) +(** {1 Logic Terms} *) +(* ************************************************************************** *) + +(** returns a anonymous term of the given type. + @plugin development guide *) +val term : ?loc:Location.t -> term_node -> logic_type -> term + +(** & *) +val taddrof: ?loc:Location.t -> term_lval -> logic_type -> term + +(** [..] *) +val trange: ?loc:Location.t -> term option * term option -> term + +(** integer constant *) +val tinteger: ?loc:Location.t -> ?ikind:ikind -> int -> term + +(** integer constant *) +val tinteger_s64: ?loc:Location.t -> ?ikind:ikind -> int64 -> term + +(** \at *) +val tat: ?loc:Location.t -> term * logic_label -> term + +(** \old + @since Nitrogen-20111001 +*) +val told: ?loc:Location.t -> term -> term + +(** variable *) +val tvar: ?loc:Location.t -> logic_var -> term + +(** \result *) +val tresult: ?loc:Location.t -> typ -> term + +(** [true] if the term is \result (potentially enclosed in \at)*) +val is_result: term -> bool + +(** [true] if the term is \exit_status (potentially enclosed in \at) + @since Nitrogen-20111001 +*) +val is_exit_status: term -> bool + +(* +Local Variables: +compile-command: "make -C ../../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_env.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_env.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_env.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_env.ml 2011-10-10 08:40:07.000000000 +0000 @@ -27,11 +27,8 @@ module CurrentLoc = Cil_const.CurrentLoc let error (b,_e) fstring = - Cilmsg.abort - ~source:{ - Log.src_file = b.Lexing.pos_fname ; - Log.src_line = b.Lexing.pos_lnum ; - } + Kernel.abort + ~source:b ("In annotation: " ^^ fstring) module Logic_builtin = @@ -218,9 +215,9 @@ end) let apply () = - Cilmsg.feedback ~level:5 "Applying logic built-ins hooks for project %s" + Kernel.feedback ~level:5 "Applying logic built-ins hooks for project %s" (Project.get_name (Project.current())); - if Applied.get () then Cilmsg.feedback ~level:5 "Already applied" + if Applied.get () then Kernel.feedback ~level:5 "Already applied" else begin Applied.set true; apply () end end diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_lexer.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_lexer.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_lexer.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_lexer.ml 2011-10-10 08:48:48.000000000 +0000 @@ -46,7 +46,7 @@ fun s -> try Hashtbl.find h s with Not_found -> IDENTIFIER s - let identifier = + let identifier, is_acsl_keyword = let all_kw = Hashtbl.create 37 in let c_kw = Hashtbl.create 37 in let type_kw = Hashtbl.create 3 in @@ -94,6 +94,7 @@ "logic", LOGIC, false; "long", LONG, true; "loop", LOOP, false; + "modelfield", MODEL, false;(* ACSL extension for model fields *) "module", MODULE, false;(* ACSL extension for external spec file *) "pragma", PRAGMA, false; "predicate", PREDICATE, false; @@ -116,7 +117,7 @@ ]; List.iter (fun (x, y) -> Hashtbl.add type_kw x y) ["integer", INTEGER; "real", REAL; "boolean", BOOLEAN; ]; - fun s -> + (fun s -> try Hashtbl.find (if Logic_utils.is_kw_c_mode () then c_kw else all_kw) s with Not_found -> @@ -126,7 +127,8 @@ Hashtbl.find type_kw s with Not_found -> if Logic_utils.is_rt_type_mode () then TYPENAME s - else IDENTIFIER s) + else IDENTIFIER s)), + (fun s -> Hashtbl.mem all_kw s || Hashtbl.mem type_kw s) let bs_identifier = let h = Hashtbl.create 97 in @@ -141,6 +143,7 @@ "\\forall", FORALL; "\\fresh", FRESH; "\\from", FROM; + "\\initialized", INITIALIZED; "\\inter", INTER; "\\lambda", LAMBDA; "\\let", LET; @@ -204,72 +207,72 @@ Lexing.pos_bol = bol; } -# 208 "cil/src/logic/logic_lexer.ml" +# 211 "cil/src/logic/logic_lexer.ml" let __ocaml_lex_tables = { Lexing.lex_base = - "\000\000\196\255\197\255\000\000\203\255\204\255\205\255\206\255\ - \207\255\208\255\196\000\216\255\218\255\165\000\223\255\224\255\ - \202\000\231\255\232\255\199\000\234\255\235\255\201\000\139\000\ - \227\000\208\000\206\000\241\255\004\001\225\000\006\001\254\000\ - \036\001\109\001\198\001\000\002\236\000\254\255\030\001\091\001\ - \252\255\253\255\075\002\188\002\127\002\128\002\129\002\161\002\ - \245\255\189\002\191\002\192\002\242\255\158\002\077\001\208\000\ - \187\002\001\003\024\003\097\003\061\003\167\003\211\000\200\003\ - \232\003\009\004\041\004\082\003\244\255\051\004\080\004\112\004\ - \122\004\141\004\174\004\206\004\216\004\212\000\235\004\245\004\ - \243\255\011\005\021\005\050\005\060\005\089\005\099\005\128\005\ - \239\000\139\005\168\005\178\005\207\005\226\255\224\000\240\255\ - \200\255\202\255\228\000\228\000\239\255\238\255\237\255\209\255\ - \233\255\201\255\229\255\221\255\199\255\212\255\200\000\251\255\ - \252\255\239\005\253\255\097\001\056\006\079\006\190\001\254\255\ - \009\006\251\255\186\000\255\005\254\255\255\255\202\000\212\000\ - \252\255\239\002\252\255\224\001\254\255\255\255\253\255\242\002\ - \092\001\253\255\254\255\255\255"; + "\000\000\194\255\195\255\000\000\201\255\202\255\203\255\204\255\ + \205\255\206\255\196\000\214\255\216\255\165\000\221\255\222\255\ + \202\000\229\255\230\255\232\255\233\255\200\000\138\000\225\000\ + \220\000\223\000\205\000\241\255\001\001\223\000\004\001\252\000\ + \034\001\107\001\196\001\254\001\238\000\254\255\028\001\089\001\ + \252\255\253\255\073\002\186\002\125\002\090\001\126\002\245\255\ + \242\255\091\001\152\002\075\001\210\000\181\002\251\002\018\003\ + \081\003\219\002\151\003\246\000\055\003\189\003\119\003\222\003\ + \191\002\244\255\255\003\009\004\028\004\038\004\072\004\060\004\ + \105\004\137\004\250\000\147\004\176\004\243\255\191\004\208\004\ + \237\004\247\004\218\004\020\005\030\005\241\000\054\005\084\005\ + \094\005\064\005\224\255\226\000\240\255\198\255\200\255\244\000\ + \229\000\230\000\239\255\232\000\237\255\231\255\248\000\238\255\ + \236\255\235\255\207\255\199\255\227\255\219\255\197\255\210\255\ + \231\000\251\255\252\255\124\005\253\255\095\001\197\005\220\005\ + \188\001\254\255\026\006\251\255\206\000\252\005\254\255\255\255\ + \202\000\212\000\252\255\025\003\252\255\247\002\254\255\255\255\ + \253\255\044\003\131\001\253\255\254\255\255\255"; Lexing.lex_backtrk = - "\255\255\255\255\255\255\057\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\041\000\255\255\255\255\035\000\255\255\255\255\ - \025\000\255\255\255\255\030\000\255\255\255\255\019\000\036\000\ - \033\000\040\000\045\000\255\255\059\000\027\000\059\000\008\000\ - \008\000\005\000\005\000\059\000\038\000\255\255\000\000\255\255\ - \255\255\255\255\004\000\255\255\255\255\255\255\255\255\010\000\ - \255\255\255\255\255\255\013\000\255\255\011\000\255\255\009\000\ - \007\000\255\255\255\255\006\000\255\255\255\255\006\000\255\255\ - \255\255\255\255\011\000\255\255\255\255\011\000\255\255\011\000\ - \255\255\255\255\255\255\011\000\255\255\007\000\011\000\255\255\ - \255\255\255\255\011\000\255\255\011\000\255\255\011\000\255\255\ - \028\000\011\000\255\255\011\000\255\255\255\255\044\000\255\255\ - \255\255\255\255\042\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\004\000\255\255\001\000\255\255\000\000\001\000\255\255\ - \255\255\255\255\004\000\002\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\003\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255"; + "\255\255\255\255\255\255\059\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\043\000\255\255\255\255\037\000\255\255\255\255\ + \027\000\255\255\255\255\255\255\255\255\021\000\038\000\035\000\ + \032\000\042\000\047\000\255\255\061\000\029\000\061\000\008\000\ + \008\000\005\000\005\000\061\000\040\000\255\255\000\000\255\255\ + \255\255\255\255\004\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\011\000\255\255\009\000\007\000\255\255\255\255\ + \006\000\255\255\255\255\006\000\255\255\255\255\255\255\011\000\ + \255\255\255\255\011\000\255\255\011\000\255\255\255\255\255\255\ + \011\000\255\255\007\000\011\000\255\255\255\255\255\255\011\000\ + \255\255\011\000\255\255\011\000\255\255\030\000\011\000\255\255\ + \011\000\255\255\255\255\046\000\255\255\255\255\255\255\255\255\ + \044\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\004\000\255\255\001\000\255\255\000\000\ + \001\000\255\255\255\255\255\255\004\000\002\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\003\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255"; Lexing.lex_default = "\003\000\000\000\000\000\255\255\000\000\000\000\000\000\000\000\ \000\000\000\000\255\255\000\000\000\000\255\255\000\000\000\000\ - \255\255\000\000\000\000\255\255\000\000\000\000\255\255\255\255\ - \255\255\255\255\255\255\000\000\049\000\255\255\045\000\255\255\ + \255\255\000\000\000\000\000\000\000\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\000\000\043\000\255\255\046\000\255\255\ \255\255\255\255\255\255\255\255\255\255\000\000\255\255\039\000\ - \000\000\000\000\255\255\049\000\045\000\045\000\045\000\045\000\ - \000\000\049\000\049\000\049\000\000\000\255\255\255\255\255\255\ + \000\000\000\000\255\255\043\000\046\000\046\000\046\000\000\000\ + \000\000\043\000\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\000\000\255\255\255\255\255\255\ + \255\255\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\000\000\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\000\000\255\255\000\000\ - \000\000\000\000\255\255\255\255\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\111\000\000\000\ - \000\000\255\255\000\000\255\255\255\255\255\255\255\255\000\000\ - \121\000\000\000\255\255\255\255\000\000\000\000\255\255\255\255\ - \000\000\130\000\000\000\135\000\000\000\000\000\000\000\135\000\ - \137\000\000\000\000\000\000\000"; + \255\255\255\255\000\000\255\255\000\000\000\000\000\000\255\255\ + \255\255\255\255\000\000\255\255\000\000\000\000\255\255\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \113\000\000\000\000\000\255\255\000\000\255\255\255\255\255\255\ + \255\255\000\000\123\000\000\000\255\255\255\255\000\000\000\000\ + \255\255\255\255\000\000\132\000\000\000\137\000\000\000\000\000\ + \000\000\137\000\139\000\000\000\000\000\000\000"; Lexing.lex_trans = "\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\038\000\037\000\001\000\038\000\038\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ - \038\000\022\000\028\000\027\000\021\000\011\000\024\000\030\000\ - \009\000\008\000\014\000\015\000\020\000\019\000\029\000\036\000\ + \038\000\021\000\028\000\027\000\020\000\011\000\023\000\030\000\ + \009\000\008\000\014\000\015\000\019\000\024\000\029\000\036\000\ \032\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ \031\000\031\000\016\000\017\000\025\000\026\000\010\000\018\000\ \038\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ @@ -279,7 +282,7 @@ \001\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\007\000\023\000\006\000\012\000\001\000\ + \033\000\033\000\033\000\007\000\022\000\006\000\012\000\001\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ @@ -296,190 +299,183 @@ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\001\000\ - \002\000\109\000\108\000\107\000\106\000\104\000\103\000\102\000\ - \105\000\101\000\097\000\094\000\096\000\098\000\255\255\088\000\ - \255\255\089\000\089\000\089\000\089\000\089\000\089\000\089\000\ - \089\000\089\000\089\000\039\000\055\000\093\000\095\000\062\000\ - \077\000\099\000\100\000\126\000\113\000\055\000\255\255\038\000\ - \062\000\077\000\038\000\038\000\053\000\255\255\031\000\031\000\ - \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ - \127\000\128\000\000\000\000\000\055\000\000\000\038\000\062\000\ - \077\000\000\000\000\000\054\000\000\000\055\000\000\000\000\000\ - \062\000\077\000\055\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\053\000\055\000\056\000\056\000\056\000\056\000\ - \056\000\056\000\056\000\056\000\056\000\056\000\038\000\000\000\ - \050\000\000\000\046\000\054\000\000\000\041\000\139\000\000\000\ - \000\000\054\000\055\000\000\000\000\000\000\000\000\000\000\000\ - \055\000\000\000\000\000\055\000\000\000\000\000\000\000\000\000\ - \079\000\055\000\079\000\000\000\057\000\078\000\078\000\078\000\ - \078\000\078\000\078\000\078\000\078\000\078\000\078\000\000\000\ - \000\000\054\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \055\000\118\000\118\000\118\000\118\000\118\000\118\000\118\000\ - \118\000\055\000\000\000\000\000\057\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \112\000\000\000\000\000\000\000\033\000\000\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \043\000\255\255\000\000\000\000\255\255\044\000\119\000\119\000\ - \119\000\119\000\119\000\119\000\119\000\119\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \000\000\000\000\134\000\000\000\255\255\000\000\255\255\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \002\000\111\000\110\000\109\000\108\000\106\000\105\000\104\000\ + \107\000\102\000\091\000\255\255\095\000\085\000\255\255\086\000\ + \086\000\086\000\086\000\086\000\086\000\086\000\086\000\086\000\ + \086\000\094\000\101\000\093\000\096\000\039\000\052\000\090\000\ + \092\000\099\000\097\000\048\000\098\000\038\000\100\000\052\000\ + \038\000\038\000\050\000\255\255\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\031\000\031\000\103\000\128\000\ + \129\000\130\000\000\000\000\000\038\000\000\000\052\000\000\000\ + \000\000\051\000\059\000\115\000\000\000\000\000\074\000\052\000\ + \052\000\000\000\000\000\059\000\000\000\000\000\000\000\074\000\ + \050\000\052\000\053\000\053\000\053\000\053\000\053\000\053\000\ + \053\000\053\000\053\000\053\000\038\000\049\000\000\000\000\000\ + \045\000\051\000\059\000\041\000\255\255\255\255\074\000\051\000\ + \052\000\000\000\000\000\059\000\000\000\000\000\052\000\074\000\ + \000\000\052\000\000\000\000\000\000\000\000\000\076\000\052\000\ + \076\000\000\000\054\000\075\000\075\000\075\000\075\000\075\000\ + \075\000\075\000\075\000\075\000\075\000\000\000\000\000\051\000\ + \000\000\000\000\000\000\000\000\000\000\141\000\052\000\120\000\ + \120\000\120\000\120\000\120\000\120\000\120\000\120\000\052\000\ + \000\000\000\000\054\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\000\000\000\000\ + \000\000\000\000\033\000\000\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\043\000\114\000\ + \000\000\000\000\000\000\044\000\121\000\121\000\121\000\121\000\ + \121\000\121\000\121\000\121\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\000\000\000\000\ + \000\000\255\255\000\000\000\000\255\255\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\000\000\000\000\000\000\000\000\033\000\000\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\000\000\ + \000\000\000\000\000\000\033\000\000\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\040\000\138\000\000\000\000\000\042\000\ - \000\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ + \042\000\040\000\255\255\255\255\000\000\042\000\000\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\000\000\000\000\000\000\ - \000\000\255\255\255\255\255\255\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\255\255\048\000\ - \047\000\000\000\042\000\255\255\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\140\000\000\000\000\000\000\000\255\255\ + \255\255\000\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\255\255\255\255\ - \048\000\255\255\255\255\000\000\080\000\000\000\082\000\082\000\ - \082\000\082\000\082\000\082\000\082\000\082\000\082\000\082\000\ - \000\000\000\000\000\000\046\000\046\000\046\000\255\255\052\000\ - \255\255\051\000\052\000\081\000\068\000\000\000\000\000\000\000\ - \000\000\053\000\068\000\056\000\056\000\056\000\056\000\056\000\ - \056\000\056\000\056\000\056\000\056\000\000\000\000\000\000\000\ - \132\000\133\000\000\000\255\255\132\000\046\000\255\255\000\000\ - \054\000\000\000\000\000\081\000\068\000\000\000\000\000\077\000\ - \000\000\000\000\068\000\000\000\000\000\000\000\000\000\132\000\ - \077\000\131\000\000\000\000\000\134\000\000\000\000\000\000\000\ - \050\000\050\000\000\000\050\000\050\000\000\000\000\000\000\000\ - \054\000\000\000\000\000\000\000\000\000\000\000\000\000\077\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\058\000\ - \077\000\059\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \059\000\059\000\059\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \073\000\073\000\073\000\073\000\073\000\073\000\073\000\073\000\ - \073\000\073\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\073\000\073\000\073\000\073\000\073\000\073\000\000\000\ - \000\000\000\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \072\000\000\000\072\000\000\000\000\000\071\000\071\000\071\000\ - \071\000\071\000\071\000\071\000\071\000\071\000\071\000\000\000\ - \000\000\073\000\073\000\073\000\073\000\073\000\073\000\255\255\ - \255\255\255\255\066\000\066\000\066\000\066\000\066\000\066\000\ - \066\000\066\000\066\000\066\000\000\000\000\000\000\000\061\000\ - \000\000\059\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \059\000\059\000\059\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\255\255\059\000\059\000\059\000\059\000\059\000\059\000\ - \000\000\000\000\000\000\000\000\000\000\062\000\000\000\000\000\ - \000\000\060\000\000\000\000\000\000\000\000\000\062\000\000\000\ - \000\000\000\000\000\000\000\000\255\255\255\255\000\000\255\255\ - \255\255\000\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \000\000\000\000\000\000\000\000\000\000\062\000\000\000\000\000\ - \000\000\060\000\000\000\000\000\000\000\000\000\062\000\064\000\ - \064\000\064\000\064\000\064\000\064\000\064\000\064\000\064\000\ - \064\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \064\000\064\000\064\000\064\000\064\000\064\000\000\000\255\255\ - \000\000\000\000\255\255\070\000\000\000\070\000\000\000\063\000\ - \069\000\069\000\069\000\069\000\069\000\069\000\069\000\069\000\ - \069\000\069\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \064\000\064\000\064\000\064\000\064\000\064\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\063\000\ - \064\000\064\000\064\000\064\000\064\000\064\000\064\000\064\000\ - \064\000\064\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\064\000\064\000\064\000\064\000\064\000\064\000\000\000\ - \000\000\000\000\000\000\000\000\067\000\000\000\067\000\000\000\ - \065\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ - \066\000\066\000\066\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\064\000\064\000\064\000\064\000\064\000\064\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \065\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ - \066\000\066\000\066\000\069\000\069\000\069\000\069\000\069\000\ - \069\000\069\000\069\000\069\000\069\000\000\000\000\000\068\000\ - \000\000\000\000\000\000\000\000\000\000\068\000\000\000\000\000\ - \000\000\068\000\000\000\000\000\000\000\000\000\000\000\068\000\ - \069\000\069\000\069\000\069\000\069\000\069\000\069\000\069\000\ - \069\000\069\000\000\000\000\000\000\000\000\000\000\000\068\000\ - \000\000\000\000\000\000\000\000\000\000\068\000\000\000\000\000\ - \000\000\068\000\000\000\000\000\000\000\000\000\000\000\068\000\ - \071\000\071\000\071\000\071\000\071\000\071\000\071\000\071\000\ - \071\000\071\000\071\000\071\000\071\000\071\000\071\000\071\000\ - \071\000\071\000\071\000\071\000\000\000\000\000\068\000\000\000\ - \000\000\000\000\000\000\000\000\068\000\073\000\073\000\073\000\ - \073\000\073\000\073\000\073\000\073\000\073\000\073\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\073\000\073\000\ - \073\000\073\000\073\000\073\000\000\000\000\000\068\000\000\000\ - \000\000\076\000\000\000\076\000\068\000\074\000\075\000\075\000\ - \075\000\075\000\075\000\075\000\075\000\075\000\075\000\075\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\073\000\073\000\ - \073\000\073\000\073\000\073\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\074\000\075\000\075\000\ - \075\000\075\000\075\000\075\000\075\000\075\000\075\000\075\000\ + \042\000\042\000\042\000\042\000\255\255\047\000\000\000\000\000\ + \042\000\000\000\042\000\042\000\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\042\000\255\255\000\000\077\000\000\000\ + \079\000\079\000\079\000\079\000\079\000\079\000\079\000\079\000\ + \079\000\079\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\045\000\045\000\000\000\048\000\078\000\065\000\000\000\ + \000\000\000\000\000\000\050\000\065\000\053\000\053\000\053\000\ + \053\000\053\000\053\000\053\000\053\000\053\000\053\000\063\000\ + \063\000\063\000\063\000\063\000\063\000\063\000\063\000\063\000\ + \063\000\000\000\051\000\000\000\000\000\078\000\065\000\000\000\ + \255\255\074\000\000\000\255\255\065\000\000\000\069\000\000\000\ + \069\000\000\000\074\000\068\000\068\000\068\000\068\000\068\000\ + \068\000\068\000\068\000\068\000\068\000\000\000\049\000\000\000\ + \000\000\136\000\051\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\074\000\134\000\135\000\000\000\000\000\134\000\000\000\ + \000\000\055\000\074\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\255\255\000\000\000\000\ + \255\255\134\000\000\000\133\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\070\000\070\000\070\000\070\000\070\000\070\000\ + \070\000\070\000\070\000\070\000\000\000\000\000\136\000\000\000\ + \000\000\000\000\000\000\070\000\070\000\070\000\070\000\070\000\ + \070\000\000\000\000\000\000\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\067\000\000\000\067\000\000\000\000\000\066\000\ + \066\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ + \066\000\000\000\000\000\070\000\070\000\070\000\070\000\070\000\ + \070\000\000\000\000\000\000\000\000\000\255\255\255\255\058\000\ + \000\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \000\000\000\000\000\000\000\000\000\000\059\000\000\000\000\000\ + \000\000\057\000\064\000\000\000\064\000\000\000\059\000\063\000\ + \063\000\063\000\063\000\063\000\063\000\063\000\063\000\063\000\ + \063\000\000\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \000\000\000\000\255\255\000\000\000\000\059\000\000\000\000\000\ + \000\000\057\000\000\000\000\000\000\000\000\000\059\000\061\000\ + \061\000\061\000\061\000\061\000\061\000\061\000\061\000\061\000\ + \061\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \061\000\061\000\061\000\061\000\061\000\061\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\060\000\ + \000\000\000\000\000\000\000\000\000\000\061\000\061\000\061\000\ + \061\000\061\000\061\000\061\000\061\000\061\000\061\000\255\255\ + \061\000\061\000\061\000\061\000\061\000\061\000\061\000\061\000\ + \061\000\061\000\061\000\061\000\000\000\000\000\000\000\060\000\ + \000\000\000\000\000\000\000\000\000\000\062\000\063\000\063\000\ + \063\000\063\000\063\000\063\000\063\000\063\000\063\000\063\000\ + \000\000\255\255\000\000\000\000\000\000\000\000\061\000\061\000\ + \061\000\061\000\061\000\061\000\065\000\000\000\000\000\000\000\ + \000\000\000\000\065\000\000\000\255\255\062\000\000\000\066\000\ + \066\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ + \066\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ + \066\000\066\000\066\000\000\000\065\000\065\000\000\000\000\000\ + \000\000\000\000\065\000\065\000\068\000\068\000\068\000\068\000\ + \068\000\068\000\068\000\068\000\068\000\068\000\068\000\068\000\ + \068\000\068\000\068\000\068\000\068\000\068\000\068\000\068\000\ + \000\000\000\000\065\000\000\000\000\000\065\000\000\000\073\000\ + \065\000\073\000\000\000\065\000\072\000\072\000\072\000\072\000\ + \072\000\072\000\072\000\072\000\072\000\072\000\000\000\000\000\ + \070\000\070\000\070\000\070\000\070\000\070\000\070\000\070\000\ + \070\000\070\000\065\000\000\000\000\000\000\000\000\000\000\000\ + \065\000\070\000\070\000\070\000\070\000\070\000\070\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \071\000\072\000\072\000\072\000\072\000\072\000\072\000\072\000\ + \072\000\072\000\072\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\070\000\070\000\070\000\070\000\070\000\070\000\065\000\ + \000\000\000\000\000\000\000\000\000\000\065\000\000\000\000\000\ + \071\000\072\000\072\000\072\000\072\000\072\000\072\000\072\000\ + \072\000\072\000\072\000\075\000\075\000\075\000\075\000\075\000\ + \075\000\075\000\075\000\075\000\075\000\000\000\000\000\065\000\ + \000\000\000\000\000\000\000\000\000\000\065\000\000\000\000\000\ + \000\000\065\000\000\000\000\000\000\000\000\000\000\000\065\000\ \075\000\075\000\075\000\075\000\075\000\075\000\075\000\075\000\ - \075\000\075\000\000\000\000\000\068\000\000\000\000\000\000\000\ - \000\000\000\000\068\000\078\000\078\000\078\000\078\000\078\000\ - \078\000\078\000\078\000\078\000\078\000\078\000\078\000\078\000\ - \078\000\078\000\078\000\078\000\078\000\078\000\078\000\000\000\ - \000\000\068\000\000\000\000\000\068\000\000\000\087\000\068\000\ - \087\000\000\000\068\000\086\000\086\000\086\000\086\000\086\000\ - \086\000\086\000\086\000\086\000\086\000\082\000\082\000\082\000\ - \082\000\082\000\082\000\082\000\082\000\082\000\082\000\000\000\ - \000\000\068\000\000\000\000\000\000\000\000\000\000\000\068\000\ - \000\000\000\000\083\000\068\000\000\000\085\000\000\000\085\000\ - \000\000\068\000\084\000\084\000\084\000\084\000\084\000\084\000\ - \084\000\084\000\084\000\084\000\084\000\084\000\084\000\084\000\ - \084\000\084\000\084\000\084\000\084\000\084\000\000\000\000\000\ - \000\000\000\000\083\000\068\000\000\000\000\000\000\000\000\000\ - \000\000\068\000\068\000\000\000\000\000\000\000\000\000\000\000\ - \068\000\084\000\084\000\084\000\084\000\084\000\084\000\084\000\ - \084\000\084\000\084\000\086\000\086\000\086\000\086\000\086\000\ - \086\000\086\000\086\000\086\000\086\000\000\000\000\000\000\000\ - \000\000\000\000\068\000\000\000\000\000\000\000\000\000\000\000\ - \068\000\068\000\000\000\000\000\000\000\000\000\000\000\068\000\ + \075\000\075\000\084\000\000\000\084\000\000\000\000\000\083\000\ + \083\000\083\000\083\000\083\000\083\000\083\000\083\000\083\000\ + \083\000\065\000\000\000\000\000\000\000\000\000\000\000\065\000\ + \079\000\079\000\079\000\079\000\079\000\079\000\079\000\079\000\ + \079\000\079\000\081\000\081\000\081\000\081\000\081\000\081\000\ + \081\000\081\000\081\000\081\000\000\000\080\000\065\000\000\000\ + \082\000\000\000\082\000\000\000\065\000\081\000\081\000\081\000\ + \081\000\081\000\081\000\081\000\081\000\081\000\081\000\081\000\ + \081\000\081\000\081\000\081\000\081\000\081\000\081\000\081\000\ + \081\000\000\000\000\000\000\000\000\000\080\000\065\000\000\000\ + \000\000\000\000\000\000\000\000\065\000\065\000\000\000\000\000\ + \000\000\000\000\000\000\065\000\083\000\083\000\083\000\083\000\ + \083\000\083\000\083\000\083\000\083\000\083\000\083\000\083\000\ + \083\000\083\000\083\000\083\000\083\000\083\000\083\000\083\000\ + \000\000\000\000\065\000\000\000\000\000\065\000\000\000\000\000\ + \065\000\000\000\000\000\065\000\000\000\000\000\086\000\086\000\ \086\000\086\000\086\000\086\000\086\000\086\000\086\000\086\000\ - \086\000\086\000\000\000\089\000\089\000\089\000\089\000\089\000\ - \089\000\089\000\089\000\089\000\089\000\000\000\000\000\000\000\ - \000\000\068\000\000\000\000\000\000\000\000\000\000\000\068\000\ - \090\000\068\000\000\000\092\000\000\000\092\000\000\000\068\000\ - \091\000\091\000\091\000\091\000\091\000\091\000\091\000\091\000\ - \091\000\091\000\091\000\091\000\091\000\091\000\091\000\091\000\ - \091\000\091\000\091\000\091\000\000\000\000\000\000\000\000\000\ - \090\000\068\000\000\000\000\000\000\000\000\000\000\000\068\000\ - \068\000\000\000\000\000\000\000\000\000\000\000\068\000\091\000\ - \091\000\091\000\091\000\091\000\091\000\091\000\091\000\091\000\ - \091\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\114\000\124\000\125\000\000\000\000\000\114\000\000\000\ - \068\000\000\000\000\000\000\000\000\000\000\000\068\000\115\000\ - \115\000\115\000\115\000\115\000\115\000\115\000\115\000\000\000\ - \000\000\124\000\000\000\000\000\000\000\000\000\114\000\123\000\ - \123\000\123\000\123\000\123\000\123\000\123\000\123\000\123\000\ - \123\000\123\000\123\000\123\000\123\000\123\000\123\000\123\000\ - \123\000\123\000\123\000\000\000\000\000\000\000\000\000\116\000\ - \000\000\000\000\000\000\114\000\000\000\000\000\000\000\000\000\ - \114\000\114\000\000\000\000\000\000\000\114\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\114\000\000\000\000\000\ - \000\000\114\000\000\000\114\000\000\000\114\000\000\000\116\000\ - \117\000\117\000\117\000\117\000\117\000\117\000\117\000\117\000\ - \117\000\117\000\000\000\000\000\000\000\122\000\000\000\000\000\ - \000\000\117\000\117\000\117\000\117\000\117\000\117\000\117\000\ - \117\000\117\000\117\000\117\000\117\000\117\000\117\000\117\000\ - \117\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \117\000\117\000\117\000\117\000\117\000\117\000\000\000\000\000\ - \000\000\117\000\117\000\117\000\117\000\117\000\117\000\000\000\ + \088\000\088\000\088\000\088\000\088\000\088\000\088\000\088\000\ + \088\000\088\000\065\000\087\000\065\000\000\000\000\000\089\000\ + \065\000\089\000\065\000\000\000\088\000\088\000\088\000\088\000\ + \088\000\088\000\088\000\088\000\088\000\088\000\088\000\088\000\ + \088\000\088\000\088\000\088\000\088\000\088\000\088\000\088\000\ + \000\000\000\000\000\000\087\000\065\000\000\000\116\000\000\000\ + \000\000\000\000\065\000\116\000\065\000\000\000\000\000\000\000\ + \000\000\000\000\065\000\000\000\117\000\117\000\117\000\117\000\ + \117\000\117\000\117\000\117\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\116\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\065\000\000\000\000\000\000\000\ + \000\000\000\000\065\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\118\000\000\000\000\000\000\000\ + \116\000\000\000\000\000\000\000\000\000\116\000\116\000\000\000\ + \000\000\000\000\116\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\116\000\000\000\000\000\000\000\116\000\000\000\ + \116\000\000\000\116\000\000\000\118\000\119\000\119\000\119\000\ + \119\000\119\000\119\000\119\000\119\000\119\000\119\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\119\000\119\000\ + \119\000\119\000\119\000\119\000\119\000\119\000\119\000\119\000\ + \119\000\119\000\119\000\119\000\119\000\119\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\119\000\119\000\119\000\ + \119\000\119\000\119\000\126\000\127\000\000\000\119\000\119\000\ + \119\000\119\000\119\000\119\000\125\000\125\000\125\000\125\000\ + \125\000\125\000\125\000\125\000\125\000\125\000\000\000\000\000\ + \000\000\000\000\126\000\000\000\000\000\119\000\119\000\119\000\ + \119\000\119\000\119\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\125\000\125\000\125\000\125\000\125\000\125\000\ + \125\000\125\000\125\000\125\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \117\000\117\000\117\000\117\000\117\000\117\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\124\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -489,7 +485,6 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\255\255\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -498,7 +493,8 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - "; + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\255\255"; Lexing.lex_check = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -532,191 +528,183 @@ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\000\000\ - \000\000\010\000\010\000\013\000\016\000\019\000\022\000\023\000\ - \016\000\024\000\025\000\026\000\025\000\025\000\028\000\029\000\ - \030\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ - \029\000\029\000\029\000\036\000\055\000\088\000\094\000\062\000\ - \077\000\098\000\099\000\122\000\110\000\055\000\028\000\038\000\ - \062\000\077\000\038\000\038\000\031\000\030\000\031\000\031\000\ - \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ - \126\000\127\000\255\255\255\255\055\000\255\255\038\000\062\000\ - \077\000\255\255\255\255\031\000\255\255\055\000\255\255\255\255\ - \062\000\077\000\031\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\032\000\031\000\032\000\032\000\032\000\032\000\ - \032\000\032\000\032\000\032\000\032\000\032\000\038\000\255\255\ - \028\000\255\255\030\000\031\000\255\255\039\000\136\000\255\255\ - \255\255\032\000\031\000\255\255\255\255\255\255\255\255\255\255\ - \032\000\255\255\255\255\031\000\255\255\255\255\255\255\255\255\ - \054\000\032\000\054\000\255\255\032\000\054\000\054\000\054\000\ - \054\000\054\000\054\000\054\000\054\000\054\000\054\000\255\255\ - \255\255\032\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \032\000\115\000\115\000\115\000\115\000\115\000\115\000\115\000\ - \115\000\032\000\255\255\255\255\032\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \110\000\255\255\255\255\255\255\033\000\255\255\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \034\000\131\000\255\255\255\255\131\000\034\000\118\000\118\000\ - \118\000\118\000\118\000\118\000\118\000\118\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \255\255\255\255\131\000\255\255\028\000\255\255\030\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ + \000\000\010\000\010\000\013\000\016\000\021\000\022\000\023\000\ + \016\000\024\000\026\000\028\000\025\000\029\000\030\000\029\000\ + \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ + \029\000\025\000\024\000\025\000\025\000\036\000\052\000\085\000\ + \091\000\095\000\096\000\028\000\097\000\038\000\099\000\052\000\ + \038\000\038\000\031\000\030\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\031\000\031\000\102\000\124\000\ + \128\000\129\000\255\255\255\255\038\000\255\255\052\000\255\255\ + \255\255\031\000\059\000\112\000\255\255\255\255\074\000\052\000\ + \031\000\255\255\255\255\059\000\255\255\255\255\255\255\074\000\ + \032\000\031\000\032\000\032\000\032\000\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\038\000\028\000\255\255\255\255\ + \030\000\031\000\059\000\039\000\045\000\049\000\074\000\032\000\ + \031\000\255\255\255\255\059\000\255\255\255\255\032\000\074\000\ + \255\255\031\000\255\255\255\255\255\255\255\255\051\000\032\000\ + \051\000\255\255\032\000\051\000\051\000\051\000\051\000\051\000\ + \051\000\051\000\051\000\051\000\051\000\255\255\255\255\032\000\ + \255\255\255\255\255\255\255\255\255\255\138\000\032\000\117\000\ + \117\000\117\000\117\000\117\000\117\000\117\000\117\000\032\000\ + \255\255\255\255\032\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\255\255\255\255\ + \255\255\255\255\033\000\255\255\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\034\000\112\000\ + \255\255\255\255\255\255\034\000\120\000\120\000\120\000\120\000\ + \120\000\120\000\120\000\120\000\034\000\034\000\034\000\034\000\ + \034\000\034\000\034\000\034\000\034\000\034\000\255\255\255\255\ + \255\255\028\000\255\255\255\255\030\000\034\000\034\000\034\000\ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\255\255\255\255\255\255\255\255\034\000\255\255\034\000\ + \034\000\034\000\034\000\034\000\034\000\034\000\034\000\255\255\ + \255\255\255\255\255\255\034\000\255\255\034\000\034\000\034\000\ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ + \034\000\034\000\034\000\034\000\034\000\034\000\034\000\035\000\ + \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\035\000\039\000\136\000\255\255\255\255\035\000\ - \255\255\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ + \035\000\039\000\045\000\049\000\255\255\035\000\255\255\035\000\ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\035\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\255\255\255\255\255\255\ - \255\255\044\000\045\000\046\000\042\000\042\000\042\000\042\000\ + \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ + \035\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\138\000\255\255\255\255\255\255\044\000\ + \046\000\255\255\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\044\000\045\000\ - \046\000\255\255\042\000\047\000\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\042\000\044\000\046\000\255\255\255\255\ + \042\000\255\255\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\043\000\049\000\ - \047\000\050\000\051\000\255\255\053\000\255\255\053\000\053\000\ - \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ - \255\255\255\255\255\255\044\000\045\000\046\000\043\000\049\000\ - \131\000\050\000\051\000\053\000\053\000\255\255\255\255\255\255\ - \255\255\056\000\053\000\056\000\056\000\056\000\056\000\056\000\ - \056\000\056\000\056\000\056\000\056\000\255\255\255\255\255\255\ - \129\000\129\000\255\255\135\000\129\000\047\000\135\000\255\255\ - \056\000\255\255\255\255\053\000\053\000\255\255\255\255\056\000\ - \255\255\255\255\053\000\255\255\255\255\255\255\255\255\129\000\ - \056\000\129\000\255\255\255\255\135\000\255\255\255\255\255\255\ - \043\000\049\000\255\255\050\000\051\000\255\255\255\255\255\255\ - \056\000\255\255\255\255\255\255\255\255\255\255\255\255\056\000\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\057\000\ - \056\000\057\000\057\000\057\000\057\000\057\000\057\000\057\000\ - \057\000\057\000\057\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\057\000\057\000\057\000\057\000\057\000\057\000\ + \042\000\042\000\042\000\042\000\043\000\255\255\050\000\255\255\ + \050\000\050\000\050\000\050\000\050\000\050\000\050\000\050\000\ + \050\000\050\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\044\000\046\000\255\255\043\000\050\000\050\000\255\255\ + \255\255\255\255\255\255\053\000\050\000\053\000\053\000\053\000\ + \053\000\053\000\053\000\053\000\053\000\053\000\053\000\064\000\ + \064\000\064\000\064\000\064\000\064\000\064\000\064\000\064\000\ + \064\000\255\255\053\000\255\255\255\255\050\000\050\000\255\255\ + \133\000\053\000\255\255\133\000\050\000\255\255\057\000\255\255\ + \057\000\255\255\053\000\057\000\057\000\057\000\057\000\057\000\ + \057\000\057\000\057\000\057\000\057\000\255\255\043\000\255\255\ + \255\255\133\000\053\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\053\000\131\000\131\000\255\255\255\255\131\000\255\255\ + \255\255\054\000\053\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\054\000\054\000\054\000\137\000\255\255\255\255\ + \137\000\131\000\255\255\131\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\055\000\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\255\255\255\255\137\000\255\255\ + \255\255\255\255\255\255\055\000\055\000\055\000\055\000\055\000\ + \055\000\255\255\255\255\255\255\054\000\054\000\054\000\054\000\ + \054\000\054\000\060\000\255\255\060\000\255\255\255\255\060\000\ + \060\000\060\000\060\000\060\000\060\000\060\000\060\000\060\000\ + \060\000\255\255\255\255\055\000\055\000\055\000\055\000\055\000\ + \055\000\255\255\255\255\255\255\255\255\044\000\046\000\056\000\ + \255\255\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\056\000\056\000\056\000\056\000\056\000\056\000\ + \255\255\255\255\255\255\255\255\255\255\056\000\255\255\255\255\ + \255\255\056\000\062\000\255\255\062\000\255\255\056\000\062\000\ + \062\000\062\000\062\000\062\000\062\000\062\000\062\000\062\000\ + \062\000\255\255\056\000\056\000\056\000\056\000\056\000\056\000\ + \255\255\255\255\043\000\255\255\255\255\056\000\255\255\255\255\ + \255\255\056\000\255\255\255\255\255\255\255\255\056\000\058\000\ \058\000\058\000\058\000\058\000\058\000\058\000\058\000\058\000\ - \058\000\058\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\058\000\058\000\058\000\058\000\058\000\058\000\255\255\ - \255\255\255\255\057\000\057\000\057\000\057\000\057\000\057\000\ - \060\000\255\255\060\000\255\255\255\255\060\000\060\000\060\000\ - \060\000\060\000\060\000\060\000\060\000\060\000\060\000\255\255\ - \255\255\058\000\058\000\058\000\058\000\058\000\058\000\044\000\ - \045\000\046\000\067\000\067\000\067\000\067\000\067\000\067\000\ - \067\000\067\000\067\000\067\000\255\255\255\255\255\255\059\000\ - \255\255\059\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \059\000\059\000\059\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\047\000\059\000\059\000\059\000\059\000\059\000\059\000\ - \255\255\255\255\255\255\255\255\255\255\059\000\255\255\255\255\ - \255\255\059\000\255\255\255\255\255\255\255\255\059\000\255\255\ - \255\255\255\255\255\255\255\255\043\000\049\000\255\255\050\000\ - \051\000\255\255\059\000\059\000\059\000\059\000\059\000\059\000\ - \255\255\255\255\255\255\255\255\255\255\059\000\255\255\255\255\ - \255\255\059\000\255\255\255\255\255\255\255\255\059\000\061\000\ - \061\000\061\000\061\000\061\000\061\000\061\000\061\000\061\000\ - \061\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \061\000\061\000\061\000\061\000\061\000\061\000\255\255\129\000\ - \255\255\255\255\135\000\063\000\255\255\063\000\255\255\061\000\ + \058\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \058\000\058\000\058\000\058\000\058\000\058\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\058\000\ + \255\255\255\255\255\255\255\255\255\255\061\000\061\000\061\000\ + \061\000\061\000\061\000\061\000\061\000\061\000\061\000\133\000\ + \058\000\058\000\058\000\058\000\058\000\058\000\061\000\061\000\ + \061\000\061\000\061\000\061\000\255\255\255\255\255\255\058\000\ + \255\255\255\255\255\255\255\255\255\255\061\000\063\000\063\000\ \063\000\063\000\063\000\063\000\063\000\063\000\063\000\063\000\ - \063\000\063\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \061\000\061\000\061\000\061\000\061\000\061\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\061\000\ - \064\000\064\000\064\000\064\000\064\000\064\000\064\000\064\000\ - \064\000\064\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\064\000\064\000\064\000\064\000\064\000\064\000\255\255\ - \255\255\255\255\255\255\255\255\065\000\255\255\065\000\255\255\ - \064\000\065\000\065\000\065\000\065\000\065\000\065\000\065\000\ - \065\000\065\000\065\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\064\000\064\000\064\000\064\000\064\000\064\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \064\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ - \066\000\066\000\066\000\069\000\069\000\069\000\069\000\069\000\ - \069\000\069\000\069\000\069\000\069\000\255\255\255\255\066\000\ - \255\255\255\255\255\255\255\255\255\255\066\000\255\255\255\255\ - \255\255\069\000\255\255\255\255\255\255\255\255\255\255\069\000\ + \255\255\131\000\255\255\255\255\255\255\255\255\061\000\061\000\ + \061\000\061\000\061\000\061\000\063\000\255\255\255\255\255\255\ + \255\255\255\255\063\000\255\255\137\000\061\000\255\255\066\000\ + \066\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ + \066\000\067\000\067\000\067\000\067\000\067\000\067\000\067\000\ + \067\000\067\000\067\000\255\255\063\000\066\000\255\255\255\255\ + \255\255\255\255\063\000\066\000\068\000\068\000\068\000\068\000\ + \068\000\068\000\068\000\068\000\068\000\068\000\069\000\069\000\ + \069\000\069\000\069\000\069\000\069\000\069\000\069\000\069\000\ + \255\255\255\255\068\000\255\255\255\255\066\000\255\255\071\000\ + \068\000\071\000\255\255\066\000\071\000\071\000\071\000\071\000\ + \071\000\071\000\071\000\071\000\071\000\071\000\255\255\255\255\ \070\000\070\000\070\000\070\000\070\000\070\000\070\000\070\000\ - \070\000\070\000\255\255\255\255\255\255\255\255\255\255\066\000\ - \255\255\255\255\255\255\255\255\255\255\066\000\255\255\255\255\ - \255\255\069\000\255\255\255\255\255\255\255\255\255\255\069\000\ - \071\000\071\000\071\000\071\000\071\000\071\000\071\000\071\000\ - \071\000\071\000\072\000\072\000\072\000\072\000\072\000\072\000\ - \072\000\072\000\072\000\072\000\255\255\255\255\071\000\255\255\ - \255\255\255\255\255\255\255\255\071\000\073\000\073\000\073\000\ - \073\000\073\000\073\000\073\000\073\000\073\000\073\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\073\000\073\000\ - \073\000\073\000\073\000\073\000\255\255\255\255\071\000\255\255\ - \255\255\074\000\255\255\074\000\071\000\073\000\074\000\074\000\ - \074\000\074\000\074\000\074\000\074\000\074\000\074\000\074\000\ - \255\255\255\255\255\255\255\255\255\255\255\255\073\000\073\000\ - \073\000\073\000\073\000\073\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\073\000\075\000\075\000\ - \075\000\075\000\075\000\075\000\075\000\075\000\075\000\075\000\ + \070\000\070\000\068\000\255\255\255\255\255\255\255\255\255\255\ + \068\000\070\000\070\000\070\000\070\000\070\000\070\000\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \070\000\072\000\072\000\072\000\072\000\072\000\072\000\072\000\ + \072\000\072\000\072\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\070\000\070\000\070\000\070\000\070\000\070\000\072\000\ + \255\255\255\255\255\255\255\255\255\255\072\000\255\255\255\255\ + \070\000\073\000\073\000\073\000\073\000\073\000\073\000\073\000\ + \073\000\073\000\073\000\075\000\075\000\075\000\075\000\075\000\ + \075\000\075\000\075\000\075\000\075\000\255\255\255\255\072\000\ + \255\255\255\255\255\255\255\255\255\255\072\000\255\255\255\255\ + \255\255\075\000\255\255\255\255\255\255\255\255\255\255\075\000\ \076\000\076\000\076\000\076\000\076\000\076\000\076\000\076\000\ - \076\000\076\000\255\255\255\255\075\000\255\255\255\255\255\255\ - \255\255\255\255\075\000\078\000\078\000\078\000\078\000\078\000\ - \078\000\078\000\078\000\078\000\078\000\079\000\079\000\079\000\ - \079\000\079\000\079\000\079\000\079\000\079\000\079\000\255\255\ - \255\255\078\000\255\255\255\255\075\000\255\255\081\000\078\000\ - \081\000\255\255\075\000\081\000\081\000\081\000\081\000\081\000\ - \081\000\081\000\081\000\081\000\081\000\082\000\082\000\082\000\ - \082\000\082\000\082\000\082\000\082\000\082\000\082\000\255\255\ - \255\255\078\000\255\255\255\255\255\255\255\255\255\255\078\000\ - \255\255\255\255\082\000\082\000\255\255\083\000\255\255\083\000\ - \255\255\082\000\083\000\083\000\083\000\083\000\083\000\083\000\ - \083\000\083\000\083\000\083\000\084\000\084\000\084\000\084\000\ - \084\000\084\000\084\000\084\000\084\000\084\000\255\255\255\255\ - \255\255\255\255\082\000\082\000\255\255\255\255\255\255\255\255\ - \255\255\082\000\084\000\255\255\255\255\255\255\255\255\255\255\ - \084\000\085\000\085\000\085\000\085\000\085\000\085\000\085\000\ - \085\000\085\000\085\000\086\000\086\000\086\000\086\000\086\000\ - \086\000\086\000\086\000\086\000\086\000\255\255\255\255\255\255\ - \255\255\255\255\084\000\255\255\255\255\255\255\255\255\255\255\ - \084\000\086\000\255\255\255\255\255\255\255\255\255\255\086\000\ - \087\000\087\000\087\000\087\000\087\000\087\000\087\000\087\000\ - \087\000\087\000\255\255\089\000\089\000\089\000\089\000\089\000\ - \089\000\089\000\089\000\089\000\089\000\255\255\255\255\255\255\ - \255\255\086\000\255\255\255\255\255\255\255\255\255\255\086\000\ - \089\000\089\000\255\255\090\000\255\255\090\000\255\255\089\000\ - \090\000\090\000\090\000\090\000\090\000\090\000\090\000\090\000\ - \090\000\090\000\091\000\091\000\091\000\091\000\091\000\091\000\ - \091\000\091\000\091\000\091\000\255\255\255\255\255\255\255\255\ - \089\000\089\000\255\255\255\255\255\255\255\255\255\255\089\000\ - \091\000\255\255\255\255\255\255\255\255\255\255\091\000\092\000\ - \092\000\092\000\092\000\092\000\092\000\092\000\092\000\092\000\ - \092\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\113\000\120\000\120\000\255\255\255\255\113\000\255\255\ - \091\000\255\255\255\255\255\255\255\255\255\255\091\000\113\000\ - \113\000\113\000\113\000\113\000\113\000\113\000\113\000\255\255\ - \255\255\120\000\255\255\255\255\255\255\255\255\113\000\123\000\ - \123\000\123\000\123\000\123\000\123\000\123\000\123\000\123\000\ - \123\000\120\000\120\000\120\000\120\000\120\000\120\000\120\000\ - \120\000\120\000\120\000\255\255\255\255\255\255\255\255\113\000\ - \255\255\255\255\255\255\113\000\255\255\255\255\255\255\255\255\ - \113\000\113\000\255\255\255\255\255\255\113\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\113\000\255\255\255\255\ - \255\255\113\000\255\255\113\000\255\255\113\000\255\255\113\000\ - \116\000\116\000\116\000\116\000\116\000\116\000\116\000\116\000\ - \116\000\116\000\255\255\255\255\255\255\120\000\255\255\255\255\ - \255\255\116\000\116\000\116\000\116\000\116\000\116\000\117\000\ - \117\000\117\000\117\000\117\000\117\000\117\000\117\000\117\000\ - \117\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \117\000\117\000\117\000\117\000\117\000\117\000\255\255\255\255\ - \255\255\116\000\116\000\116\000\116\000\116\000\116\000\255\255\ + \076\000\076\000\078\000\255\255\078\000\255\255\255\255\078\000\ + \078\000\078\000\078\000\078\000\078\000\078\000\078\000\078\000\ + \078\000\075\000\255\255\255\255\255\255\255\255\255\255\075\000\ + \079\000\079\000\079\000\079\000\079\000\079\000\079\000\079\000\ + \079\000\079\000\082\000\082\000\082\000\082\000\082\000\082\000\ + \082\000\082\000\082\000\082\000\255\255\079\000\079\000\255\255\ + \080\000\255\255\080\000\255\255\079\000\080\000\080\000\080\000\ + \080\000\080\000\080\000\080\000\080\000\080\000\080\000\081\000\ + \081\000\081\000\081\000\081\000\081\000\081\000\081\000\081\000\ + \081\000\255\255\255\255\255\255\255\255\079\000\079\000\255\255\ + \255\255\255\255\255\255\255\255\079\000\081\000\255\255\255\255\ + \255\255\255\255\255\255\081\000\083\000\083\000\083\000\083\000\ + \083\000\083\000\083\000\083\000\083\000\083\000\084\000\084\000\ + \084\000\084\000\084\000\084\000\084\000\084\000\084\000\084\000\ + \255\255\255\255\083\000\255\255\255\255\081\000\255\255\255\255\ + \083\000\255\255\255\255\081\000\255\255\255\255\086\000\086\000\ + \086\000\086\000\086\000\086\000\086\000\086\000\086\000\086\000\ + \089\000\089\000\089\000\089\000\089\000\089\000\089\000\089\000\ + \089\000\089\000\083\000\086\000\086\000\255\255\255\255\087\000\ + \083\000\087\000\086\000\255\255\087\000\087\000\087\000\087\000\ + \087\000\087\000\087\000\087\000\087\000\087\000\088\000\088\000\ + \088\000\088\000\088\000\088\000\088\000\088\000\088\000\088\000\ + \255\255\255\255\255\255\086\000\086\000\255\255\115\000\255\255\ + \255\255\255\255\086\000\115\000\088\000\255\255\255\255\255\255\ + \255\255\255\255\088\000\255\255\115\000\115\000\115\000\115\000\ + \115\000\115\000\115\000\115\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\115\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\088\000\255\255\255\255\255\255\ + \255\255\255\255\088\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\115\000\255\255\255\255\255\255\ + \115\000\255\255\255\255\255\255\255\255\115\000\115\000\255\255\ + \255\255\255\255\115\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\115\000\255\255\255\255\255\255\115\000\255\255\ + \115\000\255\255\115\000\255\255\115\000\118\000\118\000\118\000\ + \118\000\118\000\118\000\118\000\118\000\118\000\118\000\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\118\000\118\000\ + \118\000\118\000\118\000\118\000\119\000\119\000\119\000\119\000\ + \119\000\119\000\119\000\119\000\119\000\119\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\119\000\119\000\119\000\ + \119\000\119\000\119\000\122\000\122\000\255\255\118\000\118\000\ + \118\000\118\000\118\000\118\000\125\000\125\000\125\000\125\000\ + \125\000\125\000\125\000\125\000\125\000\125\000\255\255\255\255\ + \255\255\255\255\122\000\255\255\255\255\119\000\119\000\119\000\ + \119\000\119\000\119\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\122\000\122\000\122\000\122\000\122\000\122\000\ + \122\000\122\000\122\000\122\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \117\000\117\000\117\000\117\000\117\000\117\000\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\122\000\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ @@ -725,7 +713,6 @@ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\120\000\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ @@ -734,15 +721,17 @@ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - "; + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\122\000"; Lexing.lex_base_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \007\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\ + \010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -753,15 +742,13 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000"; Lexing.lex_backtrk_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\ - \000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -772,7 +759,9 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000"; Lexing.lex_default_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -791,7 +780,7 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000"; Lexing.lex_trans_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -865,356 +854,366 @@ } let rec token lexbuf = -lexbuf.Lexing.lex_mem <- Array.create 3 (-1) ; __ocaml_lex_token_rec lexbuf 0 + lexbuf.Lexing.lex_mem <- Array.create 3 (-1) ; __ocaml_lex_token_rec lexbuf 0 and __ocaml_lex_token_rec lexbuf __ocaml_lex_state = match Lexing.new_engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 253 "cil/src/logic/logic_lexer.mll" +# 256 "cil/src/logic/logic_lexer.mll" ( token lexbuf ) -# 875 "cil/src/logic/logic_lexer.ml" +# 864 "cil/src/logic/logic_lexer.ml" | 1 -> -# 254 "cil/src/logic/logic_lexer.mll" +# 257 "cil/src/logic/logic_lexer.mll" ( update_newline_loc lexbuf; token lexbuf ) -# 880 "cil/src/logic/logic_lexer.ml" +# 869 "cil/src/logic/logic_lexer.ml" | 2 -> -# 255 "cil/src/logic/logic_lexer.mll" +# 258 "cil/src/logic/logic_lexer.mll" ( update_newline_loc lexbuf; token lexbuf ) -# 885 "cil/src/logic/logic_lexer.ml" +# 874 "cil/src/logic/logic_lexer.ml" | 3 -> -# 256 "cil/src/logic/logic_lexer.mll" +# 259 "cil/src/logic/logic_lexer.mll" ( token lexbuf ) -# 890 "cil/src/logic/logic_lexer.ml" +# 879 "cil/src/logic/logic_lexer.ml" | 4 -> -# 258 "cil/src/logic/logic_lexer.mll" +# 261 "cil/src/logic/logic_lexer.mll" ( bs_identifier lexbuf ) -# 895 "cil/src/logic/logic_lexer.ml" +# 884 "cil/src/logic/logic_lexer.ml" | 5 -> -# 259 "cil/src/logic/logic_lexer.mll" +# 262 "cil/src/logic/logic_lexer.mll" ( let s = lexeme lexbuf in identifier s ) -# 900 "cil/src/logic/logic_lexer.ml" +# 889 "cil/src/logic/logic_lexer.ml" | 6 -> -# 261 "cil/src/logic/logic_lexer.mll" +# 264 "cil/src/logic/logic_lexer.mll" ( CONSTANT (IntConstant (lexeme lexbuf)) ) -# 905 "cil/src/logic/logic_lexer.ml" +# 894 "cil/src/logic/logic_lexer.ml" | 7 -> -# 262 "cil/src/logic/logic_lexer.mll" +# 265 "cil/src/logic/logic_lexer.mll" ( CONSTANT (IntConstant (lexeme lexbuf)) ) -# 910 "cil/src/logic/logic_lexer.ml" +# 899 "cil/src/logic/logic_lexer.ml" | 8 -> -# 263 "cil/src/logic/logic_lexer.mll" +# 266 "cil/src/logic/logic_lexer.mll" ( CONSTANT10 (lexeme lexbuf) ) -# 915 "cil/src/logic/logic_lexer.ml" +# 904 "cil/src/logic/logic_lexer.ml" | 9 -> -# 264 "cil/src/logic/logic_lexer.mll" +# 267 "cil/src/logic/logic_lexer.mll" ( CONSTANT (IntConstant (lexeme lexbuf)) ) -# 920 "cil/src/logic/logic_lexer.ml" +# 909 "cil/src/logic/logic_lexer.ml" | 10 -> let -# 265 "cil/src/logic/logic_lexer.mll" +# 268 "cil/src/logic/logic_lexer.mll" prelude -# 926 "cil/src/logic/logic_lexer.ml" +# 915 "cil/src/logic/logic_lexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_mem.(0) and -# 265 "cil/src/logic/logic_lexer.mll" - content -# 931 "cil/src/logic/logic_lexer.ml" +# 268 "cil/src/logic/logic_lexer.mll" + content +# 920 "cil/src/logic/logic_lexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_mem.(0) (lexbuf.Lexing.lex_curr_pos + -1) in -# 266 "cil/src/logic/logic_lexer.mll" +# 269 "cil/src/logic/logic_lexer.mll" ( let b = Buffer.create 5 in Buffer.add_string b prelude; let lbf = Lexing.from_string content in CONSTANT (IntConstant (chr b lbf ^ "'")) ) -# 940 "cil/src/logic/logic_lexer.ml" +# 929 "cil/src/logic/logic_lexer.ml" | 11 -> -# 279 "cil/src/logic/logic_lexer.mll" +# 282 "cil/src/logic/logic_lexer.mll" ( CONSTANT (FloatConstant (lexeme lexbuf)) ) -# 945 "cil/src/logic/logic_lexer.ml" +# 934 "cil/src/logic/logic_lexer.ml" | 12 -> let -# 282 "cil/src/logic/logic_lexer.mll" +# 285 "cil/src/logic/logic_lexer.mll" n -# 951 "cil/src/logic/logic_lexer.ml" +# 940 "cil/src/logic/logic_lexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos (lexbuf.Lexing.lex_curr_pos + -2) in -# 282 "cil/src/logic/logic_lexer.mll" +# 285 "cil/src/logic/logic_lexer.mll" ( lexbuf.lex_curr_pos <- lexbuf.lex_curr_pos - 2; CONSTANT (IntConstant n) ) -# 956 "cil/src/logic/logic_lexer.ml" +# 945 "cil/src/logic/logic_lexer.ml" | 13 -> let -# 285 "cil/src/logic/logic_lexer.mll" +# 288 "cil/src/logic/logic_lexer.mll" prelude -# 962 "cil/src/logic/logic_lexer.ml" +# 951 "cil/src/logic/logic_lexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_mem.(0) and -# 285 "cil/src/logic/logic_lexer.mll" - content -# 967 "cil/src/logic/logic_lexer.ml" +# 288 "cil/src/logic/logic_lexer.mll" + content +# 956 "cil/src/logic/logic_lexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_mem.(0) (lexbuf.Lexing.lex_curr_pos + -1) in -# 286 "cil/src/logic/logic_lexer.mll" +# 289 "cil/src/logic/logic_lexer.mll" ( STRING_LITERAL (prelude.[0] = 'L',content) ) -# 971 "cil/src/logic/logic_lexer.ml" +# 960 "cil/src/logic/logic_lexer.ml" | 14 -> -# 287 "cil/src/logic/logic_lexer.mll" +# 290 "cil/src/logic/logic_lexer.mll" ( hash lexbuf ) -# 976 "cil/src/logic/logic_lexer.ml" +# 965 "cil/src/logic/logic_lexer.ml" | 15 -> -# 288 "cil/src/logic/logic_lexer.mll" +# 291 "cil/src/logic/logic_lexer.mll" ( IMPLIES ) -# 981 "cil/src/logic/logic_lexer.ml" +# 970 "cil/src/logic/logic_lexer.ml" | 16 -> -# 289 "cil/src/logic/logic_lexer.mll" +# 292 "cil/src/logic/logic_lexer.mll" ( IFF ) -# 986 "cil/src/logic/logic_lexer.ml" +# 975 "cil/src/logic/logic_lexer.ml" | 17 -> -# 290 "cil/src/logic/logic_lexer.mll" - ( AND ) -# 991 "cil/src/logic/logic_lexer.ml" +# 293 "cil/src/logic/logic_lexer.mll" + ( BIMPLIES ) +# 980 "cil/src/logic/logic_lexer.ml" | 18 -> -# 291 "cil/src/logic/logic_lexer.mll" - ( OR ) -# 996 "cil/src/logic/logic_lexer.ml" +# 294 "cil/src/logic/logic_lexer.mll" + ( BIFF ) +# 985 "cil/src/logic/logic_lexer.ml" | 19 -> -# 292 "cil/src/logic/logic_lexer.mll" - ( NOT ) -# 1001 "cil/src/logic/logic_lexer.ml" +# 295 "cil/src/logic/logic_lexer.mll" + ( AND ) +# 990 "cil/src/logic/logic_lexer.ml" | 20 -> -# 293 "cil/src/logic/logic_lexer.mll" - ( DOLLAR ) -# 1006 "cil/src/logic/logic_lexer.ml" +# 296 "cil/src/logic/logic_lexer.mll" + ( OR ) +# 995 "cil/src/logic/logic_lexer.ml" | 21 -> -# 294 "cil/src/logic/logic_lexer.mll" - ( COMMA ) -# 1011 "cil/src/logic/logic_lexer.ml" +# 297 "cil/src/logic/logic_lexer.mll" + ( NOT ) +# 1000 "cil/src/logic/logic_lexer.ml" | 22 -> -# 295 "cil/src/logic/logic_lexer.mll" - ( ARROW ) -# 1016 "cil/src/logic/logic_lexer.ml" +# 298 "cil/src/logic/logic_lexer.mll" + ( DOLLAR ) +# 1005 "cil/src/logic/logic_lexer.ml" | 23 -> -# 296 "cil/src/logic/logic_lexer.mll" - ( Stack.push Test state_stack; QUESTION ) -# 1021 "cil/src/logic/logic_lexer.ml" +# 299 "cil/src/logic/logic_lexer.mll" + ( COMMA ) +# 1010 "cil/src/logic/logic_lexer.ml" | 24 -> -# 297 "cil/src/logic/logic_lexer.mll" - ( SEMICOLON ) -# 1026 "cil/src/logic/logic_lexer.ml" +# 300 "cil/src/logic/logic_lexer.mll" + ( ARROW ) +# 1015 "cil/src/logic/logic_lexer.ml" | 25 -> -# 298 "cil/src/logic/logic_lexer.mll" +# 301 "cil/src/logic/logic_lexer.mll" + ( Stack.push Test state_stack; QUESTION ) +# 1020 "cil/src/logic/logic_lexer.ml" + + | 26 -> +# 302 "cil/src/logic/logic_lexer.mll" + ( SEMICOLON ) +# 1025 "cil/src/logic/logic_lexer.ml" + + | 27 -> +# 303 "cil/src/logic/logic_lexer.mll" ( match get_state() with Normal -> COLON | Test -> pop_state(); COLON2 ) -# 1034 "cil/src/logic/logic_lexer.ml" +# 1033 "cil/src/logic/logic_lexer.ml" - | 26 -> -# 302 "cil/src/logic/logic_lexer.mll" + | 28 -> +# 307 "cil/src/logic/logic_lexer.mll" ( COLONCOLON ) -# 1039 "cil/src/logic/logic_lexer.ml" +# 1038 "cil/src/logic/logic_lexer.ml" - | 27 -> -# 303 "cil/src/logic/logic_lexer.mll" + | 29 -> +# 308 "cil/src/logic/logic_lexer.mll" ( DOT ) -# 1044 "cil/src/logic/logic_lexer.ml" +# 1043 "cil/src/logic/logic_lexer.ml" - | 28 -> -# 304 "cil/src/logic/logic_lexer.mll" + | 30 -> +# 309 "cil/src/logic/logic_lexer.mll" ( DOTDOT ) -# 1049 "cil/src/logic/logic_lexer.ml" +# 1048 "cil/src/logic/logic_lexer.ml" - | 29 -> -# 305 "cil/src/logic/logic_lexer.mll" + | 31 -> +# 310 "cil/src/logic/logic_lexer.mll" ( DOTDOTDOT ) -# 1054 "cil/src/logic/logic_lexer.ml" +# 1053 "cil/src/logic/logic_lexer.ml" - | 30 -> -# 306 "cil/src/logic/logic_lexer.mll" + | 32 -> +# 311 "cil/src/logic/logic_lexer.mll" ( MINUS ) -# 1059 "cil/src/logic/logic_lexer.ml" +# 1058 "cil/src/logic/logic_lexer.ml" - | 31 -> -# 307 "cil/src/logic/logic_lexer.mll" + | 33 -> +# 312 "cil/src/logic/logic_lexer.mll" ( PLUS ) -# 1064 "cil/src/logic/logic_lexer.ml" +# 1063 "cil/src/logic/logic_lexer.ml" - | 32 -> -# 308 "cil/src/logic/logic_lexer.mll" + | 34 -> +# 313 "cil/src/logic/logic_lexer.mll" ( STAR ) -# 1069 "cil/src/logic/logic_lexer.ml" +# 1068 "cil/src/logic/logic_lexer.ml" - | 33 -> -# 309 "cil/src/logic/logic_lexer.mll" + | 35 -> +# 314 "cil/src/logic/logic_lexer.mll" ( AMP ) -# 1074 "cil/src/logic/logic_lexer.ml" +# 1073 "cil/src/logic/logic_lexer.ml" - | 34 -> -# 310 "cil/src/logic/logic_lexer.mll" + | 36 -> +# 315 "cil/src/logic/logic_lexer.mll" ( HATHAT ) -# 1079 "cil/src/logic/logic_lexer.ml" +# 1078 "cil/src/logic/logic_lexer.ml" - | 35 -> -# 311 "cil/src/logic/logic_lexer.mll" + | 37 -> +# 316 "cil/src/logic/logic_lexer.mll" ( HAT ) -# 1084 "cil/src/logic/logic_lexer.ml" +# 1083 "cil/src/logic/logic_lexer.ml" - | 36 -> -# 312 "cil/src/logic/logic_lexer.mll" + | 38 -> +# 317 "cil/src/logic/logic_lexer.mll" ( PIPE ) -# 1089 "cil/src/logic/logic_lexer.ml" +# 1088 "cil/src/logic/logic_lexer.ml" - | 37 -> -# 313 "cil/src/logic/logic_lexer.mll" + | 39 -> +# 318 "cil/src/logic/logic_lexer.mll" ( TILDE ) -# 1094 "cil/src/logic/logic_lexer.ml" +# 1093 "cil/src/logic/logic_lexer.ml" - | 38 -> -# 314 "cil/src/logic/logic_lexer.mll" + | 40 -> +# 319 "cil/src/logic/logic_lexer.mll" ( SLASH ) -# 1099 "cil/src/logic/logic_lexer.ml" +# 1098 "cil/src/logic/logic_lexer.ml" - | 39 -> -# 315 "cil/src/logic/logic_lexer.mll" + | 41 -> +# 320 "cil/src/logic/logic_lexer.mll" ( PERCENT ) -# 1104 "cil/src/logic/logic_lexer.ml" +# 1103 "cil/src/logic/logic_lexer.ml" - | 40 -> -# 316 "cil/src/logic/logic_lexer.mll" + | 42 -> +# 321 "cil/src/logic/logic_lexer.mll" ( LT ) -# 1109 "cil/src/logic/logic_lexer.ml" +# 1108 "cil/src/logic/logic_lexer.ml" - | 41 -> -# 317 "cil/src/logic/logic_lexer.mll" + | 43 -> +# 322 "cil/src/logic/logic_lexer.mll" ( GT ) -# 1114 "cil/src/logic/logic_lexer.ml" +# 1113 "cil/src/logic/logic_lexer.ml" - | 42 -> -# 318 "cil/src/logic/logic_lexer.mll" + | 44 -> +# 323 "cil/src/logic/logic_lexer.mll" ( LE ) -# 1119 "cil/src/logic/logic_lexer.ml" +# 1118 "cil/src/logic/logic_lexer.ml" - | 43 -> -# 319 "cil/src/logic/logic_lexer.mll" + | 45 -> +# 324 "cil/src/logic/logic_lexer.mll" ( GE ) -# 1124 "cil/src/logic/logic_lexer.ml" +# 1123 "cil/src/logic/logic_lexer.ml" - | 44 -> -# 320 "cil/src/logic/logic_lexer.mll" + | 46 -> +# 325 "cil/src/logic/logic_lexer.mll" ( EQ ) -# 1129 "cil/src/logic/logic_lexer.ml" +# 1128 "cil/src/logic/logic_lexer.ml" - | 45 -> -# 321 "cil/src/logic/logic_lexer.mll" + | 47 -> +# 326 "cil/src/logic/logic_lexer.mll" ( EQUAL ) -# 1134 "cil/src/logic/logic_lexer.ml" +# 1133 "cil/src/logic/logic_lexer.ml" - | 46 -> -# 322 "cil/src/logic/logic_lexer.mll" + | 48 -> +# 327 "cil/src/logic/logic_lexer.mll" ( NE ) -# 1139 "cil/src/logic/logic_lexer.ml" +# 1138 "cil/src/logic/logic_lexer.ml" - | 47 -> -# 323 "cil/src/logic/logic_lexer.mll" + | 49 -> +# 328 "cil/src/logic/logic_lexer.mll" ( Stack.push Normal state_stack; LPAR ) -# 1144 "cil/src/logic/logic_lexer.ml" +# 1143 "cil/src/logic/logic_lexer.ml" - | 48 -> -# 324 "cil/src/logic/logic_lexer.mll" + | 50 -> +# 329 "cil/src/logic/logic_lexer.mll" ( pop_state(); RPAR ) -# 1149 "cil/src/logic/logic_lexer.ml" +# 1148 "cil/src/logic/logic_lexer.ml" - | 49 -> -# 325 "cil/src/logic/logic_lexer.mll" + | 51 -> +# 330 "cil/src/logic/logic_lexer.mll" ( Stack.push Normal state_stack; LBRACE ) -# 1154 "cil/src/logic/logic_lexer.ml" +# 1153 "cil/src/logic/logic_lexer.ml" - | 50 -> -# 326 "cil/src/logic/logic_lexer.mll" + | 52 -> +# 331 "cil/src/logic/logic_lexer.mll" ( pop_state(); RBRACE ) -# 1159 "cil/src/logic/logic_lexer.ml" +# 1158 "cil/src/logic/logic_lexer.ml" - | 51 -> -# 327 "cil/src/logic/logic_lexer.mll" + | 53 -> +# 332 "cil/src/logic/logic_lexer.mll" ( Stack.push Normal state_stack; LSQUARE ) -# 1164 "cil/src/logic/logic_lexer.ml" +# 1163 "cil/src/logic/logic_lexer.ml" - | 52 -> -# 328 "cil/src/logic/logic_lexer.mll" + | 54 -> +# 333 "cil/src/logic/logic_lexer.mll" ( pop_state(); RSQUARE ) -# 1169 "cil/src/logic/logic_lexer.ml" +# 1168 "cil/src/logic/logic_lexer.ml" - | 53 -> -# 329 "cil/src/logic/logic_lexer.mll" + | 55 -> +# 334 "cil/src/logic/logic_lexer.mll" ( LTCOLON ) -# 1174 "cil/src/logic/logic_lexer.ml" +# 1173 "cil/src/logic/logic_lexer.ml" - | 54 -> -# 330 "cil/src/logic/logic_lexer.mll" + | 56 -> +# 335 "cil/src/logic/logic_lexer.mll" ( COLONGT ) -# 1179 "cil/src/logic/logic_lexer.ml" +# 1178 "cil/src/logic/logic_lexer.ml" - | 55 -> -# 331 "cil/src/logic/logic_lexer.mll" + | 57 -> +# 336 "cil/src/logic/logic_lexer.mll" ( LTLT ) -# 1184 "cil/src/logic/logic_lexer.ml" +# 1183 "cil/src/logic/logic_lexer.ml" - | 56 -> -# 332 "cil/src/logic/logic_lexer.mll" + | 58 -> +# 337 "cil/src/logic/logic_lexer.mll" ( GTGT ) -# 1189 "cil/src/logic/logic_lexer.ml" +# 1188 "cil/src/logic/logic_lexer.ml" - | 57 -> + | 59 -> let -# 333 "cil/src/logic/logic_lexer.mll" +# 338 "cil/src/logic/logic_lexer.mll" c -# 1195 "cil/src/logic/logic_lexer.ml" +# 1194 "cil/src/logic/logic_lexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in -# 333 "cil/src/logic/logic_lexer.mll" +# 338 "cil/src/logic/logic_lexer.mll" ( find_utf8 c ) -# 1199 "cil/src/logic/logic_lexer.ml" +# 1198 "cil/src/logic/logic_lexer.ml" - | 58 -> -# 334 "cil/src/logic/logic_lexer.mll" + | 60 -> +# 339 "cil/src/logic/logic_lexer.mll" ( EOF ) -# 1204 "cil/src/logic/logic_lexer.ml" +# 1203 "cil/src/logic/logic_lexer.ml" - | 59 -> -# 335 "cil/src/logic/logic_lexer.mll" + | 61 -> +# 340 "cil/src/logic/logic_lexer.mll" ( lex_error lexbuf ("illegal character " ^ lexeme lexbuf) ) -# 1209 "cil/src/logic/logic_lexer.ml" +# 1208 "cil/src/logic/logic_lexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state and chr buffer lexbuf = - __ocaml_lex_chr_rec buffer lexbuf 110 + __ocaml_lex_chr_rec buffer lexbuf 112 and __ocaml_lex_chr_rec buffer lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 339 "cil/src/logic/logic_lexer.mll" +# 344 "cil/src/logic/logic_lexer.mll" ( let s = lexeme lexbuf in let real_s = String.sub s 2 (String.length s - 2) in let rec add_one_char s = @@ -1231,10 +1230,10 @@ Buffer.add_char buffer (Char.chr c); add_one_char s in add_one_char real_s; chr buffer lexbuf ) -# 1235 "cil/src/logic/logic_lexer.ml" +# 1234 "cil/src/logic/logic_lexer.ml" | 1 -> -# 356 "cil/src/logic/logic_lexer.mll" +# 361 "cil/src/logic/logic_lexer.mll" ( let s = lexeme lexbuf in let real_s = String.sub s 1 (String.length s - 1) in let rec value i s = @@ -1244,10 +1243,10 @@ in let c = value 0 real_s in Buffer.add_char buffer (Char.chr c); chr buffer lexbuf ) -# 1248 "cil/src/logic/logic_lexer.ml" +# 1247 "cil/src/logic/logic_lexer.ml" | 2 -> -# 366 "cil/src/logic/logic_lexer.mll" +# 371 "cil/src/logic/logic_lexer.mll" ( Buffer.add_char buffer (match (lexeme lexbuf).[1] with 'a' -> '\007' @@ -1262,36 +1261,36 @@ | '\\' -> '\\' | _ -> assert false ); chr buffer lexbuf) -# 1266 "cil/src/logic/logic_lexer.ml" +# 1265 "cil/src/logic/logic_lexer.ml" | 3 -> -# 380 "cil/src/logic/logic_lexer.mll" +# 385 "cil/src/logic/logic_lexer.mll" ( Buffer.contents buffer ) -# 1271 "cil/src/logic/logic_lexer.ml" +# 1270 "cil/src/logic/logic_lexer.ml" | 4 -> -# 381 "cil/src/logic/logic_lexer.mll" +# 386 "cil/src/logic/logic_lexer.mll" ( Buffer.add_string buffer (lexeme lexbuf); chr buffer lexbuf ) -# 1276 "cil/src/logic/logic_lexer.ml" +# 1275 "cil/src/logic/logic_lexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_chr_rec buffer lexbuf __ocaml_lex_state and hash lexbuf = - __ocaml_lex_hash_rec lexbuf 120 + __ocaml_lex_hash_rec lexbuf 122 and __ocaml_lex_hash_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 384 "cil/src/logic/logic_lexer.mll" +# 389 "cil/src/logic/logic_lexer.mll" ( update_newline_loc lexbuf; token lexbuf) -# 1287 "cil/src/logic/logic_lexer.ml" +# 1286 "cil/src/logic/logic_lexer.ml" | 1 -> -# 385 "cil/src/logic/logic_lexer.mll" +# 390 "cil/src/logic/logic_lexer.mll" ( hash lexbuf) -# 1292 "cil/src/logic/logic_lexer.ml" +# 1291 "cil/src/logic/logic_lexer.ml" | 2 -> -# 386 "cil/src/logic/logic_lexer.mll" +# 391 "cil/src/logic/logic_lexer.mll" ( (* We are seeing a line number. This is the number for the * next line *) let s = Lexing.lexeme lexbuf in @@ -1299,44 +1298,43 @@ int_of_string s with Failure ("int_of_string") -> (* the int is too big. *) - let src = Cil.source (lexbuf.lex_start_p, lexbuf.lex_curr_p) in - Cilmsg.warning ~source:src + Kernel.warning ~source:lexbuf.lex_start_p "Bad line number in preprocessed file: %s" s; (-1) in update_line_loc lexbuf (lineno - 1) true 0; (* A file name may follow *) file lexbuf ) -# 1311 "cil/src/logic/logic_lexer.ml" +# 1309 "cil/src/logic/logic_lexer.ml" | 3 -> -# 401 "cil/src/logic/logic_lexer.mll" +# 405 "cil/src/logic/logic_lexer.mll" ( hash lexbuf ) -# 1316 "cil/src/logic/logic_lexer.ml" +# 1314 "cil/src/logic/logic_lexer.ml" | 4 -> -# 402 "cil/src/logic/logic_lexer.mll" +# 406 "cil/src/logic/logic_lexer.mll" ( endline lexbuf) -# 1321 "cil/src/logic/logic_lexer.ml" +# 1319 "cil/src/logic/logic_lexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_hash_rec lexbuf __ocaml_lex_state and file lexbuf = - __ocaml_lex_file_rec lexbuf 129 + __ocaml_lex_file_rec lexbuf 131 and __ocaml_lex_file_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 405 "cil/src/logic/logic_lexer.mll" +# 409 "cil/src/logic/logic_lexer.mll" ( update_newline_loc lexbuf; token lexbuf) -# 1332 "cil/src/logic/logic_lexer.ml" +# 1330 "cil/src/logic/logic_lexer.ml" | 1 -> -# 406 "cil/src/logic/logic_lexer.mll" +# 410 "cil/src/logic/logic_lexer.mll" ( file lexbuf) -# 1337 "cil/src/logic/logic_lexer.ml" +# 1335 "cil/src/logic/logic_lexer.ml" | 2 -> -# 408 "cil/src/logic/logic_lexer.mll" +# 412 "cil/src/logic/logic_lexer.mll" ( let n = Lexing.lexeme lexbuf in let n1 = String.sub n 1 @@ -1344,39 +1342,39 @@ update_file_loc lexbuf n1; endline lexbuf ) -# 1348 "cil/src/logic/logic_lexer.ml" +# 1346 "cil/src/logic/logic_lexer.ml" | 3 -> -# 416 "cil/src/logic/logic_lexer.mll" +# 420 "cil/src/logic/logic_lexer.mll" ( endline lexbuf) -# 1353 "cil/src/logic/logic_lexer.ml" +# 1351 "cil/src/logic/logic_lexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_file_rec lexbuf __ocaml_lex_state and endline lexbuf = - __ocaml_lex_endline_rec lexbuf 136 + __ocaml_lex_endline_rec lexbuf 138 and __ocaml_lex_endline_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 419 "cil/src/logic/logic_lexer.mll" +# 423 "cil/src/logic/logic_lexer.mll" ( update_newline_loc lexbuf; token lexbuf) -# 1364 "cil/src/logic/logic_lexer.ml" +# 1362 "cil/src/logic/logic_lexer.ml" | 1 -> -# 420 "cil/src/logic/logic_lexer.mll" +# 424 "cil/src/logic/logic_lexer.mll" ( EOF ) -# 1369 "cil/src/logic/logic_lexer.ml" +# 1367 "cil/src/logic/logic_lexer.ml" | 2 -> -# 421 "cil/src/logic/logic_lexer.mll" +# 425 "cil/src/logic/logic_lexer.mll" ( endline lexbuf) -# 1374 "cil/src/logic/logic_lexer.ml" +# 1372 "cil/src/logic/logic_lexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_endline_rec lexbuf __ocaml_lex_state ;; -# 423 "cil/src/logic/logic_lexer.mll" +# 427 "cil/src/logic/logic_lexer.mll" open Format @@ -1402,26 +1400,19 @@ f token lb with | Parsing.Parse_error as _e -> - Cil.error_loc ( - lb.lex_curr_p.Lexing.pos_fname, - lb.lex_curr_p.Lexing.pos_lnum) - "unexpected token '%s'@." (Lexing.lexeme lb); - Logic_utils.exit_kw_c_mode (); - raise Parsing.Parse_error - + Kernel.error + ~source:lb.lex_curr_p + "unexpected token '%s'" (Lexing.lexeme lb); + Logic_utils.exit_kw_c_mode (); + raise Parsing.Parse_error | Error (_, m) -> - Cil.error_loc ( - lb.lex_curr_p.Lexing.pos_fname, - lb.lex_curr_p.Lexing.pos_lnum) - "%s@." m; - Logic_utils.exit_kw_c_mode (); - raise Parsing.Parse_error + Kernel.error ~source:lb.lex_curr_p "%s" m; + Logic_utils.exit_kw_c_mode (); + raise Parsing.Parse_error | Logic_utils.Not_well_formed (loc, m) -> - Cil.error_loc - ((fst loc).Lexing.pos_fname,(fst loc).Lexing.pos_lnum) - "%s@." m; - Logic_utils.exit_kw_c_mode (); - raise Parsing.Parse_error + Kernel.error ~source:(fst loc) "%s" m; + Logic_utils.exit_kw_c_mode (); + raise Parsing.Parse_error let lexpr = parse_from_location Logic_parser.lexpr_eof @@ -1433,4 +1424,4 @@ let ext_spec = parse_from_location Logic_parser.ext_spec -# 1437 "cil/src/logic/logic_lexer.ml" +# 1428 "cil/src/logic/logic_lexer.ml" diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_lexer.mll frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_lexer.mll --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_lexer.mll 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_lexer.mll 2011-10-10 08:40:07.000000000 +0000 @@ -69,7 +69,7 @@ fun s -> try Hashtbl.find h s with Not_found -> IDENTIFIER s - let identifier = + let identifier, is_acsl_keyword = let all_kw = Hashtbl.create 37 in let c_kw = Hashtbl.create 37 in let type_kw = Hashtbl.create 3 in @@ -117,6 +117,7 @@ "logic", LOGIC, false; "long", LONG, true; "loop", LOOP, false; + "modelfield", MODEL, false;(* ACSL extension for model fields *) "module", MODULE, false;(* ACSL extension for external spec file *) "pragma", PRAGMA, false; "predicate", PREDICATE, false; @@ -139,7 +140,7 @@ ]; List.iter (fun (x, y) -> Hashtbl.add type_kw x y) ["integer", INTEGER; "real", REAL; "boolean", BOOLEAN; ]; - fun s -> + (fun s -> try Hashtbl.find (if Logic_utils.is_kw_c_mode () then c_kw else all_kw) s with Not_found -> @@ -149,7 +150,8 @@ Hashtbl.find type_kw s with Not_found -> if Logic_utils.is_rt_type_mode () then TYPENAME s - else IDENTIFIER s) + else IDENTIFIER s)), + (fun s -> Hashtbl.mem all_kw s || Hashtbl.mem type_kw s) let bs_identifier = let h = Hashtbl.create 97 in @@ -164,6 +166,7 @@ "\\forall", FORALL; "\\fresh", FRESH; "\\from", FROM; + "\\initialized", INITIALIZED; "\\inter", INTER; "\\lambda", LAMBDA; "\\let", LET; @@ -262,7 +265,7 @@ | '0' rD+ rIS? { CONSTANT (IntConstant (lexeme lexbuf)) } | rD+ { CONSTANT10 (lexeme lexbuf) } | rD+ rIS { CONSTANT (IntConstant (lexeme lexbuf)) } - | ('L'? "'" as prelude) (([^'\'''\n']|"\\'")+ as content) "'" + | ('L'? "'" as prelude) (([^ '\\' '\'' '\n']|("\\"[^ '\n']))+ as content) "'" { let b = Buffer.create 5 in Buffer.add_string b prelude; @@ -282,11 +285,13 @@ | (rD+ as n) ".." { lexbuf.lex_curr_pos <- lexbuf.lex_curr_pos - 2; CONSTANT (IntConstant n) } - | 'L'? '"' as prelude (([^'"''\n']|"\\\"")+ as content) '"' + | 'L'? '"' as prelude (([^ '\\' '"' '\n']|("\\"[^ '\n']))* as content) '"' { STRING_LITERAL (prelude.[0] = 'L',content) } | '#' { hash lexbuf } | "==>" { IMPLIES } | "<==>" { IFF } + | "-->" { BIMPLIES } + | "<-->" { BIFF } | "&&" { AND } | "||" { OR } | "!" { NOT } @@ -390,8 +395,7 @@ int_of_string s with Failure ("int_of_string") -> (* the int is too big. *) - let src = Cil.source (lexbuf.lex_start_p, lexbuf.lex_curr_p) in - Cilmsg.warning ~source:src + Kernel.warning ~source:lexbuf.lex_start_p "Bad line number in preprocessed file: %s" s; (-1) in @@ -445,26 +449,19 @@ f token lb with | Parsing.Parse_error as _e -> - Cil.error_loc ( - lb.lex_curr_p.Lexing.pos_fname, - lb.lex_curr_p.Lexing.pos_lnum) - "unexpected token '%s'@." (Lexing.lexeme lb); - Logic_utils.exit_kw_c_mode (); - raise Parsing.Parse_error - + Kernel.error + ~source:lb.lex_curr_p + "unexpected token '%s'" (Lexing.lexeme lb); + Logic_utils.exit_kw_c_mode (); + raise Parsing.Parse_error | Error (_, m) -> - Cil.error_loc ( - lb.lex_curr_p.Lexing.pos_fname, - lb.lex_curr_p.Lexing.pos_lnum) - "%s@." m; - Logic_utils.exit_kw_c_mode (); - raise Parsing.Parse_error + Kernel.error ~source:lb.lex_curr_p "%s" m; + Logic_utils.exit_kw_c_mode (); + raise Parsing.Parse_error | Logic_utils.Not_well_formed (loc, m) -> - Cil.error_loc - ((fst loc).Lexing.pos_fname,(fst loc).Lexing.pos_lnum) - "%s@." m; - Logic_utils.exit_kw_c_mode (); - raise Parsing.Parse_error + Kernel.error ~source:(fst loc) "%s" m; + Logic_utils.exit_kw_c_mode (); + raise Parsing.Parse_error let lexpr = parse_from_location Logic_parser.lexpr_eof diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_parser.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_parser.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_parser.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_parser.ml 2011-10-10 08:48:48.000000000 +0000 @@ -99,6 +99,7 @@ | LBRACE | RBRACE | GHOST + | MODEL | CASE | VOID | CHAR @@ -121,6 +122,8 @@ | COMPLETE | DISJOINT | TERMINATES + | BIFF + | BIMPLIES | HAT | HATHAT | PIPE @@ -134,6 +137,7 @@ | BSTYPE | WITH | CONST + | INITIALIZED open Parsing;; # 28 "cil/src/logic/logic_parser.mly" @@ -267,7 +271,7 @@ | [] -> annots (* Already considered all cases. *) | _ -> AAssigns (bhvs2,Writes a2) :: annots -# 271 "cil/src/logic/logic_parser.ml" +# 275 "cil/src/logic/logic_parser.ml" let yytransl_const = [| 257 (* MODULE *); 258 (* FUNCTION *); @@ -364,41 +368,45 @@ 353 (* LBRACE *); 354 (* RBRACE *); 355 (* GHOST *); - 356 (* CASE *); - 357 (* VOID *); - 358 (* CHAR *); - 359 (* SIGNED *); - 360 (* UNSIGNED *); - 361 (* SHORT *); - 362 (* LONG *); - 363 (* DOUBLE *); - 364 (* STRUCT *); - 365 (* ENUM *); - 366 (* UNION *); - 367 (* BSUNION *); - 368 (* INTER *); - 369 (* LTCOLON *); - 370 (* COLONGT *); - 371 (* TYPE *); - 372 (* BEHAVIOR *); - 373 (* BEHAVIORS *); - 374 (* ASSUMES *); - 375 (* COMPLETE *); - 376 (* DISJOINT *); - 377 (* TERMINATES *); - 378 (* HAT *); - 379 (* HATHAT *); - 380 (* PIPE *); - 381 (* TILDE *); - 382 (* GTGT *); - 383 (* LTLT *); - 384 (* SIZEOF *); - 385 (* LAMBDA *); - 386 (* LET *); - 387 (* TYPEOF *); - 388 (* BSTYPE *); - 389 (* WITH *); - 390 (* CONST *); + 356 (* MODEL *); + 357 (* CASE *); + 358 (* VOID *); + 359 (* CHAR *); + 360 (* SIGNED *); + 361 (* UNSIGNED *); + 362 (* SHORT *); + 363 (* LONG *); + 364 (* DOUBLE *); + 365 (* STRUCT *); + 366 (* ENUM *); + 367 (* UNION *); + 368 (* BSUNION *); + 369 (* INTER *); + 370 (* LTCOLON *); + 371 (* COLONGT *); + 372 (* TYPE *); + 373 (* BEHAVIOR *); + 374 (* BEHAVIORS *); + 375 (* ASSUMES *); + 376 (* COMPLETE *); + 377 (* DISJOINT *); + 378 (* TERMINATES *); + 379 (* BIFF *); + 380 (* BIMPLIES *); + 381 (* HAT *); + 382 (* HATHAT *); + 383 (* PIPE *); + 384 (* TILDE *); + 385 (* GTGT *); + 386 (* LTLT *); + 387 (* SIZEOF *); + 388 (* LAMBDA *); + 389 (* LET *); + 390 (* TYPEOF *); + 391 (* BSTYPE *); + 392 (* WITH *); + 393 (* CONST *); + 394 (* INITIALIZED *); 0|] let yytransl_block = [| @@ -413,127 +421,129 @@ \005\000\006\000\007\000\008\000\009\000\010\000\011\000\011\000\ \012\000\012\000\001\000\014\000\014\000\013\000\013\000\013\000\ \013\000\013\000\013\000\013\000\013\000\013\000\013\000\013\000\ -\016\000\016\000\020\000\020\000\020\000\020\000\017\000\017\000\ -\017\000\019\000\019\000\023\000\023\000\023\000\023\000\023\000\ -\023\000\023\000\018\000\018\000\018\000\018\000\018\000\018\000\ +\013\000\013\000\016\000\016\000\020\000\020\000\020\000\020\000\ +\017\000\017\000\017\000\019\000\019\000\023\000\023\000\023\000\ +\023\000\023\000\023\000\023\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ -\018\000\024\000\024\000\027\000\037\000\038\000\034\000\034\000\ -\039\000\039\000\040\000\035\000\035\000\036\000\036\000\041\000\ -\041\000\042\000\042\000\043\000\043\000\022\000\044\000\044\000\ -\044\000\045\000\046\000\046\000\025\000\025\000\049\000\049\000\ -\047\000\047\000\047\000\047\000\050\000\050\000\050\000\051\000\ -\051\000\052\000\053\000\054\000\054\000\055\000\055\000\028\000\ -\057\000\057\000\058\000\058\000\058\000\032\000\032\000\060\000\ -\060\000\056\000\056\000\059\000\059\000\059\000\059\000\059\000\ -\059\000\059\000\062\000\062\000\048\000\048\000\061\000\061\000\ +\018\000\018\000\018\000\018\000\024\000\024\000\027\000\037\000\ +\038\000\034\000\034\000\039\000\039\000\040\000\035\000\035\000\ +\036\000\036\000\041\000\041\000\042\000\042\000\043\000\043\000\ +\022\000\044\000\044\000\044\000\045\000\046\000\046\000\025\000\ +\025\000\049\000\049\000\047\000\047\000\047\000\047\000\050\000\ +\050\000\050\000\051\000\051\000\052\000\053\000\054\000\054\000\ +\055\000\055\000\028\000\057\000\057\000\058\000\058\000\058\000\ +\032\000\032\000\060\000\060\000\056\000\056\000\059\000\059\000\ +\059\000\059\000\059\000\059\000\059\000\062\000\062\000\048\000\ +\048\000\061\000\061\000\033\000\033\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ -\033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ -\033\000\033\000\063\000\063\000\064\000\065\000\066\000\067\000\ -\068\000\069\000\071\000\072\000\073\000\074\000\004\000\076\000\ -\076\000\079\000\079\000\080\000\080\000\080\000\078\000\078\000\ -\082\000\082\000\083\000\083\000\077\000\077\000\085\000\085\000\ -\086\000\088\000\088\000\089\000\089\000\089\000\089\000\092\000\ -\092\000\092\000\092\000\096\000\093\000\094\000\099\000\099\000\ -\100\000\084\000\087\000\095\000\090\000\091\000\091\000\003\000\ -\097\000\097\000\097\000\097\000\097\000\097\000\097\000\097\000\ -\097\000\097\000\097\000\097\000\097\000\097\000\097\000\101\000\ -\101\000\113\000\102\000\102\000\107\000\103\000\103\000\108\000\ -\114\000\114\000\104\000\104\000\109\000\109\000\109\000\115\000\ -\112\000\105\000\105\000\110\000\119\000\119\000\119\000\119\000\ -\120\000\120\000\106\000\106\000\111\000\111\000\075\000\075\000\ -\070\000\070\000\122\000\002\000\002\000\002\000\098\000\098\000\ -\098\000\098\000\098\000\127\000\130\000\130\000\130\000\130\000\ -\130\000\130\000\132\000\132\000\133\000\131\000\134\000\136\000\ -\135\000\129\000\129\000\129\000\129\000\129\000\128\000\128\000\ -\128\000\128\000\128\000\128\000\137\000\137\000\138\000\138\000\ -\125\000\125\000\081\000\081\000\081\000\081\000\081\000\139\000\ -\139\000\139\000\140\000\143\000\143\000\144\000\145\000\145\000\ -\145\000\147\000\147\000\148\000\141\000\141\000\141\000\141\000\ -\141\000\141\000\142\000\142\000\142\000\150\000\150\000\153\000\ -\153\000\153\000\153\000\153\000\152\000\154\000\154\000\151\000\ -\151\000\156\000\156\000\155\000\155\000\157\000\157\000\158\000\ -\158\000\149\000\149\000\031\000\031\000\146\000\146\000\029\000\ -\121\000\121\000\126\000\126\000\118\000\015\000\015\000\026\000\ -\026\000\030\000\021\000\021\000\160\000\160\000\160\000\160\000\ -\160\000\160\000\160\000\160\000\160\000\160\000\160\000\160\000\ -\160\000\160\000\160\000\160\000\160\000\160\000\161\000\161\000\ -\117\000\117\000\117\000\117\000\117\000\162\000\162\000\162\000\ -\162\000\162\000\162\000\162\000\162\000\163\000\163\000\163\000\ -\163\000\163\000\163\000\163\000\163\000\163\000\163\000\163\000\ -\163\000\163\000\164\000\164\000\164\000\164\000\164\000\164\000\ -\164\000\165\000\165\000\165\000\165\000\165\000\165\000\159\000\ -\159\000\159\000\159\000\159\000\159\000\116\000\116\000\116\000\ -\123\000\123\000\166\000\166\000\166\000\166\000\166\000\166\000\ +\033\000\033\000\033\000\033\000\033\000\063\000\063\000\064\000\ +\065\000\066\000\067\000\068\000\069\000\071\000\072\000\073\000\ +\074\000\004\000\076\000\076\000\079\000\079\000\080\000\080\000\ +\080\000\078\000\078\000\082\000\082\000\083\000\083\000\077\000\ +\077\000\085\000\085\000\086\000\088\000\088\000\089\000\089\000\ +\089\000\089\000\092\000\092\000\092\000\092\000\093\000\093\000\ +\097\000\097\000\098\000\084\000\087\000\094\000\090\000\091\000\ +\091\000\003\000\095\000\095\000\095\000\095\000\095\000\095\000\ +\095\000\095\000\095\000\095\000\095\000\095\000\095\000\095\000\ +\095\000\099\000\099\000\111\000\100\000\100\000\105\000\101\000\ +\101\000\106\000\112\000\112\000\102\000\102\000\107\000\107\000\ +\107\000\113\000\110\000\103\000\103\000\108\000\117\000\117\000\ +\117\000\117\000\118\000\118\000\104\000\104\000\109\000\109\000\ +\075\000\075\000\070\000\070\000\120\000\002\000\002\000\002\000\ +\096\000\096\000\096\000\096\000\096\000\124\000\128\000\128\000\ +\128\000\128\000\128\000\128\000\130\000\130\000\131\000\129\000\ +\132\000\134\000\133\000\127\000\127\000\127\000\127\000\127\000\ +\126\000\126\000\126\000\126\000\126\000\126\000\135\000\135\000\ +\136\000\136\000\123\000\123\000\081\000\081\000\081\000\081\000\ +\081\000\081\000\137\000\137\000\137\000\138\000\139\000\139\000\ +\142\000\142\000\143\000\144\000\144\000\144\000\146\000\146\000\ +\147\000\140\000\140\000\140\000\140\000\140\000\140\000\141\000\ +\141\000\141\000\149\000\149\000\152\000\152\000\152\000\152\000\ +\152\000\151\000\153\000\153\000\150\000\150\000\155\000\155\000\ +\154\000\154\000\156\000\156\000\157\000\157\000\148\000\148\000\ +\031\000\031\000\145\000\145\000\029\000\119\000\119\000\125\000\ +\125\000\116\000\015\000\015\000\026\000\026\000\030\000\021\000\ +\021\000\159\000\159\000\159\000\159\000\159\000\159\000\159\000\ +\159\000\159\000\159\000\159\000\159\000\159\000\159\000\159\000\ +\159\000\159\000\159\000\160\000\160\000\115\000\115\000\115\000\ +\115\000\115\000\161\000\161\000\161\000\161\000\161\000\161\000\ +\161\000\161\000\162\000\162\000\162\000\162\000\162\000\162\000\ +\162\000\162\000\162\000\162\000\162\000\162\000\162\000\162\000\ +\163\000\163\000\163\000\163\000\163\000\163\000\163\000\164\000\ +\164\000\164\000\164\000\164\000\164\000\158\000\158\000\158\000\ +\158\000\158\000\158\000\114\000\114\000\114\000\121\000\121\000\ +\165\000\165\000\165\000\165\000\165\000\165\000\165\000\165\000\ +\165\000\165\000\165\000\165\000\165\000\165\000\165\000\165\000\ +\165\000\165\000\165\000\165\000\165\000\165\000\165\000\165\000\ +\165\000\166\000\166\000\166\000\166\000\166\000\166\000\166\000\ \166\000\166\000\166\000\166\000\166\000\166\000\166\000\166\000\ \166\000\166\000\166\000\166\000\166\000\166\000\166\000\166\000\ -\166\000\166\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\124\000\124\000\000\000\000\000\ -\000\000\000\000" +\166\000\166\000\166\000\166\000\166\000\166\000\166\000\166\000\ +\166\000\166\000\166\000\166\000\166\000\166\000\166\000\166\000\ +\166\000\166\000\166\000\166\000\166\000\166\000\166\000\166\000\ +\166\000\166\000\166\000\122\000\122\000\000\000\000\000\000\000\ +\000\000" let yylen = "\002\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\ \001\000\003\000\002\000\000\000\001\000\003\000\003\000\003\000\ -\003\000\003\000\003\000\003\000\003\000\005\000\003\000\001\000\ -\001\000\002\000\006\000\004\000\004\000\004\000\001\000\001\000\ -\002\000\002\000\003\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\002\000\001\000\001\000\004\000\006\000\ -\008\000\004\000\001\000\001\000\003\000\003\000\003\000\003\000\ -\003\000\003\000\003\000\004\000\004\000\002\000\002\000\002\000\ -\002\000\002\000\004\000\004\000\004\000\006\000\004\000\004\000\ -\001\000\004\000\004\000\007\000\004\000\001\000\003\000\003\000\ -\003\000\003\000\004\000\003\000\003\000\003\000\004\000\005\000\ -\001\000\004\000\004\000\003\000\005\000\007\000\003\000\003\000\ -\005\000\001\000\002\000\003\000\002\000\003\000\001\000\003\000\ -\003\000\003\000\003\000\001\000\003\000\001\000\003\000\003\000\ -\006\000\001\000\002\000\001\000\001\000\001\000\001\000\003\000\ -\003\000\002\000\001\000\002\000\001\000\001\000\001\000\000\000\ -\001\000\004\000\003\000\004\000\000\000\001\000\003\000\001\000\ -\003\000\001\000\001\000\001\000\003\000\002\000\002\000\002\000\ -\001\000\001\000\001\000\002\000\002\000\002\000\003\000\001\000\ -\003\000\000\000\001\000\001\000\001\000\002\000\002\000\003\000\ -\002\000\001\000\003\000\004\000\001\000\002\000\003\000\004\000\ -\001\000\001\000\001\000\001\000\001\000\002\000\002\000\001\000\ -\002\000\002\000\001\000\001\000\002\000\002\000\001\000\002\000\ -\002\000\003\000\002\000\003\000\002\000\003\000\003\000\003\000\ -\004\000\004\000\001\000\001\000\002\000\003\000\003\000\003\000\ -\001\000\006\000\001\000\004\000\003\000\003\000\003\000\003\000\ -\003\000\003\000\003\000\003\000\003\000\003\000\004\000\000\000\ -\001\000\001\000\002\000\001\000\005\000\003\000\000\000\001\000\ -\001\000\002\000\003\000\001\000\000\000\001\000\001\000\002\000\ -\002\000\000\000\001\000\001\000\001\000\001\000\002\000\001\000\ -\002\000\002\000\002\000\001\000\001\000\001\000\000\000\001\000\ -\001\000\003\000\003\000\003\000\004\000\003\000\003\000\002\000\ -\006\000\003\000\004\000\004\000\005\000\005\000\005\000\006\000\ -\006\000\007\000\007\000\007\000\007\000\007\000\007\000\000\000\ -\001\000\004\000\000\000\001\000\003\000\000\000\001\000\003\000\ -\003\000\001\000\000\000\001\000\004\000\004\000\003\000\002\000\ -\001\000\000\000\001\000\005\000\003\000\003\000\004\000\004\000\ -\000\000\004\000\000\000\001\000\005\000\005\000\001\000\003\000\ -\001\000\001\000\001\000\002\000\003\000\002\000\004\000\001\000\ -\001\000\002\000\001\000\001\000\002\000\002\000\004\000\002\000\ -\002\000\002\000\000\000\001\000\004\000\004\000\004\000\003\000\ -\005\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\006\000\006\000\003\000\003\000\005\000\004\000\005\000\004\000\ -\001\000\002\000\006\000\004\000\001\000\001\000\001\000\000\000\ -\003\000\003\000\009\000\001\000\004\000\001\000\001\000\004\000\ -\007\000\000\000\001\000\003\000\007\000\006\000\006\000\005\000\ -\005\000\005\000\005\000\004\000\003\000\000\000\002\000\001\000\ -\006\000\005\000\003\000\005\000\001\000\000\000\002\000\001\000\ -\001\000\000\000\003\000\002\000\003\000\001\000\004\000\001\000\ -\003\000\000\000\006\000\001\000\003\000\001\000\003\000\001\000\ -\000\000\001\000\001\000\003\000\001\000\001\000\001\000\001\000\ +\003\000\003\000\003\000\003\000\003\000\003\000\003\000\005\000\ +\003\000\001\000\001\000\002\000\006\000\004\000\004\000\004\000\ +\001\000\001\000\002\000\002\000\003\000\001\000\001\000\001\000\ +\001\000\001\000\001\000\001\000\001\000\002\000\001\000\001\000\ +\004\000\006\000\008\000\004\000\004\000\001\000\001\000\003\000\ +\003\000\003\000\003\000\003\000\003\000\003\000\004\000\004\000\ +\002\000\002\000\002\000\002\000\002\000\004\000\004\000\004\000\ +\006\000\004\000\004\000\001\000\004\000\004\000\007\000\004\000\ +\001\000\003\000\003\000\003\000\003\000\004\000\003\000\003\000\ +\003\000\004\000\005\000\001\000\004\000\004\000\003\000\005\000\ +\007\000\003\000\003\000\005\000\001\000\002\000\003\000\002\000\ +\003\000\001\000\003\000\003\000\003\000\003\000\001\000\003\000\ +\001\000\003\000\003\000\006\000\001\000\002\000\001\000\001\000\ +\001\000\001\000\003\000\003\000\002\000\001\000\002\000\001\000\ +\001\000\001\000\000\000\001\000\004\000\003\000\004\000\000\000\ +\001\000\003\000\001\000\003\000\001\000\001\000\001\000\003\000\ +\002\000\002\000\002\000\001\000\001\000\001\000\002\000\002\000\ +\002\000\003\000\001\000\003\000\000\000\001\000\001\000\001\000\ +\002\000\002\000\003\000\002\000\001\000\003\000\004\000\001\000\ +\002\000\003\000\004\000\001\000\001\000\001\000\001\000\001\000\ +\002\000\002\000\001\000\002\000\002\000\001\000\001\000\002\000\ +\002\000\001\000\002\000\002\000\003\000\002\000\003\000\002\000\ +\003\000\003\000\003\000\004\000\004\000\001\000\001\000\002\000\ +\003\000\003\000\003\000\001\000\006\000\001\000\004\000\003\000\ +\003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\ +\003\000\004\000\000\000\001\000\001\000\002\000\001\000\005\000\ +\003\000\000\000\001\000\001\000\002\000\003\000\001\000\000\000\ +\001\000\001\000\002\000\002\000\000\000\001\000\001\000\001\000\ +\001\000\002\000\001\000\002\000\002\000\002\000\001\000\002\000\ +\000\000\001\000\001\000\003\000\003\000\003\000\004\000\003\000\ +\003\000\002\000\006\000\003\000\004\000\004\000\005\000\005\000\ +\005\000\006\000\006\000\007\000\007\000\007\000\007\000\007\000\ +\007\000\000\000\001\000\004\000\000\000\001\000\003\000\000\000\ +\001\000\003\000\003\000\001\000\000\000\001\000\004\000\004\000\ +\003\000\002\000\001\000\000\000\001\000\005\000\003\000\003\000\ +\004\000\004\000\000\000\004\000\000\000\001\000\005\000\005\000\ +\001\000\003\000\001\000\001\000\001\000\002\000\003\000\002\000\ +\001\000\004\000\001\000\002\000\001\000\001\000\002\000\002\000\ +\004\000\002\000\002\000\002\000\000\000\001\000\004\000\004\000\ +\004\000\003\000\005\000\001\000\001\000\001\000\001\000\001\000\ +\001\000\001\000\006\000\006\000\003\000\003\000\005\000\004\000\ +\005\000\004\000\001\000\002\000\006\000\004\000\001\000\001\000\ +\001\000\001\000\000\000\003\000\003\000\009\000\005\000\005\000\ +\001\000\004\000\001\000\001\000\004\000\007\000\000\000\001\000\ +\003\000\007\000\006\000\006\000\005\000\005\000\005\000\005\000\ +\004\000\003\000\000\000\002\000\001\000\006\000\005\000\003\000\ +\005\000\001\000\000\000\002\000\001\000\001\000\000\000\003\000\ +\002\000\003\000\001\000\004\000\001\000\003\000\000\000\006\000\ +\001\000\003\000\001\000\003\000\001\000\000\000\001\000\001\000\ +\003\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ @@ -552,196 +562,200 @@ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\001\000\001\000\002\000\002\000\002\000\ -\002\000\002\000" +\001\000\001\000\001\000\001\000\002\000\002\000\002\000\002\000\ +\002\000" let yydefred = "\000\000\ -\000\000\000\000\000\000\000\000\000\000\212\001\211\001\210\001\ -\213\001\214\001\215\001\000\000\153\001\098\000\125\000\126\000\ -\000\000\165\001\162\001\166\001\205\001\208\001\159\001\164\001\ -\000\000\000\000\000\000\000\000\045\000\046\000\000\000\000\000\ -\073\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\192\001\195\001\188\001\175\001\206\001\ -\190\001\051\000\089\000\185\001\177\001\183\001\198\001\201\001\ -\193\001\199\001\178\001\179\001\180\001\181\001\176\001\207\001\ -\209\001\197\001\200\001\194\001\203\001\196\001\000\000\157\001\ -\174\001\158\001\169\001\173\001\168\001\167\001\161\001\171\001\ -\163\001\172\001\000\000\000\000\202\001\184\001\204\001\191\001\ -\187\001\189\001\186\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\160\001\047\002\000\000\000\000\024\000\025\000\000\000\ -\032\000\000\000\052\000\150\001\000\000\182\001\151\001\216\001\ -\217\001\219\001\220\001\221\001\218\001\000\000\001\000\000\000\ -\001\000\000\000\000\000\000\000\000\000\001\000\001\000\001\000\ -\000\000\001\000\000\000\170\001\048\002\000\000\000\000\000\000\ -\000\000\226\001\000\000\000\000\056\001\000\000\060\001\000\000\ -\000\000\000\000\000\000\000\000\079\001\080\001\093\001\094\001\ -\095\001\224\001\225\001\223\001\001\000\049\002\000\000\000\000\ -\017\001\000\000\000\000\050\002\000\000\217\000\000\000\220\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\176\000\169\000\170\000\171\000\195\000\172\000\ -\173\000\000\000\000\000\180\000\000\000\196\000\004\000\004\000\ -\004\000\000\000\000\000\000\000\119\000\000\000\154\001\000\000\ -\000\000\000\000\033\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\156\001\000\000\ -\155\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\011\000\000\000\000\000\000\000\000\000\000\000\036\000\ -\037\000\038\000\039\000\040\000\041\000\000\000\042\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\026\000\000\000\099\000\000\000\001\000\000\000\000\000\ -\000\000\152\001\149\001\000\000\000\000\000\000\001\000\001\000\ -\001\000\000\000\222\001\000\000\001\000\000\000\000\000\000\000\ -\000\000\001\000\000\000\000\000\103\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\002\000\090\001\052\001\ -\043\002\005\002\006\002\024\002\038\002\000\002\001\002\002\002\ -\008\002\009\002\010\002\026\002\016\002\023\002\014\002\011\002\ -\030\002\004\002\255\001\012\002\232\001\013\002\020\002\021\002\ -\254\001\032\002\031\002\242\001\243\001\231\001\240\001\227\001\ -\241\001\229\001\228\001\247\001\248\001\249\001\233\001\007\002\ -\036\002\029\002\035\002\042\002\253\001\041\002\033\002\025\002\ -\039\002\040\002\239\001\230\001\238\001\234\001\022\002\037\002\ -\015\002\246\001\235\001\027\002\003\002\018\002\019\002\034\002\ -\044\002\017\002\028\002\236\001\237\001\245\001\244\001\250\001\ -\251\001\000\000\252\001\000\000\054\001\078\001\076\001\077\001\ -\075\001\074\001\058\001\000\000\068\001\061\001\062\001\064\001\ -\065\001\066\001\000\000\000\001\001\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\230\000\000\000\000\000\219\000\003\000\ -\177\000\174\000\181\000\000\000\178\000\175\000\182\000\000\000\ -\187\000\000\000\197\000\000\000\000\000\000\000\081\000\000\000\ -\082\000\000\000\146\000\145\000\149\000\148\000\000\000\165\000\ -\000\000\000\000\150\000\000\000\156\000\000\000\000\000\000\000\ -\129\000\122\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\101\000\000\000\000\000\092\000\000\000\000\000\095\000\096\000\ -\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\019\000\000\000\000\000\000\000\000\000\ -\059\000\058\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\085\000\000\000\000\000\034\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\084\001\000\000\000\000\ -\083\001\000\000\000\000\000\000\000\000\000\000\001\000\072\001\ -\000\000\032\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\139\000\152\000\002\000\000\000\002\000\001\000\000\000\001\000\ -\000\000\107\001\000\000\000\000\001\000\000\000\117\001\000\000\ -\207\000\053\001\046\002\000\000\000\000\000\000\001\000\000\000\ -\000\000\002\001\222\000\001\000\249\000\000\000\000\000\000\000\ -\224\000\000\000\000\000\232\000\000\000\000\000\240\000\233\000\ -\235\000\000\000\000\000\000\000\000\000\000\000\186\000\000\000\ -\188\000\000\000\192\000\198\000\199\000\200\000\000\000\100\000\ -\000\000\000\000\127\000\000\000\166\000\158\000\000\000\151\000\ -\000\000\161\000\000\000\000\000\000\000\000\000\000\000\120\000\ -\121\000\000\000\074\000\000\000\069\000\000\000\072\000\071\000\ -\047\000\000\000\000\000\050\000\105\000\106\000\000\000\000\000\ -\116\000\117\000\000\000\000\000\000\000\000\000\104\000\000\000\ -\109\000\090\000\091\000\067\000\068\000\144\000\155\000\000\000\ -\000\000\087\000\000\000\000\000\061\000\060\000\035\000\075\000\ -\000\000\001\000\001\000\205\000\148\001\001\000\001\000\055\001\ -\063\001\070\001\000\000\071\001\050\001\051\001\047\001\002\000\ -\000\000\069\001\000\000\000\000\002\000\049\001\086\001\000\000\ -\088\001\000\000\000\000\000\000\092\001\006\000\213\000\000\000\ -\206\000\000\000\144\001\000\000\000\000\000\000\000\000\001\000\ -\116\001\000\000\001\000\001\000\001\000\001\000\120\001\000\000\ -\000\000\125\001\000\000\001\000\001\000\000\000\000\000\129\001\ -\000\000\128\001\000\000\000\000\018\001\021\001\000\000\001\000\ -\000\000\000\000\001\000\000\000\033\001\003\001\004\001\000\000\ -\251\000\000\000\215\000\226\000\000\000\000\000\248\000\000\000\ -\000\000\000\000\059\001\241\000\245\000\242\000\246\000\239\000\ -\243\000\244\000\000\000\000\000\193\000\194\000\163\000\000\000\ -\160\000\138\000\000\000\000\000\136\000\131\000\000\000\000\000\ -\010\000\000\000\000\000\000\000\000\000\093\000\097\000\000\000\ -\000\000\115\000\000\000\088\000\000\000\000\000\141\001\000\000\ -\000\000\000\000\025\001\214\000\000\000\002\000\073\001\210\000\ -\085\001\087\001\097\001\098\001\153\000\001\000\115\001\101\001\ -\000\000\000\000\000\000\000\000\002\000\000\000\108\001\000\000\ -\001\000\000\000\001\000\000\000\000\000\000\000\113\001\119\001\ -\112\001\000\000\000\000\000\000\002\000\001\000\114\001\001\000\ -\132\001\024\001\000\000\000\000\000\000\000\000\007\001\005\001\ -\006\001\000\000\000\000\221\000\250\000\227\000\252\000\254\000\ -\000\000\255\000\003\000\004\000\168\000\164\000\000\000\132\000\ -\130\000\070\000\048\000\000\000\000\000\111\000\000\000\000\000\ -\000\000\000\000\091\001\082\001\081\001\048\001\211\000\000\000\ -\143\001\001\000\142\000\143\000\208\000\000\000\110\001\000\000\ -\111\001\000\000\000\000\001\000\123\001\002\000\000\000\133\001\ -\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\001\001\000\000\009\001\008\001\000\000\031\001\028\001\ -\253\000\000\000\202\000\135\000\137\000\000\000\094\000\000\000\ -\076\000\109\001\000\000\141\000\000\000\000\000\000\000\000\000\ -\000\000\209\000\001\000\001\000\135\001\131\001\030\001\000\000\ -\000\000\000\000\012\001\010\001\014\001\013\001\011\001\015\001\ -\029\001\204\000\049\000\000\000\105\001\000\000\000\000\127\001\ -\122\001\124\001\000\000\137\001\001\000\000\000\000\000\000\000\ -\146\001\000\000\113\000\000\000\121\001\099\001\000\000\036\001\ -\035\001\000\000\000\000\000\000\000\000\139\001\000\000\037\001\ -\000\000\038\001\045\001\044\001\046\001\042\001\040\001\039\001" +\000\000\000\000\000\000\000\000\000\000\218\001\217\001\216\001\ +\219\001\220\001\221\001\000\000\158\001\101\000\128\000\129\000\ +\000\000\170\001\167\001\171\001\211\001\214\001\164\001\169\001\ +\000\000\000\000\000\000\000\000\047\000\048\000\000\000\000\000\ +\076\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\197\001\200\001\193\001\180\001\212\001\ +\195\001\054\000\092\000\190\001\182\001\188\001\203\001\206\001\ +\198\001\204\001\183\001\184\001\185\001\186\001\181\001\213\001\ +\215\001\202\001\205\001\199\001\209\001\201\001\000\000\208\001\ +\162\001\179\001\163\001\174\001\178\001\173\001\172\001\166\001\ +\176\001\168\001\177\001\000\000\000\000\207\001\189\001\210\001\ +\196\001\192\001\194\001\191\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\165\001\000\000\054\002\000\000\000\000\026\000\ +\027\000\000\000\034\000\000\000\055\000\155\001\000\000\187\001\ +\156\001\222\001\223\001\225\001\226\001\227\001\224\001\000\000\ +\001\000\000\000\001\000\000\000\000\000\000\000\000\000\001\000\ +\001\000\001\000\000\000\001\000\000\000\000\000\175\001\055\002\ +\000\000\000\000\000\000\000\000\232\001\000\000\000\000\057\001\ +\000\000\062\001\000\000\000\000\000\000\000\000\000\000\081\001\ +\082\001\095\001\096\001\097\001\098\001\230\001\231\001\229\001\ +\001\000\056\002\000\000\000\000\019\001\000\000\000\000\057\002\ +\000\000\220\000\000\000\223\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\179\000\172\000\ +\173\000\174\000\198\000\175\000\176\000\000\000\000\000\183\000\ +\000\000\199\000\004\000\004\000\004\000\000\000\000\000\000\000\ +\122\000\000\000\159\001\000\000\000\000\000\000\035\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\161\001\000\000\160\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\038\000\039\000\ +\040\000\041\000\042\000\043\000\000\000\044\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\028\000\000\000\102\000\000\000\001\000\000\000\000\000\000\000\ +\157\001\154\001\000\000\000\000\000\000\001\000\001\000\001\000\ +\000\000\228\001\000\000\001\000\000\000\000\000\053\001\000\000\ +\000\000\000\000\001\000\000\000\000\000\108\001\000\000\000\000\ +\000\000\000\000\142\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\002\000\092\001\054\001\050\002\012\002\013\002\031\002\ +\045\002\007\002\008\002\009\002\015\002\016\002\017\002\033\002\ +\023\002\030\002\021\002\018\002\037\002\011\002\006\002\019\002\ +\238\001\020\002\027\002\028\002\005\002\039\002\038\002\248\001\ +\249\001\237\001\246\001\233\001\247\001\235\001\234\001\253\001\ +\254\001\255\001\239\001\014\002\043\002\036\002\042\002\049\002\ +\004\002\048\002\040\002\032\002\046\002\047\002\245\001\236\001\ +\244\001\240\001\029\002\044\002\022\002\252\001\241\001\034\002\ +\010\002\025\002\026\002\041\002\051\002\024\002\035\002\242\001\ +\243\001\251\001\250\001\001\002\000\002\002\002\000\000\003\002\ +\000\000\056\001\080\001\078\001\079\001\077\001\076\001\060\001\ +\000\000\070\001\063\001\064\001\066\001\067\001\068\001\000\000\ +\002\001\001\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\233\000\000\000\000\000\222\000\003\000\180\000\177\000\184\000\ +\000\000\181\000\178\000\185\000\000\000\190\000\000\000\200\000\ +\000\000\000\000\000\000\084\000\000\000\085\000\000\000\149\000\ +\148\000\152\000\151\000\000\000\168\000\000\000\000\000\153\000\ +\000\000\159\000\000\000\000\000\000\000\132\000\125\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\104\000\000\000\000\000\095\000\ +\000\000\000\000\098\000\099\000\000\000\000\000\000\000\000\000\ +\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\019\000\000\000\000\000\000\000\000\000\000\000\000\000\062\000\ +\061\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\088\000\000\000\000\000\036\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\086\001\000\000\000\000\085\001\ +\000\000\000\000\000\000\000\000\000\000\001\000\074\001\000\000\ +\034\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\155\000\002\000\000\000\002\000\001\000\000\000\001\000\000\000\ +\112\001\000\000\000\000\001\000\001\000\001\000\000\000\122\001\ +\000\000\210\000\055\001\053\002\000\000\000\000\000\000\001\000\ +\000\000\000\000\004\001\225\000\001\000\251\000\000\000\000\000\ +\000\000\227\000\000\000\000\000\235\000\000\000\000\000\243\000\ +\236\000\238\000\000\000\000\000\000\000\000\000\000\000\189\000\ +\000\000\191\000\000\000\195\000\201\000\202\000\203\000\000\000\ +\103\000\000\000\000\000\130\000\000\000\169\000\161\000\000\000\ +\154\000\000\000\164\000\000\000\000\000\000\000\000\000\000\000\ +\123\000\124\000\000\000\077\000\072\000\000\000\075\000\074\000\ +\049\000\000\000\000\000\053\000\108\000\109\000\000\000\000\000\ +\119\000\120\000\000\000\000\000\000\000\000\000\107\000\000\000\ +\112\000\093\000\094\000\070\000\071\000\147\000\158\000\000\000\ +\000\000\090\000\000\000\052\000\000\000\064\000\063\000\037\000\ +\078\000\000\000\001\000\001\000\208\000\153\001\001\000\001\000\ +\058\001\065\001\072\001\000\000\073\001\052\001\049\001\002\000\ +\000\000\071\001\000\000\000\000\002\000\051\001\088\001\000\000\ +\090\001\000\000\010\000\000\000\000\000\094\001\006\000\216\000\ +\000\000\209\000\000\000\149\001\000\000\000\000\000\000\000\000\ +\001\000\121\001\000\000\001\000\001\000\001\000\001\000\125\001\ +\000\000\000\000\130\001\000\000\000\000\000\000\000\000\001\000\ +\001\000\000\000\000\000\134\001\000\000\133\001\000\000\000\000\ +\020\001\023\001\000\000\001\000\000\000\000\000\001\000\000\000\ +\035\001\005\001\006\001\000\000\253\000\000\000\218\000\229\000\ +\000\000\000\000\250\000\000\000\000\000\000\000\061\001\244\000\ +\000\000\247\000\245\000\242\000\246\000\000\000\000\000\196\000\ +\197\000\166\000\000\000\163\000\141\000\000\000\000\000\139\000\ +\134\000\000\000\000\000\000\000\000\000\000\000\000\000\096\000\ +\100\000\000\000\000\000\118\000\000\000\091\000\000\000\000\000\ +\146\001\000\000\000\000\000\000\027\001\217\000\000\000\002\000\ +\075\001\213\000\087\001\089\001\100\001\101\001\156\000\001\000\ +\120\001\106\001\000\000\000\000\000\000\000\000\002\000\000\000\ +\113\001\000\000\001\000\000\000\001\000\000\000\000\000\000\000\ +\118\001\124\001\117\001\002\000\103\001\104\001\000\000\000\000\ +\002\000\001\000\119\001\001\000\137\001\026\001\000\000\000\000\ +\000\000\000\000\009\001\007\001\008\001\000\000\000\000\224\000\ +\252\000\230\000\254\000\000\001\000\000\001\001\248\000\003\000\ +\004\000\171\000\167\000\000\000\135\000\133\000\073\000\050\000\ +\000\000\000\000\114\000\000\000\000\000\000\000\000\000\093\001\ +\084\001\083\001\050\001\214\000\000\000\148\001\001\000\145\000\ +\146\000\211\000\000\000\115\001\000\000\116\001\000\000\000\000\ +\001\000\128\001\212\000\000\000\138\001\215\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\003\001\000\000\ +\011\001\010\001\000\000\033\001\030\001\255\000\000\000\205\000\ +\138\000\140\000\000\000\097\000\000\000\079\000\114\001\000\000\ +\144\000\000\000\000\000\000\000\000\000\000\000\001\000\001\000\ +\140\001\136\001\032\001\000\000\000\000\000\000\014\001\012\001\ +\016\001\015\001\013\001\017\001\031\001\207\000\051\000\000\000\ +\110\001\000\000\000\000\132\001\127\001\129\001\000\000\142\001\ +\001\000\000\000\000\000\000\000\151\001\000\000\116\000\000\000\ +\126\001\102\001\000\000\038\001\037\001\000\000\000\000\000\000\ +\000\000\144\001\000\000\039\001\000\000\040\001\047\001\046\001\ +\048\001\044\001\042\001\041\001" let yydgoto = "\005\000\ -\099\000\133\000\158\000\164\000\032\001\049\002\078\002\180\001\ -\032\002\021\003\229\001\158\002\208\001\188\000\101\000\102\000\ -\103\000\104\000\026\001\105\000\248\000\210\000\027\001\106\000\ -\107\000\108\000\189\000\242\002\180\002\109\000\010\002\190\000\ -\234\001\236\000\237\000\120\002\121\002\239\000\122\002\241\000\ -\123\002\124\002\125\002\212\000\213\000\202\001\203\001\204\001\ -\092\002\243\002\244\002\245\002\028\003\029\003\030\003\195\001\ -\192\000\193\000\196\001\035\002\197\001\198\001\236\002\019\002\ -\052\001\043\001\183\002\043\003\026\002\159\002\164\002\107\003\ -\050\001\022\002\160\002\165\000\163\001\064\002\166\000\167\000\ -\168\000\065\002\066\002\067\002\164\001\165\001\166\001\072\002\ -\073\002\074\002\075\002\076\002\228\002\230\002\077\002\233\002\ -\159\000\137\000\222\002\062\002\160\000\158\001\056\002\209\002\ -\053\003\114\003\159\001\057\002\120\003\054\003\188\003\211\002\ -\161\000\020\002\212\002\045\001\110\000\036\001\166\003\167\003\ -\168\003\166\002\139\000\138\001\140\000\169\003\141\000\142\000\ -\147\001\149\001\144\000\150\001\145\000\146\000\147\000\148\000\ -\149\000\150\000\031\002\151\000\152\000\153\000\053\001\061\001\ -\054\001\181\002\041\002\042\002\034\003\192\002\201\002\193\002\ -\194\002\136\003\202\002\049\003\203\002\108\003\111\000\112\000\ -\113\000\114\000\115\000\116\000\117\000\139\001\140\001" +\101\000\136\000\162\000\168\000\039\001\066\002\095\002\193\001\ +\048\002\039\003\241\001\055\001\056\001\192\000\103\000\104\000\ +\105\000\106\000\033\001\107\000\252\000\214\000\034\001\108\000\ +\109\000\110\000\193\000\005\003\197\002\111\000\025\002\194\000\ +\246\001\240\000\241\000\136\002\137\002\243\000\138\002\245\000\ +\139\002\140\002\141\002\216\000\217\000\215\001\216\001\217\001\ +\109\002\006\003\007\003\008\003\046\003\047\003\048\003\208\001\ +\196\000\197\000\209\001\050\002\210\001\211\001\255\002\034\002\ +\061\001\050\001\200\002\214\002\041\002\175\002\180\002\128\003\ +\059\001\037\002\176\002\169\000\176\001\081\002\170\000\171\000\ +\172\000\082\002\083\002\084\002\177\001\178\001\179\001\089\002\ +\090\002\091\002\092\002\093\002\248\002\094\002\163\000\250\002\ +\242\002\079\002\164\000\171\001\073\002\229\002\073\003\135\003\ +\172\001\074\002\141\003\074\003\208\003\231\002\165\000\035\002\ +\232\002\052\001\112\000\043\001\186\003\187\003\188\003\182\002\ +\142\000\151\001\143\000\144\000\189\003\145\000\160\001\162\001\ +\147\000\163\001\148\000\149\000\150\000\151\000\152\000\153\000\ +\047\002\154\000\155\000\156\000\157\000\062\001\073\001\063\001\ +\198\002\056\002\057\002\052\003\209\002\221\002\210\002\211\002\ +\157\003\222\002\069\003\223\002\129\003\113\000\114\000\115\000\ +\116\000\117\000\118\000\119\000\152\001\153\001" -let yysindex = "\062\002\ -\061\025\062\030\003\255\057\002\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\195\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\001\016\001\016\062\029\076\255\000\000\000\000\093\255\098\255\ -\000\000\203\255\035\000\062\000\085\000\098\000\102\000\250\029\ -\250\029\250\029\250\029\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\049\024\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\111\000\126\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\250\029\143\000\001\016\012\000\161\000\ -\167\000\000\000\000\000\025\000\183\255\000\000\000\000\143\008\ -\000\000\015\000\000\000\000\000\061\255\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\066\000\000\000\097\028\ -\000\000\226\030\064\000\122\000\061\025\000\000\000\000\000\000\ -\097\028\000\000\118\000\000\000\000\000\137\000\000\000\073\004\ -\186\001\000\000\037\023\206\001\000\000\167\001\000\000\005\255\ -\005\255\005\255\005\255\005\255\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\228\001\113\000\ -\000\000\223\000\097\028\000\000\242\000\000\000\057\002\000\000\ -\251\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\120\000\177\000\000\000\062\255\000\000\000\000\000\000\ -\000\000\000\000\096\255\253\000\015\001\026\001\121\255\001\016\ -\202\000\251\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\120\000\177\000\000\000\062\255\000\000\000\000\000\000\ -\000\000\229\000\157\000\017\001\000\000\245\000\000\000\250\029\ -\143\000\080\255\000\000\061\025\061\025\061\025\061\025\061\025\ -\061\025\061\025\061\025\061\025\080\255\080\255\080\255\080\255\ -\137\000\061\025\014\006\232\000\234\000\036\001\046\001\045\001\ -\058\001\061\025\061\025\080\255\073\026\027\001\000\000\065\001\ -\000\000\061\025\001\016\061\025\061\025\061\025\061\025\061\025\ -\061\025\000\000\061\025\061\025\061\025\061\025\137\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\137\000\000\000\250\029\ -\250\029\250\029\250\029\250\029\061\025\250\029\212\028\250\029\ -\250\029\000\000\159\029\000\000\061\025\000\000\097\028\061\025\ -\030\001\000\000\000\000\070\001\096\001\038\001\000\000\000\000\ -\000\000\097\028\000\000\047\001\000\000\097\028\097\028\004\006\ -\110\001\000\000\110\001\058\255\000\000\124\001\124\001\025\001\ -\121\001\097\028\111\001\068\001\107\001\000\000\000\000\000\000\ +let yysindex = "\152\002\ +\193\026\243\031\003\255\122\005\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\075\027\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\001\018\001\018\219\030\101\255\000\000\000\000\125\255\194\255\ +\000\000\201\255\213\255\013\000\015\000\020\000\027\000\167\031\ +\167\031\167\031\167\031\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\173\025\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\058\000\103\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\167\031\121\000\001\018\213\000\ +\126\000\160\000\000\000\176\000\000\000\120\000\091\255\000\000\ +\000\000\075\007\000\000\233\255\000\000\000\000\059\255\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\255\ +\000\000\252\029\000\000\154\032\046\000\119\000\193\026\000\000\ +\000\000\000\000\252\029\000\000\210\003\137\000\000\000\000\000\ +\245\000\000\000\030\003\211\001\000\000\153\024\231\001\000\000\ +\204\000\000\000\104\000\104\000\104\000\104\000\104\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\234\001\117\000\000\000\232\000\252\029\000\000\ +\252\000\000\000\122\005\000\000\240\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\064\255\137\255\000\000\ +\047\255\000\000\000\000\000\000\000\000\000\000\054\255\239\000\ +\249\000\000\001\185\255\001\018\092\000\240\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\064\255\137\255\000\000\ +\047\255\000\000\000\000\000\000\000\000\200\000\215\255\241\000\ +\000\000\233\000\000\000\167\031\121\000\100\255\000\000\193\026\ +\193\026\193\026\193\026\193\026\193\026\193\026\193\026\193\026\ +\100\255\100\255\100\255\100\255\245\000\193\026\184\021\227\000\ +\231\000\020\001\042\001\045\001\050\001\193\026\193\026\100\255\ +\213\027\015\001\000\000\061\001\000\000\193\026\001\018\193\026\ +\193\026\193\026\193\026\193\026\193\026\193\026\000\000\193\026\ +\193\026\193\026\193\026\193\026\193\026\245\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\245\000\000\000\167\031\167\031\ +\167\031\167\031\167\031\193\026\167\031\112\030\167\031\167\031\ +\000\000\070\031\000\000\193\026\000\000\252\029\193\026\027\001\ +\000\000\000\000\071\001\089\001\034\001\000\000\000\000\000\000\ +\252\029\000\000\044\001\000\000\252\029\252\029\000\000\226\007\ +\168\000\107\001\000\000\107\001\043\255\000\000\105\001\105\001\ +\021\001\104\001\000\000\024\001\041\001\252\029\097\001\057\001\ +\109\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -750,82 +764,84 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\143\002\000\000\037\023\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\097\028\000\000\000\000\000\000\000\000\ -\000\000\000\000\075\001\000\000\000\000\080\001\074\001\091\255\ -\116\001\097\028\152\001\000\000\242\000\197\000\000\000\000\000\ -\000\000\000\000\000\000\040\255\000\000\000\000\000\000\042\255\ -\000\000\133\001\000\000\110\001\110\001\110\001\000\000\061\025\ -\000\000\250\029\000\000\000\000\000\000\000\000\202\000\000\000\ -\208\000\246\000\000\000\121\255\000\000\059\255\061\025\157\000\ -\000\000\000\000\194\255\171\000\024\029\061\025\144\001\144\005\ -\002\001\185\007\158\001\062\003\168\003\124\009\236\009\178\003\ -\000\000\248\004\097\001\000\000\073\026\016\000\000\000\000\000\ -\061\025\141\001\061\025\099\001\151\001\000\000\154\001\012\004\ -\155\001\202\000\061\025\061\025\148\006\106\001\163\255\163\255\ -\148\255\016\255\173\003\000\000\113\001\125\255\117\255\087\008\ -\000\000\000\000\134\000\134\000\080\255\080\255\080\255\225\007\ -\112\001\080\255\080\255\000\000\123\004\123\004\000\000\143\008\ -\161\001\083\001\156\001\174\001\087\008\000\000\097\028\089\002\ -\000\000\119\001\131\001\129\001\183\024\130\001\000\000\000\000\ -\183\024\000\000\132\001\135\001\097\028\097\028\137\001\001\016\ -\000\000\000\000\000\000\124\001\000\000\000\000\097\028\000\000\ -\242\255\000\000\108\001\037\002\000\000\181\001\000\000\086\001\ -\000\000\000\000\000\000\196\001\003\255\143\001\000\000\177\030\ -\236\255\000\000\000\000\000\000\000\000\205\001\097\028\223\002\ -\000\000\152\001\057\002\000\000\097\028\219\027\000\000\000\000\ -\000\000\035\001\035\001\197\000\003\255\001\016\000\000\203\001\ -\000\000\204\001\000\000\000\000\000\000\000\000\087\008\000\000\ -\080\255\217\001\000\000\168\001\000\000\000\000\059\255\000\000\ -\001\016\000\000\087\008\222\001\001\016\208\000\194\255\000\000\ -\000\000\087\008\000\000\061\025\000\000\097\028\000\000\000\000\ -\000\000\061\025\061\025\000\000\000\000\000\000\014\255\142\001\ -\000\000\000\000\216\001\220\001\016\000\087\008\000\000\087\008\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\087\008\ -\166\009\000\000\226\001\061\025\000\000\000\000\000\000\000\000\ -\244\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\097\028\000\000\000\000\000\000\000\000\000\000\ -\169\001\000\000\061\025\179\001\000\000\000\000\000\000\188\001\ -\000\000\189\001\160\000\160\000\000\000\000\000\000\000\061\000\ -\000\000\234\001\000\000\231\001\170\001\050\010\254\001\000\000\ -\000\000\171\001\000\000\000\000\000\000\000\000\000\000\175\001\ -\037\002\000\000\202\001\000\000\000\000\050\010\011\002\000\000\ -\211\001\000\000\160\001\005\255\000\000\000\000\219\001\000\000\ -\172\001\234\255\000\000\236\001\000\000\000\000\000\000\238\001\ -\000\000\022\002\000\000\000\000\242\000\039\002\000\000\040\002\ -\054\002\051\002\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\033\002\041\002\000\000\000\000\000\000\005\002\ -\000\000\000\000\060\002\056\002\000\000\000\000\061\002\019\002\ -\000\000\071\002\156\006\060\011\061\025\000\000\000\000\016\000\ -\207\026\000\000\061\025\000\000\087\008\061\025\000\000\015\002\ -\020\002\021\002\000\000\000\000\183\024\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\097\028\064\002\157\000\157\000\000\000\067\002\000\000\025\002\ -\000\000\003\002\000\000\124\001\086\002\038\002\000\000\000\000\ -\000\000\050\010\094\002\160\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\048\002\097\028\140\000\158\255\000\000\000\000\ -\000\000\049\002\177\030\000\000\000\000\000\000\000\000\000\000\ -\096\002\000\000\000\000\000\000\000\000\000\000\243\014\000\000\ -\000\000\000\000\000\000\061\025\003\010\000\000\171\023\087\008\ -\087\008\100\002\000\000\000\000\000\000\000\000\000\000\052\002\ -\000\000\000\000\000\000\000\000\000\000\050\010\000\000\124\002\ -\000\000\124\001\156\255\000\000\000\000\000\000\106\002\000\000\ -\000\000\001\016\109\002\130\002\160\001\177\030\128\002\029\002\ -\030\002\000\000\050\002\000\000\000\000\177\030\000\000\000\000\ -\000\000\001\016\000\000\000\000\000\000\026\007\000\000\016\000\ -\000\000\000\000\126\002\000\000\061\025\165\255\183\024\084\002\ -\085\002\000\000\000\000\000\000\000\000\000\000\000\000\044\002\ -\097\028\097\028\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\065\002\000\000\134\010\087\002\000\000\ -\000\000\000\000\093\002\000\000\000\000\172\001\003\255\098\002\ -\000\000\101\002\000\000\171\001\000\000\000\000\102\002\000\000\ -\000\000\177\030\155\002\140\000\140\000\000\000\044\002\000\000\ -\047\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" +\000\000\000\000\000\000\000\000\000\000\000\000\145\002\000\000\ +\153\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\252\029\000\000\000\000\000\000\000\000\000\000\000\000\075\001\ +\000\000\000\000\082\001\084\001\151\255\123\001\252\029\163\001\ +\000\000\252\000\082\002\000\000\000\000\000\000\000\000\000\000\ +\094\255\000\000\000\000\000\000\096\255\000\000\143\001\000\000\ +\107\001\107\001\107\001\000\000\193\026\000\000\167\031\000\000\ +\000\000\000\000\000\000\092\000\000\000\255\000\132\000\000\000\ +\185\255\000\000\061\255\193\026\215\255\000\000\000\000\010\000\ +\026\000\088\021\193\026\153\001\097\003\024\014\104\003\201\003\ +\217\008\162\014\001\015\199\009\000\000\090\012\108\001\000\000\ +\213\027\093\000\000\000\000\000\193\026\150\001\193\026\112\001\ +\161\001\000\000\165\001\178\010\169\001\092\000\193\026\193\026\ +\084\012\117\001\205\012\085\004\085\004\175\000\111\001\049\255\ +\000\000\123\255\123\255\126\001\083\001\023\255\018\020\000\000\ +\000\000\118\001\118\001\100\255\100\255\100\255\021\019\124\001\ +\100\255\100\255\000\000\069\001\069\001\000\000\075\007\178\001\ +\094\001\164\001\180\001\018\020\000\000\252\029\235\000\000\000\ +\139\001\144\001\145\001\055\026\156\001\000\000\000\000\055\026\ +\000\000\157\001\159\001\193\026\252\029\252\029\167\001\001\018\ +\000\000\000\000\105\001\000\000\000\000\252\029\000\000\045\255\ +\000\000\119\001\069\002\000\000\000\000\000\000\232\001\000\000\ +\113\001\000\000\000\000\000\000\227\001\003\255\174\001\000\000\ +\097\032\032\000\000\000\000\000\000\000\000\000\233\001\252\029\ +\247\002\000\000\163\001\122\005\000\000\252\029\115\029\000\000\ +\000\000\000\000\053\002\053\002\082\002\003\255\001\018\000\000\ +\229\001\000\000\230\001\000\000\000\000\000\000\000\000\018\020\ +\000\000\100\255\237\001\000\000\189\001\000\000\000\000\061\255\ +\000\000\001\018\000\000\018\020\241\001\001\018\255\000\010\000\ +\000\000\000\000\018\020\000\000\000\000\252\029\000\000\000\000\ +\000\000\193\026\193\026\000\000\000\000\000\000\114\255\166\001\ +\000\000\000\000\239\001\235\001\093\000\018\020\000\000\018\020\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\020\ +\222\004\000\000\249\001\000\000\193\026\000\000\000\000\000\000\ +\000\000\005\002\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\252\029\000\000\000\000\000\000\000\000\ +\192\001\000\000\193\026\204\001\000\000\000\000\000\000\205\001\ +\000\000\207\001\000\000\168\000\168\000\000\000\000\000\000\000\ +\218\255\000\000\253\001\000\000\250\001\184\001\210\003\020\002\ +\000\000\000\000\190\001\000\000\000\000\000\000\000\000\000\000\ +\195\001\069\002\000\000\223\001\210\003\198\001\200\001\000\000\ +\000\000\210\003\031\002\000\000\236\001\000\000\175\001\104\000\ +\000\000\000\000\242\001\000\000\186\001\181\255\000\000\251\001\ +\000\000\000\000\000\000\252\001\000\000\029\002\000\000\000\000\ +\252\000\032\002\000\000\034\002\046\002\055\002\000\000\000\000\ +\003\255\000\000\000\000\000\000\000\000\039\002\062\002\000\000\ +\000\000\000\000\011\002\000\000\000\000\068\002\042\002\000\000\ +\000\000\070\002\027\002\071\002\070\013\185\017\193\026\000\000\ +\000\000\093\000\095\028\000\000\193\026\000\000\018\020\193\026\ +\000\000\021\002\033\002\035\002\000\000\000\000\055\026\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\252\029\065\002\215\255\215\255\000\000\079\002\ +\000\000\041\002\000\000\006\002\000\000\105\001\098\002\043\002\ +\000\000\000\000\000\000\000\000\000\000\000\000\103\002\175\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\045\002\252\029\ +\170\000\098\255\000\000\000\000\000\000\049\002\097\032\000\000\ +\000\000\000\000\000\000\000\000\102\002\000\000\000\000\000\000\ +\000\000\000\000\000\000\073\015\000\000\000\000\000\000\000\000\ +\193\026\136\019\000\000\035\025\018\020\018\020\110\002\000\000\ +\000\000\000\000\000\000\000\000\054\002\000\000\000\000\000\000\ +\000\000\000\000\210\003\000\000\111\002\000\000\105\001\149\255\ +\000\000\000\000\000\000\101\002\000\000\000\000\001\018\108\002\ +\129\002\175\001\097\032\127\002\026\002\030\002\000\000\100\004\ +\000\000\000\000\097\032\000\000\000\000\000\000\001\018\000\000\ +\000\000\000\000\165\013\000\000\093\000\000\000\000\000\121\002\ +\000\000\193\026\169\255\055\026\078\002\080\002\000\000\000\000\ +\000\000\000\000\000\000\036\002\252\029\252\029\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\058\002\ +\000\000\103\005\081\002\000\000\000\000\000\000\087\002\000\000\ +\000\000\186\001\003\255\094\002\000\000\095\002\000\000\190\001\ +\000\000\000\000\096\002\000\000\000\000\097\032\050\002\170\000\ +\170\000\000\000\036\002\000\000\248\255\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000" let yyrindex = "\000\000\ -\000\000\004\001\123\011\043\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\233\011\000\000\000\000\000\000\000\000\ -\148\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\032\001\187\011\028\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\044\012\000\000\000\000\000\000\000\000\ +\131\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -834,964 +850,1015 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\159\002\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\237\001\ -\000\000\191\013\000\000\000\000\047\014\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\155\002\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\004\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\171\002\000\000\000\000\000\000\179\002\058\004\ -\000\000\000\000\000\000\000\000\000\000\250\000\000\000\240\001\ -\240\001\240\001\240\001\240\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\137\005\ -\000\000\000\000\000\000\000\000\036\000\000\000\055\000\000\000\ -\056\255\090\255\154\255\082\001\027\002\035\002\095\015\176\003\ -\224\003\043\003\057\004\191\004\069\005\199\005\189\255\200\255\ -\075\000\201\015\048\003\000\000\000\000\000\000\211\000\000\000\ -\056\003\079\013\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\095\012\000\000\217\012\000\000\000\000\000\000\ -\000\000\000\000\000\000\091\000\000\000\000\000\000\000\000\000\ -\000\000\123\015\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\202\015\058\016\166\016\022\017\ -\000\000\148\002\000\000\000\000\000\000\000\000\228\002\000\000\ -\229\002\063\003\063\003\101\017\000\000\000\000\000\000\000\000\ +\000\000\086\022\000\000\010\014\000\000\000\000\125\014\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\032\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\165\002\000\000\000\000\ +\000\000\200\002\177\003\000\000\000\000\000\000\000\000\000\000\ +\200\005\000\000\205\015\205\015\205\015\205\015\205\015\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\166\005\000\000\000\000\000\000\000\000\ +\044\000\000\000\035\000\000\000\099\255\150\000\047\002\149\003\ +\242\003\077\004\165\016\214\004\095\005\163\002\250\006\012\008\ +\139\008\235\008\116\000\171\000\217\000\024\017\160\002\000\000\ +\000\000\000\000\122\000\000\000\168\002\151\013\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\165\012\000\000\ +\030\013\000\000\000\000\000\000\000\000\000\000\000\000\182\255\ +\000\000\000\000\000\000\000\000\000\000\217\015\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\148\002\000\000\000\000\000\000\ +\079\016\194\016\053\017\171\017\000\000\131\002\000\000\000\000\ +\000\000\000\000\085\002\000\000\088\002\176\002\176\002\030\018\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\164\255\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\ -\138\016\000\000\000\000\209\255\000\000\086\000\000\000\000\000\ -\000\000\000\000\194\000\042\003\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\131\002\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\133\255\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\255\ +\118\002\116\018\000\000\000\000\214\000\000\000\071\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\114\000\156\002\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\078\004\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\149\006\015\006\000\000\ -\000\000\000\000\079\004\000\000\049\000\058\000\000\000\000\000\ -\000\000\000\000\000\000\145\007\000\000\000\000\000\000\007\008\ -\000\000\125\008\000\000\000\000\000\000\000\000\000\000\233\255\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\016\003\046\011\000\000\073\003\000\000\222\009\000\000\000\000\ -\000\000\000\000\078\255\000\000\000\000\000\000\000\000\103\255\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\048\003\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\015\015\000\000\000\000\000\000\000\000\138\019\250\019\ -\192\021\229\021\000\000\000\000\121\021\094\001\087\000\174\000\ -\000\000\000\000\076\020\150\020\209\017\065\018\177\018\048\003\ -\000\000\000\019\108\019\000\000\224\020\042\021\000\000\237\001\ -\000\000\000\000\064\255\000\000\142\255\000\000\000\000\125\004\ -\000\000\000\000\015\003\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\085\027\085\027\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\086\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\246\002\000\000\000\000\000\000\189\012\ -\000\000\000\000\000\000\000\000\059\003\000\000\000\000\106\003\ -\027\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\089\004\060\000\000\000\074\003\000\000\000\000\000\000\ -\000\000\101\000\159\000\104\000\125\004\000\000\000\000\248\008\ -\000\000\110\009\000\000\000\000\000\000\000\000\004\000\000\000\ -\220\019\000\000\000\000\000\000\000\000\000\000\078\010\000\000\ -\078\003\000\000\139\001\000\000\078\003\016\003\085\255\000\000\ -\000\000\010\022\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\250\002\000\000\058\003\032\255\000\000\034\255\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\033\022\ +\193\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\184\006\047\006\000\000\000\000\000\000\194\003\ +\000\000\048\000\039\000\000\000\000\000\000\000\000\000\000\000\ +\180\007\000\000\000\000\000\000\050\008\000\000\177\008\000\000\ +\000\000\000\000\000\000\000\000\134\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\136\002\117\011\000\000\ +\182\002\000\000\022\010\000\000\000\000\000\000\000\000\063\255\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\160\002\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\102\015\000\000\000\000\ +\000\000\000\000\000\000\041\000\199\000\072\023\129\001\000\000\ +\000\000\185\022\226\022\081\000\113\023\031\023\056\002\000\000\ +\000\000\228\001\033\021\145\018\007\019\122\019\160\002\000\000\ +\237\019\099\020\000\000\148\021\007\022\000\000\086\022\000\000\ +\000\000\044\255\000\000\096\000\000\000\000\000\148\004\000\000\ +\000\000\222\002\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\233\028\233\028\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\071\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\225\002\000\000\000\000\000\000\000\000\000\000\ +\121\007\000\000\000\000\000\000\000\000\082\003\000\000\000\000\ +\251\013\065\007\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\068\004\050\000\000\000\075\003\000\000\000\000\ +\000\000\000\000\061\000\101\000\054\000\148\004\000\000\000\000\ +\042\009\000\000\163\009\000\000\000\000\000\000\000\000\154\000\ +\000\000\214\020\000\000\000\000\000\000\000\000\000\000\137\010\ +\000\000\079\003\000\000\247\015\000\000\079\003\136\002\152\255\ +\000\000\000\000\083\017\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\251\002\000\000\059\003\035\255\000\000\071\255\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\175\018\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\243\014\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\026\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\118\002\118\002\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\001\003\000\000\000\000\000\000\ +\000\000\000\000\002\003\000\000\000\000\000\000\000\000\000\000\ +\000\000\225\002\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\119\255\000\000\000\000\000\000\029\003\000\000\ +\000\000\000\000\000\000\000\000\019\001\228\014\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\086\003\000\000\000\000\000\000\ +\148\004\000\000\000\000\000\000\000\000\081\003\000\000\000\000\ +\000\000\000\000\002\011\000\000\000\000\000\000\090\003\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\159\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\011\020\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\022\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\003\000\003\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\253\002\000\000\000\000\000\000\000\000\ -\000\000\254\002\000\000\000\000\000\000\000\000\000\000\000\000\ -\246\002\000\000\000\000\000\000\000\000\000\000\150\255\000\000\ -\000\000\000\000\025\003\000\000\000\000\000\000\000\000\000\000\ -\051\012\075\007\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\082\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\071\003\000\000\000\000\000\000\000\000\190\010\ -\000\000\000\000\000\000\091\003\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\248\000\000\000\000\000\000\000\098\003\ +\000\000\000\000\000\000\000\000\000\000\210\255\000\000\156\002\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\029\003\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\063\022\000\000\000\000\000\000\ +\067\016\081\006\000\000\000\000\000\000\000\000\031\024\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\099\000\000\000\000\000\000\000\092\003\000\000\000\000\ -\000\000\000\000\000\000\082\255\000\000\042\003\000\000\000\000\ -\000\000\000\000\000\000\025\003\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\194\013\061\013\000\000\000\000\ -\000\000\000\000\172\022\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\118\255\161\023\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\074\255\ -\100\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\210\255\040\003\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100\003\ +\000\000\029\003\031\024\000\000\000\000\000\000\000\000\156\017\ +\000\000\000\000\031\024\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\082\255\034\003\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\102\003\000\000\025\003\172\022\000\000\000\000\ -\000\000\000\000\145\014\000\000\000\000\172\022\000\000\000\000\ +\000\000\000\000\040\003\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\011\004\042\003\042\003\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\034\003\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\246\003\ -\044\003\044\003\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\230\008\125\004\000\000\ -\000\000\000\000\000\000\254\002\000\000\000\000\000\000\000\000\ -\000\000\248\007\003\005\135\022\135\022\000\000\246\003\000\000\ -\176\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000" +\000\000\243\010\148\004\000\000\000\000\000\000\000\000\002\003\ +\000\000\000\000\000\000\000\000\000\000\007\010\029\005\187\023\ +\187\023\000\000\011\004\000\000\027\009\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000" let yygindex = "\000\000\ -\000\000\000\000\000\000\000\000\254\255\022\254\050\001\086\255\ -\000\000\000\000\132\003\046\255\006\000\192\002\206\255\000\000\ -\094\003\053\000\115\002\099\004\000\000\252\255\000\000\222\003\ -\110\254\174\255\153\000\017\255\023\002\192\255\252\253\000\000\ -\243\255\160\002\162\002\061\253\187\255\000\000\190\255\000\000\ -\000\000\006\002\000\000\000\000\183\002\102\254\189\002\105\255\ -\036\002\055\002\000\000\069\001\090\003\048\001\115\001\163\002\ -\094\255\000\000\044\255\000\000\103\254\220\002\051\001\153\255\ -\134\255\018\000\000\000\000\000\000\000\002\254\000\000\122\002\ -\241\001\230\001\000\000\129\002\000\000\000\000\028\004\134\254\ -\048\000\135\002\000\000\000\000\128\254\000\000\000\000\000\000\ -\127\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\050\254\212\255\000\000\050\255\224\253\000\000\000\000\023\253\ -\039\001\145\254\000\000\000\000\228\253\044\001\162\001\089\001\ -\053\001\168\002\105\004\228\004\230\253\180\001\000\000\059\001\ -\095\001\222\002\000\000\104\003\109\004\160\255\000\000\000\000\ -\000\000\009\000\000\000\239\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\181\255\000\000\004\254\000\000\133\255\000\000\ -\145\255\221\001\246\253\200\003\084\001\069\002\000\000\000\000\ -\000\000\123\001\000\000\064\253\112\253\118\001\000\000\255\255\ -\000\000\005\005\000\000\001\000\000\000\000\000\000\000" +\000\000\000\000\000\000\000\000\254\255\012\254\028\001\074\255\ +\000\000\000\000\124\003\046\255\003\000\178\002\022\000\000\000\ +\091\003\057\000\097\002\101\004\000\000\246\255\000\000\217\003\ +\102\254\176\255\227\255\030\255\003\002\179\255\245\253\000\000\ +\252\255\149\002\148\002\045\253\187\255\000\000\190\255\000\000\ +\000\000\248\001\000\000\000\000\172\002\081\254\179\002\105\255\ +\022\002\037\002\000\000\047\001\168\255\036\001\197\001\159\002\ +\095\255\000\000\155\254\000\000\096\254\212\002\037\001\150\255\ +\131\255\009\000\000\000\247\253\000\000\248\253\000\000\114\002\ +\246\001\209\001\000\000\112\002\000\000\000\000\024\004\126\254\ +\063\000\122\002\000\000\000\000\111\254\000\000\000\000\000\000\ +\104\002\000\000\000\000\000\000\115\002\230\255\027\254\204\004\ +\000\000\022\254\215\253\000\000\000\000\000\253\023\001\133\254\ +\000\000\000\000\210\253\025\001\137\001\079\001\029\001\153\002\ +\102\004\236\004\063\254\171\001\000\000\043\001\078\001\153\255\ +\000\000\092\003\108\004\000\000\160\255\000\000\000\000\006\000\ +\000\000\072\002\000\000\000\000\000\000\000\000\000\000\000\000\ +\161\255\000\000\000\000\000\254\000\000\140\255\000\000\136\255\ +\208\001\230\253\184\003\058\001\052\002\000\000\000\000\000\000\ +\098\001\000\000\013\253\114\253\092\001\000\000\255\255\000\000\ +\254\004\000\000\001\000\000\000\000\000\000\000" -let yytablesize = 8296 -let yytable = "\134\000\ -\154\000\238\000\156\000\191\000\240\000\233\001\100\000\060\001\ -\059\001\207\001\143\000\211\000\211\000\181\001\182\001\033\001\ -\055\001\038\001\057\001\135\000\205\002\214\000\187\000\037\001\ -\002\001\176\002\165\002\210\002\189\001\213\002\249\000\230\001\ -\230\001\178\002\148\002\229\000\068\002\181\001\182\001\004\002\ -\094\002\194\001\216\000\071\002\098\002\100\002\091\002\191\002\ -\231\000\136\000\105\002\062\001\044\003\155\001\218\000\254\000\ -\175\002\234\000\177\002\228\000\078\003\079\002\201\000\081\002\ -\102\000\152\002\107\000\201\000\201\000\035\001\097\002\153\001\ -\029\001\148\001\009\002\001\001\235\000\157\000\056\001\218\000\ -\211\000\119\003\122\000\177\001\038\002\253\002\020\000\220\000\ -\137\001\246\000\123\000\140\001\229\000\230\000\231\000\232\000\ -\176\000\124\000\007\001\028\001\236\000\176\000\176\000\238\000\ -\221\000\166\001\112\000\104\003\183\001\222\000\123\000\254\002\ -\161\001\014\001\201\000\009\000\106\001\124\000\201\000\134\000\ -\154\000\193\001\156\000\049\001\051\001\051\001\234\002\051\001\ -\051\001\102\000\048\001\107\000\143\003\252\000\253\000\254\000\ -\255\000\003\001\004\001\005\001\153\003\007\003\021\001\201\000\ -\244\000\080\002\201\001\082\002\176\000\123\000\217\001\000\001\ -\176\000\106\001\039\002\001\001\124\000\030\001\237\000\109\003\ -\169\000\140\001\059\002\011\002\254\000\169\000\169\000\178\001\ -\179\001\205\001\106\001\112\000\142\003\023\000\009\000\123\000\ -\001\001\176\000\190\001\147\001\249\001\012\003\124\000\136\000\ -\001\001\009\000\016\003\250\001\156\003\201\000\184\002\018\002\ -\022\001\023\001\036\002\004\000\191\002\241\002\006\001\022\003\ -\184\003\253\000\254\000\255\000\171\001\101\002\004\000\001\001\ -\187\001\071\002\002\000\091\002\169\000\002\000\223\000\163\001\ -\169\000\003\001\004\001\005\001\100\001\134\001\001\001\176\000\ -\100\001\116\003\209\001\210\001\211\001\212\001\213\001\214\001\ -\215\001\216\001\090\002\147\001\012\002\238\001\003\001\218\001\ -\033\002\169\000\037\002\100\001\135\003\012\000\003\001\023\002\ -\005\001\057\001\232\001\027\002\028\002\135\003\188\001\237\001\ -\102\002\239\001\240\001\241\001\242\001\243\001\244\001\046\002\ -\245\001\246\001\247\001\248\001\218\000\003\001\086\003\005\001\ -\013\000\134\001\215\000\247\000\184\002\135\002\117\003\028\001\ -\100\001\099\003\000\002\051\001\003\001\004\001\005\001\169\000\ -\213\002\096\002\233\000\087\003\229\000\013\002\021\002\194\001\ -\012\000\100\001\025\002\216\000\216\000\055\003\224\000\051\001\ -\174\002\231\000\093\003\052\002\056\003\054\002\214\002\218\000\ -\218\000\185\002\234\000\234\000\228\000\216\000\252\000\253\000\ -\254\000\255\000\105\003\013\000\251\001\252\001\253\001\254\001\ -\255\001\225\000\002\002\003\002\005\002\006\002\234\000\008\002\ -\000\001\004\000\194\001\213\002\001\001\131\003\069\003\134\003\ -\213\002\137\001\172\001\213\002\062\003\018\000\235\002\022\003\ -\226\000\035\001\057\003\020\000\215\002\236\000\236\000\020\000\ -\238\000\238\000\020\000\001\000\001\000\227\000\104\001\061\002\ -\218\002\228\000\104\001\084\002\085\002\086\002\223\002\020\000\ -\106\001\191\003\242\000\138\003\020\000\020\000\020\000\020\000\ -\091\003\092\003\219\001\031\001\023\003\104\001\178\003\201\001\ -\160\003\243\000\028\000\201\001\201\001\169\001\020\000\034\001\ -\013\000\046\001\003\001\004\001\005\001\185\003\020\000\213\002\ -\007\001\249\002\245\000\020\000\238\000\106\001\020\000\237\000\ -\237\000\240\000\118\000\215\000\192\003\001\000\001\000\014\001\ -\200\001\020\000\104\001\011\002\250\000\001\002\149\002\020\000\ -\020\000\215\000\251\000\168\002\170\002\199\002\200\001\058\001\ -\020\000\064\001\023\000\104\001\118\000\087\002\023\000\211\000\ -\018\001\023\000\019\001\020\001\021\001\195\002\173\001\069\002\ -\162\000\070\002\163\000\047\001\099\002\141\001\023\000\211\000\ -\014\003\020\000\020\000\106\002\216\002\191\001\045\003\192\001\ -\119\002\015\000\016\000\020\000\035\001\170\001\147\000\147\000\ -\171\001\172\001\247\001\156\001\100\001\093\002\126\002\014\000\ -\128\002\157\001\171\002\172\002\031\000\023\000\089\002\067\001\ -\136\002\137\002\023\000\162\001\179\002\023\000\022\001\023\001\ -\029\002\030\002\057\001\057\001\057\001\057\001\057\001\057\001\ -\023\000\191\001\112\003\113\003\192\001\118\000\023\000\023\000\ -\193\001\100\001\001\000\001\000\061\002\147\000\109\002\023\000\ -\184\001\147\000\061\002\226\002\163\002\168\001\174\001\011\002\ -\153\002\175\001\176\001\185\001\125\000\229\002\231\002\126\000\ -\127\000\128\000\129\000\051\001\130\000\182\002\186\001\252\000\ -\253\000\254\000\255\000\008\003\199\001\198\002\009\003\010\003\ -\093\002\205\001\023\000\082\003\193\001\134\000\154\000\131\000\ -\156\000\000\001\057\001\179\002\206\001\001\001\001\000\002\000\ -\003\000\004\000\038\003\059\001\187\003\189\003\225\001\134\000\ -\134\000\223\001\199\002\224\001\036\003\037\003\226\001\227\001\ -\032\003\057\001\143\000\143\000\057\001\057\001\057\001\057\001\ -\170\000\057\001\228\001\227\002\227\002\170\000\170\000\019\003\ -\020\003\208\001\235\001\236\001\119\000\014\002\015\002\120\000\ -\011\003\121\000\018\000\058\003\057\001\017\002\018\000\016\002\ -\122\000\018\000\123\000\124\000\215\000\033\002\024\002\251\002\ -\252\002\044\002\045\003\003\001\004\001\005\001\018\000\151\001\ -\152\001\153\001\154\001\018\000\018\000\037\002\018\000\040\002\ -\045\002\038\002\235\002\047\002\170\000\048\002\050\002\051\001\ -\170\000\005\003\053\002\055\002\058\002\018\000\060\002\028\000\ -\063\002\123\003\083\002\028\000\107\002\018\000\028\000\233\000\ -\118\002\234\000\018\000\130\002\139\002\018\000\131\002\133\002\ -\027\003\170\000\111\002\028\000\001\001\144\002\088\003\142\002\ -\018\000\096\003\059\001\098\003\145\002\199\002\018\000\018\000\ -\049\001\051\001\051\001\051\001\146\002\147\002\154\002\018\000\ -\196\002\042\003\051\001\252\000\253\000\254\000\255\000\155\002\ -\156\002\162\002\028\000\167\002\186\002\021\002\169\002\028\000\ -\173\002\197\002\028\000\204\002\153\002\000\001\206\002\170\000\ -\018\000\001\001\201\001\201\001\217\002\028\000\219\002\011\002\ -\237\002\238\002\018\000\028\000\028\000\239\002\179\002\240\002\ -\142\001\033\002\246\002\143\001\028\000\144\001\004\003\255\002\ -\067\001\067\001\067\001\067\001\067\001\067\001\145\001\146\001\ -\000\003\031\000\015\003\013\003\137\003\031\000\001\003\006\003\ -\031\000\035\001\077\003\017\003\018\003\024\003\080\003\025\003\ -\081\003\238\000\031\003\026\003\240\000\031\000\033\003\028\000\ -\039\003\041\003\031\000\031\000\031\000\031\000\046\003\003\001\ -\004\001\005\001\047\003\048\003\027\003\033\002\051\001\052\003\ -\051\001\171\000\050\003\163\003\031\000\061\003\171\000\171\000\ -\031\000\195\000\159\001\106\003\031\000\051\001\195\000\195\000\ -\067\001\031\000\164\001\059\003\031\000\060\003\063\003\064\003\ -\134\000\154\000\016\001\156\000\162\000\175\003\163\000\031\000\ -\065\003\067\003\066\003\193\001\068\003\031\000\031\000\067\001\ -\070\003\072\003\067\001\067\001\067\001\067\001\031\000\067\001\ -\027\003\126\003\073\003\074\003\235\000\171\000\083\003\051\001\ -\071\003\171\000\090\003\084\003\085\003\195\000\035\001\035\001\ -\095\003\195\000\067\001\094\003\097\003\100\003\031\000\031\000\ -\031\000\027\001\103\003\134\000\154\000\101\003\156\000\121\003\ -\129\003\031\000\171\000\134\000\154\000\147\003\156\000\110\003\ -\118\003\118\000\195\000\130\003\148\003\053\000\149\003\187\002\ -\188\002\128\000\129\000\189\002\130\000\059\000\060\000\061\000\ -\062\000\106\003\158\003\133\003\139\003\140\003\141\003\144\003\ -\125\000\145\003\146\003\126\000\127\000\128\000\129\000\190\002\ -\130\000\157\003\150\002\161\003\162\003\148\001\173\003\151\002\ -\171\000\165\003\171\003\157\000\174\003\150\003\122\000\012\000\ -\195\000\180\003\151\003\131\000\181\003\183\003\170\001\134\000\ -\154\000\001\000\156\000\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\041\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\186\003\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\222\001\222\001\222\001\222\001\222\001\222\001\222\001\ -\222\001\089\001\169\001\016\001\016\001\016\001\016\001\016\001\ -\016\001\016\001\016\001\013\000\154\000\103\000\108\000\096\001\ -\016\001\016\001\112\002\007\000\102\001\045\002\223\000\128\000\ -\016\001\016\001\016\001\016\001\016\001\155\000\026\001\118\001\ -\225\000\247\000\133\000\110\000\114\000\049\001\142\001\138\001\ -\130\001\198\001\203\000\252\000\253\000\254\000\255\000\134\000\ -\140\000\126\001\027\001\027\001\027\001\027\001\027\001\027\001\ -\001\000\001\000\136\001\145\001\122\003\000\001\231\001\088\002\ -\007\002\001\001\143\002\016\001\016\001\219\000\016\001\160\001\ -\016\001\127\002\002\003\104\002\250\002\129\002\016\001\016\001\ -\103\002\248\002\034\002\125\003\134\002\132\003\016\001\016\001\ -\016\001\016\001\016\001\016\001\016\001\016\001\016\001\016\001\ -\016\001\016\001\016\001\247\002\102\003\095\002\016\001\016\001\ -\016\001\016\001\016\001\016\001\016\001\016\001\016\001\016\001\ -\016\001\200\002\027\001\035\003\154\003\016\001\016\001\016\001\ -\016\001\016\001\016\001\016\001\113\002\051\003\172\000\003\001\ -\004\001\005\001\016\001\172\000\172\000\140\002\116\002\174\001\ -\016\001\027\001\167\001\221\002\027\001\027\001\027\001\027\001\ -\220\002\027\001\232\002\152\003\176\003\252\000\253\000\254\000\ -\255\000\177\003\252\000\253\000\254\000\255\000\115\003\252\000\ -\253\000\254\000\255\000\179\003\027\001\027\001\207\002\000\001\ -\027\001\027\001\044\001\001\001\000\001\138\000\173\000\111\003\ -\001\001\000\001\172\000\173\000\173\000\001\001\172\000\158\001\ -\170\003\190\003\161\002\051\002\063\001\089\003\041\001\041\001\ -\041\001\041\001\041\001\041\001\041\001\041\001\043\002\182\003\ -\159\003\164\003\017\001\041\001\041\001\040\003\155\000\172\000\ -\000\000\000\000\000\000\041\001\041\001\041\001\041\001\041\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\132\002\000\000\173\000\000\000\000\000\000\000\173\000\000\000\ -\000\000\003\001\004\001\005\001\000\000\000\000\003\001\004\001\ -\005\001\000\000\000\000\003\001\004\001\005\001\000\000\000\000\ -\000\000\252\000\253\000\254\000\255\000\172\000\041\001\173\000\ -\000\000\041\001\000\000\041\001\000\000\000\000\000\000\179\000\ -\041\001\041\001\041\001\000\001\179\000\179\000\000\000\001\001\ -\173\001\041\001\041\001\041\001\041\001\041\001\041\001\041\001\ -\041\001\041\001\041\001\041\001\041\001\041\001\000\000\000\000\ -\000\000\041\001\041\001\041\001\041\001\041\001\041\001\041\001\ -\041\001\041\001\041\001\041\001\000\000\173\000\000\000\000\000\ -\041\001\041\001\041\001\000\000\041\001\041\001\041\001\000\000\ -\000\000\000\000\000\000\179\000\000\000\041\001\000\000\179\000\ -\000\000\000\000\000\000\041\001\000\000\016\001\016\001\016\001\ -\016\001\016\001\016\001\016\001\016\001\003\001\004\001\005\001\ -\019\001\118\000\016\001\016\001\000\000\007\001\000\000\000\000\ -\179\000\000\000\016\001\016\001\016\001\016\001\016\001\000\000\ -\000\000\000\000\000\000\000\000\014\001\000\000\000\000\000\000\ -\125\000\000\000\000\000\126\000\127\000\128\000\129\000\000\000\ -\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\016\001\017\001\018\001\000\000\019\001\ -\020\001\021\001\000\000\131\000\000\000\016\001\179\000\000\000\ -\016\001\000\000\016\001\000\000\000\000\180\000\000\000\000\000\ -\016\001\016\001\180\000\180\000\000\000\000\000\168\001\000\000\ -\016\001\016\001\016\001\016\001\016\001\016\001\016\001\016\001\ -\016\001\016\001\016\001\016\001\016\001\000\000\000\000\000\000\ -\016\001\016\001\016\001\016\001\016\001\016\001\016\001\016\001\ -\016\001\016\001\016\001\022\001\023\001\000\000\000\000\016\001\ -\016\001\016\001\000\000\016\001\016\001\016\001\000\000\000\000\ -\000\000\180\000\000\000\000\000\016\001\180\000\000\000\000\000\ -\000\000\000\000\016\001\017\001\017\001\017\001\017\001\017\001\ -\017\001\017\001\017\001\000\000\000\000\000\000\020\001\000\000\ -\017\001\017\001\000\000\000\000\000\000\000\000\180\000\000\000\ -\017\001\017\001\017\001\017\001\017\001\252\000\253\000\254\000\ -\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\ -\000\000\000\000\000\000\001\001\000\000\000\000\000\000\117\002\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\017\001\180\000\000\000\017\001\000\000\ -\017\001\000\000\000\000\183\000\000\000\000\000\017\001\017\001\ -\183\000\183\000\000\000\000\000\167\001\000\000\017\001\017\001\ -\017\001\017\001\017\001\017\001\017\001\017\001\017\001\017\001\ -\017\001\017\001\017\001\000\000\000\000\000\000\017\001\017\001\ -\017\001\017\001\017\001\017\001\017\001\017\001\017\001\017\001\ -\017\001\003\001\004\001\005\001\000\000\017\001\017\001\017\001\ -\000\000\017\001\017\001\017\001\000\000\000\000\000\000\183\000\ -\000\000\000\000\017\001\183\000\000\000\000\000\000\000\000\000\ -\017\001\019\001\019\001\019\001\019\001\019\001\019\001\019\001\ -\019\001\000\000\000\000\000\000\022\001\000\000\019\001\019\001\ -\000\000\000\000\000\000\000\000\183\000\000\000\019\001\019\001\ -\019\001\019\001\019\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\108\002\000\000\000\000\000\000\000\000\252\000\253\000\254\000\ -\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\ -\000\000\019\001\183\000\001\001\019\001\196\000\019\001\000\000\ -\000\000\000\000\196\000\196\000\019\001\019\001\161\001\000\000\ -\000\000\000\000\000\000\000\000\019\001\019\001\019\001\019\001\ +let yytablesize = 8739 +let yytable = "\137\000\ +\158\000\242\000\160\000\102\000\244\000\194\001\195\001\146\000\ +\071\001\064\001\138\000\066\001\195\000\220\001\040\001\218\000\ +\045\001\072\001\253\000\191\000\215\000\215\000\245\001\057\001\ +\193\002\044\001\230\002\219\000\225\002\194\001\195\001\181\002\ +\085\002\202\001\221\000\242\001\242\001\117\002\237\000\165\002\ +\015\000\195\002\122\002\232\000\069\001\207\001\111\002\234\000\ +\088\002\231\000\115\002\108\002\215\002\241\000\168\001\067\001\ +\074\001\169\002\208\002\019\002\239\000\192\002\099\003\194\002\ +\139\000\157\002\196\001\105\000\190\001\053\002\036\001\145\001\ +\114\002\239\000\064\003\126\000\125\003\161\000\140\003\201\002\ +\021\000\024\002\006\001\222\000\250\000\182\001\001\001\002\001\ +\003\001\004\001\215\000\001\001\002\001\003\001\004\001\126\000\ +\233\000\234\000\235\000\236\000\240\000\238\002\107\002\110\000\ +\005\001\204\000\013\001\243\002\006\001\005\001\204\000\204\000\ +\224\000\006\001\158\001\096\002\202\002\098\002\014\001\007\001\ +\253\002\137\000\158\000\206\001\160\000\058\001\060\001\060\001\ +\068\001\060\001\163\003\060\001\105\000\021\001\126\000\233\002\ +\225\000\214\001\173\003\054\002\009\000\145\001\162\003\042\001\ +\151\002\008\001\009\001\010\001\152\001\248\000\115\000\025\003\ +\065\001\191\001\192\001\037\001\229\001\204\000\186\001\035\001\ +\126\000\204\000\028\001\150\001\127\000\137\003\183\001\026\002\ +\110\000\184\001\185\001\008\001\009\001\010\001\011\001\012\001\ +\008\001\009\001\010\001\011\001\012\001\130\003\006\001\201\002\ +\127\000\015\003\204\000\030\003\174\001\008\002\139\001\203\001\ +\034\003\176\003\051\002\033\002\009\002\204\003\014\000\009\000\ +\097\002\139\000\099\002\040\003\152\001\226\000\063\003\004\003\ +\231\001\208\002\009\000\016\003\227\000\029\001\030\001\115\000\ +\009\000\009\000\088\002\138\003\108\002\219\000\076\002\127\000\ +\228\000\049\002\213\001\221\001\222\001\223\001\224\001\225\001\ +\226\001\227\001\228\001\204\000\067\001\156\003\052\002\187\001\ +\230\001\035\001\188\001\189\001\111\001\139\001\009\001\010\001\ +\075\003\127\000\250\001\244\001\040\003\121\000\016\002\076\003\ +\249\001\156\003\251\001\252\001\253\001\254\001\255\001\000\002\ +\001\002\038\001\002\002\003\002\004\002\005\002\006\002\007\002\ +\200\001\205\001\036\001\087\003\222\000\118\002\107\003\121\000\ +\229\000\111\001\230\000\120\003\219\000\219\000\015\002\231\000\ +\219\000\041\003\060\001\221\000\221\000\213\001\232\000\237\000\ +\237\000\028\002\111\001\108\003\232\000\036\002\077\003\113\002\ +\234\000\040\002\231\000\219\000\207\001\015\000\241\000\241\000\ +\060\001\015\000\114\003\027\002\015\000\239\000\239\000\071\002\ +\069\002\201\001\211\003\001\000\001\000\246\000\038\002\123\003\ +\119\002\015\000\042\002\043\002\126\003\191\002\015\000\010\002\ +\011\002\012\002\013\002\014\002\110\002\017\002\018\002\020\002\ +\021\002\187\002\023\002\063\002\155\003\021\000\207\001\082\003\ +\015\000\021\000\090\003\152\003\021\000\240\000\240\000\204\001\ +\015\000\111\001\234\002\001\000\001\000\015\000\212\003\237\000\ +\015\000\021\000\247\000\101\002\102\002\103\002\021\000\021\000\ +\021\000\021\000\004\000\015\000\254\002\112\003\113\003\053\001\ +\016\000\015\000\015\000\176\001\249\000\150\000\150\000\214\001\ +\021\000\254\000\015\000\214\001\214\001\233\002\111\001\204\001\ +\021\000\198\003\012\000\180\003\105\001\021\000\205\001\205\003\ +\021\000\235\002\206\001\238\000\179\000\001\001\002\001\003\001\ +\004\001\179\000\179\000\021\000\002\000\171\001\013\000\002\000\ +\242\000\021\000\021\000\255\000\161\001\244\000\150\001\005\001\ +\015\000\004\000\021\000\006\001\150\000\124\000\042\001\026\002\ +\150\000\105\001\168\001\000\001\177\002\166\002\110\002\184\002\ +\186\002\233\002\206\001\219\002\078\002\012\000\233\002\104\002\ +\054\001\233\002\070\001\021\000\021\000\021\000\021\000\021\000\ +\179\000\212\002\076\001\014\000\179\000\215\000\116\002\014\000\ +\021\000\013\000\014\000\219\000\251\000\123\002\135\002\004\000\ +\032\003\105\001\236\002\057\000\215\000\105\001\154\001\014\000\ +\177\001\169\001\006\001\006\002\014\000\179\000\170\001\142\002\ +\014\000\144\002\008\001\009\001\010\001\011\001\012\001\065\003\ +\105\001\152\002\153\002\041\001\013\000\175\001\014\000\106\002\ +\045\002\046\002\197\001\109\001\233\002\198\001\014\000\109\001\ +\015\000\016\000\181\001\014\000\199\001\155\001\014\000\212\001\ +\156\001\218\001\157\001\036\001\036\001\036\001\036\001\036\001\ +\036\001\014\000\109\001\158\001\159\001\105\001\179\000\014\000\ +\014\000\133\003\134\003\179\002\170\002\026\002\001\000\001\000\ +\014\000\008\001\009\001\010\001\167\002\012\001\105\001\161\001\ +\219\001\168\002\060\001\042\001\199\002\161\000\237\001\025\000\ +\124\000\026\003\213\002\213\002\027\003\028\003\218\002\109\001\ +\249\002\249\002\188\002\189\002\235\001\103\003\137\000\158\000\ +\236\001\160\000\238\001\196\002\207\003\209\003\014\000\239\001\ +\109\001\071\001\240\001\036\001\054\003\055\003\247\001\014\001\ +\137\000\137\000\056\003\219\002\037\003\038\003\050\003\248\001\ +\146\000\146\000\029\002\247\002\247\002\078\002\021\001\030\002\ +\031\002\032\002\036\001\078\002\246\002\036\001\036\001\036\001\ +\036\001\219\000\036\001\039\002\055\002\059\002\036\001\060\002\ +\061\002\067\001\003\001\053\002\078\003\023\001\024\001\025\001\ +\064\002\026\001\027\001\028\001\013\003\014\003\036\001\067\001\ +\014\001\062\002\036\001\036\001\052\002\016\000\006\001\065\002\ +\067\002\016\000\070\002\196\002\016\000\072\002\003\001\021\001\ +\001\000\002\000\003\000\004\000\065\003\077\002\075\002\023\003\ +\060\001\016\000\144\003\080\002\100\002\124\002\016\000\016\000\ +\237\000\016\000\006\001\134\002\254\002\146\002\238\000\155\002\ +\025\001\147\002\026\001\027\001\028\001\149\002\029\001\030\001\ +\016\000\006\001\117\003\159\002\119\003\109\003\161\002\162\002\ +\016\000\029\003\045\003\164\002\163\002\016\000\219\002\061\001\ +\016\000\058\001\060\001\060\001\060\001\008\001\009\001\010\001\ +\045\003\012\001\171\002\016\000\172\002\213\002\060\001\203\002\ +\173\002\016\000\016\000\164\001\165\001\166\001\167\001\214\001\ +\214\001\036\002\016\000\178\002\183\002\170\002\185\002\029\001\ +\030\001\008\001\009\001\010\001\011\001\012\001\190\002\217\002\ +\057\000\026\002\224\002\216\002\057\000\226\002\239\002\057\000\ +\237\002\002\003\000\003\001\003\003\003\009\003\057\000\057\000\ +\057\000\057\000\057\000\057\000\057\000\022\003\057\000\017\003\ +\016\000\057\000\057\000\057\000\057\000\019\003\158\003\018\003\ +\024\003\098\003\031\003\033\003\035\003\101\003\036\003\102\003\ +\042\003\044\003\043\003\057\000\057\000\057\000\242\000\057\000\ +\049\003\244\000\051\003\057\000\057\003\067\001\059\003\061\003\ +\057\000\062\003\066\003\057\000\081\003\068\003\072\003\083\003\ +\060\001\084\003\060\001\067\003\183\003\172\000\057\000\086\002\ +\085\003\070\003\172\000\172\000\057\000\057\000\211\001\127\003\ +\196\002\060\001\079\003\080\003\025\000\057\000\086\003\088\003\ +\025\000\206\001\092\003\025\000\137\000\158\000\195\003\160\000\ +\091\003\018\001\093\003\095\003\086\002\166\000\087\002\167\000\ +\025\000\089\003\094\003\111\003\104\003\042\001\057\000\057\000\ +\057\000\057\000\057\000\147\003\057\000\057\000\239\000\118\003\ +\105\003\172\000\106\003\057\000\060\001\172\000\045\003\115\003\ +\116\003\121\003\122\003\124\003\131\003\142\003\121\000\025\000\ +\139\003\122\000\150\003\123\000\025\000\151\003\154\003\025\000\ +\137\000\158\000\124\000\160\000\125\000\126\000\172\000\159\003\ +\137\000\158\000\025\000\160\000\160\003\161\003\164\003\165\003\ +\025\000\025\000\120\000\166\003\177\003\181\003\012\000\182\003\ +\193\003\025\000\185\003\191\003\178\003\127\003\194\003\204\002\ +\205\002\130\000\131\000\206\002\132\000\200\003\201\003\203\003\ +\206\003\127\000\175\001\001\000\128\000\129\000\130\000\131\000\ +\091\001\132\000\174\001\013\000\157\000\133\000\106\000\172\000\ +\207\002\111\000\042\001\042\001\007\000\099\001\107\001\025\000\ +\052\002\226\000\158\000\137\000\158\000\134\000\160\000\131\000\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\043\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\028\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\123\001\228\000\228\001\228\001\228\001\228\001\ +\228\001\228\001\228\001\228\001\228\001\228\001\228\001\228\001\ +\228\001\228\001\018\001\018\001\018\001\018\001\018\001\018\001\ +\018\001\018\001\249\000\136\000\113\000\117\000\120\000\018\001\ +\018\001\051\001\147\001\143\001\135\001\203\001\137\000\018\001\ +\018\001\018\001\018\001\018\001\206\000\125\002\143\000\131\001\ +\141\001\150\001\243\001\143\003\127\002\127\000\105\002\160\002\ +\128\000\129\000\130\000\131\000\022\002\132\000\173\001\223\000\ +\012\003\133\000\143\002\145\002\020\003\121\002\001\001\002\001\ +\003\001\004\001\146\003\120\002\011\003\001\001\002\001\003\001\ +\004\001\134\000\018\001\018\001\150\002\018\001\153\003\018\001\ +\005\001\060\003\010\003\173\000\006\001\018\001\018\001\005\001\ +\173\000\173\000\112\002\006\001\214\001\018\001\018\001\018\001\ +\018\001\018\001\018\001\018\001\018\001\018\001\018\001\018\001\ +\018\001\018\001\220\002\174\003\071\003\018\001\018\001\018\001\ +\018\001\018\001\018\001\018\001\018\001\018\001\018\001\018\001\ +\018\001\053\003\180\001\241\002\252\002\018\001\018\001\018\001\ +\018\001\018\001\018\001\018\001\240\002\140\000\251\002\173\000\ +\196\003\136\003\197\003\173\000\018\001\128\002\172\003\199\003\ +\219\000\198\000\018\001\008\001\009\001\010\001\011\001\012\001\ +\227\002\051\001\008\001\009\001\010\001\011\001\012\001\199\000\ +\200\000\201\000\202\000\203\000\173\000\141\000\001\001\002\001\ +\003\001\004\001\132\003\190\003\068\002\210\003\075\001\058\002\ +\174\000\202\003\110\003\184\003\179\003\174\000\174\000\159\000\ +\005\001\164\001\000\000\000\000\006\001\058\003\000\000\000\000\ +\000\000\000\000\000\000\043\001\043\001\043\001\043\001\043\001\ +\043\001\043\001\043\001\000\000\000\000\000\000\000\000\000\000\ +\043\001\043\001\000\000\000\000\019\001\173\000\000\000\000\000\ +\043\001\043\001\043\001\043\001\043\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\174\000\000\000\000\000\000\000\ +\174\000\000\000\000\000\000\000\000\000\000\000\000\000\204\000\ +\205\000\206\000\207\000\208\000\209\000\210\000\211\000\212\000\ +\213\000\000\000\000\000\008\001\009\001\010\001\011\001\012\001\ +\000\000\174\000\000\000\043\001\000\000\000\000\043\001\000\000\ +\043\001\000\000\000\000\198\000\000\000\043\001\043\001\043\001\ +\198\000\198\000\000\000\000\000\169\001\000\000\043\001\043\001\ +\043\001\043\001\043\001\043\001\043\001\043\001\043\001\043\001\ +\043\001\043\001\043\001\000\000\000\000\000\000\043\001\043\001\ +\043\001\043\001\043\001\043\001\043\001\043\001\043\001\043\001\ +\043\001\043\001\174\000\002\001\003\001\004\001\043\001\043\001\ +\043\001\000\000\043\001\043\001\043\001\000\000\000\000\198\000\ +\000\000\000\000\000\000\198\000\000\000\043\001\000\000\000\000\ +\006\001\000\000\000\000\043\001\018\001\018\001\018\001\018\001\ +\018\001\018\001\018\001\018\001\000\000\000\000\000\000\000\000\ +\000\000\018\001\018\001\000\000\198\000\021\001\000\000\167\003\ +\000\000\018\001\018\001\018\001\018\001\018\001\168\003\053\000\ +\169\003\000\000\000\000\000\000\000\000\000\000\000\000\059\000\ +\060\000\061\000\062\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\059\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\001\ +\009\001\010\001\011\001\012\001\018\001\198\000\000\000\018\001\ +\170\003\018\001\000\000\000\000\175\000\171\003\000\000\018\001\ +\018\001\175\000\175\000\000\000\000\000\179\001\000\000\018\001\ +\018\001\018\001\018\001\018\001\018\001\018\001\018\001\018\001\ +\018\001\018\001\018\001\018\001\000\000\000\000\000\000\018\001\ +\018\001\018\001\018\001\018\001\018\001\018\001\018\001\018\001\ +\018\001\018\001\018\001\001\001\002\001\003\001\004\001\018\001\ +\018\001\018\001\000\000\018\001\018\001\018\001\000\000\000\000\ +\175\000\000\000\000\000\000\000\175\000\005\001\018\001\000\000\ +\000\000\006\001\000\000\000\000\018\001\019\001\019\001\019\001\ +\019\001\019\001\019\001\019\001\019\001\021\003\000\000\000\000\ +\000\000\000\000\019\001\019\001\000\000\175\000\022\001\000\000\ +\000\000\000\000\019\001\019\001\019\001\019\001\019\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\037\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\008\001\009\001\010\001\011\001\012\001\019\001\175\000\000\000\ +\019\001\000\000\019\001\000\000\000\000\176\000\000\000\000\000\ +\019\001\019\001\176\000\176\000\000\000\000\000\163\001\000\000\ \019\001\019\001\019\001\019\001\019\001\019\001\019\001\019\001\ -\019\001\000\000\000\000\000\000\019\001\019\001\019\001\019\001\ -\019\001\019\001\019\001\019\001\019\001\019\001\019\001\000\000\ -\000\000\000\000\000\000\019\001\019\001\019\001\000\000\019\001\ -\019\001\196\000\000\000\000\000\000\000\196\000\000\000\000\000\ -\019\001\003\001\004\001\005\001\000\000\000\000\019\001\020\001\ -\020\001\020\001\020\001\020\001\020\001\020\001\020\001\000\000\ -\000\000\000\000\023\001\000\000\020\001\020\001\196\000\000\000\ -\000\000\000\000\000\000\000\000\020\001\020\001\020\001\020\001\ -\020\001\252\000\253\000\254\000\255\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\252\000\253\000\254\000\255\000\000\000\ -\000\000\000\000\000\000\000\001\000\000\000\000\000\000\001\001\ -\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\ -\000\000\001\001\028\001\000\000\196\000\000\000\000\000\020\001\ -\000\000\000\000\020\001\000\000\020\001\000\000\000\000\000\000\ -\000\000\000\000\020\001\020\001\029\002\030\002\000\000\000\000\ -\000\000\000\000\020\001\020\001\020\001\020\001\020\001\020\001\ -\020\001\020\001\020\001\020\001\020\001\020\001\020\001\220\001\ -\000\000\000\000\020\001\020\001\020\001\020\001\020\001\020\001\ -\020\001\020\001\020\001\020\001\020\001\003\001\004\001\005\001\ -\000\000\020\001\020\001\020\001\000\000\020\001\020\001\003\001\ -\004\001\221\001\000\000\000\000\000\000\000\000\020\001\000\000\ -\184\000\000\000\222\001\000\000\020\001\022\001\022\001\022\001\ -\022\001\022\001\022\001\022\001\022\001\000\000\000\000\000\000\ -\138\002\000\000\022\001\022\001\000\000\000\000\000\000\000\000\ -\075\003\000\000\022\001\022\001\022\001\022\001\022\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\252\000\253\000\254\000\255\000\000\000\000\000\000\000\ -\000\000\252\000\253\000\254\000\255\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\001\000\000\000\000\000\000\001\001\ -\000\000\000\000\000\000\000\001\000\000\022\001\000\000\001\001\ -\000\000\000\000\022\001\000\000\000\000\000\000\000\000\000\000\ -\022\001\022\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\022\001\022\001\022\001\022\001\022\001\022\001\022\001\022\001\ -\022\001\022\001\022\001\022\001\022\001\000\000\000\000\027\001\ -\022\001\022\001\022\001\022\001\022\001\022\001\022\001\022\001\ -\022\001\022\001\022\001\000\000\000\000\000\000\185\000\022\001\ -\022\001\022\001\000\000\022\001\022\001\003\001\004\001\005\001\ -\000\000\000\000\000\000\000\000\022\001\003\001\004\001\005\001\ -\000\000\000\000\022\001\023\001\023\001\023\001\023\001\023\001\ -\023\001\023\001\023\001\000\000\000\000\000\000\155\003\000\000\ -\023\001\023\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\023\001\023\001\023\001\023\001\023\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\252\000\ -\253\000\254\000\255\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\028\001\028\001\028\001\028\001\028\001\ -\028\001\000\001\000\000\000\000\000\000\001\001\000\000\000\000\ -\000\000\000\000\000\000\023\001\000\000\000\000\000\000\000\000\ -\023\001\000\000\000\000\000\000\000\000\000\000\023\001\023\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\023\001\023\001\ -\023\001\023\001\023\001\023\001\023\001\023\001\023\001\023\001\ -\023\001\023\001\023\001\000\000\189\000\000\000\023\001\023\001\ -\023\001\023\001\023\001\023\001\023\001\023\001\023\001\023\001\ -\023\001\000\000\000\000\028\001\000\000\023\001\023\001\023\001\ -\000\000\023\001\023\001\003\001\004\001\005\001\000\000\184\000\ -\000\000\000\000\023\001\000\000\184\000\184\000\000\000\000\000\ -\023\001\184\000\028\001\184\000\184\000\028\001\028\001\028\001\ -\028\001\000\000\028\001\184\000\184\000\184\000\184\000\184\000\ -\184\000\184\000\184\000\184\000\000\000\000\000\184\000\184\000\ -\184\000\184\000\000\000\000\000\000\000\028\001\028\001\000\000\ -\000\000\028\001\028\001\000\000\000\000\000\000\000\000\000\000\ -\184\000\184\000\184\000\184\000\184\000\184\000\184\000\184\000\ -\184\000\000\000\000\000\000\000\000\000\184\000\000\000\000\000\ -\184\000\110\002\000\000\000\000\000\000\000\000\252\000\253\000\ -\254\000\255\000\000\000\184\000\000\000\034\001\000\000\000\000\ -\184\000\184\000\184\000\000\000\000\000\000\000\000\000\000\000\ -\000\001\000\000\184\000\000\000\001\001\000\000\000\000\190\000\ -\027\001\027\001\027\001\027\001\027\001\027\001\001\000\001\000\ -\000\000\184\000\184\000\000\000\000\000\000\000\252\000\253\000\ -\254\000\255\000\184\000\184\000\184\000\185\000\184\000\184\000\ -\000\000\000\000\185\000\185\000\000\000\184\000\184\000\185\000\ -\000\001\185\000\185\000\000\000\001\001\000\000\000\000\000\000\ -\141\002\185\000\185\000\185\000\185\000\185\000\185\000\185\000\ -\185\000\185\000\000\000\000\000\185\000\185\000\185\000\185\000\ -\000\000\000\000\003\001\004\001\005\001\000\000\000\000\000\000\ -\027\001\000\000\000\000\027\001\000\000\000\000\185\000\185\000\ -\185\000\185\000\185\000\185\000\185\000\185\000\185\000\000\000\ -\000\000\000\000\000\000\185\000\000\000\000\000\185\000\027\001\ -\000\000\000\000\027\001\027\001\027\001\027\001\000\000\027\001\ -\000\000\185\000\003\001\004\001\005\001\000\000\185\000\185\000\ -\185\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\185\000\000\000\027\001\027\001\000\000\191\000\027\001\027\001\ -\027\001\000\000\000\000\000\000\000\000\000\000\000\000\185\000\ -\185\000\000\000\000\000\000\000\252\000\253\000\254\000\255\000\ -\185\000\185\000\185\000\189\000\185\000\185\000\000\000\000\000\ -\189\000\189\000\000\000\185\000\185\000\189\000\000\001\189\000\ -\189\000\000\000\001\001\000\000\000\000\000\000\000\000\189\000\ -\189\000\189\000\189\000\189\000\189\000\189\000\189\000\189\000\ -\000\000\007\001\189\000\189\000\189\000\189\000\000\000\000\000\ -\000\000\008\001\009\001\010\001\011\001\012\001\013\001\000\000\ -\014\001\015\001\000\000\000\000\189\000\189\000\189\000\189\000\ -\189\000\189\000\189\000\189\000\189\000\000\000\000\000\000\000\ -\000\000\189\000\000\000\000\000\189\000\000\000\000\000\016\001\ -\017\001\018\001\000\000\019\001\020\001\021\001\000\000\189\000\ -\003\001\004\001\005\001\000\000\189\000\189\000\189\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\162\000\189\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\034\001\034\001\ -\034\001\034\001\034\001\034\001\000\000\189\000\189\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\189\000\189\000\ -\189\000\000\000\189\000\189\000\000\000\000\000\190\000\022\001\ -\023\001\189\000\189\000\190\000\190\000\000\000\000\000\000\000\ -\190\000\000\000\190\000\190\000\024\001\025\001\000\000\000\000\ -\000\000\000\000\190\000\190\000\190\000\190\000\190\000\190\000\ -\190\000\190\000\190\000\000\000\000\000\190\000\190\000\190\000\ -\190\000\000\000\000\000\000\000\000\000\000\000\034\001\000\000\ -\000\000\034\001\000\000\000\000\000\000\000\000\000\000\190\000\ -\190\000\190\000\190\000\190\000\190\000\190\000\190\000\190\000\ -\000\000\000\000\000\000\000\000\190\000\034\001\000\000\190\000\ -\034\001\034\001\034\001\034\001\000\000\034\001\000\000\000\000\ -\000\000\000\000\190\000\000\000\000\000\159\000\000\000\190\000\ -\190\000\190\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\034\001\190\000\000\000\000\000\034\001\034\001\034\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\190\000\190\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\190\000\190\000\190\000\191\000\190\000\190\000\000\000\ -\000\000\191\000\191\000\000\000\190\000\190\000\191\000\000\000\ -\191\000\191\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\191\000\191\000\191\000\191\000\191\000\191\000\191\000\191\000\ -\191\000\000\000\000\000\191\000\191\000\191\000\191\000\000\000\ -\000\000\000\000\000\000\000\000\114\002\000\000\000\000\000\000\ -\000\000\252\000\253\000\254\000\255\000\191\000\191\000\191\000\ -\191\000\191\000\191\000\191\000\191\000\191\000\000\000\028\001\ -\000\000\000\000\191\000\000\001\000\000\191\000\000\000\001\001\ -\000\000\000\000\000\000\000\000\000\000\167\000\000\000\000\000\ -\191\000\000\000\000\000\000\000\000\000\191\000\191\000\191\000\ -\000\000\000\000\000\000\252\000\253\000\254\000\255\000\191\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\001\191\000\191\000\ -\000\000\001\001\000\000\000\000\162\000\000\000\000\000\191\000\ -\191\000\191\000\162\000\191\000\191\000\003\003\162\000\000\000\ -\162\000\162\000\191\000\191\000\000\000\003\001\004\001\005\001\ -\162\000\162\000\162\000\162\000\162\000\162\000\162\000\162\000\ -\162\000\000\000\000\000\162\000\162\000\162\000\162\000\000\000\ -\000\000\000\000\000\000\000\000\115\002\000\000\000\000\000\000\ -\000\000\252\000\253\000\254\000\255\000\162\000\162\000\162\000\ -\162\000\162\000\162\000\162\000\000\000\162\000\000\000\003\001\ -\004\001\005\001\162\000\000\001\000\000\162\000\000\000\001\001\ -\252\000\253\000\254\000\255\000\000\000\157\000\000\000\000\000\ -\162\000\000\000\000\000\000\000\000\000\162\000\162\000\162\000\ -\215\000\194\000\000\001\000\000\000\000\000\000\001\001\162\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\195\000\ -\196\000\197\000\198\000\199\000\000\000\000\000\162\000\162\000\ -\000\000\000\000\000\000\000\000\159\000\000\000\000\000\162\000\ -\162\000\162\000\159\000\162\000\162\000\000\000\159\000\000\000\ -\159\000\159\000\162\000\162\000\127\003\003\001\004\001\005\001\ -\159\000\159\000\159\000\159\000\159\000\159\000\159\000\159\000\ -\159\000\000\000\000\000\159\000\159\000\159\000\159\000\000\000\ -\000\000\000\000\016\001\000\000\003\001\004\001\005\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\159\000\159\000\159\000\ -\159\000\159\000\159\000\159\000\000\000\159\000\000\000\000\000\ -\000\000\000\000\159\000\000\000\000\000\159\000\200\000\201\000\ -\202\000\203\000\204\000\205\000\206\000\207\000\208\000\209\000\ -\159\000\000\000\000\000\000\000\000\000\159\000\159\000\159\000\ -\000\000\000\000\000\000\252\000\253\000\254\000\255\000\159\000\ -\028\001\028\001\028\001\028\001\028\001\028\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\001\159\000\159\000\ -\000\000\001\001\000\000\000\000\167\000\000\000\000\000\159\000\ -\159\000\159\000\167\000\159\000\159\000\172\003\167\000\000\000\ -\167\000\167\000\159\000\159\000\000\000\000\000\000\000\000\000\ -\167\000\167\000\167\000\167\000\167\000\167\000\167\000\167\000\ -\167\000\000\000\000\000\167\000\167\000\167\000\167\000\000\000\ -\154\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\028\001\000\000\000\000\028\001\000\000\167\000\167\000\167\000\ -\167\000\167\000\167\000\167\000\000\000\167\000\000\000\003\001\ -\004\001\005\001\167\000\000\000\000\000\167\000\000\000\028\001\ -\000\000\000\000\028\001\028\001\028\001\028\001\000\000\028\001\ -\167\000\000\000\000\000\000\000\000\000\167\000\167\000\167\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\167\000\ -\000\000\000\000\028\001\028\001\000\000\000\000\028\001\028\001\ -\028\001\000\000\000\000\000\000\000\000\000\000\167\000\167\000\ -\000\000\000\000\034\001\000\000\157\000\000\000\000\000\167\000\ -\167\000\167\000\157\000\167\000\167\000\000\000\157\000\000\000\ -\157\000\157\000\167\000\167\000\000\000\000\000\000\000\000\000\ +\019\001\019\001\019\001\019\001\019\001\166\000\000\000\167\000\ +\019\001\019\001\019\001\019\001\019\001\019\001\019\001\019\001\ +\019\001\019\001\019\001\019\001\001\001\002\001\003\001\004\001\ +\019\001\019\001\019\001\000\000\019\001\019\001\019\001\000\000\ +\000\000\176\000\000\000\000\000\000\000\176\000\005\001\019\001\ +\000\000\000\000\006\001\000\000\000\000\019\001\021\001\021\001\ +\021\001\021\001\021\001\021\001\021\001\021\001\192\003\000\000\ +\000\000\000\000\000\000\021\001\021\001\000\000\176\000\024\001\ +\000\000\000\000\120\000\021\001\021\001\021\001\021\001\021\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\059\001\059\001\059\001\059\001\059\001\059\001\000\000\000\000\ +\000\000\127\000\000\000\000\000\128\000\129\000\130\000\131\000\ +\000\000\132\000\000\000\000\000\000\000\133\000\000\000\000\000\ +\000\000\008\001\009\001\010\001\011\001\012\001\021\001\176\000\ +\000\000\021\001\000\000\021\001\000\000\134\000\000\000\000\000\ +\000\000\021\001\021\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\021\001\021\001\021\001\021\001\021\001\021\001\021\001\ +\021\001\021\001\021\001\021\001\021\001\021\001\000\000\000\000\ +\059\001\021\001\021\001\021\001\021\001\021\001\021\001\021\001\ +\021\001\021\001\021\001\021\001\021\001\000\000\000\000\000\000\ +\000\000\021\001\021\001\021\001\000\000\021\001\021\001\059\001\ +\000\000\000\000\059\001\059\001\059\001\059\001\000\000\059\001\ +\021\001\000\000\000\000\059\001\000\000\000\000\021\001\022\001\ +\022\001\022\001\022\001\022\001\022\001\022\001\022\001\000\000\ +\000\000\000\000\000\000\059\001\022\001\022\001\000\000\000\000\ +\025\001\000\000\000\000\000\000\022\001\022\001\022\001\022\001\ +\022\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\037\001\037\001\037\001\037\001\037\001\037\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\001\ +\000\000\000\000\022\001\000\000\022\001\000\000\000\000\000\000\ +\000\000\000\000\022\001\022\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\022\001\022\001\022\001\022\001\022\001\022\001\ +\022\001\022\001\022\001\022\001\022\001\022\001\022\001\000\000\ +\000\000\037\001\022\001\022\001\022\001\022\001\022\001\022\001\ +\022\001\022\001\022\001\022\001\022\001\022\001\000\000\000\000\ +\000\000\000\000\022\001\022\001\022\001\000\000\022\001\022\001\ +\037\001\000\000\000\000\037\001\037\001\037\001\037\001\000\000\ +\037\001\022\001\000\000\187\000\037\001\000\000\000\000\022\001\ +\024\001\024\001\024\001\024\001\024\001\024\001\024\001\024\001\ +\000\000\000\000\000\000\000\000\037\001\024\001\024\001\000\000\ +\037\001\037\001\000\000\000\000\000\000\024\001\024\001\024\001\ +\024\001\024\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\024\001\000\000\000\000\000\000\000\000\024\001\000\000\000\000\ +\182\000\000\000\000\000\024\001\024\001\182\000\182\000\000\000\ +\000\000\178\001\000\000\024\001\024\001\024\001\024\001\024\001\ +\024\001\024\001\024\001\024\001\024\001\024\001\024\001\024\001\ +\000\000\000\000\000\000\024\001\024\001\024\001\024\001\024\001\ +\024\001\024\001\024\001\024\001\024\001\024\001\024\001\000\000\ +\000\000\000\000\000\000\024\001\024\001\024\001\000\000\024\001\ +\024\001\188\000\000\000\000\000\182\000\000\000\000\000\000\000\ +\182\000\000\000\024\001\000\000\000\000\000\000\000\000\000\000\ +\024\001\025\001\025\001\025\001\025\001\025\001\025\001\025\001\ +\025\001\000\000\000\000\000\000\000\000\000\000\025\001\025\001\ +\000\000\182\000\000\000\000\000\000\000\000\000\025\001\025\001\ +\025\001\025\001\025\001\000\000\000\000\014\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\015\001\016\001\017\001\ +\018\001\019\001\020\001\000\000\021\001\022\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\ +\001\000\025\001\182\000\023\001\024\001\025\001\025\001\026\001\ +\027\001\028\001\000\000\000\000\025\001\025\001\001\000\001\000\ +\001\000\001\000\001\000\000\000\025\001\025\001\025\001\025\001\ +\025\001\025\001\025\001\025\001\025\001\025\001\025\001\025\001\ +\025\001\000\000\000\000\000\000\025\001\025\001\025\001\025\001\ +\025\001\025\001\025\001\025\001\025\001\025\001\025\001\025\001\ +\192\000\000\000\000\000\000\000\025\001\025\001\025\001\000\000\ +\025\001\025\001\187\000\000\000\029\001\030\001\000\000\187\000\ +\187\000\000\000\000\000\025\001\187\000\000\000\187\000\187\000\ +\000\000\025\001\000\000\031\001\032\001\000\000\187\000\187\000\ +\187\000\187\000\187\000\187\000\187\000\187\000\187\000\000\000\ +\000\000\187\000\187\000\187\000\187\000\000\000\001\000\001\000\ +\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ +\000\000\000\000\000\000\187\000\187\000\187\000\187\000\187\000\ +\187\000\187\000\187\000\187\000\000\000\000\000\000\000\000\000\ +\187\000\000\000\000\000\187\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\044\002\000\000\000\000\000\000\187\000\001\001\ +\002\001\003\001\004\001\187\000\187\000\187\000\000\000\000\000\ +\000\000\000\000\183\000\000\000\187\000\187\000\000\000\183\000\ +\183\000\005\001\030\001\173\001\000\000\006\001\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\187\000\187\000\000\000\ +\000\000\193\000\000\000\000\000\000\000\000\000\187\000\187\000\ +\187\000\187\000\187\000\000\000\187\000\187\000\000\000\000\000\ +\188\000\000\000\000\000\187\000\187\000\188\000\188\000\000\000\ +\000\000\000\000\188\000\000\000\188\000\188\000\183\000\000\000\ +\000\000\000\000\183\000\000\000\188\000\188\000\188\000\188\000\ +\188\000\188\000\188\000\188\000\188\000\000\000\000\000\188\000\ +\188\000\188\000\188\000\000\000\008\001\009\001\010\001\011\001\ +\012\001\000\000\000\000\183\000\000\000\000\000\000\000\000\000\ +\000\000\188\000\188\000\188\000\188\000\188\000\188\000\188\000\ +\188\000\188\000\000\000\000\000\000\000\000\000\188\000\000\000\ +\000\000\188\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\188\000\000\000\000\000\000\000\ +\000\000\188\000\188\000\188\000\000\000\000\000\000\000\000\000\ +\000\000\186\000\188\000\188\000\183\000\000\000\186\000\186\000\ +\000\000\000\000\172\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\194\000\188\000\188\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\188\000\188\000\188\000\188\000\ +\188\000\000\000\188\000\188\000\000\000\000\000\000\000\192\000\ +\000\000\188\000\188\000\000\000\192\000\192\000\000\000\000\000\ +\000\000\192\000\000\000\192\000\192\000\186\000\000\000\000\000\ +\000\000\186\000\000\000\192\000\192\000\192\000\192\000\192\000\ +\192\000\192\000\192\000\192\000\000\000\000\000\192\000\192\000\ +\192\000\192\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\186\000\000\000\000\000\129\002\000\000\000\000\ +\192\000\192\000\192\000\192\000\192\000\192\000\192\000\192\000\ +\192\000\199\000\000\000\000\000\000\000\192\000\199\000\199\000\ +\192\000\000\000\166\001\000\000\000\000\000\000\001\001\002\001\ +\003\001\004\001\000\000\192\000\000\000\000\000\029\001\000\000\ +\192\000\192\000\192\000\000\000\000\000\000\000\000\000\000\000\ +\005\001\192\000\192\000\186\000\006\001\165\000\000\000\000\000\ +\000\000\000\000\000\000\030\001\030\001\030\001\030\001\030\001\ +\030\001\000\000\192\000\192\000\000\000\199\000\000\000\000\000\ +\000\000\199\000\000\000\192\000\192\000\192\000\192\000\192\000\ +\193\000\192\000\192\000\000\000\000\000\193\000\193\000\000\000\ +\192\000\192\000\193\000\000\000\193\000\193\000\000\000\000\000\ +\000\000\000\000\199\000\000\000\193\000\193\000\193\000\193\000\ +\193\000\193\000\193\000\193\000\193\000\000\000\000\000\193\000\ +\193\000\193\000\193\000\008\001\009\001\010\001\011\001\012\001\ +\000\000\000\000\000\000\030\001\000\000\000\000\030\001\000\000\ +\000\000\193\000\193\000\193\000\193\000\193\000\193\000\193\000\ +\193\000\193\000\000\000\000\000\000\000\000\000\193\000\000\000\ +\000\000\193\000\030\001\199\000\000\000\030\001\030\001\030\001\ +\030\001\000\000\030\001\000\000\193\000\000\000\030\001\000\000\ +\000\000\193\000\193\000\193\000\000\000\000\000\000\000\000\000\ +\162\000\000\000\193\000\193\000\000\000\000\000\030\001\030\001\ +\000\000\000\000\030\001\030\001\030\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\193\000\193\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\193\000\193\000\193\000\193\000\ +\193\000\194\000\193\000\193\000\000\000\000\000\194\000\194\000\ +\000\000\193\000\193\000\194\000\000\000\194\000\194\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\194\000\194\000\194\000\ +\194\000\194\000\194\000\194\000\194\000\194\000\000\000\000\000\ +\194\000\194\000\194\000\194\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\132\002\000\000\000\000\000\000\000\000\ +\000\000\000\000\194\000\194\000\194\000\194\000\194\000\194\000\ +\194\000\194\000\194\000\000\000\000\000\000\000\000\000\194\000\ +\000\000\000\000\194\000\000\000\001\001\002\001\003\001\004\001\ +\000\000\000\000\036\001\000\000\000\000\194\000\000\000\000\000\ +\000\000\000\000\194\000\194\000\194\000\000\000\005\001\000\000\ +\000\000\170\000\006\001\194\000\194\000\000\000\000\000\029\001\ +\029\001\029\001\029\001\029\001\029\001\001\000\001\000\000\000\ +\000\000\000\000\000\000\000\000\194\000\194\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\165\000\194\000\194\000\194\000\ +\194\000\194\000\165\000\194\000\194\000\000\000\165\000\000\000\ +\165\000\165\000\194\000\194\000\000\000\000\000\000\000\000\000\ +\165\000\165\000\165\000\165\000\165\000\165\000\165\000\165\000\ +\165\000\000\000\000\000\165\000\165\000\165\000\165\000\000\000\ +\000\000\008\001\009\001\010\001\011\001\012\001\000\000\029\001\ +\000\000\000\000\029\001\000\000\000\000\165\000\165\000\165\000\ +\165\000\165\000\165\000\165\000\000\000\165\000\000\000\000\000\ +\000\000\000\000\165\000\000\000\000\000\165\000\029\001\000\000\ +\000\000\029\001\029\001\029\001\029\001\000\000\029\001\000\000\ +\165\000\000\000\029\001\000\000\000\000\165\000\165\000\165\000\ +\000\000\000\000\000\000\000\000\160\000\000\000\000\000\165\000\ +\000\000\000\000\029\001\029\001\000\000\000\000\029\001\029\001\ +\029\001\000\000\000\000\000\000\000\000\000\000\000\000\165\000\ +\165\000\000\000\000\000\000\000\000\000\000\000\000\000\162\000\ +\165\000\165\000\165\000\165\000\165\000\162\000\165\000\165\000\ +\000\000\162\000\000\000\162\000\162\000\165\000\165\000\000\000\ +\000\000\000\000\000\000\162\000\162\000\162\000\162\000\162\000\ +\162\000\162\000\162\000\162\000\000\000\000\000\162\000\162\000\ +\162\000\162\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\018\001\000\000\000\000\000\000\148\002\000\000\ +\162\000\162\000\162\000\162\000\162\000\162\000\162\000\000\000\ +\162\000\000\000\000\000\000\000\000\000\162\000\000\000\000\000\ +\162\000\000\000\000\000\000\000\000\000\000\000\000\000\001\001\ +\002\001\003\001\004\001\162\000\000\000\000\000\000\000\000\000\ +\162\000\162\000\162\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\005\001\162\000\000\000\000\000\006\001\000\000\000\000\ +\000\000\000\000\000\000\036\001\036\001\036\001\036\001\036\001\ +\036\001\000\000\162\000\162\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\162\000\162\000\162\000\162\000\162\000\ +\170\000\162\000\162\000\000\000\000\000\000\000\170\000\000\000\ +\162\000\162\000\170\000\000\000\170\000\170\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\170\000\170\000\170\000\170\000\ +\170\000\170\000\170\000\170\000\170\000\000\000\000\000\170\000\ +\170\000\170\000\170\000\159\001\008\001\009\001\010\001\011\001\ +\012\001\000\000\000\000\036\001\000\000\000\000\036\001\000\000\ +\000\000\170\000\170\000\170\000\170\000\170\000\170\000\170\000\ +\000\000\170\000\000\000\000\000\000\000\000\000\170\000\000\000\ +\000\000\170\000\036\001\000\000\000\000\036\001\036\001\036\001\ +\036\001\000\000\036\001\000\000\170\000\000\000\036\001\000\000\ +\000\000\170\000\170\000\170\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\170\000\000\000\000\000\036\001\000\000\ +\000\000\000\000\036\001\036\001\036\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\170\000\170\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\160\000\170\000\170\000\170\000\170\000\ +\170\000\160\000\170\000\170\000\000\000\160\000\000\000\160\000\ +\160\000\170\000\170\000\000\000\000\000\000\000\000\000\160\000\ +\160\000\160\000\160\000\160\000\160\000\160\000\160\000\160\000\ +\000\000\000\000\160\000\160\000\160\000\160\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\182\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\160\000\160\000\160\000\000\000\ +\160\000\160\000\160\000\000\000\160\000\000\000\000\000\000\000\ +\000\000\160\000\000\000\000\000\160\000\000\000\000\000\000\000\ +\000\000\018\001\018\001\000\000\000\000\000\000\000\000\160\000\ +\018\001\018\001\000\000\000\000\160\000\160\000\160\000\000\000\ +\018\001\018\001\018\001\018\001\018\001\000\000\160\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\160\000\160\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\160\000\ +\160\000\160\000\160\000\160\000\000\000\160\000\160\000\000\000\ +\000\000\000\000\000\000\000\000\160\000\160\000\018\001\000\000\ +\018\001\000\000\000\000\000\000\000\000\000\000\018\001\018\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\018\001\018\001\ +\018\001\018\001\000\000\018\001\018\001\000\000\000\000\000\000\ +\000\000\018\001\000\000\000\000\000\000\186\000\000\000\018\001\ +\018\001\018\001\018\001\018\001\018\001\018\001\018\001\018\001\ +\018\001\018\001\000\000\000\000\000\000\000\000\000\000\018\001\ +\018\001\000\000\018\001\018\001\018\001\000\000\000\000\159\001\ +\159\001\000\000\000\000\157\001\159\001\018\001\159\001\159\001\ +\000\000\000\000\000\000\018\001\000\000\000\000\159\001\159\001\ +\159\001\159\001\159\001\159\001\159\001\159\001\159\001\000\000\ +\000\000\159\001\159\001\159\001\159\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\154\002\000\000\000\000\159\001\159\001\159\001\159\001\159\001\ +\159\001\159\001\159\001\159\001\000\000\000\000\000\000\000\000\ +\159\001\000\000\000\000\159\001\000\000\000\000\000\000\000\000\ +\000\000\001\001\002\001\003\001\004\001\000\000\159\001\001\001\ +\002\001\003\001\004\001\000\000\159\001\159\001\000\000\000\000\ +\000\000\000\000\000\000\005\001\159\001\159\001\000\000\006\001\ +\000\000\005\001\000\000\000\000\000\000\006\001\204\000\000\000\ +\000\000\133\002\000\000\000\000\000\000\159\001\159\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\159\001\159\001\ +\159\001\159\001\159\001\182\000\159\001\159\001\000\000\000\000\ +\182\000\182\000\000\000\159\001\000\000\182\000\000\000\182\000\ +\182\000\000\000\000\000\000\000\000\000\000\000\000\000\182\000\ +\182\000\182\000\182\000\182\000\182\000\182\000\182\000\182\000\ +\000\000\000\000\182\000\182\000\182\000\182\000\008\001\009\001\ +\010\001\011\001\012\001\000\000\008\001\009\001\010\001\011\001\ +\012\001\156\002\000\000\000\000\182\000\182\000\182\000\182\000\ +\182\000\182\000\182\000\182\000\182\000\000\000\000\000\000\000\ +\000\000\182\000\000\000\000\000\182\000\000\000\000\000\000\000\ +\000\000\000\000\001\001\002\001\003\001\004\001\000\000\182\000\ +\000\000\000\000\029\001\000\000\000\000\182\000\182\000\000\000\ +\000\000\000\000\000\000\000\000\005\001\182\000\182\000\000\000\ +\006\001\045\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\182\000\182\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\182\000\ +\182\000\182\000\182\000\182\000\186\000\182\000\182\000\000\000\ +\000\000\186\000\186\000\000\000\182\000\000\000\186\000\000\000\ +\186\000\186\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\186\000\186\000\186\000\186\000\186\000\186\000\186\000\186\000\ +\186\000\000\000\000\000\186\000\186\000\186\000\186\000\008\001\ +\009\001\010\001\011\001\012\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\096\003\000\000\000\000\186\000\186\000\186\000\ +\186\000\186\000\186\000\186\000\186\000\186\000\000\000\000\000\ +\000\000\000\000\186\000\000\000\000\000\186\000\000\000\000\000\ +\000\000\000\000\000\000\001\001\002\001\003\001\004\001\000\000\ +\186\000\000\000\000\000\000\000\000\000\000\000\186\000\186\000\ +\000\000\000\000\000\000\000\000\081\000\005\001\186\000\186\000\ +\000\000\006\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\186\000\ +\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\186\000\186\000\186\000\186\000\186\000\204\000\186\000\186\000\ +\000\000\000\000\204\000\204\000\000\000\186\000\000\000\204\000\ +\000\000\204\000\204\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\175\003\204\000\204\000\204\000\204\000\204\000\204\000\ +\204\000\204\000\000\000\000\000\204\000\204\000\204\000\204\000\ +\008\001\009\001\010\001\011\001\012\001\000\000\000\000\000\000\ +\000\000\000\000\001\001\002\001\003\001\004\001\204\000\204\000\ +\204\000\204\000\204\000\204\000\204\000\204\000\204\000\000\000\ +\000\000\000\000\000\000\204\000\005\001\000\000\204\000\000\000\ +\006\001\000\000\000\000\030\001\000\000\000\000\000\000\000\000\ +\000\000\204\000\000\000\000\000\000\000\000\000\000\000\204\000\ +\204\000\000\000\080\000\000\000\000\000\000\000\000\000\204\000\ +\204\000\000\000\000\000\029\001\029\001\029\001\029\001\029\001\ +\029\001\001\000\001\000\000\000\000\000\000\000\000\000\000\000\ +\204\000\204\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\204\000\204\000\204\000\204\000\204\000\045\000\204\000\ +\204\000\000\000\045\000\000\000\045\000\045\000\204\000\008\001\ +\009\001\010\001\011\001\012\001\045\000\045\000\045\000\045\000\ +\045\000\045\000\045\000\045\000\045\000\000\000\000\000\045\000\ +\045\000\045\000\045\000\000\000\000\000\000\000\000\000\000\000\ +\126\002\000\000\000\000\029\001\000\000\001\001\002\001\003\001\ +\004\001\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ +\045\000\045\000\000\000\000\000\000\000\000\000\045\000\005\001\ +\000\000\045\000\029\001\006\001\000\000\029\001\029\001\029\001\ +\029\001\000\000\029\001\000\000\045\000\000\000\029\001\000\000\ +\000\000\000\000\045\000\045\000\000\000\157\000\000\000\000\000\ +\000\000\000\000\000\000\045\000\000\000\000\000\029\001\029\001\ +\000\000\000\000\029\001\029\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\045\000\045\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\045\000\045\000\045\000\045\000\ +\045\000\081\000\045\000\045\000\000\000\081\000\000\000\081\000\ +\081\000\045\000\008\001\009\001\010\001\011\001\012\001\081\000\ +\081\000\081\000\081\000\081\000\081\000\081\000\081\000\081\000\ +\000\000\000\000\081\000\081\000\081\000\081\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\081\000\081\000\081\000\081\000\ +\081\000\081\000\081\000\081\000\081\000\000\000\000\000\000\000\ +\000\000\081\000\130\002\000\000\081\000\000\000\000\000\001\001\ +\002\001\003\001\004\001\000\000\069\001\000\000\000\000\081\000\ +\000\000\000\000\000\000\000\000\000\000\081\000\081\000\000\000\ +\046\000\005\001\000\000\000\000\000\000\006\001\081\000\000\000\ +\000\000\000\000\000\000\000\000\030\001\030\001\030\001\030\001\ +\030\001\030\001\000\000\000\000\000\000\000\000\081\000\081\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\030\000\081\000\ +\081\000\081\000\081\000\081\000\000\000\081\000\081\000\080\000\ +\000\000\000\000\000\000\080\000\081\000\080\000\080\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\080\000\080\000\080\000\ +\080\000\080\000\080\000\080\000\080\000\080\000\000\000\000\000\ +\080\000\080\000\080\000\080\000\008\001\009\001\010\001\011\001\ +\012\001\131\002\000\000\000\000\030\001\000\000\001\001\002\001\ +\003\001\004\001\080\000\080\000\080\000\080\000\080\000\080\000\ +\080\000\080\000\080\000\000\000\000\000\000\000\000\000\080\000\ +\005\001\000\000\080\000\030\001\006\001\000\000\030\001\030\001\ +\030\001\030\001\045\001\030\001\000\000\080\000\000\000\030\001\ +\000\000\000\000\000\000\080\000\080\000\000\000\065\000\000\000\ +\198\000\000\000\000\000\000\000\080\000\000\000\000\000\030\001\ +\030\001\000\000\000\000\030\001\030\001\145\003\199\000\200\000\ +\201\000\202\000\203\000\000\000\080\000\080\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\157\000\080\000\080\000\080\000\ +\080\000\080\000\157\000\080\000\080\000\000\000\157\000\000\000\ +\157\000\157\000\080\000\008\001\009\001\010\001\011\001\012\001\ \157\000\157\000\157\000\157\000\157\000\157\000\157\000\157\000\ \157\000\000\000\000\000\157\000\157\000\157\000\157\000\000\000\ -\000\000\000\000\000\000\000\000\076\003\000\000\179\000\000\000\ -\000\000\252\000\253\000\254\000\255\000\157\000\157\000\157\000\ -\000\000\157\000\157\000\157\000\000\000\157\000\000\000\000\000\ -\000\000\000\000\157\000\000\001\000\000\157\000\000\000\001\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\157\000\016\001\016\001\000\000\000\000\157\000\157\000\157\000\ -\016\001\016\001\000\000\000\000\000\000\000\000\000\000\157\000\ -\016\001\016\001\016\001\016\001\016\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\157\000\157\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\157\000\ -\157\000\157\000\000\000\157\000\157\000\000\000\000\000\000\000\ -\000\000\000\000\157\000\157\000\000\000\003\001\004\001\005\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\016\001\000\000\ -\016\001\000\000\000\000\000\000\000\000\000\000\016\001\016\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\016\001\016\001\ -\016\001\016\001\000\000\016\001\016\001\000\000\000\000\000\000\ -\183\000\016\001\000\000\000\000\000\000\000\000\016\001\016\001\ -\016\001\016\001\016\001\016\001\016\001\016\001\016\001\016\001\ -\016\001\000\000\000\000\000\000\000\000\000\000\016\001\016\001\ -\000\000\016\001\016\001\016\001\154\001\154\001\000\000\000\000\ -\152\001\154\001\016\001\154\001\154\001\000\000\000\000\000\000\ -\016\001\000\000\000\000\154\001\154\001\154\001\154\001\154\001\ -\154\001\154\001\154\001\154\001\000\000\000\000\154\001\154\001\ -\154\001\154\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\154\001\154\001\154\001\154\001\154\001\154\001\154\001\154\001\ -\154\001\000\000\000\000\000\000\000\000\154\001\000\000\000\000\ -\154\001\000\000\000\000\034\001\034\001\034\001\034\001\034\001\ -\034\001\000\000\000\000\154\001\035\001\000\000\000\000\000\000\ -\000\000\154\001\154\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\154\001\154\001\000\000\000\000\000\000\201\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\154\001\154\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\154\001\154\001\154\001\179\000\154\001\154\001\ -\000\000\000\000\179\000\179\000\000\000\154\001\000\000\179\000\ -\000\000\179\000\179\000\034\001\000\000\000\000\000\000\000\000\ -\000\000\179\000\179\000\179\000\179\000\179\000\179\000\179\000\ -\179\000\179\000\000\000\000\000\179\000\179\000\179\000\179\000\ -\000\000\000\000\034\001\000\000\000\000\034\001\034\001\034\001\ -\034\001\000\000\034\001\000\000\000\000\000\000\179\000\179\000\ -\179\000\179\000\179\000\179\000\179\000\179\000\179\000\000\000\ -\000\000\000\000\000\000\179\000\000\000\034\001\179\000\000\000\ -\000\000\034\001\034\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\179\000\000\000\000\000\000\000\000\000\000\000\179\000\ -\179\000\000\000\000\000\000\000\000\000\000\000\043\000\000\000\ -\179\000\043\001\000\000\001\000\001\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\179\000\ -\179\000\000\000\001\000\001\000\001\000\001\000\001\000\000\000\ -\179\000\179\000\179\000\000\000\179\000\179\000\000\000\183\000\ -\000\000\000\000\000\000\179\000\183\000\183\000\000\000\000\000\ -\000\000\183\000\000\000\183\000\183\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\183\000\183\000\183\000\183\000\183\000\ -\183\000\183\000\183\000\183\000\000\000\000\000\183\000\183\000\ -\183\000\183\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\183\000\183\000\183\000\183\000\183\000\183\000\183\000\183\000\ -\183\000\000\000\000\000\000\000\000\000\183\000\000\000\000\000\ -\183\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\183\000\000\000\000\000\078\000\000\000\ -\000\000\183\000\183\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\183\000\000\000\000\000\035\001\035\001\035\001\ -\035\001\035\001\035\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\183\000\183\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\183\000\183\000\183\000\201\000\183\000\183\000\ -\000\000\000\000\201\000\201\000\000\000\183\000\000\000\201\000\ -\000\000\201\000\201\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\201\000\201\000\201\000\201\000\201\000\201\000\ -\201\000\201\000\000\000\000\000\201\000\201\000\201\000\201\000\ -\000\000\000\000\000\000\000\000\000\000\035\001\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\201\000\201\000\ -\201\000\201\000\201\000\201\000\201\000\201\000\201\000\000\000\ -\044\001\000\000\000\000\201\000\035\001\000\000\201\000\035\001\ -\035\001\035\001\035\001\000\000\035\001\000\000\077\000\000\000\ -\000\000\201\000\000\000\000\000\000\000\000\000\000\000\201\000\ -\201\000\000\000\000\000\000\000\000\000\000\000\000\000\035\001\ -\201\000\000\000\000\000\035\001\035\001\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\201\000\ -\201\000\000\000\043\001\043\001\043\001\043\001\043\001\043\001\ -\201\000\201\000\201\000\043\000\201\000\201\000\000\000\043\000\ -\000\000\043\000\043\000\201\000\000\000\000\000\000\000\000\000\ -\000\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ -\043\000\043\000\000\000\000\000\043\000\043\000\043\000\043\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\043\000\043\000\ -\043\000\043\000\043\000\043\000\043\000\043\000\043\000\000\000\ -\000\000\000\000\043\001\043\000\000\000\000\000\043\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\154\000\000\000\ -\000\000\043\000\000\000\000\000\000\000\000\000\000\000\043\000\ -\043\000\043\001\000\000\000\000\043\001\043\001\043\001\043\001\ -\043\000\043\001\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\043\000\ -\043\000\000\000\000\000\000\000\043\001\000\000\000\000\000\000\ -\043\000\043\000\043\000\078\000\043\000\043\000\000\000\078\000\ -\000\000\078\000\078\000\043\000\000\000\000\000\000\000\000\000\ -\000\000\078\000\078\000\078\000\078\000\078\000\078\000\078\000\ -\078\000\078\000\000\000\000\000\078\000\078\000\078\000\078\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\078\000\078\000\ -\078\000\078\000\078\000\078\000\078\000\078\000\078\000\000\000\ -\000\000\000\000\000\000\078\000\000\000\000\000\078\000\000\000\ -\000\000\000\000\044\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\078\000\000\000\000\000\000\000\000\000\000\000\078\000\ -\078\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\078\000\044\001\044\001\044\001\044\001\044\001\044\001\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\078\000\ -\078\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\078\000\078\000\078\000\077\000\078\000\078\000\000\000\077\000\ -\000\000\077\000\077\000\078\000\000\000\000\000\000\000\000\000\ -\000\000\077\000\077\000\077\000\077\000\077\000\077\000\077\000\ -\077\000\077\000\000\000\000\000\077\000\077\000\077\000\077\000\ -\000\000\062\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\044\001\000\000\000\000\000\000\000\000\077\000\077\000\ -\077\000\077\000\077\000\077\000\077\000\077\000\077\000\000\000\ -\000\000\000\000\000\000\077\000\000\000\000\000\077\000\000\000\ -\044\001\000\000\000\000\044\001\044\001\044\001\044\001\000\000\ -\044\001\077\000\000\000\000\000\000\000\000\000\000\000\077\000\ -\077\000\000\000\194\000\000\000\000\000\000\000\000\000\000\000\ -\077\000\000\000\000\000\044\001\000\000\000\000\000\000\124\003\ -\195\000\196\000\197\000\198\000\199\000\000\000\000\000\077\000\ -\077\000\000\000\000\000\000\000\000\000\154\000\000\000\000\000\ -\077\000\077\000\077\000\154\000\077\000\077\000\000\000\154\000\ -\000\000\154\000\154\000\077\000\000\000\000\000\000\000\000\000\ -\000\000\154\000\154\000\154\000\154\000\154\000\154\000\154\000\ -\154\000\154\000\000\000\000\000\154\000\154\000\154\000\154\000\ -\000\000\063\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\154\000\154\000\ -\154\000\000\000\154\000\154\000\154\000\000\000\154\000\000\000\ -\000\000\000\000\000\000\154\000\000\000\000\000\154\000\200\000\ -\201\000\202\000\203\000\204\000\205\000\206\000\207\000\208\000\ -\209\000\154\000\000\000\000\000\000\000\000\000\146\000\154\000\ -\154\000\000\000\000\000\000\000\000\000\000\000\176\001\000\000\ -\154\000\000\000\000\000\000\000\146\000\146\000\146\000\146\000\ -\146\000\000\000\000\000\000\000\000\000\000\000\000\000\154\000\ -\154\000\000\000\000\000\000\000\000\000\000\000\000\000\044\000\ -\154\000\154\000\154\000\044\000\154\000\154\000\044\000\000\000\ -\000\000\000\000\000\000\154\000\000\000\044\000\044\000\044\000\ -\044\000\044\000\044\000\044\000\000\000\044\000\000\000\000\000\ -\044\000\044\000\044\000\044\000\000\000\065\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\044\000\044\000\044\000\044\000\044\000\044\000\ -\044\000\000\000\044\000\000\000\000\000\000\000\000\000\044\000\ -\000\000\000\000\044\000\146\000\146\000\146\000\146\000\146\000\ -\146\000\146\000\146\000\146\000\146\000\044\000\000\000\000\000\ -\145\000\000\000\000\000\044\000\044\000\000\000\062\000\000\000\ -\160\001\000\000\062\000\000\000\044\000\062\000\145\000\145\000\ -\145\000\145\000\145\000\000\000\062\000\062\000\062\000\062\000\ -\062\000\062\000\062\000\000\000\062\000\000\000\000\000\062\000\ -\062\000\062\000\062\000\000\000\044\000\044\000\044\000\000\000\ -\044\000\044\000\000\000\000\000\000\000\000\000\000\000\044\000\ -\000\000\062\000\062\000\062\000\062\000\062\000\062\000\062\000\ -\194\000\062\000\000\000\000\000\000\000\000\000\062\000\000\000\ -\000\000\062\000\000\000\000\000\000\000\066\000\195\000\196\000\ -\197\000\198\000\199\000\000\000\062\000\000\000\000\000\000\000\ -\000\000\000\000\062\000\062\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\062\000\000\000\145\000\145\000\145\000\ -\145\000\145\000\145\000\145\000\145\000\145\000\145\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\062\000\062\000\062\000\063\000\062\000\ -\062\000\000\000\063\000\000\000\000\000\063\000\062\000\000\000\ -\000\000\000\000\000\000\000\000\063\000\063\000\063\000\063\000\ -\063\000\063\000\063\000\000\000\063\000\000\000\000\000\063\000\ -\063\000\063\000\063\000\000\000\064\000\200\000\201\000\202\000\ -\203\000\204\000\205\000\206\000\207\000\208\000\209\000\000\000\ -\000\000\063\000\063\000\063\000\063\000\063\000\063\000\063\000\ -\000\000\063\000\000\000\000\000\000\000\000\000\063\000\000\000\ -\000\000\063\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\063\000\000\000\000\000\000\000\ -\000\000\005\000\063\000\063\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\063\000\000\000\000\000\000\000\005\000\ -\005\000\005\000\005\000\005\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\065\000\063\000\063\000\063\000\065\000\063\000\ -\063\000\065\000\000\000\000\000\000\000\000\000\063\000\000\000\ -\065\000\065\000\065\000\065\000\065\000\065\000\065\000\000\000\ -\065\000\000\000\000\000\065\000\065\000\065\000\065\000\000\000\ -\055\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\065\000\065\000\065\000\ -\065\000\065\000\065\000\065\000\000\000\065\000\000\000\000\000\ -\000\000\000\000\065\000\000\000\000\000\065\000\005\000\005\000\ -\005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ -\065\000\000\000\000\000\000\000\000\000\000\000\065\000\065\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\065\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\065\000\ -\065\000\065\000\066\000\065\000\065\000\000\000\066\000\000\000\ -\000\000\066\000\065\000\000\000\000\000\000\000\000\000\000\000\ -\066\000\066\000\066\000\066\000\066\000\066\000\066\000\000\000\ -\066\000\000\000\000\000\066\000\066\000\066\000\066\000\000\000\ -\056\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\066\000\066\000\066\000\ -\066\000\066\000\066\000\066\000\000\000\066\000\000\000\000\000\ -\000\000\000\000\066\000\000\000\000\000\066\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\066\000\000\000\000\000\000\000\000\000\000\000\066\000\066\000\ -\000\000\064\000\000\000\000\000\000\000\064\000\000\000\066\000\ -\064\000\000\000\000\000\000\000\000\000\000\000\000\000\064\000\ -\064\000\064\000\064\000\064\000\064\000\064\000\000\000\064\000\ -\000\000\000\000\064\000\064\000\064\000\064\000\000\000\066\000\ -\066\000\066\000\000\000\066\000\066\000\000\000\000\000\000\000\ -\000\000\000\000\066\000\000\000\064\000\064\000\064\000\064\000\ -\064\000\064\000\064\000\000\000\064\000\000\000\000\000\000\000\ -\000\000\064\000\000\000\000\000\064\000\000\000\000\000\000\000\ -\057\000\000\000\000\000\000\000\000\000\000\000\000\000\064\000\ -\000\000\000\000\000\000\000\000\000\000\064\000\064\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\064\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\055\000\064\000\064\000\ -\064\000\055\000\064\000\064\000\055\000\000\000\000\000\000\000\ -\000\000\064\000\000\000\055\000\055\000\055\000\055\000\055\000\ -\055\000\055\000\000\000\055\000\000\000\000\000\055\000\055\000\ -\055\000\055\000\000\000\000\000\000\000\000\000\000\000\084\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\055\000\055\000\055\000\055\000\055\000\055\000\055\000\000\000\ -\055\000\000\000\000\000\000\000\000\000\055\000\000\000\000\000\ -\055\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\055\000\000\000\000\000\000\000\000\000\ -\000\000\055\000\055\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\055\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\157\000\157\000\157\000\ +\000\000\157\000\157\000\157\000\000\000\157\000\000\000\000\000\ +\000\000\000\000\157\000\000\000\000\000\157\000\204\000\205\000\ +\206\000\207\000\208\000\209\000\210\000\211\000\212\000\213\000\ +\157\000\000\000\000\000\000\000\000\000\000\000\157\000\157\000\ +\000\000\066\000\000\000\000\000\000\000\000\000\000\000\157\000\ +\000\000\000\000\000\000\000\000\000\000\069\001\069\001\069\001\ +\069\001\069\001\069\001\000\000\000\000\000\000\000\000\157\000\ +\157\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\157\000\157\000\157\000\157\000\157\000\046\000\157\000\157\000\ +\000\000\046\000\000\000\000\000\046\000\157\000\000\000\000\000\ +\000\000\000\000\000\000\046\000\046\000\046\000\046\000\046\000\ +\046\000\046\000\000\000\046\000\000\000\000\000\046\000\046\000\ +\046\000\046\000\000\000\030\000\000\000\000\000\000\000\030\000\ +\000\000\000\000\030\000\000\000\000\000\069\001\000\000\000\000\ +\046\000\046\000\046\000\046\000\046\000\046\000\046\000\030\000\ +\046\000\000\000\000\000\000\000\000\000\046\000\000\000\000\000\ +\046\000\000\000\000\000\000\000\069\001\000\000\000\000\069\001\ +\069\001\069\001\069\001\046\000\069\001\000\000\000\000\000\000\ +\069\001\046\000\046\000\000\000\068\000\000\000\030\000\000\000\ +\000\000\000\000\046\000\030\000\000\000\000\000\030\000\000\000\ +\069\001\000\000\000\000\045\001\045\001\045\001\045\001\045\001\ +\045\001\030\000\000\000\000\000\000\000\000\000\000\000\030\000\ +\030\000\000\000\031\000\046\000\046\000\046\000\046\000\046\000\ +\030\000\046\000\046\000\065\000\000\000\000\000\000\000\065\000\ +\046\000\000\000\065\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\065\000\065\000\065\000\065\000\065\000\065\000\065\000\ +\000\000\065\000\000\000\000\000\065\000\065\000\065\000\065\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\ +\000\000\000\000\000\000\045\001\000\000\000\000\065\000\065\000\ +\065\000\065\000\065\000\065\000\065\000\000\000\065\000\000\000\ +\000\000\000\000\000\000\065\000\000\000\000\000\065\000\000\000\ +\000\000\000\000\045\001\046\001\000\000\045\001\045\001\045\001\ +\045\001\065\000\045\001\000\000\000\000\000\000\045\001\065\000\ +\065\000\000\000\069\000\000\000\149\000\000\000\000\000\000\000\ +\065\000\000\000\000\000\000\000\181\001\000\000\045\001\000\000\ +\000\000\000\000\149\000\149\000\149\000\149\000\149\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\065\000\065\000\065\000\065\000\065\000\066\000\065\000\ +\065\000\000\000\066\000\000\000\000\000\066\000\065\000\000\000\ +\000\000\000\000\000\000\000\000\066\000\066\000\066\000\066\000\ +\066\000\066\000\066\000\000\000\066\000\000\000\000\000\066\000\ +\066\000\066\000\066\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\066\000\066\000\066\000\066\000\066\000\066\000\066\000\ +\000\000\066\000\000\000\000\000\000\000\000\000\066\000\000\000\ +\000\000\066\000\149\000\149\000\149\000\149\000\149\000\149\000\ +\149\000\149\000\149\000\149\000\066\000\000\000\000\000\000\000\ +\000\000\000\000\066\000\066\000\000\000\067\000\000\000\148\000\ +\000\000\000\000\000\000\066\000\000\000\000\000\000\000\165\001\ +\000\000\000\000\000\000\000\000\000\000\148\000\148\000\148\000\ +\148\000\148\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\066\000\066\000\066\000\066\000\ +\066\000\068\000\066\000\066\000\000\000\068\000\000\000\000\000\ +\068\000\066\000\000\000\000\000\000\000\000\000\000\000\068\000\ +\068\000\068\000\068\000\068\000\068\000\068\000\000\000\068\000\ +\000\000\000\000\068\000\068\000\068\000\068\000\000\000\031\000\ +\000\000\000\000\000\000\031\000\000\000\000\000\031\000\000\000\ +\000\000\000\000\000\000\000\000\068\000\068\000\068\000\068\000\ +\068\000\068\000\068\000\031\000\068\000\000\000\000\000\000\000\ +\000\000\068\000\000\000\000\000\068\000\148\000\148\000\148\000\ +\148\000\148\000\148\000\148\000\148\000\148\000\148\000\068\000\ +\000\000\000\000\000\000\000\000\000\000\068\000\068\000\000\000\ +\058\000\000\000\031\000\000\000\000\000\000\000\068\000\031\000\ +\000\000\000\000\031\000\000\000\046\001\046\001\046\001\046\001\ +\046\001\046\001\000\000\000\000\000\000\031\000\000\000\000\000\ +\000\000\000\000\000\000\031\000\031\000\000\000\032\000\068\000\ +\068\000\068\000\068\000\068\000\031\000\068\000\068\000\069\000\ +\000\000\000\000\000\000\069\000\068\000\000\000\069\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\069\000\069\000\069\000\ +\069\000\069\000\069\000\069\000\000\000\069\000\000\000\000\000\ +\069\000\069\000\069\000\069\000\000\000\000\000\000\000\000\000\ +\000\000\097\003\031\000\000\000\046\001\000\000\001\001\002\001\ +\003\001\004\001\069\000\069\000\069\000\069\000\069\000\069\000\ +\069\000\000\000\069\000\000\000\000\000\000\000\000\000\069\000\ +\005\001\000\000\069\000\046\001\006\001\000\000\046\001\046\001\ +\046\001\046\001\000\000\046\001\000\000\069\000\000\000\046\001\ +\000\000\000\000\000\000\069\000\069\000\000\000\059\000\000\000\ +\198\000\000\000\000\000\000\000\069\000\000\000\000\000\046\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\199\000\200\000\ +\201\000\202\000\203\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\069\000\069\000\069\000\ +\069\000\069\000\067\000\069\000\069\000\000\000\067\000\000\000\ +\000\000\067\000\069\000\008\001\009\001\010\001\011\001\012\001\ +\067\000\067\000\067\000\067\000\067\000\067\000\067\000\000\000\ +\067\000\000\000\000\000\067\000\067\000\067\000\067\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\067\000\067\000\067\000\ +\067\000\067\000\067\000\067\000\000\000\067\000\000\000\000\000\ +\000\000\000\000\067\000\000\000\000\000\067\000\204\000\205\000\ +\206\000\207\000\208\000\209\000\210\000\211\000\212\000\213\000\ +\067\000\000\000\000\000\000\000\000\000\000\000\067\000\067\000\ +\000\000\060\000\000\000\005\000\000\000\000\000\000\000\067\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\005\000\005\000\005\000\005\000\005\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\067\000\067\000\067\000\067\000\067\000\058\000\067\000\067\000\ +\000\000\058\000\000\000\000\000\058\000\067\000\000\000\000\000\ +\000\000\000\000\000\000\058\000\058\000\058\000\058\000\058\000\ +\058\000\058\000\000\000\058\000\000\000\000\000\058\000\058\000\ +\058\000\058\000\000\000\032\000\000\000\000\000\000\000\032\000\ +\000\000\000\000\032\000\000\000\000\000\000\000\000\000\000\000\ +\058\000\058\000\058\000\058\000\058\000\058\000\058\000\032\000\ +\058\000\000\000\000\000\000\000\000\000\058\000\000\000\000\000\ +\058\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ +\005\000\005\000\005\000\058\000\000\000\000\000\000\000\000\000\ +\000\000\058\000\058\000\000\000\087\000\000\000\032\000\000\000\ +\000\000\000\000\058\000\032\000\000\000\000\000\032\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\032\000\000\000\000\000\000\000\000\000\000\000\032\000\ +\032\000\000\000\024\000\058\000\058\000\058\000\058\000\058\000\ +\032\000\058\000\058\000\059\000\000\000\000\000\000\000\059\000\ +\058\000\000\000\059\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\059\000\059\000\059\000\059\000\059\000\059\000\059\000\ +\000\000\059\000\000\000\000\000\059\000\059\000\059\000\059\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\032\000\000\000\ +\000\000\000\000\001\001\002\001\003\001\004\001\059\000\059\000\ +\059\000\059\000\059\000\059\000\059\000\000\000\059\000\000\000\ +\000\000\000\000\000\000\059\000\005\001\000\000\059\000\000\000\ +\006\001\000\000\000\000\000\000\158\002\000\000\000\000\000\000\ +\000\000\059\000\000\000\000\000\000\000\000\000\000\000\059\000\ +\059\000\000\000\089\000\000\000\000\000\000\000\000\000\000\000\ +\059\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\059\000\059\000\059\000\059\000\059\000\060\000\059\000\ +\059\000\000\000\060\000\000\000\000\000\060\000\059\000\008\001\ +\009\001\010\001\011\001\012\001\060\000\060\000\060\000\060\000\ +\060\000\060\000\060\000\000\000\060\000\000\000\000\000\060\000\ +\060\000\060\000\060\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\001\001\002\001\003\001\ +\004\001\060\000\060\000\060\000\060\000\060\000\060\000\060\000\ +\000\000\060\000\000\000\000\000\000\000\000\000\060\000\005\001\ +\000\000\060\000\000\000\006\001\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\060\000\000\000\000\000\000\000\ +\000\000\000\000\060\000\060\000\000\000\086\000\000\000\000\000\ +\000\000\000\000\000\000\060\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\148\003\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\060\000\060\000\060\000\060\000\ +\060\000\087\000\060\000\060\000\000\000\087\000\000\000\000\000\ +\087\000\060\000\008\001\009\001\010\001\011\001\012\001\087\000\ +\087\000\087\000\087\000\087\000\087\000\087\000\000\000\087\000\ +\000\000\000\000\087\000\087\000\087\000\087\000\000\000\024\000\ +\000\000\000\000\000\000\024\000\000\000\000\000\024\000\000\000\ +\056\000\000\000\000\000\000\000\087\000\087\000\087\000\087\000\ +\087\000\087\000\087\000\024\000\087\000\000\000\000\000\000\000\ +\000\000\087\000\000\000\000\000\087\000\000\000\000\000\001\001\ +\002\001\003\001\004\001\000\000\000\000\000\000\000\000\087\000\ +\000\000\000\000\000\000\000\000\000\000\087\000\087\000\000\000\ +\000\000\005\001\024\000\000\000\000\000\006\001\087\000\024\000\ +\000\000\000\000\024\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\024\000\000\000\000\000\ +\000\000\000\000\000\000\024\000\024\000\000\000\000\000\087\000\ +\087\000\087\000\087\000\087\000\024\000\087\000\087\000\089\000\ +\000\000\000\000\000\000\089\000\087\000\000\000\089\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\089\000\089\000\089\000\ +\089\000\089\000\089\000\089\000\000\000\089\000\000\000\000\000\ +\089\000\089\000\089\000\089\000\008\001\009\001\010\001\011\001\ +\012\001\000\000\024\000\082\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\089\000\089\000\089\000\089\000\089\000\089\000\ +\089\000\000\000\089\000\000\000\000\000\000\000\000\000\089\000\ +\000\000\000\000\089\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\089\000\000\000\000\000\ +\000\000\000\000\000\000\089\000\089\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\089\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\089\000\089\000\089\000\ +\089\000\089\000\086\000\089\000\089\000\000\000\086\000\000\000\ +\000\000\086\000\089\000\000\000\000\000\000\000\000\000\000\000\ +\086\000\086\000\086\000\086\000\086\000\086\000\086\000\000\000\ +\086\000\000\000\000\000\086\000\086\000\086\000\086\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\083\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\086\000\086\000\086\000\ +\086\000\086\000\086\000\086\000\000\000\086\000\000\000\000\000\ +\000\000\000\000\086\000\000\000\000\000\086\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\055\000\055\000\055\000\056\000\055\000\055\000\ -\000\000\056\000\000\000\000\000\056\000\055\000\000\000\000\000\ +\086\000\000\000\000\000\000\000\000\000\056\000\086\000\086\000\ +\000\000\056\000\000\000\000\000\056\000\000\000\000\000\086\000\ \000\000\000\000\000\000\056\000\056\000\056\000\056\000\056\000\ \056\000\056\000\000\000\056\000\000\000\000\000\056\000\056\000\ -\056\000\056\000\000\000\086\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\056\000\056\000\056\000\056\000\056\000\056\000\056\000\000\000\ -\056\000\000\000\000\000\000\000\000\000\056\000\000\000\000\000\ -\056\000\015\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\056\000\000\000\000\000\000\000\000\000\ +\056\000\056\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\086\000\086\000\086\000\086\000\086\000\033\000\086\000\086\000\ +\056\000\056\000\056\000\000\000\056\000\086\000\219\000\198\000\ +\056\000\000\000\000\000\213\001\000\000\056\000\000\000\000\000\ +\056\000\000\000\000\000\000\000\000\000\199\000\200\000\201\000\ +\202\000\203\000\000\000\056\000\000\000\000\000\000\000\000\000\ \000\000\056\000\056\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\056\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\056\000\056\000\056\000\057\000\056\000\056\000\ -\000\000\057\000\000\000\000\000\057\000\056\000\000\000\000\000\ -\000\000\000\000\000\000\057\000\057\000\057\000\057\000\057\000\ -\057\000\057\000\000\000\057\000\000\000\000\000\057\000\057\000\ -\057\000\057\000\000\000\083\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\057\000\057\000\057\000\057\000\057\000\057\000\057\000\000\000\ -\057\000\000\000\000\000\000\000\000\000\057\000\000\000\000\000\ -\057\000\014\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\057\000\000\000\000\000\000\000\000\000\ -\000\000\057\000\057\000\000\000\084\000\000\000\000\000\000\000\ -\084\000\000\000\057\000\084\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\084\000\084\000\084\000\084\000\084\000\084\000\ -\084\000\000\000\084\000\000\000\000\000\084\000\084\000\084\000\ -\084\000\000\000\057\000\057\000\057\000\000\000\057\000\057\000\ -\000\000\000\000\000\000\000\000\000\000\057\000\000\000\084\000\ -\084\000\084\000\084\000\084\000\084\000\084\000\000\000\084\000\ -\000\000\000\000\000\000\000\000\084\000\000\000\000\000\084\000\ -\000\000\000\000\000\000\054\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\084\000\000\000\000\000\000\000\000\000\000\000\ -\084\000\084\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\084\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\086\000\084\000\084\000\084\000\086\000\084\000\084\000\086\000\ -\000\000\000\000\000\000\000\000\084\000\000\000\086\000\086\000\ -\086\000\086\000\086\000\086\000\086\000\000\000\086\000\000\000\ -\000\000\086\000\086\000\086\000\086\000\053\000\015\000\000\000\ -\000\000\000\000\015\000\000\000\000\000\015\000\000\000\000\000\ -\000\000\000\000\000\000\086\000\086\000\086\000\086\000\086\000\ -\086\000\086\000\015\000\086\000\000\000\000\000\000\000\015\000\ -\086\000\000\000\000\000\086\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\086\000\000\000\ -\000\000\015\000\000\000\000\000\086\000\086\000\000\000\000\000\ -\000\000\015\000\000\000\000\000\000\000\086\000\015\000\000\000\ -\000\000\015\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\015\000\000\000\000\000\079\000\ -\000\000\000\000\015\000\015\000\000\000\086\000\086\000\086\000\ -\083\000\086\000\086\000\015\000\083\000\000\000\000\000\083\000\ -\086\000\000\000\000\000\000\000\000\000\000\000\083\000\083\000\ -\083\000\083\000\083\000\083\000\083\000\000\000\083\000\000\000\ -\000\000\083\000\083\000\083\000\083\000\000\000\014\000\000\000\ -\000\000\000\000\014\000\000\000\000\000\014\000\015\000\000\000\ -\000\000\000\000\000\000\083\000\083\000\083\000\083\000\083\000\ -\083\000\083\000\014\000\083\000\000\000\000\000\000\000\014\000\ -\083\000\000\000\000\000\083\000\000\000\000\000\000\000\000\000\ -\000\000\080\000\000\000\000\000\000\000\000\000\083\000\000\000\ -\000\000\014\000\000\000\000\000\083\000\083\000\000\000\000\000\ -\000\000\014\000\000\000\000\000\000\000\083\000\014\000\000\000\ -\000\000\014\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\014\000\000\000\000\000\000\000\ -\000\000\000\000\014\000\014\000\000\000\083\000\083\000\083\000\ -\054\000\083\000\083\000\014\000\054\000\000\000\000\000\054\000\ -\083\000\000\000\000\000\000\000\000\000\000\000\054\000\054\000\ -\054\000\054\000\054\000\054\000\054\000\000\000\054\000\000\000\ -\000\000\054\000\054\000\054\000\054\000\000\000\000\000\000\000\ -\021\000\000\000\000\000\000\000\000\000\000\000\014\000\000\000\ -\000\000\000\000\000\000\054\000\054\000\054\000\000\000\054\000\ -\000\000\000\000\000\000\054\000\000\000\000\000\000\000\000\000\ -\054\000\000\000\000\000\054\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\054\000\000\000\ -\000\000\000\000\053\000\000\000\054\000\054\000\053\000\000\000\ -\000\000\053\000\000\000\000\000\000\000\054\000\000\000\000\000\ -\053\000\053\000\053\000\053\000\053\000\053\000\053\000\000\000\ -\053\000\000\000\000\000\053\000\053\000\053\000\053\000\017\000\ -\000\000\000\000\000\000\000\000\000\000\054\000\054\000\054\000\ -\000\000\054\000\054\000\000\000\000\000\053\000\053\000\053\000\ -\054\000\053\000\000\000\000\000\000\000\053\000\000\000\000\000\ -\000\000\000\000\053\000\000\000\000\000\053\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\ -\053\000\000\000\000\000\000\000\079\000\000\000\053\000\053\000\ -\079\000\000\000\000\000\079\000\000\000\000\000\000\000\053\000\ -\000\000\000\000\079\000\079\000\079\000\079\000\079\000\079\000\ -\079\000\000\000\079\000\000\000\000\000\079\000\079\000\079\000\ -\079\000\029\000\000\000\000\000\000\000\000\000\000\000\053\000\ -\053\000\053\000\000\000\053\000\053\000\000\000\000\000\079\000\ -\000\000\000\000\053\000\079\000\000\000\000\000\000\000\079\000\ -\030\000\000\000\000\000\000\000\079\000\000\000\000\000\079\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\079\000\000\000\000\000\000\000\080\000\000\000\ -\079\000\079\000\080\000\000\000\000\000\080\000\022\000\000\000\ -\000\000\079\000\000\000\000\000\080\000\080\000\080\000\080\000\ -\080\000\080\000\080\000\000\000\080\000\000\000\000\000\080\000\ -\080\000\080\000\080\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\079\000\079\000\079\000\000\000\079\000\079\000\000\000\ -\000\000\080\000\000\000\027\000\079\000\080\000\000\000\000\000\ -\000\000\080\000\000\000\000\000\000\000\000\000\080\000\000\000\ -\000\000\080\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\080\000\000\000\000\000\000\000\ -\000\000\000\000\080\000\080\000\000\000\021\000\043\001\000\000\ -\000\000\021\000\000\000\080\000\021\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\021\000\000\000\000\000\000\000\000\000\021\000\021\000\ -\021\000\021\000\000\000\080\000\080\000\080\000\000\000\080\000\ -\080\000\000\000\000\000\027\001\000\000\000\000\080\000\000\000\ -\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\021\000\000\000\000\000\000\000\000\000\021\000\000\000\000\000\ -\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\021\000\017\000\000\000\000\000\000\000\ -\017\000\021\000\021\000\017\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\021\000\000\000\000\000\000\000\000\000\000\000\ -\017\000\000\000\000\000\000\000\000\000\017\000\017\000\017\000\ -\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\016\000\021\000\021\000\021\000\016\000\000\000\017\000\ -\016\000\000\000\000\000\000\000\000\000\021\000\000\000\017\000\ -\000\000\000\000\000\000\000\000\017\000\016\000\000\000\017\000\ -\000\000\000\000\016\000\016\000\000\000\016\000\000\000\000\000\ -\000\000\000\000\017\000\000\000\000\000\000\000\029\000\000\000\ -\017\000\017\000\029\000\000\000\016\000\029\000\000\000\000\000\ -\000\000\017\000\000\000\000\000\016\000\000\000\000\000\000\000\ -\000\000\016\000\029\000\000\000\016\000\030\000\000\000\000\000\ -\000\000\030\000\000\000\000\000\030\000\000\000\000\000\016\000\ -\000\000\000\000\017\000\000\000\000\000\016\000\016\000\000\000\ -\000\000\030\000\000\000\000\000\017\000\000\000\016\000\000\000\ -\000\000\029\000\000\000\022\000\000\000\000\000\029\000\022\000\ -\000\000\029\000\022\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\029\000\000\000\000\000\022\000\ -\030\000\000\000\029\000\029\000\000\000\030\000\000\000\000\000\ -\030\000\016\000\000\000\029\000\000\000\000\000\000\000\000\000\ -\027\000\000\000\000\000\030\000\027\000\000\000\000\000\027\000\ -\000\000\030\000\030\000\000\000\000\000\000\000\022\000\000\000\ -\000\000\000\000\030\000\022\000\027\000\000\000\022\000\043\001\ -\043\001\043\001\043\001\043\001\043\001\000\000\029\000\000\000\ -\000\000\022\000\000\000\000\000\000\000\000\000\000\000\022\000\ -\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\022\000\000\000\000\000\027\000\000\000\030\000\000\000\000\000\ -\027\000\000\000\000\000\027\000\027\001\027\001\027\001\027\001\ -\027\001\027\001\001\000\001\000\000\000\000\000\027\000\000\000\ -\000\000\000\000\000\000\000\000\027\000\027\000\000\000\000\000\ -\000\000\000\000\000\000\022\000\000\000\027\000\000\000\043\001\ -\000\000\000\000\043\001\000\000\000\000\000\000\000\000\000\000\ -\000\000\043\001\043\001\043\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\043\001\043\001\043\001\043\001\043\001\000\000\ -\000\000\043\001\043\001\043\001\043\001\000\000\043\001\000\000\ -\027\000\000\000\000\000\000\000\027\001\000\000\000\000\027\001\ -\000\000\000\000\000\000\000\000\000\000\000\000\027\001\000\000\ -\000\000\043\001\043\001\000\000\000\000\000\000\000\000\043\001\ -\000\000\000\000\000\000\027\001\000\000\000\000\027\001\027\001\ -\027\001\027\001\000\000\027\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\027\001\027\001\ -\000\000\027\001\027\001\027\001\027\001\006\000\007\000\008\000\ -\009\000\010\000\011\000\034\001\013\000\065\001\066\001\067\001\ -\068\001\069\001\018\000\019\000\070\001\071\001\072\001\073\001\ -\074\001\075\001\020\000\021\000\022\000\023\000\024\000\076\001\ -\077\001\078\001\079\001\080\001\081\001\082\001\083\001\084\001\ -\085\001\086\001\087\001\088\001\089\001\090\001\091\001\092\001\ +\000\000\000\000\205\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\056\000\056\000\056\000\056\000\056\000\ +\082\000\056\000\056\000\000\000\082\000\000\000\000\000\082\000\ +\056\000\000\000\000\000\000\000\000\000\000\000\082\000\082\000\ +\082\000\082\000\082\000\082\000\082\000\000\000\082\000\000\000\ +\023\000\082\000\082\000\082\000\082\000\204\000\205\000\206\000\ +\207\000\208\000\209\000\210\000\211\000\212\000\213\000\000\000\ +\000\000\000\000\000\000\082\000\000\000\000\000\000\000\082\000\ +\000\000\000\000\000\000\082\000\000\000\000\000\000\000\000\000\ +\082\000\000\000\000\000\082\000\000\000\001\001\002\001\003\001\ +\004\001\022\000\000\000\000\000\000\000\000\000\082\000\000\000\ +\000\000\000\000\000\000\000\000\082\000\082\000\000\000\005\001\ +\000\000\000\000\000\000\006\001\000\000\082\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\082\000\082\000\ +\082\000\082\000\082\000\083\000\082\000\082\000\000\000\083\000\ +\000\000\232\001\083\000\082\000\000\000\000\000\020\000\000\000\ +\000\000\083\000\083\000\083\000\083\000\083\000\083\000\083\000\ +\000\000\083\000\000\000\000\000\083\000\083\000\083\000\083\000\ +\000\000\000\000\008\001\009\001\010\001\011\001\233\001\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\083\000\234\001\ +\000\000\000\000\083\000\000\000\000\000\000\000\083\000\017\000\ +\000\000\000\000\000\000\083\000\000\000\000\000\083\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\083\000\000\000\000\000\000\000\000\000\000\000\083\000\ +\083\000\000\000\033\000\000\000\000\000\000\000\033\000\000\000\ +\083\000\033\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\018\000\000\000\000\000\000\000\000\000\000\000\033\000\000\000\ +\000\000\000\000\000\000\033\000\033\000\033\000\033\000\000\000\ +\000\000\083\000\083\000\083\000\083\000\083\000\000\000\083\000\ +\083\000\000\000\000\000\000\000\000\000\033\000\083\000\000\000\ +\000\000\033\000\000\000\000\000\000\000\033\000\000\000\000\000\ +\000\000\000\000\033\000\000\000\000\000\033\000\000\000\000\000\ +\029\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\033\000\000\000\000\000\000\000\000\000\000\000\033\000\033\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\033\000\ +\000\000\000\000\045\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\023\000\000\000\000\000\ +\000\000\023\000\000\000\000\000\023\000\000\000\000\000\000\000\ +\033\000\033\000\033\000\033\000\033\000\000\000\000\000\000\000\ +\000\000\023\000\000\000\000\000\000\000\033\000\023\000\023\000\ +\023\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\022\000\000\000\ +\023\000\000\000\022\000\000\000\000\000\022\000\000\000\000\000\ +\023\000\000\000\000\000\000\000\000\000\023\000\000\000\000\000\ +\023\000\000\000\022\000\000\000\000\000\000\000\000\000\022\000\ +\022\000\022\000\022\000\023\000\000\000\000\000\000\000\000\000\ +\000\000\023\000\023\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\022\000\023\000\000\000\000\000\000\000\029\001\000\000\ +\000\000\022\000\000\000\000\000\000\000\000\000\022\000\000\000\ +\000\000\022\000\000\000\020\000\000\000\000\000\000\000\020\000\ +\000\000\000\000\020\000\023\000\022\000\000\000\023\000\023\000\ +\000\000\000\000\022\000\022\000\000\000\000\000\000\000\020\000\ +\023\000\000\000\000\000\022\000\020\000\020\000\020\000\020\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\017\000\000\000\020\000\000\000\ +\017\000\000\000\000\000\017\000\022\000\000\000\020\000\022\000\ +\022\000\000\000\000\000\020\000\000\000\000\000\020\000\000\000\ +\017\000\022\000\000\000\000\000\000\000\017\000\017\000\017\000\ +\017\000\020\000\000\000\000\000\000\000\000\000\000\000\020\000\ +\020\000\000\000\000\000\000\000\000\000\018\000\000\000\017\000\ +\020\000\018\000\000\000\000\000\018\000\000\000\000\000\017\000\ +\000\000\000\000\000\000\000\000\017\000\000\000\000\000\017\000\ +\000\000\018\000\000\000\000\000\000\000\000\000\018\000\018\000\ +\000\000\018\000\017\000\000\000\020\000\020\000\000\000\000\000\ +\017\000\017\000\000\000\000\000\000\000\000\000\020\000\000\000\ +\018\000\017\000\000\000\000\000\000\000\029\000\000\000\000\000\ +\018\000\029\000\000\000\000\000\029\000\018\000\000\000\000\000\ +\018\000\000\000\000\000\045\001\045\001\045\001\045\001\045\001\ +\045\001\029\000\000\000\018\000\000\000\017\000\000\000\000\000\ +\000\000\018\000\018\000\000\000\000\000\000\000\000\000\017\000\ +\000\000\000\000\018\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\029\000\000\000\000\000\000\000\000\000\029\000\000\000\000\000\ +\029\000\000\000\000\000\000\000\000\000\000\000\018\000\000\000\ +\000\000\000\000\000\000\029\000\000\000\000\000\000\000\000\000\ +\018\000\029\000\029\000\045\001\000\000\000\000\045\001\000\000\ +\000\000\000\000\029\000\000\000\000\000\045\001\045\001\045\001\ +\000\000\000\000\000\000\000\000\000\000\000\000\045\001\045\001\ +\045\001\045\001\045\001\000\000\000\000\045\001\045\001\045\001\ +\045\001\000\000\045\001\000\000\000\000\000\000\045\001\029\001\ +\029\001\029\001\029\001\029\001\029\001\001\000\001\000\000\000\ +\029\000\000\000\000\000\000\000\000\000\000\000\045\001\045\001\ +\000\000\000\000\000\000\000\000\045\001\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\029\001\ +\000\000\000\000\029\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\029\001\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\029\001\000\000\ +\000\000\029\001\029\001\029\001\029\001\000\000\029\001\000\000\ +\000\000\000\000\029\001\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\029\001\029\001\000\000\029\001\029\001\029\001\ +\029\001\006\000\007\000\008\000\009\000\010\000\011\000\041\001\ +\013\000\077\001\078\001\079\001\080\001\081\001\018\000\019\000\ +\082\001\083\001\084\001\085\001\086\001\087\001\020\000\021\000\ +\022\000\023\000\024\000\088\001\089\001\090\001\091\001\092\001\ \093\001\094\001\095\001\096\001\097\001\098\001\099\001\100\001\ \101\001\102\001\103\001\104\001\105\001\106\001\107\001\108\001\ -\109\001\110\001\111\001\112\001\113\001\044\000\045\000\000\000\ -\046\000\047\000\048\000\049\000\114\001\115\001\116\001\052\000\ -\053\000\054\000\055\000\117\001\056\000\057\000\058\000\118\001\ -\059\000\060\000\061\000\062\000\063\000\064\000\065\000\066\000\ -\067\000\068\000\000\000\069\000\070\000\119\001\120\001\121\001\ -\072\000\073\000\074\000\075\000\076\000\077\000\078\000\079\000\ -\080\000\081\000\082\000\122\001\123\001\124\001\125\001\085\000\ -\086\000\087\000\088\000\089\000\090\000\091\000\126\001\127\001\ -\128\001\129\001\130\001\131\001\132\000\132\001\133\001\134\001\ -\135\001\136\001\098\000\006\000\007\000\008\000\009\000\010\000\ +\109\001\110\001\111\001\112\001\113\001\114\001\115\001\116\001\ +\117\001\118\001\119\001\120\001\121\001\122\001\123\001\124\001\ +\125\001\044\000\045\000\000\000\046\000\047\000\048\000\049\000\ +\126\001\127\001\128\001\052\000\053\000\054\000\055\000\129\001\ +\056\000\057\000\058\000\130\001\059\000\060\000\061\000\062\000\ +\063\000\064\000\065\000\066\000\067\000\068\000\000\000\069\000\ +\070\000\131\001\132\001\133\001\072\000\073\000\074\000\075\000\ +\076\000\077\000\078\000\079\000\080\000\081\000\082\000\083\000\ +\134\001\135\001\136\001\137\001\086\000\087\000\088\000\089\000\ +\090\000\091\000\092\000\000\000\000\000\138\001\139\001\140\001\ +\141\001\142\001\143\001\135\000\144\001\145\001\146\001\147\001\ +\148\001\099\000\149\001\006\000\007\000\008\000\009\000\010\000\ \011\000\012\000\013\000\014\000\015\000\016\000\017\000\000\000\ -\018\000\019\000\000\000\000\000\000\000\233\000\000\000\000\000\ +\018\000\019\000\000\000\000\000\000\000\237\000\000\000\000\000\ \020\000\021\000\022\000\023\000\024\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\025\000\026\000\ \000\000\000\000\000\000\000\000\027\000\028\000\029\000\030\000\ \031\000\032\000\033\000\034\000\035\000\036\000\037\000\038\000\ \039\000\000\000\000\000\040\000\041\000\042\000\043\000\000\000\ -\000\000\234\000\000\000\044\000\045\000\000\000\046\000\047\000\ +\000\000\238\000\000\000\044\000\045\000\000\000\046\000\047\000\ \048\000\049\000\000\000\050\000\051\000\052\000\053\000\054\000\ \055\000\000\000\056\000\057\000\058\000\000\000\059\000\060\000\ \061\000\062\000\063\000\064\000\065\000\066\000\067\000\068\000\ \000\000\069\000\070\000\071\000\000\000\000\000\072\000\073\000\ \074\000\075\000\076\000\077\000\078\000\079\000\080\000\081\000\ -\082\000\083\000\084\000\000\000\000\000\085\000\086\000\087\000\ -\088\000\089\000\090\000\091\000\000\000\000\000\000\000\092\000\ -\000\000\000\000\093\000\094\000\095\000\096\000\097\000\128\003\ -\098\000\006\000\007\000\008\000\009\000\010\000\011\000\012\000\ -\013\000\014\000\015\000\016\000\017\000\000\000\018\000\019\000\ -\000\000\000\000\000\000\233\000\000\000\000\000\020\000\021\000\ -\022\000\023\000\024\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\025\000\026\000\000\000\000\000\ -\000\000\000\000\027\000\028\000\029\000\030\000\031\000\032\000\ -\033\000\034\000\035\000\036\000\037\000\038\000\039\000\000\000\ -\000\000\040\000\041\000\042\000\043\000\000\000\000\000\234\000\ -\000\000\044\000\045\000\000\000\046\000\047\000\048\000\049\000\ -\000\000\050\000\051\000\052\000\053\000\054\000\055\000\000\000\ -\056\000\057\000\058\000\000\000\059\000\060\000\061\000\062\000\ -\063\000\064\000\065\000\066\000\067\000\068\000\000\000\069\000\ -\070\000\071\000\000\000\000\000\072\000\073\000\074\000\075\000\ -\076\000\077\000\078\000\079\000\080\000\081\000\082\000\083\000\ -\084\000\000\000\000\000\085\000\086\000\087\000\088\000\089\000\ -\090\000\091\000\000\000\000\000\000\000\092\000\000\000\000\000\ -\093\000\094\000\095\000\096\000\097\000\000\000\098\000\006\000\ +\082\000\083\000\084\000\085\000\000\000\000\000\086\000\087\000\ +\088\000\089\000\090\000\091\000\092\000\000\000\000\000\000\000\ +\000\000\000\000\093\000\000\000\000\000\094\000\095\000\096\000\ +\097\000\098\000\149\003\099\000\100\000\006\000\007\000\008\000\ +\009\000\010\000\011\000\012\000\013\000\014\000\015\000\016\000\ +\017\000\000\000\018\000\019\000\000\000\000\000\000\000\237\000\ +\000\000\000\000\020\000\021\000\022\000\023\000\024\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\025\000\026\000\000\000\000\000\000\000\000\000\027\000\028\000\ +\029\000\030\000\031\000\032\000\033\000\034\000\035\000\036\000\ +\037\000\038\000\039\000\000\000\000\000\040\000\041\000\042\000\ +\043\000\000\000\000\000\238\000\000\000\044\000\045\000\000\000\ +\046\000\047\000\048\000\049\000\000\000\050\000\051\000\052\000\ +\053\000\054\000\055\000\000\000\056\000\057\000\058\000\000\000\ +\059\000\060\000\061\000\062\000\063\000\064\000\065\000\066\000\ +\067\000\068\000\000\000\069\000\070\000\071\000\000\000\000\000\ +\072\000\073\000\074\000\075\000\076\000\077\000\078\000\079\000\ +\080\000\081\000\082\000\083\000\084\000\085\000\000\000\000\000\ +\086\000\087\000\088\000\089\000\090\000\091\000\092\000\000\000\ +\000\000\000\000\000\000\000\000\093\000\000\000\000\000\094\000\ +\095\000\096\000\097\000\098\000\000\000\099\000\100\000\006\000\ \007\000\008\000\009\000\010\000\011\000\012\000\013\000\014\000\ \015\000\016\000\017\000\000\000\018\000\019\000\000\000\000\000\ \000\000\000\000\000\000\000\000\020\000\021\000\022\000\023\000\ @@ -1801,17 +1868,52 @@ \035\000\036\000\037\000\038\000\039\000\000\000\000\000\040\000\ \041\000\042\000\043\000\000\000\000\000\000\000\000\000\044\000\ \045\000\000\000\046\000\047\000\048\000\049\000\000\000\050\000\ -\051\000\052\000\053\000\054\000\055\000\157\002\056\000\057\000\ +\051\000\052\000\053\000\054\000\055\000\174\002\056\000\057\000\ \058\000\000\000\059\000\060\000\061\000\062\000\063\000\064\000\ \065\000\066\000\067\000\068\000\000\000\069\000\070\000\071\000\ \000\000\000\000\072\000\073\000\074\000\075\000\076\000\077\000\ -\078\000\079\000\080\000\081\000\082\000\083\000\084\000\000\000\ -\000\000\085\000\086\000\087\000\088\000\089\000\090\000\091\000\ -\000\000\000\000\000\000\092\000\000\000\000\000\093\000\094\000\ -\095\000\096\000\097\000\000\000\098\000\006\000\007\000\008\000\ -\009\000\010\000\011\000\012\000\013\000\014\000\015\000\016\000\ +\078\000\079\000\080\000\081\000\082\000\083\000\084\000\085\000\ +\000\000\000\000\086\000\087\000\088\000\089\000\090\000\091\000\ +\092\000\000\000\000\000\000\000\000\000\000\000\093\000\000\000\ +\000\000\094\000\095\000\096\000\097\000\098\000\000\000\099\000\ +\100\000\006\000\007\000\008\000\009\000\010\000\011\000\012\000\ +\013\000\014\000\015\000\016\000\017\000\000\000\018\000\019\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\020\000\021\000\ +\022\000\023\000\024\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\025\000\026\000\000\000\000\000\ +\000\000\000\000\027\000\028\000\029\000\030\000\031\000\032\000\ +\033\000\034\000\035\000\036\000\037\000\038\000\039\000\000\000\ +\000\000\040\000\041\000\042\000\043\000\000\000\000\000\000\000\ +\000\000\044\000\045\000\000\000\046\000\047\000\048\000\049\000\ +\000\000\050\000\051\000\052\000\053\000\054\000\055\000\000\000\ +\056\000\057\000\058\000\000\000\059\000\060\000\061\000\062\000\ +\063\000\064\000\065\000\066\000\067\000\068\000\000\000\069\000\ +\070\000\071\000\000\000\000\000\072\000\073\000\074\000\075\000\ +\076\000\077\000\078\000\079\000\080\000\081\000\082\000\083\000\ +\084\000\085\000\000\000\000\000\086\000\087\000\088\000\089\000\ +\090\000\091\000\092\000\000\000\000\000\000\000\000\000\000\000\ +\093\000\000\000\000\000\094\000\095\000\096\000\097\000\098\000\ +\000\000\099\000\100\000\006\000\007\000\008\000\009\000\010\000\ +\011\000\012\000\173\000\014\000\015\000\016\000\017\000\000\000\ +\018\000\019\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\174\000\175\000\176\000\177\000\178\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\025\000\026\000\ +\000\000\000\000\000\000\000\000\027\000\028\000\029\000\030\000\ +\031\000\032\000\033\000\034\000\035\000\036\000\037\000\038\000\ +\039\000\000\000\000\000\040\000\041\000\042\000\043\000\000\000\ +\000\000\000\000\000\000\044\000\045\000\000\000\046\000\047\000\ +\048\000\049\000\000\000\050\000\051\000\052\000\053\000\054\000\ +\055\000\000\000\056\000\057\000\058\000\000\000\059\000\060\000\ +\061\000\062\000\179\000\064\000\065\000\066\000\067\000\068\000\ +\000\000\069\000\070\000\071\000\000\000\000\000\072\000\073\000\ +\180\000\181\000\182\000\183\000\184\000\185\000\186\000\187\000\ +\188\000\189\000\084\000\085\000\000\000\000\000\086\000\087\000\ +\088\000\089\000\090\000\091\000\092\000\000\000\000\000\000\000\ +\000\000\000\000\093\000\000\000\000\000\094\000\095\000\096\000\ +\097\000\098\000\000\000\190\000\100\000\006\000\007\000\008\000\ +\009\000\010\000\011\000\012\000\173\000\014\000\015\000\016\000\ \017\000\000\000\018\000\019\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\020\000\021\000\022\000\023\000\024\000\000\000\ +\000\000\000\000\174\000\175\000\176\000\177\000\178\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \025\000\026\000\000\000\000\000\000\000\000\000\027\000\028\000\ \029\000\030\000\031\000\032\000\033\000\034\000\035\000\036\000\ @@ -1821,44 +1923,11 @@ \053\000\054\000\055\000\000\000\056\000\057\000\058\000\000\000\ \059\000\060\000\061\000\062\000\063\000\064\000\065\000\066\000\ \067\000\068\000\000\000\069\000\070\000\071\000\000\000\000\000\ -\072\000\073\000\074\000\075\000\076\000\077\000\078\000\079\000\ -\080\000\081\000\082\000\083\000\084\000\000\000\000\000\085\000\ -\086\000\087\000\088\000\089\000\090\000\091\000\000\000\000\000\ -\000\000\092\000\000\000\000\000\093\000\094\000\095\000\096\000\ -\097\000\000\000\098\000\006\000\007\000\008\000\009\000\010\000\ -\011\000\012\000\169\000\014\000\015\000\016\000\017\000\000\000\ -\018\000\019\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\170\000\171\000\172\000\173\000\174\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\025\000\026\000\ -\000\000\000\000\000\000\000\000\027\000\028\000\029\000\030\000\ -\031\000\032\000\033\000\034\000\035\000\036\000\037\000\038\000\ -\039\000\000\000\000\000\040\000\041\000\042\000\043\000\000\000\ -\000\000\000\000\000\000\044\000\045\000\000\000\046\000\047\000\ -\048\000\049\000\000\000\050\000\051\000\052\000\053\000\054\000\ -\055\000\000\000\056\000\057\000\058\000\000\000\059\000\060\000\ -\061\000\062\000\175\000\064\000\065\000\066\000\067\000\068\000\ -\000\000\069\000\070\000\071\000\000\000\000\000\072\000\176\000\ -\177\000\178\000\179\000\180\000\181\000\182\000\183\000\184\000\ -\185\000\083\000\084\000\000\000\000\000\085\000\086\000\087\000\ -\088\000\089\000\090\000\091\000\000\000\000\000\000\000\092\000\ -\000\000\000\000\093\000\094\000\095\000\096\000\097\000\000\000\ -\186\000\006\000\007\000\008\000\009\000\010\000\011\000\012\000\ -\169\000\014\000\015\000\016\000\017\000\000\000\018\000\019\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\170\000\171\000\ -\172\000\173\000\174\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\025\000\026\000\000\000\000\000\ -\000\000\000\000\027\000\028\000\029\000\030\000\031\000\032\000\ -\033\000\034\000\035\000\036\000\037\000\038\000\039\000\000\000\ -\000\000\040\000\041\000\042\000\043\000\000\000\000\000\000\000\ -\000\000\044\000\045\000\000\000\046\000\047\000\048\000\049\000\ -\000\000\050\000\051\000\052\000\053\000\054\000\055\000\000\000\ -\056\000\057\000\058\000\000\000\059\000\060\000\061\000\062\000\ -\063\000\064\000\065\000\066\000\067\000\068\000\000\000\069\000\ -\070\000\071\000\000\000\000\000\072\000\176\000\177\000\178\000\ -\179\000\180\000\181\000\182\000\183\000\184\000\185\000\083\000\ -\084\000\000\000\000\000\085\000\086\000\087\000\088\000\089\000\ -\090\000\091\000\000\000\000\000\000\000\092\000\000\000\000\000\ -\093\000\094\000\095\000\096\000\097\000\000\000\098\000\006\000\ +\072\000\073\000\180\000\181\000\182\000\183\000\184\000\185\000\ +\186\000\187\000\188\000\189\000\084\000\085\000\000\000\000\000\ +\086\000\087\000\088\000\089\000\090\000\091\000\092\000\000\000\ +\000\000\000\000\000\000\000\000\093\000\000\000\000\000\094\000\ +\095\000\096\000\097\000\098\000\000\000\099\000\100\000\006\000\ \007\000\008\000\009\000\010\000\011\000\012\000\013\000\014\000\ \015\000\016\000\017\000\000\000\018\000\019\000\000\000\000\000\ \000\000\000\000\000\000\000\000\020\000\021\000\022\000\023\000\ @@ -1870,30 +1939,31 @@ \045\000\000\000\046\000\047\000\048\000\049\000\000\000\050\000\ \051\000\052\000\053\000\054\000\055\000\000\000\056\000\057\000\ \058\000\000\000\059\000\060\000\061\000\062\000\063\000\064\000\ -\065\000\066\000\067\000\068\000\000\000\069\000\070\000\079\003\ +\065\000\066\000\067\000\068\000\000\000\069\000\070\000\100\003\ \000\000\000\000\072\000\073\000\074\000\075\000\076\000\077\000\ -\078\000\079\000\080\000\081\000\082\000\083\000\084\000\000\000\ -\000\000\085\000\086\000\087\000\088\000\089\000\090\000\091\000\ -\000\000\000\000\000\000\092\000\000\000\000\000\093\000\094\000\ -\095\000\096\000\097\000\000\000\098\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\000\000\001\000\001\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\001\000\001\000\001\000\001\000\001\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\001\000\001\000\000\000\000\000\000\000\000\000\001\000\001\000\ -\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\000\000\000\000\001\000\001\000\001\000\ -\001\000\000\000\000\000\000\000\000\000\001\000\001\000\000\000\ -\001\000\001\000\001\000\001\000\000\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\000\000\001\000\001\000\001\000\000\000\ +\078\000\079\000\080\000\081\000\082\000\083\000\084\000\085\000\ +\000\000\000\000\086\000\087\000\088\000\089\000\090\000\091\000\ +\092\000\000\000\000\000\000\000\000\000\000\000\093\000\000\000\ +\000\000\094\000\095\000\096\000\097\000\098\000\000\000\099\000\ +\100\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ +\001\000\001\000\001\000\001\000\001\000\000\000\001\000\001\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\001\000\001\000\ +\001\000\001\000\001\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\001\000\001\000\000\000\000\000\ +\000\000\000\000\001\000\001\000\001\000\001\000\001\000\001\000\ +\001\000\001\000\001\000\001\000\001\000\001\000\001\000\000\000\ +\000\000\001\000\001\000\001\000\001\000\000\000\000\000\000\000\ +\000\000\001\000\001\000\000\000\001\000\001\000\001\000\001\000\ +\000\000\001\000\001\000\001\000\001\000\001\000\001\000\000\000\ +\001\000\001\000\001\000\000\000\001\000\001\000\001\000\001\000\ +\001\000\001\000\001\000\001\000\001\000\001\000\000\000\001\000\ +\001\000\001\000\000\000\000\000\001\000\001\000\001\000\001\000\ \001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\000\000\001\000\001\000\001\000\000\000\000\000\ -\001\000\001\000\001\000\001\000\001\000\001\000\001\000\001\000\ -\001\000\001\000\001\000\001\000\001\000\000\000\000\000\001\000\ -\001\000\001\000\001\000\001\000\001\000\001\000\000\000\000\000\ -\000\000\001\000\000\000\000\000\001\000\001\000\001\000\001\000\ -\001\000\000\000\001\000\006\000\007\000\008\000\009\000\010\000\ -\011\000\034\001\013\000\000\000\000\000\224\002\000\000\000\000\ +\001\000\001\000\000\000\000\000\001\000\001\000\001\000\001\000\ +\001\000\001\000\001\000\000\000\000\000\000\000\000\000\000\000\ +\001\000\000\000\000\000\001\000\001\000\001\000\001\000\001\000\ +\000\000\001\000\001\000\006\000\007\000\008\000\009\000\010\000\ +\011\000\041\001\013\000\000\000\000\000\244\002\000\000\000\000\ \018\000\019\000\000\000\000\000\000\000\000\000\000\000\000\000\ \020\000\021\000\022\000\023\000\024\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -1902,902 +1972,954 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\044\000\045\000\000\000\046\000\047\000\ \048\000\049\000\000\000\000\000\000\000\052\000\053\000\054\000\ -\225\002\000\000\056\000\057\000\058\000\000\000\059\000\060\000\ +\245\002\000\000\056\000\057\000\058\000\000\000\059\000\060\000\ \061\000\062\000\063\000\064\000\065\000\066\000\067\000\068\000\ \000\000\069\000\070\000\000\000\000\000\000\000\072\000\073\000\ \074\000\075\000\076\000\077\000\078\000\079\000\080\000\081\000\ -\082\000\000\000\000\000\000\000\000\000\085\000\086\000\087\000\ -\088\000\089\000\090\000\091\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\132\000\000\000\000\000\000\000\000\000\000\000\ -\098\000\006\000\007\000\008\000\009\000\010\000\011\000\034\001\ -\013\000\000\000\000\000\000\000\000\000\000\000\018\000\019\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\020\000\021\000\ -\022\000\023\000\024\000\000\000\000\000\000\000\000\000\000\000\ +\082\000\083\000\000\000\000\000\000\000\000\000\086\000\087\000\ +\088\000\089\000\090\000\091\000\092\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\135\000\000\000\000\000\ +\000\000\000\000\000\000\099\000\006\000\007\000\008\000\009\000\ +\010\000\011\000\041\001\013\000\000\000\000\000\000\000\000\000\ +\000\000\018\000\019\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\020\000\021\000\022\000\023\000\024\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\044\000\045\000\000\000\046\000\047\000\048\000\049\000\ -\000\000\000\000\000\000\052\000\053\000\054\000\055\000\000\000\ -\056\000\057\000\058\000\000\000\059\000\060\000\061\000\062\000\ -\063\000\064\000\065\000\066\000\067\000\068\000\000\000\069\000\ -\070\000\000\000\000\000\000\000\072\000\073\000\074\000\075\000\ -\076\000\077\000\078\000\079\000\080\000\081\000\082\000\000\000\ -\000\000\000\000\000\000\085\000\086\000\087\000\088\000\089\000\ -\090\000\091\000\215\000\194\000\014\000\015\000\016\000\017\000\ -\132\000\000\000\000\000\000\000\000\000\000\000\098\000\000\000\ -\000\000\195\000\196\000\197\000\198\000\199\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\216\000\028\000\029\000\ -\030\000\031\000\032\000\033\000\034\000\035\000\036\000\037\000\ -\038\000\039\000\000\000\000\000\040\000\041\000\042\000\043\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\050\000\051\000\215\000\194\000\ -\000\000\000\000\000\000\200\001\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\195\000\196\000\197\000\ -\198\000\199\000\000\000\000\000\071\000\000\000\000\000\000\000\ -\200\000\201\000\202\000\203\000\204\000\205\000\206\000\207\000\ -\208\000\209\000\083\000\084\000\215\000\000\000\014\000\015\000\ -\016\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\092\000\000\000\192\001\217\000\000\000\000\000\096\000\097\000\ +\000\000\000\000\000\000\000\000\044\000\045\000\000\000\046\000\ +\047\000\048\000\049\000\000\000\000\000\000\000\052\000\053\000\ +\054\000\055\000\000\000\056\000\057\000\058\000\000\000\059\000\ +\060\000\061\000\062\000\063\000\064\000\065\000\066\000\067\000\ +\068\000\000\000\069\000\070\000\000\000\000\000\000\000\072\000\ +\073\000\074\000\075\000\076\000\077\000\078\000\079\000\080\000\ +\081\000\082\000\083\000\000\000\000\000\000\000\000\000\086\000\ +\087\000\088\000\089\000\090\000\091\000\092\000\219\000\198\000\ +\014\000\015\000\016\000\017\000\000\000\000\000\135\000\000\000\ +\000\000\000\000\000\000\000\000\099\000\199\000\200\000\201\000\ +\202\000\203\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\220\000\028\000\029\000\030\000\031\000\032\000\033\000\ +\034\000\035\000\036\000\037\000\038\000\039\000\000\000\000\000\ +\040\000\041\000\042\000\043\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\050\000\051\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\071\000\000\000\000\000\000\000\000\000\204\000\205\000\206\000\ +\207\000\208\000\209\000\210\000\211\000\212\000\213\000\084\000\ +\085\000\219\000\000\000\014\000\015\000\016\000\017\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\093\000\ +\000\000\000\000\221\000\000\000\000\000\097\000\098\000\000\000\ +\000\000\100\000\000\000\000\000\000\000\000\000\025\000\026\000\ +\000\000\000\000\000\000\000\000\220\000\028\000\029\000\030\000\ +\031\000\032\000\033\000\034\000\035\000\036\000\037\000\038\000\ +\039\000\000\000\000\000\040\000\041\000\042\000\043\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\050\000\051\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\071\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\025\000\026\000\000\000\000\000\000\000\000\000\216\000\ +\000\000\000\000\084\000\085\000\219\000\000\000\014\000\015\000\ +\016\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\093\000\000\000\000\000\221\000\095\000\096\000\ +\097\000\098\000\000\000\000\000\100\000\000\000\000\000\000\000\ +\000\000\025\000\026\000\000\000\000\000\000\000\000\000\027\000\ \028\000\029\000\030\000\031\000\032\000\033\000\034\000\035\000\ \036\000\037\000\038\000\039\000\000\000\000\000\040\000\041\000\ -\042\000\043\000\000\000\000\000\200\000\201\000\202\000\203\000\ -\204\000\205\000\206\000\207\000\208\000\209\000\050\000\051\000\ +\042\000\043\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\050\000\051\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\071\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\215\000\000\000\014\000\ -\015\000\016\000\017\000\000\000\083\000\084\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\219\000\000\000\014\000\ +\015\000\016\000\017\000\000\000\000\000\084\000\085\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\092\000\000\000\000\000\217\000\094\000\095\000\ -\096\000\097\000\025\000\026\000\000\000\000\000\000\000\000\000\ -\027\000\028\000\029\000\030\000\031\000\032\000\033\000\034\000\ +\000\000\000\000\000\000\000\000\000\000\093\000\000\000\000\000\ +\221\000\095\000\096\000\097\000\098\000\000\000\000\000\100\000\ +\220\000\028\000\029\000\030\000\031\000\032\000\033\000\034\000\ \035\000\036\000\037\000\038\000\039\000\000\000\000\000\040\000\ \041\000\042\000\043\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\050\000\ \051\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\071\000\ -\215\000\000\000\014\000\015\000\016\000\017\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\083\000\084\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\092\000\000\000\000\000\217\000\094\000\ -\095\000\096\000\097\000\216\000\028\000\029\000\030\000\031\000\ -\032\000\033\000\034\000\035\000\036\000\037\000\038\000\039\000\ -\000\000\000\000\040\000\041\000\042\000\043\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\050\000\051\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\018\000\019\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\020\000\021\000\022\000\023\000\024\000\ -\000\000\000\000\071\000\000\000\000\000\000\000\000\000\000\000\ +\018\000\019\000\000\000\000\000\000\000\000\000\000\000\071\000\ +\020\000\021\000\022\000\023\000\024\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\084\000\085\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\083\000\084\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\092\000\000\000\ -\000\000\217\000\000\000\000\000\096\000\097\000\118\000\119\000\ -\000\000\046\000\120\000\048\000\121\000\000\000\000\000\000\000\ -\052\000\053\000\054\000\122\000\000\000\123\000\124\000\000\000\ -\000\000\059\000\060\000\061\000\062\000\125\000\064\000\065\000\ -\126\000\127\000\128\000\129\000\069\000\130\000\000\000\000\000\ -\000\000\072\000\073\000\074\000\075\000\076\000\077\000\078\000\ -\079\000\080\000\081\000\082\000\000\000\000\000\000\000\000\000\ -\131\000\086\000\087\000\000\000\089\000\090\000\091\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\132\000\018\000\019\000\ -\000\000\000\000\000\000\098\000\000\000\000\000\020\000\021\000\ -\022\000\023\000\024\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\093\000\000\000\ +\000\000\221\000\000\000\000\000\097\000\098\000\000\000\000\000\ +\100\000\000\000\000\000\120\000\121\000\000\000\046\000\122\000\ +\048\000\123\000\000\000\000\000\000\000\052\000\053\000\054\000\ +\124\000\000\000\125\000\126\000\000\000\000\000\059\000\060\000\ +\061\000\062\000\127\000\064\000\065\000\128\000\129\000\130\000\ +\131\000\069\000\132\000\000\000\000\000\000\000\133\000\073\000\ +\074\000\075\000\076\000\077\000\078\000\079\000\080\000\081\000\ +\082\000\083\000\000\000\000\000\000\000\000\000\134\000\087\000\ +\088\000\000\000\090\000\091\000\092\000\000\000\018\000\019\000\ +\000\000\000\000\000\000\000\000\000\000\135\000\020\000\021\000\ +\022\000\023\000\024\000\099\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\ -\019\000\000\000\000\000\000\000\000\000\000\000\048\000\020\000\ -\021\000\022\000\023\000\024\000\053\000\208\002\000\000\000\000\ -\000\000\000\000\000\000\000\000\059\000\060\000\061\000\062\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\048\000\018\000\ +\019\000\000\000\000\000\000\000\053\000\228\002\000\000\020\000\ +\021\000\022\000\023\000\024\000\059\000\060\000\061\000\062\000\ \000\000\064\000\065\000\000\000\000\000\000\000\000\000\069\000\ -\000\000\000\000\000\000\000\000\072\000\073\000\074\000\075\000\ -\076\000\077\000\078\000\079\000\080\000\081\000\082\000\000\000\ -\000\000\000\000\000\000\039\001\040\001\087\000\000\000\048\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\041\001\000\000\ -\132\000\000\000\000\000\042\001\000\000\000\000\098\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\073\000\074\000\075\000\ +\076\000\077\000\078\000\079\000\080\000\081\000\082\000\083\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\088\000\000\000\ +\000\000\000\000\000\000\046\001\047\001\000\000\000\000\048\000\ +\000\000\000\000\000\000\135\000\000\000\000\000\048\001\000\000\ +\000\000\099\000\000\000\049\001\000\000\000\000\000\000\000\000\ \000\000\000\000\064\000\065\000\000\000\000\000\000\000\000\000\ -\069\000\000\000\000\000\000\000\000\000\072\000\073\000\074\000\ +\069\000\000\000\000\000\000\000\000\000\000\000\073\000\074\000\ \075\000\076\000\077\000\078\000\079\000\080\000\081\000\082\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\087\000\000\000\ +\083\000\000\000\000\000\000\000\000\000\000\000\000\000\088\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\132\000\000\000\000\000\000\000\000\000\000\000\098\000" +\000\000\000\000\000\000\000\000\135\000\000\000\000\000\000\000\ +\000\000\000\000\099\000" let yycheck = "\002\000\ -\002\000\071\000\002\000\017\000\071\000\245\000\001\000\131\000\ -\131\000\220\000\002\000\025\000\026\000\184\000\185\000\119\000\ -\128\000\121\000\130\000\002\000\053\002\026\000\017\000\120\000\ -\000\000\036\002\025\002\056\002\191\000\056\002\095\000\242\000\ -\243\000\038\002\013\002\000\000\165\001\208\000\209\000\023\001\ -\194\001\193\000\000\000\166\001\198\001\200\001\193\001\044\002\ -\000\000\002\000\205\001\134\000\197\002\157\000\000\000\040\001\ -\035\002\000\000\037\002\000\000\000\003\022\001\007\001\022\001\ -\033\001\016\002\033\001\012\001\013\001\120\000\012\001\016\001\ -\012\001\069\001\029\001\060\001\071\000\075\001\129\000\027\000\ -\094\000\059\003\078\001\022\001\027\001\072\001\000\000\012\001\ -\139\000\094\000\013\001\028\001\040\000\041\000\042\000\043\000\ -\007\001\013\001\019\001\009\001\000\000\012\001\013\001\000\000\ -\012\001\016\001\033\001\044\003\013\001\012\001\033\001\098\001\ -\163\000\034\001\059\001\013\001\035\001\033\001\063\001\122\000\ -\122\000\063\001\122\000\126\000\127\000\128\000\077\002\130\000\ -\131\000\098\001\125\000\098\001\110\003\038\001\039\001\040\001\ -\041\001\122\001\123\001\124\001\118\003\146\002\063\001\088\001\ -\092\000\106\001\211\000\106\001\059\001\072\001\233\000\056\001\ -\063\001\072\001\097\001\060\001\072\001\097\001\000\000\048\003\ -\007\001\098\001\072\001\030\001\040\001\012\001\013\001\106\001\ -\107\001\016\001\089\001\098\001\109\003\000\000\072\001\098\001\ -\060\001\088\001\192\000\016\001\007\001\160\002\098\001\136\000\ -\060\001\083\001\165\002\014\001\128\003\134\001\035\001\039\001\ -\113\001\114\001\050\001\007\001\193\002\095\002\016\001\035\001\ -\178\003\039\001\040\001\041\001\016\001\012\001\007\001\060\001\ -\088\001\076\002\069\001\102\002\059\001\072\001\012\001\016\001\ -\063\001\122\001\123\001\124\001\012\001\072\001\060\001\134\001\ -\016\001\068\001\221\000\222\000\223\000\224\000\225\000\226\000\ -\227\000\228\000\191\001\072\001\031\001\251\000\122\001\234\000\ -\049\001\088\001\051\001\035\001\089\001\013\001\122\001\042\001\ -\124\001\000\000\245\000\046\001\047\001\089\001\134\001\250\000\ -\063\001\252\000\253\000\254\000\255\000\000\001\001\001\058\001\ -\003\001\004\001\005\001\006\001\216\000\122\001\013\003\124\001\ -\013\001\124\001\007\001\008\001\035\001\234\001\121\001\009\001\ -\072\001\036\003\021\001\030\001\122\001\123\001\124\001\134\001\ -\059\003\196\001\019\001\014\003\001\001\032\001\041\001\191\001\ -\064\001\089\001\045\001\001\001\002\001\068\001\012\001\050\001\ -\032\002\001\001\029\003\148\001\075\001\157\001\075\001\001\001\ -\002\001\072\001\001\001\002\001\001\001\002\001\038\001\039\001\ -\040\001\041\001\045\003\064\001\016\001\017\001\018\001\019\001\ -\020\001\012\001\022\001\023\001\024\001\025\001\063\001\027\001\ -\056\001\007\001\234\001\110\003\060\001\090\003\240\002\098\003\ -\115\003\140\001\016\001\118\003\221\002\000\000\078\002\035\001\ -\012\001\148\001\121\001\013\001\121\001\001\001\002\001\017\001\ -\001\001\002\001\020\001\007\001\008\001\012\001\012\001\162\001\ -\063\002\012\001\016\001\180\001\181\001\182\001\069\002\033\001\ -\035\001\075\001\012\001\102\003\038\001\039\001\040\001\041\001\ -\027\003\028\003\234\000\066\001\072\001\035\001\167\003\200\001\ -\135\003\012\001\000\000\204\001\205\001\022\001\056\001\007\001\ -\008\001\082\001\122\001\123\001\124\001\178\003\064\001\178\003\ -\019\001\108\002\012\001\069\001\226\001\072\001\072\001\001\001\ -\002\001\228\001\072\001\007\001\118\001\007\001\008\001\034\001\ -\012\001\083\001\072\001\038\002\012\001\021\001\015\002\089\001\ -\090\001\007\001\012\001\027\002\028\002\048\002\012\001\066\001\ -\098\001\000\000\013\001\089\001\098\001\184\001\017\001\205\001\ -\059\001\020\001\061\001\062\001\063\001\045\002\022\001\003\001\ -\004\001\005\001\006\001\082\001\199\001\000\000\033\001\221\001\ -\163\002\123\001\124\001\206\001\060\002\012\001\198\002\059\001\ -\221\001\010\001\011\001\133\001\015\002\102\001\012\001\013\001\ -\105\001\106\001\221\001\000\000\035\001\059\001\225\001\009\001\ -\227\001\121\001\029\002\030\002\000\000\064\001\186\001\000\000\ -\235\001\236\001\069\001\002\001\039\002\072\001\113\001\114\001\ -\089\001\090\001\001\001\002\001\003\001\004\001\005\001\006\001\ -\083\001\012\001\119\001\120\001\059\001\065\001\089\001\090\001\ -\063\001\072\001\007\001\008\001\063\002\059\001\013\001\098\001\ -\020\001\063\001\069\002\070\002\023\002\027\001\102\001\146\002\ -\016\002\105\001\106\001\013\001\088\001\074\002\075\002\091\001\ -\092\001\093\001\094\001\038\002\096\001\040\002\013\001\038\001\ -\039\001\040\001\041\001\147\002\072\001\048\002\150\002\151\002\ -\059\001\033\001\133\001\006\003\063\001\056\002\056\002\115\001\ -\056\002\056\001\065\001\110\002\072\001\060\001\001\000\002\000\ -\003\000\004\000\190\002\190\002\180\003\181\003\035\001\074\002\ -\075\002\098\001\197\002\098\001\188\002\189\002\033\001\035\001\ -\184\002\088\001\074\002\075\002\091\001\092\001\093\001\094\001\ -\007\001\096\001\033\001\074\002\075\002\012\001\013\001\171\002\ -\172\002\016\001\072\001\035\001\066\001\072\001\033\001\069\001\ -\155\002\071\001\013\001\211\002\115\001\072\001\017\001\016\001\ -\078\001\020\001\080\001\081\001\007\001\182\002\072\001\114\002\ -\115\002\097\001\106\003\122\001\123\001\124\001\033\001\145\000\ -\146\000\147\000\148\000\038\001\039\001\198\002\041\001\012\001\ -\016\001\027\001\122\003\072\001\059\001\035\001\000\000\146\002\ -\063\001\140\002\072\001\068\001\075\001\056\001\035\001\013\001\ -\001\001\068\003\022\001\017\001\013\001\064\001\020\001\019\001\ -\064\001\063\001\069\001\013\001\059\001\072\001\013\001\013\001\ -\182\002\088\001\013\001\033\001\060\001\013\001\022\003\064\001\ -\083\001\033\003\000\000\035\003\098\001\048\003\089\001\090\001\ -\187\002\188\002\189\002\190\002\033\001\016\001\072\001\098\001\ -\012\001\196\002\197\002\038\001\039\001\040\001\041\001\069\001\ -\072\001\072\001\064\001\072\001\097\001\208\002\072\001\069\001\ -\072\001\124\001\072\001\016\001\204\002\056\001\072\001\134\001\ -\123\001\060\001\027\003\028\003\016\001\083\001\000\000\090\003\ -\022\001\022\001\133\001\089\001\090\001\013\001\025\003\064\001\ -\066\001\042\003\013\001\069\001\098\001\071\001\013\001\098\001\ -\001\001\002\001\003\001\004\001\005\001\006\001\080\001\081\001\ -\033\001\013\001\072\001\083\001\100\003\017\001\035\001\012\001\ -\020\001\052\003\253\002\072\001\072\001\028\001\001\003\033\001\ -\003\003\079\003\013\001\098\001\079\003\033\001\100\001\133\001\ -\098\001\072\001\038\001\039\001\040\001\041\001\012\001\122\001\ -\123\001\124\001\072\001\124\001\042\003\094\003\033\003\116\001\ -\035\003\007\001\072\001\139\003\056\001\016\001\012\001\013\001\ -\060\001\007\001\016\001\046\003\064\001\048\003\012\001\013\001\ -\065\001\069\001\016\001\072\001\072\001\072\001\016\001\016\001\ -\059\003\059\003\000\000\059\003\004\001\165\003\006\001\083\001\ -\011\001\033\001\016\001\063\001\028\001\089\001\090\001\088\001\ -\013\001\013\001\091\001\092\001\093\001\094\001\098\001\096\001\ -\094\003\076\003\064\001\013\001\079\003\059\001\072\001\090\003\ -\033\001\063\001\027\001\072\001\072\001\059\001\145\003\146\003\ -\072\001\063\001\115\001\033\001\098\001\016\001\122\001\123\001\ -\124\001\000\000\013\001\110\003\110\003\072\001\110\003\016\001\ -\013\001\133\001\088\001\118\003\118\003\068\001\118\003\072\001\ -\072\001\065\001\088\001\072\001\075\001\076\001\077\001\091\001\ -\092\001\093\001\094\001\095\001\096\001\084\001\085\001\086\001\ -\087\001\140\003\133\003\016\001\035\001\033\001\013\001\016\001\ -\088\001\117\001\117\001\091\001\092\001\093\001\094\001\115\001\ -\096\001\028\001\066\001\072\001\072\001\069\001\072\001\071\001\ -\134\001\118\001\098\001\075\001\072\001\116\001\078\001\020\001\ -\134\001\072\001\121\001\115\001\072\001\072\001\016\001\178\003\ -\178\003\007\001\178\003\001\001\002\001\003\001\004\001\005\001\ -\006\001\007\001\008\001\009\001\010\001\011\001\012\001\013\001\ -\014\001\015\001\016\001\017\001\018\001\019\001\020\001\021\001\ -\022\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ -\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ -\038\001\039\001\040\001\041\001\042\001\043\001\044\001\045\001\ -\046\001\047\001\048\001\049\001\050\001\051\001\052\001\053\001\ -\054\001\055\001\056\001\057\001\058\001\059\001\060\001\061\001\ -\062\001\063\001\064\001\065\001\066\001\000\000\068\001\069\001\ -\070\001\071\001\072\001\073\001\074\001\075\001\076\001\077\001\ -\078\001\079\001\080\001\081\001\082\001\083\001\084\001\085\001\ -\086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ -\118\001\095\001\096\001\097\001\098\001\099\001\100\001\101\001\ -\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\111\001\112\001\113\001\114\001\115\001\116\001\117\001\ -\118\001\119\001\120\001\121\001\122\001\123\001\124\001\125\001\ -\126\001\127\001\128\001\129\001\130\001\131\001\132\001\133\001\ -\134\001\000\000\016\001\001\001\002\001\003\001\004\001\005\001\ -\006\001\007\001\008\001\020\001\013\001\098\001\098\001\072\001\ -\014\001\015\001\013\001\013\001\035\001\000\000\000\000\064\001\ -\022\001\023\001\024\001\025\001\026\001\013\001\072\001\098\001\ -\000\000\016\001\013\001\098\001\035\001\072\001\098\001\098\001\ -\072\001\016\001\028\001\038\001\039\001\040\001\041\001\013\001\ -\013\001\072\001\001\001\002\001\003\001\004\001\005\001\006\001\ -\007\001\008\001\013\001\072\001\067\003\056\001\243\000\184\001\ -\027\001\060\001\008\002\065\001\000\000\027\000\068\001\162\000\ -\070\001\226\001\125\002\205\001\110\002\228\001\076\001\077\001\ -\204\001\102\002\049\001\071\003\234\001\094\003\084\001\085\001\ +\002\000\071\000\002\000\001\000\071\000\188\000\189\000\002\000\ +\134\000\130\000\002\000\132\000\017\000\224\000\121\000\026\000\ +\123\000\134\000\096\000\017\000\025\000\026\000\249\000\127\000\ +\051\002\122\000\073\002\000\000\070\002\212\000\213\000\040\002\ +\178\001\195\000\000\000\246\000\247\000\213\001\000\000\028\002\ +\000\000\053\002\218\001\000\000\133\000\197\000\207\001\000\000\ +\179\001\000\000\211\001\206\001\062\002\000\000\161\000\133\000\ +\137\000\031\002\059\002\030\001\000\000\050\002\018\003\052\002\ +\002\000\017\001\013\001\033\001\022\001\027\001\012\001\028\001\ +\012\001\071\000\217\002\013\001\064\003\075\001\079\003\035\001\ +\000\000\036\001\060\001\027\000\095\000\022\001\038\001\039\001\ +\040\001\041\001\095\000\038\001\039\001\040\001\041\001\033\001\ +\040\000\041\000\042\000\043\000\000\000\080\002\204\001\033\001\ +\056\001\007\001\016\001\086\002\060\001\056\001\012\001\013\001\ +\012\001\060\001\016\001\022\001\072\001\022\001\019\001\000\000\ +\094\002\124\000\124\000\063\001\124\000\128\000\129\000\130\000\ +\133\000\132\000\131\003\134\000\098\001\034\001\072\001\073\002\ +\012\001\215\000\139\003\097\001\013\001\098\001\130\003\122\000\ +\246\001\123\001\124\001\125\001\016\001\093\000\033\001\163\002\ +\131\000\107\001\108\001\097\001\237\000\059\001\022\001\009\001\ +\098\001\063\001\063\001\142\000\013\001\068\001\103\001\037\001\ +\098\001\106\001\107\001\123\001\124\001\125\001\126\001\127\001\ +\123\001\124\001\125\001\126\001\127\001\068\003\060\001\035\001\ +\033\001\072\001\088\001\176\002\167\000\014\001\072\001\196\000\ +\181\002\149\003\059\001\046\001\021\001\198\003\000\000\072\001\ +\107\001\139\000\107\001\035\001\072\001\012\001\216\002\112\002\ +\238\000\210\002\083\001\098\001\012\001\114\001\115\001\098\001\ +\089\001\090\001\093\002\122\001\119\002\007\001\072\001\072\001\ +\012\001\058\001\012\001\225\000\226\000\227\000\228\000\229\000\ +\230\000\231\000\232\000\137\001\058\001\089\001\060\001\103\001\ +\238\000\009\001\106\001\107\001\035\001\127\001\124\001\125\001\ +\068\001\098\001\255\000\249\000\035\001\072\001\028\001\075\001\ +\254\000\089\001\000\001\001\001\002\001\003\001\004\001\005\001\ +\006\001\066\001\008\001\009\001\010\001\011\001\012\001\013\001\ +\088\001\059\001\000\000\249\002\220\000\012\001\031\003\098\001\ +\012\001\072\001\012\001\054\003\001\001\002\001\028\001\012\001\ +\007\001\072\001\037\001\001\001\002\001\012\001\012\001\001\001\ +\002\001\039\001\089\001\032\003\001\001\048\001\122\001\209\001\ +\001\001\052\001\001\001\002\001\204\001\013\001\001\001\002\001\ +\059\001\017\001\047\003\038\001\020\001\001\001\002\001\170\001\ +\161\001\137\001\075\001\007\001\008\001\012\001\049\001\060\003\ +\063\001\033\001\053\001\054\001\065\003\048\002\038\001\023\001\ +\024\001\025\001\026\001\027\001\059\001\029\001\030\001\031\001\ +\032\001\044\002\034\001\070\001\119\003\013\001\246\001\241\002\ +\056\001\017\001\003\003\111\003\020\001\001\001\002\001\012\001\ +\064\001\035\001\075\001\007\001\008\001\069\001\119\001\019\001\ +\072\001\033\001\012\001\193\001\194\001\195\001\038\001\039\001\ +\040\001\041\001\007\001\083\001\095\002\045\003\046\003\082\001\ +\000\000\089\001\090\001\016\001\012\001\012\001\013\001\213\001\ +\056\001\012\001\098\001\217\001\218\001\079\003\072\001\012\001\ +\064\001\187\003\013\001\156\003\035\001\069\001\059\001\198\003\ +\072\001\122\001\063\001\063\001\007\001\038\001\039\001\040\001\ +\041\001\012\001\013\001\083\001\069\001\016\001\013\001\072\001\ +\238\001\089\001\090\001\012\001\069\001\240\001\153\001\056\001\ +\136\001\007\001\098\001\060\001\059\001\078\001\161\001\053\002\ +\063\001\072\001\016\001\012\001\036\002\030\002\059\001\042\002\ +\043\002\131\003\063\001\065\002\175\001\064\001\136\003\197\001\ +\082\001\139\003\066\001\123\001\124\001\125\001\126\001\127\001\ +\059\001\060\002\000\000\013\001\063\001\218\001\212\001\017\001\ +\136\001\064\001\020\001\007\001\008\001\219\001\233\001\007\001\ +\179\002\012\001\077\002\000\000\233\001\016\001\000\000\033\001\ +\016\001\000\000\060\001\233\001\038\001\088\001\122\001\237\001\ +\009\001\239\001\123\001\124\001\125\001\126\001\127\001\218\002\ +\035\001\247\001\248\001\007\001\008\001\002\001\056\001\199\001\ +\089\001\090\001\020\001\012\001\198\003\013\001\064\001\016\001\ +\010\001\011\001\027\001\069\001\013\001\066\001\072\001\072\001\ +\069\001\033\001\071\001\001\001\002\001\003\001\004\001\005\001\ +\006\001\083\001\035\001\080\001\081\001\072\001\137\001\089\001\ +\090\001\120\001\121\001\038\002\031\002\163\002\007\001\008\001\ +\098\001\123\001\124\001\125\001\066\001\127\001\089\001\069\001\ +\072\001\071\001\053\002\030\002\055\002\075\001\035\001\000\000\ +\078\001\164\002\061\002\062\002\167\002\168\002\065\002\072\001\ +\091\002\092\002\045\002\046\002\098\001\024\003\073\002\073\002\ +\098\001\073\002\033\001\054\002\200\003\201\003\136\001\035\001\ +\089\001\207\002\033\001\065\001\205\002\206\002\072\001\019\001\ +\091\002\092\002\207\002\217\002\188\002\189\002\201\002\035\001\ +\091\002\092\002\072\001\091\002\092\002\080\002\034\001\033\001\ +\016\001\072\001\088\001\086\002\087\002\091\001\092\001\093\001\ +\094\001\007\001\096\001\072\001\012\001\097\001\100\001\016\001\ +\097\001\199\002\040\001\027\001\231\002\057\001\058\001\059\001\ +\072\001\061\001\062\001\063\001\130\002\131\002\116\001\213\002\ +\019\001\097\001\120\001\121\001\218\002\013\001\060\001\035\001\ +\000\000\017\001\072\001\126\002\020\001\068\001\040\001\034\001\ +\001\000\002\000\003\000\004\000\127\003\035\001\075\001\157\002\ +\163\002\033\001\089\003\001\001\022\001\013\001\038\001\039\001\ +\019\001\041\001\060\001\064\001\143\003\013\001\063\001\059\001\ +\059\001\013\001\061\001\062\001\063\001\013\001\114\001\115\001\ +\056\001\060\001\051\003\064\001\053\003\040\003\013\001\098\001\ +\064\001\172\002\199\002\016\001\033\001\069\001\068\003\000\000\ +\072\001\204\002\205\002\206\002\207\002\123\001\124\001\125\001\ +\213\002\127\001\072\001\083\001\069\001\216\002\217\002\097\001\ +\072\001\089\001\090\001\148\000\149\000\150\000\151\000\045\003\ +\046\003\228\002\098\001\072\001\072\001\224\002\072\001\114\001\ +\115\001\123\001\124\001\125\001\126\001\127\001\072\001\127\001\ +\013\001\111\003\016\001\012\001\017\001\072\001\000\000\020\001\ +\016\001\013\001\022\001\022\001\064\001\013\001\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\013\001\035\001\098\001\ +\136\001\038\001\039\001\040\001\041\001\035\001\121\003\033\001\ +\012\001\015\003\083\001\072\001\072\001\019\003\072\001\021\003\ +\028\001\098\001\033\001\056\001\057\001\058\001\100\003\060\001\ +\013\001\100\003\101\001\064\001\098\001\115\003\072\001\098\001\ +\069\001\098\001\012\001\072\001\016\001\127\001\117\001\016\001\ +\051\003\016\001\053\003\072\001\159\003\007\001\083\001\003\001\ +\011\001\072\001\012\001\013\001\089\001\090\001\016\001\066\003\ +\043\003\068\003\072\001\072\001\013\001\098\001\016\001\033\001\ +\017\001\063\001\033\001\020\001\079\003\079\003\185\003\079\003\ +\013\001\000\000\013\001\013\001\003\001\004\001\005\001\006\001\ +\033\001\028\001\064\001\027\001\072\001\072\003\123\001\124\001\ +\125\001\126\001\127\001\097\003\129\001\130\001\100\003\098\001\ +\072\001\059\001\072\001\136\001\111\003\063\001\115\003\033\001\ +\072\001\016\001\072\001\013\001\072\001\016\001\066\001\064\001\ +\072\001\069\001\013\001\071\001\069\001\072\001\016\001\072\001\ +\131\003\131\003\078\001\131\003\080\001\081\001\088\001\035\001\ +\139\003\139\003\083\001\139\003\033\001\013\001\016\001\118\001\ +\089\001\090\001\065\001\118\001\028\001\072\001\020\001\072\001\ +\072\001\098\001\119\001\098\001\154\003\160\003\072\001\091\001\ +\092\001\093\001\094\001\095\001\096\001\072\001\072\001\072\001\ +\119\001\088\001\016\001\007\001\091\001\092\001\093\001\094\001\ +\000\000\096\001\016\001\020\001\013\001\100\001\098\001\137\001\ +\116\001\098\001\165\003\166\003\013\001\072\001\035\001\136\001\ +\000\000\000\000\013\001\198\003\198\003\116\001\198\003\064\001\ +\001\001\002\001\003\001\004\001\005\001\006\001\007\001\008\001\ +\009\001\010\001\011\001\012\001\013\001\014\001\015\001\016\001\ +\017\001\018\001\019\001\020\001\021\001\022\001\023\001\024\001\ +\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ +\033\001\034\001\035\001\036\001\037\001\038\001\039\001\040\001\ +\041\001\042\001\043\001\044\001\045\001\046\001\047\001\048\001\ +\049\001\050\001\051\001\052\001\053\001\054\001\055\001\056\001\ +\057\001\058\001\059\001\060\001\061\001\062\001\063\001\064\001\ +\065\001\066\001\000\000\068\001\069\001\070\001\071\001\072\001\ +\073\001\074\001\075\001\076\001\077\001\078\001\079\001\080\001\ +\081\001\082\001\083\001\084\001\085\001\086\001\087\001\088\001\ +\089\001\090\001\091\001\092\001\093\001\072\001\095\001\096\001\ +\097\001\098\001\099\001\100\001\101\001\102\001\103\001\104\001\ +\105\001\106\001\107\001\108\001\109\001\110\001\111\001\112\001\ +\113\001\114\001\115\001\116\001\117\001\118\001\119\001\120\001\ +\121\001\122\001\098\001\000\000\125\001\126\001\127\001\128\001\ +\129\001\130\001\131\001\132\001\133\001\134\001\135\001\136\001\ +\137\001\138\001\001\001\002\001\003\001\004\001\005\001\006\001\ +\007\001\008\001\016\001\013\001\098\001\035\001\065\001\014\001\ +\015\001\072\001\098\001\098\001\072\001\016\001\013\001\022\001\ +\023\001\024\001\025\001\026\001\028\001\013\001\013\001\072\001\ +\013\001\072\001\247\000\088\003\013\001\088\001\197\001\023\002\ +\091\001\092\001\093\001\094\001\034\001\096\001\166\000\027\000\ +\126\002\100\001\238\001\240\001\141\002\218\001\038\001\039\001\ +\040\001\041\001\092\003\217\001\119\002\038\001\039\001\040\001\ +\041\001\116\001\065\001\000\000\246\001\068\001\115\003\070\001\ +\056\001\213\002\118\002\007\001\060\001\076\001\077\001\056\001\ +\012\001\013\001\207\001\060\001\016\001\084\001\085\001\086\001\ +\087\001\088\001\089\001\090\001\091\001\092\001\093\001\094\001\ +\095\001\096\001\065\002\143\003\228\002\100\001\101\001\102\001\ +\103\001\104\001\105\001\106\001\107\001\108\001\109\001\110\001\ +\111\001\204\002\171\000\084\002\093\002\116\001\117\001\118\001\ +\119\001\120\001\121\001\122\001\083\002\002\000\092\002\059\001\ +\186\003\073\003\186\003\063\001\131\001\013\001\136\003\187\003\ +\007\001\008\001\137\001\123\001\124\001\125\001\126\001\127\001\ +\072\002\124\000\123\001\124\001\125\001\126\001\127\001\022\001\ +\023\001\024\001\025\001\026\001\088\001\002\000\038\001\039\001\ +\040\001\041\001\072\003\166\003\153\001\203\003\139\000\064\001\ +\007\001\192\003\043\003\160\003\155\003\012\001\013\001\002\000\ +\056\001\016\001\255\255\255\255\060\001\210\002\255\255\255\255\ +\255\255\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ +\006\001\007\001\008\001\255\255\255\255\255\255\255\255\255\255\ +\014\001\015\001\255\255\255\255\000\000\137\001\255\255\255\255\ +\022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\059\001\255\255\255\255\255\255\ +\063\001\255\255\255\255\255\255\255\255\255\255\255\255\102\001\ +\103\001\104\001\105\001\106\001\107\001\108\001\109\001\110\001\ +\111\001\255\255\255\255\123\001\124\001\125\001\126\001\127\001\ +\255\255\088\001\255\255\065\001\255\255\255\255\068\001\255\255\ +\070\001\255\255\255\255\007\001\255\255\075\001\076\001\077\001\ +\012\001\013\001\255\255\255\255\016\001\255\255\084\001\085\001\ \086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ -\094\001\095\001\096\001\101\002\042\003\194\001\100\001\101\001\ +\094\001\095\001\096\001\255\255\255\255\255\255\100\001\101\001\ \102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\048\002\065\001\187\002\122\003\115\001\116\001\117\001\ -\118\001\119\001\120\001\121\001\013\001\208\002\007\001\122\001\ -\123\001\124\001\128\001\012\001\013\001\017\001\013\001\016\001\ -\134\001\088\001\167\000\067\002\091\001\092\001\093\001\094\001\ -\066\002\096\001\076\002\115\003\166\003\038\001\039\001\040\001\ -\041\001\166\003\038\001\039\001\040\001\041\001\053\003\038\001\ -\039\001\040\001\041\001\167\003\115\001\116\001\055\002\056\001\ -\119\001\120\001\122\000\060\001\056\001\002\000\007\001\052\003\ -\060\001\056\001\059\001\012\001\013\001\060\001\063\001\016\001\ -\146\003\183\003\021\002\140\001\136\000\025\003\001\001\002\001\ -\003\001\004\001\005\001\006\001\007\001\008\001\055\001\172\003\ -\134\003\140\003\000\000\014\001\015\001\193\002\002\000\088\001\ -\255\255\255\255\255\255\022\001\023\001\024\001\025\001\026\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\013\001\255\255\059\001\255\255\255\255\255\255\063\001\255\255\ -\255\255\122\001\123\001\124\001\255\255\255\255\122\001\123\001\ -\124\001\255\255\255\255\122\001\123\001\124\001\255\255\255\255\ -\255\255\038\001\039\001\040\001\041\001\134\001\065\001\088\001\ -\255\255\068\001\255\255\070\001\255\255\255\255\255\255\007\001\ -\075\001\076\001\077\001\056\001\012\001\013\001\255\255\060\001\ -\016\001\084\001\085\001\086\001\087\001\088\001\089\001\090\001\ -\091\001\092\001\093\001\094\001\095\001\096\001\255\255\255\255\ -\255\255\100\001\101\001\102\001\103\001\104\001\105\001\106\001\ -\107\001\108\001\109\001\110\001\255\255\134\001\255\255\255\255\ -\115\001\116\001\117\001\255\255\119\001\120\001\121\001\255\255\ -\255\255\255\255\255\255\059\001\255\255\128\001\255\255\063\001\ -\255\255\255\255\255\255\134\001\255\255\001\001\002\001\003\001\ -\004\001\005\001\006\001\007\001\008\001\122\001\123\001\124\001\ -\000\000\065\001\014\001\015\001\255\255\019\001\255\255\255\255\ -\088\001\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ -\255\255\255\255\255\255\255\255\034\001\255\255\255\255\255\255\ -\088\001\255\255\255\255\091\001\092\001\093\001\094\001\255\255\ -\096\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\057\001\058\001\059\001\255\255\061\001\ -\062\001\063\001\255\255\115\001\255\255\065\001\134\001\255\255\ +\110\001\111\001\137\001\039\001\040\001\041\001\116\001\117\001\ +\118\001\255\255\120\001\121\001\122\001\255\255\255\255\059\001\ +\255\255\255\255\255\255\063\001\255\255\131\001\255\255\255\255\ +\060\001\255\255\255\255\137\001\001\001\002\001\003\001\004\001\ +\005\001\006\001\007\001\008\001\255\255\255\255\255\255\255\255\ +\255\255\014\001\015\001\255\255\088\001\000\000\255\255\068\001\ +\255\255\022\001\023\001\024\001\025\001\026\001\075\001\076\001\ +\077\001\255\255\255\255\255\255\255\255\255\255\255\255\084\001\ +\085\001\086\001\087\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\000\000\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\123\001\ +\124\001\125\001\126\001\127\001\065\001\137\001\255\255\068\001\ +\117\001\070\001\255\255\255\255\007\001\122\001\255\255\076\001\ +\077\001\012\001\013\001\255\255\255\255\016\001\255\255\084\001\ +\085\001\086\001\087\001\088\001\089\001\090\001\091\001\092\001\ +\093\001\094\001\095\001\096\001\255\255\255\255\255\255\100\001\ +\101\001\102\001\103\001\104\001\105\001\106\001\107\001\108\001\ +\109\001\110\001\111\001\038\001\039\001\040\001\041\001\116\001\ +\117\001\118\001\255\255\120\001\121\001\122\001\255\255\255\255\ +\059\001\255\255\255\255\255\255\063\001\056\001\131\001\255\255\ +\255\255\060\001\255\255\255\255\137\001\001\001\002\001\003\001\ +\004\001\005\001\006\001\007\001\008\001\072\001\255\255\255\255\ +\255\255\255\255\014\001\015\001\255\255\088\001\000\000\255\255\ +\255\255\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\124\001\125\001\126\001\127\001\065\001\137\001\255\255\ \068\001\255\255\070\001\255\255\255\255\007\001\255\255\255\255\ \076\001\077\001\012\001\013\001\255\255\255\255\016\001\255\255\ \084\001\085\001\086\001\087\001\088\001\089\001\090\001\091\001\ -\092\001\093\001\094\001\095\001\096\001\255\255\255\255\255\255\ +\092\001\093\001\094\001\095\001\096\001\004\001\255\255\006\001\ \100\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ -\108\001\109\001\110\001\113\001\114\001\255\255\255\255\115\001\ -\116\001\117\001\255\255\119\001\120\001\121\001\255\255\255\255\ -\255\255\059\001\255\255\255\255\128\001\063\001\255\255\255\255\ -\255\255\255\255\134\001\001\001\002\001\003\001\004\001\005\001\ -\006\001\007\001\008\001\255\255\255\255\255\255\000\000\255\255\ -\014\001\015\001\255\255\255\255\255\255\255\255\088\001\255\255\ -\022\001\023\001\024\001\025\001\026\001\038\001\039\001\040\001\ -\041\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\056\001\ -\255\255\255\255\255\255\060\001\255\255\255\255\255\255\064\001\ +\108\001\109\001\110\001\111\001\038\001\039\001\040\001\041\001\ +\116\001\117\001\118\001\255\255\120\001\121\001\122\001\255\255\ +\255\255\059\001\255\255\255\255\255\255\063\001\056\001\131\001\ +\255\255\255\255\060\001\255\255\255\255\137\001\001\001\002\001\ +\003\001\004\001\005\001\006\001\007\001\008\001\072\001\255\255\ +\255\255\255\255\255\255\014\001\015\001\255\255\088\001\000\000\ +\255\255\255\255\065\001\022\001\023\001\024\001\025\001\026\001\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\065\001\134\001\255\255\068\001\255\255\ -\070\001\255\255\255\255\007\001\255\255\255\255\076\001\077\001\ -\012\001\013\001\255\255\255\255\016\001\255\255\084\001\085\001\ -\086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ -\094\001\095\001\096\001\255\255\255\255\255\255\100\001\101\001\ -\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\122\001\123\001\124\001\255\255\115\001\116\001\117\001\ -\255\255\119\001\120\001\121\001\255\255\255\255\255\255\059\001\ -\255\255\255\255\128\001\063\001\255\255\255\255\255\255\255\255\ -\134\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ -\008\001\255\255\255\255\255\255\000\000\255\255\014\001\015\001\ -\255\255\255\255\255\255\255\255\088\001\255\255\022\001\023\001\ -\024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\033\001\255\255\255\255\255\255\255\255\038\001\039\001\040\001\ -\041\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\056\001\ -\255\255\065\001\134\001\060\001\068\001\007\001\070\001\255\255\ -\255\255\255\255\012\001\013\001\076\001\077\001\016\001\255\255\ -\255\255\255\255\255\255\255\255\084\001\085\001\086\001\087\001\ -\088\001\089\001\090\001\091\001\092\001\093\001\094\001\095\001\ -\096\001\255\255\255\255\255\255\100\001\101\001\102\001\103\001\ -\104\001\105\001\106\001\107\001\108\001\109\001\110\001\255\255\ -\255\255\255\255\255\255\115\001\116\001\117\001\255\255\119\001\ -\120\001\059\001\255\255\255\255\255\255\063\001\255\255\255\255\ -\128\001\122\001\123\001\124\001\255\255\255\255\134\001\001\001\ +\001\001\002\001\003\001\004\001\005\001\006\001\255\255\255\255\ +\255\255\088\001\255\255\255\255\091\001\092\001\093\001\094\001\ +\255\255\096\001\255\255\255\255\255\255\100\001\255\255\255\255\ +\255\255\123\001\124\001\125\001\126\001\127\001\065\001\137\001\ +\255\255\068\001\255\255\070\001\255\255\116\001\255\255\255\255\ +\255\255\076\001\077\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\084\001\085\001\086\001\087\001\088\001\089\001\090\001\ +\091\001\092\001\093\001\094\001\095\001\096\001\255\255\255\255\ +\065\001\100\001\101\001\102\001\103\001\104\001\105\001\106\001\ +\107\001\108\001\109\001\110\001\111\001\255\255\255\255\255\255\ +\255\255\116\001\117\001\118\001\255\255\120\001\121\001\088\001\ +\255\255\255\255\091\001\092\001\093\001\094\001\255\255\096\001\ +\131\001\255\255\255\255\100\001\255\255\255\255\137\001\001\001\ \002\001\003\001\004\001\005\001\006\001\007\001\008\001\255\255\ -\255\255\255\255\000\000\255\255\014\001\015\001\088\001\255\255\ -\255\255\255\255\255\255\255\255\022\001\023\001\024\001\025\001\ -\026\001\038\001\039\001\040\001\041\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\255\255\255\255\255\255\056\001\255\255\255\255\255\255\060\001\ -\255\255\255\255\255\255\255\255\255\255\056\001\255\255\255\255\ -\255\255\060\001\000\000\255\255\134\001\255\255\255\255\065\001\ +\255\255\255\255\255\255\116\001\014\001\015\001\255\255\255\255\ +\000\000\255\255\255\255\255\255\022\001\023\001\024\001\025\001\ +\026\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\001\001\002\001\003\001\004\001\005\001\006\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\065\001\ \255\255\255\255\068\001\255\255\070\001\255\255\255\255\255\255\ -\255\255\255\255\076\001\077\001\089\001\090\001\255\255\255\255\ +\255\255\255\255\076\001\077\001\255\255\255\255\255\255\255\255\ \255\255\255\255\084\001\085\001\086\001\087\001\088\001\089\001\ -\090\001\091\001\092\001\093\001\094\001\095\001\096\001\098\001\ -\255\255\255\255\100\001\101\001\102\001\103\001\104\001\105\001\ -\106\001\107\001\108\001\109\001\110\001\122\001\123\001\124\001\ -\255\255\115\001\116\001\117\001\255\255\119\001\120\001\122\001\ -\123\001\124\001\255\255\255\255\255\255\255\255\128\001\255\255\ -\000\000\255\255\133\001\255\255\134\001\001\001\002\001\003\001\ -\004\001\005\001\006\001\007\001\008\001\255\255\255\255\255\255\ -\013\001\255\255\014\001\015\001\255\255\255\255\255\255\255\255\ -\013\001\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ +\090\001\091\001\092\001\093\001\094\001\095\001\096\001\255\255\ +\255\255\065\001\100\001\101\001\102\001\103\001\104\001\105\001\ +\106\001\107\001\108\001\109\001\110\001\111\001\255\255\255\255\ +\255\255\255\255\116\001\117\001\118\001\255\255\120\001\121\001\ +\088\001\255\255\255\255\091\001\092\001\093\001\094\001\255\255\ +\096\001\131\001\255\255\000\000\100\001\255\255\255\255\137\001\ +\001\001\002\001\003\001\004\001\005\001\006\001\007\001\008\001\ +\255\255\255\255\255\255\255\255\116\001\014\001\015\001\255\255\ +\120\001\121\001\255\255\255\255\255\255\022\001\023\001\024\001\ +\025\001\026\001\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\038\001\039\001\040\001\041\001\255\255\255\255\255\255\ -\255\255\038\001\039\001\040\001\041\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\056\001\255\255\255\255\255\255\060\001\ -\255\255\255\255\255\255\056\001\255\255\065\001\255\255\060\001\ -\255\255\255\255\070\001\255\255\255\255\255\255\255\255\255\255\ -\076\001\077\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\084\001\085\001\086\001\087\001\088\001\089\001\090\001\091\001\ -\092\001\093\001\094\001\095\001\096\001\255\255\255\255\000\000\ -\100\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ -\108\001\109\001\110\001\255\255\255\255\255\255\000\000\115\001\ -\116\001\117\001\255\255\119\001\120\001\122\001\123\001\124\001\ -\255\255\255\255\255\255\255\255\128\001\122\001\123\001\124\001\ -\255\255\255\255\134\001\001\001\002\001\003\001\004\001\005\001\ -\006\001\007\001\008\001\255\255\255\255\255\255\013\001\255\255\ -\014\001\015\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\038\001\ -\039\001\040\001\041\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ -\006\001\056\001\255\255\255\255\255\255\060\001\255\255\255\255\ -\255\255\255\255\255\255\065\001\255\255\255\255\255\255\255\255\ -\070\001\255\255\255\255\255\255\255\255\255\255\076\001\077\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\084\001\085\001\ -\086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ -\094\001\095\001\096\001\255\255\000\000\255\255\100\001\101\001\ -\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\255\255\255\255\065\001\255\255\115\001\116\001\117\001\ -\255\255\119\001\120\001\122\001\123\001\124\001\255\255\007\001\ -\255\255\255\255\128\001\255\255\012\001\013\001\255\255\255\255\ -\134\001\017\001\088\001\019\001\020\001\091\001\092\001\093\001\ -\094\001\255\255\096\001\027\001\028\001\029\001\030\001\031\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\065\001\255\255\255\255\255\255\255\255\070\001\255\255\255\255\ +\007\001\255\255\255\255\076\001\077\001\012\001\013\001\255\255\ +\255\255\016\001\255\255\084\001\085\001\086\001\087\001\088\001\ +\089\001\090\001\091\001\092\001\093\001\094\001\095\001\096\001\ +\255\255\255\255\255\255\100\001\101\001\102\001\103\001\104\001\ +\105\001\106\001\107\001\108\001\109\001\110\001\111\001\255\255\ +\255\255\255\255\255\255\116\001\117\001\118\001\255\255\120\001\ +\121\001\000\000\255\255\255\255\059\001\255\255\255\255\255\255\ +\063\001\255\255\131\001\255\255\255\255\255\255\255\255\255\255\ +\137\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ +\008\001\255\255\255\255\255\255\255\255\255\255\014\001\015\001\ +\255\255\088\001\255\255\255\255\255\255\255\255\022\001\023\001\ +\024\001\025\001\026\001\255\255\255\255\019\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\027\001\028\001\029\001\ +\030\001\031\001\032\001\255\255\034\001\035\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\007\001\ +\008\001\065\001\137\001\057\001\058\001\059\001\070\001\061\001\ +\062\001\063\001\255\255\255\255\076\001\077\001\022\001\023\001\ +\024\001\025\001\026\001\255\255\084\001\085\001\086\001\087\001\ +\088\001\089\001\090\001\091\001\092\001\093\001\094\001\095\001\ +\096\001\255\255\255\255\255\255\100\001\101\001\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ +\000\000\255\255\255\255\255\255\116\001\117\001\118\001\255\255\ +\120\001\121\001\007\001\255\255\114\001\115\001\255\255\012\001\ +\013\001\255\255\255\255\131\001\017\001\255\255\019\001\020\001\ +\255\255\137\001\255\255\129\001\130\001\255\255\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\034\001\035\001\255\255\ +\255\255\038\001\039\001\040\001\041\001\255\255\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ +\255\255\255\255\255\255\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\064\001\255\255\255\255\255\255\255\255\ +\069\001\255\255\255\255\072\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\033\001\255\255\255\255\255\255\083\001\038\001\ +\039\001\040\001\041\001\088\001\089\001\090\001\255\255\255\255\ +\255\255\255\255\007\001\255\255\097\001\098\001\255\255\012\001\ +\013\001\056\001\000\000\016\001\255\255\060\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\114\001\115\001\255\255\ +\255\255\000\000\255\255\255\255\255\255\255\255\123\001\124\001\ +\125\001\126\001\127\001\255\255\129\001\130\001\255\255\255\255\ +\007\001\255\255\255\255\136\001\137\001\012\001\013\001\255\255\ +\255\255\255\255\017\001\255\255\019\001\020\001\059\001\255\255\ +\255\255\255\255\063\001\255\255\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\255\255\123\001\124\001\125\001\126\001\ +\127\001\255\255\255\255\088\001\255\255\255\255\255\255\255\255\ +\255\255\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ +\063\001\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ +\255\255\072\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\083\001\255\255\255\255\255\255\ +\255\255\088\001\089\001\090\001\255\255\255\255\255\255\255\255\ +\255\255\007\001\097\001\098\001\137\001\255\255\012\001\013\001\ +\255\255\255\255\016\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\000\000\114\001\115\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\124\001\125\001\126\001\ +\127\001\255\255\129\001\130\001\255\255\255\255\255\255\007\001\ +\255\255\136\001\137\001\255\255\012\001\013\001\255\255\255\255\ +\255\255\017\001\255\255\019\001\020\001\059\001\255\255\255\255\ +\255\255\063\001\255\255\027\001\028\001\029\001\030\001\031\001\ \032\001\033\001\034\001\035\001\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\255\255\255\255\115\001\116\001\255\255\ -\255\255\119\001\120\001\255\255\255\255\255\255\255\255\255\255\ +\040\001\041\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\088\001\255\255\255\255\013\001\255\255\255\255\ \056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ +\064\001\007\001\255\255\255\255\255\255\069\001\012\001\013\001\ +\072\001\255\255\016\001\255\255\255\255\255\255\038\001\039\001\ +\040\001\041\001\255\255\083\001\255\255\255\255\000\000\255\255\ +\088\001\089\001\090\001\255\255\255\255\255\255\255\255\255\255\ +\056\001\097\001\098\001\137\001\060\001\000\000\255\255\255\255\ +\255\255\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ +\006\001\255\255\114\001\115\001\255\255\059\001\255\255\255\255\ +\255\255\063\001\255\255\123\001\124\001\125\001\126\001\127\001\ +\007\001\129\001\130\001\255\255\255\255\012\001\013\001\255\255\ +\136\001\137\001\017\001\255\255\019\001\020\001\255\255\255\255\ +\255\255\255\255\088\001\255\255\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\123\001\124\001\125\001\126\001\127\001\ +\255\255\255\255\255\255\065\001\255\255\255\255\068\001\255\255\ +\255\255\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ +\063\001\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ +\255\255\072\001\088\001\137\001\255\255\091\001\092\001\093\001\ +\094\001\255\255\096\001\255\255\083\001\255\255\100\001\255\255\ +\255\255\088\001\089\001\090\001\255\255\255\255\255\255\255\255\ +\000\000\255\255\097\001\098\001\255\255\255\255\116\001\117\001\ +\255\255\255\255\120\001\121\001\122\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\114\001\115\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\124\001\125\001\126\001\ +\127\001\007\001\129\001\130\001\255\255\255\255\012\001\013\001\ +\255\255\136\001\137\001\017\001\255\255\019\001\020\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\255\255\255\255\ +\038\001\039\001\040\001\041\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\013\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\056\001\057\001\058\001\059\001\060\001\061\001\ +\062\001\063\001\064\001\255\255\255\255\255\255\255\255\069\001\ +\255\255\255\255\072\001\255\255\038\001\039\001\040\001\041\001\ +\255\255\255\255\000\000\255\255\255\255\083\001\255\255\255\255\ +\255\255\255\255\088\001\089\001\090\001\255\255\056\001\255\255\ +\255\255\000\000\060\001\097\001\098\001\255\255\255\255\001\001\ +\002\001\003\001\004\001\005\001\006\001\007\001\008\001\255\255\ +\255\255\255\255\255\255\255\255\114\001\115\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\007\001\123\001\124\001\125\001\ +\126\001\127\001\013\001\129\001\130\001\255\255\017\001\255\255\ +\019\001\020\001\136\001\137\001\255\255\255\255\255\255\255\255\ +\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ +\035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ +\255\255\123\001\124\001\125\001\126\001\127\001\255\255\065\001\ +\255\255\255\255\068\001\255\255\255\255\056\001\057\001\058\001\ +\059\001\060\001\061\001\062\001\255\255\064\001\255\255\255\255\ +\255\255\255\255\069\001\255\255\255\255\072\001\088\001\255\255\ +\255\255\091\001\092\001\093\001\094\001\255\255\096\001\255\255\ +\083\001\255\255\100\001\255\255\255\255\088\001\089\001\090\001\ +\255\255\255\255\255\255\255\255\000\000\255\255\255\255\098\001\ +\255\255\255\255\116\001\117\001\255\255\255\255\120\001\121\001\ +\122\001\255\255\255\255\255\255\255\255\255\255\255\255\114\001\ +\115\001\255\255\255\255\255\255\255\255\255\255\255\255\007\001\ +\123\001\124\001\125\001\126\001\127\001\013\001\129\001\130\001\ +\255\255\017\001\255\255\019\001\020\001\136\001\137\001\255\255\ +\255\255\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\255\255\255\255\038\001\039\001\ +\040\001\041\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\000\000\255\255\255\255\255\255\013\001\255\255\ +\056\001\057\001\058\001\059\001\060\001\061\001\062\001\255\255\ \064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\033\001\255\255\255\255\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\083\001\255\255\000\000\255\255\255\255\ +\072\001\255\255\255\255\255\255\255\255\255\255\255\255\038\001\ +\039\001\040\001\041\001\083\001\255\255\255\255\255\255\255\255\ \088\001\089\001\090\001\255\255\255\255\255\255\255\255\255\255\ -\056\001\255\255\098\001\255\255\060\001\255\255\255\255\000\000\ -\001\001\002\001\003\001\004\001\005\001\006\001\007\001\008\001\ -\255\255\113\001\114\001\255\255\255\255\255\255\038\001\039\001\ -\040\001\041\001\122\001\123\001\124\001\007\001\126\001\127\001\ -\255\255\255\255\012\001\013\001\255\255\133\001\134\001\017\001\ -\056\001\019\001\020\001\255\255\060\001\255\255\255\255\255\255\ -\064\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\255\255\122\001\123\001\124\001\255\255\255\255\255\255\ -\065\001\255\255\255\255\068\001\255\255\255\255\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ -\255\255\255\255\255\255\069\001\255\255\255\255\072\001\088\001\ -\255\255\255\255\091\001\092\001\093\001\094\001\255\255\096\001\ -\255\255\083\001\122\001\123\001\124\001\255\255\088\001\089\001\ -\090\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\098\001\255\255\115\001\116\001\255\255\000\000\119\001\120\001\ -\121\001\255\255\255\255\255\255\255\255\255\255\255\255\113\001\ -\114\001\255\255\255\255\255\255\038\001\039\001\040\001\041\001\ -\122\001\123\001\124\001\007\001\126\001\127\001\255\255\255\255\ -\012\001\013\001\255\255\133\001\134\001\017\001\056\001\019\001\ -\020\001\255\255\060\001\255\255\255\255\255\255\255\255\027\001\ +\255\255\056\001\098\001\255\255\255\255\060\001\255\255\255\255\ +\255\255\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ +\006\001\255\255\114\001\115\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\123\001\124\001\125\001\126\001\127\001\ +\007\001\129\001\130\001\255\255\255\255\255\255\013\001\255\255\ +\136\001\137\001\017\001\255\255\019\001\020\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\000\000\123\001\124\001\125\001\126\001\ +\127\001\255\255\255\255\065\001\255\255\255\255\068\001\255\255\ +\255\255\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ +\255\255\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ +\255\255\072\001\088\001\255\255\255\255\091\001\092\001\093\001\ +\094\001\255\255\096\001\255\255\083\001\255\255\100\001\255\255\ +\255\255\088\001\089\001\090\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\098\001\255\255\255\255\116\001\255\255\ +\255\255\255\255\120\001\121\001\122\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\114\001\115\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\007\001\123\001\124\001\125\001\126\001\ +\127\001\013\001\129\001\130\001\255\255\017\001\255\255\019\001\ +\020\001\136\001\137\001\255\255\255\255\255\255\255\255\027\001\ +\028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ +\255\255\255\255\038\001\039\001\040\001\041\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\000\000\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\056\001\057\001\058\001\255\255\ +\060\001\061\001\062\001\255\255\064\001\255\255\255\255\255\255\ +\255\255\069\001\255\255\255\255\072\001\255\255\255\255\255\255\ +\255\255\007\001\008\001\255\255\255\255\255\255\255\255\083\001\ +\014\001\015\001\255\255\255\255\088\001\089\001\090\001\255\255\ +\022\001\023\001\024\001\025\001\026\001\255\255\098\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\114\001\115\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\123\001\ +\124\001\125\001\126\001\127\001\255\255\129\001\130\001\255\255\ +\255\255\255\255\255\255\255\255\136\001\137\001\068\001\255\255\ +\070\001\255\255\255\255\255\255\255\255\255\255\076\001\077\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\084\001\085\001\ +\086\001\087\001\255\255\089\001\090\001\255\255\255\255\255\255\ +\255\255\095\001\255\255\255\255\255\255\000\000\255\255\101\001\ +\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ +\110\001\111\001\255\255\255\255\255\255\255\255\255\255\117\001\ +\118\001\255\255\120\001\121\001\122\001\255\255\255\255\012\001\ +\013\001\255\255\255\255\016\001\017\001\131\001\019\001\020\001\ +\255\255\255\255\255\255\137\001\255\255\255\255\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\034\001\035\001\255\255\ +\255\255\038\001\039\001\040\001\041\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\013\001\255\255\255\255\056\001\057\001\058\001\059\001\060\001\ +\061\001\062\001\063\001\064\001\255\255\255\255\255\255\255\255\ +\069\001\255\255\255\255\072\001\255\255\255\255\255\255\255\255\ +\255\255\038\001\039\001\040\001\041\001\255\255\083\001\038\001\ +\039\001\040\001\041\001\255\255\089\001\090\001\255\255\255\255\ +\255\255\255\255\255\255\056\001\097\001\098\001\255\255\060\001\ +\255\255\056\001\255\255\255\255\255\255\060\001\000\000\255\255\ +\255\255\064\001\255\255\255\255\255\255\114\001\115\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\123\001\124\001\ +\125\001\126\001\127\001\007\001\129\001\130\001\255\255\255\255\ +\012\001\013\001\255\255\136\001\255\255\017\001\255\255\019\001\ +\020\001\255\255\255\255\255\255\255\255\255\255\255\255\027\001\ \028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ -\255\255\019\001\038\001\039\001\040\001\041\001\255\255\255\255\ -\255\255\027\001\028\001\029\001\030\001\031\001\032\001\255\255\ -\034\001\035\001\255\255\255\255\056\001\057\001\058\001\059\001\ +\255\255\255\255\038\001\039\001\040\001\041\001\123\001\124\001\ +\125\001\126\001\127\001\255\255\123\001\124\001\125\001\126\001\ +\127\001\013\001\255\255\255\255\056\001\057\001\058\001\059\001\ \060\001\061\001\062\001\063\001\064\001\255\255\255\255\255\255\ -\255\255\069\001\255\255\255\255\072\001\255\255\255\255\057\001\ -\058\001\059\001\255\255\061\001\062\001\063\001\255\255\083\001\ -\122\001\123\001\124\001\255\255\088\001\089\001\090\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\000\000\098\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\001\001\002\001\ -\003\001\004\001\005\001\006\001\255\255\113\001\114\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\122\001\123\001\ -\124\001\255\255\126\001\127\001\255\255\255\255\007\001\113\001\ -\114\001\133\001\134\001\012\001\013\001\255\255\255\255\255\255\ -\017\001\255\255\019\001\020\001\126\001\127\001\255\255\255\255\ -\255\255\255\255\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\034\001\035\001\255\255\255\255\038\001\039\001\040\001\ -\041\001\255\255\255\255\255\255\255\255\255\255\065\001\255\255\ -\255\255\068\001\255\255\255\255\255\255\255\255\255\255\056\001\ -\057\001\058\001\059\001\060\001\061\001\062\001\063\001\064\001\ -\255\255\255\255\255\255\255\255\069\001\088\001\255\255\072\001\ -\091\001\092\001\093\001\094\001\255\255\096\001\255\255\255\255\ -\255\255\255\255\083\001\255\255\255\255\000\000\255\255\088\001\ -\089\001\090\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\115\001\098\001\255\255\255\255\119\001\120\001\121\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\113\001\114\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\122\001\123\001\124\001\007\001\126\001\127\001\255\255\ -\255\255\012\001\013\001\255\255\133\001\134\001\017\001\255\255\ +\255\255\069\001\255\255\255\255\072\001\255\255\255\255\255\255\ +\255\255\255\255\038\001\039\001\040\001\041\001\255\255\083\001\ +\255\255\255\255\000\000\255\255\255\255\089\001\090\001\255\255\ +\255\255\255\255\255\255\255\255\056\001\097\001\098\001\255\255\ +\060\001\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\114\001\115\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\123\001\ +\124\001\125\001\126\001\127\001\007\001\129\001\130\001\255\255\ +\255\255\012\001\013\001\255\255\136\001\255\255\017\001\255\255\ \019\001\020\001\255\255\255\255\255\255\255\255\255\255\255\255\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\255\255\255\255\255\255\255\255\033\001\255\255\255\255\255\255\ -\255\255\038\001\039\001\040\001\041\001\056\001\057\001\058\001\ -\059\001\060\001\061\001\062\001\063\001\064\001\255\255\000\000\ -\255\255\255\255\069\001\056\001\255\255\072\001\255\255\060\001\ -\255\255\255\255\255\255\255\255\255\255\000\000\255\255\255\255\ -\083\001\255\255\255\255\255\255\255\255\088\001\089\001\090\001\ -\255\255\255\255\255\255\038\001\039\001\040\001\041\001\098\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\056\001\113\001\114\001\ -\255\255\060\001\255\255\255\255\007\001\255\255\255\255\122\001\ -\123\001\124\001\013\001\126\001\127\001\072\001\017\001\255\255\ -\019\001\020\001\133\001\134\001\255\255\122\001\123\001\124\001\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\255\255\255\255\255\255\255\255\033\001\255\255\255\255\255\255\ -\255\255\038\001\039\001\040\001\041\001\056\001\057\001\058\001\ -\059\001\060\001\061\001\062\001\255\255\064\001\255\255\122\001\ -\123\001\124\001\069\001\056\001\255\255\072\001\255\255\060\001\ -\038\001\039\001\040\001\041\001\255\255\000\000\255\255\255\255\ -\083\001\255\255\255\255\255\255\255\255\088\001\089\001\090\001\ -\007\001\008\001\056\001\255\255\255\255\255\255\060\001\098\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\022\001\ -\023\001\024\001\025\001\026\001\255\255\255\255\113\001\114\001\ -\255\255\255\255\255\255\255\255\007\001\255\255\255\255\122\001\ -\123\001\124\001\013\001\126\001\127\001\255\255\017\001\255\255\ -\019\001\020\001\133\001\134\001\098\001\122\001\123\001\124\001\ +\035\001\255\255\255\255\038\001\039\001\040\001\041\001\123\001\ +\124\001\125\001\126\001\127\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\013\001\255\255\255\255\056\001\057\001\058\001\ +\059\001\060\001\061\001\062\001\063\001\064\001\255\255\255\255\ +\255\255\255\255\069\001\255\255\255\255\072\001\255\255\255\255\ +\255\255\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ +\083\001\255\255\255\255\255\255\255\255\255\255\089\001\090\001\ +\255\255\255\255\255\255\255\255\000\000\056\001\097\001\098\001\ +\255\255\060\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\114\001\ +\115\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\124\001\125\001\126\001\127\001\007\001\129\001\130\001\ +\255\255\255\255\012\001\013\001\255\255\136\001\255\255\017\001\ +\255\255\019\001\020\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\013\001\028\001\029\001\030\001\031\001\032\001\033\001\ +\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ +\123\001\124\001\125\001\126\001\127\001\255\255\255\255\255\255\ +\255\255\255\255\038\001\039\001\040\001\041\001\056\001\057\001\ +\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ +\255\255\255\255\255\255\069\001\056\001\255\255\072\001\255\255\ +\060\001\255\255\255\255\000\000\255\255\255\255\255\255\255\255\ +\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ +\090\001\255\255\000\000\255\255\255\255\255\255\255\255\097\001\ +\098\001\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ +\006\001\007\001\008\001\255\255\255\255\255\255\255\255\255\255\ +\114\001\115\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\123\001\124\001\125\001\126\001\127\001\013\001\129\001\ +\130\001\255\255\017\001\255\255\019\001\020\001\136\001\123\001\ +\124\001\125\001\126\001\127\001\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\255\255\255\255\255\255\255\255\255\255\ +\033\001\255\255\255\255\065\001\255\255\038\001\039\001\040\001\ +\041\001\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ +\063\001\064\001\255\255\255\255\255\255\255\255\069\001\056\001\ +\255\255\072\001\088\001\060\001\255\255\091\001\092\001\093\001\ +\094\001\255\255\096\001\255\255\083\001\255\255\100\001\255\255\ +\255\255\255\255\089\001\090\001\255\255\000\000\255\255\255\255\ +\255\255\255\255\255\255\098\001\255\255\255\255\116\001\117\001\ +\255\255\255\255\120\001\121\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\114\001\115\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\124\001\125\001\126\001\ +\127\001\013\001\129\001\130\001\255\255\017\001\255\255\019\001\ +\020\001\136\001\123\001\124\001\125\001\126\001\127\001\027\001\ +\028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ +\255\255\255\255\038\001\039\001\040\001\041\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\056\001\057\001\058\001\059\001\ +\060\001\061\001\062\001\063\001\064\001\255\255\255\255\255\255\ +\255\255\069\001\033\001\255\255\072\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\255\255\000\000\255\255\255\255\083\001\ +\255\255\255\255\255\255\255\255\255\255\089\001\090\001\255\255\ +\000\000\056\001\255\255\255\255\255\255\060\001\098\001\255\255\ +\255\255\255\255\255\255\255\255\001\001\002\001\003\001\004\001\ +\005\001\006\001\255\255\255\255\255\255\255\255\114\001\115\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\000\000\123\001\ +\124\001\125\001\126\001\127\001\255\255\129\001\130\001\013\001\ +\255\255\255\255\255\255\017\001\136\001\019\001\020\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\255\255\255\255\ +\038\001\039\001\040\001\041\001\123\001\124\001\125\001\126\001\ +\127\001\033\001\255\255\255\255\065\001\255\255\038\001\039\001\ +\040\001\041\001\056\001\057\001\058\001\059\001\060\001\061\001\ +\062\001\063\001\064\001\255\255\255\255\255\255\255\255\069\001\ +\056\001\255\255\072\001\088\001\060\001\255\255\091\001\092\001\ +\093\001\094\001\000\000\096\001\255\255\083\001\255\255\100\001\ +\255\255\255\255\255\255\089\001\090\001\255\255\000\000\255\255\ +\008\001\255\255\255\255\255\255\098\001\255\255\255\255\116\001\ +\117\001\255\255\255\255\120\001\121\001\021\001\022\001\023\001\ +\024\001\025\001\026\001\255\255\114\001\115\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\007\001\123\001\124\001\125\001\ +\126\001\127\001\013\001\129\001\130\001\255\255\017\001\255\255\ +\019\001\020\001\136\001\123\001\124\001\125\001\126\001\127\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ \035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\255\255\255\255\000\000\255\255\122\001\123\001\124\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\056\001\057\001\058\001\ -\059\001\060\001\061\001\062\001\255\255\064\001\255\255\255\255\ -\255\255\255\255\069\001\255\255\255\255\072\001\101\001\102\001\ -\103\001\104\001\105\001\106\001\107\001\108\001\109\001\110\001\ -\083\001\255\255\255\255\255\255\255\255\088\001\089\001\090\001\ -\255\255\255\255\255\255\038\001\039\001\040\001\041\001\098\001\ -\001\001\002\001\003\001\004\001\005\001\006\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\056\001\113\001\114\001\ -\255\255\060\001\255\255\255\255\007\001\255\255\255\255\122\001\ -\123\001\124\001\013\001\126\001\127\001\072\001\017\001\255\255\ -\019\001\020\001\133\001\134\001\255\255\255\255\255\255\255\255\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\065\001\255\255\255\255\068\001\255\255\056\001\057\001\058\001\ -\059\001\060\001\061\001\062\001\255\255\064\001\255\255\122\001\ -\123\001\124\001\069\001\255\255\255\255\072\001\255\255\088\001\ -\255\255\255\255\091\001\092\001\093\001\094\001\255\255\096\001\ -\083\001\255\255\255\255\255\255\255\255\088\001\089\001\090\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\098\001\ -\255\255\255\255\115\001\116\001\255\255\255\255\119\001\120\001\ -\121\001\255\255\255\255\255\255\255\255\255\255\113\001\114\001\ -\255\255\255\255\000\000\255\255\007\001\255\255\255\255\122\001\ -\123\001\124\001\013\001\126\001\127\001\255\255\017\001\255\255\ -\019\001\020\001\133\001\134\001\255\255\255\255\255\255\255\255\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\255\255\255\255\255\255\255\255\033\001\255\255\000\000\255\255\ -\255\255\038\001\039\001\040\001\041\001\056\001\057\001\058\001\ \255\255\060\001\061\001\062\001\255\255\064\001\255\255\255\255\ -\255\255\255\255\069\001\056\001\255\255\072\001\255\255\060\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\083\001\007\001\008\001\255\255\255\255\088\001\089\001\090\001\ -\014\001\015\001\255\255\255\255\255\255\255\255\255\255\098\001\ -\022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\113\001\114\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\122\001\ -\123\001\124\001\255\255\126\001\127\001\255\255\255\255\255\255\ -\255\255\255\255\133\001\134\001\255\255\122\001\123\001\124\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\068\001\255\255\ -\070\001\255\255\255\255\255\255\255\255\255\255\076\001\077\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\084\001\085\001\ -\086\001\087\001\255\255\089\001\090\001\255\255\255\255\255\255\ -\000\000\095\001\255\255\255\255\255\255\255\255\100\001\101\001\ -\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\255\255\255\255\255\255\255\255\255\255\116\001\117\001\ -\255\255\119\001\120\001\121\001\012\001\013\001\255\255\255\255\ -\016\001\017\001\128\001\019\001\020\001\255\255\255\255\255\255\ -\134\001\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ -\032\001\033\001\034\001\035\001\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ -\064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ -\006\001\255\255\255\255\083\001\000\000\255\255\255\255\255\255\ -\255\255\089\001\090\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\097\001\098\001\255\255\255\255\255\255\000\000\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\113\001\114\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\122\001\123\001\124\001\007\001\126\001\127\001\ -\255\255\255\255\012\001\013\001\255\255\133\001\255\255\017\001\ -\255\255\019\001\020\001\065\001\255\255\255\255\255\255\255\255\ -\255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\255\255\088\001\255\255\255\255\091\001\092\001\093\001\ -\094\001\255\255\096\001\255\255\255\255\255\255\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ -\255\255\255\255\255\255\069\001\255\255\115\001\072\001\255\255\ -\255\255\119\001\120\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ -\090\001\255\255\255\255\255\255\255\255\255\255\000\000\255\255\ -\098\001\000\000\255\255\007\001\008\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\113\001\ -\114\001\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ -\122\001\123\001\124\001\255\255\126\001\127\001\255\255\007\001\ -\255\255\255\255\255\255\133\001\012\001\013\001\255\255\255\255\ -\255\255\017\001\255\255\019\001\020\001\255\255\255\255\255\255\ +\255\255\255\255\069\001\255\255\255\255\072\001\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ +\083\001\255\255\255\255\255\255\255\255\255\255\089\001\090\001\ +\255\255\000\000\255\255\255\255\255\255\255\255\255\255\098\001\ +\255\255\255\255\255\255\255\255\255\255\001\001\002\001\003\001\ +\004\001\005\001\006\001\255\255\255\255\255\255\255\255\114\001\ +\115\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\124\001\125\001\126\001\127\001\013\001\129\001\130\001\ +\255\255\017\001\255\255\255\255\020\001\136\001\255\255\255\255\ \255\255\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ -\032\001\033\001\034\001\035\001\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ +\032\001\033\001\255\255\035\001\255\255\255\255\038\001\039\001\ +\040\001\041\001\255\255\013\001\255\255\255\255\255\255\017\001\ +\255\255\255\255\020\001\255\255\255\255\065\001\255\255\255\255\ +\056\001\057\001\058\001\059\001\060\001\061\001\062\001\033\001\ \064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ -\108\001\109\001\110\001\083\001\255\255\255\255\000\000\255\255\ -\255\255\089\001\090\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\098\001\255\255\255\255\001\001\002\001\003\001\ -\004\001\005\001\006\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\113\001\114\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\122\001\123\001\124\001\007\001\126\001\127\001\ -\255\255\255\255\012\001\013\001\255\255\133\001\255\255\017\001\ -\255\255\019\001\020\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\255\255\255\255\255\255\255\255\065\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ -\000\000\255\255\255\255\069\001\088\001\255\255\072\001\091\001\ -\092\001\093\001\094\001\255\255\096\001\255\255\000\000\255\255\ -\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ -\090\001\255\255\255\255\255\255\255\255\255\255\255\255\115\001\ -\098\001\255\255\255\255\119\001\120\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\113\001\ -\114\001\255\255\001\001\002\001\003\001\004\001\005\001\006\001\ -\122\001\123\001\124\001\013\001\126\001\127\001\255\255\017\001\ -\255\255\019\001\020\001\133\001\255\255\255\255\255\255\255\255\ +\072\001\255\255\255\255\255\255\088\001\255\255\255\255\091\001\ +\092\001\093\001\094\001\083\001\096\001\255\255\255\255\255\255\ +\100\001\089\001\090\001\255\255\000\000\255\255\064\001\255\255\ +\255\255\255\255\098\001\069\001\255\255\255\255\072\001\255\255\ +\116\001\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ +\006\001\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ +\090\001\255\255\000\000\123\001\124\001\125\001\126\001\127\001\ +\098\001\129\001\130\001\013\001\255\255\255\255\255\255\017\001\ +\136\001\255\255\020\001\255\255\255\255\255\255\255\255\255\255\ \255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ -\255\255\255\255\065\001\069\001\255\255\255\255\072\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\000\000\255\255\ -\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ -\090\001\088\001\255\255\255\255\091\001\092\001\093\001\094\001\ -\098\001\096\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\113\001\ -\114\001\255\255\255\255\255\255\115\001\255\255\255\255\255\255\ -\122\001\123\001\124\001\013\001\126\001\127\001\255\255\017\001\ -\255\255\019\001\020\001\133\001\255\255\255\255\255\255\255\255\ -\255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ +\255\255\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\136\001\255\255\ +\255\255\255\255\255\255\065\001\255\255\255\255\056\001\057\001\ +\058\001\059\001\060\001\061\001\062\001\255\255\064\001\255\255\ \255\255\255\255\255\255\069\001\255\255\255\255\072\001\255\255\ -\255\255\255\255\000\000\255\255\255\255\255\255\255\255\255\255\ -\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ -\090\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\098\001\001\001\002\001\003\001\004\001\005\001\006\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\113\001\ -\114\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\122\001\123\001\124\001\013\001\126\001\127\001\255\255\017\001\ -\255\255\019\001\020\001\133\001\255\255\255\255\255\255\255\255\ -\255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\065\001\255\255\255\255\255\255\255\255\056\001\057\001\ -\058\001\059\001\060\001\061\001\062\001\063\001\064\001\255\255\ -\255\255\255\255\255\255\069\001\255\255\255\255\072\001\255\255\ -\088\001\255\255\255\255\091\001\092\001\093\001\094\001\255\255\ -\096\001\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ -\090\001\255\255\008\001\255\255\255\255\255\255\255\255\255\255\ -\098\001\255\255\255\255\115\001\255\255\255\255\255\255\021\001\ -\022\001\023\001\024\001\025\001\026\001\255\255\255\255\113\001\ -\114\001\255\255\255\255\255\255\255\255\007\001\255\255\255\255\ -\122\001\123\001\124\001\013\001\126\001\127\001\255\255\017\001\ -\255\255\019\001\020\001\133\001\255\255\255\255\255\255\255\255\ -\255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ -\034\001\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ -\255\255\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\056\001\057\001\ -\058\001\255\255\060\001\061\001\062\001\255\255\064\001\255\255\ -\255\255\255\255\255\255\069\001\255\255\255\255\072\001\101\001\ -\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\083\001\255\255\255\255\255\255\255\255\008\001\089\001\ -\090\001\255\255\255\255\255\255\255\255\255\255\016\001\255\255\ -\098\001\255\255\255\255\255\255\022\001\023\001\024\001\025\001\ -\026\001\255\255\255\255\255\255\255\255\255\255\255\255\113\001\ -\114\001\255\255\255\255\255\255\255\255\255\255\255\255\013\001\ -\122\001\123\001\124\001\017\001\126\001\127\001\020\001\255\255\ -\255\255\255\255\255\255\133\001\255\255\027\001\028\001\029\001\ -\030\001\031\001\032\001\033\001\255\255\035\001\255\255\255\255\ -\038\001\039\001\040\001\041\001\255\255\000\000\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\056\001\057\001\058\001\059\001\060\001\061\001\ -\062\001\255\255\064\001\255\255\255\255\255\255\255\255\069\001\ -\255\255\255\255\072\001\101\001\102\001\103\001\104\001\105\001\ -\106\001\107\001\108\001\109\001\110\001\083\001\255\255\255\255\ -\008\001\255\255\255\255\089\001\090\001\255\255\013\001\255\255\ -\016\001\255\255\017\001\255\255\098\001\020\001\022\001\023\001\ -\024\001\025\001\026\001\255\255\027\001\028\001\029\001\030\001\ -\031\001\032\001\033\001\255\255\035\001\255\255\255\255\038\001\ -\039\001\040\001\041\001\255\255\122\001\123\001\124\001\255\255\ -\126\001\127\001\255\255\255\255\255\255\255\255\255\255\133\001\ -\255\255\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ -\008\001\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ -\255\255\072\001\255\255\255\255\255\255\000\000\022\001\023\001\ -\024\001\025\001\026\001\255\255\083\001\255\255\255\255\255\255\ -\255\255\255\255\089\001\090\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\098\001\255\255\101\001\102\001\103\001\ -\104\001\105\001\106\001\107\001\108\001\109\001\110\001\255\255\ +\255\255\255\255\088\001\000\000\255\255\091\001\092\001\093\001\ +\094\001\083\001\096\001\255\255\255\255\255\255\100\001\089\001\ +\090\001\255\255\000\000\255\255\008\001\255\255\255\255\255\255\ +\098\001\255\255\255\255\255\255\016\001\255\255\116\001\255\255\ +\255\255\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\122\001\123\001\124\001\013\001\126\001\ -\127\001\255\255\017\001\255\255\255\255\020\001\133\001\255\255\ +\255\255\123\001\124\001\125\001\126\001\127\001\013\001\129\001\ +\130\001\255\255\017\001\255\255\255\255\020\001\136\001\255\255\ \255\255\255\255\255\255\255\255\027\001\028\001\029\001\030\001\ \031\001\032\001\033\001\255\255\035\001\255\255\255\255\038\001\ -\039\001\040\001\041\001\255\255\000\000\101\001\102\001\103\001\ -\104\001\105\001\106\001\107\001\108\001\109\001\110\001\255\255\ +\039\001\040\001\041\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ \255\255\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ -\255\255\072\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\083\001\255\255\255\255\255\255\ -\255\255\008\001\089\001\090\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\098\001\255\255\255\255\255\255\022\001\ -\023\001\024\001\025\001\026\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\013\001\122\001\123\001\124\001\017\001\126\001\ -\127\001\020\001\255\255\255\255\255\255\255\255\133\001\255\255\ +\255\255\072\001\102\001\103\001\104\001\105\001\106\001\107\001\ +\108\001\109\001\110\001\111\001\083\001\255\255\255\255\255\255\ +\255\255\255\255\089\001\090\001\255\255\000\000\255\255\008\001\ +\255\255\255\255\255\255\098\001\255\255\255\255\255\255\016\001\ +\255\255\255\255\255\255\255\255\255\255\022\001\023\001\024\001\ +\025\001\026\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\124\001\125\001\126\001\ +\127\001\013\001\129\001\130\001\255\255\017\001\255\255\255\255\ +\020\001\136\001\255\255\255\255\255\255\255\255\255\255\027\001\ +\028\001\029\001\030\001\031\001\032\001\033\001\255\255\035\001\ +\255\255\255\255\038\001\039\001\040\001\041\001\255\255\013\001\ +\255\255\255\255\255\255\017\001\255\255\255\255\020\001\255\255\ +\255\255\255\255\255\255\255\255\056\001\057\001\058\001\059\001\ +\060\001\061\001\062\001\033\001\064\001\255\255\255\255\255\255\ +\255\255\069\001\255\255\255\255\072\001\102\001\103\001\104\001\ +\105\001\106\001\107\001\108\001\109\001\110\001\111\001\083\001\ +\255\255\255\255\255\255\255\255\255\255\089\001\090\001\255\255\ +\000\000\255\255\064\001\255\255\255\255\255\255\098\001\069\001\ +\255\255\255\255\072\001\255\255\001\001\002\001\003\001\004\001\ +\005\001\006\001\255\255\255\255\255\255\083\001\255\255\255\255\ +\255\255\255\255\255\255\089\001\090\001\255\255\000\000\123\001\ +\124\001\125\001\126\001\127\001\098\001\129\001\130\001\013\001\ +\255\255\255\255\255\255\017\001\136\001\255\255\020\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\255\255\035\001\255\255\255\255\ +\038\001\039\001\040\001\041\001\255\255\255\255\255\255\255\255\ +\255\255\033\001\136\001\255\255\065\001\255\255\038\001\039\001\ +\040\001\041\001\056\001\057\001\058\001\059\001\060\001\061\001\ +\062\001\255\255\064\001\255\255\255\255\255\255\255\255\069\001\ +\056\001\255\255\072\001\088\001\060\001\255\255\091\001\092\001\ +\093\001\094\001\255\255\096\001\255\255\083\001\255\255\100\001\ +\255\255\255\255\255\255\089\001\090\001\255\255\000\000\255\255\ +\008\001\255\255\255\255\255\255\098\001\255\255\255\255\116\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\022\001\023\001\ +\024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\123\001\124\001\125\001\ +\126\001\127\001\013\001\129\001\130\001\255\255\017\001\255\255\ +\255\255\020\001\136\001\123\001\124\001\125\001\126\001\127\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\255\255\ \035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\056\001\057\001\058\001\ \059\001\060\001\061\001\062\001\255\255\064\001\255\255\255\255\ -\255\255\255\255\069\001\255\255\255\255\072\001\101\001\102\001\ -\103\001\104\001\105\001\106\001\107\001\108\001\109\001\110\001\ +\255\255\255\255\069\001\255\255\255\255\072\001\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ \083\001\255\255\255\255\255\255\255\255\255\255\089\001\090\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\098\001\ +\255\255\000\000\255\255\008\001\255\255\255\255\255\255\098\001\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\022\001\023\001\024\001\025\001\026\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\124\001\125\001\126\001\127\001\013\001\129\001\130\001\ +\255\255\017\001\255\255\255\255\020\001\136\001\255\255\255\255\ +\255\255\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\255\255\035\001\255\255\255\255\038\001\039\001\ +\040\001\041\001\255\255\013\001\255\255\255\255\255\255\017\001\ +\255\255\255\255\020\001\255\255\255\255\255\255\255\255\255\255\ +\056\001\057\001\058\001\059\001\060\001\061\001\062\001\033\001\ +\064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ +\072\001\102\001\103\001\104\001\105\001\106\001\107\001\108\001\ +\109\001\110\001\111\001\083\001\255\255\255\255\255\255\255\255\ +\255\255\089\001\090\001\255\255\000\000\255\255\064\001\255\255\ +\255\255\255\255\098\001\069\001\255\255\255\255\072\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ +\090\001\255\255\000\000\123\001\124\001\125\001\126\001\127\001\ +\098\001\129\001\130\001\013\001\255\255\255\255\255\255\017\001\ +\136\001\255\255\020\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ +\255\255\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\136\001\255\255\ +\255\255\255\255\038\001\039\001\040\001\041\001\056\001\057\001\ +\058\001\059\001\060\001\061\001\062\001\255\255\064\001\255\255\ +\255\255\255\255\255\255\069\001\056\001\255\255\072\001\255\255\ +\060\001\255\255\255\255\255\255\064\001\255\255\255\255\255\255\ +\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ +\090\001\255\255\000\000\255\255\255\255\255\255\255\255\255\255\ +\098\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\122\001\ -\123\001\124\001\013\001\126\001\127\001\255\255\017\001\255\255\ -\255\255\020\001\133\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\123\001\124\001\125\001\126\001\127\001\013\001\129\001\ +\130\001\255\255\017\001\255\255\255\255\020\001\136\001\123\001\ +\124\001\125\001\126\001\127\001\027\001\028\001\029\001\030\001\ +\031\001\032\001\033\001\255\255\035\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\038\001\039\001\040\001\ +\041\001\056\001\057\001\058\001\059\001\060\001\061\001\062\001\ +\255\255\064\001\255\255\255\255\255\255\255\255\069\001\056\001\ +\255\255\072\001\255\255\060\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\083\001\255\255\255\255\255\255\ +\255\255\255\255\089\001\090\001\255\255\000\000\255\255\255\255\ +\255\255\255\255\255\255\098\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\098\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\123\001\124\001\125\001\126\001\ +\127\001\013\001\129\001\130\001\255\255\017\001\255\255\255\255\ +\020\001\136\001\123\001\124\001\125\001\126\001\127\001\027\001\ +\028\001\029\001\030\001\031\001\032\001\033\001\255\255\035\001\ +\255\255\255\255\038\001\039\001\040\001\041\001\255\255\013\001\ +\255\255\255\255\255\255\017\001\255\255\255\255\020\001\255\255\ +\000\000\255\255\255\255\255\255\056\001\057\001\058\001\059\001\ +\060\001\061\001\062\001\033\001\064\001\255\255\255\255\255\255\ +\255\255\069\001\255\255\255\255\072\001\255\255\255\255\038\001\ +\039\001\040\001\041\001\255\255\255\255\255\255\255\255\083\001\ +\255\255\255\255\255\255\255\255\255\255\089\001\090\001\255\255\ +\255\255\056\001\064\001\255\255\255\255\060\001\098\001\069\001\ +\255\255\255\255\072\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\083\001\255\255\255\255\ +\255\255\255\255\255\255\089\001\090\001\255\255\255\255\123\001\ +\124\001\125\001\126\001\127\001\098\001\129\001\130\001\013\001\ +\255\255\255\255\255\255\017\001\136\001\255\255\020\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\255\255\035\001\255\255\255\255\ +\038\001\039\001\040\001\041\001\123\001\124\001\125\001\126\001\ +\127\001\255\255\136\001\000\000\255\255\255\255\255\255\255\255\ +\255\255\255\255\056\001\057\001\058\001\059\001\060\001\061\001\ +\062\001\255\255\064\001\255\255\255\255\255\255\255\255\069\001\ +\255\255\255\255\072\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\083\001\255\255\255\255\ +\255\255\255\255\255\255\089\001\090\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\098\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\123\001\124\001\125\001\ +\126\001\127\001\013\001\129\001\130\001\255\255\017\001\255\255\ +\255\255\020\001\136\001\255\255\255\255\255\255\255\255\255\255\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\255\255\ \035\001\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ -\000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\000\000\255\255\ \255\255\255\255\255\255\255\255\255\255\056\001\057\001\058\001\ \059\001\060\001\061\001\062\001\255\255\064\001\255\255\255\255\ \255\255\255\255\069\001\255\255\255\255\072\001\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\083\001\255\255\255\255\255\255\255\255\255\255\089\001\090\001\ -\255\255\013\001\255\255\255\255\255\255\017\001\255\255\098\001\ -\020\001\255\255\255\255\255\255\255\255\255\255\255\255\027\001\ -\028\001\029\001\030\001\031\001\032\001\033\001\255\255\035\001\ -\255\255\255\255\038\001\039\001\040\001\041\001\255\255\122\001\ -\123\001\124\001\255\255\126\001\127\001\255\255\255\255\255\255\ -\255\255\255\255\133\001\255\255\056\001\057\001\058\001\059\001\ -\060\001\061\001\062\001\255\255\064\001\255\255\255\255\255\255\ -\255\255\069\001\255\255\255\255\072\001\255\255\255\255\255\255\ -\000\000\255\255\255\255\255\255\255\255\255\255\255\255\083\001\ -\255\255\255\255\255\255\255\255\255\255\089\001\090\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\098\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\013\001\122\001\123\001\ -\124\001\017\001\126\001\127\001\020\001\255\255\255\255\255\255\ -\255\255\133\001\255\255\027\001\028\001\029\001\030\001\031\001\ +\083\001\255\255\255\255\255\255\255\255\013\001\089\001\090\001\ +\255\255\017\001\255\255\255\255\020\001\255\255\255\255\098\001\ +\255\255\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ \032\001\033\001\255\255\035\001\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\255\255\255\255\255\255\255\255\000\000\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\255\255\ -\064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\083\001\255\255\255\255\255\255\255\255\ +\040\001\041\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\123\001\124\001\125\001\126\001\127\001\000\000\129\001\130\001\ +\056\001\057\001\058\001\255\255\060\001\136\001\007\001\008\001\ +\064\001\255\255\255\255\012\001\255\255\069\001\255\255\255\255\ +\072\001\255\255\255\255\255\255\255\255\022\001\023\001\024\001\ +\025\001\026\001\255\255\083\001\255\255\255\255\255\255\255\255\ \255\255\089\001\090\001\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\098\001\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\059\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\123\001\124\001\125\001\126\001\127\001\ +\013\001\129\001\130\001\255\255\017\001\255\255\255\255\020\001\ +\136\001\255\255\255\255\255\255\255\255\255\255\027\001\028\001\ +\029\001\030\001\031\001\032\001\033\001\255\255\035\001\255\255\ +\000\000\038\001\039\001\040\001\041\001\102\001\103\001\104\001\ +\105\001\106\001\107\001\108\001\109\001\110\001\111\001\255\255\ +\255\255\255\255\255\255\056\001\255\255\255\255\255\255\060\001\ +\255\255\255\255\255\255\064\001\255\255\255\255\255\255\255\255\ +\069\001\255\255\255\255\072\001\255\255\038\001\039\001\040\001\ +\041\001\000\000\255\255\255\255\255\255\255\255\083\001\255\255\ +\255\255\255\255\255\255\255\255\089\001\090\001\255\255\056\001\ +\255\255\255\255\255\255\060\001\255\255\098\001\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\122\001\123\001\124\001\013\001\126\001\127\001\ -\255\255\017\001\255\255\255\255\020\001\133\001\255\255\255\255\ -\255\255\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ -\032\001\033\001\255\255\035\001\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\000\000\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\123\001\124\001\ +\125\001\126\001\127\001\013\001\129\001\130\001\255\255\017\001\ +\255\255\098\001\020\001\136\001\255\255\255\255\000\000\255\255\ +\255\255\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ +\255\255\035\001\255\255\255\255\038\001\039\001\040\001\041\001\ +\255\255\255\255\123\001\124\001\125\001\126\001\127\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\056\001\136\001\ +\255\255\255\255\060\001\255\255\255\255\255\255\064\001\000\000\ +\255\255\255\255\255\255\069\001\255\255\255\255\072\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ +\090\001\255\255\013\001\255\255\255\255\255\255\017\001\255\255\ +\098\001\020\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\000\000\255\255\255\255\255\255\255\255\255\255\033\001\255\255\ +\255\255\255\255\255\255\038\001\039\001\040\001\041\001\255\255\ +\255\255\123\001\124\001\125\001\126\001\127\001\255\255\129\001\ +\130\001\255\255\255\255\255\255\255\255\056\001\136\001\255\255\ +\255\255\060\001\255\255\255\255\255\255\064\001\255\255\255\255\ +\255\255\255\255\069\001\255\255\255\255\072\001\255\255\255\255\ +\000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\083\001\255\255\255\255\255\255\255\255\255\255\089\001\090\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\098\001\ +\255\255\255\255\000\000\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\013\001\255\255\255\255\ +\255\255\017\001\255\255\255\255\020\001\255\255\255\255\255\255\ +\123\001\124\001\125\001\126\001\127\001\255\255\255\255\255\255\ +\255\255\033\001\255\255\255\255\255\255\136\001\038\001\039\001\ +\040\001\041\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\013\001\255\255\ +\056\001\255\255\017\001\255\255\255\255\020\001\255\255\255\255\ \064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\083\001\255\255\255\255\255\255\255\255\ +\072\001\255\255\033\001\255\255\255\255\255\255\255\255\038\001\ +\039\001\040\001\041\001\083\001\255\255\255\255\255\255\255\255\ \255\255\089\001\090\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\056\001\098\001\255\255\255\255\255\255\000\000\255\255\ +\255\255\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ +\255\255\072\001\255\255\013\001\255\255\255\255\255\255\017\001\ +\255\255\255\255\020\001\123\001\083\001\255\255\126\001\127\001\ +\255\255\255\255\089\001\090\001\255\255\255\255\255\255\033\001\ +\136\001\255\255\255\255\098\001\038\001\039\001\040\001\041\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\013\001\255\255\056\001\255\255\ +\017\001\255\255\255\255\020\001\123\001\255\255\064\001\126\001\ +\127\001\255\255\255\255\069\001\255\255\255\255\072\001\255\255\ +\033\001\136\001\255\255\255\255\255\255\038\001\039\001\040\001\ +\041\001\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ +\090\001\255\255\255\255\255\255\255\255\013\001\255\255\056\001\ +\098\001\017\001\255\255\255\255\020\001\255\255\255\255\064\001\ +\255\255\255\255\255\255\255\255\069\001\255\255\255\255\072\001\ +\255\255\033\001\255\255\255\255\255\255\255\255\038\001\039\001\ +\255\255\041\001\083\001\255\255\126\001\127\001\255\255\255\255\ +\089\001\090\001\255\255\255\255\255\255\255\255\136\001\255\255\ +\056\001\098\001\255\255\255\255\255\255\013\001\255\255\255\255\ +\064\001\017\001\255\255\255\255\020\001\069\001\255\255\255\255\ +\072\001\255\255\255\255\001\001\002\001\003\001\004\001\005\001\ +\006\001\033\001\255\255\083\001\255\255\126\001\255\255\255\255\ +\255\255\089\001\090\001\255\255\255\255\255\255\255\255\136\001\ \255\255\255\255\098\001\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\122\001\123\001\124\001\013\001\126\001\127\001\ -\255\255\017\001\255\255\255\255\020\001\133\001\255\255\255\255\ -\255\255\255\255\255\255\027\001\028\001\029\001\030\001\031\001\ -\032\001\033\001\255\255\035\001\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\000\000\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\056\001\057\001\058\001\059\001\060\001\061\001\062\001\255\255\ \064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ +\072\001\255\255\255\255\255\255\255\255\255\255\126\001\255\255\ \255\255\255\255\255\255\083\001\255\255\255\255\255\255\255\255\ -\255\255\089\001\090\001\255\255\013\001\255\255\255\255\255\255\ -\017\001\255\255\098\001\020\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\255\255\035\001\255\255\255\255\038\001\039\001\040\001\ -\041\001\255\255\122\001\123\001\124\001\255\255\126\001\127\001\ -\255\255\255\255\255\255\255\255\255\255\133\001\255\255\056\001\ -\057\001\058\001\059\001\060\001\061\001\062\001\255\255\064\001\ -\255\255\255\255\255\255\255\255\069\001\255\255\255\255\072\001\ -\255\255\255\255\255\255\000\000\255\255\255\255\255\255\255\255\ -\255\255\255\255\083\001\255\255\255\255\255\255\255\255\255\255\ -\089\001\090\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\098\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\136\001\089\001\090\001\065\001\255\255\255\255\068\001\255\255\ +\255\255\255\255\098\001\255\255\255\255\075\001\076\001\077\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\084\001\085\001\ +\086\001\087\001\088\001\255\255\255\255\091\001\092\001\093\001\ +\094\001\255\255\096\001\255\255\255\255\255\255\100\001\001\001\ +\002\001\003\001\004\001\005\001\006\001\007\001\008\001\255\255\ +\136\001\255\255\255\255\255\255\255\255\255\255\116\001\117\001\ +\255\255\255\255\255\255\255\255\122\001\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\013\001\122\001\123\001\124\001\017\001\126\001\127\001\020\001\ -\255\255\255\255\255\255\255\255\133\001\255\255\027\001\028\001\ -\029\001\030\001\031\001\032\001\033\001\255\255\035\001\255\255\ -\255\255\038\001\039\001\040\001\041\001\000\000\013\001\255\255\ -\255\255\255\255\017\001\255\255\255\255\020\001\255\255\255\255\ -\255\255\255\255\255\255\056\001\057\001\058\001\059\001\060\001\ -\061\001\062\001\033\001\064\001\255\255\255\255\255\255\038\001\ -\069\001\255\255\255\255\072\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\083\001\255\255\ -\255\255\056\001\255\255\255\255\089\001\090\001\255\255\255\255\ -\255\255\064\001\255\255\255\255\255\255\098\001\069\001\255\255\ -\255\255\072\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\083\001\255\255\255\255\000\000\ -\255\255\255\255\089\001\090\001\255\255\122\001\123\001\124\001\ -\013\001\126\001\127\001\098\001\017\001\255\255\255\255\020\001\ -\133\001\255\255\255\255\255\255\255\255\255\255\027\001\028\001\ -\029\001\030\001\031\001\032\001\033\001\255\255\035\001\255\255\ -\255\255\038\001\039\001\040\001\041\001\255\255\013\001\255\255\ -\255\255\255\255\017\001\255\255\255\255\020\001\133\001\255\255\ -\255\255\255\255\255\255\056\001\057\001\058\001\059\001\060\001\ -\061\001\062\001\033\001\064\001\255\255\255\255\255\255\038\001\ -\069\001\255\255\255\255\072\001\255\255\255\255\255\255\255\255\ -\255\255\000\000\255\255\255\255\255\255\255\255\083\001\255\255\ -\255\255\056\001\255\255\255\255\089\001\090\001\255\255\255\255\ -\255\255\064\001\255\255\255\255\255\255\098\001\069\001\255\255\ -\255\255\072\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\083\001\255\255\255\255\255\255\ -\255\255\255\255\089\001\090\001\255\255\122\001\123\001\124\001\ -\013\001\126\001\127\001\098\001\017\001\255\255\255\255\020\001\ -\133\001\255\255\255\255\255\255\255\255\255\255\027\001\028\001\ -\029\001\030\001\031\001\032\001\033\001\255\255\035\001\255\255\ -\255\255\038\001\039\001\040\001\041\001\255\255\255\255\255\255\ -\000\000\255\255\255\255\255\255\255\255\255\255\133\001\255\255\ -\255\255\255\255\255\255\056\001\057\001\058\001\255\255\060\001\ -\255\255\255\255\255\255\064\001\255\255\255\255\255\255\255\255\ -\069\001\255\255\255\255\072\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\083\001\255\255\ -\255\255\255\255\013\001\255\255\089\001\090\001\017\001\255\255\ -\255\255\020\001\255\255\255\255\255\255\098\001\255\255\255\255\ -\027\001\028\001\029\001\030\001\031\001\032\001\033\001\255\255\ -\035\001\255\255\255\255\038\001\039\001\040\001\041\001\000\000\ -\255\255\255\255\255\255\255\255\255\255\122\001\123\001\124\001\ -\255\255\126\001\127\001\255\255\255\255\056\001\057\001\058\001\ -\133\001\060\001\255\255\255\255\255\255\064\001\255\255\255\255\ -\255\255\255\255\069\001\255\255\255\255\072\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\000\000\255\255\255\255\255\255\ -\083\001\255\255\255\255\255\255\013\001\255\255\089\001\090\001\ -\017\001\255\255\255\255\020\001\255\255\255\255\255\255\098\001\ -\255\255\255\255\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\255\255\035\001\255\255\255\255\038\001\039\001\040\001\ -\041\001\000\000\255\255\255\255\255\255\255\255\255\255\122\001\ -\123\001\124\001\255\255\126\001\127\001\255\255\255\255\056\001\ -\255\255\255\255\133\001\060\001\255\255\255\255\255\255\064\001\ -\000\000\255\255\255\255\255\255\069\001\255\255\255\255\072\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\083\001\255\255\255\255\255\255\013\001\255\255\ -\089\001\090\001\017\001\255\255\255\255\020\001\000\000\255\255\ -\255\255\098\001\255\255\255\255\027\001\028\001\029\001\030\001\ -\031\001\032\001\033\001\255\255\035\001\255\255\255\255\038\001\ -\039\001\040\001\041\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\122\001\123\001\124\001\255\255\126\001\127\001\255\255\ -\255\255\056\001\255\255\000\000\133\001\060\001\255\255\255\255\ -\255\255\064\001\255\255\255\255\255\255\255\255\069\001\255\255\ -\255\255\072\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\083\001\255\255\255\255\255\255\ -\255\255\255\255\089\001\090\001\255\255\013\001\000\000\255\255\ -\255\255\017\001\255\255\098\001\020\001\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\033\001\255\255\255\255\255\255\255\255\038\001\039\001\ -\040\001\041\001\255\255\122\001\123\001\124\001\255\255\126\001\ -\127\001\255\255\255\255\000\000\255\255\255\255\133\001\255\255\ -\056\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\064\001\255\255\255\255\255\255\255\255\069\001\255\255\255\255\ -\072\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\083\001\013\001\255\255\255\255\255\255\ -\017\001\089\001\090\001\020\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\098\001\255\255\255\255\255\255\255\255\255\255\ -\033\001\255\255\255\255\255\255\255\255\038\001\039\001\040\001\ -\041\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\013\001\122\001\123\001\124\001\017\001\255\255\056\001\ -\020\001\255\255\255\255\255\255\255\255\133\001\255\255\064\001\ -\255\255\255\255\255\255\255\255\069\001\033\001\255\255\072\001\ -\255\255\255\255\038\001\039\001\255\255\041\001\255\255\255\255\ -\255\255\255\255\083\001\255\255\255\255\255\255\013\001\255\255\ -\089\001\090\001\017\001\255\255\056\001\020\001\255\255\255\255\ -\255\255\098\001\255\255\255\255\064\001\255\255\255\255\255\255\ -\255\255\069\001\033\001\255\255\072\001\013\001\255\255\255\255\ -\255\255\017\001\255\255\255\255\020\001\255\255\255\255\083\001\ -\255\255\255\255\123\001\255\255\255\255\089\001\090\001\255\255\ -\255\255\033\001\255\255\255\255\133\001\255\255\098\001\255\255\ -\255\255\064\001\255\255\013\001\255\255\255\255\069\001\017\001\ -\255\255\072\001\020\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\083\001\255\255\255\255\033\001\ -\064\001\255\255\089\001\090\001\255\255\069\001\255\255\255\255\ -\072\001\133\001\255\255\098\001\255\255\255\255\255\255\255\255\ -\013\001\255\255\255\255\083\001\017\001\255\255\255\255\020\001\ -\255\255\089\001\090\001\255\255\255\255\255\255\064\001\255\255\ -\255\255\255\255\098\001\069\001\033\001\255\255\072\001\001\001\ -\002\001\003\001\004\001\005\001\006\001\255\255\133\001\255\255\ -\255\255\083\001\255\255\255\255\255\255\255\255\255\255\089\001\ -\090\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\098\001\255\255\255\255\064\001\255\255\133\001\255\255\255\255\ -\069\001\255\255\255\255\072\001\001\001\002\001\003\001\004\001\ -\005\001\006\001\007\001\008\001\255\255\255\255\083\001\255\255\ -\255\255\255\255\255\255\255\255\089\001\090\001\255\255\255\255\ -\255\255\255\255\255\255\133\001\255\255\098\001\255\255\065\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\065\001\ \255\255\255\255\068\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\075\001\076\001\077\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\084\001\085\001\086\001\087\001\088\001\255\255\ +\255\255\075\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\088\001\255\255\ \255\255\091\001\092\001\093\001\094\001\255\255\096\001\255\255\ -\133\001\255\255\255\255\255\255\065\001\255\255\255\255\068\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\075\001\255\255\ -\255\255\115\001\116\001\255\255\255\255\255\255\255\255\121\001\ -\255\255\255\255\255\255\088\001\255\255\255\255\091\001\092\001\ -\093\001\094\001\255\255\096\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\100\001\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\115\001\116\001\ -\255\255\118\001\119\001\120\001\121\001\001\001\002\001\003\001\ -\004\001\005\001\006\001\007\001\008\001\009\001\010\001\011\001\ -\012\001\013\001\014\001\015\001\016\001\017\001\018\001\019\001\ -\020\001\021\001\022\001\023\001\024\001\025\001\026\001\027\001\ -\028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ -\036\001\037\001\038\001\039\001\040\001\041\001\042\001\043\001\ -\044\001\045\001\046\001\047\001\048\001\049\001\050\001\051\001\ -\052\001\053\001\054\001\055\001\056\001\057\001\058\001\059\001\ -\060\001\061\001\062\001\063\001\064\001\065\001\066\001\255\255\ -\068\001\069\001\070\001\071\001\072\001\073\001\074\001\075\001\ -\076\001\077\001\078\001\079\001\080\001\081\001\082\001\083\001\ -\084\001\085\001\086\001\087\001\088\001\089\001\090\001\091\001\ -\092\001\093\001\255\255\095\001\096\001\097\001\098\001\099\001\ -\100\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ -\108\001\109\001\110\001\111\001\112\001\113\001\114\001\115\001\ -\116\001\117\001\118\001\119\001\120\001\121\001\122\001\123\001\ -\124\001\125\001\126\001\127\001\128\001\129\001\130\001\131\001\ -\132\001\133\001\134\001\001\001\002\001\003\001\004\001\005\001\ +\255\255\255\255\116\001\117\001\255\255\119\001\120\001\121\001\ +\122\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ +\008\001\009\001\010\001\011\001\012\001\013\001\014\001\015\001\ +\016\001\017\001\018\001\019\001\020\001\021\001\022\001\023\001\ +\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\038\001\039\001\ +\040\001\041\001\042\001\043\001\044\001\045\001\046\001\047\001\ +\048\001\049\001\050\001\051\001\052\001\053\001\054\001\055\001\ +\056\001\057\001\058\001\059\001\060\001\061\001\062\001\063\001\ +\064\001\065\001\066\001\255\255\068\001\069\001\070\001\071\001\ +\072\001\073\001\074\001\075\001\076\001\077\001\078\001\079\001\ +\080\001\081\001\082\001\083\001\084\001\085\001\086\001\087\001\ +\088\001\089\001\090\001\091\001\092\001\093\001\255\255\095\001\ +\096\001\097\001\098\001\099\001\100\001\101\001\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ +\112\001\113\001\114\001\115\001\116\001\117\001\118\001\119\001\ +\120\001\121\001\122\001\255\255\255\255\125\001\126\001\127\001\ +\128\001\129\001\130\001\131\001\132\001\133\001\134\001\135\001\ +\136\001\137\001\138\001\001\001\002\001\003\001\004\001\005\001\ \006\001\007\001\008\001\009\001\010\001\011\001\012\001\255\255\ \014\001\015\001\255\255\255\255\255\255\019\001\255\255\255\255\ \022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ @@ -2811,26 +2933,27 @@ \086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ \255\255\095\001\096\001\097\001\255\255\255\255\100\001\101\001\ \102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\111\001\112\001\255\255\255\255\115\001\116\001\117\001\ -\118\001\119\001\120\001\121\001\255\255\255\255\255\255\125\001\ -\255\255\255\255\128\001\129\001\130\001\131\001\132\001\133\001\ -\134\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ -\008\001\009\001\010\001\011\001\012\001\255\255\014\001\015\001\ -\255\255\255\255\255\255\019\001\255\255\255\255\022\001\023\001\ -\024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\036\001\037\001\255\255\255\255\ -\255\255\255\255\042\001\043\001\044\001\045\001\046\001\047\001\ -\048\001\049\001\050\001\051\001\052\001\053\001\054\001\255\255\ -\255\255\057\001\058\001\059\001\060\001\255\255\255\255\063\001\ -\255\255\065\001\066\001\255\255\068\001\069\001\070\001\071\001\ -\255\255\073\001\074\001\075\001\076\001\077\001\078\001\255\255\ -\080\001\081\001\082\001\255\255\084\001\085\001\086\001\087\001\ -\088\001\089\001\090\001\091\001\092\001\093\001\255\255\095\001\ -\096\001\097\001\255\255\255\255\100\001\101\001\102\001\103\001\ -\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ -\112\001\255\255\255\255\115\001\116\001\117\001\118\001\119\001\ -\120\001\121\001\255\255\255\255\255\255\125\001\255\255\255\255\ -\128\001\129\001\130\001\131\001\132\001\255\255\134\001\001\001\ +\110\001\111\001\112\001\113\001\255\255\255\255\116\001\117\001\ +\118\001\119\001\120\001\121\001\122\001\255\255\255\255\255\255\ +\255\255\255\255\128\001\255\255\255\255\131\001\132\001\133\001\ +\134\001\135\001\136\001\137\001\138\001\001\001\002\001\003\001\ +\004\001\005\001\006\001\007\001\008\001\009\001\010\001\011\001\ +\012\001\255\255\014\001\015\001\255\255\255\255\255\255\019\001\ +\255\255\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\036\001\037\001\255\255\255\255\255\255\255\255\042\001\043\001\ +\044\001\045\001\046\001\047\001\048\001\049\001\050\001\051\001\ +\052\001\053\001\054\001\255\255\255\255\057\001\058\001\059\001\ +\060\001\255\255\255\255\063\001\255\255\065\001\066\001\255\255\ +\068\001\069\001\070\001\071\001\255\255\073\001\074\001\075\001\ +\076\001\077\001\078\001\255\255\080\001\081\001\082\001\255\255\ +\084\001\085\001\086\001\087\001\088\001\089\001\090\001\091\001\ +\092\001\093\001\255\255\095\001\096\001\097\001\255\255\255\255\ +\100\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ +\108\001\109\001\110\001\111\001\112\001\113\001\255\255\255\255\ +\116\001\117\001\118\001\119\001\120\001\121\001\122\001\255\255\ +\255\255\255\255\255\255\255\255\128\001\255\255\255\255\131\001\ +\132\001\133\001\134\001\135\001\255\255\137\001\138\001\001\001\ \002\001\003\001\004\001\005\001\006\001\007\001\008\001\009\001\ \010\001\011\001\012\001\255\255\014\001\015\001\255\255\255\255\ \255\255\255\255\255\255\255\255\022\001\023\001\024\001\025\001\ @@ -2844,44 +2967,11 @@ \082\001\255\255\084\001\085\001\086\001\087\001\088\001\089\001\ \090\001\091\001\092\001\093\001\255\255\095\001\096\001\097\001\ \255\255\255\255\100\001\101\001\102\001\103\001\104\001\105\001\ -\106\001\107\001\108\001\109\001\110\001\111\001\112\001\255\255\ -\255\255\115\001\116\001\117\001\118\001\119\001\120\001\121\001\ -\255\255\255\255\255\255\125\001\255\255\255\255\128\001\129\001\ -\130\001\131\001\132\001\255\255\134\001\001\001\002\001\003\001\ -\004\001\005\001\006\001\007\001\008\001\009\001\010\001\011\001\ -\012\001\255\255\014\001\015\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\036\001\037\001\255\255\255\255\255\255\255\255\042\001\043\001\ -\044\001\045\001\046\001\047\001\048\001\049\001\050\001\051\001\ -\052\001\053\001\054\001\255\255\255\255\057\001\058\001\059\001\ -\060\001\255\255\255\255\255\255\255\255\065\001\066\001\255\255\ -\068\001\069\001\070\001\071\001\255\255\073\001\074\001\075\001\ -\076\001\077\001\078\001\255\255\080\001\081\001\082\001\255\255\ -\084\001\085\001\086\001\087\001\088\001\089\001\090\001\091\001\ -\092\001\093\001\255\255\095\001\096\001\097\001\255\255\255\255\ -\100\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ -\108\001\109\001\110\001\111\001\112\001\255\255\255\255\115\001\ -\116\001\117\001\118\001\119\001\120\001\121\001\255\255\255\255\ -\255\255\125\001\255\255\255\255\128\001\129\001\130\001\131\001\ -\132\001\255\255\134\001\001\001\002\001\003\001\004\001\005\001\ -\006\001\007\001\008\001\009\001\010\001\011\001\012\001\255\255\ -\014\001\015\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\036\001\037\001\ -\255\255\255\255\255\255\255\255\042\001\043\001\044\001\045\001\ -\046\001\047\001\048\001\049\001\050\001\051\001\052\001\053\001\ -\054\001\255\255\255\255\057\001\058\001\059\001\060\001\255\255\ -\255\255\255\255\255\255\065\001\066\001\255\255\068\001\069\001\ -\070\001\071\001\255\255\073\001\074\001\075\001\076\001\077\001\ -\078\001\255\255\080\001\081\001\082\001\255\255\084\001\085\001\ -\086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ -\255\255\095\001\096\001\097\001\255\255\255\255\100\001\101\001\ -\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\111\001\112\001\255\255\255\255\115\001\116\001\117\001\ -\118\001\119\001\120\001\121\001\255\255\255\255\255\255\125\001\ -\255\255\255\255\128\001\129\001\130\001\131\001\132\001\255\255\ -\134\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ +\106\001\107\001\108\001\109\001\110\001\111\001\112\001\113\001\ +\255\255\255\255\116\001\117\001\118\001\119\001\120\001\121\001\ +\122\001\255\255\255\255\255\255\255\255\255\255\128\001\255\255\ +\255\255\131\001\132\001\133\001\134\001\135\001\255\255\137\001\ +\138\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ \008\001\009\001\010\001\011\001\012\001\255\255\014\001\015\001\ \255\255\255\255\255\255\255\255\255\255\255\255\022\001\023\001\ \024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ @@ -2895,26 +2985,27 @@ \088\001\089\001\090\001\091\001\092\001\093\001\255\255\095\001\ \096\001\097\001\255\255\255\255\100\001\101\001\102\001\103\001\ \104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ -\112\001\255\255\255\255\115\001\116\001\117\001\118\001\119\001\ -\120\001\121\001\255\255\255\255\255\255\125\001\255\255\255\255\ -\128\001\129\001\130\001\131\001\132\001\255\255\134\001\001\001\ -\002\001\003\001\004\001\005\001\006\001\007\001\008\001\009\001\ -\010\001\011\001\012\001\255\255\014\001\015\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\022\001\023\001\024\001\025\001\ -\026\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\036\001\037\001\255\255\255\255\255\255\255\255\ -\042\001\043\001\044\001\045\001\046\001\047\001\048\001\049\001\ -\050\001\051\001\052\001\053\001\054\001\255\255\255\255\057\001\ -\058\001\059\001\060\001\255\255\255\255\255\255\255\255\065\001\ -\066\001\255\255\068\001\069\001\070\001\071\001\255\255\073\001\ -\074\001\075\001\076\001\077\001\078\001\255\255\080\001\081\001\ -\082\001\255\255\084\001\085\001\086\001\087\001\088\001\089\001\ -\090\001\091\001\092\001\093\001\255\255\095\001\096\001\097\001\ -\255\255\255\255\100\001\101\001\102\001\103\001\104\001\105\001\ -\106\001\107\001\108\001\109\001\110\001\111\001\112\001\255\255\ -\255\255\115\001\116\001\117\001\118\001\119\001\120\001\121\001\ -\255\255\255\255\255\255\125\001\255\255\255\255\128\001\129\001\ -\130\001\131\001\132\001\255\255\134\001\001\001\002\001\003\001\ +\112\001\113\001\255\255\255\255\116\001\117\001\118\001\119\001\ +\120\001\121\001\122\001\255\255\255\255\255\255\255\255\255\255\ +\128\001\255\255\255\255\131\001\132\001\133\001\134\001\135\001\ +\255\255\137\001\138\001\001\001\002\001\003\001\004\001\005\001\ +\006\001\007\001\008\001\009\001\010\001\011\001\012\001\255\255\ +\014\001\015\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\036\001\037\001\ +\255\255\255\255\255\255\255\255\042\001\043\001\044\001\045\001\ +\046\001\047\001\048\001\049\001\050\001\051\001\052\001\053\001\ +\054\001\255\255\255\255\057\001\058\001\059\001\060\001\255\255\ +\255\255\255\255\255\255\065\001\066\001\255\255\068\001\069\001\ +\070\001\071\001\255\255\073\001\074\001\075\001\076\001\077\001\ +\078\001\255\255\080\001\081\001\082\001\255\255\084\001\085\001\ +\086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ +\255\255\095\001\096\001\097\001\255\255\255\255\100\001\101\001\ +\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ +\110\001\111\001\112\001\113\001\255\255\255\255\116\001\117\001\ +\118\001\119\001\120\001\121\001\122\001\255\255\255\255\255\255\ +\255\255\255\255\128\001\255\255\255\255\131\001\132\001\133\001\ +\134\001\135\001\255\255\137\001\138\001\001\001\002\001\003\001\ \004\001\005\001\006\001\007\001\008\001\009\001\010\001\011\001\ \012\001\255\255\014\001\015\001\255\255\255\255\255\255\255\255\ \255\255\255\255\022\001\023\001\024\001\025\001\026\001\255\255\ @@ -2928,10 +3019,45 @@ \084\001\085\001\086\001\087\001\088\001\089\001\090\001\091\001\ \092\001\093\001\255\255\095\001\096\001\097\001\255\255\255\255\ \100\001\101\001\102\001\103\001\104\001\105\001\106\001\107\001\ -\108\001\109\001\110\001\111\001\112\001\255\255\255\255\115\001\ -\116\001\117\001\118\001\119\001\120\001\121\001\255\255\255\255\ -\255\255\125\001\255\255\255\255\128\001\129\001\130\001\131\001\ -\132\001\255\255\134\001\001\001\002\001\003\001\004\001\005\001\ +\108\001\109\001\110\001\111\001\112\001\113\001\255\255\255\255\ +\116\001\117\001\118\001\119\001\120\001\121\001\122\001\255\255\ +\255\255\255\255\255\255\255\255\128\001\255\255\255\255\131\001\ +\132\001\133\001\134\001\135\001\255\255\137\001\138\001\001\001\ +\002\001\003\001\004\001\005\001\006\001\007\001\008\001\009\001\ +\010\001\011\001\012\001\255\255\014\001\015\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\022\001\023\001\024\001\025\001\ +\026\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\036\001\037\001\255\255\255\255\255\255\255\255\ +\042\001\043\001\044\001\045\001\046\001\047\001\048\001\049\001\ +\050\001\051\001\052\001\053\001\054\001\255\255\255\255\057\001\ +\058\001\059\001\060\001\255\255\255\255\255\255\255\255\065\001\ +\066\001\255\255\068\001\069\001\070\001\071\001\255\255\073\001\ +\074\001\075\001\076\001\077\001\078\001\255\255\080\001\081\001\ +\082\001\255\255\084\001\085\001\086\001\087\001\088\001\089\001\ +\090\001\091\001\092\001\093\001\255\255\095\001\096\001\097\001\ +\255\255\255\255\100\001\101\001\102\001\103\001\104\001\105\001\ +\106\001\107\001\108\001\109\001\110\001\111\001\112\001\113\001\ +\255\255\255\255\116\001\117\001\118\001\119\001\120\001\121\001\ +\122\001\255\255\255\255\255\255\255\255\255\255\128\001\255\255\ +\255\255\131\001\132\001\133\001\134\001\135\001\255\255\137\001\ +\138\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ +\008\001\009\001\010\001\011\001\012\001\255\255\014\001\015\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\022\001\023\001\ +\024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\036\001\037\001\255\255\255\255\ +\255\255\255\255\042\001\043\001\044\001\045\001\046\001\047\001\ +\048\001\049\001\050\001\051\001\052\001\053\001\054\001\255\255\ +\255\255\057\001\058\001\059\001\060\001\255\255\255\255\255\255\ +\255\255\065\001\066\001\255\255\068\001\069\001\070\001\071\001\ +\255\255\073\001\074\001\075\001\076\001\077\001\078\001\255\255\ +\080\001\081\001\082\001\255\255\084\001\085\001\086\001\087\001\ +\088\001\089\001\090\001\091\001\092\001\093\001\255\255\095\001\ +\096\001\097\001\255\255\255\255\100\001\101\001\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ +\112\001\113\001\255\255\255\255\116\001\117\001\118\001\119\001\ +\120\001\121\001\122\001\255\255\255\255\255\255\255\255\255\255\ +\128\001\255\255\255\255\131\001\132\001\133\001\134\001\135\001\ +\255\255\137\001\138\001\001\001\002\001\003\001\004\001\005\001\ \006\001\007\001\008\001\255\255\255\255\011\001\255\255\255\255\ \014\001\015\001\255\255\255\255\255\255\255\255\255\255\255\255\ \022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ @@ -2945,106 +3071,111 @@ \086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ \255\255\095\001\096\001\255\255\255\255\255\255\100\001\101\001\ \102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ -\110\001\255\255\255\255\255\255\255\255\115\001\116\001\117\001\ -\118\001\119\001\120\001\121\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\128\001\255\255\255\255\255\255\255\255\255\255\ -\134\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\ -\008\001\255\255\255\255\255\255\255\255\255\255\014\001\015\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\022\001\023\001\ -\024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ +\110\001\111\001\255\255\255\255\255\255\255\255\116\001\117\001\ +\118\001\119\001\120\001\121\001\122\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\131\001\255\255\255\255\ +\255\255\255\255\255\255\137\001\001\001\002\001\003\001\004\001\ +\005\001\006\001\007\001\008\001\255\255\255\255\255\255\255\255\ +\255\255\014\001\015\001\255\255\255\255\255\255\255\255\255\255\ +\255\255\022\001\023\001\024\001\025\001\026\001\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\065\001\066\001\255\255\068\001\069\001\070\001\071\001\ -\255\255\255\255\255\255\075\001\076\001\077\001\078\001\255\255\ -\080\001\081\001\082\001\255\255\084\001\085\001\086\001\087\001\ -\088\001\089\001\090\001\091\001\092\001\093\001\255\255\095\001\ -\096\001\255\255\255\255\255\255\100\001\101\001\102\001\103\001\ -\104\001\105\001\106\001\107\001\108\001\109\001\110\001\255\255\ -\255\255\255\255\255\255\115\001\116\001\117\001\118\001\119\001\ -\120\001\121\001\007\001\008\001\009\001\010\001\011\001\012\001\ -\128\001\255\255\255\255\255\255\255\255\255\255\134\001\255\255\ -\255\255\022\001\023\001\024\001\025\001\026\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\065\001\066\001\255\255\068\001\ +\069\001\070\001\071\001\255\255\255\255\255\255\075\001\076\001\ +\077\001\078\001\255\255\080\001\081\001\082\001\255\255\084\001\ +\085\001\086\001\087\001\088\001\089\001\090\001\091\001\092\001\ +\093\001\255\255\095\001\096\001\255\255\255\255\255\255\100\001\ +\101\001\102\001\103\001\104\001\105\001\106\001\107\001\108\001\ +\109\001\110\001\111\001\255\255\255\255\255\255\255\255\116\001\ +\117\001\118\001\119\001\120\001\121\001\122\001\007\001\008\001\ +\009\001\010\001\011\001\012\001\255\255\255\255\131\001\255\255\ +\255\255\255\255\255\255\255\255\137\001\022\001\023\001\024\001\ +\025\001\026\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\042\001\043\001\044\001\045\001\046\001\047\001\048\001\ +\049\001\050\001\051\001\052\001\053\001\054\001\255\255\255\255\ +\057\001\058\001\059\001\060\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\073\001\074\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\097\001\255\255\255\255\255\255\255\255\102\001\103\001\104\001\ +\105\001\106\001\107\001\108\001\109\001\110\001\111\001\112\001\ +\113\001\007\001\255\255\009\001\010\001\011\001\012\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\128\001\ +\255\255\255\255\131\001\255\255\255\255\134\001\135\001\255\255\ +\255\255\138\001\255\255\255\255\255\255\255\255\036\001\037\001\ +\255\255\255\255\255\255\255\255\042\001\043\001\044\001\045\001\ +\046\001\047\001\048\001\049\001\050\001\051\001\052\001\053\001\ +\054\001\255\255\255\255\057\001\058\001\059\001\060\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\073\001\074\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\042\001\043\001\044\001\ -\045\001\046\001\047\001\048\001\049\001\050\001\051\001\052\001\ -\053\001\054\001\255\255\255\255\057\001\058\001\059\001\060\001\ +\255\255\255\255\255\255\097\001\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\073\001\074\001\007\001\008\001\ -\255\255\255\255\255\255\012\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\022\001\023\001\024\001\ -\025\001\026\001\255\255\255\255\097\001\255\255\255\255\255\255\ -\101\001\102\001\103\001\104\001\105\001\106\001\107\001\108\001\ -\109\001\110\001\111\001\112\001\007\001\255\255\009\001\010\001\ +\255\255\255\255\112\001\113\001\007\001\255\255\009\001\010\001\ \011\001\012\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\125\001\255\255\059\001\128\001\255\255\255\255\131\001\132\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\128\001\255\255\255\255\131\001\132\001\133\001\ +\134\001\135\001\255\255\255\255\138\001\255\255\255\255\255\255\ \255\255\036\001\037\001\255\255\255\255\255\255\255\255\042\001\ \043\001\044\001\045\001\046\001\047\001\048\001\049\001\050\001\ \051\001\052\001\053\001\054\001\255\255\255\255\057\001\058\001\ -\059\001\060\001\255\255\255\255\101\001\102\001\103\001\104\001\ -\105\001\106\001\107\001\108\001\109\001\110\001\073\001\074\001\ +\059\001\060\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\073\001\074\001\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\097\001\255\255\ \255\255\255\255\255\255\255\255\255\255\007\001\255\255\009\001\ -\010\001\011\001\012\001\255\255\111\001\112\001\255\255\255\255\ +\010\001\011\001\012\001\255\255\255\255\112\001\113\001\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\125\001\255\255\255\255\128\001\129\001\130\001\ -\131\001\132\001\036\001\037\001\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\128\001\255\255\255\255\ +\131\001\132\001\133\001\134\001\135\001\255\255\255\255\138\001\ \042\001\043\001\044\001\045\001\046\001\047\001\048\001\049\001\ \050\001\051\001\052\001\053\001\054\001\255\255\255\255\057\001\ \058\001\059\001\060\001\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\073\001\ \074\001\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\097\001\ -\007\001\255\255\009\001\010\001\011\001\012\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\111\001\112\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\125\001\255\255\255\255\128\001\129\001\ -\130\001\131\001\132\001\042\001\043\001\044\001\045\001\046\001\ -\047\001\048\001\049\001\050\001\051\001\052\001\053\001\054\001\ -\255\255\255\255\057\001\058\001\059\001\060\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\073\001\074\001\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\014\001\015\001\255\255\255\255\255\255\ -\255\255\255\255\255\255\022\001\023\001\024\001\025\001\026\001\ -\255\255\255\255\097\001\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\111\001\112\001\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\125\001\255\255\ -\255\255\128\001\255\255\255\255\131\001\132\001\065\001\066\001\ -\255\255\068\001\069\001\070\001\071\001\255\255\255\255\255\255\ -\075\001\076\001\077\001\078\001\255\255\080\001\081\001\255\255\ -\255\255\084\001\085\001\086\001\087\001\088\001\089\001\090\001\ -\091\001\092\001\093\001\094\001\095\001\096\001\255\255\255\255\ -\255\255\100\001\101\001\102\001\103\001\104\001\105\001\106\001\ -\107\001\108\001\109\001\110\001\255\255\255\255\255\255\255\255\ -\115\001\116\001\117\001\255\255\119\001\120\001\121\001\255\255\ -\255\255\255\255\255\255\255\255\255\255\128\001\014\001\015\001\ -\255\255\255\255\255\255\134\001\255\255\255\255\022\001\023\001\ -\024\001\025\001\026\001\255\255\255\255\255\255\255\255\255\255\ +\014\001\015\001\255\255\255\255\255\255\255\255\255\255\097\001\ +\022\001\023\001\024\001\025\001\026\001\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\112\001\113\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\128\001\255\255\ +\255\255\131\001\255\255\255\255\134\001\135\001\255\255\255\255\ +\138\001\255\255\255\255\065\001\066\001\255\255\068\001\069\001\ +\070\001\071\001\255\255\255\255\255\255\075\001\076\001\077\001\ +\078\001\255\255\080\001\081\001\255\255\255\255\084\001\085\001\ +\086\001\087\001\088\001\089\001\090\001\091\001\092\001\093\001\ +\094\001\095\001\096\001\255\255\255\255\255\255\100\001\101\001\ +\102\001\103\001\104\001\105\001\106\001\107\001\108\001\109\001\ +\110\001\111\001\255\255\255\255\255\255\255\255\116\001\117\001\ +\118\001\255\255\120\001\121\001\122\001\255\255\014\001\015\001\ +\255\255\255\255\255\255\255\255\255\255\131\001\022\001\023\001\ +\024\001\025\001\026\001\137\001\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\255\255\255\255\255\255\255\255\255\255\255\255\014\001\ -\015\001\255\255\255\255\255\255\255\255\255\255\070\001\022\001\ -\023\001\024\001\025\001\026\001\076\001\077\001\255\255\255\255\ -\255\255\255\255\255\255\255\255\084\001\085\001\086\001\087\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\070\001\014\001\ +\015\001\255\255\255\255\255\255\076\001\077\001\255\255\022\001\ +\023\001\024\001\025\001\026\001\084\001\085\001\086\001\087\001\ \255\255\089\001\090\001\255\255\255\255\255\255\255\255\095\001\ -\255\255\255\255\255\255\255\255\100\001\101\001\102\001\103\001\ -\104\001\105\001\106\001\107\001\108\001\109\001\110\001\255\255\ -\255\255\255\255\255\255\066\001\067\001\117\001\255\255\070\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\077\001\255\255\ -\128\001\255\255\255\255\082\001\255\255\255\255\134\001\255\255\ +\255\255\255\255\255\255\255\255\255\255\101\001\102\001\103\001\ +\104\001\105\001\106\001\107\001\108\001\109\001\110\001\111\001\ +\255\255\255\255\255\255\255\255\255\255\255\255\118\001\255\255\ +\255\255\255\255\255\255\066\001\067\001\255\255\255\255\070\001\ +\255\255\255\255\255\255\131\001\255\255\255\255\077\001\255\255\ +\255\255\137\001\255\255\082\001\255\255\255\255\255\255\255\255\ \255\255\255\255\089\001\090\001\255\255\255\255\255\255\255\255\ -\095\001\255\255\255\255\255\255\255\255\100\001\101\001\102\001\ +\095\001\255\255\255\255\255\255\255\255\255\255\101\001\102\001\ \103\001\104\001\105\001\106\001\107\001\108\001\109\001\110\001\ -\255\255\255\255\255\255\255\255\255\255\255\255\117\001\255\255\ +\111\001\255\255\255\255\255\255\255\255\255\255\255\255\118\001\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ -\255\255\128\001\255\255\255\255\255\255\255\255\255\255\134\001" +\255\255\255\255\255\255\255\255\131\001\255\255\255\255\255\255\ +\255\255\255\255\137\001" let yynames_const = "\ MODULE\000\ @@ -3142,6 +3273,7 @@ LBRACE\000\ RBRACE\000\ GHOST\000\ + MODEL\000\ CASE\000\ VOID\000\ CHAR\000\ @@ -3164,6 +3296,8 @@ COMPLETE\000\ DISJOINT\000\ TERMINATES\000\ + BIFF\000\ + BIMPLIES\000\ HAT\000\ HATHAT\000\ PIPE\000\ @@ -3177,6 +3311,7 @@ BSTYPE\000\ WITH\000\ CONST\000\ + INITIALIZED\000\ " let yynames_block = "\ @@ -3191,188 +3326,204 @@ (fun _ -> failwith "parser") ; (fun __caml_parser_env -> Obj.repr( -# 225 "cil/src/logic/logic_parser.mly" +# 228 "cil/src/logic/logic_parser.mly" ( enter_kw_c_mode () ) -# 3197 "cil/src/logic/logic_parser.ml" +# 3332 "cil/src/logic/logic_parser.ml" : 'enter_kw_c_mode)) ; (fun __caml_parser_env -> Obj.repr( -# 228 "cil/src/logic/logic_parser.mly" +# 231 "cil/src/logic/logic_parser.mly" ( exit_kw_c_mode () ) -# 3203 "cil/src/logic/logic_parser.ml" +# 3338 "cil/src/logic/logic_parser.ml" : 'exit_kw_c_mode)) ; (fun __caml_parser_env -> Obj.repr( -# 231 "cil/src/logic/logic_parser.mly" +# 234 "cil/src/logic/logic_parser.mly" ( if is_rt_type () then enter_rt_type_mode () ) -# 3209 "cil/src/logic/logic_parser.ml" +# 3344 "cil/src/logic/logic_parser.ml" : 'enter_rt_type)) ; (fun __caml_parser_env -> Obj.repr( -# 234 "cil/src/logic/logic_parser.mly" +# 237 "cil/src/logic/logic_parser.mly" ( if is_rt_type () then exit_rt_type_mode () ) -# 3215 "cil/src/logic/logic_parser.ml" +# 3350 "cil/src/logic/logic_parser.ml" : 'exit_rt_type)) ; (fun __caml_parser_env -> Obj.repr( -# 237 "cil/src/logic/logic_parser.mly" +# 240 "cil/src/logic/logic_parser.mly" ( set_rt_type () ) -# 3221 "cil/src/logic/logic_parser.ml" +# 3356 "cil/src/logic/logic_parser.ml" : 'begin_rt_type)) ; (fun __caml_parser_env -> Obj.repr( -# 240 "cil/src/logic/logic_parser.mly" +# 243 "cil/src/logic/logic_parser.mly" ( reset_rt_type () ) -# 3227 "cil/src/logic/logic_parser.ml" +# 3362 "cil/src/logic/logic_parser.ml" : 'end_rt_type)) ; (fun __caml_parser_env -> Obj.repr( -# 245 "cil/src/logic/logic_parser.mly" +# 248 "cil/src/logic/logic_parser.mly" ( [] ) -# 3233 "cil/src/logic/logic_parser.ml" +# 3368 "cil/src/logic/logic_parser.ml" : 'lexpr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_lexpr_list) in Obj.repr( -# 246 "cil/src/logic/logic_parser.mly" +# 249 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3240 "cil/src/logic/logic_parser.ml" +# 3375 "cil/src/logic/logic_parser.ml" : 'lexpr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 250 "cil/src/logic/logic_parser.mly" +# 253 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 3247 "cil/src/logic/logic_parser.ml" +# 3382 "cil/src/logic/logic_parser.ml" : 'ne_lexpr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ne_lexpr_list) in Obj.repr( -# 251 "cil/src/logic/logic_parser.mly" +# 254 "cil/src/logic/logic_parser.mly" ( _1 :: _3 ) -# 3255 "cil/src/logic/logic_parser.ml" +# 3390 "cil/src/logic/logic_parser.ml" : 'ne_lexpr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 255 "cil/src/logic/logic_parser.mly" +# 258 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3262 "cil/src/logic/logic_parser.ml" +# 3397 "cil/src/logic/logic_parser.ml" : Logic_ptree.lexpr)) ; (fun __caml_parser_env -> Obj.repr( -# 259 "cil/src/logic/logic_parser.mly" +# 262 "cil/src/logic/logic_parser.mly" ( None ) -# 3268 "cil/src/logic/logic_parser.ml" +# 3403 "cil/src/logic/logic_parser.ml" : 'lexpr_option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 260 "cil/src/logic/logic_parser.mly" +# 263 "cil/src/logic/logic_parser.mly" ( Some _1 ) -# 3275 "cil/src/logic/logic_parser.ml" +# 3410 "cil/src/logic/logic_parser.ml" : 'lexpr_option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 265 "cil/src/logic/logic_parser.mly" +# 268 "cil/src/logic/logic_parser.mly" ( info (PLimplies (_1, _3)) ) -# 3283 "cil/src/logic/logic_parser.ml" +# 3418 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 266 "cil/src/logic/logic_parser.mly" +# 269 "cil/src/logic/logic_parser.mly" ( info (PLiff (_1, _3)) ) -# 3291 "cil/src/logic/logic_parser.ml" +# 3426 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 267 "cil/src/logic/logic_parser.mly" +# 270 "cil/src/logic/logic_parser.mly" ( info (PLor (_1, _3)) ) -# 3299 "cil/src/logic/logic_parser.ml" +# 3434 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 268 "cil/src/logic/logic_parser.mly" +# 271 "cil/src/logic/logic_parser.mly" ( info (PLand (_1, _3)) ) -# 3307 "cil/src/logic/logic_parser.ml" +# 3442 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 269 "cil/src/logic/logic_parser.mly" +# 272 "cil/src/logic/logic_parser.mly" ( info (PLxor (_1, _3)) ) -# 3315 "cil/src/logic/logic_parser.ml" +# 3450 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 271 "cil/src/logic/logic_parser.mly" +# 274 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bbw_and, _3)) ) -# 3323 "cil/src/logic/logic_parser.ml" +# 3458 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 272 "cil/src/logic/logic_parser.mly" +# 275 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bbw_or, _3)) ) -# 3331 "cil/src/logic/logic_parser.ml" +# 3466 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 273 "cil/src/logic/logic_parser.mly" +# 276 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bbw_xor, _3)) ) -# 3339 "cil/src/logic/logic_parser.ml" +# 3474 "cil/src/logic/logic_parser.ml" + : 'lexpr)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in + Obj.repr( +# 277 "cil/src/logic/logic_parser.mly" + ( info (PLbinop (info (PLunop (Ubw_not, _1)), Bbw_or, _3)) ) +# 3482 "cil/src/logic/logic_parser.ml" + : 'lexpr)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in + Obj.repr( +# 278 "cil/src/logic/logic_parser.mly" + ( info (PLbinop (info (PLunop (Ubw_not, _1)), Bbw_xor, _3)) ) +# 3490 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 275 "cil/src/logic/logic_parser.mly" +# 280 "cil/src/logic/logic_parser.mly" ( info (PLif (_1, _3, _5)) ) -# 3348 "cil/src/logic/logic_parser.ml" +# 3499 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'any_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 277 "cil/src/logic/logic_parser.mly" +# 282 "cil/src/logic/logic_parser.mly" ( info (PLnamed (_1, _3)) ) -# 3356 "cil/src/logic/logic_parser.ml" +# 3507 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_rel) in Obj.repr( -# 278 "cil/src/logic/logic_parser.mly" +# 283 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3363 "cil/src/logic/logic_parser.ml" +# 3514 "cil/src/logic/logic_parser.ml" : 'lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_end_rel) in Obj.repr( -# 282 "cil/src/logic/logic_parser.mly" +# 287 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3370 "cil/src/logic/logic_parser.ml" +# 3521 "cil/src/logic/logic_parser.ml" : 'lexpr_rel)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr_inner) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'rel_list) in Obj.repr( -# 284 "cil/src/logic/logic_parser.mly" +# 289 "cil/src/logic/logic_parser.mly" ( let rel, rhs, _, oth_rel = _2 in let loc = loc_start _1, loc_end rhs in let relation = loc_info loc (PLrel(_1,rel,rhs)) in @@ -3380,76 +3531,76 @@ None -> relation | Some oth_relation -> info (PLand(relation,oth_relation)) ) -# 3384 "cil/src/logic/logic_parser.ml" +# 3535 "cil/src/logic/logic_parser.ml" : 'lexpr_rel)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'bounded_var) in let _4 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _6 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 294 "cil/src/logic/logic_parser.mly" +# 299 "cil/src/logic/logic_parser.mly" (info (PLlet(_2,_4,_6))) -# 3393 "cil/src/logic/logic_parser.ml" +# 3544 "cil/src/logic/logic_parser.ml" : 'lexpr_binder)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'binders) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 296 "cil/src/logic/logic_parser.mly" +# 301 "cil/src/logic/logic_parser.mly" ( info (PLforall (_2, _4)) ) -# 3401 "cil/src/logic/logic_parser.ml" +# 3552 "cil/src/logic/logic_parser.ml" : 'lexpr_binder)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'binders) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 298 "cil/src/logic/logic_parser.mly" +# 303 "cil/src/logic/logic_parser.mly" ( info (PLexists (_2, _4)) ) -# 3409 "cil/src/logic/logic_parser.ml" +# 3560 "cil/src/logic/logic_parser.ml" : 'lexpr_binder)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'binders) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 300 "cil/src/logic/logic_parser.mly" +# 305 "cil/src/logic/logic_parser.mly" ( info (PLlambda (_2,_4)) ) -# 3417 "cil/src/logic/logic_parser.ml" +# 3568 "cil/src/logic/logic_parser.ml" : 'lexpr_binder)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 304 "cil/src/logic/logic_parser.mly" +# 309 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3424 "cil/src/logic/logic_parser.ml" +# 3575 "cil/src/logic/logic_parser.ml" : 'lexpr_end_rel)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_binder) in Obj.repr( -# 305 "cil/src/logic/logic_parser.mly" +# 310 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3431 "cil/src/logic/logic_parser.ml" +# 3582 "cil/src/logic/logic_parser.ml" : 'lexpr_end_rel)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_binder) in Obj.repr( -# 306 "cil/src/logic/logic_parser.mly" +# 311 "cil/src/logic/logic_parser.mly" ( info (PLnot _2) ) -# 3438 "cil/src/logic/logic_parser.ml" +# 3589 "cil/src/logic/logic_parser.ml" : 'lexpr_end_rel)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'relation) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_end_rel) in Obj.repr( -# 311 "cil/src/logic/logic_parser.mly" +# 316 "cil/src/logic/logic_parser.mly" ( _1, _2, fst(relation_sense _1 Unknown), None ) -# 3446 "cil/src/logic/logic_parser.ml" +# 3597 "cil/src/logic/logic_parser.ml" : 'rel_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'relation) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'rel_list) in Obj.repr( -# 313 "cil/src/logic/logic_parser.mly" +# 318 "cil/src/logic/logic_parser.mly" ( let next_rel, rhs, sense, oth_rel = _3 in let (sense, correct) = relation_sense _1 sense @@ -3469,59 +3620,59 @@ raise (Not_well_formed(loc,"Inconsistent relation chain.")); end ) -# 3473 "cil/src/logic/logic_parser.ml" +# 3624 "cil/src/logic/logic_parser.ml" : 'rel_list)) ; (fun __caml_parser_env -> Obj.repr( -# 335 "cil/src/logic/logic_parser.mly" +# 340 "cil/src/logic/logic_parser.mly" ( Lt ) -# 3479 "cil/src/logic/logic_parser.ml" +# 3630 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> Obj.repr( -# 336 "cil/src/logic/logic_parser.mly" +# 341 "cil/src/logic/logic_parser.mly" ( Gt ) -# 3485 "cil/src/logic/logic_parser.ml" +# 3636 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> Obj.repr( -# 337 "cil/src/logic/logic_parser.mly" +# 342 "cil/src/logic/logic_parser.mly" ( Le ) -# 3491 "cil/src/logic/logic_parser.ml" +# 3642 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> Obj.repr( -# 338 "cil/src/logic/logic_parser.mly" +# 343 "cil/src/logic/logic_parser.mly" ( Ge ) -# 3497 "cil/src/logic/logic_parser.ml" +# 3648 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> Obj.repr( -# 339 "cil/src/logic/logic_parser.mly" +# 344 "cil/src/logic/logic_parser.mly" ( Eq ) -# 3503 "cil/src/logic/logic_parser.ml" +# 3654 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> Obj.repr( -# 340 "cil/src/logic/logic_parser.mly" +# 345 "cil/src/logic/logic_parser.mly" ( Neq ) -# 3509 "cil/src/logic/logic_parser.ml" +# 3660 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> Obj.repr( -# 342 "cil/src/logic/logic_parser.mly" +# 347 "cil/src/logic/logic_parser.mly" ( let l = loc () in raise (Not_well_formed(l, "Assignment operators not allowed in annotations.")) ) -# 3520 "cil/src/logic/logic_parser.ml" +# 3671 "cil/src/logic/logic_parser.ml" : 'relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'string) in Obj.repr( -# 351 "cil/src/logic/logic_parser.mly" +# 356 "cil/src/logic/logic_parser.mly" ( let (is_wide,content) = _1 in let cst = if is_wide then @@ -3531,1162 +3682,1169 @@ in info (PLconstant cst) ) -# 3535 "cil/src/logic/logic_parser.ml" +# 3686 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 360 "cil/src/logic/logic_parser.mly" +# 365 "cil/src/logic/logic_parser.mly" ( info (PLnot _2) ) -# 3542 "cil/src/logic/logic_parser.ml" +# 3693 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> Obj.repr( -# 361 "cil/src/logic/logic_parser.mly" +# 366 "cil/src/logic/logic_parser.mly" ( info PLtrue ) -# 3548 "cil/src/logic/logic_parser.ml" +# 3699 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> Obj.repr( -# 362 "cil/src/logic/logic_parser.mly" +# 367 "cil/src/logic/logic_parser.mly" ( info PLfalse ) -# 3554 "cil/src/logic/logic_parser.ml" +# 3705 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 363 "cil/src/logic/logic_parser.mly" +# 368 "cil/src/logic/logic_parser.mly" ( info (PLvalid (_3)) ) -# 3561 "cil/src/logic/logic_parser.ml" +# 3712 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 364 "cil/src/logic/logic_parser.mly" +# 369 "cil/src/logic/logic_parser.mly" ( info (PLvalid_index (_3,_5)) ) -# 3569 "cil/src/logic/logic_parser.ml" +# 3720 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 5 : 'lexpr) in let _5 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr) in let _7 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 366 "cil/src/logic/logic_parser.mly" +# 371 "cil/src/logic/logic_parser.mly" ( info (PLvalid_range (_3,_5,_7)) ) -# 3578 "cil/src/logic/logic_parser.ml" +# 3729 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 367 "cil/src/logic/logic_parser.mly" +# 372 "cil/src/logic/logic_parser.mly" + ( info (PLinitialized (_3)) ) +# 3736 "cil/src/logic/logic_parser.ml" + : 'lexpr_inner)) +; (fun __caml_parser_env -> + let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in + Obj.repr( +# 373 "cil/src/logic/logic_parser.mly" ( info (PLfresh (_3)) ) -# 3585 "cil/src/logic/logic_parser.ml" +# 3743 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> Obj.repr( -# 368 "cil/src/logic/logic_parser.mly" +# 374 "cil/src/logic/logic_parser.mly" ( info PLnull ) -# 3591 "cil/src/logic/logic_parser.ml" +# 3749 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'constant) in Obj.repr( -# 369 "cil/src/logic/logic_parser.mly" +# 375 "cil/src/logic/logic_parser.mly" ( info (PLconstant _1) ) -# 3598 "cil/src/logic/logic_parser.ml" +# 3756 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 370 "cil/src/logic/logic_parser.mly" +# 376 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Badd, _3)) ) -# 3606 "cil/src/logic/logic_parser.ml" +# 3764 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 371 "cil/src/logic/logic_parser.mly" +# 377 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bsub, _3)) ) -# 3614 "cil/src/logic/logic_parser.ml" +# 3772 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 372 "cil/src/logic/logic_parser.mly" +# 378 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bmul, _3)) ) -# 3622 "cil/src/logic/logic_parser.ml" +# 3780 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 373 "cil/src/logic/logic_parser.mly" +# 379 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bdiv, _3)) ) -# 3630 "cil/src/logic/logic_parser.ml" +# 3788 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 374 "cil/src/logic/logic_parser.mly" +# 380 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Bmod, _3)) ) -# 3638 "cil/src/logic/logic_parser.ml" +# 3796 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'identifier_or_typename) in Obj.repr( -# 375 "cil/src/logic/logic_parser.mly" +# 381 "cil/src/logic/logic_parser.mly" ( info (PLarrow (_1, _3)) ) -# 3646 "cil/src/logic/logic_parser.ml" +# 3804 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'identifier_or_typename) in Obj.repr( -# 376 "cil/src/logic/logic_parser.mly" +# 382 "cil/src/logic/logic_parser.mly" ( info (PLdot (_1, _3)) ) -# 3654 "cil/src/logic/logic_parser.ml" +# 3812 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'range) in Obj.repr( -# 377 "cil/src/logic/logic_parser.mly" +# 383 "cil/src/logic/logic_parser.mly" ( info (PLarrget (_1, _3)) ) -# 3662 "cil/src/logic/logic_parser.ml" +# 3820 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 378 "cil/src/logic/logic_parser.mly" +# 384 "cil/src/logic/logic_parser.mly" ( info (PLarrget (_1, _3)) ) -# 3670 "cil/src/logic/logic_parser.ml" +# 3828 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 379 "cil/src/logic/logic_parser.mly" +# 385 "cil/src/logic/logic_parser.mly" ( info (PLunop (Uminus, _2)) ) -# 3677 "cil/src/logic/logic_parser.ml" +# 3835 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 380 "cil/src/logic/logic_parser.mly" +# 386 "cil/src/logic/logic_parser.mly" ( _2 ) -# 3684 "cil/src/logic/logic_parser.ml" +# 3842 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 381 "cil/src/logic/logic_parser.mly" +# 387 "cil/src/logic/logic_parser.mly" ( info (PLunop (Ubw_not, _2)) ) -# 3691 "cil/src/logic/logic_parser.ml" +# 3849 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 382 "cil/src/logic/logic_parser.mly" +# 388 "cil/src/logic/logic_parser.mly" ( info (PLunop (Ustar, _2)) ) -# 3698 "cil/src/logic/logic_parser.ml" +# 3856 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 383 "cil/src/logic/logic_parser.mly" +# 389 "cil/src/logic/logic_parser.mly" ( info (PLunop (Uamp, _2)) ) -# 3705 "cil/src/logic/logic_parser.ml" +# 3863 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 384 "cil/src/logic/logic_parser.mly" +# 390 "cil/src/logic/logic_parser.mly" ( info (PLsizeofE _3) ) -# 3712 "cil/src/logic/logic_parser.ml" +# 3870 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'logic_type) in Obj.repr( -# 385 "cil/src/logic/logic_parser.mly" +# 391 "cil/src/logic/logic_parser.mly" ( info (PLsizeof _3) ) -# 3719 "cil/src/logic/logic_parser.ml" +# 3877 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 386 "cil/src/logic/logic_parser.mly" +# 392 "cil/src/logic/logic_parser.mly" ( info (PLold _3) ) -# 3726 "cil/src/logic/logic_parser.ml" +# 3884 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'label_name) in Obj.repr( -# 387 "cil/src/logic/logic_parser.mly" +# 393 "cil/src/logic/logic_parser.mly" ( info (PLat (_3, _5)) ) -# 3734 "cil/src/logic/logic_parser.ml" +# 3892 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 388 "cil/src/logic/logic_parser.mly" +# 394 "cil/src/logic/logic_parser.mly" ( info (PLbase_addr _3) ) -# 3741 "cil/src/logic/logic_parser.ml" +# 3899 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 389 "cil/src/logic/logic_parser.mly" +# 395 "cil/src/logic/logic_parser.mly" ( info (PLblock_length _3) ) -# 3748 "cil/src/logic/logic_parser.ml" +# 3906 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> Obj.repr( -# 390 "cil/src/logic/logic_parser.mly" +# 396 "cil/src/logic/logic_parser.mly" ( info PLresult ) -# 3754 "cil/src/logic/logic_parser.ml" +# 3912 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_lexpr_list) in Obj.repr( -# 392 "cil/src/logic/logic_parser.mly" +# 398 "cil/src/logic/logic_parser.mly" ( info (PLseparated _3) ) -# 3761 "cil/src/logic/logic_parser.ml" +# 3919 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'identifier) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_lexpr_list) in Obj.repr( -# 394 "cil/src/logic/logic_parser.mly" +# 400 "cil/src/logic/logic_parser.mly" ( info (PLapp (_1, [], _3)) ) -# 3769 "cil/src/logic/logic_parser.ml" +# 3927 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'identifier) in let _3 = (Parsing.peek_val __caml_parser_env 4 : 'ne_tvar_list) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_lexpr_list) in Obj.repr( -# 396 "cil/src/logic/logic_parser.mly" +# 402 "cil/src/logic/logic_parser.mly" ( info (PLapp (_1, _3, _6)) ) -# 3778 "cil/src/logic/logic_parser.ml" +# 3936 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'identifier) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_tvar_list) in Obj.repr( -# 398 "cil/src/logic/logic_parser.mly" +# 404 "cil/src/logic/logic_parser.mly" ( info (PLapp (_1, _3, [])) ) -# 3786 "cil/src/logic/logic_parser.ml" +# 3944 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 399 "cil/src/logic/logic_parser.mly" +# 405 "cil/src/logic/logic_parser.mly" ( info (PLvar _1) ) -# 3793 "cil/src/logic/logic_parser.ml" +# 3951 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 400 "cil/src/logic/logic_parser.mly" +# 406 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Brshift, _3))) -# 3801 "cil/src/logic/logic_parser.ml" +# 3959 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 401 "cil/src/logic/logic_parser.mly" +# 407 "cil/src/logic/logic_parser.mly" ( info (PLbinop (_1, Blshift, _3))) -# 3809 "cil/src/logic/logic_parser.ml" +# 3967 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 402 "cil/src/logic/logic_parser.mly" +# 408 "cil/src/logic/logic_parser.mly" ( info _2.lexpr_node ) -# 3816 "cil/src/logic/logic_parser.ml" +# 3974 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'range) in Obj.repr( -# 403 "cil/src/logic/logic_parser.mly" +# 409 "cil/src/logic/logic_parser.mly" ( info _2.lexpr_node ) -# 3823 "cil/src/logic/logic_parser.ml" +# 3981 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'cast_logic_type) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 405 "cil/src/logic/logic_parser.mly" +# 411 "cil/src/logic/logic_parser.mly" ( info (PLcast (_2, _4)) ) -# 3831 "cil/src/logic/logic_parser.ml" +# 3989 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 407 "cil/src/logic/logic_parser.mly" +# 413 "cil/src/logic/logic_parser.mly" ( info (PLsubtype (_1, _3)) ) -# 3839 "cil/src/logic/logic_parser.ml" +# 3997 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'logic_type) in Obj.repr( -# 409 "cil/src/logic/logic_parser.mly" +# 415 "cil/src/logic/logic_parser.mly" ( info (PLcoercion (_1, _3)) ) -# 3847 "cil/src/logic/logic_parser.ml" +# 4005 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_inner) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_inner) in Obj.repr( -# 411 "cil/src/logic/logic_parser.mly" +# 417 "cil/src/logic/logic_parser.mly" ( info (PLcoercionE (_1, _3)) ) -# 3855 "cil/src/logic/logic_parser.ml" +# 4013 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 412 "cil/src/logic/logic_parser.mly" +# 418 "cil/src/logic/logic_parser.mly" ( info (PLtypeof _3) ) -# 3862 "cil/src/logic/logic_parser.ml" +# 4020 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'type_spec) in Obj.repr( -# 413 "cil/src/logic/logic_parser.mly" +# 419 "cil/src/logic/logic_parser.mly" ( info (PLtype _3) ) -# 3869 "cil/src/logic/logic_parser.ml" +# 4027 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> Obj.repr( -# 415 "cil/src/logic/logic_parser.mly" +# 421 "cil/src/logic/logic_parser.mly" ( info PLempty ) -# 3875 "cil/src/logic/logic_parser.ml" +# 4033 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr_list) in Obj.repr( -# 416 "cil/src/logic/logic_parser.mly" +# 422 "cil/src/logic/logic_parser.mly" ( info (PLunion _3) ) -# 3882 "cil/src/logic/logic_parser.ml" +# 4040 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr_list) in Obj.repr( -# 417 "cil/src/logic/logic_parser.mly" +# 423 "cil/src/logic/logic_parser.mly" ( info (PLinter _3) ) -# 3889 "cil/src/logic/logic_parser.ml" +# 4047 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 419 "cil/src/logic/logic_parser.mly" +# 425 "cil/src/logic/logic_parser.mly" ( info (PLsingleton (_2)) ) -# 3896 "cil/src/logic/logic_parser.ml" +# 4054 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'binders) in Obj.repr( -# 421 "cil/src/logic/logic_parser.mly" +# 427 "cil/src/logic/logic_parser.mly" (info (PLcomprehension (_2,_4,None)) ) -# 3904 "cil/src/logic/logic_parser.ml" +# 4062 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 5 : 'lexpr) in let _4 = (Parsing.peek_val __caml_parser_env 3 : 'binders) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 423 "cil/src/logic/logic_parser.mly" +# 429 "cil/src/logic/logic_parser.mly" ( info (PLcomprehension (_2,_4,Some _6)) ) -# 3913 "cil/src/logic/logic_parser.ml" +# 4071 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'field_init) in Obj.repr( -# 426 "cil/src/logic/logic_parser.mly" +# 432 "cil/src/logic/logic_parser.mly" ( info (PLinitField(_2)) ) -# 3920 "cil/src/logic/logic_parser.ml" +# 4078 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'array_init) in Obj.repr( -# 428 "cil/src/logic/logic_parser.mly" +# 434 "cil/src/logic/logic_parser.mly" ( info (PLinitIndex(_2)) ) -# 3927 "cil/src/logic/logic_parser.ml" +# 4085 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'lexpr) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'update) in Obj.repr( -# 430 "cil/src/logic/logic_parser.mly" +# 436 "cil/src/logic/logic_parser.mly" ( List.fold_left (fun a (path,upd_val) -> info (PLupdate(a,path,upd_val))) _2 _4 ) -# 3936 "cil/src/logic/logic_parser.ml" +# 4094 "cil/src/logic/logic_parser.ml" : 'lexpr_inner)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : bool*string) in Obj.repr( -# 437 "cil/src/logic/logic_parser.mly" +# 443 "cil/src/logic/logic_parser.mly" ( _1 ) -# 3943 "cil/src/logic/logic_parser.ml" +# 4101 "cil/src/logic/logic_parser.ml" : 'string)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'string) in let _2 = (Parsing.peek_val __caml_parser_env 0 : bool*string) in Obj.repr( -# 438 "cil/src/logic/logic_parser.mly" +# 444 "cil/src/logic/logic_parser.mly" ( let (is_wide,prefix) = _1 in let (is_wide2,suffix) = _2 in (is_wide || is_wide2, prefix ^ suffix) ) -# 3955 "cil/src/logic/logic_parser.ml" +# 4113 "cil/src/logic/logic_parser.ml" : 'string)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr_option) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr_option) in Obj.repr( -# 446 "cil/src/logic/logic_parser.mly" +# 452 "cil/src/logic/logic_parser.mly" ( info (PLrange(_1,_3)) ) -# 3963 "cil/src/logic/logic_parser.ml" +# 4121 "cil/src/logic/logic_parser.ml" : 'range)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'identifier_or_typename) in Obj.repr( -# 452 "cil/src/logic/logic_parser.mly" +# 458 "cil/src/logic/logic_parser.mly" ( _2 ) -# 3970 "cil/src/logic/logic_parser.ml" +# 4128 "cil/src/logic/logic_parser.ml" : 'field_path_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'field_path_elt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 455 "cil/src/logic/logic_parser.mly" +# 461 "cil/src/logic/logic_parser.mly" ( (_1, _3) ) -# 3978 "cil/src/logic/logic_parser.ml" +# 4136 "cil/src/logic/logic_parser.ml" : 'field_init_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'field_init_elt) in Obj.repr( -# 459 "cil/src/logic/logic_parser.mly" +# 465 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 3985 "cil/src/logic/logic_parser.ml" +# 4143 "cil/src/logic/logic_parser.ml" : 'field_init)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'field_init_elt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'field_init) in Obj.repr( -# 460 "cil/src/logic/logic_parser.mly" +# 466 "cil/src/logic/logic_parser.mly" ( _1::_3 ) -# 3993 "cil/src/logic/logic_parser.ml" +# 4151 "cil/src/logic/logic_parser.ml" : 'field_init)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in Obj.repr( -# 464 "cil/src/logic/logic_parser.mly" +# 470 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4000 "cil/src/logic/logic_parser.ml" +# 4158 "cil/src/logic/logic_parser.ml" : 'array_path_elt)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'range) in Obj.repr( -# 465 "cil/src/logic/logic_parser.mly" +# 471 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4007 "cil/src/logic/logic_parser.ml" +# 4165 "cil/src/logic/logic_parser.ml" : 'array_path_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'array_path_elt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 469 "cil/src/logic/logic_parser.mly" +# 475 "cil/src/logic/logic_parser.mly" ( (_1, _3) ) -# 4015 "cil/src/logic/logic_parser.ml" +# 4173 "cil/src/logic/logic_parser.ml" : 'array_init_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'array_init_elt) in Obj.repr( -# 473 "cil/src/logic/logic_parser.mly" +# 479 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4022 "cil/src/logic/logic_parser.ml" +# 4180 "cil/src/logic/logic_parser.ml" : 'array_init)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'array_init_elt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'array_init) in Obj.repr( -# 474 "cil/src/logic/logic_parser.mly" +# 480 "cil/src/logic/logic_parser.mly" ( _1::_3 ) -# 4030 "cil/src/logic/logic_parser.ml" +# 4188 "cil/src/logic/logic_parser.ml" : 'array_init)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'update_elt) in Obj.repr( -# 479 "cil/src/logic/logic_parser.mly" +# 485 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4037 "cil/src/logic/logic_parser.ml" +# 4195 "cil/src/logic/logic_parser.ml" : 'update)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'update_elt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'update) in Obj.repr( -# 480 "cil/src/logic/logic_parser.mly" +# 486 "cil/src/logic/logic_parser.mly" ( _1::_3 ) -# 4045 "cil/src/logic/logic_parser.ml" +# 4203 "cil/src/logic/logic_parser.ml" : 'update)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'path) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'lexpr) in Obj.repr( -# 484 "cil/src/logic/logic_parser.mly" +# 490 "cil/src/logic/logic_parser.mly" ( _1, PLupdateTerm _3 ) -# 4053 "cil/src/logic/logic_parser.ml" +# 4211 "cil/src/logic/logic_parser.ml" : 'update_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : 'path) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'update) in Obj.repr( -# 485 "cil/src/logic/logic_parser.mly" +# 491 "cil/src/logic/logic_parser.mly" ( _1, PLupdateCont _5 ) -# 4061 "cil/src/logic/logic_parser.ml" +# 4219 "cil/src/logic/logic_parser.ml" : 'update_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'path_elt) in Obj.repr( -# 489 "cil/src/logic/logic_parser.mly" +# 495 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4068 "cil/src/logic/logic_parser.ml" +# 4226 "cil/src/logic/logic_parser.ml" : 'path)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'path_elt) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'path) in Obj.repr( -# 490 "cil/src/logic/logic_parser.mly" +# 496 "cil/src/logic/logic_parser.mly" ( _1::_2 ) -# 4076 "cil/src/logic/logic_parser.ml" +# 4234 "cil/src/logic/logic_parser.ml" : 'path)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'field_path_elt) in Obj.repr( -# 494 "cil/src/logic/logic_parser.mly" +# 500 "cil/src/logic/logic_parser.mly" ( PLpathField _1 ) -# 4083 "cil/src/logic/logic_parser.ml" +# 4241 "cil/src/logic/logic_parser.ml" : 'path_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'array_path_elt) in Obj.repr( -# 495 "cil/src/logic/logic_parser.mly" +# 501 "cil/src/logic/logic_parser.mly" ( PLpathIndex _1 ) -# 4090 "cil/src/logic/logic_parser.ml" +# 4248 "cil/src/logic/logic_parser.ml" : 'path_elt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'binders_reentrance) in Obj.repr( -# 501 "cil/src/logic/logic_parser.mly" +# 507 "cil/src/logic/logic_parser.mly" ( let (_lt, vars) = _1 in vars ) -# 4097 "cil/src/logic/logic_parser.ml" +# 4255 "cil/src/logic/logic_parser.ml" : 'binders)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec) in Obj.repr( -# 505 "cil/src/logic/logic_parser.mly" +# 511 "cil/src/logic/logic_parser.mly" ( let (lt, var) = _1 in (lt, [var]) ) -# 4104 "cil/src/logic/logic_parser.ml" +# 4262 "cil/src/logic/logic_parser.ml" : 'binders_reentrance)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'binders_reentrance) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'decl_spec) in Obj.repr( -# 507 "cil/src/logic/logic_parser.mly" +# 513 "cil/src/logic/logic_parser.mly" ( let _, vars = _1 in let (lt, var) = _3 in (lt, vars @ [ var ]) ) -# 4115 "cil/src/logic/logic_parser.ml" +# 4273 "cil/src/logic/logic_parser.ml" : 'binders_reentrance)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'binders_reentrance) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'var_spec) in Obj.repr( -# 512 "cil/src/logic/logic_parser.mly" +# 518 "cil/src/logic/logic_parser.mly" ( let last_type_spec, vars = _1 in (last_type_spec, vars @ [ let (modif, name) = _3 in (modif last_type_spec, name)]) ) -# 4125 "cil/src/logic/logic_parser.ml" +# 4283 "cil/src/logic/logic_parser.ml" : 'binders_reentrance)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'type_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'var_spec) in Obj.repr( -# 518 "cil/src/logic/logic_parser.mly" +# 524 "cil/src/logic/logic_parser.mly" ( (_1, let (modif, name) = _2 in (modif _1, name)) ) -# 4133 "cil/src/logic/logic_parser.ml" +# 4291 "cil/src/logic/logic_parser.ml" : 'decl_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'var_spec_bis) in Obj.repr( -# 522 "cil/src/logic/logic_parser.mly" +# 528 "cil/src/logic/logic_parser.mly" ( let (outer, inner,name) = _1 in ((fun x -> outer (inner x)), name)) -# 4141 "cil/src/logic/logic_parser.ml" +# 4299 "cil/src/logic/logic_parser.ml" : 'var_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'stars) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'var_spec_bis) in Obj.repr( -# 525 "cil/src/logic/logic_parser.mly" +# 531 "cil/src/logic/logic_parser.mly" ( let (outer, inner, name) = _2 in ((fun x -> outer (inner (_1 x))), name) ) -# 4150 "cil/src/logic/logic_parser.ml" +# 4308 "cil/src/logic/logic_parser.ml" : 'var_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Logic_ptree.constant) in Obj.repr( -# 530 "cil/src/logic/logic_parser.mly" +# 536 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4157 "cil/src/logic/logic_parser.ml" +# 4315 "cil/src/logic/logic_parser.ml" : 'constant)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 531 "cil/src/logic/logic_parser.mly" +# 537 "cil/src/logic/logic_parser.mly" ( IntConstant _1 ) -# 4164 "cil/src/logic/logic_parser.ml" +# 4322 "cil/src/logic/logic_parser.ml" : 'constant)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'constant) in Obj.repr( -# 535 "cil/src/logic/logic_parser.mly" +# 541 "cil/src/logic/logic_parser.mly" ( Some _1 ) -# 4171 "cil/src/logic/logic_parser.ml" +# 4329 "cil/src/logic/logic_parser.ml" : 'constant_option)) ; (fun __caml_parser_env -> Obj.repr( -# 536 "cil/src/logic/logic_parser.mly" +# 542 "cil/src/logic/logic_parser.mly" ( None ) -# 4177 "cil/src/logic/logic_parser.ml" +# 4335 "cil/src/logic/logic_parser.ml" : 'constant_option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 540 "cil/src/logic/logic_parser.mly" +# 546 "cil/src/logic/logic_parser.mly" ( ((fun x -> x),(fun x -> x), _1) ) -# 4184 "cil/src/logic/logic_parser.ml" +# 4342 "cil/src/logic/logic_parser.ml" : 'var_spec_bis)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'var_spec_bis) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'constant_option) in Obj.repr( -# 542 "cil/src/logic/logic_parser.mly" +# 548 "cil/src/logic/logic_parser.mly" ( let (outer, inner, name) = _1 in (outer, (fun x -> inner (LTarray (x,_3))), name) ) -# 4194 "cil/src/logic/logic_parser.ml" +# 4352 "cil/src/logic/logic_parser.ml" : 'var_spec_bis)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'var_spec) in Obj.repr( -# 545 "cil/src/logic/logic_parser.mly" +# 551 "cil/src/logic/logic_parser.mly" ( let (modif, name) = _2 in (modif, (fun x -> x), name) ) -# 4201 "cil/src/logic/logic_parser.ml" +# 4359 "cil/src/logic/logic_parser.ml" : 'var_spec_bis)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'var_spec_bis) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'abs_param_type_list) in Obj.repr( -# 547 "cil/src/logic/logic_parser.mly" +# 553 "cil/src/logic/logic_parser.mly" ( let (outer, inner,name) = _1 in let params = _3 in (outer, (fun x -> inner (LTarrow (params,x))), name) ) -# 4212 "cil/src/logic/logic_parser.ml" +# 4370 "cil/src/logic/logic_parser.ml" : 'var_spec_bis)) ; (fun __caml_parser_env -> Obj.repr( -# 554 "cil/src/logic/logic_parser.mly" +# 560 "cil/src/logic/logic_parser.mly" ( [ ] ) -# 4218 "cil/src/logic/logic_parser.ml" +# 4376 "cil/src/logic/logic_parser.ml" : 'abs_param_type_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'abs_param_list) in Obj.repr( -# 555 "cil/src/logic/logic_parser.mly" +# 561 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4225 "cil/src/logic/logic_parser.ml" +# 4383 "cil/src/logic/logic_parser.ml" : 'abs_param_type_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'abs_param_list) in Obj.repr( -# 556 "cil/src/logic/logic_parser.mly" +# 562 "cil/src/logic/logic_parser.mly" ( Format.eprintf "Warning: elipsis type is not yet implemented." ; (* TODO: *) raise Parse_error ) -# 4235 "cil/src/logic/logic_parser.ml" +# 4393 "cil/src/logic/logic_parser.ml" : 'abs_param_type_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'abs_param) in Obj.repr( -# 563 "cil/src/logic/logic_parser.mly" +# 569 "cil/src/logic/logic_parser.mly" ( [ _1 ] ) -# 4242 "cil/src/logic/logic_parser.ml" +# 4400 "cil/src/logic/logic_parser.ml" : 'abs_param_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'abs_param_list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'abs_param) in Obj.repr( -# 564 "cil/src/logic/logic_parser.mly" +# 570 "cil/src/logic/logic_parser.mly" ( _1 @ [ _3 ] ) -# 4250 "cil/src/logic/logic_parser.ml" +# 4408 "cil/src/logic/logic_parser.ml" : 'abs_param_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_type) in Obj.repr( -# 571 "cil/src/logic/logic_parser.mly" +# 577 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4257 "cil/src/logic/logic_parser.ml" +# 4415 "cil/src/logic/logic_parser.ml" : 'abs_param)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 577 "cil/src/logic/logic_parser.mly" +# 583 "cil/src/logic/logic_parser.mly" ( LTnamed(_1, []) ) -# 4264 "cil/src/logic/logic_parser.ml" +# 4422 "cil/src/logic/logic_parser.ml" : 'id_as_typename)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'parameter) in Obj.repr( -# 581 "cil/src/logic/logic_parser.mly" +# 587 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4271 "cil/src/logic/logic_parser.ml" +# 4429 "cil/src/logic/logic_parser.ml" : 'ne_parameters)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'parameter) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ne_parameters) in Obj.repr( -# 582 "cil/src/logic/logic_parser.mly" +# 588 "cil/src/logic/logic_parser.mly" ( _1 :: _3 ) -# 4279 "cil/src/logic/logic_parser.ml" +# 4437 "cil/src/logic/logic_parser.ml" : 'ne_parameters)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'type_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'var_spec) in Obj.repr( -# 586 "cil/src/logic/logic_parser.mly" +# 592 "cil/src/logic/logic_parser.mly" ( let (modif, name) = _2 in (modif _1, name)) -# 4287 "cil/src/logic/logic_parser.ml" +# 4445 "cil/src/logic/logic_parser.ml" : 'parameter)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'id_as_typename) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'var_spec) in Obj.repr( -# 587 "cil/src/logic/logic_parser.mly" +# 593 "cil/src/logic/logic_parser.mly" ( let (modif, name) = _2 in (modif _1, name) ) -# 4295 "cil/src/logic/logic_parser.ml" +# 4453 "cil/src/logic/logic_parser.ml" : 'parameter)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'type_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'abs_spec_option) in Obj.repr( -# 594 "cil/src/logic/logic_parser.mly" +# 600 "cil/src/logic/logic_parser.mly" ( _2 _1 ) -# 4303 "cil/src/logic/logic_parser.ml" +# 4461 "cil/src/logic/logic_parser.ml" : 'logic_type)) ; (fun __caml_parser_env -> Obj.repr( -# 598 "cil/src/logic/logic_parser.mly" +# 604 "cil/src/logic/logic_parser.mly" ( ) -# 4309 "cil/src/logic/logic_parser.ml" +# 4467 "cil/src/logic/logic_parser.ml" : 'cv)) ; (fun __caml_parser_env -> Obj.repr( -# 599 "cil/src/logic/logic_parser.mly" +# 605 "cil/src/logic/logic_parser.mly" ( ) -# 4315 "cil/src/logic/logic_parser.ml" +# 4473 "cil/src/logic/logic_parser.ml" : 'cv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'type_spec) in Obj.repr( -# 603 "cil/src/logic/logic_parser.mly" +# 609 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4322 "cil/src/logic/logic_parser.ml" +# 4480 "cil/src/logic/logic_parser.ml" : 'type_spec_cv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'cv) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'type_spec) in Obj.repr( -# 604 "cil/src/logic/logic_parser.mly" +# 610 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4330 "cil/src/logic/logic_parser.ml" +# 4488 "cil/src/logic/logic_parser.ml" : 'type_spec_cv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'type_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'cv) in Obj.repr( -# 605 "cil/src/logic/logic_parser.mly" +# 611 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4338 "cil/src/logic/logic_parser.ml" +# 4496 "cil/src/logic/logic_parser.ml" : 'type_spec_cv)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'type_spec_cv) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'abs_spec_option) in Obj.repr( -# 608 "cil/src/logic/logic_parser.mly" +# 614 "cil/src/logic/logic_parser.mly" ( _2 _1 ) -# 4346 "cil/src/logic/logic_parser.ml" +# 4504 "cil/src/logic/logic_parser.ml" : 'cast_logic_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'type_spec_cv) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'abs_spec) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'cv) in Obj.repr( -# 609 "cil/src/logic/logic_parser.mly" +# 615 "cil/src/logic/logic_parser.mly" ( _2 _1 ) -# 4355 "cil/src/logic/logic_parser.ml" +# 4513 "cil/src/logic/logic_parser.ml" : 'cast_logic_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'id_as_typename) in Obj.repr( -# 613 "cil/src/logic/logic_parser.mly" +# 619 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4362 "cil/src/logic/logic_parser.ml" +# 4520 "cil/src/logic/logic_parser.ml" : 'logic_rt_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'begin_rt_type) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'logic_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'end_rt_type) in Obj.repr( -# 614 "cil/src/logic/logic_parser.mly" +# 620 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4371 "cil/src/logic/logic_parser.ml" +# 4529 "cil/src/logic/logic_parser.ml" : 'logic_rt_type)) ; (fun __caml_parser_env -> Obj.repr( -# 618 "cil/src/logic/logic_parser.mly" +# 624 "cil/src/logic/logic_parser.mly" ( fun t -> t ) -# 4377 "cil/src/logic/logic_parser.ml" +# 4535 "cil/src/logic/logic_parser.ml" : 'abs_spec_option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'abs_spec) in Obj.repr( -# 619 "cil/src/logic/logic_parser.mly" +# 625 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4384 "cil/src/logic/logic_parser.ml" +# 4542 "cil/src/logic/logic_parser.ml" : 'abs_spec_option)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'tabs) in Obj.repr( -# 623 "cil/src/logic/logic_parser.mly" +# 629 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4391 "cil/src/logic/logic_parser.ml" +# 4549 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'stars) in Obj.repr( -# 624 "cil/src/logic/logic_parser.mly" +# 630 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4398 "cil/src/logic/logic_parser.ml" +# 4556 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'stars) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'tabs) in Obj.repr( -# 625 "cil/src/logic/logic_parser.mly" +# 631 "cil/src/logic/logic_parser.mly" ( fun t -> _2 (_1 t) ) -# 4406 "cil/src/logic/logic_parser.ml" +# 4564 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'stars) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'abs_spec_bis) in Obj.repr( -# 626 "cil/src/logic/logic_parser.mly" +# 632 "cil/src/logic/logic_parser.mly" ( fun t -> _2 (_1 t) ) -# 4414 "cil/src/logic/logic_parser.ml" +# 4572 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'stars) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'abs_spec_bis) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'tabs) in Obj.repr( -# 627 "cil/src/logic/logic_parser.mly" +# 633 "cil/src/logic/logic_parser.mly" ( fun t -> _2 (_3 (_1 t)) ) -# 4423 "cil/src/logic/logic_parser.ml" +# 4581 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'abs_spec_bis) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'tabs) in Obj.repr( -# 628 "cil/src/logic/logic_parser.mly" +# 634 "cil/src/logic/logic_parser.mly" ( fun t -> _1 (_2 t) ) -# 4431 "cil/src/logic/logic_parser.ml" +# 4589 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'abs_spec_bis) in Obj.repr( -# 629 "cil/src/logic/logic_parser.mly" +# 635 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4438 "cil/src/logic/logic_parser.ml" +# 4596 "cil/src/logic/logic_parser.ml" : 'abs_spec)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'abs_spec) in Obj.repr( -# 633 "cil/src/logic/logic_parser.mly" +# 639 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4445 "cil/src/logic/logic_parser.ml" +# 4603 "cil/src/logic/logic_parser.ml" : 'abs_spec_bis)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'abs_spec_bis) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'abs_param_type_list) in Obj.repr( -# 634 "cil/src/logic/logic_parser.mly" +# 640 "cil/src/logic/logic_parser.mly" ( fun t -> _1 (LTarrow(_3,t)) ) -# 4453 "cil/src/logic/logic_parser.ml" +# 4611 "cil/src/logic/logic_parser.ml" : 'abs_spec_bis)) ; (fun __caml_parser_env -> Obj.repr( -# 638 "cil/src/logic/logic_parser.mly" +# 644 "cil/src/logic/logic_parser.mly" ( fun t -> LTpointer t ) -# 4459 "cil/src/logic/logic_parser.ml" +# 4617 "cil/src/logic/logic_parser.ml" : 'stars)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'stars) in Obj.repr( -# 639 "cil/src/logic/logic_parser.mly" +# 645 "cil/src/logic/logic_parser.mly" ( fun t -> _1 (LTpointer t) ) -# 4466 "cil/src/logic/logic_parser.ml" +# 4624 "cil/src/logic/logic_parser.ml" : 'stars)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'constant_option) in Obj.repr( -# 644 "cil/src/logic/logic_parser.mly" +# 650 "cil/src/logic/logic_parser.mly" ( fun t -> LTarray (t,_2) ) -# 4475 "cil/src/logic/logic_parser.ml" +# 4633 "cil/src/logic/logic_parser.ml" : 'tabs)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'constant_option) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'tabs) in Obj.repr( -# 648 "cil/src/logic/logic_parser.mly" +# 654 "cil/src/logic/logic_parser.mly" ( fun t -> (LTarray (_4 t,_2)) ) -# 4485 "cil/src/logic/logic_parser.ml" +# 4643 "cil/src/logic/logic_parser.ml" : 'tabs)) ; (fun __caml_parser_env -> Obj.repr( -# 654 "cil/src/logic/logic_parser.mly" +# 660 "cil/src/logic/logic_parser.mly" ( LTinteger ) -# 4491 "cil/src/logic/logic_parser.ml" +# 4649 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 655 "cil/src/logic/logic_parser.mly" +# 661 "cil/src/logic/logic_parser.mly" ( LTreal ) -# 4497 "cil/src/logic/logic_parser.ml" +# 4655 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 656 "cil/src/logic/logic_parser.mly" +# 662 "cil/src/logic/logic_parser.mly" ( LTnamed (Utf8_logic.boolean,[]) ) -# 4503 "cil/src/logic/logic_parser.ml" +# 4661 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 657 "cil/src/logic/logic_parser.mly" +# 663 "cil/src/logic/logic_parser.mly" ( LTvoid ) -# 4509 "cil/src/logic/logic_parser.ml" +# 4667 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 658 "cil/src/logic/logic_parser.mly" +# 664 "cil/src/logic/logic_parser.mly" ( LTint IChar ) -# 4515 "cil/src/logic/logic_parser.ml" +# 4673 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 659 "cil/src/logic/logic_parser.mly" +# 665 "cil/src/logic/logic_parser.mly" ( LTint ISChar ) -# 4521 "cil/src/logic/logic_parser.ml" +# 4679 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 660 "cil/src/logic/logic_parser.mly" +# 666 "cil/src/logic/logic_parser.mly" ( LTint IUChar ) -# 4527 "cil/src/logic/logic_parser.ml" +# 4685 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 661 "cil/src/logic/logic_parser.mly" +# 667 "cil/src/logic/logic_parser.mly" ( LTint IInt ) -# 4533 "cil/src/logic/logic_parser.ml" +# 4691 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 662 "cil/src/logic/logic_parser.mly" +# 668 "cil/src/logic/logic_parser.mly" ( LTint IInt ) -# 4539 "cil/src/logic/logic_parser.ml" +# 4697 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 663 "cil/src/logic/logic_parser.mly" +# 669 "cil/src/logic/logic_parser.mly" ( LTint IUInt ) -# 4545 "cil/src/logic/logic_parser.ml" +# 4703 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 664 "cil/src/logic/logic_parser.mly" +# 670 "cil/src/logic/logic_parser.mly" ( LTint IUInt ) -# 4551 "cil/src/logic/logic_parser.ml" +# 4709 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 665 "cil/src/logic/logic_parser.mly" +# 671 "cil/src/logic/logic_parser.mly" ( LTint IShort ) -# 4557 "cil/src/logic/logic_parser.ml" +# 4715 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 666 "cil/src/logic/logic_parser.mly" +# 672 "cil/src/logic/logic_parser.mly" ( LTint IShort ) -# 4563 "cil/src/logic/logic_parser.ml" +# 4721 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 667 "cil/src/logic/logic_parser.mly" +# 673 "cil/src/logic/logic_parser.mly" ( LTint IUShort ) -# 4569 "cil/src/logic/logic_parser.ml" +# 4727 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 668 "cil/src/logic/logic_parser.mly" +# 674 "cil/src/logic/logic_parser.mly" ( LTint ILong ) -# 4575 "cil/src/logic/logic_parser.ml" +# 4733 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 669 "cil/src/logic/logic_parser.mly" +# 675 "cil/src/logic/logic_parser.mly" ( LTint ILong ) -# 4581 "cil/src/logic/logic_parser.ml" +# 4739 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 670 "cil/src/logic/logic_parser.mly" +# 676 "cil/src/logic/logic_parser.mly" ( LTint IULong ) -# 4587 "cil/src/logic/logic_parser.ml" +# 4745 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 671 "cil/src/logic/logic_parser.mly" +# 677 "cil/src/logic/logic_parser.mly" ( LTint ILong ) -# 4593 "cil/src/logic/logic_parser.ml" +# 4751 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 672 "cil/src/logic/logic_parser.mly" +# 678 "cil/src/logic/logic_parser.mly" ( LTint ILong ) -# 4599 "cil/src/logic/logic_parser.ml" +# 4757 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 673 "cil/src/logic/logic_parser.mly" +# 679 "cil/src/logic/logic_parser.mly" ( LTint IULong ) -# 4605 "cil/src/logic/logic_parser.ml" +# 4763 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 674 "cil/src/logic/logic_parser.mly" +# 680 "cil/src/logic/logic_parser.mly" ( LTint ILongLong ) -# 4611 "cil/src/logic/logic_parser.ml" +# 4769 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 676 "cil/src/logic/logic_parser.mly" +# 682 "cil/src/logic/logic_parser.mly" ( LTint ILongLong ) -# 4617 "cil/src/logic/logic_parser.ml" +# 4775 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 678 "cil/src/logic/logic_parser.mly" +# 684 "cil/src/logic/logic_parser.mly" ( LTint IULongLong ) -# 4623 "cil/src/logic/logic_parser.ml" +# 4781 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 680 "cil/src/logic/logic_parser.mly" +# 686 "cil/src/logic/logic_parser.mly" ( LTint ILongLong ) -# 4629 "cil/src/logic/logic_parser.ml" +# 4787 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 682 "cil/src/logic/logic_parser.mly" +# 688 "cil/src/logic/logic_parser.mly" ( LTint ILongLong ) -# 4635 "cil/src/logic/logic_parser.ml" +# 4793 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 684 "cil/src/logic/logic_parser.mly" +# 690 "cil/src/logic/logic_parser.mly" ( LTint IULongLong ) -# 4641 "cil/src/logic/logic_parser.ml" +# 4799 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 686 "cil/src/logic/logic_parser.mly" +# 692 "cil/src/logic/logic_parser.mly" ( LTfloat FFloat ) -# 4647 "cil/src/logic/logic_parser.ml" +# 4805 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 687 "cil/src/logic/logic_parser.mly" +# 693 "cil/src/logic/logic_parser.mly" ( LTfloat FDouble ) -# 4653 "cil/src/logic/logic_parser.ml" +# 4811 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 688 "cil/src/logic/logic_parser.mly" +# 694 "cil/src/logic/logic_parser.mly" ( LTfloat FLongDouble ) -# 4659 "cil/src/logic/logic_parser.ml" +# 4817 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'exit_rt_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 689 "cil/src/logic/logic_parser.mly" +# 695 "cil/src/logic/logic_parser.mly" ( LTstruct _3 ) -# 4667 "cil/src/logic/logic_parser.ml" +# 4825 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'exit_rt_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 690 "cil/src/logic/logic_parser.mly" +# 696 "cil/src/logic/logic_parser.mly" ( LTenum _3 ) -# 4675 "cil/src/logic/logic_parser.ml" +# 4833 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'exit_rt_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 691 "cil/src/logic/logic_parser.mly" +# 697 "cil/src/logic/logic_parser.mly" ( LTunion _3 ) -# 4683 "cil/src/logic/logic_parser.ml" +# 4841 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 692 "cil/src/logic/logic_parser.mly" +# 698 "cil/src/logic/logic_parser.mly" ( LTnamed (_1,[]) ) -# 4690 "cil/src/logic/logic_parser.ml" +# 4848 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : string) in @@ -4694,417 +4852,411 @@ let _4 = (Parsing.peek_val __caml_parser_env 2 : 'ne_logic_type_list) in let _6 = (Parsing.peek_val __caml_parser_env 0 : 'exit_rt_type) in Obj.repr( -# 694 "cil/src/logic/logic_parser.mly" +# 700 "cil/src/logic/logic_parser.mly" ( LTnamed(_1,_4) ) -# 4700 "cil/src/logic/logic_parser.ml" +# 4858 "cil/src/logic/logic_parser.ml" : 'type_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_type) in Obj.repr( -# 698 "cil/src/logic/logic_parser.mly" +# 704 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4707 "cil/src/logic/logic_parser.ml" +# 4865 "cil/src/logic/logic_parser.ml" : 'ne_logic_type_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'logic_type) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'enter_rt_type) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'ne_logic_type_list) in Obj.repr( -# 699 "cil/src/logic/logic_parser.mly" +# 705 "cil/src/logic/logic_parser.mly" ( _1 :: _4 ) -# 4716 "cil/src/logic/logic_parser.ml" +# 4874 "cil/src/logic/logic_parser.ml" : 'ne_logic_type_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 705 "cil/src/logic/logic_parser.mly" +# 711 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4725 "cil/src/logic/logic_parser.ml" +# 4883 "cil/src/logic/logic_parser.ml" : 'full_lexpr)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'identifier) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 709 "cil/src/logic/logic_parser.mly" +# 715 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4734 "cil/src/logic/logic_parser.ml" +# 4892 "cil/src/logic/logic_parser.ml" : 'full_identifier)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'identifier_or_typename) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 713 "cil/src/logic/logic_parser.mly" +# 719 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4743 "cil/src/logic/logic_parser.ml" +# 4901 "cil/src/logic/logic_parser.ml" : 'full_identifier_or_typename)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ne_parameters) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 717 "cil/src/logic/logic_parser.mly" +# 723 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4752 "cil/src/logic/logic_parser.ml" +# 4910 "cil/src/logic/logic_parser.ml" : 'full_parameters)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'parameter) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 721 "cil/src/logic/logic_parser.mly" +# 727 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4761 "cil/src/logic/logic_parser.ml" +# 4919 "cil/src/logic/logic_parser.ml" : 'full_parameter)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'zones) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 725 "cil/src/logic/logic_parser.mly" +# 731 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4770 "cil/src/logic/logic_parser.ml" +# 4928 "cil/src/logic/logic_parser.ml" : 'full_zones)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ne_lexpr_list) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 729 "cil/src/logic/logic_parser.mly" +# 735 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4779 "cil/src/logic/logic_parser.ml" +# 4937 "cil/src/logic/logic_parser.ml" : 'full_ne_lexpr_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'logic_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 733 "cil/src/logic/logic_parser.mly" +# 739 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4788 "cil/src/logic/logic_parser.ml" +# 4946 "cil/src/logic/logic_parser.ml" : 'full_logic_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'logic_rt_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 737 "cil/src/logic/logic_parser.mly" +# 743 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4797 "cil/src/logic/logic_parser.ml" +# 4955 "cil/src/logic/logic_parser.ml" : 'full_logic_rt_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'enter_kw_c_mode) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'assigns) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'exit_kw_c_mode) in Obj.repr( -# 740 "cil/src/logic/logic_parser.mly" +# 746 "cil/src/logic/logic_parser.mly" ( _2 ) -# 4806 "cil/src/logic/logic_parser.ml" +# 4964 "cil/src/logic/logic_parser.ml" : 'full_assigns)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'ext_global_clauses_opt) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'ext_module_specs_opt) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ext_global_specs_opt) in Obj.repr( -# 746 "cil/src/logic/logic_parser.mly" +# 752 "cil/src/logic/logic_parser.mly" ( ("",_1,_2)::_3 ) -# 4815 "cil/src/logic/logic_parser.ml" +# 4973 "cil/src/logic/logic_parser.ml" : Logic_ptree.ext_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 750 "cil/src/logic/logic_parser.mly" +# 756 "cil/src/logic/logic_parser.mly" ( [] ) -# 4821 "cil/src/logic/logic_parser.ml" +# 4979 "cil/src/logic/logic_parser.ml" : 'ext_global_clauses_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_clauses) in Obj.repr( -# 751 "cil/src/logic/logic_parser.mly" +# 757 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4828 "cil/src/logic/logic_parser.ml" +# 4986 "cil/src/logic/logic_parser.ml" : 'ext_global_clauses_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_clause) in Obj.repr( -# 755 "cil/src/logic/logic_parser.mly" +# 761 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4835 "cil/src/logic/logic_parser.ml" +# 4993 "cil/src/logic/logic_parser.ml" : 'ext_global_clauses)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_global_clause) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_clauses) in Obj.repr( -# 756 "cil/src/logic/logic_parser.mly" +# 762 "cil/src/logic/logic_parser.mly" ( _1::_2 ) -# 4843 "cil/src/logic/logic_parser.ml" +# 5001 "cil/src/logic/logic_parser.ml" : 'ext_global_clauses)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'decl) in Obj.repr( -# 760 "cil/src/logic/logic_parser.mly" +# 766 "cil/src/logic/logic_parser.mly" ( Ext_decl (loc_decl _1) ) -# 4850 "cil/src/logic/logic_parser.ml" +# 5008 "cil/src/logic/logic_parser.ml" : 'ext_global_clause)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'any_identifier) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 761 "cil/src/logic/logic_parser.mly" +# 767 "cil/src/logic/logic_parser.mly" ( Ext_macro (_2, _4) ) -# 4858 "cil/src/logic/logic_parser.ml" +# 5016 "cil/src/logic/logic_parser.ml" : 'ext_global_clause)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'string) in Obj.repr( -# 762 "cil/src/logic/logic_parser.mly" - ( let b,s = _2 in Ext_include(b,s) ) -# 4865 "cil/src/logic/logic_parser.ml" +# 768 "cil/src/logic/logic_parser.mly" + ( let b,s = _2 in Ext_include(b,s, loc()) ) +# 5023 "cil/src/logic/logic_parser.ml" : 'ext_global_clause)) ; (fun __caml_parser_env -> Obj.repr( -# 766 "cil/src/logic/logic_parser.mly" +# 772 "cil/src/logic/logic_parser.mly" ( [] ) -# 4871 "cil/src/logic/logic_parser.ml" +# 5029 "cil/src/logic/logic_parser.ml" : 'ext_global_specs_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_specs) in Obj.repr( -# 767 "cil/src/logic/logic_parser.mly" +# 773 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4878 "cil/src/logic/logic_parser.ml" +# 5036 "cil/src/logic/logic_parser.ml" : 'ext_global_specs_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_spec) in Obj.repr( -# 771 "cil/src/logic/logic_parser.mly" +# 777 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4885 "cil/src/logic/logic_parser.ml" +# 5043 "cil/src/logic/logic_parser.ml" : 'ext_global_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_global_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_specs) in Obj.repr( -# 772 "cil/src/logic/logic_parser.mly" +# 778 "cil/src/logic/logic_parser.mly" ( _1::_2 ) -# 4893 "cil/src/logic/logic_parser.ml" +# 5051 "cil/src/logic/logic_parser.ml" : 'ext_global_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'ext_module_markup) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ext_global_clauses_opt) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ext_module_specs) in Obj.repr( -# 777 "cil/src/logic/logic_parser.mly" +# 783 "cil/src/logic/logic_parser.mly" ( (_1,_2,_3) ) -# 4902 "cil/src/logic/logic_parser.ml" +# 5060 "cil/src/logic/logic_parser.ml" : 'ext_global_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_module_markup) in Obj.repr( -# 779 "cil/src/logic/logic_parser.mly" +# 785 "cil/src/logic/logic_parser.mly" ( (_1,[],[]) ) -# 4909 "cil/src/logic/logic_parser.ml" +# 5067 "cil/src/logic/logic_parser.ml" : 'ext_global_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 783 "cil/src/logic/logic_parser.mly" +# 789 "cil/src/logic/logic_parser.mly" ( [] ) -# 4915 "cil/src/logic/logic_parser.ml" +# 5073 "cil/src/logic/logic_parser.ml" : 'ext_module_specs_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_module_specs) in Obj.repr( -# 784 "cil/src/logic/logic_parser.mly" +# 790 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4922 "cil/src/logic/logic_parser.ml" +# 5080 "cil/src/logic/logic_parser.ml" : 'ext_module_specs_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_module_spec) in Obj.repr( -# 788 "cil/src/logic/logic_parser.mly" +# 794 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4929 "cil/src/logic/logic_parser.ml" +# 5087 "cil/src/logic/logic_parser.ml" : 'ext_module_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_module_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_module_specs) in Obj.repr( -# 789 "cil/src/logic/logic_parser.mly" +# 795 "cil/src/logic/logic_parser.mly" ( _1::_2 ) -# 4937 "cil/src/logic/logic_parser.ml" +# 5095 "cil/src/logic/logic_parser.ml" : 'ext_module_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_function_markup) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_function_specs_opt) in Obj.repr( -# 793 "cil/src/logic/logic_parser.mly" +# 799 "cil/src/logic/logic_parser.mly" ( (_1,_2) ) -# 4945 "cil/src/logic/logic_parser.ml" +# 5103 "cil/src/logic/logic_parser.ml" : 'ext_module_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 797 "cil/src/logic/logic_parser.mly" +# 803 "cil/src/logic/logic_parser.mly" ( [] ) -# 4951 "cil/src/logic/logic_parser.ml" +# 5109 "cil/src/logic/logic_parser.ml" : 'ext_function_specs_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_function_specs) in Obj.repr( -# 798 "cil/src/logic/logic_parser.mly" +# 804 "cil/src/logic/logic_parser.mly" ( _1 ) -# 4958 "cil/src/logic/logic_parser.ml" +# 5116 "cil/src/logic/logic_parser.ml" : 'ext_function_specs_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_at_loop_markup) in Obj.repr( -# 802 "cil/src/logic/logic_parser.mly" +# 808 "cil/src/logic/logic_parser.mly" ( []) -# 4965 "cil/src/logic/logic_parser.ml" +# 5123 "cil/src/logic/logic_parser.ml" : 'ext_function_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_at_stmt_markup) in Obj.repr( -# 803 "cil/src/logic/logic_parser.mly" +# 809 "cil/src/logic/logic_parser.mly" ( []) -# 4972 "cil/src/logic/logic_parser.ml" +# 5130 "cil/src/logic/logic_parser.ml" : 'ext_function_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_function_spec) in Obj.repr( -# 804 "cil/src/logic/logic_parser.mly" +# 810 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 4979 "cil/src/logic/logic_parser.ml" +# 5137 "cil/src/logic/logic_parser.ml" : 'ext_function_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_function_spec) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_function_specs) in Obj.repr( -# 805 "cil/src/logic/logic_parser.mly" +# 811 "cil/src/logic/logic_parser.mly" ( _1::_2 ) -# 4987 "cil/src/logic/logic_parser.ml" +# 5145 "cil/src/logic/logic_parser.ml" : 'ext_function_specs)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_global_clause) in Obj.repr( -# 810 "cil/src/logic/logic_parser.mly" +# 816 "cil/src/logic/logic_parser.mly" ( Ext_glob _1 ) -# 4994 "cil/src/logic/logic_parser.ml" +# 5152 "cil/src/logic/logic_parser.ml" : 'ext_function_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_at_loop_markup) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_stmt_loop_spec) in Obj.repr( -# 812 "cil/src/logic/logic_parser.mly" - ( Ext_loop_spec(_1,_2) ) -# 5002 "cil/src/logic/logic_parser.ml" +# 818 "cil/src/logic/logic_parser.mly" + ( Ext_loop_spec(_1,_2,loc()) ) +# 5160 "cil/src/logic/logic_parser.ml" : 'ext_function_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_at_stmt_markup) in - let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_stmt_specs) in + let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_stmt_loop_spec) in Obj.repr( -# 814 "cil/src/logic/logic_parser.mly" - ( Ext_stmt_spec(_1,_2) ) -# 5010 "cil/src/logic/logic_parser.ml" +# 820 "cil/src/logic/logic_parser.mly" + ( Ext_stmt_spec(_1,_2,loc()) ) +# 5168 "cil/src/logic/logic_parser.ml" : 'ext_function_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_contract_markup) in - let _2 = (Parsing.peek_val __caml_parser_env 0 : 'ext_contract) in + let _2 = (Parsing.peek_val __caml_parser_env 0 : 'contract) in Obj.repr( -# 816 "cil/src/logic/logic_parser.mly" - ( Ext_spec _2 ) -# 5018 "cil/src/logic/logic_parser.ml" +# 822 "cil/src/logic/logic_parser.mly" + ( let s,pos = _2 in Ext_spec (s,pos) ) +# 5176 "cil/src/logic/logic_parser.ml" : 'ext_function_spec)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 0 : 'contract) in - Obj.repr( -# 820 "cil/src/logic/logic_parser.mly" - ( let s,_pos = _1 in s ) -# 5025 "cil/src/logic/logic_parser.ml" - : 'ext_contract)) -; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'annotation) in Obj.repr( -# 824 "cil/src/logic/logic_parser.mly" +# 826 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5032 "cil/src/logic/logic_parser.ml" +# 5183 "cil/src/logic/logic_parser.ml" : 'ext_stmt_loop_spec)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 0 : 'annotation) in + let _1 = (Parsing.peek_val __caml_parser_env 1 : 'ext_contract_markup) in + let _2 = (Parsing.peek_val __caml_parser_env 0 : 'contract) in Obj.repr( -# 828 "cil/src/logic/logic_parser.mly" - ( _1 ) -# 5039 "cil/src/logic/logic_parser.ml" - : 'ext_stmt_specs)) +# 827 "cil/src/logic/logic_parser.mly" + ( let s, pos = _2 in Acode_annot (pos, AStmtSpec ([],s)) ) +# 5191 "cil/src/logic/logic_parser.ml" + : 'ext_stmt_loop_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 832 "cil/src/logic/logic_parser.mly" +# 831 "cil/src/logic/logic_parser.mly" ( "" ) -# 5045 "cil/src/logic/logic_parser.ml" +# 5197 "cil/src/logic/logic_parser.ml" : 'ext_identifier_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ext_identifier) in Obj.repr( -# 833 "cil/src/logic/logic_parser.mly" +# 832 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5052 "cil/src/logic/logic_parser.ml" +# 5204 "cil/src/logic/logic_parser.ml" : 'ext_identifier_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'any_identifier) in Obj.repr( -# 837 "cil/src/logic/logic_parser.mly" +# 836 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5059 "cil/src/logic/logic_parser.ml" +# 5211 "cil/src/logic/logic_parser.ml" : 'ext_identifier)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ext_identifier) in Obj.repr( -# 841 "cil/src/logic/logic_parser.mly" +# 840 "cil/src/logic/logic_parser.mly" ( _2 ) -# 5066 "cil/src/logic/logic_parser.ml" +# 5218 "cil/src/logic/logic_parser.ml" : 'ext_module_markup)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ext_identifier) in Obj.repr( -# 845 "cil/src/logic/logic_parser.mly" - ( _2 ) -# 5073 "cil/src/logic/logic_parser.ml" +# 844 "cil/src/logic/logic_parser.mly" + ( _2, loc() ) +# 5225 "cil/src/logic/logic_parser.ml" : 'ext_function_markup)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ext_identifier_opt) in Obj.repr( -# 849 "cil/src/logic/logic_parser.mly" +# 848 "cil/src/logic/logic_parser.mly" ( _2 ) -# 5080 "cil/src/logic/logic_parser.ml" +# 5232 "cil/src/logic/logic_parser.ml" : 'ext_contract_markup)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 853 "cil/src/logic/logic_parser.mly" +# 852 "cil/src/logic/logic_parser.mly" ( _3 ) -# 5087 "cil/src/logic/logic_parser.ml" +# 5239 "cil/src/logic/logic_parser.ml" : 'ext_at_loop_markup)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 857 "cil/src/logic/logic_parser.mly" +# 856 "cil/src/logic/logic_parser.mly" ( _2 ) -# 5094 "cil/src/logic/logic_parser.ml" +# 5246 "cil/src/logic/logic_parser.ml" : 'ext_at_stmt_markup)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'any_identifier) in Obj.repr( -# 858 "cil/src/logic/logic_parser.mly" +# 857 "cil/src/logic/logic_parser.mly" ( _2 ) -# 5101 "cil/src/logic/logic_parser.ml" +# 5253 "cil/src/logic/logic_parser.ml" : 'ext_at_stmt_markup)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'contract) in Obj.repr( -# 864 "cil/src/logic/logic_parser.mly" +# 863 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5108 "cil/src/logic/logic_parser.ml" +# 5260 "cil/src/logic/logic_parser.ml" : Logic_ptree.spec * Cabs.cabsloc)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : 'requires) in @@ -5114,7 +5266,7 @@ let _5 = (Parsing.peek_val __caml_parser_env 1 : 'behaviors) in let _6 = (Parsing.peek_val __caml_parser_env 0 : 'complete_or_disjoint) in Obj.repr( -# 869 "cil/src/logic/logic_parser.mly" +# 868 "cil/src/logic/logic_parser.mly" ( let requires=_1 in let (assigns,post_cond,extended) = _4 in let behaviors = _5 in @@ -5134,33 +5286,33 @@ spec_disjoint_behaviors = disjoints; }, loc() ) -# 5138 "cil/src/logic/logic_parser.ml" +# 5290 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'requires) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ne_terminates) in Obj.repr( -# 888 "cil/src/logic/logic_parser.mly" +# 887 "cil/src/logic/logic_parser.mly" ( clause_order 3 "requires" "terminates" ) -# 5146 "cil/src/logic/logic_parser.ml" +# 5298 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'requires) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'terminates) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_decreases) in Obj.repr( -# 890 "cil/src/logic/logic_parser.mly" +# 889 "cil/src/logic/logic_parser.mly" ( clause_order 4 "requires" "decreases" ) -# 5155 "cil/src/logic/logic_parser.ml" +# 5307 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'requires) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'terminates) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_decreases) in Obj.repr( -# 892 "cil/src/logic/logic_parser.mly" +# 891 "cil/src/logic/logic_parser.mly" ( clause_order 4 "terminates" "decreases" ) -# 5164 "cil/src/logic/logic_parser.ml" +# 5316 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'requires) in @@ -5168,9 +5320,9 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : 'decreases) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'ne_simple_clauses) in Obj.repr( -# 894 "cil/src/logic/logic_parser.mly" +# 893 "cil/src/logic/logic_parser.mly" ( clause_order 5 "requires" "post-condition or assigns" ) -# 5174 "cil/src/logic/logic_parser.ml" +# 5326 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'requires) in @@ -5178,9 +5330,9 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : 'decreases) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'ne_simple_clauses) in Obj.repr( -# 896 "cil/src/logic/logic_parser.mly" +# 895 "cil/src/logic/logic_parser.mly" ( clause_order 5 "terminates" "post-condition or assigns" ) -# 5184 "cil/src/logic/logic_parser.ml" +# 5336 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 4 : 'requires) in @@ -5188,9 +5340,9 @@ let _3 = (Parsing.peek_val __caml_parser_env 2 : 'decreases) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'ne_simple_clauses) in Obj.repr( -# 898 "cil/src/logic/logic_parser.mly" +# 897 "cil/src/logic/logic_parser.mly" ( clause_order 5 "decreases" "post-condition or assigns" ) -# 5194 "cil/src/logic/logic_parser.ml" +# 5346 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : 'requires) in @@ -5199,9 +5351,9 @@ let _4 = (Parsing.peek_val __caml_parser_env 2 : 'simple_clauses) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'ne_behaviors) in Obj.repr( -# 900 "cil/src/logic/logic_parser.mly" +# 899 "cil/src/logic/logic_parser.mly" ( clause_order 6 "terminates" "behavior" ) -# 5205 "cil/src/logic/logic_parser.ml" +# 5357 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 5 : 'requires) in @@ -5210,9 +5362,9 @@ let _4 = (Parsing.peek_val __caml_parser_env 2 : 'simple_clauses) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'ne_behaviors) in Obj.repr( -# 902 "cil/src/logic/logic_parser.mly" +# 901 "cil/src/logic/logic_parser.mly" ( clause_order 6 "decreases" "behavior" ) -# 5216 "cil/src/logic/logic_parser.ml" +# 5368 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'requires) in @@ -5222,9 +5374,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 2 : 'behaviors) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_complete_or_disjoint) in Obj.repr( -# 905 "cil/src/logic/logic_parser.mly" +# 904 "cil/src/logic/logic_parser.mly" ( clause_order 7 "requires" "complete or disjoint" ) -# 5228 "cil/src/logic/logic_parser.ml" +# 5380 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'requires) in @@ -5234,9 +5386,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 2 : 'behaviors) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_complete_or_disjoint) in Obj.repr( -# 908 "cil/src/logic/logic_parser.mly" +# 907 "cil/src/logic/logic_parser.mly" ( clause_order 7 "terminates" "complete or disjoint" ) -# 5240 "cil/src/logic/logic_parser.ml" +# 5392 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'requires) in @@ -5246,9 +5398,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 2 : 'behaviors) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_complete_or_disjoint) in Obj.repr( -# 911 "cil/src/logic/logic_parser.mly" +# 910 "cil/src/logic/logic_parser.mly" ( clause_order 7 "decreases" "complete or disjoint" ) -# 5252 "cil/src/logic/logic_parser.ml" +# 5404 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'requires) in @@ -5258,9 +5410,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 2 : 'behaviors) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_complete_or_disjoint) in Obj.repr( -# 914 "cil/src/logic/logic_parser.mly" +# 913 "cil/src/logic/logic_parser.mly" ( clause_order 7 "behavior" "complete or disjoint" ) -# 5264 "cil/src/logic/logic_parser.ml" +# 5416 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'requires) in @@ -5270,9 +5422,9 @@ let _5 = (Parsing.peek_val __caml_parser_env 2 : 'behaviors) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_complete_or_disjoint) in Obj.repr( -# 917 "cil/src/logic/logic_parser.mly" +# 916 "cil/src/logic/logic_parser.mly" ( clause_order 7 "assigns" "complete or disjoint" ) -# 5276 "cil/src/logic/logic_parser.ml" +# 5428 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'requires) in @@ -5283,163 +5435,163 @@ let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_complete_or_disjoint) in let _7 = (Parsing.peek_val __caml_parser_env 0 : 'post_cond_kind) in Obj.repr( -# 920 "cil/src/logic/logic_parser.mly" +# 919 "cil/src/logic/logic_parser.mly" ( clause_order 7 "post-condition" "complete or disjoint" ) -# 5289 "cil/src/logic/logic_parser.ml" +# 5441 "cil/src/logic/logic_parser.ml" : 'contract)) ; (fun __caml_parser_env -> Obj.repr( -# 924 "cil/src/logic/logic_parser.mly" +# 923 "cil/src/logic/logic_parser.mly" ( [] ) -# 5295 "cil/src/logic/logic_parser.ml" +# 5447 "cil/src/logic/logic_parser.ml" : 'requires)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_requires) in Obj.repr( -# 925 "cil/src/logic/logic_parser.mly" +# 924 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5302 "cil/src/logic/logic_parser.ml" +# 5454 "cil/src/logic/logic_parser.ml" : 'requires)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'full_lexpr) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'requires) in Obj.repr( -# 929 "cil/src/logic/logic_parser.mly" +# 928 "cil/src/logic/logic_parser.mly" ( _2::_4 ) -# 5310 "cil/src/logic/logic_parser.ml" +# 5462 "cil/src/logic/logic_parser.ml" : 'ne_requires)) ; (fun __caml_parser_env -> Obj.repr( -# 933 "cil/src/logic/logic_parser.mly" +# 932 "cil/src/logic/logic_parser.mly" ( None ) -# 5316 "cil/src/logic/logic_parser.ml" +# 5468 "cil/src/logic/logic_parser.ml" : 'terminates)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_terminates) in Obj.repr( -# 934 "cil/src/logic/logic_parser.mly" +# 933 "cil/src/logic/logic_parser.mly" ( Some _1 ) -# 5323 "cil/src/logic/logic_parser.ml" +# 5475 "cil/src/logic/logic_parser.ml" : 'terminates)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 938 "cil/src/logic/logic_parser.mly" +# 937 "cil/src/logic/logic_parser.mly" ( _2 ) -# 5330 "cil/src/logic/logic_parser.ml" +# 5482 "cil/src/logic/logic_parser.ml" : 'ne_terminates)) ; (fun __caml_parser_env -> Obj.repr( -# 942 "cil/src/logic/logic_parser.mly" +# 941 "cil/src/logic/logic_parser.mly" ( None ) -# 5336 "cil/src/logic/logic_parser.ml" +# 5488 "cil/src/logic/logic_parser.ml" : 'decreases)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_decreases) in Obj.repr( -# 943 "cil/src/logic/logic_parser.mly" +# 942 "cil/src/logic/logic_parser.mly" ( Some _1 ) -# 5343 "cil/src/logic/logic_parser.ml" +# 5495 "cil/src/logic/logic_parser.ml" : 'decreases)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'variant) in Obj.repr( -# 947 "cil/src/logic/logic_parser.mly" +# 946 "cil/src/logic/logic_parser.mly" ( _2 ) -# 5350 "cil/src/logic/logic_parser.ml" +# 5502 "cil/src/logic/logic_parser.ml" : 'ne_decreases)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'full_lexpr) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'any_identifier) in Obj.repr( -# 951 "cil/src/logic/logic_parser.mly" +# 950 "cil/src/logic/logic_parser.mly" ( (_1, Some _3) ) -# 5358 "cil/src/logic/logic_parser.ml" +# 5510 "cil/src/logic/logic_parser.ml" : 'variant)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_lexpr) in Obj.repr( -# 952 "cil/src/logic/logic_parser.mly" +# 951 "cil/src/logic/logic_parser.mly" ( (_1, None) ) -# 5365 "cil/src/logic/logic_parser.ml" +# 5517 "cil/src/logic/logic_parser.ml" : 'variant)) ; (fun __caml_parser_env -> Obj.repr( -# 956 "cil/src/logic/logic_parser.mly" +# 955 "cil/src/logic/logic_parser.mly" ( WritesAny,[],[] ) -# 5371 "cil/src/logic/logic_parser.ml" +# 5523 "cil/src/logic/logic_parser.ml" : 'simple_clauses)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_simple_clauses) in Obj.repr( -# 957 "cil/src/logic/logic_parser.mly" +# 956 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5378 "cil/src/logic/logic_parser.ml" +# 5530 "cil/src/logic/logic_parser.ml" : 'simple_clauses)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'post_cond_kind) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'full_lexpr) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'simple_clauses) in Obj.repr( -# 962 "cil/src/logic/logic_parser.mly" +# 961 "cil/src/logic/logic_parser.mly" ( let assigns,post_cond,extended = _4 in assigns,((_1,_2)::post_cond),extended ) -# 5387 "cil/src/logic/logic_parser.ml" +# 5539 "cil/src/logic/logic_parser.ml" : 'ne_simple_clauses)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'full_assigns) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'simple_clauses) in Obj.repr( -# 964 "cil/src/logic/logic_parser.mly" +# 963 "cil/src/logic/logic_parser.mly" ( let assigns,post_cond,extended = _4 in let a = merge_assigns assigns _2 in a,post_cond,extended ) -# 5398 "cil/src/logic/logic_parser.ml" +# 5550 "cil/src/logic/logic_parser.ml" : 'ne_simple_clauses)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'grammar_extension) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'simple_clauses) in Obj.repr( -# 969 "cil/src/logic/logic_parser.mly" +# 968 "cil/src/logic/logic_parser.mly" ( let assigns,post_cond,extended = _3 in assigns,post_cond,_1::extended ) -# 5408 "cil/src/logic/logic_parser.ml" +# 5560 "cil/src/logic/logic_parser.ml" : 'ne_simple_clauses)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'grammar_extension_name) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'full_zones) in Obj.repr( -# 976 "cil/src/logic/logic_parser.mly" +# 975 "cil/src/logic/logic_parser.mly" ( _1,_2 ) -# 5416 "cil/src/logic/logic_parser.ml" +# 5568 "cil/src/logic/logic_parser.ml" : 'grammar_extension)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'post_cond) in Obj.repr( -# 980 "cil/src/logic/logic_parser.mly" +# 979 "cil/src/logic/logic_parser.mly" ( fst _1 ) -# 5423 "cil/src/logic/logic_parser.ml" +# 5575 "cil/src/logic/logic_parser.ml" : 'post_cond_kind)) ; (fun __caml_parser_env -> Obj.repr( -# 984 "cil/src/logic/logic_parser.mly" +# 983 "cil/src/logic/logic_parser.mly" ( [] ) -# 5429 "cil/src/logic/logic_parser.ml" +# 5581 "cil/src/logic/logic_parser.ml" : 'behaviors)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_behaviors) in Obj.repr( -# 985 "cil/src/logic/logic_parser.mly" +# 984 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5436 "cil/src/logic/logic_parser.ml" +# 5588 "cil/src/logic/logic_parser.ml" : 'behaviors)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'behavior_name) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'behavior_body) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'behaviors) in Obj.repr( -# 989 "cil/src/logic/logic_parser.mly" +# 988 "cil/src/logic/logic_parser.mly" ( let (assumes,requires,(assigns,post_cond,extended)) = _4 in let behaviors = _5 in let b = @@ -5448,194 +5600,190 @@ ~extended:(wrap_extended extended) () in b::behaviors ) -# 5452 "cil/src/logic/logic_parser.ml" +# 5604 "cil/src/logic/logic_parser.ml" : 'ne_behaviors)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'assumes) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'requires) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'simple_clauses) in Obj.repr( -# 999 "cil/src/logic/logic_parser.mly" +# 998 "cil/src/logic/logic_parser.mly" ( _1,_2,_3 ) -# 5461 "cil/src/logic/logic_parser.ml" +# 5613 "cil/src/logic/logic_parser.ml" : 'behavior_body)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'assumes) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'ne_requires) in Obj.repr( -# 1001 "cil/src/logic/logic_parser.mly" +# 1000 "cil/src/logic/logic_parser.mly" ( clause_order 3 "assumes" "requires" ) -# 5469 "cil/src/logic/logic_parser.ml" +# 5621 "cil/src/logic/logic_parser.ml" : 'behavior_body)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'assumes) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'requires) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_simple_clauses) in Obj.repr( -# 1003 "cil/src/logic/logic_parser.mly" +# 1002 "cil/src/logic/logic_parser.mly" ( clause_order 4 "assumes" "assigns or post-condition" ) -# 5478 "cil/src/logic/logic_parser.ml" +# 5630 "cil/src/logic/logic_parser.ml" : 'behavior_body)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'assumes) in let _2 = (Parsing.peek_val __caml_parser_env 2 : 'requires) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_simple_clauses) in Obj.repr( -# 1005 "cil/src/logic/logic_parser.mly" +# 1004 "cil/src/logic/logic_parser.mly" ( clause_order 4 "requires" "assigns or post-condition" ) -# 5487 "cil/src/logic/logic_parser.ml" +# 5639 "cil/src/logic/logic_parser.ml" : 'behavior_body)) ; (fun __caml_parser_env -> Obj.repr( -# 1009 "cil/src/logic/logic_parser.mly" +# 1008 "cil/src/logic/logic_parser.mly" ( [] ) -# 5493 "cil/src/logic/logic_parser.ml" +# 5645 "cil/src/logic/logic_parser.ml" : 'assumes)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'full_lexpr) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'assumes) in Obj.repr( -# 1011 "cil/src/logic/logic_parser.mly" +# 1010 "cil/src/logic/logic_parser.mly" ( _2::_4 ) -# 5501 "cil/src/logic/logic_parser.ml" +# 5653 "cil/src/logic/logic_parser.ml" : 'assumes)) ; (fun __caml_parser_env -> Obj.repr( -# 1015 "cil/src/logic/logic_parser.mly" +# 1014 "cil/src/logic/logic_parser.mly" ( [],[] ) -# 5507 "cil/src/logic/logic_parser.ml" +# 5659 "cil/src/logic/logic_parser.ml" : 'complete_or_disjoint)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_complete_or_disjoint) in Obj.repr( -# 1016 "cil/src/logic/logic_parser.mly" +# 1015 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5514 "cil/src/logic/logic_parser.ml" +# 5666 "cil/src/logic/logic_parser.ml" : 'complete_or_disjoint)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'behavior_name_list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'complete_or_disjoint) in Obj.repr( -# 1021 "cil/src/logic/logic_parser.mly" +# 1020 "cil/src/logic/logic_parser.mly" ( let complete,disjoint = _5 in _3::complete, disjoint ) -# 5522 "cil/src/logic/logic_parser.ml" +# 5674 "cil/src/logic/logic_parser.ml" : 'ne_complete_or_disjoint)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'behavior_name_list) in let _5 = (Parsing.peek_val __caml_parser_env 0 : 'complete_or_disjoint) in Obj.repr( -# 1024 "cil/src/logic/logic_parser.mly" +# 1023 "cil/src/logic/logic_parser.mly" ( let complete,disjoint = _5 in complete,_3::disjoint ) -# 5530 "cil/src/logic/logic_parser.ml" +# 5682 "cil/src/logic/logic_parser.ml" : 'ne_complete_or_disjoint)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'zones) in Obj.repr( -# 1030 "cil/src/logic/logic_parser.mly" +# 1029 "cil/src/logic/logic_parser.mly" ( List.map (fun x -> (x,FromAny)) _1 ) -# 5537 "cil/src/logic/logic_parser.ml" +# 5689 "cil/src/logic/logic_parser.ml" : 'assigns)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'ne_zones) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'zones) in Obj.repr( -# 1031 "cil/src/logic/logic_parser.mly" +# 1030 "cil/src/logic/logic_parser.mly" (List.map (fun x -> (x, From _3)) _1) -# 5545 "cil/src/logic/logic_parser.ml" +# 5697 "cil/src/logic/logic_parser.ml" : 'assigns)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_zones) in Obj.repr( -# 1040 "cil/src/logic/logic_parser.mly" +# 1039 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5552 "cil/src/logic/logic_parser.ml" +# 5704 "cil/src/logic/logic_parser.ml" : 'zones)) ; (fun __caml_parser_env -> Obj.repr( -# 1041 "cil/src/logic/logic_parser.mly" +# 1040 "cil/src/logic/logic_parser.mly" ( [] ) -# 5558 "cil/src/logic/logic_parser.ml" +# 5710 "cil/src/logic/logic_parser.ml" : 'zones)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_lexpr_list) in Obj.repr( -# 1045 "cil/src/logic/logic_parser.mly" +# 1044 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5565 "cil/src/logic/logic_parser.ml" +# 5717 "cil/src/logic/logic_parser.ml" : 'ne_zones)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'annotation) in Obj.repr( -# 1051 "cil/src/logic/logic_parser.mly" +# 1050 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5572 "cil/src/logic/logic_parser.ml" +# 5724 "cil/src/logic/logic_parser.ml" : Logic_ptree.annot)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'is_spec) in let _2 = (Parsing.peek_val __caml_parser_env 1 : 'any) in Obj.repr( -# 1052 "cil/src/logic/logic_parser.mly" +# 1051 "cil/src/logic/logic_parser.mly" ( Aspec ) -# 5580 "cil/src/logic/logic_parser.ml" +# 5732 "cil/src/logic/logic_parser.ml" : Logic_ptree.annot)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'decl_list) in Obj.repr( -# 1053 "cil/src/logic/logic_parser.mly" +# 1052 "cil/src/logic/logic_parser.mly" ( Adecl (_1) ) -# 5587 "cil/src/logic/logic_parser.ml" +# 5739 "cil/src/logic/logic_parser.ml" : Logic_ptree.annot)) ; (fun __caml_parser_env -> - let _2 = (Parsing.peek_val __caml_parser_env 2 : 'ne_behavior_name_list) in - let _4 = (Parsing.peek_val __caml_parser_env 0 : 'contract) in - Obj.repr( -# 1058 "cil/src/logic/logic_parser.mly" - ( - Format.eprintf - "Behavior list is forgotten by the current implementation@."; - Afor_spec (loc(), _2, fst (_4)) - ) -# 5599 "cil/src/logic/logic_parser.ml" - : 'annotation)) -; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annotations) in Obj.repr( -# 1064 "cil/src/logic/logic_parser.mly" +# 1057 "cil/src/logic/logic_parser.mly" ( let (b,v,p) = _1 in (* TODO: do better, do not lose the structure ! *) let l = b@v@p in Aloop_annot (loc (), l) ) -# 5609 "cil/src/logic/logic_parser.ml" +# 5749 "cil/src/logic/logic_parser.ml" + : 'annotation)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 2 : 'ne_behavior_name_list) in + let _4 = (Parsing.peek_val __caml_parser_env 0 : 'contract) in + Obj.repr( +# 1062 "cil/src/logic/logic_parser.mly" + ( let s, pos = _4 in Acode_annot (pos, AStmtSpec (_2,s)) ) +# 5757 "cil/src/logic/logic_parser.ml" : 'annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'code_annotation) in Obj.repr( -# 1068 "cil/src/logic/logic_parser.mly" +# 1063 "cil/src/logic/logic_parser.mly" ( Acode_annot (loc(),_1) ) -# 5616 "cil/src/logic/logic_parser.ml" +# 5764 "cil/src/logic/logic_parser.ml" : 'annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'code_annotation) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'beg_code_annotation) in Obj.repr( -# 1070 "cil/src/logic/logic_parser.mly" +# 1065 "cil/src/logic/logic_parser.mly" ( raise (Not_well_formed (loc(), "Only one code annotation is allowed per comment")) ) -# 5627 "cil/src/logic/logic_parser.ml" +# 5775 "cil/src/logic/logic_parser.ml" : 'annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_identifier_or_typename) in Obj.repr( -# 1074 "cil/src/logic/logic_parser.mly" +# 1069 "cil/src/logic/logic_parser.mly" ( Aattribute_annot (loc (), _1) ) -# 5634 "cil/src/logic/logic_parser.ml" +# 5782 "cil/src/logic/logic_parser.ml" : 'annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_stack) in Obj.repr( -# 1081 "cil/src/logic/logic_parser.mly" +# 1076 "cil/src/logic/logic_parser.mly" ( let (i,a,b,v,p) = _1 in let invs = List.map (fun i -> AInvariant([],true,i)) i in let oth = @@ -5647,29 +5795,29 @@ AAssigns ([],a)::b in (invs@oth,v,p) ) -# 5651 "cil/src/logic/logic_parser.ml" +# 5799 "cil/src/logic/logic_parser.ml" : 'loop_annotations)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'loop_invariant) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_opt) in Obj.repr( -# 1097 "cil/src/logic/logic_parser.mly" +# 1092 "cil/src/logic/logic_parser.mly" ( let (i,a,b,v,p) = _2 in (_1::i,a,b,v,p) ) -# 5659 "cil/src/logic/logic_parser.ml" +# 5807 "cil/src/logic/logic_parser.ml" : 'loop_annot_stack)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'loop_effects) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_opt) in Obj.repr( -# 1099 "cil/src/logic/logic_parser.mly" +# 1094 "cil/src/logic/logic_parser.mly" ( let (i,a,b,v,p) = _2 in (i,merge_assigns a _1,b,v,p) ) -# 5667 "cil/src/logic/logic_parser.ml" +# 5815 "cil/src/logic/logic_parser.ml" : 'loop_annot_stack)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'ne_behavior_name_list) in let _4 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_stack) in Obj.repr( -# 1101 "cil/src/logic/logic_parser.mly" +# 1096 "cil/src/logic/logic_parser.mly" ( let (i,a,b,v,p) = _4 in let behav = _2 in let invs = List.map (fun i -> AInvariant(behav,true,i)) i in @@ -5680,13 +5828,13 @@ in ([],WritesAny,invs@oth,v,p) ) -# 5684 "cil/src/logic/logic_parser.ml" +# 5832 "cil/src/logic/logic_parser.ml" : 'loop_annot_stack)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'loop_variant) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_opt) in Obj.repr( -# 1112 "cil/src/logic/logic_parser.mly" +# 1107 "cil/src/logic/logic_parser.mly" ( let pos,loop_variant = _1 in let (i,a,b,v,p) = _2 in check_empty @@ -5702,76 +5850,76 @@ check_empty (pos,"loop annotations can have at most one variant.") v ; (i,a,b,AVariant loop_variant::v,p) ) -# 5706 "cil/src/logic/logic_parser.ml" +# 5854 "cil/src/logic/logic_parser.ml" : 'loop_annot_stack)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'loop_pragma) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_opt) in Obj.repr( -# 1128 "cil/src/logic/logic_parser.mly" +# 1123 "cil/src/logic/logic_parser.mly" ( let (i,a,b,v,p) = _2 in (i,a,b,v,APragma (Loop_pragma _1)::p) ) -# 5714 "cil/src/logic/logic_parser.ml" +# 5862 "cil/src/logic/logic_parser.ml" : 'loop_annot_stack)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'loop_grammar_extension) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_opt) in Obj.repr( -# 1129 "cil/src/logic/logic_parser.mly" +# 1124 "cil/src/logic/logic_parser.mly" ( raise (Not_well_formed (loc(),"Grammar extension for loop annotations is not yet implemented")) ) -# 5726 "cil/src/logic/logic_parser.ml" +# 5874 "cil/src/logic/logic_parser.ml" : 'loop_annot_stack)) ; (fun __caml_parser_env -> Obj.repr( -# 1138 "cil/src/logic/logic_parser.mly" +# 1133 "cil/src/logic/logic_parser.mly" ( ([], WritesAny, [], [], []) ) -# 5732 "cil/src/logic/logic_parser.ml" +# 5880 "cil/src/logic/logic_parser.ml" : 'loop_annot_opt)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'loop_annot_stack) in Obj.repr( -# 1140 "cil/src/logic/logic_parser.mly" +# 1135 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5739 "cil/src/logic/logic_parser.ml" +# 5887 "cil/src/logic/logic_parser.ml" : 'loop_annot_opt)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'full_assigns) in Obj.repr( -# 1144 "cil/src/logic/logic_parser.mly" +# 1139 "cil/src/logic/logic_parser.mly" ( _3 ) -# 5746 "cil/src/logic/logic_parser.ml" +# 5894 "cil/src/logic/logic_parser.ml" : 'loop_effects)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1148 "cil/src/logic/logic_parser.mly" +# 1143 "cil/src/logic/logic_parser.mly" ( _3 ) -# 5753 "cil/src/logic/logic_parser.ml" +# 5901 "cil/src/logic/logic_parser.ml" : 'loop_invariant)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'variant) in Obj.repr( -# 1152 "cil/src/logic/logic_parser.mly" +# 1147 "cil/src/logic/logic_parser.mly" ( loc(),_3 ) -# 5760 "cil/src/logic/logic_parser.ml" +# 5908 "cil/src/logic/logic_parser.ml" : 'loop_variant)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'grammar_extension) in Obj.repr( -# 1157 "cil/src/logic/logic_parser.mly" +# 1152 "cil/src/logic/logic_parser.mly" ( raise (Not_well_formed (loc(),"Grammar extension for loop annotations is not yet implemented")) ) -# 5769 "cil/src/logic/logic_parser.ml" +# 5917 "cil/src/logic/logic_parser.ml" : 'loop_grammar_extension)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'any_identifier) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_ne_lexpr_list) in Obj.repr( -# 1164 "cil/src/logic/logic_parser.mly" +# 1159 "cil/src/logic/logic_parser.mly" ( if _3 = "UNROLL_LOOP" || _3 = "UNROLL" then match _4 with | [level] -> Unroll_level level @@ -5782,275 +5930,302 @@ else if _3 = "WIDEN_HINTS" then Widen_hints _4 else raise (Not_well_formed (loc(),"unknown loop pragma")) ) -# 5786 "cil/src/logic/logic_parser.ml" +# 5934 "cil/src/logic/logic_parser.ml" : 'loop_pragma)) ; (fun __caml_parser_env -> Obj.repr( -# 1179 "cil/src/logic/logic_parser.mly" +# 1174 "cil/src/logic/logic_parser.mly" () -# 5792 "cil/src/logic/logic_parser.ml" +# 5940 "cil/src/logic/logic_parser.ml" : 'beg_code_annotation)) ; (fun __caml_parser_env -> Obj.repr( -# 1180 "cil/src/logic/logic_parser.mly" +# 1175 "cil/src/logic/logic_parser.mly" () -# 5798 "cil/src/logic/logic_parser.ml" +# 5946 "cil/src/logic/logic_parser.ml" : 'beg_code_annotation)) ; (fun __caml_parser_env -> Obj.repr( -# 1181 "cil/src/logic/logic_parser.mly" +# 1176 "cil/src/logic/logic_parser.mly" () -# 5804 "cil/src/logic/logic_parser.ml" +# 5952 "cil/src/logic/logic_parser.ml" : 'beg_code_annotation)) ; (fun __caml_parser_env -> Obj.repr( -# 1182 "cil/src/logic/logic_parser.mly" +# 1177 "cil/src/logic/logic_parser.mly" () -# 5810 "cil/src/logic/logic_parser.ml" +# 5958 "cil/src/logic/logic_parser.ml" : 'beg_code_annotation)) ; (fun __caml_parser_env -> Obj.repr( -# 1183 "cil/src/logic/logic_parser.mly" +# 1178 "cil/src/logic/logic_parser.mly" () -# 5816 "cil/src/logic/logic_parser.ml" +# 5964 "cil/src/logic/logic_parser.ml" : 'beg_code_annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'slice_pragma) in Obj.repr( -# 1187 "cil/src/logic/logic_parser.mly" +# 1182 "cil/src/logic/logic_parser.mly" ( APragma (Slice_pragma _1) ) -# 5823 "cil/src/logic/logic_parser.ml" +# 5971 "cil/src/logic/logic_parser.ml" : 'code_annotation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'impact_pragma) in Obj.repr( -# 1188 "cil/src/logic/logic_parser.mly" +# 1183 "cil/src/logic/logic_parser.mly" ( APragma (Impact_pragma _1) ) -# 5830 "cil/src/logic/logic_parser.ml" +# 5978 "cil/src/logic/logic_parser.ml" : 'code_annotation)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'ne_behavior_name_list) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1190 "cil/src/logic/logic_parser.mly" +# 1185 "cil/src/logic/logic_parser.mly" ( AAssert (_2,_5) ) -# 5838 "cil/src/logic/logic_parser.ml" +# 5986 "cil/src/logic/logic_parser.ml" : 'code_annotation)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'ne_behavior_name_list) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1192 "cil/src/logic/logic_parser.mly" +# 1187 "cil/src/logic/logic_parser.mly" ( AInvariant (_2,false,_5) ) -# 5846 "cil/src/logic/logic_parser.ml" +# 5994 "cil/src/logic/logic_parser.ml" : 'code_annotation)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1193 "cil/src/logic/logic_parser.mly" +# 1188 "cil/src/logic/logic_parser.mly" ( AAssert ([],_2) ) -# 5853 "cil/src/logic/logic_parser.ml" +# 6001 "cil/src/logic/logic_parser.ml" : 'code_annotation)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1194 "cil/src/logic/logic_parser.mly" +# 1189 "cil/src/logic/logic_parser.mly" ( AInvariant ([],false,_2) ) -# 5860 "cil/src/logic/logic_parser.ml" +# 6008 "cil/src/logic/logic_parser.ml" : 'code_annotation)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'any_identifier) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1199 "cil/src/logic/logic_parser.mly" +# 1194 "cil/src/logic/logic_parser.mly" ( if _3 = "expr" then SPexpr _4 else raise (Not_well_formed (loc(), "unknown slice pragma")) ) -# 5869 "cil/src/logic/logic_parser.ml" +# 6017 "cil/src/logic/logic_parser.ml" : 'slice_pragma)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'any_identifier) in Obj.repr( -# 1202 "cil/src/logic/logic_parser.mly" +# 1197 "cil/src/logic/logic_parser.mly" ( if _3 = "ctrl" then SPctrl else if _3 = "stmt" then SPstmt else raise (Not_well_formed (loc(), "unknown slice pragma")) ) -# 5878 "cil/src/logic/logic_parser.ml" +# 6026 "cil/src/logic/logic_parser.ml" : 'slice_pragma)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'any_identifier) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1209 "cil/src/logic/logic_parser.mly" +# 1204 "cil/src/logic/logic_parser.mly" ( if _3 = "expr" then IPexpr _4 else raise (Not_well_formed (loc(), "unknown impact pragma")) ) -# 5887 "cil/src/logic/logic_parser.ml" +# 6035 "cil/src/logic/logic_parser.ml" : 'impact_pragma)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : 'any_identifier) in Obj.repr( -# 1212 "cil/src/logic/logic_parser.mly" +# 1207 "cil/src/logic/logic_parser.mly" ( if _3 = "stmt" then IPstmt else raise (Not_well_formed (loc(), "unknown impact pragma")) ) -# 5895 "cil/src/logic/logic_parser.ml" +# 6043 "cil/src/logic/logic_parser.ml" : 'impact_pragma)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'decl) in Obj.repr( -# 1219 "cil/src/logic/logic_parser.mly" +# 1214 "cil/src/logic/logic_parser.mly" ( [loc_decl _1] ) -# 5902 "cil/src/logic/logic_parser.ml" +# 6050 "cil/src/logic/logic_parser.ml" : 'decl_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'decl) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'decl_list) in Obj.repr( -# 1220 "cil/src/logic/logic_parser.mly" +# 1215 "cil/src/logic/logic_parser.mly" ( (loc_decl _1) :: _2 ) -# 5910 "cil/src/logic/logic_parser.ml" +# 6058 "cil/src/logic/logic_parser.ml" : 'decl_list)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 3 : 'any_identifier) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1224 "cil/src/logic/logic_parser.mly" +# 1219 "cil/src/logic/logic_parser.mly" ( LDinvariant (_3, _5) ) -# 5918 "cil/src/logic/logic_parser.ml" +# 6066 "cil/src/logic/logic_parser.ml" : 'decl)) ; (fun __caml_parser_env -> - let _2 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in + let _2 = (Parsing.peek_val __caml_parser_env 2 : 'ne_zones) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'volatile_opt) in Obj.repr( -# 1225 "cil/src/logic/logic_parser.mly" - ( LDvolatile (_2, _3) ) -# 5926 "cil/src/logic/logic_parser.ml" +# 1220 "cil/src/logic/logic_parser.mly" + ( LDvolatile (_2, _3) ) +# 6074 "cil/src/logic/logic_parser.ml" : 'decl)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'type_annot) in Obj.repr( -# 1226 "cil/src/logic/logic_parser.mly" +# 1221 "cil/src/logic/logic_parser.mly" (LDtype_annot _1) -# 5933 "cil/src/logic/logic_parser.ml" +# 6081 "cil/src/logic/logic_parser.ml" + : 'decl)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 0 : 'model_annot) in + Obj.repr( +# 1222 "cil/src/logic/logic_parser.mly" + (LDmodel_annot _1) +# 6088 "cil/src/logic/logic_parser.ml" : 'decl)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_def) in Obj.repr( -# 1227 "cil/src/logic/logic_parser.mly" +# 1223 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5940 "cil/src/logic/logic_parser.ml" +# 6095 "cil/src/logic/logic_parser.ml" : 'decl)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'deprecated_logic_decl) in Obj.repr( -# 1228 "cil/src/logic/logic_parser.mly" +# 1224 "cil/src/logic/logic_parser.mly" ( _1 ) -# 5947 "cil/src/logic/logic_parser.ml" +# 6102 "cil/src/logic/logic_parser.ml" : 'decl)) ; (fun __caml_parser_env -> Obj.repr( -# 1232 "cil/src/logic/logic_parser.mly" +# 1228 "cil/src/logic/logic_parser.mly" ( None, None ) -# 5953 "cil/src/logic/logic_parser.ml" +# 6108 "cil/src/logic/logic_parser.ml" : 'volatile_opt)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'any_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'volatile_opt) in Obj.repr( -# 1234 "cil/src/logic/logic_parser.mly" +# 1230 "cil/src/logic/logic_parser.mly" ( let read,write=_3 in if read = None then (Some _2),write else (Format.eprintf "Warning: read %s ignored@." _2; _3) ) -# 5966 "cil/src/logic/logic_parser.ml" +# 6121 "cil/src/logic/logic_parser.ml" : 'volatile_opt)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'any_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'volatile_opt) in Obj.repr( -# 1241 "cil/src/logic/logic_parser.mly" +# 1237 "cil/src/logic/logic_parser.mly" ( let read,write=_3 in if write = None then read,(Some _2) else (Format.eprintf "Warning: write %s ignored@." _2; _3) ) -# 5979 "cil/src/logic/logic_parser.ml" +# 6134 "cil/src/logic/logic_parser.ml" : 'volatile_opt)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 6 : 'any_identifier) in let _5 = (Parsing.peek_val __caml_parser_env 4 : 'full_parameter) in let _8 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1252 "cil/src/logic/logic_parser.mly" +# 1248 "cil/src/logic/logic_parser.mly" ( let typ,name = _5 in{ inv_name = _3; this_name = name; this_type = typ; inv = _8; } ) -# 5988 "cil/src/logic/logic_parser.ml" +# 6143 "cil/src/logic/logic_parser.ml" : 'type_annot)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_identifier) in + let _2 = (Parsing.peek_val __caml_parser_env 3 : 'type_spec) in + let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_parameter) in + Obj.repr( +# 1253 "cil/src/logic/logic_parser.mly" + ( let typ,name = _4 in + { model_for_type = _2; model_name = name; model_type = typ; } + ) +# 6153 "cil/src/logic/logic_parser.ml" + : 'model_annot)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 3 : 'id_as_typename) in + let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_parameter) in Obj.repr( # 1257 "cil/src/logic/logic_parser.mly" + ( let typ,name = _4 in + { model_for_type = _2; model_name = name; model_type = typ; } + ) +# 6163 "cil/src/logic/logic_parser.ml" + : 'model_annot)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_identifier) in + Obj.repr( +# 1264 "cil/src/logic/logic_parser.mly" ( enter_type_variables_scope []; (_1,[]) ) -# 5995 "cil/src/logic/logic_parser.ml" +# 6170 "cil/src/logic/logic_parser.ml" : 'poly_id_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'full_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_tvar_list) in Obj.repr( -# 1259 "cil/src/logic/logic_parser.mly" +# 1266 "cil/src/logic/logic_parser.mly" ( enter_type_variables_scope _3; (_1,_3) ) -# 6003 "cil/src/logic/logic_parser.ml" +# 6178 "cil/src/logic/logic_parser.ml" : 'poly_id_type)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'poly_id_type) in Obj.repr( -# 1266 "cil/src/logic/logic_parser.mly" +# 1273 "cil/src/logic/logic_parser.mly" ( let (id,_) = _1 in Logic_env.add_typename id; _1 ) -# 6010 "cil/src/logic/logic_parser.ml" +# 6185 "cil/src/logic/logic_parser.ml" : 'poly_id_type_add_typename)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'poly_id_type) in Obj.repr( -# 1270 "cil/src/logic/logic_parser.mly" +# 1277 "cil/src/logic/logic_parser.mly" ( let (id,tvar) = _1 in (id,[],tvar) ) -# 6017 "cil/src/logic/logic_parser.ml" +# 6192 "cil/src/logic/logic_parser.ml" : 'poly_id)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'full_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_label_list) in Obj.repr( -# 1272 "cil/src/logic/logic_parser.mly" +# 1279 "cil/src/logic/logic_parser.mly" ( enter_type_variables_scope []; (_1,_3,[]) ) -# 6025 "cil/src/logic/logic_parser.ml" +# 6200 "cil/src/logic/logic_parser.ml" : 'poly_id)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 6 : 'full_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 4 : 'ne_label_list) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'ne_tvar_list) in Obj.repr( -# 1274 "cil/src/logic/logic_parser.mly" +# 1281 "cil/src/logic/logic_parser.mly" ( enter_type_variables_scope _6; _1,_3,_6 ) -# 6034 "cil/src/logic/logic_parser.ml" +# 6209 "cil/src/logic/logic_parser.ml" : 'poly_id)) ; (fun __caml_parser_env -> Obj.repr( -# 1278 "cil/src/logic/logic_parser.mly" +# 1285 "cil/src/logic/logic_parser.mly" ( [] ) -# 6040 "cil/src/logic/logic_parser.ml" +# 6215 "cil/src/logic/logic_parser.ml" : 'opt_parameters)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'parameters) in Obj.repr( -# 1279 "cil/src/logic/logic_parser.mly" +# 1286 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6047 "cil/src/logic/logic_parser.ml" +# 6222 "cil/src/logic/logic_parser.ml" : 'opt_parameters)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'full_parameters) in Obj.repr( -# 1283 "cil/src/logic/logic_parser.mly" +# 1290 "cil/src/logic/logic_parser.mly" ( _2 ) -# 6054 "cil/src/logic/logic_parser.ml" +# 6229 "cil/src/logic/logic_parser.ml" : 'parameters)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 5 : 'full_logic_rt_type) in @@ -6058,117 +6233,117 @@ let _4 = (Parsing.peek_val __caml_parser_env 3 : 'opt_parameters) in let _6 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1289 "cil/src/logic/logic_parser.mly" +# 1296 "cil/src/logic/logic_parser.mly" ( let (id, labels, tvars) = _3 in exit_type_variables_scope (); LDlogic_def (id, labels, tvars, _2, _4, _6) ) -# 6066 "cil/src/logic/logic_parser.ml" +# 6241 "cil/src/logic/logic_parser.ml" : 'logic_def)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'poly_id) in let _3 = (Parsing.peek_val __caml_parser_env 3 : 'opt_parameters) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1294 "cil/src/logic/logic_parser.mly" +# 1301 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); LDpredicate_def (id, labels, tvars, _3, _5) ) -# 6077 "cil/src/logic/logic_parser.ml" +# 6252 "cil/src/logic/logic_parser.ml" : 'logic_def)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'poly_id) in let _3 = (Parsing.peek_val __caml_parser_env 3 : 'parameters) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'indcases) in Obj.repr( -# 1299 "cil/src/logic/logic_parser.mly" +# 1306 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); LDinductive_def(id, labels, tvars, _3, _5) ) -# 6088 "cil/src/logic/logic_parser.ml" +# 6263 "cil/src/logic/logic_parser.ml" : 'logic_def)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'poly_id) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1303 "cil/src/logic/logic_parser.mly" +# 1310 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); LDlemma (id, false, labels, tvars, _4) ) -# 6098 "cil/src/logic/logic_parser.ml" +# 6273 "cil/src/logic/logic_parser.ml" : 'logic_def)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'any_identifier) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'logic_decls) in Obj.repr( -# 1307 "cil/src/logic/logic_parser.mly" +# 1314 "cil/src/logic/logic_parser.mly" ( LDaxiomatic(_2,_4) ) -# 6106 "cil/src/logic/logic_parser.ml" +# 6281 "cil/src/logic/logic_parser.ml" : 'logic_def)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'poly_id_type_add_typename) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'typedef) in Obj.repr( -# 1309 "cil/src/logic/logic_parser.mly" +# 1316 "cil/src/logic/logic_parser.mly" ( let (id,tvars) = _2 in exit_type_variables_scope (); LDtype(id,tvars,Some _4) ) -# 6117 "cil/src/logic/logic_parser.ml" +# 6292 "cil/src/logic/logic_parser.ml" : 'logic_def)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'full_logic_rt_type) in let _3 = (Parsing.peek_val __caml_parser_env 2 : 'poly_id) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'opt_parameters) in Obj.repr( -# 1318 "cil/src/logic/logic_parser.mly" +# 1325 "cil/src/logic/logic_parser.mly" ( let (id, labels, tvars) = _3 in exit_type_variables_scope (); Format.eprintf "Warning: deprecated logic declaration '%s', should be declared inside an axiomatic block@." id; LDlogic_reads (id, labels, tvars, _2, _4, None) ) -# 6129 "cil/src/logic/logic_parser.ml" +# 6304 "cil/src/logic/logic_parser.ml" : 'deprecated_logic_decl)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 2 : 'poly_id) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'opt_parameters) in Obj.repr( -# 1324 "cil/src/logic/logic_parser.mly" +# 1331 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); Format.eprintf "Warning: deprecated logic declaration `%s', should be declared inside an axiomatic block@." id; LDpredicate_reads (id, labels, tvars, _3, None) ) -# 6140 "cil/src/logic/logic_parser.ml" +# 6315 "cil/src/logic/logic_parser.ml" : 'deprecated_logic_decl)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'poly_id_type) in Obj.repr( -# 1330 "cil/src/logic/logic_parser.mly" +# 1337 "cil/src/logic/logic_parser.mly" ( let (id,tvars) = _2 in Logic_env.add_typename id; exit_type_variables_scope (); Format.eprintf "Warning: deprecated logic type declaration `%s', should be declared inside an axiomatic block@." id; LDtype(id,tvars,None) ) -# 6151 "cil/src/logic/logic_parser.ml" +# 6326 "cil/src/logic/logic_parser.ml" : 'deprecated_logic_decl)) ; (fun __caml_parser_env -> Obj.repr( -# 1340 "cil/src/logic/logic_parser.mly" +# 1347 "cil/src/logic/logic_parser.mly" ( [] ) -# 6157 "cil/src/logic/logic_parser.ml" +# 6332 "cil/src/logic/logic_parser.ml" : 'logic_decls)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'logic_decl_loc) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'logic_decls) in Obj.repr( -# 1342 "cil/src/logic/logic_parser.mly" +# 1349 "cil/src/logic/logic_parser.mly" ( _1::_2 ) -# 6165 "cil/src/logic/logic_parser.ml" +# 6340 "cil/src/logic/logic_parser.ml" : 'logic_decls)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_def) in Obj.repr( -# 1346 "cil/src/logic/logic_parser.mly" +# 1353 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6172 "cil/src/logic/logic_parser.ml" +# 6347 "cil/src/logic/logic_parser.ml" : 'logic_decl)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'full_logic_rt_type) in @@ -6176,1173 +6351,1185 @@ let _4 = (Parsing.peek_val __caml_parser_env 2 : 'opt_parameters) in let _5 = (Parsing.peek_val __caml_parser_env 1 : 'reads_clause) in Obj.repr( -# 1349 "cil/src/logic/logic_parser.mly" +# 1356 "cil/src/logic/logic_parser.mly" ( let (id, labels, tvars) = _3 in exit_type_variables_scope (); LDlogic_reads (id, labels, tvars, _2, _4, _5) ) -# 6184 "cil/src/logic/logic_parser.ml" +# 6359 "cil/src/logic/logic_parser.ml" : 'logic_decl)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'poly_id) in let _3 = (Parsing.peek_val __caml_parser_env 2 : 'opt_parameters) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'reads_clause) in Obj.repr( -# 1354 "cil/src/logic/logic_parser.mly" +# 1361 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); LDpredicate_reads (id, labels, tvars, _3, _4) ) -# 6195 "cil/src/logic/logic_parser.ml" +# 6370 "cil/src/logic/logic_parser.ml" : 'logic_decl)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'poly_id_type) in Obj.repr( -# 1359 "cil/src/logic/logic_parser.mly" +# 1366 "cil/src/logic/logic_parser.mly" ( let (id,tvars) = _2 in Logic_env.add_typename id; exit_type_variables_scope (); LDtype(id,tvars,None) ) -# 6205 "cil/src/logic/logic_parser.ml" +# 6380 "cil/src/logic/logic_parser.ml" : 'logic_decl)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'poly_id) in let _4 = (Parsing.peek_val __caml_parser_env 1 : 'full_lexpr) in Obj.repr( -# 1365 "cil/src/logic/logic_parser.mly" +# 1372 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); LDlemma (id, true, labels, tvars, _4) ) -# 6215 "cil/src/logic/logic_parser.ml" +# 6390 "cil/src/logic/logic_parser.ml" : 'logic_decl)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_decl) in Obj.repr( -# 1371 "cil/src/logic/logic_parser.mly" +# 1378 "cil/src/logic/logic_parser.mly" ( loc_decl _1 ) -# 6222 "cil/src/logic/logic_parser.ml" +# 6397 "cil/src/logic/logic_parser.ml" : 'logic_decl_loc)) ; (fun __caml_parser_env -> Obj.repr( -# 1376 "cil/src/logic/logic_parser.mly" +# 1383 "cil/src/logic/logic_parser.mly" ( None ) -# 6228 "cil/src/logic/logic_parser.ml" +# 6403 "cil/src/logic/logic_parser.ml" : 'reads_clause)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'zones) in Obj.repr( -# 1377 "cil/src/logic/logic_parser.mly" +# 1384 "cil/src/logic/logic_parser.mly" ( Some _2 ) -# 6235 "cil/src/logic/logic_parser.ml" +# 6410 "cil/src/logic/logic_parser.ml" : 'reads_clause)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_datacons_list) in Obj.repr( -# 1381 "cil/src/logic/logic_parser.mly" +# 1388 "cil/src/logic/logic_parser.mly" ( TDsum _1 ) -# 6242 "cil/src/logic/logic_parser.ml" +# 6417 "cil/src/logic/logic_parser.ml" : 'typedef)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_logic_type) in Obj.repr( -# 1382 "cil/src/logic/logic_parser.mly" +# 1389 "cil/src/logic/logic_parser.mly" ( TDsyn _1 ) -# 6249 "cil/src/logic/logic_parser.ml" +# 6424 "cil/src/logic/logic_parser.ml" : 'typedef)) ; (fun __caml_parser_env -> Obj.repr( -# 1386 "cil/src/logic/logic_parser.mly" +# 1393 "cil/src/logic/logic_parser.mly" ( [] ) -# 6255 "cil/src/logic/logic_parser.ml" +# 6430 "cil/src/logic/logic_parser.ml" : 'datacons_list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'datacons) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'datacons_list) in Obj.repr( -# 1387 "cil/src/logic/logic_parser.mly" +# 1394 "cil/src/logic/logic_parser.mly" ( _2 :: _3 ) -# 6263 "cil/src/logic/logic_parser.ml" +# 6438 "cil/src/logic/logic_parser.ml" : 'datacons_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'datacons) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'datacons_list) in Obj.repr( -# 1391 "cil/src/logic/logic_parser.mly" +# 1398 "cil/src/logic/logic_parser.mly" ( _1 :: _2 ) -# 6271 "cil/src/logic/logic_parser.ml" +# 6446 "cil/src/logic/logic_parser.ml" : 'ne_datacons_list)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'datacons) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'datacons_list) in Obj.repr( -# 1392 "cil/src/logic/logic_parser.mly" +# 1399 "cil/src/logic/logic_parser.mly" ( _2 :: _3 ) -# 6279 "cil/src/logic/logic_parser.ml" +# 6454 "cil/src/logic/logic_parser.ml" : 'ne_datacons_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_identifier) in Obj.repr( -# 1396 "cil/src/logic/logic_parser.mly" +# 1403 "cil/src/logic/logic_parser.mly" ( (_1,[]) ) -# 6286 "cil/src/logic/logic_parser.ml" +# 6461 "cil/src/logic/logic_parser.ml" : 'datacons)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'full_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'ne_type_list) in Obj.repr( -# 1397 "cil/src/logic/logic_parser.mly" +# 1404 "cil/src/logic/logic_parser.mly" ( (_1,_3) ) -# 6294 "cil/src/logic/logic_parser.ml" +# 6469 "cil/src/logic/logic_parser.ml" : 'datacons)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_logic_type) in Obj.repr( -# 1401 "cil/src/logic/logic_parser.mly" +# 1408 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 6301 "cil/src/logic/logic_parser.ml" +# 6476 "cil/src/logic/logic_parser.ml" : 'ne_type_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'full_logic_type) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ne_type_list) in Obj.repr( -# 1402 "cil/src/logic/logic_parser.mly" +# 1409 "cil/src/logic/logic_parser.mly" ( _1::_3 ) -# 6309 "cil/src/logic/logic_parser.ml" +# 6484 "cil/src/logic/logic_parser.ml" : 'ne_type_list)) ; (fun __caml_parser_env -> Obj.repr( -# 1406 "cil/src/logic/logic_parser.mly" +# 1413 "cil/src/logic/logic_parser.mly" ( [] ) -# 6315 "cil/src/logic/logic_parser.ml" +# 6490 "cil/src/logic/logic_parser.ml" : 'indcases)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 4 : 'poly_id) in let _4 = (Parsing.peek_val __caml_parser_env 2 : 'lexpr) in let _6 = (Parsing.peek_val __caml_parser_env 0 : 'indcases) in Obj.repr( -# 1408 "cil/src/logic/logic_parser.mly" +# 1415 "cil/src/logic/logic_parser.mly" ( let (id,labels,tvars) = _2 in exit_type_variables_scope (); (id,labels,tvars,_4)::_6 ) -# 6326 "cil/src/logic/logic_parser.ml" +# 6501 "cil/src/logic/logic_parser.ml" : 'indcases)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_identifier) in Obj.repr( -# 1415 "cil/src/logic/logic_parser.mly" +# 1422 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 6333 "cil/src/logic/logic_parser.ml" +# 6508 "cil/src/logic/logic_parser.ml" : 'ne_tvar_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'full_identifier) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ne_tvar_list) in Obj.repr( -# 1416 "cil/src/logic/logic_parser.mly" +# 1423 "cil/src/logic/logic_parser.mly" ( _1 :: _3 ) -# 6341 "cil/src/logic/logic_parser.ml" +# 6516 "cil/src/logic/logic_parser.ml" : 'ne_tvar_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'label_name) in Obj.repr( -# 1420 "cil/src/logic/logic_parser.mly" +# 1427 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 6348 "cil/src/logic/logic_parser.ml" +# 6523 "cil/src/logic/logic_parser.ml" : 'ne_label_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'label_name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ne_label_list) in Obj.repr( -# 1421 "cil/src/logic/logic_parser.mly" +# 1428 "cil/src/logic/logic_parser.mly" ( _1 :: _3 ) -# 6356 "cil/src/logic/logic_parser.ml" +# 6531 "cil/src/logic/logic_parser.ml" : 'ne_label_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'any_identifier) in Obj.repr( -# 1426 "cil/src/logic/logic_parser.mly" +# 1433 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6363 "cil/src/logic/logic_parser.ml" +# 6538 "cil/src/logic/logic_parser.ml" : 'label_name)) ; (fun __caml_parser_env -> Obj.repr( -# 1430 "cil/src/logic/logic_parser.mly" +# 1437 "cil/src/logic/logic_parser.mly" ( [] ) -# 6369 "cil/src/logic/logic_parser.ml" +# 6544 "cil/src/logic/logic_parser.ml" : 'behavior_name_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'ne_behavior_name_list) in Obj.repr( -# 1431 "cil/src/logic/logic_parser.mly" +# 1438 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6376 "cil/src/logic/logic_parser.ml" +# 6551 "cil/src/logic/logic_parser.ml" : 'behavior_name_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'behavior_name) in Obj.repr( -# 1435 "cil/src/logic/logic_parser.mly" +# 1442 "cil/src/logic/logic_parser.mly" ( [_1] ) -# 6383 "cil/src/logic/logic_parser.ml" +# 6558 "cil/src/logic/logic_parser.ml" : 'ne_behavior_name_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'behavior_name) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'ne_behavior_name_list) in Obj.repr( -# 1436 "cil/src/logic/logic_parser.mly" +# 1443 "cil/src/logic/logic_parser.mly" (_1 :: _3) -# 6391 "cil/src/logic/logic_parser.ml" +# 6566 "cil/src/logic/logic_parser.ml" : 'ne_behavior_name_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'any_identifier) in Obj.repr( -# 1440 "cil/src/logic/logic_parser.mly" +# 1447 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6398 "cil/src/logic/logic_parser.ml" +# 6573 "cil/src/logic/logic_parser.ml" : 'behavior_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'identifier_or_typename) in Obj.repr( -# 1444 "cil/src/logic/logic_parser.mly" +# 1451 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6405 "cil/src/logic/logic_parser.ml" +# 6580 "cil/src/logic/logic_parser.ml" : 'any_identifier)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'keyword) in Obj.repr( -# 1445 "cil/src/logic/logic_parser.mly" +# 1452 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6412 "cil/src/logic/logic_parser.ml" +# 6587 "cil/src/logic/logic_parser.ml" : 'any_identifier)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1449 "cil/src/logic/logic_parser.mly" +# 1456 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6419 "cil/src/logic/logic_parser.ml" +# 6594 "cil/src/logic/logic_parser.ml" : 'identifier_or_typename)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1450 "cil/src/logic/logic_parser.mly" +# 1457 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6426 "cil/src/logic/logic_parser.ml" +# 6601 "cil/src/logic/logic_parser.ml" : 'identifier_or_typename)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1454 "cil/src/logic/logic_parser.mly" +# 1461 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6433 "cil/src/logic/logic_parser.ml" +# 6608 "cil/src/logic/logic_parser.ml" : 'identifier)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'identifier) in Obj.repr( -# 1458 "cil/src/logic/logic_parser.mly" +# 1465 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6440 "cil/src/logic/logic_parser.ml" +# 6615 "cil/src/logic/logic_parser.ml" : 'bounded_var)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1460 "cil/src/logic/logic_parser.mly" +# 1467 "cil/src/logic/logic_parser.mly" ( raise (Not_well_formed(loc (), "Type names are not allowed as binding variable")) ) -# 6450 "cil/src/logic/logic_parser.ml" +# 6625 "cil/src/logic/logic_parser.ml" : 'bounded_var)) ; (fun __caml_parser_env -> Obj.repr( -# 1467 "cil/src/logic/logic_parser.mly" +# 1474 "cil/src/logic/logic_parser.mly" ( "case" ) -# 6456 "cil/src/logic/logic_parser.ml" +# 6631 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1468 "cil/src/logic/logic_parser.mly" +# 1475 "cil/src/logic/logic_parser.mly" ( "char" ) -# 6462 "cil/src/logic/logic_parser.ml" +# 6637 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1469 "cil/src/logic/logic_parser.mly" +# 1476 "cil/src/logic/logic_parser.mly" ( "boolean" ) -# 6468 "cil/src/logic/logic_parser.ml" +# 6643 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1470 "cil/src/logic/logic_parser.mly" +# 1477 "cil/src/logic/logic_parser.mly" ( "const" ) -# 6474 "cil/src/logic/logic_parser.ml" +# 6649 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1471 "cil/src/logic/logic_parser.mly" +# 1478 "cil/src/logic/logic_parser.mly" ( "double" ) -# 6480 "cil/src/logic/logic_parser.ml" +# 6655 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1472 "cil/src/logic/logic_parser.mly" +# 1479 "cil/src/logic/logic_parser.mly" ( "else" ) -# 6486 "cil/src/logic/logic_parser.ml" +# 6661 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1473 "cil/src/logic/logic_parser.mly" +# 1480 "cil/src/logic/logic_parser.mly" ( "enum" ) -# 6492 "cil/src/logic/logic_parser.ml" +# 6667 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1474 "cil/src/logic/logic_parser.mly" +# 1481 "cil/src/logic/logic_parser.mly" ( "float" ) -# 6498 "cil/src/logic/logic_parser.ml" +# 6673 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1475 "cil/src/logic/logic_parser.mly" +# 1482 "cil/src/logic/logic_parser.mly" ( "if" ) -# 6504 "cil/src/logic/logic_parser.ml" +# 6679 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1476 "cil/src/logic/logic_parser.mly" +# 1483 "cil/src/logic/logic_parser.mly" ( "int" ) -# 6510 "cil/src/logic/logic_parser.ml" +# 6685 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1477 "cil/src/logic/logic_parser.mly" +# 1484 "cil/src/logic/logic_parser.mly" ( "long" ) -# 6516 "cil/src/logic/logic_parser.ml" +# 6691 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1478 "cil/src/logic/logic_parser.mly" +# 1485 "cil/src/logic/logic_parser.mly" ( "short" ) -# 6522 "cil/src/logic/logic_parser.ml" +# 6697 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1479 "cil/src/logic/logic_parser.mly" +# 1486 "cil/src/logic/logic_parser.mly" ( "signed" ) -# 6528 "cil/src/logic/logic_parser.ml" +# 6703 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1480 "cil/src/logic/logic_parser.mly" +# 1487 "cil/src/logic/logic_parser.mly" ( "sizeof" ) -# 6534 "cil/src/logic/logic_parser.ml" +# 6709 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1481 "cil/src/logic/logic_parser.mly" +# 1488 "cil/src/logic/logic_parser.mly" ( "struct" ) -# 6540 "cil/src/logic/logic_parser.ml" +# 6715 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1482 "cil/src/logic/logic_parser.mly" +# 1489 "cil/src/logic/logic_parser.mly" ( "union" ) -# 6546 "cil/src/logic/logic_parser.ml" +# 6721 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1483 "cil/src/logic/logic_parser.mly" +# 1490 "cil/src/logic/logic_parser.mly" ( "unsigned" ) -# 6552 "cil/src/logic/logic_parser.ml" +# 6727 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1484 "cil/src/logic/logic_parser.mly" +# 1491 "cil/src/logic/logic_parser.mly" ( "void" ) -# 6558 "cil/src/logic/logic_parser.ml" +# 6733 "cil/src/logic/logic_parser.ml" : 'c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1488 "cil/src/logic/logic_parser.mly" +# 1495 "cil/src/logic/logic_parser.mly" ( "for" ) -# 6564 "cil/src/logic/logic_parser.ml" +# 6739 "cil/src/logic/logic_parser.ml" : 'acsl_c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1489 "cil/src/logic/logic_parser.mly" +# 1496 "cil/src/logic/logic_parser.mly" ( "volatile" ) -# 6570 "cil/src/logic/logic_parser.ml" +# 6745 "cil/src/logic/logic_parser.ml" : 'acsl_c_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1493 "cil/src/logic/logic_parser.mly" +# 1500 "cil/src/logic/logic_parser.mly" ( Normal, "normal" ) -# 6576 "cil/src/logic/logic_parser.ml" +# 6751 "cil/src/logic/logic_parser.ml" : 'post_cond)) ; (fun __caml_parser_env -> Obj.repr( -# 1494 "cil/src/logic/logic_parser.mly" +# 1501 "cil/src/logic/logic_parser.mly" ( Exits, "exits" ) -# 6582 "cil/src/logic/logic_parser.ml" +# 6757 "cil/src/logic/logic_parser.ml" : 'post_cond)) ; (fun __caml_parser_env -> Obj.repr( -# 1495 "cil/src/logic/logic_parser.mly" +# 1502 "cil/src/logic/logic_parser.mly" ( Breaks, "breaks" ) -# 6588 "cil/src/logic/logic_parser.ml" +# 6763 "cil/src/logic/logic_parser.ml" : 'post_cond)) ; (fun __caml_parser_env -> Obj.repr( -# 1496 "cil/src/logic/logic_parser.mly" +# 1503 "cil/src/logic/logic_parser.mly" ( Continues, "continues" ) -# 6594 "cil/src/logic/logic_parser.ml" +# 6769 "cil/src/logic/logic_parser.ml" : 'post_cond)) ; (fun __caml_parser_env -> Obj.repr( -# 1497 "cil/src/logic/logic_parser.mly" +# 1504 "cil/src/logic/logic_parser.mly" ( Returns, "returns" ) -# 6600 "cil/src/logic/logic_parser.ml" +# 6775 "cil/src/logic/logic_parser.ml" : 'post_cond)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'post_cond) in Obj.repr( -# 1501 "cil/src/logic/logic_parser.mly" +# 1508 "cil/src/logic/logic_parser.mly" ( snd _1 ) -# 6607 "cil/src/logic/logic_parser.ml" +# 6782 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1502 "cil/src/logic/logic_parser.mly" +# 1509 "cil/src/logic/logic_parser.mly" ( "assigns" ) -# 6613 "cil/src/logic/logic_parser.ml" +# 6788 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1503 "cil/src/logic/logic_parser.mly" +# 1510 "cil/src/logic/logic_parser.mly" ( "behavior" ) -# 6619 "cil/src/logic/logic_parser.ml" +# 6794 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1504 "cil/src/logic/logic_parser.mly" +# 1511 "cil/src/logic/logic_parser.mly" ( "requires" ) -# 6625 "cil/src/logic/logic_parser.ml" +# 6800 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1505 "cil/src/logic/logic_parser.mly" +# 1512 "cil/src/logic/logic_parser.mly" ( "terminates" ) -# 6631 "cil/src/logic/logic_parser.ml" +# 6806 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1506 "cil/src/logic/logic_parser.mly" +# 1513 "cil/src/logic/logic_parser.mly" ( "complete" ) -# 6637 "cil/src/logic/logic_parser.ml" +# 6812 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1507 "cil/src/logic/logic_parser.mly" +# 1514 "cil/src/logic/logic_parser.mly" ( "decreases" ) -# 6643 "cil/src/logic/logic_parser.ml" +# 6818 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1508 "cil/src/logic/logic_parser.mly" +# 1515 "cil/src/logic/logic_parser.mly" ( "disjoint" ) -# 6649 "cil/src/logic/logic_parser.ml" +# 6824 "cil/src/logic/logic_parser.ml" : 'is_acsl_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1512 "cil/src/logic/logic_parser.mly" +# 1519 "cil/src/logic/logic_parser.mly" ( "assert" ) -# 6655 "cil/src/logic/logic_parser.ml" +# 6830 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1513 "cil/src/logic/logic_parser.mly" +# 1520 "cil/src/logic/logic_parser.mly" ( "assumes" ) -# 6661 "cil/src/logic/logic_parser.ml" +# 6836 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1514 "cil/src/logic/logic_parser.mly" +# 1521 "cil/src/logic/logic_parser.mly" ( "global" ) -# 6667 "cil/src/logic/logic_parser.ml" +# 6842 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1515 "cil/src/logic/logic_parser.mly" +# 1522 "cil/src/logic/logic_parser.mly" ( "impact" ) -# 6673 "cil/src/logic/logic_parser.ml" +# 6848 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1516 "cil/src/logic/logic_parser.mly" +# 1523 "cil/src/logic/logic_parser.mly" ( "inductive" ) -# 6679 "cil/src/logic/logic_parser.ml" +# 6854 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1517 "cil/src/logic/logic_parser.mly" +# 1524 "cil/src/logic/logic_parser.mly" ( "invariant" ) -# 6685 "cil/src/logic/logic_parser.ml" +# 6860 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1518 "cil/src/logic/logic_parser.mly" +# 1525 "cil/src/logic/logic_parser.mly" ( "lemma" ) -# 6691 "cil/src/logic/logic_parser.ml" +# 6866 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1519 "cil/src/logic/logic_parser.mly" +# 1526 "cil/src/logic/logic_parser.mly" ( "logic" ) -# 6697 "cil/src/logic/logic_parser.ml" +# 6872 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1520 "cil/src/logic/logic_parser.mly" +# 1527 "cil/src/logic/logic_parser.mly" ( "loop" ) -# 6703 "cil/src/logic/logic_parser.ml" +# 6878 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1521 "cil/src/logic/logic_parser.mly" +# 1528 "cil/src/logic/logic_parser.mly" ( "pragma" ) -# 6709 "cil/src/logic/logic_parser.ml" +# 6884 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1522 "cil/src/logic/logic_parser.mly" +# 1529 "cil/src/logic/logic_parser.mly" ( "predicate" ) -# 6715 "cil/src/logic/logic_parser.ml" +# 6890 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1523 "cil/src/logic/logic_parser.mly" +# 1530 "cil/src/logic/logic_parser.mly" ( "slice" ) -# 6721 "cil/src/logic/logic_parser.ml" +# 6896 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1524 "cil/src/logic/logic_parser.mly" +# 1531 "cil/src/logic/logic_parser.mly" ( "type" ) -# 6727 "cil/src/logic/logic_parser.ml" +# 6902 "cil/src/logic/logic_parser.ml" : 'is_acsl_decl_or_code_annot)) ; (fun __caml_parser_env -> Obj.repr( -# 1528 "cil/src/logic/logic_parser.mly" +# 1532 "cil/src/logic/logic_parser.mly" + ( "model" ) +# 6908 "cil/src/logic/logic_parser.ml" + : 'is_acsl_decl_or_code_annot)) +; (fun __caml_parser_env -> + Obj.repr( +# 1536 "cil/src/logic/logic_parser.mly" ( "axiom" ) -# 6733 "cil/src/logic/logic_parser.ml" +# 6914 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1529 "cil/src/logic/logic_parser.mly" +# 1537 "cil/src/logic/logic_parser.mly" ( "behaviors" ) -# 6739 "cil/src/logic/logic_parser.ml" +# 6920 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1530 "cil/src/logic/logic_parser.mly" +# 1538 "cil/src/logic/logic_parser.mly" ( "integer" ) -# 6745 "cil/src/logic/logic_parser.ml" +# 6926 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1531 "cil/src/logic/logic_parser.mly" +# 1539 "cil/src/logic/logic_parser.mly" ( "label" ) -# 6751 "cil/src/logic/logic_parser.ml" +# 6932 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1532 "cil/src/logic/logic_parser.mly" +# 1540 "cil/src/logic/logic_parser.mly" ( "reads" ) -# 6757 "cil/src/logic/logic_parser.ml" +# 6938 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1533 "cil/src/logic/logic_parser.mly" +# 1541 "cil/src/logic/logic_parser.mly" ( "real" ) -# 6763 "cil/src/logic/logic_parser.ml" +# 6944 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1534 "cil/src/logic/logic_parser.mly" +# 1542 "cil/src/logic/logic_parser.mly" ( "writes" ) -# 6769 "cil/src/logic/logic_parser.ml" +# 6950 "cil/src/logic/logic_parser.ml" : 'is_acsl_other)) ; (fun __caml_parser_env -> Obj.repr( -# 1538 "cil/src/logic/logic_parser.mly" +# 1546 "cil/src/logic/logic_parser.mly" ( "contract" ) -# 6775 "cil/src/logic/logic_parser.ml" +# 6956 "cil/src/logic/logic_parser.ml" : 'is_ext_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1539 "cil/src/logic/logic_parser.mly" +# 1547 "cil/src/logic/logic_parser.mly" ( "function" ) -# 6781 "cil/src/logic/logic_parser.ml" +# 6962 "cil/src/logic/logic_parser.ml" : 'is_ext_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1540 "cil/src/logic/logic_parser.mly" +# 1548 "cil/src/logic/logic_parser.mly" ( "module" ) -# 6787 "cil/src/logic/logic_parser.ml" +# 6968 "cil/src/logic/logic_parser.ml" : 'is_ext_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1541 "cil/src/logic/logic_parser.mly" +# 1549 "cil/src/logic/logic_parser.mly" ( "include" ) -# 6793 "cil/src/logic/logic_parser.ml" +# 6974 "cil/src/logic/logic_parser.ml" : 'is_ext_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1542 "cil/src/logic/logic_parser.mly" +# 1550 "cil/src/logic/logic_parser.mly" ( "at" ) -# 6799 "cil/src/logic/logic_parser.ml" +# 6980 "cil/src/logic/logic_parser.ml" : 'is_ext_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1543 "cil/src/logic/logic_parser.mly" +# 1551 "cil/src/logic/logic_parser.mly" ( "let" ) -# 6805 "cil/src/logic/logic_parser.ml" +# 6986 "cil/src/logic/logic_parser.ml" : 'is_ext_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'c_keyword) in Obj.repr( -# 1547 "cil/src/logic/logic_parser.mly" +# 1555 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6812 "cil/src/logic/logic_parser.ml" +# 6993 "cil/src/logic/logic_parser.ml" : 'keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'acsl_c_keyword) in Obj.repr( -# 1548 "cil/src/logic/logic_parser.mly" +# 1556 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6819 "cil/src/logic/logic_parser.ml" +# 7000 "cil/src/logic/logic_parser.ml" : 'keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'is_ext_spec) in Obj.repr( -# 1549 "cil/src/logic/logic_parser.mly" +# 1557 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6826 "cil/src/logic/logic_parser.ml" +# 7007 "cil/src/logic/logic_parser.ml" : 'keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'is_acsl_spec) in Obj.repr( -# 1550 "cil/src/logic/logic_parser.mly" +# 1558 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6833 "cil/src/logic/logic_parser.ml" +# 7014 "cil/src/logic/logic_parser.ml" : 'keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'is_acsl_decl_or_code_annot) in Obj.repr( -# 1551 "cil/src/logic/logic_parser.mly" +# 1559 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6840 "cil/src/logic/logic_parser.ml" +# 7021 "cil/src/logic/logic_parser.ml" : 'keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'is_acsl_other) in Obj.repr( -# 1552 "cil/src/logic/logic_parser.mly" +# 1560 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6847 "cil/src/logic/logic_parser.ml" +# 7028 "cil/src/logic/logic_parser.ml" : 'keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'full_identifier_or_typename) in Obj.repr( -# 1556 "cil/src/logic/logic_parser.mly" +# 1564 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6854 "cil/src/logic/logic_parser.ml" +# 7035 "cil/src/logic/logic_parser.ml" : 'grammar_extension_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'is_acsl_other) in Obj.repr( -# 1557 "cil/src/logic/logic_parser.mly" +# 1565 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6861 "cil/src/logic/logic_parser.ml" +# 7042 "cil/src/logic/logic_parser.ml" : 'grammar_extension_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'c_keyword) in Obj.repr( -# 1558 "cil/src/logic/logic_parser.mly" +# 1566 "cil/src/logic/logic_parser.mly" ( _1 ) -# 6868 "cil/src/logic/logic_parser.ml" +# 7049 "cil/src/logic/logic_parser.ml" : 'grammar_extension_name)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'is_acsl_spec) in Obj.repr( -# 1566 "cil/src/logic/logic_parser.mly" +# 1574 "cil/src/logic/logic_parser.mly" ( () ) -# 6875 "cil/src/logic/logic_parser.ml" +# 7056 "cil/src/logic/logic_parser.ml" : 'is_spec)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'grammar_extension_name) in Obj.repr( -# 1567 "cil/src/logic/logic_parser.mly" +# 1575 "cil/src/logic/logic_parser.mly" ( () ) -# 6882 "cil/src/logic/logic_parser.ml" +# 7063 "cil/src/logic/logic_parser.ml" : 'is_spec)) ; (fun __caml_parser_env -> Obj.repr( -# 1571 "cil/src/logic/logic_parser.mly" +# 1579 "cil/src/logic/logic_parser.mly" ( () ) -# 6888 "cil/src/logic/logic_parser.ml" +# 7069 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1572 "cil/src/logic/logic_parser.mly" +# 1580 "cil/src/logic/logic_parser.mly" ( () ) -# 6894 "cil/src/logic/logic_parser.ml" +# 7075 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1573 "cil/src/logic/logic_parser.mly" +# 1581 "cil/src/logic/logic_parser.mly" ( () ) -# 6900 "cil/src/logic/logic_parser.ml" +# 7081 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1574 "cil/src/logic/logic_parser.mly" +# 1582 "cil/src/logic/logic_parser.mly" ( () ) -# 6906 "cil/src/logic/logic_parser.ml" +# 7087 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1575 "cil/src/logic/logic_parser.mly" +# 1583 "cil/src/logic/logic_parser.mly" ( () ) -# 6912 "cil/src/logic/logic_parser.ml" +# 7093 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1576 "cil/src/logic/logic_parser.mly" +# 1584 "cil/src/logic/logic_parser.mly" ( () ) -# 6918 "cil/src/logic/logic_parser.ml" +# 7099 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1577 "cil/src/logic/logic_parser.mly" +# 1585 "cil/src/logic/logic_parser.mly" ( () ) -# 6924 "cil/src/logic/logic_parser.ml" +# 7105 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1578 "cil/src/logic/logic_parser.mly" +# 1586 "cil/src/logic/logic_parser.mly" ( () ) -# 6930 "cil/src/logic/logic_parser.ml" +# 7111 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1579 "cil/src/logic/logic_parser.mly" +# 1587 "cil/src/logic/logic_parser.mly" ( () ) -# 6936 "cil/src/logic/logic_parser.ml" +# 7117 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1580 "cil/src/logic/logic_parser.mly" +# 1588 "cil/src/logic/logic_parser.mly" ( () ) -# 6942 "cil/src/logic/logic_parser.ml" +# 7123 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1581 "cil/src/logic/logic_parser.mly" +# 1589 "cil/src/logic/logic_parser.mly" ( () ) -# 6948 "cil/src/logic/logic_parser.ml" +# 7129 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1582 "cil/src/logic/logic_parser.mly" +# 1590 "cil/src/logic/logic_parser.mly" ( () ) -# 6954 "cil/src/logic/logic_parser.ml" +# 7135 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1583 "cil/src/logic/logic_parser.mly" +# 1591 "cil/src/logic/logic_parser.mly" ( () ) -# 6960 "cil/src/logic/logic_parser.ml" +# 7141 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1584 "cil/src/logic/logic_parser.mly" +# 1592 "cil/src/logic/logic_parser.mly" ( () ) -# 6966 "cil/src/logic/logic_parser.ml" +# 7147 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1585 "cil/src/logic/logic_parser.mly" +# 1593 "cil/src/logic/logic_parser.mly" ( () ) -# 6972 "cil/src/logic/logic_parser.ml" +# 7153 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1586 "cil/src/logic/logic_parser.mly" +# 1594 "cil/src/logic/logic_parser.mly" ( () ) -# 6978 "cil/src/logic/logic_parser.ml" +# 7159 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1587 "cil/src/logic/logic_parser.mly" +# 1595 "cil/src/logic/logic_parser.mly" ( () ) -# 6984 "cil/src/logic/logic_parser.ml" +# 7165 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1588 "cil/src/logic/logic_parser.mly" +# 1596 "cil/src/logic/logic_parser.mly" ( () ) -# 6990 "cil/src/logic/logic_parser.ml" +# 7171 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1589 "cil/src/logic/logic_parser.mly" +# 1597 "cil/src/logic/logic_parser.mly" ( () ) -# 6996 "cil/src/logic/logic_parser.ml" +# 7177 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1590 "cil/src/logic/logic_parser.mly" +# 1598 "cil/src/logic/logic_parser.mly" ( () ) -# 7002 "cil/src/logic/logic_parser.ml" +# 7183 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1591 "cil/src/logic/logic_parser.mly" +# 1599 "cil/src/logic/logic_parser.mly" ( () ) -# 7008 "cil/src/logic/logic_parser.ml" +# 7189 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1592 "cil/src/logic/logic_parser.mly" +# 1600 "cil/src/logic/logic_parser.mly" ( () ) -# 7014 "cil/src/logic/logic_parser.ml" +# 7195 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1593 "cil/src/logic/logic_parser.mly" +# 1601 "cil/src/logic/logic_parser.mly" ( () ) -# 7020 "cil/src/logic/logic_parser.ml" +# 7201 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> Obj.repr( -# 1594 "cil/src/logic/logic_parser.mly" +# 1602 "cil/src/logic/logic_parser.mly" + ( () ) +# 7207 "cil/src/logic/logic_parser.ml" + : 'bs_keyword)) +; (fun __caml_parser_env -> + Obj.repr( +# 1603 "cil/src/logic/logic_parser.mly" ( () ) -# 7026 "cil/src/logic/logic_parser.ml" +# 7213 "cil/src/logic/logic_parser.ml" : 'bs_keyword)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'any_identifier) in Obj.repr( -# 1598 "cil/src/logic/logic_parser.mly" +# 1607 "cil/src/logic/logic_parser.mly" ( () ) -# 7033 "cil/src/logic/logic_parser.ml" +# 7220 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'bs_keyword) in Obj.repr( -# 1599 "cil/src/logic/logic_parser.mly" +# 1608 "cil/src/logic/logic_parser.mly" ( () ) -# 7040 "cil/src/logic/logic_parser.ml" +# 7227 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1600 "cil/src/logic/logic_parser.mly" +# 1609 "cil/src/logic/logic_parser.mly" ( () ) -# 7046 "cil/src/logic/logic_parser.ml" +# 7233 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1601 "cil/src/logic/logic_parser.mly" +# 1610 "cil/src/logic/logic_parser.mly" ( () ) -# 7052 "cil/src/logic/logic_parser.ml" +# 7239 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1602 "cil/src/logic/logic_parser.mly" +# 1611 "cil/src/logic/logic_parser.mly" ( () ) -# 7058 "cil/src/logic/logic_parser.ml" +# 7245 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1603 "cil/src/logic/logic_parser.mly" +# 1612 "cil/src/logic/logic_parser.mly" ( () ) -# 7064 "cil/src/logic/logic_parser.ml" +# 7251 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1604 "cil/src/logic/logic_parser.mly" +# 1613 "cil/src/logic/logic_parser.mly" ( () ) -# 7070 "cil/src/logic/logic_parser.ml" +# 7257 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1605 "cil/src/logic/logic_parser.mly" +# 1614 "cil/src/logic/logic_parser.mly" ( () ) -# 7076 "cil/src/logic/logic_parser.ml" +# 7263 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1606 "cil/src/logic/logic_parser.mly" +# 1615 "cil/src/logic/logic_parser.mly" ( () ) -# 7082 "cil/src/logic/logic_parser.ml" +# 7269 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1607 "cil/src/logic/logic_parser.mly" +# 1616 "cil/src/logic/logic_parser.mly" ( () ) -# 7088 "cil/src/logic/logic_parser.ml" +# 7275 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : Logic_ptree.constant) in Obj.repr( -# 1608 "cil/src/logic/logic_parser.mly" +# 1617 "cil/src/logic/logic_parser.mly" ( () ) -# 7095 "cil/src/logic/logic_parser.ml" +# 7282 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 1609 "cil/src/logic/logic_parser.mly" +# 1618 "cil/src/logic/logic_parser.mly" ( () ) -# 7102 "cil/src/logic/logic_parser.ml" +# 7289 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1610 "cil/src/logic/logic_parser.mly" +# 1619 "cil/src/logic/logic_parser.mly" ( () ) -# 7108 "cil/src/logic/logic_parser.ml" +# 7295 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1611 "cil/src/logic/logic_parser.mly" +# 1620 "cil/src/logic/logic_parser.mly" ( () ) -# 7114 "cil/src/logic/logic_parser.ml" +# 7301 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1612 "cil/src/logic/logic_parser.mly" +# 1621 "cil/src/logic/logic_parser.mly" ( () ) -# 7120 "cil/src/logic/logic_parser.ml" +# 7307 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1613 "cil/src/logic/logic_parser.mly" +# 1622 "cil/src/logic/logic_parser.mly" ( () ) -# 7126 "cil/src/logic/logic_parser.ml" +# 7313 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1614 "cil/src/logic/logic_parser.mly" +# 1623 "cil/src/logic/logic_parser.mly" ( () ) -# 7132 "cil/src/logic/logic_parser.ml" +# 7319 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1615 "cil/src/logic/logic_parser.mly" +# 1624 "cil/src/logic/logic_parser.mly" ( () ) -# 7138 "cil/src/logic/logic_parser.ml" +# 7325 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1616 "cil/src/logic/logic_parser.mly" +# 1625 "cil/src/logic/logic_parser.mly" ( () ) -# 7144 "cil/src/logic/logic_parser.ml" +# 7331 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1617 "cil/src/logic/logic_parser.mly" +# 1626 "cil/src/logic/logic_parser.mly" ( () ) -# 7150 "cil/src/logic/logic_parser.ml" +# 7337 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1618 "cil/src/logic/logic_parser.mly" +# 1627 "cil/src/logic/logic_parser.mly" ( () ) -# 7156 "cil/src/logic/logic_parser.ml" +# 7343 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1619 "cil/src/logic/logic_parser.mly" +# 1628 "cil/src/logic/logic_parser.mly" ( () ) -# 7162 "cil/src/logic/logic_parser.ml" +# 7349 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1620 "cil/src/logic/logic_parser.mly" +# 1629 "cil/src/logic/logic_parser.mly" ( () ) -# 7168 "cil/src/logic/logic_parser.ml" +# 7355 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1621 "cil/src/logic/logic_parser.mly" +# 1630 "cil/src/logic/logic_parser.mly" ( () ) -# 7174 "cil/src/logic/logic_parser.ml" +# 7361 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1622 "cil/src/logic/logic_parser.mly" +# 1631 "cil/src/logic/logic_parser.mly" ( () ) -# 7180 "cil/src/logic/logic_parser.ml" +# 7367 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1623 "cil/src/logic/logic_parser.mly" +# 1632 "cil/src/logic/logic_parser.mly" ( () ) -# 7186 "cil/src/logic/logic_parser.ml" +# 7373 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1624 "cil/src/logic/logic_parser.mly" +# 1633 "cil/src/logic/logic_parser.mly" ( () ) -# 7192 "cil/src/logic/logic_parser.ml" +# 7379 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1625 "cil/src/logic/logic_parser.mly" +# 1634 "cil/src/logic/logic_parser.mly" ( () ) -# 7198 "cil/src/logic/logic_parser.ml" +# 7385 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1626 "cil/src/logic/logic_parser.mly" +# 1635 "cil/src/logic/logic_parser.mly" ( () ) -# 7204 "cil/src/logic/logic_parser.ml" +# 7391 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1627 "cil/src/logic/logic_parser.mly" +# 1636 "cil/src/logic/logic_parser.mly" ( () ) -# 7210 "cil/src/logic/logic_parser.ml" +# 7397 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1628 "cil/src/logic/logic_parser.mly" +# 1637 "cil/src/logic/logic_parser.mly" ( () ) -# 7216 "cil/src/logic/logic_parser.ml" +# 7403 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1629 "cil/src/logic/logic_parser.mly" +# 1638 "cil/src/logic/logic_parser.mly" ( () ) -# 7222 "cil/src/logic/logic_parser.ml" +# 7409 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1630 "cil/src/logic/logic_parser.mly" +# 1639 "cil/src/logic/logic_parser.mly" ( () ) -# 7228 "cil/src/logic/logic_parser.ml" +# 7415 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1631 "cil/src/logic/logic_parser.mly" +# 1640 "cil/src/logic/logic_parser.mly" ( () ) -# 7234 "cil/src/logic/logic_parser.ml" +# 7421 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1632 "cil/src/logic/logic_parser.mly" +# 1641 "cil/src/logic/logic_parser.mly" ( () ) -# 7240 "cil/src/logic/logic_parser.ml" +# 7427 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1633 "cil/src/logic/logic_parser.mly" +# 1642 "cil/src/logic/logic_parser.mly" ( () ) -# 7246 "cil/src/logic/logic_parser.ml" +# 7433 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1634 "cil/src/logic/logic_parser.mly" +# 1643 "cil/src/logic/logic_parser.mly" ( () ) -# 7252 "cil/src/logic/logic_parser.ml" +# 7439 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1635 "cil/src/logic/logic_parser.mly" +# 1644 "cil/src/logic/logic_parser.mly" ( () ) -# 7258 "cil/src/logic/logic_parser.ml" +# 7445 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1636 "cil/src/logic/logic_parser.mly" +# 1645 "cil/src/logic/logic_parser.mly" ( () ) -# 7264 "cil/src/logic/logic_parser.ml" +# 7451 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1637 "cil/src/logic/logic_parser.mly" +# 1646 "cil/src/logic/logic_parser.mly" ( () ) -# 7270 "cil/src/logic/logic_parser.ml" +# 7457 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1638 "cil/src/logic/logic_parser.mly" +# 1647 "cil/src/logic/logic_parser.mly" ( () ) -# 7276 "cil/src/logic/logic_parser.ml" +# 7463 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1639 "cil/src/logic/logic_parser.mly" +# 1648 "cil/src/logic/logic_parser.mly" ( () ) -# 7282 "cil/src/logic/logic_parser.ml" +# 7469 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1640 "cil/src/logic/logic_parser.mly" +# 1649 "cil/src/logic/logic_parser.mly" ( () ) -# 7288 "cil/src/logic/logic_parser.ml" +# 7475 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1641 "cil/src/logic/logic_parser.mly" +# 1650 "cil/src/logic/logic_parser.mly" ( () ) -# 7294 "cil/src/logic/logic_parser.ml" +# 7481 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1642 "cil/src/logic/logic_parser.mly" +# 1651 "cil/src/logic/logic_parser.mly" ( () ) -# 7300 "cil/src/logic/logic_parser.ml" +# 7487 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1643 "cil/src/logic/logic_parser.mly" +# 1652 "cil/src/logic/logic_parser.mly" ( () ) -# 7306 "cil/src/logic/logic_parser.ml" +# 7493 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1644 "cil/src/logic/logic_parser.mly" +# 1653 "cil/src/logic/logic_parser.mly" ( () ) -# 7312 "cil/src/logic/logic_parser.ml" +# 7499 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1645 "cil/src/logic/logic_parser.mly" +# 1654 "cil/src/logic/logic_parser.mly" ( () ) -# 7318 "cil/src/logic/logic_parser.ml" +# 7505 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : bool*string) in Obj.repr( -# 1646 "cil/src/logic/logic_parser.mly" +# 1655 "cil/src/logic/logic_parser.mly" ( () ) -# 7325 "cil/src/logic/logic_parser.ml" +# 7512 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> Obj.repr( -# 1647 "cil/src/logic/logic_parser.mly" +# 1656 "cil/src/logic/logic_parser.mly" ( () ) -# 7331 "cil/src/logic/logic_parser.ml" +# 7518 "cil/src/logic/logic_parser.ml" : 'wildcard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'wildcard) in Obj.repr( -# 1651 "cil/src/logic/logic_parser.mly" +# 1660 "cil/src/logic/logic_parser.mly" ( () ) -# 7338 "cil/src/logic/logic_parser.ml" +# 7525 "cil/src/logic/logic_parser.ml" : 'any)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'wildcard) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'any) in Obj.repr( -# 1652 "cil/src/logic/logic_parser.mly" +# 1661 "cil/src/logic/logic_parser.mly" ( () ) -# 7346 "cil/src/logic/logic_parser.ml" +# 7533 "cil/src/logic/logic_parser.ml" : 'any)) (* Entry lexpr_eof *) ; (fun __caml_parser_env -> raise (Parsing.YYexit (Parsing.peek_val __caml_parser_env 0))) @@ -7379,11 +7566,11 @@ let ext_spec (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) = (Parsing.yyparse yytables 4 lexfun lexbuf : Logic_ptree.ext_spec) ;; -# 1656 "cil/src/logic/logic_parser.mly" +# 1665 "cil/src/logic/logic_parser.mly" (* Local Variables: compile-command: "make -C ../../.." End: *) -# 7390 "cil/src/logic/logic_parser.ml" +# 7577 "cil/src/logic/logic_parser.ml" diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_parser.mli frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_parser.mli --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_parser.mli 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_parser.mli 2011-10-10 08:48:48.000000000 +0000 @@ -99,6 +99,7 @@ | LBRACE | RBRACE | GHOST + | MODEL | CASE | VOID | CHAR @@ -121,6 +122,8 @@ | COMPLETE | DISJOINT | TERMINATES + | BIFF + | BIMPLIES | HAT | HATHAT | PIPE @@ -134,6 +137,7 @@ | BSTYPE | WITH | CONST + | INITIALIZED val lexpr_eof : (Lexing.lexbuf -> token) -> Lexing.lexbuf -> Logic_ptree.lexpr diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_parser.mly frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_parser.mly --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_parser.mly 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_parser.mly 2011-10-10 08:40:07.000000000 +0000 @@ -173,15 +173,16 @@ %token EXITS BREAKS CONTINUES RETURNS %token VOLATILE READS WRITES %token LOGIC PREDICATE INDUCTIVE AXIOMATIC AXIOM LEMMA LBRACE RBRACE -%token GHOST CASE +%token GHOST MODEL CASE %token VOID CHAR SIGNED UNSIGNED SHORT LONG DOUBLE STRUCT ENUM UNION %token BSUNION INTER %token LTCOLON COLONGT TYPE BEHAVIOR BEHAVIORS ASSUMES COMPLETE DISJOINT %token TERMINATES -%token HAT HATHAT PIPE TILDE GTGT LTLT +%token BIFF BIMPLIES HAT HATHAT PIPE TILDE GTGT LTLT %token SIZEOF LAMBDA LET %token TYPEOF BSTYPE %token WITH CONST +%token INITIALIZED %right prec_named %nonassoc IDENTIFIER TYPENAME SEPARATED @@ -193,6 +194,8 @@ %left HATHAT %left AND %left PIPE +%left BIFF +%right BIMPLIES %left HAT %left AMP %nonassoc prec_no_rel @@ -271,6 +274,8 @@ | lexpr AMP lexpr { info (PLbinop ($1, Bbw_and, $3)) } | lexpr PIPE lexpr { info (PLbinop ($1, Bbw_or, $3)) } | lexpr HAT lexpr { info (PLbinop ($1, Bbw_xor, $3)) } +| lexpr BIMPLIES lexpr { info (PLbinop (info (PLunop (Ubw_not, $1)), Bbw_or, $3)) } +| lexpr BIFF lexpr { info (PLbinop (info (PLunop (Ubw_not, $1)), Bbw_xor, $3)) } | lexpr QUESTION lexpr COLON2 lexpr %prec prec_question { info (PLif ($1, $3, $5)) } /* both terms and predicates */ @@ -364,6 +369,7 @@ | VALID_INDEX LPAR lexpr COMMA lexpr RPAR { info (PLvalid_index ($3,$5)) } | VALID_RANGE LPAR lexpr COMMA lexpr COMMA lexpr RPAR { info (PLvalid_range ($3,$5,$7)) } +| INITIALIZED LPAR lexpr RPAR { info (PLinitialized ($3)) } | FRESH LPAR lexpr RPAR { info (PLfresh ($3)) } | NULL { info PLnull } | constant { info (PLconstant $1) } @@ -759,7 +765,7 @@ ext_global_clause: | decl { Ext_decl (loc_decl $1) } | EXT_LET any_identifier EQUAL full_lexpr SEMICOLON { Ext_macro ($2, $4) } -| INCLUDE string SEMICOLON { let b,s = $2 in Ext_include(b,s) } +| INCLUDE string SEMICOLON { let b,s = $2 in Ext_include(b,s, loc()) } ; ext_global_specs_opt: @@ -809,23 +815,16 @@ | ext_global_clause { Ext_glob $1 } | ext_at_loop_markup ext_stmt_loop_spec - { Ext_loop_spec($1,$2) } -| ext_at_stmt_markup ext_stmt_specs - { Ext_stmt_spec($1,$2) } -| ext_contract_markup ext_contract - { Ext_spec $2 } -; - -ext_contract: -| contract { let s,_pos = $1 in s } + { Ext_loop_spec($1,$2,loc()) } +| ext_at_stmt_markup ext_stmt_loop_spec + { Ext_stmt_spec($1,$2,loc()) } +| ext_contract_markup contract + { let s,pos = $2 in Ext_spec (s,pos) } ; ext_stmt_loop_spec: | annotation { $1 } -; - -ext_stmt_specs: -| annotation { $1 } +| ext_contract_markup contract { let s, pos = $2 in Acode_annot (pos, AStmtSpec ([],s)) } ; ext_identifier_opt: @@ -842,7 +841,7 @@ ; ext_function_markup: -| FUNCTION ext_identifier COLON { $2 } +| FUNCTION ext_identifier COLON { $2, loc() } ; ext_contract_markup: @@ -1054,17 +1053,13 @@ ; annotation: -| FOR ne_behavior_name_list COLON contract - { - Format.eprintf - "Behavior list is forgotten by the current implementation@."; - Afor_spec (loc(), $2, fst ($4)) - } | loop_annotations { let (b,v,p) = $1 in (* TODO: do better, do not lose the structure ! *) let l = b@v@p in Aloop_annot (loc (), l) } +| FOR ne_behavior_name_list COLON contract + { let s, pos = $4 in Acode_annot (pos, AStmtSpec ($2,s)) } | code_annotation { Acode_annot (loc(),$1) } | code_annotation beg_code_annotation { raise @@ -1222,8 +1217,9 @@ decl: | GLOBAL INVARIANT any_identifier COLON full_lexpr SEMICOLON { LDinvariant ($3, $5) } -| VOLATILE lexpr volatile_opt SEMICOLON { LDvolatile ($2, $3) } +| VOLATILE ne_zones volatile_opt SEMICOLON { LDvolatile ($2, $3) } | type_annot {LDtype_annot $1} +| model_annot {LDmodel_annot $1} | logic_def { $1 } | deprecated_logic_decl { $1 } ; @@ -1252,6 +1248,17 @@ { let typ,name = $5 in{ inv_name = $3; this_name = name; this_type = typ; inv = $8; } } ; +model_annot: +| MODEL type_spec LBRACE full_parameter RBRACE + { let typ,name = $4 in + { model_for_type = $2; model_name = name; model_type = typ; } + } +| MODEL id_as_typename LBRACE full_parameter RBRACE + { let typ,name = $4 in + { model_for_type = $2; model_name = name; model_type = typ; } + } +; + poly_id_type: | full_identifier { enter_type_variables_scope []; ($1,[]) } @@ -1522,6 +1529,7 @@ | PREDICATE { "predicate" } | SLICE { "slice" } | TYPE { "type" } +| MODEL { "model" } ; is_acsl_other: @@ -1591,6 +1599,7 @@ | VALID { () } | VALID_INDEX { () } | VALID_RANGE { () } +| INITIALIZED { () } | WITH { () } ; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_preprocess.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_preprocess.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_preprocess.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_preprocess.ml 2011-10-10 08:48:48.000000000 +0000 @@ -1,4 +1,4 @@ -# 26 "cil/src/logic/logic_preprocess.mll" +# 25 "cil/src/logic/logic_preprocess.mll" open Lexing type state = NORMAL | SLASH | INCOMMENT @@ -26,10 +26,10 @@ let backslash = "__BACKSLASH__" let abort_preprocess reason outfile = - let source = { Log.src_file = !curr_file; - Log.src_line = !curr_line } + let source = {Lexing.dummy_pos with Lexing.pos_fname = !curr_file; + pos_lnum = !curr_line;} in - Cilmsg.error ~source + Kernel.error ~source "Can't preprocess annotation: %s\nAnnotation will be kept as is" reason; Buffer.output_buffer outfile buf @@ -38,7 +38,7 @@ (*Printf.printf "Preprocessing annotation:\n%!"; Buffer.output_buffer stdout buf; print_newline(); *) - let debug = Cilmsg.debug_atleast 3 in + let debug = Kernel.debug_atleast 3 in let (ppname, ppfile) = Filename.open_temp_file "ppannot" ".c" in Buffer.output_buffer ppfile macros; (* NB: the three extra spaces replace the beginning of the annotation @@ -126,11 +126,11 @@ \004\000\001\000\001\000\253\255\252\255\115\000\252\255\014\000\ \254\255\005\000\009\000\007\000\007\000\253\255\095\001\247\255\ \248\255\249\255\250\255\251\255\252\255\024\000\254\255\026\000\ - \255\255\253\255\015\000\253\255\254\255\255\255\141\000\251\255\ - \252\255\000\000\254\255\255\255\253\255\213\000\251\255\252\255\ - \006\000\254\255\255\255\253\255\172\000\252\255\253\255\254\255\ - \255\255\069\001\250\255\251\255\252\255\253\255\254\255\255\255\ - \016\000\254\255\255\255"; + \255\255\253\255\139\000\252\255\253\255\027\000\255\255\254\255\ + \141\000\250\255\251\255\036\000\254\255\255\255\252\255\253\255\ + \213\000\251\255\252\255\005\000\254\255\255\255\253\255\172\000\ + \252\255\253\255\254\255\255\255\069\001\250\255\251\255\252\255\ + \253\255\254\255\255\255\015\000\254\255\255\255"; Lexing.lex_backtrk = "\255\255\255\255\255\255\255\255\006\000\006\000\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ @@ -140,11 +140,11 @@ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\003\000\ \255\255\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\008\000\255\255\008\000\ + \255\255\255\255\255\255\255\255\255\255\003\000\255\255\255\255\ + \255\255\255\255\255\255\005\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\004\000\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\004\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \004\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255"; + \255\255\255\255\255\255\255\255\255\255\255\255"; Lexing.lex_default = "\001\000\000\000\000\000\000\000\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\017\000\ @@ -154,71 +154,71 @@ \255\255\255\255\255\255\000\000\000\000\046\000\000\000\255\255\ \000\000\255\255\255\255\255\255\255\255\000\000\055\000\000\000\ \000\000\000\000\000\000\000\000\000\000\255\255\000\000\255\255\ - \000\000\000\000\067\000\000\000\000\000\000\000\071\000\000\000\ - \000\000\255\255\000\000\000\000\000\000\078\000\000\000\000\000\ - \255\255\000\000\000\000\000\000\085\000\000\000\000\000\000\000\ - \000\000\090\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \097\000\000\000\000\000"; + \000\000\000\000\067\000\000\000\000\000\255\255\000\000\000\000\ + \073\000\000\000\000\000\255\255\000\000\000\000\000\000\000\000\ + \081\000\000\000\000\000\255\255\000\000\000\000\000\000\088\000\ + \000\000\000\000\000\000\000\000\093\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\100\000\000\000\000\000"; Lexing.lex_trans = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\039\000\002\000\008\000\016\000\026\000\049\000\000\000\ \000\000\000\000\000\000\000\000\000\000\026\000\000\000\029\000\ - \000\000\069\000\098\000\000\000\000\000\000\000\000\000\000\000\ - \039\000\000\000\008\000\005\000\026\000\049\000\025\000\076\000\ - \083\000\000\000\000\000\031\000\026\000\000\000\025\000\004\000\ + \000\000\101\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \039\000\000\000\008\000\005\000\026\000\049\000\025\000\086\000\ + \000\000\000\000\000\000\031\000\026\000\000\000\025\000\004\000\ \030\000\008\000\006\000\006\000\006\000\006\000\006\000\006\000\ \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ \006\000\006\000\006\000\006\000\006\000\006\000\044\000\065\000\ - \008\000\064\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \008\000\064\000\071\000\079\000\000\000\000\000\000\000\000\000\ \255\255\028\000\000\000\000\000\000\000\000\000\000\000\000\000\ \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ \006\000\006\000\015\000\016\000\020\000\011\000\010\000\012\000\ \015\000\022\000\013\000\021\000\015\000\024\000\007\000\019\000\ \014\000\023\000\040\000\041\000\042\000\043\000\050\000\009\000\ \051\000\015\000\052\000\053\000\049\000\048\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \078\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ - \018\000\018\000\018\000\049\000\007\000\000\000\000\000\075\000\ + \018\000\018\000\018\000\049\000\007\000\070\000\000\000\077\000\ \000\000\000\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ - \018\000\018\000\018\000\018\000\074\000\000\000\087\000\000\000\ + \018\000\018\000\018\000\018\000\076\000\069\000\090\000\000\000\ \018\000\000\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\000\000\039\000\038\000\000\000\ - \000\000\000\000\047\000\088\000\000\000\016\000\000\000\082\000\ + \000\000\000\000\047\000\091\000\000\000\016\000\000\000\085\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\073\000\000\000\000\000\039\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\036\000\081\000\ + \000\000\075\000\000\000\000\000\039\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\036\000\084\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \003\000\255\255\255\255\018\000\018\000\018\000\018\000\018\000\ - \018\000\018\000\018\000\018\000\018\000\255\255\255\255\068\000\ - \098\000\000\000\000\000\000\000\018\000\018\000\018\000\018\000\ + \018\000\018\000\018\000\018\000\018\000\255\255\255\255\101\000\ + \000\000\000\000\000\000\000\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\255\255\255\255\ - \000\000\080\000\018\000\037\000\018\000\018\000\018\000\018\000\ + \000\000\083\000\018\000\037\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ - \018\000\018\000\018\000\018\000\018\000\018\000\024\000\095\000\ + \018\000\018\000\018\000\018\000\018\000\018\000\024\000\098\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\255\255\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\024\000\000\000\091\000\ - \000\000\062\000\000\000\000\000\092\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\024\000\000\000\094\000\ + \000\000\062\000\000\000\000\000\095\000\000\000\000\000\000\000\ \000\000\000\000\000\000\255\255\000\000\006\000\006\000\006\000\ \006\000\006\000\006\000\006\000\006\000\006\000\006\000\059\000\ - \000\000\056\000\000\000\000\000\000\000\094\000\057\000\000\000\ - \000\000\063\000\000\000\000\000\000\000\072\000\061\000\000\000\ + \000\000\056\000\000\000\000\000\000\000\097\000\057\000\000\000\ + \000\000\063\000\000\000\068\000\000\000\074\000\061\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\060\000\ - \000\000\093\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\086\000\000\000\000\000\000\000\ + \000\000\096\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\089\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\058\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\255\255\000\000\000\000\000\000\ - \000\000\000\000\000\000\255\255\000\000\079\000\000\000\000\000\ + \000\000\000\000\000\000\255\255\000\000\082\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -232,7 +232,7 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\095\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\098\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\255\ @@ -241,62 +241,62 @@ "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\039\000\000\000\005\000\017\000\026\000\049\000\255\255\ \255\255\255\255\255\255\255\255\255\255\006\000\255\255\028\000\ - \255\255\066\000\096\000\255\255\255\255\255\255\255\255\255\255\ - \039\000\255\255\005\000\000\000\026\000\049\000\026\000\073\000\ - \080\000\255\255\255\255\004\000\006\000\255\255\006\000\000\000\ + \255\255\099\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \039\000\255\255\005\000\000\000\026\000\049\000\026\000\083\000\ + \255\255\255\255\255\255\004\000\006\000\255\255\006\000\000\000\ \004\000\008\000\005\000\005\000\005\000\005\000\005\000\005\000\ \005\000\005\000\005\000\005\000\006\000\006\000\006\000\006\000\ \006\000\006\000\006\000\006\000\006\000\006\000\036\000\061\000\ - \008\000\063\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \008\000\063\000\069\000\075\000\255\255\255\255\255\255\255\255\ \025\000\027\000\255\255\255\255\255\255\255\255\255\255\255\255\ \008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\ \008\000\008\000\015\000\015\000\019\000\010\000\005\000\011\000\ \014\000\007\000\012\000\020\000\021\000\023\000\005\000\009\000\ \013\000\022\000\037\000\040\000\041\000\042\000\047\000\005\000\ \050\000\015\000\051\000\052\000\045\000\045\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \075\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\015\000\015\000\015\000\015\000\015\000\015\000\015\000\ - \015\000\015\000\015\000\045\000\008\000\255\255\255\255\070\000\ + \015\000\015\000\015\000\045\000\008\000\066\000\255\255\072\000\ \255\255\255\255\015\000\015\000\015\000\015\000\015\000\015\000\ \015\000\015\000\015\000\015\000\015\000\015\000\015\000\015\000\ \015\000\015\000\015\000\015\000\015\000\015\000\015\000\015\000\ - \015\000\015\000\015\000\015\000\070\000\255\255\084\000\255\255\ + \015\000\015\000\015\000\015\000\072\000\066\000\087\000\255\255\ \015\000\255\255\015\000\015\000\015\000\015\000\015\000\015\000\ \015\000\015\000\015\000\015\000\015\000\015\000\015\000\015\000\ \015\000\015\000\015\000\015\000\015\000\015\000\015\000\015\000\ \015\000\015\000\015\000\015\000\255\255\034\000\034\000\255\255\ - \255\255\255\255\045\000\084\000\255\255\018\000\255\255\077\000\ + \255\255\255\255\045\000\087\000\255\255\018\000\255\255\080\000\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\070\000\255\255\255\255\034\000\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\034\000\077\000\ + \255\255\072\000\255\255\255\255\034\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\034\000\080\000\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \000\000\030\000\017\000\018\000\018\000\018\000\018\000\018\000\ - \018\000\018\000\018\000\018\000\018\000\028\000\031\000\066\000\ - \096\000\255\255\255\255\255\255\018\000\018\000\018\000\018\000\ + \018\000\018\000\018\000\018\000\018\000\028\000\031\000\099\000\ + \255\255\255\255\255\255\255\255\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\025\000\027\000\ - \255\255\077\000\018\000\034\000\018\000\018\000\018\000\018\000\ + \255\255\080\000\018\000\034\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\ - \018\000\018\000\018\000\018\000\018\000\018\000\024\000\089\000\ + \018\000\018\000\018\000\018\000\018\000\018\000\024\000\092\000\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\015\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\024\000\255\255\089\000\ - \255\255\054\000\255\255\255\255\089\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\024\000\255\255\092\000\ + \255\255\054\000\255\255\255\255\092\000\255\255\255\255\255\255\ \255\255\255\255\255\255\045\000\255\255\024\000\024\000\024\000\ \024\000\024\000\024\000\024\000\024\000\024\000\024\000\054\000\ - \255\255\054\000\255\255\255\255\255\255\089\000\054\000\255\255\ - \255\255\054\000\255\255\255\255\255\255\070\000\054\000\255\255\ + \255\255\054\000\255\255\255\255\255\255\092\000\054\000\255\255\ + \255\255\054\000\255\255\066\000\255\255\072\000\054\000\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\054\000\ - \255\255\089\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\084\000\255\255\255\255\255\255\ + \255\255\092\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\087\000\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\054\000\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\034\000\255\255\255\255\255\255\ - \255\255\255\255\255\255\018\000\255\255\077\000\255\255\255\255\ + \255\255\255\255\255\255\018\000\255\255\080\000\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ @@ -310,7 +310,7 @@ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\089\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\092\000\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\054\000\ @@ -328,7 +328,7 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000"; Lexing.lex_backtrk_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -342,7 +342,7 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000"; Lexing.lex_default_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -356,7 +356,7 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000"; Lexing.lex_trans_code = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\001\000\009\000\000\000\000\000\000\000\000\000\000\000\ @@ -494,16 +494,16 @@ } let rec main cpp outfile lexbuf = -lexbuf.Lexing.lex_mem <- Array.create 10 (-1) ; __ocaml_lex_main_rec cpp outfile lexbuf 0 + lexbuf.Lexing.lex_mem <- Array.create 10 (-1) ; __ocaml_lex_main_rec cpp outfile lexbuf 0 and __ocaml_lex_main_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.new_engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> let -# 144 "cil/src/logic/logic_preprocess.mll" +# 143 "cil/src/logic/logic_preprocess.mll" m # 505 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_mem.(0) lexbuf.Lexing.lex_mem.(1) in -# 146 "cil/src/logic/logic_preprocess.mll" +# 145 "cil/src/logic/logic_preprocess.mll" ( if not (List.mem m blacklisted_macros) then Buffer.add_string macros (lexeme lexbuf); @@ -515,16 +515,16 @@ | 1 -> let -# 153 "cil/src/logic/logic_preprocess.mll" +# 152 "cil/src/logic/logic_preprocess.mll" line # 521 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_mem.(0) lexbuf.Lexing.lex_mem.(1) and -# 154 "cil/src/logic/logic_preprocess.mll" +# 153 "cil/src/logic/logic_preprocess.mll" file # 526 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_mem.(2) lexbuf.Lexing.lex_mem.(3) in -# 155 "cil/src/logic/logic_preprocess.mll" +# 154 "cil/src/logic/logic_preprocess.mll" ( (try curr_line := (int_of_string line) -1 with Failure "int_of_string" -> curr_line:= -1); @@ -537,11 +537,11 @@ | 2 -> let -# 163 "cil/src/logic/logic_preprocess.mll" +# 162 "cil/src/logic/logic_preprocess.mll" c # 543 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf (lexbuf.Lexing.lex_start_pos + 2) in -# 163 "cil/src/logic/logic_preprocess.mll" +# 162 "cil/src/logic/logic_preprocess.mll" ( if c = !Clexer.annot_char then begin is_newline:=CHAR; @@ -558,11 +558,11 @@ | 3 -> let -# 175 "cil/src/logic/logic_preprocess.mll" +# 174 "cil/src/logic/logic_preprocess.mll" c # 564 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf (lexbuf.Lexing.lex_start_pos + 2) in -# 175 "cil/src/logic/logic_preprocess.mll" +# 174 "cil/src/logic/logic_preprocess.mll" ( if c = !Clexer.annot_char then begin Buffer.clear buf; @@ -582,12 +582,12 @@ # 583 "cil/src/logic/logic_preprocess.ml" | 4 -> -# 191 "cil/src/logic/logic_preprocess.mll" +# 190 "cil/src/logic/logic_preprocess.mll" ( flush outfile ) # 588 "cil/src/logic/logic_preprocess.ml" | 5 -> -# 192 "cil/src/logic/logic_preprocess.mll" +# 191 "cil/src/logic/logic_preprocess.mll" ( make_newline (); output_char outfile '\n'; main cpp outfile lexbuf ) @@ -595,11 +595,11 @@ | 6 -> let -# 195 "cil/src/logic/logic_preprocess.mll" +# 194 "cil/src/logic/logic_preprocess.mll" c # 601 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 195 "cil/src/logic/logic_preprocess.mll" +# 194 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char beg_of_line ' '; output_char outfile c; main cpp outfile lexbuf ) @@ -608,23 +608,23 @@ | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_main_rec cpp outfile lexbuf __ocaml_lex_state and maybe_ghost cpp outfile lexbuf = - __ocaml_lex_maybe_ghost_rec cpp outfile lexbuf 34 + __ocaml_lex_maybe_ghost_rec cpp outfile lexbuf 34 and __ocaml_lex_maybe_ghost_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> let -# 200 "cil/src/logic/logic_preprocess.mll" +# 199 "cil/src/logic/logic_preprocess.mll" space # 619 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in -# 200 "cil/src/logic/logic_preprocess.mll" +# 199 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_string buf space; maybe_ghost cpp outfile lexbuf ) # 625 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 203 "cil/src/logic/logic_preprocess.mll" +# 202 "cil/src/logic/logic_preprocess.mll" ( is_newline := NEWLINE; incr curr_line; @@ -634,7 +634,7 @@ # 635 "cil/src/logic/logic_preprocess.ml" | 2 -> -# 210 "cil/src/logic/logic_preprocess.mll" +# 209 "cil/src/logic/logic_preprocess.mll" ( is_ghost := true; Buffer.add_string buf " "; annot cpp outfile lexbuf @@ -642,40 +642,40 @@ # 643 "cil/src/logic/logic_preprocess.ml" | 3 -> -# 215 "cil/src/logic/logic_preprocess.mll" +# 214 "cil/src/logic/logic_preprocess.mll" ( main cpp outfile lexbuf ) # 648 "cil/src/logic/logic_preprocess.ml" | 4 -> let -# 216 "cil/src/logic/logic_preprocess.mll" +# 215 "cil/src/logic/logic_preprocess.mll" c # 654 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 216 "cil/src/logic/logic_preprocess.mll" +# 215 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf c; is_ghost:=false; annot cpp outfile lexbuf) # 658 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_maybe_ghost_rec cpp outfile lexbuf __ocaml_lex_state and maybe_oneline_ghost cpp outfile lexbuf = - __ocaml_lex_maybe_oneline_ghost_rec cpp outfile lexbuf 45 + __ocaml_lex_maybe_oneline_ghost_rec cpp outfile lexbuf 45 and __ocaml_lex_maybe_oneline_ghost_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> let -# 218 "cil/src/logic/logic_preprocess.mll" +# 217 "cil/src/logic/logic_preprocess.mll" space # 670 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in -# 218 "cil/src/logic/logic_preprocess.mll" +# 217 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_string buf space; maybe_oneline_ghost cpp outfile lexbuf ) # 676 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 221 "cil/src/logic/logic_preprocess.mll" +# 220 "cil/src/logic/logic_preprocess.mll" ( incr curr_line; main cpp outfile lexbuf @@ -683,7 +683,7 @@ # 684 "cil/src/logic/logic_preprocess.ml" | 2 -> -# 226 "cil/src/logic/logic_preprocess.mll" +# 225 "cil/src/logic/logic_preprocess.mll" ( is_ghost := true; Buffer.add_string buf " "; oneline_annot cpp outfile lexbuf @@ -692,11 +692,11 @@ | 3 -> let -# 230 "cil/src/logic/logic_preprocess.mll" +# 229 "cil/src/logic/logic_preprocess.mll" c # 698 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 231 "cil/src/logic/logic_preprocess.mll" +# 230 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf c; is_ghost:=false; @@ -707,16 +707,16 @@ | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_maybe_oneline_ghost_rec cpp outfile lexbuf __ocaml_lex_state and annot cpp outfile lexbuf = - __ocaml_lex_annot_rec cpp outfile lexbuf 54 + __ocaml_lex_annot_rec cpp outfile lexbuf 54 and __ocaml_lex_annot_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 237 "cil/src/logic/logic_preprocess.mll" +# 236 "cil/src/logic/logic_preprocess.mll" ( preprocess_annot cpp outfile; main cpp outfile lexbuf ) # 717 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 238 "cil/src/logic/logic_preprocess.mll" +# 237 "cil/src/logic/logic_preprocess.mll" ( is_newline := NEWLINE; incr curr_line; Buffer.add_char buf '\n'; @@ -724,13 +724,13 @@ # 725 "cil/src/logic/logic_preprocess.ml" | 2 -> -# 242 "cil/src/logic/logic_preprocess.mll" +# 241 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_string buf "//"; annot_comment cpp outfile lexbuf ) # 731 "cil/src/logic/logic_preprocess.ml" | 3 -> -# 244 "cil/src/logic/logic_preprocess.mll" +# 243 "cil/src/logic/logic_preprocess.mll" ( if !is_newline = NEWLINE then is_newline:=SPACE; Buffer.add_char buf ' '; @@ -738,34 +738,34 @@ # 739 "cil/src/logic/logic_preprocess.ml" | 4 -> -# 248 "cil/src/logic/logic_preprocess.mll" +# 247 "cil/src/logic/logic_preprocess.mll" ( if !is_newline = NEWLINE then is_newline:=SPACE; Buffer.add_char buf ' '; annot cpp outfile lexbuf ) # 746 "cil/src/logic/logic_preprocess.ml" | 5 -> -# 255 "cil/src/logic/logic_preprocess.mll" +# 254 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_string buf backslash; annot cpp outfile lexbuf ) # 751 "cil/src/logic/logic_preprocess.ml" | 6 -> -# 256 "cil/src/logic/logic_preprocess.mll" +# 255 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf '\''; char annot cpp outfile lexbuf ) # 756 "cil/src/logic/logic_preprocess.ml" | 7 -> -# 257 "cil/src/logic/logic_preprocess.mll" +# 256 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf '"'; string annot cpp outfile lexbuf ) # 761 "cil/src/logic/logic_preprocess.ml" | 8 -> let -# 258 "cil/src/logic/logic_preprocess.mll" +# 257 "cil/src/logic/logic_preprocess.mll" c # 767 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 258 "cil/src/logic/logic_preprocess.mll" +# 257 "cil/src/logic/logic_preprocess.mll" ( is_newline := CHAR; Buffer.add_char buf c; annot cpp outfile lexbuf ) # 772 "cil/src/logic/logic_preprocess.ml" @@ -773,35 +773,40 @@ | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_annot_rec cpp outfile lexbuf __ocaml_lex_state and annot_comment cpp outfile lexbuf = - __ocaml_lex_annot_comment_rec cpp outfile lexbuf 66 + __ocaml_lex_annot_comment_rec cpp outfile lexbuf 66 and __ocaml_lex_annot_comment_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 262 "cil/src/logic/logic_preprocess.mll" +# 261 "cil/src/logic/logic_preprocess.mll" ( incr curr_line; is_newline:=NEWLINE; Buffer.add_char buf '\n'; annot cpp outfile lexbuf ) # 785 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 265 "cil/src/logic/logic_preprocess.mll" - ( abort_preprocess "eof in the middle of a comment" outfile ) +# 264 "cil/src/logic/logic_preprocess.mll" + ( preprocess_annot cpp outfile; main cpp outfile lexbuf ) # 790 "cil/src/logic/logic_preprocess.ml" | 2 -> +# 265 "cil/src/logic/logic_preprocess.mll" + ( abort_preprocess "eof in the middle of a comment" outfile ) +# 795 "cil/src/logic/logic_preprocess.ml" + + | 3 -> let # 266 "cil/src/logic/logic_preprocess.mll" c -# 796 "cil/src/logic/logic_preprocess.ml" +# 801 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in # 266 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf c; annot_comment cpp outfile lexbuf ) -# 800 "cil/src/logic/logic_preprocess.ml" +# 805 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_annot_comment_rec cpp outfile lexbuf __ocaml_lex_state and char annot cpp outfile lexbuf = - __ocaml_lex_char_rec annot cpp outfile lexbuf 70 + __ocaml_lex_char_rec annot cpp outfile lexbuf 72 and __ocaml_lex_char_rec annot cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> @@ -809,84 +814,90 @@ ( incr curr_line; is_newline:=NEWLINE; Buffer.add_char buf '\n'; char annot cpp outfile lexbuf ) -# 813 "cil/src/logic/logic_preprocess.ml" +# 818 "cil/src/logic/logic_preprocess.ml" | 1 -> # 273 "cil/src/logic/logic_preprocess.mll" ( is_newline:=CHAR; Buffer.add_char buf '\''; annot cpp outfile lexbuf ) -# 819 "cil/src/logic/logic_preprocess.ml" +# 824 "cil/src/logic/logic_preprocess.ml" | 2 -> # 275 "cil/src/logic/logic_preprocess.mll" ( is_newline:=CHAR; Buffer.add_string buf "\\'"; char annot cpp outfile lexbuf ) -# 825 "cil/src/logic/logic_preprocess.ml" +# 830 "cil/src/logic/logic_preprocess.ml" | 3 -> # 277 "cil/src/logic/logic_preprocess.mll" - ( abort_preprocess "eof while parsing a char literal" outfile ) -# 830 "cil/src/logic/logic_preprocess.ml" + ( is_newline:=CHAR; + Buffer.add_string buf "\\\\"; char annot cpp outfile lexbuf ) +# 836 "cil/src/logic/logic_preprocess.ml" | 4 -> +# 279 "cil/src/logic/logic_preprocess.mll" + ( abort_preprocess "eof while parsing a char literal" outfile ) +# 841 "cil/src/logic/logic_preprocess.ml" + + | 5 -> let -# 278 "cil/src/logic/logic_preprocess.mll" +# 280 "cil/src/logic/logic_preprocess.mll" c -# 836 "cil/src/logic/logic_preprocess.ml" +# 847 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 278 "cil/src/logic/logic_preprocess.mll" +# 280 "cil/src/logic/logic_preprocess.mll" ( is_newline:=CHAR; Buffer.add_char buf c; char annot cpp outfile lexbuf ) -# 841 "cil/src/logic/logic_preprocess.ml" +# 852 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_char_rec annot cpp outfile lexbuf __ocaml_lex_state and string annot cpp outfile lexbuf = - __ocaml_lex_string_rec annot cpp outfile lexbuf 77 + __ocaml_lex_string_rec annot cpp outfile lexbuf 80 and __ocaml_lex_string_rec annot cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 282 "cil/src/logic/logic_preprocess.mll" +# 284 "cil/src/logic/logic_preprocess.mll" ( incr curr_line; is_newline:=NEWLINE; Buffer.add_char buf '\n'; string annot cpp outfile lexbuf ) -# 854 "cil/src/logic/logic_preprocess.ml" +# 865 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 285 "cil/src/logic/logic_preprocess.mll" +# 287 "cil/src/logic/logic_preprocess.mll" ( is_newline:=CHAR; Buffer.add_char buf '"'; annot cpp outfile lexbuf ) -# 859 "cil/src/logic/logic_preprocess.ml" +# 870 "cil/src/logic/logic_preprocess.ml" | 2 -> -# 286 "cil/src/logic/logic_preprocess.mll" +# 288 "cil/src/logic/logic_preprocess.mll" ( is_newline:=CHAR; Buffer.add_string buf "\\\""; string annot cpp outfile lexbuf ) -# 865 "cil/src/logic/logic_preprocess.ml" +# 876 "cil/src/logic/logic_preprocess.ml" | 3 -> -# 288 "cil/src/logic/logic_preprocess.mll" +# 290 "cil/src/logic/logic_preprocess.mll" ( abort_preprocess "eof while parsing a string literal" outfile ) -# 870 "cil/src/logic/logic_preprocess.ml" +# 881 "cil/src/logic/logic_preprocess.ml" | 4 -> let -# 289 "cil/src/logic/logic_preprocess.mll" +# 291 "cil/src/logic/logic_preprocess.mll" c -# 876 "cil/src/logic/logic_preprocess.ml" +# 887 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 289 "cil/src/logic/logic_preprocess.mll" +# 291 "cil/src/logic/logic_preprocess.mll" ( is_newline:=CHAR; Buffer.add_char buf c; string annot cpp outfile lexbuf ) -# 881 "cil/src/logic/logic_preprocess.ml" +# 892 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_string_rec annot cpp outfile lexbuf __ocaml_lex_state and comment cpp outfile c lexbuf = - __ocaml_lex_comment_rec cpp outfile c lexbuf 84 + __ocaml_lex_comment_rec cpp outfile c lexbuf 87 and __ocaml_lex_comment_rec cpp outfile c lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 294 "cil/src/logic/logic_preprocess.mll" +# 296 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char beg_of_line ' '; output_string outfile (lexeme lexbuf); @@ -895,104 +906,104 @@ else comment cpp outfile '/' lexbuf ) -# 899 "cil/src/logic/logic_preprocess.ml" +# 910 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 302 "cil/src/logic/logic_preprocess.mll" +# 304 "cil/src/logic/logic_preprocess.mll" ( make_newline (); output_char outfile '\n'; comment cpp outfile '\n' lexbuf ) -# 905 "cil/src/logic/logic_preprocess.ml" +# 916 "cil/src/logic/logic_preprocess.ml" | 2 -> -# 304 "cil/src/logic/logic_preprocess.mll" +# 306 "cil/src/logic/logic_preprocess.mll" ( abort_preprocess "eof while parsing C comment" outfile) -# 910 "cil/src/logic/logic_preprocess.ml" +# 921 "cil/src/logic/logic_preprocess.ml" | 3 -> let -# 305 "cil/src/logic/logic_preprocess.mll" +# 307 "cil/src/logic/logic_preprocess.mll" c -# 916 "cil/src/logic/logic_preprocess.ml" +# 927 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 305 "cil/src/logic/logic_preprocess.mll" +# 307 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char beg_of_line ' '; output_char outfile c; comment cpp outfile c lexbuf) -# 923 "cil/src/logic/logic_preprocess.ml" +# 934 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_comment_rec cpp outfile c lexbuf __ocaml_lex_state and oneline_annot cpp outfile lexbuf = - __ocaml_lex_oneline_annot_rec cpp outfile lexbuf 89 + __ocaml_lex_oneline_annot_rec cpp outfile lexbuf 92 and __ocaml_lex_oneline_annot_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 311 "cil/src/logic/logic_preprocess.mll" +# 313 "cil/src/logic/logic_preprocess.mll" ( incr curr_line; preprocess_annot cpp outfile; main cpp outfile lexbuf ) -# 937 "cil/src/logic/logic_preprocess.ml" +# 948 "cil/src/logic/logic_preprocess.ml" | 1 -> -# 315 "cil/src/logic/logic_preprocess.mll" +# 317 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf ' '; oneline_annot cpp outfile lexbuf ) -# 942 "cil/src/logic/logic_preprocess.ml" +# 953 "cil/src/logic/logic_preprocess.ml" | 2 -> -# 316 "cil/src/logic/logic_preprocess.mll" +# 318 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_string buf backslash; oneline_annot cpp outfile lexbuf ) -# 947 "cil/src/logic/logic_preprocess.ml" +# 958 "cil/src/logic/logic_preprocess.ml" | 3 -> -# 317 "cil/src/logic/logic_preprocess.mll" +# 319 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf '\''; char oneline_annot cpp outfile lexbuf ) -# 952 "cil/src/logic/logic_preprocess.ml" +# 963 "cil/src/logic/logic_preprocess.ml" | 4 -> -# 318 "cil/src/logic/logic_preprocess.mll" +# 320 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf '"'; string oneline_annot cpp outfile lexbuf ) -# 957 "cil/src/logic/logic_preprocess.ml" +# 968 "cil/src/logic/logic_preprocess.ml" | 5 -> let -# 319 "cil/src/logic/logic_preprocess.mll" +# 321 "cil/src/logic/logic_preprocess.mll" c -# 963 "cil/src/logic/logic_preprocess.ml" +# 974 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 319 "cil/src/logic/logic_preprocess.mll" +# 321 "cil/src/logic/logic_preprocess.mll" ( Buffer.add_char buf c; oneline_annot cpp outfile lexbuf ) -# 967 "cil/src/logic/logic_preprocess.ml" +# 978 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_oneline_annot_rec cpp outfile lexbuf __ocaml_lex_state and oneline_comment cpp outfile lexbuf = - __ocaml_lex_oneline_comment_rec cpp outfile lexbuf 96 + __ocaml_lex_oneline_comment_rec cpp outfile lexbuf 99 and __ocaml_lex_oneline_comment_rec cpp outfile lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 324 "cil/src/logic/logic_preprocess.mll" +# 326 "cil/src/logic/logic_preprocess.mll" ( make_newline(); output_string outfile (lexeme lexbuf); main cpp outfile lexbuf) -# 980 "cil/src/logic/logic_preprocess.ml" +# 991 "cil/src/logic/logic_preprocess.ml" | 1 -> let -# 327 "cil/src/logic/logic_preprocess.mll" +# 329 "cil/src/logic/logic_preprocess.mll" c -# 986 "cil/src/logic/logic_preprocess.ml" +# 997 "cil/src/logic/logic_preprocess.ml" = Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in -# 327 "cil/src/logic/logic_preprocess.mll" +# 329 "cil/src/logic/logic_preprocess.mll" ( output_char outfile c; oneline_comment cpp outfile lexbuf) -# 990 "cil/src/logic/logic_preprocess.ml" +# 1001 "cil/src/logic/logic_preprocess.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_oneline_comment_rec cpp outfile lexbuf __ocaml_lex_state ;; -# 329 "cil/src/logic/logic_preprocess.mll" +# 331 "cil/src/logic/logic_preprocess.mll" let file cpp filename = reset (); @@ -1007,4 +1018,4 @@ close_out ppfile; ppname -# 1011 "cil/src/logic/logic_preprocess.ml" +# 1022 "cil/src/logic/logic_preprocess.ml" diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_preprocess.mll frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_preprocess.mll --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_preprocess.mll 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_preprocess.mll 2011-10-10 08:40:07.000000000 +0000 @@ -22,7 +22,6 @@ (* *) (**************************************************************************) -(*$Id: logic_preprocess.mll,v 1.20 2008-11-20 07:44:31 uid562 Exp $*) { open Lexing type state = NORMAL | SLASH | INCOMMENT @@ -50,10 +49,10 @@ let backslash = "__BACKSLASH__" let abort_preprocess reason outfile = - let source = { Log.src_file = !curr_file; - Log.src_line = !curr_line } + let source = {Lexing.dummy_pos with Lexing.pos_fname = !curr_file; + pos_lnum = !curr_line;} in - Cilmsg.error ~source + Kernel.error ~source "Can't preprocess annotation: %s\nAnnotation will be kept as is" reason; Buffer.output_buffer outfile buf @@ -62,7 +61,7 @@ (*Printf.printf "Preprocessing annotation:\n%!"; Buffer.output_buffer stdout buf; print_newline(); *) - let debug = Cilmsg.debug_atleast 3 in + let debug = Kernel.debug_atleast 3 in let (ppname, ppfile) = Filename.open_temp_file "ppannot" ".c" in Buffer.output_buffer ppfile macros; (* NB: the three extra spaces replace the beginning of the annotation @@ -262,6 +261,7 @@ | '\n' { incr curr_line; is_newline:=NEWLINE; Buffer.add_char buf '\n'; annot cpp outfile lexbuf } + | "*/" { preprocess_annot cpp outfile; main cpp outfile lexbuf } | eof { abort_preprocess "eof in the middle of a comment" outfile } | _ as c { Buffer.add_char buf c; annot_comment cpp outfile lexbuf } @@ -274,6 +274,8 @@ Buffer.add_char buf '\''; annot cpp outfile lexbuf } | "\\'" { is_newline:=CHAR; Buffer.add_string buf "\\'"; char annot cpp outfile lexbuf } + | "\\\\" { is_newline:=CHAR; + Buffer.add_string buf "\\\\"; char annot cpp outfile lexbuf } | eof { abort_preprocess "eof while parsing a char literal" outfile } | _ as c { is_newline:=CHAR; Buffer.add_char buf c; char annot cpp outfile lexbuf } diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_print.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_print.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_print.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_print.ml 2011-10-10 08:40:07.000000000 +0000 @@ -29,7 +29,7 @@ open Escape let print_constant fmt = function - IntConstant s -> pp_print_string fmt s + | IntConstant s -> pp_print_string fmt s | FloatConstant s -> pp_print_string fmt s | StringConstant s -> fprintf fmt "\"%s\"" s | WStringConstant s -> fprintf fmt "\"%s\"" s @@ -42,11 +42,13 @@ match typ with LTvoid -> fprintf fmt "void%t" pname | LTinteger -> - let res = if !Cil.print_utf8 then Utf8_logic.integer else "integer" in - fprintf fmt "%s%t" res pname + fprintf fmt "%s%t" + (if Kernel.Unicode.get () then Utf8_logic.integer else "integer") + pname | LTreal -> - let res = if !Cil.print_utf8 then Utf8_logic.real else "real" in - fprintf fmt "%s%t" res pname + fprintf fmt "%s%t" + (if Kernel.Unicode.get () then Utf8_logic.real else "real") + pname | LTint i -> fprintf fmt "%a%t" Cil.d_ikind i pname | LTfloat f -> fprintf fmt "%a%t" Cil.d_fkind f pname | LTarray (t,c) -> @@ -118,7 +120,7 @@ | PLsizeof _ | PLsizeofE _ -> 20 | PLapp _ | PLold _ | PLat _ | PLbase_addr _ | PLblock_length _ | PLupdate _ | PLinitField _ | PLinitIndex _ - | PLvalid _ | PLvalid_index _ | PLvalid_range _ + | PLvalid _ | PLvalid_index _ | PLvalid_range _ | PLinitialized _ | PLseparated _ | PLfresh _ | PLsubtype _ | PLunion _ | PLinter _ -> 10 | PLvar _ | PLconstant _ | PLresult | PLnull | PLtypeof _ | PLtype _ | PLfalse | PLtrue | PLcomprehension _ | PLempty | PLsingleton _ -> 0 @@ -127,21 +129,21 @@ | PLpathField s -> fprintf fmt ".%s" s | PLpathIndex i -> fprintf fmt "[@[%a@]]" print_lexpr i -and print_path_val fmt (path, v) = +and print_path_val fmt (path, v) = match v with - | PLupdateTerm e -> - fprintf fmt "@[%a@ =@ %a@]" - (pp_list ~sep:"@;" print_path_elt) path print_lexpr e - | PLupdateCont path_val_list -> + | PLupdateTerm e -> + fprintf fmt "@[%a@ =@ %a@]" + (pp_list ~sep:"@;" print_path_elt) path print_lexpr e + | PLupdateCont path_val_list -> fprintf fmt "{ \\with %a@ }" (pp_list ~sep:",@ " print_path_val) path_val_list and print_init_index fmt (i,v) = print_path_val fmt ([PLpathIndex i], PLupdateTerm v) - + and print_init_field fmt (s,v) = print_path_val fmt ([PLpathField s], PLupdateTerm v) - + and print_lexpr fmt e = print_lexpr_level 100 fmt e and print_lexpr_level n fmt e = @@ -229,6 +231,8 @@ | PLvalid_range (e,i1,i2) -> fprintf fmt "\\valid_range(@;@[%a,@ %a, %a@]@;)" print_lexpr_plain e print_lexpr_plain i1 print_lexpr_plain i2 + | PLinitialized e -> + fprintf fmt "\\initialized(@;@[%a@]@;)" print_lexpr_plain e | PLseparated l -> fprintf fmt "\\separated(@;@[%a@]@;)" (pp_list ~sep:",@ " print_lexpr_plain) l @@ -267,6 +271,12 @@ ty.inv_name (print_logic_type None) ty.this_type ty.this_name print_lexpr ty.inv +let print_model_annot fmt ty = + fprintf fmt "@[model@ %a {@;@[%a@ %s]@;}@ @]" + (print_logic_type None) ty.model_for_type + (print_logic_type None) ty.model_type + ty.model_name + let rec print_decl fmt d = match d.decl_node with | LDlogic_def(name,labels,tvar,rt,prms,body) -> @@ -323,27 +333,28 @@ | LDinvariant (s,e) -> fprintf fmt "@[<2>invariant@ %s:@ %a;@]" s print_lexpr e | LDtype_annot ty -> print_type_annot fmt ty - | LDvolatile(loc,(read,write)) -> + | LDmodel_annot ty -> print_model_annot fmt ty + | LDvolatile(tsets,(read,write)) -> fprintf fmt "@[<2>volatile@ %a%a%a;@]" - print_lexpr loc + (pp_list ~pre:"@[" ~sep:",@ " ~suf:"@]" print_lexpr) tsets (pp_opt ~pre:"@ reads@ " pp_print_string) read (pp_opt ~pre:"@ writes@ " pp_print_string) write let print_deps fmt deps = match deps with FromAny -> () - | From l -> + | From l -> pp_list ~pre:"@ @[<2>\\from@ " ~sep:",@ " ~suf:"@]" print_lexpr fmt l let print_assigns fmt a = match a with WritesAny -> () | Writes l -> - pp_list ~sep:"@\n" - (fun fmt (loc,deps) -> + pp_list ~sep:"@\n" + (fun fmt (loc,deps) -> fprintf fmt "@\nassigns@ %a%a;" print_lexpr loc - print_deps deps) + print_deps deps) fmt l let print_clause name fmt e = fprintf fmt "@\n%s@ %a;" name print_lexpr e @@ -407,7 +418,10 @@ match ca with AAssert(bhvs,e) -> fprintf fmt "%aassert@ %a;" print_behaviors bhvs print_lexpr e - | AStmtSpec s -> print_spec fmt s + | AStmtSpec (bhvs,s) -> + fprintf fmt "%a%a" + print_behaviors bhvs + print_spec s | AInvariant (bhvs,loop,e) -> fprintf fmt "%a%ainvariant@ %a;" print_behaviors bhvs (pp_cond loop) "loop@ " print_lexpr e @@ -415,3 +429,9 @@ | AAssigns (bhvs,a) -> fprintf fmt "%aloop@ %a" print_behaviors bhvs print_assigns a | APragma p -> print_pragma fmt p + +(* +Local Variables: +compile-command: "make -C ../../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_ptree.mli frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_ptree.mli --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_ptree.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_ptree.mli 2011-10-10 08:40:07.000000000 +0000 @@ -135,6 +135,8 @@ (** same as [PLvalid_index], but for a range of indices. *) | PLseparated of lexpr list (** separation predicate. *) + | PLinitialized of lexpr + (** l-value is guaranteed to be initalized *) | PLfresh of lexpr (** expression points to a newly allocated block. *) | PLnamed of string * lexpr (** named expression. *) | PLsubtype of lexpr * lexpr @@ -159,6 +161,12 @@ inv: lexpr } +(** model field. *) +type model_annot = {model_for_type: logic_type; + model_type : logic_type; + model_name: string; (** name of the model field. *) + } + (** Concrete type definition. *) type typedef = | TDsum of (string * logic_type list) list @@ -226,7 +234,8 @@ represents a block of axiomatic definitions.*) | LDinvariant of string * lexpr (** global invariant. *) | LDtype_annot of type_annot (** type invariant. *) - | LDvolatile of lexpr * (string option * string option) + | LDmodel_annot of model_annot (** model field. *) + | LDvolatile of lexpr list * (string option * string option) (** volatile clause read/write. *) and deps = lexpr Cil_types.deps (** C locations. *) @@ -244,7 +253,6 @@ (** all kind of annotations*) type annot = | Adecl of decl list (** global annotation. *) - | Afor_spec of (location * string list * spec) | Aspec (* the real spec is parsed afterwards. See cparser.mly (grammar rules involving SPEC) for more details. @@ -256,18 +264,18 @@ (** ACSL extension for external spec file **) type ext_decl = - | Ext_decl of decl - | Ext_macro of string * lexpr - | Ext_include of bool * string + | Ext_decl of decl (* decl contains a location *) + | Ext_macro of string * lexpr (* lexpr contains a location *) + | Ext_include of bool * string * location type ext_function = - | Ext_spec of spec (* function spec *) - | Ext_loop_spec of string * annot (* loop annotation or + | Ext_spec of spec * location (* function spec *) + | Ext_loop_spec of string * annot * location (* loop annotation or code annotation relative to the loop body. *) - | Ext_stmt_spec of string * annot (* code annotation. *) + | Ext_stmt_spec of string * annot * location (* code annotation. *) | Ext_glob of ext_decl -type ext_module = string * ext_decl list * (string * ext_function list) list +type ext_module = string * ext_decl list * ((string * location) * ext_function list) list type ext_spec = ext_module list (* diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_typing.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_typing.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_typing.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_typing.ml 2011-10-10 08:40:07.000000000 +0000 @@ -30,12 +30,12 @@ open Format open Cil +exception Backtrack + let dloc = Lexing.dummy_pos,Lexing.dummy_pos let error (b,e) fstring = CurrentLoc.set (b,e) ; - Cil.abort_loc - (b.Lexing.pos_fname,b.Lexing.pos_lnum) - (fstring ^^ " in annotation.") + Kernel.abort ~source:b (fstring ^^ " in annotation.") let loc_join (b,_) (_,e) = (b,e) @@ -79,7 +79,7 @@ in let treat_escape_sequence () = if !i >= String.length s then - Cil.warning "Ill-formed escape sequence in wide string" + Kernel.warning ~current:true "Ill-formed escape sequence in wide string" else begin match s.[!i] with x when '0' <= x && x <= '9' -> @@ -95,8 +95,11 @@ | '"' -> incr i; res:= Int64.of_int (Char.code '"') ::!res | '?' -> incr i; res:= Int64.of_int (Char.code '?') ::!res | '\\' -> incr i; res:= Int64.of_int (Char.code '\\')::!res - | c -> incr i; Cil.warning "Ill-formed escape sequence in wide string"; - res:= Int64.of_int (Char.code c) :: !res + | c -> + incr i; + Kernel.warning ~current:true + "Ill-formed escape sequence in wide string"; + res:= Int64.of_int (Char.code c) :: !res end in while (!i < String.length s) do @@ -116,10 +119,38 @@ | _ -> f loc in aux loc -let is_same_type t1 t2 = - Logic_utils.is_same_type +let is_same_type ?(drop_attributes=true) t1 t2 = + Logic_utils.is_same_type ~drop_attributes (Logic_utils.unroll_type t1) (Logic_utils.unroll_type t2) +let type_rel = function + | Eq -> Cil_types.Req + | Neq -> Cil_types.Rneq + | Lt -> Cil_types.Rlt + | Le -> Cil_types.Rle + | Gt -> Cil_types.Rgt + | Ge -> Cil_types.Rge + +let type_binop = function + | Badd -> PlusA + | Bsub -> MinusA + | Bmul -> Mult + | Bdiv -> Div + | Bmod -> Mod + | Bbw_and -> BAnd + | Bbw_or -> BOr + | Bbw_xor -> BXor + | Blshift -> Shiftlt + | Brshift -> Shiftrt + +let binop_of_rel = function + | Eq -> Cil_types.Eq + | Neq -> Cil_types.Ne + | Ge -> Cil_types.Ge + | Gt -> Cil_types.Gt + | Le -> Cil_types.Le + | Lt -> Cil_types.Lt + (* Logical environments *) module Lenv = struct @@ -149,6 +180,8 @@ (Logic_env.find_all_logic_functions name <> []) in let rec aux i = + if i < 0 then + Kernel.fatal ~current:true "Out of indexes for temp logic var"; let name' = name ^ "_" ^ (string_of_int i) in if exists name' then aux (i+1) else name' in if exists name then aux 0 else name @@ -161,7 +194,8 @@ match kind, env.enclosing_post_state with | _, None -> kind | Normal, Some kind -> kind - | _, Some _ -> Cil.fatal "Inconsistent logic labels env stack" + | _, Some _ -> + Kernel.fatal ~current:true "Inconsistent logic labels env stack" in { env with is_post_state = Some real_kind; enclosing_post_state = Some real_kind @@ -225,11 +259,8 @@ let env = Lenv.add_logic_label "Here" Logic_const.here_label env in Lenv.set_current_logic_label Logic_const.here_label env -let append_pre_label ~pre_is_old env = - let l = - if pre_is_old then Logic_const.old_label - else Logic_const.pre_label in - Lenv.add_logic_label "Pre" l env +let append_pre_label env = + Lenv.add_logic_label "Pre" Logic_const.pre_label env let append_old_and_post_labels env = Lenv.add_logic_label "Post" Logic_const.post_label @@ -246,6 +277,10 @@ let v = Cil_const.make_logic_var "\\result" typ in Lenv.add_var "\\result" v env +let add_exit_status env = + let v = Cil_const.make_logic_var "\\exit_status" Linteger in + Lenv.add_var "\\exit_status" v env + let enter_post_state env kind = Lenv.enter_post_state env kind let post_state_env kind typ = @@ -254,11 +289,12 @@ let env = append_old_and_post_labels env in (* NB: this allows to have \result and Exits as termination kind *) let env = add_result env typ in + let env = add_exit_status env in let env = enter_post_state env kind in env type typing_context = { - annonCompFieldName : string; + anonCompFieldName : string; conditionalConversion : typ -> typ -> typ; find_macro : string -> lexpr; find_var : string -> logic_var; @@ -300,11 +336,107 @@ end let register_behavior_extension = Extensions.register + +let rec arithmetic_conversion ty1 ty2 = + match unroll_type ty1, unroll_type ty2 with + | Ctype ty1, Ctype ty2 -> + if isIntegralType ty1 && isIntegralType ty2 + then Linteger + else Lreal + | (Linteger, Ctype t | Ctype t, Linteger) when isIntegralType t -> + Linteger + | (Linteger, Ctype t | Ctype t , Linteger) when isArithmeticType t-> Lreal + | (Lreal, Ctype ty | Ctype ty, Lreal) when isArithmeticType ty -> Lreal + | Linteger, Linteger -> Linteger + | (Lreal | Linteger) , (Lreal | Linteger) -> Lreal + | Ltype ({lt_name="set"} as lt,[t1]),t2 + | t1,Ltype ({lt_name="set"} as lt,[t2]) -> + Ltype(lt,[arithmetic_conversion t1 t2]) + | _ -> + Kernel.fatal + "arithmetic conversion between non arithmetic types %a and %a" + d_logic_type ty1 d_logic_type ty2 + + let plain_arithmetic_type t = + match unroll_type t with + | Ctype ty -> Cil.isArithmeticType ty + | Linteger | Lreal -> true + | Ltype _ | Lvar _ | Larrow _ -> false + + let plain_integral_type t = + match unroll_type t with + | Ctype ty -> Cil.isIntegralType ty + | Linteger -> true + | Ltype _ | Lreal | Lvar _ | Larrow _ -> false + + let plain_boolean_type t = + match unroll_type t with + | Ctype ty -> isIntegralType ty + | Linteger -> true + | Ltype ({lt_name = name},[]) -> + name = Utf8_logic.boolean + | Lreal | Ltype _ | Lvar _ | Larrow _ -> false + + let plain_non_void_ptr loc typ = + match unroll_type typ with + Ctype (TPtr(ty,_) | TArray(ty,_,_,_)) -> + not (Cil.isVoidType ty) + | _ -> error loc "not a pointer or array type" + + let is_arithmetic_type = plain_or_set plain_arithmetic_type + + let is_integral_type = plain_or_set plain_integral_type + + (* can we have sets of boolean as for now ? *) + let is_boolean_type = plain_or_set plain_boolean_type + + let is_non_void_ptr loc = plain_or_set (plain_non_void_ptr loc) + + let check_non_void_ptr loc typ = + if not (is_non_void_ptr loc typ) then + error loc "expecting a non-void pointer" + + let rec add_offset toadd = function + | TNoOffset -> toadd + | TField(fid', offset) -> TField(fid', add_offset toadd offset) + | TIndex(e, offset) -> TIndex(e, add_offset toadd offset) + + let add_offset_lval toadd (b, off) = b, add_offset toadd off + + let dummy_loc = Cil_datatype.Location.unknown + + let rec type_of_pointed t = + match unroll_type t with + Ctype ty when isPointerType ty -> Ctype (Cil.typeOf_pointed ty) + | Ltype ({lt_name = "set"} as lt,[t]) -> + Ltype(lt,[type_of_pointed t]) + | _ -> + Kernel.fatal "type %a is not a pointer type" d_logic_type t + + let type_of_array_elem = + plain_or_set + (fun t -> + match unroll_type t with + Ctype ty when isArrayType ty -> Ctype (Cil.typeOf_array_elem ty) + | _ -> + error (CurrentLoc.get()) "type %a is not an array type" + d_logic_type t) + + let plain_mk_mem ?loc t ofs = match t.term_node with + | TAddrOf lv -> add_offset_lval ofs lv + | TStartOf lv -> add_offset_lval (TIndex (Cil.lzero ?loc (), ofs)) lv + | _ -> TMem t, ofs + + let mk_mem ?loc t ofs = + lift_set + (fun t -> term ?loc (TLval (plain_mk_mem ?loc t ofs)) + (type_of_pointed t.term_type)) + t module Make (C : sig - val annonCompFieldName : string + val anonCompFieldName : string val conditionalConversion : typ -> typ -> typ val find_macro : string -> lexpr val find_var : string -> logic_var @@ -322,6 +454,7 @@ val find_all_logic_functions: string -> logic_info list val find_logic_type: string -> logic_type_info val find_logic_ctor: string -> logic_ctor_info + val integral_cast: Cil_types.typ -> Cil_types.term -> Cil_types.term end) = struct @@ -333,7 +466,7 @@ type_predicate= type_predicate; type_term= type_term; type_assigns = type_assigns; - annonCompFieldName = C.annonCompFieldName; + anonCompFieldName = C.anonCompFieldName; conditionalConversion = C.conditionalConversion; find_macro = C.find_macro; find_var = C.find_var; @@ -461,42 +594,6 @@ | Ctype t -> t | Ltype _ | Linteger | Lreal | Lvar _ | Larrow _ -> error loc "not a C type" - let rec add_offset toadd = function - | TNoOffset -> toadd - | TField(fid', offset) -> TField(fid', add_offset toadd offset) - | TIndex(e, offset) -> TIndex(e, add_offset toadd offset) - - let add_offset_lval toadd (b, off) = b, add_offset toadd off - - let dummy_loc = Lexing.dummy_pos,Lexing.dummy_pos - - let rec type_of_pointed t = - match unroll_type t with - Ctype ty when isPointerType ty -> Ctype (Cil.typeOf_pointed ty) - | Ltype ({lt_name = "set"} as lt,[t]) -> - Ltype(lt,[type_of_pointed t]) - | _ -> - Cilmsg.fatal "type %a is not a pointer type" d_logic_type t - - let type_of_array_elem = - plain_or_set - (fun t -> - match unroll_type t with - Ctype ty when isArrayType ty -> Ctype (Cil.typeOf_array_elem ty) - | _ -> - error (CurrentLoc.get()) "type %a is not an array type" - d_logic_type t) - - let plain_mk_mem ?loc t ofs = match t.term_node with - | TAddrOf lv -> add_offset_lval ofs lv - | TStartOf lv -> add_offset_lval (TIndex (Cil.lzero ?loc (), ofs)) lv - | _ -> TMem t, ofs - - let mk_mem ?loc t ofs = - lift_set - (fun t -> term ?loc (TLval (plain_mk_mem ?loc t ofs)) - (type_of_pointed t.term_type)) - t let mk_logic_access env t = match t.term_node with @@ -523,9 +620,6 @@ | TLval lv -> Logic_const.term ~loc (TLval (add_offset_lval f_ofs lv)) f_type - | Told t1 -> - Logic_const.term - ~loc (Told (t_dot_x t1)) f_type | Tat (t1,l) -> Logic_const.term ~loc (Tat (t_dot_x t1,l)) f_type @@ -545,26 +639,74 @@ })) f_type in t_dot_x t + let mk_at_here idx = + let rec needs_at idx = + match idx.term_node with + | TConst _ | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ + | TAlignOf _ | TAlignOfE _ | Tat _ | Ttypeof _ | Ttype _ + | Tempty_set | Tbase_addr _ | Tblock_length _ | Tnull + -> false + | TLval _ -> true + | TUnOp(_,t) -> needs_at t + | TBinOp(_,t1,t2) -> needs_at t1 || needs_at t2 + | TCastE(_,t) -> needs_at t + | TAddrOf (_,o) -> needs_at_offset o + | TStartOf (_,o) -> needs_at_offset o + | Tapp(_,_,l) | TDataCons(_,l) -> List.exists needs_at l + | Tlambda(_,t) -> needs_at t + | TCoerce(t,_) -> needs_at t + | TCoerceE(t,_) -> needs_at t + | TUpdate(t1,o,t2) -> needs_at t1 || needs_at_offset o || needs_at t2 + | Tunion l | Tinter l -> List.exists needs_at l + | Tcomprehension(t,_,None) -> needs_at t + | Tcomprehension(t,_,Some p) -> needs_at t || needs_at_pred p + | Trange (None, None) -> false + | Trange (None, Some t) | Trange(Some t, None) -> needs_at t + | Trange (Some t1, Some t2) -> needs_at t1 || needs_at t2 + | Tlet(_,t) -> needs_at t + | Tif(t1,t2,t3) -> needs_at t1 || needs_at t2 || needs_at t3 + and needs_at_offset = function + | TNoOffset -> false + | TIndex (t,o) -> needs_at t || needs_at_offset o + | TField(_,o) -> needs_at_offset o + and needs_at_pred p = + match p.content with + | Pfalse | Ptrue | Pat _ -> false + | Papp(_,_,t) | Pseparated t -> List.exists needs_at t + | Prel(_,t1,t2) -> needs_at t1 || needs_at t2 + | Pand(p1,p2) | Por(p1,p2) | Pxor(p1,p2) + | Pimplies(p1,p2) | Piff(p1,p2) + -> needs_at_pred p1 || needs_at_pred p2 + | Pnot p | Plet (_,p) | Pforall(_,p) | Pexists(_,p) -> needs_at_pred p + | Pif(t,p1,p2) -> needs_at t || needs_at_pred p1 || needs_at_pred p2 + | Pvalid t | Pinitialized t -> needs_at t + | Pvalid_index(t1,t2) -> needs_at t1 || needs_at t2 + | Pvalid_range(t1,t2,t3) -> needs_at t1 || needs_at t2 || needs_at t3 + | Pfresh _ -> true + | Psubtype _ -> false + in + if needs_at idx then tat ~loc:idx.term_loc (idx,here_label) else idx + let mk_shift loc env idx t_elt t = - let add_offset array = + let add_offset array idx = Logic_const.term ~loc (TLval (add_offset_lval (TIndex (idx, TNoOffset)) array)) t_elt in + let here_idx = mk_at_here idx in match t.term_node with - | TStartOf array -> add_offset array - | TLval array when isLogicArrayType t.term_type -> - add_offset array + | TStartOf array -> add_offset array idx + | TLval array when isLogicArrayType t.term_type -> add_offset array idx | Tlet (def, ({ term_node = TLval array} as t)) when isLogicArrayType t.term_type -> - Logic_const.term ~loc (Tlet (def, add_offset array)) t_elt + Logic_const.term ~loc (Tlet (def, add_offset array idx)) t_elt | Tat({term_node = TStartOf (TVar { lv_origin = Some v},_ as lv)},lab) when v.vformal && lab = old_label && env.Lenv.is_funspec -> - Logic_const.tat ~loc (add_offset lv,lab) + Logic_const.tat ~loc (add_offset lv here_idx,lab) | Tat({term_node = TLval (TVar { lv_origin = Some v},_ as lv)},lab) when v.vformal && lab = old_label && env.Lenv.is_funspec && isLogicArrayType t.term_type -> - Logic_const.tat ~loc (add_offset lv,lab) + Logic_const.tat ~loc (add_offset lv here_idx,lab) | _ -> let b = { term_node = TBinOp (IndexPI, t, idx); term_name = []; @@ -573,45 +715,6 @@ in mk_mem b TNoOffset - let plain_arithmetic_type t = - match unroll_type t with - | Ctype ty -> Cil.isArithmeticType ty - | Linteger | Lreal -> true - | Ltype _ | Lvar _ | Larrow _ -> false - - let plain_integral_type t = - match unroll_type t with - | Ctype ty -> Cil.isIntegralType ty - | Linteger -> true - | Ltype _ | Lreal | Lvar _ | Larrow _ -> false - - let plain_boolean_type t = - match unroll_type t with - | Ctype ty -> isIntegralType ty - | Linteger -> true - | Ltype ({lt_name = name},[]) -> - name = Utf8_logic.boolean - | Lreal | Ltype _ | Lvar _ | Larrow _ -> false - - let plain_non_void_ptr loc typ = - match unroll_type typ with - Ctype (TPtr(ty,_) | TArray(ty,_,_,_)) -> - not (Cil.isVoidType ty) - | _ -> error loc "not a pointer or array type" - - let is_arithmetic_type = plain_or_set plain_arithmetic_type - - let is_integral_type = plain_or_set plain_integral_type - - (* can we have sets of boolean as for now ? *) - let is_boolean_type = plain_or_set plain_boolean_type - - let is_non_void_ptr loc = plain_or_set (plain_non_void_ptr loc) - - let check_non_void_ptr loc typ = - if not (is_non_void_ptr loc typ) then - error loc "expecting a non-void pointer" - let is_set_type t = match unroll_type t with Ltype ({lt_name = "set"},[_]) -> true @@ -648,15 +751,18 @@ let c_mk_cast e oldt newt = if Cilutil.equals (type_sig_logic oldt) (type_sig_logic newt) then begin e - end else begin + end + else begin (* Watch out for constants *) if isPointerType newt && isLogicNull e && not (isLogicZero e) then e else if isPointerType newt && isArrayType oldt && is_C_array e then mk_logic_StartOf e else - match newt, e.term_node with + match Cil.unrollType newt, e.term_node with | TInt(newik, []), TConst (CInt64(i, _, _)) -> { e with term_node = TConst (CInt64 (i, newik, None)) } + | TEnum (ei,[]), TConst (CEnum { eihost = ei'}) + when ei.ename = ei'.ename -> e | _ -> { e with term_node = TCastE (newt, e); term_type = Ctype newt } end @@ -707,9 +813,15 @@ (isPointerType ctyp1 && isPointerType ctyp2 && (compatible_pointed() || isLogicNull term)) + let is_enum_cst e t = + match e.term_node with + | TConst (CEnum ei) -> is_same_type (Ctype (TEnum (ei.eihost,[]))) t + | _ -> false + let rec mk_cast e newt = let loc = e.term_loc in if is_same_type e.term_type newt then e + else if is_enum_cst e newt then e else begin match (unroll_type e.term_type), @@ -721,7 +833,10 @@ | t1, Ltype ({lt_name = name},[]) when name = Utf8_logic.boolean && is_integral_type t1 -> { e with - term_node = TBinOp(Cil_types.Ne,e,lzero ~loc ()); + term_node = + TBinOp(Cil_types.Ne, + mk_cast e Linteger, + lzero ~loc ()); term_type = Ltype(C.find_logic_type Utf8_logic.boolean,[]) } | Ltype({lt_name = "set"},[ty1]), Ltype({lt_name="set"},[ty2]) -> let e = mk_cast {e with term_type = ty1} ty2 in @@ -732,7 +847,11 @@ | Linteger, Linteger | Lreal, Lreal -> e | Linteger, Ctype t when isLogicPointerType newt && isLogicNull e -> c_mk_cast e intType t - | Linteger, Ctype _ | Lreal, Ctype _ -> + | Linteger, Ctype t when isIntegralType t -> + (try + C.integral_cast t e + with Failure s -> error loc "%s" s) + | Linteger, Ctype _ | Lreal, Ctype _ -> error loc "invalid implicit cast from %a to C type %a" d_logic_type e.term_type d_logic_type newt | Ctype t, Linteger when Cil.isIntegralType t -> @@ -782,18 +901,19 @@ | TBuiltin_va_list _, (TInt _ | TPtr _) -> result | (TInt _ | TPtr _), TBuiltin_va_list _ -> - Cil.warnOpt "Casting %a to __builtin_va_list" Cil.d_type ot; - result + Kernel.debug ~level:3 "Casting %a to __builtin_va_list" Cil.d_type ot; + result | TPtr _, TEnum _ -> - Cil.warnOpt "Casting a pointer into an enumeration type"; - result + Kernel.debug ~level:3 "Casting a pointer into an enumeration type"; + result | (TInt _ | TEnum _ | TPtr _ ), TVoid _ -> (ot, e) | TComp (comp1, _, _), TComp (comp2, _, _) - when comp1.ckey = comp2.ckey -> - (nt, e) + when comp1.ckey = comp2.ckey -> + nt, e | _ -> - Cil.fatal "Logic_typing.c_cast_to: %a -> %a@." Cil.d_type ot Cil.d_type nt + Kernel.fatal ~current:true + "Logic_typing.c_cast_to: %a -> %a@." Cil.d_type ot Cil.d_type nt end (* for overloading: raised when an arguments list does not fit a @@ -803,6 +923,30 @@ (* keep in sync with fresh_type below *) let generated_var s = String.contains s '#' + (* keep in sync with generated_var above*) + class fresh_type_var = + object(self) + inherit Cil.nopCilVisitor + val alpha_rename = Hashtbl.create 7 + val mutable count = 0 + method private fresh_s s = + count <- succ count; Printf.sprintf "%s#%d" s count + method vlogic_type = function + Lvar s when Hashtbl.mem alpha_rename s -> + Cil.ChangeTo (Lvar (Hashtbl.find alpha_rename s)) + | Lvar s -> + let s' = self#fresh_s s in + Hashtbl.add alpha_rename s s'; + Cil.ChangeTo (Lvar s') + | _ -> Cil.DoChildren + method reset_count () = count <- 0 + method reset () = Hashtbl.clear alpha_rename + end + + let fresh_type = new fresh_type_var + + let fresh typ = visitCilLogicType (fresh_type :> cilVisitor) typ + let rec partial_unif ~overloaded loc ot nt env = match (unroll_type ot),(unroll_type nt) with | Lvar s1, Lvar s2 -> @@ -827,7 +971,9 @@ with Not_found -> Lenv.add_type_var s2 ot env, ot, ot else if s1 = s2 then env, ot, ot (* same type *) - else error loc "implicit unification of type variables %s and %s" s1 s2 + else + error loc + "implicit unification of type variables %s and %s" s1 s2 | Lvar s1, _ when generated_var s1 -> (try let ot = Lenv.find_type_var s1 env in partial_unif ~overloaded loc ot nt env @@ -890,6 +1036,7 @@ if (isIntegralType ty1 && isIntegralType ty2 && (sz1 < sz2 || (sz1 = sz2 && (isSignedInteger ty1 = isSignedInteger ty2)) + || is_enum_cst oterm nt )) || is_implicit_pointer_conversion oterm ty1 ty2 || (match unrollType ty1, unrollType ty2 with @@ -901,26 +1048,47 @@ | _ -> false) then begin let t,e = c_cast_to ty1 ty2 oterm in Ctype t, e - end else - if overloaded then raise Not_applicable + end else if overloaded then raise Not_applicable + else if + isArrayType ty1 && isPointerType ty2 + && (Cilutil.equals + (type_sig_logic (typeOf_array_elem ty1)) + (type_sig_logic (typeOf_pointed ty2))) + then if Logic_utils.is_C_array oterm then + error loc + "In ACSL, there is no implicit conversion between \ + a C array and a pointer. Either introduce an explicit cast \ + or take the address of the first element of %a" d_term oterm + else + error loc + "%a is a logic array. Only C arrays can be \ + converted to pointers, and this conversion must be \ + explicit (cast or take the address of the first element)" + d_term oterm else error loc "invalid implicit conversion from '%a' to '%a'" d_type ty1 d_type ty2 | Ctype ty, Linteger when Cil.isIntegralType ty -> Linteger, oterm | Ctype ty, Lreal when Cil.isArithmeticType ty -> Lreal, oterm - | Linteger, Lreal when not overloaded -> Lreal, oterm + | Linteger, Lreal -> Lreal, oterm (* Integer 0 is also a valid pointer. *) | Linteger, Ctype ty when Cil.isPointerType ty && isLogicNull oterm -> nt, { oterm with term_node = TCastE(ty,oterm); term_type = nt } - (* can convert implicitly a singleton into a set, - but not the reverse. *) + | Linteger, Ctype ty when Cil.isIntegralType ty -> + (try + nt, C.integral_cast ty oterm + with Failure s -> error loc "%s" s) + (* can convert implicitly a singleton into a set, + but not the reverse. *) | Ltype (t1,l1), Ltype (t2,l2) when t1.lt_name = t2.lt_name -> (* not sure this is really what we want: can foo be implicitly converted into foo ? *) let l = - List.map2 (fun x y -> fst (implicit_conversion ~overloaded loc oterm x y)) l1 l2 + List.map2 + (fun x y -> + fst (implicit_conversion ~overloaded loc oterm x y)) l1 l2 in Ltype(t1,l),oterm | t1, Ltype ({lt_name = "set"},[t2]) -> @@ -933,7 +1101,8 @@ (* contravariance. *) let args = List.map2 - (fun x y -> fst (implicit_conversion ~overloaded loc oterm x y)) args2 args1 + (fun x y -> fst (implicit_conversion ~overloaded loc oterm x y)) + args2 args1 in let rt,_ = implicit_conversion ~overloaded loc oterm rt1 rt2 in Larrow(args,rt), oterm @@ -950,25 +1119,27 @@ let t,e = implicit_conversion ~overloaded loc oterm ot nt in env, t, e - let convertible t1 t2 = - try - let _ = - implicit_conversion - ~overloaded:true - Cil_datatype.Location.unknown - t1 - t1.term_type - t2.term_type - in true - with Not_applicable -> false + let convertible (t1,t) (t2,_) = + let res = + try + let _ = + implicit_conversion + ~overloaded:true Cil_datatype.Location.unknown t t1 t2 + in true + with Not_applicable -> false + in + Kernel.debug ~level:4 "Checking conversion between %a and %a: %B@." + Cil.d_logic_type t1 Cil.d_logic_type t2 res; + res - let convertible_non_null t1 t2 = - match (unroll_type t1.term_type, unroll_type t2.term_type) with + let convertible_non_null (ty1,t as t1) (ty2,_ as t2) = + match (unroll_type ty1, unroll_type ty2) with | Ctype ty1, Ctype ty2 when - isPointerType ty1 && isPointerType ty2 && isLogicNull t1 -> + isPointerType ty1 && isPointerType ty2 && isLogicNull t -> isVoidPtrType ty2 | _ -> convertible t1 t2 +(* TODO: filter on signatures, not on type-checked actual arguments !!!!!! *) let filter_non_minimal_arguments l ((_,_,tl,_) as p) = let rec aux acc l = match l with @@ -1003,8 +1174,7 @@ aux (p'::acc) r in let l = aux [] l in - assert (l <> []); - l + assert (l <> []); l let rec logic_arithmetic_promotion t = match unroll_type t with @@ -1015,13 +1185,13 @@ (match Cil.unrollType ty with TFloat _ -> Lreal | _ -> - Cilmsg.fatal + Kernel.fatal "logic arithmetic promotion on non-arithmetic type %a" d_logic_type t) | Ltype ({lt_name="set"} as lt,[t]) -> Ltype(lt,[logic_arithmetic_promotion t]) | Ltype _ | Lvar _ | Larrow _ -> - Cilmsg.fatal "logic arithmetic promotion on non-arithmetic type %a" + Kernel.fatal "logic arithmetic promotion on non-arithmetic type %a" d_logic_type t let rec integral_promotion t = @@ -1031,38 +1201,28 @@ | Linteger -> Linteger | Ltype ({lt_name="set"} as lt,[t]) -> Ltype(lt,[integral_promotion t]) | Ltype _ | Lreal | Lvar _ | Larrow _ | Ctype _ -> - Cilmsg.fatal + Kernel.fatal "logic integral promotion on non-integral type %a" d_logic_type t - let rec arithmetic_conversion ty1 ty2 = - match unroll_type ty1, unroll_type ty2 with - | Ctype ty1, Ctype ty2 -> - if isIntegralType ty1 && isIntegralType ty2 - then Linteger - else Lreal - | (Linteger, Ctype t | Ctype t, Linteger) when isIntegralType t -> - Linteger - | (Linteger, Ctype t | Ctype t , Linteger) when isArithmeticType t-> Lreal - | (Lreal, Ctype ty | Ctype ty, Lreal) when isArithmeticType ty -> Lreal - | Linteger, Linteger -> Linteger - | (Lreal | Linteger) , (Lreal | Linteger) -> Lreal - | Ltype ({lt_name="set"} as lt,[t1]),t2 - | t1,Ltype ({lt_name="set"} as lt,[t2]) -> - Ltype(lt,[arithmetic_conversion t1 t2]) - | _ -> - Cilmsg.fatal - "arithmetic conversion between non arithmetic types %a and %a" - d_logic_type ty1 d_logic_type ty2 - let conditional_conversion loc env t1 t2 = - let _, t1, t2 = partial_unif ~overloaded:false loc t1 t2 env in - let rt = + (* a comparison is mainly a function of type 'a -> 'a -> Bool/Prop. + performs the needed unifications on both sides.*) + let var = fresh (Lvar "cmp") in + let env,t1,_ = partial_unif ~overloaded:false loc t1 var env in + let _,t2,_ = partial_unif ~overloaded:false loc t2 var env in + let rec aux t1 t2 = match (unroll_type t1), (unroll_type t2) with - | _ when is_same_type t1 t2 -> t1 + | t1, t2 when is_same_type t1 t2 -> t1 | Ctype ty1, Ctype ty2 -> if isIntegralType ty1 && isIntegralType ty2 then - Linteger + if (isSignedInteger ty1) <> (isSignedInteger ty2) then + (* in ACSL, the comparison between 0xFFFFFFFF seen as int and + unsigned int is not true: we really have to operate at + the integer level. + *) + Linteger + else Ctype (C.conditionalConversion ty1 ty2) else if isArithmeticType ty1 && isArithmeticType ty2 then Lreal else if is_same_ptr_type ty1 ty2 || is_same_array_type ty1 ty2 then @@ -1074,28 +1234,27 @@ d_type ty1 d_type ty2 else (* pointer to integer conversion *) Ctype (C.conditionalConversion ty1 ty2) - | (Linteger, Ctype t | Ctype t, Linteger) when Cil.isIntegralType t - -> - Linteger + | (Linteger, Ctype t | Ctype t, Linteger) + when Cil.isIntegralType t -> Linteger + | (Linteger, Ctype t | Ctype t, Linteger) + when Cil.isArithmeticType t -> Lreal | (Ltype({lt_name = name},[]), t | t, Ltype({lt_name = name},[])) when is_integral_type t && name = Utf8_logic.boolean -> Ltype(C.find_logic_type Utf8_logic.boolean,[]) - | Lreal, Ctype ty | Ctype ty, Lreal -> - (match Cil.unrollType ty with - TFloat _ -> Lreal - | _ -> error loc "types %a and %a are not convertible" - d_logic_type t1 d_logic_type t2) + | Lreal, Ctype ty | Ctype ty, Lreal when isArithmeticType ty -> Lreal | Ltype (s1,l1), Ltype (s2,l2) when s1.lt_name = s2.lt_name && List.for_all2 is_same_type l1 l2 -> t1 | Lvar s1, Lvar s2 when s1 = s2 -> t1 | Linteger, Linteger -> Linteger | (Lreal | Linteger) , (Lreal | Linteger) -> Lreal + | Ltype ({lt_name = "set"} as lt,[t1]), t2 + | t1, Ltype({lt_name="set"} as lt,[t2]) -> Ltype(lt,[aux t1 t2]) | _ -> error loc "types %a and %a are not convertible" d_logic_type t1 d_logic_type t2 in - rt,t1,t2 + let rt = aux t1 t2 in rt,t1,t2 let location_to_char_ptr t = let convert_one_location t = @@ -1133,17 +1292,9 @@ error Cil_datatype.Location.unknown "cannot take the address of non-C values (type %a)" d_logic_type t - let binop_of_rel = function - Eq -> Cil_types.Eq - | Neq -> Cil_types.Ne - | Ge -> Cil_types.Ge - | Gt -> Cil_types.Gt - | Le -> Cil_types.Le - | Lt -> Cil_types.Lt - (* Typing terms *) - let parseInt s = + let parseInt s loc = let explode s = let l = ref [] in String.iter (fun c -> l:=Int64.of_int (Char.code c) :: !l) s; @@ -1155,14 +1306,14 @@ let tokens = explode content in let value = Cil.reduce_multichar Cil.theMachine.Cil.wcharType tokens in - Cil.kinteger64 - ~loc:Cil_datatype.Location.unknown Cil.theMachine.Cil.wcharKind value + Cil.kinteger64 + ~loc Cil.theMachine.Cil.wcharKind (My_bigint.of_int64 value) | '\'' -> (* 'char' *) let content = String.sub s 1 (String.length s - 2) in let tokens = explode content in let value,_= Cil.interpret_character_constant tokens in dummy_exp (Const value) - | _ -> Cil.parseInt ~loc:Cil_datatype.Location.unknown s + | _ -> Cil.parseInt ~loc s let find_logic_label loc env l = try Lenv.find_logic_label l env @@ -1228,30 +1379,6 @@ let rename_variable t v1 v2 = visitCilTerm (new rename_variable v1 v2) t - (* keep in sync with generated_var above*) - class fresh_type_var = - object(self) - inherit Cil.nopCilVisitor - val alpha_rename = Hashtbl.create 7 - val mutable count = 0 - method private fresh_s s = - count <- succ count; Printf.sprintf "%s#%d" s count - method vlogic_type = function - Lvar s when Hashtbl.mem alpha_rename s -> - Cil.ChangeTo (Lvar (Hashtbl.find alpha_rename s)) - | Lvar s -> - let s' = self#fresh_s s in - Hashtbl.add alpha_rename s s'; - Cil.ChangeTo (Lvar s') - | _ -> Cil.DoChildren - method reset_count () = count <- 0 - method reset () = Hashtbl.clear alpha_rename - end - - let fresh_type = new fresh_type_var - - let fresh typ = visitCilLogicType (fresh_type :> cilVisitor) typ - let find_logic_info v env = try Lenv.find_logic_info v.lv_name env with Not_found -> @@ -1308,99 +1435,88 @@ let normalize_lambda_term env term = let add_binders quants term = match term.term_node, (unroll_type term.term_type) with - | Tlambda(quants',term), Larrow (args,rt_typ) -> - let args = - List.fold_right (fun x l -> x.lv_type :: l) quants args - in - { term with - term_node = Tlambda (quants @ quants', term); - term_type = Larrow (args,rt_typ) } - | Tlambda _ , _ -> fatal "\\lambda with a non-arrow type" - | _,typ -> - { term with - term_node = Tlambda(quants, term); - term_type = Larrow(List.map (fun x -> x.lv_type) quants,typ) - } + | Tlambda(quants',term), Larrow (args,rt_typ) -> + let args = List.fold_right (fun x l -> x.lv_type :: l) quants args in + { term with + term_node = Tlambda (quants @ quants', term); + term_type = Larrow (args,rt_typ) } + | Tlambda _ , _ -> + Kernel.fatal ~current:true "\\lambda with a non-arrow type" + | _,typ -> + { term with + term_node = Tlambda(quants, term); + term_type = Larrow(List.map (fun x -> x.lv_type) quants,typ) } in let rec aux known_vars kont term = match term.term_node with - | TLval(TVar v, TNoOffset) -> - known_vars, kont (eta_expand term.term_loc term.term_name env v) - | TConst _ | TLval _ | TSizeOf _ | TSizeOfE _ - | TSizeOfStr _ | TAlignOf _ | TAlignOfE _ - | TUnOp _ | TBinOp _ | TCastE _ | TAddrOf _ | TStartOf _ - | Tapp _ | TDataCons _ | Tbase_addr _ - | Tblock_length _ | Tnull | TCoerce _ | TCoerceE _ - | TUpdate _ | Ttypeof _ | Ttype _ | Tempty_set - (* [VP] I suppose that an union of functions - is theoretically possible but I'm not sure that we want to - lift the lambda anyway, even though this contradicts the - idea that you can always replace a term by a set of terms - *) - | Tunion _ | Tinter _ | Tcomprehension _ - | Trange _ - - -> known_vars, kont term - | Tlambda (quants,term) -> - List.iter (fresh_vars known_vars) quants; - let known_vars = - List.fold_left (fun l x -> x.lv_name :: l) known_vars quants - in - aux known_vars (kont $ (add_binders quants)) term - | Tif (cond, ttrue, tfalse) -> - let known_vars, ttrue = aux known_vars (fun x -> x) ttrue in - let known_vars, tfalse = aux known_vars (fun x -> x) tfalse in - let term = - match ttrue.term_node, tfalse.term_node with - | Tlambda(quants1,term1), Tlambda(quants2,term2) -> - assert( - Cilmsg.verify(List.length quants1 = List.length quants2) - "Branches of conditional have different number \ + | TLval(TVar v, TNoOffset) -> + known_vars, kont (eta_expand term.term_loc term.term_name env v) + | TConst _ | TLval _ | TSizeOf _ | TSizeOfE _ + | TSizeOfStr _ | TAlignOf _ | TAlignOfE _ + | TUnOp _ | TBinOp _ | TCastE _ | TAddrOf _ | TStartOf _ + | Tapp _ | TDataCons _ | Tbase_addr _ + | Tblock_length _ | Tnull | TCoerce _ | TCoerceE _ + | TUpdate _ | Ttypeof _ | Ttype _ | Tempty_set + (* [VP] I suppose that an union of functions + is theoretically possible but I'm not sure that we want to + lift the lambda anyway, even though this contradicts the + idea that you can always replace a term by a set of terms + *) + | Tunion _ | Tinter _ | Tcomprehension _ + | Trange _ + + -> known_vars, kont term + | Tlambda (quants,term) -> + List.iter (fresh_vars known_vars) quants; + let known_vars = + List.fold_left (fun l x -> x.lv_name :: l) known_vars quants + in + aux known_vars (kont $ (add_binders quants)) term + | Tif (cond, ttrue, tfalse) -> + let known_vars, ttrue = aux known_vars (fun x -> x) ttrue in + let known_vars, tfalse = aux known_vars (fun x -> x) tfalse in + let term = + match ttrue.term_node, tfalse.term_node with + | Tlambda(quants1,term1), Tlambda(quants2,term2) -> + assert( + Kernel.verify(List.length quants1 = List.length quants2) + "Branches of conditional have different number \ of \\lambda"); - let term2 = - List.fold_left2 rename_variable term2 quants2 quants1 - in - { term with - term_node = - Tlambda(quants1, - {term with - term_node = Tif(cond,term1,term2); - term_type = term1.term_type}); - term_type = ttrue.term_type } - | Tlambda _, _ | _, Tlambda _ -> - fatal "Branches of conditional have different number \ - of \\lambda" - | _,_ -> term - in known_vars, kont term - | Told t -> - let push_old t = match t.term_node with - Tlambda(quants,t) -> - { term with - term_node = - Tlambda(quants, {t with term_node = Told t})} - | _ -> term - in - aux known_vars (kont $ push_old) t - | Tat (t,lab) -> - let push_at t = match t.term_node with - Tlambda(quants,t) -> - { term with - term_node = - Tlambda(quants, {t with term_node = Tat (t,lab)})} - | _ -> term - in - aux known_vars (kont $ push_at) t - | Tlet(v,body) -> - fresh_vars known_vars v.l_var_info; - let known_vars = v.l_var_info.lv_name :: known_vars in - let push_let t = match t.term_node with - Tlambda(quants, t) -> - { term with - term_node = - Tlambda(quants, { t with term_node = Tlet(v,t) } ); } - | _ -> term + let term2 = + List.fold_left2 rename_variable term2 quants2 quants1 in - aux known_vars (kont $ push_let) body + { term with + term_node = + Tlambda(quants1, + {term with + term_node = Tif(cond,term1,term2); + term_type = term1.term_type}); + term_type = ttrue.term_type } + | Tlambda _, _ | _, Tlambda _ -> + Kernel.fatal ~current:true + "Branches of conditional have different number of \\lambda" + | _,_ -> term + in known_vars, kont term + | Tat (t,lab) -> + let push_at t = match t.term_node with + Tlambda(quants,t) -> + { term with + term_node = + Tlambda(quants, {t with term_node = Tat (t,lab)})} + | _ -> term + in + aux known_vars (kont $ push_at) t + | Tlet(v,body) -> + fresh_vars known_vars v.l_var_info; + let known_vars = v.l_var_info.lv_name :: known_vars in + let push_let t = match t.term_node with + Tlambda(quants, t) -> + { term with + term_node = + Tlambda(quants, { t with term_node = Tlet(v,t) } ); } + | _ -> term + in + aux known_vars (kont $ push_let) body in snd (aux [] (fun x -> x) term) let check_func_labels loc env info = @@ -1417,7 +1533,7 @@ let f_ofs, _ = plain_type_of_field loc f t_type in let result = match f_ofs with | TField (_,TNoOffset) -> false - | TField _ -> true ; + | TField _ -> true ; | _ -> assert false in result | PLpathIndex _ -> false @@ -1427,7 +1543,7 @@ let f_ofs, ofs_type = plain_type_of_field loc f t_type in let f_ofs, ofs_type = match f_ofs with | TField (f,TNoOffset) ->( mk_field f),ofs_type - | TField (f,_) -> (mk_field f), + | TField (f,_) -> (mk_field f), (* f is an anonymous field, find its type *) (let c_type = match t_type with | Ctype c_type -> c_type @@ -1487,13 +1603,13 @@ let updated = mk_let (opt_idx_let (TUpdate(t,toff,v))) in updated, t_type - let rec term env t = + let rec term ?(silent=false) env t = match t.lexpr_node with | PLnamed(name,t) -> - let t = term env t in + let t = term ~silent env t in { t with term_name = name :: t.term_name } | _ -> - let t', ty = term_node env t.lexpr_loc t.lexpr_node in + let t', ty = term_node ~silent env t.lexpr_loc t.lexpr_node in { term_node = t'; term_loc=t.lexpr_loc; term_type=ty; term_name = [] } and normalize_update_term env loc t v = function @@ -1501,8 +1617,8 @@ into {x \with .c = {x.c \with [idx] = v}}. \let expressions can be introduced. *) | [] -> assert false (* parsing invariant *) - | (toff::tail) as offs -> - begin + | (toff::tail) as offs -> + begin let t_type = t.term_type in let tail = if has_extra_offset_to_TField loc t_type toff then @@ -1558,7 +1674,7 @@ and normalizing_cont t2 = normalize_update_cont env loc t2 (cont,toffs) in normalize_updated_offset_term idx_typing env loc t normalizing_cont toff - and term_node env loc pl = + and term_node ?(silent=false) env loc pl = match pl with | PLinitIndex _ -> error loc "unsupported aggregated array construct" @@ -1582,7 +1698,7 @@ TSizeOfE t, Linteger | PLnamed _ -> assert false (* should be captured by term *) | PLconstant (IntConstant s) -> - begin match (parseInt s).enode with + begin match (parseInt s loc).enode with | Const (CInt64 (_,_,_) as c) -> TConst c, Linteger | Const ((CChr _) as c) -> (* a char literal has type int *) TConst c, Linteger @@ -1613,7 +1729,8 @@ TConst(CReal(float_of_string baseint, kind, Some str)), Lreal with Failure _ as e -> - Cil.abort "float_of_string %s (%s)" str (Printexc.to_string e) + Kernel.abort ~current:true + "float_of_string %s (%s)" str (Printexc.to_string e) end | PLconstant (StringConstant s) -> TConst (CStr (unescape s)), Ctype Cil.charPtrType @@ -1637,15 +1754,9 @@ end else term, info.lv_type in begin - (if x = "\\exit_status" then - match Lenv.current_post_state env with - | Some Exits -> () - | _ -> - Cil.abort - "\\exit_status can only be found in exits clause"); try - let def = C.find_macro x - in term_node env loc def.lexpr_node + let def = C.find_macro x + in term_node ~silent env loc def.lexpr_node with Not_found -> try (* NB: In the current implementation and ACSL format, \let @@ -1655,10 +1766,11 @@ *) let lv = Lenv.find_var x env in (match lv.lv_type with - | Ctype (TVoid _)-> - Cil.abort "Variable %s is bound to a predicate, \ - not a term" x - | _ -> old_val lv) + | Ctype (TVoid _)-> + if silent then raise Backtrack; + Kernel.abort ~current:true + "Variable %s is bound to a predicate, not a term" x + | _ -> old_val lv) with Not_found -> try let info = C.find_var x in @@ -1671,7 +1783,7 @@ with Not_found -> try let e,t = C.find_enum_tag x in - begin match (Cil.constFold true e).enode with + begin match e.enode with | Const c -> TConst c, Ctype t | _ -> assert false end @@ -1708,7 +1820,9 @@ | Some t, l -> fresh (Larrow (List.map (fun x -> x.lv_type) l, t)) - | None, _ -> error loc "%s is not a logic variable" x + | None, _ -> + if silent then raise Backtrack; + error loc "%s is not a logic variable" x in match f.l_labels with [] -> @@ -1721,6 +1835,7 @@ "%s labels must be explicitely instantiated" x in match C.find_all_logic_functions x with + [] -> error loc "unbound logic variable %s" x | [f] -> make_expr f | l -> @@ -1756,7 +1871,9 @@ type_logic_app env loc f labels ttl in match t with - | None -> error loc "symbol %s is a predicate, not a function" f + | None -> + if silent then raise Backtrack; + error loc "symbol %s is a predicate, not a function" f | Some t -> Tapp(info, label_assoc, tl), t end | PLunop (Ubw_not, t) -> @@ -1787,27 +1904,17 @@ let ty1 = t1.term_type in let t2 = term env t2 in let ty2 = t2.term_type in - let type_binop = function - | Badd -> PlusA - | Bsub -> MinusA - | Bmul -> Mult - | Bdiv -> Div - | Bmod -> Mod - | Bbw_and -> BAnd - | Bbw_or -> BOr - | Bbw_xor -> BXor - | Blshift -> Shiftlt - | Brshift -> Shiftrt - in let binop op tr = TBinOp (op, mk_cast t1 tr, mk_cast t2 tr), logic_arithmetic_promotion tr in begin match op with - | Bmul | Bdiv when is_arithmetic_type ty1 && is_arithmetic_type ty2 -> + | Bmul | Bdiv + when is_arithmetic_type ty1 && is_arithmetic_type ty2 -> binop (type_binop op) (arithmetic_conversion ty1 ty2) | Bmod when is_integral_type ty1 && is_integral_type ty2 -> binop (type_binop op) (arithmetic_conversion ty1 ty2) - | Badd | Bsub when is_arithmetic_type ty1 && is_arithmetic_type ty2 -> + | Badd | Bsub + when is_arithmetic_type ty1 && is_arithmetic_type ty2 -> binop (type_binop op) (arithmetic_conversion ty1 ty2) | Bbw_and | Bbw_or | Bbw_xor when is_integral_type ty1 && is_integral_type ty2 -> @@ -1818,13 +1925,21 @@ | Badd when isLogicPointer t1 && is_integral_type ty2 -> let t1 = mk_logic_pointer_or_StartOf t1 in let ty1 = t1.term_type in - TBinOp (PlusPI, t1, mk_cast t2 (integral_promotion ty2)), + (match t1.term_node with + | TStartOf lv -> + TAddrOf (Cil.addTermOffsetLval (TIndex (t2,TNoOffset)) lv) + | _ -> + TBinOp (PlusPI, t1, mk_cast t2 (integral_promotion ty2))), set_conversion ty1 ty2 | Badd when is_integral_type ty1 && isLogicPointer t2 -> let t2 = mk_logic_pointer_or_StartOf t2 in let ty2 = t2.term_type in assert (isLogicPointerType t2.term_type); - TBinOp (PlusPI, t2, mk_cast t1 (integral_promotion ty1)), + (match t2.term_node with + | TStartOf lv -> + TAddrOf (Cil.addTermOffsetLval (TIndex(t1,TNoOffset)) lv) + | _ -> + TBinOp (PlusPI, t2, mk_cast t1 (integral_promotion ty1))), set_conversion ty2 ty1 | Bsub when isLogicPointer t1 && is_integral_type ty2 -> let t1 = mk_logic_pointer_or_StartOf t1 in @@ -1849,12 +1964,17 @@ check_current_label loc env; (* memory access need a current label to have some semantics *) let t = term env t in + if not (isLogicPointer t) then + error loc "%a is not a pointer" d_term t; let t = mk_logic_pointer_or_StartOf t in let struct_type = type_of_pointed t.term_type in let f_ofs, f_type = type_of_field loc f struct_type in (mk_mem ~loc t f_ofs).term_node, f_type - | PLarrget (t1, t2) -> (* TODO: take into account logic arrays. *) + | PLarrget (t1, t2) -> + (* TODO: take into account logic arrays which do not need + labels to be readable. The call to check_current_label has + to be relaxed. *) check_current_label loc env; (* memory access need a current label to have some semantics *) let t1 = term env t1 in @@ -1877,7 +1997,7 @@ then mk_logic_access env t1, t2, type_of_array_elem t1.term_type else if - isLogicArrayType t1.term_type && is_integral_type t2.term_type + isLogicArrayType t2.term_type && is_integral_type t1.term_type then mk_logic_access env t2, t1, type_of_array_elem t2.term_type else error loc "subscripted value is neither array nor pointer" @@ -1886,9 +2006,9 @@ t.term_node, t.term_type | PLif (t1, t2, t3) -> - let t1 = type_bool_term env t1 in - let t2 = term env t2 in - let t3 = term env t3 in + let t1 = type_bool_term ~silent env t1 in + let t2 = term ~silent env t2 in + let t3 = term ~silent env t3 in let ty,ty2,ty3 = conditional_conversion loc env t2.term_type t3.term_type in let t2 = { t2 with term_type = ty2 } in @@ -1898,13 +2018,13 @@ | PLold t -> let lab = find_old_label loc env in let env = Lenv.set_current_logic_label lab env in - let t = term env t in + let t = term ~silent env t in (* could be Tat(t,lab) *) - Told t, t.term_type + Tat (t, Logic_const.old_label), t.term_type | PLat (t, l) -> let lab = find_logic_label loc env l in let env = Lenv.set_current_logic_label lab env in - let t = term env t in + let t = term ~silent env t in Tat (t, lab), t.term_type | PLbase_addr t -> check_current_label loc env; @@ -1930,7 +2050,7 @@ match t.lv_type with Ctype ty -> TLval(TResult ty,TNoOffset), t.lv_type - | _ -> Cilmsg.fatal "\\result associated to non-C type" + | _ -> Kernel.fatal "\\result associated to non-C type" (* \\result is the value returned by a C function. It has always a C type *) with Not_found -> error loc "\\result meaningless") @@ -1939,12 +2059,17 @@ let t = term env t in (* no casts of tsets in grammar *) (match unroll_type ~unroll_typedef:false (logic_type loc env ty) with - | (Ctype ty) as cty - -> - (*TODO: Use c_mk_cast or handle conversion from array to ptr*) - TCastE (ty, t), cty - | Linteger | Lreal | Ltype _ | Lvar _ | Larrow _ -> - error loc "cannot cast to logic type") + | (Ctype tnew) as ctnew -> + (match t.term_type with + | Ctype told -> + if isPointerType tnew && isArrayType told + && not (is_C_array t) then + error loc + "cannot cast logic array to pointer type"; + (c_mk_cast t told tnew).term_node , ctnew + | _ -> TCastE (tnew, t), ctnew) + | Linteger | Lreal | Ltype _ | Lvar _ | Larrow _ -> + error loc "cannot cast to logic type") | PLcoercion (t,ty) -> let t = term env t in (match unroll_type ~unroll_typedef:false (logic_type loc env ty) with @@ -1965,9 +2090,9 @@ mk_cast { t2 with term_type = ty2} t) in let loc = loc_join t1.lexpr_loc t2.lexpr_loc in - let t1 = term env t1 in + let t1 = term ~silent env t1 in let ty1 = t1.term_type in - let t2 = term env t2 in + let t2 = term ~silent env t2 in let ty2 = t2.term_type in if not (is_plain_type ty1) || not (is_plain_type ty2) then error loc "comparison of incompatible types %a and %a" @@ -1975,14 +2100,13 @@ else let expr = match op with | _ when plain_arithmetic_type ty1 && plain_arithmetic_type ty2 -> - let tr = arithmetic_conversion ty1 ty2 in - TBinOp(binop_of_rel op,mk_cast t1 tr,mk_cast t2 tr) + conditional_conversion t1 t2 | Eq | Neq when isLogicPointer t1 && isLogicNull t2 -> let t1 = mk_logic_pointer_or_StartOf t1 in - TBinOp (binop_of_rel op, t1, mk_cast t2 ty1) + TBinOp (binop_of_rel op, t1, mk_cast t2 t1.term_type) | Eq | Neq when isLogicPointer t2 && isLogicNull t1 -> let t2 = mk_logic_pointer_or_StartOf t2 in - TBinOp (binop_of_rel op, mk_cast t1 ty2, t2) + TBinOp (binop_of_rel op, mk_cast t1 t2.term_type, t2) | Eq | Neq when isLogicArrayType t1.term_type && isLogicArrayType t2.term_type -> @@ -2019,18 +2143,18 @@ TDataCons(cfalse,[]), Ltype(cfalse.ctor_type,[]) | PLlambda(prms,e) -> let (prms, env) = add_quantifiers loc prms env in - let e = term env e in + let e = term ~silent env e in Tlambda(prms,e),Larrow(List.map (fun x -> x.lv_type) prms,e.term_type) | PLnot t -> - let t = type_bool_term env t in + let t = type_bool_term ~silent env t in TUnOp(LNot,t), Ltype (C.find_logic_type Utf8_logic.boolean,[]) | PLand (t1,t2) -> - let t1 = type_bool_term env t1 in - let t2 = type_bool_term env t2 in + let t1 = type_bool_term ~silent env t1 in + let t2 = type_bool_term ~silent env t2 in TBinOp(LAnd,t1,t2), Ltype (C.find_logic_type Utf8_logic.boolean,[]) | PLor (t1,t2) -> - let t1 = type_bool_term env t1 in - let t2 = type_bool_term env t2 in + let t1 = type_bool_term ~silent env t1 in + let t2 = type_bool_term ~silent env t2 in TBinOp(LOr,t1,t2), Ltype (C.find_logic_type Utf8_logic.boolean,[]) | PLtypeof t1 -> let t1 = term env t1 in @@ -2058,7 +2182,7 @@ var.l_profile <- args; var.l_body <- LBterm tdef; let env = Lenv.add_logic_info ident var env in - let tbody = term env body in + let tbody = term ~silent env body in Tlet(var,tbody), tbody.term_type | PLcomprehension(t,quants,pred) -> let quants, env = add_quantifiers loc quants env in @@ -2122,9 +2246,10 @@ (Trange(t1,t2), Ltype(C.find_logic_type "set", [arithmetic_conversion ty1 ty2])) | PLvalid _ | PLvalid_index _ | PLvalid_range _ | PLfresh _ - | PLexists _ | PLforall _ | PLimplies _ | PLiff _ + | PLinitialized _ | PLexists _ | PLforall _ | PLimplies _ | PLiff _ | PLxor _ | PLsubtype _ | PLseparated _ -> - error loc "syntax error (expression expected but predicate found)" + if silent then raise Backtrack; + error loc "syntax error (expression expected but predicate found)" and term_lval f t = let check_lval t = @@ -2133,7 +2258,8 @@ | Tat({term_node = TLval(h,_ as lv)},_) -> (match h with - TVar { lv_name = v; lv_origin = None } -> + TVar { lv_name = v; lv_origin = None } + when v <> "\\exit_status" -> error t.term_loc "not an assignable left value: %s" v (* Tresult only exists when typing C functions and Tmem would lead to an error earlier if applied @@ -2185,6 +2311,11 @@ let env, tl = type_arguments ~overloaded:true env loc params ttl in + let tl = + List.combine + (List.map (fun v -> v.lv_type) info.l_profile) + tl + in let label_assoc = labels_assoc loc f env info.l_labels labels in match info.l_type with @@ -2207,7 +2338,7 @@ let tl = List.map (fun t -> t.term_type) ttl in error loc "no such predicate or logic function %s(%a)" f (Pretty_utils.pp_list ~sep:",@ " d_logic_type) tl - | [x] -> x + | [x,y,z,t] -> (x,y,snd (List.split z),t) | _ -> let tl = List.map (fun t -> t.term_type) ttl in error loc "ambiguous logic call to %s(%a)" f @@ -2220,8 +2351,8 @@ "integer expected but %a found" d_logic_type tt.term_type; tt - and type_bool_term env t = - let tt = term env t in + and type_bool_term ?(silent=false) env t = + let tt = term ~silent env t in if not (plain_boolean_type tt.term_type) then error t.lexpr_loc "boolean expected but %a found" d_logic_type tt.term_type; @@ -2289,47 +2420,37 @@ and predicate env p0 = let loc = p0.lexpr_loc in match p0.lexpr_node with - | PLfalse -> pfalse - | PLtrue -> ptrue + | PLfalse -> unamed ~loc Pfalse + | PLtrue -> unamed ~loc Ptrue | PLrel (t1, (Eq | Neq | Lt | Le | Gt | Ge as op), t2) -> let loc = loc_join t1.lexpr_loc t2.lexpr_loc in let t1 = term env t1 in let ty1 = t1.term_type in let t2 = term env t2 in let ty2 = t2.term_type in - let type_binop = function - | Eq -> Cil_types.Req - | Neq -> Cil_types.Rneq - | Lt -> Cil_types.Rlt - | Le -> Cil_types.Rle - | Gt -> Cil_types.Rgt - | Ge -> Cil_types.Rge - in - let binop op tr = - prel ~loc (op, mk_cast t1 tr, mk_cast t2 tr) in let conditional_conversion t1 t2 = let t,ty1,ty2 = conditional_conversion loc env t1.term_type t2.term_type in prel ~loc - (type_binop op, + (type_rel op, mk_cast { t1 with term_type = ty1} t, mk_cast { t2 with term_type = ty2} t) in begin match op with | _ when is_arithmetic_type ty1 && is_arithmetic_type ty2 -> - binop (type_binop op) (arithmetic_conversion ty1 ty2) + conditional_conversion t1 t2 | Eq | Neq when isLogicPointer t1 && isLogicNull t2 -> let t1 = mk_logic_pointer_or_StartOf t1 in - prel ~loc (type_binop op, t1, mk_cast t2 ty1) + prel ~loc (type_rel op, t1, mk_cast t2 t1.term_type) | Eq | Neq when isLogicPointer t2 && isLogicNull t1 -> let t2 = mk_logic_pointer_or_StartOf t2 in - prel ~loc (type_binop op, mk_cast t1 ty2, t2) + prel ~loc (type_rel op, mk_cast t1 t2.term_type, t2) | Eq | Neq when isLogicArrayType ty1 && isLogicArrayType ty2 -> if is_same_logic_array_type ty1 ty2 then - prel ~loc (type_binop op, t1, t2) + prel ~loc (type_rel op, t1, t2) else error loc "comparison of incompatible types %a and %a" d_logic_type ty1 d_logic_type ty2 @@ -2341,7 +2462,7 @@ (isLogicVoidPointerType t1.term_type || isLogicVoidPointerType t2.term_type)) then - prel ~loc (type_binop op, t1, t2) + prel ~loc (type_rel op, t1, t2) else if (op=Eq || op = Neq) then conditional_conversion t1 t2 else @@ -2383,9 +2504,9 @@ | PLif (t, p1, p2) -> begin try - let t = type_bool_term env t in + let t = type_bool_term ~silent:true env t in pif ~loc:p0.lexpr_loc (t, predicate env p1, predicate env p2) - with _ -> + with Backtrack -> (* p1 ? p2 : p3 is syntactic sugar for (p1 ==> p2) && (!p1 ==> p3) *) predicate env {lexpr_node = @@ -2431,6 +2552,12 @@ let t = mk_logic_pointer_or_StartOf t in check_non_void_ptr t.term_loc t.term_type; pvalid_range ~loc:p0.lexpr_loc (t,a,b) + | PLinitialized (t) -> + check_current_label loc env; + let t = term env t in + let t = mk_logic_pointer_or_StartOf t in + check_non_void_ptr t.term_loc t.term_type; + pinitialized ~loc:p0.lexpr_loc t | PLold p -> let lab = find_old_label p0.lexpr_loc env in let env = Lenv.set_current_logic_label lab env in @@ -2442,37 +2569,40 @@ pat ~loc:p0.lexpr_loc (predicate env p, lab) | PLvar x -> (try - let def = C.find_macro x + let def = C.find_macro x in predicate env def with Not_found -> let loc = p0.lexpr_loc in - (* TODO: accept a predicate with arguments here (see terms) *) + let make_app info = + match info.l_type with + | None -> + let labels = match info.l_labels with + [] -> [] + | [l] -> [l,find_current_label loc env] + | _ -> + error loc + "%s labels must be explicitely instantiated" x + in + papp ~loc (info,labels,[]) + | Some _ -> boolean_to_predicate env p0 + in + try make_app (Lenv.find_logic_info x env) + with Not_found -> (try let info = List.find (fun x -> x.l_profile = []) (C.find_all_logic_functions x) - in - match info.l_type with - | None -> - let labels = match info.l_labels with - [] -> [] - | [l] -> [l,find_current_label loc env] - | _ -> - error loc - "%s labels must be explicitely instantiated" x - in - papp ~loc (info,labels,[]) - | Some _ -> boolean_to_predicate env p0 + in make_app info with Not_found -> boolean_to_predicate env p0)) | PLlet(x,def,body) -> let typ, args, tdef = try - let tdef = term env def in + let tdef = term ~silent:true env def in let tdef = normalize_lambda_term env tdef in (match tdef.term_node with Tlambda(args,t) -> Some t.term_type, args, LBterm t | _ -> Some tdef.term_type,[], LBterm tdef) - with Log.AbortError _ -> + with Backtrack -> let args, tdef = abstract_predicate env def in None, args, LBpred tdef in @@ -2514,27 +2644,23 @@ | PLcomprehension _ | PLsingleton _ | PLunion _ | PLinter _ | PLempty -> error p0.lexpr_loc "expecting a predicate and not tsets" - let type_variant env = function - | (t, None) -> (type_int_term env t, None) - | (t, r) -> (term env t, r) - (* checks if the given offset points to a location inside a formal. *) - let is_substructure off = + and is_substructure off = let rec aux is_array_field off = match off with TNoOffset -> true | TField (f,o) -> aux (Cil.isArrayType f.ftype) o - | TIndex(_,o) -> + | TIndex(_,o) -> (* if we are in the an array field, the element is still part of - the structure. Otherwise, this is an index to a memory cell + the structure. Otherwise, this is an index to a memory cell outside of the current region. *) is_array_field && aux is_array_field o - (* The formal is never an array by definition: + (* The formal is never an array by definition: start recursion with false. *) in aux false off - let term_lval_assignable ~accept_formal env t = + and term_lval_assignable ~accept_formal env t = let f t = if isLogicArrayType t.term_type then error t.term_loc "not an assignable left value: %a" d_term t @@ -2553,7 +2679,7 @@ None -> t | Some v -> if v.vformal && is_substructure o then - error t.term_loc + error t.term_loc "can not assign part of a formal parameter: %a" Cil.d_term t else t) @@ -2563,9 +2689,18 @@ end in lift_set f (term env t) + (* silent is an internal argument that should not escape the scope of this + module. + *) + let term env t = term ~silent:false env t + + let type_variant env = function + | (t, None) -> (type_int_term env t, None) + | (t, r) -> (term env t, r) + let type_from ~accept_formal env (l,d) = (* Yannick: [assigns *\at(\result,Post)] should be allowed *) - let tl = + let tl = term_lval_assignable ~accept_formal env l in let tl = Logic_const.new_identified_term tl in @@ -2573,12 +2708,12 @@ FromAny -> (tl,FromAny) | From f -> - let tf = - List.map (term_lval_assignable ~accept_formal:true env) f + let tf = + List.map (term_lval_assignable ~accept_formal:true env) f in - let tf = + let tf = List.map - (fun td -> + (fun td -> if Logic_utils.contains_result td then error td.term_loc "invalid \\result in dependencies"; Logic_const.new_identified_term td) @@ -2589,7 +2724,20 @@ let type_assign ~accept_formal env a = match a with WritesAny -> WritesAny - | Writes l -> Writes (List.map (type_from ~accept_formal env) l) + | Writes l -> + let res = List.map (type_from ~accept_formal env) l in + (* we drop assigns \result; and assigns \exit_status; without from + clause, as this does not convey any information. + *) + let res = + List.filter + (fun (l,f) -> + not (Logic_const.is_result l.it_content + || Logic_const.is_exit_status l.it_content) + || f <> FromAny) + res + in + Writes res let id_predicate env pred = Logic_const.new_predicate (predicate env pred) @@ -2610,6 +2758,21 @@ infos.l_body <- LBpred body; C.add_logic_function infos; infos + let model_annot loc ti = + let env = (Lenv.empty()) in + let model_for_type = logic_type loc env ti.model_for_type in + let model_type = logic_type loc env ti.model_type in + (* + let v = Cil_const.make_logic_var ti.model_name model_type in + (ti.model_for_type, v) + *) + let v = Cil_const.make_logic_var "this" model_for_type in + let infos = Cil_const.make_logic_info ti.model_name in + infos.l_profile <- [v]; + infos.l_type <- Some model_type; + infos.l_labels <- [Logic_const.here_label]; + C.add_logic_function infos; infos + let check_behavior_names loc existing_behaviors names = List.iter (fun x -> if not (List.mem x existing_behaviors) then @@ -2641,13 +2804,15 @@ let type_spec old_behaviors loc is_stmt_contract result env s = let env = append_here_label env in let env_with_result = add_result env result in + let env_with_result_and_exit_status = add_exit_status env_with_result in (* assigns_env is a bit special: - both \result and \exit_status (in a \at(_,Post) term are admissible) - Old and Post labels are admissible - Default label is Old (Assigns are evaluated in Pre-state *) - let assigns_env = append_old_and_post_labels env_with_result in + let assigns_env = + append_old_and_post_labels env_with_result_and_exit_status in let old = Lenv.find_logic_label "Old" assigns_env in let assigns_env = Lenv.set_current_logic_label old assigns_env in @@ -2659,7 +2824,8 @@ | Returns -> env_with_result | Normal when is_stmt_contract -> env | Normal -> env_with_result - | Exits | Breaks | Continues -> env + | Exits -> add_exit_status env + | Breaks | Continues -> env in Lenv.enter_post_state (append_old_and_post_labels env) k in @@ -2676,8 +2842,8 @@ let b = List.map (fun {b_assigns= ba; b_name = bn; b_post_cond=be; b_assumes= bas; b_requires=br; b_extended=bext} -> - let result = - { b_assigns= + let result = + { b_assigns= type_assign ~accept_formal:is_stmt_contract assigns_env ba; b_name = bn; b_post_cond = @@ -2726,7 +2892,7 @@ } let funspec old_behaviors vi formals typ s = - let env = append_pre_label ~pre_is_old:true (Lenv.funspec()) in + let env = append_pre_label (Lenv.funspec()) in let log_return_typ = Ctype (Cil.getReturnType typ) in let env = match formals with @@ -2753,7 +2919,7 @@ | IPstmt as ip -> ip let code_annot_env () = - append_here_label (append_pre_label ~pre_is_old:false (Lenv.empty())) + append_here_label (append_pre_label (Lenv.empty())) let code_annot loc current_behaviors current_return_type ca = let annot = match ca with @@ -2766,24 +2932,25 @@ APragma (Slice_pragma (slice_pragma (code_annot_env()) sp)) | APragma (Loop_pragma lp) -> APragma (Loop_pragma (loop_pragma (code_annot_env()) lp)) - | AStmtSpec s -> + | AStmtSpec (behav,s) -> (* function behaviors and statement behaviors are not at the same level. Do not mix them in a complete or disjoint clause here. *) - let env = append_pre_label ~pre_is_old:false (Lenv.empty()) in + check_behavior_names loc current_behaviors behav; + let env = append_pre_label (Lenv.empty()) in let my_spec = type_spec [] loc true current_return_type env s in ignore (check_unique_behavior_names loc current_behaviors my_spec.spec_behavior); - AStmtSpec my_spec + AStmtSpec (behav,my_spec) | AVariant v -> AVariant (type_variant (code_annot_env ()) v) | AInvariant (behav,f,i) -> check_behavior_names loc current_behaviors behav; AInvariant (behav,f,predicate (code_annot_env()) i) - | AAssigns (behav,a) -> + | AAssigns (behav,a) -> AAssigns (behav,type_assign ~accept_formal:true (code_annot_env()) a) in Logic_const.new_code_annotation annot @@ -2920,7 +3087,7 @@ info.l_body <- (match l with | Some l -> - let l = + let l = List.map (fun x -> new_identified_term (term env x)) l in LBreads l @@ -3022,9 +3189,95 @@ Dinvariant (li,loc) | LDtype_annot l -> Dtype_annot (type_annot loc l,loc) - | LDvolatile (_tsets, (_rd_opt, _wr_opt)) -> - error loc "Volatile clauses are not yet implemented" - + | LDmodel_annot l -> + Dmodel_annot (model_annot loc l,loc) + | LDvolatile (tsets, (rd_opt, wr_opt)) -> + let tsets = + List.map + (term_lval_assignable ~accept_formal:false (Lenv.empty ())) tsets + in + let checks_tsets_type fct typ = + List.iter + (fun t -> + if + not (Logic_const.plain_or_set (is_same_type ~drop_attributes:false typ) t.term_type) + then + error t.term_loc "incompatible return type of '%s' with %a" + fct Cil.d_term t) + tsets + in + let checks_reads_fct fct ty = + let error () = + error loc + "incompatible type of '%s' with volatile writes declaration" + fct; + in let ret,args,is_varg_arg,_attrib = + if not (Cil.isFunctionType ty) then + error (); + Cil.splitFunctionType ty + in let volatile_ret_type = Ctype (typeAddAttributes [Attr ("volatile",[])] ret) + in let ret_type = (Ctype ret) + in match args with + | Some [_,arg1,_] when + (not (isVoidType ret || is_varg_arg)) + && isPointerType arg1 + && is_same_type ~drop_attributes:false (Ctype (typeOf_pointed arg1)) volatile_ret_type + -> (* matching prototype: T fct (volatile T *arg1) *) + checks_tsets_type fct volatile_ret_type (* tsets should have type: volatile T *) + | Some [_,arg1,_] when + (not (isVoidType ret || is_varg_arg)) + && isPointerType arg1 + && is_same_type ~drop_attributes:false (Ctype (typeOf_pointed arg1)) ret_type + && Cil.hasLvalTypeSomeVolatileAttr ret + -> (* matching prototype: T fct (T *arg1) when T has some volatile attr*) + checks_tsets_type fct ret_type (* tsets should have type: T *) + | _ -> + error () + in + let checks_writes_fct fct ty = + let error () = + error loc + "incompatible type of '%s' with volatile writes declaration" + fct; + in let ret,args,is_varg_arg,_attrib = + if not (Cil.isFunctionType ty) then + error (); + Cil.splitFunctionType ty + in let volatile_ret_type = Ctype (typeAddAttributes [Attr ("volatile",[])] ret) + in let ret_type = (Ctype ret) + in match args with + | Some ((_,arg1,_)::[_,arg2,_]) when + (not (isVoidType ret || is_varg_arg)) + && isPointerType arg1 + && is_same_type ~drop_attributes:false (Ctype arg2) ret_type + && is_same_type ~drop_attributes:false (Ctype (typeOf_pointed arg1)) volatile_ret_type + -> (* matching prototype: T fct (volatile T *arg1, T arg2) *) + checks_tsets_type fct volatile_ret_type (* tsets should have type: volatile T *) + | Some ((_,arg1,_)::[_,arg2,_]) when + (not (isVoidType ret || is_varg_arg)) + && isPointerType arg1 + && is_same_type ~drop_attributes:false (Ctype arg2) ret_type + && is_same_type ~drop_attributes:false (Ctype (typeOf_pointed arg1)) ret_type + && Cil.hasLvalTypeSomeVolatileAttr ret + -> (* matching prototype: T fct (T *arg1, T arg2) when T has some volatile attr *) + checks_tsets_type fct ret_type (* tsets should have type: T *) + | _ -> + error () + in + let get_volatile_fct checks_type = function + | None -> None + | Some fct -> + try (match (C.find_var fct).lv_origin + with + | None -> raise Not_found + | Some vi as vi_opt-> checks_type fct vi.vtype ; vi_opt) + with Not_found -> + error loc "cannot find function '%s' for volatile clause" fct + in + let tsets = List.map (Logic_const.new_identified_term) tsets in + let rvi_opt = get_volatile_fct checks_reads_fct rd_opt in + let wvi_opt = get_volatile_fct checks_writes_fct wr_opt in + Dvolatile (tsets, rvi_opt, wvi_opt, loc) end (* diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_typing.mli frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_typing.mli --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_typing.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_typing.mli 2011-10-10 08:40:07.000000000 +0000 @@ -27,6 +27,33 @@ open Cil_types +(** Relation operators conversion + @since Nitrogen-20111001 +*) +val type_rel: Logic_ptree.relation -> Cil_types.relation + +(** Arithmetic binop conversion. Addition and Substraction are always + considered as being used on integers. It is the responsibility of the + user to introduce PlusPI/IndexPI, MinusPI and MinusPP where needed. + @since Nitrogen-20111001 +*) +val type_binop: Logic_ptree.binop -> Cil_types.binop + +val unescape: string -> string +val wcharlist_of_string: string -> int64 list + +val is_arithmetic_type: Cil_types.logic_type -> bool +val is_integral_type: Cil_types.logic_type -> bool + +val type_of_pointed: logic_type -> logic_type + +val type_of_array_elem: logic_type -> logic_type + +val add_offset_lval: term_offset -> term_lval -> term_lval + +val arithmetic_conversion: + Cil_types.logic_type -> Cil_types.logic_type -> Cil_types.logic_type + (** Local logic environment *) module Lenv : sig type t @@ -35,7 +62,7 @@ (** Functions that can be called when type-checking an extension of ACSL. *) type typing_context = { - annonCompFieldName : string; + anonCompFieldName : string; conditionalConversion : typ -> typ -> typ; find_macro : string -> Logic_ptree.lexpr; find_var : string -> logic_var; @@ -91,7 +118,7 @@ module Make (C : sig - val annonCompFieldName : string + val anonCompFieldName : string val conditionalConversion : typ -> typ -> typ val find_macro : string -> Logic_ptree.lexpr val find_var : string -> logic_var @@ -113,9 +140,23 @@ val find_logic_type: string -> logic_type_info val find_logic_ctor: string -> logic_ctor_info + (** What to do when we have a term of type Integer in a context + expecting a C integral type. + @raise Failure to reject such conversion + @since Nitrogen-20111001 + *) + val integral_cast: Cil_types.typ -> Cil_types.term -> Cil_types.term + end) : sig + (** @since Nitrogen-20111001 *) + val type_of_field: + location -> string -> logic_type -> (term_offset * logic_type) + + (** @since Nitrogen-20111001 *) + val mk_cast: Cil_types.term -> Cil_types.logic_type -> Cil_types.term + (** type-checks a term. *) val term : Lenv.t -> Logic_ptree.lexpr -> term @@ -134,6 +175,9 @@ val type_annot : location -> Logic_ptree.type_annot -> logic_info + val model_annot : + location -> Logic_ptree.model_annot -> logic_info + val annot : Logic_ptree.decl -> global_annotation (** [funspec behaviors f prms typ spec] type-checks a function contract. @@ -161,7 +205,7 @@ when [pre_is_old] is true, it adds it has a synonym for "Old". (the latter should be set when typing function contracts) *) -val append_pre_label: pre_is_old:bool -> Lenv.t -> Lenv.t +val append_pre_label: Lenv.t -> Lenv.t (** adds a given variable in local environment. *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_utils.ml frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_utils.ml --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_utils.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_utils.ml 2011-10-10 08:40:07.000000000 +0000 @@ -50,7 +50,7 @@ try List.combine tdef.lt_params prms with Invalid_argument _ -> - Cilmsg.fatal "Logic type used with wrong number of parameters" + Kernel.fatal "Logic type used with wrong number of parameters" in unroll_type ~unroll_typedef (instantiate subst ty) ) @@ -58,10 +58,14 @@ | Linteger | Lreal | Lvar _ | Larrow _ | Ctype _ as ty -> ty (* compute type signature and removes unnecessary attributes *) - let type_sig_logic ty = - let doattr = - Cil.dropAttributes ["const"; "restrict"; "declspec"; "arraylen"] - in +let type_sig_logic ?(drop_attributes=true) ty = + let attr = + if drop_attributes then + ["const"; "restrict"; "declspec";"arraylen"; "volatile"] + else [] + in + let doattr = Cil.dropAttributes attr + in typeSigWithAttrs doattr ty (* ************************************************************************* *) @@ -100,25 +104,27 @@ in let length_attr = match lo with - None -> [] - | Some _ -> begin - try - let len = Cil.bitsSizeOf tarr in - let len = try len / (Cil.bitsSizeOf ty) - with Cil.SizeOfError _ -> - Cilmsg.fatal - "Inconsistent information: I know the length of \ - array type %a, but not of its elements." - Cil.d_type tarr - in - (* Normally, overflow is checked in bitsSizeOf itself *) - let la = AInt len in - [ Attr("arraylen",[la])] + | None -> [] + | Some _ -> + (* [JS 2011/03/11] inconsistency between uses of [Kernel.fatal] and + [Kernel.warning]. The first one does not use ~current:true, but + the last one does *) + try + let len = Cil.bitsSizeOf tarr in + let len = try len / (Cil.bitsSizeOf ty) with Cil.SizeOfError _ -> - Cil.warning - "Cannot represent length of array as an attribute"; - [] - end + Kernel.fatal + "Inconsistent information: I know the length of \ + array type %a, but not of its elements." + Cil.d_type tarr + in + (* Normally, overflow is checked in bitsSizeOf itself *) + let la = AInt len in + [ Attr("arraylen",[la])] + with Cil.SizeOfError _ -> + Kernel.warning ~current:true + "Cannot represent length of array as an attribute"; + [] in Ctype(TPtr(aux (Cil.filter_qualifier_attributes attr) ty, Cil.addAttributes length_attr attr)) @@ -140,9 +146,9 @@ let translate_old_label s p = let get_label () = match s.labels with - | [] -> - s.labels <- - [Label (Printf.sprintf "__sid_%d_label" s.sid, + | [] -> + s.labels <- + [Label (Printf.sprintf "__sid_%d_label" s.sid, Cil_datatype.Stmt.loc s,false)] | _ -> () in @@ -159,14 +165,10 @@ let vis = object inherit Cil.nopCilVisitor method vpredicate = function - | Pold p -> - ChangeDoChildrenPost(make_new_at_predicate p,fun x -> x) | Pat(p,lab) when lab = Logic_const.old_label -> ChangeDoChildrenPost(make_new_at_predicate p, fun x -> x) | _ -> DoChildren method vterm_node = function - | Told t -> - ChangeDoChildrenPost(make_new_at_term t,fun x -> x) | Tat(t,lab) when lab = Logic_const.old_label -> ChangeDoChildrenPost(make_new_at_term t, fun x->x) | _ -> DoChildren @@ -190,7 +192,6 @@ (match t.term_node with | TStartOf (lh,_) -> is_C_array_lhost lh | TLval(lh,_) -> is_C_array_lhost lh - | Told t | Tat(t,_) -> is_C_array t | Tif(_,t1,t2) -> is_C_array t1 && is_C_array t2 | Tlet (_,t) -> is_C_array t | _ -> false) @@ -202,10 +203,6 @@ let my_type = array_to_ptr t.term_type in match t.term_node with TLval s -> { t with term_node = TStartOf s; term_type = my_type } - | Told t -> - { t with term_node = Told (mk_logic_StartOf t); term_type = my_type } - | Tat (t,l) -> - { t with term_node = Tat(mk_logic_StartOf t,l); term_type = my_type } | Tif(c,t1,t2) -> { t with term_node = Tif(c,mk_logic_StartOf t1, mk_logic_StartOf t2); @@ -214,7 +211,7 @@ | Tlet (body,t) -> { t with term_node = Tlet(body, mk_logic_StartOf t); term_type = my_type } - | _ -> Cilmsg.fatal "mk_logic_StartOf given a non-C-array term" + | _ -> Kernel.fatal "mk_logic_StartOf given a non-C-array term" let isLogicPointer t = isLogicPointerType t.term_type || (is_C_array t) @@ -222,7 +219,8 @@ let mk_logic_pointer_or_StartOf t = if isLogicPointer t then if is_C_array t then mk_logic_StartOf t else t - else Cilmsg.fatal "%a is neither a pointer nor a C array" d_term t + else Kernel.fatal ~source:(fst t.term_loc) + "%a is neither a pointer nor a C array" d_term t let rec expr_to_term ~cast:cast e = let e_typ = Cil.typeOf e in @@ -278,16 +276,25 @@ let array_with_range arr size = - let arr = Cil.mkCast arr Cil.charPtrType in - let arr' = expr_to_term ~cast:false arr + let loc = arr.eloc in + let insert_cast = match unrollType (typeOf arr) with + | TPtr (typ, _) -> not (sizeOf_int typ = sizeOf_int charType) + | _ -> true + in + let char_ptr = typ_to_logic_type Cil.charPtrType in + let arr = expr_to_term ~cast:true arr in + let arr = + if insert_cast + then Logic_const.term ~loc (TCastE(Cil.charPtrType, arr)) char_ptr + else arr and range_end = Logic_const.term ~loc:size.term_loc - (TBinOp (MinusA, size, Cil.lconstant 1L)) + (TBinOp (MinusA, size, Cil.lconstant My_bigint.one)) size.term_type in - let range = Logic_const.trange (Some (Cil.lconstant 0L), Some (range_end)) in - Logic_const.term ~loc:arr.eloc (TBinOp (PlusPI, arr', range)) - (typ_to_logic_type Cil.charPtrType) + let range = Logic_const.trange (Some (Cil.lconstant My_bigint.zero), + Some (range_end)) in + Logic_const.term ~loc(TBinOp (PlusPI, arr, range)) char_ptr (* ************************************************************************* *) @@ -320,7 +327,6 @@ match t.term_node with TLval(v,offs) -> lval_contains_result v || loffset_contains_result offs | Tat(t,_) -> contains_result t - | Told t -> contains_result t | _ -> false (** @return the definition of a predicate. @@ -330,18 +336,31 @@ let is_result = Logic_const.is_result + +let is_trivially_false p = + match p.content with + Pfalse -> true + | _ -> false + +let is_trivially_true p = + match p.content with + Ptrue -> true + | _ -> false + let is_same_list f l1 l2 = try List.for_all2 f l1 l2 with Invalid_argument _ -> false +(* [VP 2011-04-19] StmtLabel case is a bit restricted, but it's not really + possible to do any better, and this function should not be called in + contexts where it matters. *) let is_same_logic_label l1 l2 = match l1, l2 with StmtLabel s1, StmtLabel s2 -> !s1 == !s2 | StmtLabel _, LogicLabel _ - | LogicLabel _, StmtLabel _ - | LogicLabel (Some _,_), LogicLabel (None, _) - | LogicLabel (None,_), LogicLabel (Some _, _) -> false - | LogicLabel (Some s1, l1), LogicLabel (Some s2, l2) -> (s1 == s2) && (l1 = l2) - | LogicLabel (None, l1), LogicLabel (None, l2) -> l1 = l2 + | LogicLabel _, StmtLabel _ -> false + (* What is important here is the name of the logic label, not + the hypothetical statement it is referring to. *) + | LogicLabel (_, l1), LogicLabel (_, l2) -> l1 = l2 let is_same_opt f x1 x2 = match x1,x2 with @@ -349,20 +368,23 @@ | Some x1, Some x2 -> f x1 x2 | None, _ | _, None -> false -let rec is_same_type t1 t2 = - match t1,t2 with - Ctype t1, Ctype t2 -> - Cilutil.equals (type_sig_logic t1) (type_sig_logic t2) - | Ltype(t1,l1), Ltype(t2,l2) -> - t1.lt_name = t2.lt_name && List.for_all2 is_same_type l1 l2 - | Linteger, Linteger -> true - | Lreal, Lreal -> true - | Lvar v1, Lvar v2 -> v1 = v2 - | Larrow(args1,rt1), Larrow(args2,rt2) -> - is_same_list is_same_type args1 args2 && is_same_type rt1 rt2 - | (Ctype _| Ltype _ | Linteger | Lreal | Lvar _ | Larrow _), - (Ctype _| Ltype _ | Linteger | Lreal | Lvar _ | Larrow _) -> - false +let is_same_type ?(drop_attributes=true) t1 t2 = + let rec is_same_type t1 t2 = + match t1,t2 with + Ctype t1, Ctype t2 -> + let type_sig_logic = type_sig_logic ~drop_attributes in + Cilutil.equals (type_sig_logic t1) (type_sig_logic t2) + | Ltype(t1,l1), Ltype(t2,l2) -> + t1.lt_name = t2.lt_name && List.for_all2 is_same_type l1 l2 + | Linteger, Linteger -> true + | Lreal, Lreal -> true + | Lvar v1, Lvar v2 -> v1 = v2 + | Larrow(args1,rt1), Larrow(args2,rt2) -> + is_same_list is_same_type args1 args2 && is_same_type rt1 rt2 + | (Ctype _| Ltype _ | Linteger | Lreal | Lvar _ | Larrow _), + (Ctype _| Ltype _ | Linteger | Lreal | Lvar _ | Larrow _) -> + false + in is_same_type t1 t2 let is_same_var v1 v2 = v1.lv_name = v2.lv_name && @@ -398,13 +420,17 @@ ci1.ctor_type.lt_name = ci2.ctor_type.lt_name && is_same_list is_same_type ci1.ctor_params ci2.ctor_params -let is_same_constant c1 c2 = +let is_same_constant = Cil.compareConstant + +let rec is_same_pconstant c1 c2 = match c1, c2 with - CEnum e1, CEnum e2 -> - e1.einame = e2.einame && - e1.eival = e2.eival && - e1.eihost.ename = e2.eihost.ename - | _ -> c1 = c2 + | IntConstant c1, IntConstant c2 -> c1 = c2 + | IntConstant _, _ | _, IntConstant _ -> false + | FloatConstant c1, FloatConstant c2 -> c1 = c2 + | FloatConstant _,_ | _,FloatConstant _ -> false + | StringConstant c1, StringConstant c2 -> c1 = c2 + | StringConstant _,_ | _,StringConstant _ -> false + | WStringConstant c1, WStringConstant c2 -> c1 = c2 let rec is_same_term t1 t2 = match t1.term_node, t2.term_node with @@ -426,12 +452,13 @@ | TAddrOf l1, TAddrOf l2 -> is_same_tlval l1 l2 | TStartOf l1, TStartOf l2 -> is_same_tlval l1 l2 | Tapp(f1,labels1, args1), Tapp(f2, labels2, args2) -> - is_same_logic_signature f1 f2 && - List.for_all2 (fun l1 l2 -> l1 = l2) labels1 labels2 && - List.for_all2 is_same_term args1 args2 + is_same_logic_signature f1 f2 + && List.for_all2 + (fun (x,y) (t,z) -> is_same_logic_label x t && is_same_logic_label y z) + labels1 labels2 + && List.for_all2 is_same_term args1 args2 | Tif(c1,t1,e1), Tif(c2,t2,e2) -> is_same_term c1 c2 && is_same_term t1 t2 && is_same_term e1 e2 - | Told t1, Told t2 -> is_same_term t1 t2 | Tat(t1,l1), Tat(t2,l2) -> is_same_term t1 t2 && is_same_logic_label l1 l2 | Tbase_addr t1, Tbase_addr t2 -> is_same_term t1 t2 | Tblock_length t1, Tblock_length t2 -> is_same_term t1 t2 @@ -444,7 +471,7 @@ | Tlambda (v1,t1), Tlambda(v2,t2) -> is_same_list is_same_var v1 v2 && is_same_term t1 t2 | TUpdate(t1,i1,nt1), TUpdate(t2,i2,nt2) -> - is_same_term t1 t2 && i1 == i2 && is_same_term nt1 nt2 + is_same_term t1 t2 && is_same_offset i1 i2 && is_same_term nt1 nt2 | Ttypeof t1, Ttypeof t2 -> is_same_term t1 t2 | Ttype ty1, Ttype ty2 -> @@ -467,7 +494,7 @@ | (TConst _ | TLval _ | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ | TAlignOf _ | TAlignOfE _ | TUnOp _ | TBinOp _ | TCastE _ | TAddrOf _ | TStartOf _ | Tapp _ | Tlambda _ | TDataCons _ - | Tif _ | Told _ | Tat _ | Tbase_addr _ | Tblock_length _ | Tnull + | Tif _ | Tat _ | Tbase_addr _ | Tblock_length _ | Tnull | TCoerce _ | TCoerceE _ | TUpdate _ | Ttypeof _ | Ttype _ | Tcomprehension _ | Tempty_set | Tunion _ | Tinter _ | Trange _ | Tlet _ @@ -544,11 +571,10 @@ is_same_list is_same_var q1 q2 && is_same_named_predicate p1 p2 | Pexists(q1,p1), Pexists(q2,p2) -> is_same_list is_same_var q1 q2 && is_same_named_predicate p1 p2 - | Pold(p1), Pold(p2) -> - is_same_named_predicate p1 p2 | Pat(p1,l1), Pat(p2,l2) -> is_same_named_predicate p1 p2 && is_same_logic_label l1 l2 - | Pvalid t1, Pvalid t2 -> is_same_term t1 t2 + | Pvalid t1, Pvalid t2 + | Pinitialized t1, Pinitialized t2 -> is_same_term t1 t2 | Pvalid_index(l1,h1), Pvalid_index(l2,h2) -> is_same_term l1 l2 && is_same_term h1 h2 | Pvalid_range(b1,l1,h1), Pvalid_range(b2,l2,h2) -> @@ -561,7 +587,7 @@ with Invalid_argument _ -> false) | (Pfalse | Ptrue | Papp _ | Prel _ | Pand _ | Por _ | Pimplies _ | Piff _ | Pnot _ | Pif _ | Plet _ | Pforall _ | Pexists _ - | Pold _ | Pat _ | Pvalid _ | Pvalid_index _ | Pvalid_range _ + | Pat _ | Pvalid _ | Pvalid_index _ | Pvalid_range _ | Pinitialized _ | Pfresh _ | Psubtype _ | Pxor _ | Pseparated _ ), _ -> false @@ -656,7 +682,8 @@ match ca1.annot_content, ca2.annot_content with | AAssert(l1,p1), AAssert(l2,p2) -> is_same_list (=) l1 l2 && is_same_named_predicate p1 p2 - | AStmtSpec s1, AStmtSpec s2 -> is_same_spec s1 s2 + | AStmtSpec (l1,s1), AStmtSpec (l2,s2) -> + is_same_list (=) l1 l2 && is_same_spec s1 s2 | AInvariant(l1,b1,p1), AInvariant(l2,b2,p2) -> is_same_list (=) l1 l2 && b1 = b2 && is_same_named_predicate p1 p2 | AVariant v1, AVariant v2 -> is_same_variant v1 v2 @@ -678,10 +705,15 @@ is_same_list (=) typs1 typs2 && is_same_named_predicate st1 st2 | Dinvariant (li1,_), Dinvariant (li2,_) -> is_same_logic_info li1 li2 | Dtype_annot (li1,_), Dtype_annot (li2,_) -> is_same_logic_info li1 li2 + | Dmodel_annot (li1,_), Dmodel_annot (li2,_) -> is_same_logic_info li1 li2 + | Dvolatile(t1,r1,w1,_), Dvolatile(t2,r2,w2,_) -> + is_same_list is_same_identified_term t1 t2 && + is_same_opt (fun x y -> x.vname = y.vname) r1 r2 && + is_same_opt (fun x y -> x.vname = y.vname) w1 w2 | (Dfun_or_pred _ | Daxiomatic _ | Dtype _ | Dlemma _ - | Dinvariant _ | Dtype_annot _), + | Dinvariant _ | Dtype_annot _ | Dmodel_annot _ | Dvolatile _), (Dfun_or_pred _ | Daxiomatic _ | Dtype _ | Dlemma _ - | Dinvariant _ | Dtype_annot _) -> false + | Dinvariant _ | Dtype_annot _ | Dmodel_annot _ | Dvolatile _) -> false let is_same_axiomatic ax1 ax2 = is_same_list is_same_global_annotation ax1 ax2 @@ -692,7 +724,7 @@ | FloatConstant s1, FloatConstant s2 | StringConstant s1, StringConstant s2 | WStringConstant s1, WStringConstant s2 -> s1 = s2 - | (IntConstant _| FloatConstant _ + | (IntConstant _| FloatConstant _ | StringConstant _ | WStringConstant _), _ -> false let rec is_same_pl_type t1 t2 = @@ -702,7 +734,7 @@ | LTreal, LTreal -> true | LTint k1, LTint k2 -> (match k1, k2 with - | IBool, IBool + | IBool, IBool | IChar, IChar | ISChar, ISChar | IUChar, IUChar @@ -711,11 +743,11 @@ | IShort, IShort | IUShort, IUShort | ILong, ILong - | IULong, IULong + | IULong, IULong | ILongLong, ILongLong | IULongLong, IULongLong -> true | (IBool | IChar | ISChar | IUChar | IInt | IUInt - | IShort | IUShort | ILong + | IShort | IUShort | ILong | IULong | ILongLong | IULongLong), _ -> false ) | LTfloat k1, LTfloat k2 -> @@ -725,14 +757,14 @@ | LTarray (t1,c1), LTarray(t2,c2) -> is_same_pl_type t1 t2 && is_same_opt is_same_pl_constant c1 c2 | LTpointer t1, LTpointer t2 -> is_same_pl_type t1 t2 - | LTenum s1, LTenum s2 | LTstruct s1, LTstruct s2 + | LTenum s1, LTenum s2 | LTstruct s1, LTstruct s2 | LTunion s1, LTunion s2 -> s1 = s2 | LTnamed (s1,prms1), LTnamed(s2,prms2) -> s1 = s2 && is_same_list is_same_pl_type prms1 prms2 | LTarrow(prms1,t1), LTarrow(prms2,t2) -> is_same_list is_same_pl_type prms1 prms2 && is_same_pl_type t1 t2 | (LTvoid | LTinteger | LTreal | LTint _ | LTfloat _ | LTarrow _ - | LTarray _ | LTpointer _ | LTenum _ + | LTarray _ | LTpointer _ | LTenum _ | LTunion _ | LTnamed _ | LTstruct _),_ -> false @@ -753,7 +785,7 @@ | Bbw_and, Bbw_and | Bbw_or, Bbw_or | Bbw_xor, Bbw_xor | Blshift, Blshift | Brshift, Brshift -> true | (Badd | Bsub | Bmul | Bdiv | Bmod | Bbw_and | Bbw_or - | Bbw_xor | Blshift | Brshift),_ -> false + | Bbw_xor | Blshift | Brshift),_ -> false let is_same_relation r1 r2 = match r1, r2 with @@ -770,7 +802,7 @@ match t1, t2 with | PLupdateTerm e1, PLupdateTerm e2 -> is_same_lexpr e1 e2 | PLupdateCont l1, PLupdateCont l2 -> - let is_same_elt (p1,e1) (p2,e2) = + let is_same_elt (p1,e1) (p2,e2) = is_same_list is_same_path_elt p1 p2 && is_same_update_term e1 e2 in is_same_list is_same_elt l1 l2 | (PLupdateTerm _ | PLupdateCont _), _ -> false @@ -780,8 +812,8 @@ | PLvar s1, PLvar s2 -> s1 = s2 | PLapp (s1,l1,arg1), PLapp (s2,l2,arg2) -> s1 = s2 && is_same_list (=) l1 l2 && is_same_list is_same_lexpr arg1 arg2 - | PLlambda(q1,e1), PLlambda(q2,e2) - | PLforall (q1,e1), PLforall(q2,e2) + | PLlambda(q1,e1), PLlambda(q2,e2) + | PLforall (q1,e1), PLforall(q2,e2) | PLexists(q1,e1), PLexists(q2,e2) -> is_same_quantifiers q1 q2 && is_same_lexpr e1 e2 | PLlet(x1,d1,e1), PLlet(x2,d2,e2) -> @@ -791,31 +823,31 @@ is_same_unop op1 op2 && is_same_lexpr e1 e2 | PLbinop(le1,op1,re1), PLbinop(le2,op2,re2) -> is_same_binop op1 op2 && is_same_lexpr le1 le2 && is_same_lexpr re1 re2 - | PLdot(e1,f1), PLdot(e2,f2) | PLarrow(e1,f1), PLarrow(e2,f2) -> + | PLdot(e1,f1), PLdot(e2,f2) | PLarrow(e1,f1), PLarrow(e2,f2) -> f1 = f2 && is_same_lexpr e1 e2 - | PLarrget(b1,o1), PLarrget(b2,o2) -> + | PLarrget(b1,o1), PLarrget(b2,o2) -> is_same_lexpr b1 b2 && is_same_lexpr o1 o2 | PLold e1, PLold e2 -> is_same_lexpr e1 e2 | PLat (e1,s1), PLat(e2,s2) -> s1 = s2 && is_same_lexpr e1 e2 | PLbase_addr e1, PLbase_addr e2 | PLblock_length e1, PLblock_length e2 -> is_same_lexpr e1 e2 - | PLresult, PLresult | PLnull, PLnull - | PLfalse, PLfalse | PLtrue, PLtrue | PLempty, PLempty -> + | PLresult, PLresult | PLnull, PLnull + | PLfalse, PLfalse | PLtrue, PLtrue | PLempty, PLempty -> true - | PLcast(t1,e1), PLcast(t2,e2) | PLcoercion(e1,t1), PLcoercion (e2,t2)-> + | PLcast(t1,e1), PLcast(t2,e2) | PLcoercion(e1,t1), PLcoercion (e2,t2)-> is_same_pl_type t1 t2 && is_same_lexpr e1 e2 | PLrange(l1,h1), PLrange(l2,h2) -> is_same_opt is_same_lexpr l1 l2 && is_same_opt is_same_lexpr h1 h2 | PLsizeof t1, PLsizeof t2 -> is_same_pl_type t1 t2 | PLsizeofE e1,PLsizeofE e2 | PLtypeof e1,PLtypeof e2-> is_same_lexpr e1 e2 - | PLcoercionE (b1,t1), PLcoercionE(b2,t2) + | PLcoercionE (b1,t1), PLcoercionE(b2,t2) | PLsubtype(b1,t1), PLsubtype(b2,t2) -> is_same_lexpr b1 b2 && is_same_lexpr t1 t2 | PLupdate(b1,p1,r1), PLupdate(b2,p2,r2) -> is_same_lexpr b1 b2 && is_same_list is_same_path_elt p1 p2 && is_same_update_term r1 r2 | PLinitIndex l1, PLinitIndex l2 -> - let is_same_elt (i1,v1) (i2,v2) = + let is_same_elt (i1,v1) (i2,v2) = is_same_lexpr i1 i2 && is_same_lexpr v1 v2 in is_same_list is_same_elt l1 l2 | PLinitField l1, PLinitField l2 -> @@ -826,11 +858,12 @@ is_same_relation r1 r2 && is_same_lexpr le1 le2 && is_same_lexpr re1 re2 | PLand(l1,r1), PLand(l2,r2) | PLor(l1,r1), PLor(l2,r2) | PLimplies(l1,r1), PLimplies(l2,r2) | PLxor(l1,r1), PLxor(l2,r2) - | PLiff(l1,r1), PLiff(l2,r2) -> + | PLiff(l1,r1), PLiff(l2,r2) -> is_same_lexpr l1 l2 && is_same_lexpr r1 r2 - | PLnot e1, PLnot e2 - | PLvalid e1, PLvalid e2 - | PLfresh e1, PLfresh e2 -> + | PLnot e1, PLnot e2 + | PLvalid e1, PLvalid e2 + | PLfresh e1, PLfresh e2 + | PLinitialized e1, PLinitialized e2 -> is_same_lexpr e1 e2 | PLvalid_index (b1,o1), PLvalid_index(b2,o2) -> is_same_lexpr b1 b2 && is_same_lexpr o1 o2 @@ -842,10 +875,10 @@ is_same_lexpr c1 c2 && is_same_lexpr t1 t2 && is_same_lexpr e1 e2 | PLnamed(s1,e1), PLnamed(s2,e2) -> s1 = s2 && is_same_lexpr e1 e2 | PLcomprehension(e1,q1,p1), PLcomprehension(e2,q2,p2) -> - is_same_lexpr e1 e2 && is_same_quantifiers q1 q2 + is_same_lexpr e1 e2 && is_same_quantifiers q1 q2 && is_same_opt is_same_lexpr p1 p2 - | PLsingleton e1, PLsingleton e2 -> is_same_lexpr e1 e2 - | PLunion l1, PLunion l2 | PLinter l1, PLinter l2 -> + | PLsingleton e1, PLsingleton e2 -> is_same_lexpr e1 e2 + | PLunion l1, PLunion l2 | PLinter l1, PLinter l2 -> is_same_list is_same_lexpr l1 l2 | (PLvar _ | PLapp _ | PLlambda _ | PLlet _ | PLconstant _ | PLunop _ | PLbinop _ | PLdot _ | PLarrow _ | PLarrget _ | PLold _ | PLat _ @@ -853,88 +886,244 @@ | PLrange _ | PLsizeof _ | PLsizeofE _ | PLtypeof _ | PLcoercion _ | PLcoercionE _ | PLupdate _ | PLinitIndex _ | PLtype _ | PLfalse | PLtrue | PLinitField _ | PLrel _ | PLand _ | PLor _ | PLxor _ - | PLimplies _ | PLiff _ | PLnot _ | PLif _ | PLforall _ - | PLexists _ | PLvalid _ | PLvalid_index _ | PLvalid_range _ - | PLseparated _ | PLfresh _ | PLnamed _ | PLsubtype _ + | PLimplies _ | PLiff _ | PLnot _ | PLif _ | PLforall _ + | PLexists _ | PLvalid _ | PLvalid_index _ | PLvalid_range _ + | PLinitialized _ | PLseparated _ | PLfresh _ | PLnamed _ | PLsubtype _ | PLcomprehension _ | PLunion _ | PLinter _ | PLsingleton _ | PLempty ),_ -> false +let hash_const c = + match c with + CInt64 _ | CStr _ | CWStr _ | CChr _ | CReal _ -> Hashtbl.hash c + | CEnum ei -> 95 + Hashtbl.hash ei.einame + +let hash_label l = + match l with + StmtLabel st -> + Hashtbl.hash !st.sid (* Might not be computed yet, leading to false + positive in case a term with a stmt label + ever occurs here. + *) + | LogicLabel (_,l) -> 19 + Hashtbl.hash l + +exception StopRecursion of int + +let rec hash_term (acc,depth,tot) t = + if tot <= 0 || depth <= 0 then raise (StopRecursion acc) + else begin + match t.term_node with + | TConst c -> (acc + hash_const c, tot - 1) + | TLval lv -> hash_term_lval (acc+19,depth - 1,tot -1) lv + | TSizeOf t -> (acc + 38 + Hashtbl.hash (Cil.typeSig t), tot - 1) + | TSizeOfE t -> hash_term (acc+57,depth -1, tot-1) t + | TSizeOfStr s -> (acc + 76 + Hashtbl.hash s, tot - 1) + | TAlignOf t -> (acc + 95 + Hashtbl.hash (Cil.typeSig t), tot - 1) + | TAlignOfE t -> hash_term (acc+114,depth-1,tot-1) t + | TUnOp(op,t) -> hash_term (acc+133+Hashtbl.hash op,depth-1,tot-2) t + | TBinOp(bop,t1,t2) -> + let hash1,tot1 = + hash_term (acc+152+Hashtbl.hash bop,depth-1,tot-2) t1 + in + hash_term (hash1,depth-1,tot1) t2 + | TCastE(ty,t) -> + let hash1 = Hashtbl.hash (Cil.typeSig ty) in + hash_term (acc+171+hash1,depth-1,tot-2) t + | TAddrOf lv -> hash_term_lval (acc+190,depth-1,tot-1) lv + | TStartOf lv -> hash_term_lval (acc+209,depth-1,tot-1) lv + | Tapp (li,labs,apps) -> + let hash1 = acc + 228 + Hashtbl.hash li.l_var_info.lv_name in + let hash_lb (acc,tot) (_,lb) = + if tot = 0 then raise (StopRecursion acc) + else (acc + hash_label lb,tot - 1) + in + let hash_one_term (acc,tot) t = hash_term (acc,depth-1,tot) t in + let res = List.fold_left hash_lb (hash1,tot-1) labs in + List.fold_left hash_one_term res apps + | Tlambda(quants,t) -> + let hash_var (acc,tot) lv = + if tot = 0 then raise (StopRecursion acc) + else (acc + Hashtbl.hash lv.lv_name,tot-1) + in + let (acc,tot) = List.fold_left hash_var (acc+247,tot-1) quants in + hash_term (acc,depth-1,tot-1) t + | TDataCons(ctor,args) -> + let hash = acc + 266 + Hashtbl.hash ctor.ctor_name in + let hash_one_term (acc,tot) t = hash_term (acc,depth-1,tot) t in + List.fold_left hash_one_term (hash,tot-1) args + | Tif(t1,t2,t3) -> + let hash1,tot1 = hash_term (acc+285,depth-1,tot) t1 in + let hash2,tot2 = hash_term (hash1,depth-1,tot1) t2 in + hash_term (hash2,depth-1,tot2) t3 + | Tat(t,l) -> + let hash = acc + 304 + hash_label l in + hash_term (hash,depth-1,tot-2) t + | Tbase_addr t -> hash_term (acc+323,depth-1,tot-1) t + | Tblock_length t -> hash_term (acc+342,depth-1,tot-1) t + | Tnull -> acc+361, tot - 1 + | TCoerce(t,ty) -> + let hash = Hashtbl.hash (Cil.typeSig ty) in + hash_term (acc+380+hash,depth-1,tot-2) t + | TCoerceE(t1,t2) -> + let hash1,tot1 = hash_term (acc+399,depth-1,tot-1) t1 in + hash_term (hash1,depth-1,tot1) t2 + | TUpdate(t1,off,t2) -> + let hash1,tot1 = hash_term (acc+418,depth-1,tot-1) t1 in + let hash2,tot2 = hash_term_offset (hash1,depth-1,tot1) off in + hash_term (hash2,depth-1,tot2) t2 + | Ttypeof t -> hash_term (acc+437,depth-1,tot-1) t + | Ttype t -> acc + 456 + Hashtbl.hash (Cil.typeSig t), tot - 1 + | Tempty_set -> acc + 475, tot - 1 + | Tunion tl -> + let hash_one_term (acc,tot) t = hash_term (acc,depth-1,tot) t in + List.fold_left hash_one_term (acc+494,tot-1) tl + | Tinter tl -> + let hash_one_term (acc,tot) t = hash_term (acc,depth-1,tot) t in + List.fold_left hash_one_term (acc+513,tot-1) tl + | Tcomprehension (t,quants,_) -> (* TODO: hash predicates *) + let hash_var (acc,tot) lv = + if tot = 0 then raise (StopRecursion acc) + else (acc + Hashtbl.hash lv.lv_name,tot-1) + in + let (acc,tot) = List.fold_left hash_var (acc+532,tot-1) quants in + hash_term (acc,depth-1,tot-1) t + | Trange(t1,t2) -> + let acc = acc + 551 in + let acc,tot = + match t1 with + None -> acc,tot - 1 + | Some t -> hash_term (acc,depth-1,tot-2) t + in + if tot <= 0 then raise (StopRecursion acc) + else + (match t2 with + None -> acc, tot - 1 + | Some t -> hash_term (acc,depth-1,tot-1) t) + | Tlet(li,t) -> + hash_term + (acc + 570 + Hashtbl.hash li.l_var_info.lv_name, depth-1, tot-1) + t + end +and hash_term_lval (acc,depth,tot) (h,o) = + if depth <= 0 || tot <= 0 then raise (StopRecursion acc) + else begin + let hash, tot = hash_term_lhost (acc, depth-1, tot - 1) h in + hash_term_offset (hash, depth-1, tot) o + end +and hash_term_lhost (acc,depth,tot) h = + if depth<=0 || tot <= 0 then raise (StopRecursion acc) + else begin + match h with + | TVar lv -> acc + Hashtbl.hash lv.lv_name, tot - 1 + | TResult t -> acc + 19 + Hashtbl.hash (Cil.typeSig t), tot - 2 + | TMem t -> hash_term (acc+38,depth-1,tot-1) t + end +and hash_term_offset (acc,depth,tot) o = + if depth<=0 || tot <= 0 then raise (StopRecursion acc) + else begin + match o with + | TNoOffset -> acc, tot - 1 + | TField(fi,o) -> + hash_term_offset (acc+19+Hashtbl.hash fi.fname,depth-1,tot-1) o + | TIndex (t,o) -> + let hash, tot = hash_term (acc+38,depth-1,tot-1) t in + hash_term_offset (hash,depth-1,tot) o +end + +let hash_term t = + try fst (hash_term (0,10,100) t) + with StopRecursion h -> h + let get_behavior_names spec = List.fold_left (fun acc b -> b.b_name::acc) [] spec.spec_behavior let merge_assigns a1 a2 = if is_same_assigns a1 a2 then a1 - else + else match (a1,a2) with - WritesAny,_ -> a2 - | _,WritesAny -> a1 - | _ -> Cil.warning "incompatible assigns clauses. Keeping only one."; a1 + | WritesAny, _ -> a2 + | _, WritesAny -> a1 + | _ -> + Kernel.warning ~current:true + "incompatible assigns clauses. Keeping only one."; + a1 + +let concat_assigns a1 a2 = + match a1,a2 with + | WritesAny, _ | _, WritesAny -> WritesAny + | Writes l1, Writes l2 -> Writes (l1 @ l2) let merge_behaviors ~silent old_behaviors fresh_behaviors = old_behaviors @ (List.filter (fun b -> - try - let old_b = List.find (fun x -> x.b_name = b.b_name) - old_behaviors in - if not (is_same_behavior b old_b) then begin - if not(silent) then - Cil.warning "found different behaviors with the same name. Merging them" ; - old_b.b_assumes <- old_b.b_assumes @ b.b_assumes; - old_b.b_requires <- old_b.b_requires @ b.b_requires; - old_b.b_post_cond <- old_b.b_post_cond @ b.b_post_cond; - old_b.b_assigns <- merge_assigns old_b.b_assigns b.b_assigns; - end ; - false - with Not_found -> true) + try + let old_b = List.find (fun x -> x.b_name = b.b_name) old_behaviors in + if not (is_same_behavior b old_b) then begin + if not silent then + Kernel.warning ~current:true + "found two %s. Merging them" + (if Cil.is_default_behavior b then "default behaviors" + else "behaviors named " ^ b.b_name) + ; + old_b.b_assumes <- old_b.b_assumes @ b.b_assumes; + old_b.b_requires <- old_b.b_requires @ b.b_requires; + old_b.b_post_cond <- old_b.b_post_cond @ b.b_post_cond; + old_b.b_assigns <- merge_assigns old_b.b_assigns b.b_assigns; + end ; + false + with Not_found -> true) fresh_behaviors) let merge_funspec ?(silent_about_merging_behav=false) old_spec fresh_spec = - if is_same_spec old_spec fresh_spec || - Cil.is_empty_funspec fresh_spec - then () - else if Cil.is_empty_funspec old_spec then - begin + if not (is_same_spec old_spec fresh_spec || Cil.is_empty_funspec fresh_spec) + then + if Cil.is_empty_funspec old_spec then begin old_spec.spec_terminates <- fresh_spec.spec_terminates; old_spec.spec_behavior <- fresh_spec.spec_behavior; old_spec.spec_complete_behaviors <- fresh_spec.spec_complete_behaviors; old_spec.spec_disjoint_behaviors <- fresh_spec.spec_disjoint_behaviors; old_spec.spec_variant <- fresh_spec.spec_variant; - end - else begin - old_spec.spec_behavior <- merge_behaviors ~silent:silent_about_merging_behav - old_spec.spec_behavior fresh_spec.spec_behavior ; - begin match old_spec.spec_variant,fresh_spec.spec_variant with + end else begin + old_spec.spec_behavior <- + merge_behaviors ~silent:silent_about_merging_behav + old_spec.spec_behavior fresh_spec.spec_behavior ; + (match old_spec.spec_variant,fresh_spec.spec_variant with | None,None -> () | Some _, None -> () | None, Some _ -> old_spec.spec_variant <- fresh_spec.spec_variant | Some _old, Some _fresh -> - Cil.warning - "found two variants for function specification. Keeping only one." - end; - begin match old_spec.spec_terminates, fresh_spec.spec_terminates with - None, None -> () + Kernel.warning ~current:true + "found two variants for function specification. Keeping only one."); + (match old_spec.spec_terminates, fresh_spec.spec_terminates with + | None, None -> () | Some p1, Some p2 when is_same_identified_predicate p1 p2 -> () | _ -> - Cil.warning - "found two different terminates clause for function specification. \ - keeping only one" - end; - old_spec.spec_complete_behaviors <- - old_spec.spec_complete_behaviors @ fresh_spec.spec_complete_behaviors; - old_spec.spec_disjoint_behaviors <- - old_spec.spec_disjoint_behaviors @ fresh_spec.spec_disjoint_behaviors - end + Kernel.warning ~current:true + "found two different terminates clause for function specification. \ + keeping only one"); + old_spec.spec_complete_behaviors <- + old_spec.spec_complete_behaviors @ fresh_spec.spec_complete_behaviors; + old_spec.spec_disjoint_behaviors <- + old_spec.spec_disjoint_behaviors @ fresh_spec.spec_disjoint_behaviors + end + +let clear_funspec spec = + let tmp = Cil.empty_funspec () in + spec.spec_terminates <- tmp.spec_terminates; + spec.spec_behavior <- tmp.spec_behavior; + spec.spec_complete_behaviors <- tmp.spec_complete_behaviors; + spec.spec_disjoint_behaviors <- tmp.spec_disjoint_behaviors; + spec.spec_variant <- tmp.spec_variant let lhost_c_type = function - TVar v -> - (match v.lv_type with - Ctype ty -> ty - | _ -> assert false) + | TVar v -> + (match v.lv_type with + | Ctype ty -> ty + | _ -> assert false) | TMem t -> - (match t.term_type with - Ctype (TPtr(ty,_)) -> ty - | _ -> assert false) + (match t.term_type with + | Ctype (TPtr(ty,_)) -> ty + | _ -> assert false) | TResult ty -> ty let is_assert ca = match ca.annot_content with AAssert _ -> true | _ -> false @@ -957,11 +1146,6 @@ let is_assigns ca = match ca.annot_content with AAssigns _ -> true | _ -> false -(* -let is_loop_behavior ca = - match ca.annot_content with ALoopBehavior _ -> true | _ -> false -*) - let is_pragma ca = match ca.annot_content with APragma _ -> true | _ -> false @@ -977,10 +1161,13 @@ let is_loop_annot s = is_loop_invariant s || is_assigns s || is_variant s || is_loop_pragma s -(* -let is_loop_annot s = - is_loop_invariant s || is_loop_behavior s || is_variant s || is_loop_pragma s -*) +let is_property_pragma = function + | Loop_pragma (Unroll_level _ | Widen_hints _ | Widen_variables _) + | Slice_pragma (SPexpr _ | SPctrl | SPstmt) + | Impact_pragma (IPexpr _ | IPstmt) -> false +(* If at some time a pragma becomes something which should be proven, + update the pragma-related code in gui/property_navigator.ml *) + let extract_loop_pragma l = List.fold_right @@ -990,7 +1177,7 @@ let extract_contract l = List.fold_right (fun ca l -> match ca.annot_content with - AStmtSpec spec -> spec :: l | _ -> l) l [] + AStmtSpec (l1,spec) -> (l1,spec) :: l | _ -> l) l [] (* ************************************************************************* *) (** {2 Parsing utilities} *) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/logic/logic_utils.mli frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_utils.mli --- frama-c-20110201+carbon+dfsg/cil/src/logic/logic_utils.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/logic/logic_utils.mli 2011-10-10 08:40:07.000000000 +0000 @@ -55,7 +55,7 @@ (** computes a type signature for a C type and removes attributes that are not meaningful for the logic. See {!Cil.typeSig} for more information. *) -val type_sig_logic : typ -> typsig +val type_sig_logic : ?drop_attributes:bool -> typ -> typsig (** [isLogicType test typ] is [false] for pure logic types and the result of test for C types. @@ -140,23 +140,39 @@ val contains_result : term -> bool (** returns the body of the given predicate. - @raise Not_found if the logic_info is not the definition of a predicate. -*) + @raise Not_found if the logic_info is not the definition of a predicate. *) val get_pred_body : logic_info -> predicate named (** true if the term is \result or an offset of \result. - @deprecated since Carbon-20101201 use Logic_const.is_result instead -*) + @deprecated since Carbon-20101201 use Logic_const.is_result instead *) val is_result : term -> bool val lhost_c_type : term_lhost -> typ +(** {2 Predicates} *) + +(** [true] if the predicate is Ptrue. + @since Nitrogen-20111001 *) +val is_trivially_true: predicate named -> bool + +(** [true] if the predicate is Pfalse + @since Nitrogen-20111001 *) +val is_trivially_false: predicate named -> bool + (** {2 Structural equality between annotations} *) +val is_same_list: ('a -> 'a -> bool) -> 'a list -> 'a list -> bool + val is_same_logic_label : logic_label -> logic_label -> bool -val is_same_type : logic_type -> logic_type -> bool + +(** + @since Nitrogen-20111001 +*) +val is_same_pconstant: Logic_ptree.constant -> Logic_ptree.constant -> bool + +val is_same_type : ?drop_attributes:bool -> logic_type -> logic_type -> bool val is_same_var : logic_var -> logic_var -> bool val is_same_logic_signature : logic_info -> logic_info -> bool @@ -166,6 +182,8 @@ builtin_logic_info -> builtin_logic_info -> bool val is_same_logic_ctor_info : logic_ctor_info -> logic_ctor_info -> bool + +(** @deprecated Nitrogen-20111001 use {!Cil.compareConstant} instead. *) val is_same_constant : constant -> constant -> bool val is_same_term : term -> term -> bool val is_same_logic_info : logic_info -> logic_info -> bool @@ -219,10 +237,23 @@ val is_same_lexpr: Logic_ptree.lexpr -> Logic_ptree.lexpr -> bool +(** hash function compatible with is_same_term *) +val hash_term: term -> int + (** {2 Merging contracts} *) val get_behavior_names : ('a, 'b, 'c) spec -> string list + +(** Concatenates two assigns if both are defined, + returns WritesAny if one (or both) of them is WritesAny. + @since Nitrogen-20111001 *) +val concat_assigns: + identified_term assigns -> + identified_term assigns -> identified_term assigns + +(** merge assigns: take the one that is defined and select an arbitrary one + if both are, emitting a warning unless both are syntactically the same. *) val merge_assigns : identified_term assigns -> identified_term assigns -> identified_term assigns @@ -230,14 +261,22 @@ val merge_behaviors : silent:bool -> funbehavior list -> funbehavior list -> funbehavior list +(** [merge_funspec oldspec newspec] merges [newspec] into [oldspec]. + If the funspec belongs to a kernel function, do not forget to call + {!Kernel_function.set_spec} after merging. *) val merge_funspec : ?silent_about_merging_behav:bool -> funspec -> funspec -> unit +(** Reset the given funspec to empty. + If the funspec belongs to a kernel function, do not forget to call + {!Kernel_function.set_spec} after clearing. + @since Nitrogen-20111001 *) +val clear_funspec: funspec -> unit + (** {2 Discriminating code_annotations} *) (** Functions below allows to test a special kind of code_annotation. Use them in conjunction with {!Annotations.get_filter} to retrieve - a particular kind of annotations associated to a statement. - *) + a particular kind of annotations associated to a statement. *) val is_assert : code_annotation -> bool val is_contract : code_annotation -> bool @@ -251,10 +290,14 @@ val is_slice_pragma : code_annotation -> bool val is_impact_pragma : code_annotation -> bool val is_loop_annot : code_annotation -> bool + +val is_property_pragma : term pragma -> bool +(** Should this pragma be proved by plugins *) + val extract_loop_pragma : code_annotation list -> term loop_pragma list val extract_contract : - code_annotation list -> funspec list + code_annotation list -> (string list * funspec) list (** {2 Parsing hackery} *) (** Values that control the various modes of the parser and lexer for logic. diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep.mli frama-c-20111001+nitrogen+dfsg/cil/src/machdep.mli --- frama-c-20110201+carbon+dfsg/cil/src/machdep.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep.mli 2011-10-10 08:40:09.000000000 +0000 @@ -39,6 +39,8 @@ (* énergies alternatives). *) (**************************************************************************) +(** Machine dependent values. *) + open Cil_types type t = private diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep_ppc_32_diab.ml frama-c-20111001+nitrogen+dfsg/cil/src/machdep_ppc_32_diab.ml --- frama-c-20110201+carbon+dfsg/cil/src/machdep_ppc_32_diab.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep_ppc_32_diab.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - -open Cil_types -let gcc = { - (* Hand-crafted Diab-C compiler *) - version_major = 4; - version_minor = 4; - version = "4.4 (Diab-C Windriver)"; - sizeof_short = 2; - sizeof_int = 4; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 4; - sizeof_enum = 4; - sizeof_float = 4; - sizeof_double = 8; - enum_are_signed = true; - sizeof_longdouble = 8; - sizeof_void = 0; - sizeof_fun = 0; - size_t = "unsigned long"; - wchar_t = "int"; - ptrdiff_t = "int"; - alignof_short = 2; - alignof_int = 4; - alignof_long = 4; - alignof_longlong = 8; - alignof_ptr = 4; - alignof_enum = 4; - alignof_float = 4; - alignof_double = 8; - alignof_longdouble = 8; - alignof_str = 4; - alignof_fun = 0; - alignof_char_array = 1; - char_is_unsigned = true; - const_string_literals = false; - little_endian = false; - underscore_name = false ; -} -let hasMSVC = false -let msvc = gcc -let gccHas__builtin_va_list = false -let __thread_is_keyword = false diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep_ppc_32_diab.mli frama-c-20111001+nitrogen+dfsg/cil/src/machdep_ppc_32_diab.mli --- frama-c-20110201+carbon+dfsg/cil/src/machdep_ppc_32_diab.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep_ppc_32_diab.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - -val gcc : Cil_types.mach -val msvc : Cil_types.mach -val gccHas__builtin_va_list : bool -val __thread_is_keyword : bool diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep_ppc_32.ml frama-c-20111001+nitrogen+dfsg/cil/src/machdep_ppc_32.ml --- frama-c-20110201+carbon+dfsg/cil/src/machdep_ppc_32.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep_ppc_32.ml 2011-10-10 08:40:09.000000000 +0000 @@ -51,10 +51,8 @@ sizeof_long = 4; sizeof_longlong = 8; sizeof_ptr = 4; - sizeof_enum = 4; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 16; sizeof_void = 1; sizeof_fun = 1; @@ -66,13 +64,13 @@ alignof_long = 4; alignof_longlong = 4; alignof_ptr = 4; - alignof_enum = 4; alignof_float = 4; alignof_double = 4; alignof_longdouble = 16; alignof_str = 1; alignof_fun = 4; alignof_char_array = 1; + alignof_aligned= 16; char_is_unsigned = false; const_string_literals = true; little_endian = false; @@ -89,10 +87,8 @@ sizeof_long = 4; sizeof_longlong = 8; sizeof_ptr = 4; - sizeof_enum = 4; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 16; sizeof_void = 1; sizeof_fun = 1; @@ -104,13 +100,13 @@ alignof_long = 4; alignof_longlong = 4; alignof_ptr = 4; - alignof_enum = 4; alignof_float = 4; alignof_double = 4; alignof_longdouble = 16; alignof_str = 1; alignof_fun = 4; alignof_char_array = 1; + alignof_aligned= 16; char_is_unsigned = false; const_string_literals = true; little_endian = false; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep_x86_16.ml frama-c-20111001+nitrogen+dfsg/cil/src/machdep_x86_16.ml --- frama-c-20110201+carbon+dfsg/cil/src/machdep_x86_16.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep_x86_16.ml 2011-10-10 08:40:09.000000000 +0000 @@ -51,10 +51,8 @@ sizeof_long = 4; sizeof_longlong = 8; sizeof_ptr = 4; - sizeof_enum = 2; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 16; (*sizeof_wchar = 4;*) (*sizeof_sizeof = 4;*) @@ -65,13 +63,15 @@ alignof_long = 4; alignof_longlong = 4; alignof_ptr = 4; - alignof_enum = 2; alignof_float = 4; alignof_double = 8; alignof_longdouble = 16; alignof_str = 1; alignof_fun = 1; alignof_char_array = 1; + alignof_aligned= 8; + (* I don't know if attribute aligned is supported by any 16bits + compiler. *) char_is_unsigned = false; const_string_literals = true; little_endian = true; @@ -92,10 +92,8 @@ sizeof_long = 4; sizeof_longlong = 8; sizeof_ptr = 4; - sizeof_enum = 2; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 16; (*sizeof_wchar = 4;*) (*sizeof_sizeof = 4;*) @@ -106,13 +104,15 @@ alignof_long = 4; alignof_longlong = 4; alignof_ptr = 4; - alignof_enum = 2; alignof_float = 4; alignof_double = 8; alignof_longdouble = 16; alignof_str = 1; alignof_fun = 1; alignof_char_array = 1; + alignof_aligned= 8; + (* I don't know if attribute aligned is supported by any 16bits + compiler. *) char_is_unsigned = false; const_string_literals = true; little_endian = true; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep_x86_32.ml frama-c-20111001+nitrogen+dfsg/cil/src/machdep_x86_32.ml --- frama-c-20110201+carbon+dfsg/cil/src/machdep_x86_32.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep_x86_32.ml 2011-10-10 08:40:09.000000000 +0000 @@ -51,10 +51,8 @@ sizeof_long = 4; sizeof_longlong = 8; sizeof_ptr = 4; - sizeof_enum = 4; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 12; sizeof_void = 1; sizeof_fun = 1; @@ -66,13 +64,13 @@ alignof_long = 4; alignof_longlong = 4; alignof_ptr = 4; - alignof_enum = 4; alignof_float = 4; alignof_double = 4; alignof_longdouble = 4; alignof_str = 1; alignof_fun = 1; alignof_char_array = 1; + alignof_aligned= 16; char_is_unsigned = false; const_string_literals = true; little_endian = true; @@ -89,10 +87,8 @@ sizeof_long = 4; sizeof_longlong = 8; sizeof_ptr = 4; - sizeof_enum = 4; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 12; sizeof_void = 1; sizeof_fun = 1; @@ -104,7 +100,6 @@ alignof_long = 4; alignof_longlong = 4; alignof_ptr = 4; - alignof_enum = 4; alignof_float = 4; alignof_double = 4; alignof_longdouble = 4; @@ -112,6 +107,7 @@ alignof_fun = 1; alignof_char_array = 1; char_is_unsigned = false; + alignof_aligned= 16; const_string_literals = true; little_endian = true; underscore_name = true ; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/machdep_x86_64.ml frama-c-20111001+nitrogen+dfsg/cil/src/machdep_x86_64.ml --- frama-c-20110201+carbon+dfsg/cil/src/machdep_x86_64.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/machdep_x86_64.ml 2011-10-10 08:40:09.000000000 +0000 @@ -51,10 +51,8 @@ sizeof_long = 8; sizeof_longlong = 8; sizeof_ptr = 8; - sizeof_enum = 4; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 16; sizeof_void = 1; sizeof_fun = 1; @@ -66,13 +64,13 @@ alignof_long = 8; alignof_longlong = 8; alignof_ptr = 8; - alignof_enum = 4; alignof_float = 4; alignof_double = 8; alignof_longdouble = 16; alignof_str = 1; alignof_fun = 1; alignof_char_array = 1; + alignof_aligned= 16; char_is_unsigned = false; const_string_literals = true; little_endian = true; @@ -88,10 +86,8 @@ sizeof_long = 8; sizeof_longlong = 8; sizeof_ptr = 8; - sizeof_enum = 4; sizeof_float = 4; sizeof_double = 8; - enum_are_signed = true; sizeof_longdouble = 16; sizeof_void = 1; sizeof_fun = 1; @@ -103,13 +99,13 @@ alignof_long = 8; alignof_longlong = 8; alignof_ptr = 8; - alignof_enum = 4; alignof_float = 4; alignof_double = 8; alignof_longdouble = 16; alignof_str = 1; alignof_fun = 1; alignof_char_array = 1; + alignof_aligned= 16; char_is_unsigned = false; const_string_literals = true; little_endian = true; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/mergecil.ml frama-c-20111001+nitrogen+dfsg/cil/src/mergecil.ml --- frama-c-20110201+carbon+dfsg/cil/src/mergecil.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/mergecil.ml 2011-10-10 08:40:09.000000000 +0000 @@ -93,17 +93,17 @@ let ls = String.length s in lp <= ls && String.sub s 0 lp = p +let d_nloc fmt (lo: (location * int) option) = + match lo with + None -> Format.fprintf fmt "None" + | Some (l, idx) -> Format.fprintf fmt "Some(%d at %a)" idx d_loc l +exception NotHere -(* A name is identified by the index of the file in which it occurs (starting - * at 0 with the first file) and by the actual name. We'll keep name spaces - * separate *) - -(* We define a data structure for the equivalence classes *) -type 'a node = - { nname: string; (* The actual name *) +type ('a, 'b) node = + { nname: 'a; (* The actual name *) nfidx: int; (* The file index *) - ndata: 'a; (* Data associated with the node *) + ndata: 'b; (* Data associated with the node *) mutable nloc: (location * int) option; (* location where defined and index within the file of the definition. * If None then it means that this node actually DOES NOT appear in the @@ -113,49 +113,107 @@ * the cases of combineType (see the definition of combineTypes). We * try never to choose as representatives nodes without a definition. * We also choose as representative the one that appears earliest *) - mutable nrep: 'a node; (* A pointer to another node in its class (one - * closer to the representative). The nrep node - * is always in an earlier file, except for the - * case where a name is undefined in one file - * and defined in a later file. If this pointer - * points to the node itself then this is the - * representative. *) + mutable nrep: ('a, 'b) node; + (* A pointer to another node in its class (one + * closer to the representative). The nrep node + * is always in an earlier file, except for the + * case where a name is undefined in one file + * and defined in a later file. If this pointer + * points to the node itself then this is the + * representative. *) mutable nmergedSyns: bool (* Whether we have merged the synonyms for * the node of this name *) } -let d_nloc fmt (lo: (location * int) option) = - match lo with - None -> Format.fprintf fmt "None" - | Some (l, idx) -> Format.fprintf fmt "Some(%d at %a)" idx d_loc l +module Merging + (H: + sig + include Hashtbl.HashedType + val merge_synonym: t -> bool (* whether this name should be considered + for merging or not. + *) + val output: Format.formatter -> t -> unit + end + ): +sig +type 'a eq_table +type 'a syn_table +val create_eq_table: int -> 'a eq_table +val find_eq_table: 'a eq_table -> (int * H.t) -> (H.t, 'a) node +val add_eq_table: 'a eq_table -> (int * H.t) -> (H.t,'a) node -> unit +val iter_eq_table: + ((int * H.t) -> (H.t,'a) node -> unit) -> 'a eq_table -> unit +val clear_eq: 'a eq_table -> unit +val create_syn_table: int -> 'a syn_table +val clear_syn: 'a syn_table -> unit +val mkSelfNode: + 'a eq_table -> 'a syn_table -> int -> H.t -> 'a -> + (location * int) option -> (H.t, 'a) node +val find: bool -> (H.t, 'a) node -> (H.t, 'a) node +val union: (H.t, 'a) node -> (H.t,'a) node -> (H.t, 'a) node * (unit -> unit) +val findReplacement: + bool -> 'a eq_table -> int -> H.t -> ('a * int) option +val getNode: 'a eq_table -> 'a syn_table -> int -> + H.t -> 'a -> (location * int) option -> (H.t, 'a) node +val translate: 'a eq_table -> 'a -> ('a -> 'b) -> 'a +(* [doMergeSynonyms eq compare] + tries to merge synonyms. Do not give an error if they fail to merge + compare is a comparison function that throws Failure if no match *) +val doMergeSynonyms: 'a syn_table -> (int -> 'a -> int -> 'a -> unit) -> unit +val dumpGraph: string -> 'a eq_table -> unit +end += +struct +(* Find the representative for a node and compress the paths in the process *) +module Heq = + Hashtbl.Make + (struct + type t = int * H.t + let hash (d,x) = 19 * d + H.hash x + let equal (d1,x1) (d2,x2) = d1 = d2 && H.equal x1 x2 + end) + +module Hsyn = Hashtbl.Make(H) + +type 'a eq_table = (H.t,'a) node Heq.t +type 'a syn_table = (H.t,'a) node Hsyn.t + +let create_eq_table x = Heq.create x +let create_syn_table x = Hsyn.create x + +let clear_eq = Heq.clear +let clear_syn = Hsyn.clear + +let find_eq_table = Heq.find + +let add_eq_table = Heq.add + +let iter_eq_table = Heq.iter (* Make a node with a self loop. This is quite tricky. *) -let mkSelfNode (eq: (int * string, 'a node) H.t) (* The equivalence table *) - (syn: (string, 'a node) H.t) (* The synonyms table *) - (fidx: int) (name: string) (data: 'a) - (l: (location * int) option) = +let mkSelfNode eq syn fidx name data l = let rec res = { nname = name; nfidx = fidx; ndata = data; nloc = l; nrep = res; nmergedSyns = false; } in - H.add eq (fidx, name) res; (* Add it to the proper table *) + Heq.add eq (fidx, name) res; (* Add it to the proper table *) (* mergeSynonyms is not active for anonymous types, probably because it is licit to have two distinct anonymous types in two different files (which should not be merged). However, for anonymous enums, they can, and are, in fact merged by CIL. Hence, we permit the merging of anonymous enums with the same base name *) - if mergeSynonyms && (not (prefix "__anon" name) || prefix "__anonenum" name) - then H.add syn name res; + if mergeSynonyms && H.merge_synonym name + then Hsyn.add syn name res; res let debugFind = false (* Find the representative with or without path compression *) -let rec find (pathcomp: bool) (nd: 'a node) = +let rec find pathcomp nd = if debugFind then - Cilmsg.debug " find %s(%d)" nd.nname nd.nfidx ; + Kernel.debug " find %a(%d)" H.output nd.nname nd.nfidx ; if nd.nrep == nd then begin if debugFind then - Cilmsg.debug " = %s(%d)" nd.nname nd.nfidx ; + Kernel.debug " = %a(%d)" H.output nd.nname nd.nfidx ; nd end else begin let res = find pathcomp nd.nrep in @@ -170,7 +228,7 @@ * representatives nodes that are not defined in their files. We return a * function for undoing the union. Make sure that between the union and the * undo you do not do path compression *) -let union (nd1: 'a node) (nd2: 'a node) : 'a node * (unit -> unit) = +let union nd1 nd2 = (* Move to the representatives *) let nd1 = find true nd1 in let nd2 = find true nd2 in @@ -190,139 +248,137 @@ (* They have the same defined status. Choose the earliest *) if nd1.nfidx < nd2.nfidx then nd1, nd2 else if nd1.nfidx > nd2.nfidx then nd2, nd1 - else (* In the same file. Choose the one with the earliest index *) begin - match nd1.nloc, nd2.nloc with - Some (_, didx1), Some (_, didx2) -> - if didx1 < didx2 then nd1, nd2 else - if didx1 > didx2 then nd2, nd1 - else begin - Cil.warning - "Merging two elements (%s and %s) in the same file (%d) with the same idx (%d) within the file" - nd1.nname nd2.nname nd1.nfidx didx1 ; + else (* In the same file. Choose the one with the earliest index *) + begin + match nd1.nloc, nd2.nloc with + Some (_, didx1), Some (_, didx2) -> + if didx1 < didx2 then nd1, nd2 else + if didx1 > didx2 then nd2, nd1 + else begin + Kernel.warning + "Merging two elements (%a and %a) \ + in the same file (%d) \ + with the same idx (%d) within the file" + H.output nd1.nname H.output nd2.nname nd1.nfidx didx1 ; + nd1, nd2 + end + | _, _ -> + (* both none. Does not matter which one we choose. Should not happen + though. *) + (* sm: it does happen quite a bit when, e.g. merging STLport with + some client source; I'm disabling the warning since it supposedly + is harmless anyway, so is useless noise *) + (* sm: re-enabling on claim it now will probably not happen *) + Kernel.warning ~current:true + "Merging two undefined elements in the same file: %a and %a" + H.output nd1.nname H.output nd2.nname ; nd1, nd2 - end - | _, _ -> (* both none. Does not matter which one we choose. Should - * not happen though. *) - (* sm: it does happen quite a bit when, e.g. merging STLport with - * some client source; I'm disabling the warning since it supposedly - * is harmless anyway, so is useless noise *) - (* sm: re-enabling on claim it now will probably not happen *) - Cil.warning - "Merging two undefined elements in the same file: %s and %s" - nd1.nname nd2.nname ; - nd1, nd2 - end - else (* One is defined, the other is not. Choose the defined one *) - if nd1.nloc != None then nd1, nd2 else nd2, nd1 + end + else (* One is defined, the other is not. Choose the defined one *) + if nd1.nloc != None then nd1, nd2 else nd2, nd1 in let oldrep = norep.nrep in norep.nrep <- rep; rep, (fun () -> norep.nrep <- oldrep) end -(* -let union (nd1: 'a node) (nd2: 'a node) : 'a node * (unit -> unit) = - if nd1 == nd2 && nd1.nname = "!!!intEnumInfo!!!" then begin - ignore (warn "unioning two identical nodes for %s(%d)" - nd1.nname nd1.nfidx); - nd1, fun x -> x - end else - union nd1 nd2 -*) -(* Find the representative for a node and compress the paths in the process *) -let findReplacement - (pathcomp: bool) - (eq: (int * string, 'a node) H.t) - (fidx: int) - (name: string) : ('a * int) option = + +let findReplacement pathcomp eq fidx name = if debugFind then - Cilmsg.debug "findReplacement for %s(%d)" name fidx ; + Kernel.debug "findReplacement for %a(%d)" H.output name fidx ; try - let nd = H.find eq (fidx, name) in + let nd = Heq.find eq (fidx, name) in if nd.nrep == nd then begin if debugFind then - Cilmsg.debug " is a representative" ; + Kernel.debug " is a representative" ; None (* No replacement if this is the representative of its class *) end else let rep = find pathcomp nd in if rep != rep.nrep then - Cilmsg.abort "find does not return the representative" ; + Kernel.abort "find does not return the representative" ; if debugFind then - Cilmsg.debug " RES = %s(%d)" rep.nname rep.nfidx ; + Kernel.debug " RES = %a(%d)" H.output rep.nname rep.nfidx ; Some (rep.ndata, rep.nfidx) with Not_found -> begin if debugFind then - Cilmsg.debug " not found in the map"; + Kernel.debug " not found in the map"; None end (* Make a node if one does not already exist. Otherwise return the * representative *) -let getNode (eq: (int * string, 'a node) H.t) - (syn: (string, 'a node) H.t) - (fidx: int) (name: string) (data: 'a) - (l: (location * int) option) = +let getNode eq syn fidx name data l = let debugGetNode = false in - if debugGetNode then - Cilmsg.debug "getNode(%s(%d), %a)" name fidx d_nloc l; + if debugGetNode then + Kernel.debug "getNode(%a(%d), %a)" H.output name fidx d_nloc l; try - let res = H.find eq (fidx, name) in + let res = Heq.find eq (fidx, name) in (match res.nloc, l with (* Maybe we have a better location now *) None, Some _ -> res.nloc <- l | Some (old_l, old_idx), Some (l, idx) -> if old_idx != idx then - Cil.warning - "Duplicate definition of node %s(%d) at indices %d(%a) and %d(%a)" - name fidx old_idx d_loc old_l idx d_loc l + Kernel.warning ~current:true + "Duplicate definition of node %a(%d) at indices %d(%a) and %d(%a)" + H.output name fidx old_idx d_loc old_l idx d_loc l | _, _ -> ()); - if debugGetNode then Cilmsg.debug " node already found"; + if debugGetNode then Kernel.debug " node already found"; find false res (* No path compression *) with Not_found -> begin let res = mkSelfNode eq syn fidx name data l in - if debugGetNode then Cilmsg.debug " made a new one"; + if debugGetNode then Kernel.debug " made a new one"; res end - +let doMergeSynonyms syn compare = + Hsyn.iter + (fun n node -> + if not node.nmergedSyns then begin + (* find all the nodes for the same name *) + let all = Hsyn.find_all syn n in + (* classes are a list of representative for the nd name. + We'll select an appropriate one according to the comparison + function. *) + let rec tryone classes nd = + nd.nmergedSyns <- true; + (* Compare in turn with all the classes we have so far *) + let rec compareWithClasses = function + | [] -> [nd] (* No more classes. Add this as a new class *) + | c :: restc -> + try + compare c.nfidx c.ndata nd.nfidx nd.ndata; + (* Success. Stop here the comparison *) + c :: restc + with Failure _ -> (* Failed. Try next class *) + c :: (compareWithClasses restc) + in + compareWithClasses classes + in + (* Start with an empty set of classes for this name *) + let _ = List.fold_left tryone [] all in + () + end) + syn (* Dump a graph *) -let dumpGraph (what: string) (eq: (int * string, 'a node) H.t) : unit = - Cilmsg.debug "Equivalence graph for %s is:" what; - H.iter (fun (fidx, name) nd -> - Cilmsg.debug " %s(%d) %s-> " - name fidx (if nd.nloc = None then "(undef)" else ""); - if nd.nrep == nd then - Cilmsg.debug "*" - else - Cilmsg.debug " %s(%d)" nd.nrep.nname nd.nrep.nfidx - ) eq - - - - -(* For each name space we define a set of equivalence classes *) -let vEq: (int * string, varinfo node) H.t = H.create 111 (* Vars *) -let sEq: (int * string, compinfo node) H.t = H.create 111 (* Struct + union *) -let eEq: (int * string, enuminfo node) H.t = H.create 111 (* Enums *) -let tEq: (int * string, typeinfo node) H.t = H.create 111 (* Type names*) -let iEq: (int * string, varinfo node) H.t = H.create 111 (* Inlines *) - -let lfEq: (int * string, logic_info node) H.t = H.create 111 (* Logic functions *) -let ltEq: (int * string, logic_type_info node) H.t = H.create 111 (* Logic types *) -let lcEq: (int * string, logic_ctor_info node) H.t = H.create 111 (* Logic constructors *) - -let laEq: (int * string, (string * global_annotation list) node) H.t = H.create 111 - (* Axiomatics *) -let llEq: (int * string, (string * (bool * logic_label list * string list * - predicate named * location)) node) H.t = H.create 111 +(* FIXME: name is not a string anymore. *) +let dumpGraph what eq : unit = + Kernel.debug "Equivalence graph for %s is:" what; + Heq.iter + (fun (fidx, name) nd -> + Kernel.debug " %a(%d) %s-> " + H.output name fidx (if nd.nloc = None then "(undef)" else ""); + if nd.nrep == nd then + Kernel.debug "*" + else + Kernel.debug " %a(%d)" H.output nd.nrep.nname nd.nrep.nfidx + ) eq -exception NotHere let translate table data get_info = let result = let result = ref None in try - Hashtbl.iter + Heq.iter (fun _ node -> if get_info node.ndata == get_info data then (result := Some node; @@ -337,37 +393,86 @@ if result == result.nrep then (* Name is already correct *) data else result.nrep.ndata +end + +(* The original mergecil uses plain old Hashtbl for everything. *) +module PlainMerging = + Merging + (struct + type t = string + let hash = Hashtbl.hash + let equal = (=) + let merge_synonym name = + not (prefix "__anon" name) || prefix "__anonenum" name + let output = Format.pp_print_string + end) + +module VolatileMerging = + Merging + (struct + type t = identified_term list + let hash x = + match x with + [] -> 0 + | h::_ -> Logic_utils.hash_term h.it_content + let equal = Logic_utils.is_same_list Logic_utils.is_same_identified_term + let merge_synonym _ = true + let output fmt x = + Pretty_utils.pp_list + ~sep:("," ^^ Pretty_utils.space_sep) + (fun fmt x -> Cil.d_term fmt x.it_content) + fmt x + end) + +open PlainMerging + +(* For each name space we define a set of equivalence classes *) +let vEq = PlainMerging.create_eq_table 111 (* Vars *) +let sEq = PlainMerging.create_eq_table 111 (* Struct + union *) +let eEq = PlainMerging.create_eq_table 111 (* Enums *) +let tEq = PlainMerging.create_eq_table 111 (* Type names*) +let iEq = PlainMerging.create_eq_table 111 (* Inlines *) + +let lfEq = PlainMerging.create_eq_table 111 (* Logic functions *) +let ltEq = PlainMerging.create_eq_table 111 (* Logic types *) +let lcEq = PlainMerging.create_eq_table 111 (* Logic constructors *) + +let laEq = PlainMerging.create_eq_table 111 (* Axiomatics *) +let llEq = PlainMerging.create_eq_table 111 (* Lemmas *) + +let lvEq = VolatileMerging.create_eq_table 111 + let translate_vinfo info = try - let new_vi = translate vEq info (fun v -> v.vid) in + let new_vi = PlainMerging.translate vEq info (fun v -> v.vid) in (* Format.eprintf "TRANS %s(%d) to %s(%d)@\n" info.vname info.vid new_vi.vname new_vi.vid;*) new_vi with NotHere -> info let translate_typinfo info = - try translate tEq info (fun v -> v.tname) with NotHere -> info + try PlainMerging.translate tEq info (fun v -> v.tname) with NotHere -> info (* Sometimes we want to merge synonyms. We keep some tables indexed by names. * Each name is mapped to multiple exntries *) -let vSyn: (string, varinfo node) H.t = H.create 111 (* Not actually used *) -let iSyn: (string, varinfo node) H.t = H.create 111 (* Inlines *) -let sSyn: (string, compinfo node) H.t = H.create 111 -let eSyn: (string, enuminfo node) H.t = H.create 111 -let tSyn: (string, typeinfo node) H.t = H.create 111 -let lfSyn: (string, logic_info node) H.t = H.create 111 -let ltSyn: (string, logic_type_info node) H.t = H.create 111 -let lcSyn: (string, logic_ctor_info node) H.t = H.create 111 -let laSyn: (string, (string * global_annotation list) node) H.t = H.create 111 -let llSyn: (string, (string * (bool * logic_label list * string list * - predicate named * location)) node) H.t = H.create 111 +let vSyn = PlainMerging.create_syn_table 111 +let iSyn = PlainMerging.create_syn_table 111 +let sSyn = PlainMerging.create_syn_table 111 +let eSyn = PlainMerging.create_syn_table 111 +let tSyn = PlainMerging.create_syn_table 111 +let lfSyn = PlainMerging.create_syn_table 111 +let ltSyn = PlainMerging.create_syn_table 111 +let lcSyn = PlainMerging.create_syn_table 111 +let laSyn = PlainMerging.create_syn_table 111 +let llSyn = PlainMerging.create_syn_table 111 +let lvSyn = VolatileMerging.create_syn_table 111 (** A global environment for variables. Put in here only the non-static * variables, indexed by their name. *) -let vEnv : (string, varinfo node) H.t = H.create 111 +let vEnv : (string, (string, varinfo) node) H.t = H.create 111 (* A set of inline functions indexed by their printout ! *) -let inlineBodies : (string, varinfo node) H.t = H.create 111 +let inlineBodies : (string, (string, varinfo) node) H.t = H.create 111 (** A number of alpha conversion tables. We ought to keep one table for each * name space. Unfortunately, because of the way the C lexer works, type @@ -431,20 +536,40 @@ () let mergeSpec vi_ref vi_disc spec = - if not (Cil.is_empty_funspec spec) then + if not (Cil.is_empty_funspec spec) then begin let spec = try - let alpha = - Cil.create_alpha_renaming - (Cil.getFormalsDecl vi_disc) - (Cil.getFormalsDecl vi_ref) - in - try Cil.visitCilFunspec alpha spec with Not_found -> assert false - with Not_found -> - spec + let my_vars = Cil.getFormalsDecl vi_disc in + let to_rename = Cil.getFormalsDecl vi_ref in + Kernel.debug "Renaming arguments: %a -> %a" + (Pretty_utils.pp_list ~sep:",@ " Cil_datatype.Varinfo.pretty) my_vars + (Pretty_utils.pp_list ~sep:",@ " Cil_datatype.Varinfo.pretty) + to_rename; + let alpha = Cil.create_alpha_renaming my_vars to_rename in + Kernel.debug + "Renaming spec of function %a" Cil_datatype.Varinfo.pretty vi_disc; + Kernel.debug + "original spec is %a" Cil.d_funspec spec; + try + let res = + Cil.visitCilFunspec alpha spec + in + Kernel.debug "renamed spec is %a" Cil.d_funspec spec; + res + with Not_found -> assert false + with Not_found -> spec + in + let spec = + try + let alpha = Hashtbl.find formals_renaming vi_ref.vid in + let res = Cil.visitCilFunspec alpha spec in + Kernel.debug "renamed spec with definition's formals is %a" + Cil.d_funspec res; + res + with Not_found -> spec in add_to_merge_spec vi_ref spec - (* else no need keep empty specs *) +end (* else no need keep empty specs *) (* The index of the current file being scanned *) let currentFidx = ref 0 @@ -480,30 +605,32 @@ H.clear vEnv; - if all then H.clear vEq; + if all then PlainMerging.clear_eq vEq; - H.clear sEq; - H.clear eEq; - H.clear tEq; - H.clear iEq; - - H.clear lfEq; - H.clear ltEq; - H.clear lcEq; - H.clear laEq; - H.clear llEq; - - H.clear vSyn; - H.clear sSyn; - H.clear eSyn; - H.clear tSyn; - H.clear iSyn; - - H.clear lfSyn; - H.clear ltSyn; - H.clear lcSyn; - H.clear laSyn; - H.clear llSyn; + PlainMerging.clear_eq sEq; + PlainMerging.clear_eq eEq; + PlainMerging.clear_eq tEq; + PlainMerging.clear_eq iEq; + + PlainMerging.clear_eq lfEq; + PlainMerging.clear_eq ltEq; + PlainMerging.clear_eq lcEq; + PlainMerging.clear_eq laEq; + PlainMerging.clear_eq llEq; + VolatileMerging.clear_eq lvEq; + + PlainMerging.clear_syn vSyn; + PlainMerging.clear_syn sSyn; + PlainMerging.clear_syn eSyn; + PlainMerging.clear_syn tSyn; + PlainMerging.clear_syn iSyn; + + PlainMerging.clear_syn lfSyn; + PlainMerging.clear_syn ltSyn; + PlainMerging.clear_syn lcSyn; + PlainMerging.clear_syn laSyn; + PlainMerging.clear_syn llSyn; + VolatileMerging.clear_syn lvSyn; theFile := []; theFileTypes := []; @@ -525,36 +652,51 @@ if all then Logic_env.prepare_tables () let rec global_annot_pass1 g = match g with -| Daxiomatic(id,decls,l) -> + | Dvolatile(id,rvi,wvi,loc) -> + CurrentLoc.set loc; + ignore (VolatileMerging.getNode + lvEq lvSyn !currentFidx id (id,(rvi,wvi,loc)) + (Some (loc,!currentDeclIdx))) + | Daxiomatic(id,decls,l) -> CurrentLoc.set l; - ignore (getNode laEq laSyn !currentFidx id (id,decls) + ignore (PlainMerging.getNode laEq laSyn !currentFidx id (id,decls) (Some (l,!currentDeclIdx))); List.iter global_annot_pass1 decls -| Dfun_or_pred (li,l) -> + | Dfun_or_pred (li,l) -> CurrentLoc.set l; - (* FIXME: this is a copy of above, is it still correct for predicate ? *) - let mynode = getNode lfEq lfSyn !currentFidx li.l_var_info.lv_name li None in + let mynode = + PlainMerging.getNode + lfEq lfSyn !currentFidx li.l_var_info.lv_name li None + in (* NB: in case of mix decl/def it is the decl location that is taken. *) if mynode.nloc = None then - ignore (getNode lfEq lfSyn !currentFidx li.l_var_info.lv_name li - (Some (l, !currentDeclIdx))) - -| Dtype_annot (pi,l) -> + ignore + (PlainMerging.getNode lfEq lfSyn !currentFidx li.l_var_info.lv_name li + (Some (l, !currentDeclIdx))) + | Dtype_annot (pi,l) -> CurrentLoc.set l; - ignore (getNode lfEq lfSyn !currentFidx pi.l_var_info.lv_name pi + ignore (PlainMerging.getNode + lfEq lfSyn !currentFidx pi.l_var_info.lv_name pi (Some (l, !currentDeclIdx))) -| Dinvariant (pi,l) -> + | Dmodel_annot (mfi,l) -> CurrentLoc.set l; - ignore (getNode lfEq lfSyn !currentFidx pi.l_var_info.lv_name pi + ignore (PlainMerging.getNode + lfEq lfSyn !currentFidx mfi.l_var_info.lv_name mfi (Some (l, !currentDeclIdx))) -| Dtype (info,l) -> + | Dinvariant (pi,l) -> CurrentLoc.set l; - ignore (getNode ltEq ltSyn !currentFidx info.lt_name info + ignore (PlainMerging.getNode + lfEq lfSyn !currentFidx pi.l_var_info.lv_name pi + (Some (l, !currentDeclIdx))) + | Dtype (info,l) -> + CurrentLoc.set l; + ignore (PlainMerging.getNode ltEq ltSyn !currentFidx info.lt_name info (Some (l, !currentDeclIdx))) -| Dlemma (n,is_ax,labs,typs,st,l) -> + | Dlemma (n,is_ax,labs,typs,st,l) -> CurrentLoc.set l; - ignore (getNode llEq llSyn !currentFidx n (n,(is_ax,labs,typs,st,l)) + ignore (PlainMerging.getNode + llEq llSyn !currentFidx n (n,(is_ax,labs,typs,st,l)) (Some (l, !currentDeclIdx))) (* Some enumerations have to be turned into an integer. We implement this by @@ -569,11 +711,12 @@ eitems = []; eattr = []; ereferenced = false; + ekind = IInt; } (* And add it to the equivalence graph *) let intEnumInfoNode = - getNode eEq eSyn 0 intEnumInfo.ename intEnumInfo - (Some (Cil_datatype.Location.unknown, 0)) + PlainMerging.getNode eEq eSyn 0 intEnumInfo.ename intEnumInfo + (Some (Cil_datatype.Location.unknown, 0)) (* Combine the types. Raises the Failure exception with an error message. * isdef says whether the new type is for a definition *) @@ -588,7 +731,8 @@ let same_int64 e1 e2 = match (constFold true e1).enode, (constFold true e2).enode with - | Const(CInt64(i, _, _)), Const(CInt64(i', _, _)) -> i = i' + | Const(CInt64(i, _, _)), Const(CInt64(i', _, _)) -> + My_bigint.equal i i' | _ -> false let rec combineTypes (what: combineWhat) @@ -597,51 +741,51 @@ match oldt, t with | TVoid olda, TVoid a -> TVoid (addAttributes olda a) | TInt (oldik, olda), TInt (ik, a) -> - let combineIK oldk k = - if oldk == k - then oldk - else - if bytesSizeOfInt oldk=bytesSizeOfInt k && isSigned oldk=isSigned k - then + let combineIK oldk k = + if oldk == k + then oldk + else + if bytesSizeOfInt oldk=bytesSizeOfInt k && isSigned oldk=isSigned k + then (* the types contain the same sort of values but are not equal. For example on x86_16 machep unsigned short and unsigned int. *) - if rank oldk - let combineFK oldk k = - if oldk == k then oldk else + let combineFK oldk k = + if oldk == k then oldk else (* GCC allows a function definition to have a more precise integer * type than a prototype that says "double" *) - if not theMachine.msvcMode && oldk = FDouble && k = FFloat - && (what = CombineFunarg || what = CombineFunret) - then - k - else - raise (Failure "(different floating point types)") - in - TFloat (combineFK oldfk fk, addAttributes olda a) + if not theMachine.msvcMode && oldk = FDouble && k = FFloat + && (what = CombineFunarg || what = CombineFunret) + then + k + else + raise (Failure "(different floating point types)") + in + TFloat (combineFK oldfk fk, addAttributes olda a) | TEnum (oldei, olda), TEnum (ei, a) -> (* Matching enumerations always succeeds. But sometimes it maps both * enumerations to integers *) - matchEnumInfo oldfidx oldei fidx ei; - TEnum (oldei, addAttributes olda a) + matchEnumInfo oldfidx oldei fidx ei; + TEnum (oldei, addAttributes olda a) (* Strange one. But seems to be handled by GCC *) @@ -653,26 +797,26 @@ | TInt(IInt, olda), TEnum (ei, a) -> TEnum(ei, addAttributes olda a) | TComp (oldci, _, olda) , TComp (ci, _, a) -> - matchCompInfo oldfidx oldci fidx ci; + matchCompInfo oldfidx oldci fidx ci; (* If we get here we were successful *) - TComp (oldci, empty_size_cache (), addAttributes olda a) + TComp (oldci, empty_size_cache (), addAttributes olda a) | TArray (oldbt, oldsz, _, olda), TArray (bt, sz, _, a) -> - let combbt = combineTypes CombineOther oldfidx oldbt fidx bt in - let combinesz = - match oldsz, sz with - None, Some _ -> sz - | Some _, None -> oldsz - | None, None -> oldsz - | Some oldsz', Some sz' -> - if same_int64 oldsz' sz' then oldsz else - raise (Failure "(different array sizes)") - in - TArray (combbt, combinesz, empty_size_cache (), addAttributes olda a) + let combbt = combineTypes CombineOther oldfidx oldbt fidx bt in + let combinesz = + match oldsz, sz with + None, Some _ -> sz + | Some _, None -> oldsz + | None, None -> oldsz + | Some oldsz', Some sz' -> + if same_int64 oldsz' sz' then oldsz else + raise (Failure "(different array sizes)") + in + TArray (combbt, combinesz, empty_size_cache (), addAttributes olda a) | TPtr (oldbt, olda), TPtr (bt, a) -> - TPtr (combineTypes CombineOther oldfidx oldbt fidx bt, - addAttributes olda a) + TPtr (combineTypes CombineOther oldfidx oldbt fidx bt, + addAttributes olda a) (* WARNING: In this case we are leaking types from new to old !! *) | TFun (_, _, _, [Attr("missingproto",_)]), TFun _ -> t @@ -681,68 +825,68 @@ | TFun _, TFun (_, _, _, [Attr("missingproto",_)]) -> oldt | TFun (oldrt, oldargs, oldva, olda), TFun (rt, args, va, a) -> - let newrt = - combineTypes - (if what = CombineFundef then CombineFunret else CombineOther) - oldfidx oldrt fidx rt - in - if oldva != va then - raise (Failure "(diferent vararg specifiers)"); + let newrt = + combineTypes + (if what = CombineFundef then CombineFunret else CombineOther) + oldfidx oldrt fidx rt + in + if oldva != va then + raise (Failure "(diferent vararg specifiers)"); (* If one does not have arguments, believe the one with the * arguments *) - let newargs = - if oldargs = None then args else - if args = None then oldargs else - let oldargslist = argsToList oldargs in - let argslist = argsToList args in - if List.length oldargslist <> List.length argslist then - raise (Failure "(different number of arguments)") - else begin + let newargs = + if oldargs = None then args else + if args = None then oldargs else + let oldargslist = argsToList oldargs in + let argslist = argsToList args in + if List.length oldargslist <> List.length argslist then + raise (Failure "(different number of arguments)") + else begin (* Go over the arguments and update the old ones with the * adjusted types *) - Some - (List.map2 - (fun (on, ot, oa) (an, at, aa) -> - let n = if an <> "" then an else on in - let t = - combineTypes - (if what = CombineFundef then CombineFunarg - else CombineOther) - oldfidx ot fidx at - in - let a = addAttributes oa aa in - (n, t, a)) - oldargslist argslist) - end - in - TFun (newrt, newargs, oldva, addAttributes olda a) + Some + (List.map2 + (fun (on, ot, oa) (an, at, aa) -> + let n = if an <> "" then an else on in + let t = + combineTypes + (if what = CombineFundef then CombineFunarg + else CombineOther) + oldfidx ot fidx at + in + let a = addAttributes oa aa in + (n, t, a)) + oldargslist argslist) + end + in + TFun (newrt, newargs, oldva, addAttributes olda a) | TBuiltin_va_list olda, TBuiltin_va_list a -> - TBuiltin_va_list (addAttributes olda a) + TBuiltin_va_list (addAttributes olda a) | TNamed (oldt, olda), TNamed (t, a) -> - matchTypeInfo oldfidx oldt fidx t; + matchTypeInfo oldfidx oldt fidx t; (* If we get here we were able to match *) - TNamed(oldt, addAttributes olda a) + TNamed(oldt, addAttributes olda a) (* Unroll first the new type *) | _, TNamed (t, a) -> - let res = combineTypes what oldfidx oldt fidx t.ttype in - typeAddAttributes a res + let res = combineTypes what oldfidx oldt fidx t.ttype in + typeAddAttributes a res (* And unroll the old type as well if necessary *) | TNamed (oldt, a), _ -> - let res = combineTypes what oldfidx oldt.ttype fidx t in - typeAddAttributes a res + let res = combineTypes what oldfidx oldt.ttype fidx t in + typeAddAttributes a res | _ -> ( (* raise (Failure "(different type constructors)") *) - let msg:string = - Pretty_utils.sfprintf - "(different type constructors: %a vs. %a)" - d_type oldt d_type t - in - raise (Failure msg)) + let msg:string = + Pretty_utils.sfprintf + "(different type constructors: %a vs. %a)" + d_type oldt d_type t + in + raise (Failure msg)) (* Match two compinfos and throw a Failure if they do not match *) @@ -753,8 +897,10 @@ (* See if we have a mapping already *) (* Make the nodes if not already made. Actually return the * representatives *) - let oldcinode = getNode sEq sSyn oldfidx oldci.cname oldci None in - let cinode = getNode sEq sSyn fidx ci.cname ci None in + let oldcinode = + PlainMerging.getNode sEq sSyn oldfidx oldci.cname oldci None + in + let cinode = PlainMerging.getNode sEq sSyn fidx ci.cname ci None in if oldcinode == cinode then (* We already know they are the same *) () else begin @@ -793,16 +939,16 @@ try List.iter2 (fun oldf f -> - if oldf.fbitfield <> f.fbitfield then - raise (Failure "(different bitfield info)"); - if oldf.fattr <> f.fattr then - raise (Failure "(different field attributes)"); + if oldf.fbitfield <> f.fbitfield then + raise (Failure "(different bitfield info)"); + if oldf.fattr <> f.fattr then + raise (Failure "(different field attributes)"); (* Make sure the types are compatible *) - let newtype = - combineTypes CombineOther oldfidx oldf.ftype fidx f.ftype - in + let newtype = + combineTypes CombineOther oldfidx oldf.ftype fidx f.ftype + in (* Change the type in the representative *) - oldf.ftype <- newtype) + oldf.ftype <- newtype) oldci.cfields ci.cfields with Failure reason -> (* Our assumption was wrong. Forget the isomorphism *) @@ -819,8 +965,7 @@ (* We will reuse the old one. One of them is empty. If the old one is * empty, copy over the fields from the new one. Won't this result in * all sorts of undefined types??? *) - if old_len = 0 then - oldci.cfields <- ci.cfields; + if old_len = 0 then oldci.cfields <- ci.cfields; end; (* We get here when we succeeded checking that they are equal, or one of * them was empty *) @@ -832,8 +977,9 @@ and matchEnumInfo (oldfidx: int) (oldei: enuminfo) (fidx: int) (ei: enuminfo) : unit = (* Find the node for this enum, no path compression. *) - let oldeinode = getNode eEq eSyn oldfidx oldei.ename oldei None in - let einode = getNode eEq eSyn fidx ei.ename ei None in + let oldeinode = PlainMerging.getNode eEq eSyn oldfidx oldei.ename oldei None + in + let einode = PlainMerging.getNode eEq eSyn fidx ei.ename ei None in if oldeinode == einode then (* We already know they are the same *) () else begin @@ -849,17 +995,26 @@ * conservative check. *) List.iter2 (fun old_item item -> - if old_item.einame <> item.einame then - raise (Failure "(different names for enumeration items)"); - if not (same_int64 old_item.eival item.eival) then - raise (Failure "(different values for enumeration items)")) + if old_item.einame <> item.einame then + raise (Failure + "(different names for enumeration items)"); + if not (same_int64 old_item.eival item.eival) then + raise (Failure "(different values for enumeration items)")) oldei.eitems ei.eitems; (* Set the representative *) let newrep, _ = union oldeinode einode in (* We get here if the enumerations match *) newrep.ndata.eattr <- addAttributes oldei.eattr ei.eattr; () - with Failure _msg -> begin + with Failure msg -> begin + let pp_items = Pretty_utils.pp_list ~pre:"{" ~suf:"}" ~sep:",@ " + (fun fmt item -> Format.fprintf fmt "%s=%a" + item.eiorig_name d_exp item.eival) in + if oldeinode != intEnumInfoNode && einode != intEnumInfoNode then + Kernel.warning ~current:true + "@[cannot merge definitions of enum %s@ %s;@ items %a and@ %a@]" + oldei.ename msg + pp_items oldei.eitems pp_items ei.eitems; (* Get here if you cannot merge two enumeration nodes *) if oldeinode != intEnumInfoNode then begin let _ = union oldeinode intEnumInfoNode in () @@ -875,10 +1030,10 @@ and matchTypeInfo (oldfidx: int) (oldti: typeinfo) (fidx: int) (ti: typeinfo) : unit = if oldti.tname = "" || ti.tname = "" then - Cilmsg.fatal "matchTypeInfo for anonymous type"; + Kernel.fatal "matchTypeInfo for anonymous type"; (* Find the node for this enum, no path compression. *) - let oldtnode = getNode tEq tSyn oldfidx oldti.tname oldti None in - let tnode = getNode tEq tSyn fidx ti.tname ti None in + let oldtnode = PlainMerging.getNode tEq tSyn oldfidx oldti.tname oldti None in + let tnode = PlainMerging.getNode tEq tSyn fidx ti.tname ti None in if oldtnode == tnode then (* We already know they are the same *) () else begin @@ -920,8 +1075,12 @@ with Exit -> true let matchLogicInfo oldfidx oldpi fidx pi = - let oldtnode = getNode lfEq lfSyn oldfidx oldpi.l_var_info.lv_name oldpi None in - let tnode = getNode lfEq lfSyn fidx pi.l_var_info.lv_name pi None in + let oldtnode = + PlainMerging.getNode lfEq lfSyn oldfidx oldpi.l_var_info.lv_name oldpi None + in + let tnode = + PlainMerging.getNode lfEq lfSyn fidx pi.l_var_info.lv_name pi None + in if oldtnode == tnode then (* We already know they are the same *) () else begin @@ -931,7 +1090,7 @@ let fidx = tnode.nfidx in if Logic_utils.is_same_logic_info oldpi pi then begin if has_static_ref_logic_function oldpi then - Cilmsg.abort + Kernel.abort "multiple inclusion of logic function %s referring to a static variable" oldpi.l_var_info.lv_name else if oldfidx < fidx then @@ -939,13 +1098,14 @@ else oldtnode.nrep <- tnode.nrep end else - Cilmsg.abort "invalid multiple logic function declarations %s" pi.l_var_info.lv_name + Kernel.abort "invalid multiple logic function declarations %s" pi.l_var_info.lv_name end let matchLogicType oldfidx oldnode fidx node = let oldtnode = - getNode ltEq ltSyn oldfidx oldnode.lt_name oldnode None in - let tnode = getNode ltEq ltSyn fidx oldnode.lt_name node None in + PlainMerging.getNode ltEq ltSyn oldfidx oldnode.lt_name oldnode None + in + let tnode = PlainMerging.getNode ltEq ltSyn fidx oldnode.lt_name node None in if oldtnode == tnode then (* We already know they are the same *) () else begin @@ -959,27 +1119,26 @@ else oldtnode.nrep <- tnode.nrep end else - Cil.error "invalid multiple logic type declarations %s" node.lt_name + Kernel.error ~current:true + "invalid multiple logic type declarations %s" node.lt_name end let matchLogicCtor oldfidx oldpi fidx pi = - let oldtnode = getNode lcEq lcSyn oldfidx oldpi.ctor_name oldpi None in - let tnode = getNode lcEq lcSyn fidx pi.ctor_name pi None in - if oldtnode == tnode then (* We already know they are the same *) - () - else begin - Cil.error "invalid multiple logic constructors declarations %s" pi.ctor_name - end + let oldtnode = + PlainMerging.getNode lcEq lcSyn oldfidx oldpi.ctor_name oldpi None + in + let tnode = PlainMerging.getNode lcEq lcSyn fidx pi.ctor_name pi None in + if oldtnode != tnode then + Kernel.error ~current:true + "invalid multiple logic constructors declarations %s" pi.ctor_name let matchLogicAxiomatic oldfidx (oldid,_ as oldnode) fidx (id,_ as node) = - let oldanode = getNode laEq laSyn oldfidx oldid oldnode None in - let anode = getNode laEq laSyn fidx id node None in - if oldanode == anode then - () - else begin - let (_,oldax) = oldanode.ndata in + let oldanode = PlainMerging.getNode laEq laSyn oldfidx oldid oldnode None in + let anode = PlainMerging.getNode laEq laSyn fidx id node None in + if oldanode != anode then begin + let _, oldax = oldanode.ndata in let oldaidx = oldanode.nfidx in - let (_,ax) = anode.ndata in + let _, ax = anode.ndata in let aidx = anode.nfidx in if Logic_utils.is_same_axiomatic oldax ax then begin if oldaidx < aidx then @@ -987,14 +1146,14 @@ else oldanode.nrep <- anode.nrep end else - Cil.error "invalid multiple axiomatic declarations %s" id + Kernel.error ~current:true + "invalid multiple axiomatic declarations %s" id end let matchLogicLemma oldfidx (oldid, _ as oldnode) fidx (id, _ as node) = - let oldlnode = getNode llEq llSyn oldfidx oldid oldnode None in - let lnode = getNode llEq llSyn fidx id node None in - if oldlnode == lnode then () - else begin + let oldlnode = PlainMerging.getNode llEq llSyn oldfidx oldid oldnode None in + let lnode = PlainMerging.getNode llEq llSyn fidx id node None in + if oldlnode != lnode then begin let (oldid,(oldax,oldlabs,oldtyps,oldst,oldloc)) = oldlnode.ndata in let oldfidx = oldlnode.nfidx in let (id,(ax,labs,typs,st,loc)) = lnode.ndata in @@ -1008,7 +1167,34 @@ else oldlnode.nrep <- lnode.nrep end else - Cil.error "invalid multiple lemmas or axioms declarations for %s" id + Kernel.error ~current:true + "invalid multiple lemmas or axioms declarations for %s" id + end + +let matchVolatileClause oldfidx (oldid,_ as oldnode) fidx (id,_ as node) = + let oldlnode = + VolatileMerging.getNode lvEq lvSyn oldfidx oldid oldnode None + in + let lnode = VolatileMerging.getNode lvEq lvSyn fidx id node None in + if oldlnode != lnode then begin + let (oldid,(oldr,oldw,oldloc)) = oldlnode.ndata in + let oldfidx = oldlnode.nfidx in + let (id,(r,w,loc)) = lnode.ndata in + let fidx = lnode.nfidx in + if Logic_utils.is_same_global_annotation + (Dvolatile (oldid,oldr,oldw,oldloc)) (Dvolatile (id,r,w,loc)) + then begin + if oldfidx < fidx then + lnode.nrep <- oldlnode.nrep + else + oldlnode.nrep <- lnode.nrep + end else + Kernel.error ~current:true + "invalid multiple volatile clauses for locations %a" + (Pretty_utils.pp_list + ~sep:("," ^^ Pretty_utils.space_sep) + (fun fmt x -> Cil.d_term fmt x.it_content)) + id end (* Scan all files and do two things *) @@ -1022,10 +1208,11 @@ let rec oneFilePass1 (f:file) : unit = H.add fileNames !currentFidx f.fileName; - Cilmsg.feedback ~level:2 "Pre-merging (%d) %s" !currentFidx f.fileName ; + Kernel.feedback ~level:2 "Pre-merging (%d) %s" !currentFidx f.fileName ; currentDeclIdx := 0; if f.globinitcalled || f.globinit <> None then - Cil.warning "Merging file %s has global initializer" f.fileName; + Kernel.warning ~current:true + "Merging file %s has global initializer" f.fileName; (* We scan each file and we look at all global varinfo. We see if globals * with the same name have been encountered before and we merge those types @@ -1033,12 +1220,14 @@ let matchVarinfo (vi: varinfo) (l: location * int) = ignore (Alpha.registerAlphaName vtAlpha None vi.vname (CurrentLoc.get ())); (* Make a node for it and put it in vEq *) - let vinode = mkSelfNode vEq vSyn !currentFidx vi.vname vi (Some l) in + let vinode = + PlainMerging.mkSelfNode vEq vSyn !currentFidx vi.vname vi (Some l) + in try - let oldvinode = find true (H.find vEnv vi.vname) in + let oldvinode = PlainMerging.find true (H.find vEnv vi.vname) in let oldloc, _ = match oldvinode.nloc with - None -> (Cilmsg.fatal "old variable is undefined") + None -> (Kernel.fatal "old variable is undefined") | Some l -> l in let oldvi = oldvinode.ndata in @@ -1051,7 +1240,10 @@ !currentFidx vi.vtype; with (Failure reason) -> begin (* Go ahead when ignoring conflicts *) - let f = if !ignore_merge_conflicts then Cil.warning else Cil.fatal in + let f fmt = + if !ignore_merge_conflicts then Kernel.warning ~current:true fmt + else Kernel.fatal ~current:true fmt + in f "@[Incompatible@ declaration@ for@ %s@ (included from @ %s).@ \ Previous@ was@ at@ %a@ (include from@ %s)@ %s]" vi.vname @@ -1069,9 +1261,7 @@ if hasAttribute "const" (typeAttrs vi.vtype) != hasAttribute "const" (typeAttrs oldvi.vtype) then begin newrep.ndata.vtype <- typeRemoveAttributes ["const"] newtype; - end else begin - newrep.ndata.vtype <- newtype; - end; + end else newrep.ndata.vtype <- newtype; (* clean up the storage. *) let newstorage = if vi.vstorage = oldvi.vstorage || vi.vstorage = Extern then @@ -1082,8 +1272,9 @@ else if oldvi.vstorage = Static && vi.vstorage = NoStorage then Static else begin - Cil.warning - "Inconsistent storage specification for %s. Now is %a and previous was %a at %a" + Kernel.warning ~current:true + "Inconsistent storage specification for %s. \ +Now is %a and previous was %a at %a" vi.vname d_storage vi.vstorage d_storage oldvi.vstorage d_loc oldloc ; @@ -1092,8 +1283,8 @@ in newrep.ndata.vstorage <- newstorage; newrep.ndata.vattr <- addAttributes oldvi.vattr vi.vattr - with Not_found -> (* Not present in the previous files. Remember it for - * later *) + with Not_found -> + (* Not present in the previous files. Remember it for later *) H.add vEnv vi.vname vinode in List.iter @@ -1126,7 +1317,7 @@ end else begin if fdec.svar.vinline && mergeInlines then (* Just create the nodes for inline functions *) - ignore (getNode iEq iSyn !currentFidx + ignore (PlainMerging.getNode iEq iSyn !currentFidx fdec.svar.vname fdec.svar (Some (l, !currentDeclIdx))) end (* Make nodes for the defined type and structure tags *) @@ -1135,7 +1326,7 @@ t.treferenced <- false; if t.tname <> "" then (* The empty names are just for introducing * undefined comp tags *) - ignore (getNode tEq tSyn !currentFidx t.tname t + ignore (PlainMerging.getNode tEq tSyn !currentFidx t.tname t (Some (l, !currentDeclIdx))) else begin (* Go inside and clean the referenced flag for the * declared tags *) @@ -1143,74 +1334,42 @@ TComp (ci, _, _ ) -> ci.creferenced <- false; (* Create a node for it *) - ignore (getNode sEq sSyn !currentFidx ci.cname ci None) + ignore + (PlainMerging.getNode sEq sSyn !currentFidx ci.cname ci None) | TEnum (ei, _) -> ei.ereferenced <- false; - ignore (getNode eEq eSyn !currentFidx ei.ename ei None); + ignore + (PlainMerging.getNode + eEq eSyn !currentFidx ei.ename ei None) - | _ -> (Cilmsg.fatal "Anonymous Gtype is not TComp") + | _ -> (Kernel.fatal "Anonymous Gtype is not TComp") end | GCompTag (ci, l) -> incr currentDeclIdx; ci.creferenced <- false; - ignore (getNode sEq sSyn !currentFidx ci.cname ci + ignore (PlainMerging.getNode sEq sSyn !currentFidx ci.cname ci (Some (l, !currentDeclIdx))) + | GCompTagDecl (ci,_) -> ci.creferenced <- false + | GEnumTagDecl (ei,_) -> ei.ereferenced <- false | GEnumTag (ei, l) -> incr currentDeclIdx; ei.ereferenced <- false; - ignore (getNode eEq eSyn !currentFidx ei.ename ei + ignore (PlainMerging.getNode eEq eSyn !currentFidx ei.ename ei (Some (l, !currentDeclIdx))) | GAnnot (gannot,l) -> CurrentLoc.set l; incr currentDeclIdx; global_annot_pass1 gannot - | _ -> ()) + | GText _ | GPragma _ | GAsm _ -> ()) f.globals - -(* Try to merge synonyms. Do not give an error if they fail to merge *) -let doMergeSynonyms - (syn : (string, 'a node) H.t) - (_eq : (int * string, 'a node) H.t) - (compare : int -> 'a -> int -> 'a -> unit) (* A comparison function that - * throws Failure if no match *) - : unit = - H.iter (fun n node -> - if not node.nmergedSyns then begin - (* find all the nodes for the same name *) - let all = H.find_all syn n in - let rec tryone (classes: 'a node list) (* A number of representatives - * for this name *) - (nd: 'a node) : 'a node list (* Returns an expanded set - * of classes *) = - nd.nmergedSyns <- true; - (* Compare in turn with all the classes we have so far *) - let rec compareWithClasses = function - [] -> [nd](* No more classes. Add this as a new class *) - | c :: restc -> - try - compare c.nfidx c.ndata nd.nfidx nd.ndata; - (* Success. Stop here the comparison *) - c :: restc - with Failure _ -> (* Failed. Try next class *) - c :: (compareWithClasses restc) - in - compareWithClasses classes - in - (* Start with an empty set of classes for this name *) - let _ = List.fold_left tryone [] all in - () - end) - syn - - let matchInlines (oldfidx: int) (oldi: varinfo) (fidx: int) (i: varinfo) = - let oldinode = getNode iEq iSyn oldfidx oldi.vname oldi None in - let inode = getNode iEq iSyn fidx i.vname i None in + let oldinode = PlainMerging.getNode iEq iSyn oldfidx oldi.vname oldi None in + let inode = PlainMerging.getNode iEq iSyn fidx i.vname i None in if oldinode != inode then begin (* Replace with the representative data *) let oldi = oldinode.ndata in @@ -1247,12 +1406,20 @@ class renameVisitorClass = let rename_associated_logic_var lv = match lv.lv_origin with - None -> DoChildren + None -> + (match PlainMerging.findReplacement true lfEq !currentFidx lv.lv_name + with + | None -> DoChildren + | Some (li,_) -> + let lv' = li.l_var_info in + if lv == lv' then DoChildren (* Replacement already done... *) + else ChangeTo lv') | Some vi -> if not vi.vglob then DoChildren else begin - match findReplacement true vEq !currentFidx vi.vname with - None -> DoChildren + match PlainMerging.findReplacement true vEq !currentFidx vi.vname + with + | None -> DoChildren | Some (vi',_) -> vi'.vreferenced <- true; if vi == vi' then DoChildren (* replacement was done already*) @@ -1265,15 +1432,16 @@ end in let find_enumitem_replacement ei = - match findReplacement true eEq !currentFidx ei.eihost.ename with + match PlainMerging.findReplacement true eEq !currentFidx ei.eihost.ename with None -> None | Some (enum,_) -> if enum == intEnumInfo then begin (* Two different enums have been merged into an int type. Switch to an integer constant. *) match (constFold true ei.eival).enode with - | Const c -> Some c - | _ -> fatal "non constant value for an enum item" + | Const c -> Some c + | _ -> + Kernel.fatal ~current:true "non constant value for an enum item" end else begin (* Merged with an isomorphic type. Find the appropriate enumitem *) let n = Extlib.find_index (fun e -> e.einame = ei.einame) @@ -1297,11 +1465,11 @@ H.add varUsedAlready vi.vname (); DoChildren end else begin - match findReplacement true vEq !currentFidx vi.vname with + match PlainMerging.findReplacement true vEq !currentFidx vi.vname with None -> DoChildren | Some (vi', oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of var %s(%d) to %s(%d)" + (Kernel.debug "Renaming use of var %s(%d) to %s(%d)" vi.vname !currentFidx vi'.vname oldfidx); vi'.vreferenced <- true; @@ -1314,9 +1482,11 @@ method vlogic_var_use lv = rename_associated_logic_var lv method vlogic_info_use li = - match findReplacement true lfEq !currentFidx li.l_var_info.lv_name with + match + PlainMerging.findReplacement true lfEq !currentFidx li.l_var_info.lv_name + with None -> if debugMerge then - (Cilmsg.debug "Using logic function %s(%a)(%d)" + (Kernel.debug "Using logic function %s(%a)(%d)" li.l_var_info.lv_name (Pretty_utils.pp_list ~sep:",@ " d_logic_type) (List.map (fun v -> v.lv_type) li.l_profile) @@ -1324,7 +1494,7 @@ DoChildren | Some(li',oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of logic function %s(%a)(%d) to %s(%a)(%d)" + (Kernel.debug "Renaming use of logic function %s(%a)(%d) to %s(%a)(%d)" li.l_var_info.lv_name (Pretty_utils.pp_list ~sep:",@ " d_logic_type) (List.map (fun v -> v.lv_type) li.l_profile) @@ -1336,10 +1506,13 @@ ChangeTo li' method vlogic_info_decl li = - match findReplacement true lfEq !currentFidx li.l_var_info.lv_name with + match + PlainMerging.findReplacement + true lfEq !currentFidx li.l_var_info.lv_name + with None -> if debugMerge then - (Cilmsg.debug "Using logic function %s(%a)(%d)" + (Kernel.debug "Using logic function %s(%a)(%d)" li.l_var_info.lv_name (Pretty_utils.pp_list ~sep:",@ " d_logic_type) (List.map (fun v -> v.lv_type) li.l_profile) @@ -1347,7 +1520,7 @@ DoChildren | Some(li',oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of logic function %s(%a)(%d) to %s(%a)(%d)" + (Kernel.debug "Renaming use of logic function %s(%a)(%d) to %s(%a)(%d)" li.l_var_info.lv_name (Pretty_utils.pp_list ~sep:",@ " d_logic_type) (List.map (fun v -> v.lv_type) li.l_profile) @@ -1359,59 +1532,59 @@ ChangeTo li' method vlogic_type_info_use lt = - match findReplacement true ltEq !currentFidx lt.lt_name with + match PlainMerging.findReplacement true ltEq !currentFidx lt.lt_name with None -> if debugMerge then - (Cilmsg.debug "Using logic type %s(%d)" + (Kernel.debug "Using logic type %s(%d)" lt.lt_name !currentFidx); DoChildren | Some(lt',oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of logic type %s(%d) to %s(%d)" + (Kernel.debug "Renaming use of logic type %s(%d) to %s(%d)" lt.lt_name !currentFidx lt'.lt_name oldfidx); ChangeTo lt' method vlogic_type_info_decl lt = - match findReplacement true ltEq !currentFidx lt.lt_name with + match PlainMerging.findReplacement true ltEq !currentFidx lt.lt_name with None -> if debugMerge then - (Cilmsg.debug "Using logic type %s(%d)" + (Kernel.debug "Using logic type %s(%d)" lt.lt_name !currentFidx); DoChildren | Some(lt',oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of logic function %s(%d) to %s(%d)" + (Kernel.debug "Renaming use of logic function %s(%d) to %s(%d)" lt.lt_name !currentFidx lt'.lt_name oldfidx); ChangeTo lt' method vlogic_ctor_info_use lc = - match findReplacement true lcEq !currentFidx lc.ctor_name with + match PlainMerging.findReplacement true lcEq !currentFidx lc.ctor_name with None -> if debugMerge then - (Cilmsg.debug "Using logic constructor %s(%d)" + (Kernel.debug "Using logic constructor %s(%d)" lc.ctor_name !currentFidx); DoChildren | Some(lc',oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of logic type %s(%d) to %s(%d)" + (Kernel.debug "Renaming use of logic type %s(%d) to %s(%d)" lc.ctor_name !currentFidx lc'.ctor_name oldfidx); ChangeTo lc' method vlogic_ctor_info_decl lc = - match findReplacement true lcEq !currentFidx lc.ctor_name with + match PlainMerging.findReplacement true lcEq !currentFidx lc.ctor_name with None -> if debugMerge then - (Cilmsg.debug "Using logic constructor %s(%d)" + (Kernel.debug "Using logic constructor %s(%d)" lc.ctor_name !currentFidx); DoChildren | Some(lc',oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of logic function %s(%d) to %s(%d)" + (Kernel.debug "Renaming use of logic function %s(%d) to %s(%d)" lc.ctor_name !currentFidx lc'.ctor_name oldfidx); ChangeTo lc' @@ -1421,16 +1594,22 @@ method vtype (t: typ) = match t with TComp (ci, _, a) when not ci.creferenced -> begin - match findReplacement true sEq !currentFidx ci.cname with - None -> DoChildren + match PlainMerging.findReplacement true sEq !currentFidx ci.cname with + None -> if debugMerge then + (Kernel.debug "No renaming needed %s(%d)" ci.cname !currentFidx); + DoChildren | Some (ci', oldfidx) -> if debugMerge then - (Cilmsg.debug "Renaming use of %s(%d) to %s(%d)" + (Kernel.debug "Renaming use of %s(%d) to %s(%d)" ci.cname !currentFidx ci'.cname oldfidx); ChangeTo (TComp (ci', empty_size_cache (), visitCilAttributes (self :> cilVisitor) a)) end + | TComp(ci,_,_) -> + if debugMerge then + (Kernel.debug "%s(%d) referenced. No change" ci.cname !currentFidx); + DoChildren | TEnum (ei, a) when not ei.ereferenced -> begin - match findReplacement true eEq !currentFidx ei.ename with + match PlainMerging.findReplacement true eEq !currentFidx ei.ename with None -> DoChildren | Some (ei', _) -> if ei' == intEnumInfo then @@ -1441,7 +1620,7 @@ end | TNamed (ti, a) when not ti.treferenced -> begin - match findReplacement true tEq !currentFidx ti.tname with + match PlainMerging.findReplacement true tEq !currentFidx ti.tname with None -> DoChildren | Some (ti', _) -> ChangeTo (TNamed (ti', visitCilAttributes (self :> cilVisitor) a)) @@ -1456,6 +1635,16 @@ None -> DoChildren | Some c -> ChangeTo { e with enode = Const c }) + | CastE _ -> + (* Maybe the cast is no longer necessary if an enum has been replaced + by an integer type. *) + let post_action e = match e.enode with + | CastE(typ,exp) when + Cilutil.equals (typeSig (typeOf exp)) (typeSig typ) -> + exp + | _ -> e + in + ChangeDoChildrenPost (e,post_action) | _ -> DoChildren method vterm e = @@ -1479,19 +1668,21 @@ if f.fcomp.creferenced then DoChildren else begin - match findReplacement true sEq !currentFidx f.fcomp.cname with + match + PlainMerging.findReplacement true sEq !currentFidx f.fcomp.cname + with None -> DoChildren (* We did not replace it *) | Some (ci', _oldfidx) -> begin (* First, find out the index of the original field *) let rec indexOf (i: int) = function - [] -> Cilmsg.fatal "Cannot find field %s in %s" + [] -> Kernel.fatal "Cannot find field %s in %s" f.fname (compFullName f.fcomp) | f' :: _ when f' == f -> i | _ :: rest -> indexOf (i + 1) rest in let index = indexOf 0 f.fcomp.cfields in if List.length ci'.cfields <= index then - Cilmsg.fatal "Too few fields in replacement %s for %s" + Kernel.fatal "Too few fields in replacement %s for %s" (compFullName ci') (compFullName f.fcomp); let f' = List.nth ci'.cfields index in @@ -1507,19 +1698,21 @@ if f.fcomp.creferenced then DoChildren else begin - match findReplacement true sEq !currentFidx f.fcomp.cname with + match + PlainMerging.findReplacement true sEq !currentFidx f.fcomp.cname + with None -> DoChildren (* We did not replace it *) | Some (ci', _oldfidx) -> begin (* First, find out the index of the original field *) let rec indexOf (i: int) = function - [] -> Cilmsg.fatal "Cannot find field %s in %s" + [] -> Kernel.fatal "Cannot find field %s in %s" f.fname (compFullName f.fcomp) | f' :: _ when f' == f -> i | _ :: rest -> indexOf (i + 1) rest in let index = indexOf 0 f.fcomp.cfields in if List.length ci'.cfields <= index then - Cilmsg.fatal "Too few fields in replacement %s for %s" + Kernel.fatal "Too few fields in replacement %s for %s" (compFullName ci') (compFullName f.fcomp); let f' = List.nth ci'.cfields index in @@ -1551,11 +1744,11 @@ if vi.vreferenced then begin (* Already renamed *) DoChildren end else begin - match findReplacement true vEq !currentFidx vi.vname with + match PlainMerging.findReplacement true vEq !currentFidx vi.vname with None -> DoChildren | Some (vi', oldfidx) -> if debugMerge then - Cilmsg.debug "Renaming var %s(%d) to %s(%d)" + Kernel.debug "Renaming var %s(%d) to %s(%d)" vi.vname !currentFidx vi'.vname oldfidx; vi'.vreferenced <- true; @@ -1572,7 +1765,7 @@ with Not_found -> vi.vname in (* Now see if this must be replaced *) - match findReplacement true vEq !currentFidx origname with + match PlainMerging.findReplacement true vEq !currentFidx origname with None -> DoChildren | Some (vi', _) -> (*TODO: visit the spec to change references to formals *) @@ -1596,72 +1789,102 @@ List.iter (fun x -> ignore(visitCilLogicType vis x.lv_type)) l; !tvars -let rec logic_annot_pass2 ~in_axiomatic g a = match a with - -| Dfun_or_pred (li,l) -> - begin - CurrentLoc.set l; - match findReplacement true lfEq !currentFidx li.l_var_info.lv_name with - | None -> +let rec logic_annot_pass2 ~in_axiomatic g a = + match a with + | Dfun_or_pred (li,l) -> + begin + CurrentLoc.set l; + match + PlainMerging.findReplacement + true lfEq !currentFidx li.l_var_info.lv_name + with + | None -> if not in_axiomatic then mergePushGlobals (visitCilGlobal renameVisitor g); Logic_utils.add_logic_function li; - | Some _ -> () - (* FIXME: should we perform same actions - as the case Dlogic_reads above ? *) - end -| Dtype (t,l) -> - begin - CurrentLoc.set l; - match findReplacement true ltEq !currentFidx t.lt_name with - | None -> - if not in_axiomatic then - mergePushGlobals (visitCilGlobal renameVisitor g); - Logic_env.add_logic_type - t.lt_name (H.find ltEq (!currentFidx,t.lt_name)).ndata - | Some _ -> () - end -| Dinvariant ({l_var_info = {lv_name = n}},l) -> - begin - CurrentLoc.set l; - match findReplacement true lfEq !currentFidx n with - | None -> - assert (not in_axiomatic); - mergePushGlobals (visitCilGlobal renameVisitor g); - Logic_utils.add_logic_function (H.find lfEq (!currentFidx,n)).ndata - | Some _ -> () - end -| Dtype_annot (n,l) -> - begin - CurrentLoc.set l; - match findReplacement true lfEq !currentFidx n.l_var_info.lv_name with - | None -> - let g = visitCilGlobal renameVisitor g in - if not in_axiomatic then - mergePushGlobals g; - Logic_utils.add_logic_function - (H.find lfEq (!currentFidx,n.l_var_info.lv_name)).ndata - | Some _ -> () - end -| Dlemma (n,_,_,_,_,l) -> - begin - CurrentLoc.set l; - match findReplacement true llEq !currentFidx n with - None -> - if not in_axiomatic then - mergePushGlobals (visitCilGlobal renameVisitor g) - | Some _ -> () - end -| Daxiomatic(n,l,loc) -> - begin - CurrentLoc.set loc; - match findReplacement true laEq !currentFidx n with - None -> - assert (not in_axiomatic); + | Some _ -> () + (* FIXME: should we perform same actions + as the case Dlogic_reads above ? *) + end + | Dtype (t,l) -> + begin + CurrentLoc.set l; + match PlainMerging.findReplacement true ltEq !currentFidx t.lt_name with + | None -> + if not in_axiomatic then + mergePushGlobals (visitCilGlobal renameVisitor g); + Logic_env.add_logic_type + t.lt_name + (PlainMerging.find_eq_table ltEq (!currentFidx,t.lt_name)).ndata + | Some _ -> () + end + | Dinvariant ({l_var_info = {lv_name = n}},l) -> + begin + CurrentLoc.set l; + match PlainMerging.findReplacement true lfEq !currentFidx n with + | None -> + assert (not in_axiomatic); mergePushGlobals (visitCilGlobal renameVisitor g); - List.iter (logic_annot_pass2 ~in_axiomatic:true g) l - | Some _ -> () - end + Logic_utils.add_logic_function + (PlainMerging.find_eq_table lfEq (!currentFidx,n)).ndata + | Some _ -> () + end + | Dtype_annot (n,l) -> + begin + CurrentLoc.set l; + match + PlainMerging.findReplacement + true lfEq !currentFidx n.l_var_info.lv_name + with + | None -> + let g = visitCilGlobal renameVisitor g in + if not in_axiomatic then + mergePushGlobals g; + Logic_utils.add_logic_function + (PlainMerging.find_eq_table + lfEq (!currentFidx,n.l_var_info.lv_name)).ndata + | Some _ -> () + end + | Dmodel_annot (n,l) -> + begin + CurrentLoc.set l; + match + PlainMerging.findReplacement + true lfEq !currentFidx n.l_var_info.lv_name + with + | None -> + let g = visitCilGlobal renameVisitor g in + if not in_axiomatic then + mergePushGlobals g; + Logic_utils.add_logic_function + (PlainMerging.find_eq_table + lfEq (!currentFidx,n.l_var_info.lv_name)).ndata + | Some _ -> () + end + | Dlemma (n,_,_,_,_,l) -> + begin + CurrentLoc.set l; + match PlainMerging.findReplacement true llEq !currentFidx n with + None -> + if not in_axiomatic then + mergePushGlobals (visitCilGlobal renameVisitor g) + | Some _ -> () + end + | Dvolatile(vi,_,_,loc) -> + (CurrentLoc.set loc; + match VolatileMerging.findReplacement true lvEq !currentFidx vi with + None -> mergePushGlobals (visitCilGlobal renameVisitor g) + | Some _ -> ()) + | Daxiomatic(n,l,loc) -> + begin + CurrentLoc.set loc; + match PlainMerging.findReplacement true laEq !currentFidx n with + None -> + assert (not in_axiomatic); + mergePushGlobals (visitCilGlobal renameVisitor g); + List.iter (logic_annot_pass2 ~in_axiomatic:true g) l + | Some _ -> () + end let global_annot_pass2 g a = logic_annot_pass2 ~in_axiomatic:false g a @@ -1756,13 +1979,14 @@ and equalExps (x: exp) (y: exp) : bool = begin match x.enode,y.enode with - | Const(xc), Const(yc) -> xc = yc || (* safe to use '=' on literals *) - ( - (* CIL changes (unsigned)0 into 0U during printing.. *) + | Const(xc), Const(yc) -> + Cil.compareConstant xc yc || + ((* CIL changes (unsigned)0 into 0U during printing.. *) match xc,yc with | CInt64(xv,_,_),CInt64(yv,_,_) -> - (Int64.to_int xv) = 0 && (* ok if they're both 0 *) - (Int64.to_int yv) = 0 + (My_bigint.equal xv My_bigint.zero) + && (* ok if they're both 0 *) + (My_bigint.equal yv My_bigint.zero) | _,_ -> false ) | Lval(xl), Lval(yl) -> (equalLvals xl yl) @@ -1825,7 +2049,7 @@ * representative types or variables. We set the referenced flags once we * have replaced the names. *) let oneFilePass2 (f: file) = - Cilmsg.feedback ~level:2 "Final merging phase: %s" f.fileName; + Kernel.feedback ~level:2 "Final merging phase: %s" f.fileName; currentDeclIdx := 0; (* Even though we don't need it anymore *) H.clear varUsedAlready; H.clear originalVarNames; @@ -1859,10 +2083,7 @@ in (* Remember the original name *) H.add originalVarNames newName vi.vname; - if debugMerge then Cilmsg.debug "renaming %s at %a to %s" - vi.vname - d_loc vloc - newName; + Kernel.debug "renaming %s at %a to %s" vi.vname d_loc vloc newName; vi.vname <- newName; vi.vreferenced <- true; Cil_const.set_vid vi; @@ -1870,7 +2091,7 @@ vi end else begin (* Find the representative *) - match findReplacement true vEq !currentFidx vi.vname with + match PlainMerging.findReplacement true vEq !currentFidx vi.vname with None -> vi (* This is the representative *) | Some (vi', _) -> (* Reuse some previous one *) vi'.vreferenced <- true; (* Mark it as done already *) @@ -1879,8 +2100,7 @@ end end in - try - match g with + match g with | GVarDecl (spec,vi, l) as g -> CurrentLoc.set l; incr currentDeclIdx; @@ -1925,16 +2145,17 @@ ) else ( (* Both GVars have initializers. *) - Cil.error "global var %s at %a has different initializer than %a" + Kernel.error ~current:true + "global var %s at %a has different initializer than %a" vi'.vname - d_loc l d_loc prevLoc; + d_loc l d_loc prevLoc; false ) - with Not_found -> ( + with Not_found -> begin (* no previous definition *) - (H.add emittedVarDefn vi'.vname (vi', init.init, l)); - true (* emit it *) - ) + H.add emittedVarDefn vi'.vname (vi', init.init, l); + true (* emit it *) + end in if emitIt then @@ -1959,7 +2180,7 @@ let fdec' = match visitCilGlobal renameVisitor g with | [ GFun(fdec', _) ] -> fdec' - | _ -> Cilmsg.fatal "renameVisitor for GFun returned something else" + | _ -> Kernel.fatal "renameVisitor for GFun returned something else" in let g' = GFun(fdec', l) in (* Now restore the parameter names *) @@ -1967,14 +2188,15 @@ let oldnames, foundthem = try H.find formalNames (!currentFidx, origname), true with Not_found -> begin - Cil.warnOpt "Cannot find %s in formalNames" origname ; + Kernel.debug ~level:3 "Cannot find %s in formalNames" origname; [], false end in if foundthem then begin let _argl = argsToList args in if List.length oldnames <> List.length fdec.sformals then - Cil.fatal "After merging the function has different arguments"; + Kernel.fatal ~current:true + "After merging the function has different arguments"; List.iter2 (fun oldn a -> if oldn <> "" then a.vname <- oldn) oldnames fdec.sformals; @@ -2006,7 +2228,7 @@ n :: rest -> oldNames := rest; v.vname <- n - | _ -> Cilmsg.fatal "undoRenameOne" + | _ -> Kernel.fatal "undoRenameOne" in (* Remember the original type *) let origType = fdec'.svar.vtype in @@ -2035,22 +2257,22 @@ (* Make a node for this inline function using the original name. *) let inode = - getNode vEq vSyn !currentFidx origname fdec'.svar + PlainMerging.getNode vEq vSyn !currentFidx origname fdec'.svar (Some (l, !currentDeclIdx)) in if debugInlines then begin - Cilmsg.debug "getNode %s(%d) with loc=%a. declidx=%d" + Kernel.debug "getNode %s(%d) with loc=%a. declidx=%d" inode.nname inode.nfidx d_nloc inode.nloc !currentDeclIdx; - Cilmsg.debug + Kernel.debug "Looking for previous definition of inline %s(%d)" origname !currentFidx; end; try let oldinode = H.find inlineBodies printout in if debugInlines then - Cilmsg.debug " Matches %s(%d)" + Kernel.debug " Matches %s(%d)" oldinode.nname oldinode.nfidx; (* There is some other inline function with the same printout. * We should reuse this, but watch for the case when the inline @@ -2059,7 +2281,7 @@ if mergeInlinesRepeat then begin repeatPass2 := true end else begin - Cil.warning + Kernel.warning ~current:true "Inline function %s because it is used before it is defined" fdec'.svar.vname; raise Not_found @@ -2073,7 +2295,7 @@ fdec'.svar.vname <- origname; () (* Drop this definition *) with Not_found -> begin - if debugInlines then Cilmsg.debug " Not found"; + if debugInlines then Kernel.debug " Not found"; H.add inlineBodies printout inode; mergePushGlobal g' end @@ -2093,16 +2315,18 @@ (H.find emittedFunDefn fdec'.svar.vname) in (* previous was found *) if (curSum = prevSum) then - Cil.warning - "dropping duplicate def'n of func %s at %a in favor of that at %a" + Kernel.warning ~current:true + "dropping duplicate def'n of func %s at %a in favor of \ + that at %a" fdec'.svar.vname d_loc l d_loc prevLoc else begin (* the checksums differ, so print a warning but keep the * older one to avoid a link error later. I think this is * a reasonable approximation of what ld does. *) - Cil.warning - "def'n of func %s at %a (sum %d) conflicts with the one at %a (sum %d); keeping the one at %a." + Kernel.warning ~current:true + "def'n of func %s at %a (sum %d) conflicts with the one \ + at %a (sum %d); keeping the one at %a." fdec'.svar.vname d_loc l curSum d_loc prevLoc prevSum d_loc prevLoc @@ -2125,18 +2349,22 @@ if ci.creferenced then () else begin - match findReplacement true sEq !currentFidx ci.cname with + match + PlainMerging.findReplacement true sEq !currentFidx ci.cname + with None -> (* A new one, we must rename it and keep the definition *) (* Make sure this is root *) (try - let nd = H.find sEq (!currentFidx, ci.cname) in + let nd = + PlainMerging.find_eq_table sEq (!currentFidx, ci.cname) + in if nd.nrep != nd then - Cilmsg.fatal "Setting creferenced for struct %s which is \ + Kernel.fatal "Setting creferenced for struct %s which is \ not root!" ci.cname; with Not_found -> begin - Cilmsg.fatal "Setting creferenced for struct %s which is not \ + Kernel.fatal "Setting creferenced for struct %s which is not \ in the sEq!" ci.cname; end); @@ -2162,7 +2390,9 @@ if ei.ereferenced then () else begin - match findReplacement true eEq !currentFidx ei.ename with + match + PlainMerging.findReplacement true eEq !currentFidx ei.ename + with None -> (* We must rename it *) let newname, _ = A.newAlphaName eAlpha None ei.ename (CurrentLoc.get ()) in @@ -2211,7 +2441,9 @@ if ti.treferenced then () else begin - match findReplacement true tEq !currentFidx ti.tname with + match + PlainMerging.findReplacement true tEq !currentFidx ti.tname + with None -> (* We must rename it and keep it *) let newname, _ = A.newAlphaName vtAlpha None ti.tname (CurrentLoc.get ()) in @@ -2228,14 +2460,6 @@ incr currentDeclIdx; global_annot_pass2 g a | g -> mergePushGlobals (visitCilGlobal renameVisitor g) - with e -> begin - Cilmsg.debug "error when merging global %a: %s" d_global g - (Printexc.to_string e); - mergePushGlobal (GText (Pretty_utils.sfprintf "/* error at %t:" d_thisloc)); - mergePushGlobal g; - mergePushGlobal (GText ("*************** end of error*/")); - raise e - end in (* Now do the real PASS 2 *) List.iter processOneGlobal f.globals; @@ -2260,7 +2484,7 @@ * is being removed was used before we saw the definition and we decided to * remove it *) if mergeInlinesRepeat && !repeatPass2 then begin - Cilmsg.feedback "Repeat final merging phase: %s" f.fileName; + Kernel.feedback "Repeat final merging phase: %s" f.fileName; (* We are going to rescan the globals we have added while processing this * file. *) let theseGlobals : global list ref = ref [] in @@ -2269,7 +2493,7 @@ if tail == l then () else match l with - | [] -> Cilmsg.fatal "mergecil: scanUntil could not find the marker" + | [] -> Kernel.fatal "mergecil: scanUntil could not find the marker" | g :: rest -> theseGlobals := g :: !theseGlobals; scanUntil tail rest @@ -2300,29 +2524,47 @@ List.iter merge_one_spec to_merge let global_merge_spec g = -match g with + Kernel.debug "Merging global %a" d_global g; + match g with | GFun(fdec,_) -> - (try - let specs = - Hashtbl.find spec_to_merge fdec.svar.vid - in - merge_specs fdec.sspec specs - with Not_found -> ()) + (try + Kernel.debug "Merging global definition %a" d_global g; + let specs = + Hashtbl.find spec_to_merge fdec.svar.vid + in + List.iter (fun s -> Kernel.debug "Found spec to merge %a" d_funspec s) + specs; + Kernel.debug "Merging with %a" d_funspec fdec.sspec ; + merge_specs fdec.sspec specs + with Not_found -> + Kernel.debug "No spec_to_merge") | GVarDecl(spec,v,_) -> - let rename spec = - try - let alpha = Hashtbl.find formals_renaming v.vid in - ignore (visitCilFunspec alpha spec) - with Not_found -> () - in - (try - let specs = - Hashtbl.find spec_to_merge v.vid - in - merge_specs spec specs; - rename spec - with Not_found -> rename spec - ) + Kernel.debug "Merging global declaration %a" d_global g; + let rename spec = + try + let alpha = Hashtbl.find formals_renaming v.vid in + ignore (visitCilFunspec alpha spec) + with Not_found -> () + in + (try + let specs = + Hashtbl.find spec_to_merge v.vid + in + List.iter (fun s -> Kernel.debug "Found spec to merge %a" d_funspec s) + specs; + Kernel.debug "Renaming %a" d_funspec spec ; + rename spec; + (* The registered specs might also need renaming up to + definition's formals instead of declaration's ones. *) + List.iter rename specs; + Kernel.debug "Renamed to %a" d_funspec spec; + merge_specs spec specs; + Kernel.debug "Merged into %a" d_funspec spec ; + with Not_found -> + Kernel.debug "No spec_to_merge for declaration" ; + rename spec; + Kernel.debug "Renamed to %a" d_funspec spec ; + ) | _ -> () let merge (files: file list) (newname: string) : file = @@ -2336,21 +2578,23 @@ (* Now maybe try to force synonyms to be equal *) if mergeSynonyms then begin - doMergeSynonyms sSyn sEq matchCompInfo; - doMergeSynonyms eSyn eEq matchEnumInfo; - doMergeSynonyms tSyn tEq matchTypeInfo; - - doMergeSynonyms lfSyn lfEq matchLogicInfo; - doMergeSynonyms ltSyn ltEq matchLogicType; - doMergeSynonyms lcSyn lcEq matchLogicCtor; - doMergeSynonyms laSyn laEq matchLogicAxiomatic; - doMergeSynonyms llSyn llEq matchLogicLemma; + doMergeSynonyms sSyn matchCompInfo; + doMergeSynonyms eSyn matchEnumInfo; + doMergeSynonyms tSyn matchTypeInfo; + + doMergeSynonyms lfSyn matchLogicInfo; + doMergeSynonyms ltSyn matchLogicType; + doMergeSynonyms lcSyn matchLogicCtor; + doMergeSynonyms laSyn matchLogicAxiomatic; + doMergeSynonyms llSyn matchLogicLemma; + VolatileMerging.doMergeSynonyms lvSyn matchVolatileClause; if mergeInlines then begin (* Copy all the nodes from the iEq to vEq as well. This is needed * because vEq will be used for variable renaming *) - H.iter (fun k n -> H.add vEq k n) iEq; - doMergeSynonyms iSyn iEq matchInlines; + PlainMerging.iter_eq_table + (fun k n -> PlainMerging.add_eq_table vEq k n) iEq; + doMergeSynonyms iSyn matchInlines; end end; @@ -2386,7 +2630,7 @@ let res = if Cilmsg.had_errors () then begin - Cilmsg.error "Error during linking@." ; + Kernel.error "Error during linking@." ; { fileName = newname; globals = []; globinit = None; diff -Nru frama-c-20110201+carbon+dfsg/cil/src/rmtmps.ml frama-c-20111001+nitrogen+dfsg/cil/src/rmtmps.ml --- frama-c-20110201+carbon+dfsg/cil/src/rmtmps.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/rmtmps.ml 2011-10-10 08:40:09.000000000 +0000 @@ -68,7 +68,7 @@ | GEnumTag (info, _) | GEnumTagDecl (info, _) -> - (*trace (dprintf "clearing mark: %a\n" d_shortglobal global);*) + Kernel.debug ~level "clearing mark: %a" d_global global; info.ereferenced <- false | GCompTag (info, _) @@ -141,11 +141,11 @@ let considerPragma = let badPragma location pragma = - Cilmsg.warning ~source:(source location) "Invalid argument to pragma %s" pragma + Kernel.warning ~source:location "Invalid argument to pragma %s" pragma in function - | GPragma (Attr ("cilnoremove" as directive, args), location) -> + | GPragma (Attr ("cilnoremove" as directive, args), (location,_)) -> (* a very flexible pragma: can retain typedefs, enums, * structs, unions, or globals (functions or variables) *) begin @@ -186,18 +186,21 @@ | GVarDecl (_,v, _) -> begin (* Look for alias attributes, e.g. Linux modules *) match filterAttributes "alias" v.vattr with - [] -> () (* ordinary prototype. *) - | [Attr("alias", [AStr othername])] -> - H.add keepers.defines othername () - | _ -> - (Cil.fatal "Bad alias attribute at %a" d_loc (CurrentLoc.get ())) - end + | [] -> () (* ordinary prototype. *) + | [ Attr("alias", [AStr othername]) ] -> + H.add keepers.defines othername () + | _ -> + Kernel.fatal ~current:true + "Bad alias attribute at %a" + d_loc (CurrentLoc.get ()) + end (*** Begin CCured-specific checks: ***) (* these pragmas indirectly require that we keep the function named in -- the first arguments of boxmodelof and ccuredwrapperof, and -- the third argument of ccureddeepcopy*. *) - | GPragma (Attr("ccuredwrapper" as directive, attribute :: _), location) -> + | GPragma (Attr("ccuredwrapper" as directive, attribute :: _), + (location,_)) -> begin match attribute with | AStr name -> @@ -219,7 +222,7 @@ | _ -> () end - | GPragma (Attr(directive, _ :: _ :: attribute :: _), location) + | GPragma (Attr(directive, _ :: _ :: attribute :: _), (location,_)) when String.length directive > ccureddeepcopystring_length && (Str.first_chars directive ccureddeepcopystring_length) = ccureddeepcopystring -> @@ -256,7 +259,7 @@ let considerGlobal = function | GFun ({svar = {vname = name} as info}, location) when not (H.mem keptGlobals name) -> - (Cilmsg.debug ~level "slicing: reducing to prototype: function %s\n" name); + (Kernel.debug ~level "slicing: reducing to prototype: function %s\n" name); GVarDecl (empty_funspec(),info, location) | other -> other @@ -354,8 +357,6 @@ end | GVarDecl(_,v,_) when hasAttribute "alias" v.vattr -> true, "has GCC alias attribute" - | GVarDecl(spec,v,_) when not (Cil.is_empty_funspec spec) -> - v.vname="main", "main has formal spec" | GAnnot _ -> true, "global annotation" | _ -> false, "neither function nor variable nor annotation" @@ -463,15 +464,15 @@ begin let name = v.vname in if v.vglob then - Cilmsg.debug ~level "marking transitive use: global %s" name + Kernel.debug ~level "marking transitive use: global %s" name else - Cilmsg.debug ~level "marking transitive use: local %s" name; + Kernel.debug ~level "marking transitive use: local %s" name; (* If this is a global, we need to keep everything used in its * definition and declarations. *) if v.vglob then begin - Cilmsg.debug ~level "descending: global %s" name; + Kernel.debug ~level "descending: global %s" name; let descend global = ignore (visitCilGlobal (self :> cilVisitor) global) in @@ -484,45 +485,56 @@ end; SkipChildren - method vexpr (e: exp) = + method private mark_enum e = + let old = e.ereferenced in + if not old then + begin + Kernel.debug ~level "marking transitive use: enum %s\n" e.ename; + e.ereferenced <- true; + self#visitAttrs e.eattr; + (* Must visit the value attributed to the enum constants *) + ignore (visitCilEnumInfo (self:>cilVisitor) e); + end + else + Kernel.debug ~level "not marking transitive use: enum %s\n" e.ename; + old + + method vexpr e = match e.enode with - Const (CEnum {eihost = ei}) -> ei.ereferenced <- true; DoChildren + Const (CEnum {eihost = ei}) -> ignore (self#mark_enum ei); DoChildren | _ -> DoChildren - + + method vterm_node t = + match t with + TConst (CEnum {eihost = ei}) -> ignore (self#mark_enum ei); DoChildren + | _ -> DoChildren + + method private visitAttrs attrs = + ignore (visitCilAttributes (self :> cilVisitor) attrs) + method vtype typ = let old : bool = - let visitAttrs attrs = - ignore (visitCilAttributes (self :> cilVisitor) attrs) - in let visitType typ = ignore (visitCilType (self :> cilVisitor) typ) in match typ with | TEnum(e, attrs) -> - let old = e.ereferenced in - if not old then - begin - (Cilmsg.debug ~level "marking transitive use: enum %s\n" e.ename); - e.ereferenced <- true; - visitAttrs attrs; - visitAttrs e.eattr; - (* Must visit the value attributed to the enum constants *) - ignore (visitCilEnumInfo (self:>cilVisitor) e); - end; - old - + self#visitAttrs attrs; + self#mark_enum e + | TComp(c, _, attrs) -> let old = c.creferenced in if not old then begin - (Cilmsg.debug ~level "marking transitive use: compound %s\n" c.cname); + Kernel.debug ~level "marking transitive use: compound %s\n" + c.cname; c.creferenced <- true; (* to recurse, we must ask explicitly *) let recurse f = visitType f.ftype in List.iter recurse c.cfields; - visitAttrs attrs; - visitAttrs c.cattr + self#visitAttrs attrs; + self#visitAttrs c.cattr end; old @@ -530,13 +542,14 @@ let old = ti.treferenced in if not old then begin - (Cilmsg.debug ~level "marking transitive use: typedef %s\n" ti.tname); + Kernel.debug ~level "marking transitive use: typedef %s\n" + ti.tname; ti.treferenced <- true; (* recurse deeper into the type referred-to by the typedef *) (* to recurse, we must ask explicitly *) visitType ti.ttype; - visitAttrs attrs + self#visitAttrs attrs end; old @@ -625,7 +638,7 @@ let keep_label dest = let (ln, _), _ = labelsToKeep is_removable !dest.labels in if ln = "" then - Cilmsg.fatal "Statement has no label:@\n%a" Cil.d_stmt !dest ; + Kernel.fatal "Statement has no label:@\n%a" Cil.d_stmt !dest ; (* Mark it as used *) H.replace labelMap ln () in @@ -760,7 +773,7 @@ begin (* along the way, record the interesting locals that were removed *) let name = local.vname in - (Cilmsg.debug ~level "removing local: %s\n" name); + (Kernel.debug ~level "removing local: %s\n" name); if not (Str.string_match uninteresting name 0) then removedLocals := (func.svar.vname ^ "::" ^ name) :: !removedLocals; end; @@ -801,7 +814,7 @@ let rec removeUnusedTemps ?(isRoot : rootsFilter = isDefaultRoot) file = if not !keepUnused then begin - Cilmsg.debug ~level "Removing unused temporaries" ; + Kernel.debug ~level "Removing unused temporaries" ; (* digest any pragmas that would create additional roots *) let keepers = categorizePragmas file in @@ -827,9 +840,9 @@ if false && removedLocals != [] then let count = List.length removedLocals in if count > 2000 then - (Cilmsg.warning "%d unused local variables removed" count) + (Kernel.warning "%d unused local variables removed" count) else - (Cilmsg.warning "%d unused local variables removed:@!%a" + (Kernel.warning "%d unused local variables removed:@!%a" count (Pretty_utils.pp_list ~sep:",@," Format.pp_print_string) removedLocals) end diff -Nru frama-c-20110201+carbon+dfsg/cil/src/zrapp.ml frama-c-20111001+nitrogen+dfsg/cil/src/zrapp.ml --- frama-c-20110201+carbon+dfsg/cil/src/zrapp.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/zrapp.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,699 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - -open Escape -open Cil_types -open Cil - -module H = Hashtbl -module IH = Inthash -module M = Machdep -module U = Cilutil -module RD = Reachingdefs -module UD = Usedef -module A = Cabs -module CH = Cabshelper -module GA = GrowArray -module RCT = Rmciltmps -module DCE = Deadcodeelim -module EC = Expcompare - -let doElimTemps = ref false -let debug = ref false -let printComments = ref false -let envWarnings = ref false - -(* Stuff for Deputy support *) -let deputyAttrs = ref false - -let thisKeyword = "__this" - -type paramkind = -| PKNone -| PKThis -| PKOffset of attrparam - -let rec checkParam (ap: attrparam) : paramkind = - match ap with - | ACons (name, []) when name = thisKeyword -> PKThis - | ABinOp (PlusA, a1, a2) when checkParam a1 = PKThis -> - if a2 = AInt 0 then PKThis else PKOffset a2 - | _ -> PKNone - -(* End stuff for Deputy support *) - -(* Some(-1) => l1 < l2 - Some(0) => l1 = l2 - Some(1) => l1 > l2 - None => different files *) -let loc_comp l1 l2 = - if String.compare (fst l1).Lexing.pos_fname (fst l2).Lexing.pos_fname != 0 - then None - else if (fst l1).Lexing.pos_lnum > (fst l2).Lexing.pos_lnum - then Some(1) - else if (fst l2).Lexing.pos_lnum > (fst l1).Lexing.pos_lnum - then Some(-1) - else if (fst l1).Lexing.pos_cnum > (fst l2).Lexing.pos_cnum - then Some(1) - else if (fst l2).Lexing.pos_cnum > (fst l1).Lexing.pos_cnum - then Some(-1) - else Some(0) - -let simpleGaSearch l = - let hi = GA.max_init_index CH.commentsGA in - let rec loop i = - if i < 0 then -1 else - let (l',_,_) = GA.get CH.commentsGA i in - match loc_comp l l' with - None -> loop (i-1) - | Some(0) -> i - | Some(-1) -> loop (i-1) - | Some(1) -> i - | _ -> Cilmsg.fatal "simpleGaSearch: unexpected return from loc_comp" - in - loop hi - -(* location -> string list *) -let get_comments l = - let cabsl = l in - let s = simpleGaSearch cabsl in - - let rec loop i cl = - if i < 0 then cl else - let (l',c,b) = GA.get CH.commentsGA i in - if String.compare (fst cabsl).Lexing.pos_fname (fst l').Lexing.pos_fname != 0 - then loop (i - 1) cl - else if b then cl - else let _ = GA.set CH.commentsGA i (l',c,true) in - loop (i - 1) (c::cl) - in - (*List.rev*) (loop s []) - -(* clean up some of the mess made below *) -let rec simpl_cond e = - match e.enode with - | UnOp(LNot,{enode = BinOp(LAnd,e1,e2,t1)},t2) -> - let e1 = simpl_cond (dummy_exp (UnOp(LNot,e1,t1))) in - let e2 = simpl_cond (dummy_exp (UnOp(LNot,e2,t1))) in - new_exp ~loc:e.eloc (BinOp(LOr,e1,e2,t2)) - | UnOp(LNot,{enode = BinOp(LOr,e1,e2,t1)},t2) -> - let e1 = simpl_cond (dummy_exp (UnOp(LNot,e1,t1))) in - let e2 = simpl_cond (dummy_exp (UnOp(LNot,e2,t1))) in - new_exp ~loc:e.eloc (BinOp(LAnd,e1,e2,t2)) - | UnOp(LNot,{enode = UnOp(LNot,e,_)},_) -> simpl_cond e - | _ -> e - -(* the argument b is the body of a Loop *) -(* returns the loop termination condition *) -(* block -> exp option *) -let get_loop_condition b = - - (* returns the first non-empty - * statement of a statement list *) - (* stm list -> stm list *) - let rec skipEmpty = function - | [] -> [] - | { skind = Instr (Skip _); labels = []}::rest -> - skipEmpty rest - | x -> x - in - (* stm -> exp option * instr list *) - let rec get_cond_from_if if_stm = - match if_stm.skind with - If(e,tb,fb,_) -> - let e = EC.stripNopCasts e in - RCT.fold_blocks tb; - RCT.fold_blocks fb; - let tsl = skipEmpty tb.bstmts in - let fsl = skipEmpty fb.bstmts in - (match tsl, fsl with - {skind = Break _} :: _, [] -> Some e - | [], {skind = Break _} :: _ -> - Some(new_exp ~loc:e.eloc (UnOp(LNot, e, intType))) - | ({skind = If(_,_,_,_)} as s) :: _, [] -> - let teo = get_cond_from_if s in - (match teo with - None -> None - | Some te -> - Some(new_exp ~loc:e.eloc - (BinOp(LAnd,e,EC.stripNopCasts te,intType)))) - | [], ({skind = If(_,_,_,_)} as s) :: _ -> - let feo = get_cond_from_if s in - (match feo with - None -> None - | Some fe -> - Some(new_exp ~loc:e.eloc (BinOp(LAnd, - new_exp ~loc:e.eloc (UnOp(LNot,e,intType)), - EC.stripNopCasts fe,intType)))) - | {skind = Break _} :: _, ({skind = If(_,_,_,_)} as s):: _ -> - let feo = get_cond_from_if s in - (match feo with - None -> None - | Some fe -> - Some(new_exp - ~loc:e.eloc - (BinOp(LOr,e,EC.stripNopCasts fe,intType)))) - | ({skind = If(_,_,_,_)} as s) :: _, {skind = Break _} :: _ -> - let teo = get_cond_from_if s in - (match teo with - None -> None - | Some te -> - Some(new_exp ~loc:e.eloc - (BinOp(LOr, new_exp ~loc:e.eloc (UnOp(LNot,e,intType)), - EC.stripNopCasts te,intType)))) - | ({skind = If(_,_,_,_)} as ts) :: _ , - ({skind = If(_,_,_,_)} as fs) :: _ -> - let teo = get_cond_from_if ts in - let feo = get_cond_from_if fs in - (match teo, feo with - Some te, Some fe -> - Some(new_exp ~loc:e.eloc - (BinOp(LOr, - new_exp ~loc:e.eloc - (BinOp(LAnd,e,EC.stripNopCasts te,intType)), - new_exp ~loc:e.eloc - (BinOp(LAnd,new_exp ~loc:e.eloc - (UnOp(LNot,e,intType)), - EC.stripNopCasts fe,intType)), - intType))) - | _,_ -> None) - | _, _ -> (if !debug then Cilmsg.debug "cond_finder: branches of %a not good\n" - d_stmt if_stm; - None)) - | _ -> (if !debug then Cilmsg.debug "cond_finder: %a not an if\n" d_stmt if_stm; - None) - in - let sl = skipEmpty b.bstmts in - match sl with - ({skind = If(_,_,_,_); labels=[]} as s) :: rest -> - get_cond_from_if s, rest - | s :: _ -> - (if !debug then Cilmsg.debug "checkMover: %a is first, not an if\n" - d_stmt s; - None, sl) - | [] -> - (if !debug then Cilmsg.debug "checkMover: no statements in loop block?@\n"; - None, sl) - -(* -class zraCilPrinterClass : cilPrinter = object (self) - inherit defaultCilPrinterClass as super - - val genvHtbl : (string, varinfo) H.t = H.create 128 - val lenvHtbl : (string, varinfo) H.t = H.create 128 - - (*** VARIABLES ***) - - (* give the varinfo for the variable to be printed, - * returns the varinfo for the varinfo with that name - * in the current environment. - * Returns argument and prints a warning if the variable - * isn't in the environment *) - method private getEnvVi (v:varinfo) : varinfo = - try - if H.mem lenvHtbl v.vname - then H.find lenvHtbl v.vname - else H.find genvHtbl v.vname - with Not_found -> - if !envWarnings then ignore (warn "variable %s not in pp environment" v.vname); - v - - (* True when v agrees with the entry in the environment for the name of v. - False otherwise *) - method private checkVi (v:varinfo) : bool = - let v' = self#getEnvVi v in - v.vid = v'.vid - - method private checkViAndWarn (v:varinfo) = - if not (self#checkVi v) then - ignore (warn "mentioned variable %s and its entry in the current environment have different varinfo." - v.vname) - - - (** Get the comment out of a location if there is one *) - method pLineDirective ?(forcefile=false) l = - let ld = super#pLineDirective l in - if !printComments then - let c = String.concat "\n" (get_comments l) in - match c with - "" -> ld - | _ -> ld ++ line ++ text "/*" ++ text c ++ text "*/" ++ line - else ld - - (* variable use *) - method pVar (v:varinfo) = - (* warn about instances where a possibly unintentionally - conflicting name is used *) - if IH.mem RCT.iioh v.vid then - let rhso = IH.find RCT.iioh v.vid in - match rhso with - Some(Call(_,e,el,l)) -> - (* print a call instead of a temp variable *) - let oldpit = super#getPrintCil_datatype.InstrTerminator() in - let _ = super#setPrintCil_datatype.InstrTerminator "" in - let opc = !printComments in - let _ = printComments := false in - let c = match unrollType (typeOf e) with - TFun(rt,_,_,_) when not (Cilutil.equals (typeSig rt) (typeSig v.vtype)) -> - text "(" ++ self#pType None () v.vtype ++ text ")" - | _ -> nil in - let d = self#pCil_datatype.Instr () (Call(None,e,el,l)) in - let _ = super#setPrintCil_datatype.InstrTerminator oldpit in - let _ = printComments := opc in - c ++ d - | _ -> - if IH.mem RCT.incdecHash v.vid then - (* print an post-inc/dec instead of a temp variable *) - let redefid, rhsvi, b = IH.find RCT.incdecHash v.vid in - match b with - PlusA | PlusPI | IndexPI -> - text rhsvi.vname ++ text "++" - | MinusA | MinusPI -> - text rhsvi.vname ++ text "--" - | _ -> E.s (E.error "zraCilPrinterClass.pVar: unexpected op for inc/dec\n") - else (self#checkViAndWarn v; - text v.vname) - else if IH.mem RCT.incdecHash v.vid then - (* print an post-inc/dec instead of a temp variable *) - let redefid, rhsvi, b = IH.find RCT.incdecHash v.vid in - match b with - PlusA | PlusPI | IndexPI -> - text rhsvi.vname ++ text "++" - | MinusA | MinusPI -> - text rhsvi.vname ++ text "--" - | _ -> E.s (E.error "zraCilPrinterClass.pVar: unexpected op for inc/dec\n") - else (self#checkViAndWarn v; - text v.vname) - - (* variable declaration *) - method pVDecl () (v:varinfo) = - (* See if the name is already in the environment with a - different varinfo. If so, give a warning. - If not, add the name to the environment *) - let _ = if (H.mem lenvHtbl v.vname) && not(self#checkVi v) then - ignore( warn "name %s has already been declared locally with different varinfo\n" v.vname) - else if (H.mem genvHtbl v.vname) && not(self#checkVi v) then - ignore( warn "name %s has already been declared globally with different varinfo\n" v.vname) - else if not v.vglob then - (if !debug then ignore(E.log "zrapp: adding %s to local pp environment\n" v.vname); - H.add lenvHtbl v.vname v) - else - (if !debug then ignore(E.log "zrapp: adding %s to global pp envirnoment\n" v.vname); - H.add genvHtbl v.vname v) in - let stom, rest = separateStorageModifiers v.vattr in - (* First the storage modifiers *) - self#pLineDirective v.vdecl ++ - text (if v.vinline then "__inline " else "") - ++ d_storage () v.vstorage - ++ (self#pAttrs () stom) - ++ (self#pType (Some (text v.vname)) () v.vtype) - ++ text " " - ++ self#pAttrs () rest - - (* For printing deputy annotations *) - method pAttr (Attr (an, args) : attribute) : doc * bool = - if not (!deputyAttrs) then super#pAttr (Attr(an,args)) else - match an, args with - | "fancybounds", [AInt i1; AInt i2] -> nil, false - (*if !showBounds then - dprintf "BND(%a, %a)" self#pExp (getBoundsExp i1) - self#pExp (getBoundsExp i2), false - else - text "BND(...)", false*) - | "bounds", [a1; a2] -> - begin - match checkParam a1, checkParam a2 with - | PKThis, PKThis -> - text "COUNT(0)", false - | PKThis, PKOffset (AInt 1) -> - text "SAFE", false - | PKThis, PKOffset a -> nil, false - (*if !showBounds then - dprintf "COUNT(%a)" self#pAttrParam a, false - else - text "COUNT(...)", false*) - | _ -> nil, false - (* if !showBounds then - dprintf "BND(%a, %a)" self#pAttrParam a1 - self#pAttrParam a2, false - else - text "BND(...)", false*) - end - | "fancysize", [AInt i] -> nil, false - (*dprintf "SIZE(%a)" self#pExp (getBoundsExp i), false*) - | "size", [a] -> - dprintf "SIZE(%a)" self#pAttrParam a, false - | "fancywhen", [AInt i] -> nil, false - (*dprintf "WHEN(%a)" self#pExp (getBoundsExp i), false*) - | "when", [a] -> - dprintf "WHEN(%a)" self#pAttrParam a, false - | "nullterm", [] -> - text "NT", false - | "assumeconst", [] -> - text "ASSUMECONST", false - | "trusted", [] -> - text "TRUSTED", false - | "poly", [a] -> - dprintf "POLY(%a)" self#pAttrParam a, false - | "poly", [] -> - text "POLY", false - | "sentinel", [] -> - text "SNT", false - | "nonnull", [] -> - text "NONNULL", false - | "_ptrnode", [AInt n] -> nil, false - (*if !Doptions.emitGraphDetailLevel >= 3 then - dprintf "NODE(%d)" n, false - else - nil, false*) - | "missing_annot", _-> (* Don't bother printing thess *) - nil, false - | _ -> - super#pAttr (Attr (an, args)) - - - (*** GLOBALS ***) - method pGlobal () (g:global) : doc = (* global (vars, types, etc.) *) - match g with - | GFun (fundec, l) -> - (* If the function has attributes then print a prototype because - * GCC cannot accept function attributes in a definition *) - let oldattr = fundec.svar.vattr in - (* Always pring the file name before function declarations *) - let proto = - if oldattr <> [] then - (self#pLineDirective l) ++ (self#pVDecl () fundec.svar) - ++ chr ';' ++ line - else nil in - (* Temporarily remove the function attributes *) - fundec.svar.vattr <- []; - let body = (self#pLineDirective ~forcefile:true l) - ++ (self#pFunDecl () fundec) in - fundec.svar.vattr <- oldattr; - proto ++ body ++ line - - | GType (typ, l) -> - self#pLineDirective ~forcefile:true l ++ - text "typedef " - ++ (self#pType (Some (text typ.tname)) () typ.ttype) - ++ text ";\n" - - | GEnumTag (enum, l) -> - self#pLineDirective l ++ - text "enum" ++ align ++ text (" " ^ enum.ename) ++ - self#pAttrs () enum.eattr ++ text " {" ++ line - ++ (docList ~sep:(chr ',' ++ line) - (fun (n,i, loc) -> - text (n ^ " = ") - ++ self#pExp () i) - () enum.eitems) - ++ unalign ++ line ++ text "};\n" - - | GEnumTagDecl (enum, l) -> (* This is a declaration of a tag *) - self#pLineDirective l ++ - text ("enum " ^ enum.ename ^ ";\n") - - | GCompTag (comp, l) -> (* This is a definition of a tag *) - let n = comp.cname in - let su, su1, su2 = - if comp.cstruct then "struct", "str", "uct" - else "union", "uni", "on" - in - let sto_mod, rest_attr = separateStorageModifiers comp.cattr in - self#pLineDirective ~forcefile:true l ++ - text su1 ++ (align ++ text su2 ++ chr ' ' ++ (self#pAttrs () sto_mod) - ++ text n - ++ text " {" ++ line - ++ ((docList ~sep:line (self#pFieldDecl ())) () - comp.cfields) - ++ unalign) - ++ line ++ text "}" ++ - (self#pAttrs () rest_attr) ++ text ";\n" - - | GCompTagDecl (comp, l) -> (* This is a declaration of a tag *) - self#pLineDirective l ++ - text (compFullName comp) ++ text ";\n" - - | GVar (vi, io, l) -> - self#pLineDirective ~forcefile:true l ++ - self#pVDecl () vi - ++ chr ' ' - ++ (match io.init with - None -> nil - | Some i -> text " = " ++ - (let islong = - match i with - CompoundInit (_, il) when List.length il >= 8 -> true - | _ -> false - in - if islong then - line ++ self#pLineDirective l ++ text " " - else nil) ++ - (self#pInit () i)) - ++ text ";\n" - - (* print global variable 'extern' declarations, and function prototypes *) - | GVarDecl (spec,vi, l) -> - let builtins = if !msvcMode then msvcBuiltins else gccBuiltins in - let result = - if not !printCilAsIs && H.mem builtins vi.vname then begin - (* Compiler builtins need no prototypes. Just print them in - comments. *) - text "/* compiler builtin: \n " ++ - (self#pVDecl () vi) - ++ text "; */\n" - - end else - self#pLineDirective l ++ - (self#pVDecl () vi) - ++ text ";\n" - in - (let spec = Cilutil.pretty_to_string Logic_printer.pretty_funspec spec in - if spec = "" then nil - else text "/*@ " ++ text spec ++ text " */\n") ++ result - - | GAsm (s, l) -> - self#pLineDirective l ++ - text ("__asm__(\"" ^ escape_string s ^ "\");\n") - - | GPragma (Attr(an, args), l) -> - (* sm: suppress printing pragmas that gcc does not understand *) - (* assume anything starting with "ccured" is ours *) - (* also don't print the 'combiner' pragma *) - (* nor 'cilnoremove' *) - let suppress = - not !print_CIL_Input && - not !msvcMode && - ((startsWith "box" an) || - (startsWith "ccured" an) || - (an = "merger") || - (an = "cilnoremove")) in - let d = - match an, args with - | _, [] -> - text an - | "weak", [ACons (symbol, [])] -> - text "weak " ++ text symbol - | _ -> - text (an ^ "(") - ++ docList ~sep:(chr ',') (self#pAttrParam ()) () args - ++ text ")" - in - self#pLineDirective l - ++ (if suppress then text "/* " else text "") - ++ (text "#pragma ") - ++ d - ++ (if suppress then text " */\n" else text "\n") - | GAnnot _ -> text ("/* suppressed annotation */\n") - | GText s -> - if s <> "//" then - text s ++ text "\n" - else - nil - - - method dGlobal (out: out_channel) (g: global) : unit = - (* For all except functions and variable with initializers, use the - * pGlobal *) - match g with - GFun (fdec, l) -> - (* If the function has attributes then print a prototype because - * GCC cannot accept function attributes in a definition *) - let oldattr = fdec.svar.vattr in - let proto = - if oldattr <> [] then - (self#pLineDirective l) ++ (self#pVDecl () fdec.svar) - ++ chr ';' ++ line - else nil in - fprint out 80 (proto ++ (self#pLineDirective ~forcefile:true l)); - (* Temporarily remove the function attributes *) - fdec.svar.vattr <- []; - fprint out 80 (self#pFunDecl () fdec); - fdec.svar.vattr <- oldattr; - output_string out "\n" - - | GVar (vi, {init = Some i}, l) -> begin - fprint out 80 - (self#pLineDirective ~forcefile:true l ++ - self#pVDecl () vi - ++ text " = " - ++ (let islong = - match i with - CompoundInit (_, il) when List.length il >= 8 -> true - | _ -> false - in - if islong then - line ++ self#pLineDirective l ++ text " " - else nil)); - self#dInit out 3 i; - output_string out ";\n" - end - - | g -> fprint out 80 (self#pGlobal () g) - - method pFieldDecl () fi = - self#pLineDirective fi.floc ++ - (self#pType - (Some (text (if fi.fname = missingFieldName then "" else fi.fname))) - () - fi.ftype) - ++ text " " - ++ (match fi.fbitfield with None -> nil - | Some i -> text ": " ++ num i ++ text " ") - ++ self#pAttrs () fi.fattr - ++ text ";" - - method private pFunDecl () f = - H.add genvHtbl f.svar.vname f.svar;(* add function to global env *) - H.clear lenvHtbl; (* new local environment *) - (* add the arguments to the local environment *) - List.iter (fun vi -> H.add lenvHtbl vi.vname vi) f.sformals; - let nf = - if !doElimTemps - then RCT.eliminate_temps f - else f in - let decls = docList ~sep:line (fun vi -> self#pVDecl () vi ++ text ";") - () nf.slocals in - self#pVDecl () nf.svar - ++ line - ++ text "{ " - ++ (align - (* locals. *) - ++ decls - ++ line ++ line - (* the body *) - ++ ((* remember the declaration *) super#setCurrentFormals nf.sformals; - let body = self#pBlock () nf.sbody in - super#setCurrentFormals []; - body)) - ++ line - ++ text "}" - - method private pStmtKind (next : stmt) () (sk : stmtkind) = - match sk with - | Loop(_,b,l,_,_) -> begin - (* See if we can turn this into a while(e) {} *) - (* TODO: See if we can turn this into a do { } while(e); *) - let co, bodystmts = get_loop_condition b in - match co with - | None -> super#pStmtKind next () sk - | Some c -> begin - self#pLineDirective l - ++ text "wh" - ++ (align - ++ text "ile (" - ++ self#pExp () (simpl_cond (UnOp(LNot,c,intType))) - ++ text ") " - ++ self#pBlock () {bstmts=bodystmts; battrs=b.battrs}) - end - end - | _ -> super#pStmtKind next () sk - -end (* class zraCilPrinterClass *) - -let zraCilPrinter = new zraCilPrinterClass - -(* pretty print an expression *) -let pp_exp (fd : fundec) () (e : exp) = - deputyAttrs := true; - ignore(RCT.eliminateTempsForExpPrinting fd); - let d = zraCilPrinter#pExp () e in - deputyAttrs := false; - d - -type outfile = - { fname : string; - fchan : out_channel } -let outChannel : outfile option ref = ref None - -(* Processign of output file arguments *) -let openFile (what: string) (takeit: outfile -> unit) (fl: string) = - if !E.verboseFlag then - ignore (Printf.printf "Setting %s to %s\n" what fl); - (try takeit {fname = fl; fchan = open_out fl} - with _ -> - raise (Arg.Bad ("Cannot open " ^ what ^ " file " ^ fl))) - -let feature : featureDescr = - { fd_name = "zrapp"; - fd_enabled = ref false; - fd_description = "pretty printing with checks for name conflicts and temp variable elimination"; - fd_extraopt = [ - "--zrapp_elim_temps", - Arg.Unit (fun n -> doElimTemps := true), - "Try to eliminate temporary variables during pretty printing"; - "--zrapp_debug", - Arg.Unit (fun n -> debug := true; RD.debug := true), - "Lots of debugging info for pretty printing and reaching definitions"; - "--zrapp_debug_fn", - Arg.String (fun s -> RD.debug_fn := s), - "Only output debugging info for one function"; - "--zrapp_comments", - Arg.Unit (fun _ -> printComments := true), - "Print comments from source file in output";]; - fd_doit = - (function (f: file) -> - lineDirectiveStyle := None; - printerForMaincil := zraCilPrinter); - fd_post_check = false - } - -*) diff -Nru frama-c-20110201+carbon+dfsg/cil/src/zrapp.mli frama-c-20111001+nitrogen+dfsg/cil/src/zrapp.mli --- frama-c-20110201+carbon+dfsg/cil/src/zrapp.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/cil/src/zrapp.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula *) -(* Scott McPeak *) -(* Wes Weimer *) -(* Ben Liblit *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(**************************************************************************) - -val debug : bool ref -(* -class zraCilPrinterClass : Cil.cilPrinter - -val zraCilPrinter : Cil.cilPrinter -*) -val get_comments : Cil_types.location -> string list -(* -val feature : Cil.featureDescr -*) diff -Nru frama-c-20110201+carbon+dfsg/configure frama-c-20111001+nitrogen+dfsg/configure --- frama-c-20110201+carbon+dfsg/configure 2011-02-07 15:05:33.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/configure 2011-10-10 08:56:40.000000000 +0000 @@ -1,11 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.65. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # # # This configure script is free software; the Free Software Foundation @@ -316,7 +316,7 @@ test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -356,19 +356,19 @@ fi # as_fn_arith -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -530,7 +530,7 @@ exec 6>&1 # Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -614,8 +614,6 @@ OCAMLGRAPH_LOCAL OCAMLGRAPH_INCLUDE VERBOSEMAKE -HAS_CUSTOMTREE -CUSTOMTREE HAS_USABLE_NATIVE_DYNLINK USABLE_NATIVE_DYNLINK HAS_NATIVE_DYNLINK @@ -628,8 +626,21 @@ GTKSOURCEVIEW HAS_LABLGTK LABLGTK +ALTERGO_VERSION +COQ +HAS_COQ +ALTERGO +HAS_ALTERGO +WHYDP +HAS_WHYDP +WHY +HAS_WHY +DYNAMIC_WP +ENABLE_WP DYNAMIC_SECURITY_SLICING ENABLE_SECURITY_SLICING +DYNAMIC_REPORT +ENABLE_REPORT LTLTOBA HAS_LTLTOBA DYNAMIC_AORAI @@ -648,8 +659,6 @@ ENABLE_SEMANTIC_CALLGRAPH DYNAMIC_SCOPE ENABLE_SCOPE -DYNAMIC_REPORT -ENABLE_REPORT DYNAMIC_RTE_ANNOTATION ENABLE_RTE_ANNOTATION DYNAMIC_POSTDOMINATORS @@ -749,7 +758,6 @@ enable_pdg enable_postdominators enable_rte_annotation -enable_report enable_scope enable_semantic_callgraph enable_slicing @@ -760,8 +768,12 @@ enable_external enable_aorai with_aorai_static +enable_report +with_report_static enable_security_slicing with_security_slicing_static +enable_wp +with_wp_static ' ac_precious_vars='build_alias host_alias @@ -834,9 +846,8 @@ fi case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -881,7 +892,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -907,7 +918,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1111,7 +1122,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1127,7 +1138,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1157,8 +1168,8 @@ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." ;; *=*) @@ -1166,7 +1177,7 @@ # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1184,13 +1195,13 @@ if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" + as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1213,7 +1224,7 @@ [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1227,8 +1238,8 @@ if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1243,9 +1254,9 @@ ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" + as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" + as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1284,11 +1295,11 @@ fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1328,7 +1339,7 @@ --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages + -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1395,7 +1406,6 @@ --enable-pdg support for pdg plugin (default: yes) --enable-postdominators support for postdominators plugin (default: yes) --enable-rte_annotation support for runtime error annotation (default: yes) - --enable-report ACSL properties status report (default: yes) --enable-scope support for scope plugin (default: yes) --enable-semantic_callgraph support for semantic callgraph (default: yes) @@ -1408,8 +1418,10 @@ --enable-external=plugin allows to compile directly from Frama-C kernel some external plug-ins. --enable-aorai support for Aorai plug-in (default: yes) + --enable-report support for report plug-in (default: yes) --enable-security_slicing support for Security_slicing plug-in (default: yes) + --enable-wp support for wp plug-in (default: yes) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1417,8 +1429,10 @@ --with-all-static link all plug-ins statically (default: no) --with-no-plugin disable all plug-ins (default: no) --with-aorai-static link aorai statically (default: no) + --with-report-static link report statically (default: no) --with-security_slicing-static link security_slicing statically (default: no) + --with-wp-static link wp statically (default: no) Some influential environment variables: CC C compiler command @@ -1497,9 +1511,9 @@ if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.65 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1569,7 +1583,7 @@ mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { + test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : @@ -1593,10 +1607,10 @@ ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval "test \"\${$3+set}\"" = set; then : + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -1632,7 +1646,7 @@ else ac_header_preproc=no fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } @@ -1659,7 +1673,7 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -1723,7 +1737,7 @@ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1754,7 +1768,7 @@ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=no" @@ -1849,7 +1863,7 @@ running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -1959,9 +1973,11 @@ { echo - $as_echo "## ---------------- ## + cat <<\_ASBOX +## ---------------- ## ## Cache variables. ## -## ---------------- ##" +## ---------------- ## +_ASBOX echo # The following way of writing the cache mishandles newlines in values, ( @@ -1995,9 +2011,11 @@ ) echo - $as_echo "## ----------------- ## + cat <<\_ASBOX +## ----------------- ## ## Output variables. ## -## ----------------- ##" +## ----------------- ## +_ASBOX echo for ac_var in $ac_subst_vars do @@ -2010,9 +2028,11 @@ echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + cat <<\_ASBOX +## ------------------- ## ## File substitutions. ## -## ------------------- ##" +## ------------------- ## +_ASBOX echo for ac_var in $ac_subst_files do @@ -2026,9 +2046,11 @@ fi if test -s confdefs.h; then - $as_echo "## ----------- ## + cat <<\_ASBOX +## ----------- ## ## confdefs.h. ## -## ----------- ##" +## ----------- ## +_ASBOX echo cat confdefs.h echo @@ -2083,12 +2105,7 @@ ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -2103,11 +2120,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } + . "$ac_site_file" fi done @@ -2183,7 +2196,7 @@ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -2334,7 +2347,7 @@ if test "$short_mark" = "no"; then fp=FORCE_"$up" if eval test "\$$fp" = "yes"; then - as_fn_error $? "$lp requested but $reason." "$LINENO" 5 + as_fn_error "$lp requested but $reason." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp disabled because $reason." >&5 $as_echo "$as_me: WARNING: $lp disabled because $reason." >&2;} @@ -2563,8 +2576,8 @@ if test "$MAKE_DISTRIB" != GNU -o "$MAKE_MAJOR" -lt 3 -o "$MAKE_MINOR" -lt 81; then echo "${ECHO_T}" - as_fn_error $? "unsupported version; GNU Make version 3.81 - or higher is required." "$LINENO" 5 ; + as_fn_error "unsupported version; GNU Make version 3.81 + or higher is required." "$LINENO" 5; else echo "${ECHO_T}Good!" fi @@ -2640,7 +2653,7 @@ if test "$OCAMLC" = no ; then - as_fn_error $? "Cannot find ocamlc." "$LINENO" 5 + as_fn_error "Cannot find ocamlc." "$LINENO" 5 fi OCAML_ANNOT_OPTION="-dtypes" @@ -2894,7 +2907,7 @@ if test "$OCAMLDEP" = no ; then - as_fn_error $? "Cannot find ocamldep." "$LINENO" 5 + as_fn_error "Cannot find ocamldep." "$LINENO" 5 else # Extract the first word of "ocamldep.opt", so it can be a program name with args. set dummy ocamldep.opt; ac_word=$2 @@ -2979,7 +2992,7 @@ if test "$OCAMLLEX" = no ; then - as_fn_error $? "Cannot find ocamllex." "$LINENO" 5 + as_fn_error "Cannot find ocamllex." "$LINENO" 5 else # Extract the first word of "ocamllex.opt", so it can be a program name with args. set dummy ocamllex.opt; ac_word=$2 @@ -3064,7 +3077,7 @@ if test "$OCAMLYACC" = no ; then - as_fn_error $? "Cannot find ocamlyacc." "$LINENO" 5 + as_fn_error "Cannot find ocamlyacc." "$LINENO" 5 fi ############## @@ -3080,11 +3093,11 @@ as_ac_File=`$as_echo "ac_cv_file_$OCAMLGRAPH_HOME/graph.$OBJ_SUFFIX" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $OCAMLGRAPH_HOME/graph.$OBJ_SUFFIX" >&5 $as_echo_n "checking for $OCAMLGRAPH_HOME/graph.$OBJ_SUFFIX... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$OCAMLGRAPH_HOME/graph.$OBJ_SUFFIX"; then eval "$as_ac_File=yes" else @@ -3094,7 +3107,8 @@ eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : OCAMLGRAPH_EXISTS="yes" OCAMLGRAPH_INCLUDE="-I +ocamlgraph" fi @@ -3108,7 +3122,7 @@ then OCAMLGRAPH_VERSION=`./test_ocamlgraph` case $OCAMLGRAPH_VERSION in - 1.7) { $as_echo "$as_me:${as_lineno-$LINENO}: OcamlGraph $OCAMLGRAPH_VERSION found: great!" >&5 + 1.8) { $as_echo "$as_me:${as_lineno-$LINENO}: OcamlGraph $OCAMLGRAPH_VERSION found: great!" >&5 $as_echo "$as_me: OcamlGraph $OCAMLGRAPH_VERSION found: great!" >&6;};; *) { $as_echo "$as_me:${as_lineno-$LINENO}: OcamlGraph $OCAMLGRAPH_VERSION is incompatible with Frama-C." >&5 $as_echo "$as_me: OcamlGraph $OCAMLGRAPH_VERSION is incompatible with Frama-C." >&6;} @@ -3134,11 +3148,11 @@ as_ac_File=`$as_echo "ac_cv_file_$OCAMLGRAPH_LOCAL" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $OCAMLGRAPH_LOCAL" >&5 $as_echo_n "checking for $OCAMLGRAPH_LOCAL... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$OCAMLGRAPH_LOCAL"; then eval "$as_ac_File=yes" else @@ -3148,7 +3162,8 @@ eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : OCAMLGRAPH_EXISTS=yes fi @@ -3159,7 +3174,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "ocamlgraph.tar.gz"; then ac_cv_file_ocamlgraph_tar_gz=yes else @@ -3180,7 +3195,7 @@ else # neither directory ocamlgraph, nor ocamlgraph.tar.gz exists # broken distrib indeed - as_fn_error $? "cannot find OcamlGraph in the current directory. + as_fn_error "cannot find OcamlGraph in the current directory. Quite strange: would your Frama-C distribution be corrupted? Anyway: 1. download the latest version from http://ocamlgraph.lri.fr/download @@ -3194,7 +3209,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "ocamlgraph.tar.gz"; then ac_cv_file_ocamlgraph_tar_gz=yes else @@ -3226,10 +3241,10 @@ fi ################################################# -# Check for other non-mandatory tools/libraries # +# Check for other (optional) tools/libraries # ################################################# -new_section "configure non-mandatory tools and libraries" +new_section "configure optional tools and libraries" # Extract the first word of "ocamldoc", so it can be a program name with args. set dummy ocamldoc; ac_word=$2 @@ -3694,8 +3709,8 @@ test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3809,8 +3824,9 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } +{ as_fn_set_status 77 +as_fn_error "C compiler cannot create executables +See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3852,8 +3868,8 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } +as_fn_error "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3910,9 +3926,9 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. +as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details." "$LINENO" 5; } fi fi fi @@ -3963,8 +3979,8 @@ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +as_fn_error "cannot compute suffix of object files: cannot compile +See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -4227,7 +4243,7 @@ # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4243,11 +4259,11 @@ ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -4286,7 +4302,7 @@ # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4302,18 +4318,18 @@ ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5 ; } +as_fn_error "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c @@ -4374,7 +4390,7 @@ done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP @@ -4440,7 +4456,7 @@ done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -4572,7 +4588,8 @@ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -4635,7 +4652,7 @@ $as_echo_n "checking definition of size_t... " >&6; } TYPE_SIZE_T=`checkIntegerType "size_t"` if test "x$TYPE_SIZE_T" = "x" ;then - as_fn_error $? "Cannot find definition of size_t" "$LINENO" 5 + as_fn_error "Cannot find definition of size_t" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define TYPE_SIZE_T "$TYPE_SIZE_T" @@ -4648,7 +4665,7 @@ $as_echo_n "checking definition of wchar_t... " >&6; } TYPE_WCHAR_T=`checkIntegerType "wchar_t"` if test "x$TYPE_WCHAR_T" = "x" ;then - as_fn_error $? "Cannot find definition of wchar_t" "$LINENO" 5 + as_fn_error "Cannot find definition of wchar_t" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define TYPE_WCHAR_T "$TYPE_WCHAR_T" @@ -4661,7 +4678,7 @@ $as_echo_n "checking definition of ptrdiff_t... " >&6; } TYPE_PTRDIFF_T=`checkIntegerType "ptrdiff_t"` if test "x$TYPE_PTRDIFF_T" = "x" ;then - as_fn_error $? "Cannot find definition of ptrdiff_t" "$LINENO" 5 + as_fn_error "Cannot find definition of ptrdiff_t" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define TYPE_PTRDIFF_T "$TYPE_PTRDIFF_T" @@ -4850,7 +4867,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/constant_propagation"; then ac_cv_file_src_constant_propagation=yes else @@ -4899,7 +4916,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "semantic_constant_folding is not available" "$LINENO" 5 + as_fn_error "semantic_constant_folding is not available" "$LINENO" 5 fi FORCE_SEMANTIC_CONSTANT_FOLDING=$FORCE @@ -4918,7 +4935,9 @@ echo "semantic_constant_folding... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -4955,7 +4974,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/from"; then ac_cv_file_src_from=yes else @@ -5004,7 +5023,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "from_analysis is not available" "$LINENO" 5 + as_fn_error "from_analysis is not available" "$LINENO" 5 fi FORCE_FROM_ANALYSIS=$FORCE @@ -5023,7 +5042,9 @@ echo "from_analysis... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5060,7 +5081,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/gui"; then ac_cv_file_src_gui=yes else @@ -5109,7 +5130,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "gui is not available" "$LINENO" 5 + as_fn_error "gui is not available" "$LINENO" 5 fi FORCE_GUI=$FORCE @@ -5128,7 +5149,9 @@ echo "gui... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5164,7 +5187,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/impact"; then ac_cv_file_src_impact=yes else @@ -5213,7 +5236,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "impact is not available" "$LINENO" 5 + as_fn_error "impact is not available" "$LINENO" 5 fi FORCE_IMPACT=$FORCE @@ -5232,7 +5255,9 @@ echo "impact... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5291,7 +5316,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/inout"; then ac_cv_file_src_inout=yes else @@ -5340,7 +5365,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "inout is not available" "$LINENO" 5 + as_fn_error "inout is not available" "$LINENO" 5 fi FORCE_INOUT=$FORCE @@ -5359,7 +5384,9 @@ echo "inout... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5406,7 +5433,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/metrics"; then ac_cv_file_src_metrics=yes else @@ -5455,7 +5482,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "metrics is not available" "$LINENO" 5 + as_fn_error "metrics is not available" "$LINENO" 5 fi FORCE_METRICS=$FORCE @@ -5474,6 +5501,24 @@ echo "metrics... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) + + + + + + + + + + + + USE_VALUE_ANALYSIS=$USE_VALUE_ANALYSIS" "metrics + USED_METRICS=$USED_METRICS" "value_analysis + + @@ -5481,6 +5526,12 @@ + USE_GUI=$USE_GUI" "metrics + USED_METRICS=$USED_METRICS" "gui + + + + # occurrence @@ -5499,7 +5550,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/occurrence"; then ac_cv_file_src_occurrence=yes else @@ -5548,7 +5599,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "occurrence is not available" "$LINENO" 5 + as_fn_error "occurrence is not available" "$LINENO" 5 fi FORCE_OCCURRENCE=$FORCE @@ -5567,7 +5618,9 @@ echo "occurrence... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5614,7 +5667,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/pdg"; then ac_cv_file_src_pdg=yes else @@ -5663,7 +5716,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "pdg is not available" "$LINENO" 5 + as_fn_error "pdg is not available" "$LINENO" 5 fi FORCE_PDG=$FORCE @@ -5682,7 +5735,9 @@ echo "pdg... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5729,7 +5784,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/postdominators"; then ac_cv_file_src_postdominators=yes else @@ -5778,7 +5833,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "postdominators is not available" "$LINENO" 5 + as_fn_error "postdominators is not available" "$LINENO" 5 fi FORCE_POSTDOMINATORS=$FORCE @@ -5797,7 +5852,9 @@ echo "postdominators... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -5822,7 +5879,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/rte"; then ac_cv_file_src_rte=yes else @@ -5871,7 +5928,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "rte_annotation is not available" "$LINENO" 5 + as_fn_error "rte_annotation is not available" "$LINENO" 5 fi FORCE_RTE_ANNOTATION=$FORCE @@ -5890,100 +5947,9 @@ echo "rte_annotation... $ENABLE" - - - - - - - - - -# report -######## - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for src/report" >&5 -$as_echo_n "checking for src/report... " >&6; } -if test "${ac_cv_file_src_report+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 -if test -r "src/report"; then - ac_cv_file_src_report=yes -else - ac_cv_file_src_report=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_src_report" >&5 -$as_echo "$ac_cv_file_src_report" >&6; } -if test "x$ac_cv_file_src_report" = x""yes; then : - default=yes;plugin_present=yes -else - plugin_present=no;default=no -fi - - -FORCE=no - -# Check whether --enable-report was given. -if test "${enable_report+set}" = set; then : - enableval=$enable_report; ENABLE=$enableval;FORCE=$enableval -else - ENABLE=$default - -fi - - -if test "$ONLY_KERNEL" = "yes" -a "$FORCE" = "no"; then - ENABLE=no -fi - - - -# Test to change for static plugin, dynamic option -#default_dyn=no -#define([PLUGIN_HELP_DYN], -# AC_HELP_STRING([--enable-PLUGIN_NAME-dynamic], -# [PLUGIN_MSG (default: static)]) -#define([PLUGIN_NAME_DYN],[PLUGIN_NAME]-dynamic) -#AC_ARG_ENABLE( -# [PLUGIN_NAME_DYN], -# PLUGIN_HELP_DYN, -# ENABLE=$enableval; -# FORCE=$enableval -# ENABLE=$default_dyn -#) -#eval ENABLE_DYNAMIC_$up=\$ENABLE - -if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "report is not available" "$LINENO" 5 -fi - -FORCE_REPORT=$FORCE -PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_REPORT - -ENABLE_REPORT=$ENABLE -NAME_REPORT=report -if test "$default" = "no" -a "$FORCE" = "no"; then - INFO_REPORT=" (not available by default)" -fi - -# Dynamic plug-ins configuration -# static plug-in - DYNAMIC_REPORT=no - - - -echo "report... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6008,7 +5974,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/scope"; then ac_cv_file_src_scope=yes else @@ -6057,7 +6023,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "scope is not available" "$LINENO" 5 + as_fn_error "scope is not available" "$LINENO" 5 fi FORCE_SCOPE=$FORCE @@ -6076,7 +6042,9 @@ echo "scope... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6107,6 +6075,28 @@ + + + + REQUIRE_FROM_ANALYSIS=$REQUIRE_FROM_ANALYSIS" "scope + REQUIRED_SCOPE=$REQUIRED_SCOPE" "from_analysis + + + + + + + + + + USE_GUI=$USE_GUI" "scope + USED_SCOPE=$USED_SCOPE" "gui + + + + + + # semantic callgraph #################### @@ -6123,7 +6113,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/semantic_callgraph"; then ac_cv_file_src_semantic_callgraph=yes else @@ -6172,7 +6162,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "semantic_callgraph is not available" "$LINENO" 5 + as_fn_error "semantic_callgraph is not available" "$LINENO" 5 fi FORCE_SEMANTIC_CALLGRAPH=$FORCE @@ -6191,7 +6181,9 @@ echo "semantic_callgraph... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6238,7 +6230,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/slicing"; then ac_cv_file_src_slicing=yes else @@ -6287,7 +6279,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "slicing is not available" "$LINENO" 5 + as_fn_error "slicing is not available" "$LINENO" 5 fi FORCE_SLICING=$FORCE @@ -6306,7 +6298,9 @@ echo "slicing... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6375,7 +6369,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/sparecode"; then ac_cv_file_src_sparecode=yes else @@ -6424,7 +6418,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "sparecode is not available" "$LINENO" 5 + as_fn_error "sparecode is not available" "$LINENO" 5 fi FORCE_SPARECODE=$FORCE @@ -6443,7 +6437,9 @@ echo "sparecode... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6490,7 +6486,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/syntactic_callgraph"; then ac_cv_file_src_syntactic_callgraph=yes else @@ -6539,7 +6535,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "syntactic_callgraph is not available" "$LINENO" 5 + as_fn_error "syntactic_callgraph is not available" "$LINENO" 5 fi FORCE_SYNTACTIC_CALLGRAPH=$FORCE @@ -6558,7 +6554,9 @@ echo "syntactic_callgraph... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6600,7 +6598,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/users"; then ac_cv_file_src_users=yes else @@ -6649,7 +6647,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "users is not available" "$LINENO" 5 + as_fn_error "users is not available" "$LINENO" 5 fi FORCE_USERS=$FORCE @@ -6668,7 +6666,9 @@ echo "users... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6704,7 +6704,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/value"; then ac_cv_file_src_value=yes else @@ -6753,7 +6753,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "value_analysis is not available" "$LINENO" 5 + as_fn_error "value_analysis is not available" "$LINENO" 5 fi FORCE_VALUE_ANALYSIS=$FORCE @@ -6772,6 +6772,9 @@ echo "value_analysis... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -6783,20 +6786,8 @@ - - REQUIRE_FROM_ANALYSIS=$REQUIRE_FROM_ANALYSIS" "value_analysis - REQUIRED_VALUE_ANALYSIS=$REQUIRED_VALUE_ANALYSIS" "from_analysis - - - - - - - - - - REQUIRE_SCOPE=$REQUIRE_SCOPE" "value_analysis - REQUIRED_VALUE_ANALYSIS=$REQUIRED_VALUE_ANALYSIS" "scope + USE_GUI=$USE_GUI" "value_analysis + USED_VALUE_ANALYSIS=$USED_VALUE_ANALYSIS" "gui @@ -6806,8 +6797,8 @@ - USE_GUI=$USE_GUI" "value_analysis - USED_VALUE_ANALYSIS=$USED_VALUE_ANALYSIS" "gui + USE_SCOPE=$USE_SCOPE" "value_analysis + USED_VALUE_ANALYSIS=$USED_VALUE_ANALYSIS" "scope @@ -6835,7 +6826,7 @@ --host=$host --build=$build --mandir=$mandir; fi) else - as_fn_error $? "--enable-external expects an existing directory as argument." "$LINENO" 5 + as_fn_error "--enable-external expects an existing directory as argument." "$LINENO" 5 fi fi @@ -6852,12 +6843,14 @@ ########################################################################## # # -# This file is part of Frama-C. # +# This file is part of Aorai plug-in of Frama-C. # # # # Copyright (C) 2007-2011 # -# INSA (Institut National des Sciences Appliquees) # +# CEA (Commissariat a l'énergie atomique et aux énergies # +# alternatives) # # INRIA (Institut National de Recherche en Informatique et en # # Automatique) # +# INSA (Institut National des Sciences Appliquees) # # # # you can redistribute it and/or modify it under the terms of the GNU # # Lesser General Public License as published by the Free Software # @@ -6894,7 +6887,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "src/aorai/Makefile.in"; then ac_cv_file_src_aorai_Makefile_in=yes else @@ -6943,7 +6936,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "aorai is not available" "$LINENO" 5 + as_fn_error "aorai is not available" "$LINENO" 5 fi FORCE_AORAI=$FORCE @@ -6980,7 +6973,9 @@ echo "aorai... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -7065,12 +7060,11 @@ - ac_config_files="$ac_config_files src/aorai/Makefile" - - EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} src/aorai" - - + ac_config_files="$ac_config_files src/aorai/Makefile" + if test "$ENABLE_AORAI" != "no"; then + EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} src/aorai"; + fi @@ -7131,6 +7125,9 @@ # # ########################################################################## +######################################## +# E-ACSL as a standard Frama-C plug-in # +######################################## @@ -7146,22 +7143,23 @@ -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for src/security_slicing/Makefile.in" >&5 -$as_echo_n "checking for src/security_slicing/Makefile.in... " >&6; } -if test "${ac_cv_file_src_security_slicing_Makefile_in+set}" = set; then : + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for src/report/Makefile.in" >&5 +$as_echo_n "checking for src/report/Makefile.in... " >&6; } +if test "${ac_cv_file_src_report_Makefile_in+set}" = set; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 -if test -r "src/security_slicing/Makefile.in"; then - ac_cv_file_src_security_slicing_Makefile_in=yes + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "src/report/Makefile.in"; then + ac_cv_file_src_report_Makefile_in=yes else - ac_cv_file_src_security_slicing_Makefile_in=no + ac_cv_file_src_report_Makefile_in=no fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_src_security_slicing_Makefile_in" >&5 -$as_echo "$ac_cv_file_src_security_slicing_Makefile_in" >&6; } -if test "x$ac_cv_file_src_security_slicing_Makefile_in" = x""yes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_src_report_Makefile_in" >&5 +$as_echo "$ac_cv_file_src_report_Makefile_in" >&6; } +if test "x$ac_cv_file_src_report_Makefile_in" = x""yes; then : default=yes;plugin_present=yes else plugin_present=no;default=no @@ -7170,9 +7168,9 @@ FORCE=no -# Check whether --enable-security_slicing was given. -if test "${enable_security_slicing+set}" = set; then : - enableval=$enable_security_slicing; ENABLE=$enableval;FORCE=$enableval +# Check whether --enable-report was given. +if test "${enable_report+set}" = set; then : + enableval=$enable_report; ENABLE=$enableval;FORCE=$enableval else ENABLE=$default @@ -7201,24 +7199,24 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "security_slicing is not available" "$LINENO" 5 + as_fn_error "report is not available" "$LINENO" 5 fi -FORCE_SECURITY_SLICING=$FORCE -PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_SECURITY_SLICING +FORCE_REPORT=$FORCE +PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_REPORT -ENABLE_SECURITY_SLICING=$ENABLE -NAME_SECURITY_SLICING=security_slicing +ENABLE_REPORT=$ENABLE +NAME_REPORT=report if test "$default" = "no" -a "$FORCE" = "no"; then - INFO_SECURITY_SLICING=" (not available by default)" + INFO_REPORT=" (not available by default)" fi # Dynamic plug-ins configuration -# Check whether --with-security_slicing-static was given. -if test "${with_security_slicing_static+set}" = set; then : - withval=$with_security_slicing_static; is_static=$withval +# Check whether --with-report-static was given. +if test "${with_report_static+set}" = set; then : + withval=$with_report_static; is_static=$withval else is_static=$IS_ALL_STATIC fi @@ -7227,44 +7225,46 @@ # is_static = "yes" iff the user forces the plug-in to be static # is_static = "no" iff the user forces the plug-in to be dynamic # is_static = "" in others cases (no special instruction) - STATIC_SECURITY_SLICING=$is_static + STATIC_REPORT=$is_static if test "$is_static" != "yes"; then - USE_NATIVE_DYNLINK="${USE_NATIVE_DYNLINK} security_slicing" - DYNAMIC_SECURITY_SLICING=yes + USE_NATIVE_DYNLINK="${USE_NATIVE_DYNLINK} report" + DYNAMIC_REPORT=yes else - DYNAMIC_SECURITY_SLICING=no + DYNAMIC_REPORT=no fi -echo "security_slicing... $ENABLE" - - - +echo "report... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) -if test "$ENABLE_SECURITY_SLICING" != "no"; then +####################### +# Generating Makefile # +####################### - REQUIRE_SLICING=$REQUIRE_SLICING" "security_slicing - REQUIRED_SECURITY_SLICING=$REQUIRED_SECURITY_SLICING" "slicing + ac_config_files="$ac_config_files src/report/Makefile" + if test "$ENABLE_REPORT" != "no"; then + EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} src/report"; + fi - REQUIRE_VALUE_ANALYSIS=$REQUIRE_VALUE_ANALYSIS" "security_slicing - REQUIRED_SECURITY_SLICING=$REQUIRED_SECURITY_SLICING" "value_analysis @@ -7273,9 +7273,28 @@ + ########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2011 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## - REQUIRE_PDG=$REQUIRE_PDG" "security_slicing - REQUIRED_SECURITY_SLICING=$REQUIRED_SECURITY_SLICING" "pdg @@ -7285,22 +7304,645 @@ - USE_GUI=$USE_GUI" "security_slicing - USED_SECURITY_SLICING=$USED_SECURITY_SLICING" "gui +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for src/security_slicing/Makefile.in" >&5 +$as_echo_n "checking for src/security_slicing/Makefile.in... " >&6; } +if test "${ac_cv_file_src_security_slicing_Makefile_in+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "src/security_slicing/Makefile.in"; then + ac_cv_file_src_security_slicing_Makefile_in=yes +else + ac_cv_file_src_security_slicing_Makefile_in=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_src_security_slicing_Makefile_in" >&5 +$as_echo "$ac_cv_file_src_security_slicing_Makefile_in" >&6; } +if test "x$ac_cv_file_src_security_slicing_Makefile_in" = x""yes; then : + default=yes;plugin_present=yes +else + plugin_present=no;default=no fi +FORCE=no + +# Check whether --enable-security_slicing was given. +if test "${enable_security_slicing+set}" = set; then : + enableval=$enable_security_slicing; ENABLE=$enableval;FORCE=$enableval +else + ENABLE=$default + +fi + + +if test "$ONLY_KERNEL" = "yes" -a "$FORCE" = "no"; then + ENABLE=no +fi + + + +# Test to change for static plugin, dynamic option +#default_dyn=no +#define([PLUGIN_HELP_DYN], +# AC_HELP_STRING([--enable-PLUGIN_NAME-dynamic], +# [PLUGIN_MSG (default: static)]) +#define([PLUGIN_NAME_DYN],[PLUGIN_NAME]-dynamic) +#AC_ARG_ENABLE( +# [PLUGIN_NAME_DYN], +# PLUGIN_HELP_DYN, +# ENABLE=$enableval; +# FORCE=$enableval +# ENABLE=$default_dyn +#) +#eval ENABLE_DYNAMIC_$up=\$ENABLE + +if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then + as_fn_error "security_slicing is not available" "$LINENO" 5 +fi + +FORCE_SECURITY_SLICING=$FORCE +PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_SECURITY_SLICING + +ENABLE_SECURITY_SLICING=$ENABLE +NAME_SECURITY_SLICING=security_slicing +if test "$default" = "no" -a "$FORCE" = "no"; then + INFO_SECURITY_SLICING=" (not available by default)" +fi + +# Dynamic plug-ins configuration + + +# Check whether --with-security_slicing-static was given. +if test "${with_security_slicing_static+set}" = set; then : + withval=$with_security_slicing_static; is_static=$withval +else + is_static=$IS_ALL_STATIC +fi + + + # is_static = "yes" iff the user forces the plug-in to be static + # is_static = "no" iff the user forces the plug-in to be dynamic + # is_static = "" in others cases (no special instruction) + STATIC_SECURITY_SLICING=$is_static + if test "$is_static" != "yes"; then + USE_NATIVE_DYNLINK="${USE_NATIVE_DYNLINK} security_slicing" + DYNAMIC_SECURITY_SLICING=yes + else + DYNAMIC_SECURITY_SLICING=no + fi + + + +echo "security_slicing... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) + + + + + + + + +if test "$ENABLE_SECURITY_SLICING" != "no"; then + + + + + REQUIRE_SLICING=$REQUIRE_SLICING" "security_slicing + REQUIRED_SECURITY_SLICING=$REQUIRED_SECURITY_SLICING" "slicing + + + + + + + + + + REQUIRE_VALUE_ANALYSIS=$REQUIRE_VALUE_ANALYSIS" "security_slicing + REQUIRED_SECURITY_SLICING=$REQUIRED_SECURITY_SLICING" "value_analysis + + + + + + + + + + REQUIRE_PDG=$REQUIRE_PDG" "security_slicing + REQUIRED_SECURITY_SLICING=$REQUIRED_SECURITY_SLICING" "pdg + + + + + + + + + + USE_GUI=$USE_GUI" "security_slicing + USED_SECURITY_SLICING=$USED_SECURITY_SLICING" "gui + + + + + + +fi + + + + + ac_config_files="$ac_config_files src/security_slicing/Makefile" + + if test "$ENABLE_SECURITY_SLICING" != "no"; then + EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} src/security_slicing"; + fi + + + + + + + + + + + + + + + + + + + + + + ########################################################################## +# # +# This file is part of WP plug-in of Frama-C. # +# # +# Copyright (C) 2007-2011 # +# CEA (Commissariat a l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for src/wp/Makefile.in" >&5 +$as_echo_n "checking for src/wp/Makefile.in... " >&6; } +if test "${ac_cv_file_src_wp_Makefile_in+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "src/wp/Makefile.in"; then + ac_cv_file_src_wp_Makefile_in=yes +else + ac_cv_file_src_wp_Makefile_in=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_src_wp_Makefile_in" >&5 +$as_echo "$ac_cv_file_src_wp_Makefile_in" >&6; } +if test "x$ac_cv_file_src_wp_Makefile_in" = x""yes; then : + default=yes;plugin_present=yes +else + plugin_present=no;default=no +fi + + +FORCE=no + +# Check whether --enable-wp was given. +if test "${enable_wp+set}" = set; then : + enableval=$enable_wp; ENABLE=$enableval;FORCE=$enableval +else + ENABLE=$default + +fi + + +if test "$ONLY_KERNEL" = "yes" -a "$FORCE" = "no"; then + ENABLE=no +fi + + + +# Test to change for static plugin, dynamic option +#default_dyn=no +#define([PLUGIN_HELP_DYN], +# AC_HELP_STRING([--enable-PLUGIN_NAME-dynamic], +# [PLUGIN_MSG (default: static)]) +#define([PLUGIN_NAME_DYN],[PLUGIN_NAME]-dynamic) +#AC_ARG_ENABLE( +# [PLUGIN_NAME_DYN], +# PLUGIN_HELP_DYN, +# ENABLE=$enableval; +# FORCE=$enableval +# ENABLE=$default_dyn +#) +#eval ENABLE_DYNAMIC_$up=\$ENABLE + +if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then + as_fn_error "wp is not available" "$LINENO" 5 +fi + +FORCE_WP=$FORCE +PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_WP + +ENABLE_WP=$ENABLE +NAME_WP=wp +if test "$default" = "no" -a "$FORCE" = "no"; then + INFO_WP=" (not available by default)" +fi + +# Dynamic plug-ins configuration + + +# Check whether --with-wp-static was given. +if test "${with_wp_static+set}" = set; then : + withval=$with_wp_static; is_static=$withval +else + is_static=$IS_ALL_STATIC +fi + + + # is_static = "yes" iff the user forces the plug-in to be static + # is_static = "no" iff the user forces the plug-in to be dynamic + # is_static = "" in others cases (no special instruction) + STATIC_WP=$is_static + if test "$is_static" != "yes"; then + USE_NATIVE_DYNLINK="${USE_NATIVE_DYNLINK} wp" + DYNAMIC_WP=yes + else + DYNAMIC_WP=no + fi + + + +echo "wp... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) + + + + + + + + +if test "$ENABLE_WP" != "no"; then + + + + + USE_GUI=$USE_GUI" "wp + USED_WP=$USED_WP" "gui + + + + + + + + + + USE_RTE_ANNOTATION=$USE_RTE_ANNOTATION" "wp + USED_WP=$USED_WP" "rte_annotation + + + + + + + + USE_ALTERGO=$USE_ALTERGO" "wp + + + + + USE_COQ=$USE_COQ" "wp + + + + + USE_WHY=$USE_WHY" "wp + + + + + USE_DOT=$USE_DOT" "wp + + + + + USE_WHYDP=$USE_WHYDP" "wp + + + + # Why + + + + + + + + + + + for file in why; do + HAS_WHY= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_WHY+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_WHY"; then + ac_cv_prog_HAS_WHY="$HAS_WHY" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_WHY="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_WHY" && ac_cv_prog_HAS_WHY="no" +fi +fi +HAS_WHY=$ac_cv_prog_HAS_WHY +if test -n "$HAS_WHY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_WHY" >&5 +$as_echo "$HAS_WHY" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_WHY" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + # Why-dp + + + + + + + + + + + for file in why-dp; do + HAS_WHYDP= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_WHYDP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_WHYDP"; then + ac_cv_prog_HAS_WHYDP="$HAS_WHYDP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_WHYDP="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_WHYDP" && ac_cv_prog_HAS_WHYDP="no" +fi +fi +HAS_WHYDP=$ac_cv_prog_HAS_WHYDP +if test -n "$HAS_WHYDP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_WHYDP" >&5 +$as_echo "$HAS_WHYDP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_WHYDP" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + # alt-ergo + + + + + + + + + + + for file in alt-ergo; do + HAS_ALTERGO= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_ALTERGO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_ALTERGO"; then + ac_cv_prog_HAS_ALTERGO="$HAS_ALTERGO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_ALTERGO="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_ALTERGO" && ac_cv_prog_HAS_ALTERGO="no" +fi +fi +HAS_ALTERGO=$ac_cv_prog_HAS_ALTERGO +if test -n "$HAS_ALTERGO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_ALTERGO" >&5 +$as_echo "$HAS_ALTERGO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_ALTERGO" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + ALTERGO_VERSION=`alt-ergo -version | sed -e 's/Alt-Ergo \(.*\)/\1/' ` + { $as_echo "$as_me:${as_lineno-$LINENO}: alt-ergo version is $ALTERGO_VERSION." >&5 +$as_echo "$as_me: alt-ergo version is $ALTERGO_VERSION." >&6;} + case $ALTERGO_VERSION in + 0.92.2) { $as_echo "$as_me:${as_lineno-$LINENO}: good." >&5 +$as_echo "$as_me: good." >&6;};; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: alt-ergo's array theory unsupported." >&5 +$as_echo "$as_me: alt-ergo's array theory unsupported." >&6;};; + esac + + + # coq + + + + + + + + + + + for file in coqc; do + HAS_COQ= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_COQ+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_COQ"; then + ac_cv_prog_HAS_COQ="$HAS_COQ" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_COQ="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_COQ" && ac_cv_prog_HAS_COQ="no" +fi +fi +HAS_COQ=$ac_cv_prog_HAS_COQ +if test -n "$HAS_COQ"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_COQ" >&5 +$as_echo "$HAS_COQ" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_COQ" = "yes"; then SELECTED_VAR=$file break; fi + done + + - ac_config_files="$ac_config_files src/security_slicing/Makefile" - EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} src/security_slicing" @@ -7309,6 +7951,17 @@ +fi + + + + + ac_config_files="$ac_config_files src/wp/Makefile" + + if test "$ENABLE_WP" != "no"; then + EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} src/wp"; + fi + @@ -7349,11 +8002,11 @@ as_ac_File=`$as_echo "ac_cv_file_$OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX" >&5 $as_echo_n "checking for $OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for $OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for $OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX existence when cross compiling" "$LINENO" 5 if test -r "$OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX"; then eval "$as_ac_File=yes" else @@ -7363,7 +8016,8 @@ eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : HAS_LABLGTK=yes else HAS_LABLGTK=no @@ -7425,11 +8079,11 @@ as_ac_File=`$as_echo "ac_cv_file_$OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX" >&5 $as_echo_n "checking for $OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for $OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for $OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX existence when cross compiling" "$LINENO" 5 if test -r "$OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX"; then eval "$as_ac_File=yes" else @@ -7439,7 +8093,8 @@ eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : HAS_GTKSOURCEVIEW=yes else HAS_GTKSOURCEVIEW=no @@ -7485,11 +8140,11 @@ as_ac_File=`$as_echo "ac_cv_file_$OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX" >&5 $as_echo_n "checking for $OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for $OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for $OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX existence when cross compiling" "$LINENO" 5 if test -r "$OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX"; then eval "$as_ac_File=yes" else @@ -7499,7 +8154,8 @@ eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : HAS_GNOMECANVAS=yes else HAS_GNOMECANVAS=no @@ -7617,11 +8273,11 @@ as_ac_File=`$as_echo "ac_cv_file_$OCAMLLIB/dynlink.cmxa" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $OCAMLLIB/dynlink.cmxa" >&5 $as_echo_n "checking for $OCAMLLIB/dynlink.cmxa... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for $OCAMLLIB/dynlink.cmxa existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for $OCAMLLIB/dynlink.cmxa existence when cross compiling" "$LINENO" 5 if test -r "$OCAMLLIB/dynlink.cmxa"; then eval "$as_ac_File=yes" else @@ -7631,7 +8287,8 @@ eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : HAS_NATIVE_DYNLINK=yes else HAS_NATIVE_DYNLINK=no @@ -7663,7 +8320,7 @@ # Checking internal invariant if test "$HAS_NATIVE_DYNLINK" = "uncheck"; then - as_fn_error $? "Internal error with check of native dynlink. Please report." "$LINENO" 5 + as_fn_error "Internal error with check of native dynlink. Please report." "$LINENO" 5 fi HAS_USABLE_NATIVE_DYNLINK=no @@ -7705,7 +8362,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for dynlink existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for dynlink existence when cross compiling" "$LINENO" 5 if test -r "dynlink"; then ac_cv_file_dynlink=yes else @@ -7742,80 +8399,6 @@ rm -f test_dynlink.* fi -# Lablgtk2's custom tree model - -if test "$HAS_LABLGTK" = "yes"; then - if echo "type ('a,'b,'c,'d) t = ('a,'b,'c,'d) GTree.custom_tree_model" > test_custommodel.ml && ocamlc -c -I +lablgtk2 test_custommodel.ml 2> /dev/null; \ - then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lablgtk2's custom tree model" >&5 -$as_echo_n "checking for lablgtk2's custom tree model... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else -# we don't have a good version of lablgtk2: -# configure a dummy library "customtree" in order to -# configure plug-ins depending on lablgtk2 in a proper way - REQUIRE_CUSTOMTREE="$REQUIRE_LABLGTK" - USE_CUSTOMTREE="$USE_LABLGTK" - -# No need to check the same thing multiple times. - - - - - - - - - -# [JS 2009/06/02] sh tests and m4 variables do not mix well together. -# It works by chance but it is not robust enough. -# Should be rewritten - HAS_CUSTOMTREE=no - if test "$HAS_CUSTOMTREE" != "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for custom-tree-model" >&5 -$as_echo_n "checking for custom-tree-model... " >&6; } -if test "${ac_cv_file_custom_tree_model+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - test "$cross_compiling" = yes && - as_fn_error $? "cannot check for custom-tree-model existence when cross compiling" "$LINENO" 5 -if test -r "custom-tree-model"; then - ac_cv_file_custom_tree_model=yes -else - ac_cv_file_custom_tree_model=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_custom_tree_model" >&5 -$as_echo "$ac_cv_file_custom_tree_model" >&6; } -if test "x$ac_cv_file_custom_tree_model" = x""yes; then : - HAS_CUSTOMTREE=yes -else - HAS_CUSTOMTREE=no -fi - - if test "$HAS_CUSTOMTREE" = "yes"; then SELECTED_CUSTOMTREE=custom-tree-model - fi - fi - - CUSTOMTREE=$SELECTED_CUSTOMTREE - - - - - - - - - - - - - - fi - rm -f test_custommodel.* -fi - ######################## # Plug-in dependencies # ######################## @@ -7835,7 +8418,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$aorai"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$aorai requested but $reason." "$LINENO" 5 + as_fn_error "$aorai requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ ltl2ba\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $aorai disabled because $reason." >&5 @@ -7859,6 +8442,150 @@ fi fi + if test -n "$REQUIRE_WHY" -o -n "$USE_WHY" -o "$no" = "yes"; then + if test "$HAS_WHY" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: why not found" >&5 +$as_echo "$as_me: WARNING: why not found" >&2;} + reason="why missing" + for wp in $REQUIRE_WHY; do + up=`upper "$wp"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$wp"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$wp requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ why\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for wp in $USE_WHY; do + up=`upper "$wp"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ why\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + WHY=why + fi + fi + + if test -n "$REQUIRE_WHYDP" -o -n "$USE_WHYDP" -o "$no" = "yes"; then + if test "$HAS_WHYDP" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: why-dp not found" >&5 +$as_echo "$as_me: WARNING: why-dp not found" >&2;} + reason="why-dp missing" + for wp in $REQUIRE_WHYDP; do + up=`upper "$wp"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$wp"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$wp requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ why-dp\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for wp in $USE_WHYDP; do + up=`upper "$wp"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ why-dp\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + WHYDP=why-dp + fi + fi + + if test -n "$REQUIRE_ALTERGO" -o -n "$USE_ALTERGO" -o "$no" = "yes"; then + if test "$HAS_ALTERGO" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: alt-ergo not found" >&5 +$as_echo "$as_me: WARNING: alt-ergo not found" >&2;} + reason="alt-ergo missing" + for wp in $REQUIRE_ALTERGO; do + up=`upper "$wp"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$wp"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$wp requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ alt-ergo\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for wp in $USE_ALTERGO; do + up=`upper "$wp"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ alt-ergo\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + ALTERGO=alt-ergo + fi + fi + + if test -n "$REQUIRE_COQ" -o -n "$USE_COQ" -o "$no" = "yes"; then + if test "$HAS_COQ" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: coq not found" >&5 +$as_echo "$as_me: WARNING: coq not found" >&2;} + reason="coqc missing" + for wp in $REQUIRE_COQ; do + up=`upper "$wp"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$wp"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$wp requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ coqc\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for wp in $USE_COQ; do + up=`upper "$wp"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ coqc\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wp partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $wp partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + COQ=coqc + fi + fi + if test -n "$REQUIRE_LABLGTK" -o -n "$USE_LABLGTK" -o "$no" = "yes"; then if test "$HAS_LABLGTK" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: lablgtk2/lablgtk.$LIB_SUFFIX not found." >&5 @@ -7872,7 +8599,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ $OCAMLLIB/lablgtk2/lablgtk.$LIB_SUFFIX\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -7907,7 +8634,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ $OCAMLLIB/lablgtk2/lablgtksourceview2.$LIB_SUFFIX\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -7942,7 +8669,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ $OCAMLLIB/lablgtk2/lablgnomecanvas.$LIB_SUFFIX\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -7976,7 +8703,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ dot\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -8008,7 +8735,7 @@ # compile statically all dynamic plug-ins # except contrary instructions USE_NATIVE_DYNLINK=""; - for plugin in SEMANTIC_CONSTANT_FOLDING FROM_ANALYSIS GUI IMPACT INOUT METRICS OCCURRENCE PDG POSTDOMINATORS RTE_ANNOTATION REPORT SCOPE SEMANTIC_CALLGRAPH SLICING SPARECODE SYNTACTIC_CALLGRAPH USERS VALUE_ANALYSIS AORAI SECURITY_SLICING; do + for plugin in SEMANTIC_CONSTANT_FOLDING FROM_ANALYSIS GUI IMPACT INOUT METRICS OCCURRENCE PDG POSTDOMINATORS RTE_ANNOTATION SCOPE SEMANTIC_CALLGRAPH SLICING SPARECODE SYNTACTIC_CALLGRAPH USERS VALUE_ANALYSIS AORAI REPORT SECURITY_SLICING WP; do n=NAME_$plugin d=DYNAMIC_$plugin s=STATIC_$plugin @@ -8032,7 +8759,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ $OCAMLLIB/dynlink.cmxa\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -8062,7 +8789,7 @@ # compile statically all dynamic plug-ins # except contrary instructions USE_NATIVE_DYNLINK=""; - for plugin in SEMANTIC_CONSTANT_FOLDING FROM_ANALYSIS GUI IMPACT INOUT METRICS OCCURRENCE PDG POSTDOMINATORS RTE_ANNOTATION REPORT SCOPE SEMANTIC_CALLGRAPH SLICING SPARECODE SYNTACTIC_CALLGRAPH USERS VALUE_ANALYSIS AORAI SECURITY_SLICING; do + for plugin in SEMANTIC_CONSTANT_FOLDING FROM_ANALYSIS GUI IMPACT INOUT METRICS OCCURRENCE PDG POSTDOMINATORS RTE_ANNOTATION SCOPE SEMANTIC_CALLGRAPH SLICING SPARECODE SYNTACTIC_CALLGRAPH USERS VALUE_ANALYSIS AORAI REPORT SECURITY_SLICING WP; do n=NAME_$plugin d=DYNAMIC_$plugin s=STATIC_$plugin @@ -8086,7 +8813,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ dynlink\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -8108,41 +8835,6 @@ fi fi - if test -n "$REQUIRE_CUSTOMTREE" -o -n "$USE_CUSTOMTREE" -o "$no" = "yes"; then - if test "$HAS_CUSTOMTREE" = "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: lablgtk2's custom tree model unavailable. You need at least LablGtk 2.14." >&5 -$as_echo "$as_me: WARNING: lablgtk2's custom tree model unavailable. You need at least LablGtk 2.14." >&2;} - reason="custom-tree-model missing" - - for p in $REQUIRE_CUSTOMTREE; do - up=`upper "$p"` - ep=ENABLE_$up - eval enable_p=\$$ep - if test "$enable_p" != "no"; then - fp=FORCE_`upper "$p"` - if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 - fi - eval $ep="no\ \(see\ warning\ about\ custom-tree-model\)" - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 -$as_echo "$as_me: WARNING: $p disabled because $reason." >&2;} - eval INFO_$up=\", $reason\" - fi - done - for p in $USE_CUSTOMTREE; do - up=`upper "$p"` - ep=ENABLE_$up - eval eep="\$$ep" - if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then - eval $ep="partial\ \(see\ warning\ about\ custom-tree-model\)" - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p partially enabled because $reason." >&5 -$as_echo "$as_me: WARNING: $p partially enabled because $reason." >&2;} - eval INFO_$up=\", $reason\" - fi - done - fi - fi - # First, initialize some variables for fp in ${PLUGINS_FORCE_LIST}; do @@ -8236,13 +8928,18 @@ + + ################################################ # Finally create the Makefile from Makefile.in # ################################################ new_section "creating makefile" -ac_config_files="$ac_config_files cil/ocamlutil/perfcount.c share/Makefile.config" +ac_config_files="$ac_config_files cil/ocamlutil/perfcount.c" + +ac_config_files="$ac_config_files share/Makefile.config" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -8327,7 +9024,6 @@ ac_libobjs= ac_ltlibobjs= -U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -8489,19 +9185,19 @@ (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -8697,7 +9393,7 @@ test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -8751,7 +9447,7 @@ # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -8813,10 +9509,10 @@ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -8831,16 +9527,11 @@ while test $# != 0 do case $1 in - --*=?*) + --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; *) ac_option=$1 ac_optarg=$2 @@ -8862,7 +9553,6 @@ $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -8875,7 +9565,7 @@ ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - as_fn_error $? "ambiguous option: \`$1' + as_fn_error "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; @@ -8884,7 +9574,7 @@ ac_cs_silent=: ;; # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' + -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -8935,11 +9625,13 @@ case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "src/aorai/Makefile") CONFIG_FILES="$CONFIG_FILES src/aorai/Makefile" ;; + "src/report/Makefile") CONFIG_FILES="$CONFIG_FILES src/report/Makefile" ;; "src/security_slicing/Makefile") CONFIG_FILES="$CONFIG_FILES src/security_slicing/Makefile" ;; + "src/wp/Makefile") CONFIG_FILES="$CONFIG_FILES src/wp/Makefile" ;; "cil/ocamlutil/perfcount.c") CONFIG_FILES="$CONFIG_FILES cil/ocamlutil/perfcount.c" ;; "share/Makefile.config") CONFIG_FILES="$CONFIG_FILES share/Makefile.config" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -8976,7 +9668,7 @@ { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -8993,7 +9685,7 @@ fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' + ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi @@ -9007,18 +9699,18 @@ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -9107,28 +9799,20 @@ else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 + || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// s/^[^=]*=[ ]*$// }' fi @@ -9156,7 +9840,7 @@ if test -z "$ac_t"; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -9241,7 +9925,7 @@ _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" @@ -9254,7 +9938,7 @@ esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -9282,7 +9966,7 @@ [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -9309,7 +9993,7 @@ case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -9435,22 +10119,22 @@ $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 +which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} +which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; :H) # @@ -9461,19 +10145,19 @@ $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error $? "could not create -" "$LINENO" 5 + || as_fn_error "could not create -" "$LINENO" 5 fi ;; @@ -9483,7 +10167,11 @@ case $ac_file$ac_mode in "src/aorai/Makefile":F) chmod -w src/aorai/Makefile ;; + "src/report/Makefile":F) chmod -w src/report/Makefile ;; "src/security_slicing/Makefile":F) chmod -w src/security_slicing/Makefile ;; + "src/wp/Makefile":F) chmod -w src/wp/Makefile ;; + "cil/ocamlutil/perfcount.c":F) chmod a-w cil/ocamlutil/perfcount.c ;; + "share/Makefile.config":F) chmod a-w share/Makefile.config ;; esac done # for ac_tag @@ -9494,7 +10182,7 @@ ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -9515,14 +10203,13 @@ exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 + $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi -chmod a-w cil/ocamlutil/perfcount.c share/Makefile.config ########### # Summary # @@ -9530,7 +10217,7 @@ new_section "summary: plug-ins available" -for plugin in SEMANTIC_CONSTANT_FOLDING FROM_ANALYSIS GUI IMPACT INOUT METRICS OCCURRENCE PDG POSTDOMINATORS RTE_ANNOTATION REPORT SCOPE SEMANTIC_CALLGRAPH SLICING SPARECODE SYNTACTIC_CALLGRAPH USERS VALUE_ANALYSIS AORAI SECURITY_SLICING; do +for plugin in SEMANTIC_CONSTANT_FOLDING FROM_ANALYSIS GUI IMPACT INOUT METRICS OCCURRENCE PDG POSTDOMINATORS RTE_ANNOTATION SCOPE SEMANTIC_CALLGRAPH SLICING SPARECODE SYNTACTIC_CALLGRAPH USERS VALUE_ANALYSIS AORAI REPORT SECURITY_SLICING WP; do n=NAME_$plugin e=ENABLE_$plugin d=DYNAMIC_$plugin diff -Nru frama-c-20110201+carbon+dfsg/configure.in frama-c-20111001+nitrogen+dfsg/configure.in --- frama-c-20110201+carbon+dfsg/configure.in 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/configure.in 2011-10-10 08:40:09.000000000 +0000 @@ -240,7 +240,7 @@ then OCAMLGRAPH_VERSION=`./test_ocamlgraph` case $OCAMLGRAPH_VERSION in - 1.7) AC_MSG_NOTICE([OcamlGraph $OCAMLGRAPH_VERSION found: great!]);; + 1.8) AC_MSG_NOTICE([OcamlGraph $OCAMLGRAPH_VERSION found: great!]);; *) AC_MSG_NOTICE([OcamlGraph $OCAMLGRAPH_VERSION is incompatible with Frama-C.]) OCAMLGRAPH_EXISTS=no OCAMLGRAPH_INCLUDE=;; @@ -295,10 +295,10 @@ fi ################################################# -# Check for other non-mandatory tools/libraries # +# Check for other (optional) tools/libraries # ################################################# -new_section "configure non-mandatory tools and libraries" +new_section "configure optional tools and libraries" AC_CHECK_PROG(OCAMLDOC,ocamldoc,ocamldoc,no) if test "$OCAMLDOC" = no ; then @@ -563,6 +563,8 @@ ######### check_plugin(metrics,src/metrics,[support for metrics analysis],yes,no) +plugin_use(metrics,value_analysis) +plugin_use(metrics,gui) # occurrence ############ @@ -587,12 +589,8 @@ # rte ##### -check_plugin(rte_annotation,src/rte,[support for runtime error annotation],yes,no) - -# report -######## - -check_plugin(report,src/report,[ACSL properties status report],yes,no) +check_plugin(rte_annotation,src/rte, + [support for runtime error annotation],yes,no) # scope ############ @@ -600,6 +598,8 @@ check_plugin(scope,src/scope,[support for scope plugin],yes,no) plugin_require(scope,postdominators) plugin_require(scope,value_analysis) +plugin_require(scope,from_analysis) +plugin_use(scope,gui) # semantic callgraph #################### @@ -646,9 +646,8 @@ check_plugin(value_analysis,src/value,[support for value analysis],yes,no, [src/ai src/buckx]) -plugin_require(value_analysis,from_analysis) -plugin_require(value_analysis,scope) plugin_use(value_analysis,gui) +plugin_use(value_analysis,scope) #################### # External plugins # @@ -677,11 +676,11 @@ define([KNOWN_SRC_DIRS], KNOWN_SRC_DIRS src/kernel src/project src/logic src/dummy src/toplevel \ - src/lib src/misc src/qed) + src/lib src/misc src/qed src/type) AC_FOREACH([p],m4_esyscmd([ls src]), [ m4_if(m4_index(KNOWN_SRC_DIRS,p),[-1], - [ m4_syscmd(test -r src/p/configure.in) + [ m4_syscmd(test -r src/p/configure.in) m4_define([is_configure_in],m4_sysval) m4_syscmd(test -r src/p/configure.ac) m4_define([is_configure_ac],m4_sysval) @@ -692,7 +691,9 @@ [ m4_syscmd(test -r src/p/Makefile) m4_if(m4_sysval,[0], [ check_plugin(p,src/p,[support for p plug-in],yes,yes) - EXTERNAL_PLUGINS="$EXTERNAL_PLUGINS src/p" ])], + if test "$[ENABLE_]tovarname(p)" != "no"; then + EXTERNAL_PLUGINS="$EXTERNAL_PLUGINS src/p"; + fi])], [ m4_define([plugin_prefix],src/p) m4_include(config_file) m4_syscmd(cd src/p && [FRAMAC_SHARE]=../../share autoconf) @@ -818,29 +819,6 @@ rm -f test_dynlink.* fi -# Lablgtk2's custom tree model - -if test "$HAS_LABLGTK" = "yes"; then - if echo "type ('a,'b,'c,'d) t = ('a,'b,'c,'d) GTree.custom_tree_model" > test_custommodel.ml && ocamlc -c -I +lablgtk2 test_custommodel.ml 2> /dev/null; \ - then - AC_MSG_CHECKING([for lablgtk2's custom tree model]) - AC_MSG_RESULT([yes]) - else -# we don't have a good version of lablgtk2: -# configure a dummy library "customtree" in order to -# configure plug-ins depending on lablgtk2 in a proper way - REQUIRE_CUSTOMTREE="$REQUIRE_LABLGTK" - USE_CUSTOMTREE="$USE_LABLGTK" - configure_library( - [CUSTOMTREE], - [custom-tree-model], - [lablgtk2's custom tree model unavailable. You need at least LablGtk 2.14.], - yes - ) - fi - rm -f test_custommodel.* -fi - ######################## # Plug-in dependencies # ######################## @@ -897,9 +875,11 @@ new_section "creating makefile" -AC_CONFIG_FILES(cil/ocamlutil/perfcount.c share/Makefile.config) +AC_CONFIG_FILES([cil/ocamlutil/perfcount.c], + [chmod a-w cil/ocamlutil/perfcount.c]) +AC_CONFIG_FILES([share/Makefile.config], [chmod a-w share/Makefile.config]) + AC_OUTPUT() -chmod a-w cil/ocamlutil/perfcount.c share/Makefile.config ########### # Summary # diff -Nru frama-c-20110201+carbon+dfsg/debian/changelog frama-c-20111001+nitrogen+dfsg/debian/changelog --- frama-c-20110201+carbon+dfsg/debian/changelog 2011-11-19 16:58:03.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/changelog 2012-01-06 08:31:18.000000000 +0000 @@ -1,20 +1,30 @@ -frama-c (20110201+carbon+dfsg-2build3) precise; urgency=low +frama-c (20111001+nitrogen+dfsg-3) unstable; urgency=low - * Rebuild for OCaml 3.12.1. + * Include patchlevel2 for Nitrogen 20111001. + - add debian/patches/0006-Patchlevel2-for-Nitrogen-20111001.patch - -- Colin Watson Sat, 19 Nov 2011 16:58:03 +0000 + -- Mehdi Dogguy Fri, 06 Jan 2012 09:30:44 +0100 -frama-c (20110201+carbon+dfsg-2build2) oneiric; urgency=low +frama-c (20111001+nitrogen+dfsg-2) unstable; urgency=low - * No-change rebuild for new lablgtk ABI + * add 0005-Disable-CHMOD_RO-invocations.patch. - -- Iain Lane Sat, 24 Sep 2011 09:26:39 +0100 + -- Mehdi Dogguy Tue, 03 Jan 2012 15:24:55 +0100 -frama-c (20110201+carbon+dfsg-2build1) oneiric; urgency=low +frama-c (20111001+nitrogen+dfsg-1) unstable; urgency=low - * Rebuild to pick up ocaml fixes on armel. + * New upstream release (Closes: #652257). + * Update patches: + - remove 0001-Value-Analysis-Carbon-patchlevel-1.patch + - remove 0002-Fix-for-issue-727.patch + - rebase 0003-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch + - update 0004-Accept-ocamlgraph-1.8.patch + - add 0003-Fix-spelling-error-in-binary.patch + - add 0004-Use-bin-cp-instead-of-usr-bin-install.patch + * Bump minimum requirement for ocamlgraph to 1.8. + * Bump Standards-Version to 3.9.2, no changes needed. - -- Adam Conrad Wed, 24 Aug 2011 16:40:54 -0600 + -- Mehdi Dogguy Mon, 02 Jan 2012 17:29:13 +0100 frama-c (20110201+carbon+dfsg-2) unstable; urgency=low diff -Nru frama-c-20110201+carbon+dfsg/debian/control frama-c-20111001+nitrogen+dfsg/debian/control --- frama-c-20110201+carbon+dfsg/debian/control 2011-04-25 10:05:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/control 2012-01-06 08:30:25.000000000 +0000 @@ -9,10 +9,10 @@ ocaml-best-compilers, dh-ocaml (>= 0.9~), graphviz, - libocamlgraph-viewer-ocaml-dev (>> 1.4~), + libocamlgraph-viewer-ocaml-dev (>> 1.8~), liblablgtk2-gnome-ocaml-dev (>= 2.14.0+dfsg-2~), liblablgtksourceview2-ocaml-dev (>= 2.14.0+dfsg-2~) -Standards-Version: 3.9.0 +Standards-Version: 3.9.2 Homepage: http://frama-c.com/ Vcs-Browser: http://git.debian.org/?p=pkg-ocaml-maint/packages/frama-c.git Vcs-Git: git://git.debian.org/git/pkg-ocaml-maint/packages/frama-c.git diff -Nru frama-c-20110201+carbon+dfsg/debian/copyright frama-c-20111001+nitrogen+dfsg/debian/copyright --- frama-c-20110201+carbon+dfsg/debian/copyright 2011-04-25 10:03:10.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/copyright 2012-01-06 08:30:25.000000000 +0000 @@ -134,7 +134,6 @@ © 2001-2005 Wes Weimer © 2001-2005 Ben Liblit License: BSD-3 - See `/usr/share/common-licenses/BSD'. Files: tests/idct/* Copyright: © 2001 Renaud Pacalet @@ -143,7 +142,6 @@ Files: external/unmarshal* Copyright: © 2009-2010 Institut National de Recherche en Informatique et en Automatique License: BSD-3 - See `/usr/share/common-licenses/BSD'. Files: external/hptmap.ml Files: external/hptmap.mli diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0001-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0001-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0001-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0001-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch 2012-01-06 08:30:25.000000000 +0000 @@ -0,0 +1,27 @@ +From: Mehdi Dogguy +Date: Mon, 25 Apr 2011 12:01:09 +0200 +Subject: Add +ocamlgraph to DYN_{O,B}LINKFLAGS + +--- + Makefile | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index b70d794..6432662 100644 +--- a/Makefile ++++ b/Makefile +@@ -1324,11 +1324,11 @@ share/Makefile.kernel: Makefile share/Makefile.config share/Makefile.common + $(ECHO) "DYN_OPT_LIBS=$(filter-out $(GEN_OPT_LIBS), $(OPT_LIBS))" >> $@ + $(ECHO) "DYN_ALL_BATCH_CMX=$(addprefix $(FRAMAC_TOP_SRCDIR)/, $(ALL_BATCH_CMX))" >> $@ + $(ECHO) "else" >> $@ +- $(ECHO) "DYN_BLINKFLAGS=$(filter-out $(INCLUDES), $(BLINKFLAGS))" >> $@ ++ $(ECHO) "DYN_BLINKFLAGS=$(filter-out $(INCLUDES), $(BLINKFLAGS)) -I +ocamlgraph" >> $@ + $(ECHO) "DYN_GEN_BYTE_LIBS=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(GEN_BYTE_LIBS)))" >> $@ + $(ECHO) "DYN_BYTE_LIBS=$(filter-out $(GEN_BYTE_LIBS), $(BYTE_LIBS))" >> $@ + $(ECHO) "DYN_ALL_BATCH_CMO=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(ALL_BATCH_CMO)))" >> $@ +- $(ECHO) "DYN_OLINKFLAGS=$(filter-out $(INCLUDES), $(OLINKFLAGS))" >> $@ ++ $(ECHO) "DYN_OLINKFLAGS=$(filter-out $(INCLUDES), $(OLINKFLAGS)) -I +ocamlgraph" >> $@ + $(ECHO) "DYN_GEN_OPT_LIBS=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(GEN_OPT_LIBS)))" >> $@ + $(ECHO) "DYN_OPT_LIBS=$(filter-out $(GEN_OPT_LIBS), $(OPT_LIBS))" >> $@ + $(ECHO) "DYN_ALL_BATCH_CMX=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(ALL_BATCH_CMX)))" >> $@ +-- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0001-Value-Analysis-Carbon-patchlevel-1.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0001-Value-Analysis-Carbon-patchlevel-1.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0001-Value-Analysis-Carbon-patchlevel-1.patch 2011-04-25 10:03:11.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0001-Value-Analysis-Carbon-patchlevel-1.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,2014 +0,0 @@ -From: Mehdi Dogguy -Date: Fri, 15 Apr 2011 22:36:09 +0200 -Subject: Value Analysis Carbon patchlevel 1 - ---- - src/ai/abstract_interp.ml | 8 +- - src/ai/abstract_interp.mli | 4 + - src/ai/ival.ml | 332 ++++++++++++++++---------- - src/ai/ival.mli | 5 +- - src/ai/lattice_With_Isotropy.mli | 2 +- - src/memory_state/cvalue_type.ml | 173 ++++++++++++-- - src/memory_state/hptset.ml | 6 +- - src/memory_state/hptset.mli | 4 +- - src/memory_state/lmap.ml | 2 +- - src/memory_state/locations.ml | 31 ++- - src/memory_state/locations.mli | 3 +- - src/memory_state/offsetmap.ml | 76 +++---- - src/memory_state/offsetmap.mli | 2 +- - src/value/builtins.ml | 6 + - src/value/current_table.ml | 22 ++- - src/value/eval.ml | 479 ++++++++++++++++++++++---------------- - 16 files changed, 722 insertions(+), 433 deletions(-) - -diff --git a/src/ai/abstract_interp.ml b/src/ai/abstract_interp.ml -index 9452a63..fb37898 100644 ---- a/src/ai/abstract_interp.ml -+++ b/src/ai/abstract_interp.ml -@@ -652,7 +652,7 @@ module Make_Lattice_Interval_Set (V:Arithmetic_Value) = struct - s - end - -- let widen _wh t1 t2 = (if equal t1 t2 then t1 else top) -+ let widen _wh t1 t2 = if equal t1 t2 then t1 else top - - let meet v1 v2 = - if v1 == v2 then v1 else -@@ -1007,7 +1007,11 @@ module Int = struct - *) - let of_int64 i = big_int_of_string (Int64.to_string i) - let to_int64 i = Int64.of_string (string_of_big_int i) -- -+ let max_int64 = of_int64 Int64.max_int -+ let min_int64 = of_int64 Int64.min_int -+ let bits_of_max_float = of_int64 (Int64.bits_of_float max_float) -+ let bits_of_most_negative_float = -+ of_int64 (Int64.bits_of_float (-. max_float)) - - let of_string = big_int_of_string - let to_string = string_of_big_int -diff --git a/src/ai/abstract_interp.mli b/src/ai/abstract_interp.mli -index 69b72e4..a68e0b7 100644 ---- a/src/ai/abstract_interp.mli -+++ b/src/ai/abstract_interp.mli -@@ -197,6 +197,10 @@ module Int : sig - val of_int : int -> t - val of_int64 : int64 -> t - val to_int64 : t -> int64 -+ val max_int64 : t -+ val min_int64 : t -+ val bits_of_max_float : t -+ val bits_of_most_negative_float : t - val of_string : string -> t - val to_string : t -> string - val to_float : t -> float -diff --git a/src/ai/ival.ml b/src/ai/ival.ml -index 57e550c..32c967c 100644 ---- a/src/ai/ival.ml -+++ b/src/ai/ival.ml -@@ -43,12 +43,30 @@ module F = struct - let structural_descr = Structural_descr.t_float - let packed_descr = Structural_descr.p_float - -+ -+ let compare f1 f2 = -+ let i1 = Int64.bits_of_float f1 in -+ let i2 = Int64.bits_of_float f2 in -+ let m1 = (Int64.logand i1 Int64.min_int) in -+ let m2 = (Int64.logand i2 Int64.min_int) in -+ let i1 = if m1 <> 0L then Int64.logxor i1 Int64.max_int else i1 in -+ let i2 = if m2 <> 0L then Int64.logxor i2 Int64.max_int else i2 in -+ Pervasives.compare i1 i2 -+ -+ let equal f1 f2 = compare f1 f2 = 0 -+ -+ let zero = 0.0 -+ -+ let is_zero f = equal zero f -+ - type integer = Int.t - exception Nan_or_infinite - exception Too_small - -- let max_single_precision_float = 3.4028234663852886e38 -+ let max_single_precision_float = Int32.float_of_bits 0x7f7fffffl - let most_negative_single_precision_float = -. max_single_precision_float -+ let min_single_precision_float = Int32.float_of_bits 0x800000l -+ let neg_min_single_precision_float = -. min_single_precision_float - let max_float = max_float - let infinity = infinity - let neg_infinity = neg_infinity -@@ -84,8 +102,7 @@ module F = struct - let le_ieee = ((<=) : float -> float -> bool) - let lt_ieee = ((<) : float -> float -> bool) - -- let zero = 0.0 -- let is_zero_ieee = (=) zero -+ let is_zero_ieee x = x = zero - - let minus_zero = -0.0 - -@@ -149,13 +166,6 @@ module F = struct - let round_up = round Int64.succ Int64.pred - let round_down = round Int64.pred Int64.succ - -- let equal f1 f2 = -- if f1 = zero && f2 = zero -- then (1. /. f1) = (1. /. f2) -- else f1 = f2 -- -- let is_zero f = f = zero && ((1. /. f) = infinity) -- - let le f1 f2 = - if f1 = zero && f2 = zero - then (1. /. f1) <= (1. /. f2) -@@ -167,71 +177,72 @@ module F = struct - let max f1 f2 = - if le f1 f2 then f2 else f1 - -- let compare : float -> float -> int = Extlib.compare_basic -- - let equal_ieee = ((=) : float -> float -> bool) - let double_norm = Int64.shift_left 1L 52 - let double_mask = Int64.pred double_norm - -- let pretty fmt f = -- let use_hex = Parameters.FloatHex.get() in -- if use_hex || (Parameters.FloatNormal.get ()) -- then -- let i = Int64.bits_of_float f in -- let s = 0L <> (Int64.logand Int64.min_int i) in -- let i = Int64.logand Int64.max_int i in -- let exp = Int64.to_int (Int64.shift_right_logical i 52) in -- let man = Int64.logand i double_mask in -- let firstdigit, exp = -- if exp <> 0 -- then 1, (exp - 1023) -- else 0, -1022 -- in -- if not use_hex -- then begin -- let firstdigit, man, exp = -- if 0 <= exp && exp <= 12 -- then begin -- Int64.to_int -- (Int64.shift_right_logical -- (Int64.logor man double_norm) -- (52 - exp)), -- Int64.logand (Int64.shift_left man exp) double_mask, -- 0 -- end -- else firstdigit, man, exp -- in -- let x2157 = Int64.mul man 2157L in -- let sx14 = Int64.shift_right_logical man 14 in -- let x2274 = Int64.mul man 2274L in -- let sx20 = Int64.shift_right_logical man 20 in -- let sx26 = Int64.shift_right_logical man 26 in -- let sx2157 = Int64.shift_right_logical x2157 13 in -- let p1 = Int64.sub sx14 sx20 in -- let p2 = Int64.sub x2274 sx2157 in -- let q = Int64.add p1 sx26 in -- let q = Int64.add q p2 in -- let decdigits = Int64.shift_right_logical q 10 -- in -- if exp = 0 -- then -+ let pretty_normal ~use_hex fmt f = -+ let i = Int64.bits_of_float f in -+ let s = 0L <> (Int64.logand Int64.min_int i) in -+ let i = Int64.logand Int64.max_int i in -+ let exp = Int64.to_int (Int64.shift_right_logical i 52) in -+ let man = Int64.logand i double_mask in -+ let firstdigit, exp = -+ if exp <> 0 -+ then 1, (exp - 1023) -+ else 0, -1022 -+ in -+ if not use_hex -+ then begin -+ let firstdigit, man, exp = -+ if 0 <= exp && exp <= 12 -+ then begin -+ Int64.to_int -+ (Int64.shift_right_logical -+ (Int64.logor man double_norm) -+ (52 - exp)), -+ Int64.logand (Int64.shift_left man exp) double_mask, -+ 0 -+ end -+ else firstdigit, man, exp -+ in -+ let x2157 = Int64.mul man 2157L in -+ let sx14 = Int64.shift_right_logical man 14 in -+ let x2274 = Int64.mul man 2274L in -+ let sx20 = Int64.shift_right_logical man 20 in -+ let sx26 = Int64.shift_right_logical man 26 in -+ let sx2157 = Int64.shift_right_logical x2157 13 in -+ let p1 = Int64.sub sx14 sx20 in -+ let p2 = Int64.sub x2274 sx2157 in -+ let q = Int64.add p1 sx26 in -+ let q = Int64.add q p2 in -+ let decdigits = Int64.shift_right_logical q 10 -+ in -+ if exp = 0 -+ then - Format.fprintf fmt "%s%d.%016Ld" - (if s then "-" else "") - firstdigit - decdigits -- else -+ else - Format.fprintf fmt "%s%d.%016Ld*2^%d" - (if s then "-" else "") - firstdigit - decdigits - exp -- end -- else -- Format.fprintf fmt "%s0x%d.%013Lxp%d" -- (if s then "-" else "") -- firstdigit -- man -- exp -+ end -+ else -+ Format.fprintf fmt "%s0x%d.%013Lxp%d" -+ (if s then "-" else "") -+ firstdigit -+ man -+ exp -+ -+ let pretty fmt f = -+ let use_hex = Parameters.FloatHex.get() in -+ if use_hex || (Parameters.FloatNormal.get ()) -+ then -+ pretty_normal ~use_hex fmt f - else begin - set_round_nearest_even(); - let r = Format.sprintf "%.*g" 12 f in -@@ -411,7 +422,8 @@ module Float_abstract = struct - - let contains_a_zero (I(b, e)) = F.le_ieee b F.zero && F.le_ieee F.zero e - -- let is_zero x = compare x zero = 0 -+ let is_zero f = -+ 0 = compare zero f - - let is_singleton (I(b, e)) = F.equal b e - -@@ -437,7 +449,12 @@ module Float_abstract = struct - FP_infinite -> true - | _ -> false - in -- let b = if min_inf then F.most_negative_single_precision_float else b -+ let b = -+ if min_inf -+ then F.most_negative_single_precision_float -+ else if F.lt_ieee F.zero b && F.lt_ieee b F.min_single_precision_float -+ then F.zero -+ else b - in - let max_inf = - match classify_float e with -@@ -445,8 +462,15 @@ module Float_abstract = struct - | _ -> false - in - if max_inf -- then true, inject b F.max_single_precision_float -- else min_inf, inject b e -+ then -+ true, inject b F.max_single_precision_float -+ else -+ let e = -+ if F.lt_ieee F.neg_min_single_precision_float e && F.lt_ieee e F.minus_zero -+ then F.minus_zero -+ else e -+ in -+ min_inf, inject b e - (* in - Format.printf "Casting double -> float %a -> %B %a@." - pretty _arg -@@ -590,13 +614,20 @@ module Float_abstract = struct - then inject e2 e1 - else f1 - -- let filter_le (I(b1, e1) as f1) (I(_b2, e2)) = -- let e2 = if F.equal_ieee F.zero e2 then F.zero else e2 in -- if not (F.le b1 e2) -- then raise Bottom -- else if F.le e1 e2 -- then f1 -- else inject b1 e2 -+ let filter_le (I(b1, e1) as f1) (I(_b2, e2) as _f2) = -+ let r = -+ let e2 = if F.equal_ieee F.zero e2 then F.zero else e2 in -+ if not (F.le b1 e2) -+ then raise Bottom -+ else if F.le e1 e2 -+ then f1 -+ else inject b1 e2 -+ in -+(* Format.printf "filter %a <= %a -> %a@." -+ pretty f1 -+ pretty _f2 -+ pretty r; *) -+ r - - let filter_lt allmodes ~typ_loc (I(b1, e1) as f1) (I(_b2, e2)) = - let e2 = -@@ -988,6 +1019,40 @@ let min_and_max t = - | Top (a,b,_,_) -> a, b - | Float _ -> None, None - -+exception Unforceable -+ -+let force_float kind i = -+ match i with -+ Float _ -> false, i -+ | Set _ when is_zero i -> false, i -+ | Top _ | Set _ -> -+ ( match kind with -+ Cil_types.FDouble -> -+ ( try -+ ( match min_and_max i with -+ Some mn, Some mx -> -+ let mn, mx = -+ if Int.le Int.zero mn && Int.le mx Int.bits_of_max_float -+ then mn, mx -+ else if Int.le Int.min_int64 mn && -+ Int.le mx Int.bits_of_most_negative_float -+ then mx, mn -+ else raise Unforceable -+ in -+ let red, fa = -+ Float_abstract.inject_r -+ (Int64.float_of_bits (Int.to_int64 mn)) -+ (Int64.float_of_bits (Int.to_int64 mx)) -+ in -+ assert (not red); -+ let f = inject_float fa in -+ (* Format.printf "cv: %a -> %a@." pretty i pretty f; *) -+ false, f -+ | _, _ -> true, top_float) -+ with Unforceable -> -+ true, top_float ) -+ | _ -> false, i) -+ - let compare_min_int t1 t2 = - let m1, _ = min_and_max t1 in - let m2, _ = min_and_max t2 in -@@ -998,64 +1063,64 @@ let compare_min_int t1 t2 = - | Some m1, Some m2 -> - Int.compare m1 m2 - --let compare_max_int t1 t2 = -- let _, m1 = min_and_max t1 in -- let _, m2 = min_and_max t2 in -- match m1, m2 with -- None, None -> 0 -- | None, Some _ -> 1 -- | Some _, None -> -1 -- | Some m1, Some m2 -> -- Int.compare m2 m1 -- --let compare_min_float t1 t2 = -- let f1 = project_float t1 in -- let f2 = project_float t2 in -- Float_abstract.compare_min f1 f2 -- --let compare_max_float t1 t2 = -- let f1 = project_float t1 in -- let f2 = project_float t2 in -- Float_abstract.compare_max f1 f2 -+ let compare_max_int t1 t2 = -+ let _, m1 = min_and_max t1 in -+ let _, m2 = min_and_max t2 in -+ match m1, m2 with -+ None, None -> 0 -+ | None, Some _ -> 1 -+ | Some _, None -> -1 -+ | Some m1, Some m2 -> -+ Int.compare m2 m1 -+ -+ let compare_min_float t1 t2 = -+ let f1 = project_float t1 in -+ let f2 = project_float t2 in -+ Float_abstract.compare_min f1 f2 - --let widen wh t1 t2 = -- if equal t1 t2 || cardinal_zero_or_one t1 then t2 -- else -- match t2 with -- Float f2 -> -- ( try -+ let compare_max_float t1 t2 = - let f1 = project_float t1 in -- if not (Float_abstract.is_included f1 f2) -- then assert false; -- Float (Float_abstract.widen f1 f2) -- with Float_abstract.Nan_or_infinite -> assert false) -- | Top _ | Set _ -> -- let (mn2,mx2,r2,m2) = min_max_r_mod t2 in -- let (mn1,mx1,r1,m1) = min_max_r_mod t1 in -- let new_mod = Int.pgcd (Int.pgcd m1 m2) (Int.abs (Int.sub r1 r2)) in -- let new_rem = Int.rem r1 new_mod in -- -- let new_min = if bound_compare mn1 mn2 = 0 then mn2 else -- match mn2 with -- | None -> None -- | Some mn2 -> -- try -- let v = Widen_Hints.nearest_elt_le mn2 wh -- in Some (Int.round_up_to_r ~r:new_rem ~modu:new_mod ~min:v) -- with Not_found -> None -- in -- let new_max = if bound_compare mx1 mx2 = 0 then mx2 else -- match mx2 with None -> None -- | Some mx2 -> -- try -- let v = Widen_Hints.nearest_elt_ge mx2 wh -- in Some (Int.round_down_to_r ~r:new_rem ~modu:new_mod ~max:v) -- with Not_found -> None -- in -- let result = inject_top new_min new_max new_rem new_mod in -- (*Format.printf "%a -- %a --> %a (thx to %a)@." -- pretty t1 pretty t2 pretty result -- Widen_Hints.pretty wh;*) -+ let f2 = project_float t2 in -+ Float_abstract.compare_max f1 f2 -+ -+ let widen wh t1 t2 = -+ if equal t1 t2 || cardinal_zero_or_one t1 then t2 -+ else -+ match t2 with -+ Float f2 -> -+ ( try -+ let f1 = project_float t1 in -+ if not (Float_abstract.is_included f1 f2) -+ then assert false; -+ Float (Float_abstract.widen f1 f2) -+ with Float_abstract.Nan_or_infinite -> assert false) -+ | Top _ | Set _ -> -+ let (mn2,mx2,r2,m2) = min_max_r_mod t2 in -+ let (mn1,mx1,r1,m1) = min_max_r_mod t1 in -+ let new_mod = Int.pgcd (Int.pgcd m1 m2) (Int.abs (Int.sub r1 r2)) in -+ let new_rem = Int.rem r1 new_mod in -+ -+ let new_min = if bound_compare mn1 mn2 = 0 then mn2 else -+ match mn2 with -+ | None -> None -+ | Some mn2 -> -+ try -+ let v = Widen_Hints.nearest_elt_le mn2 wh -+ in Some (Int.round_up_to_r ~r:new_rem ~modu:new_mod ~min:v) -+ with Not_found -> None -+ in -+ let new_max = if bound_compare mx1 mx2 = 0 then mx2 else -+ match mx2 with None -> None -+ | Some mx2 -> -+ try -+ let v = Widen_Hints.nearest_elt_ge mx2 wh -+ in Some (Int.round_down_to_r ~r:new_rem ~modu:new_mod ~max:v) -+ with Not_found -> None -+ in -+ let result = inject_top new_min new_max new_rem new_mod in -+ (*Format.printf "%a -- %a --> %a (thx to %a)@." -+ pretty t1 pretty t2 pretty result -+ Widen_Hints.pretty wh;*) - result - - -@@ -1170,6 +1235,8 @@ let narrow v1 v2 = - match v1, v2 with - Float _, Float _ | (Top _| Set _), (Top _ | Set _) -> - meet v1 v2 (* meet is exact *) -+ | Float f, s | s, Float f when is_zero s -> -+ inject_float (Float_abstract.meet f Float_abstract.zero) - | _ -> v1 - - let link _ = assert false -@@ -1990,7 +2057,12 @@ let filter_float filter v1 v2 = - Float_abstract.Nan_or_infinite -> v1 - | Float_abstract.Bottom -> bottom - --let filter_le_float = filter_float Float_abstract.filter_le -+let filter_le_float x1 x2 = -+ let r = filter_float Float_abstract.filter_le x1 x2 in -+(* Format.printf "ival filter: %a %a -> %a@." -+ pretty x1 pretty x2 pretty r; *) -+ r -+ - let filter_ge_float = filter_float Float_abstract.filter_ge - let filter_lt_float allmodes ~typ_loc = - filter_float (Float_abstract.filter_lt allmodes ~typ_loc) -diff --git a/src/ai/ival.mli b/src/ai/ival.mli -index 1ffeec7..0005378 100644 ---- a/src/ai/ival.mli -+++ b/src/ai/ival.mli -@@ -27,6 +27,9 @@ module F : sig - val of_float : float -> t - val to_float : t -> float - exception Nan_or_infinite -+ val equal : t -> t -> bool -+ val pretty : Format.formatter -> t -> unit -+ val pretty_normal : use_hex:bool -> Format.formatter -> t -> unit - end - - module Float_abstract : sig -@@ -253,7 +256,7 @@ val top_float : t - val top_single_precision_float : t - val project_float : t -> Float_abstract.t - (** @raise F.Nan_or_infinite when the float is Nan or infinite. *) -- -+val force_float: Cil_types.fkind -> t -> bool * t - val in_interval : - Abstract_interp.Int.t -> - Abstract_interp.Int.t option -> -diff --git a/src/ai/lattice_With_Isotropy.mli b/src/ai/lattice_With_Isotropy.mli -index b4c27b7..8042692 100644 ---- a/src/ai/lattice_With_Isotropy.mli -+++ b/src/ai/lattice_With_Isotropy.mli -@@ -63,7 +63,7 @@ module type S = sig - - val project : t -> Locations.Location_Bytes.t - -- val pretty_c_assert : string -> Int.t -> Format.formatter -> t -> unit -+ val pretty_c_assert : (unit -> unit) -> string -> int -> Format.formatter -> t -> unit - - end - -diff --git a/src/memory_state/cvalue_type.ml b/src/memory_state/cvalue_type.ml -index 31701ee..2a9c114 100644 ---- a/src/memory_state/cvalue_type.ml -+++ b/src/memory_state/cvalue_type.ml -@@ -31,10 +31,132 @@ module V = struct - - include Location_Bytes - -- let pretty_c_assert _lv _s _fmt _v = () -+ exception Not_based_on_null -+ -+ let project_ival m = -+ try -+ let k, v = find_lonely_key m in -+ if not (Base.is_null k) -+ then raise Not_based_on_null -+ else v -+ with Not_found -> raise Not_based_on_null -+ -+ let types = Hashtbl.create 7;; -+ -+ let pretty_int_range fmt print_ampamp typname lv v = -+ let v = project_ival v in -+ ( match Ival.min_and_max v with -+ Some mn, Some mx -> -+ if Int.equal mn mx -+ then begin -+ print_ampamp(); -+ Format.fprintf fmt "*(%s*)%s == %a" -+ typname -+ lv -+ Int.pretty mn -+ end -+ else begin -+ print_ampamp(); -+ Format.fprintf fmt "%a <= *(%s*)%s && *(%s*)%s <= %a" -+ Int.pretty mn -+ typname -+ lv -+ typname -+ lv -+ Int.pretty mx; -+ end -+ | _ -> ()) -+ -+ let pretty_float_range fmt print_ampamp typname lv v = -+ let use_hex = true in -+ let v = project_ival v in -+ let v = Ival.project_float v in -+ let mn, mx = Ival.Float_abstract.min_and_max_float v in -+ if Ival.F.equal mn mx -+ then begin -+ print_ampamp(); -+ Format.fprintf fmt "*(%s*)%s == %a" -+ typname -+ lv -+ (Ival.F.pretty_normal ~use_hex) mn -+ end -+ else begin -+ print_ampamp(); -+ Format.fprintf fmt "%a <= *(%s*)%s && *(%s*)%s <= %a" -+ (Ival.F.pretty_normal ~use_hex) mn -+ typname -+ lv -+ typname -+ lv -+ (Ival.F.pretty_normal ~use_hex) mx; -+ end -+ -+ let () = -+ Hashtbl.add types 1 -+ [inject_ival (Ival.inject_range -+ (Some Int.zero) (Some (Int.of_int 255))), -+ "unsigned char", pretty_int_range; -+ inject_ival (Ival.inject_range -+ (Some (Int.of_int (-128))) (Some (Int.of_int 127))), -+ "char", pretty_int_range]; -+ Hashtbl.add types 2 -+ [inject_ival (Ival.inject_range -+ (Some Int.zero) (Some (Int.of_int 65535))), -+ "unsigned short", pretty_int_range; -+ inject_ival (Ival.inject_range -+ (Some (Int.of_int (-32768))) (Some (Int.of_int 32767))), -+ "short", pretty_int_range]; -+ Hashtbl.add types 4 -+ [ top_float, -+ "float", pretty_float_range; -+ inject_ival (Ival.inject_range -+ (Some Int.zero) (Some (Int.of_string "4294967295"))), -+ "unsigned int", pretty_int_range; -+ inject_ival (Ival.inject_range -+ (Some (Int.of_string "-2147483648")) -+ (Some (Int.of_string "2147483647"))), -+ "int", pretty_int_range]; -+ Hashtbl.add types 8 -+ [ top_float, -+ "double", pretty_float_range]; -+ () -+ -+(* let is_first = ref true in -+ let next () = -+ if !is_first then begin -+ is_first:=false; -+ print_ampamp (); -+ Format.fprintf fmt " ( "; -+ end -+ else Format.fprintf fmt " || "; -+ in -+*) -+ -+ let pretty_c_assert print_ampamp lv s_bytes fmt v = -+ try -+ let candidate_types = Hashtbl.find types s_bytes in -+ let rec find_typ l = -+ match l with -+ [] -> () -+ | (range, _, _) :: t when not (is_included v range) -> -+ find_typ t -+ | (_range, typname, pr) :: _ -> -+ pr fmt print_ampamp typname lv v -+ -+ in -+ find_typ candidate_types -+ with Not_based_on_null -> () - - let project x = x - -+ let force_float kind v = -+ try -+ let i = project_ival v in -+ let f, fi = Ival.force_float kind i in -+ f, inject_ival (fi) -+ with Not_based_on_null -> -+ true, topify_arith_origin v -+ - let is_imprecise v = - match v with - | Top _ -> true -@@ -86,16 +208,6 @@ module V = struct - - let of_char c = inject_ival (Ival.of_int (Char.code c)) - -- exception Not_based_on_null -- -- let project_ival m = -- try -- let k, v = find_lonely_key m in -- if not (Base.is_null k) -- then raise Not_based_on_null -- else v -- with Not_found -> raise Not_based_on_null -- - let subdiv_float_interval v = - try - let v_ival = project_ival v in -@@ -514,9 +626,17 @@ module V = struct - then false, v - else true, topify_misaligned_read_origin v - -- let big_endian_merge_bits ~conflate_bottom:_ ~total_length ~length ~value ~offset acc = -- if equal acc bottom || equal value bottom -- then bottom -+ let big_endian_merge_bits ~conflate_bottom ~total_length ~length ~value ~offset acc = -+ if is_bottom acc || is_bottom value -+ then begin -+ if conflate_bottom -+ then -+ bottom -+ else -+ join -+ (topify_misaligned_read_origin acc) -+ (topify_misaligned_read_origin value) -+ end - else - let total_length_i = Int.of_int total_length in - assert (Int.le (Int.add length offset) total_length_i); -@@ -543,7 +663,7 @@ module V = struct - - let little_endian_merge_bits ~conflate_bottom ~total_length ~value - ~offset acc = -- if equal acc bottom || equal value bottom -+ if is_bottom acc || is_bottom value - then begin - if conflate_bottom - then -@@ -839,16 +959,17 @@ module V_Or_Uninitialized = struct - let singleton_zero = C_init_noesc (V.singleton_zero) - - let unspecify_escaping_locals is_local t = --(* -- {initialized = t.initialized; -- no_escaping_adr = false; -- v = V.remove_escaping_locals is_local (get_v t)} --*) - let flags = get_flags t in -- let flags = flags land mask_init in -- create flags (V.remove_escaping_locals is_local (get_v t)) -+ let flags = flags land mask_init -+ (* clear noesc flag *) -+ in -+ let locals, v = -+ V.remove_escaping_locals is_local (get_v t) -+ in -+ locals, create flags v - -- let pretty_c_assert _lv _s _fmt _v = () -+ let pretty_c_assert prampamp lv s fmt v = -+ V.pretty_c_assert prampamp lv s fmt (get_v v) - - end - -@@ -976,15 +1097,15 @@ module Model = struct - | Top -> Format.fprintf fmt "1"); - Format.fprintf fmt "@]" - -- let find_unspecified = find ~conflate_bottom:true -+ let find_unspecified = find ~conflate_bottom:false - - let find ~conflate_bottom ~with_alarms x y = - let v = find ~conflate_bottom ~with_alarms x y in - let v_v = V_Or_Uninitialized.get_v v in - let bottom = V.is_bottom v_v in - let flags = V_Or_Uninitialized.get_flags v in -- if conflate_bottom -- then begin -+ -+ (* distasteful FIXME *) if conflate_bottom then begin - if not (V_Or_Uninitialized.is_initialized flags) - then warn_uninitialized with_alarms; - if not (V_Or_Uninitialized.is_noesc flags) -diff --git a/src/memory_state/hptset.ml b/src/memory_state/hptset.ml -index 3a38e95..1fefd18 100644 ---- a/src/memory_state/hptset.ml -+++ b/src/memory_state/hptset.ml -@@ -39,7 +39,7 @@ module type S = sig - val for_all: (elt -> bool) -> t -> bool - val exists: (elt -> bool) -> t -> bool - val filter: (elt -> bool) -> t -> t --(* val partition: (elt -> bool) -> t -> t * t*) -+ val partition: (elt -> bool) -> t -> t * t - val cardinal: t -> int - val min_elt: t -> elt - (* val max_elt: t -> elt -@@ -105,6 +105,10 @@ module Make(X: Id_Datatype) = struct - - let filter f s = fold (fun x acc -> if f x then add x acc else acc) s empty - -+ let partition f s = -+ fold -+ (fun x (w, wo) -> if f x then add x w, wo else w, add x wo) s (empty, empty) -+ - let mem x s = try find x s; true with Not_found -> false - - let diff s1 s2 = -diff --git a/src/memory_state/hptset.mli b/src/memory_state/hptset.mli -index 2bdf358..a8fea7e 100644 ---- a/src/memory_state/hptset.mli -+++ b/src/memory_state/hptset.mli -@@ -101,14 +101,14 @@ module type S = sig - val filter: (elt -> bool) -> t -> t - (** [filter p s] returns the set of all elements in [s] - that satisfy predicate [p]. *) --(* -+ - val partition: (elt -> bool) -> t -> t * t - (** [partition p s] returns a pair of sets [(s1, s2)], where - [s1] is the set of all the elements of [s] that satisfy the - predicate [p], and [s2] is the set of all the elements of - [s] that do not satisfy [p]. *) - --*) -+ - val cardinal: t -> int - (** Return the number of elements of a set. *) - -diff --git a/src/memory_state/lmap.ml b/src/memory_state/lmap.ml -index 9648f03..5f15aa9 100644 ---- a/src/memory_state/lmap.ml -+++ b/src/memory_state/lmap.ml -@@ -645,7 +645,7 @@ struct - result - - --(* XXXXXXXXX bug with uninitialized values *) -+(* XXXXXXXXX bug with uninitialized values ? *) - let reduce_binding ~with_alarms initial_mem - ({loc=_loc ; size=_size } as l) v = - assert -diff --git a/src/memory_state/locations.ml b/src/memory_state/locations.ml -index 313a42e..f256970 100644 ---- a/src/memory_state/locations.ml -+++ b/src/memory_state/locations.ml -@@ -31,6 +31,7 @@ module Initial_Values = struct - [Base.null,Ival.zero_or_one]; - [Base.null,Ival.top]; - [Base.null,Ival.top_float]; -+ [Base.null,Ival.top_single_precision_float]; - [] ] - end - -@@ -213,20 +214,26 @@ module Location_Bytes = struct - (** TODO: merge with above function *) - let remove_escaping_locals is_local v = - match v with -- | Top (Top_Param.Top,_) -> v -+ | Top (Top_Param.Top as t,_) -> t, v - | Top (Top_Param.Set topparam,orig) -> -- inject_top_origin -- orig -- (Top_Param.O.filter -- (fun base -> not (is_local base)) -- topparam) -+ let locals, nonlocals = -+ Top_Param.O.partition -+ is_local -+ topparam -+ in -+ (Top_Param.inject locals), inject_top_origin orig nonlocals - | Map m -> -- Map (M.fold (fun base _ acc -> -- if is_local base then -- M.remove base acc -- else acc) -- m -- m) -+ let locals, clean_map = -+ M.fold -+ (fun base _ (locals, m as acc) -> -+ if is_local base -+ then -+ (Top_Param.O.add base locals), M.remove base m -+ else acc) -+ m -+ (Top_Param.O.empty, m) -+ in -+ (Top_Param.inject locals), Map clean_map - - let contains_addresses_of_any_locals = - let f base _offsets = Base.is_any_formal_or_local base in -diff --git a/src/memory_state/locations.mli b/src/memory_state/locations.mli -index a253c6a..c086d78 100644 ---- a/src/memory_state/locations.mli -+++ b/src/memory_state/locations.mli -@@ -57,6 +57,7 @@ module Location_Bytes : sig - Top_Param.widen_hint * (Base.t -> Ival.widen_hint) - - val top_float : t -+ val top_single_precision_float : t - val is_zero : t -> bool - val hash : t -> int - val zero_or_one : t -@@ -124,7 +125,7 @@ module Location_Bytes : sig - [is_local] returns [true] - *) - -- val remove_escaping_locals : (M.key -> bool) -> t -> t -+ val remove_escaping_locals : (M.key -> bool) -> t -> Top_Param.t * t - (** TODO: merge with above function - [remove_escaping_locals is_local v] removes from [v] information - associated with bases for which [is_local] returns [true]. -diff --git a/src/memory_state/offsetmap.ml b/src/memory_state/offsetmap.ml -index f8c6b0e..b452327 100644 ---- a/src/memory_state/offsetmap.ml -+++ b/src/memory_state/offsetmap.ml -@@ -113,7 +113,7 @@ module type S = sig - where one can read an address [b]+_ *) - val create_initial: v:y -> modu:Int.t -> t - val reduce_by_int_intervals: t -> Abstract_value.Int_Intervals.t -> t -- val top_stuff : (y -> bool) -> (y -> y) -> t -> t -+ val top_stuff : (y -> bool) -> (y -> 'a * y) -> ('a -> 'a -> 'a) -> 'a -> t -> 'a * t - val iter_contents : (y -> unit) -> t -> Int.t -> unit - (** Iter on the contents of offsetmap of given size *) - val fold : (Int.t * Int.t -> Int.t * Int.t * y -> 'a -> 'a) -> t -> 'a -> 'a -@@ -149,25 +149,7 @@ module Build(V:Lattice_With_Isotropy.S) = struct - - let shift s v = M.shift s v - -- let types = Hashtbl.create 7;; -- -- let () = -- Hashtbl.add types 1 "char"; -- Hashtbl.add types 2 "short"; -- Hashtbl.add types 4 "int"; -- Hashtbl.add types 8 "long long"; -- () -- - let pretty_c_assert_typ name _typ print_ampamp fmt offs = -- let is_first = ref true in -- let next () = -- if !is_first then begin -- is_first:=false; -- print_ampamp (); -- Format.fprintf fmt " ( "; -- end -- else Format.fprintf fmt " || "; -- in - let pretty_binding (bk,ek) (offst,modu,v) = - if Int.is_zero (Int.rem bk Int.eight) - && (Int.equal (Int.pos_rem bk modu) offst) -@@ -175,28 +157,28 @@ module Build(V:Lattice_With_Isotropy.S) = struct - let ek = Int.succ ek in - if Int.is_zero (Int.rem ek Int.eight) - then -- let s = Int.sub ek bk in -- if (V.is_isotropic v || Int.equal s modu) -- then -- let s_bytes = Int.div s Int.eight in -- let s_bytes = try Int.to_int s_bytes with _ -> assert false in -- try -- let typname = Hashtbl.find types s_bytes in -- let lv = -- Format.sprintf "*(%s *)((unsigned char*)&%s+%d)" -- typname -+ -+ let step = if V.is_isotropic v then 1 else (Int.to_int modu) / 8 in -+ let start = ref ((Int.to_int bk) / 8) in -+ let ek = Int.to_int ek in -+ let ek = ek / 8 in -+ while !start < ek do -+ let lv = -+ if !start = 0 -+ then -+ Format.sprintf "&%s" name -+ else -+ Format.sprintf "((unsigned char*)&%s+%d)" - name -- s_bytes -- in -- next(); -- V.pretty_c_assert lv s fmt v -- with Not_found -> () -- else () -+ !start -+ in -+ V.pretty_c_assert print_ampamp lv step fmt v; -+ start := !start + step -+ done; - else () - else () - in -- M.iter pretty_binding offs; -- if not !is_first then Format.fprintf fmt " ) " -+ M.iter pretty_binding offs - - let pretty_debug fmt m = - M.pretty -@@ -631,21 +613,22 @@ let reciprocal_image m base = - let result = add_if_not_default (new_bi,new_ei) new_vv cleaned_m in - result - -- let top_stuff f topify offsm = -+ let top_stuff f topify join_locals acc_locals offsm = - assert (not (is_empty offsm)); - M.fold -- (fun (_,_ as i) (r,m,v) acc -> -+ (fun (_,_ as i) (r,m,v) (acc_locals, acc_o as acc) -> - assert (Int.lt r m); - assert (Int.le Int.zero r); - assert (if V.is_isotropic v then Int.is_one m else true); - assert (not (V.equal V.top v)); - if f v - then -- let topified_v = topify v in -- add_internal i (r, m, topified_v) acc -+ let locals, topified_v = topify v in -+ (join_locals acc_locals locals), -+ add_internal i (r, m, topified_v) acc_o - else acc) - offsm -- offsm -+ (acc_locals, offsm) - - (* Highest level insertion. - [add (be, ei) v m] inserts [v] in [m] at interval [be,ei] assuming the -@@ -1820,7 +1803,7 @@ module Make(V:Lattice_With_Isotropy.S) = struct - - let empty = { v = M.empty; tag = 0 } - -- let pretty_c_assert_typ _ = assert false -+ let pretty_c_assert_typ s t f fmt v = M.pretty_c_assert_typ s t f fmt v.v - let pretty_typ t fmt v = M.pretty_typ t fmt v.v - let pretty fmt v = M.pretty fmt v.v - -@@ -2032,8 +2015,11 @@ module Make(V:Lattice_With_Isotropy.S) = struct - let reduce_by_int_intervals v a = - wrap (M.reduce_by_int_intervals v.v a) - -- let top_stuff condition topify om = -- wrap (M.top_stuff condition topify om.v) -+ let top_stuff condition topify join_locals acc_locals om = -+ let locals, r = -+ M.top_stuff condition topify join_locals acc_locals om.v -+ in -+ locals, wrap r - - let iter_contents f o size = - M.iter_contents f o.v size -diff --git a/src/memory_state/offsetmap.mli b/src/memory_state/offsetmap.mli -index 76b4880..0e338b4 100644 ---- a/src/memory_state/offsetmap.mli -+++ b/src/memory_state/offsetmap.mli -@@ -141,7 +141,7 @@ module type S = sig - - val reduce_by_int_intervals: t -> Abstract_value.Int_Intervals.t -> t - -- val top_stuff : (y -> bool) -> (y -> y) -> t -> t -+ val top_stuff : (y -> bool) -> (y -> 'a * y) -> ('a -> 'a -> 'a) -> 'a -> t -> 'a * t - - val iter_contents : (y -> unit) -> t -> Int.t -> unit - (** Iter on the contents of offsetmap of given size *) -diff --git a/src/value/builtins.ml b/src/value/builtins.ml -index b4a7561..8977502 100644 ---- a/src/value/builtins.ml -+++ b/src/value/builtins.ml -@@ -259,6 +259,12 @@ let frama_c_alloc_infinite state actuals = - - let () = register_builtin "Frama_C_alloc_infinite" frama_c_alloc_infinite - -+let frama_c_dump_assert state _actuals = -+ Value_parameters.result ~current:true "Frama_C_dump_assert_each called:@\n(%a)@\nEnd of Frama_C_dump_assert_each output" -+ Relations_type.Model.pretty_c_assert state; -+ None, state, Location_Bits.Top_Param.bottom -+ -+let () = register_builtin "Frama_C_dump_assert_each" frama_c_dump_assert - - let frama_c_memcpy state actuals = - try -diff --git a/src/value/current_table.ml b/src/value/current_table.ml -index 00afadc..ec5d703 100644 ---- a/src/value/current_table.ml -+++ b/src/value/current_table.ml -@@ -72,14 +72,20 @@ module Ki = Cil_datatype.Kinstr (* do not mask kinstr in src/value *) - - let update_and_tell_if_changed current_table kinstr d = - let record = find_current current_table kinstr in -- State_imp.merge_set_return_new d record.superposition -+ if Relations_type.Model.is_reachable record.widening_state -+ then -+ let j = State_set.join d in -+ if Relations_type.Model.is_included j record.widening_state -+ then State_set.empty -+ else State_set.singleton j -+ else -+ State_imp.merge_set_return_new d record.superposition - - - let update_widening_info current_table kinstr wcounter wstate = - let record = find_current current_table kinstr in - record.widening <- wcounter; -- record.widening_state <- wstate; -- record.superposition <- State_imp.singleton wstate -+ record.widening_state <- wstate - - let merge_db_table hash_states = - let treat_instr k sum = -@@ -116,10 +122,16 @@ module Ki = Cil_datatype.Kinstr (* do not mask kinstr in src/value *) - Ki.Hashtbl.iter - (fun k record -> - Ki.Hashtbl.add r k -- (State_imp.join_dropping_relations record.superposition)) -+ (Relations_type.Model.join -+ (State_imp.join_dropping_relations record.superposition) -+ (Relations_type.Model.drop_relations record.widening_state))) - current_table; - r - - - let find_superposition current_table s = -- (find_current current_table s).superposition -+ let record = find_current current_table s in -+ let s = State_imp.to_set record.superposition in -+ if Relations_type.Model.is_reachable record.widening_state -+ then State_set.add record.widening_state s -+ else s -diff --git a/src/value/eval.ml b/src/value/eval.ml -index 69d4907..25b65cc 100644 ---- a/src/value/eval.ml -+++ b/src/value/eval.ml -@@ -145,7 +145,9 @@ end - - module PtrRelational = struct - type state = Relations_type.Model.t -- let eval_expr ~with_alarms state expr = match expr.enode with -+ let eval_expr ~with_alarms state expr = -+ let top = Cvalue_type.V.top in -+ match expr.enode with - | BinOp ((MinusA | MinusPP | Eq | Ne | Ge | Le | Gt | Lt as op),e1,e2,_) -> - let state, ev1 = !Db.Value.eval_expr_with_state ~with_alarms state e1 in - let state, ev2 = !Db.Value.eval_expr_with_state ~with_alarms state e2 in -@@ -153,7 +155,7 @@ module PtrRelational = struct - begin - match unrollType (typeOf e1) with - | TFloat _ -> -- state,Cvalue_type.V.top -+ state, top - | TInt _ | TPtr (_, _) | _ (* Enum ? *) -> - let compute_diff acc = - let lv1 = !Db.Value.find_lv_plus ~with_alarms state e1 in -@@ -180,9 +182,9 @@ module PtrRelational = struct - lv1 - in - match op with -- | MinusA -> state,compute_diff Cvalue_type.V.top -+ | MinusA -> state,compute_diff top - | MinusPP -> -- let minus_val = compute_diff Cvalue_type.V.top in -+ let minus_val = compute_diff top in - let r = - try - let size = Int_Base.project -@@ -233,10 +235,10 @@ module PtrRelational = struct - in - state, r - -- | _ -> state,Cvalue_type.V.top -+ | _ -> state,top - - end -- | _ -> state,Cvalue_type.V.top -+ | _ -> state,top - end - - -@@ -303,21 +305,45 @@ module Non_linear_assignments = - let pretty_current_cfunction_name fmt = - Kernel_function.pretty_name fmt (current_kf()) - -+let warning_once_current fmt = -+ Value_parameters.warning ~current:true ~once:true fmt -+ - exception Offset_not_based_on_Null of - Locations.Zone.t option * Location_Bytes.t - --let warn_locals_escape is_block fundec k = -- (*TODO: find a better alarm for variables escaping block scope *) -- Value_parameters.warning ~current:true ~once:true -- "local escaping the scope of %t%a through %a" -- (swap (Pretty_utils.pp_cond is_block) "a block of ") -- !d_var fundec.svar -- Base.pretty k -- --let warn_locals_escape_result fundec = -- Value_parameters.warning ~current:true ~once:true -- "local escaping the scope of %a through \\result" -- !d_var fundec.svar -+let warn_locals_escape is_block fundec k locals = -+ let pretty_base = Base.pretty in -+ let pretty_block = swap (Pretty_utils.pp_cond is_block) "a block of " in -+ let d_var = !d_var in -+ let sv = fundec.svar in -+ match locals with -+ Location_Bytes.Top_Param.Top -> -+ warning_once_current -+ "locals escaping the scope of %t%a through %a" -+ pretty_block -+ d_var sv -+ pretty_base k -+ | Location_Bytes.Top_Param.Set _ -> -+ warning_once_current -+ "locals %a escaping the scope of %t%a through %a" -+ Location_Bytes.Top_Param.pretty locals -+ pretty_block -+ d_var sv -+ pretty_base k -+ -+let warn_locals_escape_result fundec locals = -+ let d_var = !d_var in -+ let sv = fundec.svar in -+ match locals with -+ Location_Bytes.Top_Param.Top -> -+ warning_once_current -+ "locals escaping the scope of %a through \\result" -+ d_var sv -+ | Location_Bytes.Top_Param.Set _ -> -+ warning_once_current -+ "locals %a escaping the scope of %a through \\result" -+ Location_Bytes.Top_Param.pretty locals -+ d_var sv - - let do_cast ~with_alarms t expr = - let treat inttype = -@@ -329,14 +355,13 @@ let do_cast ~with_alarms t expr = - | TFloat (FFloat,_) -> - let addresses, overflow, res = V.cast_float expr in - if addresses -- then Value_parameters.warning ~current:true ~once:true -+ then warning_once_current - "addresses in float"; -- if overflow then Value_parameters.warning ~current:true ~once:true -+ if overflow then warning_once_current - "overflow in float: %a -> %a. assert(Ook)" - V.pretty expr V.pretty res; - res -- | TFloat (FDouble,_) -> -- expr -+ | TFloat (FDouble,_) - | TFloat (FLongDouble,_) -> - expr - | _ -> assert false -@@ -356,7 +381,7 @@ let do_cast ~with_alarms t expr = - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "cast to __builtin_va_list is not precisely implemented yet"); - V.topify_arith_origin expr - | TFun _ -> expr -@@ -376,13 +401,13 @@ let do_promotion ~with_alarms ~src_typ ~dest_type v e_src = - in - if alarm_use_as_float - then begin -- Value_parameters.warning ~current:true ~once:true -+ warning_once_current - "converting %a to float: assert(Ook)" - !d_exp e_src; - end; - if alarm_overflow - then -- Value_parameters.warning ~current:true ~once:true -+ warning_once_current - "Overflow in cast of %a (%a) from floating-point to integer: assert(Ook)" - !d_exp e_src - Cvalue_type.V.pretty v; -@@ -861,7 +886,7 @@ and eval_BinOp ~with_alarms e deps state = - Ival.project_float v1 - with V.Not_based_on_null - | Ival.Float_abstract.Nan_or_infinite -> -- Value_parameters.warning ~current:true ~once:true -+ warning_once_current - "converting value to float: assert(Ook)"; - Ival.Float_abstract.top - in -@@ -871,7 +896,7 @@ and eval_BinOp ~with_alarms e deps state = - Ival.project_float v2 - with V.Not_based_on_null - | Ival.Float_abstract.Nan_or_infinite -> -- Value_parameters.warning ~current:true ~once:true -+ warning_once_current - "converting value to float: assert(Ook)"; - Ival.Float_abstract.top - in -@@ -933,7 +958,7 @@ and eval_BinOp ~with_alarms e deps state = - | _ -> raise V.Not_based_on_null - end - with V.Not_based_on_null | Ival.F.Nan_or_infinite -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "float operation on address."; - V.join - (V.topify_arith_origin ev1) -@@ -1205,7 +1230,7 @@ and eval_expr_with_deps_state - CilE.Aignore -> () - | CilE.Acall f -> f() - | CilE.Alog -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "converting address to float: assert(TODO)" - end; - V.topify_arith_origin expr -@@ -1214,7 +1239,7 @@ and eval_expr_with_deps_state - CilE.Aignore -> () - | CilE.Acall f -> f() - | CilE.Alog -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "converting value to float: assert (TODO)" - end; - V.top_float -@@ -1550,7 +1575,15 @@ and eval_lval ~conflate_bottom ~with_alarms deps state (base,offset as lv) = - result_from_main_memory - in - let result_inter = Cvalue_type.V.narrow result_from_main_memory result in -- state, deps, result_inter -+ let result_conv = -+(* match unrollType (Cil.typeOfLval lv) with -+ TFloat (FDouble|FFloat as kind, _) -> -+ let f, r = Cvalue_type.V.force_float kind result_inter in -+ if f then Format.printf "TODO: assert@."; -+ r -+ | _ -> *) result_inter -+ in -+ state, deps, result_conv - - and eval_offset ~reduce_valid_index ~with_alarms deps typ state offset = - match offset with -@@ -1717,10 +1750,6 @@ let rec eval_cond ~with_alarms state cond = - if Cvalue_type.V.has_sign_problems value_for_loc && - not (Cvalue_type.V.equal value_for_loc value_for_loc2) - then begin --(* Value_parameters.warning ~current:true "oh: %a %a %a@." -- Locations.pretty loc -- V.pretty value_for_loc -- V.pretty value_for_loc2; *) - raise Not_an_exact_loc; - end; - loc, value_for_loc2, typ -@@ -1733,7 +1762,7 @@ let rec eval_cond ~with_alarms state cond = - let eval_eq_ineq eval_symetric eval_antisymetric = - let loc1 = ref None in - let loc2 = ref None in -- let result1 = -+ let state = - try - let left_loc,value_for_loc,typ_loc = - eval_as_exact_loc state exp1 -@@ -1754,12 +1783,13 @@ let rec eval_cond ~with_alarms state cond = - Relations_type.Model.reduce_binding state left_loc v_asym - with Not_an_exact_loc -> state - in -- let result2 = try -+ let state = -+ try - let right_loc,value_for_loc,typ_loc = -- eval_as_exact_loc result1 exp2 -+ eval_as_exact_loc state exp2 - in - loc2 := Some right_loc; -- let cond_expr = eval_expr ~with_alarms result1 exp1 -+ let cond_expr = eval_expr ~with_alarms state exp1 - in - let v_sym = eval_symetric - cond.positive binop cond_expr value_for_loc -@@ -1774,20 +1804,20 @@ let rec eval_cond ~with_alarms state cond = - in - if V.equal v_asym V.bottom then raise Reduce_to_bottom; - if V.equal v_asym value_for_loc -- then result1 -+ then state - else -- Relations_type.Model.reduce_binding result1 right_loc v_asym -- with Not_an_exact_loc -> result1 -+ Relations_type.Model.reduce_binding state right_loc v_asym -+ with Not_an_exact_loc -> state - in -- let result3 = -+ let state = - begin match (cond.positive, binop), !loc1, !loc2 with - ((true,Eq)|(false, Ne)), Some(left_loc), Some(right_loc) -> - Relations_type.Model.reduce_equality -- result2 left_loc right_loc -- | _ -> result2 -+ state left_loc right_loc -+ | _ -> state - end - in -- result3 -+ state - in - let t1 = unrollType (typeOf exp1) in - if isIntegralType t1 || isPointerType t1 -@@ -1896,12 +1926,12 @@ let rec eval_cond ~with_alarms state cond = - state_value - with Not_found -> result - in -- let result1 = -+ let result = - invert_cond (get_influential_vars ~with_alarms result cond.exp) - in -- if not (Relations_type.Model.is_reachable result1) -+ if not (Relations_type.Model.is_reachable result) - then raise Reduce_to_bottom -- else result1 -+ else result - - exception Ignore - (* raised to completely ignore an instruction or statement *) -@@ -1917,15 +1947,15 @@ let resolv_func_vinfo ~with_alarms deps state funcexp = - (fun acc varid -> - match varid with - | Base.String (_,_) -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "Function pointer call at string position in memory: ignoring this particular value: assert(TODO)"; - acc - | Base.Null -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "Function pointer call at absolute position in memory: ignoring this particular value: assert(TODO)"; - acc - | Base.Cell_class _ -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "Function pointer call at memory cell class: ignoring this particular value: assert(TODO)"; - acc - | Base.Var (v,_) | Base.Initialized_Var (v,_) -> -@@ -1935,7 +1965,7 @@ let resolv_func_vinfo ~with_alarms deps state funcexp = - (try - Location_Bytes.get_keys_exclusive Ival.zero loc - with Location_Bytes.Not_all_keys -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "Function pointer call is completely unknown: assuming no effects: assert(TODO)"; - raise Leaf) - in -@@ -2024,13 +2054,25 @@ let initialize_var_using_type varinfo state = - state - loc - Cvalue_type.V.top_int -- | TFloat _ -> -+ | TFloat ((FDouble | FLongDouble as fkind), _) -> -+ if fkind = FLongDouble -+ then -+ Value_parameters.warning -+ ~once:true -+ "Warning: unsupported long double treated as double"; - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - Cvalue_type.V.top_float -+ | TFloat (FFloat, _) -> -+ Relations_type.Model.add_binding -+ ~with_alarms:CilE.warn_none_mode -+ ~exact:true -+ state -+ loc -+ Cvalue_type.V.top_single_precision_float - | TFun _ -> - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode -@@ -2300,12 +2342,12 @@ let initial_state_only_globals = - let compute () = - Value_parameters.debug ~level:2 "Computing globals values"; - let state = ref Relations_type.Model.empty_map in -- let complete_init last_bitsoffset typ _l lval = -- (* Now process the non initialized bits defaulting to 0 *) -+ let complete_init ~last_bitsoffset ~abs_offset typ _l lval = -+ (* process the non initialized bits defaulting to 0 *) - begin try - let size_to_add, offset = - bitsSizeOf typ - last_bitsoffset, -- Ival.inject_singleton (Int.of_int last_bitsoffset) -+ Ival.inject_singleton (Int.of_int abs_offset) - in - assert (size_to_add >= 0); - if size_to_add <> 0 then -@@ -2390,6 +2432,7 @@ let initial_state_only_globals = - ~doinit: - (fun off init typ (acc:int) -> - let o,w = bitsOffset base_typ off in -+ (* Format.printf "acc:%d o:%d w:%d@." acc o w; *) - if acc -+ bitsOffset vinfo.vtype abs_offset -+ | _ -> -+ Value_parameters.fatal "Whacky initializer?") -+ in -+ (* Format.printf "last_bitsoffset:%d base_off:%d@\nstate after:%a@." -+ last_bitsoffset -+ base_off -+ Relations_type.Model.pretty !state; *) -+ complete_init ~last_bitsoffset -+ ~abs_offset:(base_off+last_bitsoffset) -+ base_typ -+ l -+ lval - else () - in - Globals.Vars.iter -@@ -2437,7 +2496,8 @@ let initial_state_only_globals = - (* Must not assume zero when the storage is extern. *) - state := initialize_var_using_type varinfo !state - else -- complete_init 0 varinfo.vtype [] (Var varinfo,NoOffset) -+ complete_init ~last_bitsoffset:0 ~abs_offset:0 -+ varinfo.vtype [] (Var varinfo,NoOffset) - | Some i -> - eval_init (Var varinfo,NoOffset) i - end); -@@ -3198,14 +3258,14 @@ struct - then - let sum = - Relations_type.Model.join -- (State_set.join (new_.value)) -- (State_set.join (old.value)) -+ (State_set.join new_.value) -+ (State_set.join old.value) - in - Some {counter_unroll = old.counter_unroll ; -- value = (State_set.singleton sum);} -+ value = State_set.singleton sum;} - else begin try -- let merged = State_set.merge_into (new_.value) (old.value) in -- let length_new = State_set.length (new_.value) in -+ let merged = State_set.merge_into new_.value old.value in -+ let length_new = State_set.length new_.value in - let new_counter_unroll = old.counter_unroll + length_new in - if new_counter_unroll >= !counter_unroll_target - then begin -@@ -3328,38 +3388,32 @@ struct - let is_local_bytes = Location_Bytes.contains_addresses_of_locals is_local in - fun offsetmap -> - if Cvalue_type.V_Offsetmap.is_empty offsetmap -- then offsetmap, true -+ then Location_Bytes.Top_Param.top, offsetmap - else -- let found_locals = ref false in - let loc_contains_addresses_of_locals t = -- let l = -- is_local_bytes (Cvalue_type.V_Or_Uninitialized.get_v t) -- in -- found_locals := !found_locals -- || (l -- && (match Cvalue_type.V_Or_Uninitialized.get_v t with -- | Location_Bytes.Top (Location_Bytes.Top_Param.Top,_) -> false -- (* Do not be too verbose if the value is top. *) -- | _ -> true)); -- l -+ let v = Cvalue_type.V_Or_Uninitialized.get_v t in -+ is_local_bytes v - in -- let result = -+ let locals, result = - Cvalue_type.V_Offsetmap.top_stuff - loc_contains_addresses_of_locals - (fun v -> - Cvalue_type.V_Or_Uninitialized.unspecify_escaping_locals - is_local v) -+ Location_Bytes.Top_Param.join -+ Location_Bytes.Top_Param.bottom - offsetmap - in -- result, !found_locals -+ locals, result - - let state_top_addresses_of_locals ~is_block - offsetmap_top_addresses_of_locals fundec - = - let f k offsm = -- let r,found_locals = offsetmap_top_addresses_of_locals offsm in -+ let locals, r = offsetmap_top_addresses_of_locals offsm in -+ let found_locals = not (Cvalue_type.V_Offsetmap.equal r offsm) in - if found_locals then -- warn_locals_escape is_block fundec k; -+ warn_locals_escape is_block fundec k locals; - r - in - (fun (state:Relations_type.Model.t) -> -@@ -3382,9 +3436,10 @@ struct - with Location_Bits.Top_Param.Error_Top -> - begin - let f k offsm acc = -- let r,found_locals = offsetmap_top_addresses_of_locals offsm in -+ let locals, r = offsetmap_top_addresses_of_locals offsm in -+ let found_locals = not (Cvalue_type.V_Offsetmap.equal r offsm) in - if found_locals then -- warn_locals_escape is_block fundec k; -+ warn_locals_escape is_block fundec k locals; - Cvalue_type.Model.add_offsetmap k r acc - in - let result = -@@ -3413,7 +3468,7 @@ struct - offsetmap_top_addresses_of_locals fundec - in - offsetmap_top_addresses_of_locals, state_top_addresses_of_locals -- else (fun x -> x,false),(fun x -> x) -+ else (fun x -> Location_Bytes.Top_Param.bottom, x),(fun x -> x) - - let block_top_addresses_of_locals blocks = - if List.for_all (fun b -> List.for_all (fun v -> v.vgenerated) b.blocals) -@@ -3839,7 +3894,11 @@ struct - (fun e -> - let interpreted_expr, o = - match e with -- { enode = Lval l } -> -+ { enode = Lval l } when -+ (* make sure not a bitfield *) -+ (Int.to_int (Int_Base.project (Bit_utils.sizeof_lval l))) = -+ (bitsSizeOf (typeOfLval l)) -+ -> - let _, _, interpreted_expr = - eval_lval ~conflate_bottom:false ~with_alarms - None state l -@@ -3852,11 +3911,15 @@ struct - in - ignore (conf_expr); - end; -- if calling_all_library_functions && -- V.is_bottom interpreted_expr -+ if V.is_bottom interpreted_expr - then begin -- Value_parameters.result ~current:true -- "Non-termination in evaluation of library function call l-value argument"; -+ ignore (eval_lval ~conflate_bottom:true -+ ~with_alarms None state l); (* alarm *) -+ if calling_all_library_functions -+ then begin -+ Value_parameters.result ~current:true -+ "Non-termination in evaluation of library function call l-value argument"; -+ end; - raise Got_bottom; - end; - let r = do_cast ~with_alarms (typeOf e) interpreted_expr -@@ -3866,20 +3929,29 @@ struct - state - l - in -- r, out_some o -+ ( match o with -+ Some o -> r, o -+ | None -> -+ Format.printf "failure in evaluation of function arguments@\nlval %a -> %a@." -+ !d_lval l -+ V.pretty interpreted_expr; -+ assert false) - | _ -> - let interpreted_expr = - eval_expr ~with_alarms state e - in -- if V.equal interpreted_expr V.bottom -+ if V.is_bottom interpreted_expr - then begin - Value_parameters.result ~current:true - "Non-termination in evaluation of function call expression argument"; - raise Got_bottom - end; -+ let typ = Cil.typeOf e in -+(* Format.printf "expr arg: %a %a@." -+ !d_exp e -+ !d_type typ; *) - interpreted_expr, -- Builtins.offsetmap_of_value ~typ:(Cil.typeOf e) -- interpreted_expr -+ Builtins.offsetmap_of_value ~typ interpreted_expr - in - e,interpreted_expr,o) - argl -@@ -4001,7 +4073,7 @@ struct - | None -> - (if Relations_type.Model.is_reachable new_state - then -- Value_parameters.warning ~current:true -+ warning_once_current - "In function %t: called function returns void but returned value is assigned; ignoring assignment" - pretty_current_cfunction_name; - new_state) -@@ -4036,7 +4108,7 @@ struct - let doInstr stmt (i: instr) (d: t) = - !Db.progress (); - CilE.start_stmt (Kstmt stmt); -- let d_states = (d.value) in -+ let d_states = d.value in - let unreachable = State_set.is_empty d_states in - let result = - if unreachable then -@@ -4081,7 +4153,7 @@ struct - (interp_call stmt lval_to_assign funcexp argl d_states) - } - | Asm _ -> -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "assuming assembly code has no effects in function %t" - pretty_current_cfunction_name; - Dataflow.Default -@@ -4194,125 +4266,114 @@ struct - List.iter (fun x -> check_one_stmt x seq) seq - - let doStmt (s: stmt) (d: t) = -- let states = (d.value) in -+ let states = d.value in - d.value <- State_set.empty; - let kinstr = Kstmt s in - -- -- let not_already_states = -- Current_table.update_and_tell_if_changed -- current_table -- kinstr -- states -- in -- -- if State_set.is_empty not_already_states then -+ if State_set.is_empty states -+ then - Dataflow.SDefault -- else begin -- -- let annots_before, contract = -- Annotations.single_fold_stmt -- (fun a (before, spec as acc) -> match a with -- | Before -- (User { annot_content = AStmtSpec spec' } -- | AI (_,{annot_content = AStmtSpec spec' }) ) -- -> -- let spec = match spec with -- | None -> spec' -- | Some s -> Logic_utils.merge_funspec s spec'; s -- in -- (before, Some spec) -- | Before (AI (_, b) | User b) -> b :: before, spec -- | After _ -> acc) -- s -- ([], None) -- in -- -- CilE.start_stmt kinstr; -- let states = -- List.fold_left -- (fun states annot -> interp_annot states s annot) -- states -- annots_before -- in -- let states = -- match contract with -- Some spec -> -- check_preconditions (current_kf()) kinstr -- ~slevel "statement" states spec -- | None -> states -- in -- CilE.end_stmt (); -+ else -+ let annots_before, contract = -+ Annotations.single_fold_stmt -+ (fun a (before, spec as acc) -> match a with -+ | Before -+ (User { annot_content = AStmtSpec spec' } -+ | AI (_,{annot_content = AStmtSpec spec' }) ) -+ -> -+ let spec = match spec with -+ | None -> spec' -+ | Some s -> Logic_utils.merge_funspec s spec'; s -+ in -+ (before, Some spec) -+ | Before (AI (_, b) | User b) -> b :: before, spec -+ | After _ -> acc) -+ s -+ ([], None) -+ in -+ CilE.start_stmt kinstr; -+ let states = -+ List.fold_left -+ (fun states annot -> interp_annot states s annot) -+ states -+ annots_before -+ in -+ let states = -+ match contract with -+ Some spec -> -+ check_preconditions (current_kf()) kinstr -+ ~slevel "statement" states spec -+ | None -> states -+ in -+ CilE.end_stmt (); - -+ let not_already_states = -+ Current_table.update_and_tell_if_changed -+ current_table -+ kinstr -+ states -+ in -+ if State_set.is_empty not_already_states -+ then Dataflow.SDefault -+ else - let curr_wcounter, curr_wstate = - Current_table.find_widening_info current_table kinstr in - let d = - if d.counter_unroll >= AnalysisParam.slevel -- then begin -- let state = State_set.join states in -- let joined = -- Relations_type.Model.join -+ then -+ let state = State_set.join states in -+ let joined = Relations_type.Model.join curr_wstate state in -+ let r = -+ if (AnalysisParam.is_natural_loop s) && -+ (curr_wcounter = 0) -+ then -+ let wh_key_set, wh_hints = getWidenHints s in -+ let widen_hints = -+ true, wh_key_set(* no longer used thanks to 0/1 widening*), -+ wh_hints -+ in -+ let _,result = Relations_type.Model.widen -+ widen_hints - curr_wstate -- state -- in -- let r = -- if (AnalysisParam.is_natural_loop s) && -- (curr_wcounter = 0) -- then -- let wh_key_set, wh_hints = getWidenHints s in -- let widen_hints = -- true, wh_key_set(* no longer used thanks to 0/1 widening*), -- wh_hints -- in -- let _,result = Relations_type.Model.widen -- widen_hints -- curr_wstate -- joined -- in -- result -- else - joined -- in -- let new_widening = -- if curr_wcounter = 0 -- then 1 -- else pred curr_wcounter -- in -- Current_table.update_widening_info -- current_table -- kinstr -- new_widening -- r; -- { -- counter_unroll = d.counter_unroll; -- value = (State_set.singleton r); -- } -- -- end -+ in -+ result -+ else -+ joined -+ in -+ let new_widening = -+ if curr_wcounter = 0 -+ then 1 -+ else pred curr_wcounter -+ in -+ Current_table.update_widening_info -+ current_table -+ kinstr -+ new_widening -+ r; -+ { -+ counter_unroll = d.counter_unroll; -+ value = (State_set.singleton r); -+ } - else { d with value = states } - in -- -- match s.skind with -- | Return _ -> -- Dataflow.SUse d -+ ( match s.skind with - | Loop _ -> - if d.counter_unroll >= AnalysisParam.slevel - then -- Value_parameters.result ~once:true ~current:true -- "entering loop for the first time"; -- Dataflow.SUse d -+ Value_parameters.result ~once:true ~current:true -+ "entering loop for the first time" - | UnspecifiedSequence seq -> - CilE.start_stmt kinstr; - State_set.iter -- (fun state -> check_unspecified_sequence state seq) states; -- CilE.end_stmt (); -- Dataflow.SUse d -- | _ -> Dataflow.SUse d -- end -+ (fun state -> check_unspecified_sequence state seq) states; -+ CilE.end_stmt () -+ | _ -> ()); -+ Dataflow.SUse d - - let doEdge s succ d = - let kinstr = Kstmt s in -- let states = (d.value) in -+ let states = d.value in - (* Check if there are some after-annotations to verify *) - let annots_after, _specs = - Annotations.single_fold_stmt -@@ -4411,9 +4472,9 @@ struct - | _ -> None - in - check_fct_postconditions ~result -- kf -- (State_imp.to_set init_state) -- (State_imp.to_set superpos) -+ kf -+ init_state -+ superpos - Normal - in - let state = State_set.join_dropping_relations superpos in -@@ -4437,16 +4498,16 @@ struct - (match ret_val with - | None -> ret_val - | Some ret_val -> -- let r,warn = offsetmap_top_addresses_of_locals ret_val -+ let locals, r = offsetmap_top_addresses_of_locals ret_val in -+ let warn = not (Cvalue_type.V_Offsetmap.equal r ret_val) - in -- if warn then warn_locals_escape_result fundec; -+ if warn then warn_locals_escape_result fundec locals; - Some r), - state_top_addresses_of_locals state, - !bases_containing_locals - in - result - -- - let doGuardOneCond stmt exp t = - if State_set.is_empty (t.value) - then Dataflow.GUnreachable -@@ -4643,14 +4704,21 @@ let compute_using_cfg kf ~call_kinstr initial_state = - then begin - if Value_parameters.IgnoreRecursiveCalls.get() - then begin -- Value_parameters.warning ~current:true ~once:true -+ warning_once_current - "ignoring recursive call during value analysis of %a (%a)" - Ast_info.pretty_vname f_varinfo - pretty_call_stack (call_stack ()); -+(* Db.Value.recursive_call_occurred kf; *) - raise Leaf - end -- else -+ else begin -+ warning_once_current -+ "@[recursive call@ during@ value@ analysis@ (%a <- %a)@.Use %s@ to@ ignore@ (beware@ this@ will@ make@ the analysis@ unsound)@]" -+ Ast_info.pretty_vname f_varinfo -+ pretty_call_stack (call_stack ()) -+ Value_parameters.IgnoreRecursiveCalls.option_name; - raise (Extlib.NotYetImplemented "recursive calls in value analysis") -+ end - end) - (call_stack ()); - push_call_stack {called_kf = kf; -@@ -4688,7 +4756,7 @@ let compute_using_cfg kf ~call_kinstr initial_state = - try - if hasAttribute "noreturn" f_varinfo.vattr - then -- Value_parameters.warning ~current:true ~once:true -+ warning_once_current - "function %a may terminate but has the noreturn attribute" - Kernel_function.pretty_name kf; - with Not_found -> assert false -@@ -4822,7 +4890,8 @@ let compute_using_prototype kf ~state_with_formals = - let clobbered_set = ref Location_Bits.Top_Param.bottom in - let state = - match assigns with -- | WritesAny -> Value_parameters.warning "Cannot handle empty assigns clause. Assuming assigns \\nothing: be aware this is probably incorrect."; -+ | WritesAny -> -+ warning_once_current "Cannot handle empty assigns clause. Assuming assigns \\nothing: be aware this is probably incorrect."; - state_with_formals - | Writes [] -> state_with_formals - | Writes l -> -@@ -4928,7 +4997,7 @@ let compute_using_prototype kf ~state_with_formals = - !returned_value; - acc - end else begin -- Value_parameters.warning ~once:true ~current:true -+ warning_once_current - "Can not interpret assigns in function %a; \ - effects will be ignored" - Kernel_function.pretty_name kf; acc --- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0002-Accept-ocamlgraph-1.8.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0002-Accept-ocamlgraph-1.8.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0002-Accept-ocamlgraph-1.8.patch 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0002-Accept-ocamlgraph-1.8.patch 2012-01-06 08:30:25.000000000 +0000 @@ -0,0 +1,36 @@ +From: Stephane Glondu +Date: Sat, 3 Dec 2011 17:58:39 +0100 +Subject: Accept ocamlgraph 1.8* + +--- + configure | 2 +- + configure.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure b/configure +index aecf0e1..9b31779 100755 +--- a/configure ++++ b/configure +@@ -3122,7 +3122,7 @@ if test "$OCAMLGRAPH_EXISTS" = "yes"; then + then + OCAMLGRAPH_VERSION=`./test_ocamlgraph` + case $OCAMLGRAPH_VERSION in +- 1.8) { $as_echo "$as_me:${as_lineno-$LINENO}: OcamlGraph $OCAMLGRAPH_VERSION found: great!" >&5 ++ 1.8*) { $as_echo "$as_me:${as_lineno-$LINENO}: OcamlGraph $OCAMLGRAPH_VERSION found: great!" >&5 + $as_echo "$as_me: OcamlGraph $OCAMLGRAPH_VERSION found: great!" >&6;};; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: OcamlGraph $OCAMLGRAPH_VERSION is incompatible with Frama-C." >&5 + $as_echo "$as_me: OcamlGraph $OCAMLGRAPH_VERSION is incompatible with Frama-C." >&6;} +diff --git a/configure.in b/configure.in +index e2ecfe0..abb6c11 100644 +--- a/configure.in ++++ b/configure.in +@@ -240,7 +240,7 @@ if test "$OCAMLGRAPH_EXISTS" = "yes"; then + then + OCAMLGRAPH_VERSION=`./test_ocamlgraph` + case $OCAMLGRAPH_VERSION in +- 1.8) AC_MSG_NOTICE([OcamlGraph $OCAMLGRAPH_VERSION found: great!]);; ++ 1.8*) AC_MSG_NOTICE([OcamlGraph $OCAMLGRAPH_VERSION found: great!]);; + *) AC_MSG_NOTICE([OcamlGraph $OCAMLGRAPH_VERSION is incompatible with Frama-C.]) + OCAMLGRAPH_EXISTS=no + OCAMLGRAPH_INCLUDE=;; +-- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0002-Fix-for-issue-727.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0002-Fix-for-issue-727.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0002-Fix-for-issue-727.patch 2011-04-25 10:03:11.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0002-Fix-for-issue-727.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -From: Mehdi Dogguy -Date: Sat, 23 Apr 2011 18:39:43 +0200 -Subject: Fix for issue 727 - ---- - src/kernel/visitor.ml | 26 ++++++++++++++++++-------- - 1 files changed, 18 insertions(+), 8 deletions(-) - -diff --git a/src/kernel/visitor.ml b/src/kernel/visitor.ml -index 5c6f69f..d09774e 100644 ---- a/src/kernel/visitor.ml -+++ b/src/kernel/visitor.ml -@@ -178,30 +178,38 @@ object(self) - self#get_filling_actions - end - in -- let post_action stmt = change_stmt stmt (make_children_annot self); stmt in -+ let post_action f stmt = -+ let annots = make_children_annot self in -+ let stmt = f stmt in -+ change_stmt stmt annots; stmt -+ in - let copy stmt = - change_stmt stmt - (make_children_annot self#frama_c_plain_copy); stmt - in -+ let plain_post = post_action (fun x -> x) in - match res with - | SkipChildren -> res - | JustCopy -> JustCopyPost copy - | JustCopyPost f -> JustCopyPost (f $ copy) -- | DoChildren -> ChangeDoChildrenPost (stmt, post_action) -+ | DoChildren -> ChangeDoChildrenPost (stmt, plain_post) - | ChangeTo _ | ChangeToPost _ -> res - | ChangeDoChildrenPost (stmt,f) -> -- ChangeDoChildrenPost (stmt, f $ post_action) -+ ChangeDoChildrenPost (stmt, post_action f) - - method vstmt_aux _ = DoChildren - method vglob_aux _ = DoChildren - - method vglob g = -- let has_kf = -+ let fundec, has_kf = - match g with - GVarDecl(_,v,_) when isFunctionType v.vtype -> -- self#set_current_kf (Globals.Functions.get v); true -- | GFun(f,_) -> self#set_current_kf (Globals.Functions.get f.svar); true -- | _ -> false -+ self#set_current_kf (Globals.Functions.get v); -+ None, true -+ | GFun(f,_) -> -+ self#set_current_kf (Globals.Functions.get f.svar); -+ Some f, true -+ | _ -> None, false - in - let res = self#vglob_aux g in - let make_funspec () = -@@ -283,8 +291,10 @@ object(self) - in - let post_action g = - let spec = lazy (make_funspec ()) in -+ Extlib.may self#set_current_func fundec; - List.iter (fun g -> change_glob g (Lazy.force spec)) g; - if has_kf then self#reset_current_kf(); -+ Extlib.may (fun _ -> self#reset_current_func ()) fundec; - g - in - match res with -@@ -299,7 +309,7 @@ object(self) - if has_kf then self#reset_current_kf(); - res - | ChangeToPost (l,f) -> ChangeToPost (l, f $ post_action) -- | ChangeDoChildrenPost (g,f) -> ChangeDoChildrenPost (g, f $ post_action) -+ | ChangeDoChildrenPost (g,f) -> ChangeDoChildrenPost (g, post_action $ f) - end - - class frama_c_copy prj = generic_frama_c_visitor prj (copy_visit ()) --- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0003-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0003-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0003-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch 2011-04-25 10:03:11.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0003-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -From: Mehdi Dogguy -Date: Mon, 25 Apr 2011 12:01:09 +0200 -Subject: Add +ocamlgraph to DYN_{O,B}LINKFLAGS - ---- - Makefile | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index 4c90b5d..77989e0 100644 ---- a/Makefile -+++ b/Makefile -@@ -1215,11 +1215,11 @@ share/Makefile.kernel: Makefile share/Makefile.config share/Makefile.common - $(ECHO) "DYN_OPT_LIBS=$(filter-out $(GEN_OPT_LIBS), $(OPT_LIBS))" >> $@ - $(ECHO) "DYN_ALL_BATCH_CMX=$(addprefix $(FRAMAC_TOP_SRCDIR)/, $(ALL_BATCH_CMX))" >> $@ - $(ECHO) "else" >> $@ -- $(ECHO) "DYN_BLINKFLAGS=$(filter-out $(INCLUDES), $(BLINKFLAGS))" >> $@ -+ $(ECHO) "DYN_BLINKFLAGS=$(filter-out $(INCLUDES), $(BLINKFLAGS)) -I +ocamlgraph" >> $@ - $(ECHO) "DYN_GEN_BYTE_LIBS=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(GEN_BYTE_LIBS)))" >> $@ - $(ECHO) "DYN_BYTE_LIBS=$(filter-out $(GEN_BYTE_LIBS), $(BYTE_LIBS))" >> $@ - $(ECHO) "DYN_ALL_BATCH_CMO=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(ALL_BATCH_CMO)))" >> $@ -- $(ECHO) "DYN_OLINKFLAGS=$(filter-out $(INCLUDES), $(OLINKFLAGS))" >> $@ -+ $(ECHO) "DYN_OLINKFLAGS=$(filter-out $(INCLUDES), $(OLINKFLAGS)) -I +ocamlgraph" >> $@ - $(ECHO) "DYN_GEN_OPT_LIBS=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(GEN_OPT_LIBS)))" >> $@ - $(ECHO) "DYN_OPT_LIBS=$(filter-out $(GEN_OPT_LIBS), $(OPT_LIBS))" >> $@ - $(ECHO) "DYN_ALL_BATCH_CMX=$(addprefix $(FRAMAC_LIBDIR)/, $(notdir $(ALL_BATCH_CMX)))" >> $@ --- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0003-Fix-spelling-error-in-binary.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0003-Fix-spelling-error-in-binary.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0003-Fix-spelling-error-in-binary.patch 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0003-Fix-spelling-error-in-binary.patch 2012-01-06 08:30:25.000000000 +0000 @@ -0,0 +1,171 @@ +From: Mehdi Dogguy +Date: Mon, 2 Jan 2012 14:36:52 +0100 +Subject: Fix spelling-error-in-binary + +--- + Changelog | 8 ++++---- + cil/src/cil.ml | 2 +- + cil/src/ext/cfg.mli | 2 +- + cil/src/frontc/cabs2cil.ml | 2 +- + cil/src/logic/logic_typing.ml | 6 +++--- + man/frama-c.1 | 2 +- + src/impact/register.ml | 4 ++-- + src/kernel/cmdline.mli | 2 +- + 8 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/Changelog b/Changelog +index e527189..909b359 100644 +--- a/Changelog ++++ b/Changelog +@@ -576,7 +576,7 @@ o* Cil [2010/12/20] Fixed bug #645. Ast_info.constant_expr, + mkAddrOrStartOf,mkString,parseInt,sizeOf] no longer use + an optional argument ?loc. It is now a non optional labeled + argument. Previous default value of loc was +- ~loc:Cil_datatype.Location.unkown which is most of the time ++ ~loc:Cil_datatype.Location.unknown which is most of the time + not accurate. + + ################################### +@@ -729,7 +729,7 @@ o Cil [2010/06/04] Support for custom extension in grammar of behaviors. + -* Cil [2010/05/31] Extended grammar of pragma lines. + o* Cil [2010/05/28] Fix bug #489: constant literal present in original + source are preserved in the AST. NB: this implies that they might +- be explicitely cast when an integer conversion occur. ++ be explicitly cast when an integer conversion occur. + -* Kernel [2010/05/28] Fixed bug in handling of -cpp-command + o! Cil [2010/05/21] Remove deprecated annotation_status of AAssert + in the AST +@@ -908,7 +908,7 @@ o! Kernel [2009/11/24] Use of global logic constants is now a + - Value [2009/11/24] Handling of behavior-specific assertions now + correct (albeit imprecise). + -! Kernel [2009/11/19] The journal is generated only if the GUI is +- crashing, or if the option -journal-enable is explicitely ++ crashing, or if the option -journal-enable is explicitly + set (fixed issue #!330). + +- Value [2009/11/19] New option -slevel-exclude f for fine-tuning + semantic unrolling. +@@ -1206,7 +1206,7 @@ o! Kernel [2009/01/23] File.pretty does not take anymore a formatter + -* Journal [2009/01/19] Fixed bug with -disable-journal and type with + no pretty-printer. + - Configure [2009/01/19] New option -with-all-static in order to +- statically link all plug-ins, except those explicitely ++ statically link all plug-ins, except those explicitly + specified as dynamic (bts #?430). + -* Journal [2009/01/19] Fixed bug in journalisation of non-functional values. + -* Makefile [2009/01/19] Fixed bug whenever all plug-ins should be static. +diff --git a/cil/src/cil.ml b/cil/src/cil.ml +index 8fb03a2..ea04622 100644 +--- a/cil/src/cil.ml ++++ b/cil/src/cil.ml +@@ -8880,7 +8880,7 @@ let rec mkCastT ~(e: exp) ~(oldt: typ) ~(newt: typ) = + (* Watch out for constants *) + match newt, e.enode with + (* In the case were we have a representation for the literal, +- add explicitely the cast. *) ++ add explicitly the cast. *) + TInt(newik, []), Const(CInt64(i, _, None)) -> kinteger64 ~loc newik i + | _ -> + new_exp +diff --git a/cil/src/ext/cfg.mli b/cil/src/ext/cfg.mli +index 1467255..f40ad47 100644 +--- a/cil/src/ext/cfg.mli ++++ b/cil/src/ext/cfg.mli +@@ -51,7 +51,7 @@ open Cil_types + (** Compute the CFG for an entire file, by calling cfgFun on each function. *) + val computeFileCFG: file -> unit + +-(** clear the sid (except when clear_id is explicitely set to false), ++(** clear the sid (except when clear_id is explicitly set to false), + succs, and preds fields of each statement. *) + val clearFileCFG: ?clear_id:bool -> file -> unit + +diff --git a/cil/src/frontc/cabs2cil.ml b/cil/src/frontc/cabs2cil.ml +index fabb198..a69c921 100644 +--- a/cil/src/frontc/cabs2cil.ml ++++ b/cil/src/frontc/cabs2cil.ml +@@ -2257,7 +2257,7 @@ let makeGlobalVarinfo (isadef: bool) (vi: varinfo) : varinfo * bool = + * local. This can happen when we declare an extern variable with + * global scope but we are in a local scope. *) + +- (* We lookup in the environement. If this is extern inline then the name ++ (* We lookup in the environment. If this is extern inline then the name + * was already changed to foo__extinline. We lookup with the old name *) + let lookupname = + if vi.vstorage = Static then +diff --git a/cil/src/logic/logic_typing.ml b/cil/src/logic/logic_typing.ml +index 88d686f..8f76da6 100644 +--- a/cil/src/logic/logic_typing.ml ++++ b/cil/src/logic/logic_typing.ml +@@ -1803,7 +1803,7 @@ struct + info.ctor_name + with Not_found -> + (* We have a global logic variable. It may depend on +- a single state (multiple labels need to be explicitely ++ a single state (multiple labels need to be explicitly + instantiated and are treated as PLapp below). + NB: for now, if we have a real function (with parameters + other than labels) and a label, +@@ -1832,7 +1832,7 @@ struct + Tapp(f,[l,curr],[]), typ + | _ -> + error loc +- "%s labels must be explicitely instantiated" x ++ "%s labels must be explicitly instantiated" x + in + match C.find_all_logic_functions x with + +@@ -2581,7 +2581,7 @@ struct + | [l] -> [l,find_current_label loc env] + | _ -> + error loc +- "%s labels must be explicitely instantiated" x ++ "%s labels must be explicitly instantiated" x + in + papp ~loc (info,labels,[]) + | Some _ -> boolean_to_predicate env p0 +diff --git a/man/frama-c.1 b/man/frama-c.1 +index 4c90286..7bfb92d 100644 +--- a/man/frama-c.1 ++++ b/man/frama-c.1 +@@ -356,7 +356,7 @@ removes break, continue and switch statement before analyses. Defaults to + no. + .TP + .B -then +-allows to compose analyzes: a first run of Frama-C will occur with the ++allows one to compose analyzes: a first run of Frama-C will occur with the + options before + .B -then + and a second run will be done with the options after +diff --git a/src/impact/register.ml b/src/impact/register.ml +index 42778b7..6b160a4 100644 +--- a/src/impact/register.ml ++++ b/src/impact/register.ml +@@ -41,12 +41,12 @@ let from_stmt s = + with + | Dynamic.Incompatible_type _ -> + error "versions of plug-ins `impact' and `Security_slicing' seem \ +-incompatible.\nCheck the environement variable FRAMAC_PLUGIN.\n\ ++incompatible.\nCheck the environment variable FRAMAC_PLUGIN.\n\ + Analysis discarded."; + [] + | Dynamic.Unbound_value _ -> + error "cannot access to plug-in `Security_slicing'.\n\ +-Are you sure that it is loaded? Check the environement variable \ ++Are you sure that it is loaded? Check the environment variable \ + FRAMAC_PLUGIN.\n\ + Analysis discarded."; + [] +diff --git a/src/kernel/cmdline.mli b/src/kernel/cmdline.mli +index 7bf4673..cb5cdb7 100644 +--- a/src/kernel/cmdline.mli ++++ b/src/kernel/cmdline.mli +@@ -274,7 +274,7 @@ val journal_enable: bool + (** @since Beryllium-20090601-beta1 *) + + val journal_isset: bool +- (** -journal-enable/disable explicitely set on the command line. ++ (** -journal-enable/disable explicitly set on the command line. + @since Boron-20100401 *) + + val journal_name: string +-- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0004-Use-bin-cp-instead-of-usr-bin-install.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0004-Use-bin-cp-instead-of-usr-bin-install.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0004-Use-bin-cp-instead-of-usr-bin-install.patch 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0004-Use-bin-cp-instead-of-usr-bin-install.patch 2012-01-06 08:30:25.000000000 +0000 @@ -0,0 +1,22 @@ +From: Mehdi Dogguy +Date: Mon, 2 Jan 2012 17:28:56 +0100 +Subject: Use /bin/cp instead of /usr/bin/install + +--- + share/Makefile.common | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/share/Makefile.common b/share/Makefile.common +index c9e8727..ce1a699 100644 +--- a/share/Makefile.common ++++ b/share/Makefile.common +@@ -138,7 +138,7 @@ CHMOD_RW= sh -c \ + 'for f in "$$@"; do \ + if test -e $$f; then chmod u+w $$f; fi \ + done' chmod_rw +-CP = /usr/bin/install ++CP = /bin/cp + ECHO = echo + MKDIR = mkdir -p + MV = mv +-- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0005-Disable-CHMOD_RO-invocations.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0005-Disable-CHMOD_RO-invocations.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0005-Disable-CHMOD_RO-invocations.patch 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0005-Disable-CHMOD_RO-invocations.patch 2012-01-06 08:30:25.000000000 +0000 @@ -0,0 +1,22 @@ +From: Mehdi Dogguy +Date: Tue, 3 Jan 2012 15:24:27 +0100 +Subject: Disable CHMOD_RO invocations + +--- + share/Makefile.common | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/share/Makefile.common b/share/Makefile.common +index ce1a699..1993cf1 100644 +--- a/share/Makefile.common ++++ b/share/Makefile.common +@@ -133,7 +133,7 @@ external_make = \ + + CAT = cat + CHMOD = chmod +-CHMOD_RO= chmod a-w ++CHMOD_RO= true + CHMOD_RW= sh -c \ + 'for f in "$$@"; do \ + if test -e $$f; then chmod u+w $$f; fi \ +-- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/0006-Patchlevel2-for-Nitrogen-20111001.patch frama-c-20111001+nitrogen+dfsg/debian/patches/0006-Patchlevel2-for-Nitrogen-20111001.patch --- frama-c-20110201+carbon+dfsg/debian/patches/0006-Patchlevel2-for-Nitrogen-20111001.patch 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/0006-Patchlevel2-for-Nitrogen-20111001.patch 2012-01-06 08:30:25.000000000 +0000 @@ -0,0 +1,323 @@ +From: Mehdi Dogguy +Date: Fri, 6 Jan 2012 09:30:22 +0100 +Subject: Patchlevel2 for Nitrogen 20111001 + +--- + Changelog | 21 ++++++++++++ + src/ai/base.ml | 6 ++- + src/from/from_register.ml | 3 +- + src/lib/rangemap.ml | 4 +- + src/memory_state/lmap.ml | 2 +- + src/value/eval_exprs.ml | 81 +++++++++++++++++++++++--------------------- + src/value/eval_exprs.mli | 1 + + src/value/eval_funs.ml | 4 ++- + src/value/eval_logic.ml | 11 +++++- + src/value/eval_stmts.ml | 15 +++++--- + 10 files changed, 95 insertions(+), 53 deletions(-) + +diff --git a/Changelog b/Changelog +index 909b359..e60a3ba 100644 +--- a/Changelog ++++ b/Changelog +@@ -12,6 +12,27 @@ + # '#?nnn' : OLD-BTS entry #nnn # + ############################################################################### + ++-* Value [2011/12/05] An alarm could be omitted on *p = lval; ++ when p could point into a read-only location such as a string ++ constant. Fixed. ++o* Value [2011/12/05] Fix option -absolute-valid-range being reset by ++ project copies. ++-* Value [2011/12/05] Fix wrong hash function, which could cause ++ memory overuse and worse. ++- Value [2011/10/25] Improve interpretation of ACSL annotations in ++ presence of typedefs. ++-* From [2011/10/21] The interpretation of explicit assigns clauses for ++ library function "assigns *p \from x;" was wrong: every possible ++ location was assumed to have been overwritten. ++- Value [2011/10/18] Improve evaluation of logic when option ++ -val-signed-overflow-alarms is active. ++-* Value [2011/10/17] Fixed crash when a library function is called in ++ a state where the function's precondition cannot be true. ++-* Value [2011/10/10] Fixed spurious alarm \valid(p) in *p = e; when e is ++ completely invalid. Soundness was not affected (the ++ alarm for whatever made e invalid was present). ++ ++ + ##################################### + Open Source Release Nitrogen_20111001 + ##################################### +diff --git a/src/ai/base.ml b/src/ai/base.ml +index 5669a8c..45659d0 100644 +--- a/src/ai/base.ml ++++ b/src/ai/base.ml +@@ -117,12 +117,14 @@ let bits_sizeof v = + | Var (v,_) | Initialized_Var (v,_) -> + Bit_utils.sizeof_vid v + ++let dep_absolute = [Kernel.AbsoluteValidRange.self] ++ + module MinValidAbsoluteAddress = + State_builder.Ref + (Abstract_interp.Int) + (struct + let name = "MinValidAbsoluteAddress" +- let dependencies = [] ++ let dependencies = dep_absolute + let kind = `Internal + let default () = Abstract_interp.Int.zero + end) +@@ -132,7 +134,7 @@ module MaxValidAbsoluteAddress = + (Abstract_interp.Int) + (struct + let name = "MaxValidAbsoluteAddress" +- let dependencies = [] ++ let dependencies = dep_absolute + let kind = `Internal + let default () = Abstract_interp.Int.minus_one + end) +diff --git a/src/from/from_register.ml b/src/from/from_register.ml +index ca13011..deae68a 100644 +--- a/src/from/from_register.ml ++++ b/src/from/from_register.ml +@@ -716,11 +716,12 @@ let compute_using_prototype_for_state state kf = + !Properties.Interp.loc_to_loc ~result:None state + out.it_content + in ++ let exact = Locations.Location_Bits.cardinal_zero_or_one output_loc.loc in + let output_zone = + Locations.valid_enumerate_bits ~for_writing:true + output_loc + in +- Lmap_bitwise.From_Model.add_binding ~exact:true ++ Lmap_bitwise.From_Model.add_binding ~exact + acc output_zone (input_zone ins) + with Invalid_argument "not an lvalue" -> + From_parameters.result +diff --git a/src/lib/rangemap.ml b/src/lib/rangemap.ml +index 67a58cd..a93953e 100644 +--- a/src/lib/rangemap.ml ++++ b/src/lib/rangemap.ml +@@ -88,7 +88,7 @@ module Make(Ord: Datatype.S)(Value: Datatype.S) = struct + | Node(_,_,_,_,h,_) -> h + + let hash = function +- | Empty -> 13 ++ | Empty -> 0 + | Node(_,_,_,_,_,h) -> h + + +@@ -126,7 +126,7 @@ module Make(Ord: Datatype.S)(Value: Datatype.S) = struct + let hl = height l and hr = height r in + let hashl = hash l and hashr = hash r in + let hashbinding = Hashtbl.hash (x_h, d_h) in +- let hashtree = 289 (* =17*17 *) * hashl + 17 * hashbinding + hashr in ++ let hashtree = hashl lxor hashbinding lxor hashr in + Node(l, x, d, r, (if hl >= hr then hl + 1 else hr + 1), hashtree) + + let bal l x d r = +diff --git a/src/memory_state/lmap.ml b/src/memory_state/lmap.ml +index 9867584..8786e5b 100644 +--- a/src/memory_state/lmap.ml ++++ b/src/memory_state/lmap.ml +@@ -943,7 +943,7 @@ let is_included = + let plevel = Kernel.ArrayPrecisionLevel.get() in + let treat_dst k_dst i_dst (acc_lmap : LBase.t) = + if Base.is_read_only k_dst +- then acc_lmap ++ then (CilE.warn_mem_write with_alarms; acc_lmap) + else + let validity = Base.validity k_dst in + let offsetmap_dst = LBase.find_or_default k_dst m in +diff --git a/src/value/eval_exprs.ml b/src/value/eval_exprs.ml +index 543bc91..73b5349 100644 +--- a/src/value/eval_exprs.ml ++++ b/src/value/eval_exprs.ml +@@ -960,7 +960,7 @@ and eval_expr_with_deps_state ~with_alarms deps state e = + (* Can raise a pointer comparison. CilE needs a binop there *) + in + CilE.set_syntactic_context syntactic_context; +- let result = eval_unop ~with_alarms expr t op in ++ let result = eval_unop ~check_overflow:true ~with_alarms expr t op in + state, deps, result + in + let r = +@@ -979,46 +979,49 @@ and eval_expr_with_deps_state ~with_alarms deps state e = + | _ -> ()); *) + state, deps, rr + +-and eval_unop ~with_alarms expr t op = ++(* This function evaluates a unary minus, but does _not_ check for overflows. ++ This is left to the caller *) ++and eval_uneg_exp ~with_alarms expr t = ++ match unrollType t with ++ | TFloat _ -> ++ (try ++ let v = V.project_ival expr in ++ let f = Ival.project_float v in ++ V.inject_ival ++ (Ival.inject_float (Ival.Float_abstract.neg_float f)) ++ with ++ V.Not_based_on_null -> ++ begin match with_alarms.CilE.others with ++ | CilE.Aignore -> () ++ | CilE.Acall f -> f() ++ | CilE.Alog _ -> ++ warning_once_current ++ "converting address to float: assert(TODO)" ++ end; ++ V.topify_arith_origin expr ++ | Ival.Float_abstract.Nan_or_infinite -> ++ begin match with_alarms.CilE.others with ++ | CilE.Aignore -> () ++ | CilE.Acall f -> f() ++ | CilE.Alog _ -> ++ warning_once_current ++ "converting value to float: assert (TODO)" ++ end; ++ V.top_float ++ ) ++ | _ -> ++ try ++ let v = V.project_ival expr in ++ V.inject_ival (Ival.neg v) ++ with V.Not_based_on_null -> V.topify_arith_origin expr ++ ++and eval_unop ~check_overflow ~with_alarms expr t op = + match op with + | Neg -> +- let t = unrollType t in +- (match t with TFloat _ -> +- (try +- let v = V.project_ival expr in +- let f = Ival.project_float v in +- V.inject_ival +- (Ival.inject_float (Ival.Float_abstract.neg_float f)) +- with +- V.Not_based_on_null -> +- begin match with_alarms.CilE.others with +- CilE.Aignore -> () +- | CilE.Acall f -> f() +- | CilE.Alog _ -> +- warning_once_current +- "converting address to float: assert(TODO)" +- end; +- V.topify_arith_origin expr +- | Ival.Float_abstract.Nan_or_infinite -> +- begin match with_alarms.CilE.others with +- CilE.Aignore -> () +- | CilE.Acall f -> f() +- | CilE.Alog _ -> +- warning_once_current +- "converting value to float: assert (TODO)" +- end; +- V.top_float +- ) +- | _ -> +- let result = +- try +- let v = V.project_ival expr in +- V.inject_ival (Ival.neg v) +- with V.Not_based_on_null -> V.topify_arith_origin expr +- in +- handle_signed_overflow ~with_alarms t result +- ) +- ++ let r = eval_uneg_exp ~with_alarms expr t in ++ if check_overflow ++ then handle_signed_overflow ~with_alarms t r ++ else r + | BNot -> + (try + let v = V.project_ival expr in +diff --git a/src/value/eval_exprs.mli b/src/value/eval_exprs.mli +index 3914cb8..4f76da5 100644 +--- a/src/value/eval_exprs.mli ++++ b/src/value/eval_exprs.mli +@@ -50,6 +50,7 @@ val eval_binop_int : + Cvalue.V.t -> binop -> Cvalue.V.t -> Cvalue.V.t + + val eval_unop: ++ check_overflow:bool -> + with_alarms:CilE.warn_mode -> + Cvalue.V.t -> + typ (** Type of the expression under the unop *) -> +diff --git a/src/value/eval_funs.ml b/src/value/eval_funs.ml +index 5db6453..4d1c0f4 100644 +--- a/src/value/eval_funs.ml ++++ b/src/value/eval_funs.ml +@@ -166,7 +166,9 @@ let compute_using_prototype kf ~active_behaviors ~state_with_formals = + (Kernel_function.get_name kf) + Cvalue.Model.pretty state_with_formals; *) + let vi = Kernel_function.get_vi kf in +- if Cil.hasAttribute "noreturn" vi.vattr then ++ if (not (Cvalue.Model.is_reachable state_with_formals)) || ++ Cil.hasAttribute "noreturn" vi.vattr ++ then + None, Cvalue.Model.bottom, Location_Bits.Top_Param.bottom + else + let return_type,_formals_type,_inline,_attr = +diff --git a/src/value/eval_logic.ml b/src/value/eval_logic.ml +index 52d5276..4be53b6 100644 +--- a/src/value/eval_logic.ml ++++ b/src/value/eval_logic.ml +@@ -255,7 +255,9 @@ let rec eval_term env result t = + | BNot -> t (* can only be used on an integer type *) + | LNot -> intType + in +- let eval typ v = eval_unop ~with_alarms v typ op in ++ let eval typ v = ++ eval_unop ~check_overflow:false ~with_alarms v typ op ++ in + List.map (fun (typ, v) -> typ' typ, eval typ v) l + + | Trange (otlow, othigh) -> +@@ -405,6 +407,11 @@ let eval_term_as_exact_loc env result t = + ) + | _ -> raise Not_an_exact_loc + ++let isPointerCType ct = ++ match unrollType ct with ++ TPtr _ -> true ++ | _ -> false ++ + let rec reduce_by_predicate ~result env positive p = + let result = + match positive,p.content with +@@ -459,7 +466,7 @@ let rec reduce_by_predicate ~result env positive p = + | t when isLogicRealOrFloatType t -> + eval_float (Value_parameters.AllRoundingModes.get ()) + | t when isLogicIntegralType t -> eval_int +- | Ctype (TPtr _) -> eval_int ++ | Ctype (ct) when isPointerCType ct -> eval_int + | _ -> raise Predicate_alarm + in + reduce_by_relation eval ~result env positive t1 op t2 +diff --git a/src/value/eval_stmts.ml b/src/value/eval_stmts.ml +index ca95ff7..64f2415 100644 +--- a/src/value/eval_stmts.ml ++++ b/src/value/eval_stmts.ml +@@ -562,12 +562,17 @@ struct + mem_e + reduced_state + in +- if not (Cvalue.Model.is_reachable new_reduced_state) ++ if (Cvalue.Model.is_reachable reduced_state) && ++ not (Cvalue.Model.is_reachable new_reduced_state) + then begin +- CilE.set_syntactic_context (CilE.SyMem lv); +- CilE.warn_mem_write with_alarms ; +- Value_parameters.result ~current:true +- "all target addresses were invalid. This path is assumed to be dead."; ++(* Value_parameters.result ~current:true ++ "REDUCED:@.%a@.TO:@.%a@." ++ Cvalue.Model.pretty reduced_state ++ Cvalue.Model.pretty new_reduced_state; *) ++ CilE.set_syntactic_context (CilE.SyMem lv); ++ CilE.warn_mem_write with_alarms ; ++ Value_parameters.result ~current:true ++ "all target addresses were invalid. This path is assumed to be dead."; + end; + new_reduced_state + (* | Var _ , Index _ -> assert false +-- diff -Nru frama-c-20110201+carbon+dfsg/debian/patches/series frama-c-20111001+nitrogen+dfsg/debian/patches/series --- frama-c-20110201+carbon+dfsg/debian/patches/series 2011-04-25 10:03:11.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/debian/patches/series 2012-01-06 08:30:25.000000000 +0000 @@ -1,3 +1,6 @@ -0001-Value-Analysis-Carbon-patchlevel-1.patch -0002-Fix-for-issue-727.patch -0003-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch +0001-Add-ocamlgraph-to-DYN_-O-B-LINKFLAGS.patch +0002-Accept-ocamlgraph-1.8.patch +0003-Fix-spelling-error-in-binary.patch +0004-Use-bin-cp-instead-of-usr-bin-install.patch +0005-Disable-CHMOD_RO-invocations.patch +0006-Patchlevel2-for-Nitrogen-20111001.patch diff -Nru frama-c-20110201+carbon+dfsg/doc/code/docgen.ml frama-c-20111001+nitrogen+dfsg/doc/code/docgen.ml --- frama-c-20110201+carbon+dfsg/doc/code/docgen.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/doc/code/docgen.ml 2011-10-10 08:40:04.000000000 +0000 @@ -355,7 +355,7 @@ incr Odoc_info.errors method html_of_plugin_developer_guide _t = - "Consult the Plugin Development Guide for additional details.
\n" + "Consult the Plugin Development Guide for additional details.
\n" method html_of_ignore _t = "" @@ -363,16 +363,16 @@ match t with | [] -> Odoc_info.warning "Found an empty @modify tag"; "" | Raw s :: l -> - let time, explanation = - try + let time, explanation = + try let idx = String.index s ' ' in - String.sub s 0 idx, - ":" ^ String.sub s idx (String.length s - idx) - with Not_found -> + String.sub s 0 idx, + ":" ^ String.sub s idx (String.length s - idx) + with Not_found -> s, "" in - let text = - Bold [ Raw "Change in "; Raw time ] :: Raw explanation :: l + let text = + Bold [ Raw "Change in "; Raw time ] :: Raw explanation :: l in let buf = Buffer.create 7 in self#html_of_text buf text; diff -Nru frama-c-20110201+carbon+dfsg/doc/code/intro_wp.txt frama-c-20111001+nitrogen+dfsg/doc/code/intro_wp.txt --- frama-c-20110201+carbon+dfsg/doc/code/intro_wp.txt 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/doc/code/intro_wp.txt 2011-10-10 08:40:04.000000000 +0000 @@ -1,12 +1,10 @@ @ignore @ignore -@ignore This file is part of Frama-C. +@ignore This file is part of WP plug-in of Frama-C. @ignore @ignore Copyright (C) 2007-2011 -@ignore CEA (Commissariat à l'énergie atomique et aux énergies -@ignore alternatives) -@ignore INRIA (Institut National de Recherche en Informatique et en -@ignore Automatique) +@ignore CEA (Commissariat a l'énergie atomique et aux énergies +@ignore alternatives) @ignore @ignore you can redistribute it and/or modify it under the terms of the GNU @ignore Lesser General Public License as published by the Free Software @@ -17,7 +15,7 @@ @ignore MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @ignore GNU Lesser General Public License for more details. @ignore -@ignore See the GNU Lesser General Public License version v2.1 +@ignore See the GNU Lesser General Public License version 2.1 @ignore for more details (enclosed in the file licenses/LGPLv2.1). @ignore @ignore diff -Nru frama-c-20110201+carbon+dfsg/external/hptmap.ml frama-c-20111001+nitrogen+dfsg/external/hptmap.ml --- frama-c-20110201+carbon+dfsg/external/hptmap.ml 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/hptmap.ml 2011-10-10 08:38:06.000000000 +0000 @@ -26,24 +26,16 @@ type prefix = int * int let sentinel_prefix = (-1) , (-1) -let debug = ref false - module Big_Endian = struct type mask = int -(* - let lowest_bit x = - x land (-x) - - let rec highest_bit x = - let m = lowest_bit x in - if x = m then - m - else - highest_bit (x - m) -*) - let highest_bit v = +(* inlined + let branching_bit p0 p1 = + let v = p0 lxor p1 in + (* compute highest bit. + First, set all bits with weight less than + the highest set bit *) let v1 = v lsr 1 in let v2 = v lsr 2 in let v = v lor v1 in @@ -56,21 +48,9 @@ let v2 = v lsr 18 in let v = v lor v1 in let v = v lor v2 in + (* then get highest bit *) (succ v) lsr 1 - - - (* Performing a logical ``xor'' of [i0] and [i1] yields a bit field where all differences between [i0] and [i1] - show up as one bits. (There must be at least one, since [i0] and [i1] are distinct.) The ``first'' one is - the highest bit in this bit field, since we are checking most significant bits first. - - In Okasaki's paper, this loop is sped up by computing a conservative initial guess. Indeed, the bit at which - the two prefixes disagree must be somewhere within the shorter prefix, so we can begin searching at the - least-significant valid bit in the shorter prefix. Unfortunately, to allow computing the initial guess, the - main code has to pass in additional parameters, e.g. a mask which describes the length of each prefix. This - ``pollutes'' the endianness-independent code. For this reason, this optimization isn't implemented here. *) - - let branching_bit i0 i1 = - highest_bit (i0 lxor i1) +*) (* The ``relevant'' bits in an integer [i] are those which are found (strictly) to the left of the single one bit in the mask [m]. We keep these bits, and set all others to 0. Okasaki uses a different convention, which allows @@ -81,8 +61,8 @@ (* The smaller [m] is, the more bits are relevant. *) - let shorter = - (>) + let shorter (m:int) (n:int) = m > n + end @@ -125,7 +105,9 @@ end) (V : Tagged_type) (Comp : sig val e: bool val f : Key.t -> V.t -> bool val compose : bool -> bool -> bool val default: bool end) - (Initial_Values: sig val v : (Key.t * V.t) list list end) = + (Initial_Values: sig val v : (Key.t * V.t) list list end) + (Datatype_deps: sig val l : State.t list end) + = struct type key = Key.t @@ -150,37 +132,40 @@ let compare = if Key.compare == Datatype.undefined || - V.compare == Datatype.undefined then ( - Kernel.debug "(%s, %s) ptmap, missing comparison function: %b %b" + V.compare == Datatype.undefined + then ( +(* Kernel.debug "(%s, %s) ptmap, missing comparison function: %b %b" (Type.name Key.ty) (Type.name V.ty) (Key.compare == Datatype.undefined) - (V.compare == Datatype.undefined); + (V.compare == Datatype.undefined); *) Datatype.undefined ) - else let rec compare t1 t2 = match t1, t2 with - | Empty, Empty -> 0 - | Empty, _ -> -1 - | _, Empty -> 1 - | Leaf (k1,x1,_), Leaf (k2,x2,_) -> - let c = Key.compare k1 k2 in - if c <> 0 then c else V.compare x1 x2 - | Leaf _, Branch _ -> -1 - | Branch _, Leaf _ -> 1 - | Branch (_p1,_m1,_l1,_r1,t1), Branch (_p2,_m2,_l2,_r2,t2) -> - let t1 = Tag_comp.get_tag t1 in - let t2 = Tag_comp.get_tag t2 in - Datatype.Int.compare t1 t2 - (* Taken and adapted from JCF code for the implementation - without tag *) - (*let c = Datatype.Int.compare p1 p2 in - if c <> 0 then c else - let c = Big_endian.compare m1 m2 in - if c <> 0 then c else - let c = compare l1 l2 in - if c <> 0 then c else - compare r1 r2 - *) - in compare + else + let rec compare t1 t2 = + match t1, t2 with + | Empty, Empty -> 0 + | Empty, _ -> -1 + | _, Empty -> 1 + | Leaf (k1,x1,_), Leaf (k2,x2,_) -> + let c = Key.compare k1 k2 in + if c <> 0 then c else V.compare x1 x2 + | Leaf _, Branch _ -> -1 + | Branch _, Leaf _ -> 1 + | Branch (_p1,_m1,_l1,_r1,t1), Branch (_p2,_m2,_l2,_r2,t2) -> + let t1 = Tag_comp.get_tag t1 in + let t2 = Tag_comp.get_tag t2 in + Datatype.Int.compare t1 t2 + (* Taken and adapted from JCF code for the implementation + without tag *) + (*let c = Datatype.Int.compare p1 p2 in + if c <> 0 then c else + let c = Big_endian.compare m1 m2 in + if c <> 0 then c else + let c = compare l1 l2 in + if c <> 0 then c else + compare r1 r2 + *) + in compare let contains_single_binding t = @@ -201,6 +186,12 @@ | Branch (_,_,left,_,_) -> min_binding left | Leaf (key, data, _) -> key, data + let rec max_binding t = + match t with + Empty -> raise Not_found + | Branch (_,_,_,right,_) -> max_binding right + | Leaf (key, data, _) -> key, data + let rec iter f htr = match htr with | Empty -> () @@ -227,12 +218,9 @@ | Branch (_, _, _, _, tl) -> Tag_comp.get_tag tl let hash_internal tr = - let result = match tr with Empty | Leaf _ -> tag tr | Branch(p,m,l,r, _tag) -> m + 3 * p + 2017 * (tag l) + (tag r) - in - result let hash_debug = hash_internal @@ -267,15 +255,11 @@ let initial_values = - let r = List.map + List.map (function [k,v] -> Leaf (k, v, Comp.f k v) | [] -> Empty | _ -> assert false) Initial_Values.v - in -(* Format.printf "initial values of %s:@." id; - List.iter (fun x -> Cil.log "value = %a (%d)@." pretty x (Obj.magic x)) r;*) - r let rehash_ref = ref (fun _ -> assert false) @@ -292,8 +276,8 @@ [| [| Key.packed_descr; V.packed_descr; p_abstract |]; [| p_abstract; p_abstract; - Recursive r; - Recursive r; + recursive_pack r; + recursive_pack r; p_abstract |] |]) let () = Recursive.update r structural_descr let reprs = [ Empty ] @@ -322,11 +306,13 @@ end) (struct let name = Type.name ty ^ " hashconsing table" - let dependencies = [ Ast.self ] + let dependencies = Datatype_deps.l let size = 137 let kind = `Internal end) + let self = PatriciaHashconsTbl.self + (* let inform_counter = ref 0 let inform() = @@ -424,7 +410,26 @@ matter how large $t_0$ and $t_1$ are, we can merge them simply by creating a new [Branch] node that has $t_0$ and $t_1$ as children! *) let join p0 t0 p1 t1 = - let m = Big_Endian.branching_bit p0 p1 in + let m = (* Big_Endian.branching_bit p0 p1 in (inlined) *) + let v = p0 lxor p1 in + (* compute highest bit. + First, set all bits with weight less than + the highest set bit *) + let v1 = v lsr 1 in + let v2 = v lsr 2 in + let v = v lor v1 in + let v = v lor v2 in + let v1 = v lsr 3 in + let v2 = v lsr 6 in + let v = v lor v1 in + let v = v lor v2 in + let v1 = v lsr 9 in + let v2 = v lsr 18 in + let v = v lor v1 in + let v = v lor v2 in + (* then get highest bit *) + (succ v) lsr 1 + in let p = Big_Endian.mask p0 (* for instance *) m in if (p0 land m) = 0 then wrap_Branch p m t0 t1 @@ -829,6 +834,20 @@ in add m + module Cacheable = + struct + type t = tt + let hash = tag + let sentinel = Empty + let equal = (==) + end + + module R = + struct + type t = tt + let sentinel = Empty + end + exception Found of t let symetric_merge ~cache ~decide_none ~decide_some = @@ -870,23 +889,8 @@ add m in let _name, _cache = cache in - - let module Result = - struct - type t = tt - let sentinel = Empty - end - in - let module Symcacheable = - struct - type t = tt - let hash = tag - let equal = (==) - let sentinel = Empty - end - in let module SymetricCache = - Binary_cache.Make_Symetric(Symcacheable)(Result) + Binary_cache.Make_Symetric(Cacheable)(R) in Project.register_todo_before_clear (fun _ -> SymetricCache.clear ()); let rec union s t = @@ -899,12 +903,9 @@ | Leaf(key, value, _), t | t, Leaf(key, value, _) -> symetric_fine_add key value t | Branch(p, m, s0, s1, _), Branch(q, n, t0, t1, _) -> - if !debug then - Format.printf "PTMAP Br(%d %d) Br(%d %d)@." p m q n; - if (p = q) & (m = n) then - + if (p = q) & (m = n) + then (* The trees have the same prefix. Merge their sub-trees. *) - let u0 = union s0 t0 and u1 = union s1 t1 in if t0 == u0 && t1 == u1 then t @@ -944,36 +945,20 @@ join p (union s Empty) q (union Empty t) in union - - let generic_merge ~cache ~decide = - let _name, _cache = cache in - let cache_merge = - if _cache = 0 - then fun f _ _ -> f() - else begin - let module Cacheable = - struct - type t = tt - let hash = tag - let sentinel = Empty - let equal = (==) - end - in - let module R = - struct - type t = tt - let sentinel = Empty + let generic_merge ~cache ~decide = + let _name, _cache = cache in + let cache_merge = + if _cache = 0 + then fun f x y -> f x y + else begin + let module Cache = Binary_cache.Make_Asymetric(Cacheable)(R) + in + Project.register_todo_before_clear (fun _ -> Cache.clear ()); + Cache.merge end in - let module Cache = Binary_cache.Make_Asymetric(Cacheable)(R) - in - Project.register_todo_before_clear (fun _ -> Cache.clear ()); - Cache.merge - end - in - fun m1 m2 -> - let rec union s t = - if s==t then s else + let rec union s t = if s==t then s else cache_merge compute s t + and compute s t = match s, t with | Empty, _ -> endo_map (fun k x -> decide k None (Some x)) t @@ -986,69 +971,53 @@ generic_fine_add decide key value s | Branch(p, m, s0, s1, _), Branch(q, n, t0, t1, _) -> - let compute () = - if (p = q) & (m = n) then + if (p = q) & (m = n) then - (* The trees have the same prefix. Merge their sub-trees. *) + (* The trees have the same prefix. Merge their sub-trees. *) - let u0 = union s0 t0 - and u1 = union s1 t1 in - if t0 == u0 && t1 == u1 then t - else wrap_Branch p m u0 u1 + let u0 = union s0 t0 + and u1 = union s1 t1 in + if t0 == u0 && t1 == u1 then t + else wrap_Branch p m u0 u1 - else if (Big_Endian.shorter m n) & (match_prefix q p m) then + else if (Big_Endian.shorter m n) & (match_prefix q p m) then - (* [q] contains [p]. Merge [t] with a sub-tree of [s]. *) + (* [q] contains [p]. Merge [t] with a sub-tree of [s]. *) - if (q land m) = 0 then - let s0_t = union s0 t in - let s1_e = union s1 Empty in - if s0_t == s0 && s1_e == s1 then s - else wrap_Branch p m s0_t s1_e - else - let s0_e = union s0 Empty in - let s1_t = union s1 t in - if s0_e == s0 && s1_t == s1 then s - else wrap_Branch p m s0_e s1_t - - else if (Big_Endian.shorter n m) & (match_prefix p q n) then - - (* [p] contains [q]. Merge [s] with a sub-tree of [t]. *) - - if (p land n) = 0 then - let s_t0 = union s t0 in - let e_t1 = union Empty t1 in - if t0 == s_t0 && e_t1 == t1 then t - else wrap_Branch q n s_t0 e_t1 - else - let s_t1 = union s t1 in - let e_t0 = union Empty t0 in - if t1 == s_t1 && e_t0 == t0 then t - else wrap_Branch q n e_t0 s_t1 - else - (* The prefixes disagree. *) - join p (union s Empty) q (union Empty t) - in - cache_merge compute s t - in - union m1 m2 + if (q land m) = 0 then + let s0_t = union s0 t in + let s1_e = union s1 Empty in + if s0_t == s0 && s1_e == s1 then s + else wrap_Branch p m s0_t s1_e + else + let s0_e = union s0 Empty in + let s1_t = union s1 t in + if s0_e == s0 && s1_t == s1 then s + else wrap_Branch p m s0_e s1_t - let generic_is_included exn ~cache ~decide_fst ~decide_snd ~decide_both = - let _name, _cache = cache in - let use_comp = _name = "lmap" in - let module Cacheable = - struct - type t = tt - let hash = tag - let equal = (==) - let sentinel = Empty - end - in - let module Cache = - Binary_cache.Make_Binary(Cacheable)(Cacheable) - in - Project.register_todo_before_clear (fun _ -> Cache.clear ()); + else if (Big_Endian.shorter n m) & (match_prefix p q n) then + (* [p] contains [q]. Merge [s] with a sub-tree of [t]. *) + + if (p land n) = 0 then + let s_t0 = union s t0 in + let e_t1 = union Empty t1 in + if t0 == s_t0 && e_t1 == t1 then t + else wrap_Branch q n s_t0 e_t1 + else + let s_t1 = union s t1 in + let e_t0 = union Empty t0 in + if t1 == s_t1 && e_t0 == t0 then t + else wrap_Branch q n e_t0 s_t1 + else + (* The prefixes disagree. *) + join p (union s Empty) q (union Empty t) + in + union + + let make_predicate + cache_merge exn use_comp ~decide_fst ~decide_snd ~decide_both + = let rec inclusion s t = if s!=t then if use_comp && comp t @@ -1089,7 +1058,7 @@ inclusion r t; end | Branch(p, m, s0, s1, _), Branch(q, n, t0, t1, _) -> - let compute () = + let compute s t = try if (p = q) & (m = n) then begin @@ -1135,11 +1104,36 @@ with e when e = exn -> false | _ -> assert false in - let result = Cache.merge compute s t in + let result = cache_merge compute s t in if not result then raise exn in inclusion + let generic_is_included exn ~cache ~decide_fst ~decide_snd ~decide_both = + let _name, _cache = cache in + let use_comp = _name = "lmap" in + let module Cache = + Binary_cache.Make_Binary(Cacheable)(Cacheable) + in + Project.register_todo_before_clear (fun _ -> Cache.clear ()); + make_predicate + Cache.merge + exn + use_comp + ~decide_fst ~decide_snd ~decide_both + + let generic_symetric_existential_predicate exn ~decide_one ~decide_both = + let use_comp = false in + let module Cache = + Binary_cache.Make_Symetric_Binary(Cacheable) + in + Project.register_todo_before_clear (fun _ -> Cache.clear ()); + make_predicate + Cache.merge + exn + use_comp + ~decide_fst:decide_one ~decide_snd:decide_one ~decide_both + let cached_fold ~cache ~temporary ~f ~joiner ~empty = let _name, cache = cache in let table = PatriciaHashtbl.create cache in @@ -1210,6 +1204,24 @@ in traverse m + let rec split key htr = + let id = Key.id key in + let rec aux = function + | Empty -> + (Empty, None, Empty) + | Leaf (key', data, _) -> + if Key.equal key key' then + (Empty, Some data, Empty) + else + (Empty, None, Empty) + | Branch(_, mask, l, r, _) -> + if (id land mask) = 0 then + let (ll, pres, rl) = aux l in (ll, pres, union rl r) + else + let (lr, pres, rr) = aux r in (union l lr, pres, rr) + in + aux htr + end diff -Nru frama-c-20110201+carbon+dfsg/external/hptmap.mli frama-c-20111001+nitrogen+dfsg/external/hptmap.mli --- frama-c-20110201+carbon+dfsg/external/hptmap.mli 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/hptmap.mli 2011-10-10 08:38:06.000000000 +0000 @@ -14,8 +14,6 @@ (* *) (**************************************************************************) -val debug: bool ref - module type Tagged_type = sig include Datatype.S val tag : t -> int @@ -24,6 +22,9 @@ module Tag_comp : sig type t + val get_tag : t -> int + val get_comp : t -> bool + val encode : int -> bool -> t end module Comp_unused : @@ -44,7 +45,9 @@ end) (V : Tagged_type) (Comp : sig val e: bool val f : Key.t -> V.t -> bool val compose : bool -> bool -> bool val default:bool end) - (Initial_Values : sig val v : (Key.t*V.t) list list end) : + (Initial_Values : sig val v : (Key.t*V.t) list list end) + (Datatype_deps: sig val l : State.t list end) + : sig type key = Key.t @@ -58,6 +61,7 @@ include Datatype.S with type t = tt + val self : State.t val empty : t @@ -101,6 +105,10 @@ decide_snd:(Key.t -> V.t -> unit) -> decide_both:(V.t -> V.t -> unit) -> t -> t -> unit + val generic_symetric_existential_predicate : exn -> + decide_one:(Key.t -> V.t -> unit) -> + decide_both:(V.t -> V.t -> unit) -> t -> t -> unit + val cached_fold : cache:string * int -> temporary:bool -> @@ -114,7 +122,9 @@ val is_singleton: t -> (key * V.t) option val min_binding: t -> key * V.t + val max_binding: t -> key * V.t + val split: key -> t -> t * V.t option * t end (* diff -Nru frama-c-20110201+carbon+dfsg/external/unmarshal_hashtbl_test.ml frama-c-20111001+nitrogen+dfsg/external/unmarshal_hashtbl_test.ml --- frama-c-20110201+carbon+dfsg/external/unmarshal_hashtbl_test.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unmarshal_hashtbl_test.ml 2011-10-10 08:38:06.000000000 +0000 @@ -1,6 +1,6 @@ (**************************************************************************) (* *) -(* Copyright (C) 2009-2010 INRIA *) +(* Copyright (C) 2009-2011 INRIA *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) (* *) diff -Nru frama-c-20110201+carbon+dfsg/external/unmarshal.ml frama-c-20111001+nitrogen+dfsg/external/unmarshal.ml --- frama-c-20110201+carbon+dfsg/external/unmarshal.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unmarshal.ml 2011-10-10 08:38:06.000000000 +0000 @@ -1,6 +1,6 @@ (**************************************************************************) (* *) -(* Copyright (C) 2009-2010 INRIA *) +(* Copyright (C) 2009-2011 INRIA *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) (* *) @@ -244,8 +244,10 @@ else value_raw_other ;; -(* Note: this is buggy if we're unlucky with the GC. - To do it correctly, we need a primitive to add an offset to a value. *) +(* Note: this function is 100% safe only when manipulating a pointer + outside the heap. Otherwise, we may be unlucky with the GC. + To do it correctly, we need a primitive to add an offset to a value. + (3.12.0 minimum) *) let obj_add_offset v ofs = value_raw (Int64.add (raw_value v) (Int64.of_int32 ofs)) ;; @@ -260,7 +262,11 @@ let ofs = Int32.logor (Int32.shift_left (Int32.of_int c3) 24) (Int32.of_int ((c2 lsl 16) lor (c1 lsl 8) lor c0)) in - let start = obj_add_offset (Obj.field (Obj.repr id) 0) (Int32.neg ofs) in + let start = + (* This call to obj_add_offset is safe because the pointer is outside + the heap *) + obj_add_offset (Obj.field (Obj.repr id) 0) (Int32.neg ofs) + in (start, cksum) ;; @@ -455,10 +461,16 @@ | 0x10 (* CODE_CODEPOINTER *) -> let ofs = getword ch in check_const ch cksum "input_value: code mismatch"; - return stk (do_transform t (obj_add_offset code_area_start ofs)) + let offset_pointer = + (* This call to obj_add_offset is safe because the pointer + is outside the heap *) + obj_add_offset code_area_start ofs + in + return stk (do_transform t offset_pointer) | 0x11 (* CODE_INFIXPOINTER *) -> let ofs = getword ch in let clos = intern_rec [] t in + (* This call to obj_add_offset is unsafe *) return stk (obj_add_offset clos ofs) | 0x12 (* CODE_CUSTOM *) -> diff -Nru frama-c-20110201+carbon+dfsg/external/unmarshal.mli frama-c-20111001+nitrogen+dfsg/external/unmarshal.mli --- frama-c-20110201+carbon+dfsg/external/unmarshal.mli 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unmarshal.mli 2011-10-10 08:38:06.000000000 +0000 @@ -1,6 +1,6 @@ (**************************************************************************) (* *) -(* Copyright (C) 2009-2010 INRIA *) +(* Copyright (C) 2009-2011 INRIA *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) (* *) diff -Nru frama-c-20110201+carbon+dfsg/external/unmarshal_nums.ml frama-c-20111001+nitrogen+dfsg/external/unmarshal_nums.ml --- frama-c-20110201+carbon+dfsg/external/unmarshal_nums.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unmarshal_nums.ml 2011-10-10 08:38:06.000000000 +0000 @@ -1,6 +1,6 @@ (**************************************************************************) (* *) -(* Copyright (C) 2009-2010 INRIA *) +(* Copyright (C) 2009-2011 INRIA *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) (* *) diff -Nru frama-c-20110201+carbon+dfsg/external/unmarshal_nums.mli frama-c-20111001+nitrogen+dfsg/external/unmarshal_nums.mli --- frama-c-20110201+carbon+dfsg/external/unmarshal_nums.mli 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unmarshal_nums.mli 2011-10-10 08:38:06.000000000 +0000 @@ -1,6 +1,6 @@ (**************************************************************************) (* *) -(* Copyright (C) 2009-2010 INRIA *) +(* Copyright (C) 2009-2011 INRIA *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) (* *) diff -Nru frama-c-20110201+carbon+dfsg/external/unmarshal_test.ml frama-c-20111001+nitrogen+dfsg/external/unmarshal_test.ml --- frama-c-20110201+carbon+dfsg/external/unmarshal_test.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unmarshal_test.ml 2011-10-10 08:38:06.000000000 +0000 @@ -1,6 +1,6 @@ (**************************************************************************) (* *) -(* Copyright (C) 2009-2010 INRIA *) +(* Copyright (C) 2009-2011 INRIA *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) (* *) diff -Nru frama-c-20110201+carbon+dfsg/external/unz.ml frama-c-20111001+nitrogen+dfsg/external/unz.ml --- frama-c-20110201+carbon+dfsg/external/unz.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unz.ml 2011-10-10 08:38:06.000000000 +0000 @@ -0,0 +1,80 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Unmarshal;; + +let readz ch = + let sign = read8u ch in + let charlen = read32u ch in + let str = String.create charlen in + readblock ch (Obj.repr str) 0 charlen; +(* My beautiful string reversing code; + now useless :( + let max = pred charlen in + for i = 0 to (pred max) / 2 do + let c = str.[i] in + str.[i] <- str.[max - i] ; + str.[max - i] <- c + done; +*) + let n = Z.of_bits str in + let z = if sign = 0 then n else Z.neg n in + Obj.repr z +;; + +register_custom "_z" readz;; + +(* + #load "zarith.cma" ;; + let f = open_out "test" ;; + let i = ref (-10000000000000000L) ;; + + while !i <= 10000000000000000L do + output_value f (Z.of_int64 (!i)) ; + i := Int64.add !i 100000000000L ; done + ;; + + + ocamlc -custom zarith.cma unmarshal.ml unz.ml +*) + +(* +let f = open_in "test" ;; + +let i = ref (-10000000000000000L) ;; + +while !i <= 10000000000000000L do + let z = input_val f Abstract in + let r = Z.to_int64 z in + if (r <> !i) + then begin + Format.printf "read: %Ld expected: %Ld@." + r !i; + assert false + end; + i := Int64.add !i 100000000000L ; +done +;; +*) + + + diff -Nru frama-c-20110201+carbon+dfsg/external/unz.mli frama-c-20111001+nitrogen+dfsg/external/unz.mli --- frama-c-20110201+carbon+dfsg/external/unz.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/external/unz.mli 2011-10-10 08:38:06.000000000 +0000 @@ -0,0 +1,22 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + diff -Nru frama-c-20110201+carbon+dfsg/INSTALL frama-c-20111001+nitrogen+dfsg/INSTALL --- frama-c-20110201+carbon+dfsg/INSTALL 2011-02-07 13:42:20.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/INSTALL 2011-10-10 08:40:09.000000000 +0000 @@ -29,7 +29,7 @@ ----------------------- Download the auto-installer corresponding to your system from - http://frama-c.com/download + http://frama-c.com/download.html Then just run it! @@ -45,6 +45,14 @@ or, if you don't want the Gtk-based GUI: sudo apt-get install frama-c-base +------------ +Fedora >= 13 +------------ + +If you are using Fedora >= 13 then a Frama-C package is provided: + + yum install frama-c + =============================================================================== The remainder of these installation instructions is for building Frama-C from source. @@ -60,7 +68,7 @@ 2a) On Linux-like distribution: ./configure && make && sudo make install -2b) On Windows+Cygwin: +2b) On Windows+Cygwin or Windows+MinGW+msys: ./configure --prefix C:/windows/path/with/direct/slash && make && make install 3) The binary frama-c (and frama-c-gui if you have lablgtk2) is now installed. @@ -86,15 +94,15 @@ - GnomeCanvas 2.x - LablGtk >= 2.14.0 -If OcamlGraph >= 1.6 is already installed, then it will be used by Frama-C. +If OcamlGraph 1.8 is already installed, then it will be used by Frama-C. Otherwise the distributed local copy (directory ocamlgraph) will be used. Plug-ins may have their own requirements. Consult their specific documentations for details. ------------------------ -Ubuntu Lucid Lynx 10.04 ------------------------ +-------------------------- +Ubuntu >= Lucid Lynx 10.04 +-------------------------- If you are using Ubuntu >= Lucid Lynx 10.04 then an optimal list of packages is installed by: @@ -106,7 +114,7 @@ Other Linux systems ------------------- -On other Linux systems, you may also use Godi +On any Linux systems, you may use Godi (http://godi.camlcity.org/godi/index.html) for installing Frama-C with all the OCaml requirements (but you must install C libraries and tools before). @@ -126,8 +134,8 @@ See ./configure --help for the current list of plug-ins. -Under Cygwin: -------------- +Under Cygwin or MinGW: +---------------------- Use "./configure --prefix C:/windows/path/with/direct/slash". =============================================================================== @@ -164,16 +172,21 @@ - frama-c-gui.byte bytecode version of frama-c-gui, if available - ptests.byte testing tools for Frama-c -Shared files: (usually in /usr/local/share/frama-c) +Shared files: (usually in /usr/local/share/frama-c and subdirectories) ------------- - some .h and .c files used as preludes by Frama-C; - some Makefiles used to compile dynamic plug-ins - some .rc files used to configure Frama-C +- some image files used by the Frama-C GUI Manuals: (usually in /usr/local/share/frama-c/manuals) -------- - the Frama-C manuals as .pdf files +Documentation files: (usually in /usr/local/share/frama-c/doc) +-------------------- +- files used to generate dynamic plug-in documentation + Object files: (usually in /usr/local/lib/frama-c) ------------- - object files used to compile dynamic plug-ins diff -Nru frama-c-20110201+carbon+dfsg/INSTALL_WITH_WHY frama-c-20111001+nitrogen+dfsg/INSTALL_WITH_WHY --- frama-c-20110201+carbon+dfsg/INSTALL_WITH_WHY 2011-02-07 13:42:20.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/INSTALL_WITH_WHY 2011-10-10 08:40:09.000000000 +0000 @@ -2,6 +2,12 @@ INSTALLATION INSTRUCTIONS for FRAMA_C + WHY ------------------------------------------- +This file is useful only for source distributions including both Frama-C and +Why (like http://frama-c.com/download/frama-c-Boron-20100401-why-2.24.tar.gz +for instance). + +Thus it is useless in any other context. + =============================================================================== SUMMARY =============================================================================== diff -Nru frama-c-20110201+carbon+dfsg/.make-clean-stamp frama-c-20111001+nitrogen+dfsg/.make-clean-stamp --- frama-c-20110201+carbon+dfsg/.make-clean-stamp 2011-02-07 13:42:20.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/.make-clean-stamp 2011-10-10 08:40:09.000000000 +0000 @@ -1 +1 @@ -5 +7 diff -Nru frama-c-20110201+carbon+dfsg/Makefile frama-c-20111001+nitrogen+dfsg/Makefile --- frama-c-20110201+carbon+dfsg/Makefile 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/Makefile 2011-10-10 08:40:09.000000000 +0000 @@ -138,13 +138,16 @@ endif BFLAGS = $(DEV_FLAGS) $(DEBUG) $(INCLUDES) $(COVERAGE_COMPILER_BYTE) \ - $(OCAMLVIZ_COMPILER_BYTE) + $(OCAMLVIZ_COMPILER_BYTE) $(OUNIT_COMPILER_BYTE) OFLAGS = $(DEV_FLAGS) $(DEBUG) $(INCLUDES) $(COVERAGE_COMPILER_OPT) \ - $(GPROFOPT) $(OCAMLVIZ_COMPILER_OPT) + $(GPROFOPT) $(OCAMLVIZ_COMPILER_OPT) $(OUNIT_COMPILER_OPT) -compact BLINKFLAGS = $(BFLAGS) -linkall -custom OLINKFLAGS = $(OFLAGS) -linkall +DOC_FLAGS= -colorize-code -stars -inv-merge-ml-mli -m A -hide-warnings \ + $(INCLUDES) $(GUI_INCLUDES) + # Libraries generated by Frama-C GEN_BYTE_LIBS= GEN_OPT_LIBS= @@ -154,17 +157,48 @@ $(GEN_BYTE_LIBS) OPT_LIBS = nums.cmxa unix.cmxa bigarray.cmxa str.cmxa +# For using Zarith: +ifeq ($(HAS_ZARITH),yes) +#ZARITH_LINK = -cclib -L/usr/local/Frama-C/macports/lib +#ZARITH_INC = -I /home/cuoq/zarith +BYTE_LIBS+= zarith.cma $(ZARITH_LINK) +OPT_LIBS+= zarith.cmxa $(ZARITH_LINK) +INCLUDES+= $(ZARITH_INC) +src/lib/my_bigint.ml: src/lib/my_bigint.ml.zarith + $(PRINT_CP) $@ + $(CP) $< $@ + $(CHMOD_RO) $@ +else +src/lib/my_bigint.ml: src/lib/my_bigint.ml.bigint + $(PRINT_CP) $@ + $(CP) $< $@ + $(CHMOD_RO) $@ +endif +GENERATED += src/lib/my_bigint.ml +DISTRIB_FILES+= src/lib/my_bigint.ml.zarith src/lib/my_bigint.ml.bigint + ifeq ("$(NATIVE_DYNLINK)","yes") OPT_LIBS+= dynlink.cmxa endif OPT_LIBS+= $(GEN_OPT_LIBS) -ICONS:= $(addprefix share/, \ +ICONS:= $(addprefix share/, \ frama-c.ico frama-c.gif left.png right.png \ - relies_on_hyp.png failed.png maybe.png attach.png \ - check.png \ - ) + failed.png maybe.png check.png unmark.png ) + +FEEDBACK_ICONS:= $(addprefix share/feedback/, \ + never_tried.png \ + unknown.png \ + surely_valid.png \ + surely_invalid.png \ + considered_valid.png \ + valid_under_hyp.png \ + invalid_under_hyp.png \ + invalid_but_dead.png \ + unknown_but_dead.png \ + valid_but_dead.png \ + inconsistent.png ) # Kernel files to be included in the distribution. # Plug-ins should use PLUGIN_DISTRIB_EXTERNAL if they export something else @@ -172,35 +206,42 @@ # NB: configure for the distribution is generated in the distrib directory # itself, rather than copied: otherwise, it could include references to # non-distributed plug-ins. -DISTRIB_FILES:=cil/*/*.ml* cil/src/*/*.ml* cil/*/*.in cil/LICENSE \ - cil/CHANGES cil/doc/*.html cil/doc/*.tex cil/doc/*.gif \ - share/frama-c.WIN32.rc share/frama-c.Unix.rc \ - $(ICONS) \ - man/frama-c.1 cil/doc/*.pdf cil/doc/api/*.html \ - cil/doc/examples/*.txt doc/manuals/*.pdf doc/README \ - doc/code/*.ml* doc/code/*.css doc/code/*.txt \ - doc/code/toc_head.htm doc/code/toc_tail.htm \ - tests/*/*.c tests/*/*.h tests/*/*.ml \ +DISTRIB_FILES:=cil/*/*.ml* cil/src/*/*.ml* cil/*/*.in \ + share/frama-c.WIN32.rc share/frama-c.Unix.rc \ + $(ICONS) $(FEEDBACK_ICONS) \ + man/frama-c.1 doc/manuals/*.pdf doc/README doc/code/*.ml* \ + doc/code/*.css doc/code/intro_plugin.txt \ + doc/code/intro_kernel_plugin.txt doc/code/intro_occurrence.txt \ + doc/code/intro_pdg.txt doc/code/intro_scope.txt \ + doc/code/intro_slicing.txt doc/code/intro_sparecode.txt \ + doc/code/intro_wp.txt doc/code/toc_head.htm \ + doc/code/toc_tail.htm \ + tests/*/*.c tests/*/*.i tests/*/*.h tests/*/*.ml \ ptests/*.ml* configure.in Makefile share/Makefile.kernel \ share/Makefile.plugin share/Makefile.dynamic \ share/Makefile.dynamic_config.internal \ share/Makefile.dynamic_config.external Changelog config.h.in \ - VERSION $(filter-out CVS,licenses/*) share/*.c share/*.h \ + VERSION licenses/* share/*.c share/*.h \ share/libc/*.c share/libc/*.h share/libc/sys/*.h \ - share/libc/netinet/*.h share/acsl.el \ - share/configure.ac share/Makefile.config.in \ - share/Makefile.common share/Makefile.plugin \ - share/Makefile.dynamic \ + share/libc/netinet/*.h share/acsl.el share/configure.ac \ + share/Makefile.config.in share/Makefile.common \ + share/Makefile.plugin share/Makefile.dynamic \ share/Makefile.dynamic_config.external \ - share/Makefile.dynamic_config.internal \ - $(filter-out %kui%,src/kernel/*.ml*) \ - external/hptmap.ml* external/unmarshal*.ml* \ - src/ai/*.ml* src/buckx/*.ml* src/buckx/*.c src/gui/*.ml* \ - src/lib/*.ml* src/logic/*.ml* src/memory_state/*.ml* \ - src/misc/*.ml* src/project/*.ml* src/toplevel/*.ml* \ - src/type/*.ml* bin/sed_get_make_major bin/sed_get_make_minor \ - bin/sed_inplace INSTALL INSTALL_WITH_WHY .make-clean \ - .make-clean-stamp .make-ocamlgraph-stamp + share/Makefile.dynamic_config.internal \ + src/kernel/*.ml* external/hptmap.ml* \ + external/unmarshal*.ml* external/unz.ml* \ + src/ai/*.ml* src/buckx/*.ml* \ + src/buckx/*.c src/gui/*.ml* src/logic/*.ml* \ + $(filter-out src/lib/my_bigint.ml,$(wildcard src/lib/*.ml*)) \ + src/memory_state/*.ml* src/misc/*.ml* src/project/*.ml* \ + src/toplevel/*.ml* src/type/*.ml* bin/sed_get_make_major \ + bin/sed_get_make_minor INSTALL INSTALL_WITH_WHY .make-clean \ + .make-clean-stamp .make-ocamlgraph-stamp + +# files that are needed to compile API documentation of external plugins +DOC_GEN_FILES:=$(addprefix doc/code/, \ + *.css intro_plugin.txt intro_kernel_plugin.txt kernel-doc.ocamldoc \ + docgen.cm* *.htm) ################ # Main targets # @@ -294,6 +335,23 @@ BYTE_LIBS+=$(OCAMLVIZ_LIB_BYTE) OPT_LIBS+=$(OCAMLVIZ_LIB_OPT) +######### +# OUnit # +######### + +USE_OUNIT_TOOL=no +ifeq ($(USE_OUNIT_TOOL),yes) + OCAML_LIBDIR :=$(shell ocamlc -where) + OUNIT_PATH=$(OCAML_LIBDIR)/../pkg-lib/oUnit + OUNIT_COMPILER_BYTE=-I $(OUNIT_PATH) + OUNIT_COMPILER_OPT=-I $(OUNIT_PATH) + OUNIT_LIB_BYTE=$(OUNIT_PATH)/oUnit.cma + OUNIT_LIB_OPT=$(OUNIT_PATH)/oUnit.cmxa +endif + +BYTE_LIBS+=$(OUNIT_LIB_BYTE) +OPT_LIBS+=$(OUNIT_LIB_OPT) + ############## # Ocamlgraph # ############## @@ -331,24 +389,9 @@ .PRECIOUS: .cmo .cmi .cmx .o .cmxa .cma -# viewgraph and dgraph (included in ocamlgraph) +# dgraph (included in ocamlgraph) ifeq ($(HAS_GNOMECANVAS),yes) - -lib/viewgraph.cmi: lib/graph.cmi - $(PRINT_CP) $@ - $(CP) $(patsubst lib/%,$(OCAMLGRAPH_LOCAL)/view_graph/%,$@) $@ - -lib/viewgraph.cmo: lib/graph.cmi - $(PRINT_CP) $@ - $(CP) $(patsubst lib/%,$(OCAMLGRAPH_LOCAL)/view_graph/%,$@) $@ - -lib/viewgraph.cmx: lib/graph.cmi - $(PRINT_CP) $@ - $(CP) $(patsubst lib/%,$(OCAMLGRAPH_LOCAL)/view_graph/%,$@) $@ - -lib/viewgraph.o: lib/graph.cmi - $(PRINT_CP) $@ - $(CP) $(patsubst lib/%,$(OCAMLGRAPH_LOCAL)/view_graph/%,$@) $@ +ifneq ($(ENABLE_GUI),no) lib/dgraph.cmi: lib/graph.cmi $(PRINT_CP) $@ @@ -366,7 +409,7 @@ $(PRINT_CP) $@ $(CP) $(patsubst lib/%,$(OCAMLGRAPH_LOCAL)/dgraph/%,$@) $@ -GRAPH_GUICMO= lib/dgraph.cmo lib/viewgraph.cmo +GRAPH_GUICMO= lib/dgraph.cmo GRAPH_GUICMI= $(GRAPH_GUICMO:.cmo=.cmi) GRAPH_GUICMX= $(GRAPH_GUICMO:.cmo=.cmx) GRAPH_GUIO= $(GRAPH_GUICMO:.cmo=.o) @@ -378,10 +421,12 @@ GEN_BYTE_GUI_LIBS+=$(GRAPH_GUICMO) GEN_OPT_GUI_LIBS+=$(GRAPH_GUICMX) -HAS_VIEWGRAPH=yes HAS_DGRAPH=yes -else # viewgraph and dgraph are not available +else # enable_gui is no: disable dgraph +HAS_DGRAPH=no +endif +else # gnome_canvas is not yes: disable dgraph HAS_DGRAPH=no endif @@ -391,14 +436,18 @@ BYTE_LIBS+= graph.cma OPT_LIBS+= graph.cmxa -# viewgraph and dgraph (included in ocamlgraph) +# and dgraph (included in ocamlgraph) ifeq ($(HAS_GNOMECANVAS),yes) -GRAPH_GUICMO_BASE= dgraph.cmo viewgraph.cmo +ifneq ($(ENABLE_GUI),no) +GRAPH_GUICMO_BASE= dgraph.cmo GRAPH_GUICMO=$(GRAPH_GUICMO_BASE:%=$(OCAMLGRAPH_HOME)/%) GRAPH_GUICMX= $(GRAPH_GUICMO:.cmo=.cmx) GRAPH_GUIO= $(GRAPH_GUICMO:.cmo=.o) HAS_DGRAPH=yes -else # viewgraph and dgraph not available +else # enable_gui is no: disable dgraph +HAS_DGRAPH=no +endif +else # gnome_canvas is not yes: disable dgraph HAS_DGRAPH=no endif @@ -407,7 +456,7 @@ # Redoing ocamlgraph on need ############################ -# If 'make untar-ocamlgraph' have to be performed after 'cvs update': +# If 'make untar-ocamlgraph' have to be performed after 'svn update': # change '.make-ocamlgraph-stamp' before 'cvs commit' .make-ocamlgraph: .make-ocamlgraph-stamp $(TOUCH) $@ @@ -424,7 +473,7 @@ include .make-ocamlgraph DISTRIB_FILES += .make-ocamlgraph -# force "make untar-ocamlgraph" to be executed for all users of CVS +# force "make untar-ocamlgraph" to be executed for all SVN users force-ocamlgraph: expr `$(CAT) .make-ocamlgraph-stamp` + 1 > .make-ocamlgraph-stamp @@ -440,10 +489,11 @@ # Frama-C Kernel # ################## -# Printexc library -################## +# Standard library compatibility layer +###################################### -GENERATED += src/lib/printexc_common_interface.ml +GENERATED += src/lib/printexc_common_interface.ml \ + src/lib/map_common_interface.mli src/lib/map_common_interface.ml ifeq ($(HAS_OCAML311),yes) # ocaml >= 3.11 @@ -463,6 +513,35 @@ endif +ifeq ($(HAS_OCAML312),yes) # ocaml >= 3.12 + +src/lib/map_common_interface.ml: src/lib/map_312_or_higher.ml \ + share/Makefile.config Makefile + $(PRINT_MAKING) $@ + $(CP) $< $@ + $(CHMOD_RO) $@ + +src/lib/map_common_interface.mli: src/lib/map_312_or_higher.mli \ + share/Makefile.config Makefile + $(PRINT_MAKING) $@ + $(CP) $< $@ + $(CHMOD_RO) $@ +else + +src/lib/map_common_interface.ml: src/lib/map_lower_312.ml \ + share/Makefile.config Makefile + $(PRINT_MAKING) $@ + $(CP) $< $@ + $(CHMOD_RO) $@ + +src/lib/map_common_interface.mli: src/lib/map_lower_312.mli \ + share/Makefile.config Makefile + $(PRINT_MAKING) $@ + $(CP) $< $@ + $(CHMOD_RO) $@ + +endif + # Dynlink library ################# @@ -507,15 +586,20 @@ $(CHMOD_RO) src/lib/dynlink_common_interface.ml $(PRINT_OCAMLC) $@ $(OCAMLC) -c $(BFLAGS) src/lib/dynlink_common_interface.ml - $(TOUCH) .depend -src/lib/dynlink_common_interface.o src/lib/dynlink_common_interface.cmx: src/lib/no_dynlink_opt.ml share/Makefile.config Makefile +src/lib/dynlink_common_interface.cmx: src/lib/no_dynlink_opt.ml \ + share/Makefile.config \ + Makefile $(PRINT_MAKING) src/lib/dynlink_common_interface.ml $(CP) $< src/lib/dynlink_common_interface.ml $(CHMOD_RO) src/lib/dynlink_common_interface.ml $(PRINT_OCAMLOPT) $@ $(OCAMLOPT) -c $(OFLAGS) src/lib/dynlink_common_interface.ml - $(TOUCH) .depend + +# force dependency order between these two files in order to not generate them +# in parallel since each of them generates the same .ml file +src/lib/dynlink_common_interface.cmx: src/lib/dynlink_common_interface.cmo +src/lib/dynlink_common_interface.o: src/lib/dynlink_common_interface.cmx endif @@ -542,23 +626,36 @@ $(PRINT_OCAMLC) $@ $(OCAMLC) -c $(BFLAGS) src/lib/dynlink_common_interface.ml -src/lib/dynlink_common_interface.o src/lib/dynlink_common_interface.cmx: src/lib/no_dynlink_opt.ml share/Makefile.config Makefile +src/lib/dynlink_common_interface.cmx: src/lib/no_dynlink_opt.ml \ + share/Makefile.config Makefile $(PRINT_MAKING) src/lib/dynlink_common_interface.ml $(CP) $< src/lib/dynlink_common_interface.ml $(CHMOD_RO) src/lib/dynlink_common_interface.ml $(PRINT_OCAMLOPT) $@ $(OCAMLOPT) -c $(OFLAGS) src/lib/dynlink_common_interface.ml +# force dependency order between these two files in order to not generate them +# in parallel since each of them generates the same .ml file +src/lib/dynlink_common_interface.cmx: src/lib/dynlink_common_interface.cmo +src/lib/dynlink_common_interface.o: src/lib/dynlink_common_interface.cmx + endif # Libraries which could be compiled fully independently ####################################################### EXTERNAL_LIB_CMO = unmarshal unmarshal_nums + +# Zarith +ifeq ($(HAS_ZARITH),yes) +EXTERNAL_LIB_CMO+= unz +endif + EXTERNAL_LIB_CMO:= $(patsubst %, external/%.cmo, $(EXTERNAL_LIB_CMO)) CMO += $(EXTERNAL_LIB_CMO) LIB_CMO = src/lib/printexc_common_interface \ + src/lib/map_common_interface \ src/lib/dynlink_common_interface \ src/type/structural_descr \ src/type/type \ @@ -568,9 +665,12 @@ src/lib/hook \ src/lib/bag \ src/lib/bitvector \ - src/lib/qstack + src/lib/qstack \ + src/lib/my_bigint + LIB_CMO:= $(addsuffix .cmo, $(LIB_CMO)) CMO += $(LIB_CMO) +NO_MLI+= src/lib/my_bigint.mli # Very first files to be linked (most modules use them) ############################### @@ -582,8 +682,11 @@ src/project/project_skeleton \ src/type/datatype \ src/kernel/journal \ + src/kernel/parameter \ + src/kernel/dynamic \ src/lib/rangemap \ + # project_skeleton requires log # datatype requires project_skeleton # rangemap requires datatype @@ -592,7 +695,8 @@ CMO += $(FIRST_CMO) #Project (Project_skeleton must be linked before Journal) -PROJECT_CMO= state \ +PROJECT_CMO= \ + state \ state_dependency_graph \ state_topological \ state_selection \ @@ -602,6 +706,18 @@ PROJECT_CMO:= $(patsubst %, src/project/%.cmo, $(PROJECT_CMO)) CMO += $(PROJECT_CMO) +# Kernel files usable by Cil +PRE_KERNEL_CMO= \ + src/kernel/plugin \ + src/kernel/kernel \ + src/kernel/emitter \ + src/lib/binary_cache \ + external/hptmap \ + src/lib/hptset \ + +PRE_KERNEL_CMO:= $(patsubst %, %.cmo, $(PRE_KERNEL_CMO)) +CMO += $(PRE_KERNEL_CMO) + # Cil ##### @@ -622,23 +738,23 @@ if gcc -D_GNUCC $< -o bin/machdep.exe ;then \ $(ECHO) "machdep.exe created succesfully."; \ else \ - $(RM) $@; exit 1; \ - fi + $(RM) $@; exit 1; \ + fi $(ECHO) "let gcc = {" >>$@ ./bin/machdep.exe >>$@ $(ECHO) " underscore_name = $(UNDERSCORE_NAME) ;" >> $@ $(ECHO) "}" >>$@ if cl /D_MSVC $< /Febin/machdep.exe /Fobin/machdep.obj ;then \ - $(ECHO) "let hasMSVC = true" >>$@; \ - else \ - $(ECHO) "let hasMSVC = false" >>$@; \ - fi + $(ECHO) "let hasMSVC = true" >>$@; \ + else \ + $(ECHO) "let hasMSVC = false" >>$@; \ + fi $(ECHO) "let msvc = {" >>$@ ./bin/machdep.exe >>$@ $(ECHO) " underscore_name = true ;" >> $@ $(ECHO) "}" >>$@ $(ECHO) \ - "let gccHas__builtin_va_list = $(HAVE_BUILTIN_VA_LIST)" >>$@ + "let gccHas__builtin_va_list = $(HAVE_BUILTIN_VA_LIST)" >>$@ $(ECHO) "let __thread_is_keyword = $(THREAD_IS_KEYWORD)" >>$@ $(ECHO) \ "$@ generated. You may have this file merged into Frama-C by developers." @@ -669,35 +785,34 @@ cil/ocamlutil/inthash.cmo $(STATS) cil/src/cil_datatype.cmo \ cil/ocamlutil/cilutil.cmo cil/ocamlutil/setWithNearest.cmo \ $(addprefix $(CIL_PATH)/, \ - cil_state_builder.cmo logic/utf8_logic.cmo \ - cilglobopt.cmo machdep_x86_16.cmo machdep_x86_32.cmo \ - machdep_x86_64.cmo machdep_ppc_32.cmo \ - machdep_ppc_32_diab.cmo machdep.cmo cil_const.cmo \ - logic/logic_env.cmo escape.cmo \ - logic/logic_const.cmo cil.cmo frontc/errorloc.cmo \ - frontc/cabs.cmo ext/expcompare.cmo \ - frontc/cabshelper.cmo frontc/whitetrack.cmo \ - logic/logic_utils.cmo logic/logic_builtin.cmo \ - logic/logic_print.cmo logic/logic_parser.cmo \ - logic/logic_lexer.cmo frontc/lexerhack.cmo \ - mergecil.cmo rmtmps.cmo logic/logic_typing.cmo \ - frontc/cprint.cmo frontc/cabscond.cmo \ - frontc/cabsvisit.cmo frontc/cabs2cil.cmo \ - frontc/clexer.cmo frontc/cparser.cmo \ - logic/logic_preprocess.cmo frontc/patch.cmo \ - frontc/frontc.cmo ext/obfuscate.cmo \ - ext/ciltools.cmo ext/callgraph.cmo \ - ext/dataflow.cmo ext/dominators.cmo ext/oneret.cmo \ - ext/cfg.cmo ext/usedef.cmo ext/liveness.cmo \ - ext/reachingdefs.cmo ext/availexpslv.cmo \ - ext/rmciltmps.cmo ext/deadcodeelim.cmo zrapp.cmo) \ - # end of addprefix + cil_state_builder.cmo logic/utf8_logic.cmo \ + cilglobopt.cmo machdep_x86_16.cmo machdep_x86_32.cmo \ + machdep_x86_64.cmo machdep_ppc_32.cmo \ + machdep.cmo cil_const.cmo \ + logic/logic_env.cmo escape.cmo \ + logic/logic_const.cmo cil.cmo frontc/errorloc.cmo \ + frontc/cabs.cmo ext/expcompare.cmo \ + frontc/cabshelper.cmo frontc/whitetrack.cmo \ + logic/logic_utils.cmo logic/logic_builtin.cmo \ + logic/logic_print.cmo logic/logic_parser.cmo \ + logic/logic_lexer.cmo frontc/lexerhack.cmo \ + mergecil.cmo rmtmps.cmo logic/logic_typing.cmo \ + frontc/cprint.cmo frontc/cabscond.cmo \ + frontc/cabsvisit.cmo frontc/cabs2cil.cmo \ + frontc/clexer.cmo frontc/cparser.cmo \ + logic/logic_preprocess.cmo \ + frontc/frontc.cmo ext/obfuscate.cmo \ + ext/ciltools.cmo ext/callgraph.cmo \ + ext/dataflow.cmo ext/dominators.cmo ext/oneret.cmo \ + ext/cfg.cmo ext/usedef.cmo ext/liveness.cmo \ + ext/reachingdefs.cmo ext/availexpslv.cmo \ + ext/rmciltmps.cmo ext/deadcodeelim.cmo) \ + # end of addprefix CMO += $(CIL_CMO) MLI_ONLY+= $(CIL_PATH)/cil_types.mli $(CIL_PATH)/logic/logic_ptree.mli NO_MLI+=cil/src/cilglobopt.mli \ cil/src/machdep_ppc_32.mli \ - cil/src/logic/logic_const.mli \ cil/src/frontc/cabs.mli \ cil/src/ext/expcompare.mli \ cil/src/logic/logic_lexer.mli \ @@ -733,30 +848,25 @@ # cannot use $(CONFIG_CMO) here :-( KERNEL_CMO= \ - src/kernel/dynamic.cmo \ - src/kernel/ast_printer.cmo \ src/kernel/ast_info.cmo \ - src/kernel/kernel_datatype.cmo \ - src/kernel/plugin.cmo \ - src/kernel/kernel.cmo \ + src/kernel/ast_printer.cmo \ + src/kernel/ast.cmo \ + src/logic/property.cmo \ + src/logic/property_status.cmo \ + src/kernel/annotations.cmo \ + src/kernel/globals.cmo \ + src/kernel/kernel_function.cmo \ + src/logic/description.cmo \ src/kernel/alarms.cmo \ src/kernel/cilE.cmo \ - src/memory_state/binary_cache.cmo \ - src/kernel/parameters.cmo \ src/kernel/messages.cmo \ - src/kernel/ast.cmo \ - src/ai/my_bigint.cmo \ - external/hptmap.cmo \ - src/memory_state/hptset.cmo \ src/ai/abstract_interp.cmo \ + src/ai/lattice_Interval_Set.cmo \ src/ai/int_Base.cmo \ src/kernel/unicode.cmo \ src/misc/bit_utils.cmo \ src/misc/subst.cmo \ - src/kernel/annotations.cmo \ - src/kernel/globals.cmo \ - src/kernel/kernel_function.cmo \ - src/misc/service_graph.cmo \ + src/misc/service_graph.cmo \ src/ai/ival.cmo \ src/ai/base.cmo \ src/ai/base_Set_Lattice.cmo \ @@ -768,24 +878,21 @@ src/memory_state/path_lattice.cmo \ src/memory_state/int_Interv.cmo \ src/memory_state/int_Interv_Map.cmo \ + src/memory_state/tr_offset.cmo \ src/memory_state/new_offsetmap.cmo \ src/memory_state/offsetmap.cmo \ src/memory_state/offsetmap_bitwise.cmo \ src/memory_state/lmap.cmo \ src/memory_state/lmap_bitwise.cmo \ - src/memory_state/lmap_whole.cmo \ src/memory_state/function_Froms.cmo \ - src/memory_state/cvalue_type.cmo \ + src/memory_state/cvalue.cmo \ src/memory_state/widen_type.cmo \ - src/memory_state/relations_type.cmo \ src/memory_state/state_set.cmo \ src/memory_state/state_imp.cmo \ src/kernel/stmts_graph.cmo \ src/kernel/visitor.cmo \ src/kernel/printer.cmo src/kernel/unroll_loops.cmo \ src/kernel/loop.cmo \ - src/logic/property.cmo \ - src/logic/properties_status.cmo \ $(PLUGIN_TYPES_CMO_LIST) \ src/kernel/db.cmo \ src/kernel/command.cmo \ @@ -801,17 +908,11 @@ CMO += $(KERNEL_CMO) -MLI_ONLY+= src/kernel/db_types.mli -NO_MLI+= src/ai/my_bigint.mli \ - src/ai/int_Base.mli \ - src/ai/base_Set_Lattice.mli \ - src/ai/origin.mli \ - src/ai/map_Lattice.mli \ +NO_MLI+= src/ai/map_Lattice.mli \ src/memory_state/abstract_value.mli \ src/memory_state/int_Interv_Map.mli \ src/memory_state/function_Froms.mli \ - src/memory_state/cvalue_type.mli \ - src/kernel/unroll_loops.mli \ + src/memory_state/cvalue.mli \ src/memory_state/widen.mli # Common startup module @@ -821,6 +922,25 @@ STARTUP_CMO=src/kernel/boot.cmo STARTUP_CMX=$(STARTUP_CMO:.cmo=.cmx) +# GUI modules +# See below for GUI compilation +############################################################################## + +SINGLE_GUI_CMO:= gui_parameters \ + gtk_form gtk_helper \ + source_viewer pretty_source source_manager book_manager \ + warning_manager \ + filetree \ + launcher \ + menu_manager \ + history \ + design \ + analyses_manager file_manager project_manager debug_manager \ + help_manager \ + property_navigator + +SINGLE_GUI_CMO:= $(patsubst %, src/gui/%.cmo, $(SINGLE_GUI_CMO)) + ############################################################################### # # #################### # @@ -828,8 +948,8 @@ #################### # # # # For 'internal' developpers: # -# Add your own plug-in here # -# # +# you can add your own plug-in here, # +# but it is better to have your own separated Makefile # ############################################################################### ################## @@ -855,10 +975,9 @@ PLUGIN_NAME:=Metrics PLUGIN_DISTRIBUTED:=yes PLUGIN_HAS_MLI:=yes -PLUGIN_NO_TEST:=yes PLUGIN_DIR:=src/metrics -PLUGIN_CMO:= metrics_parameters register -PLUGIN_NO_TEST:= yes +PLUGIN_CMO:= metrics_parameters css_html metrics_base \ + metrics_cabs metrics_cilast metrics_coverage register PLUGIN_GUI_CMO:=register_gui PLUGIN_INTERNAL_TEST:=yes include share/Makefile.plugin @@ -893,7 +1012,12 @@ PLUGIN_NAME:=Value PLUGIN_DIR:=src/value PLUGIN_CMO:= kf_state value_parameters library_functions mark_noresults \ - separate value_util builtins current_table eval kinstr register + separate value_util builtins \ + $(patsubst src/value/%.ml,%,\ + $(wildcard src/value/builtins_nonfree*.ml)) \ + current_table eval_exprs \ + non_linear initial_state locals_scoping \ + eval_logic eval_stmts eval_funs register PLUGIN_GUI_CMO:=register_gui PLUGIN_HAS_MLI:=yes PLUGIN_NO_TEST:=yes @@ -915,20 +1039,6 @@ PLUGIN_INTERNAL_TEST:=yes include share/Makefile.plugin -############################ -# Properties Status Report # -############################ - -PLUGIN_ENABLE:=$(ENABLE_REPORT) -PLUGIN_NAME:=Report -PLUGIN_DIR:=src/report -PLUGIN_CMO:= register -PLUGIN_HAS_MLI:=yes -PLUGIN_NO_TEST:=yes -PLUGIN_DISTRIBUTED:=yes -PLUGIN_INTERNAL_TEST:=yes -include share/Makefile.plugin - ################# # From analysis # ################# @@ -993,8 +1103,8 @@ PLUGIN_ENABLE:=$(ENABLE_INOUT) PLUGIN_NAME:=Inout PLUGIN_DIR:=src/inout -PLUGIN_CMO:= kf_state inout_parameters context inputs outputs derefs \ - access_path register +PLUGIN_CMO:= kf_state inout_parameters cumulative_analysis \ + operational_inputs inputs outputs derefs access_path register PLUGIN_TYPES_CMO:=src/memory_state/inout_type PLUGIN_HAS_MLI:=yes PLUGIN_NO_TEST:=yes @@ -1039,15 +1149,14 @@ PLUGIN_NAME:=Pdg PLUGIN_DIR:=src/pdg PLUGIN_HAS_MLI:=yes -PLUGIN_CMO:= pdg_parameters macros \ - lexical_successors \ - ctrlDpds \ +PLUGIN_CMO:= pdg_parameters \ + ctrlDpds \ pdg_state \ - build \ - sets \ - annot \ + build \ + sets \ + annot \ marks \ - register + register PDG_TYPES:=pdgIndex pdgTypes pdgMarks PDG_TYPES:=$(addprefix src/pdg_types/, $(PDG_TYPES)) @@ -1060,14 +1169,14 @@ PLUGIN_INTERNAL_TEST:=yes include share/Makefile.plugin -##################################### -# Scope : (very experimental !) # -##################################### +################################################ +# Scope : show different kinds of dependencies # +################################################ PLUGIN_ENABLE:=$(ENABLE_SCOPE) PLUGIN_NAME:=Scope PLUGIN_DIR:=src/scope -PLUGIN_CMO:= datascope zones +PLUGIN_CMO:= datascope zones defs PLUGIN_HAS_MLI:=yes PLUGIN_GUI_CMO:=dpds_gui PLUGIN_INTRO:=doc/code/intro_scope.txt @@ -1098,15 +1207,15 @@ PLUGIN_NAME:=Slicing PLUGIN_DIR:=src/slicing PLUGIN_CMO:= slicingParameters \ - slicingMacros \ - slicingMarks \ - slicingActions \ - fct_slice \ - printSlice \ - slicingProject \ + slicingMacros \ + slicingMarks \ + slicingActions \ + fct_slice \ + printSlice \ + slicingProject \ slicingTransform \ - slicingCmds \ - register + slicingCmds \ + register SLICING_TYPES:=slicingInternals slicingTypes SLICING_TYPES:=$(addprefix src/slicing_types/, $(SLICING_TYPES)) PLUGIN_TYPES_CMO:=$(SLICING_TYPES) @@ -1193,7 +1302,7 @@ $(GEN_BYTE_LIBS) $(PLUGIN_DYN_CMO_LIST) $(PRINT_OCAMLMKTOP) $@ $(OCAMLMKTOP) $(BFLAGS) -custom -o $@ $(BYTE_LIBS) \ - $(filter-out src/kernel/boot.cmo, $(ALL_BATCH_CMO)) \ + $(filter-out src/kernel/boot.cmo, $(ALL_BATCH_CMO)) \ src/toplevel/toplevel_topdirs.cmo bin/toplevel.opt$(EXE): $(ALL_BATCH_CMX) $(GEN_OPT_LIBS) $(PLUGIN_DYN_CMX_LIST) @@ -1236,7 +1345,6 @@ OPT_GUI_LIBS += lablgtk.cmxa FILES_FOR_OCAMLDEP+= src/gui/*.ml src/gui/*.mli -INSTALL_ICONS:=$(ICONS) ifeq ("$(OCAMLGRAPH_LOCAL)","") GUI_INCLUDES += $(OCAMLGRAPH) endif @@ -1276,6 +1384,7 @@ filetree \ launcher \ menu_manager \ + history \ design \ project_manager \ debug_manager \ @@ -1298,26 +1407,13 @@ else -SINGLE_GUI_CMO:= gui_parameters \ - gtk_form gtk_helper \ - source_viewer pretty_source source_manager \ - warning_manager \ - filetree \ - launcher \ - menu_manager \ - design \ - analyses_manager file_manager project_manager debug_manager \ - help_manager \ - property_navigator - -SINGLE_GUI_CMO:= $(patsubst %, src/gui/%.cmo, $(SINGLE_GUI_CMO)) - SINGLE_GUI_CMI = $(SINGLE_GUI_CMO:.cmo=.cmi) SINGLE_GUI_CMX = $(SINGLE_GUI_CMO:.cmo=.cmx) GUICMO += $(SINGLE_GUI_CMO) $(PLUGIN_GUI_CMO_LIST) -MODULES_TODOC+= $(SINGLE_GUI_CMO:.cmo=.mli) +MODULES_TODOC+= $(filter-out src/gui/book_manager.mli, \ + $(SINGLE_GUI_CMO:.cmo=.mli)) GUICMI = $(GUICMO:.cmo=.cmi) GUICMX = $(GUICMO:.cmo=.cmx) @@ -1366,7 +1462,7 @@ bin/viewer.opt$(EXE): $(filter-out $(GRAPH_GUICMX), $(ALL_GUI_CMX)) \ $(GEN_OPT_LIBS) $(GRAPH_GUIO) \ $(PLUGIN_DYN_CMX_LIST) $(PLUGIN_DYN_GUI_CMX_LIST) \ - $(PLUGIN_CMX_LIST) $(PLUGIN_GUI_CMX_LIST) + $(PLUGIN_CMX_LIST) $(PLUGIN_GUI_CMX_LIST) $(PRINT_LINKING) $@ $(OCAMLOPT) $(OLINKFLAGS) -o $@ $(OPT_LIBS) \ $(CMX) \ @@ -1439,14 +1535,17 @@ .PHONY: tests oracles btests tests_dist tests:: byte opt ptests $(PRINT_EXEC) ptests - time -p ./bin/ptests.byte$(EXE) $(PLUGIN_TESTS_LIST) + time -p ./bin/ptests.byte$(EXE) -make "$(MAKE)" $(PLUGIN_TESTS_LIST) + $(MAKE) external_tests + +external_tests: byte opt ptests for plugin in $(EXTERNAL_PLUGINS); do \ - if $(MAKE) --quiet FRAMAC_SHARE=$(FRAMAC_TOP_SRCDIR)/share -C $$plugin run_tests 2> /dev/null; \ + if $(MAKE) --quiet FRAMAC_SHARE=$(FRAMAC_TOP_SRCDIR)/share -C $$plugin run_tests 2> /dev/null; \ then \ if test -d tests/`basename $$plugin `; then \ echo ; \ echo "TESTING PLUG-IN `basename $$plugin ` (from frama-c)"; \ - time -p ./bin/ptests.byte$(EXE) `basename $$plugin `; \ + time -p ./bin/ptests.byte$(EXE) -make "$(MAKE)" `basename $$plugin `; \ else \ $(call external_make,$$plugin,tests); \ fi; \ @@ -1455,21 +1554,21 @@ oracles: opt ptests $(PRINT_MAKING) oracles - ./bin/ptests.byte$(EXE) $(PLUGIN_TESTS_LIST) > /dev/null 2>&1 - ./bin/ptests.byte$(EXE) -update $(PLUGIN_TESTS_LIST) + ./bin/ptests.byte$(EXE) -make "$(MAKE)" $(PLUGIN_TESTS_LIST) > /dev/null 2>&1 + ./bin/ptests.byte$(EXE) -make "$(MAKE)" -update $(PLUGIN_TESTS_LIST) btests: byte ptests $(PRINT_EXEC) ptests -byte - time -p ./bin/ptests.byte$(EXE) -byte $(PLUGIN_TESTS_LIST) + time -p ./bin/ptests.byte$(EXE) -make "$(MAKE)" -byte $(PLUGIN_TESTS_LIST) tests_dist: dist ptests $(PRINT_EXEC) ptests - time -p ./bin/ptests.byte$(EXE) $(PLUGIN_TESTS_LIST) + time -p ./bin/ptests.byte$(EXE) -make "$(MAKE)" $(PLUGIN_TESTS_LIST) # test only one test suite : make suite_tests %_tests: opt ptests $(PRINT_EXEC) ptests - ./bin/ptests.byte$(EXE) $($*_TESTS_OPTS) $* + ./bin/ptests.byte$(EXE) -make "$(MAKE)" $($*_TESTS_OPTS) $* # full test suite wp_TESTS_OPTS=-j 1 @@ -1531,7 +1630,7 @@ "--regex=/[ \t]*let[ \t]+rec[ \t]+\([^ \t]+\)/\1/" \ "--regex=/[ \t]*and[ \t]+\([^ \t]+\)/\1/" \ "--regex=/[ \t]*type[ \t]+\([^ \t]+\)/\1/" \ - "--regex=/[ \t]*exception[ \t]+\([^ \t]+\)/\1/" \ + "--regex=/[ \t]*exception[ \t]+\([^ \t]+\)/\1/" \ "--regex=/[ \t]*val[ \t]+\([^ \t]+\)/\1/" \ "--regex=/[ \t]*module[ \t]+\([^ \t]+\)/\1/" endif @@ -1545,19 +1644,13 @@ wc: ocamlwc -p external/*.ml* cil/*/*.ml cil/*/*.ml[ily] cil/src/*/*.ml[ily] cil/src/*/*.ml[ly] src/*/*.ml src/*/*.ml[iyl] -# private targets, usefull for recompiling the doc without dependencies +# private targets, useful for recompiling the doc without dependencies # (too long!) .PHONY: doc-kernel doc-index plugins-doc doc-update doc-tgz -ifeq ("$(OCAMLDOC)","ocamldoc.opt") -DOC_PLUGIN=$(DOC_DIR)/docgen.cmxs -else -DOC_PLUGIN=$(DOC_DIR)/docgen.cmo -endif - -DOC_DEPEND=$(MODULES_TODOC) byte $(DOC_PLUGIN) +DOC_DEPEND=$(MODULES_TODOC) bin/toplevel.byte$(EXE) $(DOC_PLUGIN) ifneq ($(ENABLE_GUI),no) -DOC_DEPEND+=bin/viewer.byte +DOC_DEPEND+=bin/viewer.byte$(EXE) endif $(DOC_DIR)/docgen.cmo: $(DOC_DIR)/docgen.ml @@ -1581,28 +1674,28 @@ $(addsuffix _DOC, $(PLUGIN_DISTRIBUTED_NAME_LIST)), \ $(PLUGIN_DOC_LIST))) -# to make the documentation for one pluggin only, -# the name of the pluggin should begin with a capital letter : +# to make the documentation for one plugin only, +# the name of the plugin should begin with a capital letter : # Example for the pdg doc : make Pdg_DOC -# While working on the documentation of a pluggin, it can also be usefull +# While working on the documentation of a plugin, it can also be useful # to use : make -o doc/code/kernel-doc.ocamldoc Plugin_DOC # to avoid redoing the global documentation each time. -DOC_FLAGS:= -colorize-code -stars -inv-merge-ml-mli -m A -hide-warnings \ - $(INCLUDES) $(GUI_INCLUDES) - STDLIB_FILES:=map set pervasives big_int list array string char marshal \ printf format scanf hashtbl buffer sys STDLIB_FILES:=$(patsubst %, $(OCAMLLIB)/%.mli, $(STDLIB_FILES)) -doc-kernel: $(DOC_DEPEND) +.PHONY: doc-kernel +doc-kernel: $(DOC_DIR)/kernel-doc.ocamldoc + +$(DOC_DIR)/kernel-doc.ocamldoc: $(DOC_DEPEND) $(PRINT_DOC) Kernel Documentation $(MKDIR) $(DOC_DIR)/html $(RM) $(DOC_DIR)/html/*.html $(OCAMLDOC) $(DOC_FLAGS) -I $(OCAMLLIB) \ $(addprefix -stdlib , $(STDLIB_FILES)) \ -t "Frama-C Kernel" \ - -sort -css-style ../style.css \ + -sort -css-style ../style.css \ -g $(DOC_PLUGIN) \ -d $(DOC_DIR)/html -dump $(DOC_DIR)/kernel-doc.ocamldoc \ $(MODULES_TODOC) @@ -1620,7 +1713,7 @@ doc-tgz: $(PRINT_MAKING) frama-c-api.tar.gz cd $(DOC_DIR); \ - $(TAR) zcf tmp.tgz index.html \ + $(TAR) zcf tmp.tgz index.html *.txt \ $(notdir $(wildcard $(DOC_DIR)/*.css $(DOC_DIR)/*.png)) html \ $(foreach p, $(PLUGIN_DISTRIBUTED_NAME_LIST), \ $(notdir $($(p)_DOC_DIR))) @@ -1709,7 +1802,9 @@ install-kernel-opt: $(PRINT_CP) native kernel API - $(CP) $(ALL_BATCH_CMX) $(filter %.o,$(ALL_BATCH_CMX:.cmx=.o)) \ + $(CP) $(ALL_BATCH_CMX) \ + $(filter %.a,$(ALL_BATCH_CMX:.cmxa=.a)) \ + $(filter %.o,$(ALL_BATCH_CMX:.cmx=.o)) \ $(FRAMAC_LIBDIR) $(CP) $(filter-out %.o, $(GEN_OPT_LIBS)) \ $(filter %.o,$(GEN_OPT_LIBS:.cmx=.o)) $(FRAMAC_LIBDIR) @@ -1719,14 +1814,21 @@ $(MKDIR) $(FRAMAC_LIBDIR) if [ "$(ENABLE_GUI)" != "no" ]; then \ $(CP) $(SINGLE_GUI_CMI) $(SINGLE_GUI_CMO) $(FRAMAC_LIBDIR); \ - fi + fi install-gui-opt: $(PRINT_CP) native gui API $(MKDIR) $(FRAMAC_LIBDIR) if [ "$(ENABLE_GUI)" != "no" -a "$(OCAMLBEST)" = "opt" ]; then \ - $(CP) $(SINGLE_GUI_CMX) $(SINGLE_GUI_CMX:.cmx=.o) $(FRAMAC_LIBDIR); \ - fi + $(CP) $(SINGLE_GUI_CMX) $(SINGLE_GUI_CMX:.cmx=.o) $(FRAMAC_LIBDIR); \ + fi + +install-doc-code: + $(PRINT_CP) API documentation + $(MKDIR) $(FRAMAC_DATADIR)/doc/code + (cd doc ; tar cf - --exclude='.svn' --exclude='*.toc' \ + --exclude='*.htm' --exclude='*.txt' code \ + | (cd $(FRAMAC_DATADIR)/doc ; tar xf -)) .PHONY: install install:: @@ -1734,28 +1836,31 @@ $(MKDIR) $(BINDIR) $(MKDIR) $(MANDIR)/man1 $(MKDIR) $(FRAMAC_PLUGINDIR)/gui + $(MKDIR) $(FRAMAC_DATADIR)/feedback $(MKDIR) $(FRAMAC_DATADIR)/libc/sys $(MKDIR) $(FRAMAC_DATADIR)/libc/netinet $(PRINT_CP) shared files - $(CP) -R share/frama-c.rc $(INSTALL_ICONS) \ + $(CP) \ share/*.c share/*.h share/acsl.el \ share/Makefile.dynamic share/Makefile.plugin share/Makefile.kernel \ share/Makefile.config share/Makefile.common share/configure.ac \ $(FRAMAC_DATADIR) + $(CP) share/frama-c.rc $(ICONS) $(FRAMAC_DATADIR) + $(CP) $(FEEDBACK_ICONS) $(FRAMAC_DATADIR)/feedback if [ -d $(EMACS_DATADIR) ]; then \ $(CP) share/acsl.el $(EMACS_DATADIR); \ fi $(CP) share/Makefile.dynamic_config.external \ - $(FRAMAC_DATADIR)/Makefile.dynamic_config + $(FRAMAC_DATADIR)/Makefile.dynamic_config $(PRINT_CP) C standard library - $(CP) -R share/libc/*.c share/libc/*.h $(FRAMAC_DATADIR)/libc - $(CP) -R share/libc/sys/*.h $(FRAMAC_DATADIR)/libc/sys - $(CP) -R share/libc/netinet/*.h $(FRAMAC_DATADIR)/libc/netinet + $(CP) share/libc/*.c share/libc/*.h $(FRAMAC_DATADIR)/libc + $(CP) share/libc/sys/*.h $(FRAMAC_DATADIR)/libc/sys + $(CP) share/libc/netinet/*.h $(FRAMAC_DATADIR)/libc/netinet $(PRINT_CP) binaries $(CP) bin/toplevel.$(OCAMLBEST) $(BINDIR)/frama-c$(EXE) $(CP) bin/toplevel.byte$(EXE) $(BINDIR)/frama-c.byte$(EXE) if [ -x bin/toplevel.top ] ; then \ - $(CP) bin/toplevel.top $(BINDIR)/frama-c.toplevel$(EXE); \ + $(CP) bin/toplevel.top $(BINDIR)/frama-c.toplevel$(EXE); \ fi if [ -x bin/viewer.$(OCAMLBEST) ] ; then \ $(CP) bin/viewer.$(OCAMLBEST) $(BINDIR)/frama-c-gui$(EXE);\ @@ -1764,17 +1869,24 @@ $(CP) bin/viewer.byte$(EXE) $(BINDIR)/frama-c-gui.byte$(EXE); \ fi $(CP) bin/ptests.byte$(EXE) $(BINDIR)/ptests.byte$(EXE) + $(PRINT_CP) config files $(CP) ptests/ptests_config.cmi $(FRAMAC_LIBDIR) $(PRINT_CP) manuals - if [ -d doc/manuals ]; then $(CP) -R doc/manuals $(FRAMAC_DATADIR); fi + if [ -d doc/manuals ]; then \ + $(MKDIR) $(FRAMAC_DATADIR)/manuals ; \ + $(CP) doc/manuals/*.pdf $(FRAMAC_DATADIR)/manuals ; \ + fi + $(PRINT_CP) API documentation + $(MKDIR) $(FRAMAC_DATADIR)/doc/code + $(CP) $(wildcard $(DOC_GEN_FILES)) $(FRAMAC_DATADIR)/doc/code $(PRINT_CP) dynamic plug-ins - if [ -d $(FRAMAC_PLUGIN) -a "$(PLUGIN_DYN_EXISTS)" = "yes" ]; then \ + if [ -d "$(FRAMAC_PLUGIN)" -a "$(PLUGIN_DYN_EXISTS)" = "yes" ]; then \ $(CP) $(patsubst %.cma,%.cmi,$(PLUGIN_DYN_CMO_LIST:%.cmo=%.cmi)) \ $(PLUGIN_DYN_CMO_LIST) $(PLUGIN_DYN_CMX_LIST) \ $(FRAMAC_PLUGINDIR); \ fi $(PRINT_CP) dynamic gui plug-ins - if [ -d $(FRAMAC_PLUGIN_GUI) -a "$(PLUGIN_DYN_GUI_EXISTS)" = "yes" ]; \ + if [ -d "$(FRAMAC_PLUGIN_GUI)" -a "$(PLUGIN_DYN_GUI_EXISTS)" = "yes" ]; \ then \ $(CP) $(PLUGIN_DYN_GUI_CMO_LIST:.cmo=.cmi) \ $(PLUGIN_DYN_GUI_CMO_LIST) $(PLUGIN_DYN_GUI_CMX_LIST) \ @@ -1792,16 +1904,28 @@ .PHONY: uninstall uninstall:: $(PRINT_RM) installed binaries - $(RM) $(BINDIR)/frama-c* $(BINDIR)/ptests.byte + $(RM) $(BINDIR)/frama-c* $(BINDIR)/ptests.byte$(EXE) $(PRINT_RM) installed shared files $(RM) -R $(FRAMAC_DATADIR) $(PRINT_RM) installed libraries $(RM) -R $(FRAMAC_LIBDIR) $(FRAMAC_PLUGINDIR) + $(PRINT_RM) installed man files + $(RM) $(MANDIR)/man1/frama-c.1 $(MANDIR)/man1/frama-c-gui.1 ################################ # File headers: license policy # ################################ +# Modify this variable if you add a new header +HEADERS:= MODIFIED_OCAMLGRAPH MODIFIED_MENHIR CEA_LGPL CEA_PROPRIETARY \ + CEA_INRIA_LGPL INRIA_LGPL \ + CIL MODIFIED_CAMLLIB INSA_INRIA_LGPL INRIA_BSD ACSL_EL JCF_LGPL \ + OCAML_STDLIB \ + AORAI_LGPL CEA_WP + +# Kernel licences +################# + MODIFIED_OCAMLGRAPH=src/project/state_topological.ml* MODIFIED_MENHIR=external/hptmap.ml* @@ -1812,15 +1936,12 @@ cil/src/frontc/*.ml* CEA_INRIA_LGPL = Makefile configure.in config.h.in \ - src/logic/*.ml* \ + src/logic/infer_annotations.ml* src/logic/logic_interp.ml* \ cil/src/logic/*.ml* \ src/pdg_types/*.ml* src/pdg/*.ml* doc/code/intro_pdg.txt \ src/slicing_types/*.ml* src/slicing/*.ml* doc/code/intro_slicing.txt \ src/scope/*.ml* doc/code/intro_scope.txt \ src/sparecode/*.ml* doc/code/intro_sparecode.txt \ - src/wp/*.ml* src/wp/configure.ac src/wp/Makefile.in \ - src/report/*.ml* \ - doc/code/intro_wp.txt \ man/frama-c.1 JCF_LGPL= @@ -1828,10 +1949,8 @@ OCAML_STDLIB=src/lib/rangemap.ml src/lib/rangemap.mli INRIA_LGPL= - INRIA_BSD= external/unmarshal*.ml* - -INSA_INRIA_LGPL= src/aorai/*.ml* src/aorai/Makefile.in src/aorai/configure.ac +INSA_INRIA_LGPL= CEA_LGPL= share/Makefile.config.in share/Makefile.common \ share/Makefile.plugin share/Makefile.dynamic \ @@ -1839,26 +1958,11 @@ share/Makefile.dynamic_config.external \ share/configure.ac configure.ml \ share/*.c share/*.h \ - src/wp/share/wp.v \ - src/wp/share/caveat_model.v \ - src/wp/share/caveat_model.why \ - src/wp/share/caveat_ergo92.why \ - src/wp/share/caveat_ergo91.why \ - src/wp/share/hoare_model.v \ - src/wp/share/hoare_model.why \ - src/wp/share/hoare_ergo92.why \ - src/wp/share/hoare_ergo91.why \ - src/wp/share/store_model.v \ - src/wp/share/store_model.why \ - src/wp/share/store_ergo92.why \ - src/wp/share/store_ergo91.why \ - src/wp/share/runtime_model.v \ - src/wp/share/runtime_model.why \ - src/wp/share/runtime_ergo92.why \ - src/wp/share/runtime_ergo91.why \ + src/report/*.ml* src/report/configure.ac src/report/Makefile.in \ share/libc/*.c share/libc/*.h \ share/libc/sys/*.h share/libc/netinet/*.h \ share/frama-c.WIN32.rc share/frama-c.Unix.rc \ + external/unz.ml* \ src/ai/*.ml* \ src/buckx/*.ml* src/buckx/*.[cS] \ src/constant_propagation/*.ml* \ @@ -1868,7 +1972,11 @@ src/impact/*.ml* \ src/kernel/*.ml* \ src/lib/*.ml* \ - src/logic/properties_status.ml* \ + src/logic/translate_lightweight.ml* \ + src/logic/description.ml* \ + src/logic/property.ml* \ + src/logic/property_status.ml* \ + src/logic/description.ml* \ src/memory_state/*.ml* \ src/metrics/*.ml* \ src/misc/*.ml* \ @@ -1896,46 +2004,114 @@ doc/code/style.css \ doc/code/intro_plugin.txt doc/code/intro_kernel_plugin.txt \ doc/code/toc_head.htm doc/code/toc_tail.htm \ - bin/lithium2beryllium.sh + bin/lithium2beryllium.sh bin/boron2carbon.sh bin/carbon2nitrogen.sh CEA_PROPRIETARY:= src/modular_dependencies/*.ml* \ - share/miel-mode.el \ + share/miel-mode.el \ + src/value/builtins_nonfree.ml \ src/finder/*.ml* src/finder/configure.ac src/finder/Makefile.in ACSL_EL := share/acsl.el -LICENSES= MODIFIED_OCAMLGRAPH MODIFIED_MENHIR CEA_LGPL CEA_PROPRIETARY \ - CEA_INRIA_LGPL INRIA_LGPL \ - CIL MODIFIED_CAMLLIB INSA_INRIA_LGPL INRIA_BSD ACSL_EL JCF_LGPL \ - OCAML_STDLIB +# Plug-in specific licences +########################### + +AORAI_LGPL:= src/aorai/*.ml* src/aorai/Makefile.in src/aorai/configure.ac + +CEA_WP:= \ + src/wp/*.ml* src/wp/configure.ac src/wp/Makefile.in \ + src/wp/share/wp.v \ + src/wp/share/caveat_model.v \ + src/wp/share/caveat_model.why \ + src/wp/share/caveat_ergo92.why \ + src/wp/share/caveat_ergo91.why \ + src/wp/share/hoare_model.v \ + src/wp/share/hoare_model.why \ + src/wp/share/hoare_ergo92.why \ + src/wp/share/hoare_ergo91.why \ + src/wp/share/store_model.v \ + src/wp/share/store_model.why \ + src/wp/share/store_ergo92.why \ + src/wp/share/store_ergo91.why \ + src/wp/share/runtime_model.v \ + src/wp/share/runtime_model.why \ + src/wp/share/runtime_ergo92.why \ + src/wp/share/runtime_ergo91.why \ + doc/code/intro_wp.txt + +# Generating headers +#################### .PHONY: headers headers:: $(GENERATED) @echo "Applying Headers..." - $(foreach l,$(LICENSES),\ + $(foreach l,$(HEADERS),\ $(foreach f,$(wildcard $($l)),$(shell if test -f $f; then \ $(HEADACHE) -h headers/$l $f; fi))) -NO_CHECK_HEADERS=cil/doc/* cil/doc/*/* cil/src/legacy/* \ - tests/*/* doc/manuals/*.pdf \ - doc/README cil/LICENSE cil/CHANGES Changelog .make* \ - licenses/* VERSION INSTALL bin/sed* \ - share/Makefile.kernel $(ICONS) \ - INSTALL_WITH_WHY +headers:: + $(MKDIR) aorai-example-tmp-dir + cd aorai-example-tmp-dir; $(TAR) xzf ../doc/manuals/aorai-example.tgz + $(CP) headers/INSA_INRIA_LGPL aorai-example-tmp-dir/example/LICENSE + $(ISED) -e 's/This file is/Files in this archive are/' \ + aorai-example-tmp-dir/example/LICENSE + $(RM) doc/manuals/aorai-example.tgz + cd aorai-example-tmp-dir; \ + $(TAR) czf ../doc/manuals/aorai-example.tgz example/ + $(RM) -r aorai-example-tmp-dir + +NO_CHECK_HEADERS=cil/doc/* cil/doc/*/* \ + tests/*/* doc/manuals/*.pdf doc/manuals/aorai-example.tgz \ + doc/README cil/LICENSE cil/CHANGES Changelog .make* \ + licenses/* VERSION INSTALL bin/sed* \ + share/Makefile.kernel $(ICONS) $(FEEDBACK_ICONS) \ + INSTALL_WITH_WHY doc/manuals/aorai-example.tgz -.PHONY: check-headers +.PHONY: check-headers check-headers-xunit check-headers: $(GENERATED) @echo "Checking Headers..." EXIT_VALUE=0; \ $(foreach f,$(wildcard $(DISTRIB_FILES)),\ $(if $(findstring $(f),\ - $(wildcard $(NO_CHECK_HEADERS)) \ - $(foreach l,$(LICENSES),$(wildcard $($l)))),,\ - EXIT_VALUE=1; \ - echo "file $(f) does not have a proper license";)) \ + $(wildcard $(NO_CHECK_HEADERS)) \ + $(foreach l,$(HEADERS),$(wildcard $($l)))),,\ + EXIT_VALUE=1; \ + echo "file $(f) does not have a proper license";)) \ exit $$EXIT_VALUE +check-headers-xunit: $(GENERATED) + @echo '' > check-headers-xunit.xml + @echo '' >> check-headers-xunit.xml + @TIME=`date +%Y-%m-%dT%T`; \ + echo "> check-headers-xunit.xml; \ + echo "id=\"0\" timestamp=\"$$TIME\" hostname=\"`hostname`\" " \ + >> check-headers-xunit.xml; \ + echo "time=\"0\" errors=\"0\" skipped=\"0\" SUMMARY>" \ + >> check-headers-xunit.xml; \ + NB_HEADERS=0; NB_NO_LICENSE=0; \ + for f in $(wildcard $(DISTRIB_FILES)); do \ + NB_HEADERS=$$(($$NB_HEADERS + 1)); \ + echo "> check-headers-xunit.xml; \ + if echo "$(wildcard $(NO_CHECK_HEADERS)) \ + $(foreach l,$(HEADERS),$(wildcard $($l)))" | \ + grep -q -e $$f; then \ + echo '/>' >> check-headers-xunit.xml; \ + else \ + NB_NO_LICENSE=$$(($$NB_NO_LICENSE + 1)); \ + echo '>' >> check-headers-xunit.xml; \ + echo '' \ + >> check-headers-xunit.xml; \ + fi; \ + done; \ + $(ISED) -e \ + "s/SUMMARY/tests=\"$$NB_HEADERS\" failures=\"$$NB_NO_LICENSE\"/" \ + check-headers-xunit.xml; \ + echo "" >> check-headers-xunit.xml; \ + echo "" >> check-headers-xunit.xml + ######################################################################## # Makefile is rebuilt whenever Makefile.in or configure.in is modified # ######################################################################## @@ -2078,7 +2254,7 @@ .depend depend:: $(GENERATED) share/Makefile.dynamic_config share/Makefile.kernel $(PLUGIN_DEP_LIST:%=%_DEP) $(PRINT_MAKING) .depend - $(RM) .depend + $(CHMOD_RW) .depend if test "$(PLUGIN_DEP_LIST)" != " "; then \ $(CAT) $(foreach d, $(PLUGIN_DEP_LIST), $(dir $d).depend) \ > .depend; \ @@ -2088,8 +2264,6 @@ $(OCAMLDEP) $(DEP_FLAGS) $(FILES_FOR_OCAMLDEP) >> .depend $(CHMOD_RO) .depend -$(ALL_CMO) $(ALL_CMX): | .depend - include .depend ##################### @@ -2108,12 +2282,12 @@ bin/ptests.byte$(EXE): $(PTESTS_SRC) $(PRINT_LINKING) $@ $(OCAMLC) -I ptests -dtypes -thread -g -o $@ \ - unix.cma threads.cma str.cma dynlink.cma $^ + unix.cma threads.cma str.cma dynlink.cma $^ else bin/ptests.byte$(EXE): $(PTESTS_SRC) $(PRINT_LINKING) $@ $(OCAMLC) -I ptests -dtypes -vmthread -g -o $@ \ - unix.cma threads.cma str.cma dynlink.cma $^ + unix.cma threads.cma str.cma dynlink.cma $^ endif #bin/ptests.opt$(EXE): $(PTESTS_SRC) # $(PRINT_LINKING) $@ @@ -2131,10 +2305,10 @@ $(TOUCH) $@; \ fi $(ECHO) \ - "let default_suites : string list ref = ref [" $(PLUGIN_TESTS_LIST:%='"%";') "];;" >> $@ + "let default_suites : string list ref = ref [" $(PLUGIN_TESTS_LIST:%='"%";') "];;" >> $@ $(ECHO) \ "let no_native_dynlink = " \ - $(subst yes,false,$(subst no,true,$(USABLE_NATIVE_DYNLINK))) ";;" \ + $(subst yes,false,$(subst no,true,$(USABLE_NATIVE_DYNLINK))) ";;" \ >> $@ $(ECHO) \ "let toplevel_path = ref \"bin/toplevel.$(OCAMLBEST)$(EXE)\";;" >> $@ @@ -2165,13 +2339,15 @@ $(addprefix src/dummy/untyped_metrics/, count_for.ml Makefile) DISTRIB_FILES+= $(PLUGIN_DISTRIBUTED_LIST) $(PLUGIN_DIST_EXTERNAL_LIST) \ - $(PLUGIN_DIST_DOC_LIST) $(STANDALONE_PLUGINS_FILES) + $(PLUGIN_DIST_DOC_LIST) $(STANDALONE_PLUGINS_FILES) EXPORT=frama-c-$(VERSION) src-distrib: src-distrib-ocamlgraph $(PRINT_TAR) tmp-distrib - $(TAR) cf tmp.tar $(DISTRIB_FILES) + $(TAR) cf tmp.tar \ + $(filter-out src/value/builtins_nonfree.ml, \ + $(wildcard $(DISTRIB_FILES))) $(PRINT_MAKING) export directories $(MKDIR) $(EXPORT)/bin $(MKDIR) $(EXPORT)/lib/plugins @@ -2186,7 +2362,7 @@ for dir in $(EXPORT)/tests/*; do \ $(MKDIR) $$dir/result; \ $(MKDIR) $$dir/oracle; \ - done + done $(PRINT_MAKING) archive $(TAR) czf frama-c-src.tar.gz $(EXPORT) $(PRINT) Cleaning diff -Nru frama-c-20110201+carbon+dfsg/.make-ocamlgraph-stamp frama-c-20111001+nitrogen+dfsg/.make-ocamlgraph-stamp --- frama-c-20110201+carbon+dfsg/.make-ocamlgraph-stamp 2011-02-07 13:42:20.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/.make-ocamlgraph-stamp 2011-10-10 08:40:09.000000000 +0000 @@ -1 +1 @@ -65 +71 diff -Nru frama-c-20110201+carbon+dfsg/man/frama-c.1 frama-c-20111001+nitrogen+dfsg/man/frama-c.1 --- frama-c-20110201+carbon+dfsg/man/frama-c.1 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/man/frama-c.1 2011-10-10 08:40:09.000000000 +0000 @@ -22,7 +22,7 @@ .\" .\" -.TH FRAMA-C 1 2010-12-17 +.TH FRAMA-C 1 2011-02-22 .SH NAME frama-c[.byte] \- a static analyzer for C programs @@ -132,6 +132,11 @@ .B -pp-annot for that. .TP +.BI \-big\-ints\-hex\ max +integers larger than +.I max +are displayed in hexadecimal (by default, all integers are displayed in decimal) +.TP .B [-no]-collapse-call-cast allows implicit cast between the value returned by a function and the lval it is assigned to. Otherwise, a temporary variable is used and the cast is @@ -195,6 +200,9 @@ .B -float-hex display floats as hexadecimal .TP +.B -float-normal +display floats with standard Ocaml routine +.TP .B -float-relative display float interval as [ .IR lower_bound ++ width\ ] @@ -272,7 +280,8 @@ integer types, endiandness, ...). The list of currently supported machines is available through .B -machdep help -option. +option. Default is +.B x86_32 .TP .BI -main\ f Sets @@ -346,6 +355,21 @@ removes break, continue and switch statement before analyses. Defaults to no. .TP +.B -then +allows to compose analyzes: a first run of Frama-C will occur with the +options before +.B -then +and a second run will be done with the options after +.B -then +on the current project from the first run. +.TP +.BI \-then\-on\ prj +Similar to +.B -then +except that the second run is performed in project +.I prj +If no such project exists, Frama-C exits with an error. +.TP .BI -time\ file outputs user time and date in the given .I file @@ -393,6 +417,35 @@ .PP will give the list of options that are specific to the plugin. +.SH EXIT STATUS +.TP +.B 0 +Successful execution +.TP +.B 1 +Invalid user input +.TP +.B 2 +User interruption (kill or equivalent) +.TP +.B 3 +Unimplemented feature +.TP +.B 4 +Internal error +.TP +.B 5 +Error while exiting normally +.TP +.B 6 +Error while exiting abnormally +.TP +.B 125 +Unknown error +.P +Exit status greater than 2 can be considered as a bug (or a feature request +for the case of exit status 3) and may be reported on Frama-C's BTS (see below). + .SH ENVIRONMENT VARIABLES It is possible to control the places where Frama-C looks for its files through the following variables. @@ -408,5 +461,10 @@ The directory where Frama-C datas are installed. .SH SEE ALSO -.IR Frama-C\ homepage , +.BR Frama-C\ user\ manual :\ $FRAMAC_SHARE /manuals/user-manual.pdf +.P +.BR Frama-C\ homepage : http://frama-c.com +.P +.BR Frama-C\ BTS : +http://bts.frama-c.com diff -Nru frama-c-20110201+carbon+dfsg/ptests/ptests_config.ml frama-c-20111001+nitrogen+dfsg/ptests/ptests_config.ml --- frama-c-20110201+carbon+dfsg/ptests/ptests_config.ml 2011-02-07 14:02:38.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/ptests/ptests_config.ml 2011-10-10 08:56:36.000000000 +0000 @@ -1,4 +1,4 @@ -let default_suites : string list ref = ref [ "occurrence"; "rte"; "idct"; "test"; "float"; "constant_propagation"; "impact"; "pdg"; "scope"; "sparecode"; "slicing"; "slicing2"; "aorai"; "dynamic"; "dynamic_plugin"; "journal"; "saveload"; "spec"; "misc"; ];; +let default_suites : string list ref = ref [ "occurrence"; "metrics"; "rte"; "idct"; "test"; "float"; "constant_propagation"; "impact"; "pdg"; "scope"; "sparecode"; "slicing"; "slicing2"; "dynamic"; "dynamic_plugin"; "journal"; "saveload"; "spec"; "misc"; ];; let no_native_dynlink = false ;; let toplevel_path = ref "bin/toplevel.opt";; let framac_share = ref (Filename.concat Filename.current_dir_name "share");; diff -Nru frama-c-20110201+carbon+dfsg/ptests/ptests.ml frama-c-20111001+nitrogen+dfsg/ptests/ptests.ml --- frama-c-20110201+carbon+dfsg/ptests/ptests.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/ptests/ptests.ml 2011-10-10 08:38:06.000000000 +0000 @@ -42,8 +42,8 @@ let cygpath r = let cmd = Format.sprintf - "bash -c \"cygpath -m %s\"" - (String.escaped (String.escaped r)) + "bash -c \"cygpath -m %s\"" + (String.escaped (String.escaped r)) in let in_channel = Unix.open_process_in cmd in let result = input_line in_channel in @@ -53,7 +53,7 @@ let temp_file = if Sys.os_type = "Win32" then fun a b -> let r = temp_file a b in - cygpath r + cygpath r else fun a b -> temp_file a b end @@ -70,9 +70,9 @@ match !default_env with [] -> () | l -> - Format.fprintf fmt "@[Env:@\n"; - List.iter (fun (x,y) -> Format.fprintf fmt "%s = \"%s\"@\n" x y) l; - Format.fprintf fmt "@]" + Format.fprintf fmt "@[Env:@\n"; + List.iter (fun (x,y) -> Format.fprintf fmt "%s = \"%s\"@\n" x y) l; + Format.fprintf fmt "@]" let default_env var value = try ignore (Unix.getenv var) with Not_found -> add_env var value @@ -100,11 +100,15 @@ (** the pattern that ends the parsing of options in a test file *) let end_comment = Str.regexp ".*\\*/" -let opt_to_byte = - let opt = Str.regexp "[.]opt\\($\\|[ \t]\\)" in - function toplevel -> - if toplevel = "frama-c" then "frama-c.byte" - else Str.global_replace opt ".byte\\1" toplevel +let regex_opt = Str.regexp ("\\([^/]+\\)[.]opt\\($\\|[ \t]\\)") +let regex_cmxs = Str.regexp ("\\([^/]+\\)[.]cmxs\\($\\|[ \t]\\)") + +let opt_to_byte toplevel = + if toplevel = "frama-c" then "frama-c.byte" + else Str.global_replace regex_opt "\\1.byte\\2" toplevel + +let opt_to_byte_options options = + Str.global_replace regex_cmxs "\\1.cmo\\2" options let needs_byte options = Ptests_config.no_native_dynlink && @@ -115,18 +119,14 @@ Ptests_config.no_native_dynlink && Str.string_match (Str.regexp ".*make.*[.]cmxs") cmd 0 -let execnow_opt_to_byte = - let test_regexp r = Filename.concat test_path r in - let opt = Str.regexp (test_regexp "\\(.+\\)[.]opt\\($\\|[ \t]\\)") in - let cmxs = Str.regexp (test_regexp "\\(.+\\)[.]cmxs\\($\\|[ \t]\\)") in - fun cmd -> - let cmd = Str.global_replace opt (test_regexp "\\1.byte\\2") cmd in - Str.global_replace cmxs (test_regexp "\\1.cmo\\2") cmd +let execnow_opt_to_byte cmd = + let cmd = opt_to_byte cmd in + opt_to_byte_options cmd let base_path = Filename.current_dir_name (* (Filename.concat (Filename.dirname Sys.executable_name) - Filename.parent_dir_name) + Filename.parent_dir_name) *) let ptests_config = "ptests_local_config.cmo" @@ -139,20 +139,24 @@ let use_byte = ref false let use_diff_as_cmp = ref (Sys.os_type = "Win32") let do_diffs = ref (if Sys.os_type = "Win32" then "diff --strip-trailing-cr -u" - else "diff -u") + else "diff -u") let do_cmp = ref (if Sys.os_type="Win32" then !do_diffs else "cmp -s") +let do_make = ref "make" let n = ref 4 (* the level of parallelism *) let suites = ref [] (** options given to toplevel for all tests *) let additional_options = ref "" (** special configuration, with associated oracles *) let special_config = ref "" +let do_error_code = ref false let exclude_suites = ref [] let exclude s = exclude_suites := s :: !exclude_suites +let xunit = ref false + let io_mutex = Mutex.create () let lock_fprintf f = @@ -186,40 +190,85 @@ locale *) ;; -let () = Arg.parse +let example_msg = + Format.sprintf + "@.@[\ + A test suite can be the name of a directory in ./tests or \ + the path to a file.@ @ \ + @[\ + Examples:@ \ + ptests@ \ + ptests -diff \"echo diff\" -examine \ + # see again the list of tests that failed@ \ + ptests misc \ + # for a single test suite@ \ + ptests tests/misc/alias.c \ + # for a single test@ \ + ptests -examine tests/misc/alias.c \ + # to see the differences again@ \ + ptests -v -j 1 \ + # to check the time taken by each test\ + @]@ @]" +;; + +let umsg = "Usage: ptests [options] [names of test suites]";; + +let rec argspec = [ - "", Arg.Unit (fun () -> ()) , "" ; - "-examine", Arg.Unit (fun () -> behavior := Examine) , - " Examine the logs that are different from oracles."; - "-update", Arg.Unit (fun () -> behavior := Update) , - " Take the current logs as oracles."; - "-show", Arg.Unit (fun () -> behavior := Show; use_byte := true) , - " Show the results of the tests. Sets -byte."; - "-run", Arg.Unit (fun () -> behavior := Run) , - "(default) Delete the logs, run the tests, then examine the logs that are different from the oracles."; - "", Arg.Unit (fun () -> ()) , "" ; - "-v", Arg.Unit (fun () -> incr verbosity), " Increase verbosity (up to twice)" ; - "-diff", Arg.String (fun s -> do_diffs := s; - if !use_diff_as_cmp then do_cmp := s), - " Use command for diffs" ; - "-cmp", Arg.String (fun s -> do_cmp:=s), - " Use command for comparison"; - "-use-diff-as-cmp", - Arg.Unit (fun () -> use_diff_as_cmp:=true; do_cmp:=!do_diffs), - "use the diff command for performing comparisons"; - "-j", Arg.Int (fun i -> if i>=0 then n := i else ( lock_printf "Option -j requires nonnegative argument@."; exit (-1))), " Use nonnegative integer n for level of parallelism" ; - "-byte", Arg.Set use_byte, " Use bytecode toplevel"; - "-opt", Arg.Clear use_byte, " Use native toplevel (default)"; - "-config", Arg.Set_string special_config, " Use special configuration \ - and oracles"; - "-add-options", Arg.Set_string additional_options, - "add additional options to be passed to the toplevels \ - that will be launched"; - "-exclude", Arg.String exclude, "exclude a test or a suite from the run"; - "", Arg.Unit (fun () -> ()) ,"\nA test suite can be the name of a directory in ./tests or the path to a file.\n\nExamples:\nptests\nptests -diff \"echo diff\" -examine # see again the list of tests that failed\nptests misc # for a single test suite\nptests tests/misc/alias.c # for a single test\nptests -examine tests/misc/alias.c # to see the differences again\nptests -v -j 1 # to check the time taken by each test\n" - ] - make_test_suite - "usage: ptests [options] [names of test suites]" + "-examine", Arg.Unit (fun () -> behavior := Examine) , + " Examine the logs that are different from oracles."; + "-update", Arg.Unit (fun () -> behavior := Update) , + " Take the current logs as oracles."; + "-show", Arg.Unit (fun () -> behavior := Show; use_byte := true) , + " Show the results of the tests. Sets -byte."; + "-run", Arg.Unit (fun () -> behavior := Run) , + " (default) Delete logs, run tests, then examine logs different from \ + oracles."; + "-v", Arg.Unit (fun () -> incr verbosity), + " Increase verbosity (up to twice)" ; + "-diff", Arg.String (fun s -> do_diffs := s; + if !use_diff_as_cmp then do_cmp := s), + " Use command for diffs" ; + "-cmp", Arg.String (fun s -> do_cmp:=s), + " Use command for comparison"; + "-make", Arg.String (fun s -> do_make := s;), + " Use command instead of make"; + "-use-diff-as-cmp", + Arg.Unit (fun () -> use_diff_as_cmp:=true; do_cmp:=!do_diffs), + " Use the diff command for performing comparisons"; + "-j", Arg.Int + (fun i -> if i>=0 + then n := i + else ( lock_printf "Option -j requires nonnegative argument@."; + exit (-1))), + " Use nonnegative integer n for level of parallelism" ; + "-byte", Arg.Set use_byte, + " Use bytecode toplevel"; + "-opt", Arg.Clear use_byte, + " Use native toplevel (default)"; + "-config", Arg.Set_string special_config, + " Use special configuration and oracles"; + "-add-options", Arg.Set_string additional_options, + " Add additional options to be passed to the toplevels that will be launched"; + "-exclude", Arg.String exclude, + " Exclude a test or a suite from the run"; + "-xunit", Arg.Set xunit, + " Create a xUnit file named xunit.xml collecting results"; + "-error-code", Arg.Set do_error_code, + " Exit with error code 1 if tests failed (useful for scripts"; +] +and help_msg () = Arg.usage (Arg.align argspec) umsg;; + +let () = + Arg.parse + ((Arg.align + (List.sort + (fun (optname1, _, _) (optname2, _, _) -> + Pervasives.compare optname1 optname2 + ) argspec) + ) @ ["", Arg.Unit (fun () -> ()), example_msg;]) + make_test_suite umsg +;; (* redefine config file if special configuration expected *) let dir_config_file = @@ -266,7 +315,7 @@ dc_default_toplevel : string; (** full path of the default toplevel. *) dc_filter : string option; (** optional filter to apply to - standard output *) + standard output *) dc_toplevels : (string * string) list; (** toplevel full path and options to launch the toplevel on *) dc_dont_run : bool; @@ -292,33 +341,49 @@ lock_printf "%% Couldn't execute command. Retrying once.@."; Thread.delay 0.1; ( match system command_string with - Unix.WEXITED r when r <> 127 -> r + Unix.WEXITED r when r <> 127 -> r | _ -> lock_printf "%% Retry failed with command:@\n%s@\nStopping@." - command_string ; + command_string ; exit 1 ) | Unix.WEXITED r -> r | Unix.WSIGNALED s -> - lock_printf "%% SIGNAL %d received while executing command:@\n%s@\nStopping@." - s command_string ; + lock_printf + "%% SIGNAL %d received while executing command:@\n%s@\nStopping@." + s command_string ; exit 1 | Unix.WSTOPPED s -> - lock_printf "%% STOP %d received while executing command:@\n%s@\nStopping@." - s command_string; + lock_printf + "%% STOP %d received while executing command:@\n%s@\nStopping@." + s command_string; exit 1 +let replace_toplevel s = + if Str.string_match toplevel_regex s 0 then + Str.replace_matched ("\\1" ^ !Ptests_config.toplevel_path ^ "\\2") s + else s + let scan_execnow dir (s:string) = let rec aux (s:execnow) = try Scanf.sscanf s.ex_cmd "%_[ ]LOG%_[ ]%[A-Za-z0-9_',+=:.\\-]%_[ ]%s@\n" - (fun name cmd -> - aux { s with ex_cmd = cmd; ex_log = name :: s.ex_log }) + (fun name cmd -> + let cmd = replace_toplevel cmd in + aux { s with ex_cmd = cmd; ex_log = name :: s.ex_log }) with Scanf.Scan_failure _ -> try - Scanf.sscanf s.ex_cmd "%_[ ]BIN%_[ ]%[A-Za-z0-9_.\\-]%_[ ]%s@\n" - (fun name cmd -> - aux { s with ex_cmd = cmd; ex_bin = name :: s.ex_bin }) + Scanf.sscanf s.ex_cmd "%_[ ]BIN%_[ ]%[A-Za-z0-9_.\\-]%_[ ]%s@\n" + (fun name cmd -> + let cmd = replace_toplevel cmd in + aux { s with ex_cmd = cmd; ex_bin = name :: s.ex_bin }) with Scanf.Scan_failure _ -> - s + try + Scanf.sscanf s.ex_cmd "%_[ ]make%_[ ]%s@\n" + (fun cmd -> + let cmd = replace_toplevel cmd in + let s = aux ({ s with ex_cmd = cmd; }) in + { s with ex_cmd = !do_make^" "^cmd; } ) + with Scanf.Scan_failure _ -> + s in aux { ex_cmd = s; ex_log = []; ex_bin = []; ex_dir = dir } @@ -332,7 +397,7 @@ Scanf.sscanf s "%_[ ]%1[+\\-]%_[ ]\"%s@\"%_[ ]%s@\n" (fun c opt rem -> match c with - "+" -> aux (opt :: opts) rem + | "+" -> aux (opt :: opts) rem | "-" -> aux (List.filter (fun x -> x <> opt) opts) rem | _ -> assert false (* format of scanned string disallow it *)) with @@ -342,9 +407,15 @@ opts | End_of_file -> opts in + (* NB: current settings does not allow to remove a multiple-argument + option (e.g. -verbose 2). + *) + (* revert the initial list, as it will be reverted back in the end. *) let opts = - aux (Str.split (Str.regexp " ") stdopts) s - in List.fold_left (fun s x -> s ^ " " ^ x) "" opts + aux (List.rev (Str.split (Str.regexp " ") stdopts)) s + in + (* preserve options ordering *) + List.fold_right (fun x s -> s ^ " " ^ x) opts "" (* how to process options *) let config_options = @@ -425,8 +496,8 @@ with End_of_file -> (match !r.dc_toplevels with - [] -> { !r with dc_toplevels = default.dc_toplevels } - | l -> { !r with dc_toplevels = List.rev l }) + | [] -> { !r with dc_toplevels = default.dc_toplevels } + | l -> { !r with dc_toplevels = List.rev l }) let scan_test_file default dir f = let f = Filename.concat dir f in @@ -437,19 +508,19 @@ in if exists_as_file then begin let scan_buffer = Scanf.Scanning.from_file f in - let rec scan_config () = - (* space in format string matches any number of whitespace *) + let rec scan_config () = + (* space in format string matches any number of whitespace *) Scanf.bscanf scan_buffer " /* run.config%s " - (fun name -> - if not - (!special_config = "" && name = "" - || name = "_" ^ !special_config) - then - (ignore (scan_options dir scan_buffer default); - scan_config ())) - in + (fun name -> + if not + (!special_config = "" && name = "" + || name = "_" ^ !special_config) + then + (ignore (scan_options dir scan_buffer default); + scan_config ())) + in try - scan_config (); + scan_config (); scan_options dir scan_buffer default with End_of_file | Scanf.Scan_failure _ -> default end else @@ -529,7 +600,7 @@ with Invalid_argument _ -> failwith ("This test file does not have any extension: " ^ - command.file) + command.file) let gen_prefix s cmd = let prefix = gen_make_file s cmd.directory (name_without_extension cmd) in @@ -544,9 +615,9 @@ || Str.string_match (Str.regexp ".*frama-c.*") command.toplevel 0 in command.toplevel ^ " " ^ - command.options ^ " " ^ - (if is_framac_toplevel then !additional_options ^ " " else "") ^ - (Filename.concat command.directory command.file) + (Filename.concat command.directory command.file) ^ " " ^ + command.options ^ + (if is_framac_toplevel then " " ^ !additional_options else "") let command_string command = let log_prefix = log_prefix command in @@ -564,29 +635,28 @@ let filter = match command.filter with | None -> None | Some filter -> - let len = String.length filter in - let rec split_filter i = - if i < len && filter.[i] = ' ' then split_filter (i+1) - else - try - let idx = String.index_from filter i ' ' in - String.sub filter i idx, - String.sub filter idx (len - idx) - with Not_found -> - String.sub filter i (len - i), "" - in - let exec_name, params = split_filter 0 in + let len = String.length filter in + let rec split_filter i = + if i < len && filter.[i] = ' ' then split_filter (i+1) + else + try + let idx = String.index_from filter i ' ' in + String.sub filter i idx, + String.sub filter idx (len - idx) + with Not_found -> + String.sub filter i (len - i), "" + in + let exec_name, params = split_filter 0 in let exec_name = - if Sys.file_exists exec_name || not (Filename.is_relative exec_name) + if Sys.file_exists exec_name || not (Filename.is_relative exec_name) then exec_name - else - Filename.concat - (Filename.dirname (Filename.dirname log_prefix)) - (Filename.basename exec_name) - in - Some (exec_name ^ params) + else + Filename.concat + (Filename.dirname (Filename.dirname log_prefix)) + (Filename.basename exec_name) + in + Some (exec_name ^ params) in - let command_string = basic_command_string command in let command_string = command_string ^ " 2>" ^ stderr @@ -639,6 +709,83 @@ with Unix.Unix_error _ -> ()) (execnow.ex_bin @ execnow.ex_log) +module Make_Report(M:sig type t end)=struct + module H=Hashtbl.Make + (struct + type t = toplevel_command + let project cmd = (cmd.directory,cmd.file,cmd.n) + let compare c1 c2 = Pervasives.compare (project c1) (project c2) + let equal c1 c2 = (project c1)=(project c2) + let hash c = Hashtbl.hash (project c) + end) + let tbl = H.create 774 + let m = Mutex.create () + let record cmd (v:M.t) = + if !xunit then begin + Mutex.lock m; + H.add tbl cmd v; + Mutex.unlock m + end + let iter f = + Mutex.lock m; + H.iter f tbl; + Mutex.unlock m + let find k = H.find tbl k + let remove k = H.remove tbl k + +end +module Report_run=Make_Report(struct type t=int +(* At some point will contain the running time*) +end) + +let report_run cmp r = Report_run.record cmp r +module Report_cmp=Make_Report(struct type t=int*int end) +let report_cmp = Report_cmp.record +let pretty_report fmt = + Report_run.iter + (fun test _run_result -> + Format.fprintf fmt + "%s@." + (Filename.basename test.directory) test.file + (let res,err = Report_cmp.find test in + Report_cmp.remove test; + (if res=0 && err=0 then "" else + Format.sprintf "%s" + (if res=1 then "Stdout oracle difference" + else if res=2 then "Stdout System Error (missing oracle?)" + else if err=1 then "Stderr oracle difference" + else if err=2 then "Stderr System Error (missing oracle?)" + else "Unexpected errror")))); + (* Test that were compared bu not runned *) + Report_cmp.iter + (fun test (res,err) -> + Format.fprintf fmt + "%s@." + (Filename.basename test.directory) test.file + (if res=0 && err=0 then "" else + Format.sprintf "%s" + (if res=1 then "Stdout oracle difference" + else if res=2 then "Stdout System Error (missing oracle?)" + else if err=1 then "Stderr oracle difference" + else if err=2 then "Stderr System Error (missing oracle?)" + else "Unexpected errror"))) +let xunit_report () = + if !xunit then begin + let out = open_out_bin "xunit.xml" in + let fmt = Format.formatter_of_out_channel out in + Format.fprintf fmt + "\ + %t@\n\ + @." + (shared.summary_log-shared.summary_ok) + "Frama-C" + shared.summary_log + (Unix.gettimeofday ()) + pretty_report; + close_out out; + end + + let do_command command = match command with Toplevel command -> @@ -651,50 +798,50 @@ (* Run, Show or Examine *) if !behavior <> Examine then begin - let command_string = command_string command in - if !verbosity >= 1 - then lock_printf "%% launch %s@." command_string ; - ignore (launch command_string) - end; - lock (); - shared.summary_run <- succ shared.summary_run ; - shared.summary_log <- shared.summary_log + 2 ; - Queue.push (Cmp_Toplevel command) shared.cmps; - unlock () - end + let command_string = command_string command in + if !verbosity >= 1 + then lock_printf "%% launch %s@." command_string ; + report_run command (launch command_string) + end; + lock (); + shared.summary_run <- succ shared.summary_run ; + shared.summary_log <- shared.summary_log + 2 ; + Queue.push (Cmp_Toplevel command) shared.cmps; + unlock () + end | Target (execnow, cmds) -> let continue res = lock(); - shared.summary_log <- succ shared.summary_log; + shared.summary_log <- succ shared.summary_log; if res = 0 - then begin - shared.summary_ok <- succ shared.summary_ok; - Queue.transfer shared.commands cmds; - shared.commands <- cmds; + then begin + shared.summary_ok <- succ shared.summary_ok; + Queue.transfer shared.commands cmds; + shared.commands <- cmds; shared.building_target <- false; Condition.broadcast shared.work_available; - if !behavior = Examine || !behavior = Run - then begin - List.iter - (fun f -> Queue.push (Cmp_Log(execnow.ex_dir, f)) shared.cmps) - execnow.ex_log - end + if !behavior = Examine || !behavior = Run + then begin + List.iter + (fun f -> Queue.push (Cmp_Log(execnow.ex_dir, f)) shared.cmps) + execnow.ex_log + end end - else begin - let rec treat_cmd = function - Toplevel cmd -> - shared.summary_run <- shared.summary_run + 1; - let log_prefix = log_prefix cmd in - begin try - Unix.unlink (log_prefix ^ ".res.log ") - with Unix.Unix_error _ -> () - end; - | Target (execnow,cmds) -> + else begin + let rec treat_cmd = function + Toplevel cmd -> + shared.summary_run <- shared.summary_run + 1; + let log_prefix = log_prefix cmd in + begin try + Unix.unlink (log_prefix ^ ".res.log ") + with Unix.Unix_error _ -> () + end; + | Target (execnow,cmds) -> shared.summary_run <- succ shared.summary_run; remove_execnow_results execnow; Queue.iter treat_cmd cmds - in - Queue.iter treat_cmd cmds; + in + Queue.iter treat_cmd cmds; Queue.push (Target_error execnow) shared.diffs; shared.building_target <- false; Condition.signal shared.diff_available @@ -704,26 +851,26 @@ if !behavior = Update then begin update_command command; - lock (); - shared.building_target <- false; - Condition.signal shared.work_available; - unlock (); - end else + lock (); + shared.building_target <- false; + Condition.signal shared.work_available; + unlock (); + end else begin if !behavior <> Examine - then begin - remove_execnow_results execnow; - let cmd = + then begin + remove_execnow_results execnow; + let cmd = if !use_byte || execnow_needs_byte execnow.ex_cmd then - execnow_opt_to_byte execnow.ex_cmd + execnow_opt_to_byte execnow.ex_cmd else - execnow.ex_cmd - in - let r = launch cmd in - continue r - end - else - continue 0 + execnow.ex_cmd + in + let r = launch cmd in + continue r + end + else + continue 0 end let log_ext = function Res -> ".res" | Err -> ".err" @@ -734,7 +881,8 @@ lock(); Queue.push (Command_error(cmp,log_kind)) shared.diffs; Condition.signal shared.diff_available; - unlock() + unlock(); + -1 end else let ext = log_ext log_kind in let log_file = log_prefix ^ ext ^ ".log " in @@ -748,18 +896,21 @@ cmp_string; match launch cmp_string with 0 -> - lock(); - shared.summary_ok <- shared.summary_ok + 1; - unlock() + lock(); + shared.summary_ok <- shared.summary_ok + 1; + unlock(); + 0 | 1 -> - lock(); - Queue.push (Command_error (cmp,log_kind)) shared.diffs; - Condition.signal shared.diff_available; - unlock() + lock(); + Queue.push (Command_error (cmp,log_kind)) shared.diffs; + Condition.signal shared.diff_available; + unlock(); + 1 | 2 -> - lock_printf - "%% System error while comparing. Maybe one of the files is missing...@\n%s or %s@." - log_file oracle_file; + lock_printf + "%% System error while comparing. Maybe one of the files is missing...@\n%s or %s@." + log_file oracle_file; + 2 | n -> lock_printf "%% Comparison function exited with code %d for files %s and %s. \ @@ -782,18 +933,18 @@ shared.summary_log <- succ shared.summary_log; match launch cmp_string with 0 -> - lock(); - shared.summary_ok <- shared.summary_ok + 1; - unlock() + lock(); + shared.summary_ok <- shared.summary_ok + 1; + unlock() | 1 -> - lock(); - Queue.push (Log_error (dir,file)) shared.diffs; - Condition.signal shared.diff_available; - unlock() + lock(); + Queue.push (Log_error (dir,file)) shared.diffs; + Condition.signal shared.diff_available; + unlock() | 2 -> - lock_printf - "%% System error while comparing. Maybe one of the files is missing...@\n%s or %s@." - log_file oracle_file; + lock_printf + "%% System error while comparing. Maybe one of the files is missing...@\n%s or %s@." + log_file oracle_file; | n -> lock_printf "%% Diff function exited with code %d for files %s and %s. \ @@ -805,10 +956,11 @@ | Cmp_Toplevel cmp -> let log_prefix = log_prefix cmp in let oracle_prefix = oracle_prefix cmp in - compare_one_file cmp log_prefix oracle_prefix Res; - compare_one_file cmp log_prefix oracle_prefix Err + let res = compare_one_file cmp log_prefix oracle_prefix Res in + let err = compare_one_file cmp log_prefix oracle_prefix Err in + report_cmp cmp (res,err) | Cmp_Log(dir, f) -> - compare_one_log_file dir f + ignore (compare_one_log_file dir f) let worker_thread () = while true do @@ -821,46 +973,46 @@ do_cmp cmp with Queue.Empty -> try - let rec real_command () = - let command = - try - if shared.building_target then raise Queue.Empty; - Queue.pop shared.target_queue - with Queue.Empty -> - Queue.pop shared.commands - in - match command with - Target _ -> - if shared.building_target - then begin - Queue.push command shared.target_queue; - real_command() - end - else begin - shared.building_target <- true; - command - end - | _ -> command - in - let command = real_command() in - unlock () ; - do_command command + let rec real_command () = + let command = + try + if shared.building_target then raise Queue.Empty; + Queue.pop shared.target_queue + with Queue.Empty -> + Queue.pop shared.commands + in + match command with + Target _ -> + if shared.building_target + then begin + Queue.push command shared.target_queue; + real_command() + end + else begin + shared.building_target <- true; + command + end + | _ -> command + in + let command = real_command() in + unlock () ; + do_command command with Queue.Empty -> - if shared.commands_finished - && Queue.is_empty shared.target_queue - && not shared.building_target - (* a target being built would mean work can still appear *) + if shared.commands_finished + && Queue.is_empty shared.target_queue + && not shared.building_target + (* a target being built would mean work can still appear *) - then (unlock () ; Thread.exit ()); + then (unlock () ; Thread.exit ()); - Condition.signal shared.commands_empty; - (* we still have the lock at this point *) + Condition.signal shared.commands_empty; + (* we still have the lock at this point *) - Condition.wait shared.work_available shared.lock; - (* this atomically releases the lock and suspends - the thread on the condition work_available *) + Condition.wait shared.work_available shared.lock; + (* this atomically releases the lock and suspends + the thread on the condition work_available *) - unlock (); + unlock (); done let do_diff = function @@ -875,8 +1027,8 @@ let oracle_prefix = oracle_prefix diff in let diff_string = !do_diffs ^ " " ^ - oracle_prefix ^ log_ext ^ ".oracle " ^ - log_prefix ^ log_ext ^ ".log" + oracle_prefix ^ log_ext ^ ".oracle " ^ + log_prefix ^ log_ext ^ ".log" in ignore (launch diff_string) | Target_error execnow -> @@ -888,8 +1040,8 @@ then ignore (launch ("cat " ^ result_file)) else let diff_string = - !do_diffs ^ " " ^ make_oracle_file dir file ^ " " ^ result_file - in + !do_diffs ^ " " ^ make_oracle_file dir file ^ " " ^ result_file + in ignore (launch diff_string) @@ -906,7 +1058,7 @@ Condition.wait shared.diff_available shared.lock (* this atomically releases the lock and suspends - the thread on the condition cmp_available *) + the thread on the condition cmp_available *) done let test_pattern config = @@ -930,14 +1082,19 @@ (* enqueue the test files *) let suites = match !suites with - [] -> !Ptests_config.default_suites + [] -> + let priority = "idct" in + let default = !Ptests_config.default_suites in + if List.mem priority default + then priority :: (List.filter (fun name -> name <> priority) default) + else default | l -> List.rev l in let interpret_as_file suite = - try - ignore (Filename.chop_extension suite); - true - with Invalid_argument _ -> false + try + let ext = Filename.chop_extension suite in + ext <> "" + with Invalid_argument _ -> false in let exclude_suite, exclude_file = List.fold_left @@ -951,20 +1108,20 @@ (* the "suite" may be a directory in [test_path] or a single file *) let interpret_as_file = interpret_as_file suite in let directory = - if interpret_as_file - then - Filename.dirname suite - else - Filename.concat test_path suite + if interpret_as_file + then + Filename.dirname suite + else + Filename.concat test_path suite in let config = Filename.concat directory dir_config_file in let dir_config = if Sys.file_exists config - then begin - let scan_buffer = Scanf.Scanning.from_file config in + then begin + let scan_buffer = Scanf.Scanning.from_file config in scan_options directory scan_buffer default_config end - else default_config + else default_config in if interpret_as_file then begin @@ -973,17 +1130,17 @@ { dir_config with dc_is_explicit_test = true}) files end else begin - if not (List.mem suite exclude_suite) then begin + if not (List.mem suite exclude_suite) then begin let dir_files = Sys.readdir directory in - for i = 0 to pred (Array.length dir_files) do - let file = dir_files.(i) in - assert (Filename.is_relative file); - if test_pattern dir_config file && + for i = 0 to pred (Array.length dir_files) do + let file = dir_files.(i) in + assert (Filename.is_relative file); + if test_pattern dir_config file && (not (List.mem (Filename.concat directory file) exclude_file)) - then Queue.push (file, directory, dir_config) files; - done + then Queue.push (file, directory, dir_config) files; + done end - end) + end) suites let dispatcher () = @@ -993,7 +1150,7 @@ lock (); while (Queue.length shared.commands) + (Queue.length shared.cmps) >= !n do - Condition.wait shared.commands_empty shared.lock; + Condition.wait shared.commands_empty shared.lock; done; (* we have the lock *) let file, directory, config = Queue.pop files in @@ -1001,25 +1158,25 @@ scan_test_file config directory file in let i = ref 0 in let make_toplevel_cmd (toplevel, options) = - let toplevel = - if !use_byte || needs_byte options - then opt_to_byte toplevel - else toplevel - in + let toplevel, options = + if !use_byte || needs_byte options + then opt_to_byte toplevel, opt_to_byte_options options + else toplevel,options + in {file=file; options = options; toplevel = toplevel; n = !i; directory = directory; - filter = config.dc_filter} + filter = config.dc_filter} in let treat_option q option = - Queue.push - (Toplevel (make_toplevel_cmd option)) - q; - incr i + Queue.push + (Toplevel (make_toplevel_cmd option)) + q; + incr i in if not config.dc_dont_run then begin - (match config.dc_execnow with - | hd :: tl -> + (match config.dc_execnow with + | hd :: tl -> let subworkqueue = Queue.create () in List.iter (treat_option subworkqueue) config.dc_toplevels; let target = @@ -1030,12 +1187,12 @@ Target(execnow,subworkqueue)) (Target(hd,subworkqueue)) tl in - Queue.push target shared.commands + Queue.push target shared.commands | [] -> List.iter - (treat_option shared.commands) - config.dc_toplevels); - Condition.broadcast shared.work_available; + (treat_option shared.commands) + config.dc_toplevels); + Condition.broadcast shared.work_available; end; unlock () ; done @@ -1056,8 +1213,8 @@ ignore (Thread.create (fun () -> while true do - Condition.broadcast shared.work_available; - Thread.delay 0.5; + Condition.broadcast shared.work_available; + Thread.delay 0.5; done) ()); Array.iter Thread.join worker_ids; @@ -1071,8 +1228,8 @@ ignore (Thread.create (fun () -> while true do - Condition.broadcast shared.diff_available; - Thread.delay 0.5; + Condition.broadcast shared.diff_available; + Thread.delay 0.5; done) ()); Thread.join diff_id; @@ -1080,7 +1237,13 @@ then lock_printf "%% Diffs finished. Summary:@\nRun = %d@\nOk = %d of %d@." shared.summary_run shared.summary_ok shared.summary_log; - exit 0; + xunit_report (); + let error_code = + if !do_error_code && shared.summary_log <> shared.summary_ok + then 1 + else 0 + in + exit error_code (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/share/acsl.el frama-c-20111001+nitrogen+dfsg/share/acsl.el --- frama-c-20110201+carbon+dfsg/share/acsl.el 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/acsl.el 2011-10-10 08:38:37.000000000 +0000 @@ -137,7 +137,7 @@ (2 font-lock-keyword-face t)) ("\\(axiom\\|behavior\\|case\\|inductive\\|predicate\\|l\\(ogic\\|emma\\)\\)\\>[ \t\n@]*\\([a-zA-Z_][a-zA-Z_0-9]*\\)" (,pre-match-form) nil (3 font-lock-function-name-face t)) - ("\\\\\\(at\\|e\\(mpty\\|xists\\)\\|f\\(alse\\|orall\\)\\|old\\|result\\|true\\|valid\\(_range\\)?\\)" (,pre-match-form) nil + ("\\\\\\(at\\|e\\(mpty\\|xists\\)\\|f\\(alse\\|orall\\)\\|old\\|result\\|true\\|valid\\(_range\\|_index\\)?\\)" (,pre-match-form) nil (0 font-lock-constant-face t))))) "Default highlighting for ACSL mode") Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/attach.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/attach.png differ diff -Nru frama-c-20110201+carbon+dfsg/share/builtin.h frama-c-20111001+nitrogen+dfsg/share/builtin.h --- frama-c-20110201+carbon+dfsg/share/builtin.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/builtin.h 2011-10-10 08:38:37.000000000 +0000 @@ -28,18 +28,25 @@ extern int Frama_C_entropy_source; -/*@ assigns \result \from a, b, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; +/*@ + ensures (\result == a) || (\result == b); + assigns \result \from a, b, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; */ int Frama_C_nondet(int a, int b); -/*@ assigns \result \from a, b, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; +/*@ + ensures (\result == a) || (\result == b); + assigns \result \from a, b, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; */ void *Frama_C_nondet_ptr(void *a, void *b); -/*@ assigns \result \from min, max, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; +/*@ + requires min <= max; + ensures min <= \result <= max; + assigns \result \from min, max, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; */ int Frama_C_interval(int min, int max); @@ -59,10 +66,9 @@ */ double Frama_C_double_interval(double min, double max); -/*@ - assigns dest[0..n-1] \from src[0..n-1] ; -*/ -void Frama_C_memcpy(char *dest, const char *src, unsigned long n); +/*@ assigns ((char*)dest)[0..n-1] \from ((char*)src)[0..n-1]; + assigns \result \from dest; */ +void* Frama_C_memcpy(char *dest, const char *src, unsigned long n); /*@ assigns \empty; diff -Nru frama-c-20110201+carbon+dfsg/share/configure.ac frama-c-20111001+nitrogen+dfsg/share/configure.ac --- frama-c-20110201+carbon+dfsg/share/configure.ac 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/configure.ac 2011-10-10 08:38:37.000000000 +0000 @@ -151,7 +151,9 @@ AC_SUBST([ENABLE_]UP) AC_SUBST([DYNAMIC_]UP) echo "PLUGIN_NAME... $ENABLE" -m4_undefine([PLUGIN_NAME]) +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) m4_undefine([PLUGIN_FILE]) m4_undefine([PLUGIN_MSG]) m4_undefine([PLUGIN_DEFAULT]) @@ -608,11 +610,14 @@ AC_FOREACH([plugin_file],$1,[plugin_prefix/plugin_file ])) m4_define([files_chmod], AC_FOREACH([plugin_file],plugin_files,[chmod -w plugin_file])) - AC_CONFIG_FILES(plugin_files,files_chmod) - m4_ifdef([FRAMAC_MAIN_AUTOCONF], - [EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} plugin_prefix"], - [ - write_plugin_summary - AC_OUTPUT() - ]) + AC_CONFIG_FILES(plugin_files,files_chmod) + m4_ifdef( + [FRAMAC_MAIN_AUTOCONF], + if test "$[ENABLE_]tovarname(PLUGIN_NAME)" != "no"; then + [EXTERNAL_PLUGINS="${EXTERNAL_PLUGINS} plugin_prefix"]; + fi, + [ + write_plugin_summary + AC_OUTPUT() + ]) ]) Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/considered_valid.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/considered_valid.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/inconsistent.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/inconsistent.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/invalid_but_dead.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/invalid_but_dead.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/invalid_under_hyp.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/invalid_under_hyp.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/never_tried.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/never_tried.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/surely_invalid.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/surely_invalid.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/surely_valid.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/surely_valid.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/unknown_but_dead.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/unknown_but_dead.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/unknown.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/unknown.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/valid_but_dead.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/valid_but_dead.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/feedback/valid_under_hyp.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/feedback/valid_under_hyp.png differ diff -Nru frama-c-20110201+carbon+dfsg/share/frama-c.WIN32.rc frama-c-20111001+nitrogen+dfsg/share/frama-c.WIN32.rc --- frama-c-20110201+carbon+dfsg/share/frama-c.WIN32.rc 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/frama-c.WIN32.rc 2011-10-10 08:38:37.000000000 +0000 @@ -23,14 +23,14 @@ # Default font for all widgets The first exisiting font is used. style "general" { - font_name = "Lucida Sans Unicode" + font_name = "Sans" } widget "*" style "general" # Style for widgets displaying source code. style "monospace" { - font_name = "Mono" + font_name = "Sans" } widget "*source" style "monospace" diff -Nru frama-c-20110201+carbon+dfsg/share/libc/dirent.h frama-c-20111001+nitrogen+dfsg/share/libc/dirent.h --- frama-c-20110201+carbon+dfsg/share/libc/dirent.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/dirent.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,36 +20,36 @@ /* */ /**************************************************************************/ -#ifndef __FC_DIRENT_H -#define __FC_DIRENT_H - -typedef struct __FC_DIR_T { unsigned int __fc_dir_contents; } DIR; - -#include "__fc_define_ino_t.h" - -struct dirent { - ino_t d_ino; - char d_name[255]; -}; - -int alphasort(const struct dirent **, const struct dirent **); -int closedir(DIR *); -int dirfd(DIR *); -DIR *fdopendir(int); -DIR *opendir(const char *); -struct dirent *readdir(DIR *); -int readdir_r(DIR *restrict, struct dirent *restrict, - struct dirent **restrict); -void rewinddir(DIR *); -int scandir(const char *, struct dirent ***, - int (*)(const struct dirent *), - int (*)(const struct dirent **, - const struct dirent **)); - -void seekdir(DIR *, long); -long telldir(DIR *); - - - -#endif - +#ifndef __FC_DIRENT_H +#define __FC_DIRENT_H + +typedef struct __FC_DIR_T { unsigned int __fc_dir_contents; } DIR; + +#include "__fc_define_ino_t.h" + +struct dirent { + ino_t d_ino; + char d_name[255]; +}; + +int alphasort(const struct dirent **, const struct dirent **); +int closedir(DIR *); +int dirfd(DIR *); +DIR *fdopendir(int); +DIR *opendir(const char *); +struct dirent *readdir(DIR *); +int readdir_r(DIR *restrict, struct dirent *restrict, + struct dirent **restrict); +void rewinddir(DIR *); +int scandir(const char *, struct dirent ***, + int (*)(const struct dirent *), + int (*)(const struct dirent **, + const struct dirent **)); + +void seekdir(DIR *, long); +long telldir(DIR *); + + + +#endif + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_builtin.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_builtin.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_builtin.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_builtin.h 2011-10-10 08:38:36.000000000 +0000 @@ -48,12 +48,9 @@ */ float Frama_C_float_interval(float min, float max); -/*@ - assigns ((char *)dest)[0] \from ((char *)src)[0]; -// supported, but not really treated... -// assigns ((char *)dest)[0..n-1] \from ((char *)src)[0..n-1]; -*/ -void Frama_C_memcpy(void *dest, const void *src, unsigned long n); +/*@ assigns ((char *)dest)[0..n-1] \from ((char *)src)[0..n-1]; + assigns \result \from dest; */ +void* Frama_C_memcpy(char *dest, const char *src, unsigned long n); /*@ assigns \empty; @@ -64,4 +61,6 @@ size_t Frama_C_offset(const void*); +void *Frama_C_undegenerate(const void*); + #endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_define_intptr_t.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_intptr_t.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_define_intptr_t.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_intptr_t.h 2011-10-10 08:38:36.000000000 +0000 @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2011 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It 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 Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +#ifndef __FRAMA_C_DEFINE_INTPTR_T +#define __FRAMA_C_DEFINE_INTPTR_T +#include "__fc_machdep.h" + +#ifdef __INTPTR_T +typedef __INTPTR_T intptr_t; +#endif + +#endif + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_define_pid_t.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_pid_t.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_define_pid_t.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_pid_t.h 2011-10-10 08:38:36.000000000 +0000 @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2011 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It 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 Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +#ifndef __FRAMA_C_DEFINE_PID_T +#define __FRAMA_C_DEFINE_PID_T + +typedef unsigned int pid_t; + +#endif + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_define_ssize_t.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_ssize_t.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_define_ssize_t.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_ssize_t.h 2011-10-10 08:38:36.000000000 +0000 @@ -0,0 +1,28 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2011 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It 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 Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +#ifndef __FRAMA_C_DEFINE_SSIZE_T +#define __FRAMA_C_DEFINE_SSIZE_T +#include "__fc_machdep.h" +typedef __SSIZE_T ssize_t; +#endif + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_define_suseconds_t.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_suseconds_t.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_define_suseconds_t.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_suseconds_t.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,8 +20,8 @@ /* */ /**************************************************************************/ - -#ifndef __FRAMA_C_DEFINE_SUSECONDS_T -#define __FRAMA_C_DEFINE_SUSECONDS_T -typedef unsigned int suseconds_t; -#endif + +#ifndef __FRAMA_C_DEFINE_SUSECONDS_T +#define __FRAMA_C_DEFINE_SUSECONDS_T +typedef signed int suseconds_t; +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_define_time_t.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_time_t.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_define_time_t.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_time_t.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,8 +20,8 @@ /* */ /**************************************************************************/ - -#ifndef __FRAMA_C_DEFINE_TIME_T -#define __FRAMA_C_DEFINE_TIME_T -typedef unsigned int time_t; -#endif + +#ifndef __FRAMA_C_DEFINE_TIME_T +#define __FRAMA_C_DEFINE_TIME_T +typedef unsigned int time_t; +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_define_useconds_t.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_useconds_t.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_define_useconds_t.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_define_useconds_t.h 2011-10-10 08:38:36.000000000 +0000 @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2011 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It 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 Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + + +#ifndef __FRAMA_C_DEFINE_USECONDS_T +#define __FRAMA_C_DEFINE_USECONDS_T +typedef unsigned int useconds_t; +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/__fc_machdep.h frama-c-20111001+nitrogen+dfsg/share/libc/__fc_machdep.h --- frama-c-20110201+carbon+dfsg/share/libc/__fc_machdep.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/__fc_machdep.h 2011-10-10 08:38:36.000000000 +0000 @@ -28,7 +28,7 @@ #ifdef __FRAMA_C_MACHDEP_x86_32 /* Required */ -#define __CHAR_UNSIGNED__ +#undef __CHAR_UNSIGNED__ #define __WORDSIZE 32 #define __SIZEOF_SHORT 2 #define __SIZEOF_INT 4 @@ -86,6 +86,6 @@ #endif -#define __umax(oct,TYP) ((((1##TYP << (oct*__CHAR_BIT - 1))*2)-1)) -#define __smin(oct,TYP) (-(1##TYP << (oct*__CHAR_BIT - 1))) -#define __smax(oct,TYP) ((1##TYP << (oct*__CHAR_BIT - 1))-1) +#define __umax(typ) ((typ)(-1)) +#define __smin(oct,TYP) (2*(-(1##TYP << (oct*__CHAR_BIT - 2)))) +#define __smax(oct,TYP) ((1##TYP << (oct*__CHAR_BIT - 2))-1+(1##TYP << (oct*__CHAR_BIT - 2))) diff -Nru frama-c-20110201+carbon+dfsg/share/libc/fcntl.h frama-c-20111001+nitrogen+dfsg/share/libc/fcntl.h --- frama-c-20110201+carbon+dfsg/share/libc/fcntl.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/fcntl.h 2011-10-10 08:38:36.000000000 +0000 @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2011 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It 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 Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + off_t l_start; /* Offset where the lock begins. */ + off_t l_len; /* Size of the locked area; zero means until EOF. */ + pid_t l_pid; /* Process holding the lock. */ + }; + +int creat(const char *, mode_t); +int fcntl(int, int, ...); +int open(const char *, int, ...); + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/limits.h frama-c-20111001+nitrogen+dfsg/share/libc/limits.h --- frama-c-20110201+carbon+dfsg/share/libc/limits.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/limits.h 2011-10-10 08:38:36.000000000 +0000 @@ -35,7 +35,7 @@ # define SCHAR_MAX __smax(1,) /* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ -# define UCHAR_MAX __umax(1,) +# define UCHAR_MAX __umax(unsigned char) /* Minimum and maximum values a `char' can hold. */ # ifdef __CHAR_UNSIGNED__ @@ -53,28 +53,28 @@ # define SHRT_MAX __smax(__SIZEOF_SHORT,) /* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */ -# define USHRT_MAX __umax(__SIZEOF_SHORT,) +# define USHRT_MAX __umax(unsigned short) /* Minimum and maximum values a `signed int' can hold. */ # define INT_MIN __smin(__SIZEOF_INT,) # define INT_MAX __smax(__SIZEOF_INT,) /* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ -# define UINT_MAX __umax(__SIZEOF_INT,U) +# define UINT_MAX __umax(unsigned int) /* Minimum and maximum values a `signed long int' can hold. */ # define LONG_MAX __smax(__SIZEOF_LONG,L) # define LONG_MIN __smin(__SIZEOF_LONG,L) /* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */ -#define ULONG_MAX __umax(__SIZEOF_LONG,UL) +#define ULONG_MAX __umax(unsigned long) /* Minimum and maximum values a `signed long long int' can hold. */ # define LLONG_MAX __smax(__SIZEOF_LONGLONG,LL) # define LLONG_MIN __smin(__SIZEOF_LONGLONG,LL) /* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ -# define ULLONG_MAX __umax(__SIZEOF_LONGLONG,ULL) +# define ULLONG_MAX __umax(unsigned long long) #endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/math.c frama-c-20111001+nitrogen+dfsg/share/libc/math.c --- frama-c-20110201+carbon+dfsg/share/libc/math.c 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/math.c 2011-10-10 08:38:36.000000000 +0000 @@ -23,3 +23,25 @@ /* ISO C: 7.12 */ #include "math.h" + +double Frama_C_exp(double x); +double exp(double x){ + return Frama_C_exp(x); +} + +double Frama_C_cos(double x); +double cos(double x){ + return Frama_C_cos(x); +} + +double Frama_C_sin(double x); +double sin(double x){ + return Frama_C_sin(x); +} + +double fabs(double x){ + if(x==0.0) return 0.0; + if (x>0.0) return x; + return -x; +} + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/pwd.h frama-c-20111001+nitrogen+dfsg/share/libc/pwd.h --- frama-c-20110201+carbon+dfsg/share/libc/pwd.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/pwd.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,27 +20,27 @@ /* */ /**************************************************************************/ -#ifndef __FC_PWD_H__ -#define __FC_PWD_H__ - -#include "__fc_define_uid_and_gid.h" - -struct passwd { - char *pw_name; - uid_t pw_uid; - gid_t pw_gid; - char *pw_dir; - char *pw_shell; -}; - -struct passwd *getpwnam(const char *); -struct passwd *getpwuid(uid_t); -int getpwnam_r(const char *, struct passwd *, char *, - size_t, struct passwd **); -int getpwuid_r(uid_t, struct passwd *, char *, - size_t, struct passwd **); -void endpwent(void); -struct passwd *getpwent(void); -void setpwent(void); - -#endif +#ifndef __FC_PWD_H__ +#define __FC_PWD_H__ + +#include "__fc_define_uid_and_gid.h" + +struct passwd { + char *pw_name; + uid_t pw_uid; + gid_t pw_gid; + char *pw_dir; + char *pw_shell; +}; + +struct passwd *getpwnam(const char *); +struct passwd *getpwuid(uid_t); +int getpwnam_r(const char *, struct passwd *, char *, + size_t, struct passwd **); +int getpwuid_r(uid_t, struct passwd *, char *, + size_t, struct passwd **); +void endpwent(void); +struct passwd *getpwent(void); +void setpwent(void); + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/stdint.h frama-c-20111001+nitrogen+dfsg/share/libc/stdint.h --- frama-c-20110201+carbon+dfsg/share/libc/stdint.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/stdint.h 2011-10-10 08:38:36.000000000 +0000 @@ -72,9 +72,7 @@ typedef __UINT_FAST64_T uint_fast64_t; /* ISO C: 7.18.1.4 */ -#ifdef __INTPTR_T -typedef __INTPTR_T intptr_t; -#endif +#include "__fc_define_intptr_t.h" #ifdef __UINTPTR_T typedef __UINTPTR_T uintptr_t; diff -Nru frama-c-20110201+carbon+dfsg/share/libc/stdio.h frama-c-20111001+nitrogen+dfsg/share/libc/stdio.h --- frama-c-20110201+carbon+dfsg/share/libc/stdio.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/stdio.h 2011-10-10 08:38:36.000000000 +0000 @@ -163,7 +163,8 @@ const char * restrict format, va_list arg); -/*@ assigns arg \from format[..], *stream; */ +/*@ assigns *stream \from format[..], *stream; +// TODO: assign arg too. */ int vfscanf(FILE * restrict stream, const char * restrict format, va_list arg); @@ -172,9 +173,8 @@ int vprintf(const char * restrict format, va_list arg); -/*@ assigns *__fc_stdin, arg \from format[..]; -// unsupported... - */ +/*@ assigns *__fc_stdin \from format[..]; +// TODO: assign arg too. */ int vscanf(const char * restrict format, va_list arg); @@ -190,7 +190,7 @@ const char * restrict format, va_list arg); -/*@ assigns arg ; */ +/* @ TODO: assigns arg ; */ int vsscanf(const char * restrict s, const char * restrict format, va_list arg); diff -Nru frama-c-20110201+carbon+dfsg/share/libc/string.h frama-c-20111001+nitrogen+dfsg/share/libc/string.h --- frama-c-20110201+carbon+dfsg/share/libc/string.h 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/string.h 2011-10-10 08:38:36.000000000 +0000 @@ -25,9 +25,9 @@ #ifndef __FC_STRING_H_ #define __FC_STRING_H_ -#include <__fc_string_axiomatic.h> -#include -#include +#include "__fc_string_axiomatic.h" +#include "stddef.h" +#include "limits.h" #include "__fc_define_restrict.h" // Query memory diff -Nru frama-c-20110201+carbon+dfsg/share/libc/sys/socket.h frama-c-20111001+nitrogen+dfsg/share/libc/sys/socket.h --- frama-c-20110201+carbon+dfsg/share/libc/sys/socket.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/sys/socket.h 2011-10-10 08:38:32.000000000 +0000 @@ -20,133 +20,134 @@ /* */ /**************************************************************************/ -#ifndef __FC_SOCKET_H__ -#define __FC_SOCKET_H__ - -typedef uint32_t socklen_t; -typedef uint16_t sa_family_t; - -struct sockaddr { - sa_family_t sa_family; /* address family, AF_xxx */ - char sa_data[14]; /* 14 bytes of protocol address */ -}; - -struct sockaddr_storage { - sa_family_t ss_family; -}; - -#include "__fc_define_iovec.h" - -struct cmsghdr { - socklen_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -#define SCM_RIGHTS 0 - -struct msghdr { - void *msg_name; - socklen_t msg_namelen; - struct iovec *msg_iov; - int msg_iovlen; - void *msg_control; - socklen_t msg_controllen; - int msg_flags; -}; - -/* Socket types. */ -#define SOCK_STREAM 1 /* stream (connection) socket */ -#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ -#define SOCK_RAW 3 /* raw socket */ -#define SOCK_RDM 4 /* reliably-delivered message */ -#define SOCK_SEQPACKET 5 /* sequential packet socket */ - -/* Supported address families. */ -/* - * Address families. - */ -#define AF_UNSPEC 0 /* unspecified */ -#define AF_UNIX 1 /* local to host (pipes, portals) */ -#define AF_LOCAL 1 /* POSIX name for AF_UNIX */ -#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ -#define AF_IMPLINK 3 /* arpanet imp addresses */ -#define AF_PUP 4 /* pup protocols: e.g. BSP */ -#define AF_CHAOS 5 /* mit CHAOS protocols */ -#define AF_NS 6 /* XEROX NS protocols */ -#define AF_ISO 7 /* ISO protocols */ -#define AF_OSI AF_ISO /* OSI is ISO */ -#define AF_ECMA 8 /* european computer manufacturers */ -#define AF_DATAKIT 9 /* datakit protocols */ -#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ -#define AF_SNA 11 /* IBM SNA */ -#define AF_DECnet 12 /* DECnet */ -#define AF_DLI 13 /* Direct data link interface */ -#define AF_LAT 14 /* LAT */ -#define AF_HYLINK 15 /* NSC Hyperchannel */ -#define AF_APPLETALK 16 /* AppleTalk */ -#define AF_NETBIOS 17 /* NetBios-style addresses */ - -#define AF_MAX 32 -/* - * Protocol families, same as address families for now. - */ -#define PF_UNSPEC AF_UNSPEC -#define PF_UNIX AF_UNIX -#define PF_LOCAL AF_LOCAL -#define PF_INET AF_INET -#define PF_IMPLINK AF_IMPLINK -#define PF_PUP AF_PUP -#define PF_CHAOS AF_CHAOS -#define PF_NS AF_NS -#define PF_ISO AF_ISO -#define PF_OSI AF_OSI -#define PF_ECMA AF_ECMA -#define PF_DATAKIT AF_DATAKIT -#define PF_CCITT AF_CCITT -#define PF_SNA AF_SNA -#define PF_DECnet AF_DECnet -#define PF_DLI AF_DLI -#define PF_LAT AF_LAT -#define PF_HYLINK AF_HYLINK -#define PF_APPLETALK AF_APPLETALK -#define PF_NETBIOS AF_NETBIOS - -#define PF_MAX AF_MAX - -#define SOL_SOCKET 0xffff /* options for socket level */ - -#define SO_DEBUG 0x0001 /* turn on debugging info recording */ -#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_REUSEADDR 0x0004 /* allow local address reuse */ -#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_DONTROUTE 0x0010 /* just use interface addresses */ -#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ -#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ -#define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ -#define SO_DONTLINGER (u_int)(~SO_LINGER) -#define SO_PEERCRED 0x0200 /* same as getpeereid */ - - -int accept(int, struct sockaddr *restrict, socklen_t *restrict); -int bind(int, const struct sockaddr *, socklen_t); -int connect(int, const struct sockaddr *, socklen_t); -int getpeername(int, struct sockaddr *restrict, socklen_t *restrict); -int getsockname(int, struct sockaddr *restrict, socklen_t *restrict); -int getsockopt(int, int, int, void *restrict, socklen_t *restrict); -int listen(int, int); -ssize_t recv(int, void *, size_t, int); -ssize_t recvfrom(int, void *restrict, size_t, int, - struct sockaddr *restrict, socklen_t *restrict); -ssize_t recvmsg(int, struct msghdr *, int); -ssize_t send(int, const void *, size_t, int); -ssize_t sendmsg(int, const struct msghdr *, int); -ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, - socklen_t); -int setsockopt(int, int, int, const void *, socklen_t); -int shutdown(int, int); -int socket(int, int, int); -int sockatmark(int); -int socketpair(int, int, int, int[2]); -#endif +#ifndef __FC_SOCKET_H__ +#define __FC_SOCKET_H__ +#include "__fc_machdep.h" + +typedef __UINT_LEAST32_T socklen_t; +typedef __UINT_LEAST16_T sa_family_t; + +struct sockaddr { + sa_family_t sa_family; /* address family, AF_xxx */ + char sa_data[14]; /* 14 bytes of protocol address */ +}; + +struct sockaddr_storage { + sa_family_t ss_family; +}; + +#include "__fc_define_iovec.h" + +struct cmsghdr { + socklen_t cmsg_len; + int cmsg_level; + int cmsg_type; +}; + +#define SCM_RIGHTS 0 + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ + +/* Supported address families. */ +/* + * Address families. + */ +#define AF_UNSPEC 0 /* unspecified */ +#define AF_UNIX 1 /* local to host (pipes, portals) */ +#define AF_LOCAL 1 /* POSIX name for AF_UNIX */ +#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define AF_IMPLINK 3 /* arpanet imp addresses */ +#define AF_PUP 4 /* pup protocols: e.g. BSP */ +#define AF_CHAOS 5 /* mit CHAOS protocols */ +#define AF_NS 6 /* XEROX NS protocols */ +#define AF_ISO 7 /* ISO protocols */ +#define AF_OSI AF_ISO /* OSI is ISO */ +#define AF_ECMA 8 /* european computer manufacturers */ +#define AF_DATAKIT 9 /* datakit protocols */ +#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ +#define AF_SNA 11 /* IBM SNA */ +#define AF_DECnet 12 /* DECnet */ +#define AF_DLI 13 /* Direct data link interface */ +#define AF_LAT 14 /* LAT */ +#define AF_HYLINK 15 /* NSC Hyperchannel */ +#define AF_APPLETALK 16 /* AppleTalk */ +#define AF_NETBIOS 17 /* NetBios-style addresses */ + +#define AF_MAX 32 +/* + * Protocol families, same as address families for now. + */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_LOCAL AF_LOCAL +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_ISO AF_ISO +#define PF_OSI AF_OSI +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK +#define PF_NETBIOS AF_NETBIOS + +#define PF_MAX AF_MAX + +#define SOL_SOCKET 0xffff /* options for socket level */ + +#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ +#define SO_DONTLINGER (unsigned int)(~SO_LINGER) +#define SO_PEERCRED 0x0200 /* same as getpeereid */ + + +int accept(int, struct sockaddr *restrict, socklen_t *restrict); +int bind(int, const struct sockaddr *, socklen_t); +int connect(int, const struct sockaddr *, socklen_t); +int getpeername(int, struct sockaddr *restrict, socklen_t *restrict); +int getsockname(int, struct sockaddr *restrict, socklen_t *restrict); +int getsockopt(int, int, int, void *restrict, socklen_t *restrict); +int listen(int, int); +ssize_t recv(int, void *, size_t, int); +ssize_t recvfrom(int, void *restrict, size_t, int, + struct sockaddr *restrict, socklen_t *restrict); +ssize_t recvmsg(int, struct msghdr *, int); +ssize_t send(int, const void *, size_t, int); +ssize_t sendmsg(int, const struct msghdr *, int); +ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, + socklen_t); +int setsockopt(int, int, int, const void *, socklen_t); +int shutdown(int, int); +int socket(int, int, int); +int sockatmark(int); +int socketpair(int, int, int, int[2]); +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/sys/stat.h frama-c-20111001+nitrogen+dfsg/share/libc/sys/stat.h --- frama-c-20110201+carbon+dfsg/share/libc/sys/stat.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/sys/stat.h 2011-10-10 08:38:32.000000000 +0000 @@ -20,43 +20,43 @@ /* */ /**************************************************************************/ -#ifndef __FC_SYS_STAT_H -#define __FC_SYS_STAT_H - -#include "__fc_define_ino_t.h" -#include "__fc_define_uid_and_gid.h" -#include "__fc_define_time_t.h" -#include "__fc_define_blkcnt_t.h" -#include "__fc_define_blksize_t.h" -#include "__fc_define_dev_t.h" -#include "__fc_define_mode_t.h" -#include "__fc_define_nlink_t.h" -#include "__fc_define_off_t.h" - -struct stat { - dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; - off_t st_size; - time_t st_atime; - time_t st_mtime; - time_t st_ctime; - blksize_t st_blksize; - blkcnt_t st_blocks; -}; - -int chmod(const char *, mode_t); -int fchmod(int, mode_t); -int fstat(int, struct stat *); -int lstat(const char *, struct stat *); -int mkdir(const char *, mode_t); -int mkfifo(const char *, mode_t); -int mknod(const char *, mode_t, dev_t); -int stat(const char *, struct stat *); -mode_t umask(mode_t); - -#endif +#ifndef __FC_SYS_STAT_H +#define __FC_SYS_STAT_H + +#include "../__fc_define_ino_t.h" +#include "../__fc_define_uid_and_gid.h" +#include "../__fc_define_time_t.h" +#include "../__fc_define_blkcnt_t.h" +#include "../__fc_define_blksize_t.h" +#include "../__fc_define_dev_t.h" +#include "../__fc_define_mode_t.h" +#include "../__fc_define_nlink_t.h" +#include "../__fc_define_off_t.h" + +struct stat { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; + blksize_t st_blksize; + blkcnt_t st_blocks; +}; + +int chmod(const char *, mode_t); +int fchmod(int, mode_t); +int fstat(int, struct stat *); +int lstat(const char *, struct stat *); +int mkdir(const char *, mode_t); +int mkfifo(const char *, mode_t); +int mknod(const char *, mode_t, dev_t); +int stat(const char *, struct stat *); +mode_t umask(mode_t); + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/sys/time.h frama-c-20111001+nitrogen+dfsg/share/libc/sys/time.h --- frama-c-20110201+carbon+dfsg/share/libc/sys/time.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/sys/time.h 2011-10-10 08:38:32.000000000 +0000 @@ -20,16 +20,16 @@ /* */ /**************************************************************************/ -#ifndef __FC_SYS_TIME_H__ -#define __FC_SYS_TIME_H__ - -typedef struct {char __fc_fd_set;} fd_set; -#include "__fc_define_time_t.h" -#include "__fc_define_suseconds_t.h" - -struct timeval { - time_t tv_sec; - suseconds_t tv_usec; -}; - -#endif +#ifndef __FC_SYS_TIME_H__ +#define __FC_SYS_TIME_H__ + +typedef struct {char __fc_fd_set;} fd_set; +#include "../__fc_define_time_t.h" +#include "../__fc_define_suseconds_t.h" + +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/sys/types.h frama-c-20111001+nitrogen+dfsg/share/libc/sys/types.h --- frama-c-20110201+carbon+dfsg/share/libc/sys/types.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/sys/types.h 2011-10-10 08:38:32.000000000 +0000 @@ -23,18 +23,19 @@ #ifndef __FC_SYS_TYPES_H__ #define __FC_SYS_TYPES_H__ -#include "__fc_machdep.h" +#include "../__fc_machdep.h" -typedef __SSIZE_T ssize_t; -#include "__fc_define_uid_and_gid.h" -#include "__fc_define_time_t.h" -#include "__fc_define_suseconds_t.h" -#include "__fc_define_ino_t.h" -#include "__fc_define_blkcnt_t.h" -#include "__fc_define_blksize_t.h" -#include "__fc_define_dev_t.h" -#include "__fc_define_mode_t.h" -#include "__fc_define_nlink_t.h" -#include "__fc_define_off_t.h" +#include "../__fc_define_pid_t.h" +#include "../__fc_define_ssize_t.h" +#include "../__fc_define_uid_and_gid.h" +#include "../__fc_define_time_t.h" +#include "../__fc_define_suseconds_t.h" +#include "../__fc_define_ino_t.h" +#include "../__fc_define_blkcnt_t.h" +#include "../__fc_define_blksize_t.h" +#include "../__fc_define_dev_t.h" +#include "../__fc_define_mode_t.h" +#include "../__fc_define_nlink_t.h" +#include "../__fc_define_off_t.h" #endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/sys/uio.h frama-c-20111001+nitrogen+dfsg/share/libc/sys/uio.h --- frama-c-20110201+carbon+dfsg/share/libc/sys/uio.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/sys/uio.h 2011-10-10 08:38:32.000000000 +0000 @@ -20,18 +20,14 @@ /* */ /**************************************************************************/ -#ifndef FC_UIO -#define FC_UIO - - -typedef __SIZE_T size_t; -typedef __SIZE_T size_t; - -#include "__fc_define_ssize_t.h" -#include "__fc_define_size_t.h" -#include "__fc_define_iovec.h" - -ssize_t readv(int, const struct iovec *, int); -ssize_t writev(int, const struct iovec *, int); - -#endif +#ifndef FC_UIO +#define FC_UIO + +#include "../__fc_define_ssize_t.h" +#include "../__fc_define_size_t.h" +#include "../__fc_define_iovec.h" + +ssize_t readv(int, const struct iovec *, int); +ssize_t writev(int, const struct iovec *, int); + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/sys/wait.h frama-c-20111001+nitrogen+dfsg/share/libc/sys/wait.h --- frama-c-20110201+carbon+dfsg/share/libc/sys/wait.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/sys/wait.h 2011-10-10 08:38:32.000000000 +0000 @@ -20,23 +20,25 @@ /* */ /**************************************************************************/ -#ifndef __FC_WAIT_H__ -#define __FC_WAIT_H__ - -#define WNOHANG 0 -#define WUNTRACED 1 -#define WEXITED 2 -#define WSTOPPED 3 -#define WCONTINUED 4 -#define WNOWAIT 5 - -enum idtype_t { P_ALL, P_PID, P_PGID }; -#if 0 -pid_t wait(int *); -pid_t wait3(int *, int, struct rusage *); -int waitid(idtype_t, id_t, siginfo_t *, int); -pid_t waitpid(pid_t, int *, int); -#endif - -#endif - +#ifndef __FC_WAIT_H__ +#define __FC_WAIT_H__ + +#define WNOHANG 0 +#define WUNTRACED 1 +#define WEXITED 2 +#define WSTOPPED 3 +#define WCONTINUED 4 +#define WNOWAIT 5 + +#include "../__fc_define_pid_t.h" +enum idtype_t { P_ALL, P_PID, P_PGID }; +pid_t wait(int *); + +#if 0 +pid_t wait3(int *, int, struct rusage *); +int waitid(idtype_t, id_t, siginfo_t *, int); +pid_t waitpid(pid_t, int *, int); +#endif + +#endif + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/syslog.h frama-c-20111001+nitrogen+dfsg/share/libc/syslog.h --- frama-c-20110201+carbon+dfsg/share/libc/syslog.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/syslog.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,49 +20,49 @@ /* */ /**************************************************************************/ - - -#define LOG_PID 1 -#define LOG_CONS (1<<2) -#define LOG_NDELAY (1<<3) -#define LOG_ODELAY (1<<4) -#define LOG_NOWAIT (1<<5) - -#define LOG_KERN 1 -#define LOG_USER 2 -#define LOG_MAIL 3 -#define LOG_NEWS 4 -#define LOG_UUCP 5 -#define LOG_DAEMON 6 -#define LOG_AUTH 7 -#define LOG_CRON 8 -#define LOG_LPR 9 -#define LOG_LOCAL0 10 -#define LOG_LOCAL1 11 -#define LOG_LOCAL2 12 -#define LOG_LOCAL3 13 -#define LOG_LOCAL4 14 -#define LOG_LOCAL5 15 -#define LOG_LOCAL6 16 -#define LOG_LOCAL7 17 - -#define LOG_MASK(pri) pri - -#define LOG_EMERG 1 -#define LOG_ALERT 2 -#define LOG_CRIT 3 -#define LOG_ERR 4 -#define LOG_WARNING 5 -#define LOG_NOTICE 6 -#define LOG_INFO 7 -#define LOG_DEBUG 8 - -/*@ assigns \nothing ; */ -void closelog(void); -/*@ assigns \nothing ; */ -void openlog(const char *, int, int); -/*@ assigns \nothing ; */ -int setlogmask(int); -/*@ assigns \nothing ; */ -void syslog(int, const char *, ...); - + + +#define LOG_PID 1 +#define LOG_CONS (1<<2) +#define LOG_NDELAY (1<<3) +#define LOG_ODELAY (1<<4) +#define LOG_NOWAIT (1<<5) + +#define LOG_KERN 1 +#define LOG_USER 2 +#define LOG_MAIL 3 +#define LOG_NEWS 4 +#define LOG_UUCP 5 +#define LOG_DAEMON 6 +#define LOG_AUTH 7 +#define LOG_CRON 8 +#define LOG_LPR 9 +#define LOG_LOCAL0 10 +#define LOG_LOCAL1 11 +#define LOG_LOCAL2 12 +#define LOG_LOCAL3 13 +#define LOG_LOCAL4 14 +#define LOG_LOCAL5 15 +#define LOG_LOCAL6 16 +#define LOG_LOCAL7 17 + +#define LOG_MASK(pri) pri + +#define LOG_EMERG 1 +#define LOG_ALERT 2 +#define LOG_CRIT 3 +#define LOG_ERR 4 +#define LOG_WARNING 5 +#define LOG_NOTICE 6 +#define LOG_INFO 7 +#define LOG_DEBUG 8 + +/*@ assigns \nothing ; */ +void closelog(void); +/*@ assigns \nothing ; */ +void openlog(const char *, int, int); +/*@ assigns \nothing ; */ +int setlogmask(int); +/*@ assigns \nothing ; */ +void syslog(int, const char *, ...); + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/termios.h frama-c-20111001+nitrogen+dfsg/share/libc/termios.h --- frama-c-20110201+carbon+dfsg/share/libc/termios.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/termios.h 2011-10-10 08:38:36.000000000 +0000 @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2011 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It 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 Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +/* c_cflag bit meaning */ +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +struct termios { + tcflag_t c_iflag; /* input specific flags (bitmask) */ + tcflag_t c_oflag; /* output specific flags (bitmask) */ + tcflag_t c_cflag; /* control flags (bitmask) */ + tcflag_t c_lflag; /* local flags (bitmask) */ + cc_t c_cc[NCCS]; /* special characters */ +}; + +speed_t cfgetispeed(const struct termios *); +speed_t cfgetospeed(const struct termios *); +int cfsetispeed(struct termios *, speed_t); +int cfsetospeed(struct termios *, speed_t); +int tcdrain(int); +int tcflow(int, int); +int tcflush(int, int); +int tcgetattr(int, struct termios *); +pid_t tcgetsid(int); +int tcsendbreak(int, int); +int tcsetattr(int, int, struct termios *); + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/libc/tgmath.h frama-c-20111001+nitrogen+dfsg/share/libc/tgmath.h --- frama-c-20110201+carbon+dfsg/share/libc/tgmath.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/tgmath.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,5 +20,5 @@ /* */ /**************************************************************************/ -/* ISO C: 7.22 */ -#error "Frama-C: unsupported tgmath.h" +/* ISO C: 7.22 */ +#error "Frama-C: unsupported tgmath.h" diff -Nru frama-c-20110201+carbon+dfsg/share/libc/uchar.h frama-c-20111001+nitrogen+dfsg/share/libc/uchar.h --- frama-c-20110201+carbon+dfsg/share/libc/uchar.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/uchar.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,6 +20,6 @@ /* */ /**************************************************************************/ -/* ISO C: 7.24 */ -#error "Frama-C: unsupported uchar.h" - +/* ISO C: 7.24 */ +#error "Frama-C: unsupported uchar.h" + diff -Nru frama-c-20110201+carbon+dfsg/share/libc/unistd.h frama-c-20111001+nitrogen+dfsg/share/libc/unistd.h --- frama-c-20110201+carbon+dfsg/share/libc/unistd.h 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/libc/unistd.h 2011-10-10 08:38:36.000000000 +0000 @@ -20,3 +20,119 @@ /* */ /**************************************************************************/ +#include "__fc_define_size_t.h" +#include "__fc_define_null.h" +#include "__fc_define_ssize_t.h" +#include "__fc_define_uid_and_gid.h" +#include "__fc_define_off_t.h" +#include "__fc_define_pid_t.h" +#include "__fc_define_useconds_t.h" +#include "__fc_define_intptr_t.h" + +/* Values for the second argument to access. + These may be OR'd together. */ +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define X_OK 1 /* Test for execute permission. */ +#define F_OK 0 /* Test for existence. */ + +/* Standard file descriptors. */ +#define STDIN_FILENO 0 /* Standard input. */ +#define STDOUT_FILENO 1 /* Standard output. */ +#define STDERR_FILENO 2 /* Standard error output. */ + +/* Values for the WHENCE argument to lseek. */ +#ifndef __FC_STDIO /* has the same definitions. */ +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Seek from end of file. */ +#endif + +int access(const char *, int); +unsigned int alarm(unsigned int); +int brk(void *); +int chdir(const char *); +int chroot(const char *); +int chown(const char *, uid_t, gid_t); +int close(int); +size_t confstr(int, char *, size_t); +char *crypt(const char *, const char *); +char *ctermid(char *); +char *cuserid(char *s); +int dup(int); +int dup2(int, int); +void encrypt(char[64], int); +int execl(const char *, const char *, ...); +int execle(const char *, const char *, ...); +int execlp(const char *, const char *, ...); +int execv(const char *, char *const []); +int execve(const char *, char *const [], char *const []); +int execvp(const char *, char *const []); +void _exit(int); +int fchown(int, uid_t, gid_t); +int fchdir(int); +int fdatasync(int); +pid_t fork(void); +long int fpathconf(int, int); +int fsync(int); +int ftruncate(int, off_t); +char *getcwd(char *, size_t); +int getdtablesize(void); +gid_t getegid(void); +uid_t geteuid(void); +gid_t getgid(void); +int getgroups(int, gid_t []); +long gethostid(void); +char *getlogin(void); +int getlogin_r(char *, size_t); +int getopt(int, char * const [], const char *); +int getpagesize(void); +char *getpass(const char *); +pid_t getpgid(pid_t); +pid_t getpgrp(void); +pid_t getpid(void); +pid_t getppid(void); +pid_t getsid(pid_t); +uid_t getuid(void); +char *getwd(char *); +int isatty(int); +int lchown(const char *, uid_t, gid_t); +int link(const char *, const char *); +int lockf(int, int, off_t); +off_t lseek(int, off_t, int); +int nice(int); +long int pathconf(const char *, int); +int pause(void); +int pipe(int [2]); +ssize_t pread(int, void *, size_t, off_t); +int pthread_atfork(void (*)(void), void (*)(void), + void(*)(void)); +ssize_t pwrite(int, const void *, size_t, off_t); +ssize_t read(int, void *, size_t); +int readlink(const char *, char *, size_t); +int rmdir(const char *); +void *sbrk(intptr_t); +int setgid(gid_t); +int setpgid(pid_t, pid_t); +pid_t setpgrp(void); +int setregid(gid_t, gid_t); +int setreuid(uid_t, uid_t); +pid_t setsid(void); +int setuid(uid_t); +unsigned int sleep(unsigned int); +void swab(const void *, void *, ssize_t); +int symlink(const char *, const char *); +void sync(void); +long int sysconf(int); +pid_t tcgetpgrp(int); +int tcsetpgrp(int, pid_t); +int truncate(const char *, off_t); +char *ttyname(int); +int ttyname_r(int, char *, size_t); +useconds_t ualarm(useconds_t, useconds_t); +int unlink(const char *); +int usleep(useconds_t); +pid_t vfork(void); +ssize_t write(int, const void *, size_t); + +#endif diff -Nru frama-c-20110201+carbon+dfsg/share/Makefile.common frama-c-20111001+nitrogen+dfsg/share/Makefile.common --- frama-c-20110201+carbon+dfsg/share/Makefile.common 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/Makefile.common 2011-10-10 08:38:37.000000000 +0000 @@ -116,10 +116,14 @@ # a given rule (second argument) external_make = \ $(MAKE) FRAMAC_INTERNAL=yes \ - PLUGIN_LIB_DIR=$(FRAMAC_TOP_SRCDIR)/$(PLUGIN_LIB_DIR) \ - PLUGIN_GUI_LIB_DIR=$(FRAMAC_TOP_SRCDIR)/$(PLUGIN_GUI_LIB_DIR) \ - FRAMAC_LIBDIR=$(FRAMAC_TOP_SRCDIR)/lib/fc \ - FRAMAC_SHARE=$(FRAMAC_TOP_SRCDIR)/share -C $(1) $(2) + PLUGIN_LIB_DIR="\ + $(if $(filter /%,$(PLUGIN_LIB_DIR)),$(PLUGIN_LIB_DIR),\ + $(FRAMAC_TOP_SRCDIR)/$(PLUGIN_LIB_DIR))" \ + PLUGIN_GUI_LIB_DIR="\ + $(if $(filter /%,$(PLUGIN_GUI_LIB_DIR)),$(PLUGIN_GUI_LIB_DIR),\ + $(FRAMAC_TOP_SRCDIR)/$(PLUGIN_GUI_LIB_DIR))" \ + FRAMAC_LIBDIR="$(FRAMAC_TOP_SRCDIR)/lib/fc" \ + FRAMAC_SHARE="$(FRAMAC_TOP_SRCDIR)/share" -C $(1) $(2) ################## # Shell commands # @@ -130,11 +134,19 @@ CAT = cat CHMOD = chmod CHMOD_RO= chmod a-w -CP = cp -f +CHMOD_RW= sh -c \ +'for f in "$$@"; do \ + if test -e $$f; then chmod u+w $$f; fi \ +done' chmod_rw +CP = /usr/bin/install ECHO = echo MKDIR = mkdir -p MV = mv -ISED = ./bin/sed_inplace +ISED = sh -c \ +'new_temp=`mktemp /tmp/frama-c.XXXXXXX` || exit 1; \ +sed "$$@" > $$new_temp; \ +eval last=\$${$$\#}; \ +mv $$new_temp $$last' sed_inplace SED = sed RM = rm -f TAR = tar @@ -181,7 +193,12 @@ # Function with two arguments: # - $(1) is the test directory under consideration. # - $(2) is the name of Frama-C component under test (plugin or some core part) -.PRECIOUS: $(patsubst %.ml, %.cmo %.cmx %.cmxs %.opt %.byte, $(wildcard tests/$(1)/*.ml)) +ML_TESTS:=$(wildcard tests/$(1)/*.ml) +.PRECIOUS: $(patsubst %.ml, %.cmo, $(ML_TESTS)) \ + $(patsubst %.ml, %.cmx, $(ML_TESTS)) \ + $(patsubst %.ml, %.cmxs, $(ML_TESTS)) \ + $(patsubst %.ml, %.opt, $(ML_TESTS)) \ + $(patsubst %.ml, %.byte, $(ML_TESTS)) # [JS 2009/03/18] in the 5 rules below, don't print anything while VERBOSEMAKE # is not set (otherwise "make tests" is too much verbose) @@ -219,6 +236,16 @@ endef #COMPILE_TESTS_ML_FILES ################# +# Documentation # +################# + +ifeq ("$(OCAMLDOC)","ocamldoc.opt") +DOC_PLUGIN=$(DOC_DIR)/docgen.cmxs +else +DOC_PLUGIN=$(DOC_DIR)/docgen.cmo +endif + +################# # Generic rules # ################# @@ -288,11 +315,15 @@ .mll.ml: $(PRINT_OCAMLLEX) $@ + $(CHMOD_RW) $@ $(OCAMLLEX) $< + $(CHMOD_RO) $@ %.mli %.ml: %.mly $(PRINT_OCAMLYACC) $@ + $(CHMOD_RW) $(<:.mly=.ml) $(<:.mly=.mli) $(OCAMLYACC) -v $< + $(CHMOD_RO) $(<:.mly=.ml) $(<:.mly=.mli) .tex.dvi: $(PRINT_LATEX) $@ diff -Nru frama-c-20110201+carbon+dfsg/share/Makefile.dynamic frama-c-20111001+nitrogen+dfsg/share/Makefile.dynamic --- frama-c-20110201+carbon+dfsg/share/Makefile.dynamic 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/Makefile.dynamic 2011-10-10 08:38:37.000000000 +0000 @@ -20,16 +20,16 @@ # # ########################################################################## -FRAMAC_SRC ?= ../.. +PLUGIN_ENABLE ?=yes +PLUGIN_DIR ?=. + +FRAMAC_SRC ?=$(PLUGIN_DIR)/../.. FRAMAC_MAKE ?=no ifndef MAKECONFIG_DIR MAKECONFIG_DIR :=$(FRAMAC_SHARE) endif -PLUGIN_ENABLE ?=yes -PLUGIN_DIR ?=. - ifndef PLUGIN_DYNAMIC PLUGIN_DYNAMIC :=yes endif @@ -43,6 +43,14 @@ ifeq ($(FRAMAC_MAKE),yes) PLUGIN_RESET :=yes + +.PHONY: $(PLUGIN_DIR)/TESTS $(PLUGIN_NAME)_TESTS + +$(PLUGIN_NAME)_TESTS: $(PLUGIN_DIR)/TESTS + +$(PLUGIN_DIR)/TESTS: + $(call external_make, $(dir $@), tests) + else PLUGIN_RESET :=no include $(MAKECONFIG_DIR)/Makefile.common @@ -50,7 +58,7 @@ #special goal for use by frama-c's main Makefile. run_tests: -ifdef PLUGIN_NO_DEFAULT_TEST +ifndef PLUGIN_NO_DEFAULT_TEST ifndef PLUGIN_NO_TEST true else @@ -62,8 +70,47 @@ ifeq ($(PLUGIN_ENABLE),no) tests:: +doc:: else +.PHONY: plugin-doc/$(PLUGIN_NAME) +ifneq ($(FRAMAC_INTERNAL),yes) +plugin-doc/$(PLUGIN_NAME): + if test ! -e $(DOC_DIR)/kernel-doc.ocamldoc; then \ + echo "Frama-C kernel was not installed with code documentation \ +support. Cannot compile API documentation. To install it, run 'make doc \ +install-doc-code' in Frama-C's main directory"; \ + exit 1; \ + fi + $(MKDIR) $($(@:plugin-doc/%=%_DOC_DIR)) +else +ifeq ($(FRAMAC_MAKE),yes) +plugin-doc/$(PLUGIN_NAME): + : +else +plugin-doc/$(PLUGIN_NAME): + $(MKDIR) $($(@:plugin-doc/%=%_DOC_DIR)) +endif +endif + +doc:: plugin-doc/$(PLUGIN_NAME) $(PLUGIN_NAME)_DOC + +clean-doc:: $(PLUGIN_DIR)/$(PLUGIN_NAME)_CLEAN_DOC + +ifneq ($(FRAMAC_MAKE),yes) +install-doc-code:: $(PLUGIN_NAME)_INSTALL_DOC +endif + +$(PLUGIN_NAME)_INSTALL_DOC: plugin-doc/$(PLUGIN_NAME) + $(PRINT_CP) $(patsubst %_INSTALL_DOC,%,$@) Documentation + $(MKDIR) $(FRAMAC_SHARE)/doc/$(@:%_INSTALL_DOC=%) + $(CP) $(patsubst %,"%", \ + $(wildcard $($(@:%_INSTALL_DOC=%_DOC_DIR))/*.css \ + $($(@:%_INSTALL_DOC=%_DOC_DIR))/*.html \ + $($(@:%_INSTALL_DOC=%_DOC_DIR))/*.png)) \ + $(FRAMAC_SHARE)/doc/$(@:%_INSTALL_DOC=%) + + ifndef PLUGIN_INTERNAL_TEST ifndef PLUGIN_NO_TEST PTESTS_DEP=$(PLUGIN_DIR)/Makefile @@ -77,7 +124,7 @@ $(PLUGIN_DIR)/ptests_local_config.ml: $(PTESTS_DEP) $(PRINT_MAKING) $@ - $(RM) $@ + $(CHMOD_RW) $@ $(ECHO) \ "Ptests_config.default_suites:= [" $(PLUGIN_TESTS_DIRS:%='"%";') "];;" > $@ if test "$(USABLE_NATIVE_DYNLINK)" = "yes" \ @@ -121,13 +168,17 @@ PLUGIN_GUI_LIB_DIR ?= $(PLUGIN_DIR)/gui PLUGIN_INSTALL_DIR ?=$(DESTDIR)$(FRAMAC_PLUGINDIR) -PLUGIN_FLAGS:=$(FLAGS) $(DEBUG) $(FRAMAC_INCLUDES) +PLUGIN_FLAGS:=$(FLAGS) $(DEBUG) $(FRAMAC_INCLUDES) $(OCAMLGRAPH_INCLUDE) PLUGIN_BFLAGS:=$(PLUGIN_FLAGS) $(PLUGIN_BFLAGS) PLUGIN_OFLAGS:=$(PLUGIN_FLAGS) $(PLUGIN_OFLAGS) ifeq ($(FRAMAC_INTERNAL),yes) PLUGIN_DEPFLAGS:=$(PLUGIN_DEPFLAGS) +ifneq ($(FRAMAC_MAKE),yes) +PLUGIN_DOC_DIR:=$(PLUGIN_DIR)/doc/code +endif else PLUGIN_DEPFLAGS:=$(FRAMAC_INCLUDES) $(PLUGIN_DEPFLAGS) +PLUGIN_DOC_DIR:=$(PLUGIN_DIR)/doc/code endif PLUGIN_DOCFLAGS:=$(FRAMAC_INCLUDES) $(PLUGIN_DOCFLAGS) @@ -147,25 +198,24 @@ # do not define additional targets if you come from the Frama-C Makefile ifneq ($(FRAMAC_MAKE),yes) -frama-c-$(PLUGIN_NAME).byte$(EXE): $(TARGET_CMO) +$(PLUGIN_DIR)/frama-c-$(PLUGIN_NAME).byte$(EXE): $(TARGET_CMO) $(PRINT_LINKING) $@ $(OCAMLC) $(DYN_BLINKFLAGS) -o $@ \ $(DYN_BYTE_LIBS) $(DYN_GEN_BYTE_LIBS) \ $(patsubst %boot.cmo, $(PLUGIN_EXTRA_BYTE) $(TARGET_CMO) %boot.cmo, \ $(DYN_ALL_BATCH_CMO)) -frama-c-$(PLUGIN_NAME).opt$(EXE): $(TARGET_CMX) +$(PLUGIN_DIR)/frama-c-$(PLUGIN_NAME).opt$(EXE): $(TARGET_CMX) $(PRINT_LINKING) $@ $(OCAMLOPT) $(DYN_OLINKFLAGS) -o $@ \ $(DYN_OPT_LIBS) $(DYN_GEN_OPT_LIBS) \ $(patsubst %boot.cmx, $(PLUGIN_EXTRA_OPT) $(TARGET_CMX) %boot.cmx, \ $(DYN_ALL_BATCH_CMX)) -static.byte:: frama-c-$(PLUGIN_NAME).byte$(EXE) -static.opt:: frama-c-$(PLUGIN_NAME).opt$(EXE) -static:: frama-c-$(PLUGIN_NAME).byte$(EXE) \ - frama-c-$(PLUGIN_NAME).$(OCAMLBEST)$(EXE) - +static.byte:: $(PLUGIN_DIR)/frama-c-$(PLUGIN_NAME).byte$(EXE) +static.opt:: $(PLUGIN_DIR)/frama-c-$(PLUGIN_NAME).opt$(EXE) +static:: $(PLUGIN_DIR)/frama-c-$(PLUGIN_NAME).byte$(EXE) \ + $(PLUGIN_DIR)/frama-c-$(PLUGIN_NAME).$(OCAMLBEST)$(EXE) .PHONY: tests all install uninstall clean depend @@ -173,17 +223,12 @@ $(RM) ptests_local_config.ml $(RM) frama-c-$(PLUGIN_NAME) frama-c-$(PLUGIN_NAME).byte -ifeq ($(FRAMAC_MAKE),yes) -all:: byte $(OCAMLBEST) gui - -else ifeq ($(USABLE_NATIVE_DYNLINK),no) STATIC=static else STATIC= endif all:: $(PLUGIN_DIR)/.depend byte $(OCAMLBEST) gui $(STATIC) -endif ifneq ($(PLUGIN_ENABLE),no) install:: @@ -200,6 +245,7 @@ fi ifeq ($(HAS_GUI),yes) $(PRINT_CP) $(PLUGIN_INSTALL_DIR)/gui + $(MKDIR) $(PLUGIN_INSTALL_DIR)/gui $(CP) $(TARGETS_GUI) $(PLUGIN_INSTALL_DIR)/gui endif diff -Nru frama-c-20110201+carbon+dfsg/share/Makefile.dynamic_config.external frama-c-20111001+nitrogen+dfsg/share/Makefile.dynamic_config.external --- frama-c-20110201+carbon+dfsg/share/Makefile.dynamic_config.external 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/Makefile.dynamic_config.external 2011-10-10 08:38:37.000000000 +0000 @@ -21,8 +21,8 @@ ########################################################################## export FRAMAC_INTERNAL=no -export FRAMAC_PLUGINDIR="$(FRAMAC_LIBDIR)/plugins" -export FRAMAC_GUI_PLUGIN="$(FRAMAC_LIBDIR)/gui" +export FRAMAC_PLUGINDIR=$(FRAMAC_LIBDIR)/plugins +export FRAMAC_GUI_PLUGIN=$(FRAMAC_LIBDIR)/gui export FRAMAC_PLUGIN_TEST=. export FRAMAC_GUI_PLUGIN_TEST=. export FRAMAC_OPT=$(BINDIR)/frama-c$(EXE) @@ -30,3 +30,4 @@ export FRAMAC_INCLUDES=-I "$(FRAMAC_LIBDIR)" export FRAMAC_LIB="$(FRAMAC_LIBDIR)" export PTESTS=$(BINDIR)/ptests.byte$(EXE) +export DOC_DIR=$(FRAMAC_SHARE)/doc/code diff -Nru frama-c-20110201+carbon+dfsg/share/Makefile.dynamic_config.internal frama-c-20111001+nitrogen+dfsg/share/Makefile.dynamic_config.internal --- frama-c-20110201+carbon+dfsg/share/Makefile.dynamic_config.internal 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/Makefile.dynamic_config.internal 2011-10-10 08:38:37.000000000 +0000 @@ -30,3 +30,4 @@ export PTESTS=$(abspath $(FRAMAC_SRC)/bin/ptests.byte$(EXE)) export PLUGIN_LIB_DIR=$(abspath $(FRAMAC_SRC)/lib/plugins) export FRAMAC_LIB=$(abspath $(FRAMAC_SRC)/lib/fc) +export DOC_DIR=$(abspath $(FRAMAC_SRC)/doc/code) \ No newline at end of file diff -Nru frama-c-20110201+carbon+dfsg/share/Makefile.kernel frama-c-20111001+nitrogen+dfsg/share/Makefile.kernel --- frama-c-20110201+carbon+dfsg/share/Makefile.kernel 2011-02-07 14:02:38.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/Makefile.kernel 2011-10-10 08:56:36.000000000 +0000 @@ -1,21 +1,21 @@ # This makefile was automatically generated. # Do not modify. ifeq ($(FRAMAC_INTERNAL),yes) -DYN_BLINKFLAGS=-w +a-4-6-7-9 -annot -g -linkall -custom -I /localhome/virgile/tmp/Carbon-20110201/src/misc -I /localhome/virgile/tmp/Carbon-20110201/src/ai -I /localhome/virgile/tmp/Carbon-20110201/src/memory_state -I /localhome/virgile/tmp/Carbon-20110201/src/toplevel -I /localhome/virgile/tmp/Carbon-20110201/src/slicing_types -I /localhome/virgile/tmp/Carbon-20110201/src/pdg_types -I /localhome/virgile/tmp/Carbon-20110201/src/kernel -I /localhome/virgile/tmp/Carbon-20110201/src/logic -I /localhome/virgile/tmp/Carbon-20110201/src/lib -I /localhome/virgile/tmp/Carbon-20110201/src/type -I /localhome/virgile/tmp/Carbon-20110201/src/project -I /localhome/virgile/tmp/Carbon-20110201/src/buckx -I /localhome/virgile/tmp/Carbon-20110201/src/gui -I /localhome/virgile/tmp/Carbon-20110201/external -I /localhome/virgile/tmp/Carbon-20110201/cil/src -I /localhome/virgile/tmp/Carbon-20110201/cil/src/ext -I /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc -I /localhome/virgile/tmp/Carbon-20110201/cil/src/logic -I /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil -I /localhome/virgile/tmp/Carbon-20110201/lib/plugins -I /localhome/virgile/tmp/Carbon-20110201/lib -DYN_GEN_BYTE_LIBS=/localhome/virgile/tmp/Carbon-20110201/lib/graph.cmo /localhome/virgile/tmp/Carbon-20110201/src/buckx/mybigarray.o /localhome/virgile/tmp/Carbon-20110201/src/buckx/buckx_c.o +DYN_BLINKFLAGS=-w +a-4-6-7-9 -annot -g -linkall -custom -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/misc -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/toplevel -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/slicing_types -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/pdg_types -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/type -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/gui -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/external -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib +DYN_GEN_BYTE_LIBS=/localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/graph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx/mybigarray.o /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx/buckx_c.o DYN_BYTE_LIBS=nums.cma unix.cma bigarray.cma str.cma dynlink.cma -DYN_ALL_BATCH_CMO=/localhome/virgile/tmp/Carbon-20110201/unmarshal.cmo /localhome/virgile/tmp/Carbon-20110201/unmarshal_nums.cmo /localhome/virgile/tmp/Carbon-20110201/printexc_common_interface.cmo /localhome/virgile/tmp/Carbon-20110201/dynlink_common_interface.cmo /localhome/virgile/tmp/Carbon-20110201/structural_descr.cmo /localhome/virgile/tmp/Carbon-20110201/type.cmo /localhome/virgile/tmp/Carbon-20110201/descr.cmo /localhome/virgile/tmp/Carbon-20110201/extlib.cmo /localhome/virgile/tmp/Carbon-20110201/pretty_utils.cmo /localhome/virgile/tmp/Carbon-20110201/hook.cmo /localhome/virgile/tmp/Carbon-20110201/bag.cmo /localhome/virgile/tmp/Carbon-20110201/bitvector.cmo /localhome/virgile/tmp/Carbon-20110201/qstack.cmo /localhome/virgile/tmp/Carbon-20110201/config.cmo /localhome/virgile/tmp/Carbon-20110201/log.cmo /localhome/virgile/tmp/Carbon-20110201/cmdline.cmo /localhome/virgile/tmp/Carbon-20110201/project_skeleton.cmo /localhome/virgile/tmp/Carbon-20110201/datatype.cmo /localhome/virgile/tmp/Carbon-20110201/journal.cmo /localhome/virgile/tmp/Carbon-20110201/rangemap.cmo /localhome/virgile/tmp/Carbon-20110201/state.cmo /localhome/virgile/tmp/Carbon-20110201/state_dependency_graph.cmo /localhome/virgile/tmp/Carbon-20110201/state_topological.cmo /localhome/virgile/tmp/Carbon-20110201/state_selection.cmo /localhome/virgile/tmp/Carbon-20110201/project.cmo /localhome/virgile/tmp/Carbon-20110201/dashtbl.cmo /localhome/virgile/tmp/Carbon-20110201/state_builder.cmo /localhome/virgile/tmp/Carbon-20110201/cilmsg.cmo /localhome/virgile/tmp/Carbon-20110201/alpha.cmo /localhome/virgile/tmp/Carbon-20110201/clist.cmo /localhome/virgile/tmp/Carbon-20110201/growArray.cmo /localhome/virgile/tmp/Carbon-20110201/inthash.cmo /localhome/virgile/tmp/Carbon-20110201/cil_datatype.cmo /localhome/virgile/tmp/Carbon-20110201/cilutil.cmo /localhome/virgile/tmp/Carbon-20110201/setWithNearest.cmo /localhome/virgile/tmp/Carbon-20110201/cil_state_builder.cmo /localhome/virgile/tmp/Carbon-20110201/utf8_logic.cmo /localhome/virgile/tmp/Carbon-20110201/cilglobopt.cmo /localhome/virgile/tmp/Carbon-20110201/machdep_x86_16.cmo /localhome/virgile/tmp/Carbon-20110201/machdep_x86_32.cmo /localhome/virgile/tmp/Carbon-20110201/machdep_x86_64.cmo /localhome/virgile/tmp/Carbon-20110201/machdep_ppc_32.cmo /localhome/virgile/tmp/Carbon-20110201/machdep_ppc_32_diab.cmo /localhome/virgile/tmp/Carbon-20110201/machdep.cmo /localhome/virgile/tmp/Carbon-20110201/cil_const.cmo /localhome/virgile/tmp/Carbon-20110201/logic_env.cmo /localhome/virgile/tmp/Carbon-20110201/escape.cmo /localhome/virgile/tmp/Carbon-20110201/logic_const.cmo /localhome/virgile/tmp/Carbon-20110201/cil.cmo /localhome/virgile/tmp/Carbon-20110201/errorloc.cmo /localhome/virgile/tmp/Carbon-20110201/cabs.cmo /localhome/virgile/tmp/Carbon-20110201/expcompare.cmo /localhome/virgile/tmp/Carbon-20110201/cabshelper.cmo /localhome/virgile/tmp/Carbon-20110201/whitetrack.cmo /localhome/virgile/tmp/Carbon-20110201/logic_utils.cmo /localhome/virgile/tmp/Carbon-20110201/logic_builtin.cmo /localhome/virgile/tmp/Carbon-20110201/logic_print.cmo /localhome/virgile/tmp/Carbon-20110201/logic_parser.cmo /localhome/virgile/tmp/Carbon-20110201/logic_lexer.cmo /localhome/virgile/tmp/Carbon-20110201/lexerhack.cmo /localhome/virgile/tmp/Carbon-20110201/mergecil.cmo /localhome/virgile/tmp/Carbon-20110201/rmtmps.cmo /localhome/virgile/tmp/Carbon-20110201/logic_typing.cmo /localhome/virgile/tmp/Carbon-20110201/cprint.cmo /localhome/virgile/tmp/Carbon-20110201/cabscond.cmo /localhome/virgile/tmp/Carbon-20110201/cabsvisit.cmo /localhome/virgile/tmp/Carbon-20110201/cabs2cil.cmo /localhome/virgile/tmp/Carbon-20110201/clexer.cmo /localhome/virgile/tmp/Carbon-20110201/cparser.cmo /localhome/virgile/tmp/Carbon-20110201/logic_preprocess.cmo /localhome/virgile/tmp/Carbon-20110201/patch.cmo /localhome/virgile/tmp/Carbon-20110201/frontc.cmo /localhome/virgile/tmp/Carbon-20110201/obfuscate.cmo /localhome/virgile/tmp/Carbon-20110201/ciltools.cmo /localhome/virgile/tmp/Carbon-20110201/callgraph.cmo /localhome/virgile/tmp/Carbon-20110201/dataflow.cmo /localhome/virgile/tmp/Carbon-20110201/dominators.cmo /localhome/virgile/tmp/Carbon-20110201/oneret.cmo /localhome/virgile/tmp/Carbon-20110201/cfg.cmo /localhome/virgile/tmp/Carbon-20110201/usedef.cmo /localhome/virgile/tmp/Carbon-20110201/liveness.cmo /localhome/virgile/tmp/Carbon-20110201/reachingdefs.cmo /localhome/virgile/tmp/Carbon-20110201/availexpslv.cmo /localhome/virgile/tmp/Carbon-20110201/rmciltmps.cmo /localhome/virgile/tmp/Carbon-20110201/deadcodeelim.cmo /localhome/virgile/tmp/Carbon-20110201/zrapp.cmo /localhome/virgile/tmp/Carbon-20110201/buckx.cmo /localhome/virgile/tmp/Carbon-20110201/dynamic.cmo /localhome/virgile/tmp/Carbon-20110201/ast_printer.cmo /localhome/virgile/tmp/Carbon-20110201/ast_info.cmo /localhome/virgile/tmp/Carbon-20110201/kernel_datatype.cmo /localhome/virgile/tmp/Carbon-20110201/plugin.cmo /localhome/virgile/tmp/Carbon-20110201/kernel.cmo /localhome/virgile/tmp/Carbon-20110201/alarms.cmo /localhome/virgile/tmp/Carbon-20110201/cilE.cmo /localhome/virgile/tmp/Carbon-20110201/binary_cache.cmo /localhome/virgile/tmp/Carbon-20110201/parameters.cmo /localhome/virgile/tmp/Carbon-20110201/messages.cmo /localhome/virgile/tmp/Carbon-20110201/ast.cmo /localhome/virgile/tmp/Carbon-20110201/my_bigint.cmo /localhome/virgile/tmp/Carbon-20110201/hptmap.cmo /localhome/virgile/tmp/Carbon-20110201/hptset.cmo /localhome/virgile/tmp/Carbon-20110201/abstract_interp.cmo /localhome/virgile/tmp/Carbon-20110201/int_Base.cmo /localhome/virgile/tmp/Carbon-20110201/unicode.cmo /localhome/virgile/tmp/Carbon-20110201/bit_utils.cmo /localhome/virgile/tmp/Carbon-20110201/subst.cmo /localhome/virgile/tmp/Carbon-20110201/annotations.cmo /localhome/virgile/tmp/Carbon-20110201/globals.cmo /localhome/virgile/tmp/Carbon-20110201/kernel_function.cmo /localhome/virgile/tmp/Carbon-20110201/service_graph.cmo /localhome/virgile/tmp/Carbon-20110201/ival.cmo /localhome/virgile/tmp/Carbon-20110201/base.cmo /localhome/virgile/tmp/Carbon-20110201/base_Set_Lattice.cmo /localhome/virgile/tmp/Carbon-20110201/origin.cmo /localhome/virgile/tmp/Carbon-20110201/map_Lattice.cmo /localhome/virgile/tmp/Carbon-20110201/abstract_value.cmo /localhome/virgile/tmp/Carbon-20110201/locations.cmo /localhome/virgile/tmp/Carbon-20110201/shifted_Location.cmo /localhome/virgile/tmp/Carbon-20110201/path_lattice.cmo /localhome/virgile/tmp/Carbon-20110201/int_Interv.cmo /localhome/virgile/tmp/Carbon-20110201/int_Interv_Map.cmo /localhome/virgile/tmp/Carbon-20110201/new_offsetmap.cmo /localhome/virgile/tmp/Carbon-20110201/offsetmap.cmo /localhome/virgile/tmp/Carbon-20110201/offsetmap_bitwise.cmo /localhome/virgile/tmp/Carbon-20110201/lmap.cmo /localhome/virgile/tmp/Carbon-20110201/lmap_bitwise.cmo /localhome/virgile/tmp/Carbon-20110201/lmap_whole.cmo /localhome/virgile/tmp/Carbon-20110201/function_Froms.cmo /localhome/virgile/tmp/Carbon-20110201/cvalue_type.cmo /localhome/virgile/tmp/Carbon-20110201/widen_type.cmo /localhome/virgile/tmp/Carbon-20110201/relations_type.cmo /localhome/virgile/tmp/Carbon-20110201/state_set.cmo /localhome/virgile/tmp/Carbon-20110201/state_imp.cmo /localhome/virgile/tmp/Carbon-20110201/stmts_graph.cmo /localhome/virgile/tmp/Carbon-20110201/visitor.cmo /localhome/virgile/tmp/Carbon-20110201/printer.cmo /localhome/virgile/tmp/Carbon-20110201/unroll_loops.cmo /localhome/virgile/tmp/Carbon-20110201/loop.cmo /localhome/virgile/tmp/Carbon-20110201/property.cmo /localhome/virgile/tmp/Carbon-20110201/properties_status.cmo /localhome/virgile/tmp/Carbon-20110201/inout_type.cmo /localhome/virgile/tmp/Carbon-20110201/pdgIndex.cmo /localhome/virgile/tmp/Carbon-20110201/pdgTypes.cmo /localhome/virgile/tmp/Carbon-20110201/pdgMarks.cmo /localhome/virgile/tmp/Carbon-20110201/slicingInternals.cmo /localhome/virgile/tmp/Carbon-20110201/slicingTypes.cmo /localhome/virgile/tmp/Carbon-20110201/db.cmo /localhome/virgile/tmp/Carbon-20110201/command.cmo /localhome/virgile/tmp/Carbon-20110201/task.cmo /localhome/virgile/tmp/Carbon-20110201/translate_lightweight.cmo /localhome/virgile/tmp/Carbon-20110201/file.cmo /localhome/virgile/tmp/Carbon-20110201/filter.cmo /localhome/virgile/tmp/Carbon-20110201/special_hooks.cmo /localhome/virgile/tmp/Carbon-20110201/widen.cmo /localhome/virgile/tmp/Carbon-20110201/bit_model_access.cmo /localhome/virgile/tmp/Carbon-20110201/logic_interp.cmo /localhome/virgile/tmp/Carbon-20110201/infer_annotations.cmo /localhome/virgile/tmp/Carbon-20110201/Occurrence.cmo /localhome/virgile/tmp/Carbon-20110201/Metrics.cmo /localhome/virgile/tmp/Carbon-20110201/Syntactic_callgraph.cmo /localhome/virgile/tmp/Carbon-20110201/Value.cmo /localhome/virgile/tmp/Carbon-20110201/RteGen.cmo /localhome/virgile/tmp/Carbon-20110201/Report.cmo /localhome/virgile/tmp/Carbon-20110201/From.cmo /localhome/virgile/tmp/Carbon-20110201/Users.cmo /localhome/virgile/tmp/Carbon-20110201/Constant_Propagation.cmo /localhome/virgile/tmp/Carbon-20110201/Postdominators.cmo /localhome/virgile/tmp/Carbon-20110201/Inout.cmo /localhome/virgile/tmp/Carbon-20110201/Semantic_callgraph.cmo /localhome/virgile/tmp/Carbon-20110201/Impact.cmo /localhome/virgile/tmp/Carbon-20110201/Pdg.cmo /localhome/virgile/tmp/Carbon-20110201/Scope.cmo /localhome/virgile/tmp/Carbon-20110201/Sparecode.cmo /localhome/virgile/tmp/Carbon-20110201/Slicing.cmo /localhome/virgile/tmp/Carbon-20110201/boot.cmo -DYN_OLINKFLAGS=-w +a-4-6-7-9 -annot -g -linkall -I /localhome/virgile/tmp/Carbon-20110201/src/misc -I /localhome/virgile/tmp/Carbon-20110201/src/ai -I /localhome/virgile/tmp/Carbon-20110201/src/memory_state -I /localhome/virgile/tmp/Carbon-20110201/src/toplevel -I /localhome/virgile/tmp/Carbon-20110201/src/slicing_types -I /localhome/virgile/tmp/Carbon-20110201/src/pdg_types -I /localhome/virgile/tmp/Carbon-20110201/src/kernel -I /localhome/virgile/tmp/Carbon-20110201/src/logic -I /localhome/virgile/tmp/Carbon-20110201/src/lib -I /localhome/virgile/tmp/Carbon-20110201/src/type -I /localhome/virgile/tmp/Carbon-20110201/src/project -I /localhome/virgile/tmp/Carbon-20110201/src/buckx -I /localhome/virgile/tmp/Carbon-20110201/src/gui -I /localhome/virgile/tmp/Carbon-20110201/external -I /localhome/virgile/tmp/Carbon-20110201/cil/src -I /localhome/virgile/tmp/Carbon-20110201/cil/src/ext -I /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc -I /localhome/virgile/tmp/Carbon-20110201/cil/src/logic -I /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil -I /localhome/virgile/tmp/Carbon-20110201/lib/plugins -I /localhome/virgile/tmp/Carbon-20110201/lib -DYN_GEN_OPT_LIBS=/localhome/virgile/tmp/Carbon-20110201/lib/graph.cmx /localhome/virgile/tmp/Carbon-20110201/src/buckx/mybigarray.o /localhome/virgile/tmp/Carbon-20110201/src/buckx/buckx_c.o +DYN_ALL_BATCH_CMO=/localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/unmarshal.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/unmarshal_nums.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/printexc_common_interface.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/map_common_interface.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/dynlink_common_interface.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/structural_descr.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/type.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/descr.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/extlib.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/pretty_utils.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/hook.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/bag.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/bitvector.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/qstack.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/my_bigint.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/config.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/log.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cmdline.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/project_skeleton.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/datatype.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/journal.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/parameter.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/dynamic.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/rangemap.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state_dependency_graph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state_topological.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state_selection.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/project.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/dashtbl.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state_builder.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/plugin.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/kernel.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/emitter.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/binary_cache.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/hptmap.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/hptset.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cilmsg.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/alpha.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/clist.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/growArray.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/inthash.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil_datatype.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cilutil.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/setWithNearest.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil_state_builder.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/utf8_logic.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cilglobopt.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/machdep_x86_16.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/machdep_x86_32.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/machdep_x86_64.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/machdep_ppc_32.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/machdep.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil_const.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_env.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/escape.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_const.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/errorloc.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cabs.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/expcompare.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cabshelper.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/whitetrack.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_utils.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_builtin.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_print.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_parser.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_lexer.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lexerhack.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/mergecil.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/rmtmps.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_typing.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cprint.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cabscond.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cabsvisit.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cabs2cil.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/clexer.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cparser.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_preprocess.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/frontc.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/obfuscate.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/ciltools.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/callgraph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/dataflow.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/dominators.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/oneret.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cfg.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/usedef.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/liveness.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/reachingdefs.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/availexpslv.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/rmciltmps.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/deadcodeelim.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/buckx.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/ast_info.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/ast_printer.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/ast.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/property.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/property_status.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/annotations.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/globals.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/kernel_function.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/description.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/alarms.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cilE.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/messages.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/abstract_interp.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lattice_Interval_Set.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/int_Base.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/unicode.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/bit_utils.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/subst.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/service_graph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/ival.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/base.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/base_Set_Lattice.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/origin.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/map_Lattice.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/abstract_value.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/locations.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/shifted_Location.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/path_lattice.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/int_Interv.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/int_Interv_Map.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/tr_offset.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/new_offsetmap.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/offsetmap.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/offsetmap_bitwise.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lmap.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lmap_bitwise.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/function_Froms.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cvalue.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/widen_type.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state_set.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/state_imp.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/stmts_graph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/visitor.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/printer.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/unroll_loops.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/loop.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/inout_type.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/pdgIndex.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/pdgTypes.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/pdgMarks.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/slicingInternals.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/slicingTypes.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/db.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/command.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/task.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/translate_lightweight.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/file.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/filter.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/special_hooks.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/widen.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/bit_model_access.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/logic_interp.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/infer_annotations.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Occurrence.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Metrics.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Syntactic_callgraph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Value.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/RteGen.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/From.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Users.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Constant_Propagation.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Postdominators.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Inout.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Semantic_callgraph.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Impact.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Pdg.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Scope.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Sparecode.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/Slicing.cmo /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/boot.cmo +DYN_OLINKFLAGS=-w +a-4-6-7-9 -annot -g -compact -linkall -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/misc -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/toplevel -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/slicing_types -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/pdg_types -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/type -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/gui -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/external -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins -I /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib +DYN_GEN_OPT_LIBS=/localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/graph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx/mybigarray.o /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx/buckx_c.o DYN_OPT_LIBS=nums.cmxa unix.cmxa bigarray.cmxa str.cmxa dynlink.cmxa -DYN_ALL_BATCH_CMX=/localhome/virgile/tmp/Carbon-20110201/external/unmarshal.cmx /localhome/virgile/tmp/Carbon-20110201/external/unmarshal_nums.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/printexc_common_interface.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/dynlink_common_interface.cmx /localhome/virgile/tmp/Carbon-20110201/src/type/structural_descr.cmx /localhome/virgile/tmp/Carbon-20110201/src/type/type.cmx /localhome/virgile/tmp/Carbon-20110201/src/type/descr.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/extlib.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/pretty_utils.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/hook.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/bag.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/bitvector.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/qstack.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/config.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/log.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/cmdline.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/project_skeleton.cmx /localhome/virgile/tmp/Carbon-20110201/src/type/datatype.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/journal.cmx /localhome/virgile/tmp/Carbon-20110201/src/lib/rangemap.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/state.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/state_dependency_graph.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/state_topological.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/state_selection.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/project.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/dashtbl.cmx /localhome/virgile/tmp/Carbon-20110201/src/project/state_builder.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/cilmsg.cmx /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil/alpha.cmx /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil/clist.cmx /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil/growArray.cmx /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil/inthash.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/cil_datatype.cmx /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil/cilutil.cmx /localhome/virgile/tmp/Carbon-20110201/cil/ocamlutil/setWithNearest.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/cil_state_builder.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/utf8_logic.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/cilglobopt.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/machdep_x86_16.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/machdep_x86_32.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/machdep_x86_64.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/machdep_ppc_32.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/machdep_ppc_32_diab.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/machdep.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/cil_const.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_env.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/escape.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_const.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/cil.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/errorloc.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cabs.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/expcompare.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cabshelper.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/whitetrack.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_utils.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_builtin.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_print.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_parser.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_lexer.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/lexerhack.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/mergecil.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/rmtmps.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_typing.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cprint.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cabscond.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cabsvisit.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cabs2cil.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/clexer.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/cparser.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/logic/logic_preprocess.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/patch.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/frontc/frontc.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/obfuscate.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/ciltools.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/callgraph.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/dataflow.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/dominators.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/oneret.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/cfg.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/usedef.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/liveness.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/reachingdefs.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/availexpslv.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/rmciltmps.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/ext/deadcodeelim.cmx /localhome/virgile/tmp/Carbon-20110201/cil/src/zrapp.cmx /localhome/virgile/tmp/Carbon-20110201/src/buckx/buckx.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/dynamic.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/ast_printer.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/ast_info.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/kernel_datatype.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/plugin.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/kernel.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/alarms.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/cilE.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/binary_cache.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/parameters.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/messages.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/ast.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/my_bigint.cmx /localhome/virgile/tmp/Carbon-20110201/external/hptmap.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/hptset.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/abstract_interp.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/int_Base.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/unicode.cmx /localhome/virgile/tmp/Carbon-20110201/src/misc/bit_utils.cmx /localhome/virgile/tmp/Carbon-20110201/src/misc/subst.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/annotations.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/globals.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/kernel_function.cmx /localhome/virgile/tmp/Carbon-20110201/src/misc/service_graph.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/ival.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/base.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/base_Set_Lattice.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/origin.cmx /localhome/virgile/tmp/Carbon-20110201/src/ai/map_Lattice.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/abstract_value.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/locations.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/shifted_Location.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/path_lattice.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/int_Interv.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/int_Interv_Map.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/new_offsetmap.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/offsetmap.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/offsetmap_bitwise.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/lmap.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/lmap_bitwise.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/lmap_whole.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/function_Froms.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/cvalue_type.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/widen_type.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/relations_type.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/state_set.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/state_imp.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/stmts_graph.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/visitor.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/printer.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/unroll_loops.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/loop.cmx /localhome/virgile/tmp/Carbon-20110201/src/logic/property.cmx /localhome/virgile/tmp/Carbon-20110201/src/logic/properties_status.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/inout_type.cmx /localhome/virgile/tmp/Carbon-20110201/src/pdg_types/pdgIndex.cmx /localhome/virgile/tmp/Carbon-20110201/src/pdg_types/pdgTypes.cmx /localhome/virgile/tmp/Carbon-20110201/src/pdg_types/pdgMarks.cmx /localhome/virgile/tmp/Carbon-20110201/src/slicing_types/slicingInternals.cmx /localhome/virgile/tmp/Carbon-20110201/src/slicing_types/slicingTypes.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/db.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/command.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/task.cmx /localhome/virgile/tmp/Carbon-20110201/src/logic/translate_lightweight.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/file.cmx /localhome/virgile/tmp/Carbon-20110201/src/misc/filter.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/special_hooks.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/widen.cmx /localhome/virgile/tmp/Carbon-20110201/src/memory_state/bit_model_access.cmx /localhome/virgile/tmp/Carbon-20110201/src/logic/logic_interp.cmx /localhome/virgile/tmp/Carbon-20110201/src/logic/infer_annotations.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Occurrence.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Metrics.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Syntactic_callgraph.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Value.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/RteGen.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Report.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/From.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Users.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Constant_Propagation.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Postdominators.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Inout.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Semantic_callgraph.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Impact.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Pdg.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Scope.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Sparecode.cmx /localhome/virgile/tmp/Carbon-20110201/lib/plugins/Slicing.cmx /localhome/virgile/tmp/Carbon-20110201/src/kernel/boot.cmx +DYN_ALL_BATCH_CMX=/localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/external/unmarshal.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/external/unmarshal_nums.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/printexc_common_interface.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/map_common_interface.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/dynlink_common_interface.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/type/structural_descr.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/type/type.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/type/descr.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/extlib.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/pretty_utils.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/hook.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/bag.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/bitvector.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/qstack.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/my_bigint.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/config.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/log.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/cmdline.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/project_skeleton.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/type/datatype.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/journal.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/parameter.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/dynamic.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/rangemap.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/state.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/state_dependency_graph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/state_topological.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/state_selection.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/project.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/dashtbl.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/project/state_builder.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/plugin.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/kernel.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/emitter.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/binary_cache.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/external/hptmap.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/lib/hptset.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/cilmsg.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil/alpha.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil/clist.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil/growArray.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil/inthash.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/cil_datatype.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil/cilutil.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/ocamlutil/setWithNearest.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/cil_state_builder.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/utf8_logic.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/cilglobopt.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/machdep_x86_16.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/machdep_x86_32.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/machdep_x86_64.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/machdep_ppc_32.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/machdep.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/cil_const.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_env.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/escape.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_const.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/cil.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/errorloc.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cabs.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/expcompare.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cabshelper.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/whitetrack.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_utils.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_builtin.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_print.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_parser.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_lexer.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/lexerhack.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/mergecil.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/rmtmps.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_typing.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cprint.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cabscond.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cabsvisit.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cabs2cil.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/clexer.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/cparser.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/logic/logic_preprocess.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/frontc/frontc.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/obfuscate.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/ciltools.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/callgraph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/dataflow.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/dominators.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/oneret.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/cfg.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/usedef.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/liveness.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/reachingdefs.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/availexpslv.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/rmciltmps.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/cil/src/ext/deadcodeelim.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/buckx/buckx.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/ast_info.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/ast_printer.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/ast.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic/property.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic/property_status.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/annotations.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/globals.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/kernel_function.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic/description.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/alarms.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/cilE.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/messages.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/abstract_interp.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/lattice_Interval_Set.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/int_Base.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/unicode.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/misc/bit_utils.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/misc/subst.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/misc/service_graph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/ival.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/base.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/base_Set_Lattice.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/origin.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/ai/map_Lattice.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/abstract_value.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/locations.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/shifted_Location.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/path_lattice.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/int_Interv.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/int_Interv_Map.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/tr_offset.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/new_offsetmap.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/offsetmap.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/offsetmap_bitwise.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/lmap.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/lmap_bitwise.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/function_Froms.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/cvalue.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/widen_type.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/state_set.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/state_imp.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/stmts_graph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/visitor.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/printer.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/unroll_loops.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/loop.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/inout_type.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/pdg_types/pdgIndex.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/pdg_types/pdgTypes.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/pdg_types/pdgMarks.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/slicing_types/slicingInternals.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/slicing_types/slicingTypes.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/db.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/command.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/task.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic/translate_lightweight.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/file.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/misc/filter.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/special_hooks.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/widen.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/memory_state/bit_model_access.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic/logic_interp.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/logic/infer_annotations.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Occurrence.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Metrics.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Syntactic_callgraph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Value.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/RteGen.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/From.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Users.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Constant_Propagation.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Postdominators.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Inout.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Semantic_callgraph.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Impact.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Pdg.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Scope.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Sparecode.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/lib/plugins/Slicing.cmx /localhome/julien/tmp/frama-c/tags/Nitrogen-20111001/src/kernel/boot.cmx else DYN_BLINKFLAGS=-w +a-4-6-7-9 -annot -g -linkall -custom DYN_GEN_BYTE_LIBS=/usr/local/lib/frama-c/graph.cmo /usr/local/lib/frama-c/mybigarray.o /usr/local/lib/frama-c/buckx_c.o DYN_BYTE_LIBS=nums.cma unix.cma bigarray.cma str.cma dynlink.cma -DYN_ALL_BATCH_CMO=/usr/local/lib/frama-c/unmarshal.cmo /usr/local/lib/frama-c/unmarshal_nums.cmo /usr/local/lib/frama-c/printexc_common_interface.cmo /usr/local/lib/frama-c/dynlink_common_interface.cmo /usr/local/lib/frama-c/structural_descr.cmo /usr/local/lib/frama-c/type.cmo /usr/local/lib/frama-c/descr.cmo /usr/local/lib/frama-c/extlib.cmo /usr/local/lib/frama-c/pretty_utils.cmo /usr/local/lib/frama-c/hook.cmo /usr/local/lib/frama-c/bag.cmo /usr/local/lib/frama-c/bitvector.cmo /usr/local/lib/frama-c/qstack.cmo /usr/local/lib/frama-c/config.cmo /usr/local/lib/frama-c/log.cmo /usr/local/lib/frama-c/cmdline.cmo /usr/local/lib/frama-c/project_skeleton.cmo /usr/local/lib/frama-c/datatype.cmo /usr/local/lib/frama-c/journal.cmo /usr/local/lib/frama-c/rangemap.cmo /usr/local/lib/frama-c/state.cmo /usr/local/lib/frama-c/state_dependency_graph.cmo /usr/local/lib/frama-c/state_topological.cmo /usr/local/lib/frama-c/state_selection.cmo /usr/local/lib/frama-c/project.cmo /usr/local/lib/frama-c/dashtbl.cmo /usr/local/lib/frama-c/state_builder.cmo /usr/local/lib/frama-c/cilmsg.cmo /usr/local/lib/frama-c/alpha.cmo /usr/local/lib/frama-c/clist.cmo /usr/local/lib/frama-c/growArray.cmo /usr/local/lib/frama-c/inthash.cmo /usr/local/lib/frama-c/cil_datatype.cmo /usr/local/lib/frama-c/cilutil.cmo /usr/local/lib/frama-c/setWithNearest.cmo /usr/local/lib/frama-c/cil_state_builder.cmo /usr/local/lib/frama-c/utf8_logic.cmo /usr/local/lib/frama-c/cilglobopt.cmo /usr/local/lib/frama-c/machdep_x86_16.cmo /usr/local/lib/frama-c/machdep_x86_32.cmo /usr/local/lib/frama-c/machdep_x86_64.cmo /usr/local/lib/frama-c/machdep_ppc_32.cmo /usr/local/lib/frama-c/machdep_ppc_32_diab.cmo /usr/local/lib/frama-c/machdep.cmo /usr/local/lib/frama-c/cil_const.cmo /usr/local/lib/frama-c/logic_env.cmo /usr/local/lib/frama-c/escape.cmo /usr/local/lib/frama-c/logic_const.cmo /usr/local/lib/frama-c/cil.cmo /usr/local/lib/frama-c/errorloc.cmo /usr/local/lib/frama-c/cabs.cmo /usr/local/lib/frama-c/expcompare.cmo /usr/local/lib/frama-c/cabshelper.cmo /usr/local/lib/frama-c/whitetrack.cmo /usr/local/lib/frama-c/logic_utils.cmo /usr/local/lib/frama-c/logic_builtin.cmo /usr/local/lib/frama-c/logic_print.cmo /usr/local/lib/frama-c/logic_parser.cmo /usr/local/lib/frama-c/logic_lexer.cmo /usr/local/lib/frama-c/lexerhack.cmo /usr/local/lib/frama-c/mergecil.cmo /usr/local/lib/frama-c/rmtmps.cmo /usr/local/lib/frama-c/logic_typing.cmo /usr/local/lib/frama-c/cprint.cmo /usr/local/lib/frama-c/cabscond.cmo /usr/local/lib/frama-c/cabsvisit.cmo /usr/local/lib/frama-c/cabs2cil.cmo /usr/local/lib/frama-c/clexer.cmo /usr/local/lib/frama-c/cparser.cmo /usr/local/lib/frama-c/logic_preprocess.cmo /usr/local/lib/frama-c/patch.cmo /usr/local/lib/frama-c/frontc.cmo /usr/local/lib/frama-c/obfuscate.cmo /usr/local/lib/frama-c/ciltools.cmo /usr/local/lib/frama-c/callgraph.cmo /usr/local/lib/frama-c/dataflow.cmo /usr/local/lib/frama-c/dominators.cmo /usr/local/lib/frama-c/oneret.cmo /usr/local/lib/frama-c/cfg.cmo /usr/local/lib/frama-c/usedef.cmo /usr/local/lib/frama-c/liveness.cmo /usr/local/lib/frama-c/reachingdefs.cmo /usr/local/lib/frama-c/availexpslv.cmo /usr/local/lib/frama-c/rmciltmps.cmo /usr/local/lib/frama-c/deadcodeelim.cmo /usr/local/lib/frama-c/zrapp.cmo /usr/local/lib/frama-c/buckx.cmo /usr/local/lib/frama-c/dynamic.cmo /usr/local/lib/frama-c/ast_printer.cmo /usr/local/lib/frama-c/ast_info.cmo /usr/local/lib/frama-c/kernel_datatype.cmo /usr/local/lib/frama-c/plugin.cmo /usr/local/lib/frama-c/kernel.cmo /usr/local/lib/frama-c/alarms.cmo /usr/local/lib/frama-c/cilE.cmo /usr/local/lib/frama-c/binary_cache.cmo /usr/local/lib/frama-c/parameters.cmo /usr/local/lib/frama-c/messages.cmo /usr/local/lib/frama-c/ast.cmo /usr/local/lib/frama-c/my_bigint.cmo /usr/local/lib/frama-c/hptmap.cmo /usr/local/lib/frama-c/hptset.cmo /usr/local/lib/frama-c/abstract_interp.cmo /usr/local/lib/frama-c/int_Base.cmo /usr/local/lib/frama-c/unicode.cmo /usr/local/lib/frama-c/bit_utils.cmo /usr/local/lib/frama-c/subst.cmo /usr/local/lib/frama-c/annotations.cmo /usr/local/lib/frama-c/globals.cmo /usr/local/lib/frama-c/kernel_function.cmo /usr/local/lib/frama-c/service_graph.cmo /usr/local/lib/frama-c/ival.cmo /usr/local/lib/frama-c/base.cmo /usr/local/lib/frama-c/base_Set_Lattice.cmo /usr/local/lib/frama-c/origin.cmo /usr/local/lib/frama-c/map_Lattice.cmo /usr/local/lib/frama-c/abstract_value.cmo /usr/local/lib/frama-c/locations.cmo /usr/local/lib/frama-c/shifted_Location.cmo /usr/local/lib/frama-c/path_lattice.cmo /usr/local/lib/frama-c/int_Interv.cmo /usr/local/lib/frama-c/int_Interv_Map.cmo /usr/local/lib/frama-c/new_offsetmap.cmo /usr/local/lib/frama-c/offsetmap.cmo /usr/local/lib/frama-c/offsetmap_bitwise.cmo /usr/local/lib/frama-c/lmap.cmo /usr/local/lib/frama-c/lmap_bitwise.cmo /usr/local/lib/frama-c/lmap_whole.cmo /usr/local/lib/frama-c/function_Froms.cmo /usr/local/lib/frama-c/cvalue_type.cmo /usr/local/lib/frama-c/widen_type.cmo /usr/local/lib/frama-c/relations_type.cmo /usr/local/lib/frama-c/state_set.cmo /usr/local/lib/frama-c/state_imp.cmo /usr/local/lib/frama-c/stmts_graph.cmo /usr/local/lib/frama-c/visitor.cmo /usr/local/lib/frama-c/printer.cmo /usr/local/lib/frama-c/unroll_loops.cmo /usr/local/lib/frama-c/loop.cmo /usr/local/lib/frama-c/property.cmo /usr/local/lib/frama-c/properties_status.cmo /usr/local/lib/frama-c/inout_type.cmo /usr/local/lib/frama-c/pdgIndex.cmo /usr/local/lib/frama-c/pdgTypes.cmo /usr/local/lib/frama-c/pdgMarks.cmo /usr/local/lib/frama-c/slicingInternals.cmo /usr/local/lib/frama-c/slicingTypes.cmo /usr/local/lib/frama-c/db.cmo /usr/local/lib/frama-c/command.cmo /usr/local/lib/frama-c/task.cmo /usr/local/lib/frama-c/translate_lightweight.cmo /usr/local/lib/frama-c/file.cmo /usr/local/lib/frama-c/filter.cmo /usr/local/lib/frama-c/special_hooks.cmo /usr/local/lib/frama-c/widen.cmo /usr/local/lib/frama-c/bit_model_access.cmo /usr/local/lib/frama-c/logic_interp.cmo /usr/local/lib/frama-c/infer_annotations.cmo /usr/local/lib/frama-c/Occurrence.cmo /usr/local/lib/frama-c/Metrics.cmo /usr/local/lib/frama-c/Syntactic_callgraph.cmo /usr/local/lib/frama-c/Value.cmo /usr/local/lib/frama-c/RteGen.cmo /usr/local/lib/frama-c/Report.cmo /usr/local/lib/frama-c/From.cmo /usr/local/lib/frama-c/Users.cmo /usr/local/lib/frama-c/Constant_Propagation.cmo /usr/local/lib/frama-c/Postdominators.cmo /usr/local/lib/frama-c/Inout.cmo /usr/local/lib/frama-c/Semantic_callgraph.cmo /usr/local/lib/frama-c/Impact.cmo /usr/local/lib/frama-c/Pdg.cmo /usr/local/lib/frama-c/Scope.cmo /usr/local/lib/frama-c/Sparecode.cmo /usr/local/lib/frama-c/Slicing.cmo /usr/local/lib/frama-c/boot.cmo -DYN_OLINKFLAGS=-w +a-4-6-7-9 -annot -g -linkall +DYN_ALL_BATCH_CMO=/usr/local/lib/frama-c/unmarshal.cmo /usr/local/lib/frama-c/unmarshal_nums.cmo /usr/local/lib/frama-c/printexc_common_interface.cmo /usr/local/lib/frama-c/map_common_interface.cmo /usr/local/lib/frama-c/dynlink_common_interface.cmo /usr/local/lib/frama-c/structural_descr.cmo /usr/local/lib/frama-c/type.cmo /usr/local/lib/frama-c/descr.cmo /usr/local/lib/frama-c/extlib.cmo /usr/local/lib/frama-c/pretty_utils.cmo /usr/local/lib/frama-c/hook.cmo /usr/local/lib/frama-c/bag.cmo /usr/local/lib/frama-c/bitvector.cmo /usr/local/lib/frama-c/qstack.cmo /usr/local/lib/frama-c/my_bigint.cmo /usr/local/lib/frama-c/config.cmo /usr/local/lib/frama-c/log.cmo /usr/local/lib/frama-c/cmdline.cmo /usr/local/lib/frama-c/project_skeleton.cmo /usr/local/lib/frama-c/datatype.cmo /usr/local/lib/frama-c/journal.cmo /usr/local/lib/frama-c/parameter.cmo /usr/local/lib/frama-c/dynamic.cmo /usr/local/lib/frama-c/rangemap.cmo /usr/local/lib/frama-c/state.cmo /usr/local/lib/frama-c/state_dependency_graph.cmo /usr/local/lib/frama-c/state_topological.cmo /usr/local/lib/frama-c/state_selection.cmo /usr/local/lib/frama-c/project.cmo /usr/local/lib/frama-c/dashtbl.cmo /usr/local/lib/frama-c/state_builder.cmo /usr/local/lib/frama-c/plugin.cmo /usr/local/lib/frama-c/kernel.cmo /usr/local/lib/frama-c/emitter.cmo /usr/local/lib/frama-c/binary_cache.cmo /usr/local/lib/frama-c/hptmap.cmo /usr/local/lib/frama-c/hptset.cmo /usr/local/lib/frama-c/cilmsg.cmo /usr/local/lib/frama-c/alpha.cmo /usr/local/lib/frama-c/clist.cmo /usr/local/lib/frama-c/growArray.cmo /usr/local/lib/frama-c/inthash.cmo /usr/local/lib/frama-c/cil_datatype.cmo /usr/local/lib/frama-c/cilutil.cmo /usr/local/lib/frama-c/setWithNearest.cmo /usr/local/lib/frama-c/cil_state_builder.cmo /usr/local/lib/frama-c/utf8_logic.cmo /usr/local/lib/frama-c/cilglobopt.cmo /usr/local/lib/frama-c/machdep_x86_16.cmo /usr/local/lib/frama-c/machdep_x86_32.cmo /usr/local/lib/frama-c/machdep_x86_64.cmo /usr/local/lib/frama-c/machdep_ppc_32.cmo /usr/local/lib/frama-c/machdep.cmo /usr/local/lib/frama-c/cil_const.cmo /usr/local/lib/frama-c/logic_env.cmo /usr/local/lib/frama-c/escape.cmo /usr/local/lib/frama-c/logic_const.cmo /usr/local/lib/frama-c/cil.cmo /usr/local/lib/frama-c/errorloc.cmo /usr/local/lib/frama-c/cabs.cmo /usr/local/lib/frama-c/expcompare.cmo /usr/local/lib/frama-c/cabshelper.cmo /usr/local/lib/frama-c/whitetrack.cmo /usr/local/lib/frama-c/logic_utils.cmo /usr/local/lib/frama-c/logic_builtin.cmo /usr/local/lib/frama-c/logic_print.cmo /usr/local/lib/frama-c/logic_parser.cmo /usr/local/lib/frama-c/logic_lexer.cmo /usr/local/lib/frama-c/lexerhack.cmo /usr/local/lib/frama-c/mergecil.cmo /usr/local/lib/frama-c/rmtmps.cmo /usr/local/lib/frama-c/logic_typing.cmo /usr/local/lib/frama-c/cprint.cmo /usr/local/lib/frama-c/cabscond.cmo /usr/local/lib/frama-c/cabsvisit.cmo /usr/local/lib/frama-c/cabs2cil.cmo /usr/local/lib/frama-c/clexer.cmo /usr/local/lib/frama-c/cparser.cmo /usr/local/lib/frama-c/logic_preprocess.cmo /usr/local/lib/frama-c/frontc.cmo /usr/local/lib/frama-c/obfuscate.cmo /usr/local/lib/frama-c/ciltools.cmo /usr/local/lib/frama-c/callgraph.cmo /usr/local/lib/frama-c/dataflow.cmo /usr/local/lib/frama-c/dominators.cmo /usr/local/lib/frama-c/oneret.cmo /usr/local/lib/frama-c/cfg.cmo /usr/local/lib/frama-c/usedef.cmo /usr/local/lib/frama-c/liveness.cmo /usr/local/lib/frama-c/reachingdefs.cmo /usr/local/lib/frama-c/availexpslv.cmo /usr/local/lib/frama-c/rmciltmps.cmo /usr/local/lib/frama-c/deadcodeelim.cmo /usr/local/lib/frama-c/buckx.cmo /usr/local/lib/frama-c/ast_info.cmo /usr/local/lib/frama-c/ast_printer.cmo /usr/local/lib/frama-c/ast.cmo /usr/local/lib/frama-c/property.cmo /usr/local/lib/frama-c/property_status.cmo /usr/local/lib/frama-c/annotations.cmo /usr/local/lib/frama-c/globals.cmo /usr/local/lib/frama-c/kernel_function.cmo /usr/local/lib/frama-c/description.cmo /usr/local/lib/frama-c/alarms.cmo /usr/local/lib/frama-c/cilE.cmo /usr/local/lib/frama-c/messages.cmo /usr/local/lib/frama-c/abstract_interp.cmo /usr/local/lib/frama-c/lattice_Interval_Set.cmo /usr/local/lib/frama-c/int_Base.cmo /usr/local/lib/frama-c/unicode.cmo /usr/local/lib/frama-c/bit_utils.cmo /usr/local/lib/frama-c/subst.cmo /usr/local/lib/frama-c/service_graph.cmo /usr/local/lib/frama-c/ival.cmo /usr/local/lib/frama-c/base.cmo /usr/local/lib/frama-c/base_Set_Lattice.cmo /usr/local/lib/frama-c/origin.cmo /usr/local/lib/frama-c/map_Lattice.cmo /usr/local/lib/frama-c/abstract_value.cmo /usr/local/lib/frama-c/locations.cmo /usr/local/lib/frama-c/shifted_Location.cmo /usr/local/lib/frama-c/path_lattice.cmo /usr/local/lib/frama-c/int_Interv.cmo /usr/local/lib/frama-c/int_Interv_Map.cmo /usr/local/lib/frama-c/tr_offset.cmo /usr/local/lib/frama-c/new_offsetmap.cmo /usr/local/lib/frama-c/offsetmap.cmo /usr/local/lib/frama-c/offsetmap_bitwise.cmo /usr/local/lib/frama-c/lmap.cmo /usr/local/lib/frama-c/lmap_bitwise.cmo /usr/local/lib/frama-c/function_Froms.cmo /usr/local/lib/frama-c/cvalue.cmo /usr/local/lib/frama-c/widen_type.cmo /usr/local/lib/frama-c/state_set.cmo /usr/local/lib/frama-c/state_imp.cmo /usr/local/lib/frama-c/stmts_graph.cmo /usr/local/lib/frama-c/visitor.cmo /usr/local/lib/frama-c/printer.cmo /usr/local/lib/frama-c/unroll_loops.cmo /usr/local/lib/frama-c/loop.cmo /usr/local/lib/frama-c/inout_type.cmo /usr/local/lib/frama-c/pdgIndex.cmo /usr/local/lib/frama-c/pdgTypes.cmo /usr/local/lib/frama-c/pdgMarks.cmo /usr/local/lib/frama-c/slicingInternals.cmo /usr/local/lib/frama-c/slicingTypes.cmo /usr/local/lib/frama-c/db.cmo /usr/local/lib/frama-c/command.cmo /usr/local/lib/frama-c/task.cmo /usr/local/lib/frama-c/translate_lightweight.cmo /usr/local/lib/frama-c/file.cmo /usr/local/lib/frama-c/filter.cmo /usr/local/lib/frama-c/special_hooks.cmo /usr/local/lib/frama-c/widen.cmo /usr/local/lib/frama-c/bit_model_access.cmo /usr/local/lib/frama-c/logic_interp.cmo /usr/local/lib/frama-c/infer_annotations.cmo /usr/local/lib/frama-c/Occurrence.cmo /usr/local/lib/frama-c/Metrics.cmo /usr/local/lib/frama-c/Syntactic_callgraph.cmo /usr/local/lib/frama-c/Value.cmo /usr/local/lib/frama-c/RteGen.cmo /usr/local/lib/frama-c/From.cmo /usr/local/lib/frama-c/Users.cmo /usr/local/lib/frama-c/Constant_Propagation.cmo /usr/local/lib/frama-c/Postdominators.cmo /usr/local/lib/frama-c/Inout.cmo /usr/local/lib/frama-c/Semantic_callgraph.cmo /usr/local/lib/frama-c/Impact.cmo /usr/local/lib/frama-c/Pdg.cmo /usr/local/lib/frama-c/Scope.cmo /usr/local/lib/frama-c/Sparecode.cmo /usr/local/lib/frama-c/Slicing.cmo /usr/local/lib/frama-c/boot.cmo +DYN_OLINKFLAGS=-w +a-4-6-7-9 -annot -g -compact -linkall DYN_GEN_OPT_LIBS=/usr/local/lib/frama-c/graph.cmx /usr/local/lib/frama-c/mybigarray.o /usr/local/lib/frama-c/buckx_c.o DYN_OPT_LIBS=nums.cmxa unix.cmxa bigarray.cmxa str.cmxa dynlink.cmxa -DYN_ALL_BATCH_CMX=/usr/local/lib/frama-c/unmarshal.cmx /usr/local/lib/frama-c/unmarshal_nums.cmx /usr/local/lib/frama-c/printexc_common_interface.cmx /usr/local/lib/frama-c/dynlink_common_interface.cmx /usr/local/lib/frama-c/structural_descr.cmx /usr/local/lib/frama-c/type.cmx /usr/local/lib/frama-c/descr.cmx /usr/local/lib/frama-c/extlib.cmx /usr/local/lib/frama-c/pretty_utils.cmx /usr/local/lib/frama-c/hook.cmx /usr/local/lib/frama-c/bag.cmx /usr/local/lib/frama-c/bitvector.cmx /usr/local/lib/frama-c/qstack.cmx /usr/local/lib/frama-c/config.cmx /usr/local/lib/frama-c/log.cmx /usr/local/lib/frama-c/cmdline.cmx /usr/local/lib/frama-c/project_skeleton.cmx /usr/local/lib/frama-c/datatype.cmx /usr/local/lib/frama-c/journal.cmx /usr/local/lib/frama-c/rangemap.cmx /usr/local/lib/frama-c/state.cmx /usr/local/lib/frama-c/state_dependency_graph.cmx /usr/local/lib/frama-c/state_topological.cmx /usr/local/lib/frama-c/state_selection.cmx /usr/local/lib/frama-c/project.cmx /usr/local/lib/frama-c/dashtbl.cmx /usr/local/lib/frama-c/state_builder.cmx /usr/local/lib/frama-c/cilmsg.cmx /usr/local/lib/frama-c/alpha.cmx /usr/local/lib/frama-c/clist.cmx /usr/local/lib/frama-c/growArray.cmx /usr/local/lib/frama-c/inthash.cmx /usr/local/lib/frama-c/cil_datatype.cmx /usr/local/lib/frama-c/cilutil.cmx /usr/local/lib/frama-c/setWithNearest.cmx /usr/local/lib/frama-c/cil_state_builder.cmx /usr/local/lib/frama-c/utf8_logic.cmx /usr/local/lib/frama-c/cilglobopt.cmx /usr/local/lib/frama-c/machdep_x86_16.cmx /usr/local/lib/frama-c/machdep_x86_32.cmx /usr/local/lib/frama-c/machdep_x86_64.cmx /usr/local/lib/frama-c/machdep_ppc_32.cmx /usr/local/lib/frama-c/machdep_ppc_32_diab.cmx /usr/local/lib/frama-c/machdep.cmx /usr/local/lib/frama-c/cil_const.cmx /usr/local/lib/frama-c/logic_env.cmx /usr/local/lib/frama-c/escape.cmx /usr/local/lib/frama-c/logic_const.cmx /usr/local/lib/frama-c/cil.cmx /usr/local/lib/frama-c/errorloc.cmx /usr/local/lib/frama-c/cabs.cmx /usr/local/lib/frama-c/expcompare.cmx /usr/local/lib/frama-c/cabshelper.cmx /usr/local/lib/frama-c/whitetrack.cmx /usr/local/lib/frama-c/logic_utils.cmx /usr/local/lib/frama-c/logic_builtin.cmx /usr/local/lib/frama-c/logic_print.cmx /usr/local/lib/frama-c/logic_parser.cmx /usr/local/lib/frama-c/logic_lexer.cmx /usr/local/lib/frama-c/lexerhack.cmx /usr/local/lib/frama-c/mergecil.cmx /usr/local/lib/frama-c/rmtmps.cmx /usr/local/lib/frama-c/logic_typing.cmx /usr/local/lib/frama-c/cprint.cmx /usr/local/lib/frama-c/cabscond.cmx /usr/local/lib/frama-c/cabsvisit.cmx /usr/local/lib/frama-c/cabs2cil.cmx /usr/local/lib/frama-c/clexer.cmx /usr/local/lib/frama-c/cparser.cmx /usr/local/lib/frama-c/logic_preprocess.cmx /usr/local/lib/frama-c/patch.cmx /usr/local/lib/frama-c/frontc.cmx /usr/local/lib/frama-c/obfuscate.cmx /usr/local/lib/frama-c/ciltools.cmx /usr/local/lib/frama-c/callgraph.cmx /usr/local/lib/frama-c/dataflow.cmx /usr/local/lib/frama-c/dominators.cmx /usr/local/lib/frama-c/oneret.cmx /usr/local/lib/frama-c/cfg.cmx /usr/local/lib/frama-c/usedef.cmx /usr/local/lib/frama-c/liveness.cmx /usr/local/lib/frama-c/reachingdefs.cmx /usr/local/lib/frama-c/availexpslv.cmx /usr/local/lib/frama-c/rmciltmps.cmx /usr/local/lib/frama-c/deadcodeelim.cmx /usr/local/lib/frama-c/zrapp.cmx /usr/local/lib/frama-c/buckx.cmx /usr/local/lib/frama-c/dynamic.cmx /usr/local/lib/frama-c/ast_printer.cmx /usr/local/lib/frama-c/ast_info.cmx /usr/local/lib/frama-c/kernel_datatype.cmx /usr/local/lib/frama-c/plugin.cmx /usr/local/lib/frama-c/kernel.cmx /usr/local/lib/frama-c/alarms.cmx /usr/local/lib/frama-c/cilE.cmx /usr/local/lib/frama-c/binary_cache.cmx /usr/local/lib/frama-c/parameters.cmx /usr/local/lib/frama-c/messages.cmx /usr/local/lib/frama-c/ast.cmx /usr/local/lib/frama-c/my_bigint.cmx /usr/local/lib/frama-c/hptmap.cmx /usr/local/lib/frama-c/hptset.cmx /usr/local/lib/frama-c/abstract_interp.cmx /usr/local/lib/frama-c/int_Base.cmx /usr/local/lib/frama-c/unicode.cmx /usr/local/lib/frama-c/bit_utils.cmx /usr/local/lib/frama-c/subst.cmx /usr/local/lib/frama-c/annotations.cmx /usr/local/lib/frama-c/globals.cmx /usr/local/lib/frama-c/kernel_function.cmx /usr/local/lib/frama-c/service_graph.cmx /usr/local/lib/frama-c/ival.cmx /usr/local/lib/frama-c/base.cmx /usr/local/lib/frama-c/base_Set_Lattice.cmx /usr/local/lib/frama-c/origin.cmx /usr/local/lib/frama-c/map_Lattice.cmx /usr/local/lib/frama-c/abstract_value.cmx /usr/local/lib/frama-c/locations.cmx /usr/local/lib/frama-c/shifted_Location.cmx /usr/local/lib/frama-c/path_lattice.cmx /usr/local/lib/frama-c/int_Interv.cmx /usr/local/lib/frama-c/int_Interv_Map.cmx /usr/local/lib/frama-c/new_offsetmap.cmx /usr/local/lib/frama-c/offsetmap.cmx /usr/local/lib/frama-c/offsetmap_bitwise.cmx /usr/local/lib/frama-c/lmap.cmx /usr/local/lib/frama-c/lmap_bitwise.cmx /usr/local/lib/frama-c/lmap_whole.cmx /usr/local/lib/frama-c/function_Froms.cmx /usr/local/lib/frama-c/cvalue_type.cmx /usr/local/lib/frama-c/widen_type.cmx /usr/local/lib/frama-c/relations_type.cmx /usr/local/lib/frama-c/state_set.cmx /usr/local/lib/frama-c/state_imp.cmx /usr/local/lib/frama-c/stmts_graph.cmx /usr/local/lib/frama-c/visitor.cmx /usr/local/lib/frama-c/printer.cmx /usr/local/lib/frama-c/unroll_loops.cmx /usr/local/lib/frama-c/loop.cmx /usr/local/lib/frama-c/property.cmx /usr/local/lib/frama-c/properties_status.cmx /usr/local/lib/frama-c/inout_type.cmx /usr/local/lib/frama-c/pdgIndex.cmx /usr/local/lib/frama-c/pdgTypes.cmx /usr/local/lib/frama-c/pdgMarks.cmx /usr/local/lib/frama-c/slicingInternals.cmx /usr/local/lib/frama-c/slicingTypes.cmx /usr/local/lib/frama-c/db.cmx /usr/local/lib/frama-c/command.cmx /usr/local/lib/frama-c/task.cmx /usr/local/lib/frama-c/translate_lightweight.cmx /usr/local/lib/frama-c/file.cmx /usr/local/lib/frama-c/filter.cmx /usr/local/lib/frama-c/special_hooks.cmx /usr/local/lib/frama-c/widen.cmx /usr/local/lib/frama-c/bit_model_access.cmx /usr/local/lib/frama-c/logic_interp.cmx /usr/local/lib/frama-c/infer_annotations.cmx /usr/local/lib/frama-c/Occurrence.cmx /usr/local/lib/frama-c/Metrics.cmx /usr/local/lib/frama-c/Syntactic_callgraph.cmx /usr/local/lib/frama-c/Value.cmx /usr/local/lib/frama-c/RteGen.cmx /usr/local/lib/frama-c/Report.cmx /usr/local/lib/frama-c/From.cmx /usr/local/lib/frama-c/Users.cmx /usr/local/lib/frama-c/Constant_Propagation.cmx /usr/local/lib/frama-c/Postdominators.cmx /usr/local/lib/frama-c/Inout.cmx /usr/local/lib/frama-c/Semantic_callgraph.cmx /usr/local/lib/frama-c/Impact.cmx /usr/local/lib/frama-c/Pdg.cmx /usr/local/lib/frama-c/Scope.cmx /usr/local/lib/frama-c/Sparecode.cmx /usr/local/lib/frama-c/Slicing.cmx /usr/local/lib/frama-c/boot.cmx +DYN_ALL_BATCH_CMX=/usr/local/lib/frama-c/unmarshal.cmx /usr/local/lib/frama-c/unmarshal_nums.cmx /usr/local/lib/frama-c/printexc_common_interface.cmx /usr/local/lib/frama-c/map_common_interface.cmx /usr/local/lib/frama-c/dynlink_common_interface.cmx /usr/local/lib/frama-c/structural_descr.cmx /usr/local/lib/frama-c/type.cmx /usr/local/lib/frama-c/descr.cmx /usr/local/lib/frama-c/extlib.cmx /usr/local/lib/frama-c/pretty_utils.cmx /usr/local/lib/frama-c/hook.cmx /usr/local/lib/frama-c/bag.cmx /usr/local/lib/frama-c/bitvector.cmx /usr/local/lib/frama-c/qstack.cmx /usr/local/lib/frama-c/my_bigint.cmx /usr/local/lib/frama-c/config.cmx /usr/local/lib/frama-c/log.cmx /usr/local/lib/frama-c/cmdline.cmx /usr/local/lib/frama-c/project_skeleton.cmx /usr/local/lib/frama-c/datatype.cmx /usr/local/lib/frama-c/journal.cmx /usr/local/lib/frama-c/parameter.cmx /usr/local/lib/frama-c/dynamic.cmx /usr/local/lib/frama-c/rangemap.cmx /usr/local/lib/frama-c/state.cmx /usr/local/lib/frama-c/state_dependency_graph.cmx /usr/local/lib/frama-c/state_topological.cmx /usr/local/lib/frama-c/state_selection.cmx /usr/local/lib/frama-c/project.cmx /usr/local/lib/frama-c/dashtbl.cmx /usr/local/lib/frama-c/state_builder.cmx /usr/local/lib/frama-c/plugin.cmx /usr/local/lib/frama-c/kernel.cmx /usr/local/lib/frama-c/emitter.cmx /usr/local/lib/frama-c/binary_cache.cmx /usr/local/lib/frama-c/hptmap.cmx /usr/local/lib/frama-c/hptset.cmx /usr/local/lib/frama-c/cilmsg.cmx /usr/local/lib/frama-c/alpha.cmx /usr/local/lib/frama-c/clist.cmx /usr/local/lib/frama-c/growArray.cmx /usr/local/lib/frama-c/inthash.cmx /usr/local/lib/frama-c/cil_datatype.cmx /usr/local/lib/frama-c/cilutil.cmx /usr/local/lib/frama-c/setWithNearest.cmx /usr/local/lib/frama-c/cil_state_builder.cmx /usr/local/lib/frama-c/utf8_logic.cmx /usr/local/lib/frama-c/cilglobopt.cmx /usr/local/lib/frama-c/machdep_x86_16.cmx /usr/local/lib/frama-c/machdep_x86_32.cmx /usr/local/lib/frama-c/machdep_x86_64.cmx /usr/local/lib/frama-c/machdep_ppc_32.cmx /usr/local/lib/frama-c/machdep.cmx /usr/local/lib/frama-c/cil_const.cmx /usr/local/lib/frama-c/logic_env.cmx /usr/local/lib/frama-c/escape.cmx /usr/local/lib/frama-c/logic_const.cmx /usr/local/lib/frama-c/cil.cmx /usr/local/lib/frama-c/errorloc.cmx /usr/local/lib/frama-c/cabs.cmx /usr/local/lib/frama-c/expcompare.cmx /usr/local/lib/frama-c/cabshelper.cmx /usr/local/lib/frama-c/whitetrack.cmx /usr/local/lib/frama-c/logic_utils.cmx /usr/local/lib/frama-c/logic_builtin.cmx /usr/local/lib/frama-c/logic_print.cmx /usr/local/lib/frama-c/logic_parser.cmx /usr/local/lib/frama-c/logic_lexer.cmx /usr/local/lib/frama-c/lexerhack.cmx /usr/local/lib/frama-c/mergecil.cmx /usr/local/lib/frama-c/rmtmps.cmx /usr/local/lib/frama-c/logic_typing.cmx /usr/local/lib/frama-c/cprint.cmx /usr/local/lib/frama-c/cabscond.cmx /usr/local/lib/frama-c/cabsvisit.cmx /usr/local/lib/frama-c/cabs2cil.cmx /usr/local/lib/frama-c/clexer.cmx /usr/local/lib/frama-c/cparser.cmx /usr/local/lib/frama-c/logic_preprocess.cmx /usr/local/lib/frama-c/frontc.cmx /usr/local/lib/frama-c/obfuscate.cmx /usr/local/lib/frama-c/ciltools.cmx /usr/local/lib/frama-c/callgraph.cmx /usr/local/lib/frama-c/dataflow.cmx /usr/local/lib/frama-c/dominators.cmx /usr/local/lib/frama-c/oneret.cmx /usr/local/lib/frama-c/cfg.cmx /usr/local/lib/frama-c/usedef.cmx /usr/local/lib/frama-c/liveness.cmx /usr/local/lib/frama-c/reachingdefs.cmx /usr/local/lib/frama-c/availexpslv.cmx /usr/local/lib/frama-c/rmciltmps.cmx /usr/local/lib/frama-c/deadcodeelim.cmx /usr/local/lib/frama-c/buckx.cmx /usr/local/lib/frama-c/ast_info.cmx /usr/local/lib/frama-c/ast_printer.cmx /usr/local/lib/frama-c/ast.cmx /usr/local/lib/frama-c/property.cmx /usr/local/lib/frama-c/property_status.cmx /usr/local/lib/frama-c/annotations.cmx /usr/local/lib/frama-c/globals.cmx /usr/local/lib/frama-c/kernel_function.cmx /usr/local/lib/frama-c/description.cmx /usr/local/lib/frama-c/alarms.cmx /usr/local/lib/frama-c/cilE.cmx /usr/local/lib/frama-c/messages.cmx /usr/local/lib/frama-c/abstract_interp.cmx /usr/local/lib/frama-c/lattice_Interval_Set.cmx /usr/local/lib/frama-c/int_Base.cmx /usr/local/lib/frama-c/unicode.cmx /usr/local/lib/frama-c/bit_utils.cmx /usr/local/lib/frama-c/subst.cmx /usr/local/lib/frama-c/service_graph.cmx /usr/local/lib/frama-c/ival.cmx /usr/local/lib/frama-c/base.cmx /usr/local/lib/frama-c/base_Set_Lattice.cmx /usr/local/lib/frama-c/origin.cmx /usr/local/lib/frama-c/map_Lattice.cmx /usr/local/lib/frama-c/abstract_value.cmx /usr/local/lib/frama-c/locations.cmx /usr/local/lib/frama-c/shifted_Location.cmx /usr/local/lib/frama-c/path_lattice.cmx /usr/local/lib/frama-c/int_Interv.cmx /usr/local/lib/frama-c/int_Interv_Map.cmx /usr/local/lib/frama-c/tr_offset.cmx /usr/local/lib/frama-c/new_offsetmap.cmx /usr/local/lib/frama-c/offsetmap.cmx /usr/local/lib/frama-c/offsetmap_bitwise.cmx /usr/local/lib/frama-c/lmap.cmx /usr/local/lib/frama-c/lmap_bitwise.cmx /usr/local/lib/frama-c/function_Froms.cmx /usr/local/lib/frama-c/cvalue.cmx /usr/local/lib/frama-c/widen_type.cmx /usr/local/lib/frama-c/state_set.cmx /usr/local/lib/frama-c/state_imp.cmx /usr/local/lib/frama-c/stmts_graph.cmx /usr/local/lib/frama-c/visitor.cmx /usr/local/lib/frama-c/printer.cmx /usr/local/lib/frama-c/unroll_loops.cmx /usr/local/lib/frama-c/loop.cmx /usr/local/lib/frama-c/inout_type.cmx /usr/local/lib/frama-c/pdgIndex.cmx /usr/local/lib/frama-c/pdgTypes.cmx /usr/local/lib/frama-c/pdgMarks.cmx /usr/local/lib/frama-c/slicingInternals.cmx /usr/local/lib/frama-c/slicingTypes.cmx /usr/local/lib/frama-c/db.cmx /usr/local/lib/frama-c/command.cmx /usr/local/lib/frama-c/task.cmx /usr/local/lib/frama-c/translate_lightweight.cmx /usr/local/lib/frama-c/file.cmx /usr/local/lib/frama-c/filter.cmx /usr/local/lib/frama-c/special_hooks.cmx /usr/local/lib/frama-c/widen.cmx /usr/local/lib/frama-c/bit_model_access.cmx /usr/local/lib/frama-c/logic_interp.cmx /usr/local/lib/frama-c/infer_annotations.cmx /usr/local/lib/frama-c/Occurrence.cmx /usr/local/lib/frama-c/Metrics.cmx /usr/local/lib/frama-c/Syntactic_callgraph.cmx /usr/local/lib/frama-c/Value.cmx /usr/local/lib/frama-c/RteGen.cmx /usr/local/lib/frama-c/From.cmx /usr/local/lib/frama-c/Users.cmx /usr/local/lib/frama-c/Constant_Propagation.cmx /usr/local/lib/frama-c/Postdominators.cmx /usr/local/lib/frama-c/Inout.cmx /usr/local/lib/frama-c/Semantic_callgraph.cmx /usr/local/lib/frama-c/Impact.cmx /usr/local/lib/frama-c/Pdg.cmx /usr/local/lib/frama-c/Scope.cmx /usr/local/lib/frama-c/Sparecode.cmx /usr/local/lib/frama-c/Slicing.cmx /usr/local/lib/frama-c/boot.cmx endif diff -Nru frama-c-20110201+carbon+dfsg/share/Makefile.plugin frama-c-20111001+nitrogen+dfsg/share/Makefile.plugin --- frama-c-20110201+carbon+dfsg/share/Makefile.plugin 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/share/Makefile.plugin 2011-10-10 08:38:37.000000000 +0000 @@ -143,15 +143,34 @@ # is behaving correctly. PLUGIN_BASE:=$(strip $(if $(notdir $(PLUGIN_DIR)),$(notdir $(PLUGIN_DIR)),\ $(notdir $(patsubst %/,%,$(PLUGIN_DIR))))) + +################ +# ml sources # +################ + +PLUGIN_SRC:= $(patsubst %,$(PLUGIN_DIR)/%.ml*, $(PLUGIN_CMO)) \ + $(patsubst %,$(PLUGIN_DIR)/%.mli, $(PLUGIN_CMI)) \ + $(patsubst %,$(PLUGIN_DIR)/%.ml*, $(PLUGIN_GUI_CMO)) \ + $(patsubst %.cmo,%.ml*, $(PLUGIN_TYPES_CMO)) + +$(PLUGIN_NAME)_SRC:=$(PLUGIN_SRC) + +PLUGIN_ML_SRC:=$(patsubst %.ml*,%.ml,$(PLUGIN_SRC)) \ + $(patsubst %.ml*,%.mli,$(filter %.ml*,$(PLUGIN_SRC))) +$(PLUGIN_NAME)_ML_SRC:=$(PLUGIN_ML_SRC) + ################ # distribution # ################ ifeq ($(PLUGIN_DISTRIBUTED),yes) -ifdef PLUGIN_TYPES_CMO -PLUGIN_DISTRIBUTED_LIST += $(wildcard $(patsubst %.cmo,%.ml, $(PLUGIN_TYPES_CMO))) $(wildcard $(patsubst %.cmo,%.mli, $(PLUGIN_TYPES_CMO))) +PLUGIN_DISTRIBUTED_LIST += $(PLUGIN_SRC) + +ifeq ($(PLUGIN_HAS_MLI),yes) +PLUGIN_DISTRIBUTED_LIST += $(PLUGIN_DIR)/$(PLUGIN_NAME).mli endif -PLUGIN_DISTRIBUTED_LIST += $(PLUGIN_DIR)/*.ml* + +# VP: this needs to be adapted for external plugins. ifeq ($(PLUGIN_HAS_EXT_DOC),yes) PLUGIN_EXT_DOC_DIR:=doc/$(PLUGIN_BASE) PLUGIN_DIST_DOC_LIST += doc/plugins/$(PLUGIN_BASE).pdf @@ -198,6 +217,10 @@ PLUGIN_CMI:= $(patsubst %, $(PLUGIN_DIR)/%.cmi, $(PLUGIN_CMI)) \ $(PLUGIN_CMO:.cmo=.cmi) +$(PLUGIN_NAME)_CMO:=$(PLUGIN_CMO) +$(PLUGIN_NAME)_CMX:=$(PLUGIN_CMX) +$(PLUGIN_NAME)_CMI:=$(PLUGIN_CMI) + HAS_GUI:=no ifneq ($(ENABLE_GUI),no) ifneq ("$(PLUGIN_GUI_CMO)","") @@ -211,6 +234,10 @@ endif endif +$(PLUGIN_NAME)_GUI_CMO:=$(PLUGIN_GUI_CMO) +$(PLUGIN_NAME)_GUI_CMX:=$(PLUGIN_GUI_CMX) +$(PLUGIN_NAME)_GUI_CMI:=$(PLUGIN_GUI_CMI) + # The packing files TARGET_CMO:= $(PLUGIN_LIB_DIR)/$(PLUGIN_NAME).cmo ifdef PLUGIN_EXTRA_BYTE @@ -237,6 +264,9 @@ else TARGET_GUI_CMXS:= endif +else +TARGET_GUI_CMO:= +TARGET_GUI_CMX:= endif # Some meta-variables for compilation flags @@ -275,14 +305,17 @@ # Set the compilation flags for the plugin $(NAME_BFLAGS):=$(BFLAGS) -I $(PLUGIN_DIR) $(PLUGIN_BFLAGS) $(NAME_OFLAGS):=$(OFLAGS) -I $(PLUGIN_DIR) $(PLUGIN_OFLAGS) +$(NAME_DOCFLAGS):= $(DOC_FLAGS) $(PLUGIN_DOCFLAGS) \ + -I $($(PLUGIN_NAME)_DIR) -I . $(OCAMLGRAPH_INCLUDE) ifeq ($(HAS_GUI),yes) $(NAME_GUI_BFLAGS):=$(BFLAGS) -I $(PLUGIN_DIR) $(PLUGIN_BFLAGS) -I +lablgtk2 $(NAME_GUI_OFLAGS):=$(OFLAGS) -I $(PLUGIN_DIR) $(PLUGIN_OFLAGS) -I +lablgtk2 $(TARGET_GUI_BFLAGS):= $(PLUGIN_LINK_GUI_BFLAGS) $(TARGET_GUI_OFLAGS):=-pack $(PLUGIN_LINK_GUI_OFLAGS) +$(NAME_DOCFLAGS) := $($(NAME_DOCFLAGS)) -I +lablgtk2 endif $(NAME_DEPFLAGS):= -I $(PLUGIN_DIR) $(PLUGIN_DEPFLAGS) -$(NAME_DOCFLAGS):= $(PLUGIN_DOCFLAGS) + $(TARGET_BFLAGS):= $(PLUGIN_LINK_BFLAGS) $(TARGET_OFLAGS):=-pack $(PLUGIN_LINK_OFLAGS) @@ -331,7 +364,7 @@ $($(basename $(notdir $@))_TARGET_BFLAGS) \ $($(basename $(notdir $@))_CMO) -$(TARGET_CMX): $(PLUGIN_CMX) $(TARGET_CMI) $(PACKED_CMX) \ +$(TARGET_CMX): $(PLUGIN_CMX) $(TARGET_CMI) \ $(PLUGIN_DEPENDS:%=$(PLUGIN_LIB_DIR)/%.cmi) \ $(PLUGIN_DEPENDS:%=$(PLUGIN_LIB_DIR)/%.cmx) $(PRINT_PACKING) $@ @@ -353,6 +386,7 @@ PLUGIN_MLI:= $(PLUGIN_NAME)_MLI:= +TARGET_CMI:= $(TARGET_CMO): $(PLUGIN_CMO) \ $(PLUGIN_DEPENDS:%=$(PLUGIN_LIB_DIR)/%.cmi) @@ -441,7 +475,8 @@ # packing gui files without signature ##################################### -PLUGIN_GUI_MLI:= +TARGET_GUI_MLI:= +TARGET_GUI_CMI:= $(PLUGIN_NAME)_gui_MLI:= $(TARGET_GUI_CMO): $(PLUGIN_GUI_CMO) \ @@ -466,8 +501,11 @@ $(MKDIR) $(PLUGIN_LIB_DIR)/gui $(OCAMLOPT) -o $@ -shared $^ endif -endif -endif +endif # PLUGIN_HAS_MLI +else +TARGET_GUI_MLI:= +TARGET_GUI_CMI:= +endif # HAS_GUI ######### @@ -483,18 +521,14 @@ MODULES_TODOC+= $(PLUGIN_TYPES_TODOC) PLUGIN_UNDOC := $(addprefix $(PLUGIN_DIR)/, $(PLUGIN_UNDOC)) -ifeq ($(ENABLE_GUI),no) -PLUGIN_UNDOC += $(patsubst %, $(PLUGIN_DIR)/%.ml, $(PLUGIN_GUI_CMO)) \ - $(patsubst %, $(PLUGIN_DIR)/%.mli, $(PLUGIN_GUI_CMO)) -endif -PLUGIN_DOC_SRC := $(filter-out $(PLUGIN_UNDOC), \ - $(wildcard $(PLUGIN_DIR)/*.ml) \ - $(filter-out $(PLUGIN_MLI), $(wildcard $(PLUGIN_DIR)/*.mli))) - -$(PLUGIN_NAME)_DOC_SRC:= $(PLUGIN_DOC_SRC) +PLUGIN_DOC_SRC:=$(filter-out $(PLUGIN_UNDOC), $(PLUGIN_ML_SRC)) +$(PLUGIN_NAME)_DOC_SRC:=$(PLUGIN_DOC_SRC) +ifndef PLUGIN_DOC_DIR PLUGIN_DOC_DIR := $(DOC_DIR)/$(PLUGIN_BASE) +endif + $(PLUGIN_NAME)_DOC_DIR:= $(PLUGIN_DOC_DIR) $(PLUGIN_NAME)_INTRO:=$(PLUGIN_INTRO) @@ -504,7 +538,14 @@ $(PLUGIN_NAME)_CAT_INTRO:= endif -$(PLUGIN_DOC_DIR)/$(PLUGIN_NAME).txt: $(DOC_DIR)/intro_kernel_plugin.txt $(DOC_DIR)/intro_plugin.txt $(PLUGIN_INTRO) +ifeq ($(FRAMAC_MAKE),yes) +DOC_INTRO:= $(DOC_DIR)/intro_kernel_plugin.txt \ + $(DOC_DIR)/intro_plugin.txt +else +DOC_INTRO:= +endif + +$(PLUGIN_DOC_DIR)/$(PLUGIN_NAME).txt: $(DOC_INTRO) $(PLUGIN_INTRO) $(PRINT_MAKING) "$@" $(MKDIR) $(dir $@) if test -f "$(DOC_DIR)/html/Db.$(basename $(notdir $@)).html" ; then \ @@ -516,24 +557,39 @@ -e "/^@ignore/d" $@ $($(basename $(notdir $@))_CAT_INTRO) -$(PLUGIN_DOC_DIR)/FLAGS:= -I $($(PLUGIN_NAME)_DIR) $(PLUGIN_DOCFLAGS) +ifeq ($(FRAMAC_INTERNAL),yes) +OCAMLDOC_GEN:=$(DOC_PLUGIN) +ifneq ($(FRAMAC_MAKE),yes) +$(DOC_PLUGIN): $(DOC_DIR)/docgen.ml + $(OCAMLC) -c -I +ocamldoc $(DOC_DIR)/docgen.ml +# not doing kernel documentation if just compiling plugin's one +else +OCAMLDOC_GEN+=$(DOC_DIR)/kernel-doc.ocamldoc +endif +else +OCAMLDOC_GEN:= +endif .PHONY: $(PLUGIN_NAME)_DOC -$(PLUGIN_NAME)_DOC: $(PLUGIN_CMO) $(PLUGIN_DOC_SRC) \ - $(DOC_DIR)/kernel-doc.ocamldoc \ - $(DOC_PLUGIN) \ +$(PLUGIN_NAME)_DOC: $(PLUGIN_CMO) \ + $(OCAMLDOC_GEN) \ $(PLUGIN_DOC_DIR)/$(PLUGIN_NAME).txt \ $(PLUGIN_DOC_DIR)/modules.svg $(PRINT_DOC) $(patsubst %_DOC,%,$@) $(MKDIR) $($@_DIR) $(RM) $($@_DIR)/*.html +# Only generate toc for kernel's documentation if we are in Frama-C's main +# Makefile +ifeq ($(FRAMAC_MAKE), yes) $(ECHO) '
  • $(subst _, ,$(patsubst %_DOC,%,$@))
  • ' > $(DOC_DIR)/$(patsubst %_DOC,%,$@).toc - $(OCAMLDOC) $(DOC_FLAGS) $($($@_DIR)/FLAGS) \ - -t "$(patsubst %_DOC,%,$@) plugin" \ - -intro $($@_DIR)/$(patsubst %_DOC,%,$@).txt \ - -css-style ../style.css \ - -d $($@_DIR) -g $(DOC_PLUGIN) -docpath ../html \ - -load $(DOC_DIR)/kernel-doc.ocamldoc $($@_SRC) +endif + $(OCAMLDOC) $($@FLAGS) \ + -t "$(patsubst %_DOC,%,$@) plugin" \ + -intro $($@_DIR)/$(patsubst %_DOC,%,$@).txt \ + -css-style $(DOC_DIR)/style.css \ + -d $($@_DIR) -g $(DOC_PLUGIN) -docpath $(DOC_DIR)/html \ + $(addprefix -load , $(wildcard $(DOC_DIR)/kernel-doc.ocamldoc)) \ + $(wildcard $($@_SRC)) # [rb+js] 20090619 # pwd is required to avoid "bad directory" message on OpenBSD # don't know why @@ -552,23 +608,27 @@ # $(PLUGIN_DOC_DIR)/modules.ps \ # $(PLUGIN_DOC_DIR)/modules-all.ps \ # $(PLUGIN_DOC_DIR)/types.ps - -$(PLUGIN_DOC_DIR)/modules.dot: $(PLUGIN_DOC_SRC) +$(PLUGIN_DOC_DIR)/modules.dot: DOC_FLAGS:=$($(NAME_DOCFLAGS)) +$(PLUGIN_DOC_DIR)/modules.dot: $(wildcard $(PLUGIN_DOC_SRC)) $(PRINT_DOC) $@ $(MKDIR) $(dir $@) - $(OCAMLDOC) $(DOC_FLAGS) $($(dir $@)FLAGS) -o $@ -dot $^ + $(OCAMLDOC) $(DOC_FLAGS) -o $@ -dot $^ \ + || { $(RM) $@; exit 2; } # in case of error, ocamldoc still generates + # something $(ISED) -e "s/rotate=90;//" \ -e 's/digraph G/digraph "Plugin architecture ($(subst /,,$(subst doc/code,,$(dir $@))))"/' \ $@ -$(PLUGIN_DOC_DIR)/modules-all.dot: $(PLUGIN_DOC_SRC) +$(PLUGIN_DOC_DIR)/modules-all.dot: DOC_FLAGS:=$($(NAME_DOCFLAGS)) +$(PLUGIN_DOC_DIR)/modules-all.dot: $(wildcard $(PLUGIN_DOC_SRC)) $(PRINT_DOC) $@ $(MKDIR) $(dir $@) $(OCAMLDOC) $(DOC_FLAGS) $($(dir $@)FLAGS) -o $@ -dot \ -dot-include-all $^ $(ISED) -e "s/rotate=90;//" $@ -$(PLUGIN_DOC_DIR)/types.dot: $(PLUGIN_DOC_SRC) +$(PLUGIN_DOC_DIR)/types.dot: DOC_FLAGS:=$($(NAME_DOCFLAGS)) +$(PLUGIN_DOC_DIR)/types.dot: $(wildcard $(PLUGIN_DOC_SRC)) $(PRINT_DOC) $@ $(MKDIR) $(dir $@) $(OCAMLDOC) $(DOC_FLAGS) $($(dir $@)FLAGS) -o $@ -dot -dot-types $^ @@ -576,7 +636,7 @@ .PHONY: $(PLUGIN_NAME)_metrics $(PLUGIN_NAME)_metrics : $(PLUGIN_DOC_DIR)/metrics.html -$(PLUGIN_DOC_DIR)/metrics.html : $(PLUGIN_DOC_SRC) +$(PLUGIN_DOC_DIR)/metrics.html : $(wildcard $(PLUGIN_DOC_SRC)) $(PRINT_DOC) $@ ocamlmetrics $^ > $@ @@ -620,33 +680,41 @@ # Depend # ########## +# for reasons known to themselves, ocamldep and make are confused by ./file.ml +# hence (one of) the patsubst below in case PLUGIN_DIR is . + # If you explicitly do "make depend", force the computation of dependencies .PHONY: $(PLUGIN_DIR)/$(PLUGIN_NAME)_DEP_REDO $(PLUGIN_DIR)/$(PLUGIN_NAME)_DEP_REDO: $(PLUGIN_GENERATED) $(TARGET_MLI) $(TARGET_GUI_MLI) $(PRINT_DEP) $(dir $@).depend - $(RM) $(dir $@).depend + $(CHMOD_RW) $(dir $@).depend $(OCAMLDEP) $(INCLUDES_FOR_OCAMLDEP) \ $($(patsubst %_DEP_REDO,%_DEPFLAGS,$(basename $(notdir $@)))) \ - $(dir $@)*.mli $(dir $@)*.ml \ - $($(patsubst %_DEP_REDO,%_MLI, $(basename $(notdir $@))))\ - $($(patsubst %_DEP_REDO,%_gui_MLI, $(basename $(notdir $@))))\ - $(foreach d, $($(patsubst %_DEP_REDO,%_DEPFLAGS_TEST,$(basename $(notdir $@)))), -I $d $d/*.ml $d/*.mli) \ + $(patsubst ./%,%, \ + $($(patsubst %_DEP_REDO,%_ML_SRC,$(basename $(notdir $@)))) \ + $($(patsubst %_DEP_REDO,%_MLI, $(basename $(notdir $@))))\ + $($(patsubst %_DEP_REDO,%_gui_MLI, $(basename $(notdir $@))))) \ + $(foreach d, \ + $($(patsubst %_DEP_REDO,%_DEPFLAGS_TEST, \ + $(basename $(notdir $@)))), \ + -I $d $d/*.ml $d/*.mli) \ > $(dir $@).depend $(CHMOD_RO) $(dir $@).depend # Otherwise do it only if necessary $(PLUGIN_DIR)/$(PLUGIN_NAME)_DEP: $(PLUGIN_GENERATED) $(TARGET_MLI) $(TARGET_GUI_MLI) $(PRINT_DEP) $(dir $@).depend - $(RM) $(dir $@).depend + $(CHMOD_RW) $(dir $@).depend $(OCAMLDEP) $(INCLUDES_FOR_OCAMLDEP) \ $($(basename $(notdir $@))FLAGS) \ - $(dir $@)*.mli $(dir $@)*.ml \ - $($(patsubst %_DEP,%_MLI, $(basename $(notdir $@))))\ - $($(patsubst %_DEP,%_gui_MLI, $(basename $(notdir $@))))\ + $(patsubst ./%,%, \ + $($(patsubst %_DEP,%_ML_SRC,$(basename $(notdir $@)))) \ + $($(patsubst %_DEP,%_MLI, $(basename $(notdir $@)))) \ + $($(patsubst %_DEP,%_gui_MLI, $(basename $(notdir $@))))) \ $(foreach d, $($(basename $(notdir $@))FLAGS_TEST), -I $d $d/*.ml $d/*.mli) \ > $(dir $@).depend $(TOUCH) $@ - $(CHMOD_RO) $(dir $@).depend + $(CHMOD_RW) $(dir $@).depend # touch above = Do not recompute dependances each times ############ @@ -661,7 +729,21 @@ fi $(RM) $(PLUGIN_GENERATED) $(RM) $(@:%CLEAN=%DEP) $(@:%CLEAN=%DEP_REDO) - $(RM) $(dir $@)*.cm* $(dir $@)*.o $(dir $@)*.annot $(dir $@)*~ + $(RM) $(patsubst %.cmo,%.cm*,$($(patsubst %_CLEAN,%_CMO,$(notdir $@)))) + $(RM) $(patsubst %.cmi,%.cm*,$($(patsubst %_CLEAN,%_CMI,$(notdir $@)))) + $(RM) $(patsubst %.cmo,%.annot,\ + $($(patsubst %_CLEAN,%_CMO,$(notdir $@)))) + $(RM) $(patsubst %.cmo,%.o,$($(patsubst %_CLEAN,%_CMO,$(notdir $@)))) + $(RM) $(patsubst %.cmo,%.cm*,\ + $($(patsubst %_CLEAN,%_GUI_CMO,$(notdir $@)))) + $(RM) $(patsubst %.cmi,%.cm*, \ + $($(patsubst %_CLEAN,%_GUI_CMI,$(notdir $@)))) + $(RM) $(patsubst %.cmo,%.annot, \ + $($(patsubst %_CLEAN,%_GUI_CMO,$(notdir $@)))) + $(RM) $(patsubst %.cmo,%.o, \ + $($(patsubst %_CLEAN,%_GUI_CMO,$(notdir $@)))) + $(RM) $(dir $@)*~ $(dir $@)*.cm* $(dir $@)*.o $(dir $@)*.annot + $(RM) -r $(dir $@)gui $(RM) $(foreach d, $(@:%CLEAN=%TESTS_LIB), \ $(foreach f, $($(notdir $d)), \ $f $(f:.cmx=.cmo) $(f:.cmx=.opt) $(f:.cmx=.byte) $(f:.cmx=.o))) @@ -765,6 +847,8 @@ PLUGIN_TYPES_CMO:= PLUGIN_GUI_CMO:= PLUGIN_GUI_CMX:= +PLUGIN_GUI_CMI:= +PLUGIN_GUI_MLI:= TARGET_GUI_CMO:= TARGET_GUI_CMX:= PLUGIN_UNDOC:= @@ -788,6 +872,7 @@ PLUGIN_EXTRA_BYTE:= PLUGIN_EXTRA_OPT:= PLUGIN_INTERNAL_TEST:= +PLUGIN_DOC_DIR:= endif ############################################################################### Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/relies_on_hyp.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/relies_on_hyp.png differ Binary files /tmp/hE2hslVzkn/frama-c-20110201+carbon+dfsg/share/unmark.png and /tmp/awbN00zI9M/frama-c-20111001+nitrogen+dfsg/share/unmark.png differ diff -Nru frama-c-20110201+carbon+dfsg/src/ai/abstract_interp.ml frama-c-20111001+nitrogen+dfsg/src/ai/abstract_interp.ml --- frama-c-20110201+carbon+dfsg/src/ai/abstract_interp.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/abstract_interp.ml 2011-10-10 08:38:27.000000000 +0000 @@ -116,61 +116,9 @@ val mem : O.elt -> t -> bool end -module type Value = Datatype.S_with_collections +module type LatValue = Datatype.S_with_collections -module type Arithmetic_Value = sig - include Value - val gt : t -> t -> bool - val le : t -> t -> bool - val ge : t -> t -> bool - val lt : t -> t -> bool - val add : t -> t -> t - val sub : t -> t -> t - val mul : t -> t -> t - val native_div : t -> t -> t - val rem : t -> t -> t - val pos_div : t -> t -> t - val c_div : t -> t -> t - val c_rem : t -> t -> t - val cast: size:t -> signed:bool -> value:t -> t - val abs : t -> t - val zero : t - val one : t - val two : t - val four : t - val onethousand : t - val minus_one : t - val is_zero : t -> bool - val is_one : t -> bool - val pgcd : t -> t -> t - val ppcm : t -> t -> t - val min : t -> t -> t - val max : t -> t -> t - val length : t -> t -> t (** b - a + 1 *) - val of_int : int -> t - val of_float : float -> t - val of_int64 : Int64.t -> t - val to_int : t -> int - val to_float : t -> float - val neg : t -> t - val succ : t -> t - val pred : t -> t - val round_up_to_r : min:t -> r:t -> modu:t -> t - val round_down_to_r : max:t -> r:t -> modu:t -> t - val pos_rem : t -> t -> t - val shift_left : t -> t -> t - val shift_right : t -> t -> t - val fold : (t -> 'a -> 'a) -> inf:t -> sup:t -> step:t -> 'a -> 'a - val logand : t -> t -> t - val logor : t -> t -> t - val logxor : t -> t -> t - val lognot : t -> t - val power_two : int -> t - val two_power : t -> t - val extract_bits : start:t -> stop:t -> t -> t -end - -module Make_Lattice_Set(V:Value): Lattice_Set with type O.elt = V.t = struct +module Make_Lattice_Set(V:LatValue): Lattice_Set with type O.elt = V.t = struct exception Error_Top exception Error_Bottom @@ -183,13 +131,13 @@ (* TODO: really unchangedcompares? *) let contains_single_elt s = try - let mi = min_elt s in - let ma = max_elt s in - if mi == ma - then (* exactly one elt *) Some mi - else None + let mi = min_elt s in + let ma = max_elt s in + if mi == ma + then (* exactly one elt *) Some mi + else None with Not_found -> - None + None end type tt = Set of O.t | Top @@ -202,10 +150,10 @@ let hash c = match c with | Top -> 12373 | Set s -> - let f v acc = - 67 * acc + (V.hash v) - in - O.fold f s 17 + let f v acc = + 67 * acc + (V.hash v) + in + O.fold f s 17 let tag = hash @@ -262,10 +210,10 @@ match s with | Top -> raise Not_less_than | Set s -> - let c = O.cardinal s in - if c > n - then raise Not_less_than; - c + let c = O.cardinal s in + if c > n + then raise Not_less_than; + c let cardinal_zero_or_one s = try ignore (cardinal_less_than s 1) ; true @@ -305,10 +253,13 @@ | Set s -> if O.is_empty s then Format.fprintf fmt "BottomSet" else - Format.fprintf fmt "@[{@[%a@]}@]" - (fun fmt s -> - O.iter - (Format.fprintf fmt "@[%a;@]@ " V.pretty) s) s + Pretty_utils.pp_iter + ~pre:"{" + ~suf:"}" + ~sep:";@ " + O.iter + (fun fmt v -> Format.fprintf fmt "@[%a@]" V.pretty v) + fmt s let is_included t1 t2 = (t1 == t2) || @@ -351,33 +302,33 @@ include Datatype.Make (struct - type t = tt - let name = V.name ^ " lattice_set" - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| O.packed_descr |] |]) - let reprs = Top :: List.map (fun o -> Set o) O.reprs - let equal = equal - let compare = compare - let hash = tag - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let pretty = pretty - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project + type t = tt + let name = V.name ^ " lattice_set" + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum [| [| O.packed_descr |] |]) + let reprs = Top :: List.map (fun o -> Set o) O.reprs + let equal = equal + let compare = compare + let hash = tag + let rehash = Datatype.identity + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = pretty + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project end) end -module Make_Hashconsed_Lattice_Set(V: Hptset.Id_Datatype) +module Make_Hashconsed_Lattice_Set(V: Hptset.Id_Datatype)(O: Hptset.S with type elt = V.t) : Lattice_Set with type O.elt=V.t = struct exception Error_Top exception Error_Bottom - module O = Hptset.Make(V) + module O = O type tt = Set of O.t | Top type y = O.t @@ -389,10 +340,10 @@ let hash c = match c with | Top -> 12373 | Set s -> - let f v acc = - 67 * acc + (V.id v) - in - O.fold f s 17 + let f v acc = + 67 * acc + (V.id v) + in + O.fold f s 17 let tag = hash @@ -447,10 +398,10 @@ match s with Top -> raise Not_less_than | Set s -> - let c = O.cardinal s in - if c > n - then raise Not_less_than; - c + let c = O.cardinal s in + if c > n + then raise Not_less_than; + c let cardinal_zero_or_one s = try @@ -490,10 +441,13 @@ | Set s -> if O.is_empty s then Format.fprintf fmt "BottomSet" else - Format.fprintf fmt "@[{@[%a@]}@]" - (fun fmt s -> - O.iter - (Format.fprintf fmt "@[%a;@]@ " V.pretty) s) s + Pretty_utils.pp_iter + ~pre:"@[{" + ~suf:"}@]" + ~sep:";@ " + O.iter + (fun fmt v -> Format.fprintf fmt "@[%a@]" V.pretty v) + fmt s let is_included t1 t2 = (t1 == t2) || @@ -535,21 +489,21 @@ include Datatype.Make (struct - type t = tt - let name = V.name ^ " hashconsed_lattice_set" - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| O.packed_descr |] |]) - let reprs = Top :: List.map (fun o -> Set o) O.reprs - let equal = equal - let compare = compare - let hash = hash - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let pretty = pretty - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project + type t = tt + let name = V.name ^ " hashconsed_lattice_set" + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum [| [| O.packed_descr |] |]) + let reprs = Top :: List.map (fun o -> Set o) O.reprs + let equal = equal + let compare = compare + let hash = hash + let rehash = Datatype.identity + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = pretty + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project end) let () = Type.set_ml_name ty None @@ -557,265 +511,7 @@ module Make_Pair = Datatype.Pair - -module Make_Lattice_Interval_Set (V:Arithmetic_Value) = struct - - exception Error_Top - exception Error_Bottom - - module Interval = Make_Pair(V)(V) - type elt = Interval.t - - type tt = Top | Set of elt list - - type widen_hint = unit - - let bottom = Set [] - let top = Top - - let check t = - assert (match t with - | Top -> true - | Set s -> - let last_stop = ref None in - List.for_all - (fun (a,b) -> V.compare a b <= 0 && - match !last_stop with - None -> last_stop := Some b; true - | Some l -> last_stop := Some b; V.gt a l) - s) ; - t - - let hash l = match l with - Top -> 667 - | Set l -> - List.fold_left - (fun acc p -> 371 * acc + Interval.hash p) - 443 - l - - let tag = hash - - let cardinal_zero_or_one v = - match v with - Top -> false - | Set [x,y] -> V.equal x y - | Set _ -> false - - let cardinal_less_than v n = - match v with - Top -> raise Not_less_than - | Set l -> - let rec aux l card = match l with - [] -> card - | (x,y)::t -> - let nn = V.of_int n in - let card = V.add card ((V.succ (V.sub y x))) in - if V.gt card nn - then raise Not_less_than - else aux t card - in - V.to_int (aux l V.zero) - - let splitting_cardinal_less_than ~split_non_enumerable _v _n = - ignore (split_non_enumerable); - assert false - - let compare e1 e2 = - if e1 == e2 then 0 - else - match e1,e2 with - | Top,_ -> 1 - | _, Top -> -1 - | Set e1, Set e2 -> - Extlib.list_compare Interval.compare e1 e2 - - let equal e1 e2 = compare e1 e2 = 0 - - let pretty fmt t = - match t with - | Top -> Format.fprintf fmt "TopISet" - | Set s -> - if s=[] then Format.fprintf fmt "BottomISet" - else begin - Format.fprintf fmt "{%a}" - (fun fmt s -> - List.iter - (fun (b,e) -> - Format.fprintf - fmt - "[%a..%a]; " - V.pretty b - V.pretty e - ) - s) - s - end - - let widen _wh t1 t2 = (if equal t1 t2 then t1 else top) - - let meet v1 v2 = - if v1 == v2 then v1 else - - (match v1,v2 with - | Top, v | v, Top -> v - | Set s1 , Set s2 -> Set ( - let rec aux acc (l1:elt list) (l2:elt list) = match l1,l2 with - | [],_|_,[] -> List.rev acc - | (((b1,e1)) as i1)::r1, - (((b2,e2)) as i2)::r2 -> - let c = V.compare b1 b2 in - if c = 0 then (* intervals start at the same value *) - let ce = V.compare e1 e2 in - if ce=0 then - aux ((b1,e1)::acc) r1 r2 (* same intervals *) - else - (* one interval is included in the other *) - let min,not_min,min_tail,not_min_tail = - if ce > 0 then i2,i1,r2,r1 else - i1,i2,r1,r2 - in - aux ((min)::acc) min_tail - ((( - (snd (min), - snd (not_min)))):: - not_min_tail) - else (* intervals start at different values *) - let _min,min_end,not_min_begin,min_tail,not_min_from = - if c > 0 - then b2,e2,b1,r2,l1 - else b1,e1,b2,r1,l2 - in - let c_min = V.compare min_end not_min_begin in - if c_min >= 0 then - (* intersecting intervals *) - aux acc - (( - (not_min_begin,min_end)) - ::min_tail) - not_min_from - else - (* disjoint intervals *) - aux acc min_tail not_min_from - in aux [] s1 s2)) - - let join v1 v2 = - if v1 == v2 then v1 else - (match v1,v2 with - | Top, _ | _, Top -> Top - | Set (s1:elt list) , Set (s2:elt list) -> - let rec aux (l1:elt list) (l2:elt list) = match l1,l2 with - | [],l|l,[] -> l - | (b1,e1)::r1,(b2,e2)::r2 -> - let c = V.compare b1 b2 in - let min_begin,min_end,min_tail,not_min_from = - if c >= 0 then b2,e2,r2,l1 - else b1,e1,r1,l2 - in - let rec enlarge_interval stop l1 look_in_me = - match look_in_me with - | [] -> stop,l1,[] - | ((b,e))::r -> - if V.compare stop (V.pred b) >= 0 - then - if V.compare stop e >= 0 - then enlarge_interval stop l1 r - else enlarge_interval e r l1 - else stop,l1,look_in_me - in - let stop,new_l1,new_l2 = - enlarge_interval - min_end - min_tail - not_min_from - in ((min_begin,stop)):: - (aux new_l1 new_l2) - in Set (aux s1 s2)) - - let inject l = (Set l) - - let inject_one ~size ~value = - (inject [value,V.add value (V.pred size)]) - - let inject_bounds min max = - if V.le min max - then inject [min,max] - else bottom - - let transform _f = (* f must be non-decreasing *) - assert false - - let apply2 _f _s1 _s2 = assert false - - let apply1 _f _s = assert false - - let is_included t1 t2 = - (t1 == t2) || - match t1,t2 with - | _,Top -> true - | Top,_ -> false - | Set s1,Set s2 -> - let rec aux l1 l2 = match l1 with - | [] -> true - | i::r -> - let rec find (b,e as arg) l = - match l with - | [] -> raise Not_found - | (b',e')::r -> - if V.compare b b' >= 0 - && V.compare e' e >= 0 - then l - else if V.compare e' b >= 0 then - raise Not_found - else find arg r - in - try aux r (find i l2) - with Not_found -> false - in - aux s1 s2 - - let link t1 t2 = join t1 t2 (* join is in fact an exact union *) - - let is_included_exn v1 v2 = - if not (is_included v1 v2) then raise Is_not_included - - let intersects t1 t2 = - let m = meet t1 t2 in - not (equal m bottom) - - let fold f v acc = - match v with - | Top -> raise Error_Top - | Set s -> - List.fold_right f s acc - - let narrow = meet - - include Datatype.Make - (struct - type t = tt - let name = Interval.name ^ " lattice_interval_set" - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum - [| [| Structural_descr.pack - (Structural_descr.t_list (Descr.str Interval.descr)) |] |]) - let reprs = Top :: List.map (fun o -> Set [ o ]) Interval.reprs - let equal = equal - let compare = compare - let hash = hash - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let pretty = pretty - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) - let () = Type.set_ml_name ty None - -end - -module Make_Lattice_Base (V:Value):(Lattice_Base with type l = V.t) = struct +module Make_Lattice_Base (V:LatValue):(Lattice_Base with type l = V.t) = struct type l = V.t type tt = Top | Bottom | Value of l @@ -926,7 +622,7 @@ let name = V.name ^ " lattice_base" let structural_descr = Structural_descr.Structure - (Structural_descr.Sum [| [| V.packed_descr |] |]) + (Structural_descr.Sum [| [| V.packed_descr |] |]) let reprs = Top :: Bottom :: List.map (fun v -> Value v) V.reprs let equal = equal let compare = compare @@ -943,188 +639,16 @@ end module Int = struct - open My_bigint - + include My_bigint.M include Datatype.Big_int - let small_nums = Array.init 33 (fun i -> big_int_of_int i) - - let zero = zero_big_int - let one = unit_big_int - let minus_one = minus_big_int unit_big_int - let two = small_nums.(2) - let four = small_nums.(4) - let eight = small_nums.(8) - let thirtytwo = small_nums.(32) - let onethousand = big_int_of_int 1000 - let billion_one = big_int_of_int 1_000_000_001 - - let rem = mod_big_int - let div = div_big_int - let mul = mult_big_int - let sub = sub_big_int - let abs = abs_big_int - let succ = succ_big_int - let pred = pred_big_int - let neg = minus_big_int - let add = add_big_int - - let hash c = - let i = - try - int_of_big_int c - with Failure _ -> int_of_big_int (rem c billion_one) - in - 197 + i - - let tag = hash - - let log_shift_right = log_shift_right_big_int - let shift_right = shift_right_big_int - let shift_left = shift_left_big_int - - let logand = land_big_int - let lognot = lnot_big_int - let logor = lor_big_int - let logxor = lxor_big_int - - let le = le_big_int - let lt = lt_big_int - let ge = ge_big_int - let gt = gt_big_int - - let to_int v = - try int_of_big_int v - with Failure "int_of_big_int" -> assert false - let of_int i = - if 0 <= i && i <= 32 - then small_nums.(i) - else big_int_of_int i - - (* for the two functions below wait until the minimum supported - OCaml version is after: - http://caml.inria.fr/mantis/print_bug_page.php?bug_id=4792 - *) - let of_int64 i = big_int_of_string (Int64.to_string i) - let to_int64 i = Int64.of_string (string_of_big_int i) - - - let of_string = big_int_of_string - let to_string = string_of_big_int - let to_float = float_of_big_int - let of_float _ = assert false - - let minus_one = pred zero - let pretty fmt i = Format.pp_print_string fmt (string_of_big_int i) - let pretty_debug = pretty - - let is_zero v = (sign_big_int v) = 0 - - let is_one v = equal one v - let pos_div = div - let pos_rem = rem - let native_div = div - let c_div u v = - let bad_div = div u v in - if (lt u zero) && not (is_zero (rem u v)) - then - if lt v zero - then pred bad_div - else succ bad_div - else bad_div - let c_rem u v = - sub u (mul v (c_div u v)) - - let cast ~size ~signed ~value = - let factor = two_power size in - let mask = two_power (sub size one) in - - if (not signed) then pos_rem value factor - else - if equal (logand mask value) zero - then logand value (pred mask) + let pretty fmt v = + if not (Kernel.BigIntsHex.is_default ()) then + let max = of_int (Kernel.BigIntsHex.get ()) in + if gt (abs v) max then My_bigint.pretty ~hexa:true fmt v + else My_bigint.pretty ~hexa:false fmt v else - logor (lognot (pred mask)) value - - let two_power = My_bigint.two_power - - let power_two = My_bigint.power_two - - let extract_bits ~start ~stop v = - assert (ge start zero && ge stop start); - (*Format.printf "%a[%a..%a]@\n" pretty v pretty start pretty stop;*) - let r = bitwise_extraction (to_int start) (to_int stop) v in - (*Format.printf "%a[%a..%a]=%a@\n" pretty v pretty start pretty stop pretty r;*) - r - - (* - - include Int64 - let pretty fmt i = Format.fprintf fmt "%Ld" i - let pretty_s () i = Format.sprintf "%Ld" i - let is_zero v = 0 = (compare zero v) - let lt = (<) - let le = (<=) - let neq = (<>) - let eq = (=) - let gt = (>) - let ge = (>=) - - let shift_left x y = shift_left x (to_int y) - let shift_right x y = shift_right x (to_int y) - let log_shift_right x y = shift_right_logical x (to_int y) - let of_int64 x = x - let to_int64 x = x - - let pos_div u v = - let bad_div = div u v in - let bad_rem = rem u v in - if compare bad_rem zero >= 0 - then bad_div - else (sub bad_div one) - - let pos_rem x m = - let r = rem x m in - if lt r zero then add r m (* cannot overflow because r and m - have different signs *) - else r - - let c_div = div - - *) - - let is_even v = is_zero (logand one v) - - (** [pgcd u 0] is allowed and returns [u] *) - let pgcd u v = - let r = - if is_zero v - then u - else gcd_big_int u v in - r - - let ppcm u v = - if u = zero || v = zero - then zero - else native_div (mul u v) (pgcd u v) - - let length u v = succ (sub v u) - - let min = min_big_int - let max = max_big_int - - let round_down_to_zero v modu = - mul (pos_div v modu) modu - - (** [round_up_to_r m r modu] is the smallest number [n] such that - [n]>=[m] and [n] = [r] modulo [modu] *) - let round_up_to_r ~min:m ~r ~modu = - add (add (round_down_to_zero (pred (sub m r)) modu) r) modu - - (** [round_down_to_r m r modu] is the largest number [n] such that - [n]<=[m] and [n] = [r] modulo [modu] *) - let round_down_to_r ~max:m ~r ~modu = - add (round_down_to_zero (sub m r) modu) r + My_bigint.pretty ~hexa:false fmt v (** execute [f] on [inf], [inf + step], ... *) let fold f ~inf ~sup ~step acc = @@ -1133,15 +657,14 @@ let nb_loop = div (sub sup inf) step in let next = add step in let rec fold ~counter ~inf acc = - if equal counter onethousand then - CilE.warn_once "enumerating %s integers" (to_string nb_loop); - if le inf sup - then begin -(* Format.printf "Int.fold: %a@\n" pretty inf; *) - fold ~counter:(succ counter) ~inf:(next inf) (f inf acc) - end - else acc - in + if equal counter onethousand then + Kernel.warning ~once:true ~current:true + "enumerating %s integers" (to_string nb_loop); + if le inf sup then begin + (* Format.printf "Int.fold: %a@\n" pretty inf; *) + fold ~counter:(succ counter) ~inf:(next inf) (f inf acc) + end else acc + in fold ~counter:zero ~inf acc end @@ -1156,6 +679,7 @@ module VarinfoSetLattice = Make_Hashconsed_Lattice_Set (struct include Cil_datatype.Varinfo let id v = v.Cil_types.vid end) + (Cil_datatype.Varinfo.Hptset) module LocationSetLattice = struct include Make_Lattice_Set(Cil_datatype.Location) @@ -1188,8 +712,8 @@ let cardinal_zero_or_one v = match v with | Bottom -> true | Product (t1, t2) -> - (L1.cardinal_zero_or_one t1) && - (L2.cardinal_zero_or_one t2) + (L1.cardinal_zero_or_one t1) && + (L2.cardinal_zero_or_one t2) let compare = if L1.compare == Datatype.undefined || L2.compare == Datatype.undefined then ( @@ -1205,8 +729,8 @@ | Bottom, Product _ -> 1 | Product _,Bottom -> -1 | (Product (a,b)), (Product (a',b')) -> - let c = L1.compare a a' in - if c = 0 then L2.compare b b' else c + let c = L1.compare a a' in + if c = 0 then L2.compare b b' else c let equal x x' = if x == x' then true else @@ -1215,7 +739,7 @@ | Bottom, Product _ -> false | Product _,Bottom -> false | (Product (a,b)), (Product (a',b')) -> - L1.equal a a' && L2.equal b b' + L1.equal a a' && L2.equal b b' let top = Product(L1.top,L2.top) @@ -1251,7 +775,7 @@ match x1,x2 with | Bottom, v | v, Bottom -> v | Product (l1,ll1), Product (l2,ll2) -> - Product(L1.join l1 l2, L2.join ll1 ll2) + Product(L1.join l1 l2, L2.join ll1 ll2) let link _ = assert false (** Not implemented yet. *) @@ -1262,22 +786,22 @@ match x1,x2 with | Bottom, _ | _, Bottom -> Bottom | Product (l1,ll1), Product (l2,ll2) -> - let l1 = L1.meet l1 l2 in - let l2 = L2.meet ll1 ll2 in + let l1 = L1.meet l1 l2 in + let l2 = L2.meet ll1 ll2 in inject l1 l2 let pretty fmt x = match x with Bottom -> - Format.fprintf fmt "BotProd" + Format.fprintf fmt "BotProd" | Product(l1,l2) -> - Format.fprintf fmt "(%a,%a)" L1.pretty l1 L2.pretty l2 + Format.fprintf fmt "(%a,%a)" L1.pretty l1 L2.pretty l2 let intersects x1 x2 = match x1,x2 with | Bottom, _ | _, Bottom -> false | Product (l1,ll1), Product (l2,ll2) -> - (L1.intersects l1 l2) && (L2.intersects ll1 ll2) + (L1.intersects l1 l2) && (L2.intersects ll1 ll2) let is_included x1 x2 = (x1 == x2) || @@ -1285,7 +809,7 @@ | Bottom, _ -> true | _, Bottom -> false | Product (l1,ll1), Product (l2,ll2) -> - (L1.is_included l1 l2) && (L2.is_included ll1 ll2) + (L1.is_included l1 l2) && (L2.is_included ll1 ll2) let is_included_exn x1 x2 = if x1 != x2 @@ -1294,36 +818,36 @@ | Bottom, _ -> () | _, Bottom -> raise Is_not_included | Product (l1,ll1), Product (l2,ll2) -> - L1.is_included_exn l1 l2; - L2.is_included_exn ll1 ll2 + L1.is_included_exn l1 l2; + L2.is_included_exn ll1 ll2 let transform _f (_l1,_ll1) (_l2,_ll2) = raise (Invalid_argument "Abstract_interp.Make_Lattice_Product.transform") include Datatype.Make (struct - type t = tt (*= Product of t1*t2 | Bottom*) - let name = "(" ^ L1.name ^ ", " ^ L2.name ^ ") lattice_product" - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| L1.packed_descr; L2.packed_descr |] |]) - let reprs = - Bottom :: - List.fold_left - (fun acc l1 -> - List.fold_left - (fun acc l2 -> Product(l1, l2) :: acc) acc L2.reprs) - [] - L1.reprs - let equal = equal - let compare = compare - let hash = tag - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let pretty = pretty - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project + type t = tt (*= Product of t1*t2 | Bottom*) + let name = "(" ^ L1.name ^ ", " ^ L2.name ^ ") lattice_product" + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum [| [| L1.packed_descr; L2.packed_descr |] |]) + let reprs = + Bottom :: + List.fold_left + (fun acc l1 -> + List.fold_left + (fun acc l2 -> Product(l1, l2) :: acc) acc L2.reprs) + [] + L1.reprs + let equal = equal + let compare = compare + let hash = tag + let rehash = Datatype.identity + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = pretty + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project end) let () = Type.set_ml_name ty None @@ -1474,7 +998,7 @@ let reprs = Top :: Bottom :: List.fold_left - (fun acc t -> T2 t :: acc) (List.map (fun t -> T1 t) L1.reprs) L2.reprs + (fun acc t -> T2 t :: acc) (List.map (fun t -> T1 t) L1.reprs) L2.reprs let equal = equal let compare = compare let hash = tag diff -Nru frama-c-20110201+carbon+dfsg/src/ai/abstract_interp.mli frama-c-20111001+nitrogen+dfsg/src/ai/abstract_interp.mli --- frama-c-20110201+carbon+dfsg/src/ai/abstract_interp.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/abstract_interp.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,7 +20,11 @@ (* *) (**************************************************************************) -(** @plugin development guide *) +(** Undocumented. + Do not use this module if you don't know what you are doing. + @plugin development guide *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) (** Raised by [cardinal_less_than] *) exception Not_less_than @@ -56,7 +60,7 @@ val cardinal_less_than: t -> int -> int (** [cardinal_less_than t v ] - @raise Not_less_than whenever the cardinal of [t] is higher than [v] *) + @raise Not_less_than whenever the cardinal of [t] is higher than [v] *) val tag : t -> int @@ -71,7 +75,7 @@ val diff_if_one : t -> t -> t (** [diff t1 t2] is an over-approximation of [t1-t2]. - @return t1 if [t2] is not a singleton. *) + @return t1 if [t2] is not a singleton. *) val fold_enum : split_non_enumerable:int -> (t -> 'a -> 'a) -> t -> 'a -> 'a @@ -124,138 +128,28 @@ val mem : O.elt -> t -> bool end -module type Value = Datatype.S_with_collections - -module type Arithmetic_Value = sig - include Value - val gt : t -> t -> bool - val le : t -> t -> bool - val ge : t -> t -> bool - val lt : t -> t -> bool - val add : t -> t -> t - val sub : t -> t -> t - val mul : t -> t -> t - val native_div : t -> t -> t - val rem : t -> t -> t - val pos_div : t -> t -> t - val c_div : t -> t -> t - val c_rem : t -> t -> t - val cast: size:t -> signed:bool -> value:t -> t - val abs : t -> t - val zero : t - val one : t - val two : t - val four : t - val onethousand : t - val minus_one : t - val is_zero : t -> bool - val is_one : t -> bool - val pgcd : t -> t -> t - val ppcm : t -> t -> t - val min : t -> t -> t - val max : t -> t -> t - val length : t -> t -> t (** b - a + 1 *) - val of_int : int -> t - val of_float : float -> t - val of_int64 : Int64.t -> t - val to_int : t -> int - val to_float : t -> float - val neg : t -> t - val succ : t -> t - val pred : t -> t - val round_up_to_r : min:t -> r:t -> modu:t -> t - val round_down_to_r : max:t -> r:t -> modu:t -> t - val pos_rem : t -> t -> t - val shift_left : t -> t -> t - val shift_right : t -> t -> t - val fold : (t -> 'a -> 'a) -> inf:t -> sup:t -> step:t -> 'a -> 'a - val logand : t -> t -> t - val logor : t -> t -> t - val logxor : t -> t -> t - val lognot : t -> t - val power_two : int -> t - val two_power : t -> t - val extract_bits : start:t -> stop:t -> t -> t -end +module type LatValue = Datatype.S_with_collections module Int : sig - include Arithmetic_Value with type t = My_bigint.big_int - val small_nums : t array - val zero : t - val four : t - val eight : t - val thirtytwo : t - val div : t -> t -> t - - val billion_one : t - val tag : t -> int - val log_shift_right : t -> t -> t - val shift_right : t -> t -> t - val shift_left : t -> t -> t - - val to_int : t -> int - val of_int : int -> t - val of_int64 : int64 -> t - val to_int64 : t -> int64 - val of_string : string -> t - val to_string : t -> string - val to_float : t -> float - val of_float : 'a -> 'b - val minus_one : t - val pretty_debug : Format.formatter -> t -> unit - val is_zero : t -> bool - val is_one : t -> bool - val pos_div : t -> t -> t - val pos_rem : t -> t -> t - val native_div : - t -> t -> t - val c_div : t -> t -> t - val c_rem : t -> t -> t - val power_two : int -> t - val extract_bits : - start:t -> - stop:t -> t -> t - val is_even : t -> bool - val pgcd : t -> t -> t - val ppcm : t -> t -> t - val length : t -> t -> t - val min : t -> t -> t - val max : t -> t -> t - val round_down_to_zero : - t -> t -> t - val round_up_to_r : - min:t -> - r:t -> modu:t -> t - val round_down_to_r : - max:t -> - r:t -> modu:t -> t - val fold : - (t -> 'a -> 'a) -> - inf:t -> - sup:t -> step:t -> 'a -> 'a + include My_bigint.S + include LatValue with type t = My_bigint.t + val pretty : Format.formatter -> t -> unit + val fold : (t -> 'a -> 'a) -> inf:t -> sup:t -> step:t -> 'a -> 'a end -module Make_Lattice_Base (V : Value) : Lattice_Base with type l = V.t - -module Make_Pair (V:Value)(W:Value) : Datatype.S with type t = V.t * W.t +module Make_Lattice_Base (V : LatValue) : Lattice_Base with type l = V.t -module Make_Lattice_Interval_Set (V:Arithmetic_Value) : sig - type elt = Make_Pair(V)(V).t - type tt = private Top | Set of elt list - include Lattice with type t = tt - val inject_one : size:V.t -> value:V.t -> t - val inject_bounds : V.t -> V.t -> t - val inject : elt list -> t - val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a - val splitting_cardinal_less_than : - split_non_enumerable:int -> t -> int -> int -end +module Make_Pair (V:LatValue)(W:LatValue) : Datatype.S with type t = V.t * W.t -module Make_Lattice_Set (V : Value) : Lattice_Set with type O.elt=V.t +module Make_Lattice_Set (V : LatValue) : Lattice_Set with type O.elt=V.t -module Make_Hashconsed_Lattice_Set(V : Hptset.Id_Datatype) +module Make_Hashconsed_Lattice_Set + (V : Hptset.Id_Datatype) + (O: Hptset.S with type elt = V.t) : Lattice_Set with type O.elt=V.t +(** See e.g. Base.ml and Locations.ml to see how this functor shoudl be + applied. *) module LocationSetLattice : sig include Lattice_Set with type O.elt = Cil_types.location diff -Nru frama-c-20110201+carbon+dfsg/src/ai/base.ml frama-c-20111001+nitrogen+dfsg/src/ai/base.ml --- frama-c-20110201+carbon+dfsg/src/ai/base.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/base.ml 2011-10-10 08:38:27.000000000 +0000 @@ -25,14 +25,6 @@ open Abstract_interp open Abstract_value -type cell_class_attributes = - { cname : string ; - cid : int ; - cneverexact : bool ; - ctyp : Cil_types.typ ; - cvolatile : bool ; - } - let name = "base" type validity = @@ -42,20 +34,21 @@ | Periodic of Abstract_interp.Int.t*Abstract_interp.Int.t* Abstract_interp.Int.t +type string_id = Cil_types.exp + type base = | Var of varinfo * validity | Initialized_Var of varinfo * validity - (** base that is implicitely initialized. *) + (** base that is implicitly initialized. *) | Null (** base for addresses like [(int* )0x123] *) - | String of int * string (** String constants *) - | Cell_class of cell_class_attributes (** a class of memory cells *) + | String of int * string_id (** String constants *) let invalid = Known(Int.one, Int.zero) let id = function | Var (vi,_) | Initialized_Var (vi,_) -> vi.vid | Null -> 0 - | String (id,_) | Cell_class {cid = id} -> id + | String (id,_) -> id let hash = id @@ -75,53 +68,55 @@ | Known (b,e) -> Format.fprintf fmt "Known %a-%a" Int.pretty b Int.pretty e | Periodic (b,e,p) -> Format.fprintf fmt "Periodic %a-%a (%a)" - Int.pretty b Int.pretty e - Int.pretty p + Int.pretty b Int.pretty e + Int.pretty p + +type cstring = CSString of string | CSWstring of Escape.wstring + +let get_string exp = + match exp.enode with + Const (CStr s) -> CSString s + | Const (CWStr w) -> CSWstring w + | _ -> assert false let pretty fmt t = Format.fprintf fmt "%s" (match t with - | String (_,s) -> Format.sprintf "%S" s - | Cell_class c -> Format.sprintf "%S" c.cname + | String (_,{enode=Const (CStr s)}) -> + Format.sprintf "%S" s + | String (_,{enode=Const (CWStr s)}) -> + Format.sprintf "L\"%s\"" (Escape.escape_wstring s) + | String _ -> assert false | Var (t,_) | Initialized_Var (t,_) -> Pretty_utils.sfprintf "@[%a@]" !Ast_printer.d_ident t.vname | Null -> "NULL") -(* -let pretty_caml fmt t = - match t with - String (_,s) -> Format.fprintf fmt "(Base.create_string %S)" s - | Var (t,_) | Initialized_Var (t,_) -> - Base. -*) - let compare v1 v2 = Datatype.Int.compare (id v1) (id v2) let typeof v = match v with | String (_,_) -> Some charConstPtrType | Null -> None - | Cell_class c -> - Some c.ctyp | Var (v,_) | Initialized_Var (v,_) -> Some (unrollType v.vtype) +let cstring_bitlength e = + let u, l = + match e with + {enode=Const (CStr s)} -> + 8 (* FIXME: CHAR_BIT *), (String.length s) + | {enode=Const (CWStr s)} -> + bitsSizeOf theMachine.wcharType, (List.length s) + | _ -> assert false + in + Int.of_int (u*(succ l)) + let bits_sizeof v = match v with - | String (_,s) -> - Int_Base.inject - (Int.mul Int.eight (Int.succ (Int.of_int (String.length s)))) + | String (_,e) -> + Int_Base.inject (cstring_bitlength e) | Null -> Int_Base.top - | Cell_class c -> - Bit_utils.sizeof c.ctyp | Var (v,_) | Initialized_Var (v,_) -> Bit_utils.sizeof_vid v -(* match findAttribute "original_type" (typeAttr typ) with - | [] -> Bit_utils.sizeof_vid v - | [ASizeOf (TArray (_, Some _,_) as pointed_typ)] -> - bitsSizeOf pointed_typ -*) - -(** All absolute address are invalid *) module MinValidAbsoluteAddress = State_builder.Ref (Abstract_interp.Int) @@ -143,18 +138,18 @@ end) let () = - Parameters.AbsoluteValidRange.add_set_hook + Kernel.AbsoluteValidRange.add_set_hook (fun _ x -> try Scanf.sscanf x "%Li-%Li" - (fun min max -> - let mul8 = Int64.mul 8L in + (fun min max -> + let mul8 = Int64.mul 8L in MinValidAbsoluteAddress.set - (Abstract_interp.Int.of_int64 (mul8 min)); + (Abstract_interp.Int.of_int64 (mul8 min)); MaxValidAbsoluteAddress.set - (Abstract_interp.Int.of_int64 - (Int64.pred (mul8 (Int64.succ max))))) + (Abstract_interp.Int.of_int64 + (Int64.pred (mul8 (Int64.succ max))))) with End_of_file | Scanf.Scan_failure _ | Failure _ as e -> - Kernel.abort "Invalid -absolute-valid-range integer-integer: each integer may be in decimal, hexadecimal (0x, 0X), octal (0o) or binary (0b) notation and has to hold in 64 bits. A correct example is -absolute-valid-range 1-0xFFFFFF0.@\nError was %S@." + Kernel.abort "Invalid -absolute-valid-range integer-integer: each integer may be in decimal, hexadecimal (0x, 0X), octal (0o) or binary (0b) notation and has to hold in 64 bits. A correct example is -absolute-valid-range 1-0xFFFFFF0.@\nError was %S@." (Printexc.to_string e)) let min_valid_absolute_address = MinValidAbsoluteAddress.get @@ -164,7 +159,7 @@ match v with | Null -> Known (min_valid_absolute_address (), max_valid_absolute_address ()) | Var (_,v) | Initialized_Var (_,v) -> v - | String _ | Cell_class _ -> + | String _ -> let max_valid = bits_sizeof v in match max_valid with | Int_Base.Bottom -> assert false @@ -176,7 +171,14 @@ exception Not_valid_offset -let is_valid_offset size base offset = +let is_read_only base = + match base with + String _ -> true + | _ -> false (* TODO: completely const types *) + +let is_valid_offset ~for_writing size base offset = + if for_writing && (is_read_only base) + then raise Not_valid_offset; match validity base with | Known (min_valid,max_valid) | Periodic (min_valid, max_valid, _)-> @@ -197,7 +199,7 @@ let is_function base = match base with - String _ | Null | Cell_class _ | Initialized_Var _ -> false + String _ | Null | Initialized_Var _ -> false | Var(v,_) -> isFunctionType v.vtype @@ -205,7 +207,6 @@ let is_volatile v = match v with | String _ | Null -> false - | Cell_class c -> c.cvolatile | Var vv -> hasAttribute "volatile" (typeAttrs vv.vtype) *) @@ -220,53 +221,52 @@ else match b with Var (v,_) | Initialized_Var (v,_) -> - Int.is_zero (Int.rem (Int.of_int (Cil.alignOf_int(v.vtype))) alignment) + Int.is_zero (Int.rem (Int.of_int (Cil.alignOf_int(v.vtype))) alignment) | Null -> true | String _ -> Int.is_one alignment - | Cell_class _ -> assert false let is_any_formal_or_local v = match v with | Var (v,_) | Initialized_Var (v,_) -> not v.vlogic && not v.vglob - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let is_any_local v = match v with | Var (v,_) | Initialized_Var (v,_) -> not v.vlogic && not v.vglob && not v.vformal - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let is_global v = match v with | Var (v,_) | Initialized_Var (v,_) -> v.vglob - | Null | String _ | Cell_class _ -> true + | Null | String _ -> true let is_formal_or_local v fundec = match v with | Var (v,_) | Initialized_Var (v,_) -> Ast_info.Function.is_formal_or_local v fundec - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let is_formal_of_prototype v vi = match v with | Var (v,_) | Initialized_Var (v,_) -> Ast_info.Function.is_formal_of_prototype v vi - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let is_local v fundec = match v with | Var (v,_) | Initialized_Var (v,_) -> Ast_info.Function.is_local v fundec - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let is_formal v fundec = match v with | Var (v,_) | Initialized_Var (v,_) -> Ast_info.Function.is_formal v fundec - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let is_block_local v block = match v with | Var (v,_) | Initialized_Var (v,_) -> Ast_info.is_block_local v block - | Null | String _ | Cell_class _ -> false + | Null | String _ -> false let validity_from_type v = if isFunctionType v.vtype then invalid @@ -276,9 +276,9 @@ | Int_Base.Bottom -> assert false | Int_Base.Top -> (* TODO: - if (some configuration option) - then Unknown (Int.zero, Bit_utils.max_bit_address ()) - else *) + if (some configuration option) + then Unknown (Int.zero, Bit_utils.max_bit_address ()) + else *) invalid | Int_Base.Value size when Int.gt size Int.zero -> (*Format.printf "Got %a for %s@\n" Int.pretty size v.vname;*) @@ -294,7 +294,7 @@ type t = base let name = "Base" let structural_descr = Structural_descr.Abstract (* TODO better *) - let reprs = [ Null; String(-1, "") ] + let reprs = [ Null ] let equal = equal let compare = compare let pretty = pretty @@ -308,6 +308,11 @@ include D +module Hptset = Hptset.Make + (struct include D let id = id end) + (struct let v = [ [ ] ] end) + (struct let l = [ Ast.self ] end) + module VarinfoLogic = Cil_state_builder.Varinfo_hashtbl (D) @@ -329,17 +334,17 @@ let validity = validity_from_type varinfo in let name = varinfo.vname in let validity = - if Str.string_match regexp name 0 - then + if Str.string_match regexp name 0 then let period = Str.matched_group 1 name in let period = int_of_string period in - CilE.warn_once "Periodic variable %s of period %d@." - name - period; + Kernel.warning ~current:true ~once:true + "Periodic variable %s of period %d@." + name + period; match validity with | Known(mn, mx) -> - assert (Int.is_zero mn); - Periodic(mn, mx, Int.of_int period) + assert (Int.is_zero mn); + Periodic(mn, mx, Int.of_int period) | _ -> assert false else validity in @@ -361,7 +366,7 @@ module LiteralStrings = State_builder.Hashtbl - (Datatype.String.Hashtbl) + (Datatype.Int.Hashtbl) (D) (struct let name = "litteral strings" @@ -370,8 +375,8 @@ let kind = `Internal end) -let create_string s = - LiteralStrings.memo (fun _ -> String (Cil_const.new_raw_id (), s)) s +let create_string e = + LiteralStrings.memo (fun _ -> String (Cil_const.new_raw_id (), e)) e.eid (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/ai/base.mli frama-c-20111001+nitrogen+dfsg/src/ai/base.mli --- frama-c-20110201+carbon+dfsg/src/ai/base.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/base.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,8 +20,12 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + val name : string -type cell_class_attributes type validity = | All @@ -30,15 +34,17 @@ | Periodic of Abstract_interp.Int.t*Abstract_interp.Int.t* Abstract_interp.Int.t +type string_id + type base = private | Var of Cil_types.varinfo * validity (** Base for uninitialized variables *) | Initialized_Var of Cil_types.varinfo * validity (** Base for variables initialized to zero . *) | Null (** Base for addresses like [(int* )0x123] *) - | String of int * string (** String constants *) - | Cell_class of cell_class_attributes (** A class of memory cells *) + | String of int * string_id (** String constants *) include Datatype.S_with_collections with type t = base +module Hptset: Hptset.S with type elt = t val pretty_validity : Format.formatter -> validity -> unit @@ -46,13 +52,16 @@ val null : t val is_null : t -> bool +val is_read_only : t -> bool + val bits_sizeof : t -> Int_Base.t val id : t -> int val is_aligned_by : t -> Abstract_interp.Int.t -> bool val validity : t -> validity exception Not_valid_offset -val is_valid_offset : Abstract_interp.Int.t -> t -> Ival.t -> unit +val is_valid_offset : + for_writing:bool -> Abstract_interp.Int.t -> t -> Ival.t -> unit val is_function : t -> bool @@ -84,7 +93,10 @@ (** Return the base corresponding to a variable. *) val create_initialized : Cil_types.varinfo -> validity -> t -val create_string : string -> t +val create_string : Cil_types.exp -> t + +type cstring = CSString of string | CSWstring of Escape.wstring +val get_string : string_id -> cstring val min_valid_absolute_address: unit -> Abstract_interp.Int.t val max_valid_absolute_address: unit -> Abstract_interp.Int.t diff -Nru frama-c-20110201+carbon+dfsg/src/ai/base_Set_Lattice.ml frama-c-20111001+nitrogen+dfsg/src/ai/base_Set_Lattice.ml --- frama-c-20110201+carbon+dfsg/src/ai/base_Set_Lattice.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/base_Set_Lattice.ml 2011-10-10 08:38:27.000000000 +0000 @@ -21,3 +21,9 @@ (**************************************************************************) include Abstract_interp.Make_Lattice_Set(Base) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/base_Set_Lattice.mli frama-c-20111001+nitrogen+dfsg/src/ai/base_Set_Lattice.mli --- frama-c-20110201+carbon+dfsg/src/ai/base_Set_Lattice.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/base_Set_Lattice.mli 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + +include Abstract_interp.Lattice_Set with type O.elt = Base.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/int_Base.ml frama-c-20111001+nitrogen+dfsg/src/ai/int_Base.ml --- frama-c-20110201+carbon+dfsg/src/ai/int_Base.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/int_Base.ml 2011-10-10 08:38:27.000000000 +0000 @@ -23,7 +23,7 @@ open Abstract_interp include Make_Lattice_Base(Int) -let neg x = +let neg x = match x with | Value v -> inject (Int.neg v) | Top | Bottom -> x @@ -31,4 +31,9 @@ let one = inject Int.one let zero = inject Int.zero let is_zero x = equal x zero - + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/int_Base.mli frama-c-20111001+nitrogen+dfsg/src/ai/int_Base.mli --- frama-c-20110201+carbon+dfsg/src/ai/int_Base.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/int_Base.mli 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. + @plugin development guide *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + +include Abstract_interp.Lattice_Base with type l = Abstract_interp.Int.t + +val zero: t +val one: t +val minus_one: t + +val is_zero: t -> bool +val neg: t -> t + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/ival.ml frama-c-20111001+nitrogen+dfsg/src/ai/ival.ml --- frama-c-20110201+carbon+dfsg/src/ai/ival.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/ival.ml 2011-10-10 08:38:27.000000000 +0000 @@ -27,8 +27,9 @@ exception Can_not_subdiv -let small_cardinal = 7 +let small_cardinal = 8 let small_cardinal_Int = Int.of_int small_cardinal +let small_cardinal_log = 3 external set_round_downward: unit -> unit = "set_round_downward" external set_round_upward: unit -> unit = "set_round_upward" @@ -43,16 +44,36 @@ let structural_descr = Structural_descr.t_float let packed_descr = Structural_descr.p_float + + let compare f1 f2 = + let i1 = Int64.bits_of_float f1 in + let i2 = Int64.bits_of_float f2 in + let m1 = (Int64.logand i1 Int64.min_int) in + let m2 = (Int64.logand i2 Int64.min_int) in + let i1 = if m1 <> 0L then Int64.logxor i1 Int64.max_int else i1 in + let i2 = if m2 <> 0L then Int64.logxor i2 Int64.max_int else i2 in + Pervasives.compare i1 i2 + + let equal f1 f2 = compare f1 f2 = 0 + + let zero = 0.0 + + let is_zero f = equal zero f + type integer = Int.t exception Nan_or_infinite exception Too_small - let max_single_precision_float = 3.4028234663852886e38 + let max_single_precision_float = Int32.float_of_bits 0x7f7fffffl let most_negative_single_precision_float = -. max_single_precision_float + let min_single_precision_float = Int32.float_of_bits 0x800000l + let neg_min_single_precision_float = -. min_single_precision_float let max_float = max_float let infinity = infinity let neg_infinity = neg_infinity let most_negative_float = -. max_float + let min_denormal = Int64.float_of_bits 1L + let neg_min_denormal = -. min_denormal let is_infinity = (=) infinity let is_neg_infinity = (=) neg_infinity @@ -72,35 +93,114 @@ let mult = wrap_bin ( *.) let div = wrap_bin (/.) + let one_half = 0.5 + + let double_norm = Int64.shift_left 1L 52 + let double_mask = Int64.pred double_norm + + let pretty_normal ~use_hex fmt f = + let i = Int64.bits_of_float f in + let s = 0L <> (Int64.logand Int64.min_int i) in + let i = Int64.logand Int64.max_int i in + let exp = Int64.to_int (Int64.shift_right_logical i 52) in + let man = Int64.logand i double_mask in + let s = if s then "-" else "" in + let firstdigit, exp = + if exp <> 0 + then 1, (exp - 1023) + else 0, -1022 + in + if not use_hex + then begin + let firstdigit, man, exp = + if 0 <= exp && exp <= 12 + then begin + Int64.to_int + (Int64.shift_right_logical + (Int64.logor man double_norm) + (52 - exp)), + Int64.logand (Int64.shift_left man exp) double_mask, + 0 + end + else firstdigit, man, exp + in + let d = + Int64.float_of_bits + (Int64.logor 0x3ff0000000000000L man) + in + let d = d -. 1.0 in + let d = d *. 10000000000000000. in + let decdigits = Int64.of_float d in + if exp = 0 + then + Format.fprintf fmt "%s%d.%016Ld" + s + firstdigit + decdigits + else + Format.fprintf fmt "%s%d.%016Ld*2^%d" + s + firstdigit + decdigits + exp + end + else + Format.fprintf fmt "%s0x%d.%013Lxp%d" + s + firstdigit + man + exp + + let pretty fmt f = + let use_hex = Kernel.FloatHex.get() in + set_round_nearest_even(); + if use_hex || (Kernel.FloatNormal.get ()) + then + pretty_normal ~use_hex fmt f + else begin + let r = Format.sprintf "%.*g" 12 f in + if (String.contains r '.' || String.contains r 'e' || + String.contains r 'E') + || (match classify_float f with + | FP_normal | FP_subnormal | FP_zero -> false + | FP_infinite | FP_nan -> true) + then Format.pp_print_string fmt r + else Format.fprintf fmt "%s." r + end + let avg x y = + let h = 0.5 in let xp = x >= 0. in let yp = y >= 0. in if xp = yp then - let d = x -. y in y +. d /. 2. + let d = x -. y in y +. h *. d else - (x +. y) /. 2. + (x +. y) *. h let le_ieee = ((<=) : float -> float -> bool) let lt_ieee = ((<) : float -> float -> bool) - let zero = 0.0 - let is_zero_ieee = (=) zero + let is_zero_ieee x = x = zero let minus_zero = -0.0 let sqrt = wrap_un sqrt let cos = wrap_un cos + let sin = wrap_un sin + let exp = wrap_un exp let minus_one = -1.0 let one = 1.0 - let one_half = 0.5 let minus_one_half = -0.5 let ten = 10. let m_pi = 3.14159265358979323846264338327950288 let m_minus_pi = -. m_pi let m_pi_2 = 1.57079632679489661923132169163975144 + let m_minus_pi_2 = -. m_pi_2 + let ff = 4.5 + let minus_ff = -4.5 let of_int = float_of_int @@ -115,12 +215,12 @@ else if f <= 1e80 then 1e80 else max_float - let widen_down f = + let widen_down f = if f >= zero then zero else if f >= minus_one_half then minus_one_half else if f >= minus_one then minus_one else if f >= m_minus_pi then m_minus_pi - else if f >= most_negative_single_precision_float + else if f >= most_negative_single_precision_float then most_negative_single_precision_float else most_negative_float @@ -128,9 +228,9 @@ let r = Int64.bits_of_float float in let f = if r >= 0L then - int64fup + int64fup else - int64fdown + int64fdown in Int64.float_of_bits (f r) @@ -138,24 +238,17 @@ match classify_float float with FP_nan | FP_infinite -> raise Nan_or_infinite | FP_normal | FP_subnormal -> - let f = round_normal int64fup int64fdown float in - ( match classify_float f with - FP_nan | FP_infinite -> raise Nan_or_infinite - | FP_normal | FP_subnormal | FP_zero -> f ) + let f = round_normal int64fup int64fdown float in + ( match classify_float f with + FP_nan | FP_infinite -> raise Nan_or_infinite + | FP_normal | FP_subnormal | FP_zero -> f ) | FP_zero -> - (round_normal int64fup int64fdown (float +. min_float)) -. min_float + (round_normal int64fup int64fdown (float +. min_float)) -. min_float let round_up = round Int64.succ Int64.pred let round_down = round Int64.pred Int64.succ - let equal f1 f2 = - if f1 = zero && f2 = zero - then (1. /. f1) = (1. /. f2) - else f1 = f2 - - let is_zero f = f = zero && ((1. /. f) = infinity) - let le f1 f2 = if f1 = zero && f2 = zero then (1. /. f1) <= (1. /. f2) @@ -167,82 +260,7 @@ let max f1 f2 = if le f1 f2 then f2 else f1 - let compare : float -> float -> int = Extlib.compare_basic - let equal_ieee = ((=) : float -> float -> bool) - let double_norm = Int64.shift_left 1L 52 - let double_mask = Int64.pred double_norm - - let pretty fmt f = - let use_hex = Parameters.FloatHex.get() in - if use_hex || (Parameters.FloatNormal.get ()) - then - let i = Int64.bits_of_float f in - let s = 0L <> (Int64.logand Int64.min_int i) in - let i = Int64.logand Int64.max_int i in - let exp = Int64.to_int (Int64.shift_right_logical i 52) in - let man = Int64.logand i double_mask in - let firstdigit, exp = - if exp <> 0 - then 1, (exp - 1023) - else 0, -1022 - in - if not use_hex - then begin - let firstdigit, man, exp = - if 0 <= exp && exp <= 12 - then begin - Int64.to_int - (Int64.shift_right_logical - (Int64.logor man double_norm) - (52 - exp)), - Int64.logand (Int64.shift_left man exp) double_mask, - 0 - end - else firstdigit, man, exp - in - let x2157 = Int64.mul man 2157L in - let sx14 = Int64.shift_right_logical man 14 in - let x2274 = Int64.mul man 2274L in - let sx20 = Int64.shift_right_logical man 20 in - let sx26 = Int64.shift_right_logical man 26 in - let sx2157 = Int64.shift_right_logical x2157 13 in - let p1 = Int64.sub sx14 sx20 in - let p2 = Int64.sub x2274 sx2157 in - let q = Int64.add p1 sx26 in - let q = Int64.add q p2 in - let decdigits = Int64.shift_right_logical q 10 - in - if exp = 0 - then - Format.fprintf fmt "%s%d.%016Ld" - (if s then "-" else "") - firstdigit - decdigits - else - Format.fprintf fmt "%s%d.%016Ld*2^%d" - (if s then "-" else "") - firstdigit - decdigits - exp - end - else - Format.fprintf fmt "%s0x%d.%013Lxp%d" - (if s then "-" else "") - firstdigit - man - exp - else begin - set_round_nearest_even(); - let r = Format.sprintf "%.*g" 12 f in - if (String.contains r '.' || String.contains r 'e' || - String.contains r 'E') - || (match classify_float f with - | FP_normal | FP_subnormal | FP_zero -> false - | FP_infinite | FP_nan -> true) - then Format.pp_print_string fmt r - else Format.fprintf fmt "%s." r - end let hash = Hashtbl.hash @@ -280,15 +298,14 @@ let inject b e = assert - ( if not (F.le b e) - then begin - Format.printf "assertion 0936 failed.@.%30.30f@.%30.30f@." - b e; - false - end - else true - - ); + ( if not (F.le b e) + then begin + Format.printf "assertion 0936 failed.@\n%a .. %a@." + (F.pretty_normal ~use_hex:true) b + (F.pretty_normal ~use_hex:true) e; + false + end + else true); I(b, e) let inject_r b e = @@ -297,27 +314,27 @@ let c = F.classify_float e in let overflow_alarm, e = - match c with - FP_infinite | FP_subnormal -> - let pos = F.le_ieee F.zero e in - ( match c, pos with - FP_infinite, true -> true, F.max_float - | FP_infinite, false -> raise Bottom - | _, true -> false, e - | _, false -> false, F.minus_zero ) - | _ -> false, e + match c with + FP_infinite | FP_subnormal -> + let pos = F.le_ieee F.zero e in + ( match c, pos with + FP_infinite, true -> true, F.max_float + | FP_infinite, false -> raise Bottom + | _, true -> false, e + | _, false -> false, F.minus_zero ) + | _ -> false, e in let c = F.classify_float b in let overflow_alarm, b = - match c with - FP_infinite | FP_subnormal -> - let pos = F.le_ieee F.zero b in - ( match c, pos with - FP_infinite, true -> raise Bottom - | FP_infinite, false -> true, F.most_negative_float - | _, true -> overflow_alarm, F.zero - | _, false -> overflow_alarm, b ) - | _ -> overflow_alarm, b + match c with + FP_infinite | FP_subnormal -> + let pos = F.le_ieee F.zero b in + ( match c, pos with + FP_infinite, true -> raise Bottom + | FP_infinite, false -> true, F.most_negative_float + | _, true -> overflow_alarm, F.zero + | _, false -> overflow_alarm, b ) + | _ -> overflow_alarm, b in overflow_alarm, inject b e @@ -354,18 +371,18 @@ if F.equal b e then Format.fprintf fmt "%a" F.pretty b else begin - if (Parameters.FloatRelative.get()) + if (Kernel.FloatRelative.get()) then begin - set_round_upward (); - let d = F.sub e b in - Format.fprintf fmt "[%a ++ %a]" - F.pretty b - F.pretty d + set_round_upward (); + let d = F.sub e b in + Format.fprintf fmt "[%a ++ %a]" + F.pretty b + F.pretty d end else - Format.fprintf fmt "[%a .. %a]" - F.pretty b - F.pretty e + Format.fprintf fmt "[%a .. %a]" + F.pretty b + F.pretty e end let hash (I(b,e)) = @@ -396,22 +413,23 @@ let bound = ref b in let acc = ref acc in begin try - for i = n downto 2 do - let new_bound = F.add !bound (F.div (F.sub e !bound) (F.of_int i)) in - acc := f (inject !bound new_bound) !acc; - (* Format.printf "float fold_split %a@." - pretty (!bound, new_bound); *) - bound := new_bound - done; + for i = n downto 2 do + let new_bound = F.add !bound (F.div (F.sub e !bound) (F.of_int i)) in + acc := f (inject !bound new_bound) !acc; + (* Format.printf "float fold_split %a@." + pretty (!bound, new_bound); *) + bound := new_bound + done; with Nan_or_infinite -> () end; (* Format.printf "float fold_split %a@." - pretty (!bound, e); *) + pretty (!bound, e); *) f (inject !bound e) !acc let contains_a_zero (I(b, e)) = F.le_ieee b F.zero && F.le_ieee F.zero e - let is_zero x = compare x zero = 0 + let is_zero f = + 0 = compare zero f let is_singleton (I(b, e)) = F.equal b e @@ -421,8 +439,8 @@ type rounding_mode = Any | Nearest_Even - let top_single_precision_float = - inject + let top_single_precision_float = + inject F.most_negative_single_precision_float F.max_single_precision_float @@ -432,21 +450,33 @@ let b = F.round_to_single_precision_float b in set_round_upward (); let e = F.round_to_single_precision_float e in - let min_inf = - match classify_float b with - FP_infinite -> true - | _ -> false - in - let b = if min_inf then F.most_negative_single_precision_float else b - in - let max_inf = - match classify_float e with - FP_infinite -> true - | _ -> false - in - if max_inf - then true, inject b F.max_single_precision_float - else min_inf, inject b e + let min_inf = + match classify_float b with + FP_infinite -> true + | _ -> false + in + let b = + if min_inf + then F.most_negative_single_precision_float + else if F.lt_ieee F.zero b && F.lt_ieee b F.min_single_precision_float + then F.zero + else b + in + let max_inf = + match classify_float e with + FP_infinite -> true + | _ -> false + in + if max_inf + then + true, inject b F.max_single_precision_float + else + let e = + if F.lt_ieee F.neg_min_single_precision_float e && F.lt_ieee e F.minus_zero + then F.minus_zero + else e + in + min_inf, inject b e (* in Format.printf "Casting double -> float %a -> %B %a@." pretty _arg @@ -483,15 +513,15 @@ let max = if rounding_mode = Any then begin - set_round_upward (); - let a = F.mult b1 b2 in - let b = F.mult b1 e2 in - let c = F.mult e1 b2 in - let d = F.mult e1 e2 in - F.max (F.max a b) (F.max c d) - end + set_round_upward (); + let a = F.mult b1 b2 in + let b = F.mult b1 e2 in + let c = F.mult e1 b2 in + let d = F.mult e1 e2 in + F.max (F.max a b) (F.max c d) + end else - F.max (F.max a b) (F.max c d) + F.max (F.max a b) (F.max c d) in inject_r min max @@ -509,13 +539,13 @@ let max = if rounding_mode = Any then begin - set_round_upward (); - let c1 = F.div b1 b2 in - let c2 = F.div b1 e2 in - let c3 = F.div e1 b2 in - let c4 = F.div e1 e2 in - F.max (F.max c1 c2) (F.max c3 c4) - end + set_round_upward (); + let c1 = F.div b1 b2 in + let c2 = F.div b1 e2 in + let c3 = F.div e1 b2 in + let c4 = F.div e1 e2 in + F.max (F.max c1 c2) (F.max c3 c4) + end else F.max (F.max c1 c2) (F.max c3 c4) in inject_r min max @@ -528,10 +558,10 @@ if F.le_ieee F.zero b then false, F.sqrt b else begin - if not (F.le_ieee F.zero e) - then raise Bottom; - true, F.minus_zero - end + if not (F.le_ieee F.zero e) + then raise Bottom; + true, F.minus_zero + end in if rounding_mode = Any then set_round_upward (); @@ -541,16 +571,77 @@ let minus_one_one = inject F.minus_one F.one let cos_float v = + set_round_nearest_even (); match v with - I(b, e) when F.equal b e -> - let c = F.cos b in - inject c c - (* | I(b, e) when F.le_ieee F.zero b && F.le_ieee e F.m_pi-> - inject (F.cos e) (F.cos b) - | I(b, e) when F.le_ieee F.m_minus_pi b && F.le_ieee e F.zero -> - inject (F.cos b) (F.cos e) *) + I(b, e) when F.equal b e -> + let c = F.cos b in + inject c c | _ -> - minus_one_one + minus_one_one + + let sin_float v = + set_round_nearest_even (); + match v with + | I(b, e) when F.equal b e -> let c = F.sin b in inject c c + | _ -> minus_one_one + + let cos_float_precise v = + set_round_nearest_even (); + match v with + | I(b, e) -> + if F.equal b e + then + let c = F.cos b in + inject c c + else if F.le_ieee b F.minus_ff || F.le_ieee F.ff e + then minus_one_one + else begin + let allpos = F.le_ieee F.zero b in + let allneg = F.le_ieee e F.zero in + if F.le_ieee F.m_minus_pi b && F.le_ieee e F.m_pi + then begin + if allpos + then + inject (F.cos e) (F.cos b) + else if allneg + then + inject (F.cos b) (F.cos e) + else + inject (F.min (F.cos b) (F.cos e)) F.one + end + else if allpos || allneg + then inject F.minus_one (F.max (F.cos b) (F.cos e)) + else minus_one_one + end + + let sin_float_precise v = + set_round_nearest_even (); + match v with + | I(b, e) -> + if F.equal b e + then let c = F.sin b in inject c c + else if F.le_ieee b F.minus_ff || F.le_ieee F.ff e + then minus_one_one + else if F.le_ieee e F.m_pi_2 + then begin + if F.le_ieee F.m_minus_pi_2 b + then inject (F.sin b) (F.sin e) + else if F.le_ieee e F.m_minus_pi_2 + then inject (F.sin e) (F.sin b) + else inject F.minus_one (F.max (F.sin b) (F.sin e)) + end + else if F.le_ieee F.m_pi_2 b + then + inject (F.sin e) (F.sin b) + else if F.le_ieee F.m_minus_pi_2 b + then + inject (F.min (F.sin b) (F.sin e)) F.one + else minus_one_one + + let exp_float v = + match v with + I(b, e) -> + inject (F.exp b) (F.exp e) let widen (I(b1,e1)) (I(b2, e2)) = assert (F.le b2 b1); @@ -563,7 +654,7 @@ let I(b1, e1) = f1 in let I(b2, e2) = f2 in let intersects = - F.le_ieee b1 e2 && F.le_ieee b2 e1 + F.le_ieee b1 e2 && F.le_ieee b2 e1 in if not intersects then true, false @@ -590,60 +681,107 @@ then inject e2 e1 else f1 - let filter_le (I(b1, e1) as f1) (I(_b2, e2)) = - let e2 = if F.equal_ieee F.zero e2 then F.zero else e2 in - if not (F.le b1 e2) - then raise Bottom - else if F.le e1 e2 - then f1 - else inject b1 e2 - - let filter_lt allmodes ~typ_loc (I(b1, e1) as f1) (I(_b2, e2)) = + let filter_le_f allmodes ~typ_loc (I(b1, e1) as f1) e2 = + let e2 = + if F.equal_ieee F.zero e2 + then F.zero + else + ( match allmodes, typ_loc with + false, Cil_types.TFloat (Cil_types.FFloat, _) -> + set_round_downward (); + F.round_to_single_precision_float e2 + | _ -> e2 ) + in + if not (F.le b1 e2) + then raise Bottom + else if F.le e1 e2 + then f1 + else inject b1 e2 + + let filter_le allmodes ~typ_loc f1 (I(_b2, e2) as _f2) = + filter_le_f allmodes ~typ_loc f1 e2 + + let filter_lt allmodes ~typ_loc (I(b1, _e1) as f1) (I(_b2, e2)) = + if F.le_ieee e2 b1 + then raise Bottom + else let e2 = - if F.equal_ieee F.zero e2 - then F.zero + if allmodes + then e2 + else if F.equal_ieee F.zero e2 + then F.neg_min_denormal + else F.round_down e2 + in + filter_le_f allmodes ~typ_loc f1 e2 + + let filter_ge_f allmodes ~typ_loc (I(b1, e1) as f1) b2 = + let b2 = + if F.equal_ieee F.minus_zero b2 + then F.minus_zero else ( match allmodes, typ_loc with - false, Cil_types.TFloat (Cil_types.FDouble, _) -> F.round_down e2 - | _ -> e2 ) + false, Cil_types.TFloat (Cil_types.FFloat, _) -> + set_round_upward (); + F.round_to_single_precision_float b2 + | _ -> b2 ) in - if not (F.le b1 e2) - then raise Bottom - else if F.le e1 e2 - then f1 - else inject b1 e2 - - let filter_ge (I(b1, e1) as f1) (I(b2, _e2)) = - let b2 = if F.equal_ieee F.minus_zero b2 then F.minus_zero else b2 in if not (F.le b2 e1) then raise Bottom else if F.le b2 b1 then f1 else inject b2 e1 - let filter_gt allmodes ~typ_loc (I(b1, e1) as f1) (I(b2, _e2)) = + let filter_ge allmodes ~typ_loc f1 (I(b2, _e2)) = + filter_ge_f allmodes ~typ_loc f1 b2 + + let filter_gt allmodes ~typ_loc (I(_b1, e1) as f1) (I(b2, _e2)) = + if F.le_ieee e1 b2 + then raise Bottom + else let b2 = - if F.equal_ieee F.zero b2 - then F.zero - else - ( match allmodes, typ_loc with - false, Cil_types.TFloat (Cil_types.FDouble, _) -> F.round_up b2 - | _ -> b2 ) - in - if not (F.le b2 e1) - then raise Bottom - else if F.le b2 b1 - then f1 - else inject b2 e1 + if allmodes + then b2 + else if F.equal_ieee F.zero b2 + then F.min_denormal + else F.round_up b2 + in + filter_ge_f allmodes ~typ_loc f1 b2 - let subdiv_float_interval (I(l, u) as i) = + let subdiv_float_interval ~size (I(l, u) as i) = let midpoint = F.avg l u in - if F.equal l midpoint || F.equal u midpoint + let midpointl, midpointu = + if size <> 32 && size <> 64 + then midpoint, midpoint + else + let smidpoint = F.round_up midpoint in + if size = 64 + then + let smidpoint = + if F.le smidpoint u then smidpoint else u + in + midpoint, smidpoint + else begin (* 32 *) + set_round_upward (); + assert (F.equal l (F.round_to_single_precision_float l)); + assert (F.equal u (F.round_to_single_precision_float u)); + let midpointu = F.round_to_single_precision_float smidpoint in + set_round_downward (); + let midpointl = F.round_to_single_precision_float midpoint in + midpointl, midpointu + end + in + if F.le midpointu l || F.le u midpointl then raise Can_not_subdiv; - let i1, i2 as c = inject l midpoint, inject midpoint u in +(* Format.printf "%a %a %a %a@." + (F.pretty_normal ~use_hex:true) l + (F.pretty_normal ~use_hex:true) midpointl + (F.pretty_normal ~use_hex:true) midpointu + (F.pretty_normal ~use_hex:true) u; *) + let i1 = inject l midpointl in assert (is_included i1 i); + let i2 = inject midpointu u in assert (is_included i2 i); - c + i1, i2 end @@ -655,17 +793,17 @@ let pretty fmt s = if is_empty s then Format.fprintf fmt "{}" - else begin - Format.fprintf fmt "{%a}" - (fun fmt s -> - iter - (Format.fprintf fmt "%a; " Int.pretty) s) s - end + else + Pretty_utils.pp_iter + ~pre:"@[{" + ~suf:"}@]" + ~sep:";@ " + iter Int.pretty fmt s let default_widen_hints = List.fold_left (fun acc x -> - add (Int.of_int x) acc) + add (Int.of_int x) acc) empty [ -128;-1;0;1;3;15;127;512;32767;1 lsl 29 ] @@ -685,9 +823,16 @@ exception Error_Top exception Error_Bottom + module O = Set.Make(Int) + +type pre_set = + Pre_set of O.t * int + | Pre_top of Int.t * Int.t * Int.t + type tt = - | Set of O.t | Float of Float_abstract.t + | Set of Int.t array + | Float of Float_abstract.t | Top of Int.t option * Int.t option * Int.t * Int.t module Widen_Hints = Widen_Arithmetic_Value_Set @@ -695,18 +840,21 @@ let some_zero = Some Int.zero -let bottom = Set O.empty +let bottom = Set (Array.make 0 Int.zero) let top = Top(None, None, Int.zero, Int.one) +let set_of_array a = + Array.fold_right O.add a O.empty + let hash_v_option v = match v with None -> 97 | Some v -> Int.hash v let hash v = match v with - Set s -> O.fold (fun v acc -> 1031 * acc + (Int.hash v)) s 17 + Set s -> Array.fold_left (fun acc v -> 1031 * acc + (Int.hash v)) 17 s | Top(mn,mx,r,m) -> hash_v_option mn + 5501 * (hash_v_option mx) + - 59 * (Int.hash r) + 13031 * (Int.hash m) + 59 * (Int.hash r) + 13031 * (Int.hash m) | Float(f) -> 3 + 17 * Float_abstract.hash f @@ -722,7 +870,20 @@ let compare e1 e2 = if e1==e2 then 0 else match e1,e2 with - | Set e1,Set e2 -> O.compare e1 e2 + | Set e1,Set e2 -> + let l1 = Array.length e1 in + let l2 = Array.length e2 in + if l1 <> l2 + then l1 - l2 (* no overflow here *) + else + let rec c i = + if i = l1 then 0 + else + let r = Int.compare e1.(i) e2.(i) in + if r <> 0 then r + else c (succ i) + in + c 0 | _, Set _ -> 1 | Set _, _ -> -1 | Top(mn,mx,r,m), Top(mn',mx',r',m') -> @@ -737,41 +898,38 @@ | Top _, _ -> -1 | Float(f1), Float(f2) -> Float_abstract.compare f1 f2 - (*| _, Float _ -> 1 - | Float _, _ -> -1 *) + (*| _, Float _ -> 1 + | Float _, _ -> -1 *) let equal e1 e2 = compare e1 e2 = 0 let pretty fmt t = match t with | Top(mn,mx,r,m) -> - if equal t top then - Format.fprintf fmt "[--..--]" - else - Format.fprintf fmt "[%a..%a]%t" - (fun fmt -> - (function None -> Format.fprintf fmt "--" - | Some v -> Int.pretty fmt v)) - mn - (fun fmt -> - (function None -> Format.fprintf fmt "--" - | Some v -> Int.pretty fmt v)) - mx - (fun fmt -> - if Int.is_zero r && Int.is_one m then - Format.fprintf fmt "" - else Format.fprintf fmt ",%a%%%a" - Int.pretty r - Int.pretty m) + let print_bound fmt = + function + None -> Format.fprintf fmt "--" + | Some v -> Int.pretty fmt v + in + Format.fprintf fmt "[%a..%a]%t" + print_bound mn + print_bound mx + (fun fmt -> + if Int.is_zero r && Int.is_one m then + Format.fprintf fmt "" + else Format.fprintf fmt ",%a%%%a" + Int.pretty r + Int.pretty m) | Float (f) -> Float_abstract.pretty fmt f | Set s -> - if O.is_empty s then Format.fprintf fmt "BottomMod" + if Array.length s = 0 then Format.fprintf fmt "BottomMod" else begin - Format.fprintf fmt "{%a}" - (fun fmt s -> - O.iter - (Format.fprintf fmt "%a; " Int.pretty) s) s + Pretty_utils.pp_iter + ~pre:"@[{" + ~suf:"}@]" + ~sep:";@ " + Array.iter Int.pretty fmt s end let compare_elt_min elt min = @@ -796,78 +954,94 @@ let check doc min max r modu = assert(assert (Int.ge r Int.zero ); - assert (Int.ge modu Int.one ); - (match min with - | None -> () - | Some m -> if not (Int.equal (Int.pos_rem m modu) r) then - begin - ignore (CilE.warn_once "Make_Lattice_Mod.check: '%s'\n" doc); - Format.printf "min=%a modu=%a r=%a@." Int.pretty m Int.pretty modu Int.pretty r; - assert false - end); - (match max with - | None -> () - | Some m -> assert (Int.equal (Int.pos_rem m modu) r)); - true) + assert (Int.ge modu Int.one ); + (match min with + | None -> () + | Some m -> + if not (Int.equal (Int.pos_rem m modu) r) then begin + Kernel.warning ~once:true ~current:true + "Make_Lattice_Mod.check: '%s'\n" doc; + Kernel.feedback "min=%a modu=%a r=%a@." + Int.pretty m Int.pretty modu Int.pretty r; + assert false + end); + (match max with + | None -> () + | Some m -> assert (Int.equal (Int.pos_rem m modu) r)); + true) let cardinal_zero_or_one v = match v with | Top _ -> false - | Set s -> O.cardinal s <= 1 + | Set s -> Array.length s <= 1 | Float (f) -> Float_abstract.is_singleton f let is_singleton_int v = match v with | Float _ | Top _ -> false -| Set s -> O.cardinal s = 1 +| Set s -> Array.length s = 1 -let is_bottom = equal bottom +let is_bottom x = x == bottom let o_zero = O.singleton Int.zero let o_one = O.singleton Int.one let o_zero_or_one = O.union o_zero o_one -let zero = Set o_zero -let one = Set o_one -let zero_or_one = Set o_zero_or_one +let small_nums = Array.map (fun i -> Set [| i |]) Int.small_nums -let small_nums = Array.map (fun i -> Set (O.singleton i)) Int.small_nums +let zero = small_nums.(0) +let one = small_nums.(1) +let zero_or_one = Set [| Int.zero ; Int.one |] + +let is_zero x = x == zero + +let inject_singleton e = + if Int.le Int.zero e && Int.le e Int.thirtytwo + then small_nums.(Int.to_int e) + else Set [| e |] + +let share_set o s = + if s = 0 then bottom + else if s = 1 + then begin + let e = O.min_elt o in + inject_singleton e + end + else if O.equal o o_zero_or_one + then zero_or_one + else + let a = Array.make s Int.zero in + let i = ref 0 in + O.iter (fun e -> a.(!i) <- e; incr i) o; + assert (!i = s); + Set a -let share_set s = - try - let min = O.min_elt s in - let max = O.max_elt s in - if Int.equal min max - then begin - if Int.le Int.zero min && Int.le min Int.thirtytwo - then small_nums.(Int.to_int min) - else Set s - end - else if O.equal s o_zero_or_one +let share_array a s = + if s = 0 then bottom + else + let e = a.(0) in + if s = 1 && Int.le Int.zero e && Int.le e Int.thirtytwo + then small_nums.(Int.to_int e) + else if s = 2 && Int.is_zero e && Int.is_one a.(1) then zero_or_one - else Set s - with Not_found -> bottom - - -let inject_singleton s = - share_set (O.singleton s) + else Set a let inject_float f = if Float_abstract.is_zero f then zero else Float f -let subdiv_float_interval v = +let subdiv_float_interval ~size v = match v with | Float f -> - let f1, f2 = Float_abstract.subdiv_float_interval f in + let f1, f2 = Float_abstract.subdiv_float_interval ~size f in inject_float f1, inject_float f2 - | Top _ | Set _ -> assert false + | Top _ | Set _ -> + assert (is_zero v); + raise Can_not_subdiv (* let minus_zero = Float (Float_abstract.minus_zero, Float_abstract.minus_zero) *) -let is_zero = equal zero - let is_one = equal one let project_float v = @@ -883,16 +1057,30 @@ (compare_elt_min x min) && (compare_elt_max x max) +let array_mem v a = + let l = Array.length a in + let rec c i = + if i = l then (-1) + else + let ae = a.(i) in + if Int.equal ae v + then i + else if Int.gt ae v + then (-1) + else c (succ i) + in + c 0 + let contains_zero s = match s with | Top(mn,mx,r,m) -> in_interval Int.zero mn mx r m - | Set s -> O.mem Int.zero s + | Set s -> (array_mem Int.zero s)>=0 | Float f -> Float_abstract.contains_zero f exception Not_Singleton_Int let project_int v = match v with -| Set s when O.cardinal s = 1 -> O.min_elt s +| Set [| e |] -> e | _ -> raise Not_Singleton_Int let cardinal_less_than v n = @@ -900,9 +1088,10 @@ match v with | Top (None,_,_,_) | Top (_,None,_,_) -> raise Not_less_than | Top (Some mn, Some mx,_,m) -> - Int.succ ((Int.native_div (Int.sub mx mn) m)) - | Set s -> Int.of_int (O.cardinal s) - | Float f -> if Float_abstract.is_singleton f then Int.one else raise Not_less_than + Int.succ ((Int.native_div (Int.sub mx mn) m)) + | Set s -> Int.of_int (Array.length s) + | Float f -> + if Float_abstract.is_singleton f then Int.one else raise Not_less_than in if Int.le c (Int.of_int n) then Int.to_int c (* This is smaller than the original [n] *) @@ -913,11 +1102,11 @@ match v with | Top (None,_,_,_) | Top (_,None,_,_) -> raise Not_less_than | Top (Some mn, Some mx,_,m) -> - Int.succ ((Int.native_div (Int.sub mx mn) m)) - | Set s -> Int.of_int (O.cardinal s) + Int.succ ((Int.native_div (Int.sub mx mn) m)) + | Set s -> Int.of_int (Array.length s) | Float f -> - if Float_abstract.is_singleton f then Int.one - else Int.of_int split_non_enumerable + if Float_abstract.is_singleton f then Int.one + else Int.of_int split_non_enumerable in if Int.le c (Int.of_int n) then Int.to_int c @@ -931,18 +1120,25 @@ check "inject_top" min max r modu; match min, max with | Some mn, Some mx -> - if Int.ge mx mn then - if (Int.le (Int.length mn mx) (Int.mul modu small_cardinal_Int)) - then - let s = ref O.empty in - let i = ref mn in - while (Int.le !i mx) - do - s := O.add !i !s; - i := Int.add modu !i - done; - share_set (!s) - else Top (min, max, r, modu) + if Int.gt mx mn then + let l = Int.succ (Int.div (Int.sub mx mn) modu) in + if Int.le l small_cardinal_Int + then + let l = Int.to_int l in + let s = Array.make l Int.zero in + let v = ref mn in + let i = ref 0 in + while (!i < l) + do + s.(!i) <- !v; + v := Int.add modu !v; + incr i + done; + assert (Int.equal !v (Int.add modu mx)); + share_array s l + else Top (min, max, r, modu) + else if Int.equal mx mn + then inject_singleton mn else bottom | _ -> share_top min max r modu @@ -956,38 +1152,131 @@ let m = O.min_elt s in let modu = O.fold (fun x acc -> - if Int.equal x m - then acc - else Int.pgcd (Int.sub x m) acc) + if Int.equal x m + then acc + else Int.pgcd (Int.sub x m) acc) s Int.zero in let r = Int.pos_rem m modu in - let max = Some(O.max_elt s) in - let min = Some m in - check "unsafe_make_top_from_set_4" min max r modu; + let max = O.max_elt s in + let min = m in (min,max,r,modu) let unsafe_make_top_from_set s = let min, max, r, modu = unsafe_make_top_from_set_4 s in + share_top (Some min) (Some max) r modu + +let unsafe_make_top_from_array_4 s = + let l = Array.length s in + assert (l >= 2); + let m = s.(0) in + let modu = + Array.fold_left + (fun acc x -> + if Int.equal x m + then acc + else Int.pgcd (Int.sub x m) acc) + Int.zero + s + in + let r = Int.pos_rem m modu in + let max = Some s.(pred l) in + let min = Some m in + check "unsafe_make_top_from_array_4" min max r modu; + (min,max,r,modu) + +let unsafe_make_top_from_array s = + let min, max, r, modu = unsafe_make_top_from_array_4 s in share_top min max r modu +let empty_ps = Pre_set (O.empty, 0) + +let add_ps ps x = + match ps with + Pre_set(o,s) -> + assert (O.cardinal o = s); + if (O.mem x o) (* TODO: improve *) + then ps + else + let no = O.add x o in + if s < small_cardinal + then begin + assert (O.cardinal no = succ s); + Pre_set (no, succ s) + end + else + let min, max, _r, modu = unsafe_make_top_from_set_4 no in + Pre_top (min, max, modu) + | Pre_top (min, max, modu) -> + let new_modu = + if Int.equal x min + then modu + else Int.pgcd (Int.sub x min) modu + in + let new_min = Int.min min x + in + let new_max = Int.max max x + in + Pre_top (new_min, new_max, new_modu) + +let inject_ps ps = + match ps with + Pre_set(o, s) -> share_set o s + | Pre_top (min, max, modu) -> + Top(Some min, Some max, Int.pos_rem min modu, modu) + let min_max_r_mod t = match t with | Set s -> - assert (O.cardinal s >= 2); - unsafe_make_top_from_set_4 s + assert (Array.length s >= 2); + unsafe_make_top_from_array_4 s | Top (a,b,c,d) -> a,b,c,d | Float _ -> None, None, Int.zero, Int.one let min_and_max t = match t with | Set s -> - assert (O.cardinal s >= 1); - Some (O.min_elt s), Some (O.max_elt s) + let l = Array.length s in + assert (l >= 1); + Some s.(0), Some s.(pred l) | Top (a,b,_,_) -> a, b | Float _ -> None, None +exception Unforceable + +let force_float kind i = + match i with + Float _ -> false, i + | Set _ when is_zero i -> false, i + | Top _ | Set _ -> + ( match kind with + Cil_types.FDouble -> + ( try + ( match min_and_max i with + Some mn, Some mx -> + let mn, mx = + if Int.le Int.zero mn && Int.le mx Int.bits_of_max_float + then mn, mx + else if Int.le Int.min_int64 mn && + Int.le mx Int.bits_of_most_negative_float + then mx, mn + else raise Unforceable + in + let red, fa = + Float_abstract.inject_r + (Int64.float_of_bits (Int.to_int64 mn)) + (Int64.float_of_bits (Int.to_int64 mx)) + in + assert (not red); + let f = inject_float fa in + (* Format.printf "cv: %a -> %a@." pretty i pretty f; *) + false, f + | _, _ -> true, top_float) + with Unforceable -> + true, top_float ) + | _ -> false, i) + let compare_min_int t1 t2 = let m1, _ = min_and_max t1 in let m2, _ = min_and_max t2 in @@ -998,94 +1287,88 @@ | Some m1, Some m2 -> Int.compare m1 m2 -let compare_max_int t1 t2 = - let _, m1 = min_and_max t1 in - let _, m2 = min_and_max t2 in - match m1, m2 with - None, None -> 0 - | None, Some _ -> 1 - | Some _, None -> -1 - | Some m1, Some m2 -> - Int.compare m2 m1 - -let compare_min_float t1 t2 = - let f1 = project_float t1 in - let f2 = project_float t2 in - Float_abstract.compare_min f1 f2 - -let compare_max_float t1 t2 = - let f1 = project_float t1 in - let f2 = project_float t2 in - Float_abstract.compare_max f1 f2 - -let widen wh t1 t2 = - if equal t1 t2 || cardinal_zero_or_one t1 then t2 - else - match t2 with - Float f2 -> - ( try - let f1 = project_float t1 in - if not (Float_abstract.is_included f1 f2) - then assert false; - Float (Float_abstract.widen f1 f2) - with Float_abstract.Nan_or_infinite -> assert false) - | Top _ | Set _ -> - let (mn2,mx2,r2,m2) = min_max_r_mod t2 in - let (mn1,mx1,r1,m1) = min_max_r_mod t1 in - let new_mod = Int.pgcd (Int.pgcd m1 m2) (Int.abs (Int.sub r1 r2)) in - let new_rem = Int.rem r1 new_mod in - - let new_min = if bound_compare mn1 mn2 = 0 then mn2 else - match mn2 with - | None -> None - | Some mn2 -> - try - let v = Widen_Hints.nearest_elt_le mn2 wh - in Some (Int.round_up_to_r ~r:new_rem ~modu:new_mod ~min:v) - with Not_found -> None - in - let new_max = if bound_compare mx1 mx2 = 0 then mx2 else - match mx2 with None -> None - | Some mx2 -> - try - let v = Widen_Hints.nearest_elt_ge mx2 wh - in Some (Int.round_down_to_r ~r:new_rem ~modu:new_mod ~max:v) - with Not_found -> None - in - let result = inject_top new_min new_max new_rem new_mod in - (*Format.printf "%a -- %a --> %a (thx to %a)@." - pretty t1 pretty t2 pretty result - Widen_Hints.pretty wh;*) - result - - -let inject_set s = - if (O.cardinal s) <= small_cardinal - then share_set s - else unsafe_make_top_from_set s + let compare_max_int t1 t2 = + let _, m1 = min_and_max t1 in + let _, m2 = min_and_max t2 in + match m1, m2 with + None, None -> 0 + | None, Some _ -> 1 + | Some _, None -> -1 + | Some m1, Some m2 -> + Int.compare m2 m1 + + let compare_min_float t1 t2 = + let f1 = project_float t1 in + let f2 = project_float t2 in + Float_abstract.compare_min f1 f2 + + let compare_max_float t1 t2 = + let f1 = project_float t1 in + let f2 = project_float t2 in + Float_abstract.compare_max f1 f2 + + let widen wh t1 t2 = + if equal t1 t2 || cardinal_zero_or_one t1 then t2 + else + match t2 with + Float f2 -> + ( try + let f1 = project_float t1 in + if not (Float_abstract.is_included f1 f2) + then assert false; + Float (Float_abstract.widen f1 f2) + with Float_abstract.Nan_or_infinite -> assert false) + | Top _ | Set _ -> + let (mn2,mx2,r2,m2) = min_max_r_mod t2 in + let (mn1,mx1,r1,m1) = min_max_r_mod t1 in + let new_mod = Int.pgcd (Int.pgcd m1 m2) (Int.abs (Int.sub r1 r2)) in + let new_rem = Int.rem r1 new_mod in + + let new_min = if bound_compare mn1 mn2 = 0 then mn2 else + match mn2 with + | None -> None + | Some mn2 -> + try + let v = Widen_Hints.nearest_elt_le mn2 wh + in Some (Int.round_up_to_r ~r:new_rem ~modu:new_mod ~min:v) + with Not_found -> None + in + let new_max = if bound_compare mx1 mx2 = 0 then mx2 else + match mx2 with None -> None + | Some mx2 -> + try + let v = Widen_Hints.nearest_elt_ge mx2 wh + in Some (Int.round_down_to_r ~r:new_rem ~modu:new_mod ~max:v) + with Not_found -> None + in + let result = inject_top new_min new_max new_rem new_mod in +(* Format.printf "%a -- %a --> %a (thx to %a)@." + pretty t1 pretty t2 pretty result + Widen_Hints.pretty wh; *) + result let compute_first_common mn1 mn2 r modu = - if mn1 = None && mn2 = None + if mn1 == None && mn2 == None then None else let m = match (mn1, mn2) with | Some m, None | None, Some m -> m | Some m1, Some m2 -> - Int.max m1 m2 + Int.max m1 m2 | None, None -> assert false (* already tested above *) in Some (Int.round_up_to_r m r modu) let compute_last_common mx1 mx2 r modu = - if mx1 = None && mx2 = None + if mx1 == None && mx2 == None then None else let m = match (mx1, mx2) with | Some m, None | None, Some m -> m | Some m1, Some m2 -> - Int.min m1 m2 + Int.min m1 m2 | None, None -> assert false (* already tested above *) in Some (Int.round_down_to_r m r modu) @@ -1124,100 +1407,243 @@ with Found i -> i, modu +let array_truncate r i = + if i = 0 + then bottom + else if i = 1 + then inject_singleton r.(0) + else begin + (Obj.truncate (Obj.repr r) i); + assert (Array.length r = i); + Set r + end +let array_inter a1 a2 = + let l1 = Array.length a1 in + let l2 = Array.length a2 in + let lr_max = min l1 l2 in + let r = Array.make lr_max Int.zero in + let rec c i i1 i2 = + if i1 = l1 || i2 = l2 + then array_truncate r i + else + let e1 = a1.(i1) in + let e2 = a2.(i2) in + if Int.equal e1 e2 + then begin + r.(i) <- e1; + c (succ i) (succ i1) (succ i2) + end + else if Int.lt e1 e2 + then c i (succ i1) i2 + else c i i1 (succ i2) + in + c 0 0 0 let meet v1 v2 = if v1 == v2 then v1 else let result = match v1,v2 with | Top(min1,max1,r1,modu1), Top(min2,max2,r2,modu2) -> - begin - try - let r,modu = compute_r_common r1 modu1 r2 modu2 in - inject_top - (compute_first_common min1 min2 r modu) - (compute_last_common max1 max2 r modu) - r - modu - with Error_Bottom -> - (*Format.printf "meet to bottom: %a /\\ %a@\n" - pretty v1 pretty v2;*) - bottom - end - | Set s1 , Set s2 -> share_set (O.inter s1 s2) - | Set s, Top(min, max, r, modu) - | Top(min, max, r, modu), Set s -> - share_set - (O.filter - (fun x -> in_interval x min max r modu) - s) + begin + try + let r,modu = compute_r_common r1 modu1 r2 modu2 in + inject_top + (compute_first_common min1 min2 r modu) + (compute_last_common max1 max2 r modu) + r + modu + with Error_Bottom -> + (*Format.printf "meet to bottom: %a /\\ %a@\n" + pretty v1 pretty v2;*) + bottom + end + | Set s1 , Set s2 -> array_inter s1 s2 + | Set s, Top(min, max, rm, modu) + | Top(min, max, rm, modu), Set s -> + let l = Array.length s in + let r = Array.create l Int.zero in + let rec c i j = + if i = l + then + array_truncate r j + else + let si = succ i in + let x = s.(i) in + if in_interval x min max rm modu + then begin + r.(j) <- x; + c si (succ j) + end + else + c si j + in + c 0 0 | Float(f1), Float(f2) -> - ( try - inject_float (Float_abstract.meet f1 f2) - with Float_abstract.Bottom -> bottom ) + ( try + inject_float (Float_abstract.meet f1 f2) + with Float_abstract.Bottom -> bottom ) | (Float f) as ff, other | other, ((Float f) as ff) -> - if equal top other - then ff - else if (Float_abstract.contains_zero f) && contains_zero other - then zero - else bottom + if equal top other + then ff + else if (Float_abstract.contains_zero f) && contains_zero other + then zero + else bottom in (* Format.printf "meet: %a /\\ %a -> %a@\n" - pretty v1 pretty v2 pretty result;*) + pretty v1 pretty v2 pretty result;*) result -let narrow v1 v2 = +let narrow v1 v2 = match v1, v2 with - Float _, Float _ | (Top _| Set _), (Top _ | Set _) -> + Float _, Float _ | (Top _| Set _), (Top _ | Set _) -> meet v1 v2 (* meet is exact *) + | Float f, s | s, Float f when is_zero s -> + ( try + inject_float (Float_abstract.meet f Float_abstract.zero) + with Float_abstract.Bottom -> bottom ) | _ -> v1 let link _ = assert false - (** This is NOT exact *) let join v1 v2 = let result = if v1 == v2 then v1 else - match v1,v2 with - | Top(mn1,mx1,r1,m1), Top(mn2,mx2,r2,m2) -> - check "join left" mn1 mx1 r1 m1; - check "join right" mn2 mx2 r2 m2; - let modu = Int.pgcd (Int.pgcd m1 m2) (Int.abs(Int.sub r1 r2)) in - let r = Int.rem r1 modu in - let min = min_min mn1 mn2 in - let max = max_max mx1 mx2 in - let r = inject_top min max r modu in - r - | Set s, (Top(min, max, r, modu) as t) - | (Top(min, max, r, modu) as t), Set s -> - if O.is_empty s then t - else - let f elt modu = Int.pgcd modu (Int.abs(Int.sub r elt)) in - let new_modu = O.fold f s modu in - let new_r = Int.rem r new_modu in - let new_min = match min with - None -> None - | Some m -> Some (Int.min m (O.min_elt s)) - in - let new_max = match max with - None -> None - | Some m -> Some (Int.max m (O.max_elt s)) - in - check "inside join" new_min new_max new_r new_modu; - share_top new_min new_max new_r new_modu - | Set s1 , Set s2 -> - let u = O.union s1 s2 in - inject_set u - | Float(f1), Float(f2) -> - inject_float (Float_abstract.join f1 f2) - | Float (f) as ff, other | other, (Float (f) as ff) -> - if is_zero other - then inject_float (Float_abstract.join Float_abstract.zero f) - else if is_bottom other then ff - else top + match v1,v2 with + | Top(mn1,mx1,r1,m1), Top(mn2,mx2,r2,m2) -> + check "join left" mn1 mx1 r1 m1; + check "join right" mn2 mx2 r2 m2; + let modu = Int.pgcd (Int.pgcd m1 m2) (Int.abs(Int.sub r1 r2)) in + let r = Int.rem r1 modu in + let min = min_min mn1 mn2 in + let max = max_max mx1 mx2 in + let r = inject_top min max r modu in + r + | Set s, (Top(min, max, r, modu) as t) + | (Top(min, max, r, modu) as t), Set s -> + let l = Array.length s in + if l = 0 then t + else + let f modu elt = Int.pgcd modu (Int.abs(Int.sub r elt)) in + let new_modu = Array.fold_left f modu s in + let new_r = Int.rem r new_modu in + let new_min = match min with + None -> None + | Some m -> Some (Int.min m s.(0)) + in + let new_max = match max with + None -> None + | Some m -> Some (Int.max m s.(pred l)) + in + check "inside join" new_min new_max new_r new_modu; + share_top new_min new_max new_r new_modu + | Set s1 , Set s2 -> + let l1 = Array.length s1 in + if l1 = 0 + then v2 + else + let l2 = Array.length s2 in + if l2 = 0 + then v1 + else + (* second pass: make a set or make a top *) + let second uniq = + if uniq <= small_cardinal + then + let r = Array.create uniq Int.zero in + let rec c i i1 i2 = + if i1 = l1 + then begin + Array.blit s2 i2 r i (l2 - i2); + share_array r uniq + end + else if i2 = l2 + then begin + Array.blit s1 i1 r i (l1 - i1); + share_array r uniq + end + else + let si = succ i in + let e1 = s1.(i1) in + let e2 = s2.(i2) in + if Int.lt e2 e1 + then begin + r.(i) <- e2; + c si i1 (succ i2) + end + else begin + r.(i) <- e1; + let si1 = succ i1 in + if Int.equal e1 e2 + then begin + c si si1 (succ i2) + end + else begin + c si si1 i2 + end + end + in + c 0 0 0 + else begin + let m = Int.min s1.(0) s2.(0) in + let accum acc x = + if Int.equal x m + then acc + else Int.pgcd (Int.sub x m) acc + in + let modu = ref Int.zero in + for j = 0 to pred l1 do + modu := accum !modu s1.(j) + done; + for j = 0 to pred l2 do + modu := accum !modu s2.(j) + done; + inject_ps + (Pre_top (m, Int.max s1.(pred l1) s2.(pred l2), !modu)) + end + in + (* first pass: count unique elements and detect inclusions *) + let rec first i1 i2 uniq inc1 inc2 = + let finished1 = i1 = l1 in + if finished1 + then begin + if inc2 + then v2 + else second (uniq + l2 - i2) + end + else + let finished2 = i2 = l2 in + if finished2 + then begin + if inc1 + then v1 + else second (uniq + l1 - i1) + end + else + let e1 = s1.(i1) in + let e2 = s2.(i2) in + if Int.lt e2 e1 + then begin + first i1 (succ i2) (succ uniq) false inc2 + end + else if Int.gt e2 e1 + then begin + first (succ i1) i2 (succ uniq) inc1 false + end + else first (succ i1) (succ i2) (succ uniq) inc1 inc2 + in + first 0 0 0 true true + + | Float(f1), Float(f2) -> + inject_float (Float_abstract.join f1 f2) + | Float (f) as ff, other | other, (Float (f) as ff) -> + if is_zero other + then inject_float (Float_abstract.join Float_abstract.zero f) + else if is_bottom other then ff + else top in - (* Format.printf "mod_join %a %a -> %a@." - pretty v1 pretty v2 pretty result; *) +(* Format.printf "mod_join %a %a -> %a@." + pretty v1 pretty v2 pretty result; *) result (* TODO: rename this function in fold_int *) @@ -1228,7 +1654,7 @@ | Top(Some inf, Some sup, _, step) -> Int.fold f ~inf ~sup ~step acc | Set s -> - O.fold f s acc + Array.fold_left (fun acc x -> f x acc) acc s let fold_enum ~split_non_enumerable f v acc = match v with @@ -1236,17 +1662,17 @@ f v acc | Float (fl) -> Float_abstract.fold_split - split_non_enumerable - (fun fl acc -> f (inject_float fl) acc) - fl - acc + split_non_enumerable + (fun fl acc -> f (inject_float fl) acc) + fl + acc | Top(_,_,_,_) | Set _ -> fold (fun x acc -> f (inject_singleton x) acc) v acc - (** [min_is_lower mn1 mn2] is true iff mn1 is a lower min than mn2 *) + (** [min_is_lower mn1 mn2] is true iff mn1 is a lower min than mn2 *) let min_is_lower mn1 mn2 = match mn1, mn2 with None, _ -> true @@ -1254,7 +1680,7 @@ | Some m1, Some m2 -> Int.le m1 m2 - (** [max_is_greater mx1 mx2] is true iff mx1 is a greater max than mx2 *) + (** [max_is_greater mx1 mx2] is true iff mx1 is a greater max than mx2 *) let max_is_greater mx1 mx2 = match mx1, mx2 with None, _ -> true @@ -1265,6 +1691,34 @@ let rem_is_included r1 m1 r2 m2 = (Int.is_zero (Int.rem m1 m2)) && (Int.equal (Int.rem r1 m2) r2) +let array_for_all f (a : My_bigint.t array) = + let l = Array.length a in + let rec c i = + i = l || + ((f a.(i)) && c (succ i)) + in + c 0 + +let array_subset a1 a2 = + let l1 = Array.length a1 in + let l2 = Array.length a2 in + if l1 > l2 then false + else + let rec c i1 i2 = + if i1 = l1 then true + else if i2 = l2 then false + else + let e1 = a1.(i1) in + let e2 = a2.(i2) in + let si2 = succ i2 in + if Int.equal e1 e2 + then c (succ i1) si2 + else if Int.lt e1 e2 + then false + else c i1 si2 (* TODO: improve by not reading a1.(i1) all the time *) + in + c 0 0 + let is_included t1 t2 = (t1 == t2) || match t1,t2 with @@ -1273,10 +1727,10 @@ (max_is_greater mx2 mx1) && rem_is_included r1 m1 r2 m2 | Top _, Set _ -> false (* Top _ represents more elements - than can be represented by Set _ *) + than can be represented by Set _ *) | Set s, Top(min, max, r, modu) -> - O.for_all (fun x -> in_interval x min max r modu) s - | Set s1, Set s2 -> O.subset s1 s2 + array_for_all (fun x -> in_interval x min max r modu) s + | Set s1, Set s2 -> array_subset s1 s2 | Float(f1), Float(f2) -> Float_abstract.is_included f1 f2 | Float _, _ -> equal t2 top @@ -1286,101 +1740,233 @@ if not (is_included v1 v2) then raise Is_not_included (* In this lattice, [meet t1 t2=bottom] iff the - intersection of [t1] and [t2] is empty. *) + intersection of [t1] and [t2] is empty. *) + let intersects t1 t2 = not (equal bottom (meet t1 t2)) -let map_set f s = - O.fold - (fun v -> O.add (f v)) +let partially_overlaps size t1 t2 = + match t1, t2 with + Set s1, Set s2 -> + not + (array_for_all + (fun e1 -> + array_for_all + (fun e2 -> + Int.equal e1 e2 || + Int.le e1 (Int.sub e2 size) || + Int.ge e1 (Int.add e2 size)) + s2) + s1) + | Set s, Top(mi, ma, r, modu) | Top(mi, ma, r, modu), Set s -> + not + (array_for_all + (fun e -> + let psize = Int.pred size in + (not (compare_elt_min (Int.add e psize) mi)) || + (not (compare_elt_max (Int.sub e psize) ma)) || + ( Int.ge modu size && + let re = Int.pos_rem (Int.sub e r) modu in + Int.is_zero re || + (Int.ge re size && + Int.le re (Int.sub modu size)) )) + s) + | _ -> false (* TODO *) + +let map_set_exnsafe_acc f acc (s : My_bigint.t array) = + Array.fold_left + (fun acc v -> add_ps acc (f v)) + acc s - O.empty -let apply2 f s1 s2 = - O.fold - (fun v -> O.union (map_set (f v) s2)) - s1 - O.empty +let map_set_exnsafe f (s : My_bigint.t array) = + inject_ps (map_set_exnsafe_acc f empty_ps s) +let apply2_notzero f (s1 : My_bigint.t array) s2 = + inject_ps + (Array.fold_left + (fun acc v1 -> + Array.fold_left + (fun acc v2 -> + if Int.is_zero v2 + then acc + else add_ps acc (f v1 v2)) + acc + s2) + empty_ps + s1) + +let apply2_n f (s1 : My_bigint.t array) (s2 : My_bigint.t array) = + let ps = ref empty_ps in + let l1 = Array.length s1 in + let l2 = Array.length s2 in + for i1 = 0 to pred l1 do + let e1 = s1.(i1) in + for i2 = 0 to pred l2 do + ps := add_ps !ps (f e1 s2.(i2)) + done + done; + inject_ps !ps + +let apply2_v f s1 s2 = + match s1, s2 with + [| x1 |], [| x2 |] -> + inject_singleton (f x1 x2) + | _ -> apply2_n f s1 s2 + exception Apply_Set_Exn of exn -let apply_set info f v1 v2 = +let apply_set f v1 v2 = match v1,v2 with | Set s1, Set s2 -> - begin try - let result = try - apply2 f s1 s2 - with e -> raise (Apply_Set_Exn e) - in - inject_set result - with - Apply_Set_Exn(e) -> - ignore (CilE.warn_once - "binary operator '%s' raised an exception '%s' when applied" - info - (Printexc.to_string e)); - top - end + apply2_n f s1 s2 | _ -> (*ignore (CilE.warn_once "unsupported case for binary operator '%s'" info);*) top -let rec apply_set_unary _info f v = +let rec apply_set_unary _info f v = (* TODO: improve by allocating array*) match v with - | Set s -> - inject_set (map_set f s) + | Set s -> map_set_exnsafe f s | _ -> (*ignore (CilE.warn_once "unsupported case for unary operator '%s'" info);*) top - (* TODO: rename in add_int *) +let apply_bin_1_strict_incr f x (s : My_bigint.t array) = + let l = Array.length s in + let r = Array.create l Int.zero in + let rec c i = + if i = l + then share_array r l + else + let v = f x s.(i) in + r.(i) <- v; + c (succ i) + in + c 0 + +let apply_bin_1_strict_decr f x (s : My_bigint.t array) = + let l = Array.length s in + let r = Array.create l Int.zero in + let rec c i = + if i = l + then share_array r l + else + let v = f x s.(i) in + r.(l - i - 1) <- v; + c (succ i) + in + c 0 + +let map_set_strict_decr f (s : My_bigint.t array) = + let l = Array.length s in + let r = Array.create l Int.zero in + let rec c i = + if i = l + then share_array r l + else + let v = f s.(i) in + r.(l - i - 1) <- v; + c (succ i) + in + c 0 + +let map_set_decr f (s : My_bigint.t array) = + let l = Array.length s in + if l = 0 + then bottom + else + let r = Array.create l Int.zero in + let rec c srcindex dstindex last = + if srcindex < 0 + then begin + r.(dstindex) <- last; + array_truncate r (succ dstindex) + end + else + let v = f s.(srcindex) in + if Int.equal v last + then + c (pred srcindex) dstindex last + else begin + r.(dstindex) <- last; + c (pred srcindex) (succ dstindex) v + end + in + c (l-2) 0 (f s.(pred l)) + +let map_set_incr f (s : My_bigint.t array) = + let l = Array.length s in + if l = 0 + then bottom + else + let r = Array.create l Int.zero in + let rec c srcindex dstindex last = + if srcindex = l + then begin + r.(dstindex) <- last; + array_truncate r (succ dstindex) + end + else + let v = f s.(srcindex) in + if Int.equal v last + then + c (succ srcindex) dstindex last + else begin + r.(dstindex) <- last; + c (succ srcindex) (succ dstindex) v + end + in + c 1 0 (f s.(0)) + + (* TODO: rename to add_int *) let rec add v1 v2 = - if is_zero v1 then v2 else if is_zero v2 then v1 else match v1,v2 with Float _, _ | _, Float _ -> top + | Set [| x |], Set s | Set s, Set [| x |]-> + apply_bin_1_strict_incr Int.add x s | Set s1, Set s2 -> - inject_set (apply2 Int.add s1 s2) + apply2_n Int.add s1 s2 | Top(mn1,mx1,r1,m1), Top(mn2,mx2,r2,m2) -> let m = Int.pgcd m1 m2 in let r = Int.rem (Int.add r1 r2) m in let mn = - try - Some (Int.round_up_to_r (opt2 Int.add mn1 mn2) r m) - with Infinity -> None + try + Some (Int.round_up_to_r (opt2 Int.add mn1 mn2) r m) + with Infinity -> None in let mx = - try - Some (Int.round_down_to_r (opt2 Int.add mx1 mx2) r m) - with Infinity -> None + try + Some (Int.round_down_to_r (opt2 Int.add mx1 mx2) r m) + with Infinity -> None in inject_top mn mx r m | Set s, (Top(mn1,mx1,r1,m1) as t) | (Top(mn1,mx1,r1,m1) as t), Set s -> - if O.is_empty s + let l = Array.length s in + if l = 0 then bottom - else let mn = O.min_elt s in - let mx = O.max_elt s in - if Int.equal mn mx + else if l = 1 then (* only one element *) - let incr = Int.add mn in - let new_mn = opt1 incr mn1 in - let new_mx = opt1 incr mx1 in - let new_r = Int.pos_rem (incr r1) m1 in - check "add" new_mn new_mx new_r m1 ; - share_top new_mn new_mx new_r m1 + let mn = s.(0) in + let incr = Int.add mn in + let new_mn = opt1 incr mn1 in + let new_mx = opt1 incr mx1 in + let new_r = Int.pos_rem (incr r1) m1 in + check "add" new_mn new_mx new_r m1 ; + share_top new_mn new_mx new_r m1 else - add t (unsafe_make_top_from_set s) + add t (unsafe_make_top_from_array s) - (* TODO rename to neg_int *) + (* TODO rename to neg_int *) let neg v = match v with | Float _ -> top - | Set s -> Set (map_set Int.neg s) + | Set s -> map_set_strict_decr Int.neg s | Top(mn,mx,r,m) -> share_top - (opt1 Int.neg mx) - (opt1 Int.neg mn) - (Int.pos_rem (Int.neg r) m) - m + (opt1 Int.neg mx) + (opt1 Int.neg mn) + (Int.pos_rem (Int.neg r) m) + m let sub v1 v2 = add v1 (neg v2) @@ -1418,37 +2004,44 @@ let negative = Top(None, Some Int.minus_one,Int.zero,Int.one) let min_int s = - try - match s with - | Top (min,_,_,_) -> min - | Set s -> Some (O.min_elt s) - | Float _ -> None - with Not_found -> raise Error_Bottom + match s with + | Top (min,_,_,_) -> min + | Set s -> + if Array.length s = 0 + then raise Error_Bottom + else + Some s.(0) + | Float _ -> None + let max_int s = - try - match s with - | Top (_,max,_,_) -> max - | Set s -> Some (O.max_elt s) - | Float _ -> None - with Not_found -> raise Error_Bottom + match s with + | Top (_,max,_,_) -> max + | Set s -> + let l = Array.length s in + if l = 0 + then raise Error_Bottom + else + Some s.(pred l) + | Float _ -> None + exception No_such_element -let smallest_above min x = +let smallest_above min x = (* TODO: improve for Set *) match x with | Set s -> let r = ref None in - O.iter - (fun e -> - if Int.ge e min - then match !r with - | Some rr when Int.lt e rr -> r := Some e - | None -> r := Some e - | _ -> ()) - s; + Array.iter + (fun e -> + if Int.ge e min + then match !r with + | Some rr when Int.lt e rr -> r := Some e + | None -> r := Some e + | _ -> ()) + s; begin match !r with - None -> raise No_such_element + None -> raise No_such_element | Some r -> r end | Top(mn,mx,r,modu) -> @@ -1460,21 +2053,21 @@ else Int.round_up_to_r ~min ~r ~modu | Float _ -> raise No_such_element -let largest_below max x = +let largest_below max x = (* TODO: improve for Set *) match x with | Float _ -> raise No_such_element | Set s -> let r = ref None in - O.iter - (fun e -> - if Int.le e max - then match !r with - | Some rr when Int.gt e rr -> r := Some e - | None -> r := Some e - | _ -> ()) - s; + Array.iter + (fun e -> + if Int.le e max + then match !r with + | Some rr when Int.gt e rr -> r := Some e + | None -> r := Some e + | _ -> ()) + s; begin match !r with - None -> raise No_such_element + None -> raise No_such_element | Some r -> r end | Top(mn,mx,r,modu) -> @@ -1496,7 +2089,7 @@ f x (* [different_bits min min] returns the mask of the bits that can be different - for different numbers in the interval [min]..[max] *) + for different numbers in the interval [min]..[max] *) let different_bits min max = let x = Int.logxor min max in next_pred_power_of_two x @@ -1509,8 +2102,8 @@ let x1 = different_bits min1 max1 in let x2 = different_bits min2 max2 in (* Format.printf "pos_max_land %a %a -> %a | %a %a -> %a@." - Int.pretty min1 Int.pretty max1 Int.pretty x1 - Int.pretty min2 Int.pretty max2 Int.pretty x2;*) + Int.pretty min1 Int.pretty max1 Int.pretty x1 + Int.pretty min2 Int.pretty max2 Int.pretty x2;*) if Int.lt x1 x2 then (*let diff = Int.sub x2 x1 in*) @@ -1537,49 +2130,48 @@ else match v1, v2 with Float _, _ | _, Float _ -> top - | Set _, Set _ -> - (apply_set "|" Int.logor) v1 v2 - | Top _, _ | _, Top _ -> - ( match min_and_max v1 with - Some mn1, Some mx1 when Int.ge mn1 Int.zero -> - ( match min_and_max v2 with - Some mn2, Some mx2 when Int.ge mn2 Int.zero -> - let r = next_pred_power_of_two (Int.logor mx1 mx2) in - inject_range (Some (Int.max mn1 mn2)) (Some r) - | _ -> top ) - | _ -> top ) + | Set s1, Set s2 -> + apply2_v Int.logor s1 s2 + | Top _, _ | _, Top _ -> + ( match min_and_max v1 with + Some mn1, Some mx1 when Int.ge mn1 Int.zero -> + ( match min_and_max v2 with + Some mn2, Some mx2 when Int.ge mn2 Int.zero -> + let r = next_pred_power_of_two (Int.logor mx1 mx2) in + inject_range (Some (Int.max mn1 mn2)) (Some r) + | _ -> top ) + | _ -> top ) let contains_non_zero v = - match v with - | Top _ | Float _ -> true - | Set s -> O.exists (fun e -> not (Int.is_zero e)) s + not (is_zero v || is_bottom v) - (* TODO: rename this function to scale_int *) + (* TODO: rename this function to scale_int *) let scale f v = - let result = + if Int.is_zero f + then zero + else match v with | Float _ -> top | Top(mn1,mx1,r1,m1) -> - let incr = Int.mul f in - if Int.is_zero f - then singleton_zero - else if Int.gt f Int.zero - then - let modu = incr m1 in - share_top - (opt1 incr mn1) (opt1 incr mx1) - (Int.pos_rem (incr r1) modu) modu - else - let modu = Int.neg (incr m1) in - share_top - (opt1 incr mx1) (opt1 incr mn1) - (Int.pos_rem (incr r1) modu) modu - | Set s -> share_set (map_set (Int.mul f) s) - in - (* Format.printf "scale: %a . %a -> %a@\n" - Int.pretty f pretty v pretty result; *) - result + let incr = Int.mul f in + if Int.is_zero f + then singleton_zero + else if Int.gt f Int.zero + then + let modu = incr m1 in + share_top + (opt1 incr mn1) (opt1 incr mx1) + (Int.pos_rem (incr r1) modu) modu + else + let modu = Int.neg (incr m1) in + share_top + (opt1 incr mx1) (opt1 incr mn1) + (Int.pos_rem (incr r1) modu) modu + | Set s -> + if Int.ge f Int.zero + then apply_bin_1_strict_incr Int.mul f s + else apply_bin_1_strict_decr Int.mul f s let scale_div ~pos f v = assert (not (Int.is_zero f)); @@ -1591,41 +2183,46 @@ match v with | Top(mn1,mx1,r1,m1) -> let r, modu = - if (Int.is_zero (Int.rem m1 f)) && - ((Int.is_zero (Int.rem r1 f)) || - (min_is_lower (some_zero) mn1) || (* all positive *) - (max_is_greater (some_zero) mx1) || (* all negative *) - pos (* good div *) ) - then - let modu = Int.abs (div_f m1) in - (Int.pos_rem (div_f r1) modu), modu - else (* degeneration*) - Int.zero, Int.one + if (Int.is_zero (Int.rem m1 f)) && + ((Int.is_zero (Int.rem r1 f)) || + (min_is_lower (some_zero) mn1) || (* all positive *) + (max_is_greater (some_zero) mx1) || (* all negative *) + pos (* good div *) ) + then + let modu = Int.abs (div_f m1) in + (Int.pos_rem (div_f r1) modu), modu + else (* degeneration*) + Int.zero, Int.one in let divf_mn1 = opt1 div_f mn1 in let divf_mx1 = opt1 div_f mx1 in let mn, mx = - if Int.gt f Int.zero - then divf_mn1, divf_mx1 - else divf_mx1, divf_mn1 + if Int.gt f Int.zero + then divf_mn1, divf_mx1 + else divf_mx1, divf_mn1 in inject_top mn mx r modu - | Set s -> share_set (map_set div_f s) + | Set s -> + if Int.lt f Int.zero + then + map_set_decr div_f s + else + map_set_incr div_f s | Float _ -> top let div_set x sy = - O.fold - (fun elt acc -> + Array.fold_left + (fun acc elt -> if Int.is_zero elt then acc else join acc (scale_div ~pos:false elt x)) - sy bottom + sy (* ymin and ymax must be the same sign *) let div_range x ymn ymx = match min_and_max x with - Some xmn, Some xmx -> + | Some xmn, Some xmx -> let c1 = Int.c_div xmn ymn in let c2 = Int.c_div xmx ymn in let c3 = Int.c_div xmn ymx in @@ -1633,69 +2230,61 @@ let min = Int.min (Int.min c1 c2) (Int.min c3 c4) in let max = Int.max (Int.max c1 c2) (Int.max c3 c4) in - (* Format.printf "div: %a %a %a %a@." - Int.pretty mn Int.pretty mx Int.pretty xmn Int.pretty xmx; *) - inject_range (Some min) (Some max) + (* Format.printf "div: %a %a %a %a@." + Int.pretty mn Int.pretty mx Int.pretty xmn Int.pretty xmx; *) + inject_range (Some min) (Some max) | _ -> - CilE.warn_once "approximating result of division. Please report if it matters."; + Kernel.warning ~once:true ~current:true + "approximating result of division. Please report if it matters."; top let div x y = - let result = - (*if (intersects y negative || intersects x negative) - then ignore (CilE.warn_once "using 'round towards zero' semantics for '/', which only became specified in C99."); *) - match y with - Set sy -> - div_set x sy - | Top (Some mn,Some mx, r, modu) -> - let result_pos = - if Int.gt mx Int.zero - then - let lpos = - if Int.gt mn Int.zero - then mn - else - Int.round_up_to_r ~min:Int.one ~r ~modu - in - div_range x lpos mx - else - bottom - in - let result_neg = - if Int.lt mn Int.zero - then - let gneg = - if Int.lt mx Int.zero - then mx - else - Int.round_down_to_r ~max:Int.minus_one ~r ~modu - in - div_range x mn gneg - else - bottom - in - join result_neg result_pos - | Top _ | Float _-> - CilE.warn_once "approximating result of division. Please report if it matters."; - top - - in -(* Format.printf "div: %a / %a -> %a@\n" - pretty x pretty y pretty result; *) - result - - (* [scale_rem ~pos:false f v] is an over-approximation of the set of - elements [x mod f] for [x] in [v]. + (*if (intersects y negative || intersects x negative) then ignore + (CilE.warn_once "using 'round towards zero' semantics for '/', + which only became specified in C99."); *) + match y with + Set sy -> + div_set x sy + | Top (Some mn,Some mx, r, modu) -> + let result_pos = + if Int.gt mx Int.zero + then + let lpos = + if Int.gt mn Int.zero + then mn + else + Int.round_up_to_r ~min:Int.one ~r ~modu + in + div_range x lpos mx + else + bottom + in + let result_neg = + if Int.lt mn Int.zero + then + let gneg = + if Int.lt mx Int.zero + then mx + else + Int.round_down_to_r ~max:Int.minus_one ~r ~modu + in + div_range x mn gneg + else + bottom + in + join result_neg result_pos + | Top _ | Float _-> + Kernel.warning ~once:true ~current:true + "approximating result of division. Please report if it matters."; + top - [scale_rem ~pos:true f v] is an over-approximation of the set of - elements [x pos_rem f] for [x] in [v]. - *) +(* [scale_rem ~pos:false f v] is an over-approximation of the set of + elements [x mod f] for [x] in [v]. - (* TODO : rename to div_int *) -(*let div = - if contains_zero y + [scale_rem ~pos:true f v] is an over-approximation of the set of + elements [x pos_rem f] for [x] in [v]. *) let scale_rem ~pos f v = @@ -1711,45 +2300,45 @@ in match v with | Top(mn,mx,r,m) -> - let modu = Int.pgcd f m in - let rr = Int.pos_rem r modu in - let binf,bsup = - if pos - then (Int.round_up_to_r ~min:Int.zero ~r:rr ~modu), - (Int.round_down_to_r ~max:(Int.pred f) ~r:rr ~modu) - else - let min = - if all_positives mn then Int.zero else Int.neg (Int.pred f) - in - let max = - if all_negatives mx then Int.zero else Int.pred f - in - (Int.round_up_to_r ~min ~r:rr ~modu, - Int.round_down_to_r ~max ~r:rr ~modu) - in - let mn_rem,mx_rem = - match mn,mx with - | Some mn,Some mx -> - let mn_rem = rem_f mn in - let mx_rem = rem_f mx in - (* Format.printf "scale_rem 1:%a %a %a %b %b %a %a@." - Int.pretty mn Int.pretty mx Int.pretty f - (Int.lt mx f) (Int.gt mn (Int.neg f)) - Int.pretty mn_rem Int.pretty mx_rem;*) - if - ((Int.lt (Int.sub mx mn) f) || - ((Int.lt mx f) && (Int.gt mn (Int.neg f)))) && - (Int.le mn_rem mx_rem) - then - ( (*Format.printf "scale_rem 2:%a %a %a %a@." - Int.pretty mn Int.pretty mx Int.pretty mn_rem Int.pretty mx_rem; *) - - mn_rem,mx_rem) - else binf,bsup - | _ -> binf,bsup - in - inject_top (Some mn_rem) (Some mx_rem) rr modu - | Set s -> share_set (map_set rem_f s) + let modu = Int.pgcd f m in + let rr = Int.pos_rem r modu in + let binf,bsup = + if pos + then (Int.round_up_to_r ~min:Int.zero ~r:rr ~modu), + (Int.round_down_to_r ~max:(Int.pred f) ~r:rr ~modu) + else + let min = + if all_positives mn then Int.zero else Int.neg (Int.pred f) + in + let max = + if all_negatives mx then Int.zero else Int.pred f + in + (Int.round_up_to_r ~min ~r:rr ~modu, + Int.round_down_to_r ~max ~r:rr ~modu) + in + let mn_rem,mx_rem = + match mn,mx with + | Some mn,Some mx -> + let mn_rem = rem_f mn in + let mx_rem = rem_f mx in + (* Format.printf "scale_rem 1:%a %a %a %b %b %a %a@." + Int.pretty mn Int.pretty mx Int.pretty f + (Int.lt mx f) (Int.gt mn (Int.neg f)) + Int.pretty mn_rem Int.pretty mx_rem;*) + if + ((Int.lt (Int.sub mx mn) f) || + ((Int.lt mx f) && (Int.gt mn (Int.neg f)))) && + (Int.le mn_rem mx_rem) + then + ( (*Format.printf "scale_rem 2:%a %a %a %a@." + Int.pretty mn Int.pretty mx Int.pretty mn_rem Int.pretty mx_rem; *) + + mn_rem,mx_rem) + else binf,bsup + | _ -> binf,bsup + in + inject_top (Some mn_rem) (Some mx_rem) rr modu + | Set s -> map_set_exnsafe rem_f s | Float _ -> top @@ -1758,20 +2347,21 @@ Top _ | Float _ -> top | Set yy -> ( match x with - Set _ -> apply_set "%" Int.c_rem x y + Set xx -> apply2_notzero Int.c_rem xx yy | Float _ -> top | Top _ -> - let f y acc = - join (scale_rem ~pos:false y x) acc - in - O.fold f yy bottom) + let f acc y = + join (scale_rem ~pos:false y x) acc + in + Array.fold_left f bottom yy) module AllValueHashtbl = Hashtbl.Make (struct type t = Int.t * bool * int let equal (a,b,c:t) (d,e,f:t) = b=e && c=f && Int.equal a d - let hash (a,b,c:t) = 257 * (Hashtbl.hash b) + 17 * (Hashtbl.hash c) + Int.hash a + let hash (a,b,c:t) = + 257 * (Hashtbl.hash b) + 17 * (Hashtbl.hash c) + Int.hash a end) let all_values_table = AllValueHashtbl.create 7 @@ -1779,23 +2369,20 @@ let create_all_values ~modu ~signed ~size = let t = modu, signed, size in try - let r = AllValueHashtbl.find all_values_table t in -(* Format.printf "create_all success %a@." pretty r; *) - r + AllValueHashtbl.find all_values_table t with Not_found -> let mn, mx = if signed then - let b = Int.power_two (size-1) in - (Int.round_up_to_r ~min:(Int.neg b) ~modu ~r:Int.zero, - Int.round_down_to_r ~max:(Int.pred b) ~modu ~r:Int.zero) + let b = Int.power_two (size-1) in + (Int.round_up_to_r ~min:(Int.neg b) ~modu ~r:Int.zero, + Int.round_down_to_r ~max:(Int.pred b) ~modu ~r:Int.zero) else - let b = Int.power_two size in - Int.zero, + let b = Int.power_two size in + Int.zero, Int.round_down_to_r ~max:(Int.pred b) ~modu ~r:Int.zero in - let r = Top(Some mn, Some mx, Int.zero, modu) in + let r = inject_top (Some mn) (Some mx) Int.zero modu in AllValueHashtbl.add all_values_table t r; -(* Format.printf "create_all %a@." pretty r; *) r let cast ~size ~signed ~value = @@ -1812,40 +2399,40 @@ let modu = Int.pgcd factor m in let rr = Int.pos_rem r modu in let min_val = Some (if signed then - Int.round_up_to_r ~min:(Int.neg mask) ~r:rr ~modu + Int.round_up_to_r ~min:(Int.neg mask) ~r:rr ~modu else - Int.round_up_to_r ~min:Int.zero ~r:rr ~modu) + Int.round_up_to_r ~min:Int.zero ~r:rr ~modu) in let max_val = Some (if signed then - Int.round_down_to_r ~max:(Int.pred mask) ~r:rr ~modu + Int.round_down_to_r ~max:(Int.pred mask) ~r:rr ~modu else - Int.round_down_to_r ~max:(Int.pred factor) - ~r:rr - ~modu) + Int.round_down_to_r ~max:(Int.pred factor) + ~r:rr + ~modu) in inject_top min_val max_val rr modu in match value with | Top(Some mn,Some mx,r,m) -> - let highbits_mn,highbits_mx = - if signed then - Int.logand (Int.add mn mask) not_p_factor, - Int.logand (Int.add mx mask) not_p_factor - else - Int.logand mn not_p_factor, Int.logand mx not_p_factor - in - if Int.equal highbits_mn highbits_mx - then - if Int.is_zero highbits_mn - then value - else - let new_min = rem_f mn in - let new_r = Int.pos_rem new_min m in - inject_top (Some new_min) (Some (rem_f mx)) new_r m - else best_effort r m + let highbits_mn,highbits_mx = + if signed then + Int.logand (Int.add mn mask) not_p_factor, + Int.logand (Int.add mx mask) not_p_factor + else + Int.logand mn not_p_factor, Int.logand mx not_p_factor + in + if Int.equal highbits_mn highbits_mx + then + if Int.is_zero highbits_mn + then value + else + let new_min = rem_f mn in + let new_r = Int.pos_rem new_min m in + inject_top (Some new_min) (Some (rem_f mx)) new_r m + else best_effort r m | Top (_,_,r,m) -> - best_effort r m - | Set s -> inject_set (map_set rem_f s) + best_effort r m + | Set s -> map_set_exnsafe rem_f s | Float _ -> top in (* Format.printf "Cast with size:%d signed:%b to %a@\n" @@ -1858,58 +2445,64 @@ let cast_float v = match v with - | Float f -> + | Float f -> let b, f = Float_abstract.round_to_single_precision_float f in b, Float f | Set _ when is_zero v -> false, zero - | Set _ | Top _ -> + | Set _ | Top _ -> true, top_single_precision_float (* TODO rename to mul_int *) let rec mul v1 v2 = (* Format.printf "mul. Args: '%a' '%a'@\n" pretty v1 pretty v2; *) let result = - if is_one v1 then v2 else if is_one v2 then v1 else - match v1,v2 with - | Float _, _ | _, Float _ -> - top - | Set s1, Set s2 -> - inject_set (apply2 Int.mul s1 s2) - | Top(mn1,mx1,r1,m1), Top(mn2,mx2,r2,m2) -> - check "mul left" mn1 mx1 r1 m1; - check "mul right" mn2 mx2 r2 m2; - let mn1 = inject_min mn1 in - let mx1 = inject_max mx1 in - let mn2 = inject_min mn2 in - let mx2 = inject_max mx2 in - let a = ext_mul mn1 mn2 in - let b = ext_mul mn1 mx2 in - let c = ext_mul mx1 mn2 in - let d = ext_mul mx1 mx2 in - - let min = ext_min (ext_min a b) (ext_min c d) in - let max = ext_max (ext_max a b) (ext_max c d) in - - (* let multipl1 = Int.pgcd m1 r1 in - let multipl2 = Int.pgcd m2 r2 in - let modu1 = Int.pgcd m1 m2 in - let modu2 = Int.mul multipl1 multipl2 in - let modu = Int.ppcm modu1 modu2 in *) - let modu = Int.pgcd (Int.pgcd (Int.mul m1 m2) (Int.mul r1 m2)) (Int.mul r2 m1) - in - let r = Int.rem (Int.mul r1 r2) modu in - (* let t = Top (ext_proj min, ext_proj max, r, modu) in - Format.printf "mul. Result: '%a'@\n" pretty t; *) - inject_top (ext_proj min) (ext_proj max) r modu - | Set s, (Top(_,_,_,_) as t) | (Top(_,_,_,_) as t), Set s -> - if O.is_empty s - then bottom - else let mn = O.min_elt s in - let mx = O.max_elt s in - if Int.equal mn mx - then (* only one element *) - scale mn t - else mul t (unsafe_make_top_from_set s) + if is_one v1 then v2 + else if is_zero v2 || is_zero v1 then zero + else if is_one v2 then v1 + else + match v1,v2 with + | Float _, _ | _, Float _ -> + top + | Set s1, Set [| x |] | Set [| x |], Set s1 -> + if Int.ge x Int.zero + then apply_bin_1_strict_incr Int.mul x s1 + else apply_bin_1_strict_decr Int.mul x s1 + | Set s1, Set s2 -> + apply2_n Int.mul s1 s2 + | Top(mn1,mx1,r1,m1), Top(mn2,mx2,r2,m2) -> + check "mul left" mn1 mx1 r1 m1; + check "mul right" mn2 mx2 r2 m2; + let mn1 = inject_min mn1 in + let mx1 = inject_max mx1 in + let mn2 = inject_min mn2 in + let mx2 = inject_max mx2 in + let a = ext_mul mn1 mn2 in + let b = ext_mul mn1 mx2 in + let c = ext_mul mx1 mn2 in + let d = ext_mul mx1 mx2 in + + let min = ext_min (ext_min a b) (ext_min c d) in + let max = ext_max (ext_max a b) (ext_max c d) in + + (* let multipl1 = Int.pgcd m1 r1 in + let multipl2 = Int.pgcd m2 r2 in + let modu1 = Int.pgcd m1 m2 in + let modu2 = Int.mul multipl1 multipl2 in + let modu = Int.ppcm modu1 modu2 in *) + let modu = Int.pgcd (Int.pgcd (Int.mul m1 m2) (Int.mul r1 m2)) (Int.mul r2 m1) + in + let r = Int.rem (Int.mul r1 r2) modu in + (* let t = Top (ext_proj min, ext_proj max, r, modu) in + Format.printf "mul. Result: '%a'@\n" pretty t; *) + inject_top (ext_proj min) (ext_proj max) r modu + | Set s, (Top(_,_,_,_) as t) | (Top(_,_,_,_) as t), Set s -> + let l = Array.length s in + if l = 0 + then bottom + else if l = 1 + then (* only one element *) + scale s.(0) t + else mul t (unsafe_make_top_from_array s) in (* Format.printf "mul. result : %a@\n" pretty result;*) result @@ -1918,7 +2511,11 @@ try let min = smallest_above Int.zero y in let min = Int.shift_left Int.one min in - let max = largest_below (Int.pred size) y in + let max = match size with + | None -> + (match max_int y with Some v -> v | None -> raise No_such_element) + | Some size -> largest_below (Int.pred size) y + in let max = Int.shift_left Int.one max in let factor = inject_top (Some min) (Some max) Int.zero min in (* Format.printf "shift_left %a factor:%a@." pretty y pretty factor; *) @@ -1930,17 +2527,21 @@ let result = try let min = smallest_above Int.zero y in - let max = largest_below (Int.pred size) y in + let max = match size with + | None -> + (match max_int y with Some v -> v | None -> raise No_such_element) + | Some size -> largest_below (Int.pred size) y + in Int.fold - (fun n acc -> join acc (scale_div ~pos:true - (Int.shift_left Int.one n) x)) - ~inf:min ~sup:max ~step:Int.one - bottom + (fun n acc -> join acc (scale_div ~pos:true + (Int.shift_left Int.one n) x)) + ~inf:min ~sup:max ~step:Int.one + bottom with No_such_element -> bottom in (* Format.printf "shift_right %a >> %a -> %a@." - pretty x pretty y pretty result; *) + pretty x pretty y pretty result; *) result let interp_boolean ~contains_zero ~contains_non_zero = @@ -1950,23 +2551,12 @@ | false, true -> singleton_one | false, false -> bottom -(** return the smallest lattice element that contains all elements of [s] - that are in relation [f] ([<=],[>=],...) to [bound] *) -let filter_set f bound s = - share_set - (O.fold - (fun v acc -> - if f (Int.compare v bound) - then O.add v acc - else acc) - s - O.empty) - let filter_le_int max v = match v with | Float _ -> v | Set _ | Top _ -> narrow v (Top(None,max,Int.zero,Int.one)) + let filter_ge_int min v = match v with | Float _ -> v @@ -1990,87 +2580,90 @@ Float_abstract.Nan_or_infinite -> v1 | Float_abstract.Bottom -> bottom -let filter_le_float = filter_float Float_abstract.filter_le -let filter_ge_float = filter_float Float_abstract.filter_ge -let filter_lt_float allmodes ~typ_loc = +let filter_le_float allmodes ~typ_loc = + filter_float (Float_abstract.filter_le allmodes ~typ_loc) +let filter_ge_float allmodes ~typ_loc = + filter_float (Float_abstract.filter_ge allmodes ~typ_loc) +let filter_lt_float allmodes ~typ_loc = filter_float (Float_abstract.filter_lt allmodes ~typ_loc) -let filter_gt_float allmodes ~typ_loc = +let filter_gt_float allmodes ~typ_loc = filter_float (Float_abstract.filter_gt allmodes ~typ_loc) -let rec diff value rem = - match value,rem with - | Set s1, Set s2 -> - share_set (O.diff s1 s2) - | Set s, Top(min, max, r, modu) -> - share_set (O.filter - (fun x -> not (in_interval x min max r modu)) - s) - | Top(min, max, r, modu), Set s -> - let changed = ref false in - let new_min = match min with - | Some min when O.mem min s -> - changed := true; - Some (Int.add min modu) - | _ -> min - in - let new_max = match max with - | Some max when O.mem max s -> - changed := true; - Some (Int.sub max modu) - | _ -> max - in - if !changed then - diff (inject_top new_min new_max r modu) rem +let diff _ _ = assert false + +let diff_if_one value rem = + match rem, value with + Set [| v |], Set a -> + let index = array_mem v a in + if index >= 0 + then + let l = Array.length a in + let pl = pred l in + let r = Array.make l Int.zero in + Array.blit a 0 r 0 index; + Array.blit a (succ index) r index (pl-index); + share_array r pl else value - | Top(_min1, _max1, _r1, _modu1), Top(_min2, _max2, _r2, _modu2) -> - value (* TODO : can do better *) - | Float f1, Float f2 -> inject_float (Float_abstract.diff f1 f2) - | Float _ , _ | _, Float _ -> value - -let diff_if_one value rem = - if not (cardinal_zero_or_one rem) then - value - else diff value rem + | Set [| v |], Top (Some mn, mx, r, m) when Int.equal v mn -> + inject_top (Some (Int.add mn m)) mx r m + | Set [| v |], Top (mn, Some mx, r, m) when Int.equal v mx -> + inject_top mn (Some (Int.sub mx m)) r m + | Set [| v |], Top ((Some mn as min), (Some mx as max), r, m) when + Int.equal (Int.sub mx mn) (Int.mul m small_cardinal_Int) && + in_interval v min max r m -> + let r = ref mn in + Set + (Array.init + small_cardinal + (fun _ -> + let c = !r in + let corrected_c = + if Int.equal c v then Int.add c m else c + in + r := Int.add corrected_c m; + corrected_c)) + + | _ -> value (* TODO: more cases: Float *) let extract_bits ~start ~stop v = match v with | Set s -> - share_set - (O.fold - (fun elt acc -> O.add (Int.extract_bits ~start ~stop elt) acc) - s - O.empty) + inject_ps + (Array.fold_left + (fun acc elt -> add_ps acc (Int.extract_bits ~start ~stop elt)) + empty_ps + s) | Top _ | Float _ -> inject_top - some_zero - (Some (Int.pred (Int.power_two (Int.to_int (Int.length start stop))))) - Int.zero - Int.one + some_zero + (Some (Int.pred (Int.power_two (Int.to_int (Int.length start stop))))) + Int.zero + Int.one let b64 = Int.of_int 64 let all_values ~size v = if Int.lt b64 size then false (* values of this size cannot be enumerated anyway in C. - They may occur while initializing large blocks of arrays. + They may occur while initializing large blocks of arrays. *) else - let c = - match v with - | Float _ -> false - | Top (None,_,_,modu) | Top (_,None,_,modu) -> - Int.is_one modu - | Top (Some mn, Some mx,_,modu) -> - Int.is_one modu && - Int.le - (Int.power_two (Int.to_int size)) - (Int.succ (Int.sub mx mn)) - | Set _ -> - equal - (cast ~size ~signed:false ~value:v) - (cast ~size ~signed:false ~value:top) - in - c + match v with + | Float _ -> false + | Top (None,_,_,modu) | Top (_,None,_,modu) -> + Int.is_one modu + | Top (Some mn, Some mx,_,modu) -> + Int.is_one modu && + Int.le + (Int.power_two (Int.to_int size)) + (Int.succ (Int.sub mx mn)) + | Set s -> + let siz = Int.to_int size in + Array.length s >= 1 lsl siz && + equal + (cast ~size ~signed:false ~value:v) + (create_all_values ~size:siz ~signed:false ~modu:Int.one) + let compare_C f v1 v2 = let min1 = min_int v1 in @@ -2085,29 +2678,26 @@ let name = Int.name ^ " lattice_mod" open Structural_descr let structural_descr = - let s_int = Descr.str Int.descr in - Structure - (Sum - [| - [| pack (t_set_unchanged_compares s_int) |]; - [| Float_abstract.packed_descr |]; - [| pack (t_option s_int); - pack (t_option s_int); - Int.packed_descr; - Int.packed_descr |] - |]) - let reprs = - List.fold_left - (fun acc m -> - List.fold_left - (fun acc n -> Top (None, None, m, n) :: acc) acc Int.reprs) - [] - Int.reprs + let s_int = Descr.str Int.descr in + Structure + (Sum + [| + [| pack (t_array s_int) |]; + [| Float_abstract.packed_descr |]; + [| pack (t_option s_int); + pack (t_option s_int); + Int.packed_descr; + Int.packed_descr |] + |]) + let reprs = [ top ; bottom ] let equal = equal let compare = compare let hash = hash let pretty = pretty - let rehash = Datatype.identity + let rehash x = + match x with + | Set a -> share_array a (Array.length a) + | _ -> x let internal_pretty_code = Datatype.pp_fail let mem_project = Datatype.never_any_project let copy = Datatype.undefined @@ -2131,38 +2721,42 @@ if is_included r all then false, false, r else false, true, (narrow r all) - with + with F.Non_representable_float -> (* raised by F.to_integer *) false, true, all | Float_abstract.Nan_or_infinite -> (* raised by project_float *) true, true, all - + let of_int i = inject_singleton (Int.of_int i) let of_int64 i = inject_singleton (Int.of_int64 i) +let negbil = Int.neg Int.billion_one + let cast_int_to_float rounding_mode v = match min_and_max v with None, _ | _, None -> false (* not ok *), top_float | Some min, Some max -> ( try - set_round_nearest_even (); (* PC: Do not even ask *) - let b = F.of_float (Int.to_float min) in - let e = F.of_float (Int.to_float max) in - if rounding_mode = Float_abstract.Nearest_Even - then true (* ok *), inject_float (Float_abstract.inject b e) - else begin - let b = F.round_down b - in - let e = F.round_up e - in - true, inject_float (Float_abstract.inject b e) - end - with - F.Nan_or_infinite | F.Non_representable_float -> false, top_float) + set_round_nearest_even (); (* PC: Do not even ask *) + let b = F.of_float (Int.to_float min) in + let e = F.of_float (Int.to_float max) in + if rounding_mode = Float_abstract.Nearest_Even + || (Int.le negbil min) && (Int.le max Int.billion_one) + (* PC: No, really, don't ask *) + then true (* ok *), inject_float (Float_abstract.inject b e) + else begin + let b = F.round_down b + in + let e = F.round_up e + in + true, inject_float (Float_abstract.inject b e) + end + with + F.Nan_or_infinite | F.Non_representable_float -> false, top_float) let cast ~size ~signed ~value = - if Parameters.Overflow.get () then cast ~size ~signed ~value else value + if Kernel.Overflow.get () then cast ~size ~signed ~value else value let set_bits mn mx = match mn, mx with @@ -2170,133 +2764,169 @@ Int.logand (Int.lognot (different_bits mn mx)) mn | _ -> Int.zero +let sub_bits x = (* TODO: can be improved *) + let popcnt = Int.popcount x in + let rec aux cursor acc = + if Int.gt cursor x + then acc + else + let acc = + if Int.is_zero (Int.logand cursor x) + then acc + else O.fold (fun e acc -> O.add (Int.logor cursor e) acc) acc acc + in + aux (Int.shift_left cursor Int.one) acc + in + let o = aux Int.one o_zero in + let s = 1 lsl popcnt in + assert (O.cardinal o = s); + inject_ps (Pre_set (o, s)) + let bitwise_and ~size ~signed v1 v2 = if is_bottom v1 || is_bottom v2 then bottom else - let v1 = - match v1 with - Float _ -> create_all_values ~size ~signed ~modu:Int.one + let v1 = + match v1 with + Float _ -> create_all_values ~size ~signed ~modu:Int.one | _ -> v1 in - let v2 = + let v2 = match v2 with - Float _ -> create_all_values ~size ~signed ~modu:Int.one + Float _ -> create_all_values ~size ~signed ~modu:Int.one | _ -> v2 in match v1, v2 with Float _, _ | _, Float _ -> assert false - | Top _, _ | _, Top _ -> - let half_range = Int.power_two (pred size) in - let minint = Int.neg half_range in - let max_int_v1, max_int_v2 as max_int_v1_v2 = max_int v1, max_int v2 in - let min_int_v1, min_int_v2 as min_int_v1_v2 = min_int v1, min_int v2 in - let vmax = - match max_int_v1_v2 with - Some maxv1, Some maxv2 -> - if Int.lt maxv1 Int.zero && Int.lt maxv2 Int.zero - then begin - Some (match min_int_v1_v2 with - Some minv1, Some minv2 -> - pos_max_land minv1 maxv1 minv2 maxv2 - | _ -> assert false) - end - else - let max1 = (* improved min of maxv1 and maxv2*) - try - let bi1 = smallest_above Int.zero v1 in - let bi2 = smallest_above Int.zero v2 in - pos_max_land bi1 maxv1 bi2 maxv2 - with No_such_element -> minint - in - let max2 = (* improved min of maxv1 and altmax2*) - try - let altmax2 = - Int.add half_range (largest_below Int.minus_one v2) - in - let bi1 = smallest_above Int.zero v1 in - let bi2 = - Int.add half_range (smallest_above minint v2) - in - pos_max_land bi1 maxv1 bi2 altmax2 - with No_such_element -> minint - in - let max3 = (* improved min of maxv2 and altmax1*) - try - let altmax1 = - Int.add half_range (largest_below Int.minus_one v1) - in - let bi2 = smallest_above Int.zero v2 in - let bi1 = - Int.add half_range (smallest_above minint v1) - in - pos_max_land bi2 maxv2 bi1 altmax1 - with No_such_element -> minint - in + | Top _, other | other, Top _ -> + let half_range = Int.power_two (pred size) in + let minint = Int.neg half_range in + let max_int_v1, max_int_v2 as max_int_v1_v2 = max_int v1, max_int v2 in + let min_int_v1, min_int_v2 as min_int_v1_v2 = min_int v1, min_int v2 in + let vmax = + match max_int_v1_v2 with + Some maxv1, Some maxv2 -> + if Int.lt maxv1 Int.zero && Int.lt maxv2 Int.zero + then begin + Some (match min_int_v1_v2 with + Some minv1, Some minv2 -> + pos_max_land minv1 maxv1 minv2 maxv2 + | _ -> assert false) + end + else + let max1 = (* improved min of maxv1 and maxv2*) + try + let bi1 = smallest_above Int.zero v1 in + let bi2 = smallest_above Int.zero v2 in + pos_max_land bi1 maxv1 bi2 maxv2 + with No_such_element -> minint + in + let max2 = (* improved min of maxv1 and altmax2*) + try + let altmax2 = + Int.add half_range (largest_below Int.minus_one v2) + in + let bi1 = smallest_above Int.zero v1 in + let bi2 = + Int.add half_range (smallest_above minint v2) + in + pos_max_land bi1 maxv1 bi2 altmax2 + with No_such_element -> minint + in + let max3 = (* improved min of maxv2 and altmax1*) + try + let altmax1 = + Int.add half_range (largest_below Int.minus_one v1) + in + let bi2 = smallest_above Int.zero v2 in + let bi1 = + Int.add half_range (smallest_above minint v1) + in + pos_max_land bi2 maxv2 bi1 altmax1 + with No_such_element -> minint + in (* Format.printf "bitwise_and v1 %a v2 %a maxv1 %a maxv2 %a \ max1 max2 max3 %a %a %a@." - pretty v1 pretty v2 - Int.pretty maxv1 Int.pretty maxv2 - Int.pretty max1 Int.pretty max2 Int.pretty max3; *) - Some (Int.max max1 (Int.max max2 max3)) - | _ -> None - in - let somenegativev1 = intersects v1 negative in - let somenegativev2 = intersects v2 negative in - let vmin = - if somenegativev1 && somenegativev2 - then Some minint - else if somenegativev1 || somenegativev2 - then some_zero - else begin - let bits1 = set_bits min_int_v1 max_int_v1 in - let bits2 = set_bits min_int_v2 max_int_v2 in - let min_a = Int.logand bits1 bits2 in - let min_a = - if not signed - then - let rec find_mask x bit acc = - if Int.is_zero (Int.logand x bit) - then acc - else - find_mask - x - (Int.shift_right bit Int.one) - (Int.logor bit acc) - in - match min_int_v1_v2 with - Some m1, Some m2 -> - let mask1 = find_mask bits1 half_range Int.zero in - let min_b = Int.logand mask1 m2 in - let mask2 = find_mask bits2 half_range Int.zero in - let min_c = Int.logand mask2 m1 in -(* Format.printf - "bitwise_and v1 %a v2 %a min_b %a min_c %a@." - pretty v1 pretty v2 - Int.pretty min_b Int.pretty min_c; *) - Int.max (Int.max min_a min_b) min_c - | _ -> assert false - else min_a + pretty v1 pretty v2 + Int.pretty maxv1 Int.pretty maxv2 + Int.pretty max1 Int.pretty max2 Int.pretty max3; *) + Some (Int.max max1 (Int.max max2 max3)) + | _ -> None + in + let somenegativev1 = intersects v1 negative in + let somenegativev2 = intersects v2 negative in + let vmin = + if somenegativev1 && somenegativev2 + then Some minint + else if somenegativev1 || somenegativev2 + then some_zero + else begin + let bits1 = set_bits min_int_v1 max_int_v1 in + let bits2 = set_bits min_int_v2 max_int_v2 in + let min_a = Int.logand bits1 bits2 in + let min_a = + if not signed + then + let rec find_mask x bit acc = + if Int.is_zero (Int.logand x bit) + then acc + else + find_mask + x + (Int.shift_right bit Int.one) + (Int.logor bit acc) + in + match min_int_v1_v2 with + Some m1, Some m2 -> + let mask1 = find_mask bits1 half_range Int.zero in + let min_b = Int.logand mask1 m2 in + let mask2 = find_mask bits2 half_range Int.zero in + let min_c = Int.logand mask2 m1 in +(* Format.printf + "bitwise_and v1 %a v2 %a min_b %a min_c %a@." + pretty v1 pretty v2 + Int.pretty min_b Int.pretty min_c; *) + Int.max (Int.max min_a min_b) min_c + | _ -> assert false + else min_a + in +(* Format.printf "bitwise_and v1 %a v2 %a bits1 %a bits2 %a@." + pretty v1 pretty v2 + Int.pretty bits1 Int.pretty bits2; *) + Some min_a + end + in + let result = inject_top vmin vmax Int.zero Int.one in + ( match other with + Top _ | Float _ -> result + | Set s -> + if + array_for_all + (fun elt -> + Int.ge elt Int.zero && + Int.popcount elt <= small_cardinal_log) + s + then + let result2 = + Array.fold_left + (fun acc elt -> + join + (sub_bits elt) + acc) + bottom + s in -(* Format.printf "bitwise_and v1 %a v2 %a bits1 %a bits2 %a@." - pretty v1 pretty v2 - Int.pretty bits1 Int.pretty bits2; *) - Some min_a - end - in - inject_top vmin vmax Int.zero Int.one - | Set _, Set _ -> - (apply_set "&" Int.logand) v1 v2 + narrow result result2 + else result) + | Set s1, Set s2 -> + apply2_v Int.logand s1 s2 let tag = hash let pretty_debug = pretty let name = "ival" -(*let pretty fmt x = - Format.fprintf fmt "%a ((%d))@." pretty x (tag x)*) - (* Local Variables: -compile-command: "make -C ../.." +compile-command: "make -C ../.. byte" End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/ival.mli frama-c-20111001+nitrogen+dfsg/src/ai/ival.mli --- frama-c-20110201+carbon+dfsg/src/ai/ival.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/ival.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,13 +20,26 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. + @plugin development guide *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + exception Can_not_subdiv +external set_round_downward: unit -> unit = "set_round_downward" +external set_round_upward: unit -> unit = "set_round_upward" +external set_round_nearest_even: unit -> unit = "set_round_nearest_even" + module F : sig type t val of_float : float -> t val to_float : t -> float exception Nan_or_infinite + val equal : t -> t -> bool + val pretty : Format.formatter -> t -> unit + val pretty_normal : use_hex:bool -> Format.formatter -> t -> unit end module Float_abstract : sig @@ -37,13 +50,13 @@ type rounding_mode = Any | Nearest_Even (** [inject] creates an abstract float interval. - Does not handle infinites. - Does not enlarge subnormals to handle flush-to-zero modes *) + Does not handle infinites. + Does not enlarge subnormals to handle flush-to-zero modes *) val inject : F.t -> F.t -> t (** [inject_r] creates an abstract float interval. - It handles infinites and flush-to-zero. - the returned boolean is true if there was reduction *) + It handles infinites and flush-to-zero. + the returned boolean is true if there was reduction *) val inject_r : F.t -> F.t -> bool * t val min_and_max_float : t -> F.t * F.t @@ -69,13 +82,17 @@ val sqrt_float : rounding_mode -> t -> bool * t val minus_one_one : t val cos_float : t -> t + val cos_float_precise : t -> t + val sin_float : t -> t + val sin_float_precise : t -> t + val exp_float : t -> t val widen : t -> t -> t val equal_float_ieee : t -> t -> bool * bool val maybe_le_ieee_float : t -> t -> bool val maybe_lt_ieee_float : t -> t -> bool val diff : t -> t -> t - val filter_le : t -> t -> t - val filter_ge : t -> t -> t + val filter_le : bool -> typ_loc:Cil_types.typ -> t -> t -> t + val filter_ge : bool -> typ_loc:Cil_types.typ -> t -> t -> t val filter_lt : bool -> typ_loc:Cil_types.typ -> t -> t -> t val filter_gt : bool -> typ_loc:Cil_types.typ -> t -> t -> t end @@ -111,7 +128,7 @@ end type tt = - | Set of O.t + | Set of Abstract_interp.Int.t array | Float of Float_abstract.t | Top of Abstract_interp.Int.t option * Abstract_interp.Int.t option * Abstract_interp.Int.t * Abstract_interp.Int.t @@ -207,9 +224,11 @@ val narrow : t -> t -> t val bottom : t val top : t +val is_bottom : t -> bool val is_included : t -> t -> bool val is_included_exn : t -> t -> unit val intersects : t -> t -> bool +val partially_overlaps : Abstract_interp.Int.t -> t -> t -> bool val widen : widen_hint -> t -> t -> t val fold_enum : split_non_enumerable:int -> (t -> 'a -> 'a) -> t -> 'a -> 'a val diff : t -> t -> t @@ -253,7 +272,7 @@ val top_single_precision_float : t val project_float : t -> Float_abstract.t (** @raise F.Nan_or_infinite when the float is Nan or infinite. *) - +val force_float: Cil_types.fkind -> t -> bool * t val in_interval : Abstract_interp.Int.t -> Abstract_interp.Int.t option -> @@ -280,13 +299,14 @@ [max]. [None] means unbounded. *) val fold : (Abstract_interp.Int.t -> 'a -> 'a) -> t -> 'a -> 'a -exception Apply_Set_Exn of exn + val apply_set : - string -> - (Abstract_interp.Int.t -> Abstract_interp.Int.t -> Abstract_interp.Int.t) -> + (Abstract_interp.Int.t -> Abstract_interp.Int.t -> Abstract_interp.Int.t ) -> t -> t -> t + val apply_set_unary : - 'a -> (Abstract_interp.Int.t -> Abstract_interp.Int.t) -> t -> t + 'a -> (Abstract_interp.Int.t -> Abstract_interp.Int.t ) -> t -> t + val singleton_zero : t (** The lattice element that contains only the integer zero. *) val singleton_one : t @@ -294,7 +314,7 @@ val zero_or_one : t (** The lattice element that contains only the integers zero and one. *) val contains_non_zero : t -> bool -val subdiv_float_interval : t -> t * t +val subdiv_float_interval : size:int -> t -> t * t val scale : Abstract_interp.Int.t -> t -> t val scale_div : pos:bool -> Abstract_interp.Int.t -> t -> t val negative : t @@ -302,14 +322,17 @@ val scale_rem : pos:bool -> Abstract_interp.Int.t -> t -> t val c_rem : t -> t -> t val mul : t -> t -> t -val shift_left : size:Abstract_interp.Int.t -> t -> t -> t -val shift_right : size:Abstract_interp.Int.t -> t -> t -> t +val shift_left : size:Abstract_interp.Int.t option -> t -> t -> t +val shift_right : size:Abstract_interp.Int.t option -> t -> t -> t val interp_boolean : contains_zero:bool -> contains_non_zero:bool -> t - +(* val filter_set : (int -> bool) -> Abstract_interp.Int.t -> O.t -> t (** return the smallest lattice element that contains the elements of [s] that are in relation [f] ([<=],[>=],...) to [bound] *) +*) + +val set_of_array : Abstract_interp.Int.t array -> O.t val extract_bits : start:Abstract_interp.Int.t -> stop:Abstract_interp.Int.t -> t -> t @@ -324,8 +347,8 @@ val filter_ge : t -> t -> t val filter_lt : t -> t -> t val filter_gt : t -> t -> t -val filter_le_float : t -> t -> t -val filter_ge_float : t -> t -> t +val filter_le_float : bool -> typ_loc:Cil_types.typ -> t -> t -> t +val filter_ge_float : bool -> typ_loc:Cil_types.typ -> t -> t -> t val filter_lt_float : bool -> typ_loc:Cil_types.typ -> t -> t -> t val filter_gt_float : bool -> typ_loc:Cil_types.typ -> t -> t -> t val compare_C : @@ -337,7 +360,7 @@ Abstract_interp.Int.t option -> Abstract_interp.Int.t option -> Abstract_interp.Int.t option val scale_int64base : Int_Base.tt -> t -> t -val cast_float_to_int : +val cast_float_to_int : signed:bool -> size:int -> t -> bool * bool * t val of_int : int -> t val of_int64 : int64 -> t @@ -349,6 +372,6 @@ (* Local Variables: -compile-command: "make -C ../.." +compile-command: "make -C ../.. byte" End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/lattice_Interval_Set.ml frama-c-20111001+nitrogen+dfsg/src/ai/lattice_Interval_Set.ml --- frama-c-20110201+carbon+dfsg/src/ai/lattice_Interval_Set.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/lattice_Interval_Set.ml 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,271 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Abstract_interp + +module V = Int + +exception Error_Top +exception Error_Bottom + +module Interval = Make_Pair(V)(V) +type elt = Interval.t + +type tt = Top | Set of elt list + +type widen_hint = unit + +let bottom = Set [] +let top = Top + +let check t = + assert (match t with + | Top -> true + | Set s -> + let last_stop = ref None in + List.for_all + (fun (a,b) -> V.compare a b <= 0 && + match !last_stop with + None -> last_stop := Some b; true + | Some l -> last_stop := Some b; V.gt a l) + s) ; + t + +let hash l = match l with + Top -> 667 +| Set l -> + List.fold_left + (fun acc p -> 371 * acc + Interval.hash p) + 443 + l + +let tag = hash + +let cardinal_zero_or_one v = + match v with + Top -> false + | Set [x,y] -> V.equal x y + | Set _ -> false + +let cardinal_less_than v n = + match v with + Top -> raise Not_less_than + | Set l -> + let rec aux l card = match l with + [] -> card + | (x,y)::t -> + let nn = V.of_int n in + let card = V.add card ((V.succ (V.sub y x))) in + if V.gt card nn + then raise Not_less_than + else aux t card + in + V.to_int (aux l V.zero) + +let splitting_cardinal_less_than ~split_non_enumerable _v _n = + ignore (split_non_enumerable); + assert false + +let compare e1 e2 = + if e1 == e2 then 0 + else + match e1,e2 with + | Top,_ -> 1 + | _, Top -> -1 + | Set e1, Set e2 -> + Extlib.list_compare Interval.compare e1 e2 + +let equal e1 e2 = compare e1 e2 = 0 + +let pretty fmt t = + match t with + | Top -> Format.fprintf fmt "TopISet" + | Set s -> + if s==[] then Format.fprintf fmt "BottomISet" + else + Pretty_utils.pp_iter + ~pre:"@[{" ~suf:"}@]" ~sep:";@ " + List.iter + (fun fmt (b,e) -> + Format.fprintf fmt "[%a..%a]" V.pretty b V.pretty e) + fmt s + +let widen _wh t1 t2 = if equal t1 t2 then t1 else top + +let meet v1 v2 = + if v1 == v2 then v1 else + + (match v1,v2 with + | Top, v | v, Top -> v + | Set s1 , Set s2 -> Set ( + let rec aux acc (l1:elt list) (l2:elt list) = match l1,l2 with + | [],_|_,[] -> List.rev acc + | (((b1,e1)) as i1)::r1, + (((b2,e2)) as i2)::r2 -> + let c = V.compare b1 b2 in + if c = 0 then (* intervals start at the same value *) + let ce = V.compare e1 e2 in + if ce=0 then + aux ((b1,e1)::acc) r1 r2 (* same intervals *) + else + (* one interval is included in the other *) + let min,not_min,min_tail,not_min_tail = + if ce > 0 then i2,i1,r2,r1 else + i1,i2,r1,r2 + in + aux ((min)::acc) min_tail + ((( + (snd (min), + snd (not_min)))):: + not_min_tail) + else (* intervals start at different values *) + let _min,min_end,not_min_begin,min_tail,not_min_from = + if c > 0 + then b2,e2,b1,r2,l1 + else b1,e1,b2,r1,l2 + in + let c_min = V.compare min_end not_min_begin in + if c_min >= 0 then + (* intersecting intervals *) + aux acc + (( + (not_min_begin,min_end)) + ::min_tail) + not_min_from + else + (* disjoint intervals *) + aux acc min_tail not_min_from + in aux [] s1 s2)) + +let join v1 v2 = + if v1 == v2 then v1 else + (match v1,v2 with + | Top, _ | _, Top -> Top + | Set (s1:elt list) , Set (s2:elt list) -> + let rec aux (l1:elt list) (l2:elt list) = match l1,l2 with + | [],l|l,[] -> l + | (b1,e1)::r1,(b2,e2)::r2 -> + let c = V.compare b1 b2 in + let min_begin,min_end,min_tail,not_min_from = + if c >= 0 then b2,e2,r2,l1 + else b1,e1,r1,l2 + in + let rec enlarge_interval stop l1 look_in_me = + match look_in_me with + | [] -> stop,l1,[] + | ((b,e))::r -> + if V.compare stop (V.pred b) >= 0 + then + if V.compare stop e >= 0 + then enlarge_interval stop l1 r + else enlarge_interval e r l1 + else stop,l1,look_in_me + in + let stop,new_l1,new_l2 = + enlarge_interval + min_end + min_tail + not_min_from + in ((min_begin,stop)):: + (aux new_l1 new_l2) + in Set (aux s1 s2)) + +let inject l = (Set l) + +let inject_one ~size ~value = + (inject [value,V.add value (V.pred size)]) + +let inject_bounds min max = + if V.le min max + then inject [min,max] + else bottom + +let transform _f = (* f must be non-decreasing *) + assert false + +let apply2 _f _s1 _s2 = assert false + +let apply1 _f _s = assert false + +let is_included t1 t2 = + (t1 == t2) || + match t1,t2 with + | _,Top -> true + | Top,_ -> false + | Set s1,Set s2 -> + let rec aux l1 l2 = match l1 with + | [] -> true + | i::r -> + let rec find (b,e as arg) l = + match l with + | [] -> raise Not_found + | (b',e')::r -> + if V.compare b b' >= 0 + && V.compare e' e >= 0 + then l + else if V.compare e' b >= 0 then + raise Not_found + else find arg r + in + try aux r (find i l2) + with Not_found -> false + in + aux s1 s2 + +let link t1 t2 = join t1 t2 (* join is in fact an exact union *) + +let is_included_exn v1 v2 = + if not (is_included v1 v2) then raise Is_not_included + +let intersects t1 t2 = + let m = meet t1 t2 in + not (equal m bottom) + +let fold f v acc = + match v with + | Top -> raise Error_Top + | Set s -> + List.fold_right f s acc + +let narrow = meet + +include Datatype.Make +(struct + type t = tt + let name = Interval.name ^ " lattice_interval_set" + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum + [| [| Structural_descr.pack + (Structural_descr.t_list (Descr.str Interval.descr)) |] |]) + let reprs = Top :: List.map (fun o -> Set [ o ]) Interval.reprs + let equal = equal + let compare = compare + let hash = hash + let rehash = Datatype.identity + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = pretty + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project + end) +let () = Type.set_ml_name ty None diff -Nru frama-c-20110201+carbon+dfsg/src/ai/lattice_Interval_Set.mli frama-c-20111001+nitrogen+dfsg/src/ai/lattice_Interval_Set.mli --- frama-c-20110201+carbon+dfsg/src/ai/lattice_Interval_Set.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/lattice_Interval_Set.mli 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,37 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + +open Abstract_interp + +type elt = Int.t * Int.t +type tt = private Top | Set of elt list +include Lattice with type t = tt +val inject_one : size:Int.t -> value:Int.t -> t +val inject_bounds : Int.t -> Int.t -> t +val inject : elt list -> t +val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a +val splitting_cardinal_less_than : split_non_enumerable:int -> t -> int -> int diff -Nru frama-c-20110201+carbon+dfsg/src/ai/lattice_With_Isotropy.mli frama-c-20111001+nitrogen+dfsg/src/ai/lattice_With_Isotropy.mli --- frama-c-20110201+carbon+dfsg/src/ai/lattice_With_Isotropy.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/lattice_With_Isotropy.mli 2011-10-10 08:38:27.000000000 +0000 @@ -47,23 +47,11 @@ val singleton_zero : t val of_char : char -> t - - (** [is_included_actual_generic bases actual generic] - returns [i] if the hidden variables of [generic] can - be instanciated with an instanciation [i] so that [actual] - is included in "[i(generic)]". Raises [Is_not_included] - if the instanciation was not found. *) - val is_included_actual_generic : - Base.Set.t -> - Base.Set.t ref -> - Locations.Location_Bytes.t Base.Map.t ref -> - t -> - t -> - unit + val of_int64 : Int64.t -> t val project : t -> Locations.Location_Bytes.t - val pretty_c_assert : string -> Int.t -> Format.formatter -> t -> unit + val pretty_c_assert : (unit -> unit) -> string -> int -> Format.formatter -> t -> unit end diff -Nru frama-c-20110201+carbon+dfsg/src/ai/map_Lattice.ml frama-c-20111001+nitrogen+dfsg/src/ai/map_Lattice.ml --- frama-c-20110201+carbon+dfsg/src/ai/map_Lattice.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/map_Lattice.ml 2011-10-10 08:38:27.000000000 +0000 @@ -20,6 +20,12 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please write a .mli and + document it. *) + (* In this kind of Map, absent keys are implicitly bound to V.bottom *) open Abstract_interp @@ -38,7 +44,13 @@ (* module Top_Param = Make_Hashconsed_Lattice_Set(K) *) module M = - Hptmap.Make(K)(V)(Hptmap.Comp_unused)(struct let v = [] :: [K.null,V.top]::L.v end) + Hptmap.Make + (K) + (V) + (Hptmap.Comp_unused) + (struct let v = [] :: [K.null,V.top]::L.v end) + (struct let l = [ Ast.self ] end) + module Top_Param = Top_Param @@ -55,12 +67,12 @@ let hash v = match v with Map m -> - (* let f k v acc = - (V.hash v) + 11 * acc + 54971 * K.hash k in - M.fold f m 3647 *) - M.tag m + (* let f k v acc = + (V.hash v) + 11 * acc + 54971 * K.hash k in + M.fold f m 3647 *) + M.tag m | Top (bases, orig) -> - Origin.hash orig + (299 * (Top_Param.hash bases)) + Origin.hash orig + (299 * (Top_Param.hash bases)) let tag = hash @@ -92,16 +104,18 @@ let pretty fmt m = match m with | Top (t, a) -> - Format.fprintf fmt "{{ mix of %a. Origin: %a}}" - Top_Param.pretty t - Origin.pretty a - | Map m -> - let print_binding k v = - Format.fprintf fmt "@ %a -> %a ;" K.pretty k V.pretty v - in - Format.fprintf fmt "{{" ; - (M.iter print_binding) m; - Format.fprintf fmt "}}" + Format.fprintf fmt "@[{{ mix of %a.@ Origin: %a}}@]" + Top_Param.pretty t + Origin.pretty a + | Map m -> + Pretty_utils.pp_iter + ~pre:"@[{{ " + ~suf:" }}@]" + ~sep:";@ " + (fun pp map -> M.iter (fun k v -> pp (k, v)) map) + (fun fmt (k, v) -> Format.fprintf fmt "%a -> %a" K.pretty k V.pretty v) + fmt m + let find_or_bottom k m = try @@ -112,12 +126,12 @@ let split k m = match m with | Top (t,_) -> - if Top_Param.is_included (Top_Param.inject_singleton k) t - then V.top, m - else V.bottom, m + if Top_Param.is_included (Top_Param.inject_singleton k) t + then V.top, m + else V.bottom, m | Map m -> - find_or_bottom k m, - Map (M.remove k m) + find_or_bottom k m, + Map (M.remove k m) let inject_map m = Map m @@ -134,9 +148,9 @@ m1 == m2 || match m1, m2 with | Top (s, a), Top (s', a') -> - Top_Param.equal s s' && Origin.equal a a' + Top_Param.equal s s' && Origin.equal a a' | Map m1, Map m2 -> - M.equal m1 m2 + M.equal m1 m2 | _ -> false let compare = @@ -173,60 +187,60 @@ in fun m1 m2 -> if m1 == m2 then m1 else - let result = - match m1, m2 with - | Top(x1,a1), Top(x2,a2) -> - Top(Top_Param.join x1 x2, Origin.join a1 a2) - | Top (Top_Param.Top,_) as x, Map _ - | Map _, (Top (Top_Param.Top,_) as x) -> - x - | Top (Top_Param.Set t,a), Map m | Map m, Top (Top_Param.Set t,a) -> - inject_top_origin a - (M.fold + let result = + match m1, m2 with + | Top(x1,a1), Top(x2,a2) -> + Top(Top_Param.join x1 x2, Origin.join a1 a2) + | Top (Top_Param.Top,_) as x, Map _ + | Map _, (Top (Top_Param.Top,_) as x) -> + x + | Top (Top_Param.Set t,a), Map m | Map m, Top (Top_Param.Set t,a) -> + inject_top_origin a + (M.fold (fun k _ acc -> Top_Param.O.add k acc) m t) | Map mm1, Map mm2 -> - let result = Map (symetric_merge mm1 mm2) in - assert ( + let result = Map (symetric_merge mm1 mm2) in + assert ( - let n = succ !check_join_assert in - check_join_assert := n; - n land 63 <> 0 || - (let merge_key k v acc = - M.add k (V.join v (find_or_bottom k mm2)) acc - in - let r2 = Map (M.fold merge_key mm1 mm2) in - if equal result r2 then - true - else begin - Format.printf "Map_Lattice.join incorrect %a (%d;%x) %a (%d;%x) -> %a (%d;%x) %a (%d;%x)@." - pretty m1 (hash m1) (Extlib.address_of_value m1) - pretty m2 (hash m2) (Extlib.address_of_value m2) - pretty result (hash result) (Extlib.address_of_value result) - pretty r2 (hash r2) (Extlib.address_of_value r2); - false; - end)); - - result - in - (*Format.printf "Map_Lattice_join@\nm1=%a@\nm2=%a@\nm1Um2=%a@\n" - pretty m1 pretty m2 pretty result;*) - result + let n = succ !check_join_assert in + check_join_assert := n; + n land 63 <> 0 || + (let merge_key k v acc = + M.add k (V.join v (find_or_bottom k mm2)) acc + in + let r2 = Map (M.fold merge_key mm1 mm2) in + if equal result r2 then + true + else begin + Format.printf "Map_Lattice.join incorrect %a (%d;%x) %a (%d;%x) -> %a (%d;%x) %a (%d;%x)@." + pretty m1 (hash m1) (Extlib.address_of_value m1) + pretty m2 (hash m2) (Extlib.address_of_value m2) + pretty result (hash result) (Extlib.address_of_value result) + pretty r2 (hash r2) (Extlib.address_of_value r2); + false; + end)); + + result + in + (*Format.printf "Map_Lattice_join@\nm1=%a@\nm2=%a@\nm1Um2=%a@\n" + pretty m1 pretty m2 pretty result;*) + result let cached_fold ~cache ~temporary ~f ~projection ~joiner ~empty = let folded_f = M.cached_fold ~cache ~temporary ~f ~joiner ~empty in function m -> match m with - Top (Top_Param.Top, _) -> raise Error_Top + Top (Top_Param.Top, _) -> raise Error_Top | Top (Top_Param.Set s, _) -> - let f_base base acc = - let total_itvs = projection base in - joiner (f base total_itvs) acc - in - Top_Param.O.fold f_base s empty + let f_base base acc = + let total_itvs = projection base in + joiner (f base total_itvs) acc + in + Top_Param.O.fold f_base s empty | Map mm -> - folded_f mm + folded_f mm let map_offsets f m = match m with @@ -242,11 +256,11 @@ match m with | Top _ -> raise Not_exclusive | Map m -> - let v = find_or_bottom k m in - let map_without = M.remove k m in - if M.is_empty map_without - then v - else raise Not_exclusive + let v = find_or_bottom k m in + let map_without = M.remove k m in + if M.is_empty map_without + then v + else raise Not_exclusive exception Not_all_keys @@ -257,13 +271,13 @@ match m with | Top _ -> raise Not_all_keys | Map m -> - M.fold - (fun k v acc -> - if not (V.equal v v0) - then raise Not_all_keys - else k::acc) - m - [] + M.fold + (fun k v acc -> + if not (V.equal v v0) + then raise Not_all_keys + else k::acc) + m + [] (** Over-approximation of the filter (in the case [Top Top])*) let filter_base f m = @@ -283,35 +297,35 @@ if m1 == m2 then m1 else match m1, m2 with | Top (x1, a1), Top (x2, a2) -> - let meet_topparam = Top_Param.meet x1 x2 in - Top (meet_topparam, Origin.meet a1 a2) + let meet_topparam = Top_Param.meet x1 x2 in + Top (meet_topparam, Origin.meet a1 a2) | Top (Top_Param.Top, _), (Map _ as x) | (Map _ as x),Top (Top_Param.Top, _) -> x | Top (Top_Param.Set set, _), (Map _ as x) | (Map _ as x), Top (Top_Param.Set set, _) -> filter_base (fun v -> is_in_set ~set v) x | Map m1, Map m2 -> - let merge_key k v acc = - add_or_bottom k (V.meet v (find_or_bottom k m2)) acc - in - Map (M.fold merge_key m1 M.empty) + let merge_key k v acc = + add_or_bottom k (V.meet v (find_or_bottom k m2)) acc + in + Map (M.fold merge_key m1 M.empty) (* let narrow m1 m2 = if m1 == m2 then m1 else match m1, m2 with | Top (x1, a1), Top (x2, a2) -> - Top (Top_Param.narrow x1 x2, Origin.narrow a1 a2) + Top (Top_Param.narrow x1 x2, Origin.narrow a1 a2) | Top (Top_Param.Top, _), (Map _ as x) | (Map _ as x),Top (Top_Param.Top, _) -> x | Top (Top_Param.Set set, _), (Map _ as x) | (Map _ as x), Top (Top_Param.Set set, _) -> filter_base (fun v -> is_in_set ~set v) x | Map m1, Map m2 -> - let merge_key k v acc = - add_or_bottom k (V.narrow v (find_or_bottom k m2)) acc - in - Map (M.fold merge_key m1 M.empty) + let merge_key k v acc = + add_or_bottom k (V.narrow v (find_or_bottom k m2)) acc + in + Map (M.fold merge_key m1 M.empty) *) @@ -320,21 +334,21 @@ if m1 == m2 then m1 else match m1, m2 with | Top (x1, a1), Top (x2, a2) -> - let meet_topparam = Top_Param.meet x1 x2 in - Top (meet_topparam, origin x1 a1 x2 a2) + let meet_topparam = Top_Param.meet x1 x2 in + Top (meet_topparam, origin x1 a1 x2 a2) | Top (Top_Param.Top, _), (Map _ as x) - | (Map _ as x),Top (Top_Param.Top, _) -> x + | (Map _ as x),Top (Top_Param.Top, _) -> x | Top (Top_Param.Set set, _), (Map _ as x) - | (Map _ as x), Top (Top_Param.Set set, _) -> + | (Map _ as x), Top (Top_Param.Set set, _) -> filter_base (fun v -> is_in_set ~set v) x | Map m1, Map m2 -> - let merge_key k v acc = - add_or_bottom k (f v (find_or_bottom k m2)) acc in - Map (M.fold merge_key m1 M.empty) - in + let merge_key k v acc = + add_or_bottom k (f v (find_or_bottom k m2)) acc in + Map (M.fold merge_key m1 M.empty) + in let compute_origin_narrow x1 a1 x2 a2 = if Top_Param.equal x1 x2 then - Origin.narrow a1 a2 + Origin.narrow a1 a2 else if Top_Param.is_included x1 x2 then a1 else if Top_Param.is_included x2 x1 @@ -354,11 +368,11 @@ let widen_map = let decide k v1 v2 = let v1 = match v1 with - None -> V.bottom + None -> V.bottom | Some v1 -> v1 in let v2 = match v2 with - None -> V.bottom + None -> V.bottom | Some v2 -> v2 in V.widen (wh_k_v k) v1 v2 @@ -370,17 +384,17 @@ fun m1 m2 -> match m1, m2 with | _ , Top _ -> m2 - | Top _, _ -> assert false (* m2 should be bigger than m1 *) + | Top _, _ -> assert false (* m2 should be larger than m1 *) | Map m1, Map m2 -> - Map (widen_map m1 m2) + Map (widen_map m1 m2) let equal m1 m2 = m1 == m2 || match m1, m2 with | Top (s, a), Top (s', a') -> - Top_Param.equal s s' && Origin.equal a a' + Top_Param.equal s s' && Origin.equal a a' | Map m1, Map m2 -> - M.equal m1 m2 + M.equal m1 m2 | _ -> false let decide_fst _k _v = raise Is_not_included @@ -388,27 +402,27 @@ let decide_both = V.is_included_exn let is_included_exn = - let generic_is_included = + let map_is_included = M.generic_is_included Abstract_interp.Is_not_included - ~cache:("map_Lattice",2048) ~decide_fst ~decide_snd ~decide_both + ~cache:("map_Lattice",2048) ~decide_fst ~decide_snd ~decide_both in fun m1 m2 -> if (m1 != m2) then - (* Format.printf "begin is_included_exn map_lattice@."; *) - (match m1,m2 with + (* Format.printf "begin is_included_exn map_lattice@."; *) + (match m1,m2 with | Top (s,a), Top (s',a') -> - Top_Param.is_included_exn s s' ; - Origin.is_included_exn a a' + Top_Param.is_included_exn s s' ; + Origin.is_included_exn a a' | Map _, Top (Top_Param.Top, _) -> () | Map m, Top (Top_Param.Set set, _) -> M.iter (fun k _ -> - if not (is_in_set ~set k) - then raise Is_not_included) + if not (is_in_set ~set k) + then raise Is_not_included) m | Top _, Map _ -> raise Is_not_included - | Map m1, Map m2 -> generic_is_included m1 m2) + | Map m1, Map m2 -> map_is_included m1 m2) let check_is_included_assert = ref 0 let is_included m1 m2 = @@ -419,20 +433,20 @@ assert (let n = succ !check_is_included_assert in check_is_included_assert := n; - n land 63 <> 0 || + n land 63 <> 0 || (let mee = meet m1 m2 in let eq = equal mee m1 in if (eq <> new_) then begin - Format.printf "Map_Lattice.is_included is wrong. Args: %a(h=%d) %a(h=%d) resultnew = %b meet = %a(h=%d)@." - pretty m1 - (match m1 with Map m -> M.hash_debug m | _ -> 0) - pretty m2 - (match m2 with Map m -> M.hash_debug m | _ -> 0) - new_ - pretty mee - (match mee with Map m -> M.hash_debug m | _ -> 0); - false + Format.printf "Map_Lattice.is_included is wrong. Args: %a(h=%d) %a(h=%d) resultnew = %b meet = %a(h=%d)@." + pretty m1 + (match m1 with Map m -> M.hash_debug m | _ -> 0) + pretty m2 + (match m2 with Map m -> M.hash_debug m | _ -> 0) + new_ + pretty mee + (match mee with Map m -> M.hash_debug m | _ -> 0); + false end else true)); new_ @@ -452,8 +466,8 @@ let map = M.fold (fun k v1 acc -> - let v2 = find_or_bottom k mm2 in - let link_v = V.link v1 v2 in + let v2 = find_or_bottom k mm2 in + let link_v = V.link v1 v2 in M.add k link_v acc) mm1 mm2 @@ -462,28 +476,23 @@ exception Found_inter - let intersects m1 m2 = - let result = - match m1,m2 with + let intersects = + let map_intersects = + M.generic_symetric_existential_predicate + Found_inter + ~decide_one:(fun _ _ -> ()) + ~decide_both:(fun x y -> if V.intersects x y then raise Found_inter) + in + fun mm1 mm2 -> + match mm1, mm2 with | Top (_,_), Top (_,_) -> true | Top _, (Map _ as m) | (Map _ as m), Top _ -> not (equal m bottom) | Map m1, Map m2 -> - let intersects_in_m1 k v2 = - let v1 = find_or_bottom k m1 in - if V.intersects v1 v2 - then raise Found_inter - in try - M.iter intersects_in_m1 m2; + map_intersects m1 m2; false - with - Found_inter -> true - in - (* Format.printf "Map_Lattice.intersects: m1=%a m2=%a result=%b@\n" - pretty m1 - pretty m2 - result;*) - result + with + Found_inter -> true (** if there is only one key [k] in map [m], then returns the pair [k,v] where [v] is the value associated to [k]. @@ -492,18 +501,18 @@ match m with | Top _ -> raise Not_found | Map m -> - let elt = ref None in - let rec check_one k v already_seen = - if already_seen - then raise Not_found - else begin - elt := Some (k,v); true - end - in - ignore (M.fold check_one m false); - match !elt with - | None -> raise Not_found - | Some v -> v + let elt = ref None in + let rec check_one k v already_seen = + if already_seen + then raise Not_found + else begin + elt := Some (k,v); true + end + in + ignore (M.fold check_one m false); + match !elt with + | None -> raise Not_found + | Some v -> v (** if there is only one binding [k -> v] in map [m] (that is, only one key [k] and [cardinal_zero_or_one v]), returns the pair [k,v]. @@ -517,8 +526,8 @@ let cardinal_zero_or_one m = equal m bottom || try - let _,_ = find_lonely_binding m - in true + let _,_ = find_lonely_binding m + in true with Not_found -> false (** the cardinal of a map [m] is the sum of the cardinals of the @@ -527,112 +536,112 @@ match m with | Top _ -> raise Not_less_than | Map m -> - M.fold - (fun _base v card -> card + V.cardinal_less_than v (n-card)) - m - 0 + M.fold + (fun _base v card -> card + V.cardinal_less_than v (n-card)) + m + 0 let splitting_cardinal_less_than ~split_non_enumerable m n = match m with | Top _ -> raise Not_less_than | Map m -> - M.fold - (fun _base v card -> - card + - (V.splitting_cardinal_less_than ~split_non_enumerable - v (n-card) )) - m - 0 + M.fold + (fun _base v card -> + card + + (V.splitting_cardinal_less_than ~split_non_enumerable + v (n-card) )) + m + 0 let diff_if_one m1 m2 = match m1 with | Top _ -> m1 | Map mm1 -> - try - let k2,v2 = find_lonely_binding m2 in - let v1 = find_or_bottom k2 mm1 in - let v = V.diff_if_one v1 v2 in - Map (add_or_bottom k2 v mm1) - with Not_found -> m1 + try + let k2,v2 = find_lonely_binding m2 in + let v1 = find_or_bottom k2 mm1 in + let v = V.diff_if_one v1 v2 in + Map (add_or_bottom k2 v mm1) + with Not_found -> m1 let diff m1 m2 = match m1, m2 with | Top _, _ | _, Top _ -> m1 | Map mm1, Map mm2 -> - let result = - M.fold - (fun k v1 acc -> - let dif = - try - let v2 = M.find k mm2 in - (V.diff v1 v2) - with Not_found -> v1 - in - add_or_bottom k dif acc) - mm1 - M.empty - in - Map result + let result = + M.fold + (fun k v1 acc -> + let dif = + try + let v2 = M.find k mm2 in + (V.diff v1 v2) + with Not_found -> v1 + in + add_or_bottom k dif acc) + mm1 + M.empty + in + Map result let map_i f m = match m with | Top _ -> top | Map m -> - M.fold - (fun k vl acc -> - join acc (f k vl)) - m - bottom + M.fold + (fun k vl acc -> + join acc (f k vl)) + m + bottom let fold_bases f m acc = match m with Top(Top_Param.Set t, _) -> - let acc = if Null_Behavior.zone then acc else f K.null acc in - (Top_Param.O.fold f t acc) + let acc = if Null_Behavior.zone then acc else f K.null acc in + (Top_Param.O.fold f t acc) | Top(Top_Param.Top, _) -> - raise Error_Top + raise Error_Top | Map m -> - M.fold (fun k _ acc -> f k acc) m acc + M.fold (fun k _ acc -> f k acc) m acc (** [fold_i f m acc] folds [f] on the bindings in [m]. @raise Error_Top if [m] is too imprecise for folding. *) let fold_i f m acc = match m with Top(Top_Param.Set _, _) -> - (* In this function, - we refuse to iterate on the bases of a value Top(Top_Param.Set _,_) - *) - raise Error_Top + (* In this function, + we refuse to iterate on the bases of a value Top(Top_Param.Set _,_) + *) + raise Error_Top | Top(Top_Param.Top, _) -> - raise Error_Top + raise Error_Top | Map m -> - M.fold f m acc + M.fold f m acc let fold_topset_ok f m acc = match m with Top(Top_Param.Set t, _) -> - let acc = if Null_Behavior.zone then acc else f K.null V.top acc in - Top_Param.O.fold - (fun x acc -> f x V.top acc) - t - acc + let acc = if Null_Behavior.zone then acc else f K.null V.top acc in + Top_Param.O.fold + (fun x acc -> f x V.top acc) + t + acc | Top(Top_Param.Top, _) -> - raise Error_Top + raise Error_Top | Map m -> - M.fold f m acc + M.fold f m acc let fold_enum ~split_non_enumerable f m acc = match m with | Top _ -> raise Error_Top | Map m -> try - M.fold - (fun k vl acc -> - let g one_ival acc = + M.fold + (fun k vl acc -> + let g one_ival acc = let one_loc = inject k one_ival in f one_loc acc - in - V.fold_enum ~split_non_enumerable g vl acc) + in + V.fold_enum ~split_non_enumerable g vl acc) m acc with V.Error_Top -> raise Error_Top @@ -642,55 +651,28 @@ include Datatype.Make_with_collections (struct - type t = tt - let name = M.name ^ " map_lattice" - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum - [| [| Top_Param.packed_descr; Structural_descr.p_abstract |]; - [| M.packed_descr |] |]) - let reprs = List.map (fun m -> Map m) M.reprs - let equal = equal - let compare = compare - let hash = hash - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.pp_fail - let pretty = pretty - let mem_project = Datatype.never_any_project - let varname = Datatype.undefined + type t = tt + let name = M.name ^ " map_lattice" + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum + [| [| Top_Param.packed_descr; Structural_descr.p_abstract |]; + [| M.packed_descr |] |]) + let reprs = List.map (fun m -> Map m) M.reprs + let equal = equal + let compare = compare + let hash = hash + let rehash = Datatype.identity + let copy = Datatype.undefined + let internal_pretty_code = Datatype.pp_fail + let pretty = pretty + let mem_project = Datatype.never_any_project + let varname = Datatype.undefined end) end (* - module Trivial_Lattice = struct - type t = bool - let pretty fmt v = - match v with - | false -> Format.fprintf fmt "TTOP" - | true -> Format.fprintf fmt "TBOTTOM" - - let top = false - let bottom = true - - let meet = (||) - - let join = (&&) - - let intersects t1 t2 = not (meet t1 t2) - - let is_included t1 t2 = (join t1 t2) = t2 - - let widen wh t1 t2 = if t1 = t2 then t1 else false - - exception Error_Bottom - exception Error_Top - - end - *) - -(* Local Variables: compile-command: "make -C ../.." End: diff -Nru frama-c-20110201+carbon+dfsg/src/ai/my_bigint.ml frama-c-20111001+nitrogen+dfsg/src/ai/my_bigint.ml --- frama-c-20110201+carbon+dfsg/src/ai/my_bigint.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/my_bigint.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,231 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(* - -ledit ocaml nums.cma - -setenv OCAMLRUNPARAM bt - -ocamlc -g -o test_big_int nums.cma my_big_int.ml -./test_big_int - -*) - -include Big_int - -let compare = compare_big_int - -(* Nombre de bits significatifs dans un "word" de "Big_int" *) -let nb_digits_of_big_int = - let r = - let rec nb_digits y = - if 1 = Big_int.num_digits_big_int (Big_int.power_int_positive_int 2 y) - then nb_digits (y + 1) - else y - in nb_digits 1 - in r - -let base = Big_int.power_int_positive_int 2 nb_digits_of_big_int -let base16bits = Big_int.power_int_positive_int 2 16 - - -(* Soit X tel que x = let f a x =(a * base) + x in List.fold_left f 0 X, - * Y tel que y = let f a y =(a * base) + y in List.fold_left f 0 Y, - * alors map2_base base op x y = let f a x y =(a * base) + (op x y) in List.fold_left f 0 X Y -*) -let map2_base b op x y = - let rec map2_base_rec a x y = - let (qx, mx) = Big_int.quomod_big_int x b - and (qy, my) = Big_int.quomod_big_int y b - in let res_m = op mx my - and res_q = - if (Big_int.eq_big_int Big_int.zero_big_int qx) - && (Big_int.eq_big_int Big_int.zero_big_int qy) - then a - else map2_base_rec a qx qy - in Big_int.add_big_int (Big_int.mult_big_int res_q b) res_m - in map2_base_rec Big_int.zero_big_int x y - - -let bitwise_op_positive_big_int op x y = - assert (Big_int.ge_big_int x Big_int.zero_big_int); - assert (Big_int.ge_big_int y Big_int.zero_big_int); - let g = - let f u v = assert(Big_int.is_int_big_int u) ; - assert(Big_int.is_int_big_int v) ; - let r = op (Big_int.int_of_big_int u) (Big_int.int_of_big_int v) - in Big_int.big_int_of_int (r) - in map2_base base16bits f - in let r = map2_base base g x y - in assert (Big_int.ge_big_int r Big_int.zero_big_int); - r - - -let lnot_big_int w = Big_int.minus_big_int (Big_int.succ_big_int w) - -let shift_left_big_int x y = (* idem multiplication *) - Big_int.mult_big_int x (Big_int.power_int_positive_big_int 2 y) - -let shift_right_big_int x y = (* idem division rounding to -oo *) - Big_int.div_big_int x (Big_int.power_int_positive_big_int 2 y) - -let power_two = - let h = Hashtbl.create 7 in - fun k -> - try - Hashtbl.find h k - with Not_found -> - let p = Big_int.power_int_positive_int 2 k in - Hashtbl.add h k p; - p - -let two_power y = - try - let k = Big_int.int_of_big_int y in - power_two k - with Failure _ -> assert false - -let log_shift_right_big_int x y = (* no meaning for negative value of x *) - if (Big_int.lt_big_int x Big_int.zero_big_int) - then raise (Invalid_argument "log_shift_right_big_int") - else shift_right_big_int x y - -let bitwise_op_big_int op x y = - let (positive_x, op_sx) = - if Big_int.gt_big_int Big_int.zero_big_int x - then (lnot_big_int x, (fun u v -> op (lnot u) v)) - else (x, op) - in let (positive_y, op_sx_sy) = - if Big_int.gt_big_int Big_int.zero_big_int y - then (lnot_big_int y, (fun u v -> op_sx u (lnot v))) - else (y, op_sx) - in let (positive_op_map, op_map) = - if 0 = (op_sx_sy 0 0) - then (op_sx_sy, (fun w -> w)) - else ((fun u v -> lnot (op_sx_sy u v)), lnot_big_int) - in op_map (bitwise_op_positive_big_int positive_op_map positive_x positive_y) - - -let land_big_int = bitwise_op_big_int (land) -let lor_big_int = bitwise_op_big_int (lor) -let lxor_big_int = bitwise_op_big_int (lxor) - -(* Get the value encoded from the 'first' to 'last' bit of 'x' : - Shift right 'x' and apply a mask on it. - The result is: div (mod x (2**(last+1))) (2**first) *) -let bitwise_extraction first_bit last_bit x = - assert (first_bit <= last_bit);(* first_bit <= last_bit *) - assert (first_bit >= 0); (* first_bit >= 0 *) - let q = Big_int.div_big_int x (Big_int.power_int_positive_int 2 first_bit) - in let r = Big_int.mod_big_int q (Big_int.power_int_positive_int 2 (1 + last_bit - first_bit)) - in r - -(* Idem bitwise_extraction except it interprets the 'last' bit of 'x' as a bit of sign. - Get the value encoded from the 'first' to 'last' bit of 'x' where the 'last' bit is a sign bit. *) -let bitwise_signed_extraction first_bit last_bit x = - let r = bitwise_extraction first_bit last_bit x - in if Big_int.ge_big_int r (Big_int.power_int_positive_int 2 (last_bit - first_bit)) - then (* last bit of x is set to 1, the result have to be a negative value *) - (let r = lor_big_int r (Big_int.pred_big_int (Big_int.power_int_positive_int 2 (1 + last_bit - first_bit))) - in assert (Big_int.lt_big_int r Big_int.zero_big_int); r) - else r - -(******************** TEST ******************) -(* test par iterations sur les entiers signés se codant sur "nb_bits+1" bits - que l'on décalera "nb_declages" fois - de "declage" bits *) -(* -let test_bitwise_op_big_int nb_bits nb_declages declage= - let test_int_bitwise_op_big_int x y op = - let int_bitwise_op_big_int (op, txt) x y = - (* Printf.printf "----\n<-int_bitwise_op_big_int: %s %s %s = %s\n" - (string_of_int x) txt (string_of_int y) (string_of_int (op x y)) ; *) - let r = bitwise_op_big_int op (Big_int.big_int_of_int x) (Big_int.big_int_of_int y) - in (* Printf.printf "->int_bitwise_op_big_int= %s\n" (Big_int.string_of_big_int r) ; *) - assert (Big_int.eq_big_int r (Big_int.big_int_of_int (op x y))) ; - in int_bitwise_op_big_int op x y ; - int_bitwise_op_big_int op x (-y) ; - int_bitwise_op_big_int op (-x) y ; - int_bitwise_op_big_int op (-x) (-y) - in (* Vérification sur des "Big_int" que (X XOR -1) = NOT(X) *) - Printf.printf "Test...\n" ; - for i = 0 to ((1 lsl nb_bits) - 1) do - let u = ref (Big_int.big_int_of_int i) - in for k = 0 to nb_declages do - let test_xor w = - let r = bitwise_op_big_int (lxor) w (Big_int.big_int_of_int (-1)) - in assert (Big_int.eq_big_int r (Big_int.minus_big_int (Big_int.succ_big_int w))) - in test_xor !u ; - test_xor (Big_int.minus_big_int !u); - u := Big_int.add_big_int !u (Big_int.mult_big_int !u (Big_int.power_int_positive_int 2 declage)) ; - u := Big_int.add_big_int !u (Big_int.mult_big_int !u (Big_int.power_int_positive_int 2 declage)) ; - u := Big_int.add_big_int !u (Big_int.mult_big_int !u (Big_int.power_int_positive_int 2 declage)) ; - done - done ; - (* Vérification sur des "int" des opérations AND, OR et XOR *) - for i = 0 to ((1 lsl nb_bits) - 1) do - for j = 0 to ((1 lsl nb_bits) - 1) do - let (u,v) = (ref i, ref j) - in for k = 0 to nb_declages do - List.iter (test_int_bitwise_op_big_int !u !v) [((land), " AND "); ((lor)," OR ");((lxor)," XOR ")] ; - u := (!u lsl declage) ; - v := (!v lsl declage) ; - done - done - done -;; -*) - -(* -open Test_big_int;; -print_string ((Big_int.string_of_big_int (bitwise_op_big_int (lor) (Big_int.big_int_of_int (-1)) (Big_int.big_int_of_int (0))))^ "\n") ;; - -(* -test_bitwise_op_big_int 4 5 7;; -test_bitwise_op_big_int 3 7 9;; -*) -(* Conversion de x:Big_int dans une base *) -let decompose x base = - let rec decompose_rec r x = - let (qx, mx) = Big_int.quomod_big_int x base - in if Big_int.eq_big_int qx Big_int.zero_big_int - then (mx::r) - else decompose_rec (mx::r) qx - in decompose_rec [] x -;; - - -(* Conversion inverse *) -let recompose x base = - let f x y = Big_int.add_big_int (Big_int.mult_big_int y base) x - in List.fold_left f Big_int.zero_big_int x -;; - - -*) - -(* -let () = print_endline - (string_of_big_int - (land_big_int (big_int_of_int 31) (big_int_of_int (-16)))) -*) diff -Nru frama-c-20110201+carbon+dfsg/src/ai/origin.ml frama-c-20111001+nitrogen+dfsg/src/ai/origin.ml --- frama-c-20110201+carbon+dfsg/src/ai/origin.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/origin.ml 2011-10-10 08:38:27.000000000 +0000 @@ -72,20 +72,20 @@ let pretty fmt o = match o with | Unknown -> - Format.fprintf fmt "@[Unknown@]" + Format.fprintf fmt "Unknown" | Misalign_read o -> - Format.fprintf fmt "@[Misaligned@ %a@]" - LocationSetLattice.pretty o + Format.fprintf fmt "Misaligned@ %a" + LocationSetLattice.pretty o | Leaf o -> - Format.fprintf fmt "@[Library function@ %a@]" - LocationSetLattice.pretty o + Format.fprintf fmt "Library function@ %a" + LocationSetLattice.pretty o | Merge o -> - Format.fprintf fmt "@[Merge@ %a@]" - LocationSetLattice.pretty o + Format.fprintf fmt "Merge@ %a" + LocationSetLattice.pretty o | Arith o -> - Format.fprintf fmt "@[Arithmetic@ %a@]" - LocationSetLattice.pretty o - | Well -> Format.fprintf fmt "@[Well@]" + Format.fprintf fmt "Arithmetic@ %a" + LocationSetLattice.pretty o + | Well -> Format.fprintf fmt "Well" let hash o = match o with | Misalign_read o -> @@ -131,16 +131,16 @@ | Unknown,_ | _, Unknown -> Unknown | Well,_ | _ , Well -> Well | Misalign_read o1, Misalign_read o2 -> - Misalign_read(LocationSetLattice.join o1 o2) + Misalign_read(LocationSetLattice.join o1 o2) | _, (Misalign_read _ as m) | (Misalign_read _ as m), _ -> m | Leaf o1, Leaf o2 -> - Leaf(LocationSetLattice.join o1 o2) + Leaf(LocationSetLattice.join o1 o2) | (Leaf _ as m), _ | _, (Leaf _ as m) -> m | Merge o1, Merge o2 -> - Merge(LocationSetLattice.join o1 o2) + Merge(LocationSetLattice.join o1 o2) | (Merge _ as m), _ | _, (Merge _ as m) -> m | Arith o1, Arith o2 -> - Arith(LocationSetLattice.join o1 o2) + Arith(LocationSetLattice.join o1 o2) (* | (Arith _ as m), _ | _, (Arith _ as m) -> m *) in (* Format.printf "Origin.join %a %a -> %a@." pretty o1 pretty o2 pretty result; @@ -153,16 +153,16 @@ else match o1, o2 with | Arith o1, Arith o2 -> - Arith(LocationSetLattice.meet o1 o2) + Arith(LocationSetLattice.meet o1 o2) | (Arith _ as m), _ | _, (Arith _ as m) -> m | Merge o1, Merge o2 -> - Merge(LocationSetLattice.meet o1 o2) + Merge(LocationSetLattice.meet o1 o2) | (Merge _ as m), _ | _, (Merge _ as m) -> m | Leaf o1, Leaf o2 -> - Leaf(LocationSetLattice.meet o1 o2) + Leaf(LocationSetLattice.meet o1 o2) | (Leaf _ as m), _ | _, (Leaf _ as m) -> m | Misalign_read o1, Misalign_read o2 -> - Misalign_read(LocationSetLattice.meet o1 o2) + Misalign_read(LocationSetLattice.meet o1 o2) | _, (Misalign_read _ as m) | (Misalign_read _ as m), _ -> m | Well, Well -> Well | Well,m | m, Well -> m diff -Nru frama-c-20110201+carbon+dfsg/src/ai/origin.mli frama-c-20111001+nitrogen+dfsg/src/ai/origin.mli --- frama-c-20110201+carbon+dfsg/src/ai/origin.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/ai/origin.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + type origin = | Misalign_read of Abstract_interp.LocationSetLattice.t | Leaf of Abstract_interp.LocationSetLattice.t diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/abstract_ai.ml frama-c-20111001+nitrogen+dfsg/src/aorai/abstract_ai.ml --- frama-c-20110201+carbon+dfsg/src/aorai/abstract_ai.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/abstract_ai.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -49,7 +51,8 @@ This vistor use mainly 2 sub-functions (propagates_pre and propagates_post) that implement respectively forward and backward treatment. *) -class visit_propagating_pre_post_constraints (auto:Promelaast.buchautomata) = +class visit_propagating_pre_post_constraints + (auto:Promelaast.typed_automaton) = (***************************************************************************) (* For the two pass *) (* *) @@ -93,161 +96,149 @@ let rec propagates_pre stmt_l (pre_st,pre_tr) (*lastFuncStatusSet*) = (** This function returns the curent pre of a statement or an empty - pre if no specification exists *) - let get_pre_of stmt_ref = + pre if no specification exists *) + let get_pre_of stmt = try - let pre_st,pre_tr,_,_ = Hashtbl.find stmts_spec stmt_ref in - pre_st,pre_tr + let pre_st,pre_tr,_,_ = Hashtbl.find stmts_spec stmt in + pre_st,pre_tr with - | Not_found -> mk_empty_pre_or_post() + | Not_found -> mk_empty_pre_or_post() in - (** This function makes an OR filter between the given pre and the old pre of the given stmt - The result is storing as the new pre of the given stmt. *) - let update_stmt_pre stmt_ref pre = + (** This function makes an OR filter between the given pre and + the old pre of the given stmt. The result is stored as the new + pre of the given stmt. *) + let update_stmt_pre stmt pre = try - let old_pre_st,old_pre_tr,post_st,post_tr = Hashtbl.find stmts_spec stmt_ref in - let n_pre_st,n_pre_tr = double_bool_array_or (old_pre_st,old_pre_tr) pre in - Hashtbl.replace stmts_spec stmt_ref (n_pre_st,n_pre_tr,post_st,post_tr) + let old_pre_st,old_pre_tr,post_st,post_tr = + Hashtbl.find stmts_spec stmt + in + let n_pre_st,n_pre_tr = + double_bool_array_or (old_pre_st,old_pre_tr) pre + in + Hashtbl.replace stmts_spec stmt (n_pre_st,n_pre_tr,post_st,post_tr) with - | _ -> - let n_pre_st,n_pre_tr = pre in - Hashtbl.replace stmts_spec stmt_ref (n_pre_st,n_pre_tr,n_pre_st,n_pre_tr) + | _ -> + let n_pre_st,n_pre_tr = pre in + Hashtbl.replace stmts_spec stmt + (n_pre_st,n_pre_tr,n_pre_st,n_pre_tr) in - - - (** This function returns the current pre of the given statement. - WARNING ! - Side effects of this function : - * If the statement is in stmts_to_compute_one_more_time then it is removed - * The pre of the current stmt is updated according to the current pre_st and pre_tr + WARNING ! + Side effects of this function : + * If the statement is in stmts_to_compute_one_more_time then it is removed + * The pre of the current stmt is updated according to the current pre_st and pre_tr *) - let get_stmts_pre stmt_ref = + let get_stmts_pre stmt = (* If this statement is annotated to be computed again then we remove its annotation. *) - Hashtbl.remove stmts_to_compute_one_more_time stmt_ref; + Hashtbl.remove stmts_to_compute_one_more_time stmt; (* Registering the new specification. *) - update_stmt_pre stmt_ref (pre_st,pre_tr); - let pre = get_pre_of stmt_ref in + update_stmt_pre stmt (pre_st,pre_tr); + let pre = get_pre_of stmt in pre in - - - - match stmt_l with | [] -> - (pre_st,pre_tr) (*lastFuncStatusSet*) + (pre_st,pre_tr) (*lastFuncStatusSet*) | ({skind=Instr(Call(_,{enode = (Lval(Var(vi),_)| CastE(_,{enode = Lval (Var vi,_)})) },_,_))} as stmt)::l -> - if (Data_for_aorai.isIgnoredFunction vi.vname) then - begin - (* Updating pre-condition with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in - - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,pre_st,pre_tr); - - (* Computes next statements specification *) - propagates_pre l (pre_st,pre_tr) (*lastFuncStatusSet*) - end - else - begin - (* Updating pre-condition with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in - - (*== add new status call for stmt ==*) + if (Data_for_aorai.isIgnoredFunction vi.vname) then + begin + (* Updating pre-condition with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in + + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,pre_st,pre_tr); + + (* Computes next statements specification *) + propagates_pre l (pre_st,pre_tr) (*lastFuncStatusSet*) + end + else + begin + (* Updating pre-condition with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in + (*== add new status call for stmt ==*) (* If the statement is unreachable then we skip the call *) - if (double_bool_array_eq (pre_st,pre_tr) (mk_empty_pre_or_post())) then + if double_bool_array_eq (pre_st,pre_tr) (mk_empty_pre_or_post()) + then begin - (* When stmt=call => the spec has to be memorized as pre of the call *) - Data_for_aorai.set_func_pre_call !currentFuncName stmt.sid (pre_st,pre_tr); + (* When stmt=call => + the spec has to be memorized as pre of the call *) + Data_for_aorai.set_func_pre_call + !currentFuncName stmt.sid (pre_st,pre_tr); propagates_pre l (pre_st,pre_tr) end else begin - + let kf = Globals.Functions.get vi in (* Simulating crossing transition *) - let pre_call=Aorai_utils.get_next vi.vname Promelaast.Call pre_st in - - (* When stmt=call => the spec has to be memorized as pre of the call *) - Data_for_aorai.set_func_pre_call !currentFuncName stmt.sid pre_call; - - - - (* Registering call context for future reinforcement of pre-condition *) + let pre_call = + Aorai_utils.get_next kf Promelaast.Call pre_st + in + (* When stmt=call => + the spec has to be memorized as pre of the call *) + Data_for_aorai.set_func_pre_call + !currentFuncName stmt.sid pre_call; + (* Registering call context for future reinforcement + of pre-condition *) let (pre_usecase_st,pre_usecase_tr) = if Hashtbl.mem functions_pre_usecase vi.vname - then double_bool_array_or (Hashtbl.find functions_pre_usecase vi.vname) pre_call + then double_bool_array_or + (Hashtbl.find functions_pre_usecase vi.vname) pre_call else pre_call in - Hashtbl.replace functions_pre_usecase vi.vname (pre_usecase_st,pre_usecase_tr); - - - (* From now, pre-condition is the set of configurations from which - the operation is callable according to its post-condition. *) - let (post_call_st,post_call_tr) = (Data_for_aorai.get_func_post vi.vname) in - - (* Add the specification of the current stmt in the hashtbl. *) - (* Note that we use the pre of the statement and not the one computed for the called function. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,post_call_st,post_call_tr); - + Hashtbl.replace functions_pre_usecase vi.vname + (pre_usecase_st,pre_usecase_tr); + (* From now, pre-condition is the set of configurations + from which the operation is callable according + to its post-condition. *) + let (post_call_st,post_call_tr) = + Data_for_aorai.get_func_post vi.vname + in + (* Add the specification of the current stmt in the hashtbl. + Note that we use the pre of the statement and not the + one computed for the called function. *) + Hashtbl.replace stmts_spec + stmt (pre_st,pre_tr,post_call_st,post_call_tr); (* Computes next statements specification *) - propagates_pre l (post_call_st,post_call_tr) (*(Data_for_aorai.NamedFunctStatusSet.singleton ({id = vi.name;status=Promelaast.Return}))*) + propagates_pre l (post_call_st,post_call_tr) end end - - - | {skind=Instr(Call(_,_,_,_))}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n"; -(* Format.printf "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n";*) -(* assert false *) - - - + Aorai_option.fatal "Indirect calls are not supported yet" | ({skind=Instr (_)} as stmt)::l -> - (* Updating pre-condition with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in - - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,pre_st,pre_tr); - - (* Computes next statements specification *) - propagates_pre l (pre_st,pre_tr) (*lastFuncStatusSet*) - + (* Updating pre-condition with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,pre_st,pre_tr); + (* Computes next statements specification *) + propagates_pre l (pre_st,pre_tr) (*lastFuncStatusSet*) | ({skind=Block(b)} as stmt)::l -> - (* Updating pre-condition with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in - + (* Updating pre-condition with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in (* Propagation into block *) - let (post_st,post_tr) (*lastFuncStatusSet*)= (propagates_pre b.bstmts (pre_st,pre_tr) (*lastFuncStatusSet*)) in - - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,post_st,post_tr); - + let (post_st,post_tr) = (propagates_pre b.bstmts (pre_st,pre_tr)) in + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); (* Computes next statements specification *) - propagates_pre l (post_st,post_tr) (*lastFuncStatusSet*) - - - + propagates_pre l (post_st,post_tr) | ({skind=If(_,b1,b2,_)} as stmt)::l -> - (* Updating pre-condition with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in + (* Updating pre-condition with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in - (* Constraints propagation into branches. *) - let post_block1 (*lastFuncStatusSet1*)= propagates_pre b1.bstmts (pre_st,pre_tr) (*lastFuncStatusSet*) in - let post_block2 (*lastFuncStatusSet2*)= propagates_pre b2.bstmts (pre_st,pre_tr) (*lastFuncStatusSet*) in + (* Constraints propagation into branches. *) + let post_block1 (*lastFuncStatusSet1*)= propagates_pre b1.bstmts (pre_st,pre_tr) (*lastFuncStatusSet*) in + let post_block2 (*lastFuncStatusSet2*)= propagates_pre b2.bstmts (pre_st,pre_tr) (*lastFuncStatusSet*) in (* ====== Attention traitement necessaire pour le lastFunct en faisant le regroupement!!!*) (* ====== Attention traitement necessaire pour le lastFunct en faisant le regroupement!!!*) @@ -258,172 +249,173 @@ - (* The new post-condition is the disjunction of branches post-conditions *) - let (post_st,post_tr) = double_bool_array_or post_block1 post_block2 in + (* The new post-condition is the disjunction of branches post-conditions *) + let (post_st,post_tr) = double_bool_array_or post_block1 post_block2 in - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.add stmts_spec (ref stmt) (pre_st,pre_tr,post_st,post_tr); + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.add stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); - (* Computes next statements specification *) - propagates_pre l (post_st,post_tr) (*lastFuncStatusSet*) + (* Computes next statements specification *) + propagates_pre l (post_st,post_tr) (*lastFuncStatusSet*) | ({skind=Return (_,_)} as stmt)::l -> - (* Updating pre-condition and current result with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in - propagation_result:= (pre_st,pre_tr); - - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,pre_st,pre_tr); - - (* A pre-treatment of frama-C has to put the return statement at the - end of the function. *) - if l<>[] then assert false; + (* Updating pre-condition and current result with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in + propagation_result:= (pre_st,pre_tr); + + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,pre_st,pre_tr); + + (* A pre-treatment of frama-C has to put the return statement at the + end of the function. *) + if l<>[] then assert false; - (* Return the post-condition of the current function *) - !propagation_result (*lastFuncStatusSet*) + (* Return the post-condition of the current function *) + !propagation_result (*lastFuncStatusSet*) | ({skind=Goto(stmt_ref,_)} as stmt)::stmt_l -> - (* Updating pre-condition with previous information *) - let pre_st,pre_tr = get_stmts_pre (ref stmt) in + (* Updating pre-condition with previous information *) + let pre_st,pre_tr = get_stmts_pre stmt in - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,pre_st,pre_tr); + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,pre_st,pre_tr); - (* Modifing specification of pointed statement and registering it to be computed *) - (* If the statement has not yet been specified *) - let ref_pre_st,ref_pre_tr = get_pre_of (stmt_ref) in - - if not (double_bool_array_eq (ref_pre_st,ref_pre_tr) (pre_st,pre_tr)) then - begin - (* Updating pre-condition of pointed statement *) - update_stmt_pre stmt_ref (pre_st,pre_tr); - Hashtbl.replace stmts_to_compute_one_more_time stmt_ref true; - end; - - (* In order to treat statements that are not directly reachable, - consumes following statements until a labeled one with a defined pre-condition. *) - (*consumes stmt_l *) - let _ = propagates_pre stmt_l (mk_empty_pre_or_post ()) (*lastFuncStatusSet----> attention la sauvegarde doit être faite*) in - (mk_empty_pre_or_post ()) + (* Modifing specification of pointed statement and registering it to be computed *) + (* If the statement has not yet been specified *) + let ref_pre_st,ref_pre_tr = get_pre_of !stmt_ref in + + if not (double_bool_array_eq (ref_pre_st,ref_pre_tr) (pre_st,pre_tr)) + then + begin + (* Updating pre-condition of pointed statement *) + update_stmt_pre !stmt_ref (pre_st,pre_tr); + Hashtbl.replace stmts_to_compute_one_more_time !stmt_ref true; + end; + + (* In order to treat statements that are not directly reachable, + consumes following statements until a labeled one with a defined pre-condition. *) + (*consumes stmt_l *) + let _ = propagates_pre stmt_l (mk_empty_pre_or_post ()) (*lastFuncStatusSet----> attention la sauvegarde doit être faite*) in + (mk_empty_pre_or_post ()) | ({skind=Loop (_,block,_,_,_)} as stmt)::stmt_l -> - (* In a loop we distinguishe 4 cases of pre or post conditions: - {pre1} - While (1) { - {Pre2} - ... - if (c) {goto Label_end_loop;} - ... - {Post2} - } - {Post1} - Label_end_loop: - - - Pre1 : pre-condition before entering the loop - Pre2 : pre-condition of each iteration - Post1 : False (infinite loop) - Post2 : Post condition of an iteration - - - State_builder.of conditions : - - Initially : - Pre1 is given - Pre2 = Pre1 - - do - Post2 = (Pre2[block]) - Pre2 = Pre2 \/ Post2 - while fix-point not reached. - - Finally, the loop invariant is: - (Init => Pre1) - & (not Init => Pre2) - (where init is a fresh variable to indicate if the iteration is the first one). - - *) - - (* Updating pre-conditions with previous information *) - let loop_pre = get_stmts_pre (ref stmt) in - let block_pre = loop_pre in - - - - (* First forward propagation into block *) - let old_post = ref block_pre in - let block_post = ref( propagates_pre block.bstmts block_pre ) in - let block_pre = ref( double_bool_array_or block_pre !block_post ) in - - (* Fix-point computation *) - while not (double_bool_array_eq !old_post !block_post) do - - old_post := !block_post; - block_post:=propagates_pre block.bstmts !block_pre; - block_pre :=double_bool_array_or !block_pre !block_post - - done; - - (* Finally : Post1 = Pre2 *) - let (loop_post_st,loop_post_tr) = !block_pre in (* INTUILE *) - - - (* Updating loop information *) - Data_for_aorai.set_loop_ext_pre (ref stmt) loop_pre; - Data_for_aorai.set_loop_ext_post (ref stmt) (loop_post_st,loop_post_tr); - Data_for_aorai.set_loop_int_pre (ref stmt) !block_pre; - Data_for_aorai.set_loop_int_post (ref stmt) !block_post; - Hashtbl.replace stmts_spec (ref stmt) (fst loop_pre, snd loop_pre,loop_post_st,loop_post_tr); - - - - (* Computes next statements specification *) - (* The end of the loop is done through a goto instruction that - does not appear in the CIL structure. This is why, the - post-condition is the exit case of the loop invariant. *) - propagates_pre stmt_l (loop_post_st,loop_post_tr) (*lastFuncStatusSetPerformed ----------> depend de la loop, du nombre de tour etc*); + (* In a loop we distinguishe 4 cases of pre or post conditions: + {pre1} + While (1) { + {Pre2} + ... + if (c) {goto Label_end_loop;} + ... + {Post2} + } + {Post1} + Label_end_loop: + + + Pre1 : pre-condition before entering the loop + Pre2 : pre-condition of each iteration + Post1 : False (infinite loop) + Post2 : Post condition of an iteration + + + State_builder.of conditions : + + Initially : + Pre1 is given + Pre2 = Pre1 + + do + Post2 = (Pre2[block]) + Pre2 = Pre2 \/ Post2 + while fix-point not reached. + + Finally, the loop invariant is: + (Init => Pre1) + & (not Init => Pre2) + (where init is a fresh variable to indicate if the iteration is the first one). + + *) + + (* Updating pre-conditions with previous information *) + let loop_pre = get_stmts_pre stmt in + let block_pre = loop_pre in + + + + (* First forward propagation into block *) + let old_post = ref block_pre in + let block_post = ref( propagates_pre block.bstmts block_pre ) in + let block_pre = ref( double_bool_array_or block_pre !block_post ) in + + (* Fix-point computation *) + while not (double_bool_array_eq !old_post !block_post) do + + old_post := !block_post; + block_post:=propagates_pre block.bstmts !block_pre; + block_pre :=double_bool_array_or !block_pre !block_post + + done; + (* Finally : Post1 = Pre2 *) + let (loop_post_st,loop_post_tr) = !block_pre in (* INTUILE *) + + (* Updating loop information *) + Data_for_aorai.set_loop_ext_pre stmt loop_pre; + Data_for_aorai.set_loop_ext_post stmt (loop_post_st,loop_post_tr); + Data_for_aorai.set_loop_int_pre stmt !block_pre; + Data_for_aorai.set_loop_int_post stmt !block_post; + Hashtbl.replace stmts_spec stmt + (fst loop_pre, snd loop_pre,loop_post_st,loop_post_tr); + + (* Computes next statements specification *) + (* The end of the loop is done through a goto instruction that + does not appear in the CIL structure. This is why, the + post-condition is the exit case of the loop invariant. *) + propagates_pre stmt_l (loop_post_st,loop_post_tr) + (*lastFuncStatusSetPerformed ----------> + depend de la loop, du nombre de tour etc*); | {skind=UnspecifiedSequence(b)}::l -> - propagates_pre - ((mkStmt(Block(Cil.block_from_unspecified_sequence(b))))::l) - (pre_st,pre_tr) (*lastFuncStatusSet*) + propagates_pre + ((mkStmt(Block(Cil.block_from_unspecified_sequence(b))))::l) + (pre_st,pre_tr) (*lastFuncStatusSet*) | {skind=Switch (_,bl,stmtl,_)}::l -> - (* Step 1 : For each case, the pre-condition is set to pre_st,pre_tr. *) - List.iter - (fun stmt -> Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,pre_st,pre_tr)) - stmtl; - - (* Step 2 : The block is put into the todo list *) - propagates_pre - ((mkStmt(Block(bl)))::l) - (pre_st,pre_tr) (*lastFuncStatusSet*) + (* Step 1 : For each case, the pre-condition is set to pre_st,pre_tr. *) + List.iter + (fun stmt -> Hashtbl.replace stmts_spec stmt + (pre_st,pre_tr,pre_st,pre_tr)) + stmtl; + + (* Step 2 : The block is put into the todo list *) + propagates_pre + ((mkStmt(Block(bl)))::l) + (pre_st,pre_tr) (*lastFuncStatusSet*) | {skind=TryFinally (_,_,_) }::_ | {skind=TryExcept(_,_,_,_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : UnspecifiedSequence and try constructions are not yet supported.\n"; -(* Format.printf "Aorai plugin internal error. Status : UnspecifiedSequence and try constructions are not yet supported.\n";*) -(* assert false *) + Aorai_option.fatal "Aorai plugin internal error. Status : UnspecifiedSequence and try constructions are not yet supported.\n"; +(* Format.printf "Aorai plugin internal error. Status : UnspecifiedSequence and try constructions are not yet supported.\n";*) +(* assert false *) | {skind=Break (_)}::_ | {skind=Continue (_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Continue and Break statements have to be rewritten into statements goto during the CFG pass.\n"; -(* Format.printf "Aorai plugin internal error. Continue and Break statements have to be rewritten into statements goto during the CFG pass.\n";*) -(* assert false *) + Aorai_option.fatal "Aorai plugin internal error. Continue and Break statements have to be rewritten into statements goto during the CFG pass.\n"; +(* Format.printf "Aorai plugin internal error. Continue and Break statements have to be rewritten into statements goto during the CFG pass.\n";*) +(* assert false *) @@ -434,315 +426,330 @@ in let rec propagates_post stmt_l (post_st,post_tr) = (** This function returns the current spec of a statement or an empty - spec if no specification exists *) - let get_spec_of stmt_ref = - try let spec = Hashtbl.find stmts_spec stmt_ref in spec + spec if no specification exists *) + let get_spec_of stmt = + try let spec = Hashtbl.find stmts_spec stmt in spec with Not_found -> mk_empty_spec() in (** This function makes an AND filter between the given post and the old post of the given stmt The result is storing as the new post of the given stmt. *) - let update_stmt_post stmt_ref (post_st,post_tr) = - let old_pre_st,old_pre_tr,old_post_st,old_post_tr = get_spec_of stmt_ref in - let new_post_st,new_post_tr = (double_bool_array_and (old_post_st,old_post_tr) (post_st,post_tr)) in - Hashtbl.replace - stmts_spec - stmt_ref - (old_pre_st,old_pre_tr,new_post_st,new_post_tr) + let update_stmt_post stmt (post_st,post_tr) = + let old_pre_st,old_pre_tr,old_post_st,old_post_tr = get_spec_of stmt in + let new_post_st,new_post_tr = + (double_bool_array_and (old_post_st,old_post_tr) (post_st,post_tr)) + in + Hashtbl.replace stmts_spec stmt + (old_pre_st,old_pre_tr,new_post_st,new_post_tr) in - - - - (** This function makes an OR filter between the given post and the old post of the given stmt + (** This function makes an OR filter between the given post and + the old post of the given stmt The result is storing as the new post of the given stmt. *) - let update_stmt_post_OR stmt_ref (post_st,post_tr) = - let old_pre_st,old_pre_tr,old_post_st,old_post_tr = get_spec_of stmt_ref in - let new_post_st,new_post_tr = (double_bool_array_or (old_post_st,old_post_tr) (post_st,post_tr)) in + let update_stmt_post_OR stmt (post_st,post_tr) = + let old_pre_st,old_pre_tr,old_post_st,old_post_tr = get_spec_of stmt in + let new_post_st,new_post_tr = + (double_bool_array_or (old_post_st,old_post_tr) (post_st,post_tr)) + in Hashtbl.replace - stmts_spec - stmt_ref - (old_pre_st,old_pre_tr,new_post_st,new_post_tr) + stmts_spec + stmt + (old_pre_st,old_pre_tr,new_post_st,new_post_tr) in - - - - - (** This function returns the current spec of the given statement. - WARNING ! - Side effects of this function : - * The post of the current stmt is updated according to the given post_st and post_tr + WARNING ! + Side effects of this function : + * The post of the current stmt is updated according + to the given post_st and post_tr *) - let get_stmts_spec stmt_ref post_st post_tr = - update_stmt_post stmt_ref (post_st,post_tr); - get_spec_of stmt_ref + let get_stmts_spec stmt post_st post_tr = + update_stmt_post stmt (post_st,post_tr); + get_spec_of stmt in - - - (** Body of propagates_post (after list.rev) *) let rec prop stmt_l (post_st,post_tr) = if stmt_l <>[] then - begin - let s = (List.hd stmt_l) in - if s.labels<>[] then - begin - if List.exists (fun s -> match s with Label (_) -> true | _ -> false) s.labels then - (Hashtbl.replace status_of_labeled_stmts (ref s) true); - - if List.exists (fun s -> match s with Case (_) | Default(_) -> true | _ -> false) s.labels then - (update_stmt_post_OR (ref s) (post_st,post_tr)) - end - end; - - + begin + let s = (List.hd stmt_l) in + if s.labels<>[] then + begin + if List.exists (fun s -> match s with Label (_) -> true | _ -> false) s.labels then + (Hashtbl.replace status_of_labeled_stmts s true); + + if List.exists + (function Case (_) | Default(_) -> true | _ -> false) s.labels + then + (update_stmt_post_OR s (post_st,post_tr)) + end + end; match stmt_l with - | [] -> (post_st,post_tr) - - - | ({skind=Instr(Call(_,{enode = + | [] -> (post_st,post_tr) + | ({skind=Instr(Call(_,{enode = (Lval(Var(vi),_) | CastE(_,{enode = Lval(Var vi,_)}) )},_,_))} as stmt)::l -> - if (Data_for_aorai.isIgnoredFunction vi.vname) then begin - (* Retriving old specification information about this statement *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) post_st post_tr in - - (* Updating the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt)(pre_st,pre_tr,post_st,post_tr) ; - - (* Computes next statements specification *) - prop l (post_st,post_tr) - end - else - begin - (* Retriving old specification information about this statement *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) post_st post_tr in - + if (Data_for_aorai.isIgnoredFunction vi.vname) then begin + (* Retriving old specification information about this statement *) + let (pre_st,pre_tr,post_st,post_tr) = + get_stmts_spec stmt post_st post_tr + in + (* Updating the specification of current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); + + (* Computes next statements specification *) + prop l (post_st,post_tr) + end + else + begin + (* Retrieving old specification information + about this statement *) + let (pre_st,pre_tr,post_st,post_tr) = + get_stmts_spec stmt post_st post_tr + in (* If statement is unreachable then we skip the call *) - if (double_bool_array_eq (pre_st,pre_tr) (mk_empty_pre_or_post())) then + if (double_bool_array_eq + (pre_st,pre_tr) (mk_empty_pre_or_post())) + then begin - (* When stmt=call => the spec has to be memorized as pre of the call *) - Data_for_aorai.set_func_pre_call !currentFuncName stmt.sid (pre_st,pre_tr); - + (* When stmt=call => the spec has to be + memorized as pre of the call *) + Data_for_aorai.set_func_pre_call + !currentFuncName stmt.sid (pre_st,pre_tr); prop l (pre_st,pre_tr) end else begin - (* Registering call context for future reinforcement of post-condition *) + (* Registering call context for future reinforcement + of post-condition *) + let kf = Globals.Functions.get vi in let (cur_post_st,cur_post_tr) = if Hashtbl.mem functions_post_usecase vi.vname - then double_bool_array_or (Hashtbl.find functions_post_usecase vi.vname) (post_st,post_tr) + then double_bool_array_or + (Hashtbl.find functions_post_usecase vi.vname) + (post_st,post_tr) else (post_st,post_tr) - in Hashtbl.replace functions_post_usecase vi.vname (cur_post_st,cur_post_tr); - - (* From now, post-condition is the set of configurations from which - the operation is callable according to its pre-condition and - of the current statement pre-condition. *) + in + Hashtbl.replace + functions_post_usecase vi.vname (cur_post_st,cur_post_tr); + (* From now, post-condition is the set of configurations + from which the operation is callable according to its + pre-condition and of the current statement + pre-condition. *) let pre_call = (Data_for_aorai.get_func_pre vi.vname) in - let cur_pre = (Aorai_utils.get_prev vi.vname Promelaast.Call pre_call) in + let cur_pre = + Aorai_utils.get_prev kf Promelaast.Call pre_call + in let (cur_pre_st,cur_pre_tr) = double_bool_array_and cur_pre (pre_st,pre_tr) in - (* Updating the specification of the current stmt in the hashtbl. *) - (* Note that we use the post of the statement and not the one computed for the called function. *) - Hashtbl.replace stmts_spec (ref stmt) (cur_pre_st,cur_pre_tr,post_st,post_tr); - - (* When stmt=call => the spec has to be memorized as pre of the call *) - Data_for_aorai.set_func_pre_call !currentFuncName stmt.sid (cur_pre_st,cur_pre_tr); - - (* Computes next statements specification *) - prop l (cur_pre_st,cur_pre_tr) - end - end + (* Updating the specification of the current stmt in the hashtbl. *) + (* Note that we use the post of the statement and not the one computed for the called function. *) + Hashtbl.replace stmts_spec stmt + (cur_pre_st,cur_pre_tr,post_st,post_tr); + + (* When stmt=call => the spec has to be memorized as pre of the call *) + Data_for_aorai.set_func_pre_call !currentFuncName stmt.sid (cur_pre_st,cur_pre_tr); + + (* Computes next statements specification *) + prop l (cur_pre_st,cur_pre_tr) + end + end | {skind=Instr(Call(_,_,_,_))}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n"; -(* Format.printf "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n";*) -(* assert false *) + Aorai_option.fatal "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n"; +(* Format.printf "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n";*) +(* assert false *) | ({skind=Instr (_)} as stmt)::l -> - (* Retriving old specification information about this statement *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) post_st post_tr in + (* Retriving old specification information about this statement *) + let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec stmt post_st post_tr in - (* Updating the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt)(pre_st,pre_tr,post_st,post_tr) ; + (* Updating the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,post_st,post_tr) ; - (* Computes next statements specification *) - prop l (post_st,post_tr) + (* Computes next statements specification *) + prop l (post_st,post_tr) | ({skind=Block(b)} as stmt)::l -> - (* Retriving old specification information about this statement *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) post_st post_tr in + (* Retriving old specification information about this statement *) + let (pre_st,pre_tr,post_st,post_tr) = + get_stmts_spec stmt post_st post_tr + in + + (* Computes recursivly the block specification *) + let cur_pre = (propagates_post b.bstmts (post_st,post_tr)) in + let (pre_st,pre_tr) = double_bool_array_and cur_pre (pre_st,pre_tr) in - (* Computes recursivly the block specification *) - let cur_pre = (propagates_post b.bstmts (post_st,post_tr)) in - let (pre_st,pre_tr) = double_bool_array_and cur_pre (pre_st,pre_tr) in + (* Updating the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); - (* Updating the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,post_st,post_tr); - - (* Computes next statements specification *) - prop l (pre_st,pre_tr) + (* Computes next statements specification *) + prop l (pre_st,pre_tr) | ({skind=If(_,b1,b2,_)} as stmt)::l -> - (* Retriving old specification information about this statement *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) post_st post_tr in - - - (* Constraints propagation into branches. *) - let pre_block1 = propagates_post b1.bstmts (post_st,post_tr) in - let pre_block2 = propagates_post b2.bstmts (post_st,post_tr) in + (* Retriving old specification information about this statement *) + let (pre_st,pre_tr,post_st,post_tr) = + get_stmts_spec stmt post_st post_tr + in + (* Constraints propagation into branches. *) + let pre_block1 = propagates_post b1.bstmts (post_st,post_tr) in + let pre_block2 = propagates_post b2.bstmts (post_st,post_tr) in + (* The new pre-condition is the disjunction + of branches pre-conditions *) + let pre_blocks = double_bool_array_or pre_block1 pre_block2 in + let (pre_st,pre_tr) = + double_bool_array_and pre_blocks (pre_st,pre_tr) + in + (* Updating the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); - - (* The new pre-condition is the disjunction of branches pre-conditions *) - let pre_blocks = double_bool_array_or pre_block1 pre_block2 in - let (pre_st,pre_tr) = double_bool_array_and pre_blocks (pre_st,pre_tr) in - - - (* Updating the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,post_st,post_tr); - - (* Computes next statements specification *) - prop l (pre_st,pre_tr) + (* Computes next statements specification *) + prop l (pre_st,pre_tr) | ({skind=Return (_,_)} as stmt)::l -> - (* Retriving old specification information about this statement *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) post_st post_tr in - - (* The 'prev' according to the return will be done be the caller of the propagates function. *) - (* Updating the specification of the current stmt in the hashtbl. *) - Hashtbl.replace stmts_spec (ref stmt) (pre_st,pre_tr,post_st,post_tr); + (* Retriving old specification information about this statement *) + let (pre_st,pre_tr,post_st,post_tr) = + get_stmts_spec stmt post_st post_tr + in + (* The 'prev' according to the return will be done be the caller + of the propagates function. *) + (* Updating the specification of the current stmt in the hashtbl. *) + Hashtbl.replace stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); - (* Return the post-condition of the current function *) - prop l (post_st,post_tr) + (* Return the post-condition of the current function *) + prop l (post_st,post_tr) | ({skind=Goto(stmt_ref,_)} as stmt)::stmt_l -> - (* Retriving old specification information about this statement and the pointed one. *) - let (ref_pre_st,ref_pre_tr,_,_) = get_spec_of stmt_ref in - let (_,_,post_st,post_tr) = get_spec_of (ref stmt) in - - (* Second computation needed if the pointed stmt has not yet been treated - or if its pre differs from the current post *) - if (not !second_computation_needed) - && (Hashtbl.mem status_of_labeled_stmts (ref stmt) ) - && (not (double_bool_array_eq (ref_pre_st,ref_pre_tr) (post_st,post_tr))) - then - second_computation_needed:=not (Hashtbl.find status_of_labeled_stmts (ref stmt)); - - - (* Current post_st and post_tr are lose because they have no sense in the case of a goto instruction. *) - let (pre_st,pre_tr,post_st,post_tr) = get_stmts_spec (ref stmt) ref_pre_st ref_pre_tr in + (* Retriving old specification information about this statement and the pointed one. *) + let (ref_pre_st,ref_pre_tr,_,_) = get_spec_of !stmt_ref in + let (_,_,post_st,post_tr) = get_spec_of stmt in + + (* Second computation needed if the pointed stmt has not yet been treated + or if its pre differs from the current post *) + if (not !second_computation_needed) + && (Hashtbl.mem status_of_labeled_stmts stmt) + && (not + (double_bool_array_eq + (ref_pre_st,ref_pre_tr) (post_st,post_tr))) + then + second_computation_needed:= + not (Hashtbl.find status_of_labeled_stmts stmt); + (* Current post_st and post_tr are lost because + they have no sense in the case of a goto instruction. *) + let (pre_st,pre_tr,post_st,post_tr) = + get_stmts_spec stmt ref_pre_st ref_pre_tr + in + (* Add the specification of the current stmt in the hashtbl. *) + Hashtbl.add stmts_spec stmt (pre_st,pre_tr,post_st,post_tr); - (* Add the specification of the current stmt in the hashtbl. *) - Hashtbl.add stmts_spec (ref stmt) (pre_st,pre_tr,post_st,post_tr); - - prop stmt_l (pre_st,pre_tr) + prop stmt_l (pre_st,pre_tr) | ({skind=Loop (_,block,_,_,_)} as stmt)::stmt_l -> - (* In a loop we distinguishe 4 cases of pre or post conditions: - {pre1} - While (1) { - {Pre2} - ... - if (c) {goto Label_end_loop;} - ... - {Post2} - } - {Post1} - Label_end_loop: - - - Pre1 : pre-condition before entering the loop - Pre2 : pre-condition of each iteration - Post1 : False (Infinite loop) - Post2 : Post condition of an iteration - - - Initially : - Since the forward AI is done, an initial value is known for each annotation. - - do - Pre2 = ([block]Post2) /\ Pre2 - Post2 = Pre2 /\ Post2 - while fix-point not reached. - - Finally : - Pre1 = Pre1 /\ Pre2 - - - The loop invariant is then : - (c => Pre2) - & (!c => Post1) - & (Init => Pre1) - & (not Init => Post2) - (where init is a fresh variable to indicate if the iteration is the first one). - *) - - (* Retriving old specification information about this statement *) - let (loop_pre_st,loop_pre_tr,loop_post_st,loop_post_tr) = get_stmts_spec (ref stmt) post_st post_tr in - let loop_pre = loop_pre_st ,loop_pre_tr in - let loop_post = loop_post_st,loop_post_tr in - let block_pre = Data_for_aorai.get_loop_int_pre (ref stmt) in - let block_post = Data_for_aorai.get_loop_int_post (ref stmt) in + (* In a loop we distinguishe 4 cases of pre or post conditions: + {pre1} + While (1) { + {Pre2} + ... + if (c) {goto Label_end_loop;} + ... + {Post2} + } + {Post1} + Label_end_loop: + + + Pre1 : pre-condition before entering the loop + Pre2 : pre-condition of each iteration + Post1 : False (Infinite loop) + Post2 : Post condition of an iteration + + + Initially : + Since the forward AI is done, an initial value is known for each annotation. + + do + Pre2 = ([block]Post2) /\ Pre2 + Post2 = Pre2 /\ Post2 + while fix-point not reached. + + Finally : + Pre1 = Pre1 /\ Pre2 + + + The loop invariant is then : + (c => Pre2) + & (!c => Post1) + & (Init => Pre1) + & (not Init => Post2) + (where init is a fresh variable to indicate if the iteration is the first one). + *) + + (* Retriving old specification information about this statement *) + let (loop_pre_st,loop_pre_tr,loop_post_st,loop_post_tr) = + get_stmts_spec stmt post_st post_tr + in + let loop_pre = loop_pre_st ,loop_pre_tr in + let loop_post = loop_post_st,loop_post_tr in + let block_pre = Data_for_aorai.get_loop_int_pre stmt in + let block_post = Data_for_aorai.get_loop_int_post stmt in (* First backward propagation into block - Pre2 = ([block]Post2) /\ Pre2 - Post2 = Pre2 /\ Post2 - *) - let old_pre = ref block_pre in - let block_pre = propagates_post block.bstmts block_post in + Pre2 = ([block]Post2) /\ Pre2 + Post2 = Pre2 /\ Post2 + *) + let old_pre = ref block_pre in + let block_pre = propagates_post block.bstmts block_post in let block_pre = double_bool_array_and block_pre !old_pre in let block_post = double_bool_array_and block_pre block_post in - (* Loop initialisation for fix-point computation *) - let block_pre = ref block_pre in - let block_post = ref block_post in + (* Loop initialisation for fix-point computation *) + let block_pre = ref block_pre in + let block_post = ref block_post in - while not (double_bool_array_eq !old_pre !block_pre) do + while not (double_bool_array_eq !old_pre !block_pre) do - old_pre := !block_pre ; - block_pre := propagates_post block.bstmts !block_post ; + old_pre := !block_pre ; + block_pre := propagates_post block.bstmts !block_post ; block_pre := double_bool_array_and !block_pre !old_pre ; - block_post := double_bool_array_and !block_pre !block_post + block_post := double_bool_array_and !block_pre !block_post - done; + done; - (* The result is dereferenced *) - let block_pre = !block_pre in - let block_post = !block_post in + (* The result is dereferenced *) + let block_pre = !block_pre in + let block_post = !block_post in - (* Finally : Pre1 = Pre1 /\ Pre2 *) - let loop_pre = double_bool_array_and loop_pre block_pre in + (* Finally : Pre1 = Pre1 /\ Pre2 *) + let loop_pre = double_bool_array_and loop_pre block_pre in - (* Updating loop information *) - Data_for_aorai.set_loop_ext_pre (ref stmt) loop_pre; - Data_for_aorai.set_loop_ext_post (ref stmt) loop_post; - Data_for_aorai.set_loop_int_pre (ref stmt) block_pre; - Data_for_aorai.set_loop_int_post (ref stmt) block_post; - Hashtbl.replace stmts_spec (ref stmt) (fst loop_pre, snd loop_pre,fst loop_post, snd block_post); + (* Updating loop information *) + Data_for_aorai.set_loop_ext_pre stmt loop_pre; + Data_for_aorai.set_loop_ext_post stmt loop_post; + Data_for_aorai.set_loop_int_pre stmt block_pre; + Data_for_aorai.set_loop_int_post stmt block_post; + Hashtbl.replace stmts_spec stmt + (fst loop_pre, snd loop_pre,fst loop_post, snd block_post); (* Format.printf "\n\nNew loop pre : \n"; @@ -756,31 +763,31 @@ Format.printf "\n\n"; *) - (* Computes next statements specification *) - prop stmt_l loop_pre + (* Computes next statements specification *) + prop stmt_l loop_pre | {skind=UnspecifiedSequence(b)}::l -> - prop - ((mkStmt(Block(Cil.block_from_unspecified_sequence(b))))::l) - (post_st,post_tr) + prop + ((mkStmt(Block(Cil.block_from_unspecified_sequence(b))))::l) + (post_st,post_tr) | {skind=Switch (_,bl,stmtl,_)}::l -> - (* Step 1 : For each case, the pre-condition is set to pre_st,pre_tr. *) - List.iter - (fun stmt -> update_stmt_post_OR (ref stmt) (post_st,post_tr)) - stmtl; - - (* Step 2 : The block is put into the todo list *) - prop - ((mkStmt(Block(bl)))::l) - (post_st,post_tr) + (* Step 1 : For each case, the pre-condition is set to pre_st,pre_tr. *) + List.iter + (fun stmt -> update_stmt_post_OR stmt (post_st,post_tr)) + stmtl; + + (* Step 2 : The block is put into the todo list *) + prop + ((mkStmt(Block(bl)))::l) + (post_st,post_tr) @@ -789,14 +796,14 @@ | {skind=Break (_)}::_ | {skind=Continue (_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Goto, Break and Continue instructions are not yet supported.\n"; -(* Format.printf "Aorai plugin internal error. Status : Goto, Break and Continue instructions are not yet supported.\n";*) -(* assert false *) + Aorai_option.fatal "Aorai plugin internal error. Status : Goto, Break and Continue instructions are not yet supported.\n"; +(* Format.printf "Aorai plugin internal error. Status : Goto, Break and Continue instructions are not yet supported.\n";*) +(* assert false *) | {skind=TryFinally (_,_,_) }::_ | {skind=TryExcept(_,_,_,_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : try constructions are not yet supported.\n"; -(* Format.printf "Aorai plugin internal error. Status : try constructions are not yet supported.\n";*) -(* assert false *) + Aorai_option.fatal "Aorai plugin internal error. Status : try constructions are not yet supported.\n"; +(* Format.printf "Aorai plugin internal error. Status : try constructions are not yet supported.\n";*) +(* assert false *) in @@ -806,22 +813,20 @@ -object (*(self) *) +object (self) inherit Visitor.generic_frama_c_visitor (Project.current ()) (Cil.inplace_visit ()) as super method vfunc f = currentFuncName:=f.svar.vname; - -(* let lastFuncStatusSet = Named_funct_status_set.empty in*) -(* let lastFuncStatusSet = Named_funct_status_set.add ({id = !currentFuncName;status=Promelaast.Call}) lastFuncStatusSet in*) + let kf = Extlib.the self#current_kf in let starting_pre = (Data_for_aorai.get_func_pre f.svar.vname) in let starting_post = (Data_for_aorai.get_func_post f.svar.vname) in -(* Format.printf "\nAvant passe 1 : "; + Aorai_option.debug "Before step 1:"; Aorai_utils.debug_display_func_status f.svar.vname; -*) + Hashtbl.clear stmts_spec; Hashtbl.clear stmts_to_compute_one_more_time; @@ -835,26 +840,19 @@ let _ = propagates_pre f.sbody.bstmts cur_pre in cur_post_st := fst (!propagation_result) done; - - - (* Registration of the new post-condition *) - let post = Aorai_utils.get_next f.svar.vname Promelaast.Return !cur_post_st in + let post = Aorai_utils.get_next kf Promelaast.Return !cur_post_st in let old_post = (Data_for_aorai.get_func_post f.svar.vname) in let post = double_bool_array_and post old_post in Data_for_aorai.set_func_post f.svar.vname post; -(* Format.printf "Entre passes 1 et 2 : "; + Aorai_option.debug "Between steps 1 and 2 : "; Aorai_utils.debug_display_func_status f.svar.vname; -*) - (* Post-condition backward propagation *) let cur_post = (Data_for_aorai.get_func_post f.svar.vname) in - let cur_post = Aorai_utils.get_prev f.svar.vname Promelaast.Return cur_post in - - + let cur_post = Aorai_utils.get_prev kf Promelaast.Return cur_post in Hashtbl.clear status_of_labeled_stmts; second_computation_needed:=false; let cur_pre = ref (propagates_post f.sbody.bstmts cur_post) in @@ -865,18 +863,15 @@ cur_pre := propagates_post f.sbody.bstmts cur_post done; let cur_pre = !cur_pre in - - (* Registration of the new pre-condition *) let old_pre = Data_for_aorai.get_func_pre f.svar.vname in let pre = double_bool_array_and cur_pre old_pre in Data_for_aorai.set_func_pre f.svar.vname pre; - Aorai_option.debug "After pass 2 for function %s" f.svar.vname; + Aorai_option.debug "After step 2 for function %s" f.svar.vname; Aorai_utils.debug_display_func_status f.svar.vname; - let ending_pre = (Data_for_aorai.get_func_pre f.svar.vname) in let ending_post = (Data_for_aorai.get_func_post f.svar.vname) in @@ -888,16 +883,14 @@ DoChildren end - - - - let propagates_pre_post_constraints file root = Hashtbl.clear functions_pre_usecase ; Hashtbl.clear functions_post_usecase; spec_modified:=false; - let visitor = new visit_propagating_pre_post_constraints (Data_for_aorai.getAutomata()) in + let visitor = + new visit_propagating_pre_post_constraints (Data_for_aorai.getAutomata()) + in Cil.visitCilFile (visitor :> Cil.cilVisitor) file; List.iter @@ -906,40 +899,27 @@ begin let old_pre = (Data_for_aorai.get_func_pre name) in let old_post = (Data_for_aorai.get_func_post name) in - let pre = try Hashtbl.find functions_pre_usecase name with Not_found -> (mk_empty_pre_or_post()) in - let post = try Hashtbl.find functions_post_usecase name with Not_found -> (mk_empty_pre_or_post()) in - - - let cur_pre = double_bool_array_and pre old_pre in - let cur_post = double_bool_array_and post old_post in - - -(* - Format.printf "\nPost of %s: \n old :" name; - Aorai_utils.debug_display_stmt_all_pre old_post ; - Format.printf "\n usecase:"; - Aorai_utils.debug_display_stmt_all_pre post; - Format.printf "\n keeped :"; - Aorai_utils.debug_display_stmt_all_pre cur_post; - Format.printf "\n\n"; -*) - - - if (not (double_bool_array_eq old_pre cur_pre ) ) - then begin spec_modified:=true; end; - if (not (double_bool_array_eq old_post cur_post) ) - then begin spec_modified:=true; end; - - - Data_for_aorai.set_func_pre name cur_pre; - Data_for_aorai.set_func_post name cur_post - end + let pre = + try Hashtbl.find functions_pre_usecase name + with Not_found -> (mk_empty_pre_or_post()) + in + let post = + try Hashtbl.find functions_post_usecase name + with Not_found -> (mk_empty_pre_or_post()) + in + let cur_pre = double_bool_array_and pre old_pre in + let cur_post = double_bool_array_and post old_post in + if (not (double_bool_array_eq old_pre cur_pre ) ) + then begin spec_modified:=true; end; + if (not (double_bool_array_eq old_post cur_post) ) + then begin spec_modified:=true; end; + Data_for_aorai.set_func_pre name cur_pre; + Data_for_aorai.set_func_post name cur_post + end ) (Data_for_aorai.getFunctions_from_c ()); !spec_modified - - (* Local Variables: compile-command: "LC_ALL=C make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/Aorai.mli frama-c-20111001+nitrogen+dfsg/src/aorai/Aorai.mli --- frama-c-20110201+carbon+dfsg/src/aorai/Aorai.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/Aorai.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/aorai_option.ml frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_option.ml --- frama-c-20110201+carbon+dfsg/src/aorai/aorai_option.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_option.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -43,7 +45,7 @@ let option_name = "-aorai-to-buchi" let arg_name = "f" let help = - "only generates the buchi automata (in Promela language) in file " + "only generates the buchi automata (in Promela language) in file " let kind = `Tuning end) @@ -52,8 +54,8 @@ (struct let option_name = "-aorai-buchi" let arg_name = "f" - let help = "considers the property helpibed by the buchi automata (in \ -Promela language) from file ." + let help = "considers the property described by the buchi automata \ + (in Promela language) from file ." let kind = `Correctness end) @@ -62,19 +64,19 @@ (struct let option_name = "-aorai-automata" let arg_name = "f" - let help = "considers the property helpibed by the ya automata (in \ -Ya language) from file ." + let help = "considers the property described by the ya automata \ + (in Ya language) from file ." let kind = `Correctness end) module Output_Spec = False(struct - let option_name = "-aorai-show-op-spec" - let help = - "displays computed pre and post-condition of each operation" + let option_name = "-aorai-show-op-spec" + let help = + "displays computed pre and post-condition of each operation" let kind = `Tuning - end) + end) module Output_C_File = EmptyString @@ -87,10 +89,10 @@ module Dot = False(struct - let option_name = "-aorai-dot" - let help = "generates a dot file of the Buchi automata" + let option_name = "-aorai-dot" + let help = "generates a dot file of the Buchi automata" let kind = `Tuning - end) + end) module DotSeparatedLabels = False(struct @@ -101,46 +103,47 @@ module AbstractInterpretation = False(struct - let option_name = "-aorai-simple-AI" - let help = "use simple abstract interpretation" + let option_name = "-aorai-simple-AI" + let help = "use simple abstract interpretation" let kind = `Tuning - end) + end) module AbstractInterpretationOff = False(struct - let option_name = "-aorai-AI-off" - let help = "does not use abstract interpretation" + let option_name = "-aorai-AI-off" + let help = "does not use abstract interpretation" let kind = `Tuning - end) + end) let () = Plugin.set_negative_option_name "-aorai-spec-off" module Axiomatization = True(struct - let option_name = "-aorai-spec-on" - let help = "if set, does not axiomatize automata" + let option_name = "-aorai-spec-on" + let help = "if set, does not axiomatize automata" let kind = `Correctness end) module ConsiderAcceptance = False(struct - let option_name = "-aorai-acceptance" - let help = "if set, considers acceptation states" + let option_name = "-aorai-acceptance" + let help = "if set, considers acceptation states" let kind = `Correctness end) +let () = Plugin.set_negative_option_name "-aorai-raw-auto" module AutomataSimplification= True (struct - let option_name = "-aorai-raw-auto" + let option_name = "-aorai-simplified-auto" let help = "If set, does not simplify automata" let kind = `Tuning end) module Test = Zero(struct - let option_name = "-aorai-test" - let arg_name = "" - let help = "Testing mode (0 = no test)" + let option_name = "-aorai-test" + let arg_name = "" + let help = "Testing mode (0 = no test)" let kind = `Tuning end) @@ -153,6 +156,27 @@ let kind = `Correctness end) +module Deterministic= + State_builder.Ref + (Datatype.Bool) + (struct + let name = "Aorai_option.Deterministic" + let dependencies = [] + let kind = `Correctness + let default () = false + end) + +let reset () = + let my_opts = parameters () in + let select acc p = + let state = State.get p.Parameter.name in + State_selection.Dynamic.union + (State_selection.Dynamic.with_dependencies state) + acc + in + let selection = List.fold_left select State_selection.empty my_opts in + Project.clear ~selection () + let is_on () = not (Ltl_File.is_default () && To_Buchi.is_default () && Buchi.is_default () && Ya.is_default () ) @@ -162,18 +186,11 @@ However it works only if aorai is run from the command line. *) let init () = if is_on () then begin - Parameters.SimplifyCfg.on (); - Parameters.KeepSwitch.on () + Kernel.SimplifyCfg.on (); + Kernel.KeepSwitch.on () end -let () = - Cmdline.run_after_configuring_stage init; - let add_codeps onto = - State_dependency_graph.Static.add_codependencies - ~onto [ Ltl_File.self; To_Buchi.self; Buchi.self; Ya.self ] - in - add_codeps Parameters.SimplifyCfg.self; - add_codeps Parameters.KeepSwitch.self +let () = Cmdline.run_after_configuring_stage init let promela_file () = if Buchi.get () = "" then To_Buchi.get () else Buchi.get () diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/aorai_option.mli frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_option.mli --- frama-c-20110201+carbon+dfsg/src/aorai/aorai_option.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_option.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -25,20 +27,28 @@ include Plugin.S -module Ltl_File : STRING -module To_Buchi: STRING -module Buchi: STRING -module Ya: STRING -module Output_Spec : BOOL -module Output_C_File : STRING -module Dot : BOOL -module DotSeparatedLabels: BOOL -module AbstractInterpretation : BOOL -module Axiomatization : BOOL -module ConsiderAcceptance : BOOL -module AutomataSimplification : BOOL -module Test : INT -module AddingOperationNameAndStatusInSpecification:BOOL +module Ltl_File : String +module To_Buchi: String +module Buchi: String +module Ya: String +module Output_Spec : Bool +module Output_C_File : String +module Dot : Bool +module DotSeparatedLabels: Bool +module AbstractInterpretation : Bool +module Axiomatization : Bool +module ConsiderAcceptance : Bool +module AutomataSimplification : Bool +module Test : Int +module AddingOperationNameAndStatusInSpecification:Bool + +(** [true] if the user declares that its ya automaton is deterministic. *) +module Deterministic: State_builder.Ref with type data = bool + +val reset: unit -> unit +(** Resets all options + @since Nitrogen-20111001 + *) val is_on : unit -> bool val promela_file: unit -> string diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/aorai_register.ml frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_register.ml --- frama-c-20110201+carbon+dfsg/src/aorai/aorai_register.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_register.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,9 +23,11 @@ (* *) (**************************************************************************) +open Logic_ptree open Promelaast open Aorai_utils +(* [VP] Need to get rid of those global references at some point. *) let promela_file = ref "" let ya_file = ref "" let c_file = ref "" @@ -31,77 +35,100 @@ let ltl_tmp_file = ref "" let ltl_file = ref "" let dot_file = ref "" -let root = ref "" let generatesCFile = ref true let ltl2ba_params = " -l -p -o " let toBeRemoved = ref [] +let ltl_to_promela = Hashtbl.create 7 + +let set_ltl_correspondance h = + Hashtbl.clear ltl_to_promela; + Hashtbl.iter (fun x y -> Hashtbl.add ltl_to_promela x y) h + +let convert_ltl_exprs t = + let rec convert_cond cond = + match cond with + POr(c1,c2) -> POr (convert_cond c1, convert_cond c2) + | PAnd(c1,c2) -> PAnd(convert_cond c1, convert_cond c2) + | PNot c -> PNot (convert_cond c) + | PCall _ | PReturn _ | PTrue | PFalse -> cond + | PRel(Neq,PVar x,PCst _) -> + (try + let (rel,t1,t2) = Hashtbl.find ltl_to_promela x in PRel(rel,t1,t2) + with Not_found -> cond) + | PRel _ -> cond + in + let rec convert_seq_elt e = + { e with + condition = Extlib.opt_map convert_cond e.condition; + nested = convert_seq e.nested; } + and convert_seq s = List.map convert_seq_elt s in + let convert_parsed c = + match c with + Seq l -> Seq (convert_seq l) + | Otherwise -> Otherwise + in + let convert_trans t = { t with cross = convert_parsed t.cross } in + List.map convert_trans t + (* Promela file *) +let syntax_error loc msg = + Aorai_option.abort + "File %S, line %d, characters %d-%d:@\nSyntax error: %s" + (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum + ((fst loc).Lexing.pos_cnum - (fst loc).Lexing.pos_bol) + ((snd loc).Lexing.pos_cnum - (fst loc).Lexing.pos_bol) + msg + let ltl_to_ltlLight f_ltl f_out = try let c = open_in f_ltl in - let (ltl_form,ltl_exps) = Ltllexer.parse c in + let (ltl_form,exprs) = Ltllexer.parse c in close_in c; - Data_for_aorai.setLtl_expressions ltl_exps; - Logic_simplification.setLtl_expressions ltl_exps; - Ltl_output.output ltl_form f_out - with Not_found -> - Aorai_option.abort "Problem with file : %s" f_ltl - | Ltllexer.Error (loc,msg) -> - Aorai_option.error - "File %S, line %d, characters %d-%d" - (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum - ((fst loc).Lexing.pos_cnum - (fst loc).Lexing.pos_bol) - ((snd loc).Lexing.pos_cnum - (fst loc).Lexing.pos_bol); - Aorai_option.error "Error when parsing LTL formula"; - Aorai_option.abort "%s" msg + Ltl_output.output ltl_form f_out; + set_ltl_correspondance exprs + with + | Not_found -> Aorai_option.abort "Unknown LTL file %s" f_ltl + | Ltllexer.Error (loc,msg) -> syntax_error loc msg let load_ya_file f = try let c = open_in f in - let (automata,auto_vars,auto_funs) = Yalexer.parse c in + let automata = Yalexer.parse c in close_in c; - Data_for_aorai.setAutomata automata auto_vars auto_funs; + Data_for_aorai.setAutomata automata; with - Not_found -> - Aorai_option.fatal "Problem with file : %s\n" f - | Yalexer.Error (loc,msg) -> - Aorai_option.abort - "File %S, line %d, characters %d-%d:@\nError: %s" - (fst loc).Lexing.pos_fname (fst loc).Lexing.pos_lnum - ((fst loc).Lexing.pos_cnum - (fst loc).Lexing.pos_bol) - ((snd loc).Lexing.pos_cnum - (fst loc).Lexing.pos_bol) - msg + | Not_found -> Aorai_option.abort "Unknown Ya file %s" f + | Yalexer.Error (loc,msg) -> syntax_error loc msg let load_promela_file f = try let c = open_in f in - let (automata,auto_vars,auto_funs) = Promelalexer.parse c in + let (s,t) = Promelalexer.parse c in + let t = convert_ltl_exprs t in close_in c; - Data_for_aorai.setAutomata automata auto_vars auto_funs; - with Not_found -> - Aorai_option.fatal "Problem with file : %s\n" f -(* Format.printf "Problem with file : %s\n" f;*) -(* raise ex *) - + Data_for_aorai.setAutomata (s,t); + with + | Not_found -> Aorai_option.abort "Unknown Promela file %s" f + | Promelalexer.Error(loc,msg) -> syntax_error loc msg let load_promela_file_withexps f = try let c = open_in f in - let (automata,auto_vars,auto_funs) = Promelalexer_withexps.parse c in + let automata = Promelalexer_withexps.parse c in close_in c; - Data_for_aorai.setAutomata automata auto_vars auto_funs; - with Not_found -> - Aorai_option.fatal "Problem with file : %s\n" f -(* Format.printf "Problem with file : %s\n" f;*) -(* raise ex *) + Data_for_aorai.setAutomata automata; + with + | Not_found -> Aorai_option.abort "Unknown Promela file %s" f + | Promelalexer_withexps.Error(loc,msg) -> syntax_error loc msg let display_status () = if Aorai_option.verbose_atleast 2 then begin Aorai_option.feedback "\n" ; Aorai_option.feedback "C file: '%s'\n" !c_file ; - Aorai_option.feedback "Entry point: '%s'\n" !root ; + Aorai_option.feedback "Entry point: '%a'\n" + Kernel_function.pretty (fst (Globals.entry_point())) ; Aorai_option.feedback "LTL property: '%s'\n" !ltl_file ; Aorai_option.feedback "Files to generate: '%s' (Annotated code)\n" (if !generatesCFile then !output_c_file else "(none)"); @@ -141,7 +168,10 @@ in (* c_file name is given and has to point out a valid file. *) - c_file := List.hd (Parameters.Files.get ()); + c_file := + (match Kernel.Files.get () with + | [] -> "dummy.i" + | f :: _ -> f); if (!c_file="") then dispErr ": invalid C file name" !c_file; if (not (Sys.file_exists !c_file)) then dispErr "not found" !c_file; @@ -171,12 +201,14 @@ toBeRemoved:=(!ltl_tmp_file)::!toBeRemoved end else begin ltl_tmp_file:= - Extlib.temp_file_cleanup_at_exit - (Filename.basename !c_file) ".ltl"; + (try + Extlib.temp_file_cleanup_at_exit + (Filename.basename !c_file) ".ltl" + with Extlib.Temp_file_error s -> + Aorai_option.abort "cannot create temporary file: %s" s); promela_file:= freshname (Filename.chop_extension !ltl_tmp_file) ".promela"; - toBeRemoved:=(!promela_file)::!toBeRemoved; - toBeRemoved:=(!ltl_tmp_file)::!toBeRemoved + toBeRemoved := !ltl_tmp_file :: !promela_file :: !toBeRemoved end end else begin if Aorai_option.To_Buchi.get () <> "" && @@ -196,7 +228,6 @@ if (!ya_file="") then dispErr ": invalid Ya file name" !ya_file; if (not (Sys.file_exists !ya_file)) then dispErr "not found" !ya_file end; - root := Kernel_function.get_name (fst (Globals.entry_point ())); display_status (); !err @@ -212,7 +243,7 @@ (Aorai_option.Verbose.get () > 2) || (Aorai_option.Output_Spec.get ()) in - Aorai_option.result ~level:0 "Welcome in the Aorai plugin@."; + Aorai_option.result ~level:0 "Welcome to the Aorai plugin@."; init_test (); (* Step 1 : Capture files names *) @@ -223,12 +254,12 @@ else (* Step 2 : Work in our own project, initialized by a copy of the main one. *) - let prj = - File.create_project_from_visitor "aorai" + let work_prj = + File.create_project_from_visitor "aorai_tmp" (fun prj -> new Visitor.frama_c_copy prj) in - Project.copy ~selection:(Plugin.get_selection ()) prj; - Project.set_current prj; + Project.copy ~selection:(Plugin.get_selection ()) work_prj; + Project.set_current work_prj; let file = Ast.get () in Aorai_utils.initFile file; printverb "C file loading : done\n"; @@ -256,11 +287,6 @@ else load_promela_file !promela_file; printverb "Loading promela : done\n"; - - (* creates the enumeration corresponding to states and - fill the table mapping nums to enumitem. - *) - Aorai_utils.make_enum_states (); (* Computing the list of ignored functions *) (* Aorai_visitors.compute_ignored_functions file; *) @@ -269,13 +295,14 @@ (* Data_for_aorai.debug_ltl_expressions (); *) (*let _ = Path_analysis.test (Data_for_aorai.getAutomata())in*) - - + let root = fst (Globals.entry_point ()) in + let root_name = Kernel_function.get_name root in if (Aorai_option.Axiomatization.get()) then begin (* Step 4 : Computing the set of possible pre-states and post-states of each function *) (* And so for pre/post transitions *) - Aorai_visitors.compute_abstract file !root (Aorai_option.ConsiderAcceptance.get()); + Aorai_visitors.compute_abstract file + root_name (Aorai_option.ConsiderAcceptance.get()); printverb "Abstracting pre/post : done\n"; (* (display_operations_spec ()); *) @@ -287,12 +314,12 @@ begin (* Repeat until reach a fix-point *) while - Abstract_ai.propagates_pre_post_constraints file !root + Abstract_ai.propagates_pre_post_constraints file root_name do () done; printverb " Forward/backward abstract specification : done\n"; end else - printverb " Forward/backward abstract specification : skiped\n"; + printverb " Forward/backward abstract specification : skipped\n"; (* (display_operations_spec ());*) @@ -302,22 +329,17 @@ begin (* Repeat until reach a fix-point *) while - Bycase_ai.propagates_pre_post_constraints_bycase file !root; + Bycase_ai.propagates_pre_post_constraints_bycase + file root_name; do () done; - printverb " Consider links between input and output states : done\n"; - - - (* (* Repeat until reach a fix-point *) - while - ControlFlow_ai.propagates_pre_post_constraints file !root; - do () done; - Callgraph.printGraph stdout (Callgraph.computeGraph file); - printverb " Forward/backward AI according to control flow : skiped\n"*) + printverb + " Consider links between input and output states : done\n"; end + else begin - printverb " Consider links between input and output states : skiped\n"; - (*printverb " Forward/backward AI according to control flow : skiped\n";*) + printverb " Consider links between input and output states : skipped\n"; + (*printverb " Forward/backward AI according to control flow : skipped\n";*) end; (* (display_operations_spec_bycase ());*) @@ -327,17 +349,22 @@ (*Promelaoutput.print_raw_automata (Data_for_aorai.getAutomata()); *) if (Aorai_option.AutomataSimplification.get()) then begin + printverb "Removing unused trans : done\n"; + let l = Data_for_aorai.all_action_bindings () in Data_for_aorai.removeUnusedTransitionsAndStates (); + Data_for_aorai.clear_actions (); + List.iter + (fun ((kf,ki,pre,post),v) -> + Data_for_aorai.set_action_bindings kf ki pre post v) l; (* Promelaoutput.print_raw_automata (Data_for_aorai.getAutomata()); *) - printverb "Removing unused trans : done\n"; end else - printverb "Removing unused trans : skiped\n"; + printverb "Removing unused trans : skipped\n"; (* Step 7 : Labeling abstract file *) (* Finally the information is added into the Cil automata. *) - Aorai_utils.initGlobals !root (Aorai_option.Axiomatization.get()); + Aorai_utils.initGlobals root (Aorai_option.Axiomatization.get()); Aorai_visitors.add_sync_with_buch file; Aorai_visitors.add_pre_post_from_buch file (Aorai_option.advance_abstract_interpretation ()); @@ -349,27 +376,34 @@ begin (* Step 4': Computing the set of possible pre-states and post-states of each function *) (* And so for pre/post transitions *) - printverb "Abstracting pre/post : skiped\n"; + printverb "Abstracting pre/post : skipped\n"; (* Step 5': incrementing pre/post conditions with states and transitions information *) - printverb "Refining pre/post : skiped\n"; + printverb "Refining pre/post : skipped\n"; (* Step 6 : Removing transitions never crossed *) - printverb "Removing unused trans : skiped\n"; + printverb "Removing unused trans : skipped\n"; (* Step 7 : Labeling abstract file *) (* Finally the information is added into the Cil automata. *) - Aorai_utils.initGlobals !root (Aorai_option.Axiomatization.get()); + Aorai_utils.initGlobals root (Aorai_option.Axiomatization.get()); Aorai_visitors.add_sync_with_buch file; printverb "Annotation of Cil : partial\n" end; - - (* Step 8 : Updating succs and preds fields in stmts *) + (* Step 8 : clearing tables whose information has been + invalidated by our transformations. + *) Cfg.clearFileCFG ~clear_id:false file; Cfg.computeFileCFG file; - + let prj = + File.create_project_from_visitor "aorai" + (fun prj -> new Visitor.frama_c_copy prj) + in + Project.copy ~selection:(Plugin.get_selection ()) prj; + Project.set_current prj; + Project.remove ~project:work_prj (); (* Step 9 : Generating resulting files *) (* Dot file *) @@ -386,22 +420,27 @@ else begin let cout = open_out !output_c_file in - Cil.print_utf8:=false; - Cil.dumpFile (new Printer.print ()) cout "test_string" file; - close_out cout; - printverb "C file generation : done\n"; + Kernel.Unicode.without_unicode + (fun () -> + (* [JS 2011/03/11] should use File.pretty_ast instead *) + Cil.dumpFile (new Printer.print ()) cout "test_string" file; + close_out cout; + printverb "C file generation : done\n"; + ) () end; - printverb "Finished.\n"; - if display_op_specs then (Aorai_utils.display_operations_spec_sorted_bycase ()); + if display_op_specs then + Aorai_utils.display_operations_spec_sorted_bycase (); (* Some test traces. *) match Aorai_option.Test.get () with | 1 -> Aorai_utils.debug_display_all_specs () | _ -> () (* 0 is no test *) end ; + if !generatesCFile then Kernel.Files.set [!output_c_file]; + Aorai_option.reset (); cleanup_files () (* Plugin registration *) @@ -420,6 +459,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/aorai_utils.ml frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_utils.ml --- frama-c-20110201+carbon+dfsg/src/aorai/aorai_utils.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_utils.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,47 +23,60 @@ (* *) (**************************************************************************) +open Cil +open Logic_const +open Logic_utils +open Data_for_aorai +open Extlib open Cil_types open Cil_datatype open Promelaast open Bool3 open Spec_tools +let mkStmt stmt = Cil.mkStmt ~valid_sid:true stmt + +let mkStmtOneInstr instr = Cil.mkStmtOneInstr ~valid_sid:true instr + (**exception to avoid pre computation with structure and array**) exception LazyInit;; -(** Given a transition a function name and a function status (call or return) it returns if the cross condition can be statisfied with only function status. *) +let rename_pred v1 v2 p = + let r = + object + inherit Visitor.frama_c_copy (Project.current()) + method vlogic_var_use v = + if Cil_datatype.Logic_var.equal v v1 then Cil.ChangeTo v2 + else Cil.JustCopy + end + in + Visitor.visitFramacPredicateNamed r p + +(** Given a transition a function name and a function status (call or + return) it returns if the cross condition can be statisfied with + only function status. + *) let isCrossable tr func st = let rec isCross p = match p with - | POr (c1, c2) -> bool3or (isCross c1) (isCross c2) - | PAnd (c1, c2) -> bool3and (isCross c1) (isCross c2) - | PNot (c1) -> bool3not (isCross c1) - - | PCall (s) -> if func=s && st=Call then True else False - | PReturn (s) -> if func=s && st=Return then True else False - | PCallOrReturn (s) -> if func=s then True else False - - | PTrue -> True - | PFalse -> False -(* | PGt (_,_) - | PGe (_,_) - | PLt (_,_) - | PLe (_,_) - | PEq (_,_) - | PNeq (_,_) - | PBoolVar (_) -> Undefined*) - - | PIndexedExp (_) -> Undefined - | PFuncReturn (_, f) -> - if Datatype.String.equal func f && st = Return then Undefined else False - | PFuncParam (_, f, _) -> - if Datatype.String.equal func f && st = Call then Undefined else False - in - let res = isCross tr.cross <> False in - Aorai_option.debug ~level:2 "Function %s %s-state, \ - transition %s -> %s is%s possible" func - ( if st=Call then "pre" else "post") + | TOr (c1, c2) -> bool3or (isCross c1) (isCross c2) + | TAnd (c1, c2) -> bool3and (isCross c1) (isCross c2) + | TNot c1 -> bool3not (isCross c1) + | TCall (kf,None) when Kernel_function.equal func kf && st=Call -> True + | TCall (kf, Some _) when Kernel_function.equal func kf && st=Call -> + Undefined + | TCall _ -> False + | TReturn kf when Kernel_function.equal func kf && st=Return -> True + | TReturn _ -> False + | TTrue -> True + | TFalse -> False + | TRel _ -> Undefined + in + let cond,_ = tr.cross in + let res = isCross cond <> False in + Aorai_option.debug ~level:2 "Function %a %s-state, \ + transition %s -> %s is%s possible" Kernel_function.pretty func + (if st=Call then "pre" else "post") tr.start.Promelaast.name tr.stop.Promelaast.name (if res then "" else " NOT"); @@ -80,7 +95,8 @@ let dependencies = (* TODO: projectify the automata and depend on it. *) - [ Ast.self; Aorai_option.Ltl_File.self; + [ Ast.self; + Aorai_option.Ltl_File.self; Aorai_option.Buchi.self; Aorai_option.Ya.self ] @@ -96,19 +112,12 @@ let debug_display_func_status name = let pre = Data_for_aorai.get_func_pre name in let post = Data_for_aorai.get_func_post name in - let debug_pre = debug_display_stmt_all_pre pre in + let debug_pre = debug_display_stmt_all_pre pre in let debug_post = debug_display_stmt_all_pre post in Aorai_option.debug "%s %s %s" debug_pre name debug_post; Aorai_option.debug "\n" - - - (* ************************************************************************* *) - - - - (** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of reachable states and the @@ -119,10 +128,10 @@ List.iter (fun t -> if (states.(t.start.nums)) && (isCrossable t func status) then - begin - st.(t.stop.nums)<- true ; - tr.(t.numt)<- true - end + begin + st.(t.stop.nums)<- true ; + tr.(t.numt)<- true + end ) trans_l; (st,tr) @@ -138,26 +147,23 @@ let (_,trans_l) = Data_for_aorai.getAutomata() in List.iter (fun t -> - if (states.(t.stop.nums)) && (isCrossable t func status) && trans.(t.numt) then - st.(t.start.nums)<- true + if (states.(t.stop.nums)) && (isCrossable t func status) + && trans.(t.numt) + then + st.(t.start.nums)<- true ) trans_l; List.iter (fun t -> if (st.(t.stop.nums)) then - tr.(t.numt)<- true + tr.(t.numt)<- true ) trans_l; (st,tr) - - - (* ************************************************************************* *) - - let mk_pre_or_post_bycase_from_pre_or_post (st,tr) = let st_bc,tr_bc = mk_empty_pre_or_post_bycase () in let (_,trans_l) = Data_for_aorai.getAutomata() in @@ -171,12 +177,8 @@ (st_bc,tr_bc) - - (* ************************************************************************* *) - - let debug_display_func_status_bycase name = let pre = Data_for_aorai.get_func_pre name in (* let pre = mk_pre_or_post_bycase_from_pre_or_post pre in *) @@ -185,91 +187,8 @@ let debug_post = debug_display_stmt_all_pre_bycase post in Aorai_option.debug "%s %s %s" debug_pre name debug_post;; - - - - (* ************************************************************************* *) - -(** bool array -> (bool array array*bool array array) -> (bool array*bool array) *) -let compose_assocs_post assocs_st (post_st,post_tr) = - let st,tr = mk_empty_pre_or_post () in - let st,tr = ref st, ref tr in - Array.iteri - (fun index b -> - if b then begin - st:=bool_array_or post_st.(index) !st; - tr:=bool_array_or post_tr.(index) !tr - end - ) - assocs_st; - - (!st,!tr) - - -(** bool array array -> (bool array array*bool array array) -> (bool array array*bool array array) - Given a set of states and the bycase post-condition of an operation - this function returns the new pre-condition after the call of the operation in the context of current_st. -*) -let mk_forward_composition current_st post = - let new_st,new_tr = mk_empty_pre_or_post_bycase () in - Array.iteri - (fun index assocs -> - let s,t = compose_assocs_post assocs post in - new_st.(index)<-s; - new_tr.(index)<-t - ) - current_st; - - (new_st,new_tr) - - - -(** bool array -> (bool array * bool array) (bool array array*bool array array) -> (bool array*bool array) *) -let compose_assocs_pre assocs_st (_,pre_tr) (post_st,_) = - let st,tr = mk_empty_pre_or_post () in - let st,tr = ref st, ref tr in - let (_,trans_l) = Data_for_aorai.getAutomata() in - Array.iteri - (fun index b -> - if b then begin - Array.iteri - (fun value val_assocs -> if val_assocs.(index) then !st.(value)<-true) - post_st; - end - ) - assocs_st; - - - List.iter - (fun t -> if pre_tr.(t.numt) && (!st).(t.stop.nums) then !tr.(t.numt)<-true) - trans_l; - - - (!st,!tr) - - -(** bool array array -> (bool array*bool array) -> (bool array array*bool array array) -> (bool array array*bool array array) - Given a set of states and the bycase post-condition of an operation - this function returns the new pre-condition after the call of the operation in the context of current_st. -*) -let mk_backward_composition current_st pre post = - let new_st,new_tr = mk_empty_pre_or_post_bycase () in - Array.iteri - (fun index assocs -> - let s,t = compose_assocs_pre assocs pre post in - new_st.(index)<-s; - new_tr.(index)<-t - ) - current_st; - - (new_st,new_tr) - - - - - (** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of reachable states and the second one is the set of crossable transitions. *) let get_next_bycase func status states_bycase = (* In a first pass we compute all cases of specification (For each starting state, we compute ending states set) *) @@ -277,11 +196,11 @@ let (_,trans_l) = Data_for_aorai.getAutomata() in List.iter (fun t -> - if (isCrossable t func status) then - begin - st_bc.(t.start.nums).(t.stop.nums)<- true ; - tr_bc.(t.start.nums).(t.numt)<- true - end + if (isCrossable t func status) then + begin + st_bc.(t.start.nums).(t.stop.nums)<- true ; + tr_bc.(t.start.nums).(t.numt)<- true + end ) trans_l; @@ -290,14 +209,14 @@ Array.iteri (fun init_st init_st_assocs -> Array.iteri - (fun end_st b -> - if b then - begin - res_st_bc.(init_st) <- (bool_array_or (res_st_bc.(init_st)) (st_bc.(end_st)) ); - res_tr_bc.(init_st) <- (bool_array_or (res_tr_bc.(init_st)) (tr_bc.(end_st)) ); - end - ) - init_st_assocs; + (fun end_st b -> + if b then + begin + res_st_bc.(init_st) <- (bool_array_or (res_st_bc.(init_st)) (st_bc.(end_st)) ); + res_tr_bc.(init_st) <- (bool_array_or (res_tr_bc.(init_st)) (tr_bc.(end_st)) ); + end + ) + init_st_assocs; ) states_bycase; @@ -307,13 +226,20 @@ -(** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of possible initial states and the second one is the set of crossable transitions. *) +(** Given a function name, + its status (call or return) and an array of boolean describing states + status, it returns a couple of boolean array. + The first one describes the set of possible initial states and + the second one is the set of crossable transitions. + *) let get_prev_bycase func status (states_bycase ,transitions_bycase) = let res_st_bc,res_tr_bc = mk_empty_pre_or_post_bycase () in (* For each starting case, we call the get_prev function *) Array.iteri (fun case_st case_st_assocs -> - let prev_st,prev_tr= get_prev func status (case_st_assocs,transitions_bycase.(case_st)) in + let prev_st,prev_tr = + get_prev func status (case_st_assocs,transitions_bycase.(case_st)) + in res_st_bc.(case_st) <- prev_st; res_tr_bc.(case_st) <- prev_tr ) @@ -329,243 +255,258 @@ (* ************************************************************************* *) - - -(*open Cil_types*) - -(** Given a transition a function name and a function status (call or return) it returns if the cross condition can be statisfied with only function status. *) +(** Given a transition a function name and a function status (call or return) + it returns if the cross condition can be statisfied with only + function status. *) let isCrossableAtInit tr func = - let rec isCross = function - | POr (c1, c2) -> - (isCross c1) || (isCross c2) - | PAnd (c1, c2) -> - (isCross c1) && (isCross c2) - | PNot (c1) -> - not (isCross c1) - - | PCall (s) -> - (func=s) - | PReturn (_) -> - false - | PCallOrReturn (s) -> - func=s - - | PTrue -> - true - | PFalse -> - false -(* | PGt (_,_) - | PGe (_,_) - | PLt (_,_) - | PLe (_,_) - | PEq (_,_) - | PNeq (_,_) - | PBoolVar (_) -> Undefined*) - - | PIndexedExp e -> - (evalExpAtInit (Data_for_aorai.get_exp_from_tmpident e))<>0 - - | PFuncReturn (_, _) -> false - | PFuncParam (e, f, _) -> if func=f then (evalExpAtInit (Data_for_aorai.get_exp_from_tmpident e))<>0 else false - - - and error_msg msg = - Aorai_option.fatal "Aorai plugin internal error. Status : %s. \n" msg; - - and evalExpAtInit:Cil_types.exp -> int = fun e -> - match e.enode with - | Cil_types.Const (c) -> - begin - match c with - | Cil_types.CInt64(int64,_,_) -> Int64.to_int int64 - | Cil_types.CStr (_) - | Cil_types.CWStr(_) -> error_msg "String values not supported into LTL expressions" - | Cil_types.CChr(c) -> Char.code c - | Cil_types.CReal (_,_,_) -> error_msg "Real values not supported into LTL expressions" - | Cil_types.CEnum {eival = exp} -> evalExpAtInit exp - end - - - | Cil_types.Lval (Cil_types.Var(vi),Cil_types.NoOffset) -> get_val_from_vi vi - | Cil_types.Lval (_) -> raise LazyInit -(* error_msg "Only simple LVAL supported at this time into LTL expressions"*) - - | Cil_types.UnOp (unop,exp,typ) -> - if not (Cil.isIntegralType typ) then - error_msg "Such operator not yet supported in LTL expressions" - else - begin - match unop with - | Cil_types.Neg -> (-(evalExpAtInit exp)) - | Cil_types.BNot -> error_msg "Bitwise complement not supported in LTL expressions" - | Cil_types.LNot -> if (evalExpAtInit exp)=0 then 1 else 0 - end - - | Cil_types.BinOp (binop,exp1,exp2,typ) -> - if not (Cil.isIntegralType typ) then - error_msg "Such operator not yet supported in LTL expressions" - else - begin - match binop with - | Cil_types.PlusA -> (evalExpAtInit exp1) + (evalExpAtInit exp2) - | Cil_types.MinusA -> (evalExpAtInit exp1) - (evalExpAtInit exp2) - | Cil_types.Mult -> (evalExpAtInit exp1) * (evalExpAtInit exp2) - | Cil_types.Div -> (evalExpAtInit exp1) / (evalExpAtInit exp2) - | Cil_types.Mod -> error_msg "Modulo not yet supported in LTL expressions" - | Cil_types.PlusPI - | Cil_types.IndexPI - | Cil_types.MinusPI - | Cil_types.MinusPP -> error_msg "Pointer and array not yet supported in LTL expressions" - | Cil_types.Shiftlt - | Cil_types.Shiftrt -> error_msg "Shifts not yet supported in LTL expressions" - | Cil_types.Lt -> ( try - if (evalExpAtInit exp1) < (evalExpAtInit exp2) then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e ) - | Cil_types.Gt ->( try - if (evalExpAtInit exp1) > (evalExpAtInit exp2) then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e) - | Cil_types.Le ->(try - if (evalExpAtInit exp1) <= (evalExpAtInit exp2) then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e) - | Cil_types.Ge ->(try - if (evalExpAtInit exp1) >= (evalExpAtInit exp2) then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e) - | Cil_types.Eq ->(try - if (evalExpAtInit exp1) = (evalExpAtInit exp2) then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e) - | Cil_types.Ne ->(try - if (evalExpAtInit exp1) <> (evalExpAtInit exp2) then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e) - | Cil_types.BAnd - | Cil_types.BXor - | Cil_types.BOr -> error_msg "Bitwise operations not supported in LTL expressions" - | Cil_types.LAnd ->(try - if (evalExpAtInit exp1)<>0 && (evalExpAtInit exp2)<>0 then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e ) - | Cil_types.LOr ->(try - if (evalExpAtInit exp1)<>0 or (evalExpAtInit exp2)<>0 then 1 else 0 - with - | LazyInit -> 1 - | _ as e -> raise e ) - end - - - - | Cil_types.Info (exp,_) -> - evalExpAtInit exp - - | Cil_types.CastE (_,exp) -> - Aorai_option.warning "Warning (Aorai plugin) CastE is not yet fully supported as a valid LTL expression. " ; - evalExpAtInit exp - - - - | Cil_types.SizeOf (_) - | Cil_types.SizeOfE (_) - | Cil_types.SizeOfStr (_) -> - error_msg "Sizeof is not supported as a valid LTL expression" - - | Cil_types.AlignOf (_) - | Cil_types.AlignOfE (_) -> - error_msg "AlignOf is not supported as a valid LTL expression" - - | Cil_types.AddrOf (_) -> - error_msg "AddrOf is not yet supported as a valid LTL expression" - | Cil_types.StartOf(_) -> - error_msg "StartOf is not yet supported as a valid LTL expression" - - - and get_val_from_vi vi = - try - let ini=Globals.Vars.find vi in - match ini.Cil_types.init with - | None -> error_msg ("'"^(vi.Cil_types.vname)^"'Seems to not be initialized" ) - | Some (Cil_types.SingleInit(exp)) -> evalExpAtInit exp - | Some (Cil_types.CompoundInit(_,_)) -> error_msg "Compound values not yet supported into LTL expressions" - with - | _ -> - error_msg ("initialisation of '"^(vi.Cil_types.vname)^"' not found") - - - + (* When in doubt, return true anyway. More clever plug-ins will take care + of analysing the instrumented code if needed. *) + let eval_term_at_init t = + if Kernel.LibEntry.get() then t + else begin + let bool_res test = + if test then Cil.lconstant My_bigint.one else Cil.lzero () + in + let bool3_res dft test = + match test with + | True -> bool_res true + | False -> bool_res false + | Undefined -> dft + in + let is_true t = + match t with + | TConst(CInt64(i,_,_)) -> + Bool3.bool3_of_bool (not (My_bigint.is_zero i)) + | TConst(CChr c) -> Bool3.bool3_of_bool (not (Char.code c <> 0)) + | TConst(CReal (f,_,_)) -> Bool3.bool3_of_bool (not (f <> 0.)) + | TConst(CStr _ | CWStr _) -> Bool3.True + | _ -> Bool3.Undefined + in + let rec aux t = + match t.term_node with + | TConst (CEnum ei) -> + aux (Logic_utils.expr_to_term ~cast:false ei.eival) + | TLval lv -> + (match aux_lv lv with + | Some t -> t + | None -> t) + | TUnOp(op,t1) -> + let t1 = aux t1 in + (match op,t1.term_node with + | Neg, TConst(CInt64(i,ik,_)) -> + { t with term_node = TConst(CInt64(My_bigint.neg i,ik,None)) } + | Neg, TConst(CReal(f,fk,_)) -> + { t with term_node = TConst(CReal(~-. f,fk,None)) } + | LNot, t1 -> bool3_res t (is_true t1) + | _ -> t) + | TBinOp(op,t1,t2) -> + let t1 = aux t1 in + let t2 = aux t2 in + let rec comparison comp t1 t2 = + match t1.term_node,t2.term_node with + | TConst (CInt64(i1,_,_)), TConst (CInt64(i2,_,_)) -> + bool_res (comp (My_bigint.compare i1 i2)) + | TConst (CChr c1), TConst (CChr c2) -> + bool_res (comp (Char.compare c1 c2)) + | TConst(CReal (f1,_,_)), TConst (CReal(f2,_,_)) -> + bool_res (comp (compare f1 f2)) + | TCastE(ty1,t1), TCastE(ty2,t2) + when Cil_datatype.Typ.equal ty1 ty2 -> + comparison comp t1 t2 + | _ -> t + in + (match op, t1.term_node, t2.term_node with + + | PlusA, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + (* kind is not relevant in the logic. *) + { t with term_node = + TConst(CInt64(My_bigint.add i1 i2,ik1,None))} + | MinusA, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + { t with term_node = + TConst(CInt64(My_bigint.sub i1 i2,ik1,None)) } + | Mult, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + { t with term_node = + TConst(CInt64(My_bigint.mul i1 i2,ik1,None)) } + | Div, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + (try + { t with term_node = + TConst(CInt64(My_bigint.c_div i1 i2,ik1,None)) } + with Division_by_zero -> t) + | Mod, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + (try + { t with term_node = + TConst(CInt64(My_bigint.c_rem i1 i2,ik1,None)) } + with Division_by_zero -> t) + | Shiftlt, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + { t with term_node = + TConst(CInt64(My_bigint.shift_left i1 i2,ik1,None)) } + | Shiftrt, TConst(CInt64(i1,ik1,_)), TConst(CInt64(i2,_,_)) -> + { t with term_node = + TConst(CInt64(My_bigint.shift_right i1 i2,ik1,None)) } + | Lt, _, _ -> comparison ((<) 0) t1 t2 + | Gt, _, _ -> comparison ((>) 0) t1 t2 + | Le, _, _ -> comparison ((<=) 0) t1 t2 + | Ge, _, _ -> comparison ((>=) 0) t1 t2 + | Eq, _, _ -> comparison ((=) 0) t1 t2 + | Ne, _, _ -> comparison ((<>) 0) t1 t2 + | LAnd, t1, t2 -> + bool3_res t (Bool3.bool3and (is_true t1) (is_true t2)) + | LOr, t1, t2 -> + bool3_res t (Bool3.bool3or (is_true t1) (is_true t2)) + | _ -> t) + | TCastE(ty,t1) -> + let t1 = aux t1 in + (match t1.term_type with + Ctype ty1 when Cil_datatype.Typ.equal ty ty1 -> t1 + | _ -> { t with term_node = TCastE(ty,t1) }) + | _ -> t + and aux_lv (base,off) = + match base with + | TVar v -> + (try + Extlib.opt_bind + (fun v -> + let init = Globals.Vars.find v in + let init = match init.Cil_types.init with + None -> Cil.makeZeroInit ~loc:v.vdecl v.vtype + | Some i -> i + in + aux_init off init) + v.lv_origin + with Not_found -> None) + | TMem t -> + (match (aux t).term_node with + | TAddrOf lv -> aux_lv (Cil.addTermOffsetLval off lv) + | _ -> None) + | TResult _ -> None + and aux_init off initinfo = + match off, initinfo with + | TNoOffset, SingleInit e -> + Some (aux (Logic_utils.expr_to_term ~cast:false e)) + | TIndex(t,oth), CompoundInit (ct,initl) -> + (match (aux t).term_node with + | TConst(CInt64(i1,_,_)) -> + Cil.foldLeftCompound ~implicit:true + ~doinit: + (fun o i _ t -> + match o with + | Index({ enode = Const(CInt64(i2,_,_))},_) + when My_bigint.equal i1 i2 -> aux_init oth i + | _ -> t) + ~ct ~initl ~acc:None + | _ -> None) + | TField(f1,oth), CompoundInit(ct,initl) -> + Cil.foldLeftCompound ~implicit:true + ~doinit: + (fun o i _ t -> + match o with + | Field(f2,_) when Cil_datatype.Fieldinfo.equal f1 f2 -> + aux_init oth i + | _ -> t) + ~ct ~initl ~acc:None + | _ -> None + in + aux t + end in - isCross tr.cross - - - - + let eval_rel_at_init rel t1 t2 = + let t1 = eval_term_at_init (Cil.constFoldTerm true t1) in + let t2 = eval_term_at_init (Cil.constFoldTerm true t2) in + let comp = + match rel with + | Req -> ((=) 0) + | Rneq -> ((<>) 0) + | Rge -> ((>=) 0) + | Rgt -> ((>) 0) + | Rle -> ((<=) 0) + | Rlt -> ((<) 0) + in + let rec comparison t1 t2 = + match t1.term_node,t2.term_node with + | TConst (CInt64(i1,_,_)), TConst (CInt64(i2,_,_)) -> + Bool3.bool3_of_bool (comp (My_bigint.compare i1 i2)) + | TConst (CChr c1), TConst (CChr c2) -> + Bool3.bool3_of_bool (comp (Char.compare c1 c2)) + | TConst(CReal (f1,_,_)), TConst (CReal(f2,_,_)) -> + Bool3.bool3_of_bool (comp (compare f1 f2)) + | TCastE(ty1,t1), TCastE(ty2,t2) when Cil_datatype.Typ.equal ty1 ty2 -> + comparison t1 t2 + | _ -> Bool3.Undefined + in + comparison t1 t2 + in + let rec isCross = function + | TOr (c1, c2) -> Bool3.bool3or (isCross c1) (isCross c2) + | TAnd (c1, c2) -> Bool3.bool3and (isCross c1) (isCross c2) + | TNot (c1) -> Bool3.bool3not (isCross c1) + | TCall (s,None) -> Bool3.bool3_of_bool (Kernel_function.equal s func) + | TCall (s, Some _) when Kernel_function.equal s func -> Undefined + | TCall _ -> Bool3.False + | TReturn _ -> Bool3.False + | TTrue -> Bool3.True + | TFalse -> Bool3.False + | TRel(rel,t1,t2) -> eval_rel_at_init rel t1 t2 + + in + let (cond,_) = tr.cross in + match isCross cond with + | Bool3.True | Bool3.Undefined -> true + | Bool3.False -> false (* ************************************************************************* *) (** {b Expressions management} *) -open Cil -open Logic_const -open Logic_utils -open Cil_types -open Data_for_aorai - (** Returns an int constant expression which represents the given int value. *) let mk_int_exp value = - new_exp ~loc:Cil_datatype.Location.unknown - (Const(CInt64(Int64.of_int value,IInt,Some(string_of_int value)))) + new_exp ~loc:Cil_datatype.Location.unknown + (Const(CInt64(My_bigint.of_int value,IInt,Some(string_of_int value)))) -(** Returns an lval expression which represents the access of the host_name variable (a string) with the offset off_exp (an expression). *) +(** Returns an lval expression which represents the access + of the host_name variable (a string) with the offset off_exp + (an expression). + *) let mk_offseted_array_lval host_name off_exp = let host_lval = (Cil.var (get_varinfo host_name)) in Cil.addOffsetLval (Index(off_exp,NoOffset)) host_lval -(** Returns an lval expression which represents the access of the host_name variable (a string) with the offset off_value (an int). *) +(** Returns an lval expression which represents the access of the + host_name variable (a string) with the offset off_value (an int). *) let mk_int_offseted_array_lval host_name off_value = mk_offseted_array_lval host_name (mk_int_exp off_value) - - let rec get_concrete_param_from_formal formal formall concretel f sid = match formall, concretel with | [],_ | _, [] -> Aorai_option.fatal "The stmt %d is a call of the function %s, but it is not called with the formal parameter %s." sid f formal | f1::fl,c1::cl -> - if (String.compare formal f1.vname)=0 - then c1.enode - else get_concrete_param_from_formal formal fl cl f sid + if (String.compare formal f1.vname)=0 + then c1.enode + else get_concrete_param_from_formal formal fl cl f sid -(** Compute the set of concrete value of a call, associated to a given list of parameters. +(** Compute the set of concrete value of a call, + associated to a given list of parameters. @param f name of the called function @param sid stmt id of the call @param paramlist list of parameters name - @return a list of exp_node, such that each formal parameter from paramlist is affected by the associated expression. + @return a list of exp_node, such that each formal parameter from + paramlist is affected by the associated expression. *) let get_concrete_value_of_call (f:string) sid paramlist = - let sid = match sid with | Some(v) -> v | None -> Aorai_option.fatal "Stmt id required !!" in let (stmt,_) = Kernel_function.find_from_sid sid in let kfunc = Globals.Functions.find_by_name f in let formall = Globals.Functions.get_params kfunc in match stmt.skind with - | Instr(Call(_,_,concretel,_)) -> - List.fold_left - (fun fl p -> - (* for an observed formal param p, we are looking for its associated concrete parameter *) - (get_concrete_param_from_formal p formall concretel f sid)::fl - ) - [] - paramlist + | Instr(Cil_types.Call(_,_,concretel,_)) -> + List.fold_left + (fun fl p -> + (* for an observed formal param p, we are looking for its associated concrete parameter *) + (get_concrete_param_from_formal p formall concretel f sid)::fl + ) + [] + paramlist | _ -> Aorai_option.fatal "The stmt %d have to be a call of the function %s, but it is not a call stmt." sid f @@ -575,587 +516,156 @@ *) let get_concrete_value_of_return (f:string) = let kf = Globals.Functions.find_by_name f in - let rstmt = Kernel_function.find_return kf in + let rstmt = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> + Aorai_option.fatal "Don't know what to do with a function declaration" + in match rstmt.skind with - | Return (Some (e),_) -> e.enode + | Cil_types.Return (Some (e),_) -> e.enode | Block (b) -> - begin - let s=(List.hd (List.rev b.bstmts)) in - match s.skind with - | Return (Some (e),_) -> e.enode - | _ -> Aorai_option.fatal "The stmt %d have to be a return of the function %s, but it is not a well formed stmt." rstmt.sid f - end - | _ -> Aorai_option.fatal "The stmt %d have to be a return of the function %s, but it is not a well formed stmt." rstmt.sid f - - - - -(** This function rewrite a cross condition into a Cil expression. - Moreover, by giving current operation name and its status (call or return) - the generation simplifies the generated expression. - This function is use only to compute the C code of synchronization. -*) -let crosscond_to_exp cross func status sid = - let false_exp = Cil.zero ~loc:(CurrentLoc.get()) in - let true_exp = Cil.one ~loc:(CurrentLoc.get()) in - let rec convert : Promelaast.condition -> Bool3.t * Cil_types.exp = function - (* Lazy evaluation of logic operators if the result can be statically - computed *) - | POr (c1, c2) -> (*BinOp(LOr,convert c1,convert c2,Cil.intType)*) - begin - let (c1_val,c1_exp) = convert c1 in - match c1_val with - | Bool3.True -> (c1_val,c1_exp) - | Bool3.False -> convert c2 - | Undefined -> - let (c2_val,c2_exp) = convert c2 in - match c2_val with - | Bool3.True -> (c2_val,c2_exp) - | Bool3.False -> (c1_val,c1_exp) - | Undefined -> (Undefined, - new_exp ~loc:(CurrentLoc.get()) - (BinOp(LOr,c1_exp,c2_exp,Cil.intType))) - end - - | PAnd (c1, c2) -> (*BinOp(LAnd,convert c1,convert c2,Cil.intType)*) - begin - let (c1_val,c1_exp) = convert c1 in - match c1_val with - | Bool3.True -> convert c2 - | Bool3.False -> (c1_val,c1_exp) - | Undefined -> - let (c2_val,c2_exp) = convert c2 in - match c2_val with - | Bool3.True -> (c1_val,c1_exp) - | Bool3.False -> (c2_val,c2_exp) - | Undefined -> (Undefined, - new_exp ~loc:(CurrentLoc.get()) - (BinOp(LAnd,c1_exp,c2_exp,Cil.intType))) - end - - | PNot (c1) -> (*UnOp(LNot,convert c1,Cil.intType)*) - begin - let (c1_val,c1_exp) = convert c1 in - match c1_val with - | Bool3.True -> (Bool3.False,false_exp) - | Bool3.False -> (Bool3.True,true_exp) - | Undefined -> (c1_val, - new_exp - ~loc:(CurrentLoc.get()) - (UnOp(LNot,c1_exp,Cil.intType))) - end - - (* Call and return are statically defined *) - | PCall (s) -> - if(s=func) && (status=Promelaast.Call) then - (Bool3.True, true_exp) - else - (Bool3.False,false_exp) - - - | PReturn (s) -> - if(s=func) && (status=Promelaast.Return) then - (Bool3.True,true_exp) - (* snd (convert(PAnd( - PEq(PVar(s),PVar(curOp)), - PEq(PVar(callStatus),PVar(curOpStatus)) - ))))*) - else - (Bool3.False,false_exp) - - - - | PCallOrReturn (s) -> - if(s=func) then - (Bool3.True,true_exp) - (* snd (convert(PEq(PVar(s),PVar(curOp)))))*) - else - (Bool3.False,false_exp) - - - - - (* Other expressions are left unchanged *) - | PTrue -> (Bool3.True, true_exp) - | PFalse -> (Bool3.False, false_exp) - - | PIndexedExp(s) -> (Undefined,get_exp_from_tmpident s) - | PFuncReturn (s, f) -> - if (String.compare s func)=0 && (status=Promelaast.Return) then - (Undefined, - Cil_manipulation.exp_substitution - (get_exp_from_tmpident s) - ["\\return"] - [get_concrete_value_of_return f] - ) - else - (Bool3.False,false_exp) - - | PFuncParam (s,f,varlist) -> - if (String.compare s func)=0 && (status=Promelaast.Call) then - (Undefined, - Cil_manipulation.exp_substitution - (get_exp_from_tmpident s) - (varlist) - (get_concrete_value_of_call f sid varlist) - ) - else - (Bool3.False,false_exp) - - in - try - convert cross - with - | _ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Not_found exception during exp conversion.\n" - - - - - - - - - - - - - + begin + let s=(List.hd (List.rev b.bstmts)) in + match s.skind with + | Cil_types.Return (Some (e),_) -> e.enode + | _ -> + Aorai_option.fatal + "The stmt %d have to be a return of the function %s, \ + but it is not a well formed stmt." rstmt.sid f + end + | _ -> Aorai_option.fatal + "The stmt %d have to be a return of the function %s, \ + but it is not a well formed stmt." rstmt.sid f + +(** This function rewrites a cross condition into an ACSL expression. + Moreover, by giving current operation name and its status (call or + return) the generation simplifies the generated expression. + + When called with an event (func, call_or_return), the conditions related + to a particular event (PCall & co) will be directly evaluated to true or + false. When event is None (in particular when generating the invariants), + an appropriate predicate is generated. - - - - - - - - - - - - - -(** This function rewrite a cross condition into a Cil expression. - Moreover, by giving current operation name and its status (call or return) the generation simplifies the generated expression. - - When called with inv=true, this function is used to compute the axiomatized automata. - When called with inv=false, this function is used to compute the parametrized pre/post conditions - - @param cross condition to convert from Promelaast.condition to Cil_types.predicate + @param cross condition to convert from Promelaast.condition to + {!Cil_types.predicate} @param op_logic_var operation variable @param status_logic_var status variable (call/return) -*) -let crosscond_to_pred inv cross op_logic_var status_logic_var = - let rec convert : Promelaast.condition -> Bool3.t * Cil_types.predicate = + *) +let crosscond_to_pred ?event cross op_logic_var status_logic_var = + let inv = match event with None -> true | Some _ -> false in + let check_current_event f status pred = + let (curr_f, curr_status) = Extlib.the event in + if Kernel_function.equal curr_f f && curr_status = status then pred + else (Bool3.False, pfalse) + in + let rec convert = function (* Lazy evaluation of logic operators if the result can be statically computed *) - | POr (c1, c2) -> (*BinOp(LOr,convert c1,convert c2,Cil.intType)*) - begin - let (c1_val,c1_pred) = convert c1 in - match c1_val with + | TOr (c1, c2) -> (*BinOp(LOr,convert c1,convert c2,Cil.intType)*) + begin + let (c1_val,c1_pred) = convert c1 in + match c1_val with | Bool3.True -> (c1_val,c1_pred) - | Bool3.False -> convert c2 - | Undefined -> - let (c2_val,c2_pred) = convert c2 in - match c2_val with + | Bool3.False -> convert c2 + | Undefined -> + let (c2_val,c2_pred) = convert c2 in + match c2_val with | Bool3.True -> (c2_val,c2_pred) - | Bool3.False -> (c1_val,c1_pred) - | Undefined -> (Undefined,Por(unamed c1_pred, unamed c2_pred)) - end - - | PAnd (c1, c2) -> (*BinOp(LAnd,convert c1,convert c2,Cil.intType)*) - begin - let (c1_val,c1_pred) = convert c1 in - match c1_val with + | Bool3.False -> (c1_val,c1_pred) + | Undefined -> (Undefined,Logic_const.por(c1_pred, c2_pred)) + end + + | TAnd (c1, c2) -> (*BinOp(LAnd,convert c1,convert c2,Cil.intType)*) + begin + let (c1_val,c1_pred) = convert c1 in + match c1_val with | Bool3.True -> convert c2 - | Bool3.False -> (c1_val,c1_pred) - | Undefined -> - let (c2_val,c2_pred) = convert c2 in - match c2_val with + | Bool3.False -> (c1_val,c1_pred) + | Undefined -> + let (c2_val,c2_pred) = convert c2 in + match c2_val with | Bool3.True -> (c1_val,c1_pred) - | Bool3.False -> (c2_val,c2_pred) - | Undefined -> (Undefined,Pand(unamed c1_pred, unamed c2_pred)) - end - - | PNot (c1) -> (*UnOp(LNot,convert c1,Cil.intType)*) - begin - let (c1_val,c1_pred) = convert c1 in - match c1_val with - | Bool3.True -> (Bool3.False,Pfalse) - | Bool3.False -> (Bool3.True,Ptrue) - | Undefined -> (c1_val,Pnot(unamed c1_pred)) - end + | Bool3.False -> (c2_val,c2_pred) + | Undefined -> (Undefined,Logic_const.pand(c1_pred, c2_pred)) + end + + | TNot (c1) -> (*UnOp(LNot,convert c1,Cil.intType)*) + begin + let (c1_val,c1_pred) = convert c1 in + match c1_val with + | Bool3.True -> (Bool3.False,pfalse) + | Bool3.False -> (Bool3.True,ptrue) + | Undefined -> (c1_val,Logic_const.pnot(c1_pred)) + end (* Call and return are statically defined -- Case where inv = true *) - | PFuncParam (_, s, _) (* This introduce an over-approximation in invariant (we do not consider param value) *) - | PCall (s) when inv -> - (Undefined, - Pand( - unamed( - Prel(Req, - Logic_const.term - (TLval(TVar(op_logic_var),TNoOffset)) (Ctype Cil.intType), - Logic_const.term (TConst(func_to_cenum s)) - (Ctype Cil.intType) - ) - ), - unamed ( - Prel(Req, - Logic_const.term - (TLval(TVar(status_logic_var),TNoOffset)) - (Ctype Cil.intType), - Logic_const.term - (TConst(op_status_to_cenum Promelaast.Call)) - (Ctype Cil.intType) - ) - ) - ) - ) - - - | PFuncReturn (_, s) when inv -> (* This introduce an over-approximation in invariant (we do not consider returned value) *) - (Undefined, - Pand( - unamed( - Prel(Req, - Logic_const.term - (TLval(TVar(op_logic_var),TNoOffset)) (Ctype Cil.intType), - Logic_const.term (TConst(func_to_cenum s)) (Ctype Cil.intType) - ) - ), - unamed ( - Prel(Req, - Logic_const.term - (TLval(TVar(status_logic_var),TNoOffset)) - (Ctype Cil.intType), - Logic_const.term - (TConst(op_status_to_cenum Promelaast.Return)) - (Ctype Cil.intType) - ) - ) - ) - ) - - | PReturn (s) when inv -> - (Undefined, - Pand( - unamed( - Prel(Req, - Logic_const.term - (TLval(TVar(op_logic_var),TNoOffset)) - (Ctype Cil.intType), - Logic_const.term - (TConst(func_to_cenum s)) - (Ctype Cil.intType) - ) - ), - unamed ( - Prel(Req, - Logic_const.term - (TLval(TVar(status_logic_var),TNoOffset)) - (Ctype Cil.intType), - Logic_const.term - (TConst(op_status_to_cenum Promelaast.Return)) - (Ctype Cil.intType) - ) - ) - ) - ) - - - - | PCallOrReturn (s) when inv -> - (Undefined, - Prel(Req, - Logic_const.term - (TLval(TVar(op_logic_var),TNoOffset)) (Ctype Cil.intType), - Logic_const.term (TConst(func_to_cenum s)) + | TCall (kf,b) when inv -> + let s = Kernel_function.get_name kf in + let res = + [ prel(Req, + Logic_const.tvar op_logic_var, + Logic_const.term (TConst(func_to_cenum s)) + (Ctype (func_enum_type())) + ); + prel(Req, + Logic_const.tvar status_logic_var, + Logic_const.term + (TConst(op_status_to_cenum Promelaast.Call)) + (Ctype (status_enum_type())) + )] + in + let res = + match b with + None -> res + | Some b -> + List.rev_append + (List.rev_map + Logic_utils.named_of_identified_predicate b.b_assumes) + res + in + (Undefined, Logic_const.pands res) + | TReturn kf when inv -> + let s = Kernel_function.get_name kf in + (Undefined, + Logic_const.pand( + prel(Req, + Logic_const.term + (TLval(TVar(op_logic_var),TNoOffset)) + (Ctype Cil.intType), + Logic_const.term + (TConst(func_to_cenum s)) (Ctype Cil.intType) - ) - ) - - - - - - - (* Call and return are statically defined -- Case where inv = false *) - | PFuncParam (hash, _, _) -> - (Undefined, get_pred_from_tmpident hash) - - | PFuncReturn (hash, f) -> - let vi = (get_returninfo f) in - (Undefined, - Cil_manipulation.predicate_substitution - (get_pred_from_tmpident hash) - [vi.vname] - [TResult (vi.vtype)]) - - - | PCall (_) - | PReturn (_) - | PCallOrReturn (_) -> - (Bool3.True, Ptrue) - - - - - (* Other expressions are left unchanged *) - | PTrue -> (Bool3.True, Ptrue) - | PFalse -> (Bool3.False, Pfalse) - - | PIndexedExp(s) -> (Undefined,get_pred_from_tmpident s) - - in - try - let (_,res) = convert cross in - res - with - | _ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Not_found exception during term conversion.\n" - - - - - -(* ************************************************************************* *) -(** {b Buchi automata and C code synchronisation } *) - -let rec mk_expr_disjunction expr_l = - match expr_l with - | [] -> assert false - | expr::[] -> expr - | expr::l -> new_exp ~loc:expr.eloc - (BinOp(LOr, expr,mk_expr_disjunction l,Cil.intType)) - - -let conj_crosscond_old (value,cross) expr = - if value=Bool3.True - then expr - else new_exp ~loc:expr.eloc (BinOp (LAnd,cross,expr,Cil.intType)) - - - - -(** Computed formula : OR(tr) (crosscond(tr) && i==curStateTMP[transStart(tr)])*) -(** It remains only to affect this result to curState[state]*) -let upd_one_state trans_l statenum (*func status*) loc computedIsCrossTr (*nbTransitions*) allowedActiveSt= - let expr_l=ref [] in - List.iter - (fun tr -> - if (statenum=tr.stop.nums) && (computedIsCrossTr.(tr.numt)) && allowedActiveSt.(statenum) then - ( - (*if (nbTransitions>1) then*) - expr_l := - (new_exp ~loc (Lval(mk_int_offseted_array_lval curTrans tr.numt)) - ::!expr_l) - (*else - expr_l := (mk_int_exp 1)::!expr_l*) - ) - ) - trans_l; - - let expr = - if !expr_l=[] then mk_int_exp 0 - else mk_expr_disjunction !expr_l - in - let offset = Cil.new_exp ~loc (Const (CEnum (find_enum statenum))) - in - Cil_types.Set( - (mk_offseted_array_lval curState offset), - expr, - loc - ) - - - -(** Computed formula : crosscond(trans) && curStateTMP[transStart(trans)] && curState[transStop(trans)]*) -(** It remains only to affect this result to curTrans[trans]*) -let upd_one_trans trans func status loc allowedCrossableTr computedIsActiveSt sid = - let getNamedOffset s = Cil.new_exp ~loc (Const (CEnum (find_enum s.nums))) in - let b = ref true in - let expr= - if allowedCrossableTr.(trans.numt) && (computedIsActiveSt.(trans.start.nums)) then -(* (isCrossable trans func status) && (computedIsActiveSt.(trans.start.nums)) then *) - conj_crosscond_old - (crosscond_to_exp trans.cross func status sid) - (new_exp ~loc - (Lval(mk_offseted_array_lval curStateOld (getNamedOffset trans.start)))) - - - else - begin - b:=false; - (mk_int_exp 0) - end - in - (!b, - Cil_types.Set( - (mk_int_offseted_array_lval curTrans trans.numt), - expr, - loc - )) - - -(** This function returns the list of instructions that have to be introduced just before each call of function and each return of function. These instructions correspond to the synchronisation between C code and Buchi automata. The parameters are : - @param The buchi automata - @param func the name of the function that is called or that returns - @param status the status of this action (call or return) - @param loc the localisation associated to this generated code - @param caller the name of the caller (if any) - @param sid the stmt id of the call (if any) -*) -let synch_upd_linear (state_l,trans_l) func status loc caller sid = - (* WARNING ! The order of these operations is very important. - - Step 1 has to be done after the Step 0 and before the steps 2 and 3. - Step 4 has to be done after the Step 3. - *) - - - (* Step 0 : define new value of current operation and its status *) - let inst_curop_upd = - Set( - Cil.var (get_varinfo curOp), - new_exp ~loc (Const(func_to_cenum (func))), - loc - ) - in - let inst_curopstatus_upd = - Set( - Cil.var (get_varinfo curOpStatus), - new_exp ~loc (Const(op_status_to_cenum status)), - loc - ) - in - - (* Step 0 : computing active states, according to result from AI *) -(* let computedIsOldActiveSt= if status=Promelaast.Return then get_pre_return func else get_pre_call func in - let nbOldActiveStates=Array.fold_left (fun old b -> if b then old+1 else old) 0 computedIsActiveSt in*) - - - - (* TODO : caller et sid sont des options. Donc il faut les extraire avec un map seulement si status = call. - Il faut donc, autant que possible factoriser ce test une unique fois. - *) - - - (* Getting crossable transitions and active states from spec. *) - let allowedActiveSt,allowedCrossableTr,computedIsOldActiveSt= - if status=Promelaast.Call then - begin - (* Case of call *) - let activeSt,crossedTr = get_func_pre ~securised:true func in - let caller,sid = - match caller,sid with - | Some(c),Some(i) -> c,i - | _ -> assert false - in - let oldSt = (fst (Data_for_aorai.get_func_pre_call caller sid)) (*Si call alors on capture l'etat atteignable avec l'appel*) - in - (activeSt,crossedTr,oldSt) - end - else - begin - (* Case of return *) - let activeSt,crossedTr = pre_flattening (get_func_post_bycase ~securised:true func) in - let oldSt = Array.make(getNumberOfStates()) false in - List.iter - (fun tr -> if crossedTr.(tr.numt) then oldSt.(tr.start.nums) <- true) - trans_l ; - (activeSt,crossedTr,oldSt) - end - in - -(* (* Deducting allowed old active states. During this computation, the number of old active state is also computed. *) - let computedIsOldActiveSt = - if status=Promelaast.Call - then fst (Data_for_aorai.get_func_pre_call caller sid) (*Si call alors capture l'etat atteignable avec l'appel*) - else Array.make(getNumberOfStates()) false in (* Sinon : return est unique dans la fonction. Les etats anciennement actifs sont les origines des transitions. On construit OldActive a partir des transitions. *) - (*let computedIsOldActiveSt = if status=Promelaast.Return then get_pre_return func else get_pre_call func in*) - if status=Promelaast.Return then - List.iter - (fun tr -> - if (allowedCrossableTr.(tr.numt)) && not (computedIsOldActiveSt.(tr.start.nums)) then - computedIsOldActiveSt.(tr.start.nums) <- true - ) - trans_l ; -*) - - - (* Step 1 : update of Old states *) - (* This generation use allowed states wrt spec, and simplify cases with a single old active state *) - let step_one_inst = - List.fold_left - (fun inst_l st -> - let getNamedOffset s = Cil.new_exp ~loc (Const (CEnum (find_enum s.nums))) - in - - let rightPart = - if(computedIsOldActiveSt.(st.nums)) then - new_exp ~loc (Lval(mk_offseted_array_lval curState (getNamedOffset st))) - else - (mk_int_exp 0) - in - - ((Cil_types.Set( - (mk_offseted_array_lval curStateOld (getNamedOffset st)), - rightPart, - loc - ))::inst_l) - - ) - (inst_curopstatus_upd::[inst_curop_upd]) - state_l - in - - (* Step 2 : State_builder.of crossable transitions *) - (* Only crossable transitions wrt spec are considered. *) - let computedIsCrossTr= Array.make(getNumberOfTransitions()) false in - (*let nbTransitions = ref 0 in *) - let step_two_inst = - List.fold_left - (fun inst_l tr -> - let (b,r) = (upd_one_trans tr func status loc allowedCrossableTr computedIsOldActiveSt sid) in - (Array.set computedIsCrossTr tr.numt b; - (*(if b then nbTransitions:=!nbTransitions+1);*) - r::inst_l - ) + ), + prel(Req, + Logic_const.term + (TLval(TVar(status_logic_var),TNoOffset)) + (Ctype Cil.intType), + Logic_const.term + (TConst(op_status_to_cenum Promelaast.Return)) + (Ctype Cil.intType) + ) + ) ) - step_one_inst - trans_l - in + | TCall (f,b) -> + let pred = match b with + None -> Bool3.True, ptrue + | Some b -> + (Bool3.Undefined, + Logic_const.pands + (List.map Logic_utils.named_of_identified_predicate b.b_assumes)) + in + check_current_event f Promelaast.Call pred + | TReturn f -> + check_current_event f Promelaast.Return (Bool3.True, ptrue) - (* Step 3 : State_builder.of reachable states *) - let step_three_inst = - List.fold_left - (fun inst_l st -> - (upd_one_state trans_l st.nums loc computedIsCrossTr - (*!nbTransitions*) allowedActiveSt) - ::inst_l) - step_two_inst - state_l + (* Other expressions are left unchanged *) + | TTrue -> (Bool3.True, ptrue) + | TFalse -> (Bool3.False, pfalse) + | TRel(rel,t1,t2) -> + (Bool3.Undefined, Logic_const.prel (rel,t1,t2)) in - - step_three_inst - - - - - - -(** This function returns the list of instructions that have to be introduced just before each call of function and each return of function. These instructions correspond to the synchronisation between C code and Buchi automata. The parameters are : - @param automata The buchi automata - @param func the name of the function that is called or that returns - @param status the status of this action (call or return) - @param loc the localisation associated to this generated code - @param caller the name of the caller (if any) - @param sid the stmt id of the call (if any) -*)let synch_upd automata func status loc caller sid = - synch_upd_linear automata func status loc caller sid - - + snd (convert cross) (* ************************************************************************* *) (** {b Globals management} *) @@ -1170,31 +680,27 @@ Data_for_aorai.setCData (); (* Adding C variables into our hashtable *) Globals.Vars.iter (fun vi _ -> set_varinfo vi.vname vi); - Globals.Functions.iter(fun kf -> - let fname = Kernel_function.get_name kf in - List.iter - (fun vi -> - set_paraminfo fname vi.vname vi) - (Kernel_function.get_formals kf); - - if not (Data_for_aorai.isIgnoredFunction fname) then - begin - let fund = (Kernel_function.get_definition kf) in - let bodys = fund.sbody.bstmts in - let ret = List.hd (List.rev bodys) in - match ret.skind with - | Return (Some e,_) -> - let en = e.enode in - begin - match en with - | Lval (Var vi,NoOffset) -> set_returninfo fname vi (* Add the vi of return stmt *) - | _ -> ()(* function without returned value *) - end - - | _ -> () (* function without returned value *) - end - ) - + Globals.Functions.iter + (fun kf -> + let fname = Kernel_function.get_name kf in + List.iter + (fun vi -> set_paraminfo fname vi.vname vi) + (Kernel_function.get_formals kf); + if not (Data_for_aorai.isIgnoredFunction fname) then + begin + try + let ret = Kernel_function.find_return kf in + match ret.skind with + | Cil_types.Return (Some e,_) -> + (match e.enode with + | Lval (Var vi,NoOffset) -> + set_returninfo fname vi (* Add the vi of return stmt *) + | _ -> () (* function without returned value *)) + | _ -> () (* function without returned value *) + with Kernel_function.No_Statement -> + Aorai_option.fatal + "Don't know what to do with a function declaration" + end) (** List of globals awaiting for adding into C file globals *) let globals_queue = ref [] @@ -1203,8 +709,8 @@ let flush_globals () = let (before,after)=List.fold_left (fun (b,a) elem -> - match elem with - | GFun(f,loc) as func -> + match elem with + | GFun(f,loc) as func -> (* [VP] if address of function is taken, it might be used in a global initializer: keep a declaration at this point to ensure ending up with a compilable C file in the end... @@ -1215,45 +721,53 @@ else b in (b,func::a) - | _ as other -> (other::b,a) + | other -> (other::b,a) ) ([],[]) !file.globals in !file.globals <- (List.rev before)@(List.rev !globals_queue)@(List.rev after); -(* !file.globals <- (List.rev !globals_queue)@(!file.globals);*) + Kernel_function.clear_sid_info (); globals_queue:=[] - - - +let mk_global glob = globals_queue:=glob::(!globals_queue) (* Utilities for global variables *) let mk_global_c_initialized_vars name ty ini= - let vi = (Cil.makeGlobalVar ~logic:true name ty) in + let vi = (Cil.makeGlobalVar name ty) in vi.vghost<-true; - globals_queue:=GVar(vi,ini,vi.vdecl)::(!globals_queue); + mk_global (GVar(vi,ini,vi.vdecl)); Globals.Vars.add vi ini; set_varinfo name vi +let mk_global_var vi = + vi.vghost<-true; + let ini = + {Cil_types.init=Some(Cil.makeZeroInit ~loc:(CurrentLoc.get()) vi.vtype)} + in + mk_global (GVar(vi,ini,vi.vdecl)); + Globals.Vars.add vi ini; + set_varinfo vi.vname vi let mk_global_c_vars name ty = - let vi = (Cil.makeGlobalVar ~logic:true name ty) in - vi.vghost<-true; - let ini = - {init=Some(Cil.makeZeroInit ~loc:(CurrentLoc.get()) ty)} - in - globals_queue:=GVar(vi,ini,vi.vdecl)::(!globals_queue); - Globals.Vars.add vi ini; - set_varinfo name vi + let vi = (Cil.makeGlobalVar name ty) in + mk_global_var vi +let mk_global_c_var_init name init = + let ty = Cil.typeOf init in + let vi = Cil.makeGlobalVar name ty in + vi.vghost <- true; + let ini = { Cil_types.init = Some(SingleInit init) } in + mk_global(GVar(vi,ini,vi.vdecl)); + Globals.Vars.add vi ini; + set_varinfo name vi let mk_int_const value = - new_exp + new_exp ~loc:(CurrentLoc.get()) (Const( CInt64( - Int64.of_int (value), + My_bigint.of_int (value), IInt, Some(string_of_int(value)) ))) @@ -1285,26 +799,20 @@ let ty = (TInt(IInt,[])) in mk_global_c_vars name ty - - - - - (* Utilities for global enumerations *) - - let mk_global_c_enum_type_tagged name elements_l = let einfo = { eorig_name = name; ename = name; eitems = []; eattr = []; - ereferenced = true } + ereferenced = true; + ekind = IInt; } in let l = List.map (fun (e,i) -> - { eiorig_name = e; + { eiorig_name = e; einame = e; eival = mk_int_const i; eiloc = Location.unknown; @@ -1313,7 +821,7 @@ in einfo.eitems <- l; set_usedinfo name einfo; - globals_queue := GEnumTag(einfo, Location.unknown)::(!globals_queue); + mk_global (GEnumTag(einfo, Location.unknown)); einfo let mk_global_c_enum_type name elements = @@ -1337,14 +845,14 @@ (** {b Terms management / computation} *) (** Return an integer constant term from the given value. *) -let mk_int_term value = - Logic_const.term - (TConst( CInt64(Int64.of_int value,IInt,Some(string_of_int value)))) - (Ctype Cil.intType) +let mk_int_term value = Cil.lconstant (My_bigint.of_int value) + +(** Return an integer constant term with the 0 value. + @deprecated use directly Cil.lzero +*) +let zero_term() = Cil.lzero () -(** Return an integer constant term with the 0 value. *) -let zero_term() = - mk_int_term 0 +let one_term () = Cil.lconstant My_bigint.one (** Returns a term representing the given logic variable (usually a fresh quantified variable). *) let mk_term_from_logic_var lvar = @@ -1356,6 +864,7 @@ (TLval((Logic_utils.lval_to_term_lval ~cast:true (Cil.var vi)))) (Ctype Cil.intType) +let mk_trans_cst i = mk_int_term i (** Given an lval term 'host' and an integer value 'off', it returns a lval term host[off]. *) let mk_offseted_array host off = @@ -1364,15 +873,19 @@ (Ctype Cil.intType) let int2enumstate nums = - Logic_const.term - (TConst (CEnum (find_enum nums))) + let enum = find_enum nums in + Logic_const.term (TConst (CEnum enum)) (Ctype (TEnum (enum.eihost,[]))) (** Given an lval term 'host' and an integer value 'off', it returns a lval term host[off]. *) let mk_offseted_array_states_as_enum host off = + let enum = find_enum off in Logic_const.term - (TLval(Cil.addTermOffsetLval (TIndex(mk_dummy_term - (TConst(CEnum (find_enum off))) - Cil.intType,TNoOffset)) host)) + (TLval + (Cil.addTermOffsetLval + (TIndex(Logic_const.term + (TConst(CEnum enum)) (Ctype (TEnum (enum.eihost,[]))), + TNoOffset)) + host)) (Ctype Cil.intType) @@ -1404,9 +917,9 @@ (Ctype Cil.intType) (** Returns a lval term associated to the curState generated variable. *) -let host_state_term () = +let host_state_term() = lval_to_term_lval ~cast:true (Cil.var (get_varinfo curState)) - +(* (** Returns a lval term associated to the curStateOld generated variable. *) let host_stateOld_term () = lval_to_term_lval ~cast:true (Cil.var (get_varinfo curStateOld)) @@ -1414,36 +927,52 @@ (** Returns a lval term associated to the curTrans generated variable. *) let host_trans_term () = lval_to_term_lval ~cast:true (Cil.var (get_varinfo curTrans)) +*) +let state_term () = + Logic_const.tvar (Cil.cvar_to_lvar (get_varinfo curState)) +(* +let stateOld_term () = + Logic_const.tvar (Cil.cvar_to_lvar (get_varinfo curStateOld)) +let trans_term () = + Logic_const.tvar (Cil.cvar_to_lvar (get_varinfo curTrans)) +*) +let is_state_pred state = + if Aorai_option.Deterministic.get () then + Logic_const.prel (Req,state_term(),int2enumstate state.nums) + else + Logic_const.prel (Req,one_term(), + mk_offseted_array_states_as_enum + (host_state_term()) state.nums) + +let is_out_of_state_pred state = + if Aorai_option.Deterministic.get () then + Logic_const.prel (Rneq,state_term(),int2enumstate state.nums) + else + Logic_const.prel (Req,zero_term(), + mk_offseted_array_states_as_enum + (host_state_term()) state.nums) - - -(** Given a logic variable and two bounces, it returns the predicate: min<=v host1[i]==host2[i]) *) let mk_eq_tables host_name1 host_name2 size = let lval1 = lval_to_term_lval ~cast:true ( Cil.var (get_varinfo host_name1)) in let lval2 = lval_to_term_lval ~cast:true ( Cil.var (get_varinfo host_name2)) in let tmp_i = Cil_const.make_logic_var "_buch_i" Cil_types.Linteger in - Pforall([tmp_i], - unamed ( - Pimplies ( - unamed ( mk_logicvar_intervalle tmp_i 0 size), - unamed ( - Prel(Req, - mk_offseted_array_lval_from_lval lval1 tmp_i , - mk_offseted_array_lval_from_lval lval2 tmp_i - ) - ) - )) - ) + pforall([tmp_i], + pimplies + (mk_logicvar_intervalle tmp_i 0 size, + prel(Req, + mk_offseted_array_lval_from_lval lval1 tmp_i , + mk_offseted_array_lval_from_lval lval2 tmp_i))) - -(** Given a name of generated array and its size, it returns the expression: (Valide_range(name,0,size-) *) +(** Given a name of generated array and its size, it returns the expression: + (Valid_range(name,0,size-1) *) let mk_valid_range name size = let var = get_varinfo name in let lval = lval_to_term_lval ~cast:true (Cil.var var) in @@ -1455,30 +984,16 @@ let lstyp = Logic_const.make_set_type ltyp in Pvalid(term (TBinOp(PlusPI,(term (TLval lval) ltyp),range)) lstyp) -let mk_conjunction pred_l = - (Logic_const.pands (List.map unamed pred_l)).content - -let mk_conjunction_named = Logic_const.pands - -let mk_disjunction pred_l = - (Logic_const.pors (List.map unamed pred_l)).content - -let mk_disjunction_named = Logic_const.pors - (* Utilities for other globals *) - let mk_global_invariant pred name = let li = Cil_const.make_logic_info name in - li.l_body <- LBpred(unamed pred); - globals_queue:= - GAnnot (Cil_types.Dinvariant (li, Location.unknown), Location.unknown) - :: !globals_queue - - -let mk_global_comment txt = - globals_queue:=GText (txt)::(!globals_queue) + li.l_body <- LBpred pred; + let annot = Cil_types.Dinvariant (li,Location.unknown) in + Globals.Annotations.add_user annot; + mk_global (GAnnot (annot, Location.unknown)) +let mk_global_comment txt = mk_global (GText (txt)) (** Given + the name of the logic (string), @@ -1490,42 +1005,38 @@ A side effect of this function is the registration of this logic into the logics hashtbl from Data_for_aorai. *) let mk_global_logic name (*generics_l*) types_l type_ret (*reads*) = let log_info = Cil_const.make_logic_info name in - log_info.l_type <- type_ret; (* return type. *) - log_info.l_profile <- types_l;(* type of the arguments. *) + log_info.l_type <- type_ret; (* return type. *) + log_info.l_profile <- types_l;(* type of the arguments. *) (* - l_labels = []; (* label arguments of the function. *) - l_body = LBreads([]); (* body of the function. *) + l_labels = []; (* label arguments of the function. *) + l_body = LBreads([]); (* body of the function. *) l_tparams = [] *) Data_for_aorai.add_logic name log_info; Dfun_or_pred(log_info, Location.unknown) - let mk_global_axiom name pred = Dlemma (name, true, [], [], unamed pred, Location.unknown) - - - let mk_global_predicate name moment params_l pred = (*let log_var_params = List.map (fun p -> Cil.make_logic_var p Linteger) params_l in *) let pred_info= Cil_const.make_logic_info name in - (* name of the predicate. *) + (* name of the predicate. *) pred_info.l_profile <- params_l; (*log_var_params;*) - (* arguments of the predicate. *) + (* arguments of the predicate. *) pred_info.l_labels <- List.map (fun x -> LogicLabel(None, x)) moment; - (* label arguments. *) - pred_info.l_body <- LBpred(unamed pred); (* definition. *) + (* label arguments. *) + pred_info.l_body <- LBpred pred; (* definition. *) (* - pred_info.l_type <- None; (* return type. *) + pred_info.l_type <- None; (* return type. *) pred_info.l_tparams <- [] *) Data_for_aorai.add_predicate name pred_info; - globals_queue:= - GAnnot(Dfun_or_pred(pred_info, Location.unknown), Location.unknown) - :: !globals_queue - + let annot = Dfun_or_pred(pred_info, Location.unknown) in + Globals.Annotations.add_user annot; + mk_global (GAnnot(annot, Location.unknown)) +(* (** Generates an axiomatisation of transitions from automata into globals. These annotations are used to express some pre and post condition properties *) let mk_decl_axiomatized_automata () = @@ -1539,21 +1050,20 @@ let annotlist=List.fold_left (fun res tr -> (mk_global_axiom - (transStart^(string_of_int tr.numt)) - (Prel(Req, - Logic_const.term - (Tapp(tr_start_log_info,[],[mk_int_term tr.numt])) - (Ctype Cil.intType), - (getNamedOffset tr.start) - )) + (transStart^(string_of_int tr.numt)) + (Prel(Req, + Logic_const.term + (Tapp(tr_start_log_info,[],[mk_int_term tr.numt])) + (Ctype Cil.intType), + (getNamedOffset tr.start) + )) )::res ) [logic] trans_l in - globals_queue:= - (GAnnot(Daxiomatic(transStart,List.rev annotlist, Location.unknown), - Location.unknown)) - :: !globals_queue; + let annot = Daxiomatic(transStart,List.rev annotlist, Location.unknown) in + Globals.Annotations.add_user annot; + mk_global (GAnnot(annot, Location.unknown)); let logic=mk_global_logic transStop (*[]*) [param] (Some Linteger) (*[]*) (*[TSSingleton(TSLval(TSVar(param),TSNo_offset))]*) in @@ -1561,41 +1071,39 @@ let annotlist=List.fold_left (fun res tr -> (mk_global_axiom - (transStop^(string_of_int tr.numt)) - (Prel(Req, - Logic_const.term - (Tapp(tr_stop_log_info,[],[mk_int_term tr.numt])) - (Ctype Cil.intType), - (getNamedOffset tr.stop))) + (transStop^(string_of_int tr.numt)) + (Prel(Req, + Logic_const.term + (Tapp(tr_stop_log_info,[],[mk_int_term tr.numt])) + (Ctype Cil.intType), + (getNamedOffset tr.stop))) )::res ) [logic] trans_l in - - globals_queue:= - (GAnnot(Daxiomatic(transStop, List.rev annotlist, Location.unknown), - Location.unknown)) - :: !globals_queue; + let annot = Daxiomatic(transStop, List.rev annotlist, Location.unknown) in + Globals.Annotations.add_user annot; + mk_global (GAnnot(annot, Location.unknown)); let num= Cil_const.make_logic_var "_aorai_numTrans" Linteger in let op = Cil_const.make_logic_var "_aorai_op" Linteger in let st = Cil_const.make_logic_var "_aorai_status" Linteger in let pred = - mk_conjunction + Logic_const.pands (List.map - (fun tr -> - Pimplies( - unamed (Prel(Req, mk_term_from_logic_var num, mk_int_term tr.numt)), - unamed (crosscond_to_pred true tr.cross op st) - ) - ) - trans_l + (fun tr -> + pimplies( + crosscond_to_pred tr.cross op st, + prel(Req, mk_term_from_logic_var num, mk_int_term tr.numt) + ) + ) + trans_l ) in mk_global_predicate transCondP ["L"] [num;op;st] pred; let pred2 = - Papp( + papp( Data_for_aorai.get_predicate transCondP, [(LogicLabel(None,"L"),LogicLabel(None,"L"))], [mk_term_from_logic_var num; @@ -1605,87 +1113,41 @@ ) in mk_global_predicate transCond ["L"] [num] pred2 - - - - - +*) (* ************************************************************************* *) (** {b Initialization management / computation} *) - let get_states_trans_init root = let (states,trans) = Data_for_aorai.getAutomata () in - let st_old_exps = (Array.make (List.length states) (mk_int_exp 0)) in let st_exps = (Array.make (List.length states) (mk_int_exp 0)) in - let tr_exps = (Array.make (List.length trans ) (mk_int_exp 0)) in - let acc_exps = (Array.make (List.length states) (mk_int_exp 0)) in List.iter ( fun tr -> - if (tr.start.Promelaast.init==Bool3.True) && (isCrossableAtInit tr root) then - begin - Array.set tr_exps tr.numt (mk_int_exp 1); - Array.set st_exps tr.stop.nums (mk_int_exp 1); - Array.set st_old_exps tr.start.nums (mk_int_exp 1) - end + if (tr.start.Promelaast.init==Bool3.True) && + (isCrossableAtInit tr root) + then + begin + Array.set st_exps tr.start.nums (mk_int_exp 1); + end ) trans; - List.iter ( - fun st -> - if (st.acceptation==Bool3.True) then - begin - Array.set acc_exps st.nums (mk_int_exp 1); - end - ) states; - let st_old_init = - Array.mapi ( - fun i exp -> - (*Chaque cas doit contenir : (offset * init)*) - (Index(mk_int_exp i,NoOffset),SingleInit(exp)) - ) st_old_exps - in let st_init = Array.mapi ( fun i exp -> - (*Chaque cas doit contenir : (offset * init)*) - (Index(mk_int_exp i,NoOffset),SingleInit(exp)) + (*Chaque cas doit contenir : (offset * init)*) + (Index(mk_int_exp i,NoOffset),SingleInit(exp)) ) st_exps in - let tr_init = - Array.mapi ( - fun i exp -> - (Index(mk_int_exp i,NoOffset),SingleInit(exp)) - ) tr_exps - in - let acc_init = - Array.mapi ( - fun i exp -> - (Index(mk_int_exp i,NoOffset),SingleInit(exp)) - ) acc_exps - in - ( - {init=Some(CompoundInit(Cil.intType, Array.to_list st_old_init))}, - {init=Some(CompoundInit(Cil.intType, Array.to_list st_init))}, - {init=Some(CompoundInit(Cil.intType, Array.to_list tr_init))}, - {init=Some(CompoundInit(Cil.intType, Array.to_list acc_init))} - ) - + {Cil_types.init=Some(CompoundInit(Cil.intType, Array.to_list st_init))} let func_to_init name = - {init=Some(SingleInit( - new_exp ~loc:(CurrentLoc.get()) (Const(func_to_cenum (name)))))} + {Cil_types.init= + Some(SingleInit( + new_exp ~loc:(CurrentLoc.get()) (Const(func_to_cenum (name)))))} let funcStatus_to_init st = - {init=Some(SingleInit(new_exp ~loc:(CurrentLoc.get()) - (Const(op_status_to_cenum (st)))))} - - - - - - - + {Cil_types.init=Some(SingleInit(new_exp ~loc:(CurrentLoc.get()) + (Const(op_status_to_cenum (st)))))} class visit_decl_loops_init () = object (*(self) *) @@ -1695,8 +1157,8 @@ method vstmt_aux stmt = begin match stmt.skind with - | Loop _ -> mk_global_c_vars (Data_for_aorai.loopInit^"_"^(string_of_int stmt.sid)) (TInt(IInt,[])) - | _ -> () + | Loop _ -> mk_global_c_vars (Data_for_aorai.loopInit^"_"^(string_of_int stmt.sid)) (TInt(IInt,[])) + | _ -> () end; Cil.DoChildren end @@ -1705,554 +1167,328 @@ let visitor = new visit_decl_loops_init () in Cil.visitCilFile (visitor :> Cil.cilVisitor) !file +let change_vars subst subst_res kf label pred = + let add_label t = ChangeDoChildrenPost(t,fun t -> tat(t,label)) in + let visitor = + object + inherit Visitor.frama_c_copy (Project.current()) + + method vterm t = + match t.term_node with + TLval (TVar { lv_origin = Some v},_) when v.vglob -> add_label t + | TLval (TMem _,_) -> add_label t + | _ -> DoChildren + + method vterm_lhost = function + | TResult ty -> + (match kf with + None -> Aorai_option.fatal + "found \\result without being at a Return event" + | Some kf -> + (try + ChangeTo (TVar (Kernel_function.Hashtbl.find subst_res kf)) + with Not_found -> + let new_lv = + Cil_const.make_logic_var + ("__retres_" ^ (Kernel_function.get_name kf)) (Ctype ty) + in + Kernel_function.Hashtbl.add subst_res kf new_lv; + ChangeTo (TVar new_lv))) + | TMem _ | TVar _ -> DoChildren + + method vlogic_var_use lv = + match lv.lv_origin with + | Some v when not v.vglob -> + (try + ChangeTo (Cil_datatype.Logic_var.Hashtbl.find subst lv) + with Not_found -> + let new_lv = Cil_const.make_logic_var lv.lv_name lv.lv_type in + Cil_datatype.Logic_var.Hashtbl.add subst lv new_lv; + ChangeTo new_lv) + | Some _ | None -> DoChildren + end + in Visitor.visitFramacPredicate visitor pred +let make_prev_pred func status st auto_state = + let (_,tr_state) = auto_state in + let auto = Data_for_aorai.getAutomata () in + let trans = Path_analysis.get_transitions_to_state st auto in + let event = (func, status) in + let op = Data_for_aorai.get_logic_var Data_for_aorai.curOp in + let func_status = Data_for_aorai.get_logic_var Data_for_aorai.curOp in + List.fold_left + (fun conds tr -> + if tr_state.(tr.numt) then + let cond, _ = tr.cross in + let my_pred = + Logic_const.pand + (is_state_pred tr.start, + crosscond_to_pred ~event cond op func_status) + in + Logic_const.por (my_pred,conds) + else conds (* transition can't be taken at that point. *) + ) + pfalse trans + +let make_prev_pred_neg func status st auto_state = + let (_,tr_state) = auto_state in + let auto = Data_for_aorai.getAutomata () in + let treat_one (start_states, cond1) st = + let trans = Path_analysis.get_transitions_to_state st auto in + let event = (func, status) in + let op = Data_for_aorai.get_logic_var Data_for_aorai.curOp in + let func_status = Data_for_aorai.get_logic_var Data_for_aorai.curOp in + let start_states, cond2 = + List.fold_left + (fun (start_states,conds as acc) tr -> + if tr_state.(tr.numt) then + let cond, _ = tr.cross in + let my_pred = + Logic_const.pand + (is_state_pred tr.start, + Logic_const.pnot + (crosscond_to_pred ~event cond op func_status)) + in + Data_for_aorai.Aorai_state.Set.add tr.start start_states, + Logic_const.por (my_pred,conds) + else acc) + (start_states,pfalse) trans + in start_states, Logic_const.pand (cond1, cond2) + in + let (start_states, cond) = + List.fold_left treat_one (Data_for_aorai.Aorai_state.Set.empty,ptrue) st + in + let not_start = + Data_for_aorai.Aorai_state.Set.fold + (fun st acc -> Logic_const.pand (is_out_of_state_pred st,acc)) + start_states ptrue + in + Logic_const.por (cond, not_start) + +let pred_of_condition subst subst_res label cond = + let mk_func_event f = + let op = tat (mk_term_from_vi (get_varinfo curOp),label) in + (* [VP] TODO: change int to appropriate enum type. Also true + elsewhere. + *) + let f = term (TConst (func_to_cenum f)) (Ctype (func_enum_type ())) in + prel (Req,op,f) + in + let mk_func_status f status = + let curr = tat (mk_term_from_vi (get_varinfo curOpStatus),label) in + let call = + term (TConst (op_status_to_cenum status)) (Ctype (status_enum_type())) + in Logic_const.pand (mk_func_event f, prel(Req,curr,call)) + in + let mk_func_start f = mk_func_status f Promelaast.Call in + let mk_func_return f = mk_func_status f Promelaast.Return in + let rec aux kf pos = function + | TOr(c1,c2) -> + kf, Logic_const.por (snd (aux kf pos c1), snd (aux kf pos c2)) + | TAnd(c1,c2) -> + let kf, c1 = aux kf pos c1 in + let kf, c2 = aux kf pos c2 in + kf, Logic_const.pand (c1, c2) + | TNot c -> let kf, c = aux kf (not pos) c in kf, Logic_const.pnot c + | TCall (s,b) -> + let pred = mk_func_start (Kernel_function.get_name s) in + let pred = + match b with + | None -> pred + | Some b -> + Logic_const.pands + (pred :: + (List.map + Logic_utils.named_of_identified_predicate b.b_assumes)) + in + kf, pred + | TReturn s -> + let kf = if pos then Some s else kf in + kf, mk_func_return (Kernel_function.get_name s) + | TTrue -> kf, ptrue + | TFalse -> kf, pfalse + | TRel(rel,t1,t2) -> + kf, + unamed (change_vars subst subst_res kf label (prel (rel,t1,t2)).content) + in snd (aux None true cond) + +let mk_deterministic_lemma () = + let automaton = Data_for_aorai.getAutomata () in + let make_one_lemma state = + let label = Cil_types.LogicLabel(None, "L") in + let disjoint_guards acc trans1 trans2 = + if trans1.numt <= trans2.numt then acc + (* don't need to repeat the same condition twice*) + else + let subst = Cil_datatype.Logic_var.Hashtbl.create 5 in + let subst_res = Kernel_function.Hashtbl.create 5 in + let guard1 = + pred_of_condition subst subst_res label (fst trans1.cross) + in + let guard2 = + pred_of_condition subst subst_res label (fst trans2.cross) + in + let pred = Logic_const.pnot (Logic_const.pand (guard1, guard2)) in + let quants = + Cil_datatype.Logic_var.Hashtbl.fold + (fun _ lv acc -> lv :: acc) subst [] + in + let quants = Kernel_function.Hashtbl.fold + (fun _ lv acc -> lv :: acc) subst_res quants + in + (* [VP] far from perfect, but should give oracles for + regression tests that stay relatively stable across vid + changes. *) + let quants = + List.sort (fun v1 v2 -> String.compare v1.lv_name v2.lv_name) quants + in + Logic_const.pand (acc, (pforall (quants, pred))) + in + let trans = Path_analysis.get_transitions_of_state state automaton in + let prop = Extlib.product_fold disjoint_guards ptrue trans trans in + let name = state.Promelaast.name ^ "_deterministic_trans" in + let lemma = + Dlemma (name, false, [label],[],prop,Cil_datatype.Location.unknown) + in + Globals.Annotations.add_user lemma; + mk_global (GAnnot(lemma,Cil_datatype.Location.unknown)) + in + List.iter make_one_lemma (fst automaton) - - - - - - - - - - - -let mk_invariant_1 () = - mk_global_comment "//* Inv 1 : Each not reachable state is not active"; - let tmp_st = Cil_const.make_logic_var "_buch_st" Cil_types.Linteger in - let tmp_tr = Cil_const.make_logic_var "_buch_tr" Cil_types.Linteger in - mk_global_invariant ( - Pforall( - [tmp_st], - unamed (Pimplies ( - unamed (Pand ( - unamed (mk_logicvar_intervalle tmp_st 0 (getNumberOfStates ())), - unamed (Pforall([tmp_tr], - unamed (Pimplies ( - unamed ( mk_logicvar_intervalle tmp_tr 0 (getNumberOfTransitions ())), - unamed ( - mk_disjunction - [ (* curTrans[tr]==0 *) - Prel(Req,mk_offseted_array_lval_from_lval (host_trans_term ()) tmp_tr , mk_int_term 0) ; - (* transStop(tr)!=st *) - Prel(Rneq,(mk_logic_call transStop [tmp_tr]), mk_term_from_logic_var tmp_st) ; - (* !transCond(tr) *) - Pnot(unamed (Papp(get_predicate transCond,[],[mk_term_from_logic_var tmp_tr]))) ; - (* curStatesOld[transStart(tr)]==0 *) - Prel(Req,mk_offseted_array_lval_from_term (host_stateOld_term()) (mk_logic_call transStart [tmp_tr]), mk_int_term 0) - ] - ) - )) - )) - )), - unamed ( - (* curStates[st]==0 *) - Prel(Req,mk_offseted_array_lval_from_lval (host_state_term()) (tmp_st), mk_int_term 0) - ) - )) - ) - ) "_Buch_st_reach_1" - - - - - - - -let mk_invariant_2 () = - mk_global_comment "//* Inv 2 : Each non-active state is not reachable"; - let tmp_st = Cil_const.make_logic_var "_buch_st" Cil_types.Linteger in - let tmp_tr = Cil_const.make_logic_var "_buch_tr" Cil_types.Linteger in - mk_global_invariant ( - Pforall( - [tmp_st], - unamed (Pimplies ( - unamed (Pand ( - (* 0 <= st + if tr.start.Promelaast.init = Bool3.True then begin + match acc, isCrossableAtInit tr root with + | _, false -> acc + | Some(false,_),_ -> acc + (* once we decide that there could be two transitions active, + stay that way. *) + | Some(true,idx), true -> Some(false,idx) + (* we already have one transition that might be active. If we find + another, we don't have unicity. *) + | None, true -> Some(true,tr.numt) + (* All transitions seen so far were not active, we have found one + that is (or might be). just take it. + *) + end else acc ) - ) "_Buch_st_reach_2" - - -let mk_invariant_3 () = - mk_global_comment "//* Inv 3 : Each active state is reachable"; - let tmp_st = Cil_const.make_logic_var "_buch_st" Cil_types.Linteger in - let tmp_tr = Cil_const.make_logic_var "_buch_tr" Cil_types.Linteger in - mk_global_invariant ( - Pforall( - [tmp_st], - unamed (Pimplies ( - unamed (Pand ( - (* 0 <= st None + | Some(false,_) -> None + | Some(true,idx) -> Some idx let make_enum_states () = let state_list =fst (Data_for_aorai.getAutomata()) in - let enum = - mk_global_c_enum_type_tagged states - (List.map - (fun x -> (x.Promelaast.name, x.Promelaast.nums)) state_list) + let state_list = + List.map (fun x -> (x.Promelaast.name, x.Promelaast.nums)) state_list in + let state_list = + if not (Aorai_option.Deterministic.get ()) then state_list + else + (*[VP] Strictly speaking this is not needed, but Jessie tends + to consider that a value of enum type can only be one of the + tags, so that we must add this dummy state that is always a + possible value, even when a contract concludes that curState + is none of the others. Note that ISO C does not impose this + limitation to values of enum types. + *) + (get_fresh "aorai_reject_state", -2)::state_list + in + let enum = mk_global_c_enum_type_tagged states state_list in let mapping = List.map - (fun x -> - let item = - List.find (fun y -> y.einame = x.Promelaast.name) enum.eitems - in - (x.nums, item)) state_list - in set_enum mapping + (fun (name,id) -> + let item = + List.find (fun y -> y.einame = name) enum.eitems + in + (id, item)) + state_list + in + set_enum mapping + +let getInitialState () = + let loc = Cil_datatype.Location.unknown in + let states = fst (Data_for_aorai.getAutomata()) in + let s = List.find (fun x -> x.Promelaast.init = Bool3.True) states in + Cil.new_exp ~loc (Const (CEnum (find_enum s.nums))) (** This function computes all newly introduced globals (variables, enumeration structure, invariants, etc. *) let initGlobals root complete = mk_global_comment "//****************"; mk_global_comment "//* BEGIN Primitives generated for LTL verification"; - - mk_global_comment "//* "; - mk_global_comment "//* States and Trans Variables"; - let (st_old_init, st_init, tr_init, (*acc_init*) _) = get_states_trans_init root in - mk_global_c_initialized_array curState (getNumberOfStates()) st_init; - mk_global_c_initialized_array curTrans (getNumberOfTransitions()) tr_init; - mk_global_c_initialized_array curStateOld (getNumberOfStates()) st_old_init; -(* mk_global_c_initialized_array curTransTmp (getNumberOfTransitions()) tr_init;*) - -(* mk_global_comment "//* "; - mk_global_comment "//* Their invariants"; - mk_global_invariant - (mk_conjunction - [(mk_valid_range curTrans (getNumberOfTransitions ())) ; -(* (mk_valid_range curTransTmp (getNumberOfTransitions ())) ;*) - (mk_valid_range curState (getNumberOfStates ())) ; - (mk_valid_range curStateOld (getNumberOfStates ())) - ]) - "Buch_Ranges_Validity"; -*) -(* mk_global_invariant - (*(mk_conjunction - [*) (mk_eq_tables curTrans curTransTmp (getNumberOfTransitions ())) (*; - (mk_eq_tables curState curStateTmp (getNumberOfStates ())) - ])*) - "Buch_Arrays_Coherence"; -*) - mk_global_comment "//* "; - (*mk_global_comment "//* Acceptation States -- UNUSED AT THIS TIME !!!"; - mk_global_c_initialized_array acceptSt (getNumberOfStates()) acc_init; - mk_global_invariant (mk_valid_range acceptSt (getNumberOfStates ())) "Buch_acc_Ranges_Validity"; - *) mk_global_comment "//* "; mk_global_comment "//* Some constants"; - mk_global_c_enum_type listOp (List.map (fun e -> func_to_op_func e) (getFunctions_from_c())); - mk_global_c_initialized_enum curOp listOp (func_to_init root); + make_enum_states (); + mk_global_c_enum_type + listOp (List.map (fun e -> func_to_op_func e) (getFunctions_from_c())); + mk_global_c_initialized_enum curOp listOp + (func_to_init (Kernel_function.get_name root)); mk_global_c_enum_type listStatus (callStatus::[termStatus]); - mk_global_c_initialized_enum curOpStatus listStatus (funcStatus_to_init Promelaast.Call); + mk_global_c_initialized_enum + curOpStatus listStatus (funcStatus_to_init Promelaast.Call); + + mk_global_comment "//* "; + mk_global_comment "//* States and Trans Variables"; + let st_init = get_states_trans_init root in + if Aorai_option.Deterministic.get () then begin + mk_global_c_var_init curState (getInitialState()); + end else begin + mk_global_c_initialized_array curState (getNumberOfStates()) st_init; + end; + if complete then begin - mk_global_comment "//* "; mk_global_comment "//* Loops management"; mk_decl_loops_init (); - - - mk_global_comment "//* "; - mk_global_comment "//**************** "; - mk_global_comment "//* Axiomatized transitions automata"; - - mk_decl_axiomatized_automata (); - - mk_global_comment "//* "; - mk_global_comment "//**************** "; - mk_global_comment "//* Safety invariants"; - mk_global_comment "//* "; - - (* mk_invariant_1 (); - mk_invariant_2 (); - mk_invariant_3 (); - mk_invariant_4 (); - mk_invariant_5 (); - mk_invariant_6 (); - *) - (*mk_invariant_1_2 (); Si remis, alors considerer qu'en cas de choix non-deterministe, seule l'une des possibilite doit necessairement etre prise. En prendre plusieurs n'est ni interdit ni obligatoire.*) - mk_invariant_2_2_1 (); - mk_invariant_2_2_2 (); - (*mk_invariant_3_2 ();*) - mk_invariant_4_2 () - end - else - begin - mk_invariant_StatesDisjunction (); - mk_invariant_TransitionsDisjunction () end; + if Aorai_option.Deterministic.get () then begin + mk_global_comment "//* "; + mk_global_comment "//**************** "; + mk_global_comment "//* Proof that the automaton is deterministic"; + mk_global_comment "//* "; + mk_deterministic_lemma (); + end; + + mk_global_comment "//* "; + mk_global_comment "//****************** "; + mk_global_comment "//* Auxiliary variables used in transition conditions"; + mk_global_comment "//*"; + List.iter mk_global_var (Data_for_aorai.aux_variables()); + (match Data_for_aorai.abstract_logic_info () with + | [] -> () + | l -> + let annot = + Daxiomatic + ("Aorai_pebble_axiomatic", + List.map + (fun li -> Dfun_or_pred(li,Cil_datatype.Location.unknown)) l, + Cil_datatype.Location.unknown) + in + Globals.Annotations.add_user annot; + mk_global (GAnnot(annot, Cil_datatype.Location.unknown))); mk_global_comment "//* "; mk_global_comment "//* END Primitives generated for LTL verification"; mk_global_comment "//****************"; flush_globals() - - - - - - - - - - (* ************************************************************************* *) (** {b Pre/post management} *) - -(** Function called by mk_asbstract_pre and mk_asbstract_post. *) +(** Function called by mk_abstract_pre and mk_abstract_post. *) let mk_abstract_pre_post (states_l,trans_l) func status = - (* Intially, no state is a source for crossable transition and no transition is crossable*) + (* Initially, no state is a source for crossable + transition and no transition is crossable + *) let st_status = Array.make (List.length states_l) false in let tr_status = Array.make (List.length trans_l) false in @@ -2263,10 +1499,10 @@ List.iter (fun tr -> if isCrossable tr func status then - begin - Array.set st_status tr.stop.nums true; - Array.set tr_status tr.numt true - end + begin + Array.set st_status tr.stop.nums true; + Array.set tr_status tr.numt true + end ) trans_l; @@ -2275,186 +1511,764 @@ (**{b Pre and post condition of C functions} In our point of view, the pre or the post condition of a C function are defined by the set of states authorized just before/after the call, as such as the set of crossable - transitions. The following functions generates abstract pre and post-conditions - by using only informations deduced from the buchi automata. + transitions. The following functions generates abstract + pre and post-conditions by using only informations deduced + from the buchi automata. *) (** Given the buchi automata and the name of a function, it returns two arrays corresponding to the abstract pre-condition. *) -let mk_asbstract_pre auto func = +let mk_abstract_pre auto func = mk_abstract_pre_post auto func Promelaast.Call - (** Given the buchi automata and the name of a function, it returns two arrays corresponding to the abstract post-condition. *) -let mk_asbstract_post auto func = +let mk_abstract_post auto func = mk_abstract_pre_post auto func Promelaast.Return - - (** Generates a term representing the given pre or post condition. Transitions and states are rewritten into predicates in the same manner. The computation is then generalized Conjunction of forbidden and disjunction of authorized are computed together. *) -let pre_post_to_term (st_status, tr_status) = - let pp_to_term an_array array_term func = - let (authorized,forbidden,_) = - Array.fold_left - (fun (au_pred,fo_pred,i) b -> - if b then - begin - (por(au_pred,prel(Rneq, zero_term(), - (func array_term i))), - fo_pred, - i+1 - ) - end - else - (au_pred, - pand(fo_pred,prel(Req, zero_term(), - (func array_term i))), - i+1 - ) - ) - (pfalse,ptrue,0) - an_array - in - authorized::[forbidden] - - in - let tr = pp_to_term tr_status (host_trans_term ()) mk_offseted_array in - let st = pp_to_term st_status (host_state_term ()) mk_offseted_array_states_as_enum in - st@tr +let pre_post_to_term (st_status, _tr_status) = + if Aorai_option.Deterministic.get () then begin + let pp_to_term status var f = + let (authorized,_) = + Array.fold_left + (fun (auth,i) b -> + if b then + Logic_const.por(auth,prel(Req,var (), f i)),i+1 + else + auth,i+1) + (pfalse,0) + status + in authorized + in +(* let tr = + pp_to_term tr_status trans_term mk_trans_cst in +*) + let st = pp_to_term st_status state_term int2enumstate in + st + end else begin + let pp_to_term an_array array_term func = + let (authorized,_) = + Array.fold_left + (fun (au_pred,i) b -> + if b then + begin + (Logic_const.por(au_pred,prel(Req, one_term(), + (func array_term i))), + i+1 + ) + end + else + (au_pred,i+1) + ) + (pfalse,0) + an_array + in + authorized + in +(* let tr = pp_to_term tr_status (host_trans_term ()) mk_offseted_array in + *) + let st = + pp_to_term st_status (host_state_term ()) + mk_offseted_array_states_as_enum + in + st (* @ tr *) + end +let pre_post_to_term_neg (st_status, _) = + if Aorai_option.Deterministic.get () then begin + let pp_to_term status var f = + let (forbidden,_) = + Array.fold_left + (fun (auth,i) b -> + if not b then + Logic_const.por(auth,prel(Req,var (), f i)),i+1 + else + auth,i+1) + (pfalse,0) + status + in forbidden + in + let st = pp_to_term st_status state_term int2enumstate in + st + end else begin + let pp_to_term an_array array_term func = + let (forbidden,_) = + Array.fold_left + (fun (au_pred,i) b -> + if b then + begin + (Logic_const.pand(au_pred,prel(Req, zero_term(), + (func array_term i))), + i+1 + ) + end + else + (au_pred,i+1) + ) + (ptrue,0) + an_array + in + forbidden + in + let st = + pp_to_term st_status (host_state_term ()) + mk_offseted_array_states_as_enum + in + st + end +(* assigns curState, curOp and curOpStatus *) +let aorai_assigns loc = + let mk_from base = + let zone = + if Aorai_option.Deterministic.get () then + Logic_const.term ~loc (TLval base) (Cil.typeOfTermLval base) + else + let intv = TIndex (trange ~loc (None,None), TNoOffset) in + let tlv = Cil.addTermOffsetLval intv base in + Logic_const.term ~loc (TLval tlv) (Cil.typeOfTermLval tlv) + in (Logic_const.new_identified_term zone, FromAny) + in + Writes + [ mk_from (host_state_term ()); + (* mk_from (host_stateOld_term ()); + mk_from (host_trans_term ()); *) + (Logic_const.new_identified_term + (Logic_const.tvar ~loc + (Data_for_aorai.get_logic_var Data_for_aorai.curOpStatus)), + FromAny); + (Logic_const.new_identified_term + (Logic_const.tvar ~loc + (Data_for_aorai.get_logic_var Data_for_aorai.curOp)), + FromAny) + ] + +let action_assigns trans = + let add_if_needed v lv (known_vars, assigns as acc) = + if Cil_datatype.Varinfo.Set.mem v known_vars then acc + else + Cil_datatype.Varinfo.Set.add v known_vars, + (Logic_const.new_identified_term lv, FromAny)::assigns + in + let treat_one_action acc = + function + | Counter_init (host,off) | Counter_incr (host,off) + | Copy_value ((host,off),_) -> + let my_var = + match host with + | TVar ({ lv_origin = Some v}) -> v + | _ -> Aorai_option.fatal "Auxiliary variable is not a C global" + in + let my_off = + match off with + | TNoOffset -> TNoOffset + | TIndex _ -> TIndex(Logic_const.trange (None,None), TNoOffset) + | TField _ -> + Aorai_option.fatal "Unexpected offset in auxiliary variable" + in + add_if_needed my_var + (Logic_const.term (TLval(host,my_off)) + (Cil.typeOfTermLval (host,my_off))) + acc + | Pebble_init(_,v,c) -> + let cc = Extlib.the c.lv_origin in + let cv = Extlib.the v.lv_origin in + add_if_needed cv (Logic_const.tvar v) + (add_if_needed cc (Logic_const.tvar c) acc) + | Pebble_move(_,v1,_,v2) -> + let cv1 = Extlib.the v1.lv_origin in + let cv2 = Extlib.the v2.lv_origin in + add_if_needed cv1 (Logic_const.tvar v1) + (add_if_needed cv2 (Logic_const.tvar v2) acc) + in + let treat_one acc tr = + let empty_pebble = + match tr.start.multi_state, tr.stop.multi_state with + | Some(_,aux), None -> + let caux = Extlib.the aux.lv_origin in + add_if_needed caux (Logic_const.tvar aux) acc + | _ -> acc + in + List.fold_left treat_one_action empty_pebble (snd tr.cross) + in + Writes + (snd (List.fold_left treat_one (Cil_datatype.Varinfo.Set.empty,[]) trans)) +(* force that we have a crossable transition for each state in which the + automaton might be at current event. *) +let force_transition loc f st (_,tr_status) = + let states,_ as auto = Data_for_aorai.getAutomata() in + let aux (impossible_states,possible_states,has_crossable_trans) state = + let trans = Path_analysis.get_transitions_of_state state auto in + let add_one_trans (_,has_crossable_trans as acc) trans = + if tr_status.(trans.numt) then begin + let guard = + crosscond_to_pred ~event:(f,st) (fst trans.cross) + (Data_for_aorai.get_logic_var Data_for_aorai.curOp) + (Data_for_aorai.get_logic_var Data_for_aorai.curOpStatus) + in + true,Logic_const.por ~loc (has_crossable_trans,guard) + end else acc + in + let is_possible_start, cond = + List.fold_left add_one_trans (false,pfalse) trans + in + if is_possible_start then begin + let start = is_state_pred state in + let has_crossable_trans = + if Logic_utils.is_trivially_true cond then has_crossable_trans + else Logic_const.new_predicate + (pimplies ~loc (start,cond)) :: has_crossable_trans + in + impossible_states, + Logic_const.por ~loc (possible_states,start), has_crossable_trans + end else begin + let not_start = is_out_of_state_pred state in + Logic_const.pand ~loc (impossible_states,not_start), + possible_states, has_crossable_trans + end + in + let impossible_states, possible_states, crossable_trans = + List.fold_left aux (ptrue, pfalse,[]) states + in + let states = + if Aorai_option.Deterministic.get() then + possible_states (* We're always in exactly one state, among the possible + ones, no need to list the impossible ones. + *) + else (* requires that the cells for impossible states be '0' *) + Logic_const.pand ~loc (possible_states, impossible_states) + in + Logic_const.new_predicate states :: (List.rev crossable_trans) + +let mk_action loc l = + let mk_one_action (v,e) = + Logic_const.prel ~loc + (Req, Logic_const.term ~loc (TLval v) (Cil.typeOfTermLval v), + Logic_const.told ~loc e) + in + List.map mk_one_action l + +let find_pebble_origin lab actions = + let rec aux = function + | [] -> Aorai_option.fatal "Transition to multi-state has no pebble action" + | Pebble_init (_,_,count) :: _ -> + Logic_const.term + (TLval (TVar count, TNoOffset)) + (Logic_const.make_set_type count.lv_type) + | Pebble_move (_,_,set,_) :: _-> Data_for_aorai.pebble_set_at set lab + | _ :: tl -> aux tl + in aux actions + +let mk_sub ~loc pebble_set v = + let sub = List.hd (Logic_env.find_all_logic_functions "\\subset") in + Logic_const.papp ~loc + (sub,[], + [Logic_const.term ~loc (TLval (TVar v,TNoOffset)) pebble_set.term_type; + pebble_set]) + +let pebble_guard ~loc pebble_set aux_var guard = + let v = Cil_const.make_logic_var aux_var.lv_name aux_var.lv_type in + let g = rename_pred aux_var v guard in + let g = Logic_const.pand ~loc (mk_sub ~loc pebble_set v, g) in + Logic_const.pexists ~loc ([v], g) + +let pebble_guard_neg ~loc pebble_set aux_var guard = + let v = Cil_const.make_logic_var aux_var.lv_name aux_var.lv_type in + let g = rename_pred aux_var v guard in + let g = + Logic_const.pimplies ~loc + (mk_sub ~loc pebble_set v, Logic_const.pnot ~loc g) + in + Logic_const.pforall ~loc ([v], g) + +let pebble_post ~loc pebble_set aux_var guard = + let v = Cil_const.make_logic_var aux_var.lv_name aux_var.lv_type in + let g = rename_pred aux_var v guard in + let g = Logic_const.pimplies ~loc (mk_sub ~loc pebble_set v, g) in + Logic_const.pforall ~loc ([v], g) + +(* behavior is the list of all behaviors related to the given state, trans + the list of potentially active transitions ending in this state. + If the state is a multi-state, we have one behavior + whose assumes is the disjunction of these assumes +*) +let add_behavior_pebble_actions ~loc event behaviors state trans = + match state.multi_state with + | None -> behaviors + | Some (set,aux) -> + let name = Printf.sprintf "pebble_%s" state.name in + let assumes = + List.fold_left + (fun acc b -> + let assumes = List.map pred_of_id_pred b.b_assumes in + Logic_const.por ~loc (acc, Logic_const.pands assumes)) + pfalse behaviors + in + let assumes = [ Logic_const.new_predicate assumes ] in + let set = Data_for_aorai.pebble_set_at set Logic_const.here_label in + let treat_action guard res action = + match action with + | Copy_value _ | Counter_incr _ | Counter_init _ -> res + | Pebble_init (_,_,v) -> + let a = Cil_const.make_logic_var aux.lv_name aux.lv_type in + let guard = rename_pred aux a guard in + let guard = + Logic_const.pand ~loc + (Logic_const.prel + ~loc (Req,Logic_const.tvar a,Logic_const.tvar v), + guard) + in + Logic_const.term ~loc + (Tcomprehension (Logic_const.tvar a,[a], Some guard)) + set.term_type + :: res + | Pebble_move(_,_,s1,_) -> + let a = Cil_const.make_logic_var aux.lv_name aux.lv_type in + let guard = rename_pred aux a guard in + let in_s = + mk_sub ~loc + (Data_for_aorai.pebble_set_at s1 Logic_const.pre_label) a + in + let guard = Logic_const.pand ~loc (in_s,guard) in + Logic_const.term ~loc + (Tcomprehension (Logic_const.tvar a,[a], Some guard)) + set.term_type + :: res + in + let treat_one_trans acc tr = + let guard = crosscond_to_pred ~event (fst tr.cross) + (Data_for_aorai.get_logic_var Data_for_aorai.curOp) + (Data_for_aorai.get_logic_var Data_for_aorai.curOpStatus) + in + let guard = Logic_const.pold guard in + List.fold_left (treat_action guard) acc (snd tr.cross) + in + let res = List.fold_left treat_one_trans [] trans in + let res = Logic_const.term (Tunion res) set.term_type in + let post_cond = + [ Normal, Logic_const.new_predicate (Logic_const.prel (Req,set,res))] + in + Cil.mk_behavior ~name ~assumes ~post_cond () :: behaviors + +let mk_action ~loc a = + let term_lval lv = + Logic_const.term ~loc (TLval lv) (Cil.typeOfTermLval lv) + in + match a with + | Counter_init lv -> + [Logic_const.prel ~loc + (Req, term_lval lv, Logic_const.tinteger ~loc ~ikind:IInt 1)] + | Counter_incr lv -> + [Logic_const.prel ~loc + (Req, term_lval lv, + Logic_const.term ~loc + (TBinOp (PlusA, + Logic_const.told ~loc (term_lval lv), + Logic_const.tinteger ~loc ~ikind:IInt 1)) + (Cil.typeOfTermLval lv))] + | Pebble_init _ | Pebble_move _ -> [] (* Treated elsewhere *) + | Copy_value (lv,t) -> + [Logic_const.prel ~loc + (Req, term_lval lv, Logic_const.told t)] + +let mk_behavior ~loc auto event (st_status,tr_status) state = + Aorai_option.debug "analysis of state %s (%d out of %d)" + state.Promelaast.name state.nums (Array.length st_status); + if st_status.(state.nums) then begin + Aorai_option.debug "state %s is reachable" state.Promelaast.name; + let my_trans = Path_analysis.get_transitions_to_state state auto in + let rec treat_trans ((in_assumes, out_assumes, action_bhvs) as acc) l = + match l with + | [] -> acc + | trans :: tl -> + let consider, others = + List.partition (fun x -> x.start.nums = trans.start.nums) tl + in + let start = is_state_pred trans.start in + let not_start = is_out_of_state_pred trans.start in + let in_guard, out_guard, my_action_bhvs = + List.fold_left + (fun (in_guard, out_guard, action_bhvs) trans -> + Aorai_option.debug "examining transition %d (out of %d)" + trans.numt (Array.length tr_status); + let (cond,actions) = trans.cross in + Aorai_option.debug "transition %d is active" trans.numt; + let guard = + crosscond_to_pred ~event cond + (Data_for_aorai.get_logic_var Data_for_aorai.curOp) + (Data_for_aorai.get_logic_var Data_for_aorai.curOpStatus) + in + let my_in_guard,my_out_guard = + match state.multi_state with + | None -> guard, Logic_const.pnot ~loc guard + | Some (_,aux) -> + let set = + find_pebble_origin Logic_const.here_label actions + in + pebble_guard ~loc set aux guard, + pebble_guard_neg ~loc set aux guard + in + let out_guard = + Logic_const.pand ~loc (out_guard, my_out_guard) + in + let in_guard, action_bhvs = + match actions with + | [] -> + (Logic_const.por ~loc (in_guard,my_in_guard), + action_bhvs) + | _ -> + let name = + Printf.sprintf "buch_state_%s_in_%d" + state.name (List.length action_bhvs) + in + Aorai_option.debug "Name is %s" name; + let assumes = [ + Logic_const.new_predicate + (Logic_const.pand ~loc (start,my_in_guard)) + ] + in + let post_cond = + Normal, + Logic_const.new_predicate (is_state_pred state) + in + let treat_one_action acc a = + let posts = mk_action ~loc a in + match state.multi_state with + | None -> + acc @ + List.map + (fun x -> + (Normal, Logic_const.new_predicate x)) + posts + | Some (_,aux) -> + let set = + find_pebble_origin + Logic_const.pre_label actions + in + acc @ + List.map + (fun x -> + (Normal, + Logic_const.new_predicate + (pebble_post ~loc set aux x))) + posts + in + let post_cond = + List.fold_left treat_one_action [post_cond] actions + in + let bhv = + Cil.mk_behavior ~name ~assumes ~post_cond () + in + in_guard, bhv :: action_bhvs + in + in_guard, out_guard, action_bhvs) + (pfalse,ptrue,action_bhvs) (trans::consider) + in + treat_trans + (Logic_const.por ~loc + (in_assumes, (Logic_const.pand ~loc (start, in_guard))), + Logic_const.pand ~loc + (out_assumes, + (Logic_const.por ~loc (not_start, out_guard))), + my_action_bhvs + ) + others + in + let my_trans = List.filter (fun x -> tr_status.(x.numt)) my_trans in + let in_assumes, out_assumes, action_behaviors = + treat_trans (pfalse, ptrue, []) my_trans + in + let behaviors = + if Logic_utils.is_trivially_false in_assumes then action_behaviors + else begin + let behavior_in = + Cil.mk_behavior + ~name:(Printf.sprintf "buch_state_%s_in" state.Promelaast.name) + ~assumes:[Logic_const.new_predicate in_assumes] + ~post_cond: + [Normal, Logic_const.new_predicate (is_state_pred state)] + () + in behavior_in :: action_behaviors + end + in + let behaviors = + add_behavior_pebble_actions ~loc event behaviors state my_trans + in + let behaviors = + if Logic_utils.is_trivially_false out_assumes then behaviors + else begin + let post_cond = + match state.multi_state with + | None -> [] + | Some (set,_) -> + let set = + Data_for_aorai.pebble_set_at set Logic_const.here_label + in [Normal, + Logic_const.new_predicate + (Logic_const.prel ~loc + (Req,set, + Logic_const.term ~loc Tempty_set set.term_type))] + in + let post_cond = + (Normal, (Logic_const.new_predicate (is_out_of_state_pred state))) + :: post_cond + in + let behavior_out = + Cil.mk_behavior + ~name:(Printf.sprintf "buch_state_%s_out" state.Promelaast.name) + ~assumes:[Logic_const.new_predicate out_assumes] + ~post_cond () + in behavior_out :: behaviors + end + in + List.rev behaviors + end else begin + Aorai_option.debug "state %s is not reachable" state.Promelaast.name; + (* We know that we'll never end up in this state. *) + let name = Printf.sprintf "buch_state_%s_out" state.Promelaast.name in + let post_cond = + match state.multi_state with + | None -> [] + | Some (set,_) -> + let set = + Data_for_aorai.pebble_set_at set Logic_const.here_label + in [Normal, + Logic_const.new_predicate + (Logic_const.prel ~loc + (Req,set, + Logic_const.term ~loc Tempty_set set.term_type))] + in + let post_cond = + (Normal, Logic_const.new_predicate (is_out_of_state_pred state)) + ::post_cond + in + [mk_behavior ~name ~post_cond ()] + end -let get_preds_wrt_params (transl:bool array) (f:string) (status:Promelaast.funcStatus) = - (* These two constants are never used, but are syntactically needed to call the conversion function *) +let auto_func_behaviors loc f st (_st_status, tr_status as state) = + let event = f,st in + let call_or_ret = + match st with + | Promelaast.Call -> "call" + | Promelaast.Return -> "return" + in + Aorai_option.debug + "func behavior for %a (%s)" Kernel_function.pretty f call_or_ret; + let (states, trans) as auto = Data_for_aorai.getAutomata() in + (* requires is not needed for pre_func, as it is enforced by the + requires of the original C function itself (and the call to pre_func + by definition the first instruction of the function). + *) + let post_cond = + let called_pre = + Logic_const.new_predicate + (Logic_const.prel ~loc + (Req, + Logic_const.tvar ~loc + (Data_for_aorai.get_logic_var Data_for_aorai.curOpStatus), + (Logic_utils.mk_dummy_term + (TConst (Data_for_aorai.op_status_to_cenum st)) + Cil.intType))) + in + let called_pre_2 = + Logic_const.new_predicate + (Logic_const.prel ~loc + (Req, + Logic_const.tvar ~loc + (Data_for_aorai.get_logic_var Data_for_aorai.curOp), + (Logic_utils.mk_dummy_term + (TConst(Data_for_aorai.func_to_cenum + (Kernel_function.get_name f))) Cil.intType))) + in + (* let old_pred = Aorai_utils.mk_old_state_pred loc in *) + [(Normal, called_pre); (Normal, called_pre_2)] + in + let requires = + if st = Promelaast.Call then [] else force_transition loc f st state + in + let glob_assigns = aorai_assigns loc in + let trans_assigns = + action_assigns (List.filter (fun x -> tr_status.(x.numt)) trans) + in + let assigns = Logic_utils.concat_assigns glob_assigns trans_assigns in + let global_behavior = + Cil.mk_behavior ~requires ~post_cond ~assigns () + in + let mk_behavior acc st = + mk_behavior ~loc auto event state st @ acc + in + global_behavior :: (List.fold_left mk_behavior [] states) + +let get_preds_wrt_params transl f status = + (* These two constants are never used, but are syntactically + needed to call the conversion function *) let op = Cil_const.make_logic_var "_aorai_op" Linteger in let st = Cil_const.make_logic_var "_aorai_status" Linteger in - - + let event = (f,status) in let preds = ref [] in Array.iteri (fun trn b -> if b then - begin - (* Gets the cross condition of the transition *) - let llclause = Data_for_aorai.getParametrizedCondOfTransition trn in - let llclauseUnderContexte = Logic_simplification.simplifyDNFwrtCtx llclause f status in - if llclauseUnderContexte=[] or llclauseUnderContexte=[[PTrue]] then - () - else - let cond = Logic_simplification.dnfToCond llclauseUnderContexte in - let pred = crosscond_to_pred false cond op st in - - - (* Generates the condition of the transition *) - (* hyp <-- aoraiStates[trn]!=0 *) - let hyp = Prel(Rneq,mk_offseted_array_lval_from_term (host_trans_term()) (mk_int_term trn), mk_int_term 0) in - (* pred <-- hyp ==> pred *) - let pred = Pimplies (unamed (hyp),unamed pred) in - - (* Adds the implication in the result list *) - preds:=pred::!preds - end + begin + Aorai_option.debug "considering transition %d" trn; + let trans = Data_for_aorai.getTransition trn in + (* Gets the cross condition of the transition *) + let dnf = + snd (Logic_simplification.simplifyCond (fst trans.cross)) + in + let cond = Logic_simplification.simplifyDNFwrtCtx dnf f status in + let pred = crosscond_to_pred ~event cond op st in + let retrieve_state (st,_) = st.nums = trans.stop.nums in + let oth_preds = + try + snd (List.find retrieve_state !preds) + with Not_found -> pfalse + in + let pred = Logic_const.por (oth_preds,pred) in + preds := + (trans.stop,pred) :: + (List.filter (not $ retrieve_state) !preds) + end ) transl; + let preds = + List.map (fun (st, pred) -> pimplies (is_state_pred st, pred)) !preds + in + let pred = Logic_const.pands preds in + if Logic_utils.is_trivially_true pred then None else Some pred - if(!preds=[]) then None - else Some(mk_conjunction(!preds)) - - - -let get_preds_pre_wrt_params (f:string) = - let (_,pre_tr) = Data_for_aorai.get_func_pre f in +let get_preds_pre_wrt_params f = + let (_,pre_tr) = Data_for_aorai.get_func_pre (Kernel_function.get_name f) in get_preds_wrt_params (pre_tr) f Promelaast.Call -let get_preds_post_bc_wrt_params (f:string) = - let post = Data_for_aorai.get_func_post_bycase f in +let get_preds_post_bc_wrt_params f = + let post = Data_for_aorai.get_func_post_bycase (Kernel_function.get_name f) in let (_,post_tr) = pre_flattening post in get_preds_wrt_params (post_tr) f Promelaast.Return - - - - - - - let force_condition_to_predicate global_inv restricted_inv = let pred_l = ref [] in - let treat global restric array_term= + let mk_pred_det term index = prel(Rneq, term, mk_int_term index) in + let mk_pred_nondet base index = + prel(Req, mk_offseted_array base index, zero_term()) + in + let treat global restric mk_pred= Array.iteri (fun index value -> - if (not value) && global.(index) then - begin - let n_pred = Prel(Req,(mk_offseted_array array_term index),zero_term())in - pred_l:= n_pred::!pred_l - end + if (not value) && global.(index) then + begin + let n_pred = mk_pred index in + pred_l:= n_pred::!pred_l + end ) restric in - treat (fst global_inv) (fst restricted_inv) (host_state_term ()); - treat (snd global_inv) (snd restricted_inv) (host_trans_term ()); + treat (fst global_inv) (fst restricted_inv) + (if Aorai_option.Deterministic.get() then mk_pred_det (state_term()) + else mk_pred_nondet (host_state_term ())); +(* treat (snd global_inv) (snd restricted_inv) + (if Aorai_option.Deterministic.get() then mk_pred_det (trans_term()) + else mk_pred_nondet (host_trans_term ()));*) if !pred_l<>[] then - mk_conjunction (List.rev !pred_l) + pands (List.rev !pred_l) else - Ptrue - + ptrue +let treat_val loc pred (base, range) = + let add term = + if Cil.isLogicZero base then term + else Logic_const.term + (TBinOp (PlusA, Logic_const.tat (base,Logic_const.pre_label), term)) + Linteger + in + let add_cst i = add (Logic_const.tinteger ~ikind:IInt i) in + let res = + match range with + | Fixed i -> Logic_const.prel (Req,loc, add_cst i) + | Interval(min,max) -> + let min = Logic_const.prel (Rle, add_cst min, loc) in + let max = Logic_const.prel (Rle, loc, add_cst max) in + Logic_const.pand (min,max) + | Bounded (min,max) -> + let min = Logic_const.prel (Rle, add_cst min, loc) in + let max = Logic_const.prel (Rle, loc, add max) in + Logic_const.pand (min,max) + | Unbounded min -> Logic_const.prel (Rle, add_cst min, loc) + in + Aorai_option.debug ~dkey:"action" "Action predicate: %a" + !Ast_printer.d_predicate_named res; + Logic_const.por(pred,res) + +let update_to_pred post_state (location,vals) = + let loc = Cil_datatype.Location.unknown in + let intv = List.fold_left (treat_val location) Logic_const.pfalse vals in + match post_state.multi_state with + | None -> intv + | Some(set,aux) -> + (* [VP 2011-09-05] In fact, not all the pebble come from the considered + pre-state. Will this lead to too strong post-conditions? + *) + let set = Data_for_aorai.pebble_set_at set Logic_const.here_label in + pebble_post ~loc set aux intv + +let action_to_pred ~pre_state ~post_state kf = + let my_stmt = Kernel_function.find_return kf in + let my_kinstr = Kstmt my_stmt in + let updates = + Data_for_aorai.get_action_path kf my_kinstr pre_state post_state + in + List.map (update_to_pred post_state) updates -let get_global_loop_inv ref_stmt = +let get_global_loop_inv stmt = double_bool_array_or (double_bool_array_or - (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_pre_bycase ref_stmt)) - (Spec_tools.pre_flattening (Data_for_aorai.get_loop_ext_pre_bycase ref_stmt))) - (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_post_bycase ref_stmt)) - + (Spec_tools.pre_flattening + (Data_for_aorai.get_loop_int_pre_bycase stmt)) + (Spec_tools.pre_flattening + (Data_for_aorai.get_loop_ext_pre_bycase stmt))) + (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_post_bycase stmt)) -let get_restricted_int_pre_bc ref_stmt = - let global_loop_inv = get_global_loop_inv ref_stmt in +let get_restricted_int_pre_bc stmt = + let global_loop_inv = get_global_loop_inv stmt in force_condition_to_predicate global_loop_inv - (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_pre_bycase ref_stmt)) + (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_pre_bycase stmt)) -let get_restricted_ext_pre_bc ref_stmt = - let global_loop_inv = get_global_loop_inv ref_stmt in +let get_restricted_ext_pre_bc stmt = + let global_loop_inv = get_global_loop_inv stmt in force_condition_to_predicate global_loop_inv - (Spec_tools.pre_flattening (Data_for_aorai.get_loop_ext_pre_bycase ref_stmt)) + (Spec_tools.pre_flattening (Data_for_aorai.get_loop_ext_pre_bycase stmt)) -let get_restricted_int_post_bc ref_stmt = - let global_loop_inv = get_global_loop_inv ref_stmt in +let get_restricted_int_post_bc stmt = + let global_loop_inv = get_global_loop_inv stmt in force_condition_to_predicate global_loop_inv - (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_post_bycase ref_stmt)) - - + (Spec_tools.pre_flattening (Data_for_aorai.get_loop_int_post_bycase stmt)) let rec display s = try let i=String.index s '\n' in if i=0 then begin - Aorai_option.result " "; - display (String.sub s 1 ((String.length s)-1)) + Aorai_option.result " "; + display (String.sub s 1 ((String.length s)-1)) end else begin - Aorai_option.result "%s" (String.sub s 0 i); - if i+1=(String.length s) then - Aorai_option.result " " - else - display (String.sub s (i+1) ((String.length s)-i-1)) + Aorai_option.result "%s" (String.sub s 0 i); + if i+1=(String.length s) then + Aorai_option.result " " + else + display (String.sub s (i+1) ((String.length s)-i-1)) end with Not_found -> Aorai_option.result "%s" s - - - - (** Intermediate function that factorizes some functionalities. This function is designed to be internally called. *) let display_operations_spec__ (sorted:bool) (bycase:bool) = @@ -2464,14 +2278,14 @@ let listOfNames = if sorted then List.sort (String.compare) listOfNames else listOfNames in List.iter (fun name -> - let pre = Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_func_pre ~securised:true name) in - let post = if bycase then + let pre = Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_func_pre ~securised:true name) in + let post = if bycase then Spec_tools.debug_display_stmt_all_pre_bycase (Data_for_aorai.get_func_post_bycase ~securised:true name) - else - Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_func_post ~securised:true name) - in - Aorai_option.result "# %s %s %s" pre name post; - Aorai_option.result "\n" + else + Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_func_post ~securised:true name) + in + Aorai_option.result "# %s %s %s" pre name post; + Aorai_option.result "\n" ) listOfNames; let ignFuncs=List.fold_left @@ -2509,47 +2323,50 @@ display "\n########\n# Loops specification:\n#"; let sortedLoopsIndex = List.sort (fun r1 r2 -> - if !r1.sid > !r2.sid then 1 - else if !r1.sid < !r2.sid then -1 - else 0 - ) (Data_for_aorai.get_loops_index ()) + if r1.sid > r2.sid then 1 + else if r1.sid < r2.sid then -1 + else 0 + ) (Data_for_aorai.get_loops_index ()) in List.iter - (fun stmt_ref -> - Aorai_option.result "# stmt.sid=%d" !stmt_ref.sid; + (fun stmt -> + Aorai_option.result "# stmt.sid=%d" stmt.sid; Aorai_option.result "# loop pres : %s" - (Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_loop_ext_pre stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre + (Data_for_aorai.get_loop_ext_pre stmt)); Aorai_option.result "# %s" - (Spec_tools.debug_display_stmt_all_pre_bycase (Data_for_aorai.get_loop_ext_pre_bycase stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre_bycase + (Data_for_aorai.get_loop_ext_pre_bycase stmt)); Aorai_option.result "# block pres : %s" - (Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_loop_int_pre stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre + (Data_for_aorai.get_loop_int_pre stmt)); Aorai_option.result "# %s" - (Spec_tools.debug_display_stmt_all_pre_bycase (Data_for_aorai.get_loop_int_pre_bycase stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre_bycase + (Data_for_aorai.get_loop_int_pre_bycase stmt)); Aorai_option.result "# block posts: %s" - (Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_loop_int_post stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre + (Data_for_aorai.get_loop_int_post stmt)); Aorai_option.result "# %s" - (Spec_tools.debug_display_stmt_all_pre_bycase (Data_for_aorai.get_loop_int_post_bycase stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre_bycase + (Data_for_aorai.get_loop_int_post_bycase stmt)); Aorai_option.result "# loop posts : %s" - (Spec_tools.debug_display_stmt_all_pre (Data_for_aorai.get_loop_ext_post stmt_ref)); + (Spec_tools.debug_display_stmt_all_pre + (Data_for_aorai.get_loop_ext_post stmt)); Aorai_option.result "# %s" - (Spec_tools.debug_display_stmt_all_pre_bycase (Data_for_aorai.get_loop_ext_post_bycase stmt_ref)); - - + (Spec_tools.debug_display_stmt_all_pre_bycase + (Data_for_aorai.get_loop_ext_post_bycase stmt)); ) sortedLoopsIndex; (* Aorai_option.result *) display "# End of loops specification\n########\n" - - - - - - -let pasEtatOp pos op = Aorai_option.warning "No state can be enabled %s operation '%s'. It can be an error of the analyzed C program." pos op +let pasEtatOp pos op = + Aorai_option.warning + "No state can be enabled %s operation '%s'. \ + It can be an error of the analyzed C program." pos op let pasEtatAvantOp op = pasEtatOp "before" op let pasEtatApresOp op = pasEtatOp "after" op @@ -2568,14 +2385,14 @@ let listOfNames = List.sort (String.compare) listOfNames in List.iter (fun name -> - let pre = - Data_for_aorai.get_func_pre ~securised:true name - in - let post = - Data_for_aorai.get_func_post_bycase ~securised:true name - in - if is_empty_pre_post pre then pasEtatAvantOp name; - if is_empty_post_bc post then pasEtatApresOp name + let pre = + Data_for_aorai.get_func_pre ~securised:true name + in + let post = + Data_for_aorai.get_func_post_bycase ~securised:true name + in + if is_empty_pre_post pre then pasEtatAvantOp name; + if is_empty_post_bc post then pasEtatApresOp name ) listOfNames; @@ -2587,31 +2404,29 @@ in display ("Ignored functions: { "^ignFuncs^" }") - - let display_all_warnings_about_loops_specs() = let sortedLoopsIndex = List.sort (fun r1 r2 -> - if !r1.sid > !r2.sid then 1 - else if !r1.sid < !r2.sid then -1 - else 0) + if r1.sid > r2.sid then 1 + else if r1.sid < r2.sid then -1 + else 0) (Data_for_aorai.get_loops_index ()) in List.iter - (fun stmt_ref -> - if is_empty_pre_post (Data_for_aorai.get_loop_ext_pre stmt_ref) && - is_empty_post_bc (Data_for_aorai.get_loop_ext_pre_bycase stmt_ref) - then pasEtatAvantLoop !stmt_ref.sid; - if is_empty_pre_post (Data_for_aorai.get_loop_ext_post stmt_ref) && - is_empty_post_bc (Data_for_aorai.get_loop_ext_post_bycase stmt_ref) - then pasEtatApresLoop !stmt_ref.sid; - if is_empty_pre_post (Data_for_aorai.get_loop_int_pre stmt_ref) && - is_empty_post_bc (Data_for_aorai.get_loop_int_pre_bycase stmt_ref) - then pasEtatAvantLoopBlock !stmt_ref.sid; - if is_empty_pre_post (Data_for_aorai.get_loop_int_post stmt_ref) && - is_empty_post_bc (Data_for_aorai.get_loop_int_post_bycase stmt_ref) - then pasEtatApresLoopBlock !stmt_ref.sid) + (fun stmt -> + if is_empty_pre_post (Data_for_aorai.get_loop_ext_pre stmt) && + is_empty_post_bc (Data_for_aorai.get_loop_ext_pre_bycase stmt) + then pasEtatAvantLoop stmt.sid; + if is_empty_pre_post (Data_for_aorai.get_loop_ext_post stmt) && + is_empty_post_bc (Data_for_aorai.get_loop_ext_post_bycase stmt) + then pasEtatApresLoop stmt.sid; + if is_empty_pre_post (Data_for_aorai.get_loop_int_pre stmt) && + is_empty_post_bc (Data_for_aorai.get_loop_int_pre_bycase stmt) + then pasEtatAvantLoopBlock stmt.sid; + if is_empty_pre_post (Data_for_aorai.get_loop_int_post stmt) && + is_empty_post_bc (Data_for_aorai.get_loop_int_post_bycase stmt) + then pasEtatApresLoopBlock stmt.sid) sortedLoopsIndex let display_all_warnings_about_specs () = diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/aorai_utils.mli frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_utils.mli --- frama-c-20110201+carbon+dfsg/src/aorai/aorai_utils.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_utils.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,62 +23,68 @@ (* *) (**************************************************************************) +open Cil_types open Promelaast open Spec_tools - -(** Given a transition a function name and a function status (call or return) it returns if the cross condition can be statisfied with only function status. *) - -val isCrossable: trans -> string -> funcStatus -> bool - -(** Given a transition a function name and a function status (call or return) it returns if the cross condition can be statisfied with only function status. *) -val isCrossableAtInit: trans -> string -> bool - - +(** Given a transition a function and a function status (call or return) + it returns if the cross condition can be statisfied + with only function status. + *) + +val isCrossable: + (typed_condition * action) trans -> kernel_function -> funcStatus -> bool + +(** Given a transition and the main entry point it returns if + the cross condition can be statisfied at the beginning of the program. *) +val isCrossableAtInit: + (typed_condition * action) trans -> kernel_function -> bool (* ************************************************************************* *) (** {b Abstract pre/post} *) - - - -(** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of reachable states and the second one is the set of crossable transitions. *) -val get_next : string -> funcStatus -> bool array -> (bool array * bool array) - -(** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of possible initial states and the second one is the set of crossable transitions. *) -val get_prev : string -> funcStatus -> (bool array * bool array) -> (bool array * bool array) - - - - +(** Given a function, its status (call or return) and an array of boolean + describing states status, it returns a couple of boolean array. + The first one describes the set of reachable states and + the second one is the set of crossable transitions. *) +val get_next : + kernel_function -> funcStatus -> bool array -> (bool array * bool array) + +(** Given a function, its status (call or return) and an array of boolean + describing states status, it returns a couple of boolean array. + The first one describes the set of possible initial states and + the second one is the set of crossable transitions. *) +val get_prev : + kernel_function -> funcStatus -> + (bool array * bool array) -> (bool array * bool array) + +(** given an event (func, status) and a state returns the predicate + that guards the transition to this state. + *) +val make_prev_pred: + kernel_function -> funcStatus -> Promelaast.state + -> (bool array * bool array) -> Cil_types.predicate Cil_types.named + +(** given an event (func, status) and a state returns the + predicate that prevents transition to these states. + *) +val make_prev_pred_neg: + kernel_function -> funcStatus -> Promelaast.state list + -> (bool array * bool array) -> Cil_types.predicate Cil_types.named (* ************************************************************************* *) (** {b Behaviored pre/post (bycase approach)} *) (** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of reachable states and the second one is the set of crossable transitions. *) -val get_next_bycase : string -> funcStatus -> pre_post_bycase_t -> double_pre_post_bycase_t +val get_next_bycase : + kernel_function -> funcStatus -> pre_post_bycase_t -> double_pre_post_bycase_t (** Given a function name, is status (call or return) and an array of boolean describing states status, it returns a couple of boolean array. The first one describes the set of possible initial states and the second one is the set of crossable transitions. *) -val get_prev_bycase : string -> funcStatus -> double_pre_post_bycase_t -> double_pre_post_bycase_t - -val mk_pre_or_post_bycase_from_pre_or_post : (bool array * bool array) -> double_pre_post_bycase_t - - - -(** Given a set of states and the bycase post-condition of an operation - this function returns the new post-condition after the execution of the operation in the context of current_st. -*) -val mk_forward_composition : pre_post_bycase_t -> double_pre_post_bycase_t -> double_pre_post_bycase_t - -(** Given a set of states and the bycases pre and post-conditions of an operation - this function returns the new pre-condition before the execution of the operation in the context of current_st. -*) -val mk_backward_composition: pre_post_bycase_t -> (bool array*bool array) -> double_pre_post_bycase_t -> double_pre_post_bycase_t - - - - - +val get_prev_bycase : + kernel_function -> funcStatus -> double_pre_post_bycase_t + -> double_pre_post_bycase_t +val mk_pre_or_post_bycase_from_pre_or_post : + (bool array * bool array) -> double_pre_post_bycase_t (* ************************************************************************* *) (** {b Globals management} *) @@ -85,32 +93,7 @@ val initFile : Cil_types.file -> unit (** Given the name of the main function, this function computes all newly introduced globals (variables, enumeration structure, invariants, etc.) *) -val initGlobals : string -> bool -> unit - - - - - - - -(* ************************************************************************* *) -(** {b Buchi automata and C code synchronisation } *) - -(** This function returns the list of instructions that have to be introduced just before each call of function and each return of function. These instructions correspond to the synchronisation between C code and Buchi automata. The parameters are : - + The buchi automata - + the name of the function that is called or that returns - + the status of this action (call or return) - + the localisation associated to this generated code - + the name of the caller (if any) - + the stmt id of the call (if any) -*) -val synch_upd : buchautomata -> string -> funcStatus -> Cil_types.location -> string option -> int option -> Cil_types.instr list - - - - - - +val initGlobals : Cil_types.kernel_function -> bool -> unit (* ************************************************************************* *) (** {b Pre/post management} *) @@ -121,59 +104,105 @@ transitions. The following functions generates abstract pre and post-conditions by using only informations deduced from the buchi automata. *) -(** Given the buchi automata and the name of a function, it returns two arrays - corresponding to the abstract pre-condition. *) -val mk_asbstract_pre : buchautomata -> string -> (bool array * bool array) - -(** Given the buchi automata and the name of a function, it returns two arrays - corresponding to the abstract post-condition. *) -val mk_asbstract_post : buchautomata -> string -> (bool array * bool array) - -(** Generates a term representing the given pre or post condition. - Transitions and states are rewrited into predicates in the same maner. The computation is then generalized - Conjunction of forbidden and disjunction of authorized are compute together. *) -val pre_post_to_term : (bool array * bool array) -> (Cil_types.predicate Cil_types.named) list - - -val get_preds_pre_wrt_params : string -> Cil_types.predicate option -val get_preds_post_bc_wrt_params : string -> Cil_types.predicate option - - - +(** base lhost corresponding to curState. *) +val host_state_term: unit -> Cil_types.term_lval -(** Given a NON EMPTY list of predicates, it returns a conjunction of these predicates. *) -val mk_conjunction_named : (Cil_types.predicate Cil_types.named) list -> (Cil_types.predicate Cil_types.named) -val mk_conjunction : (Cil_types.predicate) list -> (Cil_types.predicate ) +(** returns the predicate saying that automaton is in corresponding state. *) +val is_state_pred: state -> Cil_types.predicate Cil_types.named -(** Given a NON EMPTY list of predicates, it returns a disjunction of these predicates. *) -val mk_disjunction_named : (Cil_types.predicate Cil_types.named) list -> (Cil_types.predicate Cil_types.named) -val mk_disjunction : (Cil_types.predicate ) list -> (Cil_types.predicate ) -val mk_expr_disjunction : (Cil_types.exp) list -> (Cil_types.exp) +(** returns the predicate saying that automaton is NOT + in corresponding state. *) +val is_out_of_state_pred: state -> Cil_types.predicate Cil_types.named +(** Given the buchi automata and the name of a function, it returns two arrays + corresponding to the abstract pre-condition. *) +val mk_abstract_pre : + typed_automaton -> Cil_types.kernel_function -> (bool array * bool array) +(** Given the buchi automata and the name of a function, it returns two arrays + corresponding to the abstract post-condition. *) +val mk_abstract_post : + typed_automaton -> Cil_types.kernel_function -> (bool array * bool array) -val mk_int_exp : int -> Cil_types.exp +(** Generates a term representing the given pre or post condition, i.e. + that the automaton is in one of the states mapped to [true]. *) +val pre_post_to_term : + (bool array * bool array) -> Cil_types.predicate Cil_types.named + +(** Generates the negation of the given pre/post, i.e. + that the automaton is not in one of the states mapped to [true]. + *) +val pre_post_to_term_neg : + (bool array * bool array) -> Cil_types.predicate Cil_types.named + +(** returns assigns clause corresponding to updating automaton's state. + @since Nitrogen-20111001 + *) +val aorai_assigns: + Cil_types.location -> Cil_types.identified_term Cil_types.assigns + +(** returns the list of predicates expressing that for each current state + the automaton currently is in, there is at least one transition that is + crossed. +*) +val force_transition: + Cil_types.location -> kernel_function -> Promelaast.funcStatus -> + (bool array * bool array) -> Cil_types.identified_predicate list + +(** auto_func_behaviors f st (st_status, tr_status) + generates behaviors corresponding to the transitions authorized by + tr_status for function f in status st + @since Nitrogen-20111001 +*) +val auto_func_behaviors: + Cil_types.location -> kernel_function -> Promelaast.funcStatus -> + (bool array * bool array) -> Cil_types.funbehavior list + +val get_preds_pre_wrt_params : + kernel_function -> Cil_types.predicate Cil_types.named option + +val get_preds_post_bc_wrt_params : + kernel_function -> Cil_types.predicate Cil_types.named option + +val update_to_pred: Promelaast.state -> + (term * (term * Data_for_aorai.range) list) -> predicate named + +(** for a given kf, a starting and ending state, returns the post-conditions + related to the possible values of the auxiliary variables at the exit of + the function. + *) +val action_to_pred: + pre_state: Promelaast.state -> + post_state: Promelaast.state -> + kernel_function -> predicate named list (** Return an integer constant term with the 0 value. *) val zero_term : unit -> Cil_types.term (** Given an lval term 'host' and an integer value 'off', it returns a lval term host[off]. *) val mk_offseted_array : Cil_types.term_lval -> int -> Cil_types.term -val mk_offseted_array_states_as_enum : Cil_types.term_lval -> int -> Cil_types.term +val mk_offseted_array_states_as_enum : + Cil_types.term_lval -> int -> Cil_types.term -(** Returns a term representing the given logic variable (usually a fresh quantified variable). *) +(** Returns a term representing the given logic variable + (usually a fresh quantified variable). *) val mk_term_from_vi : Cil_types.varinfo -> Cil_types.term +val force_condition_to_predicate : + (bool array * bool array) -> (bool array * bool array) -> + Cil_types.predicate Cil_types.named -val force_condition_to_predicate : (bool array * bool array) -> (bool array * bool array) -> Cil_types.predicate -val get_global_loop_inv : Cil_types.stmt ref -> (bool array * bool array) +val get_global_loop_inv : Cil_types.stmt -> (bool array * bool array) -val get_restricted_int_pre_bc : Cil_types.stmt ref -> Cil_types.predicate -val get_restricted_ext_pre_bc : Cil_types.stmt ref -> Cil_types.predicate -val get_restricted_int_post_bc : Cil_types.stmt ref -> Cil_types.predicate +val get_restricted_int_pre_bc : + Cil_types.stmt -> Cil_types.predicate Cil_types.named +val get_restricted_ext_pre_bc : + Cil_types.stmt -> Cil_types.predicate Cil_types.named +val get_restricted_int_post_bc : + Cil_types.stmt -> Cil_types.predicate Cil_types.named val make_enum_states: unit -> unit val debug_display_func_status: string -> unit @@ -184,7 +213,6 @@ val debug_display_all_specs : unit -> unit val debug_display_func_status_bycase : string -> unit - val display_all_warnings_about_specs : unit -> unit (* diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/aorai_visitors.ml frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_visitors.ml --- frama-c-20110201+carbon+dfsg/src/aorai/aorai_visitors.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/aorai_visitors.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,444 +23,637 @@ (* *) (**************************************************************************) +open Promelaast +open Extlib +open Logic_const open Cil_types open Cil open Cil_datatype open Ast_info open Spec_tools -(**************************************************************************************) +(**************************************************************************) (** - This visitor does not modify the AST. - It just generates a first abstract specification for each function. - This specification is stored into Data_for_aorai and can be accessed by using get_func_pre or get_func_post. + This visitor does not modify the AST. + It just generates a first abstract specification for each function. + This specification is stored into Data_for_aorai and can be accessed + by using get_func_pre or get_func_post. *) -class visit_computing_abstract_pre_post_from_buch (auto:Promelaast.buchautomata) (root:string) (considerAcceptance:bool) = +class visit_computing_abstract_pre_post_from_buch + (auto:Promelaast.typed_automaton) (root:string) (considerAcceptance:bool) = -object (*(self) *) - inherit Visitor.generic_frama_c_visitor - (Project.current ()) (Cil.inplace_visit ()) as super +object (self) + inherit Visitor.frama_c_inplace as super method vfunc f = + let kf = Extlib.the self#current_kf in if not (Data_for_aorai.isIgnoredFunction f.svar.vname) then begin -(* Extraction of a first abstraction of pre/post condition of the current function *) - let pre_st,pre_tr = (Aorai_utils.mk_asbstract_pre auto f.svar.vname) in - let post_st,post_tr = (Aorai_utils.mk_asbstract_post auto f.svar.vname) in - - - + (* Extraction of a first abstraction of pre/post condition of + the current function. + *) + let pre_st,pre_tr = + (Aorai_utils.mk_abstract_pre auto kf) in + let post_st,post_tr = + (Aorai_utils.mk_abstract_post auto kf) in if f.svar.vname = root then - begin - (* Pre simplification for Root (only initial states) *) - List.iter ( - fun tr -> - if (pre_tr.(tr.Promelaast.numt)) && - (*if ((pre_tr.(tr.Promelaast.numt)) || pre_st.(tr.Promelaast.stop.Promelaast.nums)) &&*) - ((tr.Promelaast.start.Promelaast.init==Bool3.False) || not (Aorai_utils.isCrossableAtInit tr root) ) - then - begin - pre_tr.(tr.Promelaast.numt)<- false; - pre_st.(tr.Promelaast.stop.Promelaast.nums)<- false - end - ) ((snd auto):Promelaast.trans list); - - - List.iter ( - fun tr -> - if (pre_tr.(tr.Promelaast.numt)) then - pre_st.(tr.Promelaast.stop.Promelaast.nums) <- true - ) ((snd auto):Promelaast.trans list); - - - - - if considerAcceptance then begin - (* Post simplification for Root (Only acceptance states) *) - List.iter ( - fun tr -> - if (post_tr.(tr.Promelaast.numt)) && - (*if ((post_tr.(tr.Promelaast.numt)) || post_st.(tr.Promelaast.stop.Promelaast.nums)) &&*) - (tr.Promelaast.stop.Promelaast.acceptation==Bool3.False) - then - begin - post_tr.(tr.Promelaast.numt)<- false; - post_st.(tr.Promelaast.stop.Promelaast.nums)<- false - end - ) ((snd auto):Promelaast.trans list); - - - List.iter ( - fun tr -> - if (post_tr.(tr.Promelaast.numt)) then - post_st.(tr.Promelaast.stop.Promelaast.nums) <- true - ) ((snd auto):Promelaast.trans list) - end - end; + begin + (* Pre simplification for Root (only initial states) *) + List.iter ( + fun tr -> + if + (pre_tr.(tr.Promelaast.numt)) && + ((tr.Promelaast.start.Promelaast.init==Bool3.False) + || not (Aorai_utils.isCrossableAtInit tr kf)) + then + begin + pre_tr.(tr.Promelaast.numt)<- false; + pre_st.(tr.Promelaast.stop.Promelaast.nums)<- false + end + ) (snd auto); - Data_for_aorai.set_func_pre f.svar.vname (pre_st,pre_tr) ; - Data_for_aorai.set_func_post f.svar.vname (post_st,post_tr) + List.iter ( + fun tr -> + if (pre_tr.(tr.Promelaast.numt)) then + pre_st.(tr.Promelaast.stop.Promelaast.nums) <- true + ) (snd auto); + + if considerAcceptance then begin + (* Post simplification for Root (Only acceptance states) *) + List.iter ( + fun tr -> + if (post_tr.(tr.Promelaast.numt)) && + (tr.Promelaast.stop.Promelaast.acceptation==Bool3.False) + then + begin + post_tr.(tr.Promelaast.numt)<- false; + post_st.(tr.Promelaast.stop.Promelaast.nums)<- false + end + ) (snd auto); + List.iter ( + fun tr -> + if (post_tr.(tr.Promelaast.numt)) then + post_st.(tr.Promelaast.stop.Promelaast.nums) <- true + ) (snd auto) + end + end; + Data_for_aorai.set_func_pre f.svar.vname (pre_st, pre_tr) ; + Data_for_aorai.set_func_post f.svar.vname (post_st, post_tr) end; DoChildren end +let get_call_name exp = match exp.enode with + | Const(CStr(s)) -> s + | Lval(Var(vi),NoOffset) -> vi.vname + | _ -> + Aorai_option.not_yet_implemented + "At this time, only explicit calls are allowed by the Aorai plugin." + +(****************************************************************************) + +(* The instrumentation is done in two passes: + 1) creating auxiliary functions for each non-ignored C function, that update + automaton's state when entering and exiting the function + 2) generating specifications for all the functions. + + We maintain tables from aux to orig so that the second visitor knows which + is which. Note that this tables are cleared after each visit, and thus need + not be projectified. +*) - - - -(**************************************************************************************) - +(* the various kinds of auxiliary functions. *) +type func_auto_mode = + Not_auto_func (* original C function. *) + | Pre_func of kernel_function (* Pre_func f denotes a function updating + the automaton before call to f. *) + | Post_func of kernel_function (* Post_func f denotes a function updating + the automaton when returning from f. *) + +(* table from auxiliary functions to the corresponding original one. *) +let func_orig_table = Cil_datatype.Varinfo.Hashtbl.create 17 + +let kind_of_func vi = + try Cil_datatype.Varinfo.Hashtbl.find func_orig_table vi + with Not_found -> Not_auto_func (** - This visitor add a ghost code before each call and return functions in order to compute the modification of the buchi automata. + This visitor adds an auxiliary function for each C function which takes + care of setting the automaton in a correct state before calling the + original one, and replaces each occurrence of the original function by + the auxiliary one. It also takes care of changing the automaton at function's + return. *) -class visit_adding_code_for_synchronisation (auto:Promelaast.buchautomata) = - let current_function = ref "" in - let get_call_name exp = - match exp.enode with - | Const(CStr(s)) -> s - | Lval(Var(vi),NoOffset) -> vi.vname - | _ -> - Aorai_option.abort - "At this time, only explicit calls are allowed by the \ - Aorai plugin.;" - in -object (*(self) *) +class visit_adding_code_for_synchronisation (auto:Promelaast.typed_automaton) = +object (self) inherit Visitor.generic_frama_c_visitor (Project.current ()) (Cil.inplace_visit ()) as super - method vfunc f = - current_function := f.svar.vname; - DoChildren + val aux_post_table = Kernel_function.Hashtbl.create 17 + method vglob_aux g = + match g with + | GFun (fundec,loc) -> + (* TODO: generate the aux_func_post *) + let kf = Extlib.the self#current_kf in + let vi = Kernel_function.get_vi kf in + let vi_pre = Cil_const.copy_with_new_vid vi in + vi_pre.vname <- Data_for_aorai.get_fresh (vi_pre.vname ^ "_pre_func"); + Cil_datatype.Varinfo.Hashtbl.add func_orig_table vi_pre (Pre_func kf); + (* TODO: + - what about protos that have no specified args + (NB: cannot be identified here because of implem of Kernel_function). + - what about varargs? + *) + let (rettype,args,varargs,_) = Cil.splitFunctionTypeVI vi_pre in + vi_pre.vtype <- TFun(Cil.voidType, args, varargs,[]); + vi_pre.vattr <- []; + (* in particular get rid of __no_return if set in vi*) + let arg = + if Cil.isVoidType rettype + then [] + else ["res",rettype,[]] + in + let vi_post = + Cil.makeGlobalVar + (Data_for_aorai.get_fresh (vi.vname ^ "_post_func")) + (TFun(voidType,Some arg,false,[])) + in + Kernel_function.Hashtbl.add aux_post_table kf vi_post; + Cil_datatype.Varinfo.Hashtbl.add func_orig_table vi_post (Post_func kf); + let globs = + [ GVarDecl(Cil.empty_funspec (), vi_pre, loc); + GVarDecl(Cil.empty_funspec (), vi_post,loc) ] + in + fundec.sbody.bstmts <- + Cil.mkStmtOneInstr + (Call(None,Cil.evar ~loc vi_pre, + List.map (fun x -> Cil.evar ~loc x) + (Kernel_function.get_formals kf), + loc)) + :: fundec.sbody.bstmts; + ChangeDoChildrenPost([g], fun x -> globs @ x) + | _ -> DoChildren method vstmt_aux stmt = match stmt.skind with - | Return (_,loc) -> - if not (Data_for_aorai.isIgnoredFunction !current_function) then begin - let sync_inst_l = Aorai_utils.synch_upd auto (!current_function) Promelaast.Return loc None None in - let new_return = mkStmt stmt.skind in - new_return.sid<-(Cil.Sid.next ()); - let new_stmts = - List.fold_left - (fun stmt_l inst -> - let n_stmt=(Cil.mkStmtOneInstr inst) in - n_stmt.sid<-(Cil.Sid.next ()); - n_stmt::stmt_l - ) - [new_return] - sync_inst_l - - in - stmt.skind<-Block(Cil.mkBlock(new_stmts)) - end; - SkipChildren - - - - (* This second treatment can be done easierly with vinst method, but sid is then set to -1 *) - | Instr(Call (_,funcexp,_,loc)) -> - if not (Data_for_aorai.isIgnoredFunction (get_call_name funcexp)) then begin - - let sync_inst_l = Aorai_utils.synch_upd auto (get_call_name funcexp) Promelaast.Call loc (Some(!current_function)) (Some(stmt.sid)) in - let new_call = mkStmt stmt.skind in - new_call.sid<-(Cil.Sid.next ()); - let new_stmts = - List.fold_left - (fun stmt_l inst -> - let n_stmt=(Cil.mkStmtOneInstr inst) in - n_stmt.sid<-(Cil.Sid.next ()); - n_stmt::stmt_l - ) - [new_call] - sync_inst_l - - in - stmt.skind<-Block(Cil.mkBlock(new_stmts)) - end; - SkipChildren - - + | Return (res,loc) -> + let kf = Extlib.the self#current_kf in + let vi = Kernel_function.get_vi kf in + let current_function = vi.vname in + if not (Data_for_aorai.isIgnoredFunction current_function) then begin + let args = match res with + | None -> [] + | Some exp -> [Cil.copy_exp exp] + in + let aux_vi = Kernel_function.Hashtbl.find aux_post_table kf in + let call = + mkStmtOneInstr (Call (None,Cil.evar ~loc aux_vi,args,loc)) + in + let new_return = mkStmt ~valid_sid:true stmt.skind in + let new_stmts = [call; new_return] in + stmt.skind<-Block(Cil.mkBlock(new_stmts)) + end; + SkipChildren | _ -> DoChildren end +(*********************************************************************) +(* update from formals of original C function to one of the auxiliary + function (f_aux or f_pre) + *) +class change_formals old_kf new_kf = + let old_formals = Kernel_function.get_formals old_kf in + let new_formals = Kernel_function.get_formals new_kf in + let formals = List.combine old_formals new_formals in +object + inherit Visitor.frama_c_inplace + method vlogic_var_use lv = + match lv.lv_origin with + | None -> SkipChildren + | Some vi -> + try + let vi'= List.assq vi formals in + ChangeTo (Cil.cvar_to_lvar vi') + with Not_found -> SkipChildren +end +(* update \result to param of f_post when it exists. Must not be called if + f_post has no parameter (original f returns void). *) +class change_result new_kf = + let v = List.hd (Kernel_function.get_formals new_kf) in +object + inherit Visitor.frama_c_inplace + method vterm_lhost lh = + match lh with + TResult _ -> ChangeTo (TVar (Cil.cvar_to_lvar v)) + | _ -> DoChildren +end +let post_treatment_loops = Hashtbl.create 97 +let get_action_invariant kf ki (status,_) = + let (state,_ as auto) = Data_for_aorai.getAutomata () in + let treat_one_state pre_state post_state = + let trans = Path_analysis.get_transitions_of_state pre_state auto in + if List.exists (fun x -> status.(x.stop.nums).(post_state.nums)) trans then + begin + let bindings = + Data_for_aorai.get_action_path kf ki pre_state post_state + in + List.map (Aorai_utils.update_to_pred post_state) bindings + end + else [] + in + List.flatten (Extlib.product treat_one_state state state) - - - - -(**************************************************************************************) - -let post_treatment_loops = Hashtbl.create 97; +let get_action_post_cond ?(pre_states=[]) ~post_states kf = + let (_, transitions) = Data_for_aorai.getAutomata () in + let pre_st, pre_tr = + Data_for_aorai.get_func_pre (Kernel_function.get_name kf) + in + let pre_states = + match pre_states with + | [] -> + let (states,_) = Data_for_aorai.getAutomata () in + List.filter (fun x -> pre_st.(x.nums)) states + | _ -> pre_states + in + let pre_states = + List.fold_left + (fun acc tr -> + if pre_tr.(tr.numt) && + List.exists + (fun x -> Data_for_aorai.Aorai_state.equal x tr.stop) pre_states + then Data_for_aorai.Aorai_state.Set.add tr.start acc else acc) + Data_for_aorai.Aorai_state.Set.empty transitions + in + let pre_states = Data_for_aorai.Aorai_state.Set.elements pre_states in + let treat_one_path pre_state post_state = + let post_conds = Aorai_utils.action_to_pred ~pre_state ~post_state kf in + Aorai_option.debug ~dkey:"action" + "Getting action post-conditions for %a, from state %s to state %s@\n%a" + Kernel_function.pretty kf + pre_state.Promelaast.name post_state.Promelaast.name + (Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep + !Ast_printer.d_predicate_named) + post_conds; + let pre = Aorai_utils.is_state_pred pre_state in + let pre = Logic_const.pold pre in + let post = Aorai_utils.is_state_pred post_state in + List.map + (fun p -> (Logic_const.pimplies (Logic_const.pand (pre,post), p))) + post_conds + in + let post_cond = + List.flatten (Extlib.product treat_one_path pre_states post_states) + in + List.map + (fun post_cond -> (Normal, Logic_const.new_predicate post_cond)) + post_cond (** This visitor add a specification to each fonction and to each loop, according to specifications stored into Data_for_aorai. *) -class visit_adding_pre_post_from_buch - (auto:Promelaast.buchautomata) treatloops = +class visit_adding_pre_post_from_buch auto treatloops = - let predicate_to_invariant ref_stmt pred = + let predicate_to_invariant kf stmt pred = (* 4) Add new annotation *) Annotations.add - !ref_stmt + kf + stmt [ (*Ast.self; *) - (*Aorai_option.Ltl_File.self; - Aorai_option.Buchi.self; - Aorai_option.Ya.self ;*) - (*Aorai_option.AbstractInterpretationOff.self ;*) - Aorai_option.AbstractInterpretation.self ] - (Db_types.Before - (Db_types.User - (Logic_const.new_code_annotation (AInvariant([],true,pred))))) ; + (*Aorai_option.Ltl_File.self; + Aorai_option.Buchi.self; + Aorai_option.Ya.self ;*) + (*Aorai_option.AbstractInterpretationOff.self ;*) + Aorai_option.AbstractInterpretation.self ] + (User + (Logic_const.new_code_annotation (AInvariant([],true,pred)))); in (** Given a couple of bool array (States , Transitions), this function computes a predicate and add it as an invariant. *) - let condition_to_invariant cond stmt_ref = - let pred_l = Aorai_utils.pre_post_to_term cond in - let pred = Aorai_utils.mk_conjunction_named pred_l in - predicate_to_invariant stmt_ref pred - in - - - (** Given the number of states a by-case post-condition and a state number, - it returns a bool array with nb_states cells. - A cell is true if and only if the associated post-condition is - equivalent to the one of the given state. *) - let get_other_states_with_equivalent_post nb_states (post_bc_st,post_bc_tr) index = - let eq_states=Array.make nb_states false in - eq_states.(index)<-true; - Array.iteri - (fun i post_st -> - if i<>index && - (bool_array_eq post_st post_bc_st.(index))&& - (bool_array_eq post_bc_tr.(i) post_bc_tr.(index)) (* Toujours Faux tq l'on veut eq des tr *) - then - eq_states.(i)<-true; - ) - post_bc_st; - eq_states + let condition_to_invariant kf (st, tr as cond) stmt = + let pred_authorized = Aorai_utils.pre_post_to_term cond in + let pred_forbidden = + Aorai_utils.pre_post_to_term_neg (Array.map not st,tr) + in + let pred = Logic_const.pand (pred_authorized, pred_forbidden) in + predicate_to_invariant kf stmt pred in - - -object (*(self) *) - - inherit Visitor.generic_frama_c_visitor - (Project.current ()) (Cil.inplace_visit ()) as super - - method vfunc f = - let spec= Kernel_function.get_spec (Globals.Functions.get f.svar) in - -(* Rewriting arrays carracterizing status into predicates *) - let preds_pre = Aorai_utils.pre_post_to_term (Data_for_aorai.get_func_pre f.svar.vname) in - let preds_post_bc = Data_for_aorai.get_func_post_bycase f.svar.vname in - -(* if AddingOperationNameAndStatusInSpecification is set*) -(* adding the condition CALLED for pre*) - let preds_pre_with_called_stat = fun preds_pre -> ( - - if Aorai_option.AddingOperationNameAndStatusInSpecification.get() then begin - let called_pre = Logic_const.prel (Req ,Aorai_utils.mk_term_from_vi (Data_for_aorai.get_varinfo Data_for_aorai.curOpStatus), (Logic_utils.mk_dummy_term (TConst(Data_for_aorai.op_status_to_cenum Promelaast.Call)) Cil.intType)) in - let called_pre_2 = Logic_const.prel (Req ,Aorai_utils.mk_term_from_vi (Data_for_aorai.get_varinfo Data_for_aorai.curOp), (Logic_utils.mk_dummy_term (TConst(Data_for_aorai.func_to_cenum f.svar.vname)) Cil.intType)) in - - List.append [called_pre;called_pre_2] preds_pre - end + let partition_pre_state (post_bc_st,_) = + let check_one_state (idx, equivs) case = + if Spec_tools.is_empty_behavior case then (idx+1,equivs) else - preds_pre - )in - let preds_pre = preds_pre_with_called_stat preds_pre in - - - let pre_wrt_params = Aorai_utils.get_preds_pre_wrt_params f.svar.vname in - let preds_pre = match pre_wrt_params with - | None -> preds_pre - | Some (p) -> (Logic_const.unamed p)::preds_pre + let is_equiv i1 = Spec_tools.bool_array_eq post_bc_st.(i1) case in + let rec aux l = + match l with + | [] -> [[idx]] + | eq::l -> + if is_equiv (List.hd eq) + then (idx::eq)::l + else eq :: aux l + in + (idx+1,aux equivs) in - - - - -(* Registration of the new specification *) - -(* + Pre-condition registration *) - - let new_requires = List.map Logic_const.new_predicate preds_pre in - let behavior = (* the default behavior having no assume *) - (Cil.mk_behavior ~requires:new_requires ()) in - spec.spec_behavior <- Logic_utils.merge_behaviors ~silent:true spec.spec_behavior [behavior] ; - - -(* + Post-condition registration *) -(* If several states are associated to the same post-condition, - then their specification is factorised. *) - let nb_states=Data_for_aorai.getNumberOfStates() in - let treated=ref (Array.make nb_states false) in - - - - -(* the goal is to know how many behavior are created: if only one behavior is created so the assumes is not needed*) - - let nb_behavior = ref 0 in - let save_assumes_l = ref [] in - (* Initialized with an empty behavior *) - let old_behavior = - ref (Cil.mk_behavior ~name:"" ()) + let (_,equivs) = Array.fold_left check_one_state (0,[]) post_bc_st in + equivs + in + let update_assigns loc spec = + let update_assigns bhv = + bhv.b_assigns <- + Logic_utils.concat_assigns bhv.b_assigns (Aorai_utils.aorai_assigns loc) + in + List.iter update_assigns spec.spec_behavior + in + let mk_auto_fct_spec kf status auto_state = + let loc = Kernel_function.get_location kf in + Aorai_utils.auto_func_behaviors loc kf status auto_state + in + let mk_pre_fct_spec kf = + mk_auto_fct_spec kf Promelaast.Call + (Data_for_aorai.get_func_pre (Kernel_function.get_name kf)) + in + let mk_post_fct_spec kf = + mk_auto_fct_spec kf Promelaast.Return + (Spec_tools.pre_flattening + (Data_for_aorai.get_func_post_bycase (Kernel_function.get_name kf))) + in + let mk_post kf = + let fct_name = Kernel_function.get_name kf in + let auto_state_pre = Data_for_aorai.get_func_pre fct_name in + (* Rewriting arrays characterizing status into predicates *) + let preds_post_bc = Data_for_aorai.get_func_post_bycase fct_name in + (* + Post-condition registration *) + (* If several states are associated to the same post-condition, + then their specification is factorised. *) + let equivs = partition_pre_state preds_post_bc in + let bhvs = + match equivs with + | [ s ] -> (* we just have one possible case, no need to generate + assumes and a negative behavior + *) + let name = "Buchi_property_behavior" in + let i = List.hd s in + let p = + Aorai_utils.pre_post_to_term + ((fst preds_post_bc).(i),(snd preds_post_bc).(i)) + in + let post_cond = Normal, Logic_const.new_predicate p in + let post_cond = + if Aorai_option.Deterministic.get () then [post_cond] + else begin + let p = + Aorai_utils.pre_post_to_term_neg + ((Array.map not (fst preds_post_bc).(i)), + (snd preds_post_bc).(i)) + in + [Normal, Logic_const.new_predicate p; post_cond] + end + in + let post_cond = + match Aorai_utils.get_preds_post_bc_wrt_params kf with + | None -> post_cond + | Some p -> (Normal, Logic_const.new_predicate p) :: post_cond + in + let post_states = + List.filter (fun x -> (fst preds_post_bc).(i).(x.nums)) + (fst (Data_for_aorai.getAutomata ())) + in + let post_cond = + post_cond @ get_action_post_cond ~post_states kf + in + [Cil.mk_behavior ~name ~post_cond ()] + | _ -> + let bhvs = + List.fold_left + (fun acc equiv -> + let case = List.hd equiv in + let pre_states = List.map Data_for_aorai.getState equiv in + let post_states = + List.filter (fun x -> (fst preds_post_bc).(case).(x.nums)) + (fst (Data_for_aorai.getAutomata ())) + in + let assumes_l = + List.map + (fun i -> + Aorai_utils.make_prev_pred + kf Promelaast.Call + (Data_for_aorai.getState i) auto_state_pre) + equiv + in + let name = "Buchi_property_behavior_in_"^(string_of_int case) in + let assumes = + [Logic_const.new_predicate (Logic_const.pors assumes_l)] + in + let p = + Aorai_utils.pre_post_to_term + ((fst preds_post_bc).(case),(snd preds_post_bc).(case)) + in + let post_cond = Normal, Logic_const.new_predicate p in + let post_cond = + match Aorai_utils.get_preds_post_bc_wrt_params kf with + | None -> [post_cond] + | Some p -> [Normal, Logic_const.new_predicate p; post_cond] + in + let post_cond = + post_cond @ + (get_action_post_cond ~pre_states ~post_states kf) + in + Cil.mk_behavior ~name ~assumes ~post_cond () :: acc) + [] + equivs + in + if Aorai_option.Deterministic.get () then bhvs + else begin + (* post-conditions for state in which we are not at the + end of the functions. They have to be grouped differently + than positive information because of non-determinism (if two + non-equivalent states are active when entering the function + and activate the same state at exit) + *) + let rec aux bhvs i = + if i < 0 then bhvs + else begin + let name = + "Buchi_property_behavior_out_" ^ (string_of_int i) in + let my_preds = + List.fold_left + (fun acc equiv -> + if (fst preds_post_bc).(List.hd equiv).(i) then + acc @ equiv + else acc) + [] equivs + in + let my_preds = List.map Data_for_aorai.getState my_preds in + let assumes = + Aorai_utils.make_prev_pred_neg + kf Promelaast.Call my_preds auto_state_pre + in + let assumes = [Logic_const.new_predicate assumes] in + let state = Data_for_aorai.getState i in + let p = Aorai_utils.is_out_of_state_pred state in + let post_cond = [Normal, Logic_const.new_predicate p] in + let bhvs = Cil.mk_behavior ~name ~assumes ~post_cond () :: bhvs + in aux bhvs (i-1) + end + in + aux bhvs (Data_for_aorai.getNumberOfStates () - 1) + end in - - - Array.iteri - (fun case preds_post -> - - if (not (Spec_tools.is_empty_behavior preds_post) ) - && (not (!treated).(case)) - then begin - let new_behavior = Cil.mk_behavior ~name:("Buchi_property_behavior_"^(string_of_int case)) () in - let all_eqs_states = get_other_states_with_equivalent_post nb_states preds_post_bc case in - let assumes_l = ref [] in - - - Array.iteri - (fun i b -> if b then - assumes_l:=Logic_const.prel( - Rneq, - Aorai_utils.zero_term(), - Aorai_utils.mk_offseted_array_states_as_enum - (Logic_utils.lval_to_term_lval ~cast:true (Cil.var (Data_for_aorai.get_varinfo Data_for_aorai.curState))) - i - )::!assumes_l - ) - all_eqs_states; - - -(* On the first behavior's creation, we supposed that assumes are not needed*) -(* but on the second, we know that the first must be set so*) -(* we put into the first the omitting behaviors (saved in old_behavior) and all assumes (saved in save_assumes_l)*) -(* After that, the loop is classic (behavior are automatically setted)*) - begin - match !nb_behavior with - | 0 -> nb_behavior:=1; - save_assumes_l := !assumes_l ; - old_behavior := new_behavior; - Aorai_option.debug "one behavior" - - | 1 -> nb_behavior:=2; - new_behavior.b_assumes<-[Logic_const.new_predicate (Aorai_utils.mk_disjunction_named !assumes_l)]; - (!old_behavior).b_assumes<-[Logic_const.new_predicate (Aorai_utils.mk_disjunction_named !save_assumes_l)]; - Aorai_option.debug "2 behaviors" - - | _ -> new_behavior.b_assumes<-[Logic_const.new_predicate (Aorai_utils.mk_disjunction_named !assumes_l)]; - end; - - - - Aorai_option.debug "behaviors registration"; - treated:=bool_array_or !treated all_eqs_states; - - (* - new_behavior.b_assumes<- - [Logic_const.new_predicate - (Logic_const.prel( - Rneq, - Aorai_utils.zero_term(), - Aorai_utils.mk_offseted_array - (Logic_const.lval_to_term_lval (Cil.var (Data_for_aorai.get_varinfo Data_for_aorai.curState))) - case))];*) - - - - let preds_list = Aorai_utils.pre_post_to_term (preds_post,(snd preds_post_bc).(case)) in - List.iter - (fun p -> - new_behavior.b_post_cond <- - ((Normal, Logic_const.new_predicate p) :: - new_behavior.b_post_cond)) - preds_list; - - - begin - let post_wrt_params = Aorai_utils.get_preds_post_bc_wrt_params f.svar.vname in - match post_wrt_params with - | None -> () - | Some (p) -> new_behavior.b_post_cond <- (Normal, Logic_const.new_predicate (Logic_const.unamed p))::new_behavior.b_post_cond - end; - - - spec.spec_behavior <- new_behavior::spec.spec_behavior - - end - ) - (fst preds_post_bc); -(* spec.spec_complete_behaviors <- new_behavior.b_name::spec.spec_complete_behaviors;*) - - (* if bycase is set*) (* adding require called and behavior ensures return *) - let preds_post_with_return_status = fun spec -> ( - if Aorai_option.AddingOperationNameAndStatusInSpecification.get() then begin - let called_post = Logic_const.new_predicate (Logic_const.prel (Req ,Aorai_utils.mk_term_from_vi (Data_for_aorai.get_varinfo Data_for_aorai.curOpStatus), (Logic_utils.mk_dummy_term (TConst(Data_for_aorai.op_status_to_cenum Promelaast.Return)) Cil.intType))) in - let called_post_2 = Logic_const.new_predicate (Logic_const.prel (Req ,Aorai_utils.mk_term_from_vi (Data_for_aorai.get_varinfo Data_for_aorai.curOp), (Logic_utils.mk_dummy_term (TConst(Data_for_aorai.func_to_cenum f.svar.vname)) Cil.intType))) in - let new_behavior = - { - b_name = "Buchi_property_behavior_function_states"; - b_assumes = [] ; - b_requires = [] ; - b_post_cond = [Normal, called_post; Normal, called_post_2] ; - b_assigns = WritesAny ; - b_extended = [] - } - in - spec.spec_behavior <- new_behavior::spec.spec_behavior - - end - else - () - )in - preds_post_with_return_status spec; - - DoChildren + + if Aorai_option.AddingOperationNameAndStatusInSpecification.get() + then begin + let called_post = + Logic_const.new_predicate + (Logic_const.prel + (Req , + Logic_const.tvar + (Data_for_aorai.get_logic_var Data_for_aorai.curOpStatus), + Logic_const.term + (TConst + (Data_for_aorai.op_status_to_cenum Promelaast.Return)) + (Ctype Cil.intType))) + in + let called_post_2 = + Logic_const.new_predicate + (Logic_const.prel + (Req, + Logic_const.tvar + (Data_for_aorai.get_logic_var Data_for_aorai.curOp), + Logic_const.term + (TConst(Data_for_aorai.func_to_cenum fct_name)) + (Ctype Cil.intType))) + in + let name = "Buchi_property_behavior_function_states" in + let post_cond = [Normal, called_post; Normal, called_post_2] in + Cil.mk_behavior ~name ~post_cond () :: bhvs + end else bhvs + in +object(self) + inherit Visitor.generic_frama_c_visitor + (Project.current ()) (Cil.inplace_visit ()) as super + (* We have to update assigns whenever a call occurs in the scope of + a statement contract (function always update the automaton's state, + so assigns there have to be changed anyway.) + *) + val has_call = Stack.create () + method private enter_block () = Stack.push (ref false) has_call + method private call () = Stack.iter (fun x -> x := true) has_call + method private leave_block () = !(Stack.pop has_call) + method vfunc f = + let my_kf = Extlib.the self#current_kf in + let vi = Kernel_function.get_vi my_kf in + let spec = Kernel_function.get_spec my_kf in + let loc = Kernel_function.get_location my_kf in + let fct_name = Kernel_function.get_name my_kf in + begin + match kind_of_func vi with + | Pre_func _ | Post_func _ -> + Aorai_option.fatal + "functions managing automaton's state are \ + not supposed to have a body" + | Not_auto_func -> (* Normal C function *) + let bhvs = mk_post my_kf in + let auto_state_pre = Data_for_aorai.get_func_pre fct_name in + let requires = + Aorai_utils.force_transition + loc my_kf Promelaast.Call auto_state_pre + in + let bhvs = + match Cil.find_default_behavior spec with + Some b -> + b.b_requires <- requires @ b.b_requires; bhvs + | None -> + let bhv = Cil.mk_behavior ~requires () in + bhv::bhvs + in + spec.spec_behavior <- bhvs @ spec.spec_behavior + end; + let after f = update_assigns f.svar.vdecl spec; f in + ChangeDoChildrenPost(f,after) + method vglob_aux g = + match g with + | GVarDecl(_,v,_) when + Cil.isFunctionType v.vtype + && not (Kernel_function.is_definition (Extlib.the self#current_kf)) + -> + let my_kf = Extlib.the self#current_kf in + (* don't use get_spec, as we'd generate default assigns, + while we'll fill the spec just below. *) + let spec = my_kf.spec in + let vi = Kernel_function.get_vi my_kf in + begin + match kind_of_func vi with + | Pre_func kf -> + (* must advance the automaton according to current call. *) + let bhvs = mk_pre_fct_spec kf in + let bhvs = + Visitor.visitFramacBehaviors (new change_formals kf my_kf) bhvs + in + spec.spec_behavior <- bhvs; + ChangeDoChildrenPost([g],fun x -> x) + | Post_func kf -> + (* must advance the automaton according to return event. *) + let (rt, _, _, _) = + Cil.splitFunctionTypeVI (Kernel_function.get_vi kf) + in + let bhvs = mk_post_fct_spec kf in + let bhvs = + (* if return type is not void, convert \result in the formal + arg of current kf. Otherwise, there's no conversion to do. + *) + if Cil.isVoidType rt then bhvs + else + Visitor.visitFramacBehaviors (new change_result my_kf) bhvs + in + spec.spec_behavior <- bhvs; + ChangeDoChildrenPost([g], fun x -> x) + | Not_auto_func -> DoChildren (* they are not considered here. *) + end + | _ -> DoChildren method vstmt_aux stmt = let treat_loop body_ref stmt = (* varinfo of the init_var associated to this loop *) - let vi_init = Data_for_aorai.get_varinfo (Data_for_aorai.loopInit^"_"^(string_of_int stmt.sid)) in - + let vi_init = + Data_for_aorai.get_varinfo + (Data_for_aorai.loopInit^"_"^(string_of_int stmt.sid)) + in (* 1) The associated init variable is set to 0 in first position (or in second position if the first stmt is a if)*) + let loc = Cil_datatype.Stmt.loc stmt in let stmt_varset = - Cil.mkStmtOneInstr - (Set((Var vi_init,NoOffset), - Aorai_utils.mk_int_exp 0, Location.unknown)) + Cil.mkStmtOneInstr + (Set((Var vi_init,NoOffset), Cil.zero ~loc, loc)) in stmt_varset.sid<-(Cil.Sid.next ()); stmt_varset.ghost<-true; - begin - (* Function adaptated from the cil printer *) + (* Function adapted from the cil printer *) try - let rec skipEmpty = function + let rec skipEmpty = function [] -> [] | {skind=Instr (Skip _);labels=[]} :: rest -> skipEmpty rest | x -> x in - match skipEmpty !body_ref.bstmts with | {skind=If(_,tb,fb,_)} as head:: _ -> begin @@ -467,149 +662,146 @@ | _, {skind=Goto _} :: _ | {skind=Goto _} :: _, _ | {skind=Break _} :: _, _ -> - !body_ref.bstmts<-head::(stmt_varset::(List.tl !body_ref.bstmts)) - - | _ -> - raise Not_found + !body_ref.bstmts <- + head :: stmt_varset :: List.tl !body_ref.bstmts + | _ -> + raise Not_found end | _ -> raise Not_found - - with - | Not_found -> - !body_ref.bstmts<-stmt_varset::!body_ref.bstmts + with + | Not_found -> + !body_ref.bstmts<-stmt_varset::!body_ref.bstmts end; - (* 2) The associated init variable is set to 1 before the loop *) let new_loop = mkStmt stmt.skind in new_loop.sid<-(Cil.Sid.next ()); let stmt_varset = - Cil.mkStmtOneInstr (Set((Var(vi_init),NoOffset), - Aorai_utils.mk_int_exp 1, Location.unknown)) + Cil.mkStmtOneInstr + (Set((Var(vi_init),NoOffset), Cil.one ~loc, loc)) in stmt_varset.sid <- Cil.Sid.next (); stmt_varset.ghost <- true; let block = mkBlock [stmt_varset;new_loop] in stmt.skind<-Block(block); - - - (* 3) Generation of the loop invariant *) let mk_imply operator predicate = - (Logic_const.unamed - (Pimplies - (Logic_const.unamed (Prel(operator, - Aorai_utils.mk_term_from_vi vi_init, - Aorai_utils.zero_term())), - Logic_const.unamed predicate))) + pimplies + (prel(operator, + Aorai_utils.mk_term_from_vi vi_init, + Aorai_utils.zero_term()), + predicate) in (* The loop invariant is : - (Global invariant) // all never reached state /crossed transition are set to zero + (Global invariant) // all never reached state are set to zero & (Pre2) // internal pre-condition & (Init => Pre1) // external pre-condition & (not Init => Post2) // internal post-condition + & counter_invariant // values of counters. (init : fresh variable which indicates if the iteration is the first one). *) - let global_loop_inv = Aorai_utils.get_global_loop_inv (ref stmt) in - condition_to_invariant global_loop_inv (ref new_loop); - - let pre2 = Aorai_utils.get_restricted_int_pre_bc (ref stmt) in - if pre2<>Cil_types.Ptrue then - predicate_to_invariant (ref new_loop) (Logic_const.unamed pre2); - - let pre1 = Aorai_utils.get_restricted_ext_pre_bc (ref stmt) in - if pre1<>Cil_types.Ptrue then - predicate_to_invariant (ref new_loop) (mk_imply Rneq pre1); - - let post2 = Aorai_utils.get_restricted_int_post_bc (ref stmt) in - if post2<>Cil_types.Ptrue then - predicate_to_invariant (ref new_loop) (mk_imply Req post2); - - + let kf = Extlib.the self#current_kf in + let global_loop_inv = Aorai_utils.get_global_loop_inv stmt in + condition_to_invariant kf global_loop_inv new_loop; + + let pre2 = Aorai_utils.get_restricted_int_pre_bc stmt in + if pre2.content <> Ptrue then + predicate_to_invariant kf new_loop pre2; + + let pre1 = Aorai_utils.get_restricted_ext_pre_bc stmt in + if pre1.content <> Ptrue then + predicate_to_invariant kf new_loop (mk_imply Rneq pre1); + + let post2 = Aorai_utils.get_restricted_int_post_bc stmt in + if post2.content <> Ptrue then + predicate_to_invariant kf new_loop (mk_imply Req post2); + + let action_state = + Spec_tools.double_bool_array_or_bycase + (Data_for_aorai.get_loop_int_post_bycase stmt) + (Data_for_aorai.get_loop_ext_pre_bycase stmt) + in + let action_inv = get_action_invariant kf (Kstmt stmt) action_state in + List.iter (predicate_to_invariant kf new_loop) action_inv; (* 4) Keeping in mind to preserve old annotations after visitor end *) Hashtbl.add post_treatment_loops (ref stmt) (ref new_loop); - (* 5) Updated stmt is returned *) - stmt + stmt + in + self#enter_block (); + let after s = + if self#leave_block () then + begin + let annots = Annotations.get_all_annotations stmt in + let annots = + List.map Annotations.get_code_annotation annots in + let specs = + snd (List.split (Logic_utils.extract_contract annots)) + in + List.iter (update_assigns (Cil_datatype.Stmt.loc stmt)) specs; + s + end + else s in if treatloops then match stmt.skind with - | Loop (_,block,_,_,_) -> - ChangeDoChildrenPost(stmt, treat_loop (ref block)) + | Loop (_,block,_,_,_) -> + ChangeDoChildrenPost(stmt, after $ (treat_loop (ref block))) - | _ -> DoChildren + | _ -> ChangeDoChildrenPost(stmt, after) else - DoChildren + ChangeDoChildrenPost(stmt,after) + + method vinst = function + | Call _ -> self#call (); DoChildren + | _ -> DoChildren + end -(**************************************************************************************) +(****************************************************************************) (** This visitor computes the list of ignored functions. - A function is ignored if its call is present in the C program, while its declaration is not available. + A function is ignored if its call is present in the C program, + while its definition is not available. *) class visit_computing_ignored_functions () = - let current_function = ref "" in - - let get_call_name exp = - match exp.enode with - | Const(CStr(s)) -> s - | Lval(Var(vi),NoOffset) -> vi.vname - | _ -> - Aorai_option.abort - "At this time, only explicit calls are allowed by the \ - Aorai plugin.;" - in - let declaredFunctions = Data_for_aorai.getFunctions_from_c () in let isDeclaredInC fname = List.exists (fun s -> (String.compare fname s)=0) declaredFunctions in - - object (*(self) *) + inherit Visitor.generic_frama_c_visitor (Project.current ()) (Cil.inplace_visit ()) as super - method vfunc f = - current_function := f.svar.vname; - DoChildren - + method vfunc _f = DoChildren method vstmt_aux stmt = match stmt.skind with | Instr(Call (_,funcexp,_,_)) -> - let name = get_call_name funcexp in - (* If the called function is neither ignored, nor declared, then it has to be added to ignored functions. *) - if (not (Data_for_aorai.isIgnoredFunction name)) - && (not (isDeclaredInC name)) then - (Data_for_aorai.addIgnoredFunction name); - DoChildren - - - + let name = get_call_name funcexp in + (* If the called function is neither ignored, nor declared, + then it has to be added to ignored functions. *) + if (not (Data_for_aorai.isIgnoredFunction name)) + && (not (isDeclaredInC name)) then + (Data_for_aorai.addIgnoredFunction name); + DoChildren | _ -> DoChildren end - - - - - -(**************************************************************************************) - - - +(*************************************************************************) (* Call of the visitors *) + let compute_abstract file root (considerAcceptance:bool) = let visitor = new visit_computing_abstract_pre_post_from_buch (Data_for_aorai.getAutomata()) (root) considerAcceptance @@ -624,36 +816,21 @@ treatloops in Cil.visitCilFile (visitor :> Cil.cilVisitor) file; - (* Transfert previous annotation on the new loop statement. + (* Transfer previous annotation on the new loop statement. Variant clause has to be preserved at the end of the annotation.*) Hashtbl.iter (fun old_stmt new_stmt -> - Annotations.single_iter_stmt - (fun an -> Annotations.add !new_stmt - [(* Ast.self; Aorai_option.Ltl_File.self; - Aorai_option.Buchi.self; - Aorai_option.Ya.self *) ] an) - !old_stmt; - - (* Erasing annotations from old statement *) - Annotations.reset_stmt ?reset:true !old_stmt; - + let new_s = !new_stmt in + let old_s = !old_stmt in + let kf = Kernel_function.find_englobing_kf old_s in + let old_annots = Annotations.get_all_annotations old_s in + (* Erasing annotations from the old statement before attaching them with + the new one *) + Annotations.reset_stmt ?reset:true kf old_s; + List.iter (Annotations.add kf new_s []) old_annots; ) post_treatment_loops - - - - - - - - - - - - - let add_sync_with_buch file = let visitor = new visit_adding_code_for_synchronisation (Data_for_aorai.getAutomata()) @@ -667,6 +844,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/bool3.ml frama-c-20111001+nitrogen+dfsg/src/aorai/bool3.ml --- frama-c-20110201+carbon+dfsg/src/aorai/bool3.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/bool3.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -49,6 +51,8 @@ | False -> True | Undefined -> Undefined +let bool3_of_bool b = if b then True else False + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/bool3.mli frama-c-20111001+nitrogen+dfsg/src/aorai/bool3.mli --- frama-c-20110201+carbon+dfsg/src/aorai/bool3.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/bool3.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -29,7 +31,7 @@ val bool3and: t -> t -> t val bool3or: t -> t -> t val bool3not: t -> t - +val bool3_of_bool: bool -> t (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/bycase_ai.ml frama-c-20111001+nitrogen+dfsg/src/aorai/bycase_ai.ml --- frama-c-20110201+carbon+dfsg/src/aorai/bycase_ai.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/bycase_ai.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,17 +23,324 @@ (* *) (**************************************************************************) -(* $Id: bycase_ai.ml,v 1.4 2008-12-19 15:30:56 uid588 Exp $ *) - +open Data_for_aorai +open Promelaast open Cil_types open Cil open Cilutil open Ast_info open Spec_tools +let active_before_call kf = + let (_,pre_trans) = Data_for_aorai.get_func_pre (Kernel_function.get_name kf) + in + let (_,trans) = Data_for_aorai.getAutomata () in + List.fold_left + (fun acc tr -> + if pre_trans.(tr.numt) then + Data_for_aorai.Aorai_state.Set.add tr.start acc + else acc) + Data_for_aorai.Aorai_state.Set.empty trans + +let merge_opt f k o1 o2 = + match o1,o2 with + | None, None -> None + | Some x, None | None, Some x -> Some x + | Some x1, Some x2 -> Some (f k x1 x2) + +let compose_range loc b r1 r2 = + match r1, r2 with + | Fixed c1, Fixed c2 -> Fixed (c1 + c2) + | Fixed c, Interval(min,max) | Interval(min,max), Fixed c -> + Interval (c+min,c+max) + | Fixed c, Bounded(min,max) | Bounded(min,max), Fixed c -> + let max = + Logic_const.term + (TBinOp(PlusA,max, Logic_const.tinteger ~ikind:IInt c)) + Linteger + in + Bounded(c+min,max) + | Fixed c1, Unbounded min | Unbounded min, Fixed c1 -> Unbounded (min+c1) + | Interval(min1,max1), Interval(min2,max2) -> + Interval(min1+min2,max1+max2) + (* NB: in the bounded case, we could check if upper bound of interval + is less then lower bound of bounded to keep bounded. + *) + | Interval(min1,_), Bounded(min2,_) | Bounded(min2,_), Interval(min1,_) + | Interval(min1,_), Unbounded min2 | Unbounded min2, Interval (min1,_) + | Bounded(min1, _), Bounded (min2, _) | Unbounded min1, Unbounded min2 + | Bounded(min1,_), Unbounded min2 | Unbounded min1, Bounded(min2,_) + -> + if Cil.isLogicZero b then Data_for_aorai.absolute_range loc (min1 + min2) + else Unbounded (min1 + min2) + +let compose_bindings map1 loc vals map = + let vals = Cil_datatype.Term.Map.fold + (fun base intv vals -> + let vals' = + if Cil.isLogicZero base then + Cil_datatype.Term.Map.add base intv Cil_datatype.Term.Map.empty + else + try + let orig_base = Cil_datatype.Term.Map.find base map1 in + Cil_datatype.Term.Map.fold + (fun base intv' map -> + let intv' = compose_range loc base intv' intv in + Cil_datatype.Term.Map.add base intv' map + ) + orig_base Cil_datatype.Term.Map.empty + with Not_found -> + Cil_datatype.Term.Map.add base intv Cil_datatype.Term.Map.empty + in + Cil_datatype.Term.Map.merge + (merge_opt (Data_for_aorai.merge_range loc)) vals' vals + ) + vals Cil_datatype.Term.Map.empty + in + try + let vals' = Cil_datatype.Term.Map.find loc map in + let vals' = + Cil_datatype.Term.Map.merge + (merge_opt (Data_for_aorai.merge_range loc)) vals' vals + in + Cil_datatype.Term.Map.add loc vals' map + with Not_found -> + Cil_datatype.Term.Map.add loc vals map + +let compose_actions map1 map2 = + let map = + Cil_datatype.Term.Map.fold (compose_bindings map1) + map2 Cil_datatype.Term.Map.empty + in + Cil_datatype.Term.Map.fold + (fun elt bind map -> + if Cil_datatype.Term.Map.mem elt map2 then map + else Cil_datatype.Term.Map.add elt bind map) map1 map + +let print_action_binding fmt action = + Cil_datatype.Term.Map.iter (fun t m -> + Cil_datatype.Term.Map.iter (fun t' itv -> + Format.fprintf fmt "%a <- %a + %a@." !Ast_printer.d_term t + !Ast_printer.d_term t' Data_for_aorai.Range.pretty itv) m) + action + +let update_action_call kf pre_ki ki called_func pre_call_st post_call_st = + let ret_called = Kstmt (Kernel_function.find_return called_func) in + let (_,pre_trans) = + Data_for_aorai.get_func_pre (Kernel_function.get_name kf) + in + let (_,call_trans) = + Data_for_aorai.get_func_pre (Kernel_function.get_name called_func) + in + let treat_one_state_post pre pre_call post_call = + let current_actions = + Data_for_aorai.get_action_bindings kf pre_ki pre pre_call in + let post_actions = + Data_for_aorai.get_action_bindings + called_func ret_called pre_call post_call + in + let res = compose_actions current_actions post_actions in +(* Format.printf "Merging actions in %a: %s -> %s@.%aand@.%agive@.%a" + Cil_datatype.Kinstr.pretty pre_ki + pre.Promelaast.name post_call.Promelaast.name + print_action_binding current_actions + print_action_binding post_actions + print_action_binding res; *) + Data_for_aorai.merge_action_bindings kf ki pre post_call res + in + let treat_one_trans_call pre pre_call trans = + if call_trans.(trans.numt) then begin + Array.iteri + (fun index b -> + if b then begin + let state = Data_for_aorai.getState index in + treat_one_state_post pre pre_call state + end) + post_call_st.(trans.stop.nums) + end + in + let auto = Data_for_aorai.getAutomata () in + let treat_one_call_state pre pre_call = + let trans = Path_analysis.get_transitions_of_state pre_call auto in + List.iter (treat_one_trans_call pre pre_call) trans + in + let treat_one_trans_pre pre trans = + if pre_trans.(trans.numt) then begin + Array.iteri + (fun index b -> + if b then begin + let state = Data_for_aorai.getState index in + treat_one_call_state pre state + end) + pre_call_st.(trans.stop.nums) + end + in + let update_one_action pre = + let trans = Path_analysis.get_transitions_of_state pre auto in + List.iter (treat_one_trans_pre pre) trans + in + let my_pre = active_before_call kf in + Data_for_aorai.Aorai_state.Set.iter update_one_action my_pre + +let compose_assocs_post assocs_st (post_st,post_tr) = + let st,tr = mk_empty_pre_or_post () in + let st,tr = ref st, ref tr in + Array.iteri + (fun index b -> + if b then begin + st:=bool_array_or post_st.(index) !st; + tr:=bool_array_or post_tr.(index) !tr + end) + assocs_st; + (!st,!tr) + +let compose_assocs_pre assocs_st (_,pre_tr) (post_st,_) = + let st,tr = mk_empty_pre_or_post () in + let st,tr = ref st, ref tr in + let (_,trans_l) = Data_for_aorai.getAutomata() in + Array.iteri + (fun index b -> + if b then begin + Array.iteri + (fun value val_assocs -> if val_assocs.(index) then !st.(value)<-true) + post_st; + end + ) + assocs_st; + List.iter + (fun t -> if pre_tr.(t.numt) && (!st).(t.stop.nums) then !tr.(t.numt)<-true) + trans_l; + (!st,!tr) + + +(** bool array array -> (bool array array*bool array array) -> (bool array array*bool array array) + Given a set of states and the bycase post-condition of an operation + this function returns the new pre-condition after the call of the operation in the context of current_st. +*) +let mk_forward_composition kf pre_ki ki called_func pre_st in_func_st post = + let new_st,new_tr = mk_empty_pre_or_post_bycase () in + Array.iteri + (fun index assocs -> + let s,t = compose_assocs_post assocs post in + new_st.(index)<-s; + new_tr.(index)<-t + ) + in_func_st; + update_action_call kf pre_ki ki called_func pre_st (fst post); + (new_st,new_tr) + +(** bool array array -> (bool array*bool array) -> (bool array array*bool array array) -> (bool array array*bool array array) + Given a set of states and the bycase post-condition of an operation + this function returns the new pre-condition after the call of the operation in the context of current_st. +*) +let mk_backward_composition current_st pre post = + let new_st,new_tr = mk_empty_pre_or_post_bycase () in + Array.iteri + (fun index assocs -> + let s,t = compose_assocs_pre assocs pre post in + new_st.(index)<-s; + new_tr.(index)<-t + ) + current_st; + (new_st,new_tr) +let merge_actions kf ki ki1 ki2 post_st1 post_st2 = + let (state,_ as auto) = Data_for_aorai.getAutomata () in +(* Format.printf "Merging from %a and %a in %a@." + Cil_datatype.Kinstr.pretty ki1 + Cil_datatype.Kinstr.pretty ki2 + Cil_datatype.Kinstr.pretty ki; *) + let merge_one_path pre_state post_state = + let trans = Path_analysis.get_transitions_of_state pre_state auto in + if List.exists + (fun x -> post_st1.(x.stop.nums).(post_state.nums)) trans + then begin + let action = + Data_for_aorai.get_action_bindings kf ki1 pre_state post_state + in + Data_for_aorai.merge_action_bindings kf ki pre_state post_state action + end; + if List.exists + (fun x -> post_st2.(x.stop.nums).(post_state.nums)) trans + then begin + let action = + Data_for_aorai.get_action_bindings kf ki2 pre_state post_state + in + Data_for_aorai.merge_action_bindings kf ki pre_state post_state action + end; +(* if List.exists + (fun x -> post_st2.(x.stop.nums).(post_state.nums) + || post_st1.(x.stop.nums).(post_state.nums)) + trans + then begin + let res = Data_for_aorai.get_action_bindings kf ki pre_state post_state in + Format.printf "%s -> %s Result is@.%a" + pre_state.Promelaast.name post_state.Promelaast.name + print_action_binding res + end *) + in + ignore (Extlib.product merge_one_path state state) +let compute_actions_invariant action_pre action_post = + let changed = ref false in + let merge_binding_opt loc base range1 range2 = + match range1, range2 with + | _, None -> range1 + | None, Some _ -> changed:=true; range2 + | Some r1, Some r2 -> + let res = Data_for_aorai.merge_range loc base r1 r2 in + if not (Data_for_aorai.Range.equal r1 res) then changed:=true; + Some res + in + let merge_bases loc bindings1 bindings2 = + match bindings1, bindings2 with + | _, None -> bindings1 + | None, Some b2 -> changed:=true; + let b1 = + Cil_datatype.Term.Map.add + (Cil.lzero ()) (Fixed 0) Cil_datatype.Term.Map.empty + in + Some (Cil_datatype.Term.Map.merge (merge_binding_opt loc) b1 b2) + | Some b1, Some b2 -> + Some (Cil_datatype.Term.Map.merge (merge_binding_opt loc) b1 b2) + in + let map = Cil_datatype.Term.Map.merge merge_bases action_pre action_post in + !changed, map + +let update_loop_actions kf init inner last (post_st,_) = + let (state,_ as auto) = Data_for_aorai.getAutomata () in + let changed = ref false in + let merge_one_path pre_state post_state = + let trans = Path_analysis.get_transitions_of_state pre_state auto in + if + List.exists (fun x -> post_st.(x.stop.nums).(post_state.nums)) trans + then begin + let action_pre = + Data_for_aorai.get_action_bindings kf init pre_state post_state + in + let action_step = + Data_for_aorai.get_action_bindings kf inner pre_state post_state + in + let has_changed, action = + compute_actions_invariant action_pre action_step + in + changed := !changed || has_changed; +(* if has_changed then begin + Format.printf + "%s -> %s In loop (init is %a, inner is %a, after is %a):@.\ + Before:@.%aAfter:@.%a" + pre_state.Promelaast.name post_state.Promelaast.name + Cil_datatype.Kinstr.pretty init Cil_datatype.Kinstr.pretty inner + Cil_datatype.Kinstr.pretty last + print_action_binding action_pre print_action_binding action; + end; +*) + Data_for_aorai.set_action_bindings kf last pre_state post_state action + end + in + ignore (Extlib.product merge_one_path state state); + !changed let init_specification () = List.iter @@ -53,52 +362,185 @@ Array.iteri (fun st2 b -> if b then - if not (Path_analysis.existing_path (Data_for_aorai.getAutomata()) st1 st2) then + if + not + (Path_analysis.existing_path + (Data_for_aorai.getAutomata()) st1 st2) + then begin post_st.(st1).(st2) <- false; - if Aorai_option.verbose_atleast 2 then - Aorai_option.feedback "Function %s : state %s unreachable in post from %s (Dijkstra simplification).\n" name (Data_for_aorai.getStateName st2) (Data_for_aorai.getStateName st1) + Aorai_option.feedback ~level:2 + "Function %s : state %s unreachable in post \ + from %s (Dijkstra simplification).\n" name + (Data_for_aorai.getStateName st2) + (Data_for_aorai.getStateName st1) end ) post ; ) post_st; - (* Removing transitions corresponding to unreachable states *) Array.iteri (fun st1 _ -> List.iter - (fun (tr:Promelaast.trans) -> + (fun tr -> let st2 = tr.Promelaast.stop.Promelaast.nums in if (not (post_st.(st1).(st2))) && post_tr.(st1).(tr.Promelaast.numt) then begin post_tr.(st1).(tr.Promelaast.numt) <- false; if Aorai_option.verbose_atleast 2 then - Aorai_option.feedback "Function %s : transition %d reaches an unreachable state in post from %s (Dijkstra simplification).\n" name tr.Promelaast.numt (Data_for_aorai.getStateName st1) + Aorai_option.feedback + "Function %s: transition %d reaches an unreachable \ + state in post from %s (Dijkstra simplification)." + name tr.Promelaast.numt + (Data_for_aorai.getStateName st1) end ) (snd (Data_for_aorai.getAutomata())) ) - post_tr; - - + post_tr; Data_for_aorai.set_func_post_bycase name (post_st,post_tr) ) (Data_for_aorai.getFunctions_from_c ()) - - - - +let tlval lv = Logic_const.term (TLval lv) (Cil.typeOfTermLval lv) +let actions_to_range l = + let treat_one_action acc = + function + | Counter_init lv -> + let t = tlval lv in + (t,(Cil.lzero(), Fixed 1)) :: acc + | Counter_incr lv -> + let t = tlval lv in + (t, (t,Fixed 1)) :: acc + | Pebble_init(_,_,c) -> (* TODO: put post-conds on pebble sets *) + let t = Logic_const.tvar c in + (t,(t,Fixed 1)) :: acc + | Pebble_move _ -> acc (* TODO: put post-conds on pebble sets *) + | Copy_value (lv,t) -> + let loc = tlval lv in + (loc,(t,Fixed 0)) :: acc + in List.fold_left treat_one_action [] l + +let update_actions_call_func kf (_,tr) = + (* We update actions for the active transitions at the entrance + of the function: the active states are exactly the ones upon which we + split (and the ending states of the active transitions) + *) + let treat_one_trans idx status = + if status then begin + let trans = Data_for_aorai.getTransition idx in + Aorai_option.debug ~dkey:"action" + "Call to %a: treating actions of trans %s -> %s" + Kernel_function.pretty kf + trans.start.Promelaast.name trans.stop.Promelaast.name; + let actions = actions_to_range (snd trans.cross) in + List.iter + (fun (l,v) -> + Aorai_option.debug ~dkey:"action" + "Add binding for %a: %a + %a" + Cil_datatype.Term.pretty l Cil_datatype.Term.pretty (fst v) + Data_for_aorai.Range.pretty (snd v); + Data_for_aorai.add_action_path kf Kglobal trans.start trans.stop l v) + actions + end + in + Array.iter (Array.iteri treat_one_trans) tr +let add_one ~is_absolute = function + | Fixed c -> Fixed (c+1) + | Interval(min,max) -> Interval(min+1,max+1) + | Bounded _ as r when is_absolute -> r + | Bounded (min,_) -> Unbounded (min+1) + | Unbounded min -> Unbounded (min+1) + +let actions_to_range_step kf ki st1 trans = + let map = Data_for_aorai.get_action_bindings kf ki st1 trans.start in + let treat_one_action acc = + function + | Counter_init lv -> + let t = tlval lv in + (t,(Cil.lzero(), Fixed 1)) :: acc + | Counter_incr lv -> + let t = tlval lv in + (try + (let bindings = Cil_datatype.Term.Map.find t map in + let abs = + try + let r = Cil_datatype.Term.Map.find (Cil.lzero()) bindings in + let r = add_one ~is_absolute:true r in + (t, (Cil.lzero(), r)) :: acc + with Not_found -> acc + in + try + let r = Cil_datatype.Term.Map.find t bindings in + let r = add_one ~is_absolute:false r in + (t, (t,r)) :: acc + with Not_found -> abs) + with Not_found -> + (* adds an absolute binding *) + (t, (Cil.lzero(), Data_for_aorai.absolute_range t 1))::acc) + | Pebble_init(_,_,c) -> (* TODO: put post-conds on pebble sets *) + let t = Logic_const.tvar c in + (t,(t,Fixed 1)) :: acc + | Pebble_move _ -> acc (* TODO: put post-conds on pebble sets *) + | Copy_value (lv,t) -> + let loc = tlval lv in + (loc,(t,Fixed 0)) :: acc + in List.fold_left treat_one_action [] (snd trans.cross) + +let update_actions_return_func kf ki tr = + let ret_ki = Kstmt (Kernel_function.find_return kf) in + let auto = Data_for_aorai.getAutomata () in + let treat_one_trans pre_state idx status = + let trans = Data_for_aorai.getTransition idx in + let map = Data_for_aorai.get_action_bindings kf ki pre_state trans.start in + if status then begin + Aorai_option.debug ~dkey:"action" + "Return statement of %a: treating transition %s -> %s \ + from initial state %s" + Kernel_function.pretty kf + trans.start.Promelaast.name trans.stop.Promelaast.name + pre_state.Promelaast.name; + Cil_datatype.Term.Map.iter + (fun l _ -> Aorai_option.debug ~dkey:"action" + "Got binding for %a" Cil_datatype.Term.pretty l) + map; + let actions = actions_to_range_step kf ki pre_state trans in + let map = + List.fold_left + (fun map (l, (b,r)) -> + Aorai_option.debug ~dkey:"action" "%a <- %a + %a" + Cil_datatype.Term.pretty l Cil_datatype.Term.pretty b + Data_for_aorai.Range.pretty r; + let bindings = + try Cil_datatype.Term.Map.find l map + with Not_found -> Cil_datatype.Term.Map.empty + in + Cil_datatype.Term.Map.add + l (Cil_datatype.Term.Map.add b r bindings) map) + map actions + in + Data_for_aorai.merge_action_bindings kf ret_ki pre_state trans.stop map + end + in + let treat_one_pre_trans trans = + Array.iteri (treat_one_trans trans.start) tr.(trans.stop.nums) + in + let treat_one_state pre_state = + let my_trans = Path_analysis.get_transitions_of_state pre_state auto in + List.iter treat_one_pre_trans my_trans + in + let pre_states = active_before_call kf in + Data_for_aorai.Aorai_state.Set.iter treat_one_state pre_states (** Global information on functions that are collected during each pass. These - information are furthermore used torestrict pre or post-condition of - fonctions according to there scope of use. + information are furthermore used to restrict pre or post-condition of + fonctions according to their scope of use. *) let functions_pre_usecase : (string , (bool array array * bool array array)) Hashtbl.t = Hashtbl.create 97 let functions_post_usecase : (string , (bool array array * bool array array)) Hashtbl.t = Hashtbl.create 97 @@ -108,10 +550,6 @@ (* Mark to ensures the completion of functions specification computation *) let spec_modified = ref false - - - - (** This visitor requires that each function has a specification. It then computes a finer specification by forward and backard abstract interpretation @@ -120,7 +558,8 @@ This vistor use mainly 2 sub-functions (propagates_pre and propagates_post) that implement respectively forward and backward treatment. *) -class visit_propagating_pre_post_constraints_bycase (auto:Promelaast.buchautomata) = +class visit_propagating_pre_post_constraints_bycase + (auto:Promelaast.typed_automaton) = (***************************************************************************) (* For the two pass *) (* *) @@ -140,10 +579,9 @@ (** During the pre-condition propagation, it represents the set of statements that need second computation of specification. For instance, it can occurs when the statement is pointed by a goto instruction. *) - let stmts_to_compute_one_more_time : (int , bool) Hashtbl.t = Hashtbl.create 97 in - (* *) - (** This variable contains the result of the pre-condition propagation. *) - let propagation_result = ref (mk_empty_pre_or_post_bycase ()) in + let stmts_to_compute_one_more_time : (int , bool) Hashtbl.t = + Hashtbl.create 97 + in (* *) (***************************************************************************) (* For the post-condition propagation pass *) @@ -174,19 +612,19 @@ let loop_bwd_int_post = Hashtbl.create 97 in (* *) (* Accessors for loop specification *) - let get_loop_local_info hashtbl stmt_ref = - try Hashtbl.find hashtbl stmt_ref + let get_loop_local_info hashtbl stmt = + try Hashtbl.find hashtbl stmt with _ -> mk_full_pre_or_post_bycase() in (* status des functions a insérer *) (* *) - let update_loop_local_info hashtbl stmt_ref value = + let update_loop_local_info hashtbl stmt value = let info = - if (Hashtbl.mem hashtbl stmt_ref ) - then double_bool_array_or_bycase value (Hashtbl.find hashtbl stmt_ref) + if Hashtbl.mem hashtbl stmt + then double_bool_array_or_bycase value (Hashtbl.find hashtbl stmt) else value in - Hashtbl.replace hashtbl stmt_ref info + Hashtbl.replace hashtbl stmt info in (* *) (***************************************************************************) @@ -200,17 +638,12 @@ in Hashtbl.replace hasbtbl key new_value in + (** Propagates pre-condition to each statement, by following control flow. + It returns a couple of bool array, defining the strongest + post-condition of the statement list. *) + let rec propagates_pre kf ki stmt_l (pre_st,pre_tr) = - - - - - -(** Propagates pre-condition to each statement, by following control flow. - It returns a couple af bool array, definig the strongest post-condition of the statement list. *) - let rec propagates_pre stmt_l (pre_st,pre_tr) = - - (** This function returns the curent pre of a statement or an empty + (** This function returns the current pre of a statement or an empty pre if no specification exists *) let get_labelled_stmt_pre stmt_sid = try @@ -222,8 +655,9 @@ - (** This function makes an OR filter between the given pre and the old pre of the given stmt - The result is storing as the new pre of the given stmt. *) + (** This function makes an OR filter between the given + pre and the old pre of the given stmt + The result is stored as the new pre of the given stmt. *) let update_labelled_stmt_pre stmt_sid pre = try let old_pre = Hashtbl.find labelled_stmts_pre stmt_sid in @@ -237,14 +671,18 @@ (** This function returns the current pre of the given statement. WARNING ! Side effects of this function : - * If the statement is in stmts_to_compute_one_more_time then it is removed - * The pre of the current stmt is updated according to the current pre_st and pre_tr + * If the statement is in stmts_to_compute_one_more_time + then it is removed + * The pre of the current stmt is updated according + to the current pre_st and pre_tr *) let update_and_get_stmts_pre stmt_sid with_labels = - (* If this statement is annotated to be computed again then we remove its annotation. *) + (* If this statement is annotated to be computed + again then we remove its annotation. *) Hashtbl.remove stmts_to_compute_one_more_time stmt_sid; - (* Registering the new specification only if it is a stmt with multiple entry points (labelled stmt) *) + (* Registering the new specification only if + it is a stmt with multiple entry points (labelled stmt) *) if with_labels then begin update_labelled_stmt_pre stmt_sid (pre_st,pre_tr); @@ -253,10 +691,6 @@ else (pre_st,pre_tr) in - - - - (* Updating pre-condition with previous information *) let pre_st,pre_tr = if stmt_l <>[] then @@ -265,114 +699,110 @@ else pre_st,pre_tr in - match stmt_l with | [] -> - (pre_st,pre_tr) - - - + (ki, pre_st,pre_tr) | ({skind=Instr(Call(_,{enode = (Lval(Var(vi),_) | CastE(_,{enode = Lval(Var vi,_)}) )},_,_))} as stmt)::l -> if (Data_for_aorai.isIgnoredFunction vi.vname) then - propagates_pre l (pre_st,pre_tr) + propagates_pre kf ki l (pre_st,pre_tr) else begin - (* If the statement is unreachable then we skip the call *) - if (double_bool_array_eq_bycase (pre_st,pre_tr) (mk_empty_pre_or_post_bycase())) then - propagates_pre l (pre_st,pre_tr) + if (double_bool_array_eq_bycase + (pre_st,pre_tr) (mk_empty_pre_or_post_bycase())) + then + propagates_pre kf ki l (pre_st,pre_tr) else begin + let called_kf = Globals.Functions.get vi in (* Simulating crossing transition *) - let pre_call=Aorai_utils.get_next_bycase vi.vname Promelaast.Call pre_st in - - (* When stmt=call => the spec has to be memorized as pre of the call *) - Data_for_aorai.set_func_pre_call_bycase !currentFuncName stmt.sid pre_call; - - - (* Registering call context for future reinforcement of pre-condition. Treatment depends on call recursivity*) -(* if (String.compare vi.vname !currentFuncName)<>0 then *) - (* * Case 1 : none recursive call *) - (* No recursive calls are stored in a table for further special treatment *) + let pre_call= + Aorai_utils.get_next_bycase + called_kf Promelaast.Call pre_st + in + (* When stmt=call => + the spec has to be memorized as pre of the call *) + Data_for_aorai.set_func_pre_call_bycase + !currentFuncName stmt.sid pre_call; + (* Registering call context for future reinforcement + of pre-condition. Treatment depends on call recursivity*) update_hashtbl_or functions_pre_usecase vi.vname pre_call; -(* else *) -(* (\* * Case 2 : recursive call *\) *) -(* (\* Recursive calls are stored in another table for different further treatment *\) *) -(* update_hashtbl_or functions_pre_usecase_Recursive vi.vname pre_call; *) - - - (* From now, pre-condition is the set of configurations from which - the operation is callable according to its post-condition. *) - let (post_call_st,post_call_tr) = Aorai_utils.mk_forward_composition (fst pre_call) (Data_for_aorai.get_func_post_bycase vi.vname) in - - - - propagates_pre l (post_call_st,post_call_tr) + (* From now, pre-condition is the set of configurations + from which the operation is callable according + to its post-condition. + *) + let my_ki = Kstmt stmt in + let post_state = + mk_forward_composition + kf ki my_ki called_kf + pre_st + (fst pre_call) + (Data_for_aorai.get_func_post_bycase vi.vname) + in + propagates_pre kf my_ki l post_state end end | {skind=Instr(Call(_,e,_,_))}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name (got %a)" - !Ast_printer.d_exp e - ; - - - - + Aorai_option.fatal + "Aorai plugin internal error. Status : Operation calls \ + has to be done by explicit operation name (got %a)" + !Ast_printer.d_exp e + ; | ({skind=Instr (_)})::l -> (* Computes next statements specification *) - propagates_pre l (pre_st,pre_tr) - - - + propagates_pre kf ki l (pre_st,pre_tr) | ({skind=Block(b)})::l -> (* Propagation into block *) - let post = (propagates_pre b.bstmts (pre_st,pre_tr)) in - + let (ki,post_st,post_tr) = + propagates_pre kf ki b.bstmts (pre_st,pre_tr) + in (* Computes next statements specification *) - propagates_pre l post - - - - | ({skind=If(_,b1,b2,_)})::l -> + propagates_pre kf ki l (post_st,post_tr) + | ({skind=If(_,b1,b2,_)} as stmt)::l -> (* Constraints propagation into branches. *) - let post_block1 = propagates_pre b1.bstmts (pre_st,pre_tr) in - let post_block2 = propagates_pre b2.bstmts (pre_st,pre_tr) in - - (* The new post-condition is the disjunction of branches post-conditions *) - let post = double_bool_array_or_bycase post_block1 post_block2 in - + let my_ki = Kstmt stmt in + let (ki1,post_st1,post_tr1) = + propagates_pre kf ki b1.bstmts (pre_st,pre_tr) + in + let (ki2, post_st2, post_tr2) = + propagates_pre kf ki b2.bstmts (pre_st,pre_tr) + in + (* The new post-condition is the disjunction of branches + post-conditions + *) + let post = + double_bool_array_or_bycase + (post_st1, post_tr1) (post_st2, post_tr2) + in + merge_actions kf my_ki ki1 ki2 post_st1 post_st2; (* Computes next statements specification *) - propagates_pre l post - - - - - | ({skind=Return (_,_)})::l -> - (* Updating pre-condition and current result with previous information *) - propagation_result:= (pre_st,pre_tr); - - (* A pre-treatment of frama-C has to put the return statement at the - end of the function. *) - if l<>[] then assert false; - - (* Return the post-condition of the current function *) - !propagation_result - - - + propagates_pre kf my_ki l post + (* Computation of return transitions is done afterwards, directly in + the visitor. + [VP 2011-09-05] Needs more investigation. Not sure the fixpoint + is reached that easily in interprocedural analysis... + *) + | [{skind=Return (_,_)}] -> (ki,pre_st,pre_tr); + | {skind=Return _} :: _ -> + Aorai_option.fatal + "Expecting return statement at the end of main block" | ({skind=Goto(stmt_ref,_)})::stmt_l -> - (* Modifing specification of pointed statement and registering it to be computed *) + (* Modifing specification of pointed statement and + registering it to be computed *) (* If the statement has not yet been specified *) let ref_pre = get_labelled_stmt_pre !stmt_ref.sid in - (* If Current statement is not include into the pointed one, then we update it. *) - let disjunction = (double_bool_array_or_bycase ref_pre (pre_st,pre_tr)) in + (* If Current statement is not + included into the pointed one, then we update it. *) + let disjunction = + (double_bool_array_or_bycase ref_pre (pre_st,pre_tr)) + in if not (double_bool_array_eq_bycase ref_pre disjunction) then begin (* Updating pre-condition of pointed statement *) @@ -381,15 +811,11 @@ end; (* In order to treat statements that are not directly reachable, - consumes following statements until a labeled one with a defined pre-condition. *) + consumes following statements until a labeled one with a + defined pre-condition. *) (* let _ = propagates_pre stmt_l (mk_empty_pre_or_post_bycase ()) in *) (* (mk_empty_pre_or_post_bycase ()) *) - propagates_pre stmt_l (mk_empty_pre_or_post_bycase ()) - - - - - + propagates_pre kf ki stmt_l (mk_empty_pre_or_post_bycase ()) | ({skind=Loop (_,block,_,_,_)} as stmt)::stmt_l -> (* In a loop we distinguishe 4 cases of pre or post conditions: @@ -428,61 +854,74 @@ and the invariant is: (Init => Pre1) & (not Init => Post2) - (where init is a fresh variable to indicate if the iteration is the first one). - - + (where init is a fresh variable to indicate if + the iteration is the first one). *) (* Updating pre-conditions with previous information *) - let loop_pre = double_bool_array_and_bycase (pre_st,pre_tr) (get_loop_local_info loop_bwd_ext_pre (ref stmt)) in + let loop_pre = + double_bool_array_and_bycase (pre_st,pre_tr) + (get_loop_local_info loop_bwd_ext_pre stmt) + in let block_pre = loop_pre in - - + let loop_ki = Kstmt stmt in (* First forward propagation into block *) + let (inner_ki, post_st, post_tr) = + propagates_pre kf ki block.bstmts block_pre + in let old_post = ref block_pre in - let block_post = ref( propagates_pre block.bstmts block_pre ) in - let block_pre = ref( double_bool_array_or_bycase block_pre !block_post ) in - + let block_post = ref(post_st, post_tr) in + let block_pre = + ref(double_bool_array_or_bycase block_pre !block_post) + in + let action_changed = + ref (update_loop_actions kf ki inner_ki loop_ki !block_pre) + in (* Fix-point computation *) - while not (double_bool_array_eq_bycase !old_post !block_post) do - + while not (double_bool_array_eq_bycase !old_post !block_post) + || !action_changed + do old_post := !block_post; - block_post:=propagates_pre block.bstmts !block_pre; - block_pre :=double_bool_array_or_bycase !block_pre !block_post - + let (inner_ki,post_st,post_tr) = + propagates_pre kf loop_ki block.bstmts !block_pre + in + block_post:= post_st, post_tr; + block_pre :=double_bool_array_or_bycase !block_pre !block_post; + action_changed:= + update_loop_actions kf loop_ki inner_ki loop_ki !block_pre done; (* Finally : Real_loop_post = Pre2 /\ BWDed_real_loop_post *) - let real_loop_post = double_bool_array_and_bycase !block_pre (get_loop_local_info loop_bwd_real_post (ref stmt)) in + let real_loop_post = + double_bool_array_and_bycase + !block_pre (get_loop_local_info loop_bwd_real_post stmt) + in (* Updating loop information *) - update_loop_local_info loop_fwd_ext_pre (ref stmt) loop_pre; - update_loop_local_info loop_fwd_int_pre (ref stmt) !block_pre; - update_loop_local_info loop_fwd_real_post (ref stmt) real_loop_post; - update_loop_local_info loop_fwd_int_post (ref stmt) !block_post; + update_loop_local_info loop_fwd_ext_pre stmt loop_pre; + update_loop_local_info loop_fwd_int_pre stmt !block_pre; + update_loop_local_info loop_fwd_real_post stmt real_loop_post; + update_loop_local_info loop_fwd_int_post stmt !block_post; (* Computes next statements specification *) (* The end of the loop is done through a goto instruction that does not appear in the CIL structure. This is why, the post-condition is the exit case of the loop invariant. *) - propagates_pre stmt_l (mk_empty_pre_or_post_bycase ())(*loop_post_st,loop_post_tr*) - - - + propagates_pre kf loop_ki stmt_l (mk_empty_pre_or_post_bycase ()) + (*loop_post_st,loop_post_tr*) + (* [VP 2011-09-06] why don't we continue with the state at + end of loop? *) | {skind=UnspecifiedSequence(b)}::l -> - let post = propagates_pre (Cil.block_from_unspecified_sequence(b)).bstmts (pre_st,pre_tr) in - - propagates_pre l post - -(* propagates_pre - ((mkStmt(Block(Cil.block_from_unspecified_sequence(b))))::l) - (pre_st,pre_tr)*) - - - + let (ki, post_st, post_tr) = + propagates_pre kf ki + (Cil.block_from_unspecified_sequence(b)).bstmts (pre_st,pre_tr) + in + propagates_pre kf ki l (post_st, post_tr) | {skind=Switch (_,bl,stmtl,_)}::l -> - (* Step 1 : For each case, the pre-condition is set to pre_st,pre_tr. *) + (* Step 1 : For each case, + the pre-condition is set to pre_st,pre_tr. + *) List.iter (fun stmt -> update_labelled_stmt_pre stmt.sid (pre_st,pre_tr)) stmtl; @@ -491,42 +930,34 @@ (* propagates_pre *) (* ((mkStmt(Block(bl)))::l) *) (* (pre_st,pre_tr) *) - let post = propagates_pre bl.bstmts (pre_st,pre_tr) in - - propagates_pre l post - - - + (* [VP 2011-09-06] We should not propagate in the block like that. + It'd be much better to use Cil's Dataflow functor. + *) + let (ki, post_st, post_tr) = + propagates_pre kf ki bl.bstmts (pre_st,pre_tr) + in + propagates_pre kf ki l (post_st, post_tr) | {skind=Break (_)}::_ | {skind=Continue (_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Continue and Break statements have to be rewritten into goto by the CFG pass.\n"; + Aorai_option.fatal + "Aorai plugin internal error. \ + Continue and Break statements have to be rewritten \ + into goto by the CFG pass."; | {skind=TryFinally (_,_,_) }::_ | {skind=TryExcept(_,_,_,_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : try constructions are not yet supported.\n"; - - - - - - - - - - - - - - - - - + Extlib.not_yet_implemented + "Aorai does not support try constructions yet" (** Propagates post-condition to each statement, by following control flow. - It returns a couple of bool array, definig the weakest pre-condition of the statement list. - Since then analysis is a backward one, the list is first reversed. *) - + It returns a couple of bool array, definig the weakest pre-condition of + the statement list. Since then analysis is a backward one, + the list is first reversed. *) +(* [VP 2011-09-06] we don't have to intervene here for actions. Just pay + attention to retrieve actions associated to states that are flagged active + at the end of this analysis. +*) in let rec propagates_post stmt_l (post_st,post_tr) = (** This function returns the current spec of a statement or an empty @@ -537,8 +968,9 @@ in - (** This function makes an OR filter between the given pre and the old pre of the given stmt - The result is storing as the new pre of the given stmt. *) + (** This function makes an OR filter between the given + pre and the old pre of the given stmt. The result is + stored as the new pre of the given stmt. *) let update_labelled_stmt_pre stmt_sid pre = let old_pre = get_labelled_stmt_pre stmt_sid in let new_pre = double_bool_array_or_bycase old_pre pre in @@ -552,12 +984,12 @@ Side effects of this function : * The pre of the current stmt is updated according to the given pre *) - let update_labelled_stmt_pre stmt_ref pre = + let update_labelled_stmt_pre stmt pre = (* Registering the new pre-condition if the stmt is labelled *) - if !stmt_ref.labels<>[] then + if stmt.labels<>[] then begin - update_labelled_stmt_pre !stmt_ref.sid pre; - Hashtbl.replace status_of_labelled_stmts !stmt_ref.sid true + update_labelled_stmt_pre stmt.sid pre; + Hashtbl.replace status_of_labelled_stmts stmt.sid true end in @@ -577,7 +1009,7 @@ )},_,_))} as stmt)::l -> if (Data_for_aorai.isIgnoredFunction vi.vname) then begin (* Updating the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) (post_st,post_tr); + update_labelled_stmt_pre stmt (post_st,post_tr); (* Computes next statements specification *) prop l (post_st,post_tr) @@ -590,121 +1022,91 @@ prop l (post_st,post_tr) else begin - (* Registering call context for future reinforcement of post-condition. Treatment depends on call recursivity*) - -(* if (String.compare vi.vname !currentFuncName)<>0 then *) - (* * Case 1 : none recursive call *) - (* No recursive calls are stored in a table for further special treatment *) - update_hashtbl_or functions_post_usecase vi.vname (post_st,post_tr); -(* else *) -(* (\* * Case 2 : recursive call *\) *) -(* (\* Recursive calls are stored in another table for different further treatment *\) *) -(* update_hashtbl_or functions_post_usecase_Recursive vi.vname (post_st,post_tr); *) - - (* From now, post-condition is the set of configurations from which - the operation is callable according to its pre-condition and - of the current statement pre-condition. *) + let kf = Globals.Functions.get vi in + update_hashtbl_or functions_post_usecase + vi.vname (post_st,post_tr); + (* From now, post-condition is the set of configurations + from which the operation is callable according to + its pre-condition and of the current statement + pre-condition. *) let pre_call = - Aorai_utils.mk_backward_composition + mk_backward_composition post_st (Data_for_aorai.get_func_pre vi.vname) (Data_for_aorai.get_func_post_bycase vi.vname) in - let cur_pre = Aorai_utils.get_prev_bycase vi.vname Promelaast.Call (pre_call) in - - - (* When stmt=call => the spec has to be memorized as pre of the call *) - Data_for_aorai.set_func_pre_call_bycase !currentFuncName stmt.sid cur_pre; - - (* Updating the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) cur_pre; + let cur_pre = + Aorai_utils.get_prev_bycase kf Promelaast.Call pre_call + in + (* When stmt=call => + the spec has to be memorized as pre of the call *) + Data_for_aorai.set_func_pre_call_bycase + !currentFuncName stmt.sid cur_pre; + (* Updating the specification of the current stmt + in the hashtbl. *) + update_labelled_stmt_pre stmt cur_pre; (* Computes next statements specification *) prop l cur_pre end end - - | {skind=Instr(Call(_,_,_,_))}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Operation calls has to be done by explicit operation name\n"; - - + Aorai_option.fatal "Indirect calls are not supported yet" | ({skind=Instr (_)} as stmt)::l -> (* Updating the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) (post_st,post_tr); - + update_labelled_stmt_pre stmt (post_st,post_tr); (* Computes next statements specification *) prop l (post_st,post_tr) - - | ({skind=Block(b)} as stmt)::l -> (* Computes recursivly the block specification *) let cur_pre = (propagates_post b.bstmts (post_st,post_tr)) in - (* Updating the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) cur_pre ; - + update_labelled_stmt_pre stmt cur_pre ; (* Computes next statements specification *) prop l cur_pre - - | ({skind=If(_,b1,b2,_)} as stmt)::l -> (* Constraints propagation into branches. *) let pre_block1 = propagates_post b1.bstmts (post_st,post_tr) in let pre_block2 = propagates_post b2.bstmts (post_st,post_tr) in - - (* The new pre-condition is the disjunction of branches pre-conditions *) + (* The new pre-condition is the disjunction of + branches pre-conditions *) let pre = double_bool_array_or_bycase pre_block1 pre_block2 in - (* Updating the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) pre; - + update_labelled_stmt_pre stmt pre; (* Computes next statements specification *) prop l pre - - - | ({skind=Return (_,_)} as stmt)::l -> - (* The 'prev' according to the return will be done be the caller of the propagates function. *) + (* The 'prev' according to the return will be done be + the caller of the propagates function. *) (* Updating the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) (post_st,post_tr); - + update_labelled_stmt_pre stmt (post_st,post_tr); (* Return the post-condition of the current function *) prop l (post_st,post_tr) - - - | ({skind=Goto(stmt_ref,_)} as stmt)::stmt_l -> - (* Retriving old specification information about this statement and the pointed one. *) + (* Retrieving old specification information about + this statement and the pointed one. *) let ref_pre = get_labelled_stmt_pre !stmt_ref.sid in - let old_ref_pre = try Hashtbl.find old_observed_labelled_stmts_pre stmt.sid with Not_found -> mk_empty_pre_or_post_bycase() in - - - (* Second computation needed if the pointed stmt has not yet been treated - or if its pre differs from the current post *) + (* Second computation needed if the pointed stmt has + not yet been treated or if its pre differs from the current post *) if not (double_bool_array_eq_bycase ref_pre old_ref_pre) then begin second_computation_needed:= true; Hashtbl.replace old_observed_labelled_stmts_pre stmt.sid ref_pre end; - (* Add the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) ref_pre; - + update_labelled_stmt_pre stmt ref_pre; prop stmt_l ref_pre - - | ({skind=Loop (_,block,_,_,_)} as stmt)::stmt_l -> (* In a loop we distinguishe 4 cases of pre or post conditions: @@ -728,10 +1130,23 @@ RealLoopPost : Real post-condition of the loop + We can consider 2 kinds of loop : + * finite + * infinite + + In a finite loop, only external gotos in the block will make the initial specification during the backward process + In an infinite loop, there is no external specification. The only known thing is then the saved internal post-condition. + Initially : - RealLoopPost = [block]EmptyPost - Pre2 = RealLoopPost - Post2 = Pre2 + if finite loop + RealLoopPost = [block]EmptyPost + Pre2 = RealLoopPost + Post2 = Pre2 + else + RealLoopPost = pre2 from FWD computation + Pre2 = RealLoopPost + Post2 = Pre2 + do Pre2 = ([block]Post2) \/ Pre2 // Adding reachable pre states @@ -743,7 +1158,7 @@ The loop invariant is then : (c => Pre2) - & (!c => Post1) + & (!c => RealLoopPost) & (Init => Pre1) & (not Init => Post2) (where init is a fresh variable to indicate if the iteration is the first one). @@ -751,19 +1166,28 @@ *) (* First backward propagation into block - RealLoopPost = ([block]EmptyPost) /\ FWD_real_post + RealLoopPost = ([block]EmptyPost) /\ FWD_real_post Pre2 = RealLoopPost Post2 = Pre2 *) + + let loopIsInfinite = ((Stmts_graph.get_all_stmt_last_stmts stmt)=[]) in let real_loop_post = - double_bool_array_and_bycase - (propagates_post block.bstmts (mk_empty_pre_or_post_bycase())) - (get_loop_local_info loop_fwd_real_post (ref stmt)) + if loopIsInfinite then begin + Aorai_option.debug "Backward parsing infinite loop"; + (get_loop_local_info loop_fwd_int_pre stmt) + end else begin + Aorai_option.debug "Backward parsing finite loop"; + double_bool_array_and_bycase + (propagates_post block.bstmts (mk_empty_pre_or_post_bycase())) + (get_loop_local_info loop_fwd_real_post stmt) + end; in let block_pre = real_loop_post in let block_post = block_pre in + (* Looped backward propagation into block do Pre2 = ([block]Post2) \/ Pre2 // Adding reachable pre states @@ -791,37 +1215,29 @@ (* Finally : Pre1 = Pre2 /\ FWD_pre1 *) - let loop_pre = double_bool_array_and_bycase block_pre (get_loop_local_info loop_fwd_ext_pre (ref stmt)) in - - + let loop_pre = + double_bool_array_and_bycase + block_pre (get_loop_local_info loop_fwd_ext_pre stmt) + in (* Updating loop information *) - update_loop_local_info loop_bwd_ext_pre (ref stmt) loop_pre; - update_loop_local_info loop_bwd_int_pre (ref stmt) block_pre; - update_loop_local_info loop_bwd_real_post (ref stmt) real_loop_post; - update_loop_local_info loop_bwd_int_post (ref stmt) block_post; - - + update_loop_local_info loop_bwd_ext_pre stmt loop_pre; + update_loop_local_info loop_bwd_int_pre stmt block_pre; + update_loop_local_info loop_bwd_real_post stmt real_loop_post; + update_loop_local_info loop_bwd_int_post stmt block_post; (* Add the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) loop_pre ; - + update_labelled_stmt_pre stmt loop_pre ; (* Computes next statements specification *) prop stmt_l loop_pre - - - - | ({skind=UnspecifiedSequence(b)} as stmt)::l -> (* Sequence is packed in a block which is added to the todo list. *) - let pre = propagates_post (Cil.block_from_unspecified_sequence(b)).bstmts (post_st,post_tr) in - + let pre = + propagates_post + (Cil.block_from_unspecified_sequence(b)).bstmts (post_st,post_tr) + in (* Add the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) pre ; - + update_labelled_stmt_pre stmt pre ; (* Computes next statements specification *) prop l (post_st,post_tr) - - - | ({skind=Switch (_,bl,stmtl,_)} as stmt)::l -> (* Step 1 : The block is treated by the classical block analysis *) (* let pre = ref (prop [mkStmt(Block(bl))] (post_st,post_tr)) in *) @@ -838,78 +1254,65 @@ stmtl; (* Add the specification of the current stmt in the hashtbl. *) - update_labelled_stmt_pre (ref stmt) !pre ; - + update_labelled_stmt_pre stmt !pre ; (* Computes next statements specification *) prop l !pre - - - - - - - - | {skind=Break (_)}::_ | {skind=Continue (_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : Break and Continue instructions are not yet supported.\n"; + Extlib.not_yet_implemented + "Break and Continue instructions are not yet supported"; | {skind=TryFinally (_,_,_) }::_ | {skind=TryExcept(_,_,_,_)}::_ -> - Aorai_option.fatal "Aorai plugin internal error. Status : try constructions are not yet supported.\n"; - - - + Extlib.not_yet_implemented + "try constructions are not yet supported."; in (* This computation is done from end to beginning *) prop (List.rev stmt_l) (post_st,post_tr) in -object (*(self) *) - +object (self) inherit Visitor.generic_frama_c_visitor (Project.current ()) (Cil.inplace_visit ()) as super method vfunc f = currentFuncName:=f.svar.vname; - + let kf = Extlib.the self#current_kf in + assert (!currentFuncName = Kernel_function.get_name kf); let starting_pre = (Data_for_aorai.get_func_pre f.svar.vname) in let starting_post = (Data_for_aorai.get_func_post_bycase f.svar.vname) in - -(* Format.printf "\nAvant passe 1 : "; *) -(* Aorai_utils.debug_display_func_status_bycase f.svar.vname; *) - - + Aorai_option.debug "Before step 1 for function %s:" f.svar.vname; + Aorai_utils.debug_display_func_status_bycase f.svar.vname; Hashtbl.clear labelled_stmts_pre; Hashtbl.clear stmts_to_compute_one_more_time; - propagation_result := (mk_empty_pre_or_post_bycase ()); - (* Pre-condition forward propagation *) - let cur_pre = Aorai_utils.mk_pre_or_post_bycase_from_pre_or_post (Data_for_aorai.get_func_pre f.svar.vname) in - let _ = propagates_pre f.sbody.bstmts cur_pre in - let cur_post_st = ref (fst !propagation_result) in + let cur_pre = + Aorai_utils.mk_pre_or_post_bycase_from_pre_or_post + (Data_for_aorai.get_func_pre f.svar.vname) + in + update_actions_call_func kf cur_pre; + let res = ref (propagates_pre kf Kglobal f.sbody.bstmts cur_pre) in while (Hashtbl.length stmts_to_compute_one_more_time) > 0 do - let _ = propagates_pre f.sbody.bstmts cur_pre in - cur_post_st := fst (!propagation_result) + res:= propagates_pre kf Kglobal f.sbody.bstmts cur_pre done; - - (* Registration of the new post-condition *) - let post = Aorai_utils.get_next_bycase f.svar.vname Promelaast.Return !cur_post_st in + let (ki, cur_post_st, _) = !res in + let post = + Aorai_utils.get_next_bycase kf Promelaast.Return cur_post_st + in let old_post = (Data_for_aorai.get_func_post_bycase f.svar.vname) in let post = double_bool_array_and_bycase post old_post in - + update_actions_return_func kf ki (snd post); Data_for_aorai.set_func_post_bycase f.svar.vname post; - -(* Format.printf "Entre passes 1 et 2 : "; *) -(* Aorai_utils.debug_display_func_status_bycase f.svar.vname; *) - - + Aorai_option.debug "Between steps 1 and 2 for function %s:" f.svar.vname; + Aorai_utils.debug_display_func_status_bycase f.svar.vname; (* Post-condition backward propagation *) - (* cur_post : bool array array * bool array array The first index is in term of the function input states *) + (* cur_post : bool array array * bool array array + The first index is in term of the function input states *) let cur_post = (Data_for_aorai.get_func_post_bycase f.svar.vname) in - let cur_post = Aorai_utils.get_prev_bycase f.svar.vname Promelaast.Return cur_post in - + let cur_post = + Aorai_utils.get_prev_bycase kf Promelaast.Return cur_post + in Hashtbl.clear labelled_stmts_pre; Hashtbl.clear status_of_labelled_stmts; Hashtbl.clear old_observed_labelled_stmts_pre; @@ -931,8 +1334,8 @@ Data_for_aorai.set_func_pre f.svar.vname pre; - Aorai_option.debug "After pass 2 for function %s" f.svar.vname; - Aorai_utils.debug_display_func_status f.svar.vname; + Aorai_option.debug "After step 2 for function %s" f.svar.vname; + Aorai_utils.debug_display_func_status_bycase f.svar.vname; let merge tbl1 tbl2 get set = @@ -994,152 +1397,23 @@ let used_post = try Hashtbl.find functions_post_usecase name with Not_found -> (mk_empty_pre_or_post_bycase()) in -(* Format.printf "\n\nFunction : %s\n" name; *) -(* Format.printf " Observed pre use_case :"; *) -(* debug_display_stmt_all_pre_bycase used_pre; *) -(* Format.printf "\n Observed post_use_case :"; *) -(* debug_display_stmt_all_pre_bycase used_post; *) -(* Format.printf "\n"; *) - (* Reformating usecases of pre and post *) let used_pre_st,used_pre_tr = pre_flattening used_pre in let used_pre_st,used_pre_tr = (ref used_pre_st),(ref used_pre_tr) in let used_post_st,used_post_tr = post_pseudo_flattening used_post in - let used_post_st,used_post_tr = (ref used_post_st),(ref used_post_tr) in - - -(* (\* If recursive calls, then using it to update used_pre *\) *) -(* begin *) -(* try *) -(* (\* Recursive calls are stored in another table *\) *) -(* let rec_pre = *) -(* Hashtbl.find functions_pre_usecase_Recursive name *) -(* in *) -(* (\* Reflexive and transitive closure on recursive calls in order to update used_pre *\) *) -(* (\* DEBUG TRACES !!!*\) *) -(* (\* Format.printf "\n\nFunction : %s\n" name; *\) *) -(* (\* Format.printf " Observed pre use_case :"; *\) *) -(* (\* debug_display_stmt_all_pre (!used_pre_st,!used_pre_tr); *\) *) -(* (\* Format.printf "\n Observed special recursion calls :"; *\) *) -(* (\* debug_display_stmt_all_pre_bycase rec_pre; *\) *) -(* (\* Format.printf "\n"; *\) *) -(* (\* END DEBUG TRACES !!!*\) *) - -(* (\* Recursive calls are considered as use_case only if external calls are done with the same starting state *\) *) -(* (\* For each state used for calling, extending used_pre according to recursive extensions *\) *) -(* let oneMoreTime = ref true in *) -(* while !oneMoreTime do *) -(* oneMoreTime:=false; *) -(* Array.iteri *) -(* (fun st value -> *) -(* if value then begin *) -(* let tmp_st=bool_array_or !used_pre_st (fst rec_pre).(st) in *) -(* let tmp_tr=bool_array_or !used_pre_tr (snd rec_pre).(st) in *) - -(* if not (double_bool_array_eq (!used_pre_st,!used_pre_tr) (tmp_st,tmp_tr)) then oneMoreTime:=true; *) - -(* used_pre_st:= tmp_st; *) -(* used_pre_tr:= tmp_tr *) -(* end *) -(* ) *) -(* !used_pre_st; *) -(* done; *) - -(* (\* DEBUG TRACES !!!*\) *) -(* (\* Format.printf " Updated pre use_case :"; *\) *) -(* (\* debug_display_stmt_all_pre (!used_pre_st,!used_pre_tr); *\) *) -(* (\* Format.printf "\n"; *\) *) -(* (\* END DEBUG TRACES !!!*\) *) - -(* with *) -(* | Not_found -> () *) -(* end; *) - - -(* (\* If recursive calls, then using it to update used_post *\) *) -(* begin *) -(* try *) -(* (\* Recursive calls are stored in another table *\) *) -(* let rec_post = *) -(* Hashtbl.find functions_post_usecase_Recursive name *) -(* in *) -(* (\* Reflexive and transitive closure on recursive calls in order to update used_pre *\) *) -(* (\* DEBUG TRACES !!!*\) *) -(* (\* Format.printf "\n\nFunction : %s\n" name; *\) *) -(* (\* Format.printf " Observed pre use_case :"; *\) *) -(* (\* debug_display_stmt_all_pre (!used_pre_st,!used_pre_tr); *\) *) -(* (\* Format.printf "\n Observed special recursion calls :"; *\) *) -(* (\* debug_display_stmt_all_pre_bycase rec_pre; *\) *) -(* (\* Format.printf "\n"; *\) *) -(* (\* END DEBUG TRACES !!!*\) *) - -(* (\* Recursive calls are considered as use_case only if external calls are done with the same starting state *\) *) -(* (\* For each state used for calling, extending used_post according to recursive extensions *\) *) -(* let oneMoreTime = ref true in *) -(* while !oneMoreTime do *) -(* oneMoreTime:=false; *) -(* Array.iteri *) -(* (fun input_st case_post_st -> *) -(* let case_post_tr = !used_post_tr.(input_st) in *) -(* Array.iteri *) -(* (fun st value -> *) -(* if value then begin *) -(* (\* !!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* Ici (fst rec_post).(st) est incorrect. *) -(* Je voudrais dire : *) -(* etant donne un etat sortie de la fonction, quel sont les etats/trans courant qui y mene *) - -(* APRES AVOIR SAUVEGARDER CETTE VERSION SANS LE REC_USED_CASE : *) - -(* Refaire tout le backarwd propagation en utilisant le bycase suivant : *) -(* exit state -> curstate -> true / false *) - -(* Actuellement (adapte pour le FWD propagation) : *) -(* entry state -> curstate -> true / false *) - -(* *\) *) - -(* let tmp_st=bool_array_or case_post_st (fst rec_post).(st) in *) -(* let tmp_tr=bool_array_or case_post_tr (snd rec_post).(st) in *) -(* (\*!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* *\) *) - -(* if not (double_bool_array_eq (case_post_st,case_post_tr) (tmp_st,tmp_tr)) then oneMoreTime:=true; *) - - -(* !used_post_st.(input_st) <- tmp_st; *) -(* !used_post_tr.(input_st) <- tmp_tr *) -(* end *) -(* ) *) -(* case_post_st *) -(* ) *) -(* !used_post_st; *) -(* done; *) - -(* (\* DEBUG TRACES !!!*\) *) -(* (\* Format.printf " Updated pre use_case :"; *\) *) -(* (\* debug_display_stmt_all_pre (!used_pre_st,!used_pre_tr); *\) *) -(* (\* Format.printf "\n"; *\) *) -(* (\* END DEBUG TRACES !!!*\) *) - -(* with *) -(* | Not_found -> () *) -(* end; *) - - - + let used_post_st,used_post_tr = + (ref used_post_st),(ref used_post_tr) + in (* Computing new pre/post *) - let cur_pre = double_bool_array_and (!used_pre_st,!used_pre_tr) old_pre in - let cur_post = double_bool_array_and_bycase (!used_post_st,!used_post_tr) old_post in - - + let cur_pre = + double_bool_array_and (!used_pre_st,!used_pre_tr) old_pre + in + let cur_post = + double_bool_array_and_bycase + (!used_post_st,!used_post_tr) old_post + in if (not (double_bool_array_eq old_pre cur_pre ) ) then begin spec_modified:=true; end; if (not (double_bool_array_eq_bycase old_post cur_post) ) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/cil_manipulation.ml frama-c-20111001+nitrogen+dfsg/src/aorai/cil_manipulation.ml --- frama-c-20110201+carbon+dfsg/src/aorai/cil_manipulation.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/cil_manipulation.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -29,19 +31,19 @@ let rec lval_substitution (lv:exp_node) (removel:string list) (addl:Cil_types.exp_node list) = match lv with | Lval(lh,off) -> - begin - match lh with - | Mem _ as t-> Lval(t,off) - | Var vi -> - match removel, addl with - | [], [] -> lv - | r::rl,a::al -> - if(String.compare vi.vname r)=0 - then a - else lval_substitution lv rl al - | _,_ -> Aorai_option.fatal "removel and addl parameters must have the same size." + begin + match lh with + | Mem _ as t-> Lval(t,off) + | Var vi -> + match removel, addl with + | [], [] -> lv + | r::rl,a::al -> + if(String.compare vi.vname r)=0 + then a + else lval_substitution lv rl al + | _,_ -> Aorai_option.fatal "removel and addl parameters must have the same size." - end + end | _ -> Aorai_option.fatal "lval_substitution have to be called with a Lval parameter" @@ -73,9 +75,9 @@ | UnOp (op,exp,typ) -> UnOp (op , exp_substitution exp removel addl , typ) | BinOp (op, exp1,exp2,typ) -> BinOp (op, - exp_substitution exp1 removel addl, - exp_substitution exp2 removel addl, - typ) + exp_substitution exp1 removel addl, + exp_substitution exp2 removel addl, + typ) | CastE (typ,exp) -> CastE (typ,exp_substitution exp removel addl) @@ -95,72 +97,71 @@ let rec term_lval_substitution ((host,offset):term_lval) (removel:string list) (addl:Cil_types.term_lhost list) = match host with | TVar(lv) -> - let res= ref (host,offset) in - List.iter2 - (fun r a -> if (String.compare r lv.lv_name)=0 then res:= (a,offset) ) - removel - addl; - !res + let res= ref (host,offset) in + List.iter2 + (fun r a -> if (String.compare r lv.lv_name)=0 then res:= (a,offset) ) + removel + addl; + !res | _ -> (host,offset) and term_substitution (t:term) (removel:string list) (addl:Cil_types.term_lhost list) = let node = match t.term_node with - | TLval (tl) -> TLval (term_lval_substitution tl removel addl) + | TLval (tl) -> TLval (term_lval_substitution tl removel addl) - | TSizeOfE t -> TSizeOfE (term_substitution t removel addl) - | TAlignOfE t -> TAlignOfE (term_substitution t removel addl) - | TUnOp (o,t) -> TUnOp (o,term_substitution t removel addl) - | TBinOp (o,t1,t2) -> TBinOp (o, - term_substitution t1 removel addl, - term_substitution t2 removel addl) - | TCastE (ty,t) -> TCastE (ty,term_substitution t removel addl) - | TAddrOf tl -> TAddrOf (term_lval_substitution tl removel addl) - | TStartOf tl -> TStartOf (term_lval_substitution tl removel addl) - | Tapp (li,lll,tl) -> Tapp (li,lll,term_list_substitution tl removel addl) - | Tlambda(q,t) -> Tlambda (q,term_substitution t removel addl) - | TDataCons (l,tl) -> TDataCons (l,term_list_substitution tl removel addl) - | Tif (t1,t2,t3) -> Tif (term_substitution t1 removel addl, - term_substitution t2 removel addl, - term_substitution t3 removel addl) - | Told (t) -> Told (term_substitution t removel addl) - | Tat (t,ll) -> Tat (term_substitution t removel addl,ll) - | Tbase_addr (t) -> Tbase_addr (term_substitution t removel addl) - | Tblock_length (t) -> Tblock_length (term_substitution t removel addl) - | TCoerce (t,ty) -> TCoerce (term_substitution t removel addl,ty) - | TCoerceE (t1,t2) -> TCoerceE (term_substitution t1 removel addl, - term_substitution t2 removel addl) - | TUpdate (t1,fi,t2) -> TUpdate (term_substitution t1 removel addl, - fi, - term_substitution t2 removel addl) - | Ttypeof (t) -> Ttypeof (term_substitution t removel addl) - | Tunion (tl) -> Tunion (term_list_substitution tl removel addl) - | Tinter (tl) -> Tinter (term_list_substitution tl removel addl) - | Tcomprehension (t,q,Some(p)) -> Tcomprehension (term_substitution t removel addl, - q, - Some(named_predicate_substitution p removel addl)) - | Tcomprehension (t,q,None) -> Tcomprehension (term_substitution t removel addl, - q, - None) - | Trange (Some(t),None) -> Trange (Some(term_substitution t removel addl), - None) - | Trange (None,Some(t)) -> Trange (None, - Some(term_substitution t removel addl)) - | Trange (None,None) -> Trange (None,None) - | Trange (Some(t1),Some(t2)) -> Trange (Some(term_substitution t1 removel addl), - Some(term_substitution t2 removel addl)) - - | Tlet (li,t) -> Tlet (li,term_substitution t removel addl) - - - | TConst _ - | TSizeOfStr _ - | TAlignOf _ - | Tnull - | Ttype _ - | Tempty_set - | TSizeOf _ as c -> c + | TSizeOfE t -> TSizeOfE (term_substitution t removel addl) + | TAlignOfE t -> TAlignOfE (term_substitution t removel addl) + | TUnOp (o,t) -> TUnOp (o,term_substitution t removel addl) + | TBinOp (o,t1,t2) -> TBinOp (o, + term_substitution t1 removel addl, + term_substitution t2 removel addl) + | TCastE (ty,t) -> TCastE (ty,term_substitution t removel addl) + | TAddrOf tl -> TAddrOf (term_lval_substitution tl removel addl) + | TStartOf tl -> TStartOf (term_lval_substitution tl removel addl) + | Tapp (li,lll,tl) -> Tapp (li,lll,term_list_substitution tl removel addl) + | Tlambda(q,t) -> Tlambda (q,term_substitution t removel addl) + | TDataCons (l,tl) -> TDataCons (l,term_list_substitution tl removel addl) + | Tif (t1,t2,t3) -> Tif (term_substitution t1 removel addl, + term_substitution t2 removel addl, + term_substitution t3 removel addl) + | Tat (t,ll) -> Tat (term_substitution t removel addl,ll) + | Tbase_addr (t) -> Tbase_addr (term_substitution t removel addl) + | Tblock_length (t) -> Tblock_length (term_substitution t removel addl) + | TCoerce (t,ty) -> TCoerce (term_substitution t removel addl,ty) + | TCoerceE (t1,t2) -> TCoerceE (term_substitution t1 removel addl, + term_substitution t2 removel addl) + | TUpdate (t1,fi,t2) -> TUpdate (term_substitution t1 removel addl, + fi, + term_substitution t2 removel addl) + | Ttypeof (t) -> Ttypeof (term_substitution t removel addl) + | Tunion (tl) -> Tunion (term_list_substitution tl removel addl) + | Tinter (tl) -> Tinter (term_list_substitution tl removel addl) + | Tcomprehension (t,q,Some(p)) -> Tcomprehension (term_substitution t removel addl, + q, + Some(named_predicate_substitution p removel addl)) + | Tcomprehension (t,q,None) -> Tcomprehension (term_substitution t removel addl, + q, + None) + | Trange (Some(t),None) -> Trange (Some(term_substitution t removel addl), + None) + | Trange (None,Some(t)) -> Trange (None, + Some(term_substitution t removel addl)) + | Trange (None,None) -> Trange (None,None) + | Trange (Some(t1),Some(t2)) -> Trange (Some(term_substitution t1 removel addl), + Some(term_substitution t2 removel addl)) + + | Tlet (li,t) -> Tlet (li,term_substitution t removel addl) + + + | TConst _ + | TSizeOfStr _ + | TAlignOf _ + | Tnull + | Ttype _ + | Tempty_set + | TSizeOf _ as c -> c in {term_node=node ; term_loc=t.term_loc ; term_type=t.term_type ; term_name=t.term_name} @@ -181,52 +182,51 @@ and predicate_substitution (pred:predicate) (removel:string list) (addl:Cil_types.term_lhost list) = match pred with - | Pfalse - | Ptrue as p -> p + | Pfalse + | Ptrue as p -> p - | Papp (li, l, term_list) -> Papp (li, l,(term_list_substitution term_list removel addl)) - | Pseparated term_list -> Pseparated (term_list_substitution term_list removel addl) - | Prel (relation,t1,t2) -> Prel (relation, - term_substitution t1 removel addl, - term_substitution t2 removel addl) - - | Pand (p1,p2) -> Pand (named_predicate_substitution p1 removel addl, - named_predicate_substitution p2 removel addl) - | Por (p1,p2) -> Por (named_predicate_substitution p1 removel addl, - named_predicate_substitution p2 removel addl) - | Pxor (p1,p2) -> Pxor (named_predicate_substitution p1 removel addl, - named_predicate_substitution p2 removel addl) - | Pimplies (p1,p2) -> Pimplies (named_predicate_substitution p1 removel addl, - named_predicate_substitution p2 removel addl) - | Piff (p1,p2) -> Piff (named_predicate_substitution p1 removel addl, - named_predicate_substitution p2 removel addl) - - | Pnot (p) -> Pnot (named_predicate_substitution p removel addl) - - | Pif (t,p1,p2) -> Pif (term_substitution t removel addl, - named_predicate_substitution p1 removel addl, - named_predicate_substitution p2 removel addl) - - - | Plet (li,p) -> Plet (li, - named_predicate_substitution p removel addl) - | Pforall (q,p) -> Pforall (q, - named_predicate_substitution p removel addl) - | Pexists (q,p) -> Pexists (q, - named_predicate_substitution p removel addl) - | Pold (p) -> Pold (named_predicate_substitution p removel addl) - - | Pat (p,l) -> Pat (named_predicate_substitution p removel addl,l) - | Pvalid (t) -> Pvalid (term_substitution t removel addl) - | Pvalid_index (t1,t2) -> Pvalid_index (term_substitution t1 removel addl, - term_substitution t2 removel addl) - | Pvalid_range (t1,t2,t3) -> Pvalid_range (term_substitution t1 removel addl, - term_substitution t2 removel addl, - term_substitution t3 removel addl) - - | Pfresh (t) -> Pfresh (term_substitution t removel addl) - | Psubtype (t1,t2) -> Psubtype (term_substitution t1 removel addl, - term_substitution t2 removel addl) + | Papp (li, l, term_list) -> Papp (li, l,(term_list_substitution term_list removel addl)) + | Pseparated term_list -> Pseparated (term_list_substitution term_list removel addl) + | Prel (relation,t1,t2) -> Prel (relation, + term_substitution t1 removel addl, + term_substitution t2 removel addl) + + | Pand (p1,p2) -> Pand (named_predicate_substitution p1 removel addl, + named_predicate_substitution p2 removel addl) + | Por (p1,p2) -> Por (named_predicate_substitution p1 removel addl, + named_predicate_substitution p2 removel addl) + | Pxor (p1,p2) -> Pxor (named_predicate_substitution p1 removel addl, + named_predicate_substitution p2 removel addl) + | Pimplies (p1,p2) -> Pimplies (named_predicate_substitution p1 removel addl, + named_predicate_substitution p2 removel addl) + | Piff (p1,p2) -> Piff (named_predicate_substitution p1 removel addl, + named_predicate_substitution p2 removel addl) + + | Pnot (p) -> Pnot (named_predicate_substitution p removel addl) + + | Pif (t,p1,p2) -> Pif (term_substitution t removel addl, + named_predicate_substitution p1 removel addl, + named_predicate_substitution p2 removel addl) + + + | Plet (li,p) -> Plet (li, + named_predicate_substitution p removel addl) + | Pforall (q,p) -> Pforall (q, + named_predicate_substitution p removel addl) + | Pexists (q,p) -> Pexists (q, + named_predicate_substitution p removel addl) + | Pat (p,l) -> Pat (named_predicate_substitution p removel addl,l) + | Pvalid (t) -> Pvalid (term_substitution t removel addl) + | Pvalid_index (t1,t2) -> Pvalid_index (term_substitution t1 removel addl, + term_substitution t2 removel addl) + | Pvalid_range (t1,t2,t3) -> Pvalid_range (term_substitution t1 removel addl, + term_substitution t2 removel addl, + term_substitution t3 removel addl) + + | Pfresh (t) -> Pfresh (term_substitution t removel addl) + | Pinitialized (t) -> Pinitialized (term_substitution t removel addl) + | Psubtype (t1,t2) -> Psubtype (term_substitution t1 removel addl, + term_substitution t2 removel addl) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/configure frama-c-20111001+nitrogen+dfsg/src/aorai/configure --- frama-c-20110201+carbon+dfsg/src/aorai/configure 2011-02-07 15:05:33.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/configure 2011-10-10 08:56:39.000000000 +0000 @@ -1,11 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.65. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # # # This configure script is free software; the Free Software Foundation @@ -315,7 +315,7 @@ test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -355,19 +355,19 @@ fi # as_fn_arith -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -529,7 +529,7 @@ exec 6>&1 # Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -670,9 +670,8 @@ fi case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -717,7 +716,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -743,7 +742,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -947,7 +946,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -963,7 +962,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -993,8 +992,8 @@ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." ;; *=*) @@ -1002,7 +1001,7 @@ # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1020,13 +1019,13 @@ if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" + as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1049,7 +1048,7 @@ [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1063,8 +1062,8 @@ if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1079,9 +1078,9 @@ ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" + as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" + as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1120,11 +1119,11 @@ fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1164,7 +1163,7 @@ --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages + -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1288,9 +1287,9 @@ if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.65 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1305,7 +1304,7 @@ running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -1415,9 +1414,11 @@ { echo - $as_echo "## ---------------- ## + cat <<\_ASBOX +## ---------------- ## ## Cache variables. ## -## ---------------- ##" +## ---------------- ## +_ASBOX echo # The following way of writing the cache mishandles newlines in values, ( @@ -1451,9 +1452,11 @@ ) echo - $as_echo "## ----------------- ## + cat <<\_ASBOX +## ----------------- ## ## Output variables. ## -## ----------------- ##" +## ----------------- ## +_ASBOX echo for ac_var in $ac_subst_vars do @@ -1466,9 +1469,11 @@ echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + cat <<\_ASBOX +## ------------------- ## ## File substitutions. ## -## ------------------- ##" +## ------------------- ## +_ASBOX echo for ac_var in $ac_subst_files do @@ -1482,9 +1487,11 @@ fi if test -s confdefs.h; then - $as_echo "## ----------- ## + cat <<\_ASBOX +## ----------- ## ## confdefs.h. ## -## ----------- ##" +## ----------- ## +_ASBOX echo cat confdefs.h echo @@ -1539,12 +1546,7 @@ ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -1559,11 +1561,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } + . "$ac_site_file" fi done @@ -1639,7 +1637,7 @@ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -1811,7 +1809,7 @@ if test "$short_mark" = "no"; then fp=FORCE_"$up" if eval test "\$$fp" = "yes"; then - as_fn_error $? "$lp requested but $reason." "$LINENO" 5 + as_fn_error "$lp requested but $reason." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp disabled because $reason." >&5 $as_echo "$as_me: WARNING: $lp disabled because $reason." >&2;} @@ -2002,7 +2000,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "Makefile.in"; then ac_cv_file_Makefile_in=yes else @@ -2051,7 +2049,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "aorai is not available" "$LINENO" 5 + as_fn_error "aorai is not available" "$LINENO" 5 fi FORCE_AORAI=$FORCE @@ -2088,7 +2086,9 @@ echo "aorai... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -2180,7 +2180,7 @@ if test "$enable_p" != "no"; then fp=FORCE_`upper "$p"` if eval test "\$$fp" = "yes"; then - as_fn_error $? "$p requested but $reason." "$LINENO" 5 + as_fn_error "$p requested but $reason." "$LINENO" 5 fi eval $ep="no\ \(see\ warning\ about\ ltl2ba\)" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 @@ -2222,7 +2222,7 @@ - ac_config_files="$ac_config_files ./Makefile" + ac_config_files="$ac_config_files ./Makefile" @@ -2246,7 +2246,7 @@ $as_echo "$as_me: $name: $ep_v$info" >&6;} fi done - cat >confcache <<\_ACEOF + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. @@ -2365,7 +2365,6 @@ ac_libobjs= ac_ltlibobjs= -U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -2527,19 +2526,19 @@ (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -2735,7 +2734,7 @@ test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -2789,7 +2788,7 @@ # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -2842,10 +2841,10 @@ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -2860,16 +2859,11 @@ while test $# != 0 do case $1 in - --*=?*) + --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; *) ac_option=$1 ac_optarg=$2 @@ -2891,7 +2885,6 @@ $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -2902,7 +2895,7 @@ ac_cs_silent=: ;; # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' + -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -2953,7 +2946,7 @@ case $ac_config_target in "./Makefile") CONFIG_FILES="$CONFIG_FILES ./Makefile" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -2989,7 +2982,7 @@ { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -3006,7 +2999,7 @@ fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' + ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi @@ -3020,18 +3013,18 @@ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -3120,28 +3113,20 @@ else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 + || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// s/^[^=]*=[ ]*$// }' fi @@ -3159,7 +3144,7 @@ esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -3187,7 +3172,7 @@ [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -3214,7 +3199,7 @@ case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -3340,22 +3325,22 @@ $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 +which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} +which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; @@ -3375,7 +3360,7 @@ ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -3396,7 +3381,7 @@ exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 + $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/configure.ac frama-c-20111001+nitrogen+dfsg/src/aorai/configure.ac --- frama-c-20110201+carbon+dfsg/src/aorai/configure.ac 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/configure.ac 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ ########################################################################## # # -# This file is part of Frama-C. # +# This file is part of Aorai plug-in of Frama-C. # # # # Copyright (C) 2007-2011 # -# INSA (Institut National des Sciences Appliquees) # +# CEA (Commissariat a l'énergie atomique et aux énergies # +# alternatives) # # INRIA (Institut National de Recherche en Informatique et en # # Automatique) # +# INSA (Institut National des Sciences Appliquees) # # # # you can redistribute it and/or modify it under the terms of the GNU # # Lesser General Public License as published by the Free Software # diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/data_for_aorai.ml frama-c-20111001+nitrogen+dfsg/src/aorai/data_for_aorai.ml --- frama-c-20110201+carbon+dfsg/src/aorai/data_for_aorai.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/data_for_aorai.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,55 +23,99 @@ (* *) (**************************************************************************) -(* $Id: data_for_ltl.ml,v 1.6 2008-12-19 15:30:56 uid588 Exp $ *) - +open Logic_ptree +open Cil open Cil_types open Spec_tools open Promelaast +open Logic_simplification + +module Aorai_state = + Datatype.Make_with_collections( + struct + type t = Promelaast.state + let structural_descr = Structural_descr.Abstract + let reprs = [ { nums = -1; name = ""; multi_state = None; + acceptation = Bool3.False; init = Bool3.False + } ] + let name = "Aorai_state" + let equal x y = Datatype.Int.equal x.nums y.nums + let hash x = x.nums + let rehash x = x + let compare x y = Datatype.Int.compare x.nums y.nums + let copy x = x + let internal_pretty_code = Datatype.undefined + let pretty fmt x = Format.fprintf fmt "state_%d" x.nums + let varname _ = + assert false (* unused while internal_pretty_code is undefined *) + let mem_project = Datatype.never_any_project + end + ) + +module Max_value_counter = + State_builder.Hashtbl + (Cil_datatype.Term.Hashtbl) + (Cil_datatype.Term) + (struct + let name = "Data_for_aorai.Max_value_counter" + let dependencies = [ Ast.self; Aorai_option.Ya.self ] + let kind = `Internal + let size = 7 + end) + +let find_max_value t = + try Some (Max_value_counter.find t) with Not_found -> None let raise_error msg = Aorai_option.fatal "Aorai plugin internal error. \nStatus : %s.\n" msg;; (* Format.printf "Aorai plugin internal error. \nStatus : %s.\n" msg; *) (* assert false *) - - -(* ************************************************************************* *) -let ltl_exps = ref (Hashtbl.create 1) - -let setLtl_expressions exps = -(* Logic_simplification.setLtl_expressions exps;*) - ltl_exps:=exps - -let ltl_expressions_iter func = - Hashtbl.iter func !ltl_exps - -let get_exp_from_tmpident var = - try let (exp,_,_) = (Hashtbl.find !ltl_exps var) in exp - with _ -> raise_error ("TMP Variable ("^var^") not declared in hashtbl") - -let get_str_exp_from_tmpident var = - try let (_,str,_) = (Hashtbl.find !ltl_exps var) in "("^(str)^")" - with _ -> raise_error ("TMP Variable ("^var^") not declared in hashtbl") - -let get_pred_from_tmpident var = - try let (_,_,pred) = (Hashtbl.find !ltl_exps var) in pred - with _ -> raise_error ("TMP Variable ("^var^") not declared in hashtbl") - -let debug_ltl_expressions () = - Aorai_option.feedback " Known ltl expressions: \n"; - Hashtbl.iter - (fun key (_,str,_) -> - Aorai_option.feedback " Var tmp : %s ~~~> exp : %s\n" key str - ) - !ltl_exps - - +let por t1 t2 = + match t1,t2 with + PTrue,_ | _,PTrue -> PTrue + | PFalse,t | t,PFalse -> t + | _,_ -> POr(t1,t2) + +let pand t1 t2 = + match t1,t2 with + PTrue,t | t,PTrue -> t + | PFalse,_ | _,PFalse -> PFalse + | _,_ -> PAnd(t1,t2) + +let pnot t = + match t with + PTrue -> PFalse + | PFalse -> PTrue + | PNot t -> t + | _ -> PNot t + +let rec is_same_expression e1 e2 = + match e1,e2 with + | PVar x, PVar y -> x = y + | PVar _,_ | _,PVar _ -> false + | PCst cst1, PCst cst2 -> Logic_utils.is_same_pconstant cst1 cst2 + | PCst _,_ | _,PCst _ -> false + | PPrm (f1,x1), PPrm(f2,x2) -> f1 = x1 && f2 = x2 + | PPrm _,_ | _,PPrm _ -> false + | PBinop(b1,l1,r1), PBinop(b2,l2,r2) -> + b1 = b2 && is_same_expression l1 l2 && is_same_expression r1 r2 + | PBinop _, _ | _, PBinop _ -> false + | PUnop(u1,e1), PUnop(u2,e2) -> u1 = u2 && is_same_expression e1 e2 + | PUnop _,_ | _,PUnop _ -> false + | PArrget(a1,i1), PArrget(a2,i2) -> + is_same_expression a1 a2 && is_same_expression i1 i2 + | PArrget _,_ | _,PArrget _ -> false + | PField(e1,f1), PField(e2,f2) -> f1 = f2 && is_same_expression e1 e2 + | PField _,_ | _,PField _ -> false + | PArrow(e1,f1), PArrow(e2,f2) -> f1 = f2 && is_same_expression e1 e2 let declared_logics = Hashtbl.create 97 let add_logic name log_info = begin + (* [VP 20110627] I don't understand the meaning of this test. If it's not + in the table, why do we delete it? *) if not (Hashtbl.mem declared_logics name) then Hashtbl.remove declared_logics name; Hashtbl.add declared_logics name log_info @@ -79,8 +125,6 @@ try Hashtbl.find declared_logics name with _ -> raise_error ("Logic function '"^name^"' not declared in hashtbl") - - let declared_predicates = Hashtbl.create 97 let add_predicate name pred_info = @@ -94,8 +138,6 @@ try Hashtbl.find declared_predicates name with _ -> raise_error ("Predicate '"^name^"' not declared in hashtbl") - - (* ************************************************************************* *) (* Some constant names used for generation *) (* Logic variables *) @@ -135,21 +177,12 @@ (* C function *) let buch_sync = "Aorai_Sync" (* Deprecated ? *) - - - - (* ************************************************************************* *) (* Buchi automata as stored after parsing *) let automata = ref ([],[]) (* Each transition with a parametrized cross condition (call param access or return value access) has its parametrized part stored in this array. *) -let cond_of_parametrizedTransitions = ref (Array.make (1) []) - -(* List of variables name observed in the promela file *) -let variables_from_auto = ref [] -(* List of functions name observed in the promela file *) -let functions_from_auto = ref [] +let cond_of_parametrizedTransitions = ref (Array.make (1) [[]]) (* List of variables name observed in the C file *) let variables_from_c = ref [] @@ -158,52 +191,1316 @@ (* List of functions call observed in the C file without declaration *) let ignored_functions = ref [] - - (** Return the buchi automata as stored after parsing *) -let getAutomata () = - !automata - +let getAutomata () = !automata (** Return the number of transitions of the automata *) -let getNumberOfTransitions () = - List.length (snd !automata) +let getNumberOfTransitions () = List.length (snd !automata) (** Return the number of states of the automata *) -let getNumberOfStates () = - List.length (fst !automata) +let getNumberOfStates () = List.length (fst !automata) +let is_c_global name = + try ignore (Globals.Vars.find_from_astinfo name VGlobal); true + with Not_found -> + try ignore (Globals.Functions.find_by_name name); true + with Not_found -> false + +let get_fresh = + let used_names = Hashtbl.create 5 in + fun name -> + if Clexer.is_c_keyword name + || Logic_lexer.is_acsl_keyword name || is_c_global name + || Hashtbl.mem used_names name + then begin + let i = ref (try Hashtbl.find used_names name with Not_found -> 0) in + let proposed_name () = name ^ "_" ^ string_of_int !i in + while is_c_global (proposed_name()) do incr i done; + Hashtbl.replace used_names name (!i+1); + proposed_name () + end + else begin + Hashtbl.add used_names name 0; + name + end + +module AuxVariables = + State_builder.List_ref + (Cil_datatype.Varinfo) + (struct + let name = "Data_for_aorai.AuxVariables" + let dependencies = + [ Aorai_option.Ltl_File.self; Aorai_option.Buchi.self; + Aorai_option.Ya.self; Ast.self ] + let kind = `Internal + end) + +module AbstractLogicInfo = + State_builder.List_ref + (Cil_datatype.Logic_info) + (struct + let name = "Data_for_aorai.AbstractLogicInfo" + let dependencies = + [ Aorai_option.Ltl_File.self; Aorai_option.Buchi.self; + Aorai_option.Ya.self; Ast.self ] + let kind = `Internal + end) + +class change_var vi1 vi2 = + object + inherit Visitor.frama_c_copy (Project.current ()) + method vlogic_var_use vi = + if Cil_datatype.Logic_var.equal vi1 vi then ChangeTo vi2 else SkipChildren + end -(** Stores the buchi automata and its variables and functions as such as it is return by the parsing *) -let setAutomata auto vars funcs = - variables_from_auto:=Hashtbl.fold (fun k _ l -> k::l) vars []; - functions_from_auto:=Hashtbl.fold (fun k _ l -> k::l) funcs []; - automata:=auto; - setNumberOfStates (getNumberOfStates ()); - setNumberOfTransitions (getNumberOfTransitions ()); - if (Array.length !cond_of_parametrizedTransitions) < (getNumberOfTransitions ()) then - cond_of_parametrizedTransitions := Array.make (getNumberOfTransitions ()) [] +let change_var_term vi1 vi2 t = + Visitor.visitFramacTerm (new change_var vi1 vi2) t + +let change_var_lval vi1 vi2 lv = + Visitor.visitFramacTermLval (new change_var vi1 vi2) lv + +let update_condition vi1 vi2 cond = + let rec aux e = + match e with + | TOr (e1,e2) -> TOr(aux e1, aux e2) + | TAnd (e1,e2) -> TAnd(aux e1, aux e2) + | TNot e -> TNot (aux e) + | TCall _ | TReturn _ | TTrue | TFalse -> e + | TRel(rel,t1,t2) -> + TRel(rel,change_var_term vi1 vi2 t1,change_var_term vi1 vi2 t2) + in aux cond + +let update_action vi1 vi2 action = + List.map + (fun (lv,t) -> change_var_lval vi1 vi2 lv, change_var_term vi1 vi2 t) + action + +let pebble_set_at li lab = + assert (li.l_profile = []); + let labels = List.map (fun x -> (x,lab)) li.l_labels in + Logic_const.term (Tapp (li,labels,[])) (Extlib.the li.l_type) + +let memo_multi_state st = + match st.multi_state with + | None -> + let aux = Cil.makeGlobalVar (get_fresh "aorai_aux") Cil.intType in + let laux = Cil.cvar_to_lvar aux in + let set = Cil_const.make_logic_info (get_fresh (st.name ^ "_pebble")) in + let typ = Logic_const.make_set_type (Ctype Cil.intType) in + set.l_var_info.lv_type <- typ; + set.l_labels <- [ LogicLabel(None,"L")]; + set.l_type <- Some typ; + set.l_body <- + LBreads + [ Logic_const.new_identified_term (Logic_const.tvar laux) ]; + let multi_state = set,laux in + st.multi_state <- Some multi_state; + multi_state + | Some multi_state -> multi_state + +let change_bound_var st1 st2 cond = + if Extlib.has_some st1.multi_state then begin + let (_,idx1) = Extlib.the st1.multi_state in + let (_,idx2) = memo_multi_state st2 in + update_condition idx1 idx2 cond + end else cond + +let add_aux_variable vi = AuxVariables.add vi + +let aux_variables = AuxVariables.get + +let add_abstract_logic_info li = AbstractLogicInfo.add li + +let abstract_logic_info = AbstractLogicInfo.get + +module StateIndex = + State_builder.Counter(struct let name = "Data_for_aorai.StateIndex" end) + +module TransIndex = + State_builder.Counter(struct let name = "Data_for_aorai.TransIndex" end) + +let new_state name = + { name = get_fresh name; acceptation = Bool3.False; + init = Bool3.False; nums = StateIndex.next(); + multi_state = None + } + +let new_intermediate_state () = new_state "aorai_intermediate_state" + +let new_trans start stop cond = + { start = start; stop = stop; cross = cond; numt = TransIndex.next () } + +let cleanup_name state = { state with name = get_fresh state.name } + +let cleanup_state_names (states,trans) = + let assoc = List.map (fun state -> state, cleanup_name state) states in + let sync_trans tr = + { tr with + start = List.assq tr.start assoc; + stop = List.assq tr.stop assoc } + in + let trans = List.map sync_trans trans in + let states = snd (List.split assoc) in + (states,trans) + +let check_states () = + let states,trans = getAutomata() in + let max = getNumberOfStates () in + List.iter + (fun x -> if x.nums >= max then + Aorai_option.fatal "State %d found while max id is supposed to be %d" + x.nums max) + states; + List.iter + (fun x -> + if not (List.memq x.start states) then + Aorai_option.fatal + "Start state %d of transition %d is not among known states" + x.start.nums x.numt; + if not (List.memq x.stop states) then + Aorai_option.fatal + "End state %d of transition %d is not among known states" + x.start.nums x.numt;) + trans + +let cst_one = PCst (Logic_ptree.IntConstant "1") + +let cst_zero = PCst (Logic_ptree.IntConstant "0") + +let is_cst_zero e = + match e with + | PCst(IntConstant "0") -> true + | _ -> false + +let is_cst_one e = + match e with + PCst (IntConstant "1") -> true + | _ -> false + +let is_single elt = + match elt.min_rep, elt.max_rep with + | Some min, Some max -> is_cst_one min && is_cst_one max + | _ -> false + +(* Epsilon transitions will account for the possibility of + not entering a repeated sequence at all. They will be normalized after + the entire automaton is processed by adding direct transitions from the + starting state to the children of the end state. +*) +type eps_trans = + Normal of typed_condition * action + | Epsilon of typed_condition * action + +let print_epsilon_trans fmt = function + | Normal (c,a) -> + Format.fprintf fmt "%a%a" + Promelaoutput.print_condition c + Promelaoutput.print_action a + | Epsilon (c,a) -> + Format.fprintf fmt "epsilon-trans:@\n%a%a" + Promelaoutput.print_condition c + Promelaoutput.print_action a + +type current_event = + | ECall of + kernel_function + * Cil_types.logic_var Cil_datatype.Varinfo.Hashtbl.t + * eps_trans Promelaast.trans + | EReturn of kernel_function + | ECOR of kernel_function + | ENone (* None found yet *) + | EMulti (* multiple event possible. + repr of the stack does not take into account + this particular event. *) + +let add_current_event event env cond = + let is_empty tbl = Cil_datatype.Varinfo.Hashtbl.length tbl = 0 in + match env with + [] -> assert false + | old_event :: tl -> + match event, old_event with + | ENone, _ -> env, cond + | _, ENone -> event::tl, cond + | ECall (kf1,_,_), ECall (kf2,_,_) + when Kernel_function.equal kf1 kf2 -> env, cond + | ECall (kf1,tbl1,_), ECall (kf2,tbl2,_)-> + (* ltl2buchi generates such inconsistent guards, but luckily does + not speak about formals. In this case, we just return False with + an empty event. If this situation occurs in an handwritten + automaton that uses formals we simply reject it. + *) + if is_empty tbl1 && is_empty tbl2 then ENone::tl, TFalse + else + Aorai_option.abort + "specification is inconsistent: two call events for distinct \ + functions %a and %a at the same time." + Kernel_function.pretty kf1 Kernel_function.pretty kf2 + | ECall (_,_,_), EMulti -> event::tl, cond + | ECall (kf1,tbl1,_), EReturn kf2 -> + if is_empty tbl1 then ENone::tl, TFalse + else + Aorai_option.abort + "specification is inconsistent: trying to call %a and \ + return from %a at the same time." + Kernel_function.pretty kf1 Kernel_function.pretty kf2 + | ECall(kf1,_,_), ECOR kf2 + when Kernel_function.equal kf1 kf2 -> + event::tl, cond + | ECall (kf1,tbl1,_), ECOR kf2 -> + if is_empty tbl1 then ENone::tl, TFalse + else + Aorai_option.abort + "specification is inconsistent: trying to call %a and \ + call or return from %a at the same time." + Kernel_function.pretty kf1 Kernel_function.pretty kf2 + | EReturn kf1, ECall(kf2,tbl2,_) -> + if is_empty tbl2 then ENone::tl, TFalse + else + Aorai_option.abort + "specification is inconsistent: trying to call %a and \ + return from %a at the same time." + Kernel_function.pretty kf2 Kernel_function.pretty kf1 + | EReturn kf1, (ECOR kf2 | EReturn kf2) + when Kernel_function.equal kf1 kf2 -> event::tl, cond + | EReturn _, EReturn _ -> ENone::tl, TFalse + | EReturn _, ECOR _ -> ENone::tl, TFalse + | EReturn _, EMulti -> ENone::tl, TFalse + | (EMulti | ECOR _), _ -> assert false + (* These are compound event. They cannot be found as individual ones*) + +let merge_current_event env1 env2 cond1 cond2 = + assert (List.tl env1 == List.tl env2); + let old_env = List.tl env2 in + match (List.hd env1, List.hd env2) with + | ENone, _ -> env2, tor cond1 cond2 + | _, ENone -> env1, tor cond1 cond2 + | ECall(kf1,_,_), ECall(kf2,_,_) + when Kernel_function.equal kf1 kf2 -> env2, tor cond1 cond2 + | ECall _, ECall _ -> EMulti::old_env, tor cond1 cond2 + | ECall _, EMulti -> env2, tor cond1 cond2 + | ECall (kf1,_,_), ECOR kf2 when Kernel_function.equal kf1 kf2 -> + env2, tor cond1 cond2 + | ECall (kf1,_,_), EReturn kf2 when Kernel_function.equal kf1 kf2 -> + ECOR kf1 :: old_env, tor cond1 cond2 + | ECall _, (ECOR _ | EReturn _) -> EMulti :: old_env, tor cond1 cond2 + | EReturn kf1, ECall (kf2,_,_) when Kernel_function.equal kf1 kf2 -> + ECOR kf1 :: old_env, tor cond1 cond2 + | EReturn _, ECall _ -> EMulti :: old_env, tor cond1 cond2 + | EReturn kf1, EReturn kf2 when Kernel_function.equal kf1 kf2 -> + env2, tor cond1 cond2 + | EReturn _, EReturn _ -> EMulti :: old_env, tor cond1 cond2 + | EReturn _, EMulti -> env2, tor cond1 cond2 + | EReturn kf1, ECOR kf2 when Kernel_function.equal kf1 kf2 -> + env2, tor cond1 cond2 + | EReturn _, ECOR _ -> + EMulti :: old_env, tor cond1 cond2 + | ECOR kf1, (ECall(kf2,_,_) | EReturn kf2 | ECOR kf2) + when Kernel_function.equal kf1 kf2 -> env1, tor cond1 cond2 + | ECOR _, (ECall _ | EReturn _ | ECOR _) -> + EMulti :: old_env, tor cond1 cond2 + | ECOR _, EMulti -> env2, tor cond1 cond2 + | EMulti, (ECall _ | EReturn _ | ECOR _) -> env1, tor cond1 cond2 + | EMulti, EMulti -> EMulti::old_env, tor cond1 cond2 + +let get_bindings st my_var = + let my_lval = TVar my_var, TNoOffset in + match st with + None -> my_lval + | Some st -> + let (_,idx) = memo_multi_state st in + Cil.addTermOffsetLval (TIndex (Logic_const.tvar idx,TNoOffset)) my_lval +let get_bindings_term st my_var typ = + Logic_const.term (TLval (get_bindings st my_var)) typ +let memo_aux_variable tr counter used_prms vi = + try + let my_var = Cil_datatype.Varinfo.Hashtbl.find used_prms vi in + get_bindings_term counter my_var (Ctype vi.vtype) + with Not_found -> + let my_type = + match counter with + | None -> vi.vtype + | Some _ -> TArray(vi.vtype,None,{scache=Not_Computed},[]) + in + let my_var = + Cil.makeGlobalVar (get_fresh ("aorai_" ^ vi.vname)) my_type + in + add_aux_variable my_var; + let my_lvar = Cil.cvar_to_lvar my_var in + Cil_datatype.Varinfo.Hashtbl.add used_prms vi my_lvar; + (match tr.cross with + | Normal (cond,action) -> + let st = Extlib.opt_map (fun _ -> tr.stop) counter in + let loc = get_bindings st my_lvar in + let copy = Copy_value (loc,Logic_const.tvar (Cil.cvar_to_lvar vi)) in + tr.cross <- Normal(cond,copy::action) + | Epsilon _ -> + Aorai_option.fatal "Epsilon transition used as Call event" + ); + get_bindings_term counter my_lvar (Ctype vi.vtype) + +let check_one top info counter s = + match info with + | ECall (kf,used_prms,tr) -> + (try + let vi = Globals.Vars.find_from_astinfo s (VFormal kf) in + if top then Some (Logic_const.tvar (Cil.cvar_to_lvar vi)) + else Some (memo_aux_variable tr counter used_prms vi) + with Not_found -> None) + | EReturn kf when top && ( Datatype.String.equal s "return" + || Datatype.String.equal s "\\result") -> + let rt = Kernel_function.get_return_type kf in + if Cil.isVoidType rt then + Aorai_option.abort + "%a returns void. \\result is meaningless in this context" + Kernel_function.pretty kf; + Some (Logic_const.term (TLval (TResult rt,TNoOffset)) (Ctype rt)) + | ECOR _ | EReturn _ | EMulti | ENone -> None + +let find_in_env env counter s = + let current, stack = + match env with + | current::stack -> current, stack + | [] -> Aorai_option.fatal "Empty type-checking environment" + in + match check_one true current counter s with + Some lv -> lv + | None -> + let module M = struct exception Found of term end in + (try + List.iter + (fun x -> + match check_one false x counter s with + None -> () + | Some lv -> raise (M.Found lv)) + stack; + let vi = Globals.Vars.find_from_astinfo s VGlobal in + Logic_const.tvar (Cil.cvar_to_lvar vi) + with + M.Found lv -> lv + | Not_found -> Aorai_option.abort "Unknown variable %s" s) + +let find_prm_in_env env ?tr counter f x = + let kf = + try Globals.Functions.find_by_name f + with Not_found -> Aorai_option.abort "Unknown function %s" f + in + if Datatype.String.equal x "return" || + Datatype.String.equal x "\\result" then begin + (* Return event *) + let rt = Kernel_function.get_return_type kf in + if Cil.isVoidType rt then + Aorai_option.abort + "%a returns void. %s().%s is meaningless in this context" + Kernel_function.pretty kf f x; + let env,cond = add_current_event (EReturn kf) env (TReturn kf) in + env, + Logic_const.term (TLval (TResult rt,TNoOffset)) (Ctype rt), + cond + end else begin (* Complete Call followed by Return event *) + let rec treat_env top = + function + | ECall(kf',_,_) as event :: _ + when Kernel_function.equal kf kf'-> + (match check_one top event counter x with + Some lv -> + env, lv, TTrue + | None -> + Aorai_option.abort "Function %s has no parameter %s" f x) + | (ENone | EReturn _ | EMulti | ECOR _ | ECall _ ) + :: tl -> + treat_env false tl + | [] -> + let env, cond = + match tr with + None -> + Aorai_option.abort + "Function %s is not in the call stack. \ + Cannot use its parameter %s here" f x + | Some tr -> + add_current_event + (ECall (kf, Cil_datatype.Varinfo.Hashtbl.create 3, tr)) + env + (TCall (kf,None)) + in + let vi = + try Globals.Vars.find_from_astinfo x (VFormal kf) + with Not_found -> + Aorai_option.abort "Function %s has no parameter %s" f x + in + (* By definition, we are at the call event: no need to store + it in an aux variable or array here. + *) + env, Logic_const.tvar (Cil.cvar_to_lvar vi), cond + in treat_env true env + end -let getStateName num = - List.fold_left - (fun name st -> if st.nums=num then st.name else name) - "" - (fst !automata) - +module C_logic_env = +struct + let anonCompFieldName = Cabs2cil.anonCompFieldName + let conditionalConversion = Cabs2cil.logicConditionalConversion + let find_macro _ = raise Not_found + let find_var _ = raise Not_found + let find_enum_tag _ = raise Not_found + let find_comp_type ~kind:_ _ = raise Not_found + let find_comp_field info s = + let field = Cil.getCompField info s in + Field(field,NoOffset) + let find_type _ = raise Not_found + let find_label _ = raise Not_found + + include Logic_env + let add_logic_function = + add_logic_function_gen Logic_utils.is_same_logic_profile + + let integral_cast ty t = + Aorai_option.abort + "term %a has type %a, but %a is expected." + Cil.d_term t Cil.d_logic_type Linteger Cil.d_type ty +end + +module LTyping = Logic_typing.Make(C_logic_env) + +let type_expr env ?tr ?current e = + let loc = Cil_datatype.Location.unknown in + let rec aux env cond e = + match e with + PVar s -> + let var = find_in_env env current s in + env, var, cond + | PPrm(f,x) -> find_prm_in_env env ?tr current f x + | PCst (Logic_ptree.IntConstant s) -> + let e = + match (Cil.parseInt ~loc s).enode with + | Const (CInt64 _ as c) -> TConst c + | Const (CChr _ as c) -> TConst c + | _ -> assert false + in + env, Logic_const.term e Linteger, cond + | PCst (Logic_ptree.FloatConstant str) -> + let e,t = + let hasSuffix str = + let l = String.length str in + fun s -> + let ls = String.length s in + l >= ls && s = String.uppercase (String.sub str (l - ls) ls) + in + (* Maybe it ends in U or UL. Strip those *) + let l = String.length str in + let hasSuffix = hasSuffix str in + let baseint, kind = + if hasSuffix "L" or hasSuffix "l" then + String.sub str 0 (l - 1), FLongDouble + else if hasSuffix "F" or hasSuffix "f" then + String.sub str 0 (l - 1), FFloat + else if hasSuffix "D" or hasSuffix "d" then + String.sub str 0 (l - 1), FDouble + else + str, FDouble + in + begin + try + TConst(CReal(float_of_string baseint, kind, Some str)), + Lreal + with Failure _ as e -> + Aorai_option.abort ~current:true + "float_of_string %s (%s)" str (Printexc.to_string e) + end + in env,Logic_const.term e t,cond + | PCst (Logic_ptree.StringConstant s) -> + let t = + Logic_const.term + (TConst(CStr (Logic_typing.unescape s))) (Ctype Cil.charPtrType) + in + env,t,cond + | PCst (Logic_ptree.WStringConstant s) -> + let t = + Logic_const.term + (TConst (CWStr (Logic_typing.wcharlist_of_string s))) + (Ctype (TPtr(Cil.theMachine.wcharType,[]))) + in env,t,cond + | PBinop(bop,e1,e2) -> + let op = Logic_typing.type_binop bop in + let env,e1,cond = aux env cond e1 in + let env,e2,cond = aux env cond e2 in + let t1 = e1.term_type in + let t2 = e2.term_type in + let t = + if Logic_typing.is_arithmetic_type t1 + && Logic_typing.is_arithmetic_type t2 + then + let t = Logic_typing.arithmetic_conversion t1 t2 in + Logic_const.term + (TBinOp (op,LTyping.mk_cast e1 t,LTyping.mk_cast e2 t)) + t + else + (match bop with + | Logic_ptree.Badd + when + Logic_typing.is_integral_type t2 + && Logic_utils.isLogicPointerType t1 -> + Logic_const.term (TBinOp (PlusPI,e1,e2)) t1 + | Logic_ptree.Bsub + when + Logic_typing.is_integral_type t2 + && Logic_utils.isLogicPointerType t1 -> + Logic_const.term (TBinOp (MinusPI,e1,e2)) t1 + | Logic_ptree.Badd + when + Logic_typing.is_integral_type t1 + && Logic_utils.isLogicPointerType t2 -> + Logic_const.term (TBinOp (PlusPI,e2,e1)) t2 + | Logic_ptree.Bsub + when + Logic_typing.is_integral_type t1 + && Logic_utils.isLogicPointerType t2 -> + Logic_const.term (TBinOp (MinusPI,e2,e1)) t2 + | Logic_ptree.Bsub + when + Logic_utils.isLogicPointerType t1 + && Logic_utils.isLogicPointerType t2 -> + Logic_const.term + (TBinOp (MinusPP,e1,LTyping.mk_cast e2 t1)) + Linteger + | _ -> + Aorai_option.abort + "Invalid operands for binary operator %a: \ + unexpected %a and %a" + !Ast_printer.d_binop op + !Ast_printer.d_term e1 + !Ast_printer.d_term e2) + in + env, t, cond + | PUnop(Logic_ptree.Uminus,e) -> + let env,t,cond = aux env cond e in + if Logic_typing.is_arithmetic_type t.term_type then + env,Logic_const.term (TUnOp (Neg,t)) Linteger,cond + else Aorai_option.abort + "Invalid operand for unary -: unexpected %a" !Ast_printer.d_term t + | PUnop(Logic_ptree.Ubw_not,e) -> + let env,t,cond = aux env cond e in + if Logic_typing.is_arithmetic_type t.term_type then + env,Logic_const.term (TUnOp (BNot,t)) Linteger,cond + else Aorai_option.abort + "Invalid operand for bitwise not: unexpected %a" !Ast_printer.d_term t + | PUnop(Logic_ptree.Uamp,e) -> + let env, t, cond = aux env cond e in + let ptr = + try Ctype (TPtr (Logic_utils.logicCType t.term_type,[])) + with Failure _ -> + Aorai_option.abort "Cannot take address: not a C type(%a): %a" + !Ast_printer.d_logic_type t.term_type !Ast_printer.d_term t + in + (match t.term_node with + | TLval v | TStartOf v -> env, Logic_const.taddrof v ptr, cond + | _ -> + Aorai_option.abort "Cannot take address: not an lvalue %a" + !Ast_printer.d_term t + ) + | PUnop (Logic_ptree.Ustar,e) -> + let env, t, cond = aux env cond e in + if Logic_utils.isLogicPointerType t.term_type then + env, + Logic_const.term + (TLval (TMem t, TNoOffset)) + (Logic_typing.type_of_pointed t.term_type), + cond + else + Aorai_option.abort "Cannot dereference term %a" !Ast_printer.d_term t + | PArrget(e1,e2) -> + let env, t1, cond = aux env cond e1 in + let env, t2, cond = aux env cond e2 in + let t = + if Logic_utils.isLogicPointerType t1.term_type + && Logic_typing.is_integral_type t2.term_type + then + Logic_const.term + (TBinOp (IndexPI,t1,t2)) + (Logic_typing.type_of_pointed t1.term_type) + else if Logic_utils.isLogicPointerType t2.term_type + && Logic_typing.is_integral_type t1.term_type + then + Logic_const.term + (TBinOp (IndexPI,t2,t1)) + (Logic_typing.type_of_pointed t2.term_type) + else if Logic_utils.isLogicArrayType t1.term_type + && Logic_typing.is_integral_type t2.term_type + then + (match t1.term_node with + | TStartOf lv | TLval lv -> + Logic_const.term + (TLval + (Logic_typing.add_offset_lval (TIndex (t2, TNoOffset)) lv)) + (Logic_typing.type_of_array_elem t1.term_type) + | _ -> + Aorai_option.fatal + "Unsupported operation: %a[%a]" + !Ast_printer.d_term t1 !Ast_printer.d_term t2) + else if Logic_utils.isLogicArrayType t2.term_type + && Logic_typing.is_integral_type t1.term_type + then + (match t2.term_node with + | TStartOf lv | TLval lv -> + Logic_const.term + (TLval + (Logic_typing.add_offset_lval (TIndex (t1, TNoOffset)) lv)) + (Logic_typing.type_of_array_elem t2.term_type) + | _ -> + Aorai_option.fatal + "Unsupported operation: %a[%a]" + !Ast_printer.d_term t1 !Ast_printer.d_term t2) + else + Aorai_option.abort + "Subscripted value is neither array nor pointer: %a[%a]" + !Ast_printer.d_term t1 !Ast_printer.d_term t2 + in + env, t, cond + | PField(e,s) -> + let env, t, cond = aux env cond e in + (match t.term_node with + | TLval lv -> + let off, ty = LTyping.type_of_field loc s t.term_type in + let lv = Logic_typing.add_offset_lval off lv in + env, Logic_const.term (TLval lv) ty, cond + | _ -> + Aorai_option.fatal + "Unsupported operation: %a.%s" !Ast_printer.d_term t s) + | PArrow(e,s) -> + let env, t, cond = aux env cond e in + if Logic_utils.isLogicPointerType t.term_type then begin + let off, ty = + LTyping.type_of_field loc s + (Logic_typing.type_of_pointed t.term_type) + in + let lv = Logic_typing.add_offset_lval off (TMem t,TNoOffset) in + env, Logic_const.term (TLval lv) ty, cond + end else + Aorai_option.abort "base term is not a pointer in %a -> %s" + !Ast_printer.d_term t s + in + aux env TTrue e +let type_cond needs_pebble env tr cond = + let current = if needs_pebble then Some tr.stop else None in + let rec aux pos env = + function + | PRel(rel,e1,e2) -> + let env, e1, c1 = type_expr env ~tr ?current e1 in + let env, e2, c2 = type_expr env ~tr ?current e2 in + let call_cond = if pos then tand c1 c2 else tor (tnot c1) (tnot c2) in + let rel = TRel(Logic_typing.type_rel rel,e1,e2) in + let cond = if pos then tand rel call_cond else tor rel call_cond in + env, cond + | PTrue -> env, TTrue + | PFalse -> env, TFalse + | POr(c1,c2) -> + let env1, c1 = aux pos env c1 in + let env2, c2 = aux pos env c2 in + merge_current_event env1 env2 c1 c2 + | PAnd(c1,c2) -> + let env, c1 = aux pos env c1 in + let env, c2 = aux pos env c2 in + env, TAnd(c1,c2) + | PNot c -> + let env, c = aux (not pos) env c in env, TNot c + | PCall (s,b) -> + let kf = + try + Globals.Functions.find_by_name s + with Not_found -> Aorai_option.abort "No such function: %s" s + in + let b = + Extlib.opt_map + (fun b -> + let bhvs = + (Kernel_function.get_spec ~populate:false kf).spec_behavior + in + try + List.find (fun x -> x.b_name = b) bhvs + with Not_found -> + Aorai_option.abort "Function %a has no behavior named %s" + Kernel_function.pretty kf b) + b + in + if pos then + add_current_event + (ECall (kf, Cil_datatype.Varinfo.Hashtbl.create 3, tr)) env + (TCall (kf,b)) + else env, TCall (kf,b) + | PReturn s -> + let kf = + try + Globals.Functions.find_by_name s + with Not_found -> Aorai_option.abort "No such function %s" s + in + if pos then add_current_event (EReturn kf) env (TReturn kf) + else env, TReturn kf + in + aux true (ENone::env) cond -(* Each transition with a parametrized cross condition (call param access or return value access) has its parametrized part stored in an array. *) -let setCondOfParametrizedTransition conds = - cond_of_parametrizedTransitions := conds +module Reject_state = + State_builder.Option_ref(Aorai_state) + (struct + let name = "Data_for_aorai.Reject_state" + let dependencies = + [ Ast.self; Aorai_option.Ltl_File.self; Aorai_option.Buchi.self; + Aorai_option.Ya.self] + let kind = `Internal + end) + +let get_reject_state () = + let create () = new_state "aorai_reject" in + Reject_state.memo create + +let rec type_seq default_state tr env needs_pebble curr_start curr_end seq = + let add_if_needed states st = + if List.for_all (fun x -> x.nums <> st.nums) states + then st::states else states + in + match seq with + | [] -> (* We identify start and end. *) + (env, [], [], curr_end, curr_end) + | elt :: seq -> + let is_single_trans = + match elt.min_rep, elt.max_rep with + | Some min, Some max -> is_cst_one min && is_cst_one max + | None, _ | _, None -> false + in + let is_opt = + match elt.min_rep with + | Some min -> is_cst_zero min + | None-> true + in + let might_be_zero = + is_opt || + (match Extlib.the elt.min_rep with PCst _ -> false | _ -> true) + in + let at_most_one = + is_opt && + match elt.max_rep with + | None -> false + | Some max -> is_cst_one max + in + let has_loop = not at_most_one && not is_single_trans in + let needs_counter = + match elt.min_rep, elt.max_rep with + | None, None -> false + | Some min, None -> not (is_cst_zero min || is_cst_one min) + | None, Some max -> not (is_cst_one max) + | Some min, Some max -> + not (is_cst_zero min || is_cst_one min) || not (is_cst_one max) + in + let fixed_number_of_loop = + match elt.min_rep, elt.max_rep with + | _, None -> false + | None, Some max -> not (is_cst_zero max) + | Some min, Some max -> is_same_expression min max + in + let my_end = + match seq with + [] when not (curr_end.nums = tr.stop.nums) + || is_single_trans || at_most_one -> curr_end + | _ -> new_intermediate_state () + in + Aorai_option.debug "Examining single elt:@\n%s -> %s:@[%a@]" + curr_start.name my_end.name Promelaoutput.print_seq_elt elt; + let guard_exit_loop env current counter = + if is_opt then TTrue + else + let e = Extlib.the elt.min_rep in + let _,e,_ = type_expr env ?current e in + (* If we have done at least the lower bound of cycles, we can exit + the loop. *) + TRel(Cil_types.Rle,e,counter) + in + let guard_loop env current counter = + match elt.max_rep with + | None -> TTrue + | Some e -> + let _,e,_ = type_expr env ?current e in + Max_value_counter.replace counter e; + (* The counter is incremented after the test: it + must be strictly less than the upper bound to enter + a new cycle. + *) + TRel(Cil_types.Rlt, counter, e) + in + let env,inner_states, inner_trans, inner_start, inner_end = + match elt.condition with + | None -> + assert (elt.nested <> []); + (* we don't have a completely empty condition. *) + type_seq + default_state tr env needs_pebble curr_start my_end elt.nested + | Some cond -> + let seq_start = + match elt.nested with + [] -> my_end + | _ -> new_intermediate_state () + in + let trans_start = new_trans curr_start seq_start (Normal (TTrue,[])) + in + let inner_env, cond = type_cond needs_pebble env trans_start cond in + let (env,states, seq_transitions, seq_end) = + match elt.nested with + | [] -> inner_env, [], [], my_end + | _ -> + let intermediate = new_intermediate_state () in + let (env, states, transitions, _, seq_end) = + type_seq + default_state tr + inner_env needs_pebble seq_start intermediate elt.nested + in env, states, transitions, seq_end + in + let states = add_if_needed states curr_start in + let transitions = trans_start :: seq_transitions in + (match trans_start.cross with + | Normal (conds,action) -> + trans_start.cross <- Normal(tand cond conds,action) + | Epsilon _ -> + Aorai_option.fatal + "Transition guard translated as epsilon transition"); + let states = add_if_needed states seq_start in + (match env with + | [] | (ENone | ECall _) :: _ -> + (env, states, transitions, curr_start, seq_end) + | EReturn kf1 :: ECall (kf2,_,_) :: tl + when Kernel_function.equal kf1 kf2 -> + (tl, states, transitions, curr_start, seq_end) + | (EReturn _ | ECOR _ ) :: _ -> + (* If there is as mismatch (e.g. Call f; Return g), it will + be caught later. There are legitimate situations for + this pattern however (if the sequence itself occurs + in a non-empty context in particular) + *) + (env, states, transitions, curr_start, seq_end) + | EMulti :: env -> + (env, states, transitions, curr_start, seq_end)) + in + let loop_end = if has_loop then new_intermediate_state () else inner_end + in + let (_,oth_states,oth_trans,oth_start,_) = + type_seq default_state tr env needs_pebble loop_end curr_end seq + in + let trans = inner_trans @ oth_trans in + let states = List.fold_left add_if_needed oth_states inner_states in + let auto = (inner_states,inner_trans) in + if at_most_one then begin + (* Just adds an epsilon transition from start to end *) + let opt = new_trans curr_start oth_start (Epsilon (TTrue,[])) in + env, states, opt::trans, curr_start, curr_end + end + else if has_loop then begin + (* TODO: makes it an integer *) + let counter = + let ty = if needs_pebble then + Cil_types.TArray (Cil.intType,None,{scache=Not_Computed},[]) + else Cil.intType + in (* We won't always need a counter *) + lazy ( + let vi = Cil.makeGlobalVar (get_fresh "aorai_counter") ty in + add_aux_variable vi; + vi + ) + in + let make_counter st = + let vi = Lazy.force counter in + let base = TVar (Cil.cvar_to_lvar vi), TNoOffset in + if needs_pebble then + let (_,idx) = memo_multi_state st in + Cil.addTermOffsetLval + (TIndex (Logic_const.tvar idx,TNoOffset)) base + else base + in + let make_counter_term st = + Logic_const.term (TLval (make_counter st)) (Ctype Cil.intType) + in + Aorai_option.debug "Inner start is %s; Inner end is %s" + inner_start.name inner_end.name; + let treat_state (states, oth_trans) st = + let trans = Path_analysis.get_transitions_of_state st auto in + if st.nums = inner_start.nums then begin + let loop_trans = + if needs_counter then begin + List.fold_left + (fun acc tr -> + let init_action = Counter_init (make_counter tr.stop) in + let init_cross = + match tr.cross with + | Normal (cond, actions) -> + Normal(cond, init_action :: actions) + | Epsilon(cond, actions) -> + Epsilon(cond, init_action :: actions) + in + Aorai_option.debug "New init trans %s -> %s: %a" + st.name tr.stop.name + print_epsilon_trans init_cross; + let init_trans = + new_trans st tr.stop init_cross + in + if at_most_one then init_trans :: acc + else begin + let st = + if needs_pebble then Some curr_start else None + in + let loop_cond = + if needs_counter then + guard_loop env st + (make_counter_term curr_start) + else TTrue + in + let loop_action = + if needs_counter then begin + let counter = make_counter curr_start in + [ Counter_incr counter ] + end else [] + in + let loop_cross = + match tr.cross with + | Normal(cond, actions) -> + Normal(tand loop_cond cond, loop_action @ actions) + | Epsilon(cond, actions) -> + Epsilon(tand loop_cond cond, loop_action @ actions) + in + Aorai_option.debug "New loop trans %s -> %s: %a" + inner_end.name tr.stop.name + print_epsilon_trans loop_cross; + let loop_trans = + new_trans inner_end tr.stop loop_cross in + init_trans :: loop_trans :: acc + end) + oth_trans trans + end else oth_trans + in + let trans = + if might_be_zero then begin + (* We can bypass the inner transition altogether *) + let zero_cond = + if is_opt then TTrue + else + let current = + if needs_pebble then Some curr_start else None + in + let _,t,_ = + type_expr env ?current (Extlib.the elt.min_rep) + in + TRel (Cil_types.Req, t, Logic_const.tinteger ~ikind:IInt 0) + in + let no_seq = new_trans st oth_start (Epsilon (zero_cond,[])) in + no_seq :: loop_trans + end else loop_trans + in + states, trans + end + else if st.nums = inner_end.nums then begin + (* adds conditions on counter if needed *) + let st = + if needs_pebble then Some curr_end else None + in + let min_cond = + if needs_counter then + guard_exit_loop env st (make_counter_term curr_end) + else TTrue + in + let min_cond = Epsilon (min_cond,[]) in + Aorai_option.debug "New exit trans %s -> %s: %a" + inner_end.name oth_start.name + print_epsilon_trans min_cond; + let exit_trans = new_trans inner_end oth_start min_cond in + let trans = exit_trans :: trans @ oth_trans in + states, trans + end else begin + (* inner state: add a rejection state for consistency purposes + iff we don't have a constant number of repetition (i.e. cut + out branches where automaton wrongly start a new step) and + don't have an otherwise branch in the original automaton. + *) + if fixed_number_of_loop || default_state then + states, trans @ oth_trans + else begin + let cond = + List.fold_left + (fun acc tr -> + match tr.cross with + | Normal (cond,_) | Epsilon (cond,_) -> + let cond = change_bound_var tr.stop st cond in + tor acc cond) + TFalse trans + in + let (cond,_) = Logic_simplification.simplifyCond cond in + let cond = tnot cond in + (match cond with + TFalse -> states, trans @ oth_trans + | _ -> + let reject = get_reject_state () in + let states = add_if_needed states reject in + let trans = new_trans st reject (Normal(cond,[])) :: trans + in states, trans @ oth_trans + ) + end + end + in + let states, trans = + List.fold_left treat_state + (* inner transition gets added in treat_state *) + (states, oth_trans) + inner_states + in + env, states, trans, curr_start, curr_end + end else + env, states, trans, curr_start, curr_end + +let single_path (states,transitions as auto) tr = + Aorai_option.Deterministic.get () || + (let init = Path_analysis.get_init_states auto in + match init with + | [ st ] -> + let auto = (states, + List.filter (fun x -> x.numt <> tr.numt) transitions) + in + Path_analysis.at_most_one_path auto st tr.start + | _ -> false) + +let find_otherwise_trans auto st = + let trans = Path_analysis.get_transitions_of_state st auto in + try let tr = List.find (fun x -> x.cross = Otherwise) trans in Some tr.stop + with Not_found -> None + +let type_trans auto env tr = + let needs_pebble = not (single_path auto tr) in + Aorai_option.debug + "Analyzing transition %s -> %s: %a (needs pebble: %B)" + tr.start.name tr.stop.name Promelaoutput.print_parsed tr.cross needs_pebble; + match tr.cross with + | Seq seq -> + let default_state = find_otherwise_trans auto tr.start in + let has_default_state = Extlib.has_some default_state in + let _,states, transitions,_,_ = + type_seq has_default_state tr env needs_pebble tr.start tr.stop seq + in + let (states, transitions as auto) = + if List.exists (fun st -> st.multi_state <> None) states then begin + (* We have introduced some multi-state somewhere, we have to introduce + pebbles and propagate them from state to state. *) + let start = tr.start in + let count = (* TODO: make it an integer. *) + Cil.makeGlobalVar + (get_fresh ("aorai_cnt_" ^ start.name)) Cil.intType + in + add_aux_variable count; + let transitions = + List.map + (fun trans -> + match trans.cross with + | Epsilon _ -> trans + | Normal(cond,actions) -> + let (dest,d_aux) = memo_multi_state tr.stop in + let actions = + if tr.start.nums <> start.nums then begin + let src,s_aux = memo_multi_state tr.start in + Pebble_move(dest,d_aux,src,s_aux) :: actions + end else begin + let v = Cil.cvar_to_lvar count in + let incr = Counter_incr (TVar v, TNoOffset) in + let init = Pebble_init (dest, d_aux, v) in + init::incr::actions + end + in + { trans with + cross = Normal(cond, actions) }) + transitions + in + states, transitions + end else + states, transitions + in + if has_default_state then begin + (* For each intermediate state, add a transition + to the end of the sequence *) + let default_state = Extlib.the default_state in + let treat_one_state acc st = + if st.nums = tr.stop.nums || st.nums = tr.start.nums then acc + else begin + let trans = Path_analysis.get_transitions_of_state st auto in + let cond = + List.fold_left + (fun acc tr -> + match tr.cross with + | Epsilon (cond,_) | Normal(cond,_) -> + let cond = change_bound_var tr.stop st cond in + tor cond acc) + TFalse trans + in + let cond = + tnot (fst (Logic_simplification.simplifyCond cond)) + in + match cond with + TFalse -> acc + | _ -> + Aorai_option.debug + "Adding default transition %s -> %s: %a" + st.name default_state.name Promelaoutput.print_condition cond; + new_trans st default_state (Normal (cond,[])) :: acc + end + in + let default_trans = List.fold_left treat_one_state transitions states in + Aorai_option.debug "Resulting transitions:@\n%a" + (Pretty_utils.pp_list ~sep:"@\n" + (fun fmt tr -> Format.fprintf fmt "%s -> %s:@[%a@]" + tr.start.name tr.stop.name print_epsilon_trans tr.cross)) + default_trans; + states, default_trans + end else begin + Aorai_option.debug "Resulting transitions:@\n%a" + (Pretty_utils.pp_list ~sep:"@\n" + (fun fmt tr -> Format.fprintf fmt "%s -> %s:@[%a@]" + tr.start.name tr.stop.name print_epsilon_trans tr.cross)) + transitions; + states, transitions + end + | Otherwise -> [],[] (* treated directly by type_seq *) + +let propagate_epsilon_transitions (states, _ as auto) = + let rec transitive_closure start (conds,actions) known_states curr = + let known_states = curr :: known_states in + let trans = Path_analysis.get_transitions_of_state curr auto in + List.fold_left + (fun acc tr -> + match tr.cross with + | Epsilon (cond,my_actions) -> + Aorai_option.debug "Treating epsilon trans %s -> %s" + curr.name tr.stop.name; + if List.exists (fun st -> st.nums = tr.stop.nums) known_states + then acc + else + transitive_closure + start (tand cond conds, my_actions @ actions) + known_states tr.stop @ acc + | Normal (cond, action) -> + Aorai_option.debug "Adding transition %s -> %s from epsilon trans" + start.name tr.stop.name; + new_trans start tr.stop (tand cond conds,action @ actions) ::acc) + [] trans + in + let treat_one_state acc st = + acc @ transitive_closure st (TTrue,[]) [] st + in + let trans = List.fold_left treat_one_state [] states in + (states, trans) -let getParametrizedCondOfTransition tr = - !cond_of_parametrizedTransitions.(tr) +let add_default_trans (states, transitions as auto) otherwise = + let add_one_trans acc tr = + let st = tr.start in + let my_trans = Path_analysis.get_transitions_of_state st auto in + Aorai_option.debug "Considering new otherwise transition: %s -> %s" + st.name tr.stop.name; + let cond = + List.fold_left + (fun acc c -> + let (cond,_) = c.cross in + Aorai_option.debug "considering trans %s -> %s: %a" + c.start.name c.stop.name Promelaoutput.print_condition cond; + let neg = tnot cond in + Aorai_option.debug "negation: %a" + Promelaoutput.print_condition neg; + Aorai_option.debug "acc: %a" + Promelaoutput.print_condition acc; + let res = tand acc (tnot cond) in + Aorai_option.debug "partial result: %a" + Promelaoutput.print_condition res; + res + ) + TTrue + my_trans + in + Aorai_option.debug "resulting transition: %a" + Promelaoutput.print_condition cond; + let cond,_ = Logic_simplification.simplifyCond cond in + let new_trans = new_trans st tr.stop (cond,[]) in + new_trans::acc + in + let transitions = List.fold_left add_one_trans transitions otherwise in + states, transitions +let type_cond_auto (st,tr as auto) = + let otherwise = List.filter (fun t -> t.cross = Otherwise) tr in + let add_if_needed acc st = + if List.memq st acc then acc else st::acc + in + let type_trans (states,transitions) tr = + let (intermediate_states, trans) = type_trans auto [] tr in + Aorai_option.debug + "Considering parsed transition %s -> %s" tr.start.name tr.stop.name; + Aorai_option.debug + "Resulting transitions:@\n%a@\nEnd of transitions" + (Pretty_utils.pp_list ~sep:"@\n" + (fun fmt tr -> + Format.fprintf fmt "%s -> %s: %a" + tr.start.name tr.stop.name print_epsilon_trans tr.cross)) + trans; + (List.fold_left add_if_needed states intermediate_states, + transitions @ trans) + in + let auto = + List.fold_left type_trans (st,[]) tr + in + let auto = propagate_epsilon_transitions auto in + let (states, transitions as auto) = add_default_trans auto otherwise in + (* nums (and in the past numt) are used as indices in arrays. Therefore, we + must ensure that we use consecutive numbers starting from 0, or we'll + have needlessly long arrays. + *) + if Aorai_option.debug_atleast 1 then + Promelaoutput.output_dot_automata auto "aorai_debug_typed.dot"; + let (nb_trans,trans) = + List.fold_left + (fun (i,l as acc) t -> + let cond, action = t.cross in + let cond = fst (Logic_simplification.simplifyCond cond) + in match cond with + TFalse -> acc + | _ -> (i+1,{ t with cross = (cond,action); numt = i } :: l)) + (0,[]) transitions + in + let nb_state, states = + List.fold_left + (fun (i,l as acc) s -> + if + List.exists + (fun t -> t.start.nums = s.nums || t.stop.nums = s.nums) + trans + then begin + s.nums <- i; + (i+1, s :: l) + end else acc) + (0,[]) states + in + setNumberOfStates nb_state; + setNumberOfTransitions nb_trans; + (List.rev states, List.rev trans) + +(** Stores the buchi automaton and its variables and + functions as it is returned by the parsing *) +let setAutomata auto = + let auto = type_cond_auto auto in + automata:=auto; + check_states (); + if Aorai_option.debug_atleast 1 then + Promelaoutput.output_dot_automata auto "aorai_debug_reduced.dot"; + if (Array.length !cond_of_parametrizedTransitions) < + (getNumberOfTransitions ()) + then + (* all transitions have a true parameterized guard, i.e. [[]] *) + cond_of_parametrizedTransitions := + Array.make (getNumberOfTransitions ()) [[]] +let getState num = List.find (fun st -> st.nums = num) (fst !automata) +let getStateName num = (getState num).name +let getTransition num = + List.find (fun trans -> trans.numt = num) (snd !automata) (** Initializes some tables according to data from Cil AST. *) let setCData () = @@ -211,23 +1508,18 @@ Globals.Functions.fold (fun f (lf_decl,lf_def) -> let name = (Kernel_function.get_name f) in - match f.Db_types.fundec with - | Db_types.Definition _ -> (lf_decl,name::lf_def) - | Db_types.Declaration _ -> (name::lf_decl,lf_def)) + match f.fundec with + | Definition _ -> (lf_decl,name::lf_def) + | Declaration _ -> (name::lf_decl,lf_def)) ([],[]) in functions_from_c:=f_def; ignored_functions:=f_decl; variables_from_c:= - Globals.Vars.fold (fun v _ lv -> (Pretty_utils.sfprintf "%a" Ast_info.pretty_vname v)::lv) [] - -(** Return the list of all function name observed in the promela file. *) -let getFunctions_from_auto () = - (!functions_from_auto) - -(** Return the list of all variables name observed in the promela file. *) -let getVariables_from_auto () = - (!variables_from_auto) + Globals.Vars.fold + (fun v _ lv -> + Pretty_utils.sfprintf "%a" Cil_datatype.Varinfo.pretty_vname v :: lv) + [] (** Return the list of all function name observed in the C file, except ignored functions. *) let getFunctions_from_c () = @@ -251,32 +1543,6 @@ (fun s -> (String.compare fname s)=0) (!ignored_functions) - -(* Manage particular consistency verification between C file and automata specification. - It returns true if and only if these checks are ok. *) -let check_consistency () = - (* Checking consistency *) - let included_funs = - List.for_all - (fun fl -> - let r=List.exists (fun fc -> fc=fl) !functions_from_c in - if not r then Aorai_option.error "Error : function '%s' from LTL not found in C code.\n" fl; - r - ) - (!functions_from_auto) - in - let included_vars = - List.for_all - (fun vl -> - let r=(List.exists (fun vc -> vc=vl) ("result"::!variables_from_c)) in - if not r then Aorai_option.error "Error : variable '%s' from LTL not found in C code.\n" vl; - r - ) (!variables_from_auto) - in - (included_funs && included_vars) - - - (* ************************************************************************* *) (* Table giving the varinfo structure associated to a given variable name *) (* In practice it contains all variables (from promela and globals from C file) and only variables *) @@ -295,7 +1561,8 @@ Hashtbl.find varinfos name with _ -> raise_error ("Variable not declared ("^name^")") - +let get_logic_var name = + let vi = get_varinfo name in Cil.cvar_to_lvar vi (* Same as get_varinfo, but the result is an option. Hence, if the variable is not found then None is return. *) @@ -305,20 +1572,16 @@ with | _ -> None - - - (* Add a new param into the association table (funcname,paramname) -> varinfo *) let set_paraminfo funcname paramname vi = (* Aorai_option.log "Adding %s(...,%s,...) " funcname paramname; *) Hashtbl.add paraminfos (funcname,paramname) vi - (* Given a function name and a param name, it returns the varinfo associated to the given param. If the variable is not found then an error message is print and an assert false is raised. *) let get_paraminfo funcname paramname = try - Hashtbl.find paraminfos (funcname,paramname) + Hashtbl.find paraminfos (funcname,paramname) with _ -> raise_error ("Parameter '"^paramname^"' not declared for function '"^funcname^"'.") (* Add a new param into the association table funcname -> varinfo *) @@ -326,20 +1589,13 @@ (* Aorai_option.log "Adding return %s(...) " funcname ; *) Hashtbl.add paraminfos (funcname,"\\return") vi - (* Given a function name, it returns the varinfo associated to the given param. If the variable is not found then an error message is print and an assert false is raised. *) let get_returninfo funcname = try - Hashtbl.find paraminfos (funcname,"\\return") + Hashtbl.find paraminfos (funcname,"\\return") with _ -> raise_error ("Return varinfo not declared for function '"^funcname^"'.") - - - - - - (* ************************************************************************* *) (**{b Pre and post condition of C functions} In our point of view, the pre or the post condition of a C function are defined by the set of states @@ -353,9 +1609,6 @@ let post_status = Hashtbl.create 97 (* bool array * bool array *) let post_status_bycase = Hashtbl.create 97 (* bool array array * bool array array *) - - - (** Returns the pre condition associated to the given C function *) let get_func_pre ?(securised=false) func = try Hashtbl.find pre_status func @@ -392,9 +1645,289 @@ let set_func_post_bycase func status = Hashtbl.replace post_status_bycase func status +module Actions_key = +Datatype.Quadruple_with_collections + (Kernel_function) (Cil_datatype.Kinstr) (Aorai_state) (Aorai_state) + (struct let module_name = "Data_for_aorai.Actions_key" end) + +type range = + | Fixed of int (** constant value *) + | Interval of int * int (** range of values *) + | Bounded of int * term (** range bounded by a logic term (depending on + program parameter). + *) + | Unbounded of int (** only the lower bound is known, + there is no upper bound *) + +module Range = Datatype.Make_with_collections + (struct + type t = range + let name = "Data_for_aorai.Range" + let rehash = Datatype.identity + let structural_descr = Structural_descr.Abstract + let reprs = + Fixed 0 :: Interval (0,1) :: Unbounded 0 :: + List.map (fun x -> Bounded (0,x)) Cil_datatype.Term.reprs + let equal = Datatype.from_compare + let compare x y = + match x,y with + | Fixed c1, Fixed c2 -> Datatype.Int.compare c1 c2 + | Fixed _, _ -> 1 + | _, Fixed _ -> -1 + | Interval (min1,max1), Interval(min2, max2) -> + let c1 = Datatype.Int.compare min1 min2 in + if c1 = 0 then Datatype.Int.compare max1 max2 else c1 + | Interval _, _ -> 1 + | _,Interval _ -> -1 + | Bounded (min1,max1), Bounded(min2,max2) -> + let c1 = Datatype.Int.compare min1 min2 in + if c1 = 0 then Cil_datatype.Term.compare max1 max2 else c1 + | Bounded _, _ -> 1 + | _, Bounded _ -> -1 + | Unbounded c1, Unbounded c2 -> Datatype.Int.compare c1 c2 + let hash = function + | Fixed c1 -> 2 * c1 + | Interval(c1,c2) -> 3 * (c1 + c2) + | Bounded (c1,c2) -> 5 * (c1 + Cil_datatype.Term.hash c2) + | Unbounded c1 -> 7 * c1 + let copy = function + | Fixed c1 -> + Fixed (Datatype.Int.copy c1) + | Interval(c1,c2) -> + Interval(Datatype.Int.copy c1, Datatype.Int.copy c2) + | Bounded(c1,c2) -> + Bounded(Datatype.Int.copy c1, Cil_datatype.Term.copy c2) + | Unbounded c1 -> Unbounded (Datatype.Int.copy c1) + let internal_pretty_code _ = Datatype.from_pretty_code + let pretty_code fmt = function + | Fixed c1 -> Format.fprintf fmt "Fixed@ %d" c1 + | Interval (c1,c2) -> + Format.fprintf fmt "Interval@ (%d,@;%d)" c1 c2 + | Bounded(c1,c2) -> + Format.fprintf fmt "Bounded@ (%d,@;%a)" c1 + Cil_datatype.Term.pretty_code c2 + | Unbounded c1 -> Format.fprintf fmt "Unbounded@ %d" c1 + let pretty fmt = function + | Fixed c1 -> Format.fprintf fmt "%d" c1 + | Interval (c1,c2) -> + Format.fprintf fmt "@[<2>[%d..@;%d]@]" c1 c2 + | Bounded(c1,c2) -> + Format.fprintf fmt "@[<2>[%d..@;%a]@]" c1 + Cil_datatype.Term.pretty c2 + | Unbounded c1 -> Format.fprintf fmt "[%d..]" c1 + let varname _ = "r" + let mem_project = Datatype.never_any_project + end) + +module Intervals = Cil_datatype.Term.Map.Make(Range) + +module Vals = Cil_datatype.Term.Map.Make(Intervals) + +module Actions = + struct + include + State_builder.Hashtbl + (Actions_key.Hashtbl) + (Vals) + (struct + let name = "Data_for_aorai.Actions" + let dependencies = + [ Ast.self; Kernel.MainFunction.self; Aorai_option.Ya.self ] + let kind = `Internal + let size = 117 + end) + end + +let test_action_bindings kf ki pre post fmt = + Format.fprintf fmt "All known action bindings@\n"; + Actions.iter + (fun (kf',ki',pre',post' as key) m -> + if Kernel_function.equal kf kf' && Cil_datatype.Kinstr.equal ki ki' && + Aorai_state.equal pre pre' && + Aorai_state.equal post post' + then begin + Format.fprintf fmt "Found an equal key(%B)!" + (Actions_key.equal (kf,ki,pre,post) key); + try ignore (Actions.find key) with Not_found -> + Format.fprintf fmt "Key itself has no binding!@\n"; + end; + Format.fprintf fmt + "@[<2>%a (statement %a), from state %s to state %s" + Kernel_function.pretty kf' Cil_datatype.Kinstr.pretty ki' + pre'.name post'.name; + Cil_datatype.Term.Map.iter + (fun l _ -> Format.fprintf fmt "@\nfound binding for %a" + Cil_datatype.Term.pretty l) m; + Format.fprintf fmt "@]@\n") + +let get_action_bindings kf ki pre post = + try Actions.find (kf, ki, pre, post) + with Not_found -> Cil_datatype.Term.Map.empty +let set_action_bindings kf ki pre post vals = + Actions.replace (kf,ki,pre,post) vals +let all_action_bindings () = + Actions.fold (fun k v l -> (k,v) :: l) [] + +let get_action_path kf ki pre post = + Aorai_option.debug "Getting actions@\n"; + try + let actions = Actions.find (kf,ki,pre,post) in + Aorai_option.debug "Actions have been found@\n"; + Cil_datatype.Term.Map.fold + (fun v map acc -> + let assoc = + Cil_datatype.Term.Map.fold + (fun x r acc -> + Aorai_option.debug ~dkey:"action" "found binding for %a" + Cil_datatype.Term.pretty v; + (x,r) :: acc) + map [] + in (v,assoc) :: acc) + actions [] + with Not_found -> + Aorai_option.debug ~dkey:"action" + "Nothing to do for %a (statement %a), from state %s to state %s@\n%t" + Kernel_function.pretty kf Cil_datatype.Kinstr.pretty ki + pre.name post.name (test_action_bindings kf ki pre post); + [] + +let get_action_path_binding kf ki pre post loc base = + let actions = Actions.find (kf,ki,pre,post) in + let bindings = Cil_datatype.Term.Map.find loc actions in + Cil_datatype.Term.Map.find base bindings + +(* If we have a bound for the number of iteration, the counter cannot grow + more than 1 + bound (we go to a rejection state otherwise). +*) +let absolute_range loc min = + let max = find_max_value loc in + match max with + | Some { term_node = TConst(CInt64 (t,_,_)) } -> + Interval(min,My_bigint.to_int t + 1) + | Some x -> + Bounded + (min, + Logic_const.term + (TBinOp(PlusA,x,Logic_const.tinteger ~ikind:IInt 1)) Linteger) + | None -> Unbounded min + +let merge_range loc base r1 r2 = + match r1,r2 with + | Fixed c1, Fixed c2 when Datatype.Int.compare c1 c2 = 0 -> r1 + | Fixed c1, Fixed c2 -> + let min, max = + if Datatype.Int.compare c1 c2 <= 0 then c1,c2 else c2,c1 in + Interval (min,max) + | Fixed c1, Interval(min,max) -> + let min = if Datatype.Int.compare c1 min <= 0 then c1 else min in + let max = if Datatype.Int.compare max c1 <= 0 then c1 else max in + Interval (min,max) + | Fixed c1, Bounded(min,_) -> + let min = if Datatype.Int.compare c1 min <= 0 then c1 else min in + Unbounded min + | Fixed c1, Unbounded min -> + let min = if Datatype.Int.compare c1 min <= 0 then c1 else min in + Unbounded min + | Interval(min,max), Fixed c -> + if Datatype.Int.compare c min < 0 || Datatype.Int.compare c max > 0 then + begin + let min = if Datatype.Int.compare c min < 0 then c else min in + if Cil.isLogicZero base then + absolute_range loc min + else Unbounded min + end else r1 + | Interval(min1,max1), Interval(min2,max2) -> + if Datatype.Int.compare min2 min1 < 0 + || Datatype.Int.compare max2 max1 > 0 then + begin + let min = + if Datatype.Int.compare min2 min1 < 0 then min2 else min1 + in + if Cil.isLogicZero base then + absolute_range loc min + else Unbounded min + end else r1 + | Interval(min1,_), (Bounded(min2,_) | Unbounded min2)-> + let min = if Datatype.Int.compare min1 min2 <= 0 then min1 else min2 in + Unbounded min + | Bounded(min1,max1), Bounded(min2,max2) + when Cil_datatype.Term.equal max1 max2 -> + let min = + if Datatype.Int.compare min2 min1 < 0 then min2 else min1 + in + Bounded(min,max1) + | Bounded(min1,_), + (Fixed min2 | Interval(min2,_) | Bounded (min2,_) | Unbounded min2) -> + let min = + if Datatype.Int.compare min2 min1 < 0 then min2 else min1 + in Unbounded min + | Unbounded min1, + (Fixed min2 | Interval(min2,_) | Bounded (min2,_) | Unbounded min2) -> + let min = + if Datatype.Int.compare min2 min1 < 0 then min2 else min1 + in Unbounded min + +let merge_action_bindings kf ki pre post vals = + let actions = + try + let my_vals = Actions.find (kf,ki,pre,post) in + let merge_range loc base r1 r2 = + match r1,r2 with + | None, None -> None + | Some r, None | None, Some r -> Some r + | Some r1, Some r2 -> Some (merge_range loc base r1 r2) + in + let merge_bindings loc b1 b2 = + match b1, b2 with + | None, None -> None + | Some b, None | None, Some b -> Some b + | Some b1, Some b2 -> + let b = + Cil_datatype.Term.Map.merge (merge_range loc) b1 b2 in + Some b + in + Cil_datatype.Term.Map.merge merge_bindings my_vals vals + with Not_found -> vals + in + Aorai_option.debug ~dkey:"action" + "Merging actions of %a (statement %a), from state %s to state %s" + Kernel_function.pretty kf Cil_datatype.Kinstr.pretty ki + pre.name post.name; + Cil_datatype.Term.Map.iter + (fun l _ -> Aorai_option.debug ~dkey:"action" + "Got binding for %a" Cil_datatype.Term.pretty l) + actions; + Actions.replace (kf,ki,pre,post) actions + +let add_action_path kf ki pre post v (b,r1) = + let actions = + try Actions.find (kf, ki, pre, post) + with Not_found -> Cil_datatype.Term.Map.empty + in + let bindings = + try Cil_datatype.Term.Map.find v actions + with Not_found -> Cil_datatype.Term.Map.empty + in + let range = + try + let r2 = Cil_datatype.Term.Map.find b bindings in + merge_range v b r2 r1 + with Not_found -> r1 + in + let bindings = Cil_datatype.Term.Map.add b range bindings in + let actions = Cil_datatype.Term.Map.add v bindings actions in + Actions.replace (kf, ki, pre, post) actions + +let remove_action_path kf ki pre post = + Aorai_option.debug ~dkey:"action" + "Removing action of %a (statement %a), from state %s to state %s" + Kernel_function.pretty kf Cil_datatype.Kinstr.pretty ki + pre.name post.name; + Actions.remove (kf,ki,pre,post) +let clear_actions = Actions.clear (* Private data, for memorization of current specification of each function *) let pre_call_status = Hashtbl.create 97 (* (String cur_op * int StmtId) -> bool array * bool array *) @@ -419,7 +1952,8 @@ (** Sets the specification of the call stmt in the given C function at the given StmtId. *) let set_func_pre_call_bycase caller sid status = - Hashtbl.replace pre_call_status (caller,sid) (Spec_tools.pre_flattening status) + Hashtbl.replace pre_call_status (caller,sid) + (Spec_tools.pre_flattening status) @@ -443,28 +1977,25 @@ (* Returns the pre condition associated to the given C function *) -let get_loop_ext_pre stmt_ref = try Hashtbl.find loop_ext_pre stmt_ref with _ -> mk_full_pre_or_post() -let get_loop_int_pre stmt_ref = try Hashtbl.find loop_int_pre stmt_ref with _ -> mk_full_pre_or_post() +let get_loop_ext_pre stmt = + try Hashtbl.find loop_ext_pre stmt with _ -> mk_full_pre_or_post() +let get_loop_int_pre stmt = + try Hashtbl.find loop_int_pre stmt with _ -> mk_full_pre_or_post() (* Sets the external or the block pre condition of the given loop *) -let set_loop_ext_pre stmt_ref pre = Hashtbl.replace loop_ext_pre stmt_ref pre -let set_loop_int_pre stmt_ref pre = Hashtbl.replace loop_int_pre stmt_ref pre +let set_loop_ext_pre stmt pre = Hashtbl.replace loop_ext_pre stmt pre +let set_loop_int_pre stmt pre = Hashtbl.replace loop_int_pre stmt pre (* Returns the post condition associated to the given C function *) -let get_loop_ext_post stmt_ref = try Hashtbl.find loop_ext_post stmt_ref with _ -> mk_full_pre_or_post() -let get_loop_int_post stmt_ref = try Hashtbl.find loop_int_post stmt_ref with _ -> mk_full_pre_or_post() +let get_loop_ext_post stmt = + try Hashtbl.find loop_ext_post stmt with _ -> mk_full_pre_or_post() +let get_loop_int_post stmt = + try Hashtbl.find loop_int_post stmt with _ -> mk_full_pre_or_post() (* Sets the external or the block post condition of the given loop *) -let set_loop_ext_post stmt_ref post = Hashtbl.replace loop_ext_post stmt_ref post -let set_loop_int_post stmt_ref post = Hashtbl.replace loop_int_post stmt_ref post - - - - - - - +let set_loop_ext_post stmt post = Hashtbl.replace loop_ext_post stmt post +let set_loop_int_post stmt post = Hashtbl.replace loop_int_post stmt post (* Private data, for memorization of current specification of each loop *) let loop_ext_pre_bycase = Hashtbl.create 97 @@ -474,36 +2005,45 @@ (* Returns the pre condition associated to the given C function *) -let get_loop_ext_pre_bycase stmt_ref = try Hashtbl.find loop_ext_pre_bycase stmt_ref with _ -> mk_full_pre_or_post_bycase() -let get_loop_int_pre_bycase stmt_ref = try Hashtbl.find loop_int_pre_bycase stmt_ref with _ -> mk_full_pre_or_post_bycase() +let get_loop_ext_pre_bycase stmt = + try Hashtbl.find loop_ext_pre_bycase stmt + with _ -> mk_full_pre_or_post_bycase() + +let get_loop_int_pre_bycase stmt = + try Hashtbl.find loop_int_pre_bycase stmt + with _ -> mk_full_pre_or_post_bycase() (* Sets the external or the block pre condition of the given loop *) -let set_loop_ext_pre_bycase stmt_ref pre = Hashtbl.replace loop_ext_pre_bycase stmt_ref pre -let set_loop_int_pre_bycase stmt_ref pre = Hashtbl.replace loop_int_pre_bycase stmt_ref pre +let set_loop_ext_pre_bycase stmt pre = + Hashtbl.replace loop_ext_pre_bycase stmt pre +let set_loop_int_pre_bycase stmt pre = + Hashtbl.replace loop_int_pre_bycase stmt pre (* Returns the post condition associated to the given C function *) -let get_loop_ext_post_bycase stmt_r = try Hashtbl.find loop_ext_post_bycase stmt_r with _ -> mk_full_pre_or_post_bycase() -let get_loop_int_post_bycase stmt_r = try Hashtbl.find loop_int_post_bycase stmt_r with _ -> mk_full_pre_or_post_bycase() +let get_loop_ext_post_bycase stmt = + try Hashtbl.find loop_ext_post_bycase stmt + with _ -> mk_full_pre_or_post_bycase() + +let get_loop_int_post_bycase stmt = + try Hashtbl.find loop_int_post_bycase stmt + with _ -> mk_full_pre_or_post_bycase() (* Sets the external or the block post condition of the given loop *) -let set_loop_ext_post_bycase stmt_ref post = Hashtbl.replace loop_ext_post_bycase stmt_ref post -let set_loop_int_post_bycase stmt_ref post = Hashtbl.replace loop_int_post_bycase stmt_ref post +let set_loop_ext_post_bycase stmt post = + Hashtbl.replace loop_ext_post_bycase stmt post +let set_loop_int_post_bycase stmt post = + Hashtbl.replace loop_int_post_bycase stmt post -(** Returns a stmt_ref list. It is the set of all registered loop in loop_specs hashtables *) +(** Returns a stmt list. It is the set of all + registered loop in loop_specs hashtables *) let get_loops_index () = Hashtbl.fold (fun key _ lk-> key::lk ) loop_int_pre_bycase [] - - - - - (* ************************************************************************* *) - let removeUnusedTransitionsAndStates () = -(* Step 1 : computation of reached states and crossed transitions *) + (* Step 1 : computation of reached states and crossed transitions *) let crossedTransitions = ref (Array.make(getNumberOfTransitions()) false) in let reachedStates = ref (Array.make(getNumberOfStates()) false) in let addHash htbl = @@ -562,92 +2102,107 @@ Format.printf "\n\n" ;*) (* Step 2 : computation of translation tables *) - let newNbTrans = Array.fold_left (fun nb tr -> if tr then nb+1 else nb ) 0 !crossedTransitions in - let newNbStates = Array.fold_left (fun nb st -> if st then nb+1 else nb ) 0 !reachedStates in - - let replaceTransitions = ref (Array.make(getNumberOfTransitions()) 0) in - let replaceStates = ref (Array.make(getNumberOfStates()) 0) in + let newNbTrans = Array.fold_left + (fun nb tr -> if tr then nb+1 else nb ) 0 !crossedTransitions in + let newNbStates = + Array.fold_left (fun nb st -> if st then nb+1 else nb ) 0 !reachedStates + in + let replaceTransitions = Array.make(getNumberOfTransitions()) 0 in + let replaceStates = Array.make(getNumberOfStates()) 0 in let nextTr = ref 0 in let nextSt = ref 0 in Array.iteri (fun i _ -> if !crossedTransitions.(i) then begin - !replaceTransitions.(i) <- !nextTr; + replaceTransitions.(i) <- !nextTr; nextTr:=!nextTr+1 end else - !replaceTransitions.(i) <- (-1) + replaceTransitions.(i) <- (-1) ) - !replaceTransitions; + replaceTransitions; Array.iteri (fun i _ -> if !reachedStates.(i) then begin - !replaceStates.(i) <- !nextSt; + replaceStates.(i) <- !nextSt; nextSt:=!nextSt+1 end else - !replaceStates.(i) <- (-1) + replaceStates.(i) <- (-1) ) - !replaceStates ; + replaceStates ; (* DEBUG : Displaying information *) -(* Format.printf "\n\n New nb trans :%d \n New nb states :%d \n" newNbTrans newNbStates; *) -(* Format.printf "\n\n Transitions replacement:\n"; *) -(* Array.iteri *) -(* (fun i v -> *) -(* Format.printf " tr%s ~> tr%s\n" (string_of_int i) (string_of_int v) *) -(* ) *) -(* !replaceTransitions; *) -(* Format.printf "\n\n States replacement:\n"; *) -(* Array.iteri *) -(* (fun i v -> *) -(* Format.printf " st%s ~> st%s\n" (string_of_int i) (string_of_int v) *) -(* ) *) -(* !replaceStates; *) -(* Format.printf "\n\n"; *) - - -(* Step 3 : rewritting stored information *) - (* Rewritting automata and parametrized conditions *) - let sts = List.rev (List.fold_left - (fun newl st -> - let newn= !replaceStates.(st.nums) in - if newn= -1 then newl - else begin st.nums<-newn;st::newl end - ) [] (fst !automata)) - in - let trs = List.rev (List.fold_left - (fun newl tr -> - let newn= !replaceTransitions.(tr.numt) in - if newn= -1 then newl - else begin tr.numt<-newn;tr::newl end - ) - [] (snd !automata)) in - let cds = ref (Array.make (newNbTrans) []) in - List.iter - (fun tr -> - let newn= !replaceTransitions.(tr.numt) in - if newn= -1 then () - else !cds.(newn) <- !cond_of_parametrizedTransitions.(tr.numt) - ) - (snd !automata); - - automata:=(sts,trs); - cond_of_parametrizedTransitions := !cds; - - (* Rewritting size of automata cached in Spec_tools *) + (* Format.printf "\n\n New nb trans :%d \n New nb states :%d \n" newNbTrans newNbStates; *) + (* Format.printf "\n\n Transitions replacement:\n"; *) + (* Array.iteri *) + (* (fun i v -> *) + (* Format.printf " tr%s ~> tr%s\n" (string_of_int i) (string_of_int v) *) + (* ) *) + (* replaceTransitions; *) + (* Format.printf "\n\n States replacement:\n"; *) + (* Array.iteri *) + (* (fun i v -> *) + (* Format.printf " st%s ~> st%s\n" (string_of_int i) (string_of_int v) *) + (* ) *) + (* replaceStates; *) + (* Format.printf "\n\n"; *) + + +(* Step 3 : rewriting stored information *) + (* Rewriting automata and parameterized conditions *) + let sts = + List.filter (fun st -> replaceStates.(st.nums) <> -1) (fst !automata) + in + let trs = + List.filter (fun tr -> replaceTransitions.(tr.numt) <> -1) (snd !automata) + in + let cds = Array.make (newNbTrans) [[]] in + (match sts with + [] -> + Aorai_option.abort + "No states left after simplification: the code is not compatible \ + with the automaton"; + | _ -> + (* [VP] we sort the states by their name, giving results that are + more robust wrt internal changes, especially for regression tests. + *) + let sts = + List.sort (fun x1 x2 -> String.compare x1.name x2.name) sts + in + Extlib.iteri + (fun i st -> replaceStates.(st.nums) <- i; st.nums <- i) sts + ); + (* Now, sort transitions according to their start and stop state *) + let trs = + List.sort + (fun tr1 tr2 -> + match Aorai_state.compare tr1.start tr2.start with + | 0 -> Aorai_state.compare tr1.stop tr2.stop + | n -> n) + trs + in + Extlib.iteri + (fun i tr -> + replaceTransitions.(tr.numt) <- i; + cds.(i) <- !cond_of_parametrizedTransitions.(tr.numt); + tr.numt <- i) + trs; + automata:= (sts,trs); + check_states(); + cond_of_parametrizedTransitions := cds; + (* Rewriting size of automata cached in Spec_tools *) setNumberOfStates newNbStates; setNumberOfTransitions newNbTrans; - (* Rewritting pre/post conditions and loops specification *) let rewriteHashtblSpec htbl = Hashtbl.iter (fun key (ost,otr) -> let nst,ntr=mk_empty_pre_or_post () in - Array.iteri (fun i b -> if b then nst.(!replaceStates.(i))<-true) ost; - Array.iteri (fun i b -> if b then ntr.(!replaceTransitions.(i))<-true) otr; + Array.iteri (fun i b -> if b then nst.(replaceStates.(i))<-true) ost; + Array.iteri (fun i b -> if b then ntr.(replaceTransitions.(i))<-true) otr; Hashtbl.replace htbl key (nst,ntr) ) htbl @@ -658,19 +2213,19 @@ let nst,ntr=mk_empty_pre_or_post_bycase () in Array.iteri (fun iniSt sp -> - let newIniSt = !replaceStates.(iniSt) in + let newIniSt = replaceStates.(iniSt) in if newIniSt <> -1 then Array.iteri - (fun i b -> if b then nst.(newIniSt).(!replaceStates.(i))<-true) + (fun i b -> if b then nst.(newIniSt).(replaceStates.(i))<-true) sp ) ost; Array.iteri (fun iniSt sp -> - let newIniSt = !replaceStates.(iniSt) in + let newIniSt = replaceStates.(iniSt) in if newIniSt <> -1 then Array.iteri - (fun i b -> if b then ntr.(newIniSt).(!replaceTransitions.(i))<-true) + (fun i b -> if b then ntr.(newIniSt).(replaceTransitions.(i))<-true) sp ) otr; @@ -702,14 +2257,7 @@ (* Given the name of a function, it return the name of the associated element in the operation list. *) -let func_to_op_func f = - "op_"^f - - - - - - +let func_to_op_func f = "op_"^f let used_enuminfo = Hashtbl.create 2 @@ -720,9 +2268,6 @@ try Hashtbl.find used_enuminfo name with _ -> raise_error ("Incomplete enum information.") - - - let get_cenum_option name = let opnamed = func_to_op_func name in Hashtbl.fold @@ -741,8 +2286,8 @@ used_enuminfo None - - +let func_enum_type () = TEnum(Hashtbl.find used_enuminfo listOp,[]) +let status_enum_type () = TEnum(Hashtbl.find used_enuminfo listStatus,[]) let func_to_cenum func = try @@ -751,7 +2296,8 @@ let rec search = function | {einame = n} as ei ::_ when n=name -> CEnum ei | _::l -> search l - | [] -> raise_error ("Operation '"^name^"' not found in operations enumeration") + | [] -> raise_error + ("Operation '"^name^"' not found in operations enumeration") in search ei.eitems (* CEnum(ex,s,ei)*) @@ -827,14 +2373,6 @@ try (Hashtbl.find local_iter_vars func_name).vname with Not_found -> raise_error "This function seems to not have iter var" - - - - - - - - (* Local Variables: compile-command: "LC_ALL=C make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/data_for_aorai.mli frama-c-20111001+nitrogen+dfsg/src/aorai/data_for_aorai.mli --- frama-c-20110201+carbon+dfsg/src/aorai/data_for_aorai.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/data_for_aorai.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,9 +23,11 @@ (* *) (**************************************************************************) -(* $Id: data_for_ltl.mli,v 1.5 2008-12-17 17:06:27 uid588 Exp $ *) +open Promelaast -(** Module of data management used in all the plugin Aorai. Operations are mainly accessors for data. The use of this module is mainly done through the ltl_utils module. *) +(** Module of data management used in all the plugin Aorai. Operations + are mainly accessors for data. The use of this module is mainly done + through the ltl_utils module. *) (* ************************************************************************* *) (** {2 LTL/Promela primitives} *) @@ -31,46 +35,67 @@ (** Here are some operations used for generation of LTL AST or Promela AST. *) +module Aorai_state: Datatype.S_with_collections with type t = Promelaast.state (** Initializes some tables according to data from Cil AST. *) val setCData : unit -> unit (** *) -val setLtl_expressions : (string, (Cil_types.exp* string*Cil_types.predicate)) Hashtbl.t -> unit +val add_logic : string -> Cil_types.logic_info -> unit (** *) -val ltl_expressions_iter : (string -> (Cil_types.exp * string*Cil_types.predicate) -> unit) -> unit +val get_logic : string -> Cil_types.logic_info + (** *) -val get_exp_from_tmpident : string -> Cil_types.exp +val add_predicate : string -> Cil_types.logic_info -> unit (** *) -val get_str_exp_from_tmpident : string -> string +val get_predicate : string -> Cil_types.logic_info -val debug_ltl_expressions : unit -> unit +(** Given a logic info representing a set of pebbles and a label, returns + the term corresponding to evaluating the set at the label. +*) +val pebble_set_at: + Cil_types.logic_info -> Cil_types.logic_label -> Cil_types.term +(** Global auxiliary variables generated during type-checking of transitions *) +val aux_variables: unit -> Cil_types.varinfo list -(** *) -val get_pred_from_tmpident : string -> Cil_types.predicate +(** Global logic info generated during type-checking (mostly encoding of + ghost variables having a logic type) +*) +val abstract_logic_info: unit -> Cil_types.logic_info list -(** *) -val add_logic : string -> Cil_types.logic_info -> unit +(** {2 Smart constructors for conditions} *) -(** *) -val get_logic : string -> Cil_types.logic_info +(**/**) +val pand: condition -> condition -> condition +val por: condition -> condition -> condition +val pnot: condition -> condition +val cst_one: expression +val cst_zero: expression -(** *) -val add_predicate : string -> Cil_types.logic_info -> unit +(** {2 Utilities for parsed_conditions } *) +(** [true] iff the expression is 1 *) +val is_cst_one: expression -> bool -(** *) -val get_predicate : string -> Cil_types.logic_info +val is_cst_zero: expression -> bool +(** [true] if the element is not repeating itself ([min_rep = max_rep = 1]) *) +val is_single: seq_elt -> bool (* ************************************************************************* *) (**{b Constants} Some constant names used for generation. *) +(** Returns a string guaranteed not to clash with C/ACSL keywords or an + existing global. + @since Nitrogen-20111001 + *) +val get_fresh: string -> string + (* Logic variables *) (** Name of TransStart logic generated variable *) val transStart : string @@ -155,21 +180,20 @@ (** DEPRECATED ?*) val buch_sync : string - - - - (* ************************************************************************* *) (**{b Buchi automata management}*) -(** Return the buchi automata as stored after parsing *) -val getAutomata : unit -> Promelaast.buchautomata +val new_state: string -> state -(** Stores the buchi automata and its variables and functions as such as it is return by the parsing *) -val setAutomata : Promelaast.buchautomata -> (string, string) Hashtbl.t -> (string, string) Hashtbl.t -> unit +val new_trans: state -> state -> 'a -> 'a trans -val setCondOfParametrizedTransition : Promelaast.condition list list array -> unit -val getParametrizedCondOfTransition : int -> Promelaast.condition list list +(** Return the buchi automata as stored after parsing *) +val getAutomata : unit -> Promelaast.typed_automaton + +(** Type-checks the parsed automaton and stores the result. + This might introduce new global variables in case of sequences. +*) +val setAutomata: Promelaast.parsed_automaton -> unit (** return the number of transitions of the automata *) val getNumberOfTransitions : unit -> int @@ -177,13 +201,6 @@ (** return the number of states of the automata *) val getNumberOfStates : unit -> int - -(** Return the list of all function name observed in the promela file. *) -val getFunctions_from_auto : unit -> string list - -(** Return the list of all variables name observed in the promela file. *) -val getVariables_from_auto : unit -> string list - (** Return the list of all function name observed in the C file. *) val getFunctions_from_c : unit -> string list @@ -199,14 +216,21 @@ (** Return true if and only if the given string fname denotes an ignored function. *) val isIgnoredFunction : string -> bool -(** Manage particular consistency verification between C file and promela specification. - It returns true if and only if these checks are ok. *) -val check_consistency : unit -> bool +(** returns the state of given index. + @since Nitrogen-20111001 +*) +val getState: int -> Promelaast.state val getStateName : int -> string +(** returns the transition having the corresponding id. + @raise Not_found if this is not the case. +*) +val getTransition: + int -> (Promelaast.typed_condition * Promelaast.action) Promelaast.trans + (* ************************************************************************* *) -(**{b Variables information} Usually it seems very usefull to access to varinfo +(**{b Variables information} Usually it seems very useful to access to varinfo structure of a variable by using only its name. These functions allow that. In practice it contains all variables (from promela and globals from C file) and only variables. *) @@ -222,21 +246,24 @@ Hence, if the variable is not found then None is return. *) val get_varinfo_option : string -> Cil_types.varinfo option - +(** get the logic variable corresponding to its C counterpart. + @since Nitrogen-20111001 +*) +val get_logic_var: string -> Cil_types.logic_var (** Add a new param into the association table (funcname,paramname) -> varinfo *) val set_paraminfo : string -> string -> Cil_types.varinfo -> unit (** Given a function name and a param name, it returns the varinfo associated to the given param. If the variable is not found then an error message is print and an assert false is raised. *) -val get_paraminfo : string -> string -> Cil_types.varinfo +val get_paraminfo : string -> string -> Cil_types.varinfo (** Add a new param into the association table (funcname,paramname) -> varinfo *) val set_returninfo : string -> Cil_types.varinfo -> unit (** Given a function name and a param name, it returns the varinfo associated to the given param. If the variable is not found then an error message is print and an assert false is raised. *) -val get_returninfo : string -> Cil_types.varinfo +val get_returninfo : string -> Cil_types.varinfo (* ************************************************************************* *) @@ -265,6 +292,99 @@ (** Sets the pre condition of the given C function *) val set_func_post_bycase : string -> (bool array array)*(bool array array) -> unit +(** Given the representation of an auxiliary counter + (found in a {!Promelaast.Counter_incr}), returns the maximal value + that it can take according to the automaton. + *) +val find_max_value: Cil_types.term -> Cil_types.term option + +(** information we have about the range of values that an auxiliary variable + can take. + *) +type range = + | Fixed of int (** constant value *) + | Interval of int * int (** range of values *) + | Bounded of int * Cil_types.term + (** range bounded by a logic term (depending on program parameter). *) + | Unbounded of int (** only the lower bound is known, + there is no upper bound *) + +module Range: Datatype.S_with_collections with type t = range + +module Intervals: Datatype.S with type t = range Cil_datatype.Term.Map.t + +module Vals: Datatype.S with type t = Intervals.t Cil_datatype.Term.Map.t + +(** [get_action_path kf ki pre post] returns the possible values of the + auxiliary variables that may have changed in a call of [kf] starting in [pre] + at stmt [ki] in state [post]. +*) +val get_action_bindings: + Cil_types.kernel_function -> + Cil_types.kinstr -> Promelaast.state -> Promelaast.state -> Vals.t + +val all_action_bindings: + unit -> + ((Cil_types.kernel_function * Cil_types.kinstr * + Promelaast.state * Promelaast.state) * Vals.t) list + +(** sets the possible values of auxiliary variables at a given stmt. If + there was a previous map, it is erased. + *) +val set_action_bindings: + Cil_types.kernel_function -> Cil_types.kinstr -> + Promelaast.state -> Promelaast.state -> Vals.t -> unit + +(** Given a term and a minimal value, returns the absolute range of variation + of the corresponding auxiliary variable, depending on its usage in the + instrumentation of the code. +*) +val absolute_range: Cil_types.term -> int -> Range.t + +(** Given an auxiliary variable, a base for its variations and two ranges of + variations, returns a range that encompasses both. + *) +val merge_range: + Cil_types.term -> Cil_types.term -> Range.t -> Range.t -> Range.t + +(** sets the possible values of auxiliary variables at a given stmt. If + there was a previous map, the content of both maps is merged. + *) +val merge_action_bindings: + Cil_types.kernel_function -> Cil_types.kinstr -> + Promelaast.state -> Promelaast.state -> Vals.t -> unit + +(** [get_action_path kf ki pre post] returns the possible values of the + auxiliary variables that may have changed in a call of [kf] starting in [pre] + at stmt [ki] in state [post]. Values are of the form [base, min, max], + stating that the location has a value between [base+min] and [base+max]. + For counters that are initialized during the call, [base] is [0]. +*) +val get_action_path: + Cil_types.kernel_function -> + Cil_types.kinstr -> Promelaast.state -> Promelaast.state -> + (Cil_types.term * (Cil_types.term * range) list) list + +(** gets a specific binding or raise Not_found if no such binding exist. *) +val get_action_path_binding: + Cil_types.kernel_function -> + Cil_types.kinstr -> Promelaast.state -> Promelaast.state -> + Cil_types.term -> Cil_types.term -> range + +(** Adds a new possible value for the given auxiliary variable in the given + "execution path" + *) +val add_action_path: + Cil_types.kernel_function -> Cil_types.kinstr -> + Promelaast.state -> Promelaast.state -> + Cil_types.term -> (Cil_types.term * range) -> unit + +(** Removes an unreachable path. *) +val remove_action_path: + Cil_types.kernel_function -> Cil_types.kinstr -> + Promelaast.state -> Promelaast.state -> unit + +val clear_actions: unit -> unit (** Gives the specification of the call stmt in the given C function at the given StmtId. *) val get_func_pre_call : string -> int -> (bool array)*(bool array) @@ -289,64 +409,62 @@ is for the crossable conditions. *) (** Returns the pre condition associated to the given C function *) -val get_loop_ext_pre : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) +val get_loop_ext_pre : Cil_types.stmt -> (bool array)*(bool array) (** Returns the pre condition associated to the given C function *) -val get_loop_int_pre : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) +val get_loop_int_pre : Cil_types.stmt -> (bool array)*(bool array) (** Sets the external or the block pre condition of the given loop *) -val set_loop_ext_pre : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) -> unit +val set_loop_ext_pre : Cil_types.stmt -> (bool array)*(bool array) -> unit (** Sets the external or the block pre condition of the given loop *) -val set_loop_int_pre : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) -> unit - +val set_loop_int_pre : Cil_types.stmt -> (bool array)*(bool array) -> unit (** Returns the post condition associated to the given C function *) -val get_loop_ext_post : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) +val get_loop_ext_post : Cil_types.stmt -> (bool array)*(bool array) (** Returns the post condition associated to the given C function *) -val get_loop_int_post : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) +val get_loop_int_post : Cil_types.stmt -> (bool array)*(bool array) (** Sets the external or the block post condition of the given loop *) -val set_loop_ext_post : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) -> unit +val set_loop_ext_post : Cil_types.stmt -> (bool array)*(bool array) -> unit (** Sets the external or the block post condition of the given loop *) -val set_loop_int_post : Cil_types.stmt Pervasives.ref -> (bool array)*(bool array) -> unit - - +val set_loop_int_post : Cil_types.stmt -> (bool array)*(bool array) -> unit (** Returns the pre condition associated to the given C function *) -val get_loop_ext_pre_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) +val get_loop_ext_pre_bycase : Cil_types.stmt -> (bool array array)*(bool array array) (** Returns the pre condition associated to the given C function *) -val get_loop_int_pre_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) - +val get_loop_int_pre_bycase : Cil_types.stmt -> (bool array array)*(bool array array) (** Sets the external or the block pre condition of the given loop *) -val set_loop_ext_pre_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) -> unit +val set_loop_ext_pre_bycase : + Cil_types.stmt -> (bool array array)*(bool array array) -> unit (** Sets the external or the block pre condition of the given loop *) -val set_loop_int_pre_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) -> unit - - -(** Returns the post condition associated to the given C function *) -val get_loop_ext_post_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) - -(** Returns the post condition associated to the given C function *) -val get_loop_int_post_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) +val set_loop_int_pre_bycase : + Cil_types.stmt -> (bool array array)*(bool array array) -> unit +(** Returns the external post-condition of the given loop *) +val get_loop_ext_post_bycase : + Cil_types.stmt -> (bool array array)*(bool array array) + +(** Returns the block post condition of the given loop *) +val get_loop_int_post_bycase : + Cil_types.stmt -> (bool array array)*(bool array array) (** Sets the external or the block post condition of the given loop *) -val set_loop_ext_post_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) -> unit +val set_loop_ext_post_bycase : + Cil_types.stmt -> (bool array array)*(bool array array) -> unit (** Sets the external or the block post condition of the given loop *) -val set_loop_int_post_bycase : Cil_types.stmt Pervasives.ref -> (bool array array)*(bool array array) -> unit - - - -(** Returns a stmt_ref list. It is the set of all registered loop in loop_specs hashtables *) -val get_loops_index : unit -> Cil_types.stmt Pervasives.ref list +val set_loop_int_post_bycase : + Cil_types.stmt -> (bool array array)*(bool array array) -> unit +(** Returns a stmt list. It is the set of all registered + loops in loop_specs hashtables *) +val get_loops_index : unit -> Cil_types.stmt list (* ************************************************************************* *) (**{b Enumeration management}*) @@ -355,7 +473,12 @@ This function is not efficient. Thus if the enumeration is known it is recommended to use one of the following functions.*) val get_cenum_option : string -> Cil_types.constant option -(** Given the name of a C operation, this function returns the associated cenum structure. *) +val func_enum_type: unit -> Cil_types.typ + +val status_enum_type: unit -> Cil_types.typ + +(** Given the name of a C operation, this function returns the + associated cenum structure. *) val func_to_cenum : string -> Cil_types.constant (** Given the name of a C operation status (Call or Return), this function returns the associated cenum structure. *) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/logic_simplification.ml frama-c-20111001+nitrogen+dfsg/src/aorai/logic_simplification.ml --- frama-c-20110201+carbon+dfsg/src/aorai/logic_simplification.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/logic_simplification.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,9 +23,18 @@ (* *) (**************************************************************************) +open Cil_types open Promelaast open Bool3 +let pretty_clause fmt l = + Format.fprintf fmt "@[<2>[%a@]]@\n" + (Pretty_utils.pp_list ~sep:",@ " Promelaoutput.print_condition) l + +let pretty_dnf fmt l = + Format.fprintf fmt "@[<2>[%a@]]@\n" + (Pretty_utils.pp_list pretty_clause) l + let rec condToDNF cond = (*Typage : condition --> liste de liste de termes (disjonction de conjonction de termes) DNF(terme) = {{terme}} @@ -34,420 +45,225 @@ negation de chaque terme *) match cond with - | POr (c1, c2) -> (condToDNF c1)@(condToDNF c2) - | PAnd (c1, c2) -> + | TOr (c1, c2) -> (condToDNF c1)@(condToDNF c2) + | TAnd (c1, c2) -> let d1,d2=(condToDNF c1), (condToDNF c2) in List.fold_left (fun lclause clauses2 -> - (List.map - (fun clauses1 -> - clauses1@clauses2 - ) - d1)@lclause - ) + (List.map (fun clauses1 -> clauses1@clauses2) d1) @ lclause + ) [] d2 - | PNot (c) -> + | TNot (c) -> begin match c with - | POr (c1, c2) -> condToDNF (PAnd(PNot(c1),PNot(c2))) - | PAnd (c1, c2) -> condToDNF (POr (PNot(c1),PNot(c2))) - | PNot (c1) -> condToDNF c1 - | _ as t -> [[PNot(t)]] + | TOr (c1, c2) -> condToDNF (TAnd(TNot(c1),TNot(c2))) + | TAnd (c1, c2) -> condToDNF (TOr (TNot(c1),TNot(c2))) + | TNot (c1) -> condToDNF c1 + | _ as t -> [[TNot(t)]] end - | _ as t -> [[t]] - - - - let removeTerm term lterm = - List.fold_left + List.fold_left (fun treated t -> match term,t with - | PCall (s1),PCall (s2) - | PReturn (s1),PReturn (s2) - | PCallOrReturn (s1),PCallOrReturn (s2) when (String.compare s1 s2)=0 -> treated - | _ as o -> (snd o)::treated - ) + | TCall (kf1,None), TCall (kf2,_) + | TReturn kf1, TReturn kf2 + when Kernel_function.equal kf1 kf2 -> treated + | TCall(kf1,Some b1), TCall(kf2, Some b2) + when Kernel_function.equal kf1 kf2 && + Datatype.String.equal b1.b_name b2.b_name -> treated + | _ -> t::treated) [] lterm - -(** Given a list of terms, if a positive call or return is present, then all negative ones are obvious and removed *) -let positiveCallOrRet clause = - let positive = ref None in - let isFalse = ref false in - let computePositive= - List.fold_left - (fun treated term -> - match term with - | PFuncParam (_,s,_) as t -> - begin match !positive with - | None -> - positive:= Some(t) ; - t::treated - - | Some(PFuncParam (_,a,_)) -> - if (String.compare a s)<>0 then isFalse:=true; - treated - - | Some(PReturn (_)) - | Some(PFuncReturn (_,_)) -> - isFalse:=true; - [] - - | Some(PCallOrReturn (a)) -> - if (String.compare a s)<>0 then isFalse:=true; - (* More specific information found in t *) - positive:= Some(t) ; - t::(removeTerm (PCallOrReturn (a)) treated) - - | Some(PCall (a)) -> - if (String.compare a s)<>0 then isFalse:=true; - (* More specific information found in t *) - positive:= Some(t) ; - t::(removeTerm (PCall (a)) treated) - - | _ -> assert false (* This Variable has to contain only positive call, - ret or call/ret conditions *) - end - - - | PCall(s) as t-> - begin match !positive with - | None -> - positive:= Some(t) ; - t::treated - - | Some(PCall (a)) - | Some(PFuncParam (_,a,_)) -> - if (String.compare a s)<>0 then isFalse:=true; - treated - - | Some(PReturn (_)) - | Some(PFuncReturn (_,_)) -> - isFalse:=true; - [] - - | Some(PCallOrReturn (a)) -> - if (String.compare a s)<>0 then isFalse:=true; - positive:= Some(t) ; - t::(removeTerm (PCallOrReturn (a)) treated) - - | _ -> assert false (* This Variable has to contain only positive call, - ret or call/ret conditions *) - end - - - - - | PFuncReturn (_,s) as t -> - begin match !positive with - | None -> - positive:= Some(t) ; - t::treated - - | Some(PFuncReturn (_,a)) -> - if (String.compare a s)<>0 then isFalse:=true; - treated - - | Some(PCall (_)) - | Some(PFuncParam (_,_,_)) -> - isFalse:=true; - [] - - | Some(PReturn (a)) -> - (* Two positives on two different functions *) - if (String.compare a s)<>0 then isFalse:=true; - (* More specific information *) - positive:= Some(t) ; - t::(removeTerm (PReturn (a)) treated) - - - | Some(PCallOrReturn (a)) -> - (* Two positives on two different functions *) - if (String.compare a s)<>0 then isFalse:=true; - (* More specific information *) - positive:= Some(t) ; - t::(removeTerm (PCallOrReturn (a)) treated) - - | _ -> assert false (* This Variable has to contain only positive call, - ret or call/ret conditions *) - end - - | PReturn (s) as t -> - begin match !positive with - | None -> - positive:= Some(t) ; - t::treated - - | Some(PReturn (a)) - | Some(PFuncReturn (_,a)) -> - if (String.compare a s)<>0 then isFalse:=true; - treated - - | Some(PCall (_)) - | Some(PFuncParam (_,_,_)) -> - isFalse:=true; - [] - - | Some(PCallOrReturn (a)) -> - (* Two positives on two different functions *) - if (String.compare a s)<>0 then isFalse:=true; - (* More specific information *) - positive:= Some(t) ; - t::(removeTerm (PCallOrReturn (a)) treated) - - | _ -> assert false (* This Variable has to contain only positive call, - ret or call/ret conditions *) - end - - - | PCallOrReturn(s) as t -> - begin match !positive with - | None -> - positive:= Some(t) ; - t::treated - - | Some(PReturn (a)) - | Some(PFuncReturn (_,a)) - | Some(PCall (a)) - | Some(PFuncParam (_,a,_)) - | Some(PCallOrReturn (a)) -> - (* Two positives on two different functions *) - if (String.compare a s)<>0 then isFalse:=true; - (* More specific information already present *) - treated - - | _ -> assert false (* This Variable has to contain only positive call, - ret or call/ret conditions *) - end - - - - | _ as t -> t::treated - ) - [] - clause - in - (* Step 2 : Remove negatives not enough expressive *) - if !isFalse then - [] - else - let res = - match !positive with - | None -> computePositive - | Some(PCall(name)) - | Some(PFuncParam(_,name,_)) -> - List.fold_left - (fun treated term -> - match term with - | PNot(PCall (s)) - | PNot(PFuncParam (_,s,_)) - | PNot(PCallOrReturn (s)) -> - (* Two opposite information *) - if (String.compare name s)=0 then isFalse:=true; - (* Positive information more specific than negative one *) - treated - - | PNot(PReturn (_)) - | PNot(PFuncReturn (_,_)) -> - (* Positive information more specific than negative one *) - treated - - | _ as t -> t::treated - ) - [] - computePositive - - | Some(PReturn (name)) - | Some(PFuncReturn (_,name)) -> - List.fold_left - (fun treated term -> - match term with - | PNot(PCall (_)) - | PNot(PFuncParam (_,_,_)) -> - (* Positive information more specific than negative one *) - treated - - | PNot(PReturn (s)) - | PNot(PCallOrReturn (s)) - | PNot(PFuncReturn (_,s)) -> - (* Two opposite information *) - if (String.compare name s)=0 then isFalse:=true; - (* Positive information more specific than negative one *) - treated - - | _ as t -> t::treated - ) - [] - computePositive - - - | Some(PCallOrReturn (name)) -> - List.fold_left - (fun treated term -> - match term with - | PNot(PCall (s)) - | PNot(PFuncParam (_,s,_)) -> - if (String.compare name s)=0 then - (PReturn(s))::(removeTerm (PCallOrReturn (name)) treated) - else - (* Positive information more specific than negative one *) - treated - - | PNot(PReturn (s)) - | PNot(PFuncReturn (_,s)) -> - if (String.compare name s)=0 then - (PCall(s))::(removeTerm (PCallOrReturn (name)) treated) - else - (* Positive information more specific than negative one *) - treated - - | PNot(PCallOrReturn (s)) -> - (* Two opposite information *) - if (String.compare name s)=0 then isFalse:=true; - (* Positive information more specific than negative one *) - treated - - | _ as t -> t::treated - ) - [] - computePositive - - - - - | _ -> assert false (* This Variable has to contain only positive call, - ret or call/ret conditions *) +(** Given a list of terms (representing a conjunction), + if a positive call or return is present, + then all negative ones are obvious and removed *) +let positiveCallOrRet clause = + try + (* Step 1: find a positive information TCall or TReturn. *) + let positive, computePositive= + List.fold_left + (fun (positive,treated as res) term -> + match term with + | TCall (kf1,None) -> + begin match positive with + | None -> (Some term, term::treated) + | Some (TCall (kf2,None)) -> + if Kernel_function.equal kf1 kf2 then res else raise Exit + | Some (TReturn _) -> raise Exit + | Some(TCall (kf2,Some _) as term2) -> + if Kernel_function.equal kf1 kf2 then + Some term, term :: removeTerm term2 treated + else raise Exit + | _ -> + Aorai_option.fatal + "inconsistent environment in positiveCallOrRet" + end + | TCall (kf1, Some b1) -> + begin match positive with + | None -> (Some term, term::treated) + | Some (TCall (kf2,None)) -> + if Kernel_function.equal kf1 kf2 then res else raise Exit + | Some (TReturn _) -> raise Exit + | Some(TCall (kf2,Some b2)) -> + if Kernel_function.equal kf1 kf2 then + if Datatype.String.equal b1.b_name b2.b_name then + res + else + positive, term :: treated + else raise Exit + | _ -> + Aorai_option.fatal + "inconsistent environment in positiveCallOrRet" + end + | TReturn kf1 -> + begin match positive with + | None -> (Some term, term::treated) + | Some (TReturn kf2) -> + if Kernel_function.equal kf1 kf2 then res else raise Exit + | Some (TCall _) -> raise Exit + | _ -> + Aorai_option.fatal + "inconsistent environment in positiveCallOrRet" + end + | _ -> positive, term::treated + ) + (None, []) + clause in - if !isFalse then - [] - else - res - - + (* Step 2 : Remove negatives not enough expressive *) + match positive with + | None -> computePositive + | Some (TCall (kf1,None)) -> + List.fold_left + (fun treated term -> + match term with + | TNot(TCall (kf2,_)) -> + if Kernel_function.equal kf1 kf2 then raise Exit + (* Positive information more specific than negative *) + else treated + | TNot(TReturn _) -> treated + | _ -> term::treated + ) + [] computePositive + | Some (TCall (kf1, Some b1)) -> + List.fold_left + (fun treated term -> + match term with + | TNot(TCall (kf2,None)) -> + if Kernel_function.equal kf1 kf2 then raise Exit + (* Positive information more specific than negative *) + else treated + | TNot(TCall(kf2, Some b2)) -> + if Kernel_function.equal kf1 kf2 then + if Datatype.String.equal b1.b_name b2.b_name then raise Exit + else term :: treated + else treated + | TNot(TReturn _) -> treated + | _ -> term::treated + ) + [] computePositive + + | Some (TReturn kf1) -> + List.fold_left + (fun treated term -> + match term with + | TNot(TCall _) -> treated + | TNot(TReturn kf2) -> + (* Two opposite information *) + if Kernel_function.equal kf1 kf2 then raise Exit else treated + | _ -> term::treated + ) + [] computePositive + | _ -> + Aorai_option.fatal "inconsistent environment in positiveCallOrRet" + with Exit -> [TFalse] (* contradictory requirements for current event. *) + +let rel_are_equals (rel1,t11,t12) (rel2,t21,t22) = + rel1 = rel2 + && Logic_utils.is_same_term t11 t21 + && Logic_utils.is_same_term t12 t22 + +let opposite_rel = + function + | Rlt -> Rge + | Rgt -> Rle + | Rge -> Rlt + | Rle -> Rgt + | Req -> Rneq + | Rneq -> Req +let contradict_rel (rel1,t11,t12) (rel2,t21,t22) = + rel_are_equals (rel1,t11,t12) (opposite_rel rel2, t21,t22) -(* !!!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* Copy from Data_for_aorai, in order to remove forward reference. *) -let ltl_exps = ref (Hashtbl.create 1) -let setLtl_expressions exps = - ltl_exps:=exps -let get_str_exp_from_tmpident var = +(** Simplify redundant relations. *) +let simplify clause = try - let (_,str,_) = (Hashtbl.find !ltl_exps var) in - str - with - | _ -> - Aorai_option.fatal "Aorai_acsl plugin internal error. Status : TMP Variable (%s) not declared in hashtbl. \n" var;; -(* !!!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* !!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - - - - -let expAreEqual e1 e2 = - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* Ici, pour les tests on lit s1 et s2, mais il faudrait dereferencer comme suit : - PIndexedExp (s) -> Data_for_aorai.get_str_exp_from_tmpident s - Ou bien - PIndexedExp (s) -> Data_for_aorai.get_exp_from_tmpident s - *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) - (* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *) -(* (String.compare e1 e2)=0 *) - let s1,s2 = (get_str_exp_from_tmpident e1),(get_str_exp_from_tmpident e2) in - (String.compare s1 s2)=0 - - - - -(** Given a list of terms, if a positive call or return is present, - then all negative ones are obvious and removed *) -let simplify clause = - let isFalse = ref false in - let result = ref [] in - List.iter - (fun term -> - match term with - | PTrue - | PNot(PFalse) -> () - | PFalse - | PNot(PTrue) -> isFalse:=true - | PIndexedExp(s1) as t -> - if - List.fold_left - (fun toKeep term -> - match term with - | PIndexedExp(s2) -> toKeep && (not (expAreEqual s1 s2)) - | PNot(PIndexedExp(s2)) when (expAreEqual s1 s2) -> isFalse:=true;false - | _ -> toKeep - ) - true - !result - then - result:=t::!result - - | PNot(PIndexedExp(s1)) as t -> - if - List.fold_left - (fun toKeep term -> - match term with - | PNot(PIndexedExp(s2)) -> toKeep && (not (expAreEqual s1 s2)) - | PIndexedExp(s2) when (expAreEqual s1 s2) -> isFalse:=true;false - | _ -> toKeep - ) - true - !result - then - result:=t::!result - - | _ as t -> - result:=t::!result - ) - clause ; - if !isFalse then [] - else if !result=[] then [PTrue] - else !result - - - + List.fold_left + (fun clause term -> + match term with + | TTrue | TNot(TFalse) -> clause + | TFalse | TNot(TTrue) -> raise Exit + | TRel(rel1,t11,t12) -> + if + List.exists + (fun term -> + match term with + | TRel(rel2,t21,t22) + when contradict_rel (rel1,t11,t12) (rel2, t21,t22) -> + raise Exit + | TRel(rel2,t21,t22) -> + rel_are_equals (rel1,t11,t12) (rel2,t21,t22) + | TNot(TRel(rel2,t21,t22)) + when (rel_are_equals (rel1,t11,t12) (rel2,t21,t22)) -> + raise Exit + | TNot(TRel(rel2,t21,t22)) -> + contradict_rel (rel1,t11,t12) (rel2,t21,t22) + | _ -> false) + clause + then clause + else term::clause + | TNot(TRel(rel1,t11,t12)) -> + if + List.exists + (fun term -> + match term with + | TNot(TRel(rel2,t21,t22)) + when contradict_rel (rel1,t11,t12) (rel2, t21,t22) -> + raise Exit + | TNot(TRel(rel2,t21,t22)) -> + rel_are_equals (rel1,t11,t12) (rel2,t21,t22) + | TRel(rel2,t21,t22) + when (rel_are_equals (rel1,t11,t12) (rel2,t21,t22)) -> + raise Exit + | TRel(rel2,t21,t22) -> + contradict_rel (rel1,t11,t12) (rel2,t21,t22) + | _ -> false) + clause + then clause + else term::clause + | _ -> term :: clause) + [] clause + with Exit -> [TFalse] -let rec termsAreEqual term1 term2 = +let rec termsAreEqual term1 term2 = match term1,term2 with - | PTrue,PTrue - | PFalse,PFalse -> true - - | PCall(a),PCall(b) - | PReturn(a),PReturn(b) - | PCallOrReturn(a),PCallOrReturn(b) -> (String.compare a b)=0 - - | PIndexedExp(a),PIndexedExp(b) -> - expAreEqual a b - - - | PNot(a),PNot(b) -> termsAreEqual a b - - | PFuncReturn (h1, f1), PFuncReturn (h2, f2) -> (String.compare f1 f2)=0 && (expAreEqual h1 h2) - | PFuncParam (h1, f1, p1), PFuncParam (h2, f2, p2) -> (String.compare f1 f2)=0 && (expAreEqual h1 h2) && p1=p2 + | TTrue,TTrue + | TFalse,TFalse -> true + | TCall (a,None), TCall (b,None) + | TReturn a, TReturn b -> Kernel_function.equal a b + | TCall (f1,Some b1), TCall(f2, Some b2) -> + Kernel_function.equal f1 f2 && Datatype.String.equal b1.b_name b2.b_name + | TNot(TRel(rel1,t11,t12)), TRel(rel2,t21,t22) + | TRel(rel1,t11,t12), TNot(TRel(rel2,t21,t22)) -> + contradict_rel (rel1,t11,t12) (rel2,t21,t22) + | TNot(a),TNot(b) -> termsAreEqual a b + | TRel(rel1,t11,t12), TRel(rel2,t21,t22) -> + rel_are_equals (rel1,t11,t12) (rel2,t21,t22) | _ -> false - (** true iff clause1 <: clause2*) let clausesAreSubSetEq clause1 clause2 = (List.for_all @@ -457,246 +273,174 @@ (** true iff clause1 <: clause2 and clause2 <: clause1 *) let clausesAreEqual clause1 clause2 = - (List.for_all - (fun t1 ->List.exists ( fun t2 -> termsAreEqual t1 t2) clause2) - clause1) - && - (List.for_all - (fun t1 ->List.exists ( fun t2 -> termsAreEqual t2 t1) clause1) - clause2) + clausesAreSubSetEq clause1 clause2 && clausesAreSubSetEq clause2 clause1 (** return the clauses list named lclauses without any clause c such as cl <: c *) let removeClause lclauses cl = List.filter (fun c -> not (clausesAreSubSetEq cl c)) lclauses - - (* Obvious version. *) let negativeClause clause = - List.map(fun term -> - match term with - | PNot(c) -> c - | PCall(s) -> PNot(PCall(s)) - | PReturn(s) -> PNot(PReturn(s)) - | PCallOrReturn(s) -> PNot(PCallOrReturn(s)) - | PIndexedExp(s) -> PNot(PIndexedExp(s)) - | PTrue -> PFalse - | PFalse -> PTrue - | PFuncReturn (hash, f) -> PNot(PFuncReturn (hash, f)) - | PFuncParam (hash, f, p) -> PNot(PFuncParam (hash, f, p)) - | PAnd (_,_) - | POr (_,_) -> assert false - ) clause + List.map + (fun term -> + match term with + | TNot(c) -> c + | TCall _ | TReturn _ | TRel _ -> TNot term + | TTrue -> TFalse + | TFalse -> TTrue + | TAnd (_,_) + | TOr (_,_) -> Aorai_option.fatal "not a DNF clause" + ) clause +let simplifyClauses clauses = + try + List.fold_left + (fun acc c -> + (* If 2 clauses are C and not C then their disjunction implies true *) + if List.exists (clausesAreEqual (negativeClause c)) acc then + raise Exit + (* If an observed clause c2 is included inside the current clause + then the current is not added *) + else if (List.exists (fun c2 -> clausesAreSubSetEq c2 c) acc) then + acc + (* If the current clause is included inside an observed clause + c2 then the current is add and c2 is removed *) + else if (List.exists (fun c2 -> clausesAreSubSetEq c c2) acc) then + c::(removeClause acc c) + (* If no simplification then c is add to the list *) + else c::acc + ) + [] clauses + with Exit -> [[]] +let tor t1 t2 = + match t1,t2 with + TTrue,_ | _,TTrue -> TTrue + | TFalse,t | t,TFalse -> t + | _,_ -> TOr(t1,t2) + +let tand t1 t2 = + match t1,t2 with + TTrue,t | t,TTrue -> t + | TFalse,_ | _,TFalse -> TFalse + | _,_ -> TAnd(t1,t2) + +let tnot t = + match t with + TTrue -> TFalse + | TFalse -> TTrue + | TNot t -> t + | TRel(rel,t1,t2) -> TRel(opposite_rel rel, t1, t2) + | _ -> TNot t -let simplifyClauses clauses = - let result= ref [] in - List.iter - (fun c -> - (* If 2 clauses are C and not C then theire disjunction implies true *) - if List.exists (clausesAreEqual (negativeClause c)) !result then result:=[PTrue]::!result - - (* If an observed clause c2 is include inside the current clause then the current is not add *) - else if (List.exists (fun c2 -> clausesAreSubSetEq c2 c) !result) then () +let tands l = List.fold_left tand TTrue l - (* If the current clause is include inside an observed clause c2 then the current is add and c2 is removed *) - else if (List.exists (fun c2 -> clausesAreSubSetEq c c2) !result) then result:=c::(removeClause !result c) - - (* If no simplification then c is add to the list *) - else result:=c::!result - ) - clauses; - !result +let tors l = List.fold_left tor TFalse l - -(** Given a DNF condition, it returns a condition in Promalaast.condition form. +(** Given a DNF condition, it returns a condition in Promelaast.condition form. WARNING : empty lists not supported *) -let dnfToCond d = - let isTrue =ref false in - - let clauseToCond c = - if c=[PTrue] then isTrue:=true; - if List.length c =1 then - (List.hd c) - else - List.fold_left (fun c1 c2 -> PAnd(c1,c2)) (List.hd c) (List.tl c) - in - let res = - if List.length d=1 then - clauseToCond (List.hd d) - else - List.fold_left (fun d1 d2 -> POr(d1,(clauseToCond d2))) (clauseToCond (List.hd d)) (List.tl d) - in - if !isTrue then PTrue else res - - +let dnfToCond d = tors (List.map tands d) let dnfToParametrized clausel = List.fold_left (fun cll cl -> let onlypcond_cl = List.fold_left - (fun res term -> - match term with - | PFuncReturn (_,_) - | PFuncParam (_, _,_) as c -> c::res - | _ -> res - - ) + (fun res term -> match term with TRel _ -> term::res | _ -> res) [] cl - in + in if onlypcond_cl=[] then cll else onlypcond_cl::cll ) [] clausel - +let simplClause dnf clause = + match clause with + | [] | [TTrue] | [TNot TFalse]-> [[]] + | [TFalse] | [TNot TTrue] -> dnf + | _ -> clause :: dnf (** Given a condition, this function does some logical simplifications. - It returns both the simplified condition and a disjunction of conjunctions of parametrized call or return. + It returns both the simplified condition and a disjunction of + conjunctions of parametrized call or return. *) -let simplifyCond condition = +let simplifyCond condition = + Aorai_option.debug + "initial condition: %a" Promelaoutput.print_condition condition; (* Step 1 : Condition is translate into Disjunctive Normal Form *) let res1 = condToDNF condition in - + Aorai_option.debug "initial dnf: %a" pretty_dnf res1; (* Step 2 : Positive Call/Ret are used to simplify negative ones *) - let res = List.fold_left (fun lclauses clause -> - let c=(positiveCallOrRet clause) in - if c=[] then lclauses - else c::lclauses - ) [] res1 in - - + let res = + List.fold_left + (fun lclauses clause -> simplClause lclauses (positiveCallOrRet clause)) + [] res1 + in + Aorai_option.debug "after step 2: %a" pretty_dnf res; (* Step 3 : simplification between exprs inside a clause *) - let res = List.fold_left (fun lclauses clause -> - let c=(simplify clause) in - if c=[] then lclauses - else c::lclauses - ) [] res in - + let res = + List.fold_left + (fun lclauses clause -> simplClause lclauses (simplify clause)) [] res + in + Aorai_option.debug "after step 3: %a" pretty_dnf res; (* Step 4 : simplification between clauses *) - let res = simplifyClauses res in - - (* Last step : list of list translate back into condition type. *) - if res=[] then (PFalse,[]) - else ((dnfToCond res),(*dnfToParametrized*) res) - - + let res = simplifyClauses res in + Aorai_option.debug "after step 4: %a" pretty_dnf res; + ((dnfToCond res), res) (** Given a list of transitions, this function returns the same list of transition with simplifyCond done on its cross condition *) let simplifyTrans transl = - List.fold_left (fun (ltr,lpcond) tr -> - let (crossCond , pcond ) = simplifyCond (tr.cross) in - (* pcond stands for parametrized condition : disjunction of conjunctions of parametrized call/return *) - let tr'={ start = tr.start ; - stop = tr.stop ; - cross = crossCond ; - numt = tr.numt - } - in - if tr'.cross <> PFalse then (tr'::ltr,pcond::lpcond) else (ltr,lpcond) - ) ([],[]) (List.rev transl) - - - - - - + List.fold_left + (fun (ltr,lpcond) tr -> + let (crossCond , pcond ) = simplifyCond (tr.cross) in + (* pcond stands for parametrized condition : + disjunction of conjunctions of parametrized call/return *) + let tr'={ start = tr.start ; + stop = tr.stop ; + cross = crossCond ; + numt = tr.numt + } + in + Aorai_option.debug "condition is %a, dnf is %a" + Promelaoutput.print_condition crossCond pretty_dnf pcond; + if tr'.cross <> TFalse then (tr'::ltr,pcond::lpcond) else (ltr,lpcond) + ) + ([],[]) (List.rev transl) (** Given a DNF condition, it returns the same condition simplified according to the context (function name and status). Hence, the returned condition is without any Call/Return stmts. *) -let simplifyDNFwrtCtx (dnf:Promelaast.condition list list) (f:string) (status:Promelaast.funcStatus) = - let rec simplCNFwrtCtx (cnf:Promelaast.condition list) = - match cnf with - | [] -> (True,[PTrue]) - | PTrue::l -> simplCNFwrtCtx l - | PFalse::_ ->(False, [PFalse]) - - | PIndexedExp(s)::l -> - let (b,l2) = simplCNFwrtCtx l in - if b=False then (False, [PFalse]) - else (Undefined,PIndexedExp(s)::l2) - - | PCall(s)::l -> - if (String.compare f s)=0 && status=Promelaast.Call then - simplCNFwrtCtx l - else - (False, [PFalse]) - - | PReturn(s)::l -> - if (String.compare f s)=0 && status=Promelaast.Return then - simplCNFwrtCtx l - else - (False, [PFalse]) - - | PCallOrReturn(s)::l -> - if (String.compare f s)=0 then - simplCNFwrtCtx l - else - (False, [PFalse]) - - - - | PFuncReturn (hash, s)::l -> - if (String.compare f s)=0 && status=Promelaast.Return then - let (b,l2)= simplCNFwrtCtx l in - if b=False then - (False, [PFalse]) - else - (Undefined,PFuncReturn(hash,s)::l2) - else - (False, [PFalse]) - - - | PFuncParam (hash, s, vl)::l -> - if (String.compare f s)=0 && status=Promelaast.Call then - let (b,l2)= simplCNFwrtCtx l in - if b=False then - (False, [PFalse]) - else - (Undefined,PFuncParam(hash,s,vl)::l2) - - else - (False, [PFalse]) - - - | PNot(c)::l -> - let (b1,l1) = simplCNFwrtCtx [c] in - if b1=True then (False, [PFalse]) - else - if b1=False then simplCNFwrtCtx l - else - begin - let nl1 = PNot(List.hd l1) in - - let (b2,l2) = simplCNFwrtCtx l in - if b2=False then (False, [PFalse]) - else (Undefined,nl1::l2) - end - - - - | PAnd (_,_) ::_ - | POr (_,_)::_ -> assert false +let simplifyDNFwrtCtx dnf kf1 status = + Aorai_option.debug "Before simplification: %a" pretty_dnf dnf; + let rec simplCondition c = + match c with + | TCall (kf2, None) -> + if Kernel_function.equal kf1 kf2 && status = Promelaast.Call then + TTrue + else TFalse + | TCall (kf2, Some _) -> + if Kernel_function.equal kf1 kf2 && status = Promelaast.Call then + c + else TFalse + | TReturn kf2 -> + if Kernel_function.equal kf1 kf2 && status = Promelaast.Return then + TTrue + else TFalse + | TNot c -> tnot (simplCondition c) + | TAnd(c1,c2) -> tand (simplCondition c1) (simplCondition c2) + | TOr (c1,c2) -> tor (simplCondition c1) (simplCondition c2) + | TTrue | TFalse | TRel _ -> c in - - List.fold_left - (fun res cll -> let (_,c) = simplCNFwrtCtx cll in - c::res) - [] - dnf - - - - - - + let rec simplCNFwrtCtx cnf = + tands (List.map simplCondition cnf) + in + let res = tors (List.map simplCNFwrtCtx dnf) in + Aorai_option.debug + "After simplification: %a" Promelaoutput.print_condition res; res (* Tests : diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/logic_simplification.mli frama-c-20111001+nitrogen+dfsg/src/aorai/logic_simplification.mli --- frama-c-20110201+carbon+dfsg/src/aorai/logic_simplification.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/logic_simplification.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,20 +23,37 @@ (* *) (**************************************************************************) +(** Basic simplification over {!Promelaast.typed_condition} *) open Promelaast -val setLtl_expressions : (string, (Cil_types.exp* string*Cil_types.predicate)) Hashtbl.t -> unit +(** {2 smart constructors for typed conditions} *) +val tand: typed_condition -> typed_condition -> typed_condition +val tor: typed_condition -> typed_condition -> typed_condition +val tnot: typed_condition -> typed_condition -(** Given a condition, this function does some logical simplifications. *) -val simplifyCond: condition -> (condition)*(Promelaast.condition list list) -(** Given a transition list, this function returns the same transition list with simplifyCond done on each cross condition. Uncrossable transition are removed. *) -val simplifyTrans: trans list -> (trans list)*(Promelaast.condition list list list) +(** {2 simplifications} *) -val dnfToCond : (Promelaast.condition list list) -> Promelaast.condition +(** Given a condition, this function does some logical simplifications + and returns an equivalent DNF form together with the simplified version +*) +val simplifyCond: + Promelaast.typed_condition -> + Promelaast.typed_condition *(Promelaast.typed_condition list list) -val simplifyDNFwrtCtx : Promelaast.condition list list -> string -> Promelaast.funcStatus -> Promelaast.condition list list +(** Given a transition list, this function returns the same transition list with simplifyCond done on each cross condition. Uncrossable transition are removed. *) +val simplifyTrans: + Promelaast.typed_condition Promelaast.trans list -> + (Promelaast.typed_condition Promelaast.trans list)* + (Promelaast.typed_condition list list list) + +val dnfToCond : + (Promelaast.typed_condition list list) -> Promelaast.typed_condition + +val simplifyDNFwrtCtx : + Promelaast.typed_condition list list -> Cil_types.kernel_function -> + Promelaast.funcStatus -> Promelaast.typed_condition (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltlast.mli frama-c-20111001+nitrogen+dfsg/src/aorai/ltlast.mli --- frama-c-20110201+carbon+dfsg/src/aorai/ltlast.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltlast.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -27,7 +29,7 @@ (** LTL formula parsed abstract syntax trees *) -type formula = +type formula = | LNext of formula (** 'Next' temporal operator *) | LUntil of formula * formula (** 'Until' temporal operator *) | LFatally of formula (** 'Fatally' temporal operator *) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltllexer.ml frama-c-20111001+nitrogen+dfsg/src/aorai/ltllexer.ml --- frama-c-20110201+carbon+dfsg/src/aorai/ltllexer.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltllexer.ml 2011-10-10 08:48:50.000000000 +0000 @@ -1,4 +1,4 @@ -# 28 "src/aorai/ltllexer.mll" +# 30 "src/aorai/ltllexer.mll" open Ltlparser @@ -28,9 +28,9 @@ in lexbuf.lex_curr_p <- { pos with - pos_fname = new_file; - pos_lnum = if absolute then line else pos.pos_lnum + line; - pos_bol = pos.pos_cnum - chars; + pos_fname = new_file; + pos_lnum = if absolute then line else pos.pos_lnum + line; + pos_bol = pos.pos_cnum - chars; } *) exception Error of (Lexing.position * Lexing.position) * string @@ -937,211 +937,211 @@ } let rec token lexbuf = - __ocaml_lex_token_rec lexbuf 0 + __ocaml_lex_token_rec lexbuf 0 and __ocaml_lex_token_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 76 "src/aorai/ltllexer.mll" +# 78 "src/aorai/ltllexer.mll" ( LTL_TRUE ) # 947 "src/aorai/ltllexer.ml" | 1 -> -# 77 "src/aorai/ltllexer.mll" +# 79 "src/aorai/ltllexer.mll" ( LTL_FALSE ) # 952 "src/aorai/ltllexer.ml" | 2 -> -# 78 "src/aorai/ltllexer.mll" - ( LTL_LPAREN ) +# 80 "src/aorai/ltllexer.mll" + ( LTL_LPAREN ) # 957 "src/aorai/ltllexer.ml" | 3 -> -# 79 "src/aorai/ltllexer.mll" - ( LTL_RPAREN ) +# 81 "src/aorai/ltllexer.mll" + ( LTL_RPAREN ) # 962 "src/aorai/ltllexer.ml" | 4 -> -# 82 "src/aorai/ltllexer.mll" - ( LTL_IMPLIES ) +# 84 "src/aorai/ltllexer.mll" + ( LTL_IMPLIES ) # 967 "src/aorai/ltllexer.ml" | 5 -> -# 83 "src/aorai/ltllexer.mll" - ( LTL_LEFT_RIGHT_ARROW ) +# 85 "src/aorai/ltllexer.mll" + ( LTL_LEFT_RIGHT_ARROW ) # 972 "src/aorai/ltllexer.ml" | 6 -> -# 84 "src/aorai/ltllexer.mll" +# 86 "src/aorai/ltllexer.mll" ( LTL_OR ) # 977 "src/aorai/ltllexer.ml" | 7 -> -# 85 "src/aorai/ltllexer.mll" +# 87 "src/aorai/ltllexer.mll" ( LTL_AND ) # 982 "src/aorai/ltllexer.ml" | 8 -> -# 86 "src/aorai/ltllexer.mll" +# 88 "src/aorai/ltllexer.mll" ( LTL_NOT ) # 987 "src/aorai/ltllexer.ml" | 9 -> -# 87 "src/aorai/ltllexer.mll" +# 89 "src/aorai/ltllexer.mll" ( LTL_GLOBALLY ) # 992 "src/aorai/ltllexer.ml" | 10 -> -# 88 "src/aorai/ltllexer.mll" +# 90 "src/aorai/ltllexer.mll" ( LTL_FATALLY ) # 997 "src/aorai/ltllexer.ml" | 11 -> -# 89 "src/aorai/ltllexer.mll" +# 91 "src/aorai/ltllexer.mll" ( LTL_UNTIL ) # 1002 "src/aorai/ltllexer.ml" | 12 -> -# 90 "src/aorai/ltllexer.mll" +# 92 "src/aorai/ltllexer.mll" ( LTL_RELEASE ) # 1007 "src/aorai/ltllexer.ml" | 13 -> -# 91 "src/aorai/ltllexer.mll" +# 93 "src/aorai/ltllexer.mll" ( LTL_NEXT ) # 1012 "src/aorai/ltllexer.ml" | 14 -> -# 95 "src/aorai/ltllexer.mll" +# 97 "src/aorai/ltllexer.mll" ( LTL_EQ ) # 1017 "src/aorai/ltllexer.ml" | 15 -> -# 96 "src/aorai/ltllexer.mll" +# 98 "src/aorai/ltllexer.mll" ( LTL_LT ) # 1022 "src/aorai/ltllexer.ml" | 16 -> -# 97 "src/aorai/ltllexer.mll" +# 99 "src/aorai/ltllexer.mll" ( LTL_GT ) # 1027 "src/aorai/ltllexer.ml" | 17 -> -# 98 "src/aorai/ltllexer.mll" +# 100 "src/aorai/ltllexer.mll" ( LTL_LE ) # 1032 "src/aorai/ltllexer.ml" | 18 -> -# 99 "src/aorai/ltllexer.mll" +# 101 "src/aorai/ltllexer.mll" ( LTL_GE ) # 1037 "src/aorai/ltllexer.ml" | 19 -> -# 100 "src/aorai/ltllexer.mll" +# 102 "src/aorai/ltllexer.mll" ( LTL_NEQ ) # 1042 "src/aorai/ltllexer.ml" | 20 -> -# 103 "src/aorai/ltllexer.mll" +# 105 "src/aorai/ltllexer.mll" ( LTL_PLUS ) # 1047 "src/aorai/ltllexer.ml" | 21 -> -# 104 "src/aorai/ltllexer.mll" +# 106 "src/aorai/ltllexer.mll" ( LTL_MINUS ) # 1052 "src/aorai/ltllexer.ml" | 22 -> -# 105 "src/aorai/ltllexer.mll" +# 107 "src/aorai/ltllexer.mll" ( LTL_DIV ) # 1057 "src/aorai/ltllexer.ml" | 23 -> -# 106 "src/aorai/ltllexer.mll" +# 108 "src/aorai/ltllexer.mll" ( LTL_STAR ) # 1062 "src/aorai/ltllexer.ml" | 24 -> -# 107 "src/aorai/ltllexer.mll" +# 109 "src/aorai/ltllexer.mll" ( LTL_MODULO) # 1067 "src/aorai/ltllexer.ml" | 25 -> -# 110 "src/aorai/ltllexer.mll" - ( LTL_RIGHT_ARROW ) +# 112 "src/aorai/ltllexer.mll" + ( LTL_RIGHT_ARROW ) # 1072 "src/aorai/ltllexer.ml" | 26 -> -# 111 "src/aorai/ltllexer.mll" +# 113 "src/aorai/ltllexer.mll" ( LTL_DOT ) # 1077 "src/aorai/ltllexer.ml" | 27 -> -# 112 "src/aorai/ltllexer.mll" +# 114 "src/aorai/ltllexer.mll" ( LTL_LEFT_SQUARE) # 1082 "src/aorai/ltllexer.ml" | 28 -> -# 113 "src/aorai/ltllexer.mll" +# 115 "src/aorai/ltllexer.mll" ( LTL_RIGHT_SQUARE) # 1087 "src/aorai/ltllexer.ml" | 29 -> -# 114 "src/aorai/ltllexer.mll" +# 116 "src/aorai/ltllexer.mll" ( LTL_ADRESSE ) # 1092 "src/aorai/ltllexer.ml" | 30 -> -# 115 "src/aorai/ltllexer.mll" +# 117 "src/aorai/ltllexer.mll" ( LTL_CALL ) # 1097 "src/aorai/ltllexer.ml" | 31 -> -# 116 "src/aorai/ltllexer.mll" +# 118 "src/aorai/ltllexer.mll" ( LTL_RETURN ) # 1102 "src/aorai/ltllexer.ml" | 32 -> -# 117 "src/aorai/ltllexer.mll" +# 119 "src/aorai/ltllexer.mll" ( LTL_CALL_OR_RETURN ) # 1107 "src/aorai/ltllexer.ml" | 33 -> -# 120 "src/aorai/ltllexer.mll" +# 122 "src/aorai/ltllexer.mll" ( comment lexbuf; token lexbuf ) # 1112 "src/aorai/ltllexer.ml" | 34 -> -# 121 "src/aorai/ltllexer.mll" +# 123 "src/aorai/ltllexer.mll" ( newline lexbuf; token lexbuf ) # 1117 "src/aorai/ltllexer.ml" | 35 -> -# 124 "src/aorai/ltllexer.mll" +# 126 "src/aorai/ltllexer.mll" ( token lexbuf ) # 1122 "src/aorai/ltllexer.ml" | 36 -> -# 125 "src/aorai/ltllexer.mll" +# 127 "src/aorai/ltllexer.mll" ( newline lexbuf; token lexbuf ) # 1127 "src/aorai/ltllexer.ml" | 37 -> -# 128 "src/aorai/ltllexer.mll" +# 130 "src/aorai/ltllexer.mll" ( LTL_INT (lexeme lexbuf) ) # 1132 "src/aorai/ltllexer.ml" | 38 -> -# 129 "src/aorai/ltllexer.mll" +# 131 "src/aorai/ltllexer.mll" ( LTL_LABEL (lexeme lexbuf) ) # 1137 "src/aorai/ltllexer.ml" | 39 -> -# 132 "src/aorai/ltllexer.mll" +# 134 "src/aorai/ltllexer.mll" ( EOF ) # 1142 "src/aorai/ltllexer.ml" | 40 -> -# 133 "src/aorai/ltllexer.mll" +# 135 "src/aorai/ltllexer.mll" ( raise_located (loc lexbuf) (Format.sprintf "Illegal_character %s\n" (lexeme lexbuf)) @@ -1151,26 +1151,26 @@ | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state and comment lexbuf = - __ocaml_lex_comment_rec lexbuf 76 + __ocaml_lex_comment_rec lexbuf 76 and __ocaml_lex_comment_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 139 "src/aorai/ltllexer.mll" +# 141 "src/aorai/ltllexer.mll" ( () ) # 1161 "src/aorai/ltllexer.ml" | 1 -> -# 140 "src/aorai/ltllexer.mll" +# 142 "src/aorai/ltllexer.mll" ( raise_located (loc lexbuf) "Unterminated_comment\n" ) # 1166 "src/aorai/ltllexer.ml" | 2 -> -# 141 "src/aorai/ltllexer.mll" +# 143 "src/aorai/ltllexer.mll" ( newline lexbuf; comment lexbuf ) # 1171 "src/aorai/ltllexer.ml" | 3 -> -# 142 "src/aorai/ltllexer.mll" +# 144 "src/aorai/ltllexer.mll" ( comment lexbuf ) # 1176 "src/aorai/ltllexer.ml" @@ -1178,14 +1178,14 @@ ;; -# 145 "src/aorai/ltllexer.mll" +# 147 "src/aorai/ltllexer.mll" let parse c = let lb = from_channel c in try Ltlparser.ltl token lb with - Parsing.Parse_error + Parsing.Parse_error | Invalid_argument _ -> raise_located (loc lb) "Syntax error" # 1192 "src/aorai/ltllexer.ml" diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltllexer.mll frama-c-20111001+nitrogen+dfsg/src/aorai/ltllexer.mll --- frama-c-20110201+carbon+dfsg/src/aorai/ltllexer.mll 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltllexer.mll 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -54,9 +56,9 @@ in lexbuf.lex_curr_p <- { pos with - pos_fname = new_file; - pos_lnum = if absolute then line else pos.pos_lnum + line; - pos_bol = pos.pos_cnum - chars; + pos_fname = new_file; + pos_lnum = if absolute then line else pos.pos_lnum + line; + pos_bol = pos.pos_cnum - chars; } *) exception Error of (Lexing.position * Lexing.position) * string @@ -68,19 +70,19 @@ -let rD = ['0'-'9'] +let rD = ['0'-'9'] let rL = ['a'-'z' 'A'-'Z' '_'] rule token = parse | "true" { LTL_TRUE } | "false" { LTL_FALSE } - | '(' { LTL_LPAREN } - | ')' { LTL_RPAREN } + | '(' { LTL_LPAREN } + | ')' { LTL_RPAREN } (* Logic operators *) - | "=>" { LTL_IMPLIES } - | "<=>" { LTL_LEFT_RIGHT_ARROW } + | "=>" { LTL_IMPLIES } + | "<=>" { LTL_LEFT_RIGHT_ARROW } | "||" { LTL_OR } | "&&" { LTL_AND } | '!' { LTL_NOT } @@ -107,7 +109,7 @@ | '%' { LTL_MODULO} (* Access *) - | "->" { LTL_RIGHT_ARROW } + | "->" { LTL_RIGHT_ARROW } | '.' { LTL_DOT } | '[' { LTL_LEFT_SQUARE} | ']' { LTL_RIGHT_SQUARE} @@ -148,6 +150,6 @@ try Ltlparser.ltl token lb with - Parsing.Parse_error + Parsing.Parse_error | Invalid_argument _ -> raise_located (loc lb) "Syntax error" } diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltl_output.ml frama-c-20111001+nitrogen+dfsg/src/aorai/ltl_output.ml --- frama-c-20110201+carbon+dfsg/src/aorai/ltl_output.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltl_output.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,70 +23,57 @@ (* *) (**************************************************************************) -(* $Id: ltl_output.ml,v 1.3 2009-03-11 12:40:58 uid588 Exp $ *) - open Format open Pervasives open Ltlast let out_fmt=ref (formatter_of_out_channel stdout) let rec ltl_form_to_string = function - | LNext (f) -> - "X("^(ltl_form_to_string f)^")" - | LUntil (f1,f2) -> - "("^(ltl_form_to_string f1)^" U "^(ltl_form_to_string f2)^")" - | LFatally (f) -> - "<>("^(ltl_form_to_string f)^")" - | LGlobally (f) -> - "[]("^(ltl_form_to_string f)^")" - | LRelease (f1,f2) -> - "("^(ltl_form_to_string f1)^" V "^(ltl_form_to_string f2)^")" - - | LNot (f) -> - "!("^(ltl_form_to_string f)^")" - | LAnd (f1,f2) -> - "("^(ltl_form_to_string f1)^" && "^(ltl_form_to_string f2)^")" - | LOr (f1,f2) -> - "("^(ltl_form_to_string f1)^" || "^(ltl_form_to_string f2)^")" - | LImplies (f1,f2) -> - "("^(ltl_form_to_string f1)^" -> "^(ltl_form_to_string f2)^")" - | LIff (f1,f2) -> - "("^(ltl_form_to_string f1)^" <-> "^(ltl_form_to_string f2)^")" - - | LTrue -> - "1" - | LFalse -> - "0" - - | LCall (s) -> - "callof_"^s - | LReturn (s) -> - "returnof_"^s - | LCallOrReturn (s) -> - "callorreturnof_"^s - - | LIdent (s) -> - s - - -let pretty_hash_ident_entry ident (_,str,_) = - fprintf !out_fmt "// '%s' = '%s'\n" ident str + | LNext (f) -> + "X("^(ltl_form_to_string f)^")" + | LUntil (f1,f2) -> + "("^(ltl_form_to_string f1)^" U "^(ltl_form_to_string f2)^")" + | LFatally (f) -> + "<>("^(ltl_form_to_string f)^")" + | LGlobally (f) -> + "[]("^(ltl_form_to_string f)^")" + | LRelease (f1,f2) -> + "("^(ltl_form_to_string f1)^" V "^(ltl_form_to_string f2)^")" + + | LNot (f) -> + "!("^(ltl_form_to_string f)^")" + | LAnd (f1,f2) -> + "("^(ltl_form_to_string f1)^" && "^(ltl_form_to_string f2)^")" + | LOr (f1,f2) -> + "("^(ltl_form_to_string f1)^" || "^(ltl_form_to_string f2)^")" + | LImplies (f1,f2) -> + "("^(ltl_form_to_string f1)^" -> "^(ltl_form_to_string f2)^")" + | LIff (f1,f2) -> + "("^(ltl_form_to_string f1)^" <-> "^(ltl_form_to_string f2)^")" + + | LTrue -> + "1" + | LFalse -> + "0" + + | LCall (s) -> + "callof_"^s + | LReturn (s) -> + "returnof_"^s + | LCallOrReturn (s) -> + "callorreturnof_"^s + | LIdent (s) -> + s let output ltl_form file = - let c = open_out file in - out_fmt:=formatter_of_out_channel c ; - + let c = open_out file in + out_fmt:=formatter_of_out_channel c ; fprintf !out_fmt "%s\n\n" (ltl_form_to_string ltl_form); - fprintf !out_fmt "// associations : \n" ; - (Data_for_aorai.ltl_expressions_iter pretty_hash_ident_entry); fprintf !out_fmt "@?"; (* Flush du flux *) - - close_out c; + close_out c; out_fmt:=formatter_of_out_channel stdout - - (* Local Variables: compile-command: "LC_ALL=C make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltl_output.mli frama-c-20111001+nitrogen+dfsg/src/aorai/ltl_output.mli --- frama-c-20110201+carbon+dfsg/src/aorai/ltl_output.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltl_output.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltlparser.ml frama-c-20111001+nitrogen+dfsg/src/aorai/ltlparser.ml --- frama-c-20110201+carbon+dfsg/src/aorai/ltlparser.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltlparser.ml 2011-10-10 08:48:50.000000000 +0000 @@ -37,10 +37,12 @@ | EOF open Parsing;; -# 28 "src/aorai/ltlparser.mly" +# 30 "src/aorai/ltlparser.mly" +open Promelaast open Parsing open Cil_types open Cil +open Logic_ptree let observed_expressions=Hashtbl.create 97 @@ -50,7 +52,7 @@ ("buchfreshident"^(string_of_int !ident_count)) let new_exp = new_exp ~loc:(CurrentLoc.get())(*TODO: give a proper loc*) -# 54 "src/aorai/ltlparser.ml" +# 56 "src/aorai/ltlparser.ml" let yytransl_const = [| 257 (* LTL_TRUE *); 258 (* LTL_FALSE *); @@ -120,72 +122,71 @@ \000\000\000\000\000\000\000\000\000\000\004\000\036\000\045\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\019\000\020\000\021\000\022\000\023\000\ -\024\000\026\000\027\000\029\000\030\000\031\000\038\000\000\000\ +\024\000\026\000\027\000\029\000\030\000\031\000\037\000\038\000\ \000\000\015\000\016\000\017\000\000\000\040\000" let yydgoto = "\002\000\ \018\000\019\000\020\000\021\000\022\000\023\000\024\000\025\000\ \026\000" -let yysindex = "\004\000\ -\079\255\000\000\000\000\000\000\079\255\079\255\079\255\079\255\ -\079\255\234\254\048\255\048\255\011\255\021\255\037\255\000\000\ -\000\000\000\000\157\000\000\000\100\255\137\255\000\000\025\255\ -\241\254\000\000\139\255\000\255\254\254\026\255\026\255\026\255\ -\026\255\000\000\048\255\025\255\025\255\024\255\028\255\036\255\ -\079\255\079\255\079\255\079\255\079\255\079\255\000\000\072\255\ -\072\255\072\255\072\255\072\255\072\255\072\255\072\255\072\255\ -\072\255\072\255\039\255\048\255\072\255\000\000\000\000\000\000\ -\254\254\056\255\073\255\080\255\029\255\029\255\029\255\087\255\ -\026\255\026\255\072\255\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\025\255\ -\047\255\000\000\000\000\000\000\081\255\000\000" +let yysindex = "\010\000\ +\066\255\000\000\000\000\000\000\066\255\066\255\066\255\066\255\ +\066\255\224\254\002\255\002\255\027\255\031\255\063\255\000\000\ +\000\000\000\000\131\000\000\000\045\255\070\255\000\000\014\255\ +\243\254\000\000\102\255\067\255\012\255\039\255\039\255\039\255\ +\039\255\000\000\002\255\014\255\014\255\007\255\037\255\043\255\ +\066\255\066\255\066\255\066\255\066\255\066\255\000\000\001\255\ +\001\255\001\255\001\255\001\255\001\255\001\255\001\255\001\255\ +\001\255\001\255\046\255\054\255\001\255\000\000\000\000\000\000\ +\012\255\098\255\099\255\100\255\111\255\111\255\111\255\016\255\ +\039\255\039\255\001\255\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\082\255\000\000\000\000\000\000\108\255\000\000" let yyrindex = "\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\148\000\131\000\000\000\105\000\ -\079\000\000\000\000\000\049\255\117\255\167\000\172\000\177\000\ -\182\000\000\000\000\000\001\000\027\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\122\000\105\000\000\000\079\000\ +\001\000\000\000\000\000\120\255\157\255\141\000\146\000\151\000\ +\156\000\000\000\000\000\027\000\053\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\006\000\007\000\008\000\171\000\ +\161\000\166\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\006\000\007\000\008\000\197\000\ -\187\000\192\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\053\000\ \000\000\000\000\000\000\000\000\000\000\000\000" let yygindex = "\000\000\ -\000\000\023\000\000\000\251\255\000\000\221\255\254\255\000\000\ +\000\000\013\000\000\000\251\255\000\000\212\255\254\255\000\000\ \000\000" -let yytablesize = 460 +let yytablesize = 434 let yytable = "\028\000\ -\043\000\064\000\029\000\063\000\001\000\010\000\013\000\014\000\ -\036\000\037\000\060\000\034\000\061\000\038\000\048\000\049\000\ -\050\000\051\000\052\000\053\000\084\000\085\000\086\000\039\000\ -\059\000\089\000\042\000\027\000\030\000\031\000\032\000\033\000\ -\065\000\041\000\042\000\043\000\044\000\045\000\046\000\040\000\ -\045\000\046\000\076\000\077\000\078\000\079\000\080\000\081\000\ -\082\000\083\000\035\000\059\000\037\000\025\000\025\000\025\000\ -\025\000\088\000\066\000\090\000\025\000\025\000\067\000\069\000\ -\070\000\071\000\072\000\073\000\074\000\093\000\068\000\011\000\ -\029\000\087\000\075\000\094\000\091\000\012\000\039\000\003\000\ -\004\000\005\000\017\000\092\000\063\000\000\000\000\000\006\000\ -\007\000\008\000\000\000\000\000\009\000\010\000\044\000\011\000\ -\000\000\000\000\045\000\046\000\010\000\012\000\011\000\000\000\ -\035\000\016\000\017\000\000\000\012\000\013\000\014\000\015\000\ -\016\000\017\000\048\000\049\000\050\000\051\000\052\000\053\000\ -\000\000\035\000\035\000\035\000\035\000\000\000\000\000\000\000\ -\035\000\035\000\028\000\035\000\035\000\035\000\035\000\035\000\ -\035\000\035\000\035\000\035\000\035\000\035\000\062\000\041\000\ -\042\000\043\000\044\000\025\000\000\000\000\000\045\000\046\000\ -\000\000\000\000\000\000\000\000\047\000\054\000\055\000\056\000\ -\057\000\058\000\000\000\000\000\000\000\000\000\012\000\000\000\ -\000\000\000\000\000\000\005\000\000\000\000\000\000\000\000\000\ -\006\000\000\000\000\000\000\000\000\000\009\000\000\000\000\000\ -\000\000\000\000\007\000\000\000\000\000\000\000\000\000\008\000\ -\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\ +\039\000\034\000\029\000\075\000\035\000\010\000\013\000\014\000\ +\036\000\037\000\001\000\084\000\085\000\086\000\061\000\064\000\ +\089\000\027\000\030\000\031\000\032\000\033\000\010\000\044\000\ +\011\000\011\000\043\000\045\000\046\000\038\000\012\000\012\000\ +\065\000\039\000\016\000\017\000\017\000\059\000\060\000\059\000\ +\060\000\066\000\076\000\077\000\078\000\079\000\080\000\081\000\ +\082\000\083\000\045\000\046\000\042\000\069\000\070\000\071\000\ +\072\000\073\000\074\000\048\000\049\000\050\000\051\000\052\000\ +\053\000\040\000\003\000\004\000\005\000\093\000\063\000\067\000\ +\029\000\000\000\006\000\007\000\008\000\068\000\035\000\009\000\ +\087\000\048\000\049\000\050\000\051\000\052\000\053\000\010\000\ +\088\000\011\000\054\000\055\000\056\000\057\000\058\000\012\000\ +\013\000\014\000\015\000\016\000\017\000\090\000\091\000\092\000\ +\028\000\062\000\041\000\042\000\043\000\044\000\094\000\063\000\ +\000\000\045\000\046\000\041\000\042\000\043\000\044\000\000\000\ +\000\000\025\000\045\000\046\000\025\000\025\000\025\000\025\000\ +\000\000\000\000\047\000\025\000\025\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\ +\000\000\005\000\000\000\000\000\000\000\000\000\006\000\000\000\ +\000\000\000\000\000\000\009\000\000\000\000\000\000\000\000\000\ +\007\000\035\000\035\000\035\000\035\000\008\000\000\000\000\000\ +\035\000\035\000\011\000\035\000\035\000\035\000\035\000\035\000\ +\035\000\035\000\035\000\035\000\035\000\035\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -193,59 +194,57 @@ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\043\000\043\000\043\000\043\000\ -\043\000\010\000\013\000\014\000\043\000\043\000\000\000\043\000\ -\043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ -\043\000\043\000\043\000\000\000\043\000\043\000\042\000\042\000\ -\042\000\042\000\042\000\000\000\000\000\000\000\042\000\042\000\ -\000\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ -\042\000\042\000\042\000\042\000\042\000\000\000\042\000\042\000\ -\037\000\037\000\037\000\037\000\037\000\000\000\000\000\000\000\ -\037\000\037\000\000\000\037\000\037\000\037\000\037\000\037\000\ -\037\000\037\000\037\000\037\000\037\000\037\000\037\000\000\000\ -\037\000\037\000\039\000\039\000\039\000\039\000\039\000\000\000\ -\000\000\000\000\039\000\039\000\000\000\039\000\039\000\039\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\039\000\039\000\039\000\039\000\ +\039\000\010\000\013\000\014\000\039\000\039\000\000\000\039\000\ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\ -\000\000\039\000\000\000\039\000\035\000\035\000\035\000\035\000\ -\035\000\000\000\000\000\000\000\035\000\035\000\000\000\035\000\ +\039\000\039\000\039\000\039\000\000\000\039\000\043\000\043\000\ +\043\000\043\000\043\000\000\000\000\000\000\000\043\000\043\000\ +\000\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ +\043\000\043\000\043\000\043\000\000\000\000\000\043\000\043\000\ +\042\000\042\000\042\000\042\000\042\000\000\000\000\000\000\000\ +\042\000\042\000\000\000\042\000\042\000\042\000\042\000\042\000\ +\042\000\042\000\042\000\042\000\042\000\042\000\000\000\000\000\ +\042\000\042\000\035\000\035\000\035\000\035\000\035\000\000\000\ +\000\000\000\000\035\000\035\000\000\000\035\000\035\000\035\000\ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ -\035\000\035\000\000\000\000\000\000\000\035\000\028\000\028\000\ -\028\000\028\000\028\000\000\000\000\000\000\000\028\000\028\000\ -\000\000\028\000\028\000\028\000\028\000\028\000\028\000\025\000\ -\025\000\025\000\025\000\025\000\000\000\000\000\000\000\025\000\ -\025\000\041\000\042\000\043\000\044\000\000\000\000\000\000\000\ -\045\000\046\000\012\000\012\000\012\000\012\000\012\000\005\000\ -\005\000\005\000\005\000\005\000\006\000\006\000\006\000\006\000\ -\006\000\009\000\009\000\009\000\009\000\009\000\007\000\007\000\ -\007\000\007\000\007\000\008\000\008\000\008\000\008\000\008\000\ -\011\000\011\000\011\000\011\000" +\000\000\000\000\000\000\035\000\028\000\028\000\028\000\028\000\ +\028\000\000\000\000\000\000\000\028\000\028\000\000\000\028\000\ +\028\000\028\000\028\000\028\000\028\000\025\000\025\000\025\000\ +\025\000\025\000\000\000\000\000\000\000\025\000\025\000\041\000\ +\042\000\043\000\044\000\000\000\000\000\000\000\045\000\046\000\ +\012\000\012\000\012\000\012\000\012\000\005\000\005\000\005\000\ +\005\000\005\000\006\000\006\000\006\000\006\000\006\000\009\000\ +\009\000\009\000\009\000\009\000\007\000\007\000\007\000\007\000\ +\007\000\008\000\008\000\008\000\008\000\008\000\011\000\011\000\ +\011\000\011\000" let yycheck = "\005\000\ -\000\000\004\001\005\000\004\001\001\000\000\000\000\000\000\000\ -\011\000\012\000\026\001\034\001\028\001\003\001\015\001\016\001\ -\017\001\018\001\019\001\020\001\056\000\057\000\058\000\003\001\ -\027\001\061\000\000\000\005\000\006\000\007\000\008\000\009\000\ -\035\000\005\001\006\001\007\001\008\001\012\001\013\001\003\001\ -\012\001\013\001\048\000\049\000\050\000\051\000\052\000\053\000\ -\054\000\055\000\003\001\027\001\000\000\005\001\006\001\007\001\ -\008\001\060\000\035\001\004\001\012\001\013\001\035\001\041\000\ -\042\000\043\000\044\000\045\000\046\000\075\000\035\001\024\001\ -\075\000\035\001\003\001\029\001\004\001\030\001\000\000\001\001\ -\002\001\003\001\035\001\004\001\004\001\255\255\255\255\009\001\ -\010\001\011\001\255\255\255\255\014\001\022\001\008\001\024\001\ -\255\255\255\255\012\001\013\001\022\001\030\001\024\001\255\255\ -\000\000\034\001\035\001\255\255\030\001\031\001\032\001\033\001\ -\034\001\035\001\015\001\016\001\017\001\018\001\019\001\020\001\ -\255\255\005\001\006\001\007\001\008\001\255\255\255\255\255\255\ -\012\001\013\001\000\000\015\001\016\001\017\001\018\001\019\001\ -\020\001\021\001\022\001\023\001\024\001\025\001\004\001\005\001\ -\006\001\007\001\008\001\000\000\255\255\255\255\012\001\013\001\ -\255\255\255\255\255\255\255\255\000\000\021\001\022\001\023\001\ -\024\001\025\001\255\255\255\255\255\255\255\255\000\000\255\255\ -\255\255\255\255\255\255\000\000\255\255\255\255\255\255\255\255\ -\000\000\255\255\255\255\255\255\255\255\000\000\255\255\255\255\ -\255\255\255\255\000\000\255\255\255\255\255\255\255\255\000\000\ +\000\000\034\001\005\000\003\001\003\001\000\000\000\000\000\000\ +\011\000\012\000\001\000\056\000\057\000\058\000\028\001\004\001\ +\061\000\005\000\006\000\007\000\008\000\009\000\022\001\008\001\ +\024\001\024\001\000\000\012\001\013\001\003\001\030\001\030\001\ +\035\000\003\001\034\001\035\001\035\001\026\001\027\001\026\001\ +\027\001\035\001\048\000\049\000\050\000\051\000\052\000\053\000\ +\054\000\055\000\012\001\013\001\000\000\041\000\042\000\043\000\ +\044\000\045\000\046\000\015\001\016\001\017\001\018\001\019\001\ +\020\001\003\001\001\001\002\001\003\001\075\000\004\001\035\001\ +\075\000\255\255\009\001\010\001\011\001\035\001\000\000\014\001\ +\035\001\015\001\016\001\017\001\018\001\019\001\020\001\022\001\ +\035\001\024\001\021\001\022\001\023\001\024\001\025\001\030\001\ +\031\001\032\001\033\001\034\001\035\001\004\001\004\001\004\001\ +\000\000\004\001\005\001\006\001\007\001\008\001\029\001\004\001\ +\255\255\012\001\013\001\005\001\006\001\007\001\008\001\255\255\ +\255\255\000\000\012\001\013\001\005\001\006\001\007\001\008\001\ +\255\255\255\255\000\000\012\001\013\001\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\000\000\255\255\255\255\255\255\ +\255\255\000\000\255\255\255\255\255\255\255\255\000\000\255\255\ +\255\255\255\255\255\255\000\000\255\255\255\255\255\255\255\255\ +\000\000\005\001\006\001\007\001\008\001\000\000\255\255\255\255\ +\012\001\013\001\000\000\015\001\016\001\017\001\018\001\019\001\ +\020\001\021\001\022\001\023\001\024\001\025\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ @@ -256,29 +255,26 @@ \255\255\255\255\255\255\255\255\004\001\005\001\006\001\007\001\ \008\001\004\001\004\001\004\001\012\001\013\001\255\255\015\001\ \016\001\017\001\018\001\019\001\020\001\021\001\022\001\023\001\ -\024\001\025\001\026\001\255\255\028\001\029\001\004\001\005\001\ +\024\001\025\001\026\001\027\001\255\255\029\001\004\001\005\001\ \006\001\007\001\008\001\255\255\255\255\255\255\012\001\013\001\ \255\255\015\001\016\001\017\001\018\001\019\001\020\001\021\001\ -\022\001\023\001\024\001\025\001\026\001\255\255\028\001\029\001\ +\022\001\023\001\024\001\025\001\255\255\255\255\028\001\029\001\ \004\001\005\001\006\001\007\001\008\001\255\255\255\255\255\255\ \012\001\013\001\255\255\015\001\016\001\017\001\018\001\019\001\ -\020\001\021\001\022\001\023\001\024\001\025\001\026\001\255\255\ +\020\001\021\001\022\001\023\001\024\001\025\001\255\255\255\255\ \028\001\029\001\004\001\005\001\006\001\007\001\008\001\255\255\ \255\255\255\255\012\001\013\001\255\255\015\001\016\001\017\001\ \018\001\019\001\020\001\021\001\022\001\023\001\024\001\025\001\ -\255\255\027\001\255\255\029\001\004\001\005\001\006\001\007\001\ +\255\255\255\255\255\255\029\001\004\001\005\001\006\001\007\001\ \008\001\255\255\255\255\255\255\012\001\013\001\255\255\015\001\ -\016\001\017\001\018\001\019\001\020\001\021\001\022\001\023\001\ -\024\001\025\001\255\255\255\255\255\255\029\001\004\001\005\001\ +\016\001\017\001\018\001\019\001\020\001\004\001\005\001\006\001\ +\007\001\008\001\255\255\255\255\255\255\012\001\013\001\005\001\ \006\001\007\001\008\001\255\255\255\255\255\255\012\001\013\001\ -\255\255\015\001\016\001\017\001\018\001\019\001\020\001\004\001\ -\005\001\006\001\007\001\008\001\255\255\255\255\255\255\012\001\ -\013\001\005\001\006\001\007\001\008\001\255\255\255\255\255\255\ -\012\001\013\001\004\001\005\001\006\001\007\001\008\001\004\001\ +\004\001\005\001\006\001\007\001\008\001\004\001\005\001\006\001\ +\007\001\008\001\004\001\005\001\006\001\007\001\008\001\004\001\ \005\001\006\001\007\001\008\001\004\001\005\001\006\001\007\001\ \008\001\004\001\005\001\006\001\007\001\008\001\004\001\005\001\ -\006\001\007\001\008\001\004\001\005\001\006\001\007\001\008\001\ -\004\001\005\001\006\001\007\001" +\006\001\007\001" let yynames_const = "\ LTL_TRUE\000\ @@ -327,361 +323,339 @@ ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'formula) in Obj.repr( -# 85 "src/aorai/ltlparser.mly" +# 89 "src/aorai/ltlparser.mly" ((_1,observed_expressions)) -# 333 "src/aorai/ltlparser.ml" - : (Ltlast.formula * (string, (Cil_types.exp* string*Cil_types.predicate)) Hashtbl.t))) +# 329 "src/aorai/ltlparser.ml" + : (Ltlast.formula * (string, (Logic_ptree.relation * Promelaast.expression * Promelaast.expression)) Hashtbl.t))) ; (fun __caml_parser_env -> Obj.repr( -# 91 "src/aorai/ltlparser.mly" +# 95 "src/aorai/ltlparser.mly" (Ltlast.LTrue) -# 339 "src/aorai/ltlparser.ml" +# 335 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> Obj.repr( -# 93 "src/aorai/ltlparser.mly" +# 97 "src/aorai/ltlparser.mly" (Ltlast.LFalse) -# 345 "src/aorai/ltlparser.ml" +# 341 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'formula) in Obj.repr( -# 95 "src/aorai/ltlparser.mly" +# 99 "src/aorai/ltlparser.mly" ( _2 ) -# 352 "src/aorai/ltlparser.ml" +# 348 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 98 "src/aorai/ltlparser.mly" +# 102 "src/aorai/ltlparser.mly" ( Ltlast.LGlobally(_2) ) -# 359 "src/aorai/ltlparser.ml" +# 355 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 100 "src/aorai/ltlparser.mly" +# 104 "src/aorai/ltlparser.mly" ( Ltlast.LFatally(_2) ) -# 366 "src/aorai/ltlparser.ml" +# 362 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'formula) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 102 "src/aorai/ltlparser.mly" +# 106 "src/aorai/ltlparser.mly" ( Ltlast.LUntil(_1,_3) ) -# 374 "src/aorai/ltlparser.ml" +# 370 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'formula) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 104 "src/aorai/ltlparser.mly" +# 108 "src/aorai/ltlparser.mly" ( Ltlast.LRelease(_1,_3) ) -# 382 "src/aorai/ltlparser.ml" +# 378 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 106 "src/aorai/ltlparser.mly" +# 110 "src/aorai/ltlparser.mly" ( Ltlast.LNext(_2) ) -# 389 "src/aorai/ltlparser.ml" +# 385 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'formula) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 109 "src/aorai/ltlparser.mly" +# 113 "src/aorai/ltlparser.mly" ( Ltlast.LOr(_1,_3) ) -# 397 "src/aorai/ltlparser.ml" +# 393 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'formula) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 111 "src/aorai/ltlparser.mly" +# 115 "src/aorai/ltlparser.mly" ( Ltlast.LAnd(_1,_3) ) -# 405 "src/aorai/ltlparser.ml" +# 401 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 113 "src/aorai/ltlparser.mly" +# 117 "src/aorai/ltlparser.mly" ( Ltlast.LNot(_2) ) -# 412 "src/aorai/ltlparser.ml" +# 408 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'formula) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 115 "src/aorai/ltlparser.mly" +# 119 "src/aorai/ltlparser.mly" ( Ltlast.LImplies(_1,_3) ) -# 420 "src/aorai/ltlparser.ml" +# 416 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'formula) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'formula) in Obj.repr( -# 117 "src/aorai/ltlparser.mly" +# 121 "src/aorai/ltlparser.mly" ( Ltlast.LIff(_1,_3) ) -# 428 "src/aorai/ltlparser.ml" +# 424 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 120 "src/aorai/ltlparser.mly" +# 124 "src/aorai/ltlparser.mly" ( Ltlast.LCall(_3)) -# 435 "src/aorai/ltlparser.ml" +# 431 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 122 "src/aorai/ltlparser.mly" +# 126 "src/aorai/ltlparser.mly" ( Ltlast.LReturn(_3)) -# 442 "src/aorai/ltlparser.ml" +# 438 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 124 "src/aorai/ltlparser.mly" +# 128 "src/aorai/ltlparser.mly" ( Ltlast.LCallOrReturn(_3)) -# 449 "src/aorai/ltlparser.ml" +# 445 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_relation) in Obj.repr( -# 128 "src/aorai/ltlparser.mly" +# 132 "src/aorai/ltlparser.mly" ( let id = get_fresh_ident () in - let (pred,exp) = _1 in - Hashtbl.add observed_expressions id - (exp, (Pretty_utils.sfprintf "%a" Cil.d_exp exp), pred); + Hashtbl.add observed_expressions id _1; Ltlast.LIdent(id) ) -# 462 "src/aorai/ltlparser.ml" +# 456 "src/aorai/ltlparser.ml" : 'formula)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 141 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Req, Logic_utils.expr_to_term ~cast:true _1 ,Logic_utils.expr_to_term ~cast:true _3), - new_exp (BinOp(Cil_types.Eq, _1 , _3 , Cil.intType)) ) - ) -# 472 "src/aorai/ltlparser.ml" +# 140 "src/aorai/ltlparser.mly" + ( Eq, _1 , _3) +# 464 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 145 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Rlt, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (BinOp(Cil_types.Lt, _1 , _3 , Cil.intType)) ) - ) -# 482 "src/aorai/ltlparser.ml" +# 141 "src/aorai/ltlparser.mly" + ( Lt, _1, _3 ) +# 472 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 149 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Rgt, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp(BinOp(Cil_types.Gt, _1 , _3 , Cil.intType)) ) - ) -# 492 "src/aorai/ltlparser.ml" +# 142 "src/aorai/ltlparser.mly" + ( Gt, _1, _3 ) +# 480 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 153 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Rle, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (BinOp(Cil_types.Le, _1 , _3 , Cil.intType) )) - ) -# 502 "src/aorai/ltlparser.ml" +# 143 "src/aorai/ltlparser.mly" + ( Le, _1, _3 ) +# 488 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 157 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Rge, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (BinOp(Cil_types.Ge, _1 , _3 , Cil.intType) )) - ) -# 512 "src/aorai/ltlparser.ml" +# 144 "src/aorai/ltlparser.mly" + ( Ge, _1, _3 ) +# 496 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 161 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (BinOp(Cil_types.Ne , _1 , _3 , Cil.intType) )) - ) -# 522 "src/aorai/ltlparser.ml" +# 145 "src/aorai/ltlparser.mly" + ( Neq, _1, _3 ) +# 504 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 165 "src/aorai/ltlparser.mly" - ( ( Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true _1 , - Logic_const.term - (TConst( CInt64(Int64.of_int 0,IInt,Some("0")))) - (Ctype Cil.intType)), - _1) - ) -# 534 "src/aorai/ltlparser.ml" +# 146 "src/aorai/ltlparser.mly" + ( Neq, _1, PCst (IntConstant "0") ) +# 511 "src/aorai/ltlparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 177 "src/aorai/ltlparser.mly" - ( new_exp (BinOp(Cil_types.PlusA, _1 , _3 , Cil.intType)) ) -# 542 "src/aorai/ltlparser.ml" +# 150 "src/aorai/ltlparser.mly" + ( PBinop(Badd,_1,_3) ) +# 519 "src/aorai/ltlparser.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 179 "src/aorai/ltlparser.mly" - ( new_exp (BinOp(Cil_types.MinusA, _1 , _3 , Cil.intType)) ) -# 550 "src/aorai/ltlparser.ml" +# 151 "src/aorai/ltlparser.mly" + ( PBinop(Bsub,_1,_3) ) +# 527 "src/aorai/ltlparser.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation_mul) in Obj.repr( -# 181 "src/aorai/ltlparser.mly" - ( _1 ) -# 557 "src/aorai/ltlparser.ml" +# 152 "src/aorai/ltlparser.mly" + ( _1 ) +# 534 "src/aorai/ltlparser.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 187 "src/aorai/ltlparser.mly" - ( new_exp (BinOp(Cil_types.Div, _1 , _3 , Cil.intType)) ) -# 565 "src/aorai/ltlparser.ml" +# 157 "src/aorai/ltlparser.mly" + ( PBinop(Bdiv,_1,_3) ) +# 542 "src/aorai/ltlparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 189 "src/aorai/ltlparser.mly" - ( new_exp (BinOp(Cil_types.Mult, _1 , _3 , Cil.intType)) ) -# 573 "src/aorai/ltlparser.ml" +# 158 "src/aorai/ltlparser.mly" + ( PBinop(Bmul,_1,_3) ) +# 550 "src/aorai/ltlparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 191 "src/aorai/ltlparser.mly" - ( new_exp (BinOp(Cil_types.Mod, _1 , _3 , Cil.intType)) ) -# 581 "src/aorai/ltlparser.ml" +# 159 "src/aorai/ltlparser.mly" + ( PBinop(Bmod,_1,_3)) +# 558 "src/aorai/ltlparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 193 "src/aorai/ltlparser.mly" - ( _1 ) -# 588 "src/aorai/ltlparser.ml" +# 160 "src/aorai/ltlparser.mly" + ( _1 ) +# 565 "src/aorai/ltlparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 199 "src/aorai/ltlparser.mly" - ( new_exp (Const(CInt64(Int64.of_string _1,IInt, Some(_1))))) -# 595 "src/aorai/ltlparser.ml" +# 165 "src/aorai/ltlparser.mly" + ( PCst (IntConstant _1) ) +# 572 "src/aorai/ltlparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 201 "src/aorai/ltlparser.mly" - ( new_exp (Const(CInt64(Int64.of_string ("-"^_2),IInt, Some("-"^_2))))) -# 602 "src/aorai/ltlparser.ml" +# 166 "src/aorai/ltlparser.mly" + ( PUnop (Uminus,PCst (IntConstant _2)) ) +# 579 "src/aorai/ltlparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 203 "src/aorai/ltlparser.mly" - ( new_exp (Lval(_1)) ) -# 609 "src/aorai/ltlparser.ml" +# 167 "src/aorai/ltlparser.mly" + ( _1 ) +# 586 "src/aorai/ltlparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'arith_relation) in Obj.repr( -# 205 "src/aorai/ltlparser.mly" - ( _2 ) -# 616 "src/aorai/ltlparser.ml" +# 168 "src/aorai/ltlparser.mly" + ( _2 ) +# 593 "src/aorai/ltlparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 2 : 'access_array) in - let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access) in + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'access) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 212 "src/aorai/ltlparser.mly" - ( Aorai_option.fatal "NOT YET IMPLEMENTED : A->B pointed structure filed access." ) -# 624 "src/aorai/ltlparser.ml" +# 174 "src/aorai/ltlparser.mly" + ( PField (PUnop(Ustar,_1),_3) ) +# 601 "src/aorai/ltlparser.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'access) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 214 "src/aorai/ltlparser.mly" - ( let (my_host,my_offset) = (_1) in - - let new_offset = Utils_parser.add_offset my_offset (Utils_parser.get_new_offset my_host my_offset _3) in - (my_host,new_offset)) -# 635 "src/aorai/ltlparser.ml" +# 175 "src/aorai/ltlparser.mly" + ( PField(_1,_3) ) +# 609 "src/aorai/ltlparser.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_array) in Obj.repr( -# 219 "src/aorai/ltlparser.mly" - (_1) -# 642 "src/aorai/ltlparser.ml" +# 176 "src/aorai/ltlparser.mly" + (_1) +# 616 "src/aorai/ltlparser.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'access_array) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'access_or_const) in Obj.repr( -# 223 "src/aorai/ltlparser.mly" - ( Cil.addOffsetLval (Index (_3,NoOffset)) _1) -# 650 "src/aorai/ltlparser.ml" +# 180 "src/aorai/ltlparser.mly" + ( PArrget(_1,_3) ) +# 624 "src/aorai/ltlparser.ml" : 'access_array)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_leaf) in Obj.repr( -# 225 "src/aorai/ltlparser.mly" - (_1) -# 657 "src/aorai/ltlparser.ml" +# 181 "src/aorai/ltlparser.mly" + (_1) +# 631 "src/aorai/ltlparser.ml" : 'access_array)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 230 "src/aorai/ltlparser.mly" - ( Aorai_option.fatal "NOT YET IMPLEMENTED : &A 'address of' access." ) -# 664 "src/aorai/ltlparser.ml" +# 185 "src/aorai/ltlparser.mly" + ( PUnop (Uamp,_2) ) +# 638 "src/aorai/ltlparser.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 232 "src/aorai/ltlparser.mly" - ( Aorai_option.fatal "NOT YET IMPLEMENTED : *A dereferencement access.") -# 671 "src/aorai/ltlparser.ml" +# 186 "src/aorai/ltlparser.mly" + ( PUnop (Ustar, _2 ) ) +# 645 "src/aorai/ltlparser.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 234 "src/aorai/ltlparser.mly" - ( Cil.var ( Data_for_aorai.get_varinfo _1) ) -# 678 "src/aorai/ltlparser.ml" +# 187 "src/aorai/ltlparser.mly" + ( PVar _1 ) +# 652 "src/aorai/ltlparser.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'access) in Obj.repr( -# 236 "src/aorai/ltlparser.mly" - ( _2 ) -# 685 "src/aorai/ltlparser.ml" +# 188 "src/aorai/ltlparser.mly" + ( _2 ) +# 659 "src/aorai/ltlparser.ml" : 'access_leaf)) (* Entry ltl *) ; (fun __caml_parser_env -> raise (Parsing.YYexit (Parsing.peek_val __caml_parser_env 0))) @@ -704,4 +678,4 @@ Parsing.names_const=yynames_const; Parsing.names_block=yynames_block } let ltl (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) = - (Parsing.yyparse yytables 1 lexfun lexbuf : (Ltlast.formula * (string, (Cil_types.exp* string*Cil_types.predicate)) Hashtbl.t)) + (Parsing.yyparse yytables 1 lexfun lexbuf : (Ltlast.formula * (string, (Logic_ptree.relation * Promelaast.expression * Promelaast.expression)) Hashtbl.t)) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltlparser.mli frama-c-20111001+nitrogen+dfsg/src/aorai/ltlparser.mli --- frama-c-20110201+carbon+dfsg/src/aorai/ltlparser.mli 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltlparser.mli 2011-10-10 08:48:50.000000000 +0000 @@ -37,4 +37,4 @@ | EOF val ltl : - (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Ltlast.formula * (string, (Cil_types.exp* string*Cil_types.predicate)) Hashtbl.t) + (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Ltlast.formula * (string, (Logic_ptree.relation * Promelaast.expression * Promelaast.expression)) Hashtbl.t) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/ltlparser.mly frama-c-20111001+nitrogen+dfsg/src/aorai/ltlparser.mly --- frama-c-20110201+carbon+dfsg/src/aorai/ltlparser.mly 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/ltlparser.mly 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ /**************************************************************************/ /* */ -/* This file is part of Frama-C. */ +/* This file is part of Aorai plug-in of Frama-C. */ /* */ /* Copyright (C) 2007-2011 */ -/* INSA (Institut National des Sciences Appliquees) */ +/* CEA (Commissariat a l'énergie atomique et aux énergies */ +/* alternatives) */ /* INRIA (Institut National de Recherche en Informatique et en */ /* Automatique) */ +/* INSA (Institut National des Sciences Appliquees) */ /* */ /* you can redistribute it and/or modify it under the terms of the GNU */ /* Lesser General Public License as published by the Free Software */ @@ -25,9 +27,11 @@ /* Originated from http://www.ltl2dstar.de/down/ltl2dstar-0.4.2.zip */ %{ +open Promelaast open Parsing open Cil_types open Cil +open Logic_ptree let observed_expressions=Hashtbl.create 97 @@ -77,7 +81,7 @@ %token EOF -%type <(Ltlast.formula * (string, (Cil_types.exp* string*Cil_types.predicate)) Hashtbl.t)> ltl +%type <(Ltlast.formula * (string, (Logic_ptree.relation * Promelaast.expression * Promelaast.expression)) Hashtbl.t)> ltl %start ltl %% @@ -127,112 +131,60 @@ | logic_relation { let id = get_fresh_ident () in - let (pred,exp) = $1 in - Hashtbl.add observed_expressions id - (exp, (Pretty_utils.sfprintf "%a" Cil.d_exp exp), pred); + Hashtbl.add observed_expressions id $1; Ltlast.LIdent(id) } ; - -/* returns a (Cil_types.predicate,Cil_types.exp) couple of expressions */ logic_relation - : arith_relation LTL_EQ arith_relation - { ( Prel(Cil_types.Req, Logic_utils.expr_to_term ~cast:true $1 ,Logic_utils.expr_to_term ~cast:true $3), - new_exp (BinOp(Cil_types.Eq, $1 , $3 , Cil.intType)) ) - } - | arith_relation LTL_LT arith_relation - { ( Prel(Cil_types.Rlt, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (BinOp(Cil_types.Lt, $1 , $3 , Cil.intType)) ) - } - | arith_relation LTL_GT arith_relation - { ( Prel(Cil_types.Rgt, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp(BinOp(Cil_types.Gt, $1 , $3 , Cil.intType)) ) - } - | arith_relation LTL_LE arith_relation - { ( Prel(Cil_types.Rle, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (BinOp(Cil_types.Le, $1 , $3 , Cil.intType) )) - } - | arith_relation LTL_GE arith_relation - { ( Prel(Cil_types.Rge, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (BinOp(Cil_types.Ge, $1 , $3 , Cil.intType) )) - } - | arith_relation LTL_NEQ arith_relation - { ( Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (BinOp(Cil_types.Ne , $1 , $3 , Cil.intType) )) - } - | arith_relation - { ( Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true $1 , - Logic_const.term - (TConst( CInt64(Int64.of_int 0,IInt,Some("0")))) - (Ctype Cil.intType)), - $1) - } - + : arith_relation LTL_EQ arith_relation { Eq, $1 , $3} + | arith_relation LTL_LT arith_relation { Lt, $1, $3 } + | arith_relation LTL_GT arith_relation { Gt, $1, $3 } + | arith_relation LTL_LE arith_relation { Le, $1, $3 } + | arith_relation LTL_GE arith_relation { Ge, $1, $3 } + | arith_relation LTL_NEQ arith_relation { Neq, $1, $3 } + | arith_relation { Neq, $1, PCst (IntConstant "0") } ; -/* returns a Cil_types.exp expression */ arith_relation - : arith_relation_mul LTL_PLUS arith_relation - { new_exp (BinOp(Cil_types.PlusA, $1 , $3 , Cil.intType)) } - | arith_relation_mul LTL_MINUS arith_relation - { new_exp (BinOp(Cil_types.MinusA, $1 , $3 , Cil.intType)) } - | arith_relation_mul - { $1 } + : arith_relation_mul LTL_PLUS arith_relation { PBinop(Badd,$1,$3) } + | arith_relation_mul LTL_MINUS arith_relation { PBinop(Bsub,$1,$3) } + | arith_relation_mul { $1 } ; arith_relation_mul - : arith_relation_mul LTL_DIV access_or_const - { new_exp (BinOp(Cil_types.Div, $1 , $3 , Cil.intType)) } - | arith_relation_mul LTL_STAR access_or_const - { new_exp (BinOp(Cil_types.Mult, $1 , $3 , Cil.intType)) } - | arith_relation_mul LTL_MODULO access_or_const - { new_exp (BinOp(Cil_types.Mod, $1 , $3 , Cil.intType)) } - | access_or_const - { $1 } + : arith_relation_mul LTL_DIV access_or_const { PBinop(Bdiv,$1,$3) } + | arith_relation_mul LTL_STAR access_or_const { PBinop(Bmul,$1,$3) } + | arith_relation_mul LTL_MODULO access_or_const { PBinop(Bmod,$1,$3)} + | access_or_const { $1 } ; /* returns a Lval exp or a Const exp*/ access_or_const - : LTL_INT - { new_exp (Const(CInt64(Int64.of_string $1,IInt, Some($1))))} - | LTL_MINUS LTL_INT - { new_exp (Const(CInt64(Int64.of_string ("-"^$2),IInt, Some("-"^$2))))} - | access - { new_exp (Lval($1)) } - | LTL_LPAREN arith_relation LTL_RPAREN - { $2 } + : LTL_INT { PCst (IntConstant $1) } + | LTL_MINUS LTL_INT { PUnop (Uminus,PCst (IntConstant $2)) } + | access { $1 } + | LTL_LPAREN arith_relation LTL_RPAREN { $2 } ; /* returns a lval */ access - : access_array LTL_RIGHT_ARROW access - { Aorai_option.fatal "NOT YET IMPLEMENTED : A->B pointed structure filed access." } - | access LTL_DOT LTL_LABEL - { let (my_host,my_offset) = ($1) in - - let new_offset = Utils_parser.add_offset my_offset (Utils_parser.get_new_offset my_host my_offset $3) in - (my_host,new_offset)} - | access_array - {$1} + : access LTL_RIGHT_ARROW LTL_LABEL { PField (PUnop(Ustar,$1),$3) } + | access LTL_DOT LTL_LABEL { PField($1,$3) } + | access_array {$1} access_array : access_array LTL_LEFT_SQUARE access_or_const LTL_RIGHT_SQUARE - { Cil.addOffsetLval (Index ($3,NoOffset)) $1} - | access_leaf - {$1} + { PArrget($1,$3) } + | access_leaf {$1} access_leaf - : LTL_ADRESSE access - { Aorai_option.fatal "NOT YET IMPLEMENTED : &A 'address of' access." } - | LTL_STAR access - { Aorai_option.fatal "NOT YET IMPLEMENTED : *A dereferencement access."} - | LTL_LABEL - { Cil.var ( Data_for_aorai.get_varinfo $1) } - | LTL_LPAREN access LTL_RPAREN - { $2 } + : LTL_ADRESSE access { PUnop (Uamp,$2) } + | LTL_STAR access { PUnop (Ustar, $2 ) } + | LTL_LABEL { PVar $1 } + | LTL_LPAREN access LTL_RPAREN { $2 } ; diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/Makefile.in frama-c-20111001+nitrogen+dfsg/src/aorai/Makefile.in --- frama-c-20110201+carbon+dfsg/src/aorai/Makefile.in 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/Makefile.in 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ ########################################################################## # # -# This file is part of Frama-C. # +# This file is part of Aorai plug-in of Frama-C. # # # # Copyright (C) 2007-2011 # -# INSA (Institut National des Sciences Appliquees) # +# CEA (Commissariat a l'énergie atomique et aux énergies # +# alternatives) # # INRIA (Institut National de Recherche en Informatique et en # # Automatique) # +# INSA (Institut National des Sciences Appliquees) # # # # you can redistribute it and/or modify it under the terms of the GNU # # Lesser General Public License as published by the Free Software # @@ -50,9 +52,9 @@ aorai_option \ cil_manipulation \ path_analysis \ - data_for_aorai \ promelaoutput \ logic_simplification \ + data_for_aorai \ aorai_utils \ ltl_output \ utils_parser \ @@ -68,8 +70,7 @@ bycase_ai \ aorai_visitors \ aorai_register -PLUGIN_CMI:= ltlast \ - promelaast +PLUGIN_CMI:= ltlast promelaast PLUGIN_HAS_MLI:=yes @@ -84,8 +85,6 @@ PLUGIN_NO_DEFAULT_TEST:=yes endif -PLUGIN_INTERNAL_TEST:=yes - include $(FRAMAC_SHARE)/Makefile.dynamic # Regenerating the Makefile on need diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/path_analysis.ml frama-c-20111001+nitrogen+dfsg/src/aorai/path_analysis.ml --- frama-c-20110201+carbon+dfsg/src/aorai/path_analysis.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/path_analysis.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -73,28 +75,11 @@ ;; *) - - - - - - - - - -let trans_l = ref [] ;; -let states_l = ref [] ;; - - - -let voisins st = +let voisins (_,trans_l) st = List.fold_left - (fun vl tr -> - if tr.start.nums=st.nums then (tr.stop,1)::vl else vl - ) + (fun vl tr -> if tr.start.nums=st.nums then (tr.stop,1)::vl else vl) [] - !trans_l - + trans_l let empty () = [] ;; let is_empty heap = (List.length heap)=0 ;; @@ -141,9 +126,7 @@ -let existing_path (stl,trl) stn1 stn2 = - states_l:=stl; - trans_l:=trl; +let existing_path (stl,_ as auto) stn1 stn2 = let st1 = ref (List.hd stl) in let st2 = ref (List.hd stl) in List.iter @@ -154,33 +137,54 @@ stl; try - let _ = dijkstra voisins !st1 !st2 in + let _ = dijkstra (voisins auto) !st1 !st2 in true with | Not_found -> false ;; +(** since Nitrogen-20111001 *) +let get_transitions_of_state st (_,tr) = + List.fold_left + (fun acc tr -> + if tr.start.nums = st.nums then tr::acc else acc) + [] tr +let get_transitions_to_state st (_,tr) = + List.fold_left + (fun acc tr -> + if tr.stop.nums = st.nums then tr::acc else acc) + [] tr +let get_init_states (st,_) = List.filter (fun x -> x.init = Bool3.True) st +let at_most_one_path (states,transitions as auto) st1 st2 = + try + let path,_ = dijkstra (voisins auto) st1 st2 in + match path with + | [] | [ _ ] -> true + | x::y::_ -> + let (trans1,trans2) = + List.partition + (fun t -> t.start.nums = x.nums && t.stop.nums = y.nums) + transitions + in + let transitions = (List.tl trans1) @ trans2 in + let auto = states, transitions in + ignore (dijkstra (voisins auto) st1 st2); + false + with Not_found -> true -let test (stl,trl) = - states_l:=stl; - trans_l:=trl; - +let test (stl,_ as auto) = let st2 = List.hd stl in let st1 = List.hd (List.tl stl) in - Aorai_option.feedback "%s" ("test : Etats choisis ("^(string_of_int st1.nums)^","^(string_of_int st2.nums)^")\n") ; - - let (res,_) = dijkstra voisins st1 st2 in - Aorai_option.feedback "Fini.\n[" ; - List.iter - (fun st -> Aorai_option.feedback "%d," st.nums) - res; - Aorai_option.feedback "]\n" ; - () - + Aorai_option.feedback "test : Etats choisis (%d,%d)" st1.nums st2.nums; + let (res,_) = dijkstra (voisins auto) st1 st2 in + Aorai_option.feedback "Fini.@\n%a" + (Pretty_utils.pp_list ~pre:"@[[" ~sep:",@ " ~suf:"@]]" + (fun fmt st -> Format.fprintf fmt "%d" st.nums)) + res (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaast.mli frama-c-20111001+nitrogen+dfsg/src/aorai/promelaast.mli --- frama-c-20110201+carbon+dfsg/src/aorai/promelaast.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaast.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,27 +23,85 @@ (* *) (**************************************************************************) -(** The abstract tree of promela representation. Such tree is used by promela parser/lexer before its translation into Data_for_aorai module. *) +(** The abstract tree of promela representation. Such tree is used by promela + parser/lexer before its translation into Data_for_aorai module. *) + +type expression = + | PVar of string + | PPrm of string * string (* f().N *) + | PCst of Logic_ptree.constant + | PBinop of Logic_ptree.binop * expression * expression + | PUnop of Logic_ptree.unop * expression + | PArrget of expression * expression + | PField of expression * string + | PArrow of expression * string -(** Promela parsed abstract syntax trees *) type condition = - | POr of condition * condition (** Logical OR *) - | PAnd of condition * condition (** Logical AND *) - | PNot of condition (** Logical NOT *) - | PCall of string (** Predicate modelling the call of an operation *) - | PReturn of string (** Predicate modelling the return of an operation *) - | PCallOrReturn of string (** Predicate modelling the call or the return of an operation *) - | PTrue (** Logical constant TRUE *) - | PFalse (** Logical constant FALSE *) - | PIndexedExp of string (** Variable introduced during ltl pre-process. - It correponds to an expression managed by the Data_for_aorai module. *) - | PFuncParam of string * string * (string list) - (** Resp HashIndex, Func name, param name list. - When function call, constraints can be expressed on its params. *) - | PFuncReturn of string * string - (** Resp HashIndex, Func name. - When function call, constraints can be expressed on its returned value. *) + | PRel of Logic_ptree.relation * expression * expression + | PTrue + | PFalse + | POr of condition * condition + | PAnd of condition * condition + | PNot of condition + | PCall of string * string option + (** Call might be done in a given behavior *) + | PReturn of string + +and seq_elt = + { condition: condition option; + nested: sequence; + min_rep: expression option; + max_rep: expression option; + } + +and sequence = seq_elt list + +(** Promela parsed abstract syntax trees. Either a sequence of event or the + otherwise keyword. A single condition is expressed with a singleton + having an empty nested sequence and min_rep and max_rep being equal to one. +*) +type parsed_condition = Seq of sequence | Otherwise +type typed_condition = + | TOr of typed_condition * typed_condition (** Logical OR *) + | TAnd of typed_condition * typed_condition (** Logical AND *) + | TNot of typed_condition (** Logical NOT *) + | TCall of Cil_types.kernel_function * Cil_types.funbehavior option + (** Predicate modelling the call of an operation *) + | TReturn of Cil_types.kernel_function + (** Predicate modelling the return of an operation *) + | TTrue (** Logical constant TRUE *) + | TFalse (** Logical constant FALSE *) + | TRel of Cil_types.relation * Cil_types.term * Cil_types.term + (** Condition. If one of the terms contains TResult, TRel is in + conjunction with exactly one TReturn event, and the TResult is + tied to the corresponding value. + *) + +type single_action = + | Counter_init of Cil_types.term_lval + | Counter_incr of Cil_types.term_lval + | Pebble_init of + Cil_types.logic_info * Cil_types.logic_var * Cil_types.logic_var + (** adds a new pebble. [Pebble_init(set,aux,count)] indicates that + pebble [count] is put in [set] whose content is governed by C + variable [aux]. + *) + | Pebble_move of + Cil_types.logic_info * + Cil_types.logic_var * Cil_types.logic_info * Cil_types.logic_var + (** [Pebble_move(new_set,new_aux,old_set,old_aux)] + moves pebbles from [old_set] to [new_set], governed by the + corresponding aux variables. *) + | Copy_value of Cil_types.term_lval * Cil_types.term + (** copy the current value of the given term into the given location + so that it can be accessed by a later state. *) + +(** Additional actions to perform when crossing a transition. + There is at most one Pebble_* action for each transition, and + each transition leading to a state with multi-state has such an action. + *) +type action = single_action list (** Internal representation of a State from the Buchi automata. *) type state = @@ -49,18 +109,33 @@ mutable acceptation : Bool3.t (** True iff state is an acceptation state *); mutable init : Bool3.t (** True iff state is an initial state *); - mutable nums : int (** Numerical ID of the state *) } + mutable nums : int; (** Numerical ID of the state *) + mutable multi_state: + (Cil_types.logic_info * Cil_types.logic_var) option + (** Translation of some sequences might lead to some kind of pebble + automaton, where we need to distinguish various branches. This is + done by having a set of pebbles instead of just a zero/one switch + to know if we are in the given state. The guards apply to each + active pebble and are thus of the form + \forall integer x; in(x,multi_state) ==> guard. + multi_state is the first lvar of the pair, x is the second + *) + } (** Internal representation of a transition from the Buchi automata. *) -type trans = { start : state ; (** Starting state of the transition *) - stop : state ; (** Ending state of the transition *) - cross : condition ; (** Cross condition of the transition *) - mutable numt : int (** Numerical ID of the transition *) - } +type 'condition trans = + { start : state ; (** Starting state of the transition *) + stop : state ; (** Ending state of the transition *) + mutable cross : 'condition ; (** Cross condition of the transition *) + mutable numt : int (** Numerical ID of the transition *) + } (** Internal representation of a Buchi automata : a list of states and a list of transitions.*) -type buchautomata = (state list) * (trans list) +type 'condition automaton = (state list) * ('condition trans list) + +type parsed_automaton = parsed_condition automaton +type typed_automaton = (typed_condition * action) automaton (** An operation can have two status: currently calling or returning. *) type funcStatus = diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelalexer.ml frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer.ml --- frama-c-20110201+carbon+dfsg/src/aorai/promelalexer.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer.ml 2011-10-10 08:48:50.000000000 +0000 @@ -1,27 +1,24 @@ -# 28 "src/aorai/promelalexer.mll" +# 30 "src/aorai/promelalexer.mll" open Promelaparser open Promelaast open Lexing - exception Error of ((Lexing.position * Lexing.position) option) * string - - let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) - - let raise_located loc e = raise (Error (Some (loc), e)) + exception Error of (Lexing.position * Lexing.position) * string + let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) + let raise_located loc e = raise (Error (loc, e)) let buf = Buffer.create 1024 let newline lexbuf = let pos = lexbuf.lex_curr_p in - lexbuf.lex_curr_p <- + lexbuf.lex_curr_p <- { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } - -# 25 "src/aorai/promelalexer.ml" +# 22 "src/aorai/promelalexer.ml" let __ocaml_lex_tables = { Lexing.lex_base = "\000\000\224\255\225\255\226\255\078\000\160\000\235\000\001\000\ @@ -1176,231 +1173,231 @@ } let rec token lexbuf = - __ocaml_lex_token_rec lexbuf 0 + __ocaml_lex_token_rec lexbuf 0 and __ocaml_lex_token_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 59 "src/aorai/promelalexer.mll" +# 55 "src/aorai/promelalexer.mll" ( PROMELA_TRUE ) -# 1186 "src/aorai/promelalexer.ml" +# 1183 "src/aorai/promelalexer.ml" | 1 -> -# 60 "src/aorai/promelalexer.mll" - ( PROMELA_NEVER ) -# 1191 "src/aorai/promelalexer.ml" +# 56 "src/aorai/promelalexer.mll" + ( PROMELA_NEVER ) +# 1188 "src/aorai/promelalexer.ml" | 2 -> -# 61 "src/aorai/promelalexer.mll" - ( PROMELA_IF ) -# 1196 "src/aorai/promelalexer.ml" +# 57 "src/aorai/promelalexer.mll" + ( PROMELA_IF ) +# 1193 "src/aorai/promelalexer.ml" | 3 -> -# 62 "src/aorai/promelalexer.mll" - ( PROMELA_FI ) -# 1201 "src/aorai/promelalexer.ml" +# 58 "src/aorai/promelalexer.mll" + ( PROMELA_FI ) +# 1198 "src/aorai/promelalexer.ml" | 4 -> -# 63 "src/aorai/promelalexer.mll" - ( PROMELA_GOTO ) -# 1206 "src/aorai/promelalexer.ml" +# 59 "src/aorai/promelalexer.mll" + ( PROMELA_GOTO ) +# 1203 "src/aorai/promelalexer.ml" | 5 -> -# 64 "src/aorai/promelalexer.mll" - ( PROMELA_SKIP ) -# 1211 "src/aorai/promelalexer.ml" +# 60 "src/aorai/promelalexer.mll" + ( PROMELA_SKIP ) +# 1208 "src/aorai/promelalexer.ml" | 6 -> -# 65 "src/aorai/promelalexer.mll" - ( PROMELA_DOUBLE_COLON ) -# 1216 "src/aorai/promelalexer.ml" +# 61 "src/aorai/promelalexer.mll" + ( PROMELA_DOUBLE_COLON ) +# 1213 "src/aorai/promelalexer.ml" | 7 -> -# 66 "src/aorai/promelalexer.mll" - ( PROMELA_COLON ) -# 1221 "src/aorai/promelalexer.ml" +# 62 "src/aorai/promelalexer.mll" + ( PROMELA_COLON ) +# 1218 "src/aorai/promelalexer.ml" | 8 -> -# 67 "src/aorai/promelalexer.mll" - ( PROMELA_SEMICOLON ) -# 1226 "src/aorai/promelalexer.ml" +# 63 "src/aorai/promelalexer.mll" + ( PROMELA_SEMICOLON ) +# 1223 "src/aorai/promelalexer.ml" | 9 -> -# 68 "src/aorai/promelalexer.mll" - ( PROMELA_LPAREN ) -# 1231 "src/aorai/promelalexer.ml" +# 64 "src/aorai/promelalexer.mll" + ( PROMELA_LPAREN ) +# 1228 "src/aorai/promelalexer.ml" | 10 -> -# 69 "src/aorai/promelalexer.mll" - ( PROMELA_RPAREN ) -# 1236 "src/aorai/promelalexer.ml" +# 65 "src/aorai/promelalexer.mll" + ( PROMELA_RPAREN ) +# 1233 "src/aorai/promelalexer.ml" | 11 -> -# 70 "src/aorai/promelalexer.mll" - ( PROMELA_LBRACE ) -# 1241 "src/aorai/promelalexer.ml" +# 66 "src/aorai/promelalexer.mll" + ( PROMELA_LBRACE ) +# 1238 "src/aorai/promelalexer.ml" | 12 -> -# 71 "src/aorai/promelalexer.mll" - ( PROMELA_RBRACE ) -# 1246 "src/aorai/promelalexer.ml" +# 67 "src/aorai/promelalexer.mll" + ( PROMELA_RBRACE ) +# 1243 "src/aorai/promelalexer.ml" | 13 -> -# 72 "src/aorai/promelalexer.mll" - ( PROMELA_RIGHT_ARROW ) -# 1251 "src/aorai/promelalexer.ml" +# 68 "src/aorai/promelalexer.mll" + ( PROMELA_RIGHT_ARROW ) +# 1248 "src/aorai/promelalexer.ml" | 14 -> -# 73 "src/aorai/promelalexer.mll" +# 69 "src/aorai/promelalexer.mll" ( PROMELA_FALSE ) -# 1256 "src/aorai/promelalexer.ml" +# 1253 "src/aorai/promelalexer.ml" | 15 -> -# 74 "src/aorai/promelalexer.mll" +# 70 "src/aorai/promelalexer.mll" ( PROMELA_OR ) -# 1261 "src/aorai/promelalexer.ml" +# 1258 "src/aorai/promelalexer.ml" | 16 -> -# 75 "src/aorai/promelalexer.mll" +# 71 "src/aorai/promelalexer.mll" ( PROMELA_AND ) -# 1266 "src/aorai/promelalexer.ml" +# 1263 "src/aorai/promelalexer.ml" | 17 -> -# 76 "src/aorai/promelalexer.mll" +# 72 "src/aorai/promelalexer.mll" ( PROMELA_NOT ) -# 1271 "src/aorai/promelalexer.ml" +# 1268 "src/aorai/promelalexer.ml" | 18 -> -# 77 "src/aorai/promelalexer.mll" +# 73 "src/aorai/promelalexer.mll" ( token lexbuf ) -# 1276 "src/aorai/promelalexer.ml" +# 1273 "src/aorai/promelalexer.ml" | 19 -> -# 78 "src/aorai/promelalexer.mll" +# 74 "src/aorai/promelalexer.mll" ( newline lexbuf; token lexbuf ) -# 1281 "src/aorai/promelalexer.ml" +# 1278 "src/aorai/promelalexer.ml" | 20 -> -# 79 "src/aorai/promelalexer.mll" +# 75 "src/aorai/promelalexer.mll" ( comment lexbuf; token lexbuf ) -# 1286 "src/aorai/promelalexer.ml" +# 1283 "src/aorai/promelalexer.ml" | 21 -> -# 80 "src/aorai/promelalexer.mll" +# 76 "src/aorai/promelalexer.mll" ( newline lexbuf; token lexbuf ) -# 1291 "src/aorai/promelalexer.ml" +# 1288 "src/aorai/promelalexer.ml" | 22 -> -# 83 "src/aorai/promelalexer.mll" - ( let s=(lexeme lexbuf) in - let s=String.sub s 7 ((String.length s)-7) in +# 79 "src/aorai/promelalexer.mll" + ( let s=(lexeme lexbuf) in + let s=String.sub s 7 ((String.length s)-7) in PROMELA_CALLOF s ) -# 1298 "src/aorai/promelalexer.ml" +# 1295 "src/aorai/promelalexer.ml" | 23 -> -# 87 "src/aorai/promelalexer.mll" - ( let s=(lexeme lexbuf) in - let s=String.sub s 9 ((String.length s)-9) in +# 83 "src/aorai/promelalexer.mll" + ( let s=(lexeme lexbuf) in + let s=String.sub s 9 ((String.length s)-9) in PROMELA_RETURNOF s ) -# 1305 "src/aorai/promelalexer.ml" +# 1302 "src/aorai/promelalexer.ml" | 24 -> -# 91 "src/aorai/promelalexer.mll" - ( let s=(lexeme lexbuf) in - let s=String.sub s 15 ((String.length s)-15) in +# 87 "src/aorai/promelalexer.mll" + ( let s=(lexeme lexbuf) in + let s=String.sub s 15 ((String.length s)-15) in PROMELA_CALLORRETURNOF s ) -# 1312 "src/aorai/promelalexer.ml" +# 1309 "src/aorai/promelalexer.ml" | 25 -> -# 96 "src/aorai/promelalexer.mll" +# 92 "src/aorai/promelalexer.mll" ( raise_located (loc lexbuf) "Illegal fonction name in Promela file." ) -# 1317 "src/aorai/promelalexer.ml" +# 1314 "src/aorai/promelalexer.ml" | 26 -> -# 97 "src/aorai/promelalexer.mll" +# 93 "src/aorai/promelalexer.mll" ( raise_located (loc lexbuf) "Illegal fonction name in Promela file." ) -# 1322 "src/aorai/promelalexer.ml" +# 1319 "src/aorai/promelalexer.ml" | 27 -> -# 98 "src/aorai/promelalexer.mll" +# 94 "src/aorai/promelalexer.mll" ( raise_located (loc lexbuf) "Illegal fonction name in Promela file." ) -# 1327 "src/aorai/promelalexer.ml" +# 1324 "src/aorai/promelalexer.ml" | 28 -> -# 102 "src/aorai/promelalexer.mll" +# 98 "src/aorai/promelalexer.mll" ( let s = lexeme lexbuf in - PROMELA_LABEL s ) -# 1333 "src/aorai/promelalexer.ml" + PROMELA_LABEL s ) +# 1330 "src/aorai/promelalexer.ml" | 29 -> -# 104 "src/aorai/promelalexer.mll" +# 100 "src/aorai/promelalexer.mll" ( EOF ) -# 1338 "src/aorai/promelalexer.ml" +# 1335 "src/aorai/promelalexer.ml" | 30 -> -# 106 "src/aorai/promelalexer.mll" +# 102 "src/aorai/promelalexer.mll" ( PROMELA_TRUE ) -# 1343 "src/aorai/promelalexer.ml" +# 1340 "src/aorai/promelalexer.ml" | 31 -> -# 107 "src/aorai/promelalexer.mll" +# 103 "src/aorai/promelalexer.mll" ( Aorai_option.error "Illegal_character : '%s'\n" (lexeme lexbuf); - raise Parsing.Parse_error) -# 1349 "src/aorai/promelalexer.ml" + raise Parsing.Parse_error) +# 1346 "src/aorai/promelalexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state and comment lexbuf = - __ocaml_lex_comment_rec lexbuf 79 + __ocaml_lex_comment_rec lexbuf 79 and __ocaml_lex_comment_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 114 "src/aorai/promelalexer.mll" +# 110 "src/aorai/promelalexer.mll" ( () ) -# 1360 "src/aorai/promelalexer.ml" +# 1357 "src/aorai/promelalexer.ml" | 1 -> -# 115 "src/aorai/promelalexer.mll" +# 111 "src/aorai/promelalexer.mll" ( Aorai_option.error "Unterminated_comment\n" (*lex_error lexbuf "Unterminated_comment"*) ) -# 1365 "src/aorai/promelalexer.ml" +# 1362 "src/aorai/promelalexer.ml" | 2 -> -# 116 "src/aorai/promelalexer.mll" +# 112 "src/aorai/promelalexer.mll" ( newline lexbuf; comment lexbuf ) -# 1370 "src/aorai/promelalexer.ml" +# 1367 "src/aorai/promelalexer.ml" | 3 -> -# 117 "src/aorai/promelalexer.mll" +# 113 "src/aorai/promelalexer.mll" ( comment lexbuf ) -# 1375 "src/aorai/promelalexer.ml" +# 1372 "src/aorai/promelalexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_comment_rec lexbuf __ocaml_lex_state ;; -# 120 "src/aorai/promelalexer.mll" +# 116 "src/aorai/promelalexer.mll" let parse c = let lb = from_channel c in try Promelaparser.promela token lb - with - Parsing.Parse_error - | Invalid_argument _ -> - let (a,b)=(loc lb) in - Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); -(* Format.print_string "Syntax error (" ; *) -(* Format.print_string "l" ; *) -(* Format.print_int a.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) -(* Format.print_string " -> l" ; *) -(* Format.print_int b.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) -(* Format.print_string ")\n" ; *) - raise_located (loc lb) "Syntax error" - - + with + Parsing.Parse_error + | Invalid_argument _ -> + let (a,b)=(loc lb) in + Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); +(* Format.print_string "Syntax error (" ; *) +(* Format.print_string "l" ; *) +(* Format.print_int a.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) +(* Format.print_string " -> l" ; *) +(* Format.print_int b.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) +(* Format.print_string ")\n" ; *) + raise_located (loc lb) "Syntax error" + + -# 1407 "src/aorai/promelalexer.ml" +# 1404 "src/aorai/promelalexer.ml" diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelalexer.mll frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer.mll --- frama-c-20110201+carbon+dfsg/src/aorai/promelalexer.mll 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer.mll 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -31,45 +33,39 @@ open Promelaast open Lexing - exception Error of ((Lexing.position * Lexing.position) option) * string - - let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) - - let raise_located loc e = raise (Error (Some (loc), e)) + exception Error of (Lexing.position * Lexing.position) * string + let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) + let raise_located loc e = raise (Error (loc, e)) let buf = Buffer.create 1024 let newline lexbuf = let pos = lexbuf.lex_curr_p in - lexbuf.lex_curr_p <- + lexbuf.lex_curr_p <- { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } - } - - - -let rD = ['0'-'9'] +let rD = ['0'-'9'] let rL = ['a'-'z' 'A'-'Z' '_'] rule token = parse | "true" { PROMELA_TRUE } - | "never" { PROMELA_NEVER } - | "if" { PROMELA_IF } - | "fi" { PROMELA_FI } - | "goto" { PROMELA_GOTO } - | "skip" { PROMELA_SKIP } - | "::" { PROMELA_DOUBLE_COLON } - | ':' { PROMELA_COLON } - | ';' { PROMELA_SEMICOLON } - | '(' { PROMELA_LPAREN } - | ')' { PROMELA_RPAREN } - | '{' { PROMELA_LBRACE } - | '}' { PROMELA_RBRACE } - | "->" { PROMELA_RIGHT_ARROW } + | "never" { PROMELA_NEVER } + | "if" { PROMELA_IF } + | "fi" { PROMELA_FI } + | "goto" { PROMELA_GOTO } + | "skip" { PROMELA_SKIP } + | "::" { PROMELA_DOUBLE_COLON } + | ':' { PROMELA_COLON } + | ';' { PROMELA_SEMICOLON } + | '(' { PROMELA_LPAREN } + | ')' { PROMELA_RPAREN } + | '{' { PROMELA_LBRACE } + | '}' { PROMELA_RBRACE } + | "->" { PROMELA_RIGHT_ARROW } | "false" { PROMELA_FALSE } | "||" { PROMELA_OR } | "&&" { PROMELA_AND } @@ -79,33 +75,33 @@ | "/*" { comment lexbuf; token lexbuf } | "//" [^ '\n']* '\n' { newline lexbuf; token lexbuf } - | "callof_" rL* (rL | rD)* - { let s=(lexeme lexbuf) in - let s=String.sub s 7 ((String.length s)-7) in + | "callof_" rL* (rL | rD)* + { let s=(lexeme lexbuf) in + let s=String.sub s 7 ((String.length s)-7) in PROMELA_CALLOF s } - | "returnof_" rL* (rL | rD)* - { let s=(lexeme lexbuf) in - let s=String.sub s 9 ((String.length s)-9) in + | "returnof_" rL* (rL | rD)* + { let s=(lexeme lexbuf) in + let s=String.sub s 9 ((String.length s)-9) in PROMELA_RETURNOF s } - | "callorreturnof_" rL* (rL | rD)* - { let s=(lexeme lexbuf) in - let s=String.sub s 15 ((String.length s)-15) in + | "callorreturnof_" rL* (rL | rD)* + { let s=(lexeme lexbuf) in + let s=String.sub s 15 ((String.length s)-15) in PROMELA_CALLORRETURNOF s } | "callof_" { raise_located (loc lexbuf) "Illegal fonction name in Promela file." } | "returnof_" { raise_located (loc lexbuf) "Illegal fonction name in Promela file." } | "callorreturnof_" { raise_located (loc lexbuf) "Illegal fonction name in Promela file." } - + | rL (rL | rD)* { let s = lexeme lexbuf in - PROMELA_LABEL s } + PROMELA_LABEL s } | eof { EOF } | "1" { PROMELA_TRUE } | _ { Aorai_option.error "Illegal_character : '%s'\n" (lexeme lexbuf); - raise Parsing.Parse_error} + raise Parsing.Parse_error} @@ -122,29 +118,23 @@ let lb = from_channel c in try Promelaparser.promela token lb - with - Parsing.Parse_error - | Invalid_argument _ -> - let (a,b)=(loc lb) in - Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); -(* Format.print_string "Syntax error (" ; *) -(* Format.print_string "l" ; *) -(* Format.print_int a.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) -(* Format.print_string " -> l" ; *) -(* Format.print_int b.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) -(* Format.print_string ")\n" ; *) - raise_located (loc lb) "Syntax error" - - - -} - - - + with + Parsing.Parse_error + | Invalid_argument _ -> + let (a,b)=(loc lb) in + Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); +(* Format.print_string "Syntax error (" ; *) +(* Format.print_string "l" ; *) +(* Format.print_int a.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) +(* Format.print_string " -> l" ; *) +(* Format.print_int b.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) +(* Format.print_string ")\n" ; *) + raise_located (loc lb) "Syntax error" +} diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelalexer_withexps.ml frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer_withexps.ml --- frama-c-20110201+carbon+dfsg/src/aorai/promelalexer_withexps.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer_withexps.ml 2011-10-10 08:48:50.000000000 +0000 @@ -1,27 +1,25 @@ -# 28 "src/aorai/promelalexer_withexps.mll" +# 30 "src/aorai/promelalexer_withexps.mll" open Promelaparser_withexps open Promelaast open Lexing - exception Error of ((Lexing.position * Lexing.position) option) * string - - let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) - - let raise_located loc e = raise (Error (Some (loc), e)) + exception Error of (Lexing.position * Lexing.position) * string + let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) + let raise_located loc e = raise (Error (loc, e)) let buf = Buffer.create 1024 let newline lexbuf = let pos = lexbuf.lex_curr_p in - lexbuf.lex_curr_p <- + lexbuf.lex_curr_p <- { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } -# 25 "src/aorai/promelalexer_withexps.ml" +# 23 "src/aorai/promelalexer_withexps.ml" let __ocaml_lex_tables = { Lexing.lex_base = "\000\000\208\255\210\255\078\000\212\255\213\255\214\255\215\255\ @@ -1188,282 +1186,282 @@ } let rec token lexbuf = - __ocaml_lex_token_rec lexbuf 0 + __ocaml_lex_token_rec lexbuf 0 and __ocaml_lex_token_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> # 59 "src/aorai/promelalexer_withexps.mll" ( PROMELA_TRUE ) -# 1198 "src/aorai/promelalexer_withexps.ml" +# 1196 "src/aorai/promelalexer_withexps.ml" | 1 -> # 60 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_NEVER ) -# 1203 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_NEVER ) +# 1201 "src/aorai/promelalexer_withexps.ml" | 2 -> # 61 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_IF ) -# 1208 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_IF ) +# 1206 "src/aorai/promelalexer_withexps.ml" | 3 -> # 62 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_FI ) -# 1213 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_FI ) +# 1211 "src/aorai/promelalexer_withexps.ml" | 4 -> # 63 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_GOTO ) -# 1218 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_GOTO ) +# 1216 "src/aorai/promelalexer_withexps.ml" | 5 -> # 64 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_SKIP ) -# 1223 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_SKIP ) +# 1221 "src/aorai/promelalexer_withexps.ml" | 6 -> # 65 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_DOUBLE_COLON ) -# 1228 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_DOUBLE_COLON ) +# 1226 "src/aorai/promelalexer_withexps.ml" | 7 -> # 66 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_COLON ) -# 1233 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_COLON ) +# 1231 "src/aorai/promelalexer_withexps.ml" | 8 -> # 67 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_SEMICOLON ) -# 1238 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_SEMICOLON ) +# 1236 "src/aorai/promelalexer_withexps.ml" | 9 -> # 68 "src/aorai/promelalexer_withexps.mll" ( PROMELA_FUNC ) -# 1243 "src/aorai/promelalexer_withexps.ml" +# 1241 "src/aorai/promelalexer_withexps.ml" | 10 -> # 69 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_LPAREN ) -# 1248 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_LPAREN ) +# 1246 "src/aorai/promelalexer_withexps.ml" | 11 -> # 70 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_RPAREN ) -# 1253 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_RPAREN ) +# 1251 "src/aorai/promelalexer_withexps.ml" | 12 -> # 71 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_LBRACE ) -# 1258 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_LBRACE ) +# 1256 "src/aorai/promelalexer_withexps.ml" | 13 -> # 72 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_RBRACE ) -# 1263 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_RBRACE ) +# 1261 "src/aorai/promelalexer_withexps.ml" | 14 -> # 73 "src/aorai/promelalexer_withexps.mll" - ( PROMELA_RIGHT_ARROW ) -# 1268 "src/aorai/promelalexer_withexps.ml" + ( PROMELA_RIGHT_ARROW ) +# 1266 "src/aorai/promelalexer_withexps.ml" | 15 -> # 74 "src/aorai/promelalexer_withexps.mll" ( PROMELA_FALSE ) -# 1273 "src/aorai/promelalexer_withexps.ml" +# 1271 "src/aorai/promelalexer_withexps.ml" | 16 -> # 75 "src/aorai/promelalexer_withexps.mll" ( PROMELA_OR ) -# 1278 "src/aorai/promelalexer_withexps.ml" +# 1276 "src/aorai/promelalexer_withexps.ml" | 17 -> # 76 "src/aorai/promelalexer_withexps.mll" ( PROMELA_AND ) -# 1283 "src/aorai/promelalexer_withexps.ml" +# 1281 "src/aorai/promelalexer_withexps.ml" | 18 -> # 77 "src/aorai/promelalexer_withexps.mll" ( PROMELA_NOT ) -# 1288 "src/aorai/promelalexer_withexps.ml" +# 1286 "src/aorai/promelalexer_withexps.ml" | 19 -> # 78 "src/aorai/promelalexer_withexps.mll" ( token lexbuf ) -# 1293 "src/aorai/promelalexer_withexps.ml" +# 1291 "src/aorai/promelalexer_withexps.ml" | 20 -> # 79 "src/aorai/promelalexer_withexps.mll" ( newline lexbuf; token lexbuf ) -# 1298 "src/aorai/promelalexer_withexps.ml" +# 1296 "src/aorai/promelalexer_withexps.ml" | 21 -> # 80 "src/aorai/promelalexer_withexps.mll" ( comment lexbuf; token lexbuf ) -# 1303 "src/aorai/promelalexer_withexps.ml" +# 1301 "src/aorai/promelalexer_withexps.ml" | 22 -> # 81 "src/aorai/promelalexer_withexps.mll" ( newline lexbuf; token lexbuf ) -# 1308 "src/aorai/promelalexer_withexps.ml" +# 1306 "src/aorai/promelalexer_withexps.ml" | 23 -> # 84 "src/aorai/promelalexer_withexps.mll" - ( let s=(lexeme lexbuf) in - let s=String.sub s 7 ((String.length s)-7) in + ( let s=(lexeme lexbuf) in + let s=String.sub s 7 ((String.length s)-7) in PROMELA_CALLOF s ) -# 1315 "src/aorai/promelalexer_withexps.ml" +# 1313 "src/aorai/promelalexer_withexps.ml" | 24 -> # 88 "src/aorai/promelalexer_withexps.mll" - ( let s=(lexeme lexbuf) in - let s=String.sub s 9 ((String.length s)-9) in + ( let s=(lexeme lexbuf) in + let s=String.sub s 9 ((String.length s)-9) in PROMELA_RETURNOF s ) -# 1322 "src/aorai/promelalexer_withexps.ml" +# 1320 "src/aorai/promelalexer_withexps.ml" | 25 -> # 92 "src/aorai/promelalexer_withexps.mll" - ( let s=(lexeme lexbuf) in - let s=String.sub s 15 ((String.length s)-15) in + ( let s=(lexeme lexbuf) in + let s=String.sub s 15 ((String.length s)-15) in PROMELA_CALLORRETURNOF s ) -# 1329 "src/aorai/promelalexer_withexps.ml" +# 1327 "src/aorai/promelalexer_withexps.ml" | 26 -> # 97 "src/aorai/promelalexer_withexps.mll" ( raise_located (loc lexbuf) "Illegal fonction name in Promela file." ) -# 1334 "src/aorai/promelalexer_withexps.ml" +# 1332 "src/aorai/promelalexer_withexps.ml" | 27 -> # 98 "src/aorai/promelalexer_withexps.mll" ( raise_located (loc lexbuf) "Illegal fonction name in Promela file." ) -# 1339 "src/aorai/promelalexer_withexps.ml" +# 1337 "src/aorai/promelalexer_withexps.ml" | 28 -> # 99 "src/aorai/promelalexer_withexps.mll" ( raise_located (loc lexbuf) "Illegal fonction name in Promela file." ) -# 1344 "src/aorai/promelalexer_withexps.ml" +# 1342 "src/aorai/promelalexer_withexps.ml" | 29 -> # 102 "src/aorai/promelalexer_withexps.mll" ( PROMELA_INT (lexeme lexbuf) ) -# 1349 "src/aorai/promelalexer_withexps.ml" +# 1347 "src/aorai/promelalexer_withexps.ml" | 30 -> # 106 "src/aorai/promelalexer_withexps.mll" ( PROMELA_EQ ) -# 1354 "src/aorai/promelalexer_withexps.ml" +# 1352 "src/aorai/promelalexer_withexps.ml" | 31 -> # 107 "src/aorai/promelalexer_withexps.mll" ( PROMELA_LT ) -# 1359 "src/aorai/promelalexer_withexps.ml" +# 1357 "src/aorai/promelalexer_withexps.ml" | 32 -> # 108 "src/aorai/promelalexer_withexps.mll" ( PROMELA_GT ) -# 1364 "src/aorai/promelalexer_withexps.ml" +# 1362 "src/aorai/promelalexer_withexps.ml" | 33 -> # 109 "src/aorai/promelalexer_withexps.mll" ( PROMELA_LE ) -# 1369 "src/aorai/promelalexer_withexps.ml" +# 1367 "src/aorai/promelalexer_withexps.ml" | 34 -> # 110 "src/aorai/promelalexer_withexps.mll" ( PROMELA_GE ) -# 1374 "src/aorai/promelalexer_withexps.ml" +# 1372 "src/aorai/promelalexer_withexps.ml" | 35 -> # 111 "src/aorai/promelalexer_withexps.mll" ( PROMELA_NEQ ) -# 1379 "src/aorai/promelalexer_withexps.ml" +# 1377 "src/aorai/promelalexer_withexps.ml" | 36 -> # 114 "src/aorai/promelalexer_withexps.mll" ( PROMELA_PLUS ) -# 1384 "src/aorai/promelalexer_withexps.ml" +# 1382 "src/aorai/promelalexer_withexps.ml" | 37 -> # 115 "src/aorai/promelalexer_withexps.mll" ( PROMELA_MINUS ) -# 1389 "src/aorai/promelalexer_withexps.ml" +# 1387 "src/aorai/promelalexer_withexps.ml" | 38 -> # 116 "src/aorai/promelalexer_withexps.mll" ( PROMELA_DIV ) -# 1394 "src/aorai/promelalexer_withexps.ml" +# 1392 "src/aorai/promelalexer_withexps.ml" | 39 -> # 117 "src/aorai/promelalexer_withexps.mll" ( PROMELA_STAR ) -# 1399 "src/aorai/promelalexer_withexps.ml" +# 1397 "src/aorai/promelalexer_withexps.ml" | 40 -> # 118 "src/aorai/promelalexer_withexps.mll" ( PROMELA_MODULO) -# 1404 "src/aorai/promelalexer_withexps.ml" +# 1402 "src/aorai/promelalexer_withexps.ml" | 41 -> # 122 "src/aorai/promelalexer_withexps.mll" ( PROMELA_DOT ) -# 1409 "src/aorai/promelalexer_withexps.ml" +# 1407 "src/aorai/promelalexer_withexps.ml" | 42 -> # 123 "src/aorai/promelalexer_withexps.mll" ( PROMELA_LEFT_SQUARE) -# 1414 "src/aorai/promelalexer_withexps.ml" +# 1412 "src/aorai/promelalexer_withexps.ml" | 43 -> # 124 "src/aorai/promelalexer_withexps.mll" ( PROMELA_RIGHT_SQUARE) -# 1419 "src/aorai/promelalexer_withexps.ml" +# 1417 "src/aorai/promelalexer_withexps.ml" | 44 -> # 130 "src/aorai/promelalexer_withexps.mll" ( let s = lexeme lexbuf in - PROMELA_LABEL s ) -# 1425 "src/aorai/promelalexer_withexps.ml" + PROMELA_LABEL s ) +# 1423 "src/aorai/promelalexer_withexps.ml" | 45 -> # 132 "src/aorai/promelalexer_withexps.mll" ( EOF ) -# 1430 "src/aorai/promelalexer_withexps.ml" +# 1428 "src/aorai/promelalexer_withexps.ml" | 46 -> # 134 "src/aorai/promelalexer_withexps.mll" ( PROMELA_TRUE ) -# 1435 "src/aorai/promelalexer_withexps.ml" +# 1433 "src/aorai/promelalexer_withexps.ml" | 47 -> # 135 "src/aorai/promelalexer_withexps.mll" ( Aorai_option.error "Illegal_character : '%s'\n" (lexeme lexbuf); - raise Parsing.Parse_error) -# 1441 "src/aorai/promelalexer_withexps.ml" + raise Parsing.Parse_error) +# 1439 "src/aorai/promelalexer_withexps.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state and comment lexbuf = - __ocaml_lex_comment_rec lexbuf 94 + __ocaml_lex_comment_rec lexbuf 94 and __ocaml_lex_comment_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> # 142 "src/aorai/promelalexer_withexps.mll" ( () ) -# 1452 "src/aorai/promelalexer_withexps.ml" +# 1450 "src/aorai/promelalexer_withexps.ml" | 1 -> # 143 "src/aorai/promelalexer_withexps.mll" ( Aorai_option.warning "Unterminated_comment\n" (*lex_error lexbuf "Unterminated_comment"*) ) -# 1457 "src/aorai/promelalexer_withexps.ml" +# 1455 "src/aorai/promelalexer_withexps.ml" | 2 -> # 144 "src/aorai/promelalexer_withexps.mll" ( newline lexbuf; comment lexbuf ) -# 1462 "src/aorai/promelalexer_withexps.ml" +# 1460 "src/aorai/promelalexer_withexps.ml" | 3 -> # 145 "src/aorai/promelalexer_withexps.mll" ( comment lexbuf ) -# 1467 "src/aorai/promelalexer_withexps.ml" +# 1465 "src/aorai/promelalexer_withexps.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_comment_rec lexbuf __ocaml_lex_state @@ -1475,24 +1473,24 @@ let lb = from_channel c in try Promelaparser_withexps.promela token lb - with - Parsing.Parse_error - | Invalid_argument _ -> - let (a,b)=(loc lb) in - Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); -(* Format.print_string "Syntax error (" ; *) -(* Format.print_string "l" ; *) -(* Format.print_int a.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) -(* Format.print_string " -> l" ; *) -(* Format.print_int b.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) -(* Format.print_string ")\n" ; *) - raise_located (loc lb) "Syntax error" - - + with + Parsing.Parse_error + | Invalid_argument _ -> + let (a,b)=(loc lb) in + Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); +(* Format.print_string "Syntax error (" ; *) +(* Format.print_string "l" ; *) +(* Format.print_int a.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) +(* Format.print_string " -> l" ; *) +(* Format.print_int b.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) +(* Format.print_string ")\n" ; *) + raise_located (loc lb) "Syntax error" + + -# 1499 "src/aorai/promelalexer_withexps.ml" +# 1497 "src/aorai/promelalexer_withexps.ml" diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelalexer_withexps.mll frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer_withexps.mll --- frama-c-20110201+carbon+dfsg/src/aorai/promelalexer_withexps.mll 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelalexer_withexps.mll 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -31,19 +33,17 @@ open Promelaast open Lexing - exception Error of ((Lexing.position * Lexing.position) option) * string - - let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) - - let raise_located loc e = raise (Error (Some (loc), e)) + exception Error of (Lexing.position * Lexing.position) * string + let loc lexbuf = (lexeme_start_p lexbuf, lexeme_end_p lexbuf) + let raise_located loc e = raise (Error (loc, e)) let buf = Buffer.create 1024 let newline lexbuf = let pos = lexbuf.lex_curr_p in - lexbuf.lex_curr_p <- + lexbuf.lex_curr_p <- { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } } @@ -51,26 +51,26 @@ -let rD = ['0'-'9'] +let rD = ['0'-'9'] let rL = ['a'-'z' 'A'-'Z' '_'] rule token = parse | "true" { PROMELA_TRUE } - | "never" { PROMELA_NEVER } - | "if" { PROMELA_IF } - | "fi" { PROMELA_FI } - | "goto" { PROMELA_GOTO } - | "skip" { PROMELA_SKIP } - | "::" { PROMELA_DOUBLE_COLON } - | ':' { PROMELA_COLON } - | ';' { PROMELA_SEMICOLON } + | "never" { PROMELA_NEVER } + | "if" { PROMELA_IF } + | "fi" { PROMELA_FI } + | "goto" { PROMELA_GOTO } + | "skip" { PROMELA_SKIP } + | "::" { PROMELA_DOUBLE_COLON } + | ':' { PROMELA_COLON } + | ';' { PROMELA_SEMICOLON } | "()" { PROMELA_FUNC } - | '(' { PROMELA_LPAREN } - | ')' { PROMELA_RPAREN } - | '{' { PROMELA_LBRACE } - | '}' { PROMELA_RBRACE } - | "->" { PROMELA_RIGHT_ARROW } + | '(' { PROMELA_LPAREN } + | ')' { PROMELA_RPAREN } + | '{' { PROMELA_LBRACE } + | '}' { PROMELA_RBRACE } + | "->" { PROMELA_RIGHT_ARROW } | "false" { PROMELA_FALSE } | "||" { PROMELA_OR } | "&&" { PROMELA_AND } @@ -80,17 +80,17 @@ | "/*" { comment lexbuf; token lexbuf } | "//" [^ '\n']* '\n' { newline lexbuf; token lexbuf } - | "callof_" rL* (rL | rD)* - { let s=(lexeme lexbuf) in - let s=String.sub s 7 ((String.length s)-7) in + | "callof_" rL* (rL | rD)* + { let s=(lexeme lexbuf) in + let s=String.sub s 7 ((String.length s)-7) in PROMELA_CALLOF s } - | "returnof_" rL* (rL | rD)* - { let s=(lexeme lexbuf) in - let s=String.sub s 9 ((String.length s)-9) in + | "returnof_" rL* (rL | rD)* + { let s=(lexeme lexbuf) in + let s=String.sub s 9 ((String.length s)-9) in PROMELA_RETURNOF s } - | "callorreturnof_" rL* (rL | rD)* - { let s=(lexeme lexbuf) in - let s=String.sub s 15 ((String.length s)-15) in + | "callorreturnof_" rL* (rL | rD)* + { let s=(lexeme lexbuf) in + let s=String.sub s 15 ((String.length s)-15) in PROMELA_CALLORRETURNOF s } @@ -100,7 +100,7 @@ | rD+ | '-' rD+ { PROMELA_INT (lexeme lexbuf) } - + (* Logic relations *) | "==" { PROMELA_EQ } @@ -118,8 +118,8 @@ | '%' { PROMELA_MODULO} (* Access *) -(* | "->" { LTL_RIGHT_ARROW }*) - | '.' { PROMELA_DOT } +(* | "->" { LTL_RIGHT_ARROW }*) + | '.' { PROMELA_DOT } | '[' { PROMELA_LEFT_SQUARE} | ']' { PROMELA_RIGHT_SQUARE} (* | '&' { PROMELA_ADRESSE }*) @@ -128,12 +128,12 @@ | rL (rL | rD)* { let s = lexeme lexbuf in - PROMELA_LABEL s } + PROMELA_LABEL s } | eof { EOF } | "1" { PROMELA_TRUE } | _ { Aorai_option.error "Illegal_character : '%s'\n" (lexeme lexbuf); - raise Parsing.Parse_error} + raise Parsing.Parse_error} @@ -150,29 +150,23 @@ let lb = from_channel c in try Promelaparser_withexps.promela token lb - with - Parsing.Parse_error - | Invalid_argument _ -> - let (a,b)=(loc lb) in - Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); -(* Format.print_string "Syntax error (" ; *) -(* Format.print_string "l" ; *) -(* Format.print_int a.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) -(* Format.print_string " -> l" ; *) -(* Format.print_int b.pos_lnum ; *) -(* Format.print_string "c" ; *) -(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) -(* Format.print_string ")\n" ; *) - raise_located (loc lb) "Syntax error" - - - -} - - - + with + Parsing.Parse_error + | Invalid_argument _ -> + let (a,b)=(loc lb) in + Aorai_option.error "Syntax error (l%d c%d -> l%dc%d)" a.pos_lnum (a.pos_cnum-a.pos_bol) b.pos_lnum (b.pos_cnum-b.pos_bol); +(* Format.print_string "Syntax error (" ; *) +(* Format.print_string "l" ; *) +(* Format.print_int a.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (a.pos_cnum-a.pos_bol) ;*) +(* Format.print_string " -> l" ; *) +(* Format.print_int b.pos_lnum ; *) +(* Format.print_string "c" ; *) +(* Format.print_int (b.pos_cnum-b.pos_bol) ;*) +(* Format.print_string ")\n" ; *) + raise_located (loc lb) "Syntax error" +} diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaoutput.ml frama-c-20111001+nitrogen+dfsg/src/aorai/promelaoutput.ml --- frama-c-20110201+carbon+dfsg/src/aorai/promelaoutput.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaoutput.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,475 +23,239 @@ (* *) (**************************************************************************) -(* $Id: promelaoutput.ml,v 1.3 2008-12-19 15:30:56 uid588 Exp $ *) - +open Cil_types +open Logic_ptree open Aorai_option -open Pretty_utils open Promelaast -open Format open Pervasives -open Data_for_aorai open Bool3 +open Pretty_utils +open Format +let string_of_unop = function + | Uminus -> "-" + | Ustar -> "*" + | Uamp -> "&" + | Ubw_not -> "~" + +let rec print_parsed_expression fmt = function + | PVar s -> Format.fprintf fmt "%s" s + | PPrm (f,s) -> Format.fprintf fmt "%s().%s" f s + | PCst (IntConstant s) -> Format.fprintf fmt "%s" s + | PCst (FloatConstant s) -> Format.fprintf fmt "%s" s + | PCst (StringConstant s) -> Format.fprintf fmt "%S" s + | PCst (WStringConstant s) -> Format.fprintf fmt "%S" s + | PBinop(bop,e1,e2) -> + Format.fprintf fmt "(@[%a@])@ %a@ (@[%a@])" + print_parsed_expression e1 Cil.d_binop (Logic_typing.type_binop bop) + print_parsed_expression e2 + | PUnop(uop,e) -> Format.fprintf fmt "%s@;(@[%a@])" + (string_of_unop uop) + print_parsed_expression e + | PArrget(e1,e2) -> Format.fprintf fmt "%a@;[@(%a@]]" + print_parsed_expression e1 print_parsed_expression e2 + | PField(e,s) -> Format.fprintf fmt "%a.%s" print_parsed_expression e s + | PArrow(e,s) -> Format.fprintf fmt "%a->%s" print_parsed_expression e s + +let rec print_parsed_condition fmt = function + | PRel(rel,e1,e2) -> + Format.fprintf fmt "%a %a@ %a" + print_parsed_expression e1 + Cil.d_relation (Logic_typing.type_rel rel) + print_parsed_expression e2 + | PTrue -> Format.pp_print_string fmt "true" + | PFalse -> Format.pp_print_string fmt "false" + | POr(e1,e2) -> Format.fprintf fmt "(@[%a@])@ or@ (@[%a@])" + print_parsed_condition e1 print_parsed_condition e2 + | PAnd(e1,e2) -> Format.fprintf fmt "(@[%a@])@ and@ (@[%a@])" + print_parsed_condition e1 print_parsed_condition e2 + | PNot c -> Format.fprintf fmt "not(@[%a@])" + print_parsed_condition c + | PCall (s,None) -> Format.fprintf fmt "CALL(%s)" s + | PCall (s, Some b) -> Format.fprintf fmt "CALL(%s::%s)" s b + | PReturn s -> Format.fprintf fmt "RETURN(%s)" s + +let rec print_seq_elt fmt elt = + Format.fprintf fmt "(%a%a){@[%a,%a@]}" + (Pretty_utils.pp_opt print_parsed_condition) elt.condition + print_sequence elt.nested + (Pretty_utils.pp_opt print_parsed_expression) elt.min_rep + (Pretty_utils.pp_opt print_parsed_expression) elt.max_rep + +and print_sequence fmt l = + Pretty_utils.pp_list ~pre:"[@[" ~sep:";@ " ~suf:"@]]" print_seq_elt fmt l + +let print_parsed fmt = function + | Seq l -> print_sequence fmt l + | Otherwise -> Format.pp_print_string fmt "Otherwise" + +let rec print_condition fmt = function + | TCall (kf,None) -> + Format.fprintf fmt "Call(%a)" Kernel_function.pretty kf + | TCall (kf, Some b) -> + Format.fprintf fmt "Call(%a::%s)" Kernel_function.pretty kf b.b_name + | TReturn kf -> + Format.fprintf fmt "Return(%a)" Kernel_function.pretty kf + | TOr (c1,c2) -> + Format.fprintf fmt "@[(@[<2>%a@])@]@ or@ @[(@[<2>%a@])@]" + print_condition c1 print_condition c2 + | TAnd (c1,c2) -> + Format.fprintf fmt "@[(@[<2>%a@])@]@ and@ @[(@[<2>%a@])@]" + print_condition c1 print_condition c2 + | TNot c -> + Format.fprintf fmt "@[@[not(%a@])@]" print_condition c + | TTrue -> Format.pp_print_string fmt "True" + | TFalse -> Format.pp_print_string fmt "False" + | TRel(rel,exp1,exp2) -> + (* \result will be printed as such, not as f().return *) + Format.fprintf fmt "@[(%a)@]@ %a@ @[(%a)@]" + !Ast_printer.d_term exp1 !Ast_printer.d_relation rel + !Ast_printer.d_term exp2 + +let print_one_action fmt = function + | Counter_init lv -> + Format.fprintf fmt "@[%a <- 1@]" !Ast_printer.d_term_lval lv + | Counter_incr lv -> + Format.fprintf fmt "@[%a <- @[%a@ +@ 1@]@]" + !Ast_printer.d_term_lval lv !Ast_printer.d_term_lval lv + | Pebble_init (set,_,v) -> + Format.fprintf fmt "@[%a <- {@[ %a @]}@]" + !Ast_printer.d_logic_var set.l_var_info !Ast_printer.d_logic_var v + | Pebble_move(s1,_,s2,_) -> + Format.fprintf fmt "@[%a <- %a@]" + !Ast_printer.d_logic_var s1.l_var_info + !Ast_printer.d_logic_var s2.l_var_info + | Copy_value(lv,v) -> + Format.fprintf fmt "@[%a <- %a@]" + !Ast_printer.d_term_lval lv !Ast_printer.d_term v + +let print_action fmt l = + Pretty_utils.pp_list ~sep:"@\n" print_one_action fmt l + +let normal_funcs = ref None + +(* Use well-parenthesized combination of escape_newline/normal_newline*) +let escape_newline fmt = + let (out,flush,newline,spaces as funcs) = + Format.pp_get_all_formatter_output_functions fmt () + in + (match !normal_funcs with + None -> normal_funcs:= Some funcs + | Some _ -> Aorai_option.fatal "Already in escape newline mode"); + let has_printed = ref false in + let newline () = + if !has_printed then out " \\\n" 0 3 + else newline () + in + let out s b l = + if String.contains (String.sub s b l) '"' then + has_printed:=not !has_printed; + out s b l + in + Format.pp_set_all_formatter_output_functions fmt ~out ~flush ~newline ~spaces + +let normal_newline fmt = + let (out, flush, newline, spaces) = Extlib.the !normal_funcs in + normal_funcs := None; + Format.pp_set_all_formatter_output_functions fmt ~out ~flush ~newline ~spaces -let out_fmt=ref (formatter_of_out_channel stdout) - - - - -(*let string_of_condition_arith = function - | PVar s -> "Var("^s^")" - | PConst c -> "Const("^(string_of_int c)^")" -*) -let rec string_of_condition = function - | PCall s -> "Call("^s^")" - | PReturn s -> "Return("^s^")" - | PCallOrReturn s -> "CallOrReturn("^s^")" - | POr (c1,c2) -> "("^(string_of_condition c1)^" or "^(string_of_condition c2)^")" - | PAnd (c1,c2 ) -> "("^(string_of_condition c1)^" and "^(string_of_condition c2)^")" - | PNot c -> "not "^(string_of_condition c) - | PTrue -> "True" - | PFalse -> "False" -(* | PGt (c1,c2) -> (string_of_condition_arith c1)^">" ^(string_of_condition_arith c2) - | PGe (c1,c2) -> (string_of_condition_arith c1)^">="^(string_of_condition_arith c2) - | PLt (c1,c2) -> (string_of_condition_arith c1)^"<" ^(string_of_condition_arith c2) - | PLe (c1,c2) -> (string_of_condition_arith c1)^"<="^(string_of_condition_arith c2) - | PEq (c1,c2) -> (string_of_condition_arith c1)^"=" ^(string_of_condition_arith c2) - | PNeq (c1,c2) -> (string_of_condition_arith c1)^"<>"^(string_of_condition_arith c2) - | PBoolVar (s) -> "BoolVar("^s^")"*) - | PIndexedExp (s) -> Data_for_aorai.get_str_exp_from_tmpident s - | PFuncReturn (s, f) -> "("^f^"()."^(Data_for_aorai.get_str_exp_from_tmpident s)^")" - | PFuncParam (s, f, _) -> "("^f^"()."^(Data_for_aorai.get_str_exp_from_tmpident s)^")" - -(*let c_string_of_condition_arith = function - | PVar s -> s - | PConst c -> string_of_int c -*) -let rec c_string_of_condition = function - | PCall s -> "(("^s^"=="^curOp^") && ("^curOpStatus^"=="^callStatus^"))" - | PReturn s -> "(("^s^"=="^curOp^") && ("^curOpStatus^"=="^termStatus^"))" - | PCallOrReturn s -> "("^s^"=="^curOp^")" - | POr (c1,c2) -> "("^(c_string_of_condition c1)^" || "^(c_string_of_condition c2)^")" - | PAnd (c1,c2 ) -> "("^(c_string_of_condition c1)^" && "^(c_string_of_condition c2)^")" - | PNot c -> "!"^(c_string_of_condition c) - | PTrue -> "1" - | PFalse -> "0" -(* | PGt (c1,c2) -> (c_string_of_condition_arith c1)^">" ^(c_string_of_condition_arith c2) - | PGe (c1,c2) -> (c_string_of_condition_arith c1)^">="^(c_string_of_condition_arith c2) - | PLt (c1,c2) -> (c_string_of_condition_arith c1)^"<" ^(c_string_of_condition_arith c2) - | PLe (c1,c2) -> (c_string_of_condition_arith c1)^"<="^(c_string_of_condition_arith c2) - | PEq (c1,c2) -> (c_string_of_condition_arith c1)^"==" ^(c_string_of_condition_arith c2) - | PNeq (c1,c2) -> (c_string_of_condition_arith c1)^"!="^(c_string_of_condition_arith c2) - | PBoolVar (s) -> s*) - | PIndexedExp (s) -> Data_for_aorai.get_str_exp_from_tmpident s - | PFuncReturn (s, _) - | PFuncParam (s, _, _) -> Data_for_aorai.get_str_exp_from_tmpident s - +let print_full_transition fmt (cond,action) = + Format.fprintf fmt "%a@\n%a" print_condition cond print_action action let trans_label num = "tr"^string_of_int(num) -let string_of_trans num cross= - (trans_label num) ^" : "^(string_of_condition cross) - -let state_label num = "st"^string_of_int(num) -let string_of_state st = (state_label st.nums) ^" : "^(st.name) - -let print_bool3 b = - Format.print_string (match b with - | True -> "True" - | False -> "False" - | Undefined -> "Undef" - ) - - -let rec print_cross cr = - printf "%s" (string_of_condition cr) - -let print_transition tr = - Format.print_string (" { "); - Format.print_int tr.numt; - Format.print_string (": "^tr.start.name^" ") ; - print_cross tr.cross ; - Format.print_string (" "^tr.stop.name ^ " }\n") - -let print_transitionl trl = - Format.print_string ("Transitions : \n") ; - List.iter print_transition trl - - -let print_state st = - Format.print_string (" "^st.name^" (acc="); - print_bool3 st.acceptation ; - Format.print_string (";init="); - print_bool3 st.init; - Format.print_string (";num="); - Format.print_int st.nums; - Format.print_string (")\n") - -let print_statel stl = - Format.print_string ("States : \n") ; - List.iter print_state stl - - -let print_raw_automata (stl,trl) = - Format.print_string ("Transitions : \n") ; - (print_statel stl) ; - (print_transitionl trl) - - - -(* -let print_automata_axiomatization (_ (*states_l*), trans_l) = - (* Generation des transitions *) - fprintf !out_fmt "logic %s : int -> int \n" transStart ; - fprintf !out_fmt "\n" ; - List.iter (fun t -> - fprintf !out_fmt "axiom %s_%d : (%s(%d) = %d)\n" transStart t.numt transStart t.numt t.start.nums - ) trans_l; - fprintf !out_fmt "\n" ; - - - fprintf !out_fmt "logic %s : int -> int \n" transStop ; - fprintf !out_fmt "\n" ; - List.iter (fun t -> - fprintf !out_fmt "axiom %s_%d : (%s(%d) = %d)\n" transStop t.numt transStop t.numt t.stop.nums - ) trans_l; - fprintf !out_fmt "\n" ; - - fprintf !out_fmt "predicate %s(%s: int, %s: int, num: int) = \n" transCond curOpStatus curOp; - let first=(List.hd trans_l) in - fprintf !out_fmt " ((num=%d) -> (%s)) " first.numt (string_of_condition first.cross); - List.iter (fun t -> - printf "and\n ((num=%d) -> (%s)) " t.numt (string_of_condition t.cross) - ) (List.tl trans_l); - fprintf !out_fmt "\n)\n" - - -*) - - - - - - - - - - -let print_start_block title = - fprintf !out_fmt "//========================\n// BEGIN %s\n//\n" title - -let print_end_block title = - fprintf !out_fmt "//\n// END %s\n//========================\n\n" title - - - - -let print_operations_list opl = - print_start_block "Operations list"; - fprintf !out_fmt "#define %s = %d \n" nbOp (List.length opl); - fprintf !out_fmt "enum %s {" listOp; - let v=ref "" in - List.iter (fun op -> fprintf !out_fmt "%s\n %s" !v op;v:=",") opl; - fprintf !out_fmt "\n}\n"; - print_end_block "Operations list" - - - -let print_operations_constants (states_l,trans_l) = - print_start_block "Operations status"; - fprintf !out_fmt "enum Status_list {\n"; - fprintf !out_fmt " %s,\n" callStatus; - fprintf !out_fmt " %s\n" termStatus; - fprintf !out_fmt "}\n"; - print_end_block "Operations status"; - - print_start_block "Some constants about the Buchi automata"; - fprintf !out_fmt "# define %s=%d\n" nbStates (List.length states_l); - fprintf !out_fmt "# define %s=%d\n" nbTrans (List.length trans_l); - fprintf !out_fmt "# define %s=%d\n" nbAcceptSt (List.fold_left (fun i s -> if s.acceptation=True then i+1 else i) 0 states_l); - print_end_block "Some constants about the Buchi automata" - - - - -let print_ghosts_declaration main states_l= - print_start_block "State ghosts variables declaration"; - fprintf !out_fmt "//%c ghost int %s = %s \n" '@' curOp main ; - fprintf !out_fmt "//%c ghost int %s = %s \n" '@' curOpStatus callStatus ; - fprintf !out_fmt "//%c ghost int %s[%s] \n" '@' curState nbStates; - fprintf !out_fmt "//%c ghost int %s[%s] \n" '@' curTrans nbTrans; - let acc = ref "" in - let sep = ref "{" in - (List.iter - (fun st -> - if st.acceptation=True then - begin - acc:=(!acc)^(!sep)^(string_of_int st.nums); - sep:="," - end) - states_l); - fprintf !out_fmt "const int %s[%s] = %s}\n" acceptSt nbAcceptSt !acc; - print_end_block "State ghosts variables declaration" - -(* -let print_automata (_ (*states_l*),trans_l) = - print_start_block "Automata definition"; - - fprintf !out_fmt "// Starting state of each transition\n//\n"; - fprintf !out_fmt "//%c logic int %s (int tr) reads tr\n" '@' transStart ; - List.iter (fun t -> - fprintf !out_fmt "//%c axiom %s_%d : %s(%d) == %d\n" '@' transStart t.numt transStart t.numt t.start.nums - ) trans_l; - - - fprintf !out_fmt "//\n// Ending state of each transition\n//\n"; - fprintf !out_fmt "//%c logic int %s (int tr) reads tr\n" '@' transStop ; - List.iter (fun t -> - fprintf !out_fmt "//%c axiom %s_%d : %s(%d) == %d\n" '@' transStop t.numt transStop t.numt t.stop.nums - ) trans_l; - - fprintf !out_fmt "//\n// Cross condition of each transition\n//\n"; - fprintf !out_fmt "/*%c predicate %s (int TransNum, int %s, int %s) = \n" '@' transCondP curOp curOpStatus; - fprintf !out_fmt " %c ((TransNum==%d) => (%s)) " '@' (List.hd trans_l).numt (c_string_of_condition (List.hd trans_l).cross); - List.iter (fun t -> - fprintf !out_fmt "&&\n %c ((TransNum==%d) => (%s)) " '@' t.numt (c_string_of_condition t.cross) - ) (List.tl trans_l); - fprintf !out_fmt "\n)\n*/\n" ; - - fprintf !out_fmt "//%c predicate %s (int TransNum) = %s (TransNum,%s,%s)\n" '@' transCond transCondP curOp curOpStatus; - - - fprintf !out_fmt "//\n// Some invariants\n//\n"; - fprintf !out_fmt "//%c invariant inv_buch_range : \\valid_range(%s,0,%s-1) \n" '@' curState nbStates; - fprintf !out_fmt "//%c invariant inv_buch_accept_valid: \\valid_range(%s,0,%s-1) \n" '@' acceptSt nbAcceptSt; - fprintf !out_fmt "//%c invariant inv_buch_accept_correct: \\forall int st ; 0<=st<%s => 0<=%s[st]<%s \n" '@' nbAcceptSt acceptSt nbStates; - - print_end_block "Automata definition" -*) - - - - - - - - - - - - - - - - - -let print_macros (states_l,trans_l) = - print_start_block "Some macros factorizing pre/post-conditions predicates"; - - fprintf !out_fmt "# define %s=(op,st) \\\n" macro_ligth; - fprintf !out_fmt " %s == op\\\n" curOp; - fprintf !out_fmt " && %s == st\\\n" curOpStatus; - fprintf !out_fmt " && (%s[ 0] != 0" curState; - for i=1 to (List.length states_l)-1 do - fprintf !out_fmt " ||\\\n %s[%2d] != 0" curState i - done; - fprintf !out_fmt ")\\\n"; - fprintf !out_fmt " && (%s[ 0] != 0" curTrans; - for i=1 to (List.length trans_l)-1 do - fprintf !out_fmt " ||\\\n %s[%2d] != 0" curTrans i - done ; - fprintf !out_fmt ")\n"; - fprintf !out_fmt "//\n"; - - - fprintf !out_fmt "# define %s=(op,st) \\\n" macro_full; - fprintf !out_fmt " %s(op,et) \\\n" macro_ligth; - fprintf !out_fmt " && (\\forall int tr ; 0<=tr<%s && %s[tr]!=0 => %s[%s(tr)]!=0 && %s(tr)) \\\n" nbTrans curTrans curState transStop transCond; - fprintf !out_fmt " && (\\forall int st ; 0<=st<%s && %s[st]!=0=> \\\n" nbStates curState; - fprintf !out_fmt " (\\exists int tr ; 0<=tr<%s && %s(tr) && %s(tr)==st && %s[tr]!=0)) \\\n" nbTrans transCond transStop curTrans; - fprintf !out_fmt " && (\\forall int st ; \\\n"; - fprintf !out_fmt " 0<=st<%s && \\\n" nbStates; - fprintf !out_fmt " (\\forall int tr ; \\\n"; - fprintf !out_fmt " 0<=tr<%s => \\\n" nbTrans; - fprintf !out_fmt " (%s[tr]==0 || \\\n" curTrans; - fprintf !out_fmt " %s(tr)!=st || \\\n" transStop; - fprintf !out_fmt " !%s(tr)) \\\n" transCond; - fprintf !out_fmt " ) \\\n"; - fprintf !out_fmt " => %s[st]==0 \\\n" curState; - fprintf !out_fmt " )\n"; - fprintf !out_fmt "//\n"; - - - fprintf !out_fmt "# define %s \\\n" macro_pure ; - fprintf !out_fmt " (\\forall int st ; 0<=st<%s && %s[st]==0 => \\\n" nbStates curState; - fprintf !out_fmt " (\\forall int tr ; 0<=tr<%s => \\\n" nbTrans; - fprintf !out_fmt " ( %s[tr]==0 || !%s(tr) \\\n" curTrans transCond; - fprintf !out_fmt " || %s(tr)!=st || \\old(%s[%s(tr)]==0)))) \\\n" transStop curState transStart; - fprintf !out_fmt " && (\\forall int end ; 0<=end<%s && %s[end]!=0 => \\\n" nbStates curState; - fprintf !out_fmt " (\\exists int tr ; 0<=tr<%s && %s[tr]!=0 && %s(tr) && \\\n" nbTrans curTrans transCond; - fprintf !out_fmt " end==%s(tr) && \\old(%s[%s(tr)]!=0)))\n" transStop curState transStart; - print_end_block "Some macros factorizing pre/post-conditions predicates" - - - - - - - - - - - - - - - - -let print_buch_synch () = - print_start_block "Function of synchronisation between C code and Buchi automata"; - - fprintf !out_fmt "/*%c requires \n" '@'; - fprintf !out_fmt " %c \\forall int st ; 0<= st < %s && %s[st]!=0 => \n" '@' nbStates curState; - fprintf !out_fmt " %c (\\exists int tr ; 0<=tr<%s && %s(tr)==st && %s(tr,CurOp,Case))\n" '@' nbTrans transStart transCondP; - fprintf !out_fmt " %c assigns %s[..], %s[..], %s, %s\n" '@' curState curTrans curOp curOpStatus; - fprintf !out_fmt " %c ensures \n" '@'; - fprintf !out_fmt " %c %s(CurOp,Case) && \n" '@' macro_ligth; - fprintf !out_fmt " %c\n" '@'; - fprintf !out_fmt " %c // Each crossable transition is crossed.\n" '@'; - fprintf !out_fmt " %c (\\forall int tr ; 0<=tr<%s && \\old(%s[%s(tr)])!=0 && %s(tr)=> \n" '@' nbTrans curState transStart transCond; - fprintf !out_fmt " %c %s[tr]!=0 && %s[%s(tr)]!=0\n" '@' curTrans curState transStop; - fprintf !out_fmt " %c ) &&\n" '@'; - fprintf !out_fmt " %c // Non-crossable transition are not crossed over.\n" '@'; - fprintf !out_fmt " %c (\\forall int tr ; 0<=tr<%s && (\\old(%s[%s(tr)])==0 || !%s(tr)) =>\n" '@' nbTrans curState transStart transCond; - fprintf !out_fmt " %c %s[tr]==0\n" '@' curTrans; - fprintf !out_fmt " %c ) &&\n" '@'; - fprintf !out_fmt " %c // Each transition annotated as crossable is crossable\n" '@' ; - fprintf !out_fmt " %c // -- Interesting for preconditions that follow the operation call --\n" '@'; - fprintf !out_fmt " %c (\\forall int tr ; 0<=tr<%s && %s[tr]!=0 => \n" '@' nbTrans curTrans; - fprintf !out_fmt " %c \\old(%s[%s(tr)])!=0 && %s (tr) && %s[%s(tr)]!=0\n" '@' curState transStart transCond curState transStop; - fprintf !out_fmt " %c ) &&\n" '@' ; - fprintf !out_fmt " %c\n" '@' ; - fprintf !out_fmt " %c // If a state is annotated as not reachable, then no crossable transition reaches it is crossable\n" '@'; - fprintf !out_fmt " %c (\\forall int st ; \n" '@' ; - fprintf !out_fmt " %c 0<=st<%s &&\n" '@' nbStates; - fprintf !out_fmt " %c (\\forall int tr ; \n" '@' ; - fprintf !out_fmt " %c 0<=tr<%s => \n" '@' nbTrans; - fprintf !out_fmt " %c (%s[tr]==0 || \n" '@' curTrans; - fprintf !out_fmt " %c %s(tr)!=st || \n" '@' transStop; - fprintf !out_fmt " %c !%s(tr) || \n" '@' transCond; - fprintf !out_fmt " %c \\old(%s[%s(tr)])==0)\n" '@' curState transStart; - fprintf !out_fmt " %c )\n" '@' ; - fprintf !out_fmt " %c => %s[st]==0\n" '@' curState; - fprintf !out_fmt " %c ) &&\n" '@' ; - fprintf !out_fmt " %c\n" '@' ; - fprintf !out_fmt " %c // Each non-active state is not reachable\n" '@' ; - fprintf !out_fmt " %c (\\forall int st ; 0<=st<%s && %s[st]==0 => \n" '@' nbStates curState; - fprintf !out_fmt " %c (\\forall int tr ; 0<=tr<%s => \n" '@' nbTrans; - fprintf !out_fmt " %c ( %s[tr]==0 || !%s(tr) \n" '@' curTrans transCond; - fprintf !out_fmt " %c || %s(tr)!=st || \\old(%s[%s(tr)]==0)))) && \n" '@' transStop curState transStart; - fprintf !out_fmt " %c // Each active state is reachable \n" '@' ; - fprintf !out_fmt " %c (\\forall int st ; 0<=st<%s && %s[st]!=0 => \n" '@' nbStates curState; - fprintf !out_fmt " %c (\\exists int tr ; 0<=tr<%s && %s[tr]!=0 && %s(tr) \n" '@' nbTrans curTrans transCond; - fprintf !out_fmt " %c && %s(tr)==st && \\old(%s[%s(tr)]!=0))) \n" '@' transStop curState transStart; - fprintf !out_fmt "*/ \n" ; - fprintf !out_fmt "void %s(int CurOp, int Case); \n" buch_sync; - - print_end_block "Function of synchronisation between C code and Buchi automata" - - - - - - - -(* -let print_automata_specification (states_l,trans_l) operations_l main_op fichier = - let cout = open_out fichier in - out_fmt:=formatter_of_out_channel cout ; - - fprintf !out_fmt "#ifndef _BUCHI_AUTOMATA_H_\n"; - fprintf !out_fmt "#define _BUCHI_AUTOMATA_H_\n\n"; - print_operations_constants (states_l,trans_l); - print_operations_list operations_l ; - print_automata (states_l,trans_l) ; - print_ghosts_declaration main_op states_l; - print_macros (states_l,trans_l); - print_buch_synch (); - fprintf !out_fmt "\n#endif /*_BUCHI_AUTOMATA_H_*/\n"; - - close_out cout; - out_fmt:=formatter_of_out_channel stdout -*) - - - - - - +let print_trans fmt trans = + Format.fprintf fmt + "@[<2>%s:@ %a@]" + (trans_label trans.numt) print_full_transition trans.cross +let state_label num = "st"^string_of_int(num) +let print_state_label fmt st = + Format.fprintf fmt "@[<2>%s:@ %s@]" (state_label st.nums) st.name +let print_bool3 fmt b = + Format.pp_print_string fmt + (match b with + | True -> "True" + | False -> "False" + | Undefined -> "Undef") + +let print_transition fmt tr = + Format.fprintf fmt "@[<2>{@ %d:@ %s@ {%a}@ %s@]}" + tr.numt tr.start.name print_full_transition tr.cross tr.stop.name + +let print_transitionl fmt trl = + Format.fprintf fmt "@[<2>Transitions:@\n%a@]" + (Pretty_utils.pp_list ~sep:"@\n" ~suf:"@\n" print_transition) trl + +let print_state fmt st = + Format.fprintf fmt "@[<2>%s@ (acc=%a;@ init=%a;@ num=%d)@]" + st.name print_bool3 st.acceptation print_bool3 st.init st.nums + +let print_statel fmt stl = + Format.fprintf fmt "@[<2>States:@\n%a@]" + (Pretty_utils.pp_list ~sep:"@\n" ~suf:"@\n" print_state) stl + +let print_raw_automata fmt (stl,trl) = + Format.fprintf fmt "@[<2>Automaton:@\n%a%a@]" + print_statel stl print_transitionl trl let dot_state out st = - if st.init=Bool3.True && st.acceptation=Bool3.True then - fprintf out " \"%s\" [shape = doubleoctagon];\n" (string_of_state st) - else if st.acceptation=Bool3.True then - fprintf out " \"%s\" [shape = octagon];\n" (string_of_state st) - else if st.init=Bool3.True then - fprintf out " \"%s\" [shape = doublecircle];\n" (string_of_state st) - else - fprintf out " \"%s\" [shape = circle];\n" (string_of_state st) - - + let shape = + if st.init = Bool3.True && st.acceptation=Bool3.True then "doubleoctagon" + else if st.acceptation=Bool3.True then "octagon" + else if st.init=Bool3.True then "doublecircle" + else "circle" + in + Format.fprintf out "\"%a\" [shape = %s];@\n" print_state_label st shape let dot_trans out tr = - fprintf + let print_label fmt tr = + if DotSeparatedLabels.get () then + Format.pp_print_int fmt tr.numt + else print_trans fmt tr + in + Format.fprintf out - " \"%s\" -> \"%s\" [ label = \"%s\"];\n" - (string_of_state tr.start) - (string_of_state tr.stop) - (if DotSeparatedLabels.get() then - trans_label tr.numt - else string_of_trans tr.numt tr.cross) - -let dot_guards out tr = - fprintf out "%s" (string_of_trans tr.numt tr.cross) + "\"%a\"@ ->@ \"%a\"@ [label = @[\"%a\"@]];@\n" + print_state_label tr.start + print_state_label tr.stop + print_label tr let output_dot_automata (states_l,trans_l) fichier = let cout = open_out fichier in - out_fmt:=formatter_of_out_channel cout ; - - fprintf !out_fmt "/* File generated by Aorai LTL2ACSL Plug-in */\n"; - fprintf !out_fmt "/* */\n"; - fprintf !out_fmt "/* Usage of dot files '.dot' : */\n"; - fprintf !out_fmt "/* dot -T > */\n"; - fprintf !out_fmt "/* */\n"; - fprintf !out_fmt "/* Allowed types : canon,dot,xdot,fig,gd,gd2, */\n"; - fprintf !out_fmt "/* gif,hpgl,imap,cmap,ismap,jpg,jpeg,mif,mp,pcl,pic,plain, */\n"; - fprintf !out_fmt "/* plain-ext,png,ps,ps2,svg,svgz,vrml,vtx,wbmp */\n"; - fprintf !out_fmt "/* */\n"; - fprintf !out_fmt "/* Example with postscript file : */\n"; - fprintf !out_fmt "/* dot property.dot -Tps > property.ps */\n"; - fprintf !out_fmt ""; - fprintf !out_fmt "digraph %s {\n" - (Filename.chop_extension (Filename.basename fichier)); - fprintf !out_fmt "\n"; - List.iter (dot_state !out_fmt) states_l; - fprintf !out_fmt "\n"; - List.iter (dot_trans !out_fmt) trans_l; - fprintf !out_fmt "\n"; - if DotSeparatedLabels.get () then begin - fprintf !out_fmt "/* guards of transitions */@\ncomment=\"%a\";@\n" - (Pretty_utils.pp_list ~sep:(format_of_string "\\n") dot_guards) trans_l - end; - fprintf !out_fmt "} /*End of graph*/\n"; - fprintf !out_fmt "\n"; - - close_out cout; - out_fmt:=formatter_of_out_channel stdout - - - - + let fmt = formatter_of_out_channel cout in + escape_newline fmt; + let one_line_comment s = + let l = String.length s in + let fill = if l >= 75 then 0 else 75 - l in + let spaces = String.make fill ' ' in + Format.fprintf fmt "@[/* %s%s*/@\n@]" s spaces + in + one_line_comment "File generated by Aorai LTL2ACSL Plug-in"; + one_line_comment ""; + one_line_comment "Usage of dot files '.dot' :"; + one_line_comment " dot -T > "; + one_line_comment ""; + one_line_comment " Allowed types : canon,dot,xdot,fig,gd,gd2,"; + one_line_comment " gif,hpgl,imap,cmap,ismap,jpg,jpeg,mif,mp,pcl,pic,plain,"; + one_line_comment " plain-ext,png,ps,ps2,svg,svgz,vrml,vtx,wbmp"; + one_line_comment ""; + one_line_comment " Example with postscript file :"; + one_line_comment " dot property.dot -Tps > property.ps"; + Format.fprintf fmt "@[<2>@\ndigraph %s {@\n@\n%a@\n%a@\n%t}@\n@]" + (Filename.chop_extension (Filename.basename fichier)) + (Pretty_utils.pp_list dot_state) states_l + (Pretty_utils.pp_list dot_trans) trans_l + (fun fmt -> + if DotSeparatedLabels.get () then + (Format.fprintf fmt + "/* guards of transitions */@\ncomment=%t\"%a\"%t;@\n" + escape_newline + (Pretty_utils.pp_list ~sep:"@\n" print_trans) trans_l + normal_newline + )); + normal_newline fmt; + close_out cout (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaoutput.mli frama-c-20111001+nitrogen+dfsg/src/aorai/promelaoutput.mli --- frama-c-20110201+carbon+dfsg/src/aorai/promelaoutput.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaoutput.mli 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -21,28 +23,37 @@ (* *) (**************************************************************************) -(* $Id: promelaoutput.mli,v 1.2 2008-10-02 13:33:29 uid588 Exp $ *) - open Promelaast -val print_raw_automata : Promelaast.buchautomata -> unit -(*val print_automata : Promelaast.buchautomata -> unit*) +val print_raw_automata : + Format.formatter -> Promelaast.typed_automaton -> unit -val print_transition : Promelaast.trans -> unit -val print_transitionl : Promelaast.trans list -> unit +val print_parsed_expression: Format.formatter -> Promelaast.expression -> unit -val print_state : Promelaast.state -> unit -val print_statel : Promelaast.state list -> unit +val print_parsed_condition: Format.formatter -> Promelaast.condition -> unit +val print_seq_elt: Format.formatter -> Promelaast.seq_elt -> unit -(*val print_automata_axiomatization : Promelaast.buchautomata -> unit -val print_automata_specification : Promelaast.buchautomata -> string list -> string -> string -> unit -*) +val print_sequence: Format.formatter -> Promelaast.sequence -> unit + +val print_parsed: Format.formatter -> Promelaast.parsed_condition -> unit + +val print_condition: Format.formatter -> Promelaast.typed_condition -> unit + +val print_action: Format.formatter -> Promelaast.action -> unit -val output_dot_automata : Promelaast.buchautomata -> string -> unit +val print_transition: + Format.formatter -> + (Promelaast.typed_condition * Promelaast.action) Promelaast.trans -> unit +val print_transitionl: + Format.formatter -> + (Promelaast.typed_condition * Promelaast.action) Promelaast.trans list -> unit +val print_state : Format.formatter -> Promelaast.state -> unit +val print_statel : Format.formatter -> Promelaast.state list -> unit +val output_dot_automata : Promelaast.typed_automaton -> string -> unit (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaparser.ml frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser.ml --- frama-c-20110201+carbon+dfsg/src/aorai/promelaparser.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser.ml 2011-10-10 08:48:50.000000000 +0000 @@ -24,18 +24,20 @@ | EOF open Parsing;; -# 28 "src/aorai/promelaparser.mly" +# 30 "src/aorai/promelaparser.mly" open Parsing open Promelaast open Bool3 - let observed_states=Hashtbl.create 1 -let observed_vars=Hashtbl.create 1 -let observed_funcs=Hashtbl.create 1 +let to_seq c = + [{ condition = Some c; nested = []; + min_rep = Some (PCst (Logic_ptree.IntConstant "1")); + max_rep = Some (PCst (Logic_ptree.IntConstant "1")); + }] -# 39 "src/aorai/promelaparser.ml" +# 41 "src/aorai/promelaparser.ml" let yytransl_const = [| 257 (* PROMELA_OR *); 258 (* PROMELA_AND *); @@ -167,74 +169,62 @@ ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'states) in Obj.repr( -# 66 "src/aorai/promelaparser.mly" +# 70 "src/aorai/promelaparser.mly" ( let states= Hashtbl.fold (fun _ st l -> if st.acceptation=Undefined or st.init=Undefined then begin - Format.print_string ("Error: the state '"^(st.name)^"' is used but never defined.\n"); - exit 1 + Aorai_option.abort + "Error: the state %s is used but never defined" st.name; end; st::l ) observed_states [] - in - let n=ref 0 in - let (transitions,_) = Logic_simplification.simplifyTrans _3 in - List.iter (fun t -> t.numt<-(!n); n:=!n+1) transitions; - - ((states , transitions),observed_vars,observed_funcs) + in + (states , _3) ) -# 189 "src/aorai/promelaparser.ml" - : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t))) +# 187 "src/aorai/promelaparser.ml" + : Promelaast.parsed_automaton)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 3 : 'states) in Obj.repr( -# 83 "src/aorai/promelaparser.mly" - ( - let states= - Hashtbl.fold (fun _ st l -> - if st.acceptation=Undefined or st.init=Undefined then - begin - Format.print_string ("Error: the state '"^(st.name)^"' is used but never defined.\n"); - exit 1 - end; - st::l - ) observed_states [] - in - let n=ref 0 in - let (transitions,_) = Logic_simplification.simplifyTrans _3 in - List.iter (fun t -> t.numt<-(!n); n:=!n+1) transitions; - - - ((states , transitions),observed_vars,observed_funcs) ) -# 212 "src/aorai/promelaparser.ml" - : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t))) +# 84 "src/aorai/promelaparser.mly" + ( + let states= + Hashtbl.fold (fun _ st l -> + if st.acceptation=Undefined or st.init=Undefined then + begin + Aorai_option.abort + "Error: the state %s is used but never defined" st.name; + end; + st::l + ) observed_states [] + in + (states , _3) ) +# 205 "src/aorai/promelaparser.ml" + : Promelaast.parsed_automaton)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'states) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'state) in Obj.repr( -# 105 "src/aorai/promelaparser.mly" +# 99 "src/aorai/promelaparser.mly" ( _1@_3 - (*let (s1,t1)=$1 in - let (s2,t2)=$3 in - (s1@s2,t1@t2)*) ) -# 225 "src/aorai/promelaparser.ml" +# 215 "src/aorai/promelaparser.ml" : 'states)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'state) in Obj.repr( -# 111 "src/aorai/promelaparser.mly" +# 102 "src/aorai/promelaparser.mly" ( _1 ) -# 232 "src/aorai/promelaparser.ml" +# 222 "src/aorai/promelaparser.ml" : 'states)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'state_labels) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'state_body) in Obj.repr( -# 115 "src/aorai/promelaparser.mly" +# 106 "src/aorai/promelaparser.mly" ( let (stl,trans)=_1 in let (trl,force_final)=_2 in @@ -244,7 +234,8 @@ try (Hashtbl.find observed_states s.name).acceptation <- True with - | Not_found -> assert false (* This state has to be in the hashtable -- by construction *) + | Not_found -> assert false + (* This state has to be in the hashtable -- by construction *) ) stl end; if trl=[] then @@ -253,41 +244,37 @@ let tr_list= List.fold_left (fun l1 (cr,stop_st) -> List.fold_left (fun l2 st -> - {start=st;stop=stop_st;cross=cr;numt=(-1)}::l2 + {start=st;stop=stop_st;cross=Seq (to_seq cr);numt=(-1)}::l2 ) l1 stl ) [] trl in (List.rev tr_list)@trans - - - - ) -# 267 "src/aorai/promelaparser.ml" +# 254 "src/aorai/promelaparser.ml" : 'state)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'label) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'state_labels) in Obj.repr( -# 146 "src/aorai/promelaparser.mly" +# 134 "src/aorai/promelaparser.mly" ( let (stl1,trl1)=_1 in let (stl2,trl2)=_2 in (stl1@stl2,trl1@trl2) ) -# 279 "src/aorai/promelaparser.ml" +# 266 "src/aorai/promelaparser.ml" : 'state_labels)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'label) in Obj.repr( -# 151 "src/aorai/promelaparser.mly" +# 139 "src/aorai/promelaparser.mly" ( _1 ) -# 286 "src/aorai/promelaparser.ml" +# 273 "src/aorai/promelaparser.ml" : 'state_labels)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 155 "src/aorai/promelaparser.mly" +# 143 "src/aorai/promelaparser.mly" ( begin (* Step 0 : trans is the set of new transitions and old is the description of the current state *) @@ -299,164 +286,174 @@ Hashtbl.find observed_states _1 with | Not_found -> - let s={name=_1;acceptation=Undefined;init=Undefined;nums=(Hashtbl.length observed_states)} in + let s = Data_for_aorai.new_state _1 in Hashtbl.add observed_states _1 s; s in - (* Step 1 : setting up the acceptance status *) + (* Step 1 : setting up the acceptance status *) (* Default status : Non acceptation state *) old.acceptation <- False; - (* Accept_all state means acceptance state with a reflexive transition without cross condition *) - (* This case is not exlusive with the following. Acceptation status is set in this last. *) - if (String.length _1>=10) && (String.compare (String.sub _1 0 10) "accept_all")=0 then - trans:={start=old;stop=old;cross=PTrue;numt=(-1)}::!trans; - - (* If the name includes accept then this state is an acceptation one. *) - if (String.length _1>=7) && (String.compare (String.sub _1 0 7) "accept_")=0 then + (* Accept_all state means acceptance state with a + reflexive transition without cross condition *) + (* This case is not exclusive with the following. + Acceptation status is set in this last. *) + if (String.length _1>=10) && + (String.compare (String.sub _1 0 10) "accept_all")=0 + then + trans:= + {start=old;stop=old;cross=Seq (to_seq PTrue);numt=(-1)} :: + !trans; + (* If the name includes accept then + this state is an acceptation one. *) + if (String.length _1>=7) && + (String.compare (String.sub _1 0 7) "accept_")=0 + then old.acceptation <- True; - (* Step 2 : setting up the init status *) - (* If the state name ended with "_init" then it is an initial state. Else, it is not. *) - if (String.length _1>=5) && (String.compare (String.sub _1 ((String.length _1)-5) 5) "_init" ) = 0 - then + (* Step 2 : setting up the init status *) + (* If the state name ended with "_init" then + it is an initial state. Else, it is not. *) + if (String.length _1>=5) && + (String.compare (String.sub _1 ((String.length _1)-5) 5) + "_init" ) = 0 + then old.init <- True else old.init <- False; - ([old],!trans) end ) -# 331 "src/aorai/promelaparser.ml" +# 328 "src/aorai/promelaparser.ml" : 'label)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'transitions) in Obj.repr( -# 198 "src/aorai/promelaparser.mly" +# 196 "src/aorai/promelaparser.mly" ( (_2,false) ) -# 338 "src/aorai/promelaparser.ml" +# 335 "src/aorai/promelaparser.ml" : 'state_body)) ; (fun __caml_parser_env -> Obj.repr( -# 199 "src/aorai/promelaparser.mly" +# 197 "src/aorai/promelaparser.mly" ( ([],false) ) -# 344 "src/aorai/promelaparser.ml" +# 341 "src/aorai/promelaparser.ml" : 'state_body)) ; (fun __caml_parser_env -> Obj.repr( -# 200 "src/aorai/promelaparser.mly" +# 198 "src/aorai/promelaparser.mly" ( ([],true) ) -# 350 "src/aorai/promelaparser.ml" +# 347 "src/aorai/promelaparser.ml" : 'state_body)) ; (fun __caml_parser_env -> Obj.repr( -# 201 "src/aorai/promelaparser.mly" +# 199 "src/aorai/promelaparser.mly" ( ([],true) ) -# 356 "src/aorai/promelaparser.ml" +# 353 "src/aorai/promelaparser.ml" : 'state_body)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'transitions) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'transition) in Obj.repr( -# 206 "src/aorai/promelaparser.mly" +# 204 "src/aorai/promelaparser.mly" ( _1@[_2] ) -# 364 "src/aorai/promelaparser.ml" +# 361 "src/aorai/promelaparser.ml" : 'transitions)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'transition) in Obj.repr( -# 207 "src/aorai/promelaparser.mly" +# 205 "src/aorai/promelaparser.mly" ( [_1] ) -# 371 "src/aorai/promelaparser.ml" +# 368 "src/aorai/promelaparser.ml" : 'transitions)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'guard) in let _5 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 211 "src/aorai/promelaparser.mly" +# 209 "src/aorai/promelaparser.mly" ( let s= try Hashtbl.find observed_states _5 with Not_found -> - let r={name=_5;init=Undefined;acceptation=Undefined;nums=(Hashtbl.length observed_states)} in - Hashtbl.add observed_states _5 r; - r + let r = Data_for_aorai.new_state _5 in + Hashtbl.add observed_states _5 r; + r in - (_2,s) + (_2,s) ) -# 390 "src/aorai/promelaparser.ml" +# 387 "src/aorai/promelaparser.ml" : 'transition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 227 "src/aorai/promelaparser.mly" - ( if not (Hashtbl.mem observed_funcs _1) then Hashtbl.add observed_funcs _1 _1 ; PCallOrReturn _1 ) -# 397 "src/aorai/promelaparser.ml" +# 224 "src/aorai/promelaparser.mly" + ( POr(PCall (_1,None), PReturn _1) ) +# 394 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 229 "src/aorai/promelaparser.mly" - ( if not (Hashtbl.mem observed_funcs _1) then Hashtbl.add observed_funcs _1 _1 ; PCall _1 ) -# 404 "src/aorai/promelaparser.ml" +# 225 "src/aorai/promelaparser.mly" + ( PCall (_1,None) ) +# 401 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 231 "src/aorai/promelaparser.mly" - ( if not (Hashtbl.mem observed_funcs _1) then Hashtbl.add observed_funcs _1 _1 ; PReturn _1 ) -# 411 "src/aorai/promelaparser.ml" +# 226 "src/aorai/promelaparser.mly" + ( PReturn _1 ) +# 408 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> Obj.repr( -# 233 "src/aorai/promelaparser.mly" - ( PTrue ) -# 417 "src/aorai/promelaparser.ml" +# 227 "src/aorai/promelaparser.mly" + ( PTrue ) +# 414 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> Obj.repr( -# 235 "src/aorai/promelaparser.mly" - ( PFalse ) -# 423 "src/aorai/promelaparser.ml" +# 228 "src/aorai/promelaparser.mly" + ( PFalse ) +# 420 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in Obj.repr( -# 237 "src/aorai/promelaparser.mly" - ( PNot _2 ) -# 430 "src/aorai/promelaparser.ml" +# 229 "src/aorai/promelaparser.mly" + ( PNot _2 ) +# 427 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'guard) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in Obj.repr( -# 239 "src/aorai/promelaparser.mly" - ( PAnd (_1,_3) ) -# 438 "src/aorai/promelaparser.ml" +# 230 "src/aorai/promelaparser.mly" + ( PAnd (_1,_3) ) +# 435 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'guard) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in Obj.repr( -# 241 "src/aorai/promelaparser.mly" - ( POr (_1,_3) ) -# 446 "src/aorai/promelaparser.ml" +# 231 "src/aorai/promelaparser.mly" + ( POr (_1,_3) ) +# 443 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'guard) in Obj.repr( -# 243 "src/aorai/promelaparser.mly" - ( _2 ) -# 453 "src/aorai/promelaparser.ml" +# 232 "src/aorai/promelaparser.mly" + ( _2 ) +# 450 "src/aorai/promelaparser.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 245 "src/aorai/promelaparser.mly" - ( if not (Hashtbl.mem observed_vars _1) then Hashtbl.add observed_vars _1 _1 ; PIndexedExp _1 ) -# 460 "src/aorai/promelaparser.ml" +# 234 "src/aorai/promelaparser.mly" + ( PRel (Logic_ptree.Neq,PVar _1,PCst(Logic_ptree.IntConstant "0")) ) +# 457 "src/aorai/promelaparser.ml" : 'guard)) (* Entry promela *) ; (fun __caml_parser_env -> raise (Parsing.YYexit (Parsing.peek_val __caml_parser_env 0))) @@ -479,4 +476,4 @@ Parsing.names_const=yynames_const; Parsing.names_block=yynames_block } let promela (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) = - (Parsing.yyparse yytables 1 lexfun lexbuf : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t)) + (Parsing.yyparse yytables 1 lexfun lexbuf : Promelaast.parsed_automaton) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaparser.mli frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser.mli --- frama-c-20110201+carbon+dfsg/src/aorai/promelaparser.mli 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser.mli 2011-10-10 08:48:50.000000000 +0000 @@ -24,4 +24,4 @@ | EOF val promela : - (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t) + (Lexing.lexbuf -> token) -> Lexing.lexbuf -> Promelaast.parsed_automaton diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaparser.mly frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser.mly --- frama-c-20110201+carbon+dfsg/src/aorai/promelaparser.mly 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser.mly 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ /**************************************************************************/ /* */ -/* This file is part of Frama-C. */ +/* This file is part of Aorai plug-in of Frama-C. */ /* */ /* Copyright (C) 2007-2011 */ -/* INSA (Institut National des Sciences Appliquees) */ +/* CEA (Commissariat a l'énergie atomique et aux énergies */ +/* alternatives) */ /* INRIA (Institut National de Recherche en Informatique et en */ /* Automatique) */ +/* INSA (Institut National des Sciences Appliquees) */ /* */ /* you can redistribute it and/or modify it under the terms of the GNU */ /* Lesser General Public License as published by the Free Software */ @@ -29,11 +31,13 @@ open Promelaast open Bool3 - let observed_states=Hashtbl.create 1 -let observed_vars=Hashtbl.create 1 -let observed_funcs=Hashtbl.create 1 +let to_seq c = + [{ condition = Some c; nested = []; + min_rep = Some (PCst (Logic_ptree.IntConstant "1")); + max_rep = Some (PCst (Logic_ptree.IntConstant "1")); + }] %} @@ -58,7 +62,7 @@ %token EOF -%type <(Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t)> promela +%type promela %start promela %% @@ -68,45 +72,32 @@ Hashtbl.fold (fun _ st l -> if st.acceptation=Undefined or st.init=Undefined then begin - Format.print_string ("Error: the state '"^(st.name)^"' is used but never defined.\n"); - exit 1 + Aorai_option.abort + "Error: the state %s is used but never defined" st.name; end; st::l ) observed_states [] - in - let n=ref 0 in - let (transitions,_) = Logic_simplification.simplifyTrans $3 in - List.iter (fun t -> t.numt<-(!n); n:=!n+1) transitions; - - ((states , transitions),observed_vars,observed_funcs) + in + (states , $3) } - | PROMELA_NEVER PROMELA_LBRACE states PROMELA_SEMICOLON PROMELA_RBRACE EOF { - let states= - Hashtbl.fold (fun _ st l -> - if st.acceptation=Undefined or st.init=Undefined then - begin - Format.print_string ("Error: the state '"^(st.name)^"' is used but never defined.\n"); - exit 1 - end; - st::l - ) observed_states [] - in - let n=ref 0 in - let (transitions,_) = Logic_simplification.simplifyTrans $3 in - List.iter (fun t -> t.numt<-(!n); n:=!n+1) transitions; - - - ((states , transitions),observed_vars,observed_funcs) } + | PROMELA_NEVER PROMELA_LBRACE states PROMELA_SEMICOLON + PROMELA_RBRACE EOF { + let states= + Hashtbl.fold (fun _ st l -> + if st.acceptation=Undefined or st.init=Undefined then + begin + Aorai_option.abort + "Error: the state %s is used but never defined" st.name; + end; + st::l + ) observed_states [] + in + (states , $3) } ; - - states : states PROMELA_SEMICOLON state { $1@$3 - (*let (s1,t1)=$1 in - let (s2,t2)=$3 in - (s1@s2,t1@t2)*) } | state { $1 } ; @@ -121,7 +112,8 @@ try (Hashtbl.find observed_states s.name).acceptation <- True with - | Not_found -> assert false (* This state has to be in the hashtable -- by construction *) + | Not_found -> assert false + (* This state has to be in the hashtable -- by construction *) ) stl end; if trl=[] then @@ -130,15 +122,11 @@ let tr_list= List.fold_left (fun l1 (cr,stop_st) -> List.fold_left (fun l2 st -> - {start=st;stop=stop_st;cross=cr;numt=(-1)}::l2 + {start=st;stop=stop_st;cross=Seq (to_seq cr);numt=(-1)}::l2 ) l1 stl ) [] trl in (List.rev tr_list)@trans - - - - } ; @@ -163,31 +151,41 @@ Hashtbl.find observed_states $1 with | Not_found -> - let s={name=$1;acceptation=Undefined;init=Undefined;nums=(Hashtbl.length observed_states)} in + let s = Data_for_aorai.new_state $1 in Hashtbl.add observed_states $1 s; s in - (* Step 1 : setting up the acceptance status *) + (* Step 1 : setting up the acceptance status *) (* Default status : Non acceptation state *) old.acceptation <- False; - (* Accept_all state means acceptance state with a reflexive transition without cross condition *) - (* This case is not exlusive with the following. Acceptation status is set in this last. *) - if (String.length $1>=10) && (String.compare (String.sub $1 0 10) "accept_all")=0 then - trans:={start=old;stop=old;cross=PTrue;numt=(-1)}::!trans; - - (* If the name includes accept then this state is an acceptation one. *) - if (String.length $1>=7) && (String.compare (String.sub $1 0 7) "accept_")=0 then + (* Accept_all state means acceptance state with a + reflexive transition without cross condition *) + (* This case is not exclusive with the following. + Acceptation status is set in this last. *) + if (String.length $1>=10) && + (String.compare (String.sub $1 0 10) "accept_all")=0 + then + trans:= + {start=old;stop=old;cross=Seq (to_seq PTrue);numt=(-1)} :: + !trans; + (* If the name includes accept then + this state is an acceptation one. *) + if (String.length $1>=7) && + (String.compare (String.sub $1 0 7) "accept_")=0 + then old.acceptation <- True; - (* Step 2 : setting up the init status *) - (* If the state name ended with "_init" then it is an initial state. Else, it is not. *) - if (String.length $1>=5) && (String.compare (String.sub $1 ((String.length $1)-5) 5) "_init" ) = 0 - then + (* Step 2 : setting up the init status *) + (* If the state name ended with "_init" then + it is an initial state. Else, it is not. *) + if (String.length $1>=5) && + (String.compare (String.sub $1 ((String.length $1)-5) 5) + "_init" ) = 0 + then old.init <- True else old.init <- False; - ([old],!trans) end } @@ -214,33 +212,24 @@ Hashtbl.find observed_states $5 with Not_found -> - let r={name=$5;init=Undefined;acceptation=Undefined;nums=(Hashtbl.length observed_states)} in - Hashtbl.add observed_states $5 r; - r + let r = Data_for_aorai.new_state $5 in + Hashtbl.add observed_states $5 r; + r in - ($2,s) + ($2,s) } ; guard - : PROMELA_CALLORRETURNOF - { if not (Hashtbl.mem observed_funcs $1) then Hashtbl.add observed_funcs $1 $1 ; PCallOrReturn $1 } - | PROMELA_CALLOF - { if not (Hashtbl.mem observed_funcs $1) then Hashtbl.add observed_funcs $1 $1 ; PCall $1 } - | PROMELA_RETURNOF - { if not (Hashtbl.mem observed_funcs $1) then Hashtbl.add observed_funcs $1 $1 ; PReturn $1 } - | PROMELA_TRUE - { PTrue } - | PROMELA_FALSE - { PFalse } - | PROMELA_NOT guard - { PNot $2 } - | guard PROMELA_AND guard - { PAnd ($1,$3) } - | guard PROMELA_OR guard - { POr ($1,$3) } - | PROMELA_LPAREN guard PROMELA_RPAREN - { $2 } - | PROMELA_LABEL - { if not (Hashtbl.mem observed_vars $1) then Hashtbl.add observed_vars $1 $1 ; PIndexedExp $1 } + : PROMELA_CALLORRETURNOF { POr(PCall ($1,None), PReturn $1) } + | PROMELA_CALLOF { PCall ($1,None) } + | PROMELA_RETURNOF { PReturn $1 } + | PROMELA_TRUE { PTrue } + | PROMELA_FALSE { PFalse } + | PROMELA_NOT guard { PNot $2 } + | guard PROMELA_AND guard { PAnd ($1,$3) } + | guard PROMELA_OR guard { POr ($1,$3) } + | PROMELA_LPAREN guard PROMELA_RPAREN { $2 } + | PROMELA_LABEL + { PRel (Logic_ptree.Neq,PVar $1,PCst(Logic_ptree.IntConstant "0")) } ; diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaparser_withexps.ml frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser_withexps.ml --- frama-c-20110201+carbon+dfsg/src/aorai/promelaparser_withexps.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser_withexps.ml 2011-10-10 08:48:50.000000000 +0000 @@ -40,36 +40,21 @@ | PROMELA_FUNC open Parsing;; -# 28 "src/aorai/promelaparser_withexps.mly" +# 30 "src/aorai/promelaparser_withexps.mly" +open Logic_ptree open Parsing open Promelaast open Bool3 let observed_states=Hashtbl.create 1 -let observed_vars=Hashtbl.create 1 -let observed_funcs=Hashtbl.create 1 -let observed_expressions=Hashtbl.create 97 - - -(* Current observed expr contains : *) -type observed_expr = Func_ret of string (* func name : a return of the given func *) - | Func_param of string * (string list) (* Func name * param : a call with given param *) - | Only_vars (* Only constants and variables *) - -let observed_expr_is_param = ref Only_vars - - -let ident_count=ref 0 -let get_fresh_ident () = - ident_count:=!ident_count+1; - ("buchfreshident"^(string_of_int !ident_count)) - -(*TODO: give a proper loc*) -let new_exp = Cil.new_exp ~loc:(Cil.CurrentLoc.get()) - -# 73 "src/aorai/promelaparser_withexps.ml" +let to_seq c = + [{ condition = Some c; nested = []; + min_rep = Some (PCst (IntConstant "1")); + max_rep = Some (PCst (IntConstant "1")); + }] +# 58 "src/aorai/promelaparser_withexps.ml" let yytransl_const = [| 257 (* PROMELA_OR *); 258 (* PROMELA_AND *); @@ -297,7 +282,7 @@ ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 2 : 'states) in Obj.repr( -# 100 "src/aorai/promelaparser_withexps.mly" +# 81 "src/aorai/promelaparser_withexps.mly" ( let states= Hashtbl.fold (fun _ st l -> @@ -308,71 +293,49 @@ end; st::l ) observed_states [] - in - Data_for_aorai.setLtl_expressions observed_expressions; - Logic_simplification.setLtl_expressions observed_expressions; - let n=ref 0 in - let (transitions,pcondsl) = Logic_simplification.simplifyTrans _3 in - let conds = Array.make (List.length transitions) [] in - List.iter2 (fun t pc -> t.numt<-(!n); conds.(!n)<-pc; n:=!n+1) transitions pcondsl; - Data_for_aorai.setCondOfParametrizedTransition conds; - - ((states , transitions),observed_vars,observed_funcs) + in + (states , _3) ) -# 323 "src/aorai/promelaparser_withexps.ml" - : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t))) +# 300 "src/aorai/promelaparser_withexps.ml" + : Promelaast.parsed_automaton)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 3 : 'states) in Obj.repr( -# 121 "src/aorai/promelaparser_withexps.mly" - ( +# 95 "src/aorai/promelaparser_withexps.mly" + ( let states= Hashtbl.fold (fun _ st l -> if st.acceptation=Undefined or st.init=Undefined then begin - Format.print_string ("Error: the state '"^(st.name)^"' is used but never defined.\n"); - exit 1 + Aorai_option.abort + "Error: state %s is used bug never defined" st.name end; st::l ) observed_states [] in - Data_for_aorai.setLtl_expressions observed_expressions; - Logic_simplification.setLtl_expressions observed_expressions; - let n=ref 0 in - let (transitions,pcondsl) = Logic_simplification.simplifyTrans _3 in - let conds = Array.make (List.length transitions) [] in - List.iter2 (fun t pc -> t.numt<-(!n); conds.(!n)<-pc; n:=!n+1) transitions pcondsl; - Data_for_aorai.setCondOfParametrizedTransition conds; - - - ((states , transitions),observed_vars,observed_funcs) ) -# 350 "src/aorai/promelaparser_withexps.ml" - : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t))) + (states , _3) ) +# 318 "src/aorai/promelaparser_withexps.ml" + : Promelaast.parsed_automaton)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'states) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'state) in Obj.repr( -# 147 "src/aorai/promelaparser_withexps.mly" - ( - _1@_3 - (*let (s1,t1)=$1 in - let (s2,t2)=$3 in - (s1@s2,t1@t2)*) - ) -# 363 "src/aorai/promelaparser_withexps.ml" +# 110 "src/aorai/promelaparser_withexps.mly" + ( _1@_3 ) +# 326 "src/aorai/promelaparser_withexps.ml" : 'states)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'state) in Obj.repr( -# 153 "src/aorai/promelaparser_withexps.mly" +# 111 "src/aorai/promelaparser_withexps.mly" ( _1 ) -# 370 "src/aorai/promelaparser_withexps.ml" +# 333 "src/aorai/promelaparser_withexps.ml" : 'states)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'state_labels) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'state_body) in Obj.repr( -# 157 "src/aorai/promelaparser_withexps.mly" +# 115 "src/aorai/promelaparser_withexps.mly" ( let (stl,trans)=_1 in let (trl,force_final)=_2 in @@ -382,7 +345,8 @@ try (Hashtbl.find observed_states s.name).acceptation <- True with - | Not_found -> assert false (* This state has to be in the hashtable -- by construction *) + | Not_found -> assert false + (* This state has to be in the hashtable -- by construction *) ) stl end; if trl=[] then @@ -391,73 +355,83 @@ let tr_list= List.fold_left (fun l1 (cr,stop_st) -> List.fold_left (fun l2 st -> - {start=st;stop=stop_st;cross=cr;numt=(-1)}::l2 + {start=st;stop=stop_st;cross=Seq (to_seq cr);numt=(-1)}::l2 ) l1 stl - ) [] trl + ) [] trl in - (List.rev tr_list)@trans - - - - + (List.rev tr_list)@trans ) -# 405 "src/aorai/promelaparser_withexps.ml" +# 365 "src/aorai/promelaparser_withexps.ml" : 'state)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'label) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'state_labels) in Obj.repr( -# 188 "src/aorai/promelaparser_withexps.mly" +# 143 "src/aorai/promelaparser_withexps.mly" ( let (stl1,trl1)=_1 in let (stl2,trl2)=_2 in (stl1@stl2,trl1@trl2) ) -# 417 "src/aorai/promelaparser_withexps.ml" +# 377 "src/aorai/promelaparser_withexps.ml" : 'state_labels)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'label) in Obj.repr( -# 193 "src/aorai/promelaparser_withexps.mly" +# 148 "src/aorai/promelaparser_withexps.mly" ( _1 ) -# 424 "src/aorai/promelaparser_withexps.ml" +# 384 "src/aorai/promelaparser_withexps.ml" : 'state_labels)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 197 "src/aorai/promelaparser_withexps.mly" +# 152 "src/aorai/promelaparser_withexps.mly" ( begin - (* Step 0 : trans is the set of new transitions and old is the description of the current state *) + (* Step 0 : trans is the set of new transitions and old + is the description of the current state *) let trans = ref [] in - (* Promela Label is a state. According to its name, we will try to give him its properties (init / accept) *) - (* Firstly, if this state is still referenced, then we get it back. Else, we make a new "empty" state *) + (* Promela Label is a state. According to its name, + we will try to give him its properties (init / accept) *) + (* Firstly, if this state is still referenced, + then we get it back. Else, we make a new "empty" state *) let old= try Hashtbl.find observed_states _1 with | Not_found -> - let s={name=_1;acceptation=Undefined;init=Undefined;nums=(Hashtbl.length observed_states)} in + let s = Data_for_aorai.new_state _1 in Hashtbl.add observed_states _1 s; s in - (* Step 1 : setting up the acceptance status *) + (* Step 1 : setting up the acceptance status *) (* Default status : Non acceptation state *) old.acceptation <- False; - (* Accept_all state means acceptance state with a reflexive transition without cross condition *) - (* This case is not exlusive with the following. Acceptation status is set in this last. *) - if (String.length _1>=10) && (String.compare (String.sub _1 0 10) "accept_all")=0 then - trans:={start=old;stop=old;cross=PTrue;numt=(-1)}::!trans; + (* Accept_all state means acceptance state with a + reflexive transition without cross condition *) + (* This case is not exclusive with the following. + Acceptation status is set in this last. *) + if (String.length _1>=10) && + (String.compare (String.sub _1 0 10) "accept_all")=0 + then + trans:= + {start=old;stop=old;cross=Seq (to_seq PTrue);numt=(-1)}::!trans; - (* If the name includes accept then this state is an acceptation one. *) - if (String.length _1>=7) && (String.compare (String.sub _1 0 7) "accept_")=0 then + (* If the name includes accept then this state is + an acceptation one. *) + if (String.length _1>=7) && + (String.compare (String.sub _1 0 7) "accept_")=0 + then old.acceptation <- True; - (* Step 2 : setting up the init status *) - (* If the state name ended with "_init" then it is an initial state. Else, it is not. *) - if (String.length _1>=5) && (String.compare (String.sub _1 ((String.length _1)-5) 5) "_init" ) = 0 - then + (* Step 2 : setting up the init status *) + (* If the state name ended with "_init" then + it is an initial state. Else, it is not. *) + if (String.length _1>=5) && + (String.compare + (String.sub _1 ((String.length _1)-5) 5) "_init" ) = 0 + then old.init <- True else old.init <- False; @@ -465,400 +439,332 @@ ([old],!trans) end ) -# 469 "src/aorai/promelaparser_withexps.ml" +# 443 "src/aorai/promelaparser_withexps.ml" : 'label)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'transitions) in Obj.repr( -# 240 "src/aorai/promelaparser_withexps.mly" +# 209 "src/aorai/promelaparser_withexps.mly" ( (_2,false) ) -# 476 "src/aorai/promelaparser_withexps.ml" +# 450 "src/aorai/promelaparser_withexps.ml" : 'state_body)) ; (fun __caml_parser_env -> Obj.repr( -# 241 "src/aorai/promelaparser_withexps.mly" +# 210 "src/aorai/promelaparser_withexps.mly" ( ([],false) ) -# 482 "src/aorai/promelaparser_withexps.ml" +# 456 "src/aorai/promelaparser_withexps.ml" : 'state_body)) ; (fun __caml_parser_env -> Obj.repr( -# 242 "src/aorai/promelaparser_withexps.mly" +# 211 "src/aorai/promelaparser_withexps.mly" ( ([],true) ) -# 488 "src/aorai/promelaparser_withexps.ml" +# 462 "src/aorai/promelaparser_withexps.ml" : 'state_body)) ; (fun __caml_parser_env -> Obj.repr( -# 243 "src/aorai/promelaparser_withexps.mly" +# 212 "src/aorai/promelaparser_withexps.mly" ( ([],true) ) -# 494 "src/aorai/promelaparser_withexps.ml" +# 468 "src/aorai/promelaparser_withexps.ml" : 'state_body)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'transitions) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'transition) in Obj.repr( -# 248 "src/aorai/promelaparser_withexps.mly" +# 217 "src/aorai/promelaparser_withexps.mly" ( _1@[_2] ) -# 502 "src/aorai/promelaparser_withexps.ml" +# 476 "src/aorai/promelaparser_withexps.ml" : 'transitions)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'transition) in Obj.repr( -# 249 "src/aorai/promelaparser_withexps.mly" +# 218 "src/aorai/promelaparser_withexps.mly" ( [_1] ) -# 509 "src/aorai/promelaparser_withexps.ml" +# 483 "src/aorai/promelaparser_withexps.ml" : 'transitions)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 3 : 'guard) in let _5 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 253 "src/aorai/promelaparser_withexps.mly" - ( +# 223 "src/aorai/promelaparser_withexps.mly" + ( let s= try Hashtbl.find observed_states _5 with Not_found -> - let r={name=_5;init=Undefined;acceptation=Undefined;nums=(Hashtbl.length observed_states)} in - Hashtbl.add observed_states _5 r; - r + let r = Data_for_aorai.new_state _5 in + Hashtbl.add observed_states _5 r; + r in - (_2,s) + (_2,s) ) -# 528 "src/aorai/promelaparser_withexps.ml" +# 502 "src/aorai/promelaparser_withexps.ml" : 'transition)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 269 "src/aorai/promelaparser_withexps.mly" - ( if not (Hashtbl.mem observed_funcs _1) then Hashtbl.add observed_funcs _1 _1 ; PCallOrReturn _1 ) -# 535 "src/aorai/promelaparser_withexps.ml" +# 238 "src/aorai/promelaparser_withexps.mly" + ( POr(PCall (_1,None), PReturn _1) ) +# 509 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 271 "src/aorai/promelaparser_withexps.mly" - ( if not (Hashtbl.mem observed_funcs _1) then Hashtbl.add observed_funcs _1 _1 ; PCall _1 ) -# 542 "src/aorai/promelaparser_withexps.ml" +# 239 "src/aorai/promelaparser_withexps.mly" + ( PCall (_1,None) ) +# 516 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 273 "src/aorai/promelaparser_withexps.mly" - ( if not (Hashtbl.mem observed_funcs _1) then Hashtbl.add observed_funcs _1 _1 ; PReturn _1 ) -# 549 "src/aorai/promelaparser_withexps.ml" +# 240 "src/aorai/promelaparser_withexps.mly" + ( PReturn _1 ) +# 523 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> Obj.repr( -# 275 "src/aorai/promelaparser_withexps.mly" - ( PTrue ) -# 555 "src/aorai/promelaparser_withexps.ml" +# 241 "src/aorai/promelaparser_withexps.mly" + ( PTrue ) +# 529 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> Obj.repr( -# 277 "src/aorai/promelaparser_withexps.mly" - ( PFalse ) -# 561 "src/aorai/promelaparser_withexps.ml" +# 242 "src/aorai/promelaparser_withexps.mly" + ( PFalse ) +# 535 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in Obj.repr( -# 279 "src/aorai/promelaparser_withexps.mly" - ( PNot _2 ) -# 568 "src/aorai/promelaparser_withexps.ml" +# 243 "src/aorai/promelaparser_withexps.mly" + ( PNot _2 ) +# 542 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'guard) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in Obj.repr( -# 281 "src/aorai/promelaparser_withexps.mly" - ( PAnd (_1,_3) ) -# 576 "src/aorai/promelaparser_withexps.ml" +# 244 "src/aorai/promelaparser_withexps.mly" + ( PAnd (_1,_3) ) +# 550 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'guard) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in Obj.repr( -# 283 "src/aorai/promelaparser_withexps.mly" - ( POr (_1,_3) ) -# 584 "src/aorai/promelaparser_withexps.ml" +# 245 "src/aorai/promelaparser_withexps.mly" + ( POr (_1,_3) ) +# 558 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'guard) in Obj.repr( -# 285 "src/aorai/promelaparser_withexps.mly" - ( _2 ) -# 591 "src/aorai/promelaparser_withexps.ml" +# 246 "src/aorai/promelaparser_withexps.mly" + ( _2 ) +# 565 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_relation) in Obj.repr( -# 290 "src/aorai/promelaparser_withexps.mly" - ( - - let id = get_fresh_ident () in - let (pred,exp) = _1 in - Hashtbl.add observed_expressions id - (exp, (Pretty_utils.sfprintf "%a" Cil.d_exp exp), pred); - (*Ltlast.LIdent(id)*) - - Hashtbl.add observed_vars id id ; - - let res = - match !observed_expr_is_param with - | Only_vars -> PIndexedExp id - | Func_param (f,l) -> PFuncParam (id,f,l) - | Func_ret f -> PFuncReturn (id,f) - in - - (* On repositionne la variable a son status par defaut pour la prochaine logic_relation *) - observed_expr_is_param := Only_vars; (* DEVRAIT ETRE FAIT AVANT LOGIC_RELATION!!!! *) - - res - ) -# 619 "src/aorai/promelaparser_withexps.ml" +# 247 "src/aorai/promelaparser_withexps.mly" + ( _1 ) +# 572 "src/aorai/promelaparser_withexps.ml" : 'guard)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 320 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Req, Logic_utils.expr_to_term ~cast:true _1 ,Logic_utils.expr_to_term ~cast:true _3), - new_exp (Cil_types.BinOp(Cil_types.Eq, _1 , _3 , Cil.intType)) ) - ) -# 629 "src/aorai/promelaparser_withexps.ml" +# 251 "src/aorai/promelaparser_withexps.mly" + ( PRel(Eq, _1, _3) ) +# 580 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 324 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Rlt, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (Cil_types.BinOp(Cil_types.Lt, _1 , _3 , Cil.intType)) ) - ) -# 639 "src/aorai/promelaparser_withexps.ml" +# 252 "src/aorai/promelaparser_withexps.mly" + ( PRel(Lt, _1, _3) ) +# 588 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 328 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Rgt, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Gt, _1 , _3 , Cil.intType)) ) - ) -# 649 "src/aorai/promelaparser_withexps.ml" +# 253 "src/aorai/promelaparser_withexps.mly" + ( PRel(Gt, _1, _3) ) +# 596 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 332 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Rle, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (Cil_types.BinOp(Cil_types.Le, _1 , _3 , Cil.intType) )) - ) -# 659 "src/aorai/promelaparser_withexps.ml" +# 254 "src/aorai/promelaparser_withexps.mly" + ( PRel(Le, _1, _3) ) +# 604 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 336 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Rge, Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (Cil_types.BinOp(Cil_types.Ge, _1 , _3 , Cil.intType) )) - ) -# 669 "src/aorai/promelaparser_withexps.ml" +# 255 "src/aorai/promelaparser_withexps.mly" + ( PRel(Ge, _1, _3) ) +# 612 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 340 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true _1 , Logic_utils.expr_to_term ~cast:true _3), - new_exp (Cil_types.BinOp(Cil_types.Ne , _1 , _3 , Cil.intType) )) - ) -# 679 "src/aorai/promelaparser_withexps.ml" +# 256 "src/aorai/promelaparser_withexps.mly" + ( PRel(Neq,_1, _3) ) +# 620 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 344 "src/aorai/promelaparser_withexps.mly" - ( ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true _1 , - Logic_const.term - (Cil_types.TConst(Cil_types.CInt64(Int64.of_int 0,Cil_types.IInt,Some("0")))) - (Cil_types.Ctype Cil.intType)), - _1) - ) -# 691 "src/aorai/promelaparser_withexps.ml" +# 257 "src/aorai/promelaparser_withexps.mly" + ( PRel(Neq,_1, PCst(IntConstant "0")) ) +# 627 "src/aorai/promelaparser_withexps.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 356 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.BinOp(Cil_types.PlusA, _1 , _3 , Cil.intType)) ) -# 699 "src/aorai/promelaparser_withexps.ml" +# 263 "src/aorai/promelaparser_withexps.mly" + ( PBinop(Badd, _1 , _3)) +# 635 "src/aorai/promelaparser_withexps.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 358 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.BinOp(Cil_types.MinusA, _1 , _3 , Cil.intType)) ) -# 707 "src/aorai/promelaparser_withexps.ml" +# 265 "src/aorai/promelaparser_withexps.mly" + ( PBinop(Bsub,_1,_3) ) +# 643 "src/aorai/promelaparser_withexps.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation_mul) in Obj.repr( -# 360 "src/aorai/promelaparser_withexps.mly" - ( _1 ) -# 714 "src/aorai/promelaparser_withexps.ml" +# 266 "src/aorai/promelaparser_withexps.mly" + ( _1 ) +# 650 "src/aorai/promelaparser_withexps.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 366 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.BinOp(Cil_types.Div, _1 , _3 , Cil.intType)) ) -# 722 "src/aorai/promelaparser_withexps.ml" +# 272 "src/aorai/promelaparser_withexps.mly" + ( PBinop(Bdiv,_1,_3) ) +# 658 "src/aorai/promelaparser_withexps.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 368 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.BinOp(Cil_types.Mult, _1 , _3 , Cil.intType)) ) -# 730 "src/aorai/promelaparser_withexps.ml" +# 274 "src/aorai/promelaparser_withexps.mly" + ( PBinop(Bmul,_1,_3) ) +# 666 "src/aorai/promelaparser_withexps.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 370 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.BinOp(Cil_types.Mod, _1 , _3 , Cil.intType)) ) -# 738 "src/aorai/promelaparser_withexps.ml" +# 276 "src/aorai/promelaparser_withexps.mly" + ( PBinop(Bmod,_1,_3) ) +# 674 "src/aorai/promelaparser_withexps.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 372 "src/aorai/promelaparser_withexps.mly" - ( _1 ) -# 745 "src/aorai/promelaparser_withexps.ml" +# 277 "src/aorai/promelaparser_withexps.mly" + ( _1 ) +# 681 "src/aorai/promelaparser_withexps.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 378 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string _1,Cil_types.IInt, Some(_1))))) -# 752 "src/aorai/promelaparser_withexps.ml" +# 281 "src/aorai/promelaparser_withexps.mly" + ( PCst(IntConstant _1) ) +# 688 "src/aorai/promelaparser_withexps.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 380 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string ("-"^_2),Cil_types.IInt, Some("-"^_2))))) -# 759 "src/aorai/promelaparser_withexps.ml" +# 283 "src/aorai/promelaparser_withexps.mly" + ( PUnop (Uminus, PCst (IntConstant _2)) ) +# 695 "src/aorai/promelaparser_withexps.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 382 "src/aorai/promelaparser_withexps.mly" - ( new_exp (Cil_types.Lval(_1)) ) -# 766 "src/aorai/promelaparser_withexps.ml" +# 284 "src/aorai/promelaparser_withexps.mly" + ( _1 ) +# 702 "src/aorai/promelaparser_withexps.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'arith_relation) in Obj.repr( -# 384 "src/aorai/promelaparser_withexps.mly" - ( _2 ) -# 773 "src/aorai/promelaparser_withexps.ml" +# 285 "src/aorai/promelaparser_withexps.mly" + ( _2 ) +# 709 "src/aorai/promelaparser_withexps.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'access) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 391 "src/aorai/promelaparser_withexps.mly" - ( - let (my_host,my_offset) = (_1) in - - let new_offset = Utils_parser.add_offset my_offset (Utils_parser.get_new_offset my_host my_offset _3) in - (my_host,new_offset)) -# 785 "src/aorai/promelaparser_withexps.ml" +# 289 "src/aorai/promelaparser_withexps.mly" + ( PField (_1,_3) ) +# 717 "src/aorai/promelaparser_withexps.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_array) in Obj.repr( -# 398 "src/aorai/promelaparser_withexps.mly" - (_1) -# 792 "src/aorai/promelaparser_withexps.ml" +# 290 "src/aorai/promelaparser_withexps.mly" + (_1) +# 724 "src/aorai/promelaparser_withexps.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'access_array) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'access_or_const) in Obj.repr( -# 402 "src/aorai/promelaparser_withexps.mly" - ( Cil.addOffsetLval (Cil_types.Index (_3,Cil_types.NoOffset)) _1) -# 800 "src/aorai/promelaparser_withexps.ml" +# 294 "src/aorai/promelaparser_withexps.mly" + ( PArrget(_1,_3) ) +# 732 "src/aorai/promelaparser_withexps.ml" : 'access_array)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_leaf) in Obj.repr( -# 404 "src/aorai/promelaparser_withexps.mly" - (_1) -# 807 "src/aorai/promelaparser_withexps.ml" +# 295 "src/aorai/promelaparser_withexps.mly" + (_1) +# 739 "src/aorai/promelaparser_withexps.ml" : 'access_array)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 409 "src/aorai/promelaparser_withexps.mly" - ( Aorai_option.fatal "NOT YET IMPLEMENTED : *A dereferencement access." ) -# 814 "src/aorai/promelaparser_withexps.ml" +# 298 "src/aorai/promelaparser_withexps.mly" + ( PUnop(Ustar,_2) ) +# 746 "src/aorai/promelaparser_withexps.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : string) in let _4 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 414 "src/aorai/promelaparser_withexps.mly" - ( - if(String.compare _4 "return")=0 then - begin - if not (!observed_expr_is_param=Only_vars) then - Aorai_option.abort "An expression can not contain at same time a reference of a returned value and itself or a reference to a param"; - - observed_expr_is_param := Func_ret _1; - Cil.var ( Data_for_aorai.get_returninfo _1) - end - else - begin - match !observed_expr_is_param with - | Func_ret _ -> - Aorai_option.abort "An expression can not contain both a reference of a returned value and another reference to itself or a reference to a param"; - - | Func_param (f,_) when not (f=_1) -> - Aorai_option.abort "An expression can not contain both references two different called functions."; - - | Only_vars -> - observed_expr_is_param:=Func_param (_1,[_4]); - Cil.var ( Data_for_aorai.get_paraminfo _1 _4) - - | Func_param (_,l) -> - observed_expr_is_param:=Func_param (_1,_4::l); - Cil.var ( Data_for_aorai.get_paraminfo _1 _4) - end - ) -# 848 "src/aorai/promelaparser_withexps.ml" +# 299 "src/aorai/promelaparser_withexps.mly" + ( PPrm(_1,_4) ) +# 754 "src/aorai/promelaparser_withexps.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 446 "src/aorai/promelaparser_withexps.mly" - ( Cil.var ( Data_for_aorai.get_varinfo _1) ) -# 855 "src/aorai/promelaparser_withexps.ml" +# 300 "src/aorai/promelaparser_withexps.mly" + ( PVar _1 ) +# 761 "src/aorai/promelaparser_withexps.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'access) in Obj.repr( -# 448 "src/aorai/promelaparser_withexps.mly" - ( _2 ) -# 862 "src/aorai/promelaparser_withexps.ml" +# 301 "src/aorai/promelaparser_withexps.mly" + ( _2 ) +# 768 "src/aorai/promelaparser_withexps.ml" : 'access_leaf)) (* Entry promela *) ; (fun __caml_parser_env -> raise (Parsing.YYexit (Parsing.peek_val __caml_parser_env 0))) @@ -881,4 +787,4 @@ Parsing.names_const=yynames_const; Parsing.names_block=yynames_block } let promela (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) = - (Parsing.yyparse yytables 1 lexfun lexbuf : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t)) + (Parsing.yyparse yytables 1 lexfun lexbuf : Promelaast.parsed_automaton) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaparser_withexps.mli frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser_withexps.mli --- frama-c-20110201+carbon+dfsg/src/aorai/promelaparser_withexps.mli 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser_withexps.mli 2011-10-10 08:48:50.000000000 +0000 @@ -40,4 +40,4 @@ | PROMELA_FUNC val promela : - (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t) + (Lexing.lexbuf -> token) -> Lexing.lexbuf -> Promelaast.parsed_automaton diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/promelaparser_withexps.mly frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser_withexps.mly --- frama-c-20110201+carbon+dfsg/src/aorai/promelaparser_withexps.mly 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/promelaparser_withexps.mly 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ /**************************************************************************/ /* */ -/* This file is part of Frama-C. */ +/* This file is part of Aorai plug-in of Frama-C. */ /* */ /* Copyright (C) 2007-2011 */ -/* INSA (Institut National des Sciences Appliquees) */ +/* CEA (Commissariat a l'énergie atomique et aux énergies */ +/* alternatives) */ /* INRIA (Institut National de Recherche en Informatique et en */ /* Automatique) */ +/* INSA (Institut National des Sciences Appliquees) */ /* */ /* you can redistribute it and/or modify it under the terms of the GNU */ /* Lesser General Public License as published by the Free Software */ @@ -25,38 +27,21 @@ /* Originated from http://www.ltl2dstar.de/down/ltl2dstar-0.4.2.zip */ %{ +open Logic_ptree open Parsing open Promelaast open Bool3 let observed_states=Hashtbl.create 1 -let observed_vars=Hashtbl.create 1 -let observed_funcs=Hashtbl.create 1 - -let observed_expressions=Hashtbl.create 97 - - -(* Current observed expr contains : *) -type observed_expr = Func_ret of string (* func name : a return of the given func *) - | Func_param of string * (string list) (* Func name * param : a call with given param *) - | Only_vars (* Only constants and variables *) - -let observed_expr_is_param = ref Only_vars - - -let ident_count=ref 0 -let get_fresh_ident () = - ident_count:=!ident_count+1; - ("buchfreshident"^(string_of_int !ident_count)) - -(*TODO: give a proper loc*) -let new_exp = Cil.new_exp ~loc:(Cil.CurrentLoc.get()) +let to_seq c = + [{ condition = Some c; nested = []; + min_rep = Some (PCst (IntConstant "1")); + max_rep = Some (PCst (IntConstant "1")); + }] %} - - %token PROMELA_OR %token PROMELA_AND %token PROMELA_NOT PROMELA_TRUE PROMELA_FALSE @@ -73,26 +58,22 @@ %token PROMELA_RPAREN PROMELA_RIGHT_ARROW %token PROMELA_TRUE PROMELA_FALSE - /* Logic relations */ %token PROMELA_EQ PROMELA_LT PROMELA_GT PROMELA_LE PROMELA_GE PROMELA_NEQ %right PROMELA_EQ PROMELA_LT PROMELA_GT PROMELA_LE PROMELA_GE PROMELA_NEQ - /* Arithmetic relations */ %token PROMELA_PLUS PROMELA_MINUS %token PROMELA_DIV PROMELA_STAR PROMELA_MODULO %right PROMELA_PLUS PROMELA_MINUS PROMELA_DIV PROMELA_STAR PROMELA_MODULO - /* Access */ %token PROMELA_DOT PROMELA_LEFT_SQUARE PROMELA_RIGHT_SQUARE %token PROMELA_CALLOF PROMELA_RETURNOF PROMELA_CALLORRETURNOF %token EOF %token PROMELA_FUNC - -%type <(Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t)> promela +%type promela %start promela %% @@ -107,49 +88,26 @@ end; st::l ) observed_states [] - in - Data_for_aorai.setLtl_expressions observed_expressions; - Logic_simplification.setLtl_expressions observed_expressions; - let n=ref 0 in - let (transitions,pcondsl) = Logic_simplification.simplifyTrans $3 in - let conds = Array.make (List.length transitions) [] in - List.iter2 (fun t pc -> t.numt<-(!n); conds.(!n)<-pc; n:=!n+1) transitions pcondsl; - Data_for_aorai.setCondOfParametrizedTransition conds; - - ((states , transitions),observed_vars,observed_funcs) + in + (states , $3) } - | PROMELA_NEVER PROMELA_LBRACE states PROMELA_SEMICOLON PROMELA_RBRACE EOF { + | PROMELA_NEVER PROMELA_LBRACE states + PROMELA_SEMICOLON PROMELA_RBRACE EOF { let states= Hashtbl.fold (fun _ st l -> if st.acceptation=Undefined or st.init=Undefined then begin - Format.print_string ("Error: the state '"^(st.name)^"' is used but never defined.\n"); - exit 1 + Aorai_option.abort + "Error: state %s is used bug never defined" st.name end; st::l ) observed_states [] in - Data_for_aorai.setLtl_expressions observed_expressions; - Logic_simplification.setLtl_expressions observed_expressions; - let n=ref 0 in - let (transitions,pcondsl) = Logic_simplification.simplifyTrans $3 in - let conds = Array.make (List.length transitions) [] in - List.iter2 (fun t pc -> t.numt<-(!n); conds.(!n)<-pc; n:=!n+1) transitions pcondsl; - Data_for_aorai.setCondOfParametrizedTransition conds; - - - ((states , transitions),observed_vars,observed_funcs) } + (states , $3) } ; - - states - : states PROMELA_SEMICOLON state { - $1@$3 - (*let (s1,t1)=$1 in - let (s2,t2)=$3 in - (s1@s2,t1@t2)*) - } + : states PROMELA_SEMICOLON state { $1@$3 } | state { $1 } ; @@ -163,7 +121,8 @@ try (Hashtbl.find observed_states s.name).acceptation <- True with - | Not_found -> assert false (* This state has to be in the hashtable -- by construction *) + | Not_found -> assert false + (* This state has to be in the hashtable -- by construction *) ) stl end; if trl=[] then @@ -172,15 +131,11 @@ let tr_list= List.fold_left (fun l1 (cr,stop_st) -> List.fold_left (fun l2 st -> - {start=st;stop=stop_st;cross=cr;numt=(-1)}::l2 + {start=st;stop=stop_st;cross=Seq (to_seq cr);numt=(-1)}::l2 ) l1 stl - ) [] trl + ) [] trl in - (List.rev tr_list)@trans - - - - + (List.rev tr_list)@trans } ; @@ -196,36 +151,50 @@ label : PROMELA_LABEL PROMELA_COLON { begin - (* Step 0 : trans is the set of new transitions and old is the description of the current state *) + (* Step 0 : trans is the set of new transitions and old + is the description of the current state *) let trans = ref [] in - (* Promela Label is a state. According to its name, we will try to give him its properties (init / accept) *) - (* Firstly, if this state is still referenced, then we get it back. Else, we make a new "empty" state *) + (* Promela Label is a state. According to its name, + we will try to give him its properties (init / accept) *) + (* Firstly, if this state is still referenced, + then we get it back. Else, we make a new "empty" state *) let old= try Hashtbl.find observed_states $1 with | Not_found -> - let s={name=$1;acceptation=Undefined;init=Undefined;nums=(Hashtbl.length observed_states)} in + let s = Data_for_aorai.new_state $1 in Hashtbl.add observed_states $1 s; s in - (* Step 1 : setting up the acceptance status *) + (* Step 1 : setting up the acceptance status *) (* Default status : Non acceptation state *) old.acceptation <- False; - (* Accept_all state means acceptance state with a reflexive transition without cross condition *) - (* This case is not exlusive with the following. Acceptation status is set in this last. *) - if (String.length $1>=10) && (String.compare (String.sub $1 0 10) "accept_all")=0 then - trans:={start=old;stop=old;cross=PTrue;numt=(-1)}::!trans; + (* Accept_all state means acceptance state with a + reflexive transition without cross condition *) + (* This case is not exclusive with the following. + Acceptation status is set in this last. *) + if (String.length $1>=10) && + (String.compare (String.sub $1 0 10) "accept_all")=0 + then + trans:= + {start=old;stop=old;cross=Seq (to_seq PTrue);numt=(-1)}::!trans; - (* If the name includes accept then this state is an acceptation one. *) - if (String.length $1>=7) && (String.compare (String.sub $1 0 7) "accept_")=0 then + (* If the name includes accept then this state is + an acceptation one. *) + if (String.length $1>=7) && + (String.compare (String.sub $1 0 7) "accept_")=0 + then old.acceptation <- True; - (* Step 2 : setting up the init status *) - (* If the state name ended with "_init" then it is an initial state. Else, it is not. *) - if (String.length $1>=5) && (String.compare (String.sub $1 ((String.length $1)-5) 5) "_init" ) = 0 - then + (* Step 2 : setting up the init status *) + (* If the state name ended with "_init" then + it is an initial state. Else, it is not. *) + if (String.length $1>=5) && + (String.compare + (String.sub $1 ((String.length $1)-5) 5) "_init" ) = 0 + then old.init <- True else old.init <- False; @@ -250,201 +219,84 @@ ; transition - : PROMELA_DOUBLE_COLON guard PROMELA_RIGHT_ARROW PROMELA_GOTO PROMELA_LABEL { + : PROMELA_DOUBLE_COLON guard + PROMELA_RIGHT_ARROW PROMELA_GOTO PROMELA_LABEL { let s= try Hashtbl.find observed_states $5 with Not_found -> - let r={name=$5;init=Undefined;acceptation=Undefined;nums=(Hashtbl.length observed_states)} in - Hashtbl.add observed_states $5 r; - r + let r = Data_for_aorai.new_state $5 in + Hashtbl.add observed_states $5 r; + r in - ($2,s) + ($2,s) } ; guard - : PROMELA_CALLORRETURNOF - { if not (Hashtbl.mem observed_funcs $1) then Hashtbl.add observed_funcs $1 $1 ; PCallOrReturn $1 } - | PROMELA_CALLOF - { if not (Hashtbl.mem observed_funcs $1) then Hashtbl.add observed_funcs $1 $1 ; PCall $1 } - | PROMELA_RETURNOF - { if not (Hashtbl.mem observed_funcs $1) then Hashtbl.add observed_funcs $1 $1 ; PReturn $1 } - | PROMELA_TRUE - { PTrue } - | PROMELA_FALSE - { PFalse } - | PROMELA_NOT guard - { PNot $2 } - | guard PROMELA_AND guard - { PAnd ($1,$3) } - | guard PROMELA_OR guard - { POr ($1,$3) } - | PROMELA_LPAREN guard PROMELA_RPAREN - { $2 } - - -/* returns a string identifer associated, through observed_expressions table, to the represented expression */ - | logic_relation - { - - let id = get_fresh_ident () in - let (pred,exp) = $1 in - Hashtbl.add observed_expressions id - (exp, (Pretty_utils.sfprintf "%a" Cil.d_exp exp), pred); - (*Ltlast.LIdent(id)*) - - Hashtbl.add observed_vars id id ; - - let res = - match !observed_expr_is_param with - | Only_vars -> PIndexedExp id - | Func_param (f,l) -> PFuncParam (id,f,l) - | Func_ret f -> PFuncReturn (id,f) - in - - (* On repositionne la variable a son status par defaut pour la prochaine logic_relation *) - observed_expr_is_param := Only_vars; (* DEVRAIT ETRE FAIT AVANT LOGIC_RELATION!!!! *) - - res - } + : PROMELA_CALLORRETURNOF { POr(PCall ($1,None), PReturn $1) } + | PROMELA_CALLOF { PCall ($1,None) } + | PROMELA_RETURNOF { PReturn $1 } + | PROMELA_TRUE { PTrue } + | PROMELA_FALSE { PFalse } + | PROMELA_NOT guard { PNot $2 } + | guard PROMELA_AND guard { PAnd ($1,$3) } + | guard PROMELA_OR guard { POr ($1,$3) } + | PROMELA_LPAREN guard PROMELA_RPAREN { $2 } + | logic_relation { $1 } ; - - - -/* returns a (Cil_types.predicate,Cil_types.exp) couple of expressions */ logic_relation - : arith_relation PROMELA_EQ arith_relation - { ( Cil_types.Prel(Cil_types.Req, Logic_utils.expr_to_term ~cast:true $1 ,Logic_utils.expr_to_term ~cast:true $3), - new_exp (Cil_types.BinOp(Cil_types.Eq, $1 , $3 , Cil.intType)) ) - } - | arith_relation PROMELA_LT arith_relation - { ( Cil_types.Prel(Cil_types.Rlt, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (Cil_types.BinOp(Cil_types.Lt, $1 , $3 , Cil.intType)) ) - } - | arith_relation PROMELA_GT arith_relation - { ( Cil_types.Prel(Cil_types.Rgt, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Gt, $1 , $3 , Cil.intType)) ) - } - | arith_relation PROMELA_LE arith_relation - { ( Cil_types.Prel(Cil_types.Rle, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (Cil_types.BinOp(Cil_types.Le, $1 , $3 , Cil.intType) )) - } - | arith_relation PROMELA_GE arith_relation - { ( Cil_types.Prel(Cil_types.Rge, Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (Cil_types.BinOp(Cil_types.Ge, $1 , $3 , Cil.intType) )) - } - | arith_relation PROMELA_NEQ arith_relation - { ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true $1 , Logic_utils.expr_to_term ~cast:true $3), - new_exp (Cil_types.BinOp(Cil_types.Ne , $1 , $3 , Cil.intType) )) - } - | arith_relation - { ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true $1 , - Logic_const.term - (Cil_types.TConst(Cil_types.CInt64(Int64.of_int 0,Cil_types.IInt,Some("0")))) - (Cil_types.Ctype Cil.intType)), - $1) - } - + : arith_relation PROMELA_EQ arith_relation { PRel(Eq, $1, $3) } + | arith_relation PROMELA_LT arith_relation { PRel(Lt, $1, $3) } + | arith_relation PROMELA_GT arith_relation { PRel(Gt, $1, $3) } + | arith_relation PROMELA_LE arith_relation { PRel(Le, $1, $3) } + | arith_relation PROMELA_GE arith_relation { PRel(Ge, $1, $3) } + | arith_relation PROMELA_NEQ arith_relation { PRel(Neq,$1, $3) } + | arith_relation { PRel(Neq,$1, PCst(IntConstant "0")) } ; /* returns a Cil_types.exp expression */ arith_relation - : arith_relation_mul PROMELA_PLUS arith_relation - { new_exp (Cil_types.BinOp(Cil_types.PlusA, $1 , $3 , Cil.intType)) } + : arith_relation_mul PROMELA_PLUS arith_relation + { PBinop(Badd, $1 , $3)} | arith_relation_mul PROMELA_MINUS arith_relation - { new_exp (Cil_types.BinOp(Cil_types.MinusA, $1 , $3 , Cil.intType)) } - | arith_relation_mul - { $1 } - ; + { PBinop(Bsub,$1,$3) } + | arith_relation_mul { $1 } + ; arith_relation_mul : arith_relation_mul PROMELA_DIV access_or_const - { new_exp (Cil_types.BinOp(Cil_types.Div, $1 , $3 , Cil.intType)) } + { PBinop(Bdiv,$1,$3) } | arith_relation_mul PROMELA_STAR access_or_const - { new_exp (Cil_types.BinOp(Cil_types.Mult, $1 , $3 , Cil.intType)) } + { PBinop(Bmul,$1,$3) } | arith_relation_mul PROMELA_MODULO access_or_const - { new_exp (Cil_types.BinOp(Cil_types.Mod, $1 , $3 , Cil.intType)) } - | access_or_const - { $1 } - ; + { PBinop(Bmod,$1,$3) } + | access_or_const { $1 } + ; -/* returns a Lval exp or a Const exp*/ access_or_const - : PROMELA_INT - { new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string $1,Cil_types.IInt, Some($1))))} + : PROMELA_INT { PCst(IntConstant $1) } | PROMELA_MINUS PROMELA_INT - { new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string ("-"^$2),Cil_types.IInt, Some("-"^$2))))} - | access - { new_exp (Cil_types.Lval($1)) } - | PROMELA_LPAREN arith_relation PROMELA_RPAREN - { $2 } - ; - + { PUnop (Uminus, PCst (IntConstant $2)) } + | access { $1 } + | PROMELA_LPAREN arith_relation PROMELA_RPAREN { $2 } + ; -/* returns a lval */ access - : access PROMELA_DOT PROMELA_LABEL - { - let (my_host,my_offset) = ($1) in - - let new_offset = Utils_parser.add_offset my_offset (Utils_parser.get_new_offset my_host my_offset $3) in - (my_host,new_offset)} - - | access_array - {$1} + : access PROMELA_DOT PROMELA_LABEL { PField ($1,$3) } + | access_array {$1} access_array : access_array PROMELA_LEFT_SQUARE access_or_const PROMELA_RIGHT_SQUARE - { Cil.addOffsetLval (Cil_types.Index ($3,Cil_types.NoOffset)) $1} - | access_leaf - {$1} - + { PArrget($1,$3) } + | access_leaf {$1} access_leaf - : PROMELA_STAR access - { Aorai_option.fatal "NOT YET IMPLEMENTED : *A dereferencement access." } - - - - | PROMELA_LABEL PROMELA_FUNC PROMELA_DOT PROMELA_LABEL - { - if(String.compare $4 "return")=0 then - begin - if not (!observed_expr_is_param=Only_vars) then - Aorai_option.abort "An expression can not contain at same time a reference of a returned value and itself or a reference to a param"; - - observed_expr_is_param := Func_ret $1; - Cil.var ( Data_for_aorai.get_returninfo $1) - end - else - begin - match !observed_expr_is_param with - | Func_ret _ -> - Aorai_option.abort "An expression can not contain both a reference of a returned value and another reference to itself or a reference to a param"; - - | Func_param (f,_) when not (f=$1) -> - Aorai_option.abort "An expression can not contain both references two different called functions."; - - | Only_vars -> - observed_expr_is_param:=Func_param ($1,[$4]); - Cil.var ( Data_for_aorai.get_paraminfo $1 $4) - - | Func_param (_,l) -> - observed_expr_is_param:=Func_param ($1,$4::l); - Cil.var ( Data_for_aorai.get_paraminfo $1 $4) - end - } - - - - - | PROMELA_LABEL - { Cil.var ( Data_for_aorai.get_varinfo $1) } - | PROMELA_LPAREN access PROMELA_RPAREN - { $2 } - - ; + : PROMELA_STAR access { PUnop(Ustar,$2) } + | PROMELA_LABEL PROMELA_FUNC PROMELA_DOT PROMELA_LABEL { PPrm($1,$4) } + | PROMELA_LABEL { PVar $1 } + | PROMELA_LPAREN access PROMELA_RPAREN { $2 } + ; diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/spec_tools.ml frama-c-20111001+nitrogen+dfsg/src/aorai/spec_tools.ml --- frama-c-20110201+carbon+dfsg/src/aorai/spec_tools.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/spec_tools.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -27,7 +29,6 @@ let numberOfTransitions = ref 0 let setNumberOfStates nbSt = numberOfStates:= nbSt let setNumberOfTransitions nbTr = numberOfTransitions := nbTr - let mk_empty_pre_st () = Array.make (!numberOfStates) false @@ -47,10 +48,9 @@ Array.make (!numberOfTransitions) false ) - - - -(** Given two bool arrays with the same length, it returns a fresh bool array corresponding to a logical OR between cells with same index from the two arrays. *) +(** Given two bool arrays with the same length, it returns a fresh + bool array corresponding to a logical AND between cells with same index + from the two arrays. *) let bool_array_and arr1 arr2 = if Array.length arr1 <> Array.length arr2 then assert false; @@ -61,7 +61,7 @@ res -(** Given two bool arrays with the same length, it returns a fresh bool array corresponding to a logical AND between cells with same index from the two arrays. *) +(** Given two bool arrays with the same length, it returns a fresh bool array corresponding to a logical OR between cells with same index from the two arrays. *) let bool_array_or arr1 arr2 = if Array.length arr1 <> Array.length arr2 then assert false; @@ -82,9 +82,6 @@ arr1; !res - - - let double_bool_array_and (a1,a2) (b1,b2) = (bool_array_and a1 b1, bool_array_and a2 b2) @@ -98,13 +95,13 @@ let double_bool_array_or (a1,a2) (b1,b2) = (bool_array_or a1 b1, bool_array_or a2 b2) + let quad_bool_array_or (a1,a2,a3,a4) (b1,b2,b3,b4) = (bool_array_or a1 b1, bool_array_or a2 b2, bool_array_or a3 b3, bool_array_or a4 b4) - let double_bool_array_eq (a1,a2) (b1,b2) = (bool_array_eq a1 b1) && (bool_array_eq a2 b2) @@ -115,16 +112,13 @@ (bool_array_eq a3 b3) && (bool_array_eq a4 b4) - - type pre_post_bycase_t = bool array array type double_pre_post_bycase_t = (pre_post_bycase_t*pre_post_bycase_t) -type quad_pre_post_bycase_t = (pre_post_bycase_t*pre_post_bycase_t*pre_post_bycase_t*pre_post_bycase_t) - +type quad_pre_post_bycase_t = + (pre_post_bycase_t*pre_post_bycase_t*pre_post_bycase_t*pre_post_bycase_t) (* ************************************************************************* *) - let mk_empty_pre_st_bycase () = Array.make_matrix (!numberOfStates) (!numberOfStates) false @@ -143,8 +137,6 @@ Array.make_matrix (!numberOfStates) (!numberOfTransitions) false ) - - let pre_flattening (pre_st,pre_tr) = let new_st,new_tr = mk_empty_pre_or_post () in let new_st,new_tr = ref new_st, ref new_tr in @@ -156,7 +148,6 @@ pre_st; (!new_st,!new_tr) - let post_pseudo_flattening post = let new_st,new_tr = mk_empty_pre_or_post_bycase () in Array.iteri @@ -171,47 +162,46 @@ -(** Given two bool arrays with the same length, it returns a fresh bool array corresponding to a logical OR between cells with same index from the two arrays. *) +(** Given two bool arrays with the same length, it returns a fresh bool array + corresponding to a logical AND between cells with same index from the + two arrays. *) let bool_array_and_bycase bc_arr1 bc_arr2 = if Array.length bc_arr1 <> Array.length bc_arr2 then assert false; - - let res=Array.make (Array.length bc_arr1) (Array.make (Array.length bc_arr1.(0)) false) in + let res=Array.make + (Array.length bc_arr1) (Array.make (Array.length bc_arr1.(0)) false) + in Array.iteri (fun case b1 -> res.(case)<-bool_array_and b1 (bc_arr2.(case))) bc_arr1; res -(** Given two bool arrays with the same length, it returns a fresh bool array corresponding to a logical AND between cells with same index from the two arrays. *) +(** Given two bool arrays with the same length, it returns a fresh bool array + corresponding to a logical OR between cells with same index from + the two arrays. *) let bool_array_or_bycase bc_arr1 bc_arr2 = if Array.length bc_arr1 <> Array.length bc_arr2 then assert false; - - let res=Array.make (Array.length bc_arr1) (Array.make (Array.length bc_arr1.(0)) false) in + let res=Array.make + (Array.length bc_arr1) (Array.make (Array.length bc_arr1.(0)) false) + in Array.iteri (fun case b1 -> res.(case)<-bool_array_or b1 (bc_arr2.(case))) bc_arr1; res - -(** Given two bool arrays with the same length, it returns true if and only if their cells are equal for each index. *) +(** Given two bool arrays with the same length, it returns true if and only + if their cells are equal for each index. *) let bool_array_eq_bycase bc_arr1 bc_arr2 = if Array.length bc_arr1 <> Array.length bc_arr2 then assert false; - let res=ref true in Array.iteri (fun case b1 -> if not (bool_array_eq b1 (bc_arr2.(case))) then res :=false) bc_arr1; !res - - - - - - let double_bool_array_and_bycase (a1,a2) (b1,b2) = (bool_array_and_bycase a1 b1, bool_array_and_bycase a2 b2) @@ -231,7 +221,6 @@ bool_array_or_bycase a3 b3, bool_array_or_bycase a4 b4) - let double_bool_array_eq_bycase (a1,a2) (b1,b2) = (bool_array_eq_bycase a1 b1) && (bool_array_eq_bycase a2 b2) @@ -242,17 +231,12 @@ (bool_array_eq_bycase a3 b3) && (bool_array_eq_bycase a4 b4) - - - - let is_empty_pre_post__ pp = Array.fold_left (fun isempty value -> isempty && not value) true pp - (** Return false if and only if all states are associated to false *) let is_empty_pre_post (pre_st,_) = is_empty_pre_post__ pre_st @@ -265,15 +249,9 @@ true post_st - - - - - let separator = "" -let concat = - String.concat "" +let concat = String.concat "" let debug_display_stmt_pre pre prefixe = let r=ref "{" in @@ -305,9 +283,6 @@ (* debug_display_stmt_pre post_st "st";*) (* Format.printf "\n" *) - - - let debug_display_stmt_all_pre (st,tr)= let tr_str = debug_display_stmt_pre tr "tr" in let st_str = debug_display_stmt_pre st "st" in @@ -317,8 +292,6 @@ (* Format.printf " st="; *) (* debug_display_stmt_pre st "st" *) - - let is_empty_behavior assocs = Array.fold_left (fun b c -> if c then false else b) true assocs @@ -336,8 +309,6 @@ assocs; !s^")" - - let debug_display_stmt_pre_bycase pre prefixe = let r=ref "{" in let result = ref "" in @@ -355,8 +326,6 @@ else concat [!result ;"}"] - - let debug_display_spec_bycase (pre_st,_,post_st,_) name= let pre_str = debug_display_stmt_pre_bycase pre_st "st" in let post_str = debug_display_stmt_pre_bycase post_st "st" in @@ -365,8 +334,6 @@ (* debug_display_stmt_pre_bycase post_st "st";*) (* Format.printf "\n" *) - - let debug_display_stmt_all_pre_bycase (st,tr)= let tr_str = debug_display_stmt_pre_bycase tr "tr" in let st_str = debug_display_stmt_pre_bycase st "st" in @@ -376,10 +343,6 @@ (* Format.printf " st="; *) (* debug_display_stmt_pre_bycase st "st" *) - - - - (* Local Variables: compile-command: "LC_ALL=C make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/utils_parser.ml frama-c-20111001+nitrogen+dfsg/src/aorai/utils_parser.ml --- frama-c-20110201+carbon+dfsg/src/aorai/utils_parser.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/utils_parser.ml 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -25,21 +27,21 @@ open Aorai_option -let rec get_last_field my_field my_offset = +let rec get_last_field my_field my_offset = match my_offset with | Cil_types.NoOffset -> my_field | Cil_types.Field(fieldinfo,the_offset) -> get_last_field fieldinfo the_offset | _ -> Aorai_option.fatal "NOT YET IMPLEMENTED : struct with array access." - -let rec add_offset father_offset new_offset = + +let rec add_offset father_offset new_offset = match father_offset with | Cil_types.NoOffset -> new_offset - | Cil_types.Field(_,the_offset) -> (Cil.addOffset father_offset (add_offset the_offset new_offset)) - | _ -> Aorai_option.fatal "NOT YET IMPLEMENTED : struct with array access." - - - + | Cil_types.Field(_,the_offset) -> (Cil.addOffset father_offset (add_offset the_offset new_offset)) + | _ -> Aorai_option.fatal "NOT YET IMPLEMENTED : struct with array access." + + + let rec get_field_info_from_name my_list name = if(List.length my_list <> 0) then begin let my_field = List.hd my_list in @@ -47,23 +49,23 @@ else get_field_info_from_name (List.tl my_list) name end else Aorai_option.fatal "no field found with name :%s" name - - - + + + let get_new_offset my_host my_offset name= match my_host with - | Cil_types.Var(var) -> + | Cil_types.Var(var) -> let var_info = var in (* if my_offset is null no need to search the last field *) (* else we need to have the last *) - - let my_comp = - if (my_offset = Cil_types.NoOffset) then - match var_info.Cil_types.vtype with + + let my_comp = + if (my_offset = Cil_types.NoOffset) then + match var_info.Cil_types.vtype with | Cil_types.TComp(mc,_,_) -> mc | _ -> assert false (*Cil_types.TComp(my_comp,_,_) = var_info.Cil_types.vtype in*) - + else begin let get_field_from_offset my_offset = begin match my_offset with @@ -77,8 +79,8 @@ mc end in - + let field_info = get_field_info_from_name my_comp.Cil_types.cfields name in Cil_types.Field(field_info,Cil_types.NoOffset) - + | _ -> Aorai_option.fatal "NOT YET IMPLEMENTED : mem is not supported" diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/yalexer.ml frama-c-20111001+nitrogen+dfsg/src/aorai/yalexer.ml --- frama-c-20110201+carbon+dfsg/src/aorai/yalexer.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/yalexer.ml 2011-10-10 08:48:50.000000000 +0000 @@ -1,4 +1,4 @@ -# 25 "src/aorai/yalexer.mll" +# 27 "src/aorai/yalexer.mll" open Yaparser open Lexing @@ -7,7 +7,7 @@ let new_line lexbuf = let lcp = lexbuf.lex_curr_p in lexbuf.lex_curr_p <- { lcp with pos_lnum = lcp.pos_lnum + 1; - pos_bol = lcp.pos_cnum; } + pos_bol = lcp.pos_cnum; } ;; exception Error of (Lexing.position * Lexing.position) * string @@ -18,304 +18,310 @@ # 19 "src/aorai/yalexer.ml" let __ocaml_lex_tables = { Lexing.lex_base = - "\000\000\214\255\215\255\216\255\217\255\002\000\003\000\031\000\ - \033\000\002\000\001\000\232\255\233\255\234\255\235\255\236\255\ - \237\255\239\255\240\255\241\255\033\000\243\255\244\255\079\000\ - \055\000\160\000\235\000\054\001\129\001\204\001\023\002\254\255\ - \255\255\033\002\108\002\183\002\002\003\077\003\152\003\227\003\ - \046\004\121\004\196\004\015\005\090\005\165\005\240\005\059\006\ - \134\006\209\006\028\007\103\007\178\007\253\007\246\255\231\255\ - \228\255\227\255\220\255\223\255\222\255\221\255"; + "\000\000\211\255\212\255\213\255\214\255\006\000\217\255\034\000\ + \035\000\065\000\066\000\004\000\001\000\230\255\004\000\007\000\ + \235\255\236\255\237\255\238\255\239\255\240\255\241\255\069\000\ + \243\255\244\255\084\000\028\000\160\000\235\000\054\001\129\001\ + \204\001\023\002\254\255\255\255\033\002\108\002\183\002\002\003\ + \077\003\152\003\227\003\046\004\121\004\196\004\015\005\090\005\ + \165\005\240\005\059\006\134\006\209\006\028\007\103\007\178\007\ + \253\007\042\000\029\000\028\000\038\000\031\000\246\255\229\255\ + \232\255\231\255\226\255\225\255\218\255\221\255\220\255\219\255\ + \215\255"; Lexing.lex_backtrk = - "\255\255\255\255\255\255\255\255\255\255\041\000\031\000\030\000\ - \029\000\026\000\025\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\013\000\255\255\255\255\010\000\ - \017\000\010\000\010\000\010\000\010\000\010\000\002\000\255\255\ - \255\255\010\000\010\000\010\000\003\000\005\000\010\000\010\000\ - \010\000\010\000\004\000\010\000\010\000\010\000\006\000\010\000\ - \010\000\007\000\010\000\010\000\010\000\008\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255"; + "\255\255\255\255\255\255\255\255\255\255\039\000\255\255\044\000\ + \033\000\032\000\031\000\028\000\027\000\255\255\022\000\021\000\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\013\000\ + \255\255\255\255\010\000\044\000\010\000\010\000\010\000\010\000\ + \010\000\002\000\255\255\255\255\010\000\010\000\010\000\003\000\ + \005\000\010\000\010\000\010\000\010\000\004\000\010\000\010\000\ + \010\000\006\000\010\000\010\000\007\000\010\000\010\000\010\000\ + \008\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255"; Lexing.lex_default = - "\001\000\000\000\000\000\000\000\000\000\255\255\255\255\255\255\ - \255\255\255\255\255\255\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\255\255\000\000\000\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\000\000\ - \000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + "\001\000\000\000\000\000\000\000\000\000\255\255\000\000\255\255\ + \255\255\255\255\255\255\255\255\255\255\000\000\255\255\255\255\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\255\ + \000\000\000\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\000\000\000\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000"; + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000"; Lexing.lex_trans = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\032\000\031\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\035\000\034\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \032\000\008\000\000\000\000\000\000\000\017\000\010\000\056\000\ - \024\000\016\000\019\000\021\000\022\000\020\000\011\000\018\000\ - \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ - \030\000\030\000\003\000\004\000\007\000\005\000\006\000\061\000\ - \060\000\023\000\023\000\029\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\028\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\015\000\059\000\014\000\058\000\055\000\ - \054\000\023\000\023\000\023\000\023\000\023\000\025\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\027\000\ - \023\000\023\000\023\000\023\000\026\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\013\000\009\000\012\000\057\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\023\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\023\000\ - \002\000\050\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\023\000\000\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\047\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\023\000\000\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\043\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\023\000\023\000\023\000\023\000\038\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \023\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\034\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\033\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\023\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\030\000\ - \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ - \030\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\037\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \023\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \035\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\023\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\036\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\023\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\000\000\000\000\000\000\ - \000\000\023\000\000\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \000\000\000\000\000\000\000\000\023\000\000\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\039\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\023\000\ - \000\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \040\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\023\000\000\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \041\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\023\000\000\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\042\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \023\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\023\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\023\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\044\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\000\000\000\000\000\000\ - \000\000\023\000\000\000\023\000\023\000\023\000\023\000\045\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \000\000\000\000\000\000\000\000\023\000\000\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\046\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\023\000\ - \000\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\023\000\000\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \048\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\023\000\000\000\023\000\ - \023\000\023\000\023\000\049\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \023\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\023\000\000\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \051\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\000\000\000\000\000\000\000\000\023\000\000\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\052\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\000\000\000\000\000\000\ - \000\000\023\000\000\000\023\000\023\000\023\000\023\000\053\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \000\000\000\000\000\000\000\000\023\000\000\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ + \035\000\010\000\000\000\000\000\000\000\020\000\012\000\066\000\ + \019\000\018\000\022\000\024\000\025\000\023\000\013\000\021\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\033\000\005\000\006\000\009\000\007\000\008\000\003\000\ + \072\000\026\000\026\000\032\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\031\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\017\000\027\000\016\000\004\000\071\000\ + \070\000\026\000\026\000\026\000\026\000\026\000\028\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\030\000\ + \026\000\026\000\026\000\026\000\029\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\015\000\011\000\014\000\069\000\068\000\ + \067\000\065\000\064\000\063\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\057\000\058\000\ + \059\000\060\000\061\000\062\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\026\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\026\000\ + \002\000\053\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\026\000\000\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\050\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\000\000\000\000\000\000\000\000\026\000\000\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\046\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\026\000\026\000\026\000\026\000\041\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \026\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\037\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\036\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\026\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\033\000\ + \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \033\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\040\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \026\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \038\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\026\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\039\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\000\000\000\000\000\000\000\000\026\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\000\000\000\000\000\000\ + \000\000\026\000\000\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \000\000\000\000\000\000\000\000\026\000\000\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\042\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\026\000\ + \000\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \043\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\026\000\000\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \044\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\000\000\000\000\000\000\000\000\026\000\000\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\045\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \026\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\026\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\000\000\000\000\000\000\000\000\026\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\047\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\000\000\000\000\000\000\ + \000\000\026\000\000\000\026\000\026\000\026\000\026\000\048\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \000\000\000\000\000\000\000\000\026\000\000\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\049\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\026\000\ + \000\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\026\000\000\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \051\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\000\000\000\000\000\000\000\000\026\000\000\000\026\000\ + \026\000\026\000\026\000\052\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \026\000\000\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\026\000\000\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \054\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\000\000\000\000\000\000\000\000\026\000\000\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\055\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\000\000\000\000\000\000\ + \000\000\026\000\000\000\026\000\026\000\026\000\026\000\056\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \000\000\000\000\000\000\000\000\026\000\000\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ @@ -338,273 +344,273 @@ \255\255\000\000\000\000\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \000\000\000\000\255\255\255\255\255\255\000\000\000\000\010\000\ + \000\000\000\000\255\255\255\255\255\255\000\000\000\000\012\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\000\ - \006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\ + \008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\007\000\000\000\008\000\020\000\ - \024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ - \000\000\000\000\000\000\000\000\000\000\000\000\009\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\255\255\255\255\255\255\255\255\023\000\255\255\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\ - \023\000\023\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\025\000\255\255\255\255\255\255\255\255\025\000\ - \000\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\ - \025\000\025\000\025\000\026\000\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\026\000\255\255\255\255\ - \255\255\255\255\026\000\255\255\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ - \026\000\026\000\026\000\026\000\026\000\026\000\027\000\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \027\000\255\255\255\255\255\255\255\255\027\000\255\255\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\ - \027\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ - \028\000\028\000\028\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\028\000\028\000\028\000\028\000\028\000\028\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\009\000\010\000\ + \011\000\014\000\015\000\023\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\027\000\057\000\ + \058\000\059\000\060\000\061\000\255\255\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\255\255\ + \255\255\255\255\255\255\026\000\255\255\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\ + \026\000\026\000\026\000\026\000\026\000\026\000\026\000\255\255\ \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ + \028\000\028\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ - \028\000\028\000\028\000\028\000\255\255\255\255\255\255\255\255\ - \028\000\255\255\028\000\028\000\028\000\028\000\028\000\028\000\ \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ + \028\000\028\000\028\000\255\255\255\255\255\255\255\255\028\000\ + \000\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ - \028\000\028\000\028\000\028\000\029\000\029\000\029\000\029\000\ - \029\000\029\000\029\000\029\000\029\000\029\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\029\000\029\000\029\000\ + \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\ + \028\000\028\000\028\000\029\000\029\000\029\000\029\000\029\000\ + \029\000\029\000\029\000\029\000\029\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\029\000\029\000\029\000\029\000\ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ - \029\000\029\000\029\000\029\000\029\000\029\000\029\000\255\255\ - \255\255\255\255\255\255\029\000\255\255\029\000\029\000\029\000\ + \029\000\029\000\029\000\029\000\029\000\029\000\255\255\255\255\ + \255\255\255\255\029\000\255\255\029\000\029\000\029\000\029\000\ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\ - \029\000\029\000\029\000\029\000\029\000\029\000\029\000\030\000\ + \029\000\029\000\029\000\029\000\029\000\029\000\030\000\030\000\ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ - \030\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\255\255\255\255\255\255\255\255\ - \033\000\255\255\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\030\000\ + \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ + \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ + \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ + \030\000\255\255\255\255\255\255\255\255\030\000\255\255\030\000\ + \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ + \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ + \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\ + \030\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\255\255\255\255\255\255\255\255\ + \031\000\255\255\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\ + \031\000\031\000\031\000\031\000\032\000\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\032\000\255\255\ + \255\255\255\255\255\255\032\000\255\255\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\ + \032\000\032\000\032\000\032\000\032\000\032\000\032\000\033\000\ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\ - \033\000\033\000\033\000\033\000\034\000\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\255\255\ - \255\255\255\255\255\255\034\000\255\255\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\ - \034\000\034\000\034\000\034\000\034\000\034\000\034\000\035\000\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\255\255\255\255\255\255\255\255\035\000\255\255\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\ - \035\000\035\000\036\000\036\000\036\000\036\000\036\000\036\000\ - \036\000\036\000\036\000\036\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\036\000\036\000\036\000\036\000\036\000\ + \033\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\ + \036\000\036\000\036\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\036\000\036\000\036\000\036\000\036\000\036\000\ \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\ \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\ - \036\000\036\000\036\000\036\000\036\000\255\255\255\255\255\255\ - \255\255\036\000\255\255\036\000\036\000\036\000\036\000\036\000\ + \036\000\036\000\036\000\036\000\255\255\255\255\255\255\255\255\ + \036\000\255\255\036\000\036\000\036\000\036\000\036\000\036\000\ \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\ \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\ - \036\000\036\000\036\000\036\000\036\000\037\000\037\000\037\000\ - \037\000\037\000\037\000\037\000\037\000\037\000\037\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\037\000\037\000\ - \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\ - \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\ + \036\000\036\000\036\000\036\000\037\000\037\000\037\000\037\000\ + \037\000\037\000\037\000\037\000\037\000\037\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\037\000\037\000\037\000\ \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\ - \255\255\255\255\255\255\255\255\037\000\255\255\037\000\037\000\ \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\ + \037\000\037\000\037\000\037\000\037\000\037\000\037\000\255\255\ + \255\255\255\255\255\255\037\000\255\255\037\000\037\000\037\000\ \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\ \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\ + \037\000\037\000\037\000\037\000\037\000\037\000\037\000\038\000\ \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ - \038\000\038\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ + \038\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ - \038\000\038\000\038\000\255\255\255\255\255\255\255\255\038\000\ - \255\255\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ + \038\000\038\000\255\255\255\255\255\255\255\255\038\000\255\255\ \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ - \038\000\038\000\038\000\039\000\039\000\039\000\039\000\039\000\ - \039\000\039\000\039\000\039\000\039\000\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\039\000\039\000\039\000\039\000\ + \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ + \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\ + \038\000\038\000\039\000\039\000\039\000\039\000\039\000\039\000\ + \039\000\039\000\039\000\039\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\039\000\039\000\039\000\039\000\039\000\ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\ - \039\000\039\000\039\000\039\000\039\000\039\000\255\255\255\255\ - \255\255\255\255\039\000\255\255\039\000\039\000\039\000\039\000\ + \039\000\039\000\039\000\039\000\039\000\255\255\255\255\255\255\ + \255\255\039\000\255\255\039\000\039\000\039\000\039\000\039\000\ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\ - \039\000\039\000\039\000\039\000\039\000\039\000\040\000\040\000\ + \039\000\039\000\039\000\039\000\039\000\040\000\040\000\040\000\ + \040\000\040\000\040\000\040\000\040\000\040\000\040\000\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\040\000\040\000\ \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\040\000\ \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ + \255\255\255\255\255\255\255\255\040\000\255\255\040\000\040\000\ \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ - \040\000\255\255\255\255\255\255\255\255\040\000\255\255\040\000\ \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ - \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\ - \040\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ - \041\000\041\000\041\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\041\000\041\000\041\000\041\000\041\000\041\000\ \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ + \041\000\041\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ - \041\000\041\000\041\000\041\000\255\255\255\255\255\255\255\255\ - \041\000\255\255\041\000\041\000\041\000\041\000\041\000\041\000\ \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ + \041\000\041\000\041\000\255\255\255\255\255\255\255\255\041\000\ + \255\255\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ - \041\000\041\000\041\000\041\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\042\000\042\000\042\000\ + \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ + \041\000\041\000\041\000\042\000\042\000\042\000\042\000\042\000\ + \042\000\042\000\042\000\042\000\042\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\042\000\255\255\ - \255\255\255\255\255\255\042\000\255\255\042\000\042\000\042\000\ + \042\000\042\000\042\000\042\000\042\000\042\000\255\255\255\255\ + \255\255\255\255\042\000\255\255\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\ - \042\000\042\000\042\000\042\000\042\000\042\000\042\000\043\000\ + \042\000\042\000\042\000\042\000\042\000\042\000\043\000\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ - \043\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ - \043\000\043\000\255\255\255\255\255\255\255\255\043\000\255\255\ + \043\000\255\255\255\255\255\255\255\255\043\000\255\255\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\ - \043\000\043\000\044\000\044\000\044\000\044\000\044\000\044\000\ - \044\000\044\000\044\000\044\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\044\000\044\000\044\000\044\000\044\000\ + \043\000\044\000\044\000\044\000\044\000\044\000\044\000\044\000\ + \044\000\044\000\044\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\044\000\044\000\044\000\044\000\044\000\044\000\ \044\000\044\000\044\000\044\000\044\000\044\000\044\000\044\000\ \044\000\044\000\044\000\044\000\044\000\044\000\044\000\044\000\ - \044\000\044\000\044\000\044\000\044\000\255\255\255\255\255\255\ - \255\255\044\000\255\255\044\000\044\000\044\000\044\000\044\000\ + \044\000\044\000\044\000\044\000\255\255\255\255\255\255\255\255\ + \044\000\255\255\044\000\044\000\044\000\044\000\044\000\044\000\ \044\000\044\000\044\000\044\000\044\000\044\000\044\000\044\000\ \044\000\044\000\044\000\044\000\044\000\044\000\044\000\044\000\ - \044\000\044\000\044\000\044\000\044\000\045\000\045\000\045\000\ - \045\000\045\000\045\000\045\000\045\000\045\000\045\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\045\000\045\000\ - \045\000\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ + \044\000\044\000\044\000\044\000\045\000\045\000\045\000\045\000\ + \045\000\045\000\045\000\045\000\045\000\045\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\045\000\045\000\045\000\ \045\000\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ \045\000\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ - \255\255\255\255\255\255\255\255\045\000\255\255\045\000\045\000\ - \045\000\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ + \045\000\045\000\045\000\045\000\045\000\045\000\045\000\255\255\ + \255\255\255\255\255\255\045\000\255\255\045\000\045\000\045\000\ \045\000\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ \045\000\045\000\045\000\045\000\045\000\045\000\045\000\045\000\ + \045\000\045\000\045\000\045\000\045\000\045\000\045\000\046\000\ \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ - \046\000\046\000\255\255\255\255\255\255\255\255\255\255\255\255\ - \255\255\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ + \046\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ - \046\000\046\000\046\000\255\255\255\255\255\255\255\255\046\000\ - \255\255\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ + \046\000\046\000\255\255\255\255\255\255\255\255\046\000\255\255\ \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ - \046\000\046\000\046\000\047\000\047\000\047\000\047\000\047\000\ - \047\000\047\000\047\000\047\000\047\000\255\255\255\255\255\255\ - \255\255\255\255\255\255\255\255\047\000\047\000\047\000\047\000\ + \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ + \046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ + \046\000\046\000\047\000\047\000\047\000\047\000\047\000\047\000\ + \047\000\047\000\047\000\047\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\047\000\047\000\047\000\047\000\047\000\ \047\000\047\000\047\000\047\000\047\000\047\000\047\000\047\000\ \047\000\047\000\047\000\047\000\047\000\047\000\047\000\047\000\ - \047\000\047\000\047\000\047\000\047\000\047\000\255\255\255\255\ - \255\255\255\255\047\000\255\255\047\000\047\000\047\000\047\000\ + \047\000\047\000\047\000\047\000\047\000\255\255\255\255\255\255\ + \255\255\047\000\255\255\047\000\047\000\047\000\047\000\047\000\ \047\000\047\000\047\000\047\000\047\000\047\000\047\000\047\000\ \047\000\047\000\047\000\047\000\047\000\047\000\047\000\047\000\ - \047\000\047\000\047\000\047\000\047\000\047\000\048\000\048\000\ - \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ - \255\255\255\255\255\255\255\255\255\255\255\255\255\255\048\000\ + \047\000\047\000\047\000\047\000\047\000\048\000\048\000\048\000\ + \048\000\048\000\048\000\048\000\048\000\048\000\048\000\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\048\000\048\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ - \048\000\255\255\255\255\255\255\255\255\048\000\255\255\048\000\ + \255\255\255\255\255\255\255\255\048\000\255\255\048\000\048\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ \048\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ - \048\000\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ - \049\000\049\000\049\000\255\255\255\255\255\255\255\255\255\255\ - \255\255\255\255\049\000\049\000\049\000\049\000\049\000\049\000\ \049\000\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ + \049\000\049\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ \049\000\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ - \049\000\049\000\049\000\049\000\255\255\255\255\255\255\255\255\ - \049\000\255\255\049\000\049\000\049\000\049\000\049\000\049\000\ \049\000\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ + \049\000\049\000\049\000\255\255\255\255\255\255\255\255\049\000\ + \255\255\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ \049\000\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ - \049\000\049\000\049\000\049\000\050\000\050\000\050\000\050\000\ - \050\000\050\000\050\000\050\000\050\000\050\000\255\255\255\255\ - \255\255\255\255\255\255\255\255\255\255\050\000\050\000\050\000\ + \049\000\049\000\049\000\049\000\049\000\049\000\049\000\049\000\ + \049\000\049\000\049\000\050\000\050\000\050\000\050\000\050\000\ + \050\000\050\000\050\000\050\000\050\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\050\000\050\000\050\000\050\000\ \050\000\050\000\050\000\050\000\050\000\050\000\050\000\050\000\ \050\000\050\000\050\000\050\000\050\000\050\000\050\000\050\000\ - \050\000\050\000\050\000\050\000\050\000\050\000\050\000\255\255\ - \255\255\255\255\255\255\050\000\255\255\050\000\050\000\050\000\ + \050\000\050\000\050\000\050\000\050\000\050\000\255\255\255\255\ + \255\255\255\255\050\000\255\255\050\000\050\000\050\000\050\000\ \050\000\050\000\050\000\050\000\050\000\050\000\050\000\050\000\ \050\000\050\000\050\000\050\000\050\000\050\000\050\000\050\000\ - \050\000\050\000\050\000\050\000\050\000\050\000\050\000\051\000\ + \050\000\050\000\050\000\050\000\050\000\050\000\051\000\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ - \051\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ - \051\000\051\000\255\255\255\255\255\255\255\255\051\000\255\255\ + \051\000\255\255\255\255\255\255\255\255\051\000\255\255\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ \051\000\051\000\051\000\051\000\051\000\051\000\051\000\051\000\ - \051\000\051\000\052\000\052\000\052\000\052\000\052\000\052\000\ - \052\000\052\000\052\000\052\000\255\255\255\255\255\255\255\255\ - \255\255\255\255\255\255\052\000\052\000\052\000\052\000\052\000\ + \051\000\052\000\052\000\052\000\052\000\052\000\052\000\052\000\ + \052\000\052\000\052\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\052\000\052\000\052\000\052\000\052\000\052\000\ \052\000\052\000\052\000\052\000\052\000\052\000\052\000\052\000\ \052\000\052\000\052\000\052\000\052\000\052\000\052\000\052\000\ - \052\000\052\000\052\000\052\000\052\000\255\255\255\255\255\255\ - \255\255\052\000\255\255\052\000\052\000\052\000\052\000\052\000\ + \052\000\052\000\052\000\052\000\255\255\255\255\255\255\255\255\ + \052\000\255\255\052\000\052\000\052\000\052\000\052\000\052\000\ \052\000\052\000\052\000\052\000\052\000\052\000\052\000\052\000\ \052\000\052\000\052\000\052\000\052\000\052\000\052\000\052\000\ - \052\000\052\000\052\000\052\000\052\000\053\000\053\000\053\000\ - \053\000\053\000\053\000\053\000\053\000\053\000\053\000\255\255\ - \255\255\255\255\255\255\255\255\255\255\255\255\053\000\053\000\ - \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ - \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ + \052\000\052\000\052\000\052\000\053\000\053\000\053\000\053\000\ + \053\000\053\000\053\000\053\000\053\000\053\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\053\000\053\000\053\000\ \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ - \255\255\255\255\255\255\255\255\053\000\255\255\053\000\053\000\ \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ + \053\000\053\000\053\000\053\000\053\000\053\000\053\000\255\255\ + \255\255\255\255\255\255\053\000\255\255\053\000\053\000\053\000\ \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ \053\000\053\000\053\000\053\000\053\000\053\000\053\000\053\000\ + \053\000\053\000\053\000\053\000\053\000\053\000\053\000\054\000\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\255\255\255\255\255\255\255\255\054\000\255\255\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\054\000\054\000\054\000\054\000\054\000\054\000\ + \054\000\054\000\055\000\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\055\000\255\255\255\255\255\255\ + \255\255\055\000\255\255\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\055\000\055\000\055\000\055\000\ + \055\000\055\000\055\000\055\000\055\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \255\255\255\255\255\255\255\255\056\000\255\255\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ + \056\000\056\000\056\000\056\000\056\000\056\000\056\000\056\000\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ @@ -637,257 +643,277 @@ } let rec token lexbuf = - __ocaml_lex_token_rec lexbuf 0 + __ocaml_lex_token_rec lexbuf 0 and __ocaml_lex_token_rec lexbuf __ocaml_lex_state = match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with | 0 -> -# 49 "src/aorai/yalexer.mll" +# 51 "src/aorai/yalexer.mll" ( token lexbuf ) -# 647 "src/aorai/yalexer.ml" +# 653 "src/aorai/yalexer.ml" | 1 -> -# 50 "src/aorai/yalexer.mll" +# 52 "src/aorai/yalexer.mll" ( new_line lexbuf; token lexbuf ) -# 652 "src/aorai/yalexer.ml" +# 658 "src/aorai/yalexer.ml" | 2 -> let -# 51 "src/aorai/yalexer.mll" +# 53 "src/aorai/yalexer.mll" lxm -# 658 "src/aorai/yalexer.ml" +# 664 "src/aorai/yalexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in -# 51 "src/aorai/yalexer.mll" +# 53 "src/aorai/yalexer.mll" ( INT(lxm) ) -# 662 "src/aorai/yalexer.ml" +# 668 "src/aorai/yalexer.ml" | 3 -> -# 52 "src/aorai/yalexer.mll" +# 54 "src/aorai/yalexer.mll" ( CALL_OF ) -# 667 "src/aorai/yalexer.ml" +# 673 "src/aorai/yalexer.ml" | 4 -> -# 53 "src/aorai/yalexer.mll" +# 55 "src/aorai/yalexer.mll" ( RETURN_OF ) -# 672 "src/aorai/yalexer.ml" +# 678 "src/aorai/yalexer.ml" | 5 -> -# 54 "src/aorai/yalexer.mll" +# 56 "src/aorai/yalexer.mll" ( CALLORRETURN_OF ) -# 677 "src/aorai/yalexer.ml" +# 683 "src/aorai/yalexer.ml" | 6 -> -# 55 "src/aorai/yalexer.mll" +# 57 "src/aorai/yalexer.mll" ( OTHERWISE ) -# 682 "src/aorai/yalexer.ml" +# 688 "src/aorai/yalexer.ml" | 7 -> -# 56 "src/aorai/yalexer.mll" +# 58 "src/aorai/yalexer.mll" ( TRUE ) -# 687 "src/aorai/yalexer.ml" +# 693 "src/aorai/yalexer.ml" | 8 -> -# 57 "src/aorai/yalexer.mll" +# 59 "src/aorai/yalexer.mll" ( FALSE ) -# 692 "src/aorai/yalexer.ml" +# 698 "src/aorai/yalexer.ml" | 9 -> -# 58 "src/aorai/yalexer.mll" - ( FUNC ) -# 697 "src/aorai/yalexer.ml" +let +# 60 "src/aorai/yalexer.mll" + lxm +# 704 "src/aorai/yalexer.ml" += Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos (lexbuf.Lexing.lex_start_pos + 7) in +# 60 "src/aorai/yalexer.mll" + ( IDENTIFIER(lxm) ) +# 708 "src/aorai/yalexer.ml" | 10 -> let -# 59 "src/aorai/yalexer.mll" +# 61 "src/aorai/yalexer.mll" lxm -# 703 "src/aorai/yalexer.ml" +# 714 "src/aorai/yalexer.ml" = Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in -# 59 "src/aorai/yalexer.mll" +# 61 "src/aorai/yalexer.mll" ( IDENTIFIER(lxm) ) -# 707 "src/aorai/yalexer.ml" +# 718 "src/aorai/yalexer.ml" | 11 -> -# 60 "src/aorai/yalexer.mll" +# 62 "src/aorai/yalexer.mll" ( COMMA ) -# 712 "src/aorai/yalexer.ml" +# 723 "src/aorai/yalexer.ml" | 12 -> -# 61 "src/aorai/yalexer.mll" +# 63 "src/aorai/yalexer.mll" ( PLUS ) -# 717 "src/aorai/yalexer.ml" +# 728 "src/aorai/yalexer.ml" | 13 -> -# 62 "src/aorai/yalexer.mll" +# 64 "src/aorai/yalexer.mll" ( MINUS ) -# 722 "src/aorai/yalexer.ml" +# 733 "src/aorai/yalexer.ml" | 14 -> -# 63 "src/aorai/yalexer.mll" +# 65 "src/aorai/yalexer.mll" ( STAR ) -# 727 "src/aorai/yalexer.ml" +# 738 "src/aorai/yalexer.ml" | 15 -> -# 64 "src/aorai/yalexer.mll" +# 66 "src/aorai/yalexer.mll" ( SLASH ) -# 732 "src/aorai/yalexer.ml" +# 743 "src/aorai/yalexer.ml" | 16 -> -# 65 "src/aorai/yalexer.mll" +# 67 "src/aorai/yalexer.mll" ( PERCENT ) -# 737 "src/aorai/yalexer.ml" +# 748 "src/aorai/yalexer.ml" | 17 -> -# 66 "src/aorai/yalexer.mll" +# 68 "src/aorai/yalexer.mll" ( LPAREN ) -# 742 "src/aorai/yalexer.ml" +# 753 "src/aorai/yalexer.ml" | 18 -> -# 67 "src/aorai/yalexer.mll" +# 69 "src/aorai/yalexer.mll" ( RPAREN ) -# 747 "src/aorai/yalexer.ml" +# 758 "src/aorai/yalexer.ml" | 19 -> -# 68 "src/aorai/yalexer.mll" +# 70 "src/aorai/yalexer.mll" ( LSQUARE ) -# 752 "src/aorai/yalexer.ml" +# 763 "src/aorai/yalexer.ml" | 20 -> -# 69 "src/aorai/yalexer.mll" +# 71 "src/aorai/yalexer.mll" ( RSQUARE ) -# 757 "src/aorai/yalexer.ml" +# 768 "src/aorai/yalexer.ml" | 21 -> -# 70 "src/aorai/yalexer.mll" +# 72 "src/aorai/yalexer.mll" ( LCURLY ) -# 762 "src/aorai/yalexer.ml" +# 773 "src/aorai/yalexer.ml" | 22 -> -# 71 "src/aorai/yalexer.mll" +# 73 "src/aorai/yalexer.mll" ( RCURLY ) -# 767 "src/aorai/yalexer.ml" +# 778 "src/aorai/yalexer.ml" | 23 -> -# 72 "src/aorai/yalexer.mll" - ( DOT ) -# 772 "src/aorai/yalexer.ml" +# 74 "src/aorai/yalexer.mll" + ( LBRACELBRACE ) +# 783 "src/aorai/yalexer.ml" | 24 -> -# 73 "src/aorai/yalexer.mll" - ( RARROW ) -# 777 "src/aorai/yalexer.ml" +# 75 "src/aorai/yalexer.mll" + ( RBRACERBRACE ) +# 788 "src/aorai/yalexer.ml" | 25 -> -# 74 "src/aorai/yalexer.mll" - ( AMP ) -# 782 "src/aorai/yalexer.ml" +# 76 "src/aorai/yalexer.mll" + ( DOT ) +# 793 "src/aorai/yalexer.ml" | 26 -> -# 75 "src/aorai/yalexer.mll" - ( PIPE ) -# 787 "src/aorai/yalexer.ml" +# 77 "src/aorai/yalexer.mll" + ( RARROW ) +# 798 "src/aorai/yalexer.ml" | 27 -> -# 76 "src/aorai/yalexer.mll" - ( AND ) -# 792 "src/aorai/yalexer.ml" +# 78 "src/aorai/yalexer.mll" + ( AMP ) +# 803 "src/aorai/yalexer.ml" | 28 -> -# 77 "src/aorai/yalexer.mll" - ( OR ) -# 797 "src/aorai/yalexer.ml" +# 79 "src/aorai/yalexer.mll" + ( PIPE ) +# 808 "src/aorai/yalexer.ml" | 29 -> -# 78 "src/aorai/yalexer.mll" - ( NOT ) -# 802 "src/aorai/yalexer.ml" +# 80 "src/aorai/yalexer.mll" + ( AND ) +# 813 "src/aorai/yalexer.ml" | 30 -> -# 79 "src/aorai/yalexer.mll" - ( LT ) -# 807 "src/aorai/yalexer.ml" +# 81 "src/aorai/yalexer.mll" + ( OR ) +# 818 "src/aorai/yalexer.ml" | 31 -> -# 80 "src/aorai/yalexer.mll" - ( GT ) -# 812 "src/aorai/yalexer.ml" +# 82 "src/aorai/yalexer.mll" + ( NOT ) +# 823 "src/aorai/yalexer.ml" | 32 -> -# 81 "src/aorai/yalexer.mll" - ( LE ) -# 817 "src/aorai/yalexer.ml" +# 83 "src/aorai/yalexer.mll" + ( LT ) +# 828 "src/aorai/yalexer.ml" | 33 -> -# 82 "src/aorai/yalexer.mll" - ( GE ) -# 822 "src/aorai/yalexer.ml" +# 84 "src/aorai/yalexer.mll" + ( GT ) +# 833 "src/aorai/yalexer.ml" | 34 -> -# 83 "src/aorai/yalexer.mll" - ( EQ ) -# 827 "src/aorai/yalexer.ml" +# 85 "src/aorai/yalexer.mll" + ( LE ) +# 838 "src/aorai/yalexer.ml" | 35 -> -# 84 "src/aorai/yalexer.mll" - ( NEQ ) -# 832 "src/aorai/yalexer.ml" +# 86 "src/aorai/yalexer.mll" + ( GE ) +# 843 "src/aorai/yalexer.ml" | 36 -> -# 85 "src/aorai/yalexer.mll" - ( TRUE ) -# 837 "src/aorai/yalexer.ml" +# 87 "src/aorai/yalexer.mll" + ( EQ ) +# 848 "src/aorai/yalexer.ml" | 37 -> -# 86 "src/aorai/yalexer.mll" - ( FALSE ) -# 842 "src/aorai/yalexer.ml" +# 88 "src/aorai/yalexer.mll" + ( NEQ ) +# 853 "src/aorai/yalexer.ml" | 38 -> -# 87 "src/aorai/yalexer.mll" +# 89 "src/aorai/yalexer.mll" ( SEMI_COLON ) -# 847 "src/aorai/yalexer.ml" +# 858 "src/aorai/yalexer.ml" | 39 -> -# 88 "src/aorai/yalexer.mll" +# 90 "src/aorai/yalexer.mll" ( COLON ) -# 852 "src/aorai/yalexer.ml" +# 863 "src/aorai/yalexer.ml" | 40 -> -# 89 "src/aorai/yalexer.mll" - ( EOF ) -# 857 "src/aorai/yalexer.ml" +# 91 "src/aorai/yalexer.mll" + ( COLUMNCOLUMN ) +# 868 "src/aorai/yalexer.ml" | 41 -> -# 90 "src/aorai/yalexer.mll" +# 92 "src/aorai/yalexer.mll" + ( CARET ) +# 873 "src/aorai/yalexer.ml" + + | 42 -> +# 93 "src/aorai/yalexer.mll" + ( QUESTION ) +# 878 "src/aorai/yalexer.ml" + + | 43 -> +# 94 "src/aorai/yalexer.mll" + ( EOF ) +# 883 "src/aorai/yalexer.ml" + + | 44 -> +# 95 "src/aorai/yalexer.mll" ( raise_located (loc lexbuf) "Unknown token" ) -# 862 "src/aorai/yalexer.ml" +# 888 "src/aorai/yalexer.ml" | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state ;; -# 95 "src/aorai/yalexer.mll" +# 97 "src/aorai/yalexer.mll" let parse c = let lb = from_channel c in try Yaparser.main token lb with - Parsing.Parse_error + Parsing.Parse_error | Invalid_argument _ -> (* [VP]: Does not contain more information than what is in the exn. *) - (*let (a,b)=(loc lb) in - Format.print_string "Syntax error (" ; - Format.print_string "l" ; - Format.print_int a.pos_lnum ; - Format.print_string "c" ; - Format.print_int (a.pos_cnum-a.pos_bol) ; - Format.print_string " -> l" ; - Format.print_int b.pos_lnum ; - Format.print_string "c" ; - Format.print_int (b.pos_cnum-b.pos_bol) ; - Format.print_string ")\n" ; + (*let (a,b)=(loc lb) in + Format.print_string "Syntax error (" ; + Format.print_string "l" ; + Format.print_int a.pos_lnum ; + Format.print_string "c" ; + Format.print_int (a.pos_cnum-a.pos_bol) ; + Format.print_string " -> l" ; + Format.print_int b.pos_lnum ; + Format.print_string "c" ; + Format.print_int (b.pos_cnum-b.pos_bol) ; + Format.print_string ")\n" ; *) - raise_located (loc lb) "Syntax error" + raise_located (loc lb) "Syntax error" -# 894 "src/aorai/yalexer.ml" +# 920 "src/aorai/yalexer.ml" diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/yalexer.mll frama-c-20111001+nitrogen+dfsg/src/aorai/yalexer.mll --- frama-c-20110201+carbon+dfsg/src/aorai/yalexer.mll 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/yalexer.mll 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of Aorai plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* INSA (Institut National des Sciences Appliquees) *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) (* INRIA (Institut National de Recherche en Informatique et en *) (* Automatique) *) +(* INSA (Institut National des Sciences Appliquees) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -30,7 +32,7 @@ let new_line lexbuf = let lcp = lexbuf.lex_curr_p in lexbuf.lex_curr_p <- { lcp with pos_lnum = lcp.pos_lnum + 1; - pos_bol = lcp.pos_cnum; } + pos_bol = lcp.pos_cnum; } ;; exception Error of (Lexing.position * Lexing.position) * string @@ -55,7 +57,7 @@ | "other" { OTHERWISE } | "true" { TRUE } | "false" { FALSE } - | "()" { FUNC } + | "\\result" as lxm { IDENTIFIER(lxm) } | ident as lxm { IDENTIFIER(lxm) } | ',' { COMMA } | '+' { PLUS } @@ -69,6 +71,8 @@ | ']' { RSQUARE } | '{' { LCURLY } | '}' { RCURLY } + | "{{" { LBRACELBRACE } + | "}}" { RBRACERBRACE } | '.' { DOT } | "->" { RARROW } | '&' { AMP } @@ -82,38 +86,36 @@ | ">=" { GE } | "==" { EQ } | "!=" { NEQ } - | "true" { TRUE } - | "false" { FALSE } | ';' { SEMI_COLON } | ':' { COLON } + | "::" { COLUMNCOLUMN } + | '^' { CARET } + | '?' { QUESTION } | eof { EOF } | _ { raise_located (loc lexbuf) "Unknown token" } - - - { let parse c = let lb = from_channel c in try Yaparser.main token lb with - Parsing.Parse_error + Parsing.Parse_error | Invalid_argument _ -> (* [VP]: Does not contain more information than what is in the exn. *) - (*let (a,b)=(loc lb) in - Format.print_string "Syntax error (" ; - Format.print_string "l" ; - Format.print_int a.pos_lnum ; - Format.print_string "c" ; - Format.print_int (a.pos_cnum-a.pos_bol) ; - Format.print_string " -> l" ; - Format.print_int b.pos_lnum ; - Format.print_string "c" ; - Format.print_int (b.pos_cnum-b.pos_bol) ; - Format.print_string ")\n" ; + (*let (a,b)=(loc lb) in + Format.print_string "Syntax error (" ; + Format.print_string "l" ; + Format.print_int a.pos_lnum ; + Format.print_string "c" ; + Format.print_int (a.pos_cnum-a.pos_bol) ; + Format.print_string " -> l" ; + Format.print_int b.pos_lnum ; + Format.print_string "c" ; + Format.print_int (b.pos_cnum-b.pos_bol) ; + Format.print_string ")\n" ; *) - raise_located (loc lb) "Syntax error" + raise_located (loc lb) "Syntax error" } diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/yaparser.ml frama-c-20111001+nitrogen+dfsg/src/aorai/yaparser.ml --- frama-c-20110201+carbon+dfsg/src/aorai/yaparser.ml 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/yaparser.ml 2011-10-10 08:48:50.000000000 +0000 @@ -10,10 +10,11 @@ | RPAREN | LSQUARE | RSQUARE + | LBRACELBRACE + | RBRACERBRACE | RARROW | TRUE | FALSE - | FUNC | NOT | DOT | AMP @@ -21,6 +22,9 @@ | SEMI_COLON | COMMA | PIPE + | CARET + | QUESTION + | COLUMNCOLUMN | EQ | LT | GT @@ -38,27 +42,26 @@ | EOF open Parsing;; -# 28 "src/aorai/yaparser.mly" +# 30 "src/aorai/yaparser.mly" +open Logic_ptree open Parsing open Promelaast open Bool3 open Format -type trans = Pred of Promelaast.condition | Otherwise +let to_seq c = + [{ condition = Some c; + nested = []; + min_rep = Some Data_for_aorai.cst_one; + max_rep = Some Data_for_aorai.cst_one; + }] + +let is_no_repet (min,max) = + let is_one c = Extlib.may_map Data_for_aorai.is_cst_one ~dft:false c in + is_one min && is_one max let observed_states = Hashtbl.create 1 let prefetched_states = Hashtbl.create 1 -let observed_vars = Hashtbl.create 1 -let observed_funcs = Hashtbl.create 1 -let observed_expressions = Hashtbl.create 97 - -(* Current observed expr contains : *) -type observed_expr = Func_ret of string (* func name : a return of the given func *) - | Func_param of string * (string list) (* Func name * param : a call with given param *) - | Only_vars (* Only constants and variables *) - -let observed_expr_is_param = ref Only_vars - let ident_count=ref 0 let get_fresh_ident () = @@ -66,23 +69,20 @@ ("buchfreshident"^(string_of_int !ident_count)) ;; - - let fetch_and_create_state name = Hashtbl.remove prefetched_states name ; try Hashtbl.find observed_states name with - Not_found -> - let s={ name=name; - acceptation=False; init=False; - nums=(Hashtbl.length observed_states) } in - Hashtbl.add observed_states name s; - s + Not_found -> + let s = Data_for_aorai.new_state name in + Hashtbl.add observed_states name s; s ;; let prefetch_and_create_state name = - if (Hashtbl.mem prefetched_states name) or not (Hashtbl.mem observed_states name) then + if (Hashtbl.mem prefetched_states name) or + not (Hashtbl.mem observed_states name) + then begin let s= fetch_and_create_state name in Hashtbl.add prefetched_states name name; @@ -92,10 +92,9 @@ (fetch_and_create_state name) ;; -(*TODO: give a proper loc*) -let new_exp = Cil.new_exp ~loc:(Cil.CurrentLoc.get()) +type pre_cond = Behavior of string | Pre of Promelaast.condition -# 99 "src/aorai/yaparser.ml" +# 98 "src/aorai/yaparser.ml" let yytransl_const = [| 257 (* CALL_OF *); 258 (* RETURN_OF *); @@ -106,31 +105,35 @@ 265 (* RPAREN *); 266 (* LSQUARE *); 267 (* RSQUARE *); - 268 (* RARROW *); - 269 (* TRUE *); - 270 (* FALSE *); - 271 (* FUNC *); - 272 (* NOT *); - 273 (* DOT *); - 274 (* AMP *); - 275 (* COLON *); - 276 (* SEMI_COLON *); - 277 (* COMMA *); - 278 (* PIPE *); - 279 (* EQ *); - 280 (* LT *); - 281 (* GT *); - 282 (* LE *); - 283 (* GE *); - 284 (* NEQ *); - 285 (* PLUS *); - 286 (* MINUS *); - 287 (* SLASH *); - 288 (* STAR *); - 289 (* PERCENT *); - 290 (* OR *); - 291 (* AND *); - 292 (* OTHERWISE *); + 268 (* LBRACELBRACE *); + 269 (* RBRACERBRACE *); + 270 (* RARROW *); + 271 (* TRUE *); + 272 (* FALSE *); + 273 (* NOT *); + 274 (* DOT *); + 275 (* AMP *); + 276 (* COLON *); + 277 (* SEMI_COLON *); + 278 (* COMMA *); + 279 (* PIPE *); + 280 (* CARET *); + 281 (* QUESTION *); + 282 (* COLUMNCOLUMN *); + 283 (* EQ *); + 284 (* LT *); + 285 (* GT *); + 286 (* LE *); + 287 (* GE *); + 288 (* NEQ *); + 289 (* PLUS *); + 290 (* MINUS *); + 291 (* SLASH *); + 292 (* STAR *); + 293 (* PERCENT *); + 294 (* OR *); + 295 (* AND *); + 296 (* OTHERWISE *); 0 (* EOF *); 0|] @@ -140,131 +143,210 @@ 0|] let yylhs = "\255\255\ -\001\000\002\000\002\000\004\000\005\000\005\000\003\000\003\000\ -\006\000\007\000\007\000\008\000\008\000\008\000\009\000\009\000\ -\009\000\009\000\009\000\009\000\009\000\009\000\009\000\009\000\ -\010\000\010\000\010\000\010\000\010\000\010\000\010\000\011\000\ -\011\000\011\000\012\000\012\000\012\000\012\000\013\000\013\000\ -\013\000\013\000\014\000\014\000\014\000\015\000\015\000\015\000\ -\015\000\000\000" +\001\000\002\000\002\000\004\000\005\000\005\000\006\000\006\000\ +\003\000\003\000\007\000\008\000\008\000\009\000\009\000\009\000\ +\011\000\011\000\012\000\012\000\013\000\013\000\013\000\013\000\ +\013\000\015\000\015\000\016\000\016\000\010\000\017\000\017\000\ +\017\000\017\000\017\000\017\000\017\000\017\000\014\000\014\000\ +\014\000\014\000\014\000\014\000\014\000\014\000\014\000\014\000\ +\019\000\019\000\019\000\019\000\019\000\019\000\019\000\018\000\ +\018\000\018\000\020\000\020\000\020\000\020\000\021\000\021\000\ +\021\000\021\000\022\000\022\000\022\000\023\000\023\000\023\000\ +\023\000\000\000" let yylen = "\002\000\ -\002\000\002\000\001\000\005\000\003\000\001\000\002\000\001\000\ -\004\000\003\000\001\000\005\000\003\000\002\000\004\000\004\000\ +\002\000\002\000\001\000\004\000\000\000\002\000\003\000\001\000\ +\002\000\001\000\004\000\003\000\001\000\005\000\003\000\002\000\ +\001\000\003\000\000\000\001\000\001\000\003\000\006\000\005\000\ +\004\000\002\000\003\000\000\000\003\000\002\000\000\000\001\000\ +\001\000\001\000\005\000\003\000\004\000\004\000\004\000\004\000\ \004\000\001\000\001\000\002\000\003\000\003\000\003\000\001\000\ \003\000\003\000\003\000\003\000\003\000\003\000\001\000\003\000\ \003\000\001\000\003\000\003\000\003\000\001\000\001\000\002\000\ -\001\000\003\000\003\000\004\000\001\000\002\000\004\000\001\000\ +\001\000\003\000\003\000\004\000\001\000\002\000\005\000\001\000\ \003\000\002\000" let yydefred = "\000\000\ -\000\000\000\000\000\000\050\000\000\000\003\000\000\000\000\000\ -\000\000\002\000\008\000\000\000\000\000\007\000\006\000\000\000\ -\000\000\000\000\000\000\000\000\011\000\004\000\000\000\000\000\ -\000\000\000\000\000\000\039\000\000\000\018\000\019\000\000\000\ -\000\000\000\000\000\000\024\000\000\000\000\000\038\000\000\000\ -\045\000\014\000\000\000\009\000\000\000\005\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\020\000\040\000\000\000\ +\000\000\000\000\000\000\074\000\000\000\003\000\000\000\000\000\ +\000\000\002\000\010\000\000\000\000\000\000\000\009\000\008\000\ +\000\000\004\000\000\000\000\000\000\000\000\000\013\000\000\000\ +\000\000\000\000\000\000\000\000\063\000\000\000\000\000\042\000\ +\043\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\048\000\000\000\062\000\000\000\069\000\016\000\000\000\011\000\ +\000\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\044\000\ +\064\000\000\000\000\000\000\000\000\000\034\000\032\000\033\000\ +\030\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\013\000\010\000\000\000\000\000\000\000\000\000\023\000\ -\042\000\049\000\000\000\000\000\000\000\000\000\000\000\025\000\ -\026\000\027\000\028\000\029\000\030\000\032\000\033\000\035\000\ -\036\000\037\000\000\000\043\000\016\000\017\000\015\000\047\000\ -\012\000\000\000\044\000" +\015\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\026\000\000\000\000\000\047\000\066\000\073\000\000\000\022\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\000\000\049\000\ +\050\000\051\000\052\000\053\000\054\000\056\000\057\000\059\000\ +\060\000\061\000\000\000\067\000\040\000\041\000\039\000\000\000\ +\000\000\025\000\000\000\027\000\020\000\000\000\000\000\018\000\ +\014\000\000\000\000\000\036\000\000\000\068\000\000\000\071\000\ +\024\000\000\000\038\000\037\000\000\000\029\000\023\000\035\000" let yydgoto = "\002\000\ -\004\000\005\000\009\000\006\000\016\000\011\000\020\000\021\000\ -\035\000\036\000\037\000\038\000\039\000\040\000\041\000" - -let yysindex = "\003\000\ -\248\254\000\000\026\255\000\000\254\254\000\000\025\255\030\255\ -\051\255\000\000\000\000\076\255\015\255\000\000\000\000\243\254\ -\010\255\078\255\073\255\239\254\000\000\000\000\080\255\084\255\ -\085\255\103\255\094\255\000\000\010\255\000\000\000\000\010\255\ -\115\255\086\255\022\255\000\000\127\255\141\255\000\000\031\255\ -\000\000\000\000\111\255\000\000\015\255\000\000\118\255\142\255\ -\143\255\139\255\082\255\127\255\031\255\000\000\000\000\086\255\ -\031\255\167\255\010\255\010\255\057\255\057\255\057\255\057\255\ -\057\255\057\255\057\255\057\255\057\255\057\255\057\255\057\255\ -\176\255\000\000\000\000\172\255\173\255\174\255\180\255\000\000\ -\000\000\000\000\000\255\181\255\029\255\029\255\057\255\000\000\ +\004\000\005\000\009\000\006\000\013\000\017\000\011\000\022\000\ +\023\000\062\000\133\000\134\000\038\000\039\000\057\000\130\000\ +\073\000\040\000\041\000\042\000\043\000\044\000\045\000" + +let yysindex = "\004\000\ +\006\255\000\000\069\255\000\000\003\255\000\000\012\255\073\255\ +\076\255\000\000\000\000\096\255\088\255\253\254\000\000\000\000\ +\105\255\000\000\080\255\127\255\121\255\252\254\000\000\129\255\ +\131\255\135\255\137\255\010\255\000\000\102\255\080\255\000\000\ +\000\000\102\255\156\255\025\255\160\255\251\254\048\255\208\255\ +\000\000\078\255\000\000\005\255\000\000\000\000\138\255\000\000\ +\253\254\000\000\166\255\171\255\173\255\055\255\102\255\175\255\ +\191\255\193\255\036\255\208\255\005\255\182\255\194\255\000\000\ +\000\000\025\255\005\255\192\255\008\255\000\000\000\000\000\000\ +\000\000\102\255\102\255\168\255\168\255\168\255\168\255\168\255\ +\168\255\168\255\168\255\168\255\168\255\168\255\168\255\203\255\ +\000\000\000\000\201\255\202\255\204\255\050\255\220\255\028\255\ +\000\000\080\255\222\255\000\000\000\000\000\000\080\255\000\000\ +\016\255\237\255\168\255\168\255\255\254\048\255\048\255\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\175\255\000\000\000\000\000\000\000\000\000\000\ -\000\000\178\255\000\000" +\000\000\000\000\233\255\000\000\000\000\000\000\000\000\102\255\ +\241\255\000\000\235\255\000\000\000\000\224\255\245\255\000\000\ +\000\000\002\000\010\000\000\000\161\255\000\000\063\255\000\000\ +\000\000\235\255\000\000\000\000\011\000\000\000\000\000\000\000" let yyrindex = "\000\000\ +\000\000\000\000\000\000\000\000\000\000\000\000\244\255\000\000\ +\019\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\153\255\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\113\255\112\000\033\000\ +\000\000\255\255\000\000\187\255\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\188\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\119\255\000\000\060\255\046\000\083\255\000\000\000\000\ +\000\000\000\000\221\255\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\043\255\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\079\255\114\255\000\000\072\255\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\110\255\134\255\000\000\000\000\000\000\ -\101\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\121\000\000\000\000\000\ +\000\000\014\000\000\000\000\000\000\000\000\000\112\255\000\000\ +\000\000\000\000\000\000\000\000\000\000\080\000\089\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\013\255\036\255\000\000\000\000\ +\000\000\000\000\121\000\000\000\000\000\000\000\000\000\000\000\ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ -\000\000\000\000\000\000" +\000\000\121\000\000\000\000\000\000\000\000\000\000\000\000\000" let yygindex = "\000\000\ -\000\000\000\000\000\000\184\000\000\000\181\000\000\000\146\000\ -\243\255\000\000\227\255\000\000\106\000\228\255\000\000" - -let yytablesize = 191 -let yytable = "\052\000\ -\053\000\008\000\044\000\001\000\045\000\057\000\022\000\023\000\ -\082\000\072\000\024\000\025\000\026\000\027\000\028\000\051\000\ -\073\000\029\000\054\000\022\000\017\000\022\000\030\000\031\000\ -\003\000\032\000\018\000\083\000\058\000\007\000\003\000\088\000\ -\089\000\090\000\091\000\092\000\093\000\094\000\095\000\033\000\ -\072\000\034\000\021\000\012\000\021\000\085\000\086\000\073\000\ -\013\000\048\000\019\000\048\000\048\000\048\000\008\000\059\000\ -\060\000\106\000\053\000\048\000\027\000\028\000\059\000\060\000\ -\087\000\048\000\048\000\048\000\048\000\048\000\048\000\048\000\ -\048\000\048\000\048\000\048\000\048\000\048\000\041\000\015\000\ -\041\000\042\000\041\000\046\000\043\000\031\000\033\000\031\000\ -\034\000\027\000\080\000\047\000\048\000\056\000\041\000\041\000\ -\041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ -\041\000\041\000\041\000\046\000\050\000\046\000\049\000\046\000\ -\031\000\031\000\074\000\059\000\060\000\034\000\031\000\055\000\ -\034\000\076\000\034\000\046\000\046\000\046\000\046\000\046\000\ -\046\000\046\000\046\000\046\000\046\000\046\000\046\000\046\000\ -\034\000\034\000\034\000\034\000\034\000\034\000\041\000\031\000\ -\031\000\077\000\078\000\034\000\034\000\061\000\062\000\063\000\ -\064\000\065\000\066\000\079\000\041\000\041\000\041\000\041\000\ -\041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\ -\041\000\067\000\068\000\069\000\070\000\071\000\096\000\097\000\ -\098\000\099\000\084\000\100\000\101\000\102\000\103\000\104\000\ -\105\000\107\000\081\000\001\000\010\000\014\000\075\000" - -let yycheck = "\029\000\ -\029\000\004\001\020\001\001\000\022\001\034\000\020\001\021\001\ -\009\001\010\001\001\001\002\001\003\001\004\001\005\001\029\000\ -\017\001\008\001\032\000\007\001\006\001\009\001\013\001\014\001\ -\033\001\016\001\012\001\056\000\007\001\004\001\033\001\061\000\ -\062\000\063\000\064\000\065\000\066\000\067\000\068\000\030\001\ -\010\001\032\001\007\001\019\001\009\001\059\000\060\000\017\001\ -\019\001\007\001\036\001\009\001\010\001\011\001\004\001\034\001\ -\035\001\087\000\087\000\017\001\004\001\005\001\034\001\035\001\ -\008\001\023\001\024\001\025\001\026\001\027\001\028\001\029\001\ -\030\001\031\001\032\001\033\001\034\001\035\001\007\001\004\001\ -\009\001\004\001\011\001\004\001\012\001\007\001\030\001\009\001\ -\032\001\004\001\009\001\008\001\008\001\008\001\023\001\024\001\ -\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001\ -\033\001\034\001\035\001\007\001\015\001\009\001\008\001\011\001\ -\034\001\035\001\004\001\034\001\035\001\032\001\009\001\005\001\ -\007\001\004\001\009\001\023\001\024\001\025\001\026\001\027\001\ +\000\000\000\000\000\000\020\001\000\000\000\000\024\001\000\000\ +\241\000\017\001\229\255\194\000\000\000\236\255\000\000\134\255\ +\000\000\226\255\000\000\000\000\185\000\228\255\000\000" + +let yytablesize = 413 +let yytable = "\060\000\ +\069\000\061\000\019\000\063\000\001\000\140\000\008\000\067\000\ +\145\000\059\000\020\000\058\000\029\000\064\000\087\000\107\000\ +\048\000\054\000\049\000\070\000\141\000\055\000\088\000\151\000\ +\102\000\087\000\095\000\071\000\058\000\108\000\072\000\012\000\ +\066\000\088\000\096\000\056\000\021\000\105\000\109\000\003\000\ +\132\000\035\000\003\000\036\000\100\000\112\000\113\000\114\000\ +\115\000\116\000\117\000\118\000\119\000\110\000\111\000\025\000\ +\026\000\027\000\028\000\029\000\036\000\128\000\030\000\094\000\ +\031\000\074\000\075\000\129\000\055\000\032\000\033\000\034\000\ +\007\000\074\000\075\000\150\000\138\000\139\000\061\000\008\000\ +\025\000\026\000\027\000\028\000\029\000\074\000\075\000\030\000\ +\035\000\031\000\036\000\017\000\014\000\017\000\032\000\033\000\ +\034\000\055\000\055\000\016\000\074\000\075\000\025\000\026\000\ +\027\000\058\000\029\000\143\000\018\000\030\000\149\000\083\000\ +\084\000\035\000\086\000\036\000\032\000\033\000\034\000\031\000\ +\019\000\031\000\019\000\031\000\072\000\072\000\024\000\072\000\ +\072\000\072\000\046\000\072\000\050\000\031\000\047\000\035\000\ +\072\000\036\000\051\000\072\000\072\000\089\000\052\000\072\000\ +\053\000\072\000\072\000\072\000\072\000\072\000\072\000\072\000\ +\072\000\072\000\072\000\072\000\072\000\072\000\072\000\072\000\ +\065\000\072\000\072\000\072\000\058\000\029\000\068\000\148\000\ +\107\000\091\000\072\000\058\000\029\000\072\000\092\000\107\000\ +\093\000\072\000\097\000\072\000\072\000\072\000\072\000\072\000\ +\072\000\072\000\072\000\072\000\072\000\072\000\072\000\072\000\ +\065\000\065\000\035\000\065\000\036\000\065\000\098\000\065\000\ +\099\000\035\000\103\000\036\000\104\000\106\000\124\000\065\000\ +\065\000\125\000\126\000\065\000\127\000\065\000\065\000\065\000\ +\065\000\065\000\065\000\065\000\065\000\065\000\065\000\065\000\ +\065\000\065\000\070\000\070\000\131\000\070\000\135\000\070\000\ +\146\000\070\000\076\000\077\000\078\000\079\000\080\000\081\000\ +\137\000\070\000\070\000\142\000\144\000\070\000\128\000\070\000\ +\070\000\070\000\070\000\070\000\070\000\070\000\070\000\070\000\ +\070\000\070\000\070\000\070\000\058\000\058\000\129\000\058\000\ +\005\000\058\000\101\000\058\000\120\000\121\000\122\000\123\000\ +\147\000\152\000\001\000\058\000\058\000\006\000\019\000\058\000\ +\010\000\058\000\058\000\058\000\058\000\058\000\058\000\058\000\ +\015\000\090\000\058\000\037\000\058\000\058\000\055\000\055\000\ +\136\000\055\000\000\000\055\000\000\000\055\000\000\000\000\000\ +\000\000\000\000\000\000\000\000\000\000\055\000\065\000\000\000\ +\000\000\055\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\000\000\055\000\000\000\000\000\055\000\000\000\055\000\055\000\ +\065\000\065\000\065\000\065\000\065\000\065\000\065\000\065\000\ +\065\000\065\000\065\000\065\000\065\000\046\000\046\000\000\000\ +\046\000\000\000\046\000\000\000\046\000\000\000\045\000\045\000\ +\000\000\045\000\000\000\045\000\046\000\045\000\000\000\000\000\ +\046\000\000\000\000\000\000\000\000\000\045\000\000\000\000\000\ +\046\000\045\000\000\000\046\000\000\000\021\000\021\000\000\000\ +\021\000\045\000\021\000\000\000\045\000\000\000\028\000\028\000\ +\000\000\028\000\000\000\028\000\021\000\000\000\000\000\000\000\ +\021\000\000\000\000\000\000\000\000\000\028\000\000\000\000\000\ +\021\000\028\000\000\000\021\000\000\000\000\000\000\000\000\000\ +\000\000\028\000\000\000\000\000\028\000" + +let yycheck = "\030\000\ +\006\001\030\000\006\001\031\000\001\000\007\001\004\001\036\000\ +\131\000\030\000\014\001\004\001\005\001\034\000\010\001\008\001\ +\021\001\008\001\023\001\025\001\022\001\012\001\018\001\146\000\ +\009\001\010\001\054\000\033\001\004\001\022\001\036\001\020\001\ +\008\001\018\001\055\000\026\001\040\001\066\000\069\000\037\001\ +\013\001\034\001\037\001\036\001\009\001\076\000\077\000\078\000\ +\079\000\080\000\081\000\082\000\083\000\074\000\075\000\001\001\ +\002\001\003\001\004\001\005\001\036\001\012\001\008\001\009\001\ +\010\001\038\001\039\001\018\001\009\001\015\001\016\001\017\001\ +\004\001\038\001\039\001\013\001\107\000\108\000\107\000\004\001\ +\001\001\002\001\003\001\004\001\005\001\038\001\039\001\008\001\ +\034\001\010\001\036\001\009\001\020\001\011\001\015\001\016\001\ +\017\001\038\001\039\001\004\001\038\001\039\001\001\001\002\001\ +\003\001\004\001\005\001\128\000\021\001\008\001\141\000\034\001\ +\035\001\034\001\037\001\036\001\015\001\016\001\017\001\007\001\ +\009\001\009\001\011\001\011\001\006\001\007\001\022\001\009\001\ +\010\001\011\001\004\001\013\001\004\001\021\001\014\001\034\001\ +\018\001\036\001\008\001\021\001\022\001\004\001\008\001\025\001\ +\008\001\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ +\034\001\035\001\036\001\037\001\038\001\039\001\006\001\007\001\ +\005\001\009\001\010\001\011\001\004\001\005\001\007\001\007\001\ +\008\001\004\001\018\001\004\001\005\001\021\001\004\001\008\001\ +\004\001\025\001\004\001\027\001\028\001\029\001\030\001\031\001\ +\032\001\033\001\034\001\035\001\036\001\037\001\038\001\039\001\ +\006\001\007\001\034\001\009\001\036\001\011\001\008\001\013\001\ +\008\001\034\001\021\001\036\001\011\001\014\001\004\001\021\001\ +\022\001\009\001\009\001\025\001\009\001\027\001\028\001\029\001\ +\030\001\031\001\032\001\033\001\034\001\035\001\036\001\037\001\ +\038\001\039\001\006\001\007\001\009\001\009\001\009\001\011\001\ +\009\001\013\001\027\001\028\001\029\001\030\001\031\001\032\001\ +\004\001\021\001\022\001\011\001\004\001\025\001\012\001\027\001\ \028\001\029\001\030\001\031\001\032\001\033\001\034\001\035\001\ -\023\001\024\001\025\001\026\001\027\001\028\001\009\001\034\001\ -\035\001\004\001\004\001\034\001\035\001\023\001\024\001\025\001\ -\026\001\027\001\028\001\017\001\023\001\024\001\025\001\026\001\ +\036\001\037\001\038\001\039\001\006\001\007\001\018\001\009\001\ +\021\001\011\001\009\001\013\001\084\000\085\000\086\000\087\000\ +\007\001\007\001\000\000\021\001\022\001\021\001\009\001\025\001\ +\005\000\027\001\028\001\029\001\030\001\031\001\032\001\033\001\ +\009\000\049\000\036\001\019\000\038\001\039\001\006\001\007\001\ +\103\000\009\001\255\255\011\001\255\255\013\001\255\255\255\255\ +\255\255\255\255\255\255\255\255\255\255\021\001\009\001\255\255\ +\255\255\025\001\255\255\255\255\255\255\255\255\255\255\255\255\ +\255\255\033\001\255\255\255\255\036\001\255\255\038\001\039\001\ \027\001\028\001\029\001\030\001\031\001\032\001\033\001\034\001\ -\035\001\029\001\030\001\031\001\032\001\033\001\069\000\070\000\ -\071\000\072\000\012\001\004\001\009\001\009\001\009\001\004\001\ -\004\001\011\001\009\001\000\000\005\000\009\000\045\000" +\035\001\036\001\037\001\038\001\039\001\006\001\007\001\255\255\ +\009\001\255\255\011\001\255\255\013\001\255\255\006\001\007\001\ +\255\255\009\001\255\255\011\001\021\001\013\001\255\255\255\255\ +\025\001\255\255\255\255\255\255\255\255\021\001\255\255\255\255\ +\033\001\025\001\255\255\036\001\255\255\006\001\007\001\255\255\ +\009\001\033\001\011\001\255\255\036\001\255\255\006\001\007\001\ +\255\255\009\001\255\255\011\001\021\001\255\255\255\255\255\255\ +\025\001\255\255\255\255\255\255\255\255\021\001\255\255\255\255\ +\033\001\025\001\255\255\036\001\255\255\255\255\255\255\255\255\ +\255\255\033\001\255\255\255\255\036\001" let yynames_const = "\ CALL_OF\000\ @@ -276,10 +358,11 @@ RPAREN\000\ LSQUARE\000\ RSQUARE\000\ + LBRACELBRACE\000\ + RBRACERBRACE\000\ RARROW\000\ TRUE\000\ FALSE\000\ - FUNC\000\ NOT\000\ DOT\000\ AMP\000\ @@ -287,6 +370,9 @@ SEMI_COLON\000\ COMMA\000\ PIPE\000\ + CARET\000\ + QUESTION\000\ + COLUMNCOLUMN\000\ EQ\000\ LT\000\ GT\000\ @@ -315,18 +401,19 @@ let _1 = (Parsing.peek_val __caml_parser_env 1 : 'options) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'states) in Obj.repr( -# 116 "src/aorai/yaparser.mly" +# 112 "src/aorai/yaparser.mly" ( List.iter (fun(key, ids) -> match key with "init" -> List.iter - (fun id -> try - (Hashtbl.find observed_states id).init <- True - with - Not_found -> - Aorai_option.abort "Error: no state '%s'\n" id) + (fun id -> + try + (Hashtbl.find observed_states id).init <- True + with + Not_found -> + Aorai_option.abort "Error: no state '%s'\n" id) ids | "accept" -> List.iter @@ -334,10 +421,9 @@ (Hashtbl.find observed_states id).acceptation <- True with Not_found -> Aorai_option.abort "no state '%s'\n" id) ids - | oth -> - Aorai_option.abort "unknown option '%s'\n" oth - ) _1 - ; + | "deterministic" -> Aorai_option.Deterministic.set true; + | oth -> Aorai_option.abort "unknown option '%s'\n" oth + ) _1; let states= Hashtbl.fold (fun _ st l -> @@ -349,491 +435,606 @@ st::l) observed_states [] in + (try + Hashtbl.iter + (fun _ st -> if st.init=True then raise Exit) observed_states; + Aorai_option.abort "Automaton does not declare an initial state" + with Exit -> ()); if Hashtbl.length prefetched_states >0 then begin let r = Hashtbl.fold - (fun s n _ -> s^"Error: the state '"^n^"' is used but never defined.\n") + (fun s n _ -> + s^"Error: the state '"^n^"' is used but never defined.\n") prefetched_states "" in Aorai_option.abort "%s" r end; - - Data_for_aorai.setLtl_expressions observed_expressions; - Logic_simplification.setLtl_expressions observed_expressions; - let n=ref 0 in - let (transitions,pcondsl) = Logic_simplification.simplifyTrans _2 in - let conds = Array.make (List.length transitions) [] in - List.iter2 (fun t pc -> t.numt<-(!n); conds.(!n)<-pc; n:=!n+1) transitions pcondsl; - Data_for_aorai.setCondOfParametrizedTransition conds; - - - ((states , transitions),observed_vars,observed_funcs) + (states, _2) ) -# 374 "src/aorai/yaparser.ml" - : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t))) +# 456 "src/aorai/yaparser.ml" + : Promelaast.parsed_automaton)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'options) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'option) in Obj.repr( -# 174 "src/aorai/yaparser.mly" +# 166 "src/aorai/yaparser.mly" ( _1@[_2] ) -# 382 "src/aorai/yaparser.ml" +# 464 "src/aorai/yaparser.ml" : 'options)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'option) in Obj.repr( -# 175 "src/aorai/yaparser.mly" +# 167 "src/aorai/yaparser.mly" ( [_1] ) -# 389 "src/aorai/yaparser.ml" +# 471 "src/aorai/yaparser.ml" : 'options)) ; (fun __caml_parser_env -> - let _2 = (Parsing.peek_val __caml_parser_env 3 : string) in - let _4 = (Parsing.peek_val __caml_parser_env 1 : 'opt_identifiers) in + let _2 = (Parsing.peek_val __caml_parser_env 2 : string) in + let _3 = (Parsing.peek_val __caml_parser_env 1 : 'opt_identifiers) in Obj.repr( -# 179 "src/aorai/yaparser.mly" - ( (_2, _4) ) -# 397 "src/aorai/yaparser.ml" +# 171 "src/aorai/yaparser.mly" + ( (_2, _3) ) +# 479 "src/aorai/yaparser.ml" : 'option)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 2 : 'opt_identifiers) in - let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 183 "src/aorai/yaparser.mly" - ( _1@[_3] ) -# 405 "src/aorai/yaparser.ml" +# 175 "src/aorai/yaparser.mly" + ( [] ) +# 485 "src/aorai/yaparser.ml" + : 'opt_identifiers)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 0 : 'id_list) in + Obj.repr( +# 176 "src/aorai/yaparser.mly" + ( _2 ) +# 492 "src/aorai/yaparser.ml" : 'opt_identifiers)) ; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'id_list) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in + Obj.repr( +# 180 "src/aorai/yaparser.mly" + ( _1@[_3] ) +# 500 "src/aorai/yaparser.ml" + : 'id_list)) +; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 184 "src/aorai/yaparser.mly" - ( [_1] ) -# 412 "src/aorai/yaparser.ml" - : 'opt_identifiers)) +# 181 "src/aorai/yaparser.mly" + ( [_1] ) +# 507 "src/aorai/yaparser.ml" + : 'id_list)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 1 : 'states) in let _2 = (Parsing.peek_val __caml_parser_env 0 : 'state) in Obj.repr( -# 192 "src/aorai/yaparser.mly" +# 185 "src/aorai/yaparser.mly" ( _1@_2 ) -# 420 "src/aorai/yaparser.ml" +# 515 "src/aorai/yaparser.ml" : 'states)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'state) in Obj.repr( -# 193 "src/aorai/yaparser.mly" +# 186 "src/aorai/yaparser.mly" ( _1 ) -# 427 "src/aorai/yaparser.ml" +# 522 "src/aorai/yaparser.ml" : 'states)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : string) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'transitions) in Obj.repr( -# 198 "src/aorai/yaparser.mly" +# 190 "src/aorai/yaparser.mly" ( let start_state = fetch_and_create_state _1 in - let (all_conds, otherwise, transitions) = + let (_, transitions) = List.fold_left - (fun (all_conds, otherwise, transitions) (cross,stop_state) -> - match otherwise, cross with - None, Pred cross -> - (POr (cross, all_conds), otherwise, - { start=start_state; stop=stop_state; - cross=cross; numt=(-1) }::transitions) - | None, Otherwise -> - let trans = { start=start_state; stop=stop_state; - cross = PFalse; numt= (-1) } - in - (all_conds, Some trans, trans::transitions) - | Some _, _ -> - Aorai_option.abort - "'other' directive in definition of %s \ - transitions is not the last one" start_state.name) - (PFalse,None,[]) _3 + (fun (otherwise, transitions) (cross,stop_state) -> + if otherwise then + Aorai_option.abort + "'other' directive in definition of %s \ + transitions is not the last one" start_state.name + else begin + let trans = + { start=start_state; stop=stop_state; + cross=cross; numt=(-1) }::transitions + in + let otherwise = + match cross with + | Otherwise -> true + | Seq _ -> false + in otherwise, trans + end) + (false,[]) _3 in - match otherwise with - None -> List.rev transitions - | Some trans -> - List.rev - ({trans with cross = PNot all_conds} :: - (List.filter (fun x -> x != trans) transitions)) + List.rev transitions ) -# 462 "src/aorai/yaparser.ml" +# 553 "src/aorai/yaparser.ml" : 'state)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'transitions) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'transition) in Obj.repr( -# 230 "src/aorai/yaparser.mly" +# 216 "src/aorai/yaparser.mly" ( _1@[_3] ) -# 470 "src/aorai/yaparser.ml" +# 561 "src/aorai/yaparser.ml" : 'transitions)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'transition) in Obj.repr( -# 231 "src/aorai/yaparser.mly" +# 217 "src/aorai/yaparser.mly" ( [_1] ) -# 477 "src/aorai/yaparser.ml" +# 568 "src/aorai/yaparser.ml" : 'transitions)) ; (fun __caml_parser_env -> - let _2 = (Parsing.peek_val __caml_parser_env 3 : 'guard) in + let _2 = (Parsing.peek_val __caml_parser_env 3 : 'seq_elt) in let _5 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 236 "src/aorai/yaparser.mly" - ( (Pred _2, prefetch_and_create_state _5) ) -# 485 "src/aorai/yaparser.ml" +# 223 "src/aorai/yaparser.mly" + ( (Seq _2, prefetch_and_create_state _5) ) +# 576 "src/aorai/yaparser.ml" : 'transition)) ; (fun __caml_parser_env -> let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 237 "src/aorai/yaparser.mly" +# 224 "src/aorai/yaparser.mly" ((Otherwise, prefetch_and_create_state _3) ) -# 492 "src/aorai/yaparser.ml" +# 583 "src/aorai/yaparser.ml" : 'transition)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 238 "src/aorai/yaparser.mly" - ( (Pred PTrue, prefetch_and_create_state _2) ) -# 499 "src/aorai/yaparser.ml" +# 225 "src/aorai/yaparser.mly" + ( (Seq (to_seq PTrue), prefetch_and_create_state _2) ) +# 590 "src/aorai/yaparser.ml" : 'transition)) ; (fun __caml_parser_env -> - let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in + let _1 = (Parsing.peek_val __caml_parser_env 0 : 'seq_elt) in Obj.repr( -# 245 "src/aorai/yaparser.mly" - ( if not (Hashtbl.mem observed_funcs _3) then Hashtbl.add observed_funcs _3 _3 ; PCallOrReturn _3 ) -# 506 "src/aorai/yaparser.ml" - : 'guard)) +# 229 "src/aorai/yaparser.mly" + ( _1 ) +# 597 "src/aorai/yaparser.ml" + : 'non_empty_seq)) ; (fun __caml_parser_env -> - let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'seq_elt) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : 'seq) in Obj.repr( -# 247 "src/aorai/yaparser.mly" - ( if not (Hashtbl.mem observed_funcs _3) then Hashtbl.add observed_funcs _3 _3 ; PCall _3 ) -# 513 "src/aorai/yaparser.ml" - : 'guard)) +# 230 "src/aorai/yaparser.mly" + ( _1 @ _3 ) +# 605 "src/aorai/yaparser.ml" + : 'non_empty_seq)) ; (fun __caml_parser_env -> - let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in Obj.repr( -# 249 "src/aorai/yaparser.mly" - ( if not (Hashtbl.mem observed_funcs _3) then Hashtbl.add observed_funcs _3 _3 ; PReturn _3 ) -# 520 "src/aorai/yaparser.ml" - : 'guard)) +# 234 "src/aorai/yaparser.mly" + ( [] ) +# 611 "src/aorai/yaparser.ml" + : 'seq)) ; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 0 : 'non_empty_seq) in Obj.repr( -# 251 "src/aorai/yaparser.mly" - ( PTrue ) -# 526 "src/aorai/yaparser.ml" +# 235 "src/aorai/yaparser.mly" + ( _1 ) +# 618 "src/aorai/yaparser.ml" + : 'seq)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 0 : 'single_cond) in + Obj.repr( +# 239 "src/aorai/yaparser.mly" + ( to_seq _1 ) +# 625 "src/aorai/yaparser.ml" : 'guard)) ; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 1 : 'non_empty_seq) in Obj.repr( -# 253 "src/aorai/yaparser.mly" - ( PFalse ) -# 532 "src/aorai/yaparser.ml" +# 240 "src/aorai/yaparser.mly" + ( _2 ) +# 632 "src/aorai/yaparser.ml" + : 'guard)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 5 : string) in + let _2 = (Parsing.peek_val __caml_parser_env 4 : 'pre_cond) in + let _4 = (Parsing.peek_val __caml_parser_env 2 : 'seq) in + let _6 = (Parsing.peek_val __caml_parser_env 0 : 'post_cond) in + Obj.repr( +# 242 "src/aorai/yaparser.mly" + ( let pre_cond = + match _2 with + | Behavior b -> PCall(_1,Some b) + | Pre c -> PAnd (PCall(_1,None), c) + in + let post_cond = + match _6 with + | None -> PReturn _1 + | Some c -> PAnd (PReturn _1,c) + in + (to_seq pre_cond) @ _4 @ to_seq post_cond + ) +# 653 "src/aorai/yaparser.ml" : 'guard)) ; (fun __caml_parser_env -> - let _2 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in + let _1 = (Parsing.peek_val __caml_parser_env 4 : string) in + let _3 = (Parsing.peek_val __caml_parser_env 2 : 'non_empty_seq) in + let _5 = (Parsing.peek_val __caml_parser_env 0 : 'post_cond) in Obj.repr( # 255 "src/aorai/yaparser.mly" - ( PNot _2 ) -# 539 "src/aorai/yaparser.ml" + ( let post_cond = + match _5 with + | None -> PReturn _1 + | Some c -> PAnd (PReturn _1,c) + in + (to_seq (PCall (_1, None))) @ _3 @ to_seq post_cond + ) +# 668 "src/aorai/yaparser.ml" : 'guard)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 2 : 'guard) in - let _3 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in + let _1 = (Parsing.peek_val __caml_parser_env 3 : string) in + let _4 = (Parsing.peek_val __caml_parser_env 0 : 'post_cond) in Obj.repr( -# 257 "src/aorai/yaparser.mly" - ( PAnd (_1,_3) ) -# 547 "src/aorai/yaparser.ml" +# 263 "src/aorai/yaparser.mly" + ( let post_cond = + match _4 with + | None -> PReturn _1 + | Some c -> PAnd (PReturn _1,c) + in + (to_seq (PCall (_1, None))) @ to_seq post_cond + ) +# 682 "src/aorai/yaparser.ml" : 'guard)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 2 : 'guard) in - let _3 = (Parsing.peek_val __caml_parser_env 0 : 'guard) in + let _2 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 259 "src/aorai/yaparser.mly" - ( POr (_1,_3) ) -# 555 "src/aorai/yaparser.ml" - : 'guard)) +# 273 "src/aorai/yaparser.mly" + ( Behavior _2 ) +# 689 "src/aorai/yaparser.ml" + : 'pre_cond)) ; (fun __caml_parser_env -> - let _2 = (Parsing.peek_val __caml_parser_env 1 : 'guard) in + let _2 = (Parsing.peek_val __caml_parser_env 1 : 'single_cond) in Obj.repr( -# 261 "src/aorai/yaparser.mly" - ( _2 ) -# 562 "src/aorai/yaparser.ml" - : 'guard)) +# 274 "src/aorai/yaparser.mly" + ( Pre _2 ) +# 696 "src/aorai/yaparser.ml" + : 'pre_cond)) +; (fun __caml_parser_env -> + Obj.repr( +# 278 "src/aorai/yaparser.mly" + ( None ) +# 702 "src/aorai/yaparser.ml" + : 'post_cond)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 1 : 'single_cond) in + Obj.repr( +# 279 "src/aorai/yaparser.mly" + ( Some _2 ) +# 709 "src/aorai/yaparser.ml" + : 'post_cond)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 1 : 'guard) in + let _2 = (Parsing.peek_val __caml_parser_env 0 : 'repetition) in + Obj.repr( +# 283 "src/aorai/yaparser.mly" + ( + let min, max = _2 in + match _1 with + | [ s ] when Data_for_aorai.is_single s -> + [ { s with min_rep = min; max_rep = max } ] + | l -> + if is_no_repet (min,max) then + l (* [ a; [b;c]; d] is equivalent to [a;b;c;d] *) + else [ { condition = None; nested = l; min_rep = min; max_rep = max } ] + ) +# 726 "src/aorai/yaparser.ml" + : 'seq_elt)) +; (fun __caml_parser_env -> + Obj.repr( +# 297 "src/aorai/yaparser.mly" + ( Some Data_for_aorai.cst_one, Some Data_for_aorai.cst_one ) +# 732 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + Obj.repr( +# 298 "src/aorai/yaparser.mly" + ( Some Data_for_aorai.cst_one, None) +# 738 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + Obj.repr( +# 299 "src/aorai/yaparser.mly" + ( None, None ) +# 744 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + Obj.repr( +# 300 "src/aorai/yaparser.mly" + ( None, Some Data_for_aorai.cst_one ) +# 750 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 3 : 'arith_relation) in + let _4 = (Parsing.peek_val __caml_parser_env 1 : 'arith_relation) in + Obj.repr( +# 301 "src/aorai/yaparser.mly" + ( Some _2, Some _4 ) +# 758 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 1 : 'arith_relation) in + Obj.repr( +# 302 "src/aorai/yaparser.mly" + ( Some _2, Some _2 ) +# 765 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in + Obj.repr( +# 303 "src/aorai/yaparser.mly" + ( Some _2, None ) +# 772 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + let _3 = (Parsing.peek_val __caml_parser_env 1 : 'arith_relation) in + Obj.repr( +# 304 "src/aorai/yaparser.mly" + ( None, Some _3 ) +# 779 "src/aorai/yaparser.ml" + : 'repetition)) +; (fun __caml_parser_env -> + let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in + Obj.repr( +# 308 "src/aorai/yaparser.mly" + ( POr (PCall (_3,None), PReturn _3) ) +# 786 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in + Obj.repr( +# 309 "src/aorai/yaparser.mly" + ( PCall (_3,None) ) +# 793 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + let _3 = (Parsing.peek_val __caml_parser_env 1 : string) in + Obj.repr( +# 310 "src/aorai/yaparser.mly" + ( PReturn _3 ) +# 800 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + Obj.repr( +# 311 "src/aorai/yaparser.mly" + ( PTrue ) +# 806 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + Obj.repr( +# 312 "src/aorai/yaparser.mly" + ( PFalse ) +# 812 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 0 : 'single_cond) in + Obj.repr( +# 313 "src/aorai/yaparser.mly" + ( PNot _2 ) +# 819 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'single_cond) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : 'single_cond) in + Obj.repr( +# 314 "src/aorai/yaparser.mly" + ( PAnd (_1,_3) ) +# 827 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + let _1 = (Parsing.peek_val __caml_parser_env 2 : 'single_cond) in + let _3 = (Parsing.peek_val __caml_parser_env 0 : 'single_cond) in + Obj.repr( +# 315 "src/aorai/yaparser.mly" + ( POr (_1,_3) ) +# 835 "src/aorai/yaparser.ml" + : 'single_cond)) +; (fun __caml_parser_env -> + let _2 = (Parsing.peek_val __caml_parser_env 1 : 'single_cond) in + Obj.repr( +# 316 "src/aorai/yaparser.mly" + ( _2 ) +# 842 "src/aorai/yaparser.ml" + : 'single_cond)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'logic_relation) in Obj.repr( -# 263 "src/aorai/yaparser.mly" - ( - - let id = get_fresh_ident () in - let (pred,exp) = _1 in - Hashtbl.add observed_expressions id - (exp, (Pretty_utils.sfprintf "%a" Cil.d_exp exp), pred); - (*Ltlast.LIdent(id)*) - - Hashtbl.add observed_vars id id ; - - let res = - match !observed_expr_is_param with - | Only_vars -> PIndexedExp id - | Func_param (f,l) -> PFuncParam (id,f,l) - | Func_ret f -> PFuncReturn (id,f) - in - - (* On repositionne la variable a son status par defaut pour la prochaine logic_relation *) - observed_expr_is_param := Only_vars; (* DEVRAIT ETRE FAIT AVANT LOGIC_RELATION!!!! *) - - res - ) -# 590 "src/aorai/yaparser.ml" - : 'guard)) +# 317 "src/aorai/yaparser.mly" + ( _1 ) +# 849 "src/aorai/yaparser.ml" + : 'single_cond)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 292 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Req, Logic_utils.expr_to_term ~cast:true _1, - Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Eq, _1 , _3 , Cil.intType)) ) ) -# 601 "src/aorai/yaparser.ml" +# 321 "src/aorai/yaparser.mly" + ( PRel(Eq, _1, _3) ) +# 857 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 296 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Rlt, Logic_utils.expr_to_term ~cast:true _1, - Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Lt, _1 , _3 , Cil.intType)) ) ) -# 612 "src/aorai/yaparser.ml" +# 322 "src/aorai/yaparser.mly" + ( PRel(Lt, _1, _3) ) +# 865 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 300 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Rgt, Logic_utils.expr_to_term ~cast:true _1, - Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Gt, _1 , _3 , Cil.intType)) ) ) -# 623 "src/aorai/yaparser.ml" +# 323 "src/aorai/yaparser.mly" + ( PRel(Gt, _1, _3) ) +# 873 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 304 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Rle, Logic_utils.expr_to_term ~cast:true _1, - Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Le, _1 , _3 , Cil.intType)) ) ) -# 634 "src/aorai/yaparser.ml" +# 324 "src/aorai/yaparser.mly" + ( PRel(Le, _1, _3) ) +# 881 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 308 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Rge, Logic_utils.expr_to_term ~cast:true _1, - Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Ge, _1 , _3 , Cil.intType) )) ) -# 645 "src/aorai/yaparser.ml" +# 325 "src/aorai/yaparser.mly" + ( PRel(Ge, _1, _3) ) +# 889 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 312 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true _1, - Logic_utils.expr_to_term ~cast:true _3), - new_exp(Cil_types.BinOp(Cil_types.Ne, _1 , _3 , Cil.intType) )) ) -# 656 "src/aorai/yaparser.ml" +# 326 "src/aorai/yaparser.mly" + ( PRel(Neq, _1, _3) ) +# 897 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 316 "src/aorai/yaparser.mly" - ( - ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true _1, - Logic_const.term(Cil_types.TConst(Cil_types.CInt64(Int64.of_int 0,Cil_types.IInt,Some("0")))) - (Cil_types.Ctype Cil.intType)), _1) ) -# 666 "src/aorai/yaparser.ml" +# 327 "src/aorai/yaparser.mly" + ( PRel (Neq, _1, PCst(IntConstant "0")) ) +# 904 "src/aorai/yaparser.ml" : 'logic_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 324 "src/aorai/yaparser.mly" - ( - new_exp (Cil_types.BinOp(Cil_types.PlusA, _1 , _3 , Cil.intType)) ) -# 675 "src/aorai/yaparser.ml" +# 331 "src/aorai/yaparser.mly" + ( PBinop(Badd,_1,_3) ) +# 912 "src/aorai/yaparser.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation) in Obj.repr( -# 326 "src/aorai/yaparser.mly" - ( - new_exp (Cil_types.BinOp(Cil_types.MinusA, _1 , _3 , Cil.intType)) ) -# 684 "src/aorai/yaparser.ml" +# 332 "src/aorai/yaparser.mly" + ( PBinop(Bsub,_1,_3) ) +# 920 "src/aorai/yaparser.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'arith_relation_mul) in Obj.repr( -# 328 "src/aorai/yaparser.mly" - ( _1 ) -# 691 "src/aorai/yaparser.ml" +# 333 "src/aorai/yaparser.mly" + ( _1 ) +# 927 "src/aorai/yaparser.ml" : 'arith_relation)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 333 "src/aorai/yaparser.mly" - ( - new_exp (Cil_types.BinOp(Cil_types.Div, _1 , _3 , Cil.intType)) ) -# 700 "src/aorai/yaparser.ml" +# 337 "src/aorai/yaparser.mly" + ( PBinop(Bdiv,_1,_3) ) +# 935 "src/aorai/yaparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 335 "src/aorai/yaparser.mly" - ( - new_exp (Cil_types.BinOp(Cil_types.Mult, _1 , _3 , Cil.intType)) ) -# 709 "src/aorai/yaparser.ml" +# 338 "src/aorai/yaparser.mly" + ( PBinop(Bmul, _1, _3) ) +# 943 "src/aorai/yaparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'arith_relation_mul) in let _3 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 337 "src/aorai/yaparser.mly" - ( - new_exp (Cil_types.BinOp(Cil_types.Mod, _1 , _3 , Cil.intType)) ) -# 718 "src/aorai/yaparser.ml" +# 339 "src/aorai/yaparser.mly" + ( PBinop(Bmod, _1, _3) ) +# 951 "src/aorai/yaparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_or_const) in Obj.repr( -# 339 "src/aorai/yaparser.mly" +# 340 "src/aorai/yaparser.mly" ( _1 ) -# 725 "src/aorai/yaparser.ml" +# 958 "src/aorai/yaparser.ml" : 'arith_relation_mul)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( # 345 "src/aorai/yaparser.mly" - ( new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string _1,Cil_types.IInt, Some(_1))))) -# 732 "src/aorai/yaparser.ml" + ( PCst (IntConstant _1) ) +# 965 "src/aorai/yaparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 347 "src/aorai/yaparser.mly" - ( new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string ("-"^_2),Cil_types.IInt, Some("-"^_2))))) -# 739 "src/aorai/yaparser.ml" +# 346 "src/aorai/yaparser.mly" + ( PUnop (Uminus, PCst (IntConstant _2)) ) +# 972 "src/aorai/yaparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 349 "src/aorai/yaparser.mly" - ( new_exp (Cil_types.Lval(_1)) ) -# 746 "src/aorai/yaparser.ml" +# 347 "src/aorai/yaparser.mly" + ( _1 ) +# 979 "src/aorai/yaparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'arith_relation) in Obj.repr( -# 351 "src/aorai/yaparser.mly" - ( _2 ) -# 753 "src/aorai/yaparser.ml" +# 348 "src/aorai/yaparser.mly" + ( _2 ) +# 986 "src/aorai/yaparser.ml" : 'access_or_const)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 2 : 'access) in let _3 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 359 "src/aorai/yaparser.mly" - ( - - let (my_host,my_offset) = (_1) in - - let new_offset = Utils_parser.add_offset my_offset (Utils_parser.get_new_offset my_host my_offset _3) in - (my_host,new_offset) - ) -# 767 "src/aorai/yaparser.ml" +# 353 "src/aorai/yaparser.mly" + ( PField(_1,_3) ) +# 994 "src/aorai/yaparser.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 3 : 'access) in let _3 = (Parsing.peek_val __caml_parser_env 1 : 'access_or_const) in Obj.repr( -# 368 "src/aorai/yaparser.mly" - ( Cil.addOffsetLval (Cil_types.Index (_3,Cil_types.NoOffset)) _1) -# 775 "src/aorai/yaparser.ml" +# 354 "src/aorai/yaparser.mly" + ( PArrget(_1,_3) ) +# 1002 "src/aorai/yaparser.ml" : 'access)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : 'access_leaf) in Obj.repr( -# 369 "src/aorai/yaparser.mly" +# 355 "src/aorai/yaparser.mly" (_1) -# 782 "src/aorai/yaparser.ml" +# 1009 "src/aorai/yaparser.ml" : 'access)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 0 : 'access) in Obj.repr( -# 374 "src/aorai/yaparser.mly" - ( Aorai_option.fatal "NOT YET IMPLEMENTED : *A dereferencement access." ) -# 789 "src/aorai/yaparser.ml" +# 359 "src/aorai/yaparser.mly" + ( PUnop (Ustar,_2) ) +# 1016 "src/aorai/yaparser.ml" : 'access_leaf)) ; (fun __caml_parser_env -> - let _1 = (Parsing.peek_val __caml_parser_env 3 : string) in - let _4 = (Parsing.peek_val __caml_parser_env 0 : string) in + let _1 = (Parsing.peek_val __caml_parser_env 4 : string) in + let _5 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 376 "src/aorai/yaparser.mly" - ( - if(String.compare _4 "return")=0 then - begin - if not (!observed_expr_is_param=Only_vars) then - Aorai_option.abort "An expression can not contain at same time a reference of a returned value and itself or a reference to a param"; - - observed_expr_is_param := Func_ret _1; - Cil.var ( Data_for_aorai.get_returninfo _1) - end - else - begin - match !observed_expr_is_param with - | Func_ret _ -> - Aorai_option.abort "An expression can not contain both a reference of a returned value and another reference to itself or a reference to a param"; - - | Func_param (f,_) when not (f=_1) -> - Aorai_option.abort "An expression can not contain both references two different called functions."; - - | Only_vars -> - observed_expr_is_param:=Func_param (_1,[_4]); - Cil.var ( Data_for_aorai.get_paraminfo _1 _4) - - | Func_param (_,l) -> - observed_expr_is_param:=Func_param (_1,_4::l); - Cil.var ( Data_for_aorai.get_paraminfo _1 _4) - end - ) -# 823 "src/aorai/yaparser.ml" +# 360 "src/aorai/yaparser.mly" + ( PPrm(_1,_5) ) +# 1024 "src/aorai/yaparser.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _1 = (Parsing.peek_val __caml_parser_env 0 : string) in Obj.repr( -# 404 "src/aorai/yaparser.mly" - ( Cil.var ( Data_for_aorai.get_varinfo _1) ) -# 830 "src/aorai/yaparser.ml" +# 361 "src/aorai/yaparser.mly" + ( PVar _1 ) +# 1031 "src/aorai/yaparser.ml" : 'access_leaf)) ; (fun __caml_parser_env -> let _2 = (Parsing.peek_val __caml_parser_env 1 : 'access) in Obj.repr( -# 406 "src/aorai/yaparser.mly" - ( _2 ) -# 837 "src/aorai/yaparser.ml" +# 362 "src/aorai/yaparser.mly" + ( _2 ) +# 1038 "src/aorai/yaparser.ml" : 'access_leaf)) (* Entry main *) ; (fun __caml_parser_env -> raise (Parsing.YYexit (Parsing.peek_val __caml_parser_env 0))) @@ -856,4 +1057,4 @@ Parsing.names_const=yynames_const; Parsing.names_block=yynames_block } let main (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) = - (Parsing.yyparse yytables 1 lexfun lexbuf : (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t)) + (Parsing.yyparse yytables 1 lexfun lexbuf : Promelaast.parsed_automaton) diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/yaparser.mli frama-c-20111001+nitrogen+dfsg/src/aorai/yaparser.mli --- frama-c-20110201+carbon+dfsg/src/aorai/yaparser.mli 2011-02-07 14:02:24.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/yaparser.mli 2011-10-10 08:48:50.000000000 +0000 @@ -10,10 +10,11 @@ | RPAREN | LSQUARE | RSQUARE + | LBRACELBRACE + | RBRACERBRACE | RARROW | TRUE | FALSE - | FUNC | NOT | DOT | AMP @@ -21,6 +22,9 @@ | SEMI_COLON | COMMA | PIPE + | CARET + | QUESTION + | COLUMNCOLUMN | EQ | LT | GT @@ -38,4 +42,4 @@ | EOF val main : - (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t) + (Lexing.lexbuf -> token) -> Lexing.lexbuf -> Promelaast.parsed_automaton diff -Nru frama-c-20110201+carbon+dfsg/src/aorai/yaparser.mly frama-c-20111001+nitrogen+dfsg/src/aorai/yaparser.mly --- frama-c-20110201+carbon+dfsg/src/aorai/yaparser.mly 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/aorai/yaparser.mly 2011-10-10 08:38:23.000000000 +0000 @@ -1,11 +1,13 @@ /**************************************************************************/ /* */ -/* This file is part of Frama-C. */ +/* This file is part of Aorai plug-in of Frama-C. */ /* */ /* Copyright (C) 2007-2011 */ -/* INSA (Institut National des Sciences Appliquees) */ +/* CEA (Commissariat a l'énergie atomique et aux énergies */ +/* alternatives) */ /* INRIA (Institut National de Recherche en Informatique et en */ /* Automatique) */ +/* INSA (Institut National des Sciences Appliquees) */ /* */ /* you can redistribute it and/or modify it under the terms of the GNU */ /* Lesser General Public License as published by the Free Software */ @@ -25,26 +27,25 @@ /* Originated from http://www.ltl2dstar.de/down/ltl2dstar-0.4.2.zip */ %{ +open Logic_ptree open Parsing open Promelaast open Bool3 open Format -type trans = Pred of Promelaast.condition | Otherwise +let to_seq c = + [{ condition = Some c; + nested = []; + min_rep = Some Data_for_aorai.cst_one; + max_rep = Some Data_for_aorai.cst_one; + }] + +let is_no_repet (min,max) = + let is_one c = Extlib.may_map Data_for_aorai.is_cst_one ~dft:false c in + is_one min && is_one max let observed_states = Hashtbl.create 1 let prefetched_states = Hashtbl.create 1 -let observed_vars = Hashtbl.create 1 -let observed_funcs = Hashtbl.create 1 -let observed_expressions = Hashtbl.create 97 - -(* Current observed expr contains : *) -type observed_expr = Func_ret of string (* func name : a return of the given func *) - | Func_param of string * (string list) (* Func name * param : a call with given param *) - | Only_vars (* Only constants and variables *) - -let observed_expr_is_param = ref Only_vars - let ident_count=ref 0 let get_fresh_ident () = @@ -52,23 +53,20 @@ ("buchfreshident"^(string_of_int !ident_count)) ;; - - let fetch_and_create_state name = Hashtbl.remove prefetched_states name ; try Hashtbl.find observed_states name with - Not_found -> - let s={ name=name; - acceptation=False; init=False; - nums=(Hashtbl.length observed_states) } in - Hashtbl.add observed_states name s; - s + Not_found -> + let s = Data_for_aorai.new_state name in + Hashtbl.add observed_states name s; s ;; let prefetch_and_create_state name = - if (Hashtbl.mem prefetched_states name) or not (Hashtbl.mem observed_states name) then + if (Hashtbl.mem prefetched_states name) or + not (Hashtbl.mem observed_states name) + then begin let s= fetch_and_create_state name in Hashtbl.add prefetched_states name name; @@ -78,40 +76,38 @@ (fetch_and_create_state name) ;; -(*TODO: give a proper loc*) -let new_exp = Cil.new_exp ~loc:(Cil.CurrentLoc.get()) +type pre_cond = Behavior of string | Pre of Promelaast.condition %} - - %token CALL_OF RETURN_OF CALLORRETURN_OF %token IDENTIFIER %token INT -%token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE +%token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE LBRACELBRACE RBRACERBRACE %token RARROW %token TRUE FALSE -%token FUNC %token NOT DOT AMP -%token COLON SEMI_COLON COMMA PIPE +%token COLON SEMI_COLON COMMA PIPE CARET QUESTION COMMA COLUMNCOLUMN %token EQ LT GT LE GE NEQ PLUS MINUS SLASH STAR PERCENT OR AND %token OTHERWISE %token EOF - +%nonassoc highest %left LPAREN RPAREN +%left LCURLY %right EQ LT GT LE GE NEQ PLUS MINUS SLASH STAR PERCENT OR AND /* [VP] priorities taken from cparser.mly */ %left LSQUARE RSQUARE %left DOT %nonassoc NOT TRUE FALSE +%nonassoc QUESTION +%right SEMICOLON +%nonassoc lowest - -%type <(Promelaast.buchautomata * (string, string) Hashtbl.t * (string, string) Hashtbl.t)> main +%type main %start main %% - main : options states { List.iter @@ -119,11 +115,12 @@ match key with "init" -> List.iter - (fun id -> try - (Hashtbl.find observed_states id).init <- True - with - Not_found -> - Aorai_option.abort "Error: no state '%s'\n" id) + (fun id -> + try + (Hashtbl.find observed_states id).init <- True + with + Not_found -> + Aorai_option.abort "Error: no state '%s'\n" id) ids | "accept" -> List.iter @@ -131,10 +128,9 @@ (Hashtbl.find observed_states id).acceptation <- True with Not_found -> Aorai_option.abort "no state '%s'\n" id) ids - | oth -> - Aorai_option.abort "unknown option '%s'\n" oth - ) $1 - ; + | "deterministic" -> Aorai_option.Deterministic.set true; + | oth -> Aorai_option.abort "unknown option '%s'\n" oth + ) $1; let states= Hashtbl.fold (fun _ st l -> @@ -146,26 +142,22 @@ st::l) observed_states [] in + (try + Hashtbl.iter + (fun _ st -> if st.init=True then raise Exit) observed_states; + Aorai_option.abort "Automaton does not declare an initial state" + with Exit -> ()); if Hashtbl.length prefetched_states >0 then begin let r = Hashtbl.fold - (fun s n _ -> s^"Error: the state '"^n^"' is used but never defined.\n") + (fun s n _ -> + s^"Error: the state '"^n^"' is used but never defined.\n") prefetched_states "" in Aorai_option.abort "%s" r end; - - Data_for_aorai.setLtl_expressions observed_expressions; - Logic_simplification.setLtl_expressions observed_expressions; - let n=ref 0 in - let (transitions,pcondsl) = Logic_simplification.simplifyTrans $2 in - let conds = Array.make (List.length transitions) [] in - List.iter2 (fun t pc -> t.numt<-(!n); conds.(!n)<-pc; n:=!n+1) transitions pcondsl; - Data_for_aorai.setCondOfParametrizedTransition conds; - - - ((states , transitions),observed_vars,observed_funcs) + (states, $2) } ; @@ -176,55 +168,49 @@ ; option - : PERCENT IDENTIFIER COLON opt_identifiers SEMI_COLON { ($2, $4) } + : PERCENT IDENTIFIER opt_identifiers SEMI_COLON { ($2, $3) } ; opt_identifiers - : opt_identifiers COMMA IDENTIFIER { $1@[$3] } - | IDENTIFIER { [$1] } + : /* empty */ { [] } + | COLON id_list { $2 } ; - - - +id_list + : id_list COMMA IDENTIFIER { $1@[$3] } + | IDENTIFIER { [$1] } + ; states : states state { $1@$2 } | state { $1 } ; - state : IDENTIFIER COLON transitions SEMI_COLON { let start_state = fetch_and_create_state $1 in - let (all_conds, otherwise, transitions) = + let (_, transitions) = List.fold_left - (fun (all_conds, otherwise, transitions) (cross,stop_state) -> - match otherwise, cross with - None, Pred cross -> - (POr (cross, all_conds), otherwise, - { start=start_state; stop=stop_state; - cross=cross; numt=(-1) }::transitions) - | None, Otherwise -> - let trans = { start=start_state; stop=stop_state; - cross = PFalse; numt= (-1) } - in - (all_conds, Some trans, trans::transitions) - | Some _, _ -> - Aorai_option.abort - "'other' directive in definition of %s \ - transitions is not the last one" start_state.name) - (PFalse,None,[]) $3 + (fun (otherwise, transitions) (cross,stop_state) -> + if otherwise then + Aorai_option.abort + "'other' directive in definition of %s \ + transitions is not the last one" start_state.name + else begin + let trans = + { start=start_state; stop=stop_state; + cross=cross; numt=(-1) }::transitions + in + let otherwise = + match cross with + | Otherwise -> true + | Seq _ -> false + in otherwise, trans + end) + (false,[]) $3 in - match otherwise with - None -> List.rev transitions - | Some trans -> - List.rev - ({trans with cross = PNot all_conds} :: - (List.filter (fun x -> x != trans) transitions)) + List.rev transitions } - ; - transitions /*=> [transition; ...] */ : transitions PIPE transition { $1@[$3] } @@ -232,177 +218,146 @@ ; -transition /*=> (guard, state) */ - : LCURLY guard RCURLY RARROW IDENTIFIER { (Pred $2, prefetch_and_create_state $5) } +transition: /*=> (guard, state) */ + | LCURLY seq_elt RCURLY RARROW IDENTIFIER + { (Seq $2, prefetch_and_create_state $5) } | OTHERWISE RARROW IDENTIFIER {(Otherwise, prefetch_and_create_state $3) } - | RARROW IDENTIFIER { (Pred PTrue, prefetch_and_create_state $2) } + | RARROW IDENTIFIER { (Seq (to_seq PTrue), prefetch_and_create_state $2) } ; +non_empty_seq: + | seq_elt { $1 } + | seq_elt SEMI_COLON seq { $1 @ $3 } +; + +seq: + | /* epsilon */ { [] } + | non_empty_seq { $1 } +; + +guard: + | single_cond { to_seq $1 } + | LSQUARE non_empty_seq RSQUARE { $2 } + | IDENTIFIER pre_cond LPAREN seq RPAREN post_cond + { let pre_cond = + match $2 with + | Behavior b -> PCall($1,Some b) + | Pre c -> PAnd (PCall($1,None), c) + in + let post_cond = + match $6 with + | None -> PReturn $1 + | Some c -> PAnd (PReturn $1,c) + in + (to_seq pre_cond) @ $4 @ to_seq post_cond + } + | IDENTIFIER LPAREN non_empty_seq RPAREN post_cond + { let post_cond = + match $5 with + | None -> PReturn $1 + | Some c -> PAnd (PReturn $1,c) + in + (to_seq (PCall ($1, None))) @ $3 @ to_seq post_cond + } + | IDENTIFIER LPAREN RPAREN post_cond + { let post_cond = + match $4 with + | None -> PReturn $1 + | Some c -> PAnd (PReturn $1,c) + in + (to_seq (PCall ($1, None))) @ to_seq post_cond + } +; + +pre_cond: + | COLUMNCOLUMN IDENTIFIER { Behavior $2 } + | LBRACELBRACE single_cond RBRACERBRACE { Pre $2 } +; + +post_cond: + | /* epsilon */ { None } + | LBRACELBRACE single_cond RBRACERBRACE { Some $2 } +; + +seq_elt: + | guard repetition { + let min, max = $2 in + match $1 with + | [ s ] when Data_for_aorai.is_single s -> + [ { s with min_rep = min; max_rep = max } ] + | l -> + if is_no_repet (min,max) then + l (* [ a; [b;c]; d] is equivalent to [a;b;c;d] *) + else [ { condition = None; nested = l; min_rep = min; max_rep = max } ] + } +; +repetition: + | /* empty */ %prec lowest + { Some Data_for_aorai.cst_one, Some Data_for_aorai.cst_one } + | PLUS { Some Data_for_aorai.cst_one, None} + | STAR { None, None } + | QUESTION { None, Some Data_for_aorai.cst_one } + | LCURLY arith_relation COMMA arith_relation RCURLY { Some $2, Some $4 } + | LCURLY arith_relation RCURLY { Some $2, Some $2 } + | LCURLY arith_relation COMMA RCURLY { Some $2, None } + | LCURLY COMMA arith_relation RCURLY { None, Some $3 } + +single_cond: + | CALLORRETURN_OF LPAREN IDENTIFIER RPAREN + { POr (PCall ($3,None), PReturn $3) } + | CALL_OF LPAREN IDENTIFIER RPAREN { PCall ($3,None) } + | RETURN_OF LPAREN IDENTIFIER RPAREN { PReturn $3 } + | TRUE { PTrue } + | FALSE { PFalse } + | NOT single_cond { PNot $2 } + | single_cond AND single_cond { PAnd ($1,$3) } + | single_cond OR single_cond { POr ($1,$3) } + | LPAREN single_cond RPAREN { $2 } + | logic_relation { $1 } +; -guard - : CALLORRETURN_OF LPAREN IDENTIFIER RPAREN - { if not (Hashtbl.mem observed_funcs $3) then Hashtbl.add observed_funcs $3 $3 ; PCallOrReturn $3 } - | CALL_OF LPAREN IDENTIFIER RPAREN - { if not (Hashtbl.mem observed_funcs $3) then Hashtbl.add observed_funcs $3 $3 ; PCall $3 } - | RETURN_OF LPAREN IDENTIFIER RPAREN - { if not (Hashtbl.mem observed_funcs $3) then Hashtbl.add observed_funcs $3 $3 ; PReturn $3 } - | TRUE - { PTrue } - | FALSE - { PFalse } - | NOT guard - { PNot $2 } - | guard AND guard - { PAnd ($1,$3) } - | guard OR guard - { POr ($1,$3) } - | LPAREN guard RPAREN - { $2 } - | logic_relation - { - - let id = get_fresh_ident () in - let (pred,exp) = $1 in - Hashtbl.add observed_expressions id - (exp, (Pretty_utils.sfprintf "%a" Cil.d_exp exp), pred); - (*Ltlast.LIdent(id)*) - - Hashtbl.add observed_vars id id ; - - let res = - match !observed_expr_is_param with - | Only_vars -> PIndexedExp id - | Func_param (f,l) -> PFuncParam (id,f,l) - | Func_ret f -> PFuncReturn (id,f) - in - - (* On repositionne la variable a son status par defaut pour la prochaine logic_relation *) - observed_expr_is_param := Only_vars; (* DEVRAIT ETRE FAIT AVANT LOGIC_RELATION!!!! *) - - res - } - ; - - - - -/* returns a (Cil_types.predicate,Cil_types.exp) couple of expressions */ logic_relation - : arith_relation EQ arith_relation { - ( Cil_types.Prel(Cil_types.Req, Logic_utils.expr_to_term ~cast:true $1, - Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Eq, $1 , $3 , Cil.intType)) ) } - | arith_relation LT arith_relation { - ( Cil_types.Prel(Cil_types.Rlt, Logic_utils.expr_to_term ~cast:true $1, - Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Lt, $1 , $3 , Cil.intType)) ) } - | arith_relation GT arith_relation { - ( Cil_types.Prel(Cil_types.Rgt, Logic_utils.expr_to_term ~cast:true $1, - Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Gt, $1 , $3 , Cil.intType)) ) } - | arith_relation LE arith_relation { - ( Cil_types.Prel(Cil_types.Rle, Logic_utils.expr_to_term ~cast:true $1, - Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Le, $1 , $3 , Cil.intType)) ) } - | arith_relation GE arith_relation { - ( Cil_types.Prel(Cil_types.Rge, Logic_utils.expr_to_term ~cast:true $1, - Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Ge, $1 , $3 , Cil.intType) )) } - | arith_relation NEQ arith_relation { - ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true $1, - Logic_utils.expr_to_term ~cast:true $3), - new_exp(Cil_types.BinOp(Cil_types.Ne, $1 , $3 , Cil.intType) )) } - | arith_relation %prec TRUE { - ( Cil_types.Prel(Cil_types.Rneq,Logic_utils.expr_to_term ~cast:true $1, - Logic_const.term(Cil_types.TConst(Cil_types.CInt64(Int64.of_int 0,Cil_types.IInt,Some("0")))) - (Cil_types.Ctype Cil.intType)), $1) } + : arith_relation EQ arith_relation { PRel(Eq, $1, $3) } + | arith_relation LT arith_relation { PRel(Lt, $1, $3) } + | arith_relation GT arith_relation { PRel(Gt, $1, $3) } + | arith_relation LE arith_relation { PRel(Le, $1, $3) } + | arith_relation GE arith_relation { PRel(Ge, $1, $3) } + | arith_relation NEQ arith_relation { PRel(Neq, $1, $3) } + | arith_relation %prec TRUE { PRel (Neq, $1, PCst(IntConstant "0")) } ; -/* returns a Cil_types.exp expression */ arith_relation - : arith_relation_mul PLUS arith_relation { - new_exp (Cil_types.BinOp(Cil_types.PlusA, $1 , $3 , Cil.intType)) } - | arith_relation_mul MINUS arith_relation { - new_exp (Cil_types.BinOp(Cil_types.MinusA, $1 , $3 , Cil.intType)) } - | arith_relation_mul { $1 } + : arith_relation_mul PLUS arith_relation { PBinop(Badd,$1,$3) } + | arith_relation_mul MINUS arith_relation { PBinop(Bsub,$1,$3) } + | arith_relation_mul %prec lowest { $1 } ; - arith_relation_mul - : arith_relation_mul SLASH access_or_const { - new_exp (Cil_types.BinOp(Cil_types.Div, $1 , $3 , Cil.intType)) } - | arith_relation_mul STAR access_or_const { - new_exp (Cil_types.BinOp(Cil_types.Mult, $1 , $3 , Cil.intType)) } - | arith_relation_mul PERCENT access_or_const { - new_exp (Cil_types.BinOp(Cil_types.Mod, $1 , $3 , Cil.intType)) } + : arith_relation_mul SLASH access_or_const { PBinop(Bdiv,$1,$3) } + | arith_relation_mul STAR access_or_const { PBinop(Bmul, $1, $3) } + | arith_relation_mul PERCENT access_or_const { PBinop(Bmod, $1, $3) } | access_or_const { $1 } ; /* returns a Lval exp or a Const exp*/ access_or_const - : INT - { new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string $1,Cil_types.IInt, Some($1))))} - | MINUS INT - { new_exp (Cil_types.Const(Cil_types.CInt64(Int64.of_string ("-"^$2),Cil_types.IInt, Some("-"^$2))))} - | access %prec TRUE - { new_exp (Cil_types.Lval($1)) } - | LPAREN arith_relation RPAREN - { $2 } + : INT { PCst (IntConstant $1) } + | MINUS INT { PUnop (Uminus, PCst (IntConstant $2)) } + | access %prec TRUE { $1 } + | LPAREN arith_relation RPAREN { $2 } ; - - /* returns a lval */ access - : access DOT IDENTIFIER - { - - let (my_host,my_offset) = ($1) in - - let new_offset = Utils_parser.add_offset my_offset (Utils_parser.get_new_offset my_host my_offset $3) in - (my_host,new_offset) - } - - | access LSQUARE access_or_const RSQUARE - { Cil.addOffsetLval (Cil_types.Index ($3,Cil_types.NoOffset)) $1} + : access DOT IDENTIFIER { PField($1,$3) } + | access LSQUARE access_or_const RSQUARE { PArrget($1,$3) } | access_leaf {$1} ; access_leaf - : STAR access - { Aorai_option.fatal "NOT YET IMPLEMENTED : *A dereferencement access." } - | IDENTIFIER FUNC DOT IDENTIFIER - { - if(String.compare $4 "return")=0 then - begin - if not (!observed_expr_is_param=Only_vars) then - Aorai_option.abort "An expression can not contain at same time a reference of a returned value and itself or a reference to a param"; - - observed_expr_is_param := Func_ret $1; - Cil.var ( Data_for_aorai.get_returninfo $1) - end - else - begin - match !observed_expr_is_param with - | Func_ret _ -> - Aorai_option.abort "An expression can not contain both a reference of a returned value and another reference to itself or a reference to a param"; - - | Func_param (f,_) when not (f=$1) -> - Aorai_option.abort "An expression can not contain both references two different called functions."; - - | Only_vars -> - observed_expr_is_param:=Func_param ($1,[$4]); - Cil.var ( Data_for_aorai.get_paraminfo $1 $4) - - | Func_param (_,l) -> - observed_expr_is_param:=Func_param ($1,$4::l); - Cil.var ( Data_for_aorai.get_paraminfo $1 $4) - end - } - | IDENTIFIER - { Cil.var ( Data_for_aorai.get_varinfo $1) } - | LPAREN access RPAREN - { $2 } - + : STAR access { PUnop (Ustar,$2) } + | IDENTIFIER LPAREN RPAREN DOT IDENTIFIER { PPrm($1,$5) } + | IDENTIFIER { PVar $1 } + | LPAREN access RPAREN { $2 } ; diff -Nru frama-c-20110201+carbon+dfsg/src/buckx/buckx_c.c frama-c-20111001+nitrogen+dfsg/src/buckx/buckx_c.c --- frama-c-20110201+carbon+dfsg/src/buckx/buckx_c.c 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/buckx/buckx_c.c 2011-10-10 08:38:26.000000000 +0000 @@ -135,3 +135,26 @@ usleep( Int_val(v) ); return Val_unit ; } + +#if 0 +extern double cos_rd(double); /* toward -inf */ +extern double cos_ru(double); /* toward +inf */ +extern unsigned long long crlibm_init(void); + +value caml_cos_rd(value arg) +{ + return caml_copy_double(cos_rd(Double_val(arg))); +} + + +value caml_cos_ru(value arg) +{ + return caml_copy_double(cos_ru(Double_val(arg))); +} + +value caml_crlibm_init(value dummy) +{ + crlibm_init(); + return Val_unit; +} +#endif diff -Nru frama-c-20110201+carbon+dfsg/src/buckx/buckx.ml frama-c-20111001+nitrogen+dfsg/src/buckx/buckx.ml --- frama-c-20110201+carbon+dfsg/src/buckx/buckx.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/buckx/buckx.ml 2011-10-10 08:38:26.000000000 +0000 @@ -57,29 +57,17 @@ module MakeBig(H:WeakHashable) = struct module W = Weak.Make(H) - let n = ref 0 - let get () = incr n; !n - type t = (W.t * int )ref - let addr t = snd !t + type t = W.t ref + let addr _t = 0 type data = H.t - let create c = - let t = ref (W.create c, (get())) in -(* Format.printf "CREATE %s: %d@." H.id (snd !t);*) - t - let merge t d = -(* let r = *)W.merge (fst !t) d (*in*) -(* if H.id = "(base, Int_Intervals) ptmap" && (addr new_tr = 1297910 || H.id - new_tr = 538304833 || H.id = 27776) then - Format.printf "MERGE %S: t=%d; d=%a " H.id (snd !t) H.pretty d;*) -(* r*) - let iter t f = W.iter f (fst !t) - let clear t = W.clear (fst !t) + let create c = ref (W.create c) + let merge t d = W.merge !t d + let iter t f = W.iter f (!t) + let clear t = W.clear (!t) let release _t = () let pretty_debug _ = assert false let shallow_copy t = ref !t let overwrite ~old ~fresh = -(* if H.id = "(base, Int_Intervals) ptmap" then - Format.printf "OVERWRITE old=%d; fresh=%d@." (snd !old) (snd !fresh);*) old := !fresh end @@ -89,8 +77,8 @@ let gc_params = Gc.get () in Gc.set { gc_params with - Gc.minor_heap_size = 1 lsl 19 ; - major_heap_increment = 1 lsl 21; + Gc.minor_heap_size = 1 lsl 18 ; + major_heap_increment = 1 lsl 22; (* space_overhead = 40 ; max_overhead = 100 *) }; diff -Nru frama-c-20110201+carbon+dfsg/src/buckx/buckx.mli frama-c-20111001+nitrogen+dfsg/src/buckx/buckx.mli --- frama-c-20110201+carbon+dfsg/src/buckx/buckx.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/buckx/buckx.mli 2011-10-10 08:38:26.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + module MemoryFootprint : State_builder.Ref with type data = int module type WeakHashable = diff -Nru frama-c-20110201+carbon+dfsg/src/constant_propagation/propagationParameters.ml frama-c-20111001+nitrogen+dfsg/src/constant_propagation/propagationParameters.ml --- frama-c-20110201+carbon+dfsg/src/constant_propagation/propagationParameters.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/constant_propagation/propagationParameters.ml 2011-10-10 08:38:28.000000000 +0000 @@ -31,28 +31,40 @@ module SemanticConstFolding = False (struct - let option_name = "-semantic-const-folding" - let help = "pretty print a version of the source code where each constant expression is replaced by its value" + let option_name = "-scf" + let help = "pretty print a version of the source code where each constant expression is replaced by its value" let kind = `Tuning end) +let () = SemanticConstFolding.add_aliases ["-semantic-const-folding"] module SemanticConstFold = StringSet (struct - let option_name = "-semantic-const-fold" + let option_name = "-scf-fct" let arg_name = "f1, ..., fn" let help = "propagate constants only into functions f1,...,fn" let kind = `Tuning end) +let () = SemanticConstFold.add_aliases ["-semantic-const-fold"] module CastIntro = False (struct - let option_name = "-cast-from-constant" - let help = "replace expressions by constants even when doing so \ + let option_name = "-scf-allow-cast" + let help = "replace expressions by constants even when doing so \ requires a pointer cast" let kind = `Tuning end) +let () = CastIntro.add_aliases ["-cast-from-constant"] + +module ExpandLogicContext = + False + (struct + let option_name = "-scf-logic" + let help = "replace values from logical context and create corresponding variables (HIGHLY EXPERIMENTAL)" + let kind = `Tuning + end) +let () = ExpandLogicContext.add_aliases ["-semantic-const-fold-logic"] (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/constant_propagation/propagationParameters.mli frama-c-20111001+nitrogen+dfsg/src/constant_propagation/propagationParameters.mli --- frama-c-20110201+carbon+dfsg/src/constant_propagation/propagationParameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/constant_propagation/propagationParameters.mli 2011-10-10 08:38:28.000000000 +0000 @@ -22,7 +22,8 @@ open Plugin -module SemanticConstFolding: BOOL -module SemanticConstFold: STRING_SET -module CastIntro: BOOL +module SemanticConstFolding: Bool +module SemanticConstFold: String_set +module CastIntro: Bool +module ExpandLogicContext: Bool include Log.Messages diff -Nru frama-c-20110201+carbon+dfsg/src/constant_propagation/register.ml frama-c-20111001+nitrogen+dfsg/src/constant_propagation/register.ml --- frama-c-20110201+carbon+dfsg/src/constant_propagation/register.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/constant_propagation/register.ml 2011-10-10 08:38:28.000000000 +0000 @@ -51,8 +51,8 @@ || Datatype.String.Set.mem name fnames; if operate then PropagationParameters.feedback - ~level:2 - "propagated constant in function %s" + ~level:2 + "propagated constant in function %s" (fundec.svar.vname); DoChildren @@ -60,143 +60,144 @@ self#on_current_stmt DoChildren (fun ki -> - PropagationParameters.debug ~level:2 - "Replacing %a ?" !Ast_printer.d_exp expr; - let type_of_expr = typeOf expr in - try - begin - match unrollType type_of_expr with - | (TInt _ - | TFloat _ - | TPtr _ - | TEnum _) -> () - | _ -> raise Cannot_expand - end; - let mkCast ~e ~newt = - (* introduce a new cast or do not expand [e] *) - let exp = mkCast e newt in - if cast_intro then - exp - else - match exp.enode with - | CastE _ -> - if exp == e (* older cast, no new cast added *) then - exp - else - (* without [cast_intro], introducing such a cast is not - allowed: do not expand [e] *) - raise Cannot_expand - | _ -> - (* remember the change done by [mkCast] (if any). - note that [mkCast] make some modifications, even if it - does not introduce a new cast. *) - exp - in - let evaled = !Value.access_expr ki expr in - let k,m = Cvalue_type.V.find_lonely_binding evaled in - let can_replace vi = - vi.vglob || - Extlib.may_map - (Kernel_function.is_formal_or_local vi) ~dft:false - self#current_kf - in - begin - match k with - | Base.Var (vi,_) | Base.Initialized_Var (vi,_) - when not vi.vlogic && can_replace vi -> - if vi.vglob && not (Varinfo.Set.mem vi known_globals) - then begin - let vi = Visitor.visitFramacVarDecl - (self:>Visitor.frama_c_visitor) vi - in - must_add_decl <- Varinfo.Set.add vi must_add_decl; - end; - (* This is a pointer coming for C code *) - PropagationParameters.debug - "Trying replacing %a from a pointer value {&%a + %a}" - !Ast_printer.d_exp expr - Base.pretty k - Ival.pretty m; - let base = mkAddrOrStartOf ~loc:expr.eloc (var vi) in - let offset = Ival.project_int m in (* these are bytes *) - let shifted = - if Abstract_interp.Int.is_zero offset then base - else - let offset,rem = - let sizeof_pointed = - try - Int_Base.project - (if isArrayType vi.vtype then - Bit_utils.osizeof_pointed vi.vtype - else - Bit_utils.osizeof vi.vtype) - with - | Int_Base.Error_Top - | Int_Base.Error_Bottom -> raise Cannot_expand - in (Abstract_interp.Int.pos_div offset sizeof_pointed), - (Abstract_interp.Int.pos_rem offset sizeof_pointed) - in let shifted = - if Abstract_interp.Int.is_zero offset - then base - else let v1 = Abstract_interp.Int.cast - ~signed:true - ~size:(Abstract_interp.Int.of_int 64) - ~value:offset - in increm64 base (Abstract_interp.Int.to_int64 v1) - in if Abstract_interp.Int.is_zero rem - then shifted - else let v1 = Abstract_interp.Int.cast - ~signed:true - ~size:(Abstract_interp.Int.of_int 64) - ~value:rem - in increm64 (mkCast ~e:shifted ~newt:Cil.charPtrType) - (Abstract_interp.Int.to_int64 v1) - in let change_to = (* Give it the right type! *) - mkCast ~e:shifted ~newt:type_of_expr - in - PropagationParameters.debug "Replacing %a with %a" - !Ast_printer.d_exp expr - !Ast_printer.d_exp change_to; - ChangeDoChildrenPost (change_to, fun x -> x) - | Base.Null -> - let e = - begin - try - (* This is an integer *) - let v = Ival.project_int m in - PropagationParameters.debug - "Trying replacing %a with a numeric value: %a" - !Ast_printer.d_exp expr - Abstract_interp.Int.pretty v; - try - let v1 = Abstract_interp.Int.cast - ~signed:true - ~size:(Abstract_interp.Int.of_int 64) - ~value:v - in - (* PropagationParameters.debug "XXXXXXXX v=%a v1=%a" - Abstract_interp.Int.pretty v - Abstract_interp.Int.pretty v1; *) - kinteger64 ~loc:expr.eloc - IULongLong - (Abstract_interp.Int.to_int64 v1) - with Failure _ -> raise Cannot_expand - with Ival.Not_Singleton_Int-> - (* TODO: floats *) - raise Cannot_expand - end - in let change_to = (* Give it the right type ! *) - mkCast ~e ~newt:(type_of_expr) - in - PropagationParameters.debug "Replacing %a with %a" - !Ast_printer.d_exp expr - !Ast_printer.d_exp change_to; - ChangeDoChildrenPost(change_to,fun x -> x) - | Base.Cell_class _ | Base.String _ - | Base.Var _ | Base.Initialized_Var _ -> DoChildren - - end - with Not_found | Cannot_expand -> DoChildren) + PropagationParameters.debug ~level:2 + "Replacing %a ?" !Ast_printer.d_exp expr; + let type_of_expr = typeOf expr in + try + begin match unrollType type_of_expr with + | (TInt _ + | TFloat _ + | TPtr _ + | TEnum _) -> () + | _ -> raise Cannot_expand + end; + let mkCast ~e ~newt = + (* introduce a new cast or do not expand [e] *) + let exp = mkCast e newt in + if cast_intro then + exp + else match exp.enode with + | CastE _ -> + if exp == e (* older cast, no new cast added *) then + exp + else + (* without [cast_intro], introducing such a cast is not + allowed: do not expand [e] *) + raise Cannot_expand + | _ -> + (* remember the change done by [mkCast] (if any). + note that [mkCast] make some modifications, even if it + does not introduce a new cast. *) + exp + in + let evaled = !Value.access_expr ki expr in + let k,m = Cvalue.V.find_lonely_binding evaled in + let can_replace vi = + vi.vglob || + Extlib.may_map + (Kernel_function.is_formal_or_local vi) ~dft:false + self#current_kf + in + begin match k with + | Base.Var(vi,_) | Base.Initialized_Var (vi,_) + when (PropagationParameters.ExpandLogicContext.get () + || not vi.vlogic) + && can_replace vi -> + if vi.vglob && not (Varinfo.Set.mem vi known_globals) then begin + let vi = + Visitor.visitFramacVarDecl (self :> Visitor.frama_c_visitor) vi + in + must_add_decl <- Varinfo.Set.add vi must_add_decl + end; (* This is a pointer coming for C code *) + PropagationParameters.debug + "Trying replacing %a from a pointer value {&%a + %a}" + !Ast_printer.d_exp expr + Base.pretty k + Ival.pretty m; + let base = mkAddrOrStartOf ~loc:expr.eloc (var vi) in + let offset = Ival.project_int m in (* these are bytes *) + let shifted = + if Abstract_interp.Int.is_zero offset then base + else + let offset,rem = + let sizeof_pointed = + try + Int_Base.project + (if isArrayType vi.vtype then + Bit_utils.osizeof_pointed vi.vtype + else Bit_utils.osizeof vi.vtype) + with + | Int_Base.Error_Top + | Int_Base.Error_Bottom -> raise Cannot_expand + in + (Abstract_interp.Int.pos_div offset sizeof_pointed), + (Abstract_interp.Int.pos_rem offset sizeof_pointed) + in + let shifted = + if Abstract_interp.Int.is_zero offset + then base + else + let v1 = Abstract_interp.Int.cast + ~signed:true + ~size:(Abstract_interp.Int.of_int 64) + ~value:offset + in + increm64 base v1 + in + if Abstract_interp.Int.is_zero rem then shifted + else let v1 = Abstract_interp.Int.cast + ~signed:true + ~size:(Abstract_interp.Int.of_int 64) + ~value:rem + in + increm64 (mkCast ~e:shifted ~newt:Cil.charPtrType) v1 + in + let change_to = (* Give it the right type! *) + mkCast ~e:shifted ~newt:type_of_expr + in + PropagationParameters.debug "Replacing %a with %a" + !Ast_printer.d_exp expr + !Ast_printer.d_exp change_to; + ChangeDoChildrenPost (change_to, fun x -> x) + | Base.Null -> + let e = + begin + try + (* This is an integer *) + let v = Ival.project_int m in + PropagationParameters.debug + "Trying to replace %a with a numeric value: %a" + !Ast_printer.d_exp expr + Abstract_interp.Int.pretty v; + try + let v1 = Abstract_interp.Int.cast + ~signed:true + ~size:(Abstract_interp.Int.of_int 64) + ~value:v + in + PropagationParameters.debug ~level:2 + "Before v=%a after as signed int64 v1=%a" + Abstract_interp.Int.pretty v + Abstract_interp.Int.pretty v1; + kinteger64 ~loc:expr.eloc + IULongLong + v1 + with Failure _ -> raise Cannot_expand + with Ival.Not_Singleton_Int-> + (* TODO: floats *) + raise Cannot_expand + end + in let change_to = (* Give it the right type ! *) + mkCast ~e ~newt:(type_of_expr) + in + PropagationParameters.debug "Replacing %a with %a (was %a)" + !Ast_printer.d_exp expr + !Ast_printer.d_exp change_to + !Ast_printer.d_exp e; + ChangeDoChildrenPost(change_to,fun x -> x) + | Base.String _ | Base.Var _ | Base.Initialized_Var _ -> DoChildren + end + with Not_found | Cannot_expand -> DoChildren) method vvdec v = if v.vglob then known_globals <- Varinfo.Set.add v known_globals; @@ -207,16 +208,16 @@ let add_decl l = Varinfo.Set.fold (fun x l -> - PropagationParameters.feedback ~level:2 - "Adding declaration of global %a" !Ast_printer.d_var x; - GVarDecl(Cil.empty_funspec(),x,x.vdecl)::l) + PropagationParameters.feedback ~level:2 + "Adding declaration of global %a" !Ast_printer.d_var x; + GVarDecl(Cil.empty_funspec(),x,x.vdecl)::l) must_add_decl l in ChangeDoChildrenPost([g],add_decl) method vlval lv = let simplify (host,offs as lv) = match host with - | Mem e -> mkMem e offs (* canonicalize *) - | Var _ -> lv + | Mem e -> mkMem e offs (* canonicalize *) + | Var _ -> lv in ChangeDoChildrenPost(lv, simplify) end @@ -233,7 +234,7 @@ let size = 7 let name = "Semantical constant propagation" let dependencies = - [ Value.self; PropagationParameters.CastIntro.self ] + [ Value.self; PropagationParameters.CastIntro.self ] let kind = `Correctness end) @@ -241,15 +242,15 @@ let get fnames cast_intro = Result.memo (fun _ -> - !Value.compute (); - let fresh_project = - FC_file.create_project_from_visitor - "propagated" - (fun prj -> new propagate prj fnames cast_intro) - in - let ctx = Parameters.get_selection_context () in - Project.copy ~selection:ctx fresh_project; - fresh_project) + !Value.compute (); + let fresh_project = + FC_file.create_project_from_visitor + "propagated" + (fun prj -> new propagate prj fnames cast_intro) + in + let ctx = Plugin.get_selection_context () in + Project.copy ~selection:ctx fresh_project; + fresh_project) (fnames, cast_intro) in Journal.register @@ -279,7 +280,7 @@ let force_semantic_folding = PropagationParameters.SemanticConstFolding.get () || not (Datatype.String.Set.is_empty - (PropagationParameters.SemanticConstFold.get ())) + (PropagationParameters.SemanticConstFold.get ())) in (* must called the function stored in [Db] for journalisation purpose *) if force_semantic_folding then !Db.Constant_Propagation.compute () @@ -291,14 +292,14 @@ Db.register_compute "Constant_Propagation.compute" [ PropagationParameters.SemanticConstFold.self; - PropagationParameters.SemanticConstFolding.self; - Result.self ] + PropagationParameters.SemanticConstFolding.self; + Result.self ] Db.Constant_Propagation.compute compute; in () (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/constant_propagation/register.mli frama-c-20111001+nitrogen+dfsg/src/constant_propagation/register.mli --- frama-c-20110201+carbon+dfsg/src/constant_propagation/register.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/constant_propagation/register.mli 2011-10-10 08:38:28.000000000 +0000 @@ -20,6 +20,6 @@ (* *) (**************************************************************************) -(** Nothing is exported here +(** Nothing is exported here Functions are registered in {!Db}. *) diff -Nru frama-c-20110201+carbon+dfsg/src/dummy/untyped_metrics/count_for.ml frama-c-20111001+nitrogen+dfsg/src/dummy/untyped_metrics/count_for.ml --- frama-c-20110201+carbon+dfsg/src/dummy/untyped_metrics/count_for.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/dummy/untyped_metrics/count_for.ml 2011-10-10 08:38:28.000000000 +0000 @@ -44,34 +44,33 @@ open Cabs -class count_for = +class count_for = object inherit Cabsvisit.nopCabsVisitor as super val mutable counted_for = 0 method counted_for = counted_for method vstmt s = - begin match s.stmt_node with - | FOR _ -> counted_for <- counted_for + 1 - | _ -> () - end; - super#vstmt s + begin match s.stmt_node with + | FOR _ -> counted_for <- counted_for + 1 + | _ -> () + end; + super#vstmt s end -let count_for (fname,_ as file) = +let count_for (fname,_ as file) = let counter = new count_for in ignore (Cabsvisit.visitCabsFile (counter:>Cabsvisit.cabsVisitor) file); - fname,counter#counted_for - + fname,counter#counted_for + let print_stat (fname,n) = Format.printf "%s: %d@." fname n -let startup _ = +let startup _ = if Enabled.get () then begin let untyped_files = Ast.UntypedFiles.get () in - + let stats = List.map count_for untyped_files in List.iter print_stat stats end -let () = +let () = Db.Main.extend startup - diff -Nru frama-c-20110201+carbon+dfsg/src/from/from_parameters.mli frama-c-20111001+nitrogen+dfsg/src/from/from_parameters.mli --- frama-c-20110201+carbon+dfsg/src/from/from_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/from/from_parameters.mli 2011-10-10 08:38:23.000000000 +0000 @@ -23,12 +23,12 @@ include Plugin.S -module ForceDeps: Plugin.BOOL -module ForceCallDeps: Plugin.BOOL +module ForceDeps: Plugin.Bool +module ForceCallDeps: Plugin.Bool (** @plugin development guide *) -module PathDeps: Plugin.BOOL +module PathDeps: Plugin.Bool (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/from/from_register_gui.ml frama-c-20111001+nitrogen+dfsg/src/from/from_register_gui.ml --- frama-c-20110201+carbon+dfsg/src/from/from_register_gui.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/from/from_register_gui.ml 2011-10-10 08:38:23.000000000 +0000 @@ -29,18 +29,18 @@ open Gtk_helper let main (main_ui:Design.main_window_extension_points) = - let filetree_selector - ~was_activated ~activating globals = - if Value.is_computed () then begin + let filetree_selector + ~was_activated ~activating globals = + if Value.is_computed () then begin if not was_activated && activating then begin match globals with (* [JS 2009/30/03] GUI may become too slow if froms are displayed *) -(* | [GFun ({svar=v},_)] -> - begin try +(* | [GFun ({svar=v},_)] -> + begin try let kf = Globals.Functions.get v in - if !From.is_computed kf then + if !From.is_computed kf then let s = fprintf_to_string "@[Functional dependencies:@\n%a@]@." !From.pretty kf in main_ui#annot_window#buffer#insert s - with Not_found -> () + with Not_found -> () end*) | _ -> (); end; @@ -56,4 +56,3 @@ compile-command: "LC_ALL=C make -C ../.. -j" End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/from/from_register_gui.mli frama-c-20111001+nitrogen+dfsg/src/from/from_register_gui.mli --- frama-c-20110201+carbon+dfsg/src/from/from_register_gui.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/from/from_register_gui.mli 2011-10-10 08:38:23.000000000 +0000 @@ -30,4 +30,3 @@ compile-command: "LC_ALL=C make -C ../.. -j" End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/from/from_register.ml frama-c-20111001+nitrogen+dfsg/src/from/from_register.ml --- frama-c-20110201+carbon+dfsg/src/from/from_register.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/from/from_register.ml 2011-10-10 08:38:23.000000000 +0000 @@ -22,14 +22,13 @@ open Cil_types open Cil -module IH = Inthash open Cil_datatype -open Db_types open Db open Locations open Abstract_interp open Abstract_value + exception Call_did_not_take_place module Functionwise_Dependencies = @@ -62,18 +61,18 @@ module type Values_To_Use_Sig = sig val lval_to_loc_with_deps : - (Cil_types.kinstr -> + (stmt -> with_alarms:CilE.warn_mode -> deps:Locations.Zone.t -> Cil_types.lval -> Locations.Zone.t * Locations.location) ref val expr_to_kernel_function : - (Cil_types.kinstr -> + (stmt -> with_alarms:CilE.warn_mode -> deps:Locations.Zone.t option -> Cil_types.exp -> Locations.Zone.t * Kernel_function.Hptset.t) ref - val get_state : Cil_types.kinstr -> Db.Value.state - val access_expr : (Cil_types.kinstr -> Cil_types.exp -> Db.Value.t) ref + val get_stmt_state : stmt -> Db.Value.state + val access_expr : (Cil_types.stmt -> Cil_types.exp -> Db.Value.t) ref end module type Recording_Sig = sig @@ -90,18 +89,18 @@ struct type t' = { additional_deps_table : Zone.t Stmt.Map.t; - (** Additional dependencies to add to all modified variables. + (** Additional dependencies to add to all modified variables. Example: variables in the condition of an IF. *) - additional_deps : Zone.t; - (** Union of the sets in StmtMap.t *) - deps_table : Lmap_bitwise.From_Model.t - (** dependency table *) + additional_deps : Zone.t; + (** Union of the sets in StmtMap.t *) + deps_table : Lmap_bitwise.From_Model.t + (** dependency table *) } let call_stack : kernel_function Stack.t = Stack.create () (** Stack of function being processed *) - let rec find_deps_no_transitivity instr expr = + let rec find_deps_no_transitivity stmt expr = (* The value of the expression [expr], just before executing the statement [instr], is a function of the values of the returned zones. *) match (stripInfo expr).enode with @@ -113,17 +112,17 @@ let deps, _ = !Values_To_Use.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode ~deps:Zone.bottom - instr + stmt lv in deps | CastE (_, e)|UnOp (_, e, _) -> - find_deps_no_transitivity instr e + find_deps_no_transitivity stmt e | BinOp (_, e1, e2, _) -> Zone.join - (find_deps_no_transitivity instr e1) - (find_deps_no_transitivity instr e2) + (find_deps_no_transitivity stmt e1) + (find_deps_no_transitivity stmt e2) | Lval v -> - find_deps_lval_no_transitivity instr v + find_deps_lval_no_transitivity stmt v and find_deps_offset_no_transitivity instr o = match o with @@ -134,15 +133,15 @@ (find_deps_no_transitivity instr e) (find_deps_offset_no_transitivity instr o) - and find_deps_lval_no_transitivity instr lv = + and find_deps_lval_no_transitivity stmt lv = let deps, loc = !Values_To_Use.lval_to_loc_with_deps - ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - instr - lv + ~with_alarms:CilE.warn_none_mode + ~deps:Zone.bottom + stmt + lv in - let direct_deps = valid_enumerate_bits loc in + let direct_deps = valid_enumerate_bits ~for_writing:false loc in let result = Zone.join deps direct_deps in From_parameters.debug "find_deps_lval_no_trs:@\n deps:%a@\n direct_deps:%a" Zone.pretty deps @@ -168,50 +167,45 @@ let debug = ref false - let current_stmt = ref Kglobal - let stmt_can_reach = REACH.stmt_can_reach type t = t' module StmtStartData = - Dataflow.StmtStartData(struct type t = t' let size = 107 end) + Dataflow.StartData(struct type t = t' let size = 107 end) - let callwise_states_with_formals = Kinstr.Hashtbl.create 7 + let callwise_states_with_formals = Stmt.Hashtbl.create 7 type substit = Froms of Zone.t | Lvalue of Lmap_bitwise.From_Model.LOffset.t let cached_substitute call_site_froms extra_loc = let f k intervs = Lmap_bitwise.From_Model.find - call_site_froms - (Zone.inject k intervs) + call_site_froms + (Zone.inject k intervs) in let joiner = Zone.join in let projection base = match Base.validity base with | Base.Periodic (min_valid, max_valid, _) | Base.Known (min_valid,max_valid) | Base.Unknown (min_valid,max_valid)-> - Int_Intervals.inject_bounds min_valid max_valid + Int_Intervals.inject_bounds min_valid max_valid | Base.All -> assert false(*TODO*) in let zone_substitution = - Zone.cached_fold ~cache:("from substitution", 331) ~temporary:true - ~f ~joiner ~empty:Zone.bottom ~projection + Zone.cached_fold ~cache:("from substitution", 331) ~temporary:true + ~f ~joiner ~empty:Zone.bottom ~projection in let zone_substitution x = try - zone_substitution x + zone_substitution x with Zone.Error_Top -> Zone.top in fun z -> Zone.join extra_loc (zone_substitution z) - let display_one_from fmt k v = - Format.fprintf fmt "Statement: %d@\n%a" - k - Lmap_bitwise.From_Model.pretty - v.deps_table; + let display_one_from fmt v = + Lmap_bitwise.From_Model.pretty fmt v.deps_table; Format.fprintf fmt "Additional Variable Map : %a@\n" (let module M = Stmt.Map.Make(Zone) in M.pretty) v.additional_deps_table; @@ -220,15 +214,18 @@ Zone.pretty v.additional_deps + let display_one_from_stmt fmt k v = + Format.fprintf fmt "Statement: %d@\n%a" k.sid display_one_from v + let display_from fmt = Format.fprintf fmt "=========FROM START=======@\n"; - StmtStartData.iter (display_one_from fmt); + StmtStartData.iter (display_one_from_stmt fmt); Format.fprintf fmt "=========FROM END=======@\n" let copy (d: t) = d let pretty fmt (v: t) = - display_one_from fmt 9999 v + display_one_from fmt v let eliminate_additional table s = let current_function = Stack.top call_stack in @@ -236,9 +233,9 @@ from a branch closing at this statement. *) Stmt.Map.fold (fun k v (acc_set,acc_map,nb) -> - (* [JS 2010/09/23] now better to let the kernel displays a (better?) - backtrace. *) -(* try*) + (* [JS 2010/09/23] now better to let the kernel displays a (better?) + backtrace. *) +(* try*) if !Postdominators.is_postdominator current_function ~opening:k @@ -247,9 +244,9 @@ else (Zone.join v acc_set), (Stmt.Map.add k v acc_map),nb+1 -(* with e -> - From_parameters.fatal "internal error 356: (%s)Open:%d Close:%d" - (Printexc.to_string e) k.sid s.sid*)) +(* with e -> + From_parameters.fatal "internal error 356: (%s)Open:%d Close:%d" + (Printexc.to_string e) k.sid s.sid*)) table (Zone.bottom, Stmt.Map.empty,0) @@ -265,7 +262,7 @@ match s.skind with | Switch (exp,_,_,_) | If (exp,_,_,_) -> - let additional_vars = find_deps (Kstmt s) data.deps_table exp in + let additional_vars = find_deps s data.deps_table exp in {data with additional_deps_table = Stmt.Map.add @@ -325,15 +322,13 @@ else Some ({merged with deps_table = result }) - let resolv_func_vinfo ?deps kinstr funcexp = - !Values_To_Use.expr_to_kernel_function ?deps kinstr funcexp + let resolv_func_vinfo ?deps stmt funcexp = + !Values_To_Use.expr_to_kernel_function ?deps stmt funcexp exception Ignore - let doInstr _stmt (i: instr) (d: t) = + let doInstr stmt (i: instr) (d: t) = !Db.progress (); - let kinstr = !current_stmt - in let add_with_additional_var lv v d = let deps, target = (* The modified location is [target], @@ -341,7 +336,7 @@ !Values_To_Use.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode ~deps:Zone.bottom - kinstr + stmt lv in let deps = Zone.join @@ -362,7 +357,7 @@ | Set (lv, exp, _) -> Dataflow.Post (fun state -> - let comp_vars = find_deps kinstr state.deps_table exp in + let comp_vars = find_deps stmt state.deps_table exp in let result = add_with_additional_var lv comp_vars state in result ) @@ -374,7 +369,7 @@ resolv_func_vinfo ~with_alarms:CilE.warn_none_mode ~deps:Zone.bottom - kinstr + stmt funcexp in let funcexp_deps = @@ -385,7 +380,7 @@ in let args_froms = List.map - (fun arg -> + (fun arg -> match arg with (* TODO : optimize the dependencies on subfields | Lval lv -> @@ -394,36 +389,36 @@ (Interp_loc.lval_to_loc_with_deps kinstr lv)) *) | _ -> - Froms (find_deps kinstr d.deps_table arg)) - argl + Froms (find_deps stmt d.deps_table arg)) + argl in - let states_with_formals = ref [] in + let states_with_formals = ref [] in let do_on kernel_function = let called_vinfo = Kernel_function.get_vi kernel_function in - if Ast_info.is_cea_function called_vinfo.vname then - state - else + if Ast_info.is_cea_function called_vinfo.vname then + state + else let { Function_Froms.deps_return = return_from; deps_table = called_func_froms } = - Froms_To_Use.get kernel_function kinstr + Froms_To_Use.get kernel_function (Kstmt stmt) in let formal_args = - Kernel_function.get_formals kernel_function - in - let state_with_formals = ref state.deps_table in + Kernel_function.get_formals kernel_function + in + let state_with_formals = ref state.deps_table in begin try List.iter2 - (fun vi from -> - match from with - Froms from -> - let zvi = Locations.zone_of_varinfo vi in - state_with_formals := - Lmap_bitwise.From_Model.add_binding - ~exact:true - !state_with_formals - zvi - from - | Lvalue _ -> assert false) + (fun vi from -> + match from with + Froms from -> + let zvi = Locations.zone_of_varinfo vi in + state_with_formals := + Lmap_bitwise.From_Model.add_binding + ~exact:true + !state_with_formals + zvi + from + | Lvalue _ -> assert false) formal_args args_froms; with Invalid_argument "List.iter2" -> @@ -434,16 +429,16 @@ (List.length args_froms)) end; - if not (Db.From.Record_From_Callbacks.is_empty ()) - then - states_with_formals := - (kernel_function, !state_with_formals) :: - !states_with_formals; + if not (Db.From.Record_From_Callbacks.is_empty ()) + then + states_with_formals := + (kernel_function, !state_with_formals) :: + !states_with_formals; let substitute = - cached_substitute + cached_substitute !state_with_formals additional_deps - in + in let new_state = (* From state just after the call, but before the result assigment *) @@ -458,48 +453,39 @@ (match lvaloption with | None -> new_state | Some lv -> + let first = ref true in (try - Lmap_bitwise.From_Model.LOffset.fold - (fun itv (_,x) acc -> + Lmap_bitwise.From_Model.LOffset.fold + (fun _itv (_,x) acc -> + if not !first + then + (* treatment below only compatible with + imprecise handling + of Return elsewhere in this file *) + raise Not_found; + first := false; let res = substitute x in let deps, loc = - !Values_To_Use.lval_to_loc_with_deps + !Values_To_Use.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode ~deps:Zone.bottom - kinstr + stmt lv in let deps = - (Lmap_bitwise.From_Model.find acc.deps_table - deps) + Lmap_bitwise.From_Model.find + acc.deps_table + deps in let deps = Zone.join res deps in let deps = Zone.join deps acc.additional_deps in - let base, range = - Location_Bits.find_lonely_binding loc.loc - in let start = match Ival.min_int range with - None -> assert false - | Some i -> i - in - let zones = - Int_Intervals.fold - (fun (lb,ub) acc -> - let zone = - Zone.inject base - (Int_Intervals.inject - [Int.add start lb, - Int.add start ub]) - in - Zone.join zone acc) - itv Zone.bottom - in - let real_loc = Locations.filter_loc loc zones in { acc with deps_table = !Db.From.update - real_loc - deps acc.deps_table} - ) - return_from new_state + loc + deps + acc.deps_table}) + return_from + new_state with Not_found -> (* from find_lonely_binding *) let vars = Lmap_bitwise.From_Model.LOffset.map @@ -512,45 +498,43 @@ new_state )) in - let f f acc = - let p = do_on f in - match acc with - None -> Some p - | Some acc_memory -> - Some - {state with - deps_table = Lmap_bitwise.From_Model.join + let f f acc = + let p = do_on f in + match acc with + None -> Some p + | Some acc_memory -> + Some + {state with + deps_table = Lmap_bitwise.From_Model.join p.deps_table acc_memory.deps_table} - in - let result = - try - ( match Kernel_function.Hptset.fold f called_vinfos None with - None -> state - | Some s -> s); - with Call_did_not_take_place -> state - in - if not (Db.From.Record_From_Callbacks.is_empty ()) - then - Kinstr.Hashtbl.replace - callwise_states_with_formals - kinstr - !states_with_formals; - result + in + let result = + try + ( match Kernel_function.Hptset.fold f called_vinfos None with + None -> state + | Some s -> s); + with Call_did_not_take_place -> state + in + if not (Db.From.Record_From_Callbacks.is_empty ()) + then + Stmt.Hashtbl.replace + callwise_states_with_formals + stmt + !states_with_formals; + result ) | _ -> Dataflow.Default let doStmt (s: stmt) (_d: t) = - if not (Db.Value.is_reachable (Values_To_Use.get_state (Kstmt s))) then + if not (Db.Value.is_reachable (Values_To_Use.get_stmt_state s)) then Dataflow.SDone - else begin - current_stmt := Kstmt s; + else Dataflow.SDefault - end let filterStmt stmt = - Db.Value.is_reachable (Values_To_Use.get_state (Kstmt stmt)) + Db.Value.is_reachable (Values_To_Use.get_stmt_state stmt) (* Remove all local variables and formals from table *) let externalize return kf state = @@ -560,8 +544,8 @@ let deps, target = !Values_To_Use.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - (Kstmt return) + ~deps:Zone.bottom + return v in Lmap_bitwise.From_Model.LOffset.join @@ -569,28 +553,26 @@ state.deps_table deps) (Lmap_bitwise.From_Model.find_base state.deps_table - (valid_enumerate_bits target)) + (valid_enumerate_bits ~for_writing:false target)) | Return (None,_) -> Lmap_bitwise.From_Model.LOffset.empty | _ -> assert false) in let deps_table = Lmap_bitwise.From_Model.filter_base - (Recording_To_Do.accept_base_in_lmap kf) - state.deps_table + (Recording_To_Do.accept_base_in_lmap kf) + state.deps_table in { deps_return = deps_return; Function_Froms.deps_table = deps_table } let doGuard s e _t = - let ki = Kstmt s in - current_stmt := ki; - let interpreted_e = !Values_To_Use.access_expr ki e in + let interpreted_e = !Values_To_Use.access_expr s e in let t1 = unrollType (typeOf e) in let do_then, do_else = if isIntegralType t1 || isPointerType t1 - then Cvalue_type.V.contains_non_zero interpreted_e, - Cvalue_type.V.contains_zero interpreted_e + then Cvalue.V.contains_non_zero interpreted_e, + Cvalue.V.contains_zero interpreted_e else true, true (* TODO: a float condition is true iff != 0.0 *) in (if do_then @@ -605,8 +587,6 @@ match REACH.blocks_closed_by_edge s succ with [] -> d | closed_blocks -> - let kinstr = Kstmt s in - current_stmt:= kinstr; let deps_table = Lmap_bitwise.From_Model.uninitialize_locals (List.fold_left (fun x y -> y.blocals @ x) [] closed_blocks) @@ -621,19 +601,20 @@ try let module Computer = Computer - (struct + (struct let stmt_can_reach = Stmts_graph.stmt_can_reach kf let blocks_closed_by_edge = Kernel_function.blocks_closed_by_edge end) in - let module Compute = Dataflow.ForwardsDataFlow(Computer) in + let module Compute = Dataflow.Forwards(Computer) in Stack.iter (fun g -> if kf == g then begin - From_parameters.error - "ignoring recursive call detected in function %a during dependencies computations." - Kernel_function.pretty_name kf; + if Db.Value.ignored_recursive_call kf then + From_parameters.error + "during dependencies computations for %a, ignoring probable recursive" + Kernel_function.pretty kf; raise Exit end) call_stack; @@ -647,38 +628,41 @@ match f.sbody.bstmts with [] -> assert false | start :: _ -> - let ret_id = Kernel_function.find_return kf in + let ret_id = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> assert false + in (* We start with only the start block *) Computer.StmtStartData.add - start.sid + start (Computer.computeFirstPredecessor start state); Compute.compute [start]; - if not (Db.From.Record_From_Callbacks.is_empty ()) - then begin - From_parameters.feedback "Now calling From callbacks"; - let states = - IH.create (Computer.StmtStartData.length ()) - in - Computer.StmtStartData.iter - (fun k record -> - IH.add states k record.deps_table); - Db.From.Record_From_Callbacks.apply - (call_stack, states, Computer.callwise_states_with_formals) - end; + if not (Db.From.Record_From_Callbacks.is_empty ()) + then begin + From_parameters.feedback "Now calling From callbacks"; + let states = + Stmt.Hashtbl.create (Computer.StmtStartData.length ()) + in + Computer.StmtStartData.iter + (fun k record -> + Stmt.Hashtbl.add states k record.deps_table); + Db.From.Record_From_Callbacks.apply + (call_stack, states, Computer.callwise_states_with_formals) + end; let _poped = Stack.pop call_stack in let last_from = try - if Db.Value.is_reachable - (Values_To_Use.get_state (Kstmt ret_id)) - then + if Db.Value.is_reachable + (Values_To_Use.get_stmt_state ret_id) + then Computer.externalize ret_id kf - (Computer.StmtStartData.find ret_id.sid) - else - raise Not_found + (Computer.StmtStartData.find ret_id) + else + raise Not_found with Not_found -> begin From_parameters.result ~current:true "Non terminating function (no dependencies)"; { Function_Froms.deps_return = @@ -686,62 +670,64 @@ deps_table = Computer.empty_from.deps_table } end in - last_from + last_from with Exit -> { Function_Froms.deps_return = Lmap_bitwise.From_Model.LOffset.empty; - deps_table = Lmap_bitwise.From_Model.empty } + deps_table = Lmap_bitwise.From_Model.empty } let compute_using_prototype_for_state state kf = - match kf.fundec with - | Definition _ -> assert false - | Declaration (_, varinfo, _,_) -> + let varinfo = Kernel_function.get_vi kf in let behaviors = !Value.valid_behaviors kf state in let assigns = Ast_info.merge_assigns behaviors in let return_deps,deps = match assigns with WritesAny -> (* [VP 2011-01-28] Shouldn't that be top? *) - Lmap_bitwise.From_Model.LOffset.empty, + Lmap_bitwise.From_Model.LOffset.empty, Lmap_bitwise.From_Model.empty - | Writes assigns -> + | Writes assigns -> let (rt_typ,_,_,_) = splitFunctionTypeVI varinfo in - let input_zone ins = - match ins with - FromAny -> Zone.top + let input_zone ins = + match ins with + FromAny -> Zone.top | From l -> (try List.fold_left (fun acc loc -> - Zone.join acc - (Locations.valid_enumerate_bits + Zone.join acc + (Locations.valid_enumerate_bits + ~for_writing:false (!Properties.Interp.loc_to_loc - ~result:None - state + ~result:None + state loc.it_content))) Zone.bottom - l + l with Invalid_argument "not an lvalue" -> From_parameters.result ~once:true ~current:true "Unable to extract precise FROM in %a" - Kernel_function.pretty_name kf; + Kernel_function.pretty kf; Zone.top) - in - let treat_assign acc (out, ins) = + in + let treat_assign acc (out, ins) = try - let output_loc = + let output_loc = !Properties.Interp.loc_to_loc ~result:None state - out.it_content - in - let output_zone = Locations.valid_enumerate_bits output_loc in - Lmap_bitwise.From_Model.add_binding ~exact:true - acc output_zone (input_zone ins) + out.it_content + in + let output_zone = + Locations.valid_enumerate_bits ~for_writing:true + output_loc + in + Lmap_bitwise.From_Model.add_binding ~exact:true + acc output_zone (input_zone ins) with Invalid_argument "not an lvalue" -> - From_parameters.result + From_parameters.result ~once:true ~current:true "Unable to extract assigns in %a" - Kernel_function.pretty_name kf; + Kernel_function.pretty kf; acc - in + in let treat_ret_assign acc (out,ins) = try let coffs = @@ -773,12 +759,25 @@ then a::ra,oa else ra,a::oa) ([],[]) assigns in - (List.fold_left treat_ret_assign - Lmap_bitwise.From_Model.LOffset.empty return_assigns, - List.fold_left - treat_assign - Lmap_bitwise.From_Model.empty - other_assigns) + let return_assigns = + match return_assigns with + | [] when Cil.isVoidType rt_typ -> + Lmap_bitwise.From_Model.LOffset.empty + | [] -> (* \from unspecified. *) + Lmap_bitwise.From_Model.LOffset.add_iset ~exact:true + (Abstract_value.Int_Intervals.from_ival_size + (Ival.of_int 0) (Bit_utils.sizeof rt_typ)) + (input_zone FromAny) + Lmap_bitwise.From_Model.LOffset.empty + | _ -> + List.fold_left treat_ret_assign + Lmap_bitwise.From_Model.LOffset.empty return_assigns + in + return_assigns, + List.fold_left + treat_assign + Lmap_bitwise.From_Model.empty + other_assigns in { deps_return = return_deps; Function_Froms.deps_table = deps } @@ -790,25 +789,24 @@ let call_site_loc = CurrentLoc.get () in From_parameters.feedback "Computing for function %a%s" - Kernel_function.pretty_name kf + Kernel_function.pretty kf (let s = ref "" in Stack.iter (fun kf -> - s := !s^" <-"^(Pretty_utils.sfprintf "%a" Kernel_function.pretty_name kf)) + s := !s^" <-"^(Pretty_utils.sfprintf "%a" Kernel_function.pretty kf)) call_stack; !s); !Db.progress (); - let result = match kf.fundec with - | Definition _ -> - compute_using_cfg kf - | Declaration _ -> - compute_using_prototype kf + let result = + if !Db.Value.use_spec_instead_of_definition kf + then compute_using_prototype kf + else compute_using_cfg kf in let result = Recording_To_Do.final_cleanup kf result in Recording_To_Do.record_kf kf result; From_parameters.feedback - "Done for function %a" Kernel_function.pretty_name kf; + "Done for function %a" Kernel_function.pretty kf; !Db.progress (); CurrentLoc.set call_site_loc; result @@ -827,19 +825,20 @@ let memo kf = Functionwise_Dependencies.memo (fun kf -> - !force_compute kf; + !force_compute kf; try Functionwise_Dependencies.find kf - with Not_found -> invalid_arg "could not compute dependencies") + with Not_found -> invalid_arg "could not compute dependencies") kf let get kf _ = memo kf end module Recording_To_Do = struct - let accept_base_in_lmap = Db.accept_base ~with_formals:false + let accept_base_in_lmap = + Db.accept_base ~with_formals:false ~with_locals:false let final_cleanup kf froms = let f k intervs = - if Db.accept_base ~with_formals:true kf k + if Db.accept_base ~with_formals:true ~with_locals:false kf k then Zone.inject k intervs else Zone.bottom in @@ -849,32 +848,43 @@ | Base.Periodic (min_valid, max_valid, _) | Base.Known (min_valid,max_valid) | Base.Unknown (min_valid,max_valid)-> - Int_Intervals.inject_bounds min_valid max_valid + Int_Intervals.inject_bounds min_valid max_valid | Base.All -> assert false(*TODO*) in let zone_substitution = Zone.cached_fold ~cache:("from cleanup", 331) ~temporary:true - ~f ~joiner ~empty:Zone.bottom ~projection + ~f ~joiner ~empty:Zone.bottom ~projection in let zone_substitution x = try - zone_substitution x + zone_substitution x with Zone.Error_Top -> Zone.top in { Function_Froms.deps_table = Lmap_bitwise.From_Model.map_and_merge - zone_substitution + zone_substitution froms.Function_Froms.deps_table - Lmap_bitwise.From_Model.empty; + Lmap_bitwise.From_Model.empty; deps_return = - Lmap_bitwise.From_Model.LOffset.map - (function b, d -> b, zone_substitution d) - froms.Function_Froms.deps_return; + Lmap_bitwise.From_Model.LOffset.map + (function b, d -> b, zone_substitution d) + froms.Function_Froms.deps_return; } let record_kf kf last_from = Functionwise_Dependencies.add kf last_from end -module From2 = Make(Db.Value)(Functionwise_From_to_use)(Recording_To_Do) +module Value_local = struct + let get_stmt_state = Db.Value.get_stmt_state + let access_expr = ref (fun s exp -> !Db.Value.access_expr (Kstmt s) exp) + let expr_to_kernel_function = + ref (fun s ~with_alarms ~deps exp -> + !Db.Value.expr_to_kernel_function (Kstmt s) ~with_alarms ~deps exp) + let lval_to_loc_with_deps = + ref (fun s ~with_alarms ~deps lval -> + !Db.Value.lval_to_loc_with_deps (Kstmt s) ~with_alarms ~deps lval) +end + +module From2 = Make(Value_local)(Functionwise_From_to_use)(Recording_To_Do) let () = force_compute := From2.compute; @@ -913,76 +923,75 @@ let call_for_individual_froms (state, call_stack) = if From_parameters.ForceCallDeps.get () then begin let current_function, call_site = List.hd call_stack in - match current_function.fundec with - Definition _ -> - let table_for_current_function = Kinstr.Hashtbl.create 7 in - call_froms_stack := - (current_function,table_for_current_function) :: !call_froms_stack - | Declaration _ -> - ( try - let _above_function, table = List.hd !call_froms_stack in - let froms = - From2.compute_using_prototype_for_state - state current_function - in - merge_call_froms table call_site froms; - record_callwise_dependencies_in_db call_site froms; - with Failure "hd" -> - From_parameters.fatal "calldeps internal error 23 empty callfromsstack %a" - Kernel_function.pretty_name current_function ) + if not (!Db.Value.use_spec_instead_of_definition current_function) then + let table_for_current_function = Kinstr.Hashtbl.create 7 in + call_froms_stack := + (current_function,table_for_current_function) :: !call_froms_stack + else + try + let _above_function, table = List.hd !call_froms_stack in + let froms = + From2.compute_using_prototype_for_state state current_function + in + merge_call_froms table call_site froms; + record_callwise_dependencies_in_db call_site froms; + with Failure "hd" -> + From_parameters.fatal "calldeps internal error 23 empty callfromsstack %a" + Kernel_function.pretty current_function end let record_for_individual_froms (call_stack, instrstates) = + let instrstates = Lazy.force instrstates in if From_parameters.ForceCallDeps.get () then begin let module Froms_To_Use = - struct - let get _f callsite = - let _current_function, table = List.hd !call_froms_stack in -(* match f.fundec with - Definition _ -> *) - begin try - Kinstr.Hashtbl.find table callsite - with Not_found -> - raise Call_did_not_take_place - - end -(* | Declaration _ -> - Functionwise_From_to_use.get f callsite *) - end + struct + let get _f callsite = + let _current_function, table = List.hd !call_froms_stack in +(* match f.fundec with + Definition _ -> *) + begin try + Kinstr.Hashtbl.find table callsite + with Not_found -> + raise Call_did_not_take_place + + end +(* | Declaration _ -> + Functionwise_From_to_use.get f callsite *) + end in let module Values_To_Use = - struct - let get_state k = - try Kinstr.Hashtbl.find instrstates k - with Not_found -> Relations_type.Model.bottom + struct + let get_stmt_state s = + try Stmt.Hashtbl.find instrstates s + with Not_found -> Cvalue.Model.bottom (* TODO: This should be better factored with Kinstr ! *) - let lval_to_loc_with_deps kinstr ~with_alarms:_ ~deps lv = - let state = get_state kinstr in + let lval_to_loc_with_deps kinstr ~with_alarms:_ ~deps lv = + let state = get_stmt_state kinstr in !Db.Value.lval_to_loc_with_deps_state state - ~deps lv + ~deps lv let lval_to_loc_with_deps = ref lval_to_loc_with_deps let expr_to_kernel_function kinstr ~with_alarms:_ ~deps exp = - let state = get_state kinstr in - !Db.Value.expr_to_kernel_function_state state ~deps exp + let state = get_stmt_state kinstr in + !Db.Value.expr_to_kernel_function_state state ~deps exp let expr_to_kernel_function = ref expr_to_kernel_function let access_expr kinstr expr = - let state = get_state kinstr in - !Db.Value.eval_expr ~with_alarms:CilE.warn_none_mode state expr + let state = get_stmt_state kinstr in + !Db.Value.eval_expr ~with_alarms:CilE.warn_none_mode state expr let access_expr = ref access_expr end in let module Recording_To_Do = struct - let accept_base_in_lmap kf base = - let fundec = Kernel_function.get_definition kf in - not (Base.is_formal_or_local base fundec) - let final_cleanup _kf froms = froms - let record_kf _kf _last_froms = () + let accept_base_in_lmap kf base = + let fundec = Kernel_function.get_definition kf in + not (Base.is_formal_or_local base fundec) + let final_cleanup _kf froms = froms + let record_kf _kf _last_froms = () end in let module Callwise_Froms = @@ -994,15 +1003,15 @@ (* pop + record in top of stack the froms of function that just finished *) match !call_froms_stack with (current_function2, _) :: (((_caller, table) :: _) as tail) -> - assert ( - if current_function2 != current_function then begin - From_parameters.fatal "calldeps %a != %a@." - Kernel_function.pretty_name current_function (* g *) - Kernel_function.pretty_name current_function2; (* f *) - end else - true); - call_froms_stack := tail; - merge_call_froms table call_site froms + assert ( + if current_function2 != current_function then begin + From_parameters.fatal "calldeps %a != %a@." + Kernel_function.pretty current_function (* g *) + Kernel_function.pretty current_function2; (* f *) + end else + true); + call_froms_stack := tail; + merge_call_froms table call_site froms | _ -> (* the entry point, probably *) Callwise_Dependencies.mark_as_computed () @@ -1012,8 +1021,8 @@ Cmdline.run_after_configuring_stage (fun () -> if From_parameters.ForceCallDeps.get() then begin - Db.Value.Record_Value_Callbacks.extend record_for_individual_froms; - Db.Value.Call_Value_Callbacks.extend call_for_individual_froms + Db.Value.Record_Value_Callbacks.extend record_for_individual_froms; + Db.Value.Call_Value_Callbacks.extend call_for_individual_froms end) let find_available kinstr = @@ -1026,38 +1035,42 @@ else begin match kinstr with | Kstmt ({skind = Instr(Call (_,funcexp,_,_))}) -> - let _, called_functions = - !Value.expr_to_kernel_function - ~with_alarms:CilE.warn_none_mode - kinstr ~deps:None funcexp - in - let treat_kf _kf acc = - let kf_froms = (assert false) - in - match acc with - None -> Some kf_froms - | Some froms -> - Some (Function_Froms.join kf_froms froms) - in - let froms = - Kernel_function.Hptset.fold treat_kf called_functions None - in - begin - match froms with - None -> assert false (* TODO: do something *) - | Some f -> f - end + let _, called_functions = + !Value.expr_to_kernel_function + ~with_alarms:CilE.warn_none_mode + kinstr ~deps:None funcexp + in + let treat_kf _kf acc = + let kf_froms = (assert false) + in + match acc with + None -> Some kf_froms + | Some froms -> + Some (Function_Froms.join kf_froms froms) + in + let froms = + Kernel_function.Hptset.fold treat_kf called_functions None + in + begin + match froms with + None -> assert false (* TODO: do something *) + | Some f -> f + end | _ -> - From_parameters.fatal "internal error 458 : From.find_available called on non-Call statement." + From_parameters.fatal "internal error 458 : From.find_available called on non-Call statement." end -let display fmt = - Format.fprintf fmt "@["; +let display_aux pp = !Db.Semantic_Callgraph.topologically_iter_on_functions (fun k -> - if !Db.Value.is_called k then Format.fprintf fmt "@[Function %a:@\n%a@]" - Kernel_function.pretty_name k !Db.From.pretty k); - Format.fprintf fmt "@]" + if !Db.Value.is_called k then + pp ("Function %a:@\n%a@." : (_, _, _, _, _, _) format6) + Kernel_function.pretty k !Db.From.pretty k) + +let display fmt = + Format.fprintf fmt "@["; + display_aux (Format.fprintf fmt); + Format.fprintf fmt "@]" let force_compute_all () = !Db.Value.compute (); @@ -1095,7 +1108,7 @@ method vstmt s = if Value.is_reachable - (Value.get_state (Kstmt (Cilutil.out_some self#current_stmt))) + (Value.get_stmt_state (Cilutil.out_some self#current_stmt)) then begin match s.skind with | UnspecifiedSequence seq -> @@ -1105,85 +1118,85 @@ seq; SkipChildren (* do not visit the additional lvals *) | If (_cond, _th, _el, _) -> - DoChildren (* for _cond and for the statements in _th, _el *) + DoChildren (* for _cond and for the statements in _th, _el *) | Loop _ | Block _ -> - DoChildren (* for the statements *) + DoChildren (* for the statements *) | Instr _ -> - DoChildren (* for Calls *) + DoChildren (* for Calls *) | Return _ | Goto _ | Break _ | Continue _ -> - SkipChildren + SkipChildren | Switch _ | TryExcept _ | TryFinally _ -> assert false end else SkipChildren method stmt_froms = let stmt = Cilutil.out_some (self#current_stmt) in - IH.find froms stmt.sid + Stmt.Hashtbl.find froms stmt method vlval lv = let deps,loc = !Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - (Kstmt (Cilutil.out_some self#current_stmt)) - lv + ~deps:Zone.bottom + (Kstmt (Cilutil.out_some self#current_stmt)) + lv in - let bits_loc = valid_enumerate_bits loc in + let bits_loc = valid_enumerate_bits ~for_writing:false loc in let all = Zone.join bits_loc deps in let froms = self#stmt_froms in let all_f = Lmap_bitwise.From_Model.find froms all in self#join all_f; (* Format.printf "lval: all %a all_f %a@." - Zone.pretty all - Zone.pretty all_f; *) + Zone.pretty all + Zone.pretty all_f; *) SkipChildren method vinst i = - if Value.is_reachable - (Value.get_state (Kstmt (Cilutil.out_some self#current_stmt))) + let current_stmt = Cilutil.out_some self#current_stmt in + if Value.is_reachable (Value.get_stmt_state current_stmt) then begin match i with | Call (_lv_opt,exp,_args,_) -> - let current_stmt = Kstmt (Cilutil.out_some self#current_stmt) in + let current_stmt = Cilutil.out_some self#current_stmt in let deps_callees, _callees = !Value.expr_to_kernel_function ~with_alarms:CilE.warn_none_mode - ~deps:(Some Zone.bottom) - current_stmt exp + ~deps:(Some Zone.bottom) + (Kstmt current_stmt) exp in - let states_with_formals = - try Kinstr.Hashtbl.find callwise_states_with_formals current_stmt - with Not_found -> assert false - in - let all_f = - List.fold_left - (fun acc (kf, state_with_formals) -> - if Kernel_function.is_definition kf - then - let deps = - try - Functionwise_Pathdeps.find kf - with Not_found -> - Format.printf "pathdeps dependencies not found for %a@." - Kernel_function.pretty_name kf; - assert false - in - let deps_f = Lmap_bitwise.From_Model.find - state_with_formals - deps - in - Zone.join acc deps_f - else begin - Format.printf "Assuming library function %a has no path dependencies@." - Kernel_function.pretty_name kf; - acc - end) - deps_callees - states_with_formals - in - self#join all_f; + let states_with_formals = + try Stmt.Hashtbl.find callwise_states_with_formals current_stmt + with Not_found -> assert false + in + let all_f = + List.fold_left + (fun acc (kf, state_with_formals) -> + if not (!Db.Value.use_spec_instead_of_definition kf) + then + let deps = + try + Functionwise_Pathdeps.find kf + with Not_found -> + Format.printf "pathdeps dependencies not found for %a@." + Kernel_function.pretty kf; + assert false + in + let deps_f = Lmap_bitwise.From_Model.find + state_with_formals + deps + in + Zone.join acc deps_f + else begin + Format.printf "Assuming library function %a has no path dependencies@." + Kernel_function.pretty kf; + acc + end) + deps_callees + states_with_formals + in + self#join all_f; SkipChildren | _ -> SkipChildren end @@ -1193,18 +1206,18 @@ match exp.enode with | AddrOf lv | StartOf lv -> let deps,_loc = - !Value.lval_to_loc_with_deps + !Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - (Kstmt (Cilutil.out_some self#current_stmt)) - lv + ~deps:Zone.bottom + (Kstmt (Cilutil.out_some self#current_stmt)) + lv in let froms = self#stmt_froms in let deps_f = Lmap_bitwise.From_Model.find froms deps in self#join deps_f; - (* Format.printf "AddrOf: deps %a deps_f %a@." - Zone.pretty deps - Zone.pretty deps_f; *) + (* Format.printf "AddrOf: deps %a deps_f %a@." + Zone.pretty deps + Zone.pretty deps_f; *) SkipChildren | _ -> DoChildren @@ -1221,13 +1234,13 @@ ignore (visitCilFunction (computer:>cilVisitor) f); let result = computer#result in Format.printf "Path dependencies of %s: %a@." - name - Zone.pretty result; + name + Zone.pretty result; try - ignore (Functionwise_Pathdeps.find kf); - assert false + ignore (Functionwise_Pathdeps.find kf); + assert false with Not_found -> - Functionwise_Pathdeps.add kf result + Functionwise_Pathdeps.add kf result end | Declaration _ -> assert false @@ -1242,32 +1255,40 @@ let forcecalldeps = From_parameters.ForceCallDeps.get () in if forcedeps then begin !Db.From.compute_all (); - From_parameters.result "%t@\n====== DEPENDENCIES COMPUTED ======" !Db.From.display + From_parameters.feedback "====== DEPENDENCIES COMPUTED ======"; + display_aux (fun fm -> From_parameters.result fm); + From_parameters.feedback "====== END OF DEPENDENCIES ======" end; if forcecalldeps then !Db.From.compute_all_calldeps (); if not_quiet && forcecalldeps then begin - From_parameters.result "====== DISPLAYING CALLWISE DEPENDENCIES ======@\n%t@\n====== END OF CALLWISE DEPENDENCIES ======" - (fun fmt -> - !Db.From.Callwise.iter + From_parameters.feedback "====== DISPLAYING CALLWISE DEPENDENCIES ======"; + !Db.From.Callwise.iter (fun ki d -> let id,typ = - match ki with - | Cil_types.Kglobal -> + match ki with + | Cil_types.Kglobal -> "entry point", - Kernel_function.get_type (fst (Globals.entry_point ())) - | Cil_types.Kstmt s -> - string_of_int s.Cil_types.sid, - let f = + Kernel_function.get_type (fst (Globals.entry_point ())) + | Cil_types.Kstmt s -> + let f = try Kernel_function.Hptset.min_elt - (Db.Value.call_to_kernel_function s) + (Db.Value.call_to_kernel_function s) with Not_found -> assert false - in + in + let id = + Pretty_utils.sfprintf "%a at %a (statement %d)" + Kernel_function.pretty f + pretty_loc_simply (Kstmt s) + s.Cil_types.sid + in + id, Kernel_function.get_type f in - Format.fprintf fmt - "@[call %s:@ %a@\n@]" - id (Function_Froms.pretty_with_type typ) d)) + From_parameters.result + "@[call %s:@\n%a@\n@]@ " + id (Function_Froms.pretty_with_type typ) d); + From_parameters.feedback "====== END OF CALLWISE DEPENDENCIES ======"; end let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/src/gui/analyses_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/analyses_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/analyses_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/analyses_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -41,14 +41,14 @@ (fun () -> match dialog#run () with | `EXECUTE -> - let run f = - loader f; - !Db.Main.play (); - host_window#reset () - in - Extlib.may run dialog#filename; + let run f = + loader f; + !Db.Main.play (); + host_window#reset () + in + Extlib.may run dialog#filename; | `DELETE_EVENT | `CANCEL -> - ()); + ()); dialog#destroy () let run_script = @@ -61,40 +61,48 @@ let insert (main_ui: Design.main_window_extension_points) = let menu_manager = main_ui#menu_manager () in let stop = ref (fun () -> assert false) (* delayed *) in + let stop_sensitive = ref false (* can the stop button be clicked? *) in let default_analyses_items = menu_manager#add_plugin [ - Menu_manager.ToolMenubar(`PROPERTIES, "Configure and run analyses"), - main_ui#launcher; - Menu_manager.Menubar(Some `EXECUTE, "Compile and run an OCaml Script"), - (fun () -> run_script main_ui); - Menu_manager.Menubar(None, "Load and run an OCaml Module"), - (fun () -> run_module main_ui); - Menu_manager.Toolbar(`STOP, "Stop running analyses"), - (fun () -> !stop ()) (* eta-expansion required *) + Menu_manager.toolmenubar ~icon:`PROPERTIES + ~label:"Analyses" ~tooltip:"Configure and run analyses" + (Menu_manager.Unit_callback main_ui#launcher); + Menu_manager.menubar ~icon:`EXECUTE "Compile and run an OCaml Script" + (Menu_manager.Unit_callback (fun () -> run_script main_ui)); + Menu_manager.menubar "Load and run an OCaml Module" + (Menu_manager.Unit_callback (fun () -> run_module main_ui)); + Menu_manager.toolbar ~sensitive:(fun () -> !stop_sensitive) ~icon:`STOP + ~label:"Stop" ~tooltip:"Stop currently running analyses" + (Menu_manager.Unit_callback (fun () -> !stop ())); ] in default_analyses_items.(0)#add_accelerator `CONTROL 'r'; let stop_button = Extlib.the default_analyses_items.(3)#tool_button in - stop_button#misc#set_sensitive false; let old_progress = ref !Db.progress in stop := (fun () -> - stop_button#misc#set_sensitive false; Db.progress := - (fun () -> + (fun () -> Db.progress := !old_progress; raise Db.Cancel)); + Gtk_helper.register_locking_machinery ~lock_last:true ~lock:(fun cancelable -> + if !stop_sensitive then Gui_parameters.warning + "Inconsistent state for stop button. Ignoring."; old_progress := !Db.progress; - menu_manager#set_sensitive false; - stop_button#misc#set_sensitive cancelable) + menu_manager#set_sensitive false; + if cancelable then (stop_button#misc#set_sensitive true; + stop_sensitive := true); + ) ~unlock:(fun () -> Db.progress := !old_progress; - menu_manager#set_sensitive true; - stop_button#misc#set_sensitive false) + menu_manager#set_sensitive true; + stop_button#misc#set_sensitive false; + stop_sensitive := false; + ) () let () = Design.register_extension insert diff -Nru frama-c-20110201+carbon+dfsg/src/gui/book_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/book_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/book_manager.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/book_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,189 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Pretty_source + +module Q = Qstack.Make + (struct + type t = GSourceView2.source_view + let equal x y = x == y + end) + +type t = { + notebook : GPack.notebook ; + views : Q.t ; +} + +let make ?tab_pos ?packing () = + let notebook = GPack.notebook + ~scrollable:true ~show_tabs:true ?tab_pos ?packing () + in + notebook#set_enable_popup true ; + { + notebook = notebook ; + views = Q.create (); + } + +let get_notebook t = t.notebook + + +let set_current_view t n = + if (n>=0) && (n < (Q.length t.views)) then t.notebook#goto_page n + +let prepend_source_tab w titre = + Gui_parameters.debug "prepend_source_tab"; + (* insert one extra tab in the source window w, with label *) + let label = GMisc.label ~text:titre () in + let sw = GBin.scrolled_window + ~vpolicy:`AUTOMATIC + ~hpolicy:`AUTOMATIC + ~packing:(fun arg -> + ignore + (w.notebook#prepend_page ~tab_label:label#coerce arg)) + () + in + let window = (Source_viewer.make ~packing:sw#add) in + (* Remove default pango menu for textviews *) + ignore (window#event#connect#button_press ~callback: + (fun ev -> GdkEvent.Button.button ev = 3)); + Q.add window w.views; + w.notebook#goto_page 0; + window + +let get_nth_page (t:t) n = + let nb = t.notebook in + nb#get_nth_page n (* Deprecated *) + +let current_page (t:t) = + let nb = t.notebook in + nb#current_page + +let last_page t = Q.length t.views - 1 + +(* ABP and methods to manage this memory *) +let get_current_view (t:t) = + let nb = t.notebook in + let cp = nb#current_page in + Gui_parameters.debug "get_current_view: %d" cp; + Q.nth cp t.views + +let get_current_index (t:t) = + let cp = t.notebook#current_page in + Gui_parameters.debug "get_current_index: %d" cp; + cp + +let delete_view (t:t) cp = + let nb = t.notebook in + Gui_parameters.debug "delete_current_view - cur is page %d" cp; + Q.remove (Q.nth cp t.views) t.views; + nb#remove_page cp; + let last = pred (Q.length t.views) in + Gui_parameters.debug "Going to page (delete_current_view) %d" last; + nb#goto_page last + +(* delete within w the tab that contains window win *) +let delete_view_and_loc w win () = + Gui_parameters.debug "delete_view_and_loc "; + let idx = Q.idx win w.views in + delete_view w idx + +let delete_current_view t = delete_view t t.notebook#current_page + +let delete_all_views (t:t) = + Q.iter (fun _ -> t.notebook#remove_page 0) t.views; + Q.clear t.views + +let append_view (t:t) (v:GSourceView2.source_view) = + let nb = t.notebook in + let next = Q.length t.views in + let text = Printf.sprintf "Page %d" next in + let label = GMisc.label ~text:text () in + let sw = GBin.scrolled_window + ~vpolicy:`AUTOMATIC + ~hpolicy:`AUTOMATIC + ~packing:(fun arg -> + ignore + (nb#append_page ~tab_label:label#coerce arg)) () in + sw#add (v:>GObj.widget); + nb#goto_page next; + Gui_parameters.debug "Going to page (append_view) %d" next; + Q.add_at_end v t.views; + Gui_parameters.debug "append_view - nb pages is %d" (Q.length t.views); + Gui_parameters.debug "append_view - current nb page is %d" nb#current_page + +let get_nth_view t (n:int) = Q.nth n t.views + +let enable_popup (t:t) (b:bool) = + let nb = t.notebook in + nb#set_enable_popup b + +let set_scrollable (t:t) (b:bool) = + let nb = t.notebook in + nb#set_scrollable b + +(* get length of the current source_views list *) +let length t = Q.length t.views + + +let append_source_tab w titre = + Gui_parameters.debug "append_source_tab"; + (* insert one extra tab in the source window w, with some title *) + let composed_label = GPack.hbox () in + + let _ = GMisc.label ~text:(titre) ~packing:composed_label#add () in + + let cbutton = GButton.button ~packing:composed_label#add () in + + cbutton#set_use_stock false ; + cbutton#set_label "X"; + cbutton#misc#set_size_request ~width:20 ~height:20 (); + + let sw = GBin.scrolled_window + ~vpolicy:`AUTOMATIC + ~hpolicy:`AUTOMATIC + ~packing:(fun arg -> + ignore + (w.notebook#append_page ~tab_label:composed_label#coerce arg)) + (* + ~packing:(fun arg -> + ignore + (w.notebook#append_page ~tab_label:label#coerce arg)) *) + () + in + let window = (Source_viewer.make ~packing:sw#add) in + ignore + (cbutton#connect#clicked + ~callback:(fun () -> delete_view_and_loc w window ())); + (* Remove default pango menu for textviews *) + ignore (window#event#connect#button_press ~callback: + (fun ev -> GdkEvent.Button.button ev = 3)); + Q.add_at_end window w.views; + let last = pred (Q.length w.views) in + (* THIS CALLS THE SWITCH_PAGE CALLBACK IMMEDIATELY! *) + w.notebook#goto_page last; + window + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/book_manager.mli frama-c-20111001+nitrogen+dfsg/src/gui/book_manager.mli --- frama-c-20110201+carbon+dfsg/src/gui/book_manager.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/book_manager.mli 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,73 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] Yet useless for the Frama-C platform. It seems to be only + used by a CEA private plug-in (AP via LC). + To the authors/users of this module: please document it. *) + +type t + +val make: + ?tab_pos:Gtk.Tags.position -> ?packing:(GObj.widget -> unit) -> unit -> t + +val get_notebook: t -> GPack.notebook + +val append_source_tab : t -> string -> GSourceView2.source_view + +val prepend_source_tab : t -> string -> GSourceView2.source_view + +val get_nth_page: t -> int -> GObj.widget + +val current_page: t -> int + +val last_page: t -> int + +val set_current_view: t -> int -> unit + +val get_current_view: t -> GSourceView2.source_view + +val get_current_index: t -> int + +val delete_current_view: t -> unit + +val delete_view: t -> int -> unit + +val delete_all_views: t -> unit + +val append_view: t -> GSourceView2.source_view -> unit + +val get_nth_view: t -> int -> GSourceView2.source_view + +val enable_popup : t -> bool -> unit + +val set_scrollable : t -> bool -> unit + +val length: t -> int + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/debug_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/debug_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/debug_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/debug_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -25,7 +25,11 @@ open Dgraph let graph_view ~packing mk_dot = - let f = Extlib.temp_file_cleanup_at_exit "framac_graph_view" "dot" in + let f = + try Extlib.temp_file_cleanup_at_exit "framac_graph_view" "dot" + with Extlib.Temp_file_error s -> + Gui_parameters.abort "cannot create temporary file: %s" s + in mk_dot f; snd (DGraphContainer.Dot.from_dot_with_commands @@ -36,9 +40,10 @@ let state_dependency_graph ~packing () = graph_view ~packing State_dependency_graph.Dynamic.dump -let status_dependency_graph ~packing () = - let g = Properties_status.Consolidation_tree.get_full_graph () in - graph_view ~packing (Properties_status.Consolidation_tree.dump g) +(* [JS 2011/07/05] to be reimplemented *) +let status_dependency_graph ~packing:_ () = assert false +(* let g = Properties_status.Consolidation_tree.get_full_graph () in + graph_view ~packing (Properties_status.Consolidation_tree.dump g)*) let graph_window main_window title mk_view = let height = int_of_float (float main_window#default_height *. 3. /. 4.) in @@ -52,19 +57,22 @@ window#show (); view#adapt_zoom () +open Menu_manager + let () = Design.register_extension (fun window -> let mk_graph = graph_window window#main_window in ignore - ((window#menu_manager ())#add_debug - ~show:(fun () -> Kernel.debug_atleast 1) - [ (let s = "State Dependency Graph" in - Menu_manager.Menubar(None, s), - fun () -> mk_graph s state_dependency_graph); - let s = "Status Graph" in - Menu_manager.Menubar(None, s), - fun () -> mk_graph s status_dependency_graph ])) + ((window#menu_manager ())#add_debug + ~show:(fun () -> Kernel.debug_atleast 1) + [ (let s = "State Dependency Graph" in + menubar s + (Unit_callback (fun () -> mk_graph s state_dependency_graph))); + (let s = "Status Graph" in + menubar s + (Unit_callback (fun () -> mk_graph s status_dependency_graph))) + ])) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/gui/design.ml frama-c-20111001+nitrogen+dfsg/src/gui/design.ml --- frama-c-20110201+carbon+dfsg/src/gui/design.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/design.ml 2011-10-10 08:38:27.000000000 +0000 @@ -21,28 +21,20 @@ (**************************************************************************) (** Main GUI skeleton *) -open Properties_status open Cil_types open Cil_datatype open Cil -open Db_types open Db open Pretty_source open Gtk_helper -module LastSelected = - State_builder.Option_ref - (Localizable) - (struct - let name = "Design.LastSelected" - let dependencies = [Ast.self] - let kind = `Internal - end) - -let apply_on_selected = LastSelected.may - let use_external_viewer = false +let apply_on_selected = + Gui_parameters.deprecated + "Design.apply_on_selected" + ~now:"History.apply_on_selected" History.apply_on_selected + let highlight_range ~scroll tag (v:GSourceView2.source_view) pb pe = let b = v#source_buffer in let start = b#get_iter (`OFFSET pb) in @@ -57,11 +49,22 @@ inherit error_manager method buffer : GSourceView2.source_buffer method locs : Pretty_source.Locs.state option - method rehighlight : unit + method rehighlight: unit + method redisplay: unit +end + +class type view_code = object + method scroll : Pretty_source.localizable -> unit + method view_stmt : stmt -> unit + method view_original_stmt : stmt -> location + method view_original : location -> unit + method display_globals : global list -> unit + method select_or_display_global : global -> unit end class type main_window_extension_points = object inherit Launcher.basic_main + inherit view_code method toplevel : main_window_extension_points method menu_manager: unit -> Menu_manager.menu_manager method file_tree : Filetree.t @@ -85,12 +88,9 @@ (main_window_extension_points -> (string * GObj.widget *(unit-> unit) option)) -> unit method rehighlight : unit -> unit - method scroll : localizable -> unit + method redisplay : unit -> unit method reactive_buffer: reactive_buffer option method original_source_viewer : Source_manager.t - method view_stmt: stmt -> unit - method view_original_stmt : stmt -> location - method view_original : location -> unit method reset : unit -> unit method error : 'a. ?parent:GWindow.window_skel -> ('a, Format.formatter, unit) format @@ -131,15 +131,19 @@ include Hashtbl.Make (struct type t = global list - let equal = List.for_all2 (==) + let equal x y = + try List.for_all2 (==) x y + with Invalid_argument _ -> false let hash = Hashtbl.hash end) let tbl = create 17 - let find k = let r = find tbl k in - r#rehighlight; - r + let find k = + let r = find tbl k in + r#rehighlight; + r + + let add k = add tbl k - let add = add tbl let clear () = clear tbl end @@ -149,105 +153,117 @@ ~activating globals = + (*Format.printf "filetree selector:%b@." (not was_activated && activating);*) if not was_activated && activating then begin let source = main_ui#source_viewer in - main_ui#display_globals globals; + (match globals with + | Filetree.File (f, l) -> + Source_manager.load_file + main_ui#original_source_viewer + ~filename:f ~line:1 () ; + main_ui#display_globals l + | Filetree.Global g -> main_ui#display_globals [g] + ); source#scroll_to_mark ~use_align:true ~xalign:1.0 ~yalign:0.5 `INSERT; - let print_one_global (v,loc) = - main_ui#protect - ~cancelable:false - (fun () -> + let print_one_global prefix (v,loc) = + main_ui#protect ~cancelable:false + (fun () -> main_ui#view_original loc; - try - let kf = Globals.Functions.get v in - main_ui#pretty_information - "Function '%a'@." Kernel_function.pretty_name kf - with Not_found -> main_ui#error "No such function: please report") + main_ui#pretty_information "%s '%s'@." prefix v.vname) in main_ui#annot_window#buffer#set_text ""; begin match globals with - | [] -> main_ui#pretty_information "No globals in this file@." - | [GFun ({svar=v},loc)] -> - print_one_global (v,loc) - | _ -> - let first_global = ref None in - let (gfun,gtype,gcomp,genum,gvardecl,gvar) = - List.fold_right - (fun g (gfun,gtype,gcomp,genum,gvardecl,gvar) -> - match g with - GFun ({svar=v},loc) -> - (match !first_global with - | None -> first_global:=Some (v,loc) - | Some _ -> ()); - (g::gfun,gtype,gcomp,genum,gvardecl,gvar) - | GType _ -> (gfun,g::gtype,gcomp,genum,gvardecl,gvar) - | GCompTagDecl _ -> (gfun,gtype,g::gcomp,genum,gvardecl,gvar) - | GEnumTagDecl _ -> (gfun,gtype,gcomp,g::genum,gvardecl,gvar) - | GVarDecl _ -> (gfun,gtype,gcomp,genum,g::gvardecl,gvar) - | GVar _ -> (gfun,gtype,gcomp,genum,gvardecl,g::gvar) - | _ -> - (* PC does this happen? *) - (gfun,gtype,gcomp,genum,gvardecl,gvar)) - globals - ([],[],[],[],[],[]) - in - let printing - (head:string) - (f:Format.formatter -> 'a -> unit) - (l:'a list) - = - if l <> [] then - main_ui#pretty_information "@[%s @[%a@]@]@." head - (Cilutil.pretty_list (Cilutil.space_sep "") f) - l - in - printing - "Functions:" - (fun fmt -> (function GFun ({svar=v},_) -> - Ast_info.pretty_vname fmt v - | _ -> assert false)) - gfun; - printing - "Types:" - (function fmt -> (function (GType ({tname=name},_)) -> - Format.pp_print_string fmt name - | _ -> assert false)) - gtype; - printing - "Composite types:" - (function fmt -> - (function GCompTagDecl - ({cname=name},_) |GCompTag ({cname=name},_)-> - Format.pp_print_string fmt name - | _ -> assert false)) - gcomp; - printing - "Enums:" - (function fmt -> - (function GEnumTagDecl - ({ename=name},_) | GEnumTag ({ename=name},_)-> - Format.pp_print_string fmt name - |_ -> assert false)) - genum; - printing - "Declared variables:" - (function fmt -> - (function GVarDecl (_,v,_) -> - Ast_info.pretty_vname fmt v - | _ -> assert false)) - gvardecl; - printing - "Variables:" - (fun fmt -> (function GVar(v,_,_) -> - Ast_info.pretty_vname fmt v - | _ -> assert false)) - gvar; + | Filetree.Global g -> + begin + History.push (History.Global g); + match g with + | GFun ({svar=v},loc) -> print_one_global "Function" (v,loc) + | GVar (v,_,loc) -> print_one_global "Variable" (v,loc) + | GVarDecl (_, v, loc) -> + if Cil.isFunctionType v.vtype + then print_one_global "Declared function" (v,loc) + else print_one_global "Variable" (v,loc) + | _ -> () (* cannot currently happen, we do not display the + other globals in the filetree *) + end + | Filetree.File (f, globals) -> + let first_global = ref None in + let (gfun,gtype,gcomp,genum,gvardecl,gvar) = + List.fold_right + (fun g (gfun,gtype,gcomp,genum,gvardecl,gvar) -> + match g with + | GFun ({svar=v},loc) -> + (match !first_global with + | None -> first_global:=Some (v,loc) + | Some _ -> ()); + (g::gfun,gtype,gcomp,genum,gvardecl,gvar) + | GType _ -> (gfun,g::gtype,gcomp,genum,gvardecl,gvar) + | GCompTagDecl _ -> (gfun,gtype,g::gcomp,genum,gvardecl,gvar) + | GEnumTagDecl _ -> (gfun,gtype,gcomp,g::genum,gvardecl,gvar) + | GVarDecl _ -> (gfun,gtype,gcomp,genum,g::gvardecl,gvar) + | GVar _ -> (gfun,gtype,gcomp,genum,gvardecl,g::gvar) + | _ -> (gfun,gtype,gcomp,genum,gvardecl,gvar)) + globals + ([],[],[],[],[],[]) + in + main_ui#pretty_information "@[File %s@]@." f; + let printing + (head:string) + (f:Format.formatter -> 'a -> unit) + (l:'a list) + = + if l <> [] then + main_ui#pretty_information "@[%s @[%a@]@]@." head + (Cilutil.pretty_list (Cilutil.space_sep "") f) + l + in + printing + "Functions:" + (fun fmt -> (function GFun ({svar=v},_) -> + Varinfo.pretty_vname fmt v + | _ -> assert false)) + gfun; + printing + "Types:" + (function fmt -> (function (GType ({tname=name},_)) -> + Format.pp_print_string fmt name + | _ -> assert false)) + gtype; + printing + "Composite types:" + (function fmt -> + (function GCompTagDecl + ({cname=name},_) |GCompTag ({cname=name},_)-> + Format.pp_print_string fmt name + | _ -> assert false)) + gcomp; + printing + "Enums:" + (function fmt -> + (function GEnumTagDecl + ({ename=name},_) | GEnumTag ({ename=name},_)-> + Format.pp_print_string fmt name + |_ -> assert false)) + genum; + printing + "Declared variables:" + (function fmt -> + (function GVarDecl (_,v,_) -> + Varinfo.pretty_vname fmt v + | _ -> assert false)) + gvardecl; + printing + "Variables:" + (fun fmt -> (function GVar(v,_,_) -> + Varinfo.pretty_vname fmt v + | _ -> assert false)) + gvar; end end - let pretty_predicate_status fmt p = - Format.fprintf fmt "Status: %a@." Properties_status.pretty_all p + let s = Property_status.get p in + Format.fprintf fmt "Status: %a@." Property_status.pretty s let rec to_do_on_select (menu_factory:GMenu.menu GMenu.factory) @@ -259,83 +275,71 @@ main_ui#pretty_information "Function: %t@." (fun fmt -> match kf with - None -> Format.pp_print_string fmt "" - | Some kf -> - Kernel_function.pretty_name fmt kf); + | None -> Format.pp_print_string fmt "" + | Some kf -> Kernel_function.pretty fmt kf); match stmt with - Kglobal -> () - | Kstmt ki -> - let loc = match loc with - | None -> main_ui#view_original_stmt ki - | Some loc -> - main_ui#view_original loc; - loc - in - let skind = - if Gui_parameters.debug_atleast 1 then - match ki with - | {skind=Block _} -> "Block " - | {skind=Instr (Skip _)} -> "Skip " - | _ -> "" - else "" - in - main_ui#pretty_information - "%sStatement: %d (line %d in %s)@." - skind - ki.sid - (fst loc).Lexing.pos_lnum - (fst loc).Lexing.pos_fname + | Kglobal -> () + | Kstmt ki -> + let loc = match loc with + | None -> main_ui#view_original_stmt ki + | Some loc -> + main_ui#view_original loc; + loc + in + let skind = + if Gui_parameters.debug_atleast 1 then + match ki with + | {skind=Block _} -> "Block " + | {skind=Instr (Skip _)} -> "Skip " + | _ -> "" + else "" + in + main_ui#pretty_information + "%sStatement: %d (line %d in %s)@." + skind + ki.sid + (fst loc).Lexing.pos_lnum + (fst loc).Lexing.pos_fname in - LastSelected.set selected; - let tree_view = main_ui#file_tree in + History.push (History.Localizable selected); let annot = main_ui#annot_window#buffer in - if button = 1 then - begin annot#set_text ""; - match selected with + if button = 1 then begin + annot#set_text ""; + match selected with | PStmt (kf, stmt) -> - main_ui#protect - ~cancelable:false - (fun () -> - current_statement_msg (Some kf) (Kstmt stmt); - (* Code annotations for this statement *) - Annotations.single_iter_stmt - (fun a -> - let pos, a = match a with - | Before a -> "Before", a - | After a -> "After", a - in - let user, s, status = match a with - | User a -> - "user", - (fun fmt -> - !Ast_printer.d_code_annotation fmt a), - (fun fmt -> - let ip = Property.ip_of_code_annot kf stmt a in - Pretty_utils.pp_list ~sep:"@\n" - pretty_predicate_status fmt ip) - | AI (_,a) -> - "alarm", - (fun fmt -> !Ast_printer.d_code_annotation fmt a), - (fun fmt -> - let ip = Property.ip_of_code_annot kf stmt a in - Pretty_utils.pp_list ~sep:"@\n" - pretty_predicate_status fmt ip) - in - main_ui#pretty_information "@[%s(%s): @[%t@]@]@.%t@." - pos user s status) - stmt) + main_ui#protect + ~cancelable:false + (fun () -> + current_statement_msg (Some kf) (Kstmt stmt); + (* Code annotations for this statement *) + Annotations.single_iter_stmt + (fun a -> + let pos, a = "Before", a in + let user, s, status = match a with + | User a -> + "user", + (fun fmt -> + !Ast_printer.d_code_annotation fmt a), + (fun fmt -> + let ip = Property.ip_of_code_annot kf stmt a in + Pretty_utils.pp_list ~sep:"@\n" + pretty_predicate_status fmt ip) + | AI (_,a) -> + "alarm", + (fun fmt -> !Ast_printer.d_code_annotation fmt a), + (fun fmt -> + let ip = Property.ip_of_code_annot kf stmt a in + Pretty_utils.pp_list ~sep:"@\n" + pretty_predicate_status fmt ip) + in + main_ui#pretty_information "@[%s(%s): @[%t@]@]@.%t@." + pos user s status) + stmt) | PIP (Property.IPCodeAnnot (kf,stmt,ca) as ip) -> current_statement_msg - ?loc:(Cil_datatype.Code_annotation.loc ca) (Some kf) (Kstmt stmt); + ?loc:(Cil_datatype.Code_annotation.loc ca) (Some kf) (Kstmt stmt); main_ui#pretty_information "Code annotation id: %d@.%a@." ca.annot_id pretty_predicate_status ip - | PIP(Property.IPBehavior (_,stmt,{b_name=n}) as ip) -> - main_ui#pretty_information "%s behavior %s@.%a@." - (match stmt with - | Kglobal -> "Function" - | Kstmt _ -> "Statement") - n - pretty_predicate_status ip | PIP(Property.IPAssigns _ as ip) -> main_ui#pretty_information "This is an assigns clause@.%a@." pretty_predicate_status ip @@ -344,72 +348,79 @@ pretty_predicate_status ip | PIP (Property.IPPredicate (Property.PKRequires _,_,_,_) as ip) -> main_ui#pretty_information "This is a requires clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP (Property.IPPredicate (Property.PKTerminates,_,_,_) as ip) -> main_ui#pretty_information "This is a terminates clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP (Property.IPPredicate (Property.PKEnsures (_,Normal),_,_,_) as ip) -> main_ui#pretty_information "This is an ensures clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP (Property.IPPredicate (Property.PKEnsures (_,Exits),_,_,_) as ip) -> main_ui#pretty_information "This is an exits clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP (Property.IPPredicate (Property.PKEnsures (_,Returns),_,_,_) as ip) -> main_ui#pretty_information "This is a returns clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP (Property.IPPredicate (Property.PKEnsures (_,Breaks),_,_,_) as ip) -> main_ui#pretty_information "This is a breaks clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP - (Property.IPPredicate (Property.PKEnsures (_,Continues),_,_,_) as ip) -> + (Property.IPPredicate (Property.PKEnsures (_,Continues),_,_,_) as ip) -> main_ui#pretty_information "This is a continues clause.@.%a@." - pretty_predicate_status ip + pretty_predicate_status ip | PIP (Property.IPPredicate(Property.PKAssumes _,_,_,_)) -> main_ui#pretty_information "This is an assumes clause.@." | PIP (Property.IPDecrease (_,Kglobal,_,_) as ip) -> - main_ui#pretty_information - "This is a decreases clause.@.%a@." + main_ui#pretty_information + "This is a decreases clause.@.%a@." pretty_predicate_status ip | PIP (Property.IPDecrease (_,Kstmt _,_,_) as ip) -> - main_ui#pretty_information - "This is a loop variant.@.%a@." + main_ui#pretty_information + "This is a loop variant.@.%a@." pretty_predicate_status ip | PIP(Property.IPDisjoint _ as ip) -> main_ui#pretty_information - "This is a disjoint behaviors clause.@.%a@." + "This is a disjoint behaviors clause.@.%a@." pretty_predicate_status ip | PIP(Property.IPComplete _ as ip) -> main_ui#pretty_information - "This is a complete behaviors clause.@.%a@." + "This is a complete behaviors clause.@.%a@." pretty_predicate_status ip | PIP(Property.IPAxiom _) -> - main_ui#pretty_information "This is an axiom@."; - | PIP(Property.IPBlob _) -> - main_ui#pretty_information "This is an internal state@."; - | PGlobal _g -> main_ui#pretty_information "This is a global@."; + main_ui#pretty_information "This is an axiom.@."; + | PIP(Property.IPAxiomatic _) -> + main_ui#pretty_information "This is an axiomatic.@."; + | PIP(Property.IPLemma _) -> + main_ui#pretty_information "This is a lemma.@."; + | PIP(Property.IPBehavior _) -> + main_ui#pretty_information "This is a behavior.@."; + | PIP(Property.IPUnreachable _) | PIP(Property.IPOther _) -> + (* these properties are not selectable *) + assert false + | PGlobal _g -> main_ui#pretty_information "This is a global.@."; | PLval (kf, ki,lv) -> begin try let ty = typeOfLval lv in if isFunctionType ty - then + then main_ui#pretty_information "This is a C function@." else begin - current_statement_msg kf ki; + current_statement_msg kf ki; let vars = extract_varinfos_from_lval lv in Varinfo.Set.iter (fun vi -> - main_ui#pretty_information + main_ui#pretty_information "Variable %a has type \"%a\".@\nIt is a %s variable.@\n\ - %tIt is %sreferenced and its address is %staken.@." - Ast_info.pretty_vname vi + %tIt is %sreferenced and its address is %staken.@." + Varinfo.pretty_vname vi !Ast_printer.d_type vi.vtype (if vi.vglob then "global" else "local") (fun fmt -> - match vi.vdescr with None -> () + match vi.vdescr with None -> () | Some s -> Format.fprintf fmt - "This is a temporary variable for \"%s\".@\n" s) + "This is a temporary variable for \"%s\".@\n" s) (if vi.vreferenced then "" else "not ") (if vi.vaddrof then "" else "not ")) vars @@ -418,7 +429,7 @@ main_ui#error "Error in lval Db.KernelFunction.find" end | PTermLval _ -> - main_ui#pretty_information "This is a logical left-value.@." + main_ui#pretty_information "This is a logical left-value.@." | PVDecl (kf,vi) -> main_ui#view_original vi.vdecl; if vi.vglob @@ -426,69 +437,61 @@ main_ui#pretty_information "This is the declaration of global %a@\nIt is %sreferenced and \ its address is %staken.@." - Ast_info.pretty_vname vi + Varinfo.pretty_vname vi (if vi.vreferenced then "" else "not ") (if vi.vaddrof then "" else "not ") else main_ui#pretty_information "This is the declaration of local %a in function %a%t@." - Ast_info.pretty_vname vi - Kernel_function.pretty_name (Cilutil.out_some kf) + Varinfo.pretty_vname vi + Kernel_function.pretty (Cilutil.out_some kf) (fun fmt -> match vi.vdescr with None -> () | Some s -> Format.fprintf fmt - "@\nThis is a temporary variable for \"%s\".@." s) + "@\nThis is a temporary variable for \"%s\".@." s) end else if button = 3 then begin match selected with | PVDecl _ -> () | PStmt (kf,ki) -> - let add_assert msg before = + let add_assert () = let txt = - GToolbox.input_string ~title:("Insert an assertion " ^ msg) "" + GToolbox.input_string ~title:"Insert an assertion" "" in Extlib.may - (fun s -> - main_ui#protect ~cancelable:false - (fun () -> - Db.Properties.add_assert - kf ki [] ~before ("assert " ^ s ^ ";"); - to_do_on_select menu_factory main_ui ~button:1 selected; - main_ui#reset ())) - txt - in - let add_assert_after _ = add_assert "after" false in - let add_assert_before _ = add_assert "before" true in - ignore (menu_factory#add_item - "Add assert _after" ~callback:add_assert_after); + (fun s -> + main_ui#protect ~cancelable:false + (fun () -> + Db.Properties.add_assert + kf ki [] ("assert " ^ s ^ ";"); + to_do_on_select menu_factory main_ui ~button:1 selected; + main_ui#reset ())) + txt + in ignore (menu_factory#add_item - "Add assert _before" ~callback:add_assert_before) + "Add assert _before" ~callback:add_assert) | PLval (_kf, _ki, lv) -> - let ty = typeOfLval lv in (* Do special actions for functions *) (* popup a menu to jump the definitions of the given varinfos *) - let do_menu l = - match l with - | [] -> () - | _ -> - try - List.iter - (fun v -> - ignore - (menu_factory#add_item - ("Go to definition of " ^ - (Pretty_utils.escape_underscores - (Pretty_utils.sfprintf "%a" - Ast_info.pretty_vname v))) - ~callback: - (fun () -> - tree_view#select_global v))) - l - with Not_found -> () + let ty = typeOfLval lv in + let do_menu vi = + try + ignore + (menu_factory#add_item + ("Go to definition of " ^ + (Pretty_utils.escape_underscores + (Pretty_utils.sfprintf "%a" Varinfo.pretty_vname vi))) + ~callback: + (fun () -> + let kf = Globals.Functions.get vi in + let glob = Kernel_function.get_global kf in + ignore (main_ui#select_or_display_global glob))) + with Not_found -> () (* Should not happend since [ty] below has a + function type *) in (match lv with | Var v,NoOffset when isFunctionType ty -> (* only simple literal calls can be resolved syntactically *) - do_menu [v] + do_menu v | _ -> ()) | PTermLval _ | PGlobal _ | PIP _ -> () end @@ -506,7 +509,7 @@ let callback = match callback with None -> None | Some cb -> - Some (fun () -> ignore (host#full_protect ~cancelable:true cb)) + Some (fun () -> ignore (host#full_protect ~cancelable:true cb)) in super#add_item ?key ?callback ?submenu string @@ -514,8 +517,8 @@ let callback = match callback with None -> None | Some cb -> - Some (fun b -> - ignore (host#full_protect ~cancelable:false (fun () -> cb b))) + Some (fun b -> + ignore (host#full_protect ~cancelable:false (fun () -> cb b))) in super#add_check_item ?active ?key ?callback string @@ -531,6 +534,7 @@ method buffer = buffer method locs = locs method rehighlight = Extlib.may Pretty_source.hilite locs + method redisplay = self#init method private init = let highlighter localizable ~start ~stop = List.iter (fun f -> f buffer localizable ~start ~stop) !highlighter @@ -541,13 +545,14 @@ (GMenu.menu ()) in List.iter - (fun f -> f popup_factory main_ui ~button localizable) - !selector; + (fun f -> f popup_factory main_ui ~button localizable) + !selector; if button = 3 && popup_factory#menu#children <> [] then - popup_factory#menu#popup + popup_factory#menu#popup ~button ~time:(GtkMain.Main.get_current_event_time ()) in + Extlib.may Locs.finalize locs; locs <- Some( Pretty_source.display_source globs @@ -567,6 +572,52 @@ with Not_found -> new reactive_buffer_cl main_ui ?parent_window globs +module Feedback = +struct + + module F = Property_status.Feedback + + let category = function + | F.Never_tried -> "never_tried" + | F.Considered_valid -> "considered_valid" + | F.Valid -> "surely_valid" + | F.Invalid -> "surely_invalid" + | F.Invalid_but_dead -> "invalid_but_dead" + | F.Valid_but_dead -> "valid_but_dead" + | F.Unknown_but_dead -> "unknown_but_dead" + | F.Unknown -> "unknown" + | F.Valid_under_hyp -> "valid_under_hyp" + | F.Invalid_under_hyp -> "invalid_under_hyp" + | F.Inconsistent -> "inconsistent" + + let declare_markers (source:GSourceView2.source_view) = + List.iter + (fun v -> + source#set_mark_category_pixbuf + ~category:(category v) + (Some (Gtk_helper.Icon.get (Gtk_helper.Icon.Feedback v)))) + [ F.Never_tried; + F.Considered_valid; + F.Valid; + F.Invalid; + F.Invalid_but_dead; + F.Valid_but_dead; + F.Unknown; + F.Unknown_but_dead; + F.Valid_under_hyp; + F.Invalid_under_hyp; + F.Inconsistent ] + + let mark (source:GSourceView2.source_buffer) ~start ~stop:_ validity = + begin + let iter = source#get_iter_at_char start in + let category = category validity in + source#remove_source_marks iter iter () ; + ignore (source#create_source_mark ~category iter) ; + end + +end + (** The main application window *) class main_window () : main_window_extension_points = let final_w,width = try true,Configuration.find_int "window_width" @@ -657,12 +708,9 @@ ~packing:filetree_frame#add () in let file_tree_view = GTree.view ~packing:filetree_scrolled_window#add () in - let () = file_tree_view#selection#set_mode `NONE in - let _ = main_window#misc#connect#after#show - (fun _ -> - file_tree_view#selection#set_mode `BROWSE) - in + let () = file_tree_view#selection#set_mode `BROWSE in let () = file_tree_view#set_rules_hint true in + let () = file_tree_view#set_headers_clickable true in (* splits between messages and sources *) let vb_message_sources = @@ -683,8 +731,9 @@ ~callback:(fun _ -> save_paned_ratio "hb_sources" hb_sources; false) in (* lower notebook *) + let fr2 = - GBin.frame ~shadow_type:`ETCHED_OUT ~packing:vb_message_sources#add2 () + GBin.frame ~shadow_type:`ETCHED_OUT ~packing:vb_message_sources#add2 () in let lower_notebook = GPack.notebook ~scrollable:true ~show_tabs:true ~packing:fr2#add () @@ -693,13 +742,13 @@ (* lower text view and its scroll view: annotations and messages *) let _,annot_window = Gtk_helper.make_text_page lower_notebook "Information" in - let pretty_information fmt = Format.fprintf (Gtk_helper.make_formatter annot_window#buffer) fmt in (* upper text view: source code *) let fr1 = GBin.frame ~shadow_type:`ETCHED_OUT ~packing:hb_sources#add1 () in + let sw = GBin.scrolled_window ~vpolicy:`AUTOMATIC ~hpolicy:`AUTOMATIC @@ -707,15 +756,23 @@ in let source_viewer = Source_viewer.make ~packing:sw#add in - let () = source_viewer#set_show_line_numbers false in - let original_source_viewer = Source_manager.make ~packing:hb_sources#add2 in + let () = + begin + source_viewer#set_show_line_numbers false ; + source_viewer#set_show_line_marks true ; + Feedback.declare_markers source_viewer ; + end + in + + let original_source_viewer = Source_manager.make ~packing:hb_sources#add2 () + in (* Remove default pango menu for textviews *) let () = ignore (source_viewer#event#connect#button_press ~callback: - (fun ev -> GdkEvent.Button.button ev = 3)); + (fun ev -> GdkEvent.Button.button ev = 3)); ignore (annot_window#event#connect#button_press ~callback: - (fun ev -> GdkEvent.Button.button ev = 3)); + (fun ev -> GdkEvent.Button.button ev = 3)); (* startup configuration *) source_viewer#buffer#place_cursor ~where:source_viewer#buffer#start_iter in @@ -734,8 +791,8 @@ (* toplevel_vbox->[*self#menu_manager();toplevel_hpaned;bottom_hbox] *) let m = new Menu_manager.menu_manager - ~packing:(toplevel_vbox#pack ~expand:false ~fill:false ~from:`START) - ~host:(self :> Gtk_helper.host) + ~packing:(toplevel_vbox#pack ~expand:false ~fill:false ~from:`START) + ~host:(self :> Gtk_helper.host) in menu_manager <- Some m; m @@ -749,6 +806,7 @@ = pretty_information method source_viewer = source_viewer + method register_source_selector f = selector := f::!selector method register_source_highlighter f = highlighter := f::!highlighter method register_panel f = panel <- f::panel @@ -757,10 +815,10 @@ let to_refresh = ref [] in let sw = GBin.scrolled_window - ~vpolicy:`AUTOMATIC - ~hpolicy:`AUTOMATIC - ~packing:filetree_panel_vpaned#add2 - () + ~vpolicy:`AUTOMATIC + ~hpolicy:`AUTOMATIC + ~packing:filetree_panel_vpaned#add2 + () in let vbox = GPack.vbox ~packing:sw#add_with_viewport () in let targets = [ @@ -770,11 +828,11 @@ let dragged_frame = ref None in List.iter (fun f -> - let text,widget,refresh = f (self:>main_window_extension_points) in - let key_config = text in - let expander = GBin.expander - ~expanded:(Configuration.find_bool ~default:true key_config) - ~packing:vbox#pack () in + let text,widget,refresh = f (self:>main_window_extension_points) in + let key_config = text in + let expander = GBin.expander + ~expanded:(Configuration.find_bool ~default:true key_config) + ~packing:vbox#pack () in let label_hb = GPack.hbox () in let _label = GMisc.label ~markup:(""^text^"") @@ -784,10 +842,10 @@ expander#set_label_widget (label_hb#coerce); ignore (expander#connect#activate (fun () -> (* Save expansion of panels*) - Configuration.set key_config - (Configuration.ConfBool (not expander#expanded)))); - let frame = GBin.frame ~packing:expander#add () in - frame#add widget; + Configuration.set key_config + (Configuration.ConfBool (not expander#expanded)))); + let frame = GBin.frame ~packing:expander#add () in + frame#add widget; (* Drag stuff *) expander#drag#source_set ~modi:[`BUTTON1] ~actions:[`MOVE] targets; @@ -796,11 +854,11 @@ ignore (expander#drag#connect#ending (fun _ -> dragged_frame:=None)); (* Refreshers *) - Extlib.may - (fun refresh -> - to_refresh:= - (fun ()-> if expander#expanded then refresh ())::!to_refresh) - refresh) + Extlib.may + (fun refresh -> + to_refresh:= + (fun ()-> if expander#expanded then refresh ())::!to_refresh) + refresh) panel; (* Drop machinery *) @@ -842,9 +900,9 @@ method launcher () = Launcher.show ~width:(try Configuration.find_int "launcher_width" - with Not_found -> main_window_metrics.Gtk.width/2) + with Not_found -> main_window_metrics.Gtk.width/2) ~height:(try Configuration.find_int "launcher_height" - with Not_found -> 2*main_window_metrics.Gtk.height/3) + with Not_found -> 2*main_window_metrics.Gtk.height/3) ~host:(self:>Launcher.basic_main) () @@ -855,8 +913,22 @@ Gui_parameters.debug "display_globals"; let buff = reactive_buffer self#toplevel globs in current_buffer_state <- Some buff; - self#source_viewer#set_buffer (buff#buffer:>GText.buffer) - + self#source_viewer#set_buffer (buff#buffer:>GText.buffer); + self#rehighlight () (* This should not be needed, but for some reason + gtk does not highlight the buffer by default *) + + + (* Cf .mli doc. In the first case, the callbacks of the filetree are called, + but not in the second case. As of 2011-05-16, the only callback is + registered here (in design.ml) and calls filetree_selector *) + method select_or_display_global g = + if not (self#toplevel#file_tree#select_global g) then + filetree_selector self#toplevel + ~was_activated:false ~activating:true (Filetree.Global g) + + method redisplay () = + Extlib.may (fun f -> f#redisplay) current_buffer_state; + History.show_current () method rehighlight () = Extlib.may (fun f -> f#rehighlight) current_buffer_state; @@ -867,12 +939,17 @@ scroll to [loc]. Otherwise, open a relevant buffer by finding a varinfo or a global for [loc], then scroll to [loc]. *) method scroll loc = - let update_source_view () = - match Pretty_source.varinfo_of_localizable loc with - | Some vi -> self#file_tree#select_global vi + (* Used to avoid having two different history events, one created + by [select_global], the other by [scroll] *) + let history = History.on_current_history () in + let update_source_view () = + match Pretty_source.kf_of_localizable loc with + | Some kf -> + let g = Kernel_function.get_global kf in + self#select_or_display_global g | None -> match loc with - | PGlobal g -> self#display_globals [g] + | PGlobal g -> self#select_or_display_global g | _ -> if Gui_parameters.debug_atleast 3 then self#error "Gui: does not know how to scroll to loc" (* In this case, there is nothing we can do: we do not @@ -883,14 +960,17 @@ | Some _ -> () | None -> update_source_view () ); - Extlib.may - (fun state -> + match current_buffer_state with + | None -> () + | Some state -> (* [current_buffer_state] contains [loc], [o] is the offset, let's scroll to it *) let show o = + history (fun () -> History.push (History.Localizable loc)); self#source_viewer#buffer#place_cursor (self#source_viewer#buffer#get_iter (`OFFSET o)); - ignore (self#source_viewer#scroll_to_mark `INSERT) + ignore (self#source_viewer#scroll_to_mark + ~use_align:true ~yalign:0.5 ~xalign:0. `INSERT) in match Pretty_source.locate_localizable (Extlib.the state#locs) loc with | Some (b,_) -> show b @@ -908,7 +988,6 @@ not shown in the buffer" (* Can appear eg. for an if (i<5) inside a loop, which is not shown in general in the source code *) - ) current_buffer_state method view_stmt stmt = let kf = Kernel_function.find_englobing_kf stmt in @@ -920,20 +999,21 @@ if not (Location.equal loc Location.unknown) then Source_manager.load_file self#original_source_viewer - (fst loc).Lexing.pos_fname - (fst loc).Lexing.pos_lnum + ~filename:(fst loc).Lexing.pos_fname + ~line:(fst loc).Lexing.pos_lnum + () method view_original_stmt st = let loc = Stmt.loc st in if use_external_viewer then begin if not (Location.equal loc Location.unknown) then let args_for_emacs = - Format.sprintf "emacsclient -n +%d %s" + Format.sprintf "emacsclient -n +%d %s" (fst loc).Lexing.pos_lnum (fst loc).Lexing.pos_fname (* Format.sprintf "mate -a -l %d %s" line file *) in if Gui_parameters.debug_atleast 1 then - self#push_info "Running %s" args_for_emacs; + self#push_info "Running %s" args_for_emacs; ignore (Sys.command args_for_emacs); if Gui_parameters.debug_atleast 1 then self#pop_info () end else @@ -950,17 +1030,17 @@ 'a. ?buffer:Buffer.t -> ('a, Format.formatter, unit) format -> 'a = fun ?buffer fmt -> let b = match buffer with - | None -> Buffer.create 80 - | Some b -> b + | None -> Buffer.create 80 + | Some b -> b in let bfmt = Format.formatter_of_buffer b in Format.kfprintf - (function fmt -> - Format.pp_print_flush fmt (); - let content = Buffer.contents b in + (function fmt -> + Format.pp_print_flush fmt (); + let content = Buffer.contents b in self#info_string content) - bfmt - fmt + bfmt + fmt method push_info fmt = self#push_info_buffer fmt @@ -973,8 +1053,8 @@ (fun _ -> self#pop_info ();true)); ignore (w#event#connect#enter_notify (fun _ -> - Format.pp_print_flush bfmt (); - self#push_info_buffer ~buffer "" ;false))) + Format.pp_print_flush bfmt (); + self#push_info_buffer ~buffer "" ;false))) bfmt fmt @@ -987,67 +1067,82 @@ method lower_notebook = lower_notebook method reset () = + Gui_parameters.debug "Redisplaying gui"; Globals_GUI.clear (); - let fresh_buffer = - GText.buffer ~text:"Please select a file in the left panel\nor start a new project." () - in - source_viewer#set_buffer fresh_buffer; + current_buffer_state <- None; self#file_tree#reset (); - reset_extensions self#toplevel + (self#menu_manager ())#refresh (); + reset_extensions self#toplevel; + if History.is_empty () then ( + self#default_screen ()) + else + History.show_current () + + method private default_screen () = + try + (* If some files have been specified on the command-line, we try + to find the main (if possible a definition, not a prototype), + and display it *) + let main, _ = Globals.entry_point () in + self#select_or_display_global (Kernel_function.get_global main) + with Globals.No_such_entry_point _ | Not_found -> + source_viewer#buffer#set_text + "Please select a file in the left panel\nor start a new project." + initializer - ignore (self#menu_manager ()); (* create the menu_manager *) - main_window#add_accel_group (self#menu_manager ())#factory#accel_group; + let menu_manager = self#menu_manager () (* create the menu_manager *) in + main_window#add_accel_group menu_manager#factory#accel_group; - let lock_gui lock _cancelable = + let lock_gui lock = (* lock left part of the GUI. *) filetree_panel_vpaned#misc#set_sensitive (not lock); if lock then - ignore (Glib.Timeout.add ~ms:25 - ~callback:(fun () -> - progress_bar#pulse (); - not !Gtk_helper.gui_unlocked)); + ignore (Glib.Timeout.add ~ms:25 + ~callback:(fun () -> + progress_bar#pulse (); + not !Gtk_helper.gui_unlocked)); Gdk.Window.set_cursor - main_window#misc#window - (if lock then watch_cursor else arrow_cursor); + main_window#misc#window + (if lock then watch_cursor else arrow_cursor); if lock then begin progress_bar#misc#show (); ignore (status_context#push "Computing") end else begin - status_context#pop(); - progress_bar#misc#hide () + status_context#pop(); + progress_bar#misc#hide () end in register_locking_machinery - ~lock:(fun cancelable -> lock_gui true cancelable) - ~unlock:(fun () -> lock_gui false false) + ~lock:(fun _cancelable -> lock_gui true) + ~unlock:(fun () -> lock_gui false) (); ignore (main_window#connect#destroy ~callback:Cmdline.bail_out); (* Set the relative position for all paned whenever the main window is resized *) ignore (main_window#misc#connect#size_allocate - (fun ({Gtk.width=w;Gtk.height=h} as rect) -> - Configuration.set "window_width" (Configuration.ConfInt w); - Configuration.set "window_height" (Configuration.ConfInt h); + (fun ({Gtk.width=w;Gtk.height=h} as rect) -> + Configuration.set "window_width" (Configuration.ConfInt w); + Configuration.set "window_height" (Configuration.ConfInt h); - if main_window_metrics.Gtk.width <> w + if main_window_metrics.Gtk.width <> w || main_window_metrics.Gtk.height <> h then - begin - place_paned hb_sources - (Configuration.find_float ~default:0.5 "hb_sources"); - place_paned vb_message_sources - (Configuration.find_float ~default:0.71 - "vb_message_sources"); - place_paned filetree_panel_vpaned - (Configuration.find_float ~default:0.5 - "filetree_panel_vpaned"); - place_paned toplevel_hpaned - (Configuration.find_float ~default:0.18 - "toplevel_hpaned"); - end; - main_window_metrics <- rect)); + begin + place_paned hb_sources + (Configuration.find_float ~default:0.5 "hb_sources"); + place_paned vb_message_sources + (Configuration.find_float ~default:0.71 + "vb_message_sources"); + place_paned filetree_panel_vpaned + (Configuration.find_float ~default:0.5 + "filetree_panel_vpaned"); + place_paned toplevel_hpaned + (Configuration.find_float ~default:0.18 + "toplevel_hpaned"); + end; + main_window_metrics <- rect)); file_tree <- Some (Filetree.make file_tree_view); self#file_tree#add_select_function (filetree_selector self#toplevel); @@ -1061,44 +1156,38 @@ let warning_manager = let packing w = - ignore - (lower_notebook#insert_page ~pos:1 - ~tab_label:(GMisc.label ~text:"Messages" ())#coerce w) + ignore + (lower_notebook#insert_page ~pos:1 + ~tab_label:(GMisc.label ~text:"Messages" ())#coerce w) in - let callback s d = - Extlib.may - ( fun state -> - let locs = localizable_from_locs (Extlib.the state#locs) s d in - match locs with - | [] -> - let loc = - { Lexing.dummy_pos with - Lexing.pos_lnum=d; Lexing.pos_fname=s } - in - self#view_original (loc,loc) - | loc :: _ -> - to_do_on_select - (new protected_menu_factory - (self :> Gtk_helper.host) - (GMenu.menu ())) - ~button:1 - self#toplevel - loc) - current_buffer_state + let callback pos = + Extlib.may self#scroll (Pretty_source.loc_to_localizable pos); + self#view_original (pos,pos) in Warning_manager.make ~packing ~callback in let display_warnings () = Warning_manager.clear warning_manager; Messages.iter - (fun _ event -> + (fun event -> Warning_manager.append warning_manager event ~on_select:(fun _ -> assert false)) in display_warnings (); + + (* Gestion of navigation history *) + ignore (History.create_buttons (self#menu_manager ())); + History.set_display_elt_callback + (function + | History.Global g -> + self#select_or_display_global g + | History.Localizable l -> + self#scroll l + ); + register_reset_extension (fun _ -> display_warnings ()); - self#source_viewer#buffer#set_text - "Please select a file in the left panel\nor start a new project."; + self#default_screen (); + menu_manager#refresh (); Project.register_after_set_current_hook ~user_only:true (fun _ -> self#reset ()) @@ -1119,7 +1208,7 @@ in let _ = w#event#connect#delete ~callback:(fun _ -> Cmdline.bail_out ()) in let tid = - Glib.Timeout.add ~ms:500 ~callback:(fun () -> w#present (); false) + Glib.Timeout.add ~ms:500 ~callback:(fun () -> w#show (); false) in let bx = GPack.vbox ~packing:w#add () in let notebook = GPack.notebook ~packing:bx#add () in @@ -1154,26 +1243,54 @@ in Kernel.register_tag_handlers (open_tag,close_tag) end; - tid, stdout, w, reparent + let force () = + Glib.Timeout.remove tid; + w#show () + in + tid, stdout, w, reparent, force let toplevel play = Gtk_helper.Configuration.load (); Db.progress := Gtk_helper.refresh_gui; let in_idle () = - let tid,_splash_out,splash_w,reparent_console = make_splash () in + let tid, splash_out, splash_w, reparent_console, force_s= make_splash () in let error_manager = new Gtk_helper.error_manager (splash_w:>GWindow.window_skel) in - error_manager#protect ~cancelable:true + let init_crashed = ref true in + error_manager#protect ~cancelable:true ~parent:(splash_w:>GWindow.window_skel) (fun () -> - play (); - Ast.compute (); - let main_ui = new main_window () in - Gtk_helper.gui_unlocked := true; - Glib.Timeout.remove tid; - reparent_console main_ui#lower_notebook; - main_ui#lower_notebook#goto_page 0; - splash_w#destroy ()) + play (); + (* This is a good point to start using real asynchronous tasks + management: plug-ins launched from command line have finished + their asynchronous tasks thanks to the default Task.on_idle. *) + Task.on_idle := + (fun f -> ignore (Glib.Timeout.add ~ms:50 ~callback:f)); + (try Ast.compute () + with e -> force_s (); raise e); + init_crashed := false); + if Ast.is_computed () then + (* if the ast has parsed, but a plugin has crashed, we display the gui *) + error_manager#protect ~cancelable:false + (fun () -> + let main_ui = new main_window () in + Gtk_helper.gui_unlocked := true; + Glib.Timeout.remove tid; + reparent_console main_ui#lower_notebook; + splash_w#destroy (); + (* Display the console if a crash has occurred. Otherwise, display + the information panel *) + if !init_crashed then + (main_ui#lower_notebook#goto_page 2; + (* BY TODO: this should scroll to the end of the console. It + does not work at all after the reparent, and only partially + before (scrollbar is wrong) *) + let end_console = splash_out#buffer#end_iter in + ignore (splash_out#scroll_to_iter ~yalign:0. end_console) + ) + else + main_ui#lower_notebook#goto_page 0 + ) in ignore (Glib.Idle.add (fun () -> in_idle (); false)); GMain.Main.main () diff -Nru frama-c-20110201+carbon+dfsg/src/gui/design.mli frama-c-20111001+nitrogen+dfsg/src/gui/design.mli --- frama-c-20110201+carbon+dfsg/src/gui/design.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/design.mli 2011-10-10 08:38:27.000000000 +0000 @@ -23,7 +23,6 @@ (** The extensible GUI. @plugin development guide *) -open Db_types open Cil_types (** This is the type of source code buffers that can react to global @@ -34,6 +33,51 @@ method buffer : GSourceView2.source_buffer method locs : Pretty_source.Locs.state option method rehighlight : unit + method redisplay : unit +end + +(** This class type lists all the methods available to navigate the + source code through the GUI *) +class type view_code = object + + (** {3 Pretty-printed code} *) + + method scroll : Pretty_source.localizable -> unit + (** Move the pretty-printed source viewer to the given localizable + if possible. Return a boolean indicating whether the operation + succeeded + + @modify Nitrogen-20111001 Now indicates whether the + operation succeeded. *) + + method display_globals : global list -> unit + (** Display the given globals in the pretty-printed source viewer. *) + + + (** {3 Original code} *) + + method view_original_stmt : stmt -> location + (** Display the given [stmt] in the original source viewer *) + + method view_original : location -> unit + (** Display the given location in the original_source_viewer *) + + + (** {3 Both pretty-printed and original code} *) + + method view_stmt : stmt -> unit + (** Display the given [stmt] in the [source_viewer] and in the + [original_source_viewer]. Equivalent to two successive + calls to [scroll] and [view_original_stmt] + @since Carbon-20101201 *) + + method select_or_display_global : global -> unit + (** This function tries to select the global in the treeview. If + this fails, for example because the global is not shown in the + treeview because of filters, it falls back to displaying the + global by hand. + + @since Nitrogen-20111001 *) end class protected_menu_factory: @@ -43,6 +87,7 @@ @modify Boron-20100401 new way of handling the menu and the toolbar @plugin development guide *) class type main_window_extension_points = object + inherit view_code (** {3 Main Components} *) @@ -51,7 +96,7 @@ method menu_manager: unit -> Menu_manager.menu_manager (** The object managing the menubar and the toolbar. - @since Boron-20100401 *) + @since Boron-20100401 *) method file_tree : Filetree.t (** The tree containing the list of files and functions *) @@ -65,8 +110,8 @@ method annot_window : GText.view (** The information panel. The text is automatically cleared whenever the selection is changed. - You should not directly use the buffer contained in the annot_window - to add text. Use the method [pretty_information]. + You should not directly use the buffer contained in the annot_window + to add text. Use the method [pretty_information]. *) method pretty_information : 'a. ('a, Format.formatter, unit) format -> 'a (** Pretty print a message in the [annot_window]. *) @@ -74,42 +119,26 @@ method lower_notebook : GPack.notebook (** The lower notebook with messages tabs *) - (** {4 Source viewer} *) + (** {4 Source viewers} *) method source_viewer : GSourceView2.source_view (** The [GText.view] showing the AST. - @plugin development guide *) - - method display_globals : global list -> unit - (** Display globals in the general [source_view]. *) + @plugin development guide *) method reactive_buffer: reactive_buffer option (** The buffer containing the AST. @since Carbon-20101201 *) - (** {4 Original source viewer} *) - method original_source_viewer : Source_manager.t - (** The multi-tab source file display widget. *) - - - method view_stmt : stmt -> unit - (** Display the given [stmt] in the [source_viewer] and in the - [original_source_viewer] - @since Carbon-20101201 *) + (** The multi-tab source file display widget containing the + original source. *) - method view_original_stmt : stmt -> location - (** Display the given [stmt] in the [original_source_viewer] *) - - method view_original : location -> unit - (** Display the given [location] in the [original_source_viewer] *) - (** {3 Dialog Boxes} *) method launcher : unit -> unit (** Display the analysis configuration dialog and offer the - opportunity to launch to the user *) + opportunity to launch to the user *) method error : 'a. ?parent:GWindow.window_skel -> ('a, Format.formatter, unit) format -> 'a @@ -138,10 +167,10 @@ method register_panel : (main_window_extension_points->(string*GObj.widget*(unit-> unit) option)) -> unit - (** [register_panel f] registers a panel in GUI. - [f self] returns the name of the panel to create, + (** [register_panel (name, widget, refresh)] registers a panel in GUI. + The arguments are the name of the panel to create, the widget containing the panel and a function to be called on - refresh. *) + refresh. *) (** {3 General features} *) @@ -151,33 +180,37 @@ method rehighlight : unit -> unit (** Force to rehilight the current displayed buffer. Plugins should call this method whenever they have changed the states - on which the function given to [register_source_highlighter] have been + on which the function given to [register_source_highlighter] have been updated. *) - method scroll : Pretty_source.localizable -> unit - (** Scroll to the given localizable in the current buffer if possible. *) + method redisplay : unit -> unit + (** @since Nitrogen-20111001 + Force to redisplay the current displayed buffer. + Plugins should call this method whenever they have changed the globals. + For example whenever a plugin adds an annotation, the buffers need + to be redisplayed. *) method protect : cancelable:bool -> ?parent:GWindow.window_skel -> (unit -> unit) -> unit (** Lock the GUI ; run the funtion ; catch all exceptions ; Unlock GUI - The parent window must be set if this method is not called directly - by the main window: it will ensure that error dialogs are transient - for the right window. + The parent window must be set if this method is not called directly + by the main window: it will ensure that error dialogs are transient + for the right window. - Set cancelable to [true] if the protected action should be cancellable - by the user through button `Stop'. *) + Set cancelable to [true] if the protected action should be cancellable + by the user through button `Stop'. *) method full_protect : 'a . cancelable:bool -> ?parent:GWindow.window_skel -> (unit -> 'a) -> 'a option (** Lock the GUI ; run the funtion ; catch all exceptions ; Unlock GUI ; returns [f ()]. - The parent window must be set if this method is not called directly - by the main window: it will ensure that error dialogs are transient - for the right window. + The parent window must be set if this method is not called directly + by the main window: it will ensure that error dialogs are transient + for the right window. - Set cancelable to [true] if the protected action should be cancellable - by the user through button `Stop'. *) + Set cancelable to [true] if the protected action should be cancellable + by the user through button `Stop'. *) method push_info : 'a. ('a, Format.formatter, unit) format -> 'a (** Pretty print a temporary information in the status bar *) @@ -205,14 +238,27 @@ called. *) val apply_on_selected : (Pretty_source.localizable -> unit) -> unit - (** [apply_on_selected f] applies [f] to the currently selected - [Pretty_source.localizable]. Does nothing if nothing is selected. *) + (** @deprecated Nitrogen-20111001 + Use History.apply_on_selected instead *) + +val reactive_buffer : main_window_extension_points -> + ?parent_window:GWindow.window -> global list -> reactive_buffer + (** This function creates a reactive buffer for the given list of globals. + These buffers are cached and sensitive to selections and highlighters. + @since Beryllium-20090901 *) + +(** Bullets at left-margins + @since Nitrogen-20111001 *) +module Feedback : +sig + + val mark : GSourceView2.source_buffer + -> start:int -> stop:int + -> Property_status.Feedback.t -> unit + +end + - val reactive_buffer : main_window_extension_points -> - ?parent_window:GWindow.window -> global list -> reactive_buffer - (** This function creates a reactive buffer for the given list of globals. - These buffers are cached and sensitive to selections and highlighters. - @since Beryllium-20090901 *) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/gui/file_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/file_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/file_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/file_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -20,23 +20,35 @@ (* *) (**************************************************************************) -let add_files host_window = +let add_files (host_window: Design.main_window_extension_points) = Gtk_helper.source_files_chooser (host_window :> Gtk_helper.source_files_chooser_host) - (Parameters.Files.get ()) + (Kernel.Files.get ()) (fun filenames -> - Parameters.Files.set filenames; + Kernel.Files.set filenames; if Ast.is_computed () then - Gui_parameters.warning "Input files unchanged. Ignored." + Gui_parameters.warning "Input files unchanged. Ignored." else begin - File.init_from_cmdline (); - host_window#reset () + File.init_from_cmdline (); + host_window#reset () end) let filename: string option ref = ref None (* [None] for opening the 'save as' dialog box; [Some f] for saving in file [f] *) +let reparse (host_window: Design.main_window_extension_points) = + ignore (host_window#full_protect ~cancelable:true + (fun () -> + let files = Kernel.Files.get () in + Kernel.Files.set []; + Kernel.Files.set files; + Ast.compute (); + !Db.Main.play (); + Source_manager.clear host_window#original_source_viewer; + )); + host_window#reset () + let save_in (host_window: Design.main_window_extension_points) parent name = try Project.save_all name; @@ -59,9 +71,9 @@ (fun () -> match dialog#run () with | `SAVE -> - Extlib.may - (save_in host_window (dialog :> GWindow.window_skel)) - dialog#filename + Extlib.may + (save_in host_window (dialog :> GWindow.window_skel)) + dialog#filename | `DELETE_EVENT | `CANCEL -> ()); dialog#destroy () @@ -82,11 +94,11 @@ host_window#protect ~cancelable:true ~parent:(dialog:>GWindow.window_skel) (fun () -> match dialog#run () with | `OPEN -> - begin match dialog#filename with - | None -> () - | Some f -> + begin match dialog#filename with + | None -> () + | Some f -> Project.load_all f - end + end | `DELETE_EVENT | `CANCEL -> ()); dialog#destroy () @@ -97,30 +109,38 @@ menu_manager#add_entries filemenu [ - Menu_manager.ToolMenubar(`FILE, "Set C source files"), - (fun () -> add_files host_window); - Menu_manager.ToolMenubar(`SAVE, "Save session"), - (fun () -> save_file host_window); - Menu_manager.ToolMenubar(`SAVE_AS, "Save session as"), - (fun () -> save_file_as host_window); - Menu_manager.ToolMenubar(`REVERT_TO_SAVED, "Load session"), - (fun () -> load_file host_window) + Menu_manager.toolmenubar + ~icon:`FILE ~label:"Source files" + ~tooltip:"Create a new session from existing C files" + (Menu_manager.Unit_callback (fun () -> add_files host_window)); + Menu_manager.toolmenubar + ~icon:`REFRESH ~label:"Reparse" + ~tooltip:"Reparse source files, and replay analyses" + (Menu_manager.Unit_callback (fun () -> reparse host_window)); + Menu_manager.toolmenubar `REVERT_TO_SAVED "Load session" + (Menu_manager.Unit_callback (fun () -> load_file host_window)); + Menu_manager.toolmenubar `SAVE "Save session" + (Menu_manager.Unit_callback (fun () -> save_file host_window)); + Menu_manager.menubar ~icon:`SAVE_AS "Save session as" + (Menu_manager.Unit_callback (fun () -> save_file_as host_window)); ] in - file_items.(1)#add_accelerator `CONTROL 's'; - file_items.(3)#add_accelerator `CONTROL 'l'; + file_items.(3)#add_accelerator `CONTROL 's'; + file_items.(2)#add_accelerator `CONTROL 'l'; let stock = `QUIT in let quit_item = menu_manager#add_entries filemenu - [ Menu_manager.Menubar(Some stock, "Exit Frama-C"), Cmdline.bail_out ] + [ Menu_manager.menubar ~icon:stock "Exit Frama-C" + (Menu_manager.Unit_callback Cmdline.bail_out) ] in quit_item.(0)#add_accelerator `CONTROL 'q'; ignore (menu_manager#add_entries filemenu ~pos:0 - [ Menu_manager.Toolbar(stock, "Exit Frama-C"), Cmdline.bail_out ]) + [ Menu_manager.toolbar ~icon:stock ~label:"Exit" ~tooltip:"Exit Frama-C" + (Menu_manager.Unit_callback Cmdline.bail_out)]) (** Register this dialog in main window menu bar *) let () = Design.register_extension insert diff -Nru frama-c-20110201+carbon+dfsg/src/gui/filetree.ml frama-c-20111001+nitrogen+dfsg/src/gui/filetree.ml --- frama-c-20110201+carbon+dfsg/src/gui/filetree.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/filetree.ml 2011-10-10 08:38:27.000000000 +0000 @@ -25,33 +25,35 @@ open Extlib open Gtk_helper +type filetree_node = + | File of string * Cil_types.global list + | Global of Cil_types.global + class type t = object method model : GTree.model + method flat_mode: bool method set_file_attribute: ?strikethrough:bool -> ?text:string -> string -> unit method set_global_attribute: ?strikethrough:bool -> ?text:string -> varinfo -> unit + method add_global_filter: + text:string -> key:string -> (Cil_types.varinfo -> bool) -> (unit -> bool) method get_file_globals: string -> (string * bool) list method add_select_function : - (was_activated:bool -> activating:bool -> global list -> unit) -> unit + (was_activated:bool -> activating:bool -> filetree_node -> unit) -> unit method append_pixbuf_column: - title:string -> (global list -> GTree.cell_properties_pixbuf list) -> unit - method select_global : varinfo -> unit + title:string -> (global list -> GTree.cell_properties_pixbuf list) -> + (unit -> bool) -> (unit -> unit) + method select_global : Cil_types.global -> bool method selected_globals : Cil_types.global list method view : GTree.view method reset : unit -> unit - method reset_dynamic_columns : - (GTree.view -> global list GTree.column -> unit) list -> unit - (** Internal use only for legacy filetree mode *) - + method register_reset_extension : (t -> unit) -> unit + method refresh_columns : unit -> unit end -module MAKE(TREE:sig type t - val sons: t -> t array - val custom_value: Gobject.g_type -> t -> column:int -> Gobject.basic - val column_list:GTree.column_list - end) = +module MAKE(TREE:sig type t val sons: t -> t array end) = struct type custom_tree = {finfo: TREE.t; @@ -103,8 +105,8 @@ done; GTree.Path.create ((!current_row.fidx)::!path) - method custom_value (t:Gobject.g_type) (row:custom_tree) ~column = - TREE.custom_value t row.finfo ~column + method custom_value (_t:Gobject.g_type) (_row:custom_tree) ~column:_ = + assert false method custom_iter_next (row:custom_tree) : custom_tree option = let nidx = succ row.fidx in @@ -176,121 +178,139 @@ false) end - let custom_tree () = - new custom_tree_class TREE.column_list + let custom_tree () = new custom_tree_class (new GTree.column_list) end module MYTREE = struct -type storage = { mutable name : string; - mutable globals: global array; - mutable strikethrough: bool} + type storage = { mutable name : string; + mutable globals: global array; + mutable strikethrough: bool} -type t = File of storage*t list | Global of storage + type t = MFile of storage*t list | MGlobal of storage -let sons t = match t with -| File (_,s) -> Array.of_list s -| Global _ -> [| |] + let storage_type = function + | MFile (s, _) -> File (s.name, Array.to_list s.globals) + | MGlobal { globals = [| g |] } -> Global g + | MGlobal _ -> assert false + let sons t = match t with + | MFile (_,s) -> Array.of_list s + | MGlobal _ -> [| |] -let sons_info = function - | File (_, l) -> - List.map (function - | Global { name = n; strikethrough = st } -> (n, st) - | File _ -> assert false (* should not happen, a file is - never under a file in the tree *) - ) l - | Global _ -> [] - -let get_storage t = match t with -| File (s,_) -> s -| Global s -> s - -let default_storage s globals = - { - name = s; - globals = globals; - strikethrough = false; - } - -(* Set up the columns *) -let column_list = new GTree.column_list -let filename_col = column_list#add Gobject.Data.string -let (glob_col:global list GTree.column) = column_list#add Gobject.Data.caml -let strikethrough_col = column_list#add Gobject.Data.boolean -let is_function_col = column_list#add Gobject.Data.boolean - -let custom_value _ t ~column = - match column with - | 0 -> (* filename_col *) `STRING (Some (get_storage t).name) - | 1 -> (* glob_col *) `CAML (Obj.repr ((get_storage t).globals)) - | 2 -> (* strikethrough_col *) `BOOL (get_storage t).strikethrough - | 3 -> (* is_function_col *) `BOOL (match t with - | File _ -> false - | Global g -> match g.globals with - | [| GFun _ |] -> true - | _ -> false) - | _ -> assert false - -let make_file (display_name, globs) : t = - let storage = default_storage display_name (Array.of_list globs) in - let sons_funs, sons_vars = List.fold_left - (* Correct the function sons_info above if a [File] constructor can - appear in [sons] *) - (fun (accf, accv as acc) glob -> match glob with - | GFun ({svar={vname=name}},_) -> - (Global(default_storage name [|glob|]))::accf, accv - - | GVar({vname=name},_,_) -> - accf, (Global(default_storage name [|glob|]))::accv - - | GVarDecl(_,({vname=name} as vi),_) -> - if Cil.isFunctionType vi.vtype then - if Kernel_function.is_definition (Globals.Functions.get vi) then - (* there is a prototype somewhere else *) - acc - else - (Global(default_storage name [|glob|]))::accf, accv - else - accf, (Global(default_storage name [|glob|]))::accv - - | _ -> acc) - ([], []) - globs - in - (* We display first all the functions sorted by their names, - then all the global variables *) - let name g = String.lowercase ((get_storage g).name) in - let sort = List.sort (fun g1 g2 -> String.compare (name g1) (name g2)) in - File (storage, (sort sons_funs) @ (sort sons_vars)) + let sons_info = function + | MFile (_, l) -> + List.map (function + | MGlobal { name = n; strikethrough = st } -> (n, st) + | MFile _ -> assert false (* should not happen, a file is + never under a file in the tree *) + ) l + | MGlobal _ -> [] + + let get_storage t = match t with + | MFile (s,_) -> s + | MGlobal s -> s + + let is_function_vi vi = Cil.isFunctionType vi.vtype + + let is_function t = match t with + | MFile _ -> false + | MGlobal g -> match g.globals with + | [| GFun _ |] -> true + | [| GVarDecl (_, vi, _) |] -> is_function_vi vi + | _ -> false + + let default_storage s globals = + { + name = s; + globals = globals; + strikethrough = false; + } + + let make_list_globals hide globs = + let l = List.fold_left + (* Correct the function sons_info above if a [File] constructor can + appear in [sons] *) + (fun acc glob -> + match glob with + | GFun ({svar=({vname=name} as vi)},_) + | GVar(({vname=name} as vi),_,_) -> + if hide vi then acc + else MGlobal(default_storage name [|glob|]) :: acc + + | GVarDecl(_, vi,_) -> + (* we have a found the prototype, but there is a definition + somewhere else. Skip the prototype. *) + if hide vi || + (Cil.isFunctionType vi.vtype && + Kernel_function.is_definition (Globals.Functions.get vi)) + then acc + else MGlobal(default_storage vi.vname [|glob|]) :: acc + + | _ -> acc) + [] + globs + in + let name g = String.lowercase ((get_storage g).name) in + let sort = List.sort (fun g1 g2 -> String.compare (name g1) (name g2)) in + sort l + + let make_file hide (display_name, globs) = + let storage = default_storage display_name (Array.of_list globs) in + let sons = make_list_globals hide globs in + storage, sons end module MODEL=MAKE(MYTREE) +(* Primitives to handle the filetree menu (which allows to hide some + entries) *) +module MenusHide = struct + let hide key () = Configuration.find_bool ~default:false key + + let menu_item (menu: GMenu.menu) ~label ~key = + let mi = GMenu.check_menu_item ~label () in + mi#set_active (hide key ()); + menu#add (mi :> GMenu.menu_item); + mi + + let mi_set_callback (mi: GMenu.check_menu_item) ~key reset = + mi#connect#toggled ~callback: + (fun () -> + let v = mi#active in + Configuration.set key (Configuration.ConfBool v); + reset ()) + +end + +let key_flat_mode = "filetree_flat_mode" +let flat_mode = MenusHide.hide key_flat_mode + module State = struct let default_filetree () = let m1 = MODEL.custom_tree () in m1, Varinfo.Hashtbl.create 17, - Hashtbl.create 17,GTree.Path.create [] + Hashtbl.create 17, + GTree.Path.create [] include State_builder.Ref (Datatype.Make (struct - include Datatype.Undefined - type t = + include Datatype.Undefined + type t = MODEL.custom_tree_class * (Gtk.tree_path * MODEL.custom_tree) Varinfo.Hashtbl.t * (string, (Gtk.tree_path * MODEL.custom_tree)) Hashtbl.t * Gtk.tree_path - let name = "Filetree.FileTree_Datatype" - (** Prevent serialization of this state containing closures *) - let reprs = [ default_filetree () ] - let mem_project = Datatype.never_any_project - end)) + let name = "Filetree.FileTree_Datatype" + (** Prevent serialization of this state containing closures *) + let reprs = [ default_filetree () ] + let mem_project = Datatype.never_any_project + end)) (struct let name = "Filetree.State" let dependencies = [ Ast.self ] @@ -298,65 +318,79 @@ let default = default_filetree end) - (** Make and fill the custom model. *) - let get () = - if is_computed () then get () + (** Make and fill the custom model with default values. *) + let compute hide_filters = + Gui_parameters.debug "Resetting GUI filetree"; + let hide g = List.exists (fun filter -> filter g) hide_filters in + clear (); + let model, global_path_tbl, file_path_tbl,_ = get () in + (* Let's fill up the model with all files and functions. *) + let files = Globals.FileIndex.get_files () in + let files' = List.map (fun s -> Globals.FileIndex.find s) files in + if flat_mode () then + let files = + MYTREE.make_list_globals hide (List.concat (List.map snd files')) + in + List.iter model#append_tree files else - let model,_,_,_ = get () in - (** Let's fill up the model with all files and functions. *) - let files = Globals.FileIndex.get_files () in - let files' = List.map (fun s -> Globals.FileIndex.find s) files in List.iter - (fun v -> model#append_tree (MYTREE.make_file v)) + (fun v -> + let name, globals = MYTREE.make_file hide v in + model#append_tree (MYTREE.MFile (name, globals))) (List.sort (fun (s1, _) (s2, _) -> String.compare s1 s2) files'); - (** Let's build the table from cil standard types to rows in the model *) + (* Let's build the table from globals to rows in the model *) + let cache path row = + (match row.MODEL.finfo with + | MYTREE.MFile (storage,_) -> + Hashtbl.add file_path_tbl storage.MYTREE.name (path,row) + | MYTREE.MGlobal storage -> + match storage.MYTREE.globals with + (* Only one element in this array by invariant: this is a leaf*) + | [| GFun ({svar=vi},_) | GVar(vi,_,_) | GVarDecl(_,vi,_) |] -> + Varinfo.Hashtbl.add global_path_tbl vi (path,row) + | _ -> (* no cache for other globals yet *) () + ); + false + in + model#custom_foreach cache; (* fills up the cache *) - (** These tables contain the path (in the treeview of file names) - to the global (reps. filename) *) - let global_path_tbl = Varinfo.Hashtbl.create 17 in - let file_path_tbl = Hashtbl.create 17 in - - let cache path row = - (match row.MODEL.finfo with - | MYTREE.File (storage,_) -> - Hashtbl.add file_path_tbl storage.MYTREE.name (path,row) - | MYTREE.Global storage -> - match storage.MYTREE.globals with - (* Only one element in this array by invariant: this is a leaf*) - | [| GFun ({svar=vi},_) - | GVar(vi,_,_) | GVarDecl(_,vi,_) |] -> - Varinfo.Hashtbl.add global_path_tbl vi (path,row) - | _ -> (* no cache for other globals yet *) ()); - false - in - model#custom_foreach cache; (* fills up the cache *) + mark_as_computed () + + let get () = + if is_computed () then get () + else (compute [] (* Failsafe: everything is shown *); + get ()) - (* These must be put in a global variable. *) - let r = model,global_path_tbl, file_path_tbl,GTree.Path.create [] in - set r; - mark_as_computed (); - r end let make (tree_view:GTree.view) = - let model,global_path_tbl, file_path_tbl, activated_path = State.get () in - - (** View part *) - let source_column = GTree.view_column ~title:"Source file" () in - source_column#set_resizable true; - let str_renderer = GTree.cell_renderer_text [] in - source_column#pack str_renderer; - source_column#add_attribute str_renderer "text" MYTREE.filename_col; - source_column#add_attribute str_renderer "strikethrough" - MYTREE.strikethrough_col; - source_column#add_attribute str_renderer "underline" - MYTREE.is_function_col; - - let _ = tree_view#append_column source_column in - - tree_view#set_model (Some (model:>GTree.model)); + (* Menu for configuring the filetree *) + let menu = GMenu.menu () in + let button_menu = GButton.button ~relief:`HALF ~label:"Source file" () in + + (* Buttons to show/hide variables and/or functions *) + let key_hide_variables = "filetree_hide_variables" in + let key_hide_functions = "filetree_hide_functions" in + let hide_variables = MenusHide.hide key_hide_variables in + let hide_functions = MenusHide.hide key_hide_functions in + let initial_filter vi = + let is_fun = MYTREE.is_function_vi vi in + if is_fun then hide_functions () + else hide_variables () + in + let mhide_variables = + MenusHide.menu_item menu ~label:"Hide variables" ~key:key_hide_variables in + let mhide_functions = + MenusHide.menu_item menu ~label:"Hide functions" ~key:key_hide_functions in + let mflat_mode = + MenusHide.menu_item menu ~label:"Flat mode" ~key:key_flat_mode in + + (* Initial filetree nodes to display *) + State.compute [initial_filter]; + let init_model, init_global_path_tbl, init_file_path_tbl, init_activated_path= + State.get () in let set_row model ?strikethrough ?text (path,raw_row) = let row = raw_row.MODEL.finfo in @@ -365,35 +399,34 @@ strikethrough; may (fun b -> (MYTREE.get_storage row).MYTREE.name <- b) text; model#custom_row_changed path raw_row - in - let set_file_attribute file_path_tbl model ?strikethrough ?text filename = - set_row model ?strikethrough ?text (Hashtbl.find file_path_tbl filename) - and set_global_attribute global_path_tbl model ?strikethrough ?text global = - set_row model ?strikethrough ?text - (Varinfo.Hashtbl.find global_path_tbl global) - and get_file_globals file_path_tbl file = - try let _, raw_row = Hashtbl.find file_path_tbl file - in MYTREE.sons_info raw_row.MODEL.finfo - with Not_found -> Gui_parameters.error "%s" file; [] - - in let myself = object(self) + val mutable reset_extensions = [] + val mutable select_functions = [] - val mutable file_path_tbl = file_path_tbl - val mutable global_path_tbl = global_path_tbl - val mutable model_custom = model - val mutable model = model - val mutable activated_path = activated_path + val mutable file_path_tbl = init_file_path_tbl + val mutable global_path_tbl = init_global_path_tbl + val mutable model_custom = init_model + val mutable activated_path = init_activated_path (* prevent double selection and restore activated path *) + val mutable hide_globals_filters = [initial_filter] + + val mutable force_selection = false + + (* Forward reference to the first column. Always set *) + val mutable source_column = None + + val mutable columns_visibility = [] + + method refresh_columns () = + List.iter (fun f -> f ()) columns_visibility method append_pixbuf_column - ~title (f:(global list -> GTree.cell_properties_pixbuf list)) = + ~title (f:(global list -> GTree.cell_properties_pixbuf list)) visible = let column = GTree.view_column ~title () in column#set_resizable true; - (* column#set_sizing `FIXED; column#set_fixed_width 70;*) let renderer = GTree.cell_renderer_pixbuf [] in column#pack renderer; column#set_cell_data_func renderer @@ -403,62 +436,86 @@ | Some {MODEL.finfo=v} -> renderer#set_properties (f (Array.to_list((MYTREE.get_storage v).MYTREE.globals))) | None -> ()); - ignore (tree_view#append_column column) + ignore (tree_view#append_column column); + (* We return a function showing or masking the column*) + let refresh () = column#set_visible (visible ()) in + refresh (); + columns_visibility <- refresh :: columns_visibility; + refresh method view = tree_view - method private model_custom = model_custom - method model = model - method private get_select_functions = select_functions - method set_file_attribute = - set_file_attribute file_path_tbl self#model_custom - method set_global_attribute = - set_global_attribute global_path_tbl self#model_custom - method get_file_globals = - get_file_globals file_path_tbl - method private set_row_attribute = set_row self#model_custom - method reset () = self#reset_internal () + method model = model_custom + + method reset () = + self#reset_internal (); + self#refresh_columns (); + List.iter (fun f -> f (self :> t)) reset_extensions; + + method register_reset_extension f = + reset_extensions <- f :: reset_extensions + + method set_file_attribute ?strikethrough ?text filename = + try + set_row model_custom ?strikethrough ?text + (Hashtbl.find file_path_tbl filename) + with Not_found -> () (* Some files might not be in the list because + of our filters. Ignore *) + + method set_global_attribute ?strikethrough ?text global = + try + set_row model_custom ?strikethrough ?text + (Varinfo.Hashtbl.find global_path_tbl global) + with Not_found -> () (* Some globals might not be in the list because of + our filters. Ignore *) + + method flat_mode = flat_mode () + + method get_file_globals file = + try let _, raw_row = Hashtbl.find file_path_tbl file in + MYTREE.sons_info raw_row.MODEL.finfo + with Not_found -> Gui_parameters.error "%s" file; [] - val mutable force_selection = false method private enable_select_functions () = - let select path deactivating = - let fail e = + let select path path_currently_selected = + let fail e = Gui_parameters.error "selector handler got an internal error, please report: %s" (Printexc.to_string e) - in - try - let path_s = GTree.Path.to_string path in + in + try + let path_s = GTree.Path.to_string path in + (*Format.printf "Select function activating:%b on path %s + was @." (not path_currently_selected) path_s;*) let was_activated = (Array.length (GTree.Path.get_indices activated_path) > 0) && GTree.Path.to_string activated_path = path_s in - if (force_selection || not was_activated) && not deactivating + if (force_selection || not was_activated) + && not path_currently_selected then begin activated_path <- path; State.set (model_custom,global_path_tbl,file_path_tbl, path); let {MODEL.finfo=t} = - match self#model_custom#custom_get_iter path with + match model_custom#custom_get_iter path with | Some s ->s | None -> assert false in - let globs = (MYTREE.get_storage t).MYTREE.globals in - (*Format.printf "Select function %b on path %s@." - (not deactivating) path_s;*) - let globs = Array.to_list globs in - List.iter - (fun f -> - try - f ~was_activated:(not force_selection && was_activated) - ~activating:(not deactivating) globs - with e-> fail e) - select_functions + let arg = MYTREE.storage_type t in + List.iter + (fun f -> + try + f ~was_activated:(not force_selection && was_activated) + ~activating:true + arg + with e-> fail e) + select_functions end; force_selection <- false; - true - with e -> + true + with e -> Gui_parameters.error - "gui could not select row in filetree, please report: %s" - (Printexc.to_string e); + "gui could not select row in filetree, please report: %s" + (Printexc.to_string e); true in tree_view#selection#set_select_function select @@ -466,39 +523,101 @@ method add_select_function f = select_functions <- select_functions@[f]; - method reset_dynamic_columns - (_:(GTree.view -> global list GTree.column -> unit) list) = - ignore (assert false) + method private varinfo_of_global g = + match g with + | GVar (vi, _, _) + | GVarDecl (_, vi, _) + | GFun ({svar = vi}, _) -> Some vi + | _ -> None - method select_global vi = - try - let path, _ = Varinfo.Hashtbl.find global_path_tbl vi in - expand_to_path tree_view path; - tree_view#selection#select_path path; - with Not_found -> - () + + method select_global g = + match self#varinfo_of_global g with + | None -> false + | Some vi -> + try + let path, _ = Varinfo.Hashtbl.find global_path_tbl vi in + expand_to_path tree_view path; + tree_view#selection#select_path path; + tree_view#scroll_to_cell + ~align:(0., 0.5) path (Extlib.the source_column); + tree_view#misc#grab_focus (); + true + with Not_found -> + false method selected_globals = - let (model,_,_,path) = State.get () in - match model#custom_get_iter path with + match model_custom#custom_get_iter activated_path with | None -> [] | Some {MODEL.finfo=f } -> Array.to_list (MYTREE.get_storage f).MYTREE.globals + + method add_global_filter ~text ~key f = + hide_globals_filters <- f :: hide_globals_filters; + let mi = MenusHide.menu_item menu ~label:text ~key in + ignore (MenusHide.mi_set_callback mi ~key self#reset); + MenusHide.hide key + method private reset_internal () = + (* We force a full recomputation using our filters for globals *) + State.compute hide_globals_filters; let mc,gc,fc,path = State.get () in tree_view#set_model (Some (mc:>GTree.model)); model_custom <- mc; - model <- mc; global_path_tbl<-gc; file_path_tbl<-fc; + tree_view#selection#unselect_path path; activated_path <- path; expand_to_path tree_view path; force_selection <- true; - tree_view#selection#select_path path + tree_view#selection#select_path path; initializer - self#enable_select_functions () + (* Source column *) + let source_renderer = GTree.cell_renderer_text [`YALIGN 0.0] in + let m_source_renderer renderer (lmodel:GTree.model) iter = + let (path:Gtk.tree_path) = lmodel#get_path iter in + match self#model#custom_get_iter path with + | Some ({MODEL.finfo=MYTREE.MFile({MYTREE.name=m; + strikethrough=strike},_) as s} + |{MODEL.finfo=MYTREE.MGlobal ({MYTREE.name=m; + strikethrough=strike}) as s}) + -> + renderer#set_properties + [`TEXT m;`STRIKETHROUGH strike; + `UNDERLINE (if MYTREE.is_function s then `LOW else `NONE)]; + + | None -> () + in + let column = GTree.view_column + ~title:"Source file" + ~renderer:((source_renderer:>GTree.cell_renderer),[]) () + in + source_column <- Some column; + column#set_cell_data_func + source_renderer (m_source_renderer source_renderer); + column#set_resizable true; + column#set_clickable true; + column#set_widget (Some button_menu#coerce); + + ignore (column#connect#clicked ~callback: + (fun () -> menu#popup + ~button:0 + ~time:(GtkMain.Main.get_current_event_time ()); + )); + + ignore (MenusHide.mi_set_callback + mhide_functions key_hide_functions self#reset); + ignore (MenusHide.mi_set_callback + mhide_variables key_hide_variables self#reset); + ignore (MenusHide.mi_set_callback + mflat_mode key_flat_mode self#reset); + menu#add (GMenu.separator_item () :> GMenu.menu_item); + + let _ = tree_view#append_column column in + tree_view#set_model (Some (init_model:>GTree.model)); + self#enable_select_functions (); end in diff -Nru frama-c-20110201+carbon+dfsg/src/gui/filetree.mli frama-c-20111001+nitrogen+dfsg/src/gui/filetree.mli --- frama-c-20110201+carbon+dfsg/src/gui/filetree.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/filetree.mli 2011-10-10 08:38:27.000000000 +0000 @@ -22,9 +22,22 @@ (** The tree containing the list of modules and functions together with dynamic columns *) +type filetree_node = + File of string * Cil_types.global list | Global of Cil_types.global +(** Caml type for the infos on a node of the tree + @since Nitrogen-20111001 *) + class type t = object method model : GTree.model + method flat_mode: bool + (** Return [true] if the filetree currently displays all globals in + flat mode (all children of the same node), [false] otherwise + (children of the file they are declared in). If [true], the methods + [set_file_attribute] and [get_files_globals] must not be used + + @since Nitrogen-20111001 *) + method set_file_attribute: ?strikethrough:bool -> ?text:string -> string -> unit (** Manually set some attributes of the given filename. *) @@ -33,25 +46,58 @@ ?strikethrough:bool -> ?text:string -> Cil_types.varinfo -> unit (** Manually set some attributes of the given variable. *) + method add_global_filter: + text:string -> key:string -> (Cil_types.varinfo -> bool) -> (unit -> bool) + (** [add_global_filter text key f] adds a filter for the visibility of + the globals, according to [f]. If any of the filters registered + through this method returns true, the global is not displayed in the + filetree. [text] is used in the filetree menu, to label the entry + permitting to activate or deactivate the filter. [key] is used to + store the current state of the filter internally. The returned + function can be used to query the current state of the filter. + + @since Nitrogen-20111001 *) + method get_file_globals: string -> (string * bool) list (** Return the names and the attributes (currently only the strikethrough property) of the globals in the file passed as argument *) method add_select_function : - (was_activated:bool -> activating:bool -> Cil_types.global list -> unit) -> unit + (was_activated:bool -> activating:bool -> filetree_node -> unit) -> unit (** Register a callback that is called whenever an element of the file tree - is selected or unselected. *) + is selected or unselected. + + @modify Nitrogen-20111001 Changed argument from a list + of globals to [filetree_node] *) method append_pixbuf_column: - title:string -> (Cil_types.global list -> GTree.cell_properties_pixbuf list) -> unit - (** [append_pixbuf_column title f] appends a new column with name [title] to the - file tree and register [f] as a callback computing the list of properties - for this column. Do not forget that properties need to be set and unset. - Selects the given variable in the tree view and run the associated callbacks. *) + title:string -> + (Cil_types.global list -> GTree.cell_properties_pixbuf list) -> + (unit -> bool) -> + (unit -> unit) + (** [append_pixbuf_column title f visible] appends a new column with name + [title] to the file tree and register [f] as a callback computing the + list of properties for this column. Do not forget that properties need + to be set and unset. The argument [visible] is used by the column + to decide whether it shoudl appear. The returned function + (of type [unit -> unit] can be used to update the visibility of the + column. Alternatively, the method [refresh_columns] does this on + all the columns. + + @modify Nitrogen-20111001 Add third argument, and change return type + *) + + method select_global : Cil_types.global -> bool + (** Selects the given global in the tree view and run the associated + callbacks. Return a boolean indicating whether the selection + succeeded. (Currently, only variables and functions can be selected, + provided they are not filtered out.) Unless you known what your + are doing, prefer calling [main_ui#select_or_display_global], + which is more resilient to globals not displayed in the filetree. - method select_global : Cil_types.varinfo -> unit - (** Selects the given variable in the tree view and run the associated callbacks. *) + @modify Nitrogen-20111001 Takes a [global] as argument, instead of + a [varinfo]. Returns a boolean to indicate success or failure. *) method selected_globals : Cil_types.global list (** @since Carbon-20101201 @@ -62,16 +108,19 @@ method reset : unit -> unit (** Resynchronize the tree view with the current project state. - This is called by the generic reset extension of {!Design} and shall - not be called by other plugins. - *) - - (**/**) - method reset_dynamic_columns : - (GTree.view -> Cil_types.global list GTree.column -> unit) list -> unit - (** Internal use only for legacy filetree mode *) - (**/**) + This is called in particular by the generic reset extension of + {!Design} *) + + method register_reset_extension : (t -> unit) -> unit + (** Register a function to be called whenever the reset method of the + filetree is called. *) + + method refresh_columns : unit -> unit + (** Refresh the state of all the non-source columns of the filetree, + by hiding those that should be hidden, and displaying the + others. Called by [reset] + @since Nitrogen-20111001 *) end val make : GTree.view -> t diff -Nru frama-c-20110201+carbon+dfsg/src/gui/gtk_form.ml frama-c-20111001+nitrogen+dfsg/src/gui/gtk_form.ml --- frama-c-20110201+carbon+dfsg/src/gui/gtk_form.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/gtk_form.ml 2011-10-10 08:38:27.000000000 +0000 @@ -36,7 +36,7 @@ (* --- Utilities --- *) (* ------------------------------------------------------------------------ *) -type 'a field = +type 'a field = ?tooltip:string -> packing:(GObj.widget -> unit) -> (unit -> 'a) -> ('a -> unit) -> demon -> unit @@ -49,7 +49,7 @@ (* ------------------------------------------------------------------------ *) (* --- Check Button --- *) (* ------------------------------------------------------------------------ *) - + let check ?label ?tooltip ~packing get set demon = let button = GButton.check_button ?label ~packing ~active:(get ()) () @@ -71,17 +71,17 @@ let callback () = try match combo_box#active_iter with - | None -> () - | Some row -> - let title = (combo_box#model#get ~row ~column) in - let (_,item) = List.find (fun (t,_) -> t=title) entries in - set item + | None -> () + | Some row -> + let title = (combo_box#model#get ~row ~column) in + let (_,item) = List.find (fun (t,_) -> t=title) entries in + set item with Not_found -> () in let rec lookup k item = function | [] -> raise Not_found | (_,value) :: entries -> - if value = item then k else lookup (succ k) item entries + if value = item then k else lookup (succ k) item entries in let update () = try combo_box#set_active (lookup 0 (get ()) entries) @@ -111,13 +111,13 @@ class form ~packing = object - + val table = GPack.table ~rows:2 ~col_spacings:8 ~packing () val mutable top = 0 method label text = - ignore (GMisc.label ~text - ~packing:(table#attach ~top ~left:0 ~expand:`NONE) ()) + ignore (GMisc.label ~text + ~packing:(table#attach ~top ~left:0 ~expand:`NONE) ()) method item obj = table#attach ~top ~left:1 ~expand:`X ~fill:`X obj ; diff -Nru frama-c-20110201+carbon+dfsg/src/gui/gtk_form.mli frama-c-20111001+nitrogen+dfsg/src/gui/gtk_form.mli --- frama-c-20110201+carbon+dfsg/src/gui/gtk_form.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/gtk_form.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + (* ------------------------------------------------------------------------ *) (* --- Forms Factory --- *) (* ------------------------------------------------------------------------ *) @@ -28,21 +33,20 @@ val demon : unit -> demon val refresh : demon -> (unit -> unit) -type 'a field = +type 'a field = ?tooltip:string -> packing:(GObj.widget -> unit) -> - (unit -> 'a) -> ('a -> unit) -> demon -> unit - + (unit -> 'a) -> ('a -> unit) -> demon -> unit + val check : ?label:string -> bool field val menu : (string * 'a) list -> ?width:int -> 'a field val spinner : ?lower:int -> ?upper:int -> ?width:int -> int field val label : text:string -> packing:(GObj.widget -> unit) -> unit -> unit -val button : label:string -> ?tooltip:string -> callback:(unit -> unit) -> packing:(GObj.widget -> unit) -> unit -> unit +val button : + label:string -> ?tooltip:string -> callback:(unit -> unit) -> + packing:(GObj.widget -> unit) -> unit -> unit -class form : packing:(GObj.widget -> unit) -> -object - +class form : packing:(GObj.widget -> unit) -> object method label : string -> unit method item : GObj.widget -> unit method row : GObj.widget -> unit - end diff -Nru frama-c-20110201+carbon+dfsg/src/gui/gtk_helper.ml frama-c-20111001+nitrogen+dfsg/src/gui/gtk_helper.ml --- frama-c-20110201+carbon+dfsg/src/gui/gtk_helper.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/gtk_helper.ml 2011-10-10 08:38:27.000000000 +0000 @@ -35,11 +35,12 @@ module Icon = struct - type kind = Frama_C | Left | Right | Relies_on_valid_hyp | Failed - | Maybe | Attach | Check - | Custom of string + type kind = Frama_C | Left | Right + | Failed | Maybe | Check | Unmark + | Custom of string + | Feedback of Property_status.Feedback.t - let default_icon = + let default_icon = [| "12 12 2 1"; ". c #ffffff"; "# c #000000"; @@ -56,51 +57,64 @@ "#..........#"; "############"|] + module F = Property_status.Feedback + let builtins = [(Frama_C,"frama-c.ico"); (Left,"left.png"); (Right,"right.png"); - (Relies_on_valid_hyp,"relies_on_hyp.png"); (Failed, "failed.png"); (Maybe, "maybe.png"); - (Attach, "attach.png"); - (Check,"check.png"); + (Check,"check.png"); + (Unmark,"unmark.png"); + (Feedback F.Never_tried,"feedback/never_tried.png"); + (Feedback F.Unknown,"feedback/unknown.png"); + (Feedback F.Valid,"feedback/surely_valid.png"); + (Feedback F.Invalid,"feedback/surely_invalid.png"); + (Feedback F.Considered_valid,"feedback/considered_valid.png"); + (Feedback F.Valid_under_hyp,"feedback/valid_under_hyp.png"); + (Feedback F.Invalid_under_hyp,"feedback/invalid_under_hyp.png"); + (Feedback F.Invalid_but_dead,"feedback/invalid_but_dead.png"); + (Feedback F.Unknown_but_dead,"feedback/unknown_but_dead.png"); + (Feedback F.Valid_but_dead,"feedback/valid_but_dead.png"); + (Feedback F.Inconsistent,"feedback/inconsistent.png"); ] type icon = Filename of string | Pixbuf of GdkPixbuf.pixbuf let h = Hashtbl.create 7 - let () = - List.iter - (fun (k,f) -> Hashtbl.add h k (Filename f)) + let () = + List.iter + (fun (k,f) -> Hashtbl.add h k (Filename f)) builtins - let get k = - try match Hashtbl.find h k with - | Filename f -> - let p = - try GdkPixbuf.from_file (Config.datadir ^ "/" ^ f) - with Glib.GError _ -> - Gui_parameters.warning ~once:true - "Frama-C images not found. Is FRAMAC_SHARE correctly set?"; - GdkPixbuf.from_xpm_data default_icon - in - Hashtbl.replace h k (Pixbuf p); - p - | Pixbuf p -> p - with Not_found -> assert false + let default () = GdkPixbuf.from_xpm_data default_icon + let get k = + try match Hashtbl.find h k with + | Filename f -> + let p = + try GdkPixbuf.from_file (Config.datadir ^ "/" ^ f) + with Glib.GError _ -> + Gui_parameters.warning ~once:true + "Frama-C images not found. Is FRAMAC_SHARE correctly set?"; + default () + in + Hashtbl.replace h k (Pixbuf p); p + | Pixbuf p -> p + with Not_found -> assert false + let register ~name ~file = Hashtbl.replace h (Custom name) (Filename file) - + end module Configuration = struct include Cilutil let configuration_file =(* This is the user home directory *) Filename.concat (try Sys.getenv "USERPROFILE" (*Win32*) with Not_found -> - try Sys.getenv "HOME" (*Unix like*) with Not_found -> - ".") + try Sys.getenv "HOME" (*Unix like*) with Not_found -> + ".") "frama-c-gui.config" let load () = Cilutil.loadConfiguration configuration_file @@ -114,8 +128,8 @@ with Not_found -> match default with | None -> raise Not_found | Some v -> - set key (ConfInt v); - v + set key (ConfInt v); + v let use_int = useConfigurationInt let find_float ?default key = @@ -123,8 +137,8 @@ with Not_found -> match default with | None -> raise Not_found | Some v -> - set key (ConfFloat v); - v + set key (ConfFloat v); + v let use_float = useConfigurationFloat let find_bool ?default key = @@ -132,8 +146,8 @@ with Not_found -> match default with | None -> raise Not_found | Some v -> - set key (ConfBool v); - v + set key (ConfBool v); + v let use_bool = useConfigurationBool let find_string = findConfigurationString @@ -251,11 +265,11 @@ try try for i = 1 to 6 do - idx := i; - if len = i then raise Exit; - let pre = String.sub s 0 (len - i) in - let suf = String.sub s (len - i) i in - if Glib.Utf8.validate pre then raise (Found (pre, suf)) + idx := i; + if len = i then raise Exit; + let pre = String.sub s 0 (len - i) in + let suf = String.sub s (len - i) i in + if Glib.Utf8.validate pre then raise (Found (pre, suf)) done; buggy_string, "" with Exit -> @@ -273,20 +287,20 @@ ignore (Glib.Io.add_watch channel ~prio:0 ~cond:[`IN; `HUP; `ERR] ~callback: begin fun cond -> try if List.mem `IN cond then begin - (* On Windows, you must use Io.read *) - let len = Glib.Io.read channel ~buf ~pos:0 ~len in - len >= 1 && - (let full_string = !current_partial ^ String.sub buf 0 len in - let to_emit, c = splitting_for_utf8 full_string in - current_partial := c; - callback to_emit) + (* On Windows, you must use Io.read *) + let len = Glib.Io.read channel ~buf ~pos:0 ~len in + len >= 1 && + (let full_string = !current_partial ^ String.sub buf 0 len in + let to_emit, c = splitting_for_utf8 full_string in + current_partial := c; + callback to_emit) end else false with e -> ignore - (callback + (callback ("Channel redirector got an exception: " - ^ (Printexc.to_string e))); + ^ (Printexc.to_string e))); false end) @@ -304,12 +318,12 @@ let get_all () = let l = ref [] in model#foreach (fun _ row -> - l := model#get ~row ~column ::!l ; - false); + l := model#get ~row ~column ::!l ; + false); !l in let view = GTree.view ~model ~reorderable:true ~packing () in - let view_column = GTree.view_column ~title:"Source file" () in + let view_column = GTree.view_column ~title:"Source file(s)" () in let str_renderer = GTree.cell_renderer_text [] in view_column#pack str_renderer; view_column#add_attribute str_renderer "text" column; @@ -572,15 +586,10 @@ in ignore (w#connect#any ~callback:(fun e -> - Format.eprintf "TRACING event: %s@." (string_of_event e); - false)) + Format.eprintf "TRACING event: %s@." (string_of_event e); + false)) -module MAKE_CUSTOM_LIST - (A:sig - type t - val custom_value: Gobject.g_type -> t -> column:int -> Gobject.basic - val column_list:GTree.column_list - end) = +module MAKE_CUSTOM_LIST(A:sig type t end) = struct type custom_list = {finfo: A.t; @@ -615,12 +624,12 @@ method custom_get_path (row:custom_list) : Gtk.tree_path = GTree.Path.create [row.fidx] - method custom_value (t:Gobject.g_type) (row:custom_list) ~column = - A.custom_value t row.finfo ~column + method custom_value (_t:Gobject.g_type) (_row:custom_list) ~column:_ = + assert false method custom_iter_next (row:custom_list) : custom_list option = let nidx = succ row.fidx in - self#find_opt nidx + self#find_opt nidx method custom_iter_children (rowopt:custom_list option):custom_list option = match rowopt with @@ -654,12 +663,23 @@ done; last_idx <- 0; H.clear roots; - - end let custom_list () = - new custom_list_class A.column_list + new custom_list_class (new GTree.column_list) + + let make_view_column model renderer properties ~title = + let m_renderer renderer (lmodel:GTree.model) iter = + let (path:Gtk.tree_path) = lmodel#get_path iter in + let props = match model#custom_get_iter path with + | Some {finfo=v} -> properties v + | None -> [] + in + renderer#set_properties props + in + let cview = GTree.view_column ~title ~renderer:(renderer,[]) () in + cview#set_cell_data_func renderer (m_renderer renderer); + cview end @@ -683,9 +703,12 @@ ?parent ~buttons:GWindow.Buttons.ok ~title:"Error" - ~modal:false + ~position:`CENTER_ALWAYS + ~modal:true () in + w#show (); + w#present (); ignore (w#run ()); w#destroy () @@ -694,8 +717,8 @@ let bfmt = Format.formatter_of_buffer b in Format.kfprintf (function fmt -> - Format.pp_print_flush fmt (); - let content = Buffer.contents b in + Format.pp_print_flush fmt (); + let content = Buffer.contents b in self#error_string ?parent content) bfmt fmt @@ -739,11 +762,11 @@ None | Globals.No_such_entry_point msg -> (try - Gui_parameters.abort "%s" msg + Gui_parameters.abort "%s" msg with | Log.AbortError _ as e -> - self#display_toplevel_error ?parent ~cancelable e; - None + self#display_toplevel_error ?parent ~cancelable e; + None | _ -> assert false) | e when Cmdline.catch_at_toplevel e -> self#display_toplevel_error ?parent ~cancelable e; @@ -818,8 +841,8 @@ ~destroy_with_parent:true () in - dialog#add_button_stock `CLOSE `CANCEL ; - dialog#add_button_stock `NEW `OPEN; + dialog#add_button_stock `CANCEL `CANCEL ; + dialog#add_button_stock `OK `OPEN; let hbox = GPack.box `HORIZONTAL ~packing:dialog#vbox#add () in let filechooser = GFile.chooser_widget ~action:`OPEN @@ -854,9 +877,9 @@ (match dialog#run () with | `OPEN -> main_ui#protect - ~cancelable:true - ~parent:(dialog :> GWindow.window_skel) - (fun () -> f (get_all ())) + ~cancelable:true + ~parent:(dialog :> GWindow.window_skel) + (fun () -> f (get_all ())) | `DELETE_EVENT | `CANCEL -> ()); dialog#destroy () @@ -868,22 +891,19 @@ let starting_time = if has_timeout then Unix.time () else 0. in let for_idle () = match check_result () with - | Command.Not_ready kill -> + | Command.Not_ready kill -> if has_timeout && Unix.time () -. starting_time >= hang_on then begin kill (); f (Unix.WSIGNALED Sys.sigalrm); false - end + end else true | Command.Result p -> f p; false in let prio = Glib.int_of_priority `LOW in ignore (Glib.Idle.add ~prio for_idle) -let () = - Task.on_idle := - (fun f -> ignore (Glib.Timeout.add ~ms:50 ~callback:f)) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/gui/gtk_helper.mli frama-c-20111001+nitrogen+dfsg/src/gui/gtk_helper.mli --- frama-c-20110201+carbon+dfsg/src/gui/gtk_helper.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/gtk_helper.mli 2011-10-10 08:38:27.000000000 +0000 @@ -32,20 +32,21 @@ (** Some generic icon management tools. @since Carbon-20101201 *) module Icon: sig - (** Generic icons available in every proper install of Frama-C. - To be able to use [Custom s] you must have called + (** Generic icons available in every proper install of Frama-C. + To be able to use [Custom s] you must have called [register ~name:s ~file] orelse you will get an generic icon placeholder. *) - type kind = Frama_C | Left | Right | Relies_on_valid_hyp | Failed - | Maybe | Attach | Check - | Custom of string + type kind = Frama_C | Left | Right + | Failed | Maybe | Check | Unmark + | Custom of string + | Feedback of Property_status.Feedback.t - (** [register ~name ~file] registers the kind [Custom name] associated - to the filename [file]. + (** [register ~name ~file] registers the kind [Custom name] associated + to the filename [file]. [$FRAMAC_SHARE/f] should point to an existing file containing - an image loadable by GdkPixbuf. + an image loadable by GdkPixbuf. *) val register: name:string -> file:string -> unit @@ -53,12 +54,15 @@ (** @return the pixbuf associated to the given kind. If the given kind is [Custom s] and no one ever called [register ~name:s ~file] where [file] is such that - [$(FRAMAC_SHARE)/f] is not a real image file loadable by GdkPixbuf, + [$(FRAMAC_SHARE)/f] is not a real image file loadable by GdkPixbuf, a generic icon placeholder is returned. *) val get: kind -> GdkPixbuf.pixbuf + + val default: unit -> GdkPixbuf.pixbuf + end - + (** Configuration module for the GUI: all magic visual constants should use this mechanism (window width, ratios, ...). @@ -145,13 +149,13 @@ ?timeout:int -> ?stdout:Buffer.t -> ?stderr:Buffer.t -> - string -> string array -> + string -> string array -> (Unix.process_status -> unit) -> unit (** Launches the given command and calls the given - function when the process terminates. - If timeout is > 0 (the default) then the process will be killed if it does - not end before timeout seconds. + function when the process terminates. + If timeout is > 0 (the default) then the process will be killed if it does + not end before timeout seconds. In this case the returned process status will be [Unix.WSIGNALED Sys.sigalrm]. *) @@ -177,10 +181,10 @@ (** 2 Tooltips *) val do_tooltip: ?tooltip:string -> < coerce: GObj.widget; .. > -> unit - (** Add the given tooltip to the given widget. + (** Add the given tooltip to the given widget. It has no effect if no tooltip is given. *) - + (** {2 Chooser} *) type 'a chooser = @@ -198,7 +202,7 @@ ?sensitive:(unit -> bool) -> ?width:int -> int chooser (** Pack a spin button. - By default, sensitivity is set to true when this function is called. *) + By default, sensitivity is set to true when this function is called. *) val on_string: ?tooltip:string -> ?use_markup:bool -> ?validator:(string -> bool) @@ -295,12 +299,7 @@ (** A functor to build custom Gtk lists. It may be part of a future lablgtk release. Do not change anything without changing lablgtk svn.*) -module MAKE_CUSTOM_LIST(A : sig - type t - val custom_value : - Gobject.g_type -> t -> column:int -> Gobject.basic - val column_list : GTree.column_list - end) +module MAKE_CUSTOM_LIST(A : sig type t end) : sig type custom_list = { finfo : A.t; fidx : int; } val inbound : int -> 'a array -> bool @@ -328,6 +327,11 @@ method clear : unit -> unit end val custom_list : unit -> custom_list_class + val make_view_column : + custom_list_class -> ('b,'a) #GTree.cell_renderer_skel -> + (A.t -> 'a list) -> + title:string -> + GTree.view_column end (* diff -Nru frama-c-20110201+carbon+dfsg/src/gui/gui_parameters.mli frama-c-20111001+nitrogen+dfsg/src/gui/gui_parameters.mli --- frama-c-20110201+carbon+dfsg/src/gui/gui_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/gui_parameters.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,9 +20,12 @@ (* *) (**************************************************************************) +(** Kernel of the GUI. *) + include Plugin.S -module Undo: Plugin.BOOL +module Undo: Plugin.Bool +(** Option -undo. *) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/gui/help_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/help_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/help_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/help_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -23,15 +23,19 @@ let show main_ui = let authors = [ "Patrick Baudin" ; + "Richard Bonichon"; "Loïc Correnson"; "Pascal Cuoq"; + "Zaynah Dargaye"; "Jean-Christophe Filliâtre"; + "Philippe Herrmann"; "Claude Marché"; "Benjamin Monate"; "Yannick Moy"; "Anne Pacalet"; "Virgile Prévosto"; - "Julien Signoles" ] + "Julien Signoles"; + "Boris Yakobowski" ] in let copyright (* should be automatically generated *) = "\t © CEA and INRIA for the Frama-C kernel and plug-ins pdg, scope, \ @@ -81,18 +85,20 @@ (fun window -> let menu_manager = window#menu_manager () in let _helpitem, helpmenu = - menu_manager#add_menu "_Help" - ~pos:(List.length menu_manager#factory#menu#children) + menu_manager#add_menu "_Help" + ~pos:(List.length menu_manager#factory#menu#children) in (* helpitem#set_right_justified true;*) ignore - (menu_manager#add_entries - helpmenu - [ Menu_manager.Menubar(Some `ABOUT, "About"), - fun () -> show window ])) + (menu_manager#add_entries + helpmenu + [ Menu_manager.menubar ~icon:`ABOUT "About" + (Menu_manager.Unit_callback (fun () -> show window)); + ]); + ) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/history.ml frama-c-20111001+nitrogen+dfsg/src/gui/history.ml --- frama-c-20110201+carbon+dfsg/src/gui/history.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/history.ml 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,201 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +type history_elt = + | Global of global + | Localizable of Pretty_source.localizable + +(* Two history elements belong to the same function *) +let history_elt_in_same_fun e1 e2 = + let f = function + | Global (GVarDecl (_, vi, _) | GFun ({svar = vi}, _)) -> + (try Some (Globals.Functions.get vi) + with Not_found -> None) + | Localizable l -> + Pretty_source.kf_of_localizable l + | _ -> None + in + match f e1 with + | None -> false + | Some f1 -> match f e2 with + | None -> false + | Some f2 -> Kernel_function.equal f1 f2 + +let key_collapse_nearby = "history.collapse_nearby" + +let collapse_nearby_clicks () = + Gtk_helper.Configuration.find_bool ~default:true key_collapse_nearby + +let set_collapse_nearby v = + Gtk_helper.Configuration.set + key_collapse_nearby (Gtk_helper.Configuration.ConfBool v) + +module HistoryElt = + Datatype.Make + (struct + include Datatype.Undefined + type t = history_elt + let name = "History.history_elt" + let reprs = List.map (fun g -> Global g) Cil_datatype.Global.reprs + let mem_project = Datatype.never_any_project + let equal e1 e2 = + let b = match e1, e2 with + | Global g1, Global g2 -> Cil_datatype.Global.equal g1 g2 + | Localizable l1, Localizable l2 -> + Pretty_source.Localizable.equal l1 l2 + | (Global _ | Localizable _), __ -> false + in + b || if collapse_nearby_clicks () + then history_elt_in_same_fun e1 e2 + else false + end) + +type history = { + back: history_elt list; + current: history_elt option; + forward: history_elt list; +} + +let default_history = { + back = []; + current = None; + forward = []; +} + +module History = + Datatype.Make + (struct + include Datatype.Undefined + type t = history + let name = "History.history" + let reprs = [default_history] + let mem_project = Datatype.never_any_project + let pretty fmt h = + Format.fprintf fmt "back %d, cur %b, forward %d" + (List.length h.back) (h.current <> None) (List.length h.forward) + end) + +include History + +module CurrentHistory = + State_builder.Ref + (History) + (struct + let name = "History.CurrentHistory" + let dependencies = [Ast.self] + let kind = `Irrelevant + let default _ = default_history + end) + +(* This is correct because the implementation makes sur that [.current = None] + implies [.forward = [] && .back = []] *) +let is_empty () = (CurrentHistory.get ()).current = None +let can_go_back () = (CurrentHistory.get ()).back <> [] +let can_go_forward () = (CurrentHistory.get ()).forward <> [] + +let display_elt = ref (fun _ -> ()) +let set_display_elt_callback f = display_elt := f + +let show_current () = + let h = CurrentHistory.get () in + Extlib.may !display_elt h.current; + CurrentHistory.set h + +let back () = + let h = CurrentHistory.get () in + match h.current, h.back with + | Some cur, prev :: prevs -> + let h' = {back = prevs; current = Some prev; forward= cur::h.forward} in + !display_elt prev; + CurrentHistory.set h' + + | None, prev :: prevs -> + let h' = { back = prevs; current = Some prev ; forward = h.forward } in + !display_elt prev; + CurrentHistory.set h' + + | _, [] -> () + +let forward () = + let h = CurrentHistory.get () in + match h.current, h.forward with + | Some cur, next :: nexts -> + let h' = { back = cur::h.back; current = Some next; forward = nexts} in + !display_elt next; + CurrentHistory.set h' + + | None, next :: nexts -> + let h' = { back = h.back; current = Some next; forward = nexts } in + !display_elt next; + CurrentHistory.set h' + + | _, [] -> () + +let on_current_history () = + let h = CurrentHistory.get () in + fun f -> CurrentHistory.set h; f () + +let push cur = + let h = CurrentHistory.get () in + let h' = match h.current with + | None -> { back = h.back; current = Some cur; forward = [] } + | Some prev -> + if HistoryElt.equal cur prev + then h + else { back = prev :: h.back; current = Some cur; forward = [] } + in + CurrentHistory.set h' + +let apply_on_selected f = + match (CurrentHistory.get ()).current with + | None | Some (Global _) -> () + | Some (Localizable loc) -> f loc + +let create_buttons (menu_manager : Menu_manager.menu_manager) = + let refresh = menu_manager#refresh in + menu_manager#add_plugin ~title:"Navigation" + [ + Menu_manager.toolmenubar + ~sensitive:can_go_back ~icon:`GO_BACK + ~label:"Back" ~tooltip:"Go to previous visited source location" + (Menu_manager.Unit_callback (fun () -> back (); refresh ())); + Menu_manager.toolmenubar + ~sensitive:can_go_forward ~icon:`GO_FORWARD + ~label:"Forward" ~tooltip:"Go to next visited source location" + (Menu_manager.Unit_callback (fun () -> forward (); refresh ())); + Menu_manager.menubar + "Collapse nearby clicks" + (Menu_manager.Bool_callback + ((fun v -> set_collapse_nearby v; refresh ()), + collapse_nearby_clicks)) + (* TODO: the callback should set the tooltips of the buttons, but I + cannot find a lablgtk way to do this *); + ] + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/history.mli frama-c-20111001+nitrogen+dfsg/src/gui/history.mli --- frama-c-20110201+carbon+dfsg/src/gui/history.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/history.mli 2011-10-10 08:38:27.000000000 +0000 @@ -0,0 +1,72 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** {1 Source code navigation history.} + @since Nitrogen-20111001 *) + +type history_elt = + | Global of Cil_types.global + | Localizable of Pretty_source.localizable + +val is_empty: unit -> bool +(** Does the history contain an event. *) + +val can_go_back: unit -> bool +(** Are there past events in the history. *) + +val can_go_forward: unit -> bool +(** Are there events to redo in the history. *) + +val back: unit -> unit +(** If possible, go back one step in the history. *) + +val forward: unit -> unit +(** If possible (ie. if [back] has been called), go forward one step + in the history. *) + +val push: history_elt -> unit + +(** Add the element to the current history; clears the forward history, + and push the old current element to the past history. *) + +val show_current: unit -> unit +(** Redisplay the current history point, if available. Useful to + refresh the gui. *) + +val on_current_history: unit -> ((unit -> unit) -> unit) +(** [on_current_history ()] returns a closure [at] such that [at f] + will execute [f] in a context in which the history will be the + one relevant when [on_current_history] was executed. *) + +val apply_on_selected: (Pretty_source.localizable -> unit) -> unit + (** [apply_on_selected f] applies [f] to the currently selected + [Pretty_source.localizable]. Does nothing if nothing is selected. *) + +(**/**) +val set_display_elt_callback: (history_elt -> unit) -> unit +val create_buttons: Menu_manager.menu_manager -> Menu_manager.item array + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/launcher.ml frama-c-20111001+nitrogen+dfsg/src/gui/launcher.ml --- frama-c-20110201+carbon+dfsg/src/gui/launcher.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/launcher.ml 2011-10-10 08:38:27.000000000 +0000 @@ -22,7 +22,7 @@ open Gtk_helper -module Parameters_hook = Hook.Make(struct end) +module Kernel_hook = Hook.Make(struct end) class type basic_main = object inherit host @@ -34,18 +34,22 @@ ignore (host#protect ~cancelable:true ~parent:(dialog :> GWindow.window_skel) (fun () -> dialog#destroy (); - Parameters_hook.apply (); - !Db.Main.play (); - host#reset ())); - Parameters_hook.clear () + Kernel_hook.apply (); + !Db.Main.play ())); + (* Even if the above operation failed, we try to reset the gui, as the + plugins might have done something before crashing *) + ignore (host#protect ~cancelable:false ~parent:(dialog :> GWindow.window_skel) + host#reset); + Kernel_hook.clear () let add_parameter (box:GPack.box) p = - let name = p.Plugin.o_name in - let tooltip = p.Plugin.o_help in + let name = p.Parameter.name in + let tooltip = p.Parameter.help in + let is_set = p.Parameter.is_set in let highlight s = "" ^ s ^ "" in let hname = highlight name in - match p.Plugin.o_kind with - | Plugin.Bool ({ Plugin.get = get; set = set; is_set = is_set }, None) -> + match p.Parameter.accessor with + | Parameter.Bool ({ Parameter.get = get; set = set }, None) -> let use_markup = is_set () in let name = if use_markup then hname else name in (* fix bts#510: a parameter [p] must be set if and only if it is set by the @@ -53,10 +57,9 @@ value if setting another parameter [p'] modifies [p] via hooking. *) let old = get () in let set r = if r <> old then set r in - Parameters_hook.extend (on_bool ~tooltip ~use_markup box name get set); + Kernel_hook.extend (on_bool ~tooltip ~use_markup box name get set); use_markup - | Plugin.Bool ({ Plugin.get = get; set = set; is_set = is_set }, - Some negative_name) -> + | Parameter.Bool ({ Parameter.get = get; set = set }, Some negative_name) -> let use_markup = is_set () in let name, negative_name = if use_markup then hname, highlight negative_name @@ -64,40 +67,39 @@ in let old = get () in let set r = if r <> old then set r in - Parameters_hook.extend + Kernel_hook.extend (on_bool_radio ~tooltip ~use_markup box name negative_name get set); use_markup - | Plugin.Int ({ Plugin.get = get; set = set; is_set = is_set }, range) -> + | Parameter.Int ({ Parameter.get = get; set = set }, range) -> let use_markup = is_set () in let name = if use_markup then hname else name in let lower, upper = range () in let old = get () in let set r = if r <> old then set r in - Parameters_hook.extend + Kernel_hook.extend (on_int ~tooltip ~use_markup ~lower ~upper box name get set); use_markup - | Plugin.String({ Plugin.get = get; set = set; is_set = is_set }, - possible_values) -> + | Parameter.String({ Parameter.get = get; set = set }, possible_values) -> let use_markup = is_set () in let name = if use_markup then hname else name in let old = get () in let set r = if r <> old then set r in (match possible_values () with | [] -> - Parameters_hook.extend (on_string ~tooltip ~use_markup box name get set) + Kernel_hook.extend (on_string ~tooltip ~use_markup box name get set) | v -> - Parameters_hook.extend - (on_string_completion - ~tooltip ~use_markup ~validator:(fun s -> List.mem s v) - v box name get set)); + Kernel_hook.extend + (on_string_completion + ~tooltip ~use_markup ~validator:(fun s -> List.mem s v) + v box name get set)); use_markup - | Plugin.StringSet { Plugin.get = get; set = set; is_set = is_set } -> + | Parameter.String_set { Parameter.get = get; set = set } + | Parameter.String_list { Parameter.get = get; set = set } -> let use_markup = is_set () in let name = if use_markup then hname else name in let old = get () in let set r = if r <> old then set r in - Parameters_hook.extend - (on_string_set ~tooltip ~use_markup box name get set); + Kernel_hook.extend (on_string_set ~tooltip ~use_markup box name get set); use_markup let mk_text ~highlight text = @@ -143,9 +145,9 @@ List.sort (fun (s1, _) (s2, _) -> String.compare s1 s2) (Hashtbl.fold - (fun l g acc -> if g = [] then acc else (l, g) :: acc) - p.Plugin.p_parameters - []) + (fun l g acc -> if g = [] then acc else (l, g) :: acc) + p.Plugin.p_parameters + []) in let highlight = List.fold_left @@ -173,9 +175,9 @@ () in ignore (dialog#misc#connect#size_allocate - (fun ({Gtk.width=w;Gtk.height=h}) -> - Configuration.set "launcher_width" (Configuration.ConfInt w); - Configuration.set "launcher_height" (Configuration.ConfInt h))); + (fun ({Gtk.width=w;Gtk.height=h}) -> + Configuration.set "launcher_width" (Configuration.ConfInt w); + Configuration.set "launcher_height" (Configuration.ConfInt h))); let box = GPack.vbox () in let scrolling = GBin.scrolled_window diff -Nru frama-c-20110201+carbon+dfsg/src/gui/menu_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/menu_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/menu_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/menu_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -21,27 +21,77 @@ (**************************************************************************) type where = - | Toolbar of GtkStock.id * string + | Toolbar of GtkStock.id * string * string | Menubar of GtkStock.id option * string - | ToolMenubar of GtkStock.id * string + | ToolMenubar of GtkStock.id * string * string -type entry = where * (unit -> unit) +type callback_state = + | Unit_callback of (unit -> unit) + | Bool_callback of (bool -> unit) * (unit -> bool) + +type entry = { + e_where: where; + e_callback: callback_state; + e_sensitive: unit -> bool; +} + +let toolbar ?(sensitive=(fun _ -> true)) ~icon ~label ?(tooltip=label) callback = { + e_where = Toolbar (icon, label, tooltip); + e_callback = callback; + e_sensitive = sensitive; +} + +let menubar ?(sensitive=(fun _ -> true)) ?icon text callback = { + e_where = Menubar (icon, text); + e_callback = callback; + e_sensitive = sensitive; +} + +let toolmenubar ?(sensitive=(fun _ -> true)) ~icon ~label ?(tooltip=label) callback = { + e_where = ToolMenubar (icon, label, tooltip); + e_callback = callback; + e_sensitive = sensitive; +} + + +type button_type = + | BStandard of GButton.tool_button + | BToggle of GButton.toggle_tool_button +let bt_type_as_skel = function + | BStandard b -> (b :> GButton.tool_button_skel) + | BToggle b -> (b :> GButton.tool_button_skel) + +type menu_item_type = + | MStandard of GMenu.menu_item + | MCheck of GMenu.check_menu_item +let mitem_type_as_skel = function + | MCheck m -> (m :> GMenu.menu_item_skel) + | MStandard m -> (m :> GMenu.menu_item_skel) + +class item ?menu ?menu_item ?button group = object (self) + + method menu_item = + match menu_item with Some (MStandard m) -> Some m | _ -> None + method check_menu_item = + match menu_item with Some (MCheck m) -> Some m | _ -> None + method menu_item_skel = + match menu_item with Some m -> Some (mitem_type_as_skel m) | _ -> None + + method tool_button = + match button with Some (BStandard b) -> Some b | _ -> None + method toggle_tool_button = + match button with Some (BToggle b) -> Some b | _ -> None + method tool_button_skel = + match button with Some b -> Some (bt_type_as_skel b) | None -> None -class item ?menu_item ?tool_button group = object - method menu_item: GMenu.menu_item option = menu_item - method tool_button: GButton.tool_button option = tool_button method add_accelerator modifier c = Extlib.may - (fun i -> - (* unfortunatly full type annotation required *) - let f: group:Gtk.accel_group -> - ?modi:Gdk.Tags.modifier list -> - ?flags:Gtk.Tags.accel_flag list -> - Gdk.keysym -> unit = - i#add_accelerator - in - f ~group ~flags:[ `VISIBLE ] ~modi:[ modifier ] (int_of_char c)) - menu_item + (fun (i : GMenu.menu_item_skel) -> + i#add_accelerator + ~group ~flags:[ `VISIBLE ] ~modi:[ modifier ] (int_of_char c) + ) self#menu_item_skel + + method menu: GMenu.menu option = menu end @@ -73,6 +123,10 @@ val debug_item_and_menu = add_submenu menubar ~pos:(-1) "_Debug" val mutable debug_actions = [] + val mutable menubar_items = [] + val mutable toolbar_buttons = [] + val mutable set_active_states = [] + (** {2 API for plug-ins} *) method add_plugin ?title = self#add_entries ?title analyses_menu @@ -81,18 +135,18 @@ let items = self#add_entries ?title (snd debug_item_and_menu) entries in let action item = if show () then begin - Extlib.may (fun i -> i#misc#show ()) item#menu_item; - Extlib.may (fun i -> i#misc#show ()) item#tool_button + Extlib.may (fun i -> i#misc#show ()) item#menu_item; + Extlib.may (fun i -> i#misc#show ()) item#tool_button end else begin - Extlib.may (fun i -> i#misc#hide ()) item#menu_item; - Extlib.may (fun i -> i#misc#hide ()) item#tool_button + Extlib.may (fun i -> i#misc#hide ()) item#menu_item; + Extlib.may (fun i -> i#misc#hide ()) item#tool_button end in let l = List.rev debug_actions in Array.iter (fun i -> - action i; - debug_actions <- (fun () -> action i) :: l) + action i; + debug_actions <- (fun () -> action i) :: l) items; items @@ -105,11 +159,11 @@ (* Toolbar *) let toolbar_pos = (* The first group will be at the end of the toolbar. - By default, add all the others just before this very first group. *) + By default, add all the others just before this very first group. *) ref (match pos, first_tool_separator with - | None, None -> 0 - | None, Some sep -> max 0 (toolbar#get_item_index sep) - | Some p, _ -> p) + | None, None -> 0 + | None, Some sep -> max 0 (toolbar#get_item_index sep) + | Some p, _ -> p) in let toolbar_packing w = toolbar#insert ~pos:!toolbar_pos w; @@ -117,55 +171,99 @@ in let add_tool_separator () = if !toolbar_pos > 0 || first_tool_separator = None then begin - let s = GButton.separator_tool_item ~packing:toolbar_packing () in - match first_tool_separator with - | None -> first_tool_separator <- Some s - | Some _ -> () + let s = GButton.separator_tool_item ~packing:toolbar_packing () in + match first_tool_separator with + | None -> first_tool_separator <- Some s + | Some _ -> () end in let extra_tool_separator () = match pos with | Some 0 -> add_tool_separator () | _ -> () in - let add_item_toolbar stock tooltip callback = - let label = + let add_item_toolbar stock label tooltip callback sensitive = +(* + let tooltip = try if (GtkStock.Item.lookup stock).GtkStock.label = "" then Some tooltip else None with Not_found -> Some tooltip in - let b = GButton.tool_button ?label ~stock ~packing:toolbar_packing () in - b#set_tooltip (GData.tooltips ()) tooltip ""; - ignore (b#connect#clicked ~callback); +*) + let b = match callback with + | Unit_callback callback -> + let b = GButton.tool_button + ~label:tooltip ~stock ~packing:toolbar_packing () + in + b#set_label label; + ignore (b#connect#clicked ~callback); + BStandard b + | Bool_callback (callback, active) -> + let b = GButton.toggle_tool_button + ~active:(active ()) ~label:tooltip ~stock + ~packing:toolbar_packing () + in + b#set_label tooltip; + ignore (b#connect#toggled + ~callback:(fun () -> callback b#get_active)); + set_active_states <- + (fun () -> b#set_active (active ())) :: set_active_states; + BToggle b + in + (bt_type_as_skel b)#set_tooltip (GData.tooltips ()) tooltip ""; + toolbar_buttons <- (b, sensitive) :: toolbar_buttons; b in (* Menubar *) let menu_pos = ref (match pos with None -> -1 | Some p -> p) in - let menubar_packing w = - let pos = !menu_pos in - (match title with - | None -> container#insert ~pos w - | Some s -> (snd (add_submenu container ~pos s))#append w); - if pos <> -1 then incr menu_pos + let container_packing w = + container#insert ~pos:!menu_pos w; + if !menu_pos <> -1 then incr menu_pos + in + let (!!) = Lazy.force in + let menubar_packing, in_menu = + let aux = + lazy (* if [title] is not None, we want to create the submenu only once, + and late enough *) + (match title with + | None -> container_packing, container + | Some s -> + let sub = snd (add_submenu container ~pos:!menu_pos s) in + (fun w -> sub#append w), sub + ) + in + lazy (fst !!aux), lazy (snd !!aux) in let add_menu_separator = - let first = ref true in fun () -> - if !menu_pos > 0 || (!menu_pos = -1 && container#children <> []) - then begin - ignore (GMenu.separator_item ~packing:menubar_packing ()); - first := false - end - in - let add_item_menu stock_opt label callback = - let item = match stock_opt with - | None -> GMenu.menu_item ~packing:menubar_packing ~label () - | Some stock -> - let image = GMisc.image ~stock () in - (GMenu.image_menu_item ~image ~packing:menubar_packing ~label () - :> GMenu.menu_item) + if !menu_pos > 0 || (!menu_pos = -1 && container#children <> []) then + ignore (GMenu.separator_item ~packing:container_packing ()) + in + let add_item_menu stock_opt label callback sensitive = + let item = match stock_opt, callback with + | None, Unit_callback callback -> + let mi = GMenu.menu_item ~packing:!!menubar_packing ~label () in + ignore (mi#connect#activate callback); + MStandard mi + | Some stock, Unit_callback callback -> + let image = GMisc.image ~stock () in + let mi = + (GMenu.image_menu_item + ~image ~packing:!!menubar_packing ~label () + :> GMenu.menu_item) + in + ignore (mi#connect#activate callback); + MStandard mi + | _, Bool_callback (callback, active) -> + let mi = GMenu.check_menu_item + ~packing:!!menubar_packing ~label ~active:(active ()) () + in + ignore (mi#connect#activate (fun () -> callback mi#active)); + set_active_states <- + (fun () -> mi#set_active (active ())) :: set_active_states; + MCheck mi in - ignore (item#connect#activate callback); + menubar_items <- (item, sensitive) :: menubar_items; item in let extra_menu_separator () = match pos with @@ -173,29 +271,28 @@ | _ -> () in (* Entries *) - let add_item (kind, callback) = - let callback () = host#protect callback ~cancelable:false in + let add_item { e_where = kind; e_callback = callback; e_sensitive = sensitive} = match kind with - | Toolbar(stock, tooltip) -> - let tool_button = add_item_toolbar stock tooltip callback in - new item ~tool_button factory#accel_group + | Toolbar(stock, label, tooltip) -> + let button = add_item_toolbar stock label tooltip callback sensitive in + new item ~button factory#accel_group | Menubar(stock_opt, label) -> - let menu_item = add_item_menu stock_opt label callback in - new item ~menu_item factory#accel_group - | ToolMenubar(stock, label) -> - let tool_button = add_item_toolbar stock label callback in - let menu_item = add_item_menu (Some stock) label callback in - new item ~menu_item ~tool_button factory#accel_group + let menu_item = add_item_menu stock_opt label callback sensitive in + new item ~menu:!!in_menu ~menu_item factory#accel_group + | ToolMenubar(stock, label, tooltip) -> + let button = add_item_toolbar stock label tooltip callback sensitive in + let menu_item = add_item_menu (Some stock) label callback sensitive in + new item ~menu:!!in_menu ~menu_item ~button factory#accel_group in let edit_menubar = List.exists - (function (Menubar _, _) | (ToolMenubar _, _) -> true | _ -> false) - entries + (function { e_where = Menubar _ | ToolMenubar _ } -> true | _ -> false) + entries in let edit_toolbar = List.exists - (function (Toolbar _, _) | (ToolMenubar _, _) -> true | _ -> false) - entries + (function { e_where = Toolbar _ | ToolMenubar _ } -> true | _ -> false) + entries in if edit_menubar then add_menu_separator (); if edit_toolbar then add_tool_separator (); @@ -205,8 +302,12 @@ Array.of_list entries method set_sensitive b = - List.iter (fun i -> i#misc#set_sensitive b) toolbar#children; - List.iter (fun i -> i#misc#set_sensitive b) menubar#children + List.iter + (fun (i, f) -> (bt_type_as_skel i)#misc#set_sensitive (b && f ())) + toolbar_buttons; + List.iter + (fun (i, f) -> (mitem_type_as_skel i)#misc#set_sensitive (b && f())) + menubar_items (** {2 Low-level API} *) @@ -214,8 +315,19 @@ method menubar = menubar method toolbar = toolbar + method refresh () = + List.iter + (fun (i, f) -> (bt_type_as_skel i)#misc#set_sensitive (f ())) + toolbar_buttons; + List.iter + (fun (i, f) -> (mitem_type_as_skel i)#misc#set_sensitive (f())) + menubar_items; + List.iter (fun f -> f ()) set_active_states; + + initializer let reset () = + self#refresh (); List.iter (fun f -> f ()) debug_actions; let debug_item = fst debug_item_and_menu in if !Plugin.positive_debug_ref > 0 then debug_item#misc#show () diff -Nru frama-c-20110201+carbon+dfsg/src/gui/menu_manager.mli frama-c-20111001+nitrogen+dfsg/src/gui/menu_manager.mli --- frama-c-20110201+carbon+dfsg/src/gui/menu_manager.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/menu_manager.mli 2011-10-10 08:38:27.000000000 +0000 @@ -26,13 +26,57 @@ (** Where to put a new entry. @since Boron-20100401 *) type where = - | Toolbar of GtkStock.id * string (** Tooltip *) + | Toolbar of GtkStock.id * string * string (** Label then tooltip *) | Menubar of GtkStock.id option (** Stock used for the icon *) * string (** Label *) - | ToolMenubar of GtkStock.id * string (** Label and tooltip *) + | ToolMenubar of GtkStock.id * string * string (** Label then tooltip *) -(** @since Boron-20100401 *) -type entry = where * (unit -> unit) (** callback *) +(** Callback for the buttons that can be in the menus. Standard buttons/menus + have a callback with no argument. Buttons/menus with states are displayed + with checkboxes in menus, or as toggle buttons in toolbars. They receive the + after-click state as argument. The state of the button with the second + argument of [Bool_callback]. Currently checks menus cannot have images in + Gtk, sor the [GtkStock.id] fields of [where] are ignored. + + @since Nitrogen-20111001 *) +type callback_state = + | Unit_callback of (unit -> unit) + | Bool_callback of (bool -> unit) * (unit -> bool) + +(** @since Boron-20100401 + @modify Nitrogen-20111001 *) +type entry = private { + e_where: where; + e_callback: callback_state (** callback called when the button is clicked *); + e_sensitive: unit -> bool (** should the button be activated when the gui + is refreshed *); +} + +(** {2 Smart constructors for menu entries.} + + If not supplied, the [active] parameter is the function that always returns + [true]. + @since Nitrogen-20111001 *) + +val toolbar: + ?sensitive:(unit -> bool) -> + icon:GtkStock.id -> + label:string -> + ?tooltip:string -> + callback_state -> + entry + +val menubar: + ?sensitive:(unit -> bool) -> ?icon:GtkStock.id -> string -> callback_state -> + entry + +val toolmenubar: + ?sensitive:(unit -> bool) -> + icon:GtkStock.id -> + label:string -> + ?tooltip:string -> + callback_state -> + entry (** The item type corresponding to an entry. @since Boron-20100401 *) @@ -41,16 +85,34 @@ method menu_item: GMenu.menu_item option (** @since Boron-20100401 *) - method tool_button: GButton.tool_button option - (** @since Boron-20100401 *) + method check_menu_item: GMenu.check_menu_item option + (** @since Nitrogen-20111001 *) + + method menu_item_skel: GMenu.menu_item_skel option + (** @since Nitrogen-20111001 *) + + method menu: GMenu.menu option + (** Return the menu in which the item has been inserted, if meaningful + @since Nitrogen-20111001 *) method add_accelerator: Gdk.Tags.modifier -> char -> unit (** Add an accelerator iff there is a menu item. - @since Boron-20100401 *) + @since Boron-20100401 *) + + + method tool_button: GButton.tool_button option + (** @since Boron-20100401 *) + + method toggle_tool_button: GButton.toggle_tool_button option + (** @since Nitrogen-20111001 *) + + method tool_button_skel: GButton.tool_button_skel option + (** @since Nitrogen-20111001 *) end -(** @since Boron-20100401 *) +(** How to handle a Frama-C menu. + @since Boron-20100401 *) class menu_manager: ?packing:(GObj.widget -> unit) -> host:Gtk_helper.host -> object @@ -58,22 +120,22 @@ method add_plugin: ?title:string -> entry list -> item array (** Add entries dedicated to a plug-in. - If [title] is specified, then the entries are added in a dedicated - sub-menu of name [title]. - The elements of the returned array are in the same order that the ones - in the input list. - @since Boron-20100401 *) + If [title] is specified, then the entries are added in a dedicated + sub-menu of name [title]. + The elements of the returned array are in the same order that the ones + in the input list. + @since Boron-20100401 *) method add_debug: ?title:string -> ?show:(unit -> bool) -> entry list -> item array (** Add entries to the menu dedicated to debugging tools. - If [title] is specified, then the entries are added in a dedicated - sub-menu of name [title]. - If [show] is specified, then the entries are only shown when this - function returns [true] (it returns [true] by default). - The elements of the returned array are in the same order that the ones - in the input list. - @since Boron-20100401 *) + If [title] is specified, then the entries are added in a dedicated + sub-menu of name [title]. + If [show] is specified, then the entries are only shown when this + function returns [true] (it returns [true] by default). + The elements of the returned array are in the same order that the ones + in the input list. + @since Boron-20100401 *) (** {2 High-level API} *) @@ -83,14 +145,14 @@ method add_entries: ?title:string -> ?pos:int -> GMenu.menu -> entry list -> item array (** Add entries in the given menu. If [title] is specified, then the - entries are added in a dedicated sub-menu of name [title]. - The elements of the returned array are in the same order that the ones - in the input list. - @since Boron-20100401 *) + entries are added in a dedicated sub-menu of name [title]. + The elements of the returned array are in the same order that the ones + in the input list. + @since Boron-20100401 *) method set_sensitive: bool -> unit (** Set the sensitive property of all the entries. - @since Boron-20100401 *) + @since Boron-20100401 *) (** {2 Low-level API} *) @@ -103,6 +165,9 @@ method toolbar: GButton.toolbar (** @since Boron-20100401 *) + method refresh: unit -> unit + (** Reset the activation state of the buttons + @since Nitrogen-20111001 *) end (* diff -Nru frama-c-20110201+carbon+dfsg/src/gui/pretty_source.ml frama-c-20111001+nitrogen+dfsg/src/gui/pretty_source.ml --- frama-c-20110201+carbon+dfsg/src/gui/pretty_source.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/pretty_source.ml 2011-10-10 08:38:27.000000000 +0000 @@ -22,10 +22,10 @@ open Format open Cil_types -open Db_types open Db open Gtk_helper open Cil_datatype +open Cil (** The kind of object that can be selected in the source viewer *) (* [VP] TODO: unify all annotations related constructor into @@ -38,9 +38,18 @@ | PVDecl of (kernel_function option * varinfo) | PGlobal of global (* all globals but variable declarations and function - definitions. *) + definitions. *) | PIP of Property.t +(*let localizable_to_locations l = + match l with + | PStmt (_,s) | PLval (_,Kstmt s,_) + | PTermLval (_,Kstmt s,_) + -> Stmt.loc s + | PVDecl (_,v) -> v.vdecl + | PGlobal g -> Global.loc g + | PIP p -> Property.loc p +*) module Localizable = Datatype.Make (struct @@ -49,18 +58,17 @@ let name = "Pretty_source.Localizable" let reprs = List.map (fun g -> PGlobal g) Global.reprs let equal l1 l2 = match l1,l2 with - | PStmt (_,ki1), PStmt (_,ki2) -> ki1.sid = ki2.sid - | PLval (_,ki1,lv1), PLval (_,ki2,lv2) -> - Kinstr.equal ki1 ki2 && lv1 == lv2 - | PTermLval (_,ki1,lv1), PTermLval (_,ki2,lv2) -> - Kinstr.equal ki1 ki2 && Logic_utils.is_same_tlval lv1 lv2 - (* [JS 2008/01/21] term_lval are not shared: cannot use == *) - | PVDecl (_,v1), PVDecl (_,v2) -> Varinfo.equal v1 v2 - | PIP ip1, PIP ip2 -> Property.equal ip1 ip2 - | PGlobal g1, PGlobal g2 -> g1 == g2 - (* TODO: add a proper comparison between two globals *) - | (PStmt _ | PLval _ | PTermLval _ | PVDecl _ | PIP _ | PGlobal _), _ - -> false + | PStmt (_,ki1), PStmt (_,ki2) -> ki1.sid = ki2.sid + | PLval (_,ki1,lv1), PLval (_,ki2,lv2) -> + Kinstr.equal ki1 ki2 && lv1 == lv2 + | PTermLval (_,ki1,lv1), PTermLval (_,ki2,lv2) -> + Kinstr.equal ki1 ki2 && Logic_utils.is_same_tlval lv1 lv2 + (* [JS 2008/01/21] term_lval are not shared: cannot use == *) + | PVDecl (_,v1), PVDecl (_,v2) -> Varinfo.equal v1 v2 + | PIP ip1, PIP ip2 -> Property.equal ip1 ip2 + | PGlobal g1, PGlobal g2 -> Cil_datatype.Global.equal g1 g2 + | (PStmt _ | PLval _ | PTermLval _ | PVDecl _ | PIP _ | PGlobal _), _ + -> false let mem_project = Datatype.never_any_project end) @@ -102,21 +110,33 @@ val find : state -> int -> (int * int) * localizable val hilite : state -> unit val set_hilite : state -> (unit -> unit) -> unit + val add_finalizer: state -> (unit -> unit) -> unit + val finalize: state -> unit end = struct type state = { table : (int*int,localizable) Hashtbl.t; - mutable hiliter : unit -> unit} + mutable hiliter : unit -> unit; + mutable finalizers: (unit -> unit) list; + } let create () = {table = Hashtbl.create 97; - hiliter = (fun () -> ())} + hiliter = (fun () -> ()); + finalizers = []; + } let hilite state = state.hiliter () let set_hilite state f = state.hiliter <- f + let add_finalizer state f = + state.finalizers <- f :: state.finalizers + + let finalize state = + List.iter (fun f -> f ()) (List.rev state.finalizers) + (* Add a location range only if it is not already there. Visually only the innermost pretty printed entity is kept. For example: 'loop assigns x;' will be indexed as an assigns @@ -130,9 +150,9 @@ let best = ref None in let update ((b,e) as loc) sid = if b <= p && p <= e then - match !best with - | None -> best := Some (loc, sid) - | Some ((b',e'),_) -> if e-b < e'-b' then best := Some (loc, sid) + match !best with + | None -> best := Some (loc, sid) + | Some ((b',e'),_) -> if e-b < e'-b' then best := Some (loc, sid) in Hashtbl.iter update state.table ; match !best with None -> raise Not_found | Some (loc,sid) -> loc, sid @@ -147,13 +167,13 @@ do incr next done; - (* Parameters.debug "Char %d has next %d" p !next;*) + (* Kernel.debug "Char %d has next %d" p !next;*) !next let iter state f = - (*Parameters.debug "Iterate on %d locations" (Hashtbl.length locs);*) + (*Kernel.debug "Iterate on %d locations" (Hashtbl.length locs);*) Hashtbl.iter f state.table - (*Parameters.debug "DONE: Iterate on %d locations" (Hashtbl.length locs);*) + (*Kernel.debug "DONE: Iterate on %d locations" (Hashtbl.length locs);*) let size state = Hashtbl.length state.table @@ -246,11 +266,11 @@ match self#current_kinstr with | Kglobal -> super#pLval fmt lv (* Do not highlight the lvals in initializers. *) - | Kstmt _ as ki -> + | Kstmt stmt as ki -> let alive = not (Value.is_computed ()) - || Db.Value.is_accessible self#current_kinstr - in + || Db.Value.is_reachable_stmt stmt + in if alive then Format.fprintf fmt "@{<%s>" (Tag.create (PLval (self#current_kf,ki,lv))); @@ -269,11 +289,11 @@ match self#current_kinstr with | Kglobal -> super#pTerm_lval fmt lv (* Do not highlight the lvals in initializers. *) - | Kstmt _ as ki -> + | Kstmt stmt as ki -> let alive = not (Value.is_computed ()) - || Db.Value.is_accessible self#current_kinstr - in + || Db.Value.is_reachable_stmt stmt + in if alive then Format.fprintf fmt "@{<%s>" (Tag.create (PTermLval (self#current_kf,ki,lv))); @@ -292,8 +312,11 @@ method pCode_annot fmt ca = match ca.annot_content with - AAssert _ | AInvariant _ | APragma _ | AVariant _ -> - let ip = + | APragma p when not (Logic_utils.is_property_pragma p) -> + (* Not currently localizable. Will be linked to the next stmt *) + super#pCode_annot fmt ca + | AAssert _ | AInvariant _ | APragma _ | AVariant _ -> + let ip = Property.ip_of_code_annot_single (Extlib.the self#current_kf) (Extlib.the self#current_stmt) @@ -328,8 +351,8 @@ let b = Extlib.the self#current_behavior in Format.fprintf fmt "@{<%s>%a@}" (Tag.create - (PIP - (Property.ip_of_requires + (PIP + (Property.ip_of_requires (Extlib.the self#current_kf) self#current_kinstr b p))) super#pRequires p; localize_predicate <- true @@ -337,9 +360,9 @@ method pBehavior fmt b = Format.fprintf fmt "@{<%s>%a@}" (Tag.create - (PIP - (Property.ip_of_behavior - (Extlib.the self#current_kf) self#current_kinstr b))) + (PIP + (Property.ip_of_behavior + (Extlib.the self#current_kf) self#current_kinstr b))) super#pBehavior b method pDecreases fmt t = @@ -347,8 +370,8 @@ Format.fprintf fmt "@{<%s>%a@}" (Tag.create (PIP - (Property.ip_of_decreases - (Extlib.the self#current_kf) self#current_kinstr t))) + (Property.ip_of_decreases + (Extlib.the self#current_kf) self#current_kinstr t))) super#pDecreases t; localize_predicate <- true @@ -357,7 +380,7 @@ Format.fprintf fmt "@{<%s>%a@}" (Tag.create (PIP - (Property.ip_of_terminates + (Property.ip_of_terminates (Extlib.the self#current_kf) self#current_kinstr t))) super#pTerminates t; localize_predicate <- true @@ -366,16 +389,16 @@ Format.fprintf fmt "@{<%s>%a@}" (Tag.create (PIP - (Property.ip_of_complete - (Extlib.the self#current_kf) self#current_kinstr t))) + (Property.ip_of_complete + (Extlib.the self#current_kf) self#current_kinstr t))) super#pComplete_behaviors t method pDisjoint_behaviors fmt t = Format.fprintf fmt "@{<%s>%a@}" (Tag.create (PIP - (Property.ip_of_disjoint - (Extlib.the self#current_kf) self#current_kinstr t))) + (Property.ip_of_disjoint + (Extlib.the self#current_kf) self#current_kinstr t))) super#pDisjoint_behaviors t method pAssumes fmt p = @@ -383,8 +406,8 @@ let b = Extlib.the self#current_behavior in Format.fprintf fmt "@{<%s>%a@}" (Tag.create - (PIP - (Property.ip_of_assumes + (PIP + (Property.ip_of_assumes (Extlib.the self#current_kf) self#current_kinstr b p))) super#pAssumes p; localize_predicate <- true @@ -394,14 +417,14 @@ let b = Extlib.the self#current_behavior in Format.fprintf fmt "@{<%s>%a@}" (Tag.create - (PIP - (Property.ip_of_ensures + (PIP + (Property.ip_of_ensures (Extlib.the self#current_kf) self#current_kinstr b pc))) super#pPost_cond pc; localize_predicate <- true method pAssigns s fmt a = - match + match Property.ip_of_assigns (Extlib.the self#current_kf) self#current_kinstr self#current_behavior_or_loop a with @@ -410,15 +433,22 @@ Format.fprintf fmt "@{<%s>%a@}" (Tag.create (PIP ip)) (super#pAssigns s) a - method pFrom s fmt from = - match - Property.ip_of_from (Extlib.the self#current_kf) self#current_kinstr - self#current_behavior_or_loop from - with - None -> super#pFrom s fmt from - | Some ip -> - Format.fprintf fmt "@{<%s>%a@}" - (Tag.create (PIP ip)) (super#pFrom s) from + method pFrom s fmt ((_, f) as from) = + match f with + | FromAny -> super#pFrom s fmt from + | From _ -> + let ip = + Property.ip_of_from (Extlib.the self#current_kf) self#current_kinstr + self#current_behavior_or_loop from + in + Format.fprintf fmt "@{<%s>%a@}" + (Tag.create (PIP ip)) (super#pFrom s) from + + method pAnnotation fmt a = + match Property.ip_of_global_annotation_single a with + | None -> super#pAnnotation fmt a + | Some ip -> + Format.fprintf fmt "@{<%s>%a@}" (Tag.create (PIP ip)) super#pAnnotation a (* Not used anymore: all identified predicates are selectable somewhere up - assert and loop invariants are PCodeAnnot @@ -473,7 +503,7 @@ let buffer_formatter state source = let starts = Stack.create () in let emit_open_tag s = - (* Parameters.debug "EMIT TAG";*) + (* Kernel.debug "EMIT TAG";*) Stack.push (source#end_iter#offset, Tag.get s) starts; @@ -499,14 +529,17 @@ Format.pp_set_margin gtk_fmt 79; gtk_fmt -let display_source globals source ~(host:Gtk_helper.host) ~highlighter ~selector = +let display_source globals + (source:GSourceView2.source_buffer) ~(host:Gtk_helper.host) + ~highlighter ~selector = let state = Locs.create () in host#protect ~cancelable:false (fun () -> Gtk_helper.refresh_gui (); source#set_text ""; - source#remove_all_tags ~start:source#start_iter ~stop:source#end_iter; + source#remove_source_marks + ~start:source#start_iter ~stop:source#end_iter (); let hiliter () = let event_tag = Gtk_helper.make_tag source ~name:"events" [] in Gtk_helper.cleanup_all_tags source; @@ -517,40 +550,40 @@ match v with | PStmt (_,ki) -> (try - let pb,pe = match ki with + let pb,pe = match ki with | {skind = Instr _ | Return _ | Goto _ | Break _ | Continue _} -> pb,pe - | {skind = If _ | Loop _ + | {skind = If _ | Loop _ | Switch _ } -> - (* These statements contain other statements. - We highlight only until the start of the first - included statement. *) + (* These statements contain other statements. + We highlight only until the start of the first + included statement. *) pb, (try Locs.find_next_start state pb - (fun p -> match p with - | PStmt _ -> true - | _ -> false (* Do not stop on expressions*)) + (fun p -> match p with + | PStmt _ -> true + | _ -> false (* Do not stop on expressions*)) with Not_found -> pb+1) - | {skind = Block _ | TryExcept _ | TryFinally _ + | {skind = Block _ | TryExcept _ | TryFinally _ | UnspecifiedSequence _} -> pb, (try Locs.find_next_start state pb (fun _ -> true) with Not_found -> pb+1) - in - highlighter v ~start:pb ~stop:pe + in + highlighter v ~start:pb ~stop:pe with Not_found -> ()) | PTermLval _ | PLval _ | PVDecl _ | PGlobal _ | PIP _ -> - highlighter v ~start:pb ~stop:pe); - (* Parameters.debug "Highlighting done (%d occurrences)" (Locs.size ());*) + highlighter v ~start:pb ~stop:pe); + (* Kernel.debug "Highlighting done (%d occurrences)" (Locs.size ());*) (* React to events on the text *) source#apply_tag ~start:source#start_iter ~stop:source#end_iter event_tag; - (* Parameters.debug "Event tag done";*) + (* Kernel.debug "Event tag done";*) in Locs.set_hilite state hiliter; - (* Parameters.debug "Display source starts";*) + (* Kernel.debug "Display source starts";*) let gtk_fmt = buffer_formatter state (source:>GText.buffer) in let tagPrinter = new tagPrinterClass in let display_global g = @@ -558,7 +591,7 @@ tagPrinter#pGlobal gtk_fmt g; Format.pp_print_flush gtk_fmt () in - (* Parameters.debug "Before Display globals %d" (List.length globals);*) + (* Kernel.debug "Before Display globals %d" (List.length globals);*) let counter = ref 0 in begin try List.iter @@ -572,46 +605,141 @@ gtk_fmt "@.<>@." !counter; - (*let ca = source#create_child_anchor source#end_iter in - source_view#add_child_at_anchor (GButton.button - ~text:"See 10 more globals" - ~callback:(fun _ -> call_cc next_10) - ()) ca *) + (*let ca = source#create_child_anchor source#end_iter in + source_view#add_child_at_anchor (GButton.button + ~text:"See 10 more globals" + ~callback:(fun _ -> call_cc next_10) + ()) ca *) end; - (* Parameters.debug "Displayed globals";*) + (* Kernel.debug "Displayed globals";*) source#place_cursor source#start_iter; (* Highlight the localizable *) hiliter (); let last_shown_area = - Gtk_helper.make_tag source ~name:"last_show_area" + Gtk_helper.make_tag source ~name:"last_shown_area" [`BACKGROUND "light green"] in let event_tag = Gtk_helper.make_tag source ~name:"events" [] in - ignore - (event_tag#connect#event ~callback: + let id = event_tag#connect#event ~callback: (fun ~origin:_ ev it -> if !Gtk_helper.gui_unlocked then if GdkEvent.get_type ev = `BUTTON_PRESS then begin let coords = GtkText.Iter.get_offset it in - try - let ((pb,pe), selected) = Locs.find state coords in - (* Highlight the pointed term *) + try + let ((pb,pe), selected) = Locs.find state coords in + (* Highlight the pointed term *) source#remove_tag - ~start:source#start_iter - ~stop:source#end_iter - last_shown_area; - apply_tag source last_shown_area pb pe; - let event_button = GdkEvent.Button.cast ev in - let button = GdkEvent.Button.button event_button in - host#protect ~cancelable:false - (fun () -> selector ~button selected); - with Not_found -> () (* no statement at this offset *) + ~start:source#start_iter + ~stop:source#end_iter + last_shown_area; + apply_tag source last_shown_area pb pe; + let event_button = GdkEvent.Button.cast ev in + let button = GdkEvent.Button.button event_button in + host#protect ~cancelable:false + (fun () -> selector ~button selected); + with Not_found -> () (* no statement at this offset *) end; - false))); + false) + in + Locs.add_finalizer state + (fun () -> GtkSignal.disconnect event_tag#as_tag id); + ); state +module LineToLocalizable = + Datatype.Hashtbl(Inthash)(Datatype.Int) + (struct let module_name = "Pretty_source.LineToLocalizable" end) +module FileToLines = + Datatype.Hashtbl(Hashtbl.Make(Datatype.String))(Datatype.String) + (struct let module_name = "Pretty_source.FilesToLine" end) + +module MappingLineLocalizable = struct + module LineToLocalizableAux = + LineToLocalizable.Make( Datatype.Pair(Location)(Localizable)) + + include State_builder.Hashtbl(FileToLines)(LineToLocalizableAux) + (struct + let size = 5 + let kind = `Internal + let dependencies = [Ast.self] + let name = "Pretty_source.line_to_localizable" + end) +end + +class pos_to_localizable = +object (self) + inherit Visitor.frama_c_inplace + + method add_range loc (localizable : localizable) = + if not (Location.equal loc Location.unknown) then ( + let p1, p2 = loc in + assert (p1.Lexing.pos_fname = p2.Lexing.pos_fname); + let file = p1.Lexing.pos_fname in + let hfile = + try MappingLineLocalizable.find file + with Not_found -> + let h = LineToLocalizable.create 17 in + MappingLineLocalizable.add file h; + h + in + for i = p1.Lexing.pos_lnum to p2.Lexing.pos_lnum do + LineToLocalizable.add hfile i (loc, localizable); + done + ); + + method vstmt_aux s = + Gui_parameters.debug ~level:3 "Locs for Stmt %d" s.sid; + self#add_range (Stmt.loc s) (PStmt (Extlib.the self#current_kf, s)); + Cil.DoChildren + + method vglob_aux g = + Gui_parameters.debug ~level:3 "Locs for global %a" Cil.d_global g; + (match g with + | GFun ({ svar = vi }, loc) -> + self#add_range loc (PVDecl (Some (Globals.Functions.get vi), vi)) + | GVar (vi, _, loc) -> + self#add_range loc (PVDecl (None, vi)) + | GVarDecl (_, vi, loc) -> + if Cil.isFunctionType vi.vtype then + self#add_range loc (PVDecl (Some (Globals.Functions.get vi), vi)) + else + self#add_range loc (PVDecl (None, vi)) + | _ -> self#add_range (Global.loc g) (PGlobal g) + ); + Cil.DoChildren +end + +let loc_to_localizable loc = + if not (MappingLineLocalizable.is_computed ()) then ( + Gui_parameters.debug "Computing inverse locs"; + let vis = new pos_to_localizable in + Visitor.visitFramacFile (vis :> Visitor.frama_c_visitor) (Ast.get ()); + MappingLineLocalizable.mark_as_computed (); + ); + try + (* Find the mapping from this file to locs-by-line *) + let hfile = MappingLineLocalizable.find loc.Lexing.pos_fname in + (* Find the localizable for this line *) + let all = LineToLocalizable.find_all hfile loc.Lexing.pos_lnum in + (* Try to a find the good localizable. When we have more than one matches + with the exact same location, we pick the last one in the list. This + will be the first statement that has been encountered, and this + criterion seems to work well with temporaries introduced by Cil *) + let last l = match List.rev l with [] -> None | (_, loc) :: _ -> Some loc in + (match all, List.filter (fun ((loc', _), _) -> loc = loc') all with + | [], _ -> None + | _, (_ :: _ as exact) -> last exact (* a pos exactly corresponds *) + | (l, _) :: __, [] -> (* No exact loc. We consider the innermost + statements, ie those at the top of the list *) + last (List.filter (fun (l', _) -> Location.equal l l') all) + ) + with Not_found -> + Gui_parameters.debug "No pretty-printed loc found"; + None + + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/gui/pretty_source.mli frama-c-20111001+nitrogen+dfsg/src/gui/pretty_source.mli --- frama-c-20110201+carbon+dfsg/src/gui/pretty_source.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/pretty_source.mli 2011-10-10 08:38:27.000000000 +0000 @@ -25,7 +25,6 @@ @plugin development guide *) open Cil_types -open Db_types (** The kind of object that can be selected in the source viewer. @plugin development guide *) @@ -36,12 +35,16 @@ | PVDecl of (kernel_function option * varinfo) | PGlobal of global (* all globals but variable declarations and function - definitions. *) + definitions. *) | PIP of Property.t module Localizable: Datatype.S with type t = localizable -module Locs: sig type state end +module Locs: sig + type state + (** To call when the source buffer is about to be discarded *) + val finalize: state -> unit +end val display_source : global list -> @@ -70,6 +73,13 @@ visible in the current [Locs.state]. This function is inefficient as it iterates on all the current [Locs.state]. *) + +val loc_to_localizable: Lexing.position -> localizable option + (** return the (hopefully) most precise localizable that contains the given + Lexing.position. + @since Nitrogen-20111001 *) + + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/gui/project_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/project_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/project_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/project_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -22,12 +22,15 @@ open Cilutil -let compare_prj p1 p2 = - let n = String.compare (Project.get_name p1) (Project.get_name p2) in - if n = 0 then Project.compare p1 p2 else n +let compare_prj (_p1, n1) (_p2, n2) = + String.compare n1 n2 let projects_list () = - let projects = Project.fold_on_projects (fun acc p -> p :: acc) [] in + let projects = + Project.fold_on_projects + (fun acc p -> (p, Project.get_unique_name p) :: acc) + [] + in List.sort compare_prj projects (* use the same order than the projects list. @@ -36,7 +39,7 @@ module PrjRadiosSet = Set.Make (struct - type t = Project.t * GMenu.radio_menu_item + type t = (Project.t * string) * GMenu.radio_menu_item let compare (p1, _) (p2, _) = compare_prj p1 p2 end) @@ -50,8 +53,8 @@ (fun filenames -> let project = Project.create "interactive" in let init () = - Parameters.Files.set filenames; - File.init_from_cmdline () + Kernel.Files.set filenames; + File.init_from_cmdline () in Project.on project init (); Project.set_current project) @@ -88,7 +91,7 @@ let dialog = GWindow.file_chooser_dialog ~action:`SAVE - ~title:("Save project %S" ^ Project.get_unique_name project) + ~title:("Save project " ^ Project.get_unique_name project) ~parent:main_ui#main_window () in (*dialog#set_do_overwrite_confirmation true ; only in later lablgtk2 *) @@ -98,9 +101,9 @@ (fun () -> match dialog#run () with | `SAVE -> - Extlib.may - (save_in main_ui (dialog :> GWindow.window_skel) project) - dialog#filename + Extlib.may + (save_in main_ui (dialog :> GWindow.window_skel) project) + dialog#filename | `DELETE_EVENT | `CANCEL -> ()); dialog#destroy () @@ -125,14 +128,14 @@ host_window#protect ~cancelable:true ~parent:(dialog:>GWindow.window_skel) (fun () -> match dialog#run () with | `OPEN -> - begin match dialog#filename with - | None -> () - | Some f -> - (try ignore (Project.load f) - with Project.IOError s | Failure s -> - host_window#error ~parent:(dialog:>GWindow.window_skel) - "Cannot load: %s" s) - end + begin match dialog#filename with + | None -> () + | Some f -> + (try ignore (Project.load f) + with Project.IOError s | Failure s -> + host_window#error ~parent:(dialog:>GWindow.window_skel) + "Cannot load: %s" s) + end | `DELETE_EVENT | `CANCEL -> ()); dialog#destroy () @@ -147,26 +150,26 @@ | None -> () | Some s -> try - ignore (Project.from_unique_name s); - main_ui#error "Project of name %S already exists" s + ignore (Project.from_unique_name s); + main_ui#error "Project of name %S already exists" s with Not_found -> - Project.set_name project s + Project.set_name project s let reset (menu: GMenu.menu) = - (* Do not reset all if there is no changes. *) + (* Do not reset all if there is no change. *) let pl = projects_list () in let same_projects = (* use that project_radios and pl are sorted in the same way *) try let rest = - PrjRadiosSet.fold - (fun (p1, _) acc -> - match acc with - | [] -> raise Exit - | p2 :: acc -> - if Project.compare p1 p2 = 0 then acc else raise Exit) - !project_radios - pl + PrjRadiosSet.fold + (fun (p1, _) acc -> + match acc with + | [] -> raise Exit + | p2 :: acc -> + if compare_prj p1 p2 = 0 then acc else raise Exit) + !project_radios + pl in rest = [] with Exit -> @@ -175,7 +178,7 @@ if same_projects then begin (* update the item status according to the current project anyway *) PrjRadiosSet.iter - (fun (p, r) -> r#set_active (Project.is_current p)) + (fun ((p, _), r) -> r#set_active (Project.is_current p)) !project_radios; false end else begin @@ -207,10 +210,11 @@ () in let callback () = if p_item#active then Project.set_current p in + let pname = Project.get_unique_name p in ignore (p_item#connect#toggled ~callback); - project_radios := PrjRadiosSet.add (p, p_item) !project_radios; + project_radios := PrjRadiosSet.add ((p, pname), p_item) !project_radios; let box = GPack.hbox ~packing:p_item#add () in - ignore (GMisc.label ~text:(Project.get_unique_name p) ~packing:box#pack ()); + ignore (GMisc.label ~text:pname ~packing:box#pack ()); let buttons_box = GPack.hbox ~packing:(box#pack ~from:`END) () in let tooltips = GData.tooltips () in let add_action stock text callback = @@ -227,17 +231,19 @@ add_action `DELETE "Delete project" (fun () -> delete_project p); add_action `SAVE "Save project" (fun () -> save_project window p); add_action `SAVE_AS "Save project as" (fun () -> save_project_as window p); - add_action `SPELL_CHECK "Rename project" (fun () -> rename_project window p); + add_action `SELECT_FONT "Rename project" (fun () -> rename_project window p); p_item let make_project_entries window menu = match projects_list () with | [] -> assert false - | pa :: tl -> + | (pa, _name) :: tl -> let mk = mk_project_entry window menu in let pa_item = mk pa in let group = pa_item#group in - List.iter (fun pa -> ignore (mk ~group pa)) tl + List.iter (fun (pa, _) -> ignore (mk ~group pa)) tl + +open Menu_manager (** Register this dialog in main window menu bar *) let () = @@ -246,26 +252,30 @@ let menu_manager = window#menu_manager () in let item, menu = menu_manager#add_menu "_Project" in let constant_items = - menu_manager#add_entries - menu - [ - Menu_manager.ToolMenubar(`NEW, "New project"), - (fun () -> new_project window); - Menu_manager.Menubar(Some `REVERT_TO_SAVED, "Load project"), - (fun () -> load_project window); - Menu_manager.ToolMenubar(`COPY, "Duplicate current project"), - (fun () -> duplicate_project window menu (Project.current ())); - Menu_manager.ToolMenubar(`DELETE, "Delete current project"), - (fun () -> delete_project (Project.current ())); - ] + menu_manager#add_entries + menu + [ + menubar ~icon:`NEW "New project" + (Unit_callback (fun () -> new_project window)); + menubar ~icon:`REVERT_TO_SAVED "Load project" + (Unit_callback (fun () -> load_project window)); + menubar ~icon:`COPY "Duplicate current project" + (Unit_callback + (fun () -> duplicate_project window menu(Project.current()))); + menubar ~icon:`DELETE "Delete current project" + (Unit_callback (fun () -> delete_project (Project.current ()))); + menubar ~icon:`SELECT_FONT "Rename current project" + (Unit_callback + (fun () -> rename_project window (Project.current ()))); + ] in let new_item = constant_items.(0) in new_item#add_accelerator `CONTROL 'n'; constant_items.(3)#add_accelerator `CONTROL 'd'; ignore (GMenu.separator_item ~packing:menu#append ()); let callback () = - let is_reset = reset menu in - if is_reset then make_project_entries window menu + let is_reset = reset menu in + if is_reset then make_project_entries window menu in ignore (item#connect#activate ~callback)) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/property_navigator.ml frama-c-20111001+nitrogen+dfsg/src/gui/property_navigator.ml --- frama-c-20110201+carbon+dfsg/src/gui/property_navigator.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/property_navigator.ml 2011-10-10 08:38:27.000000000 +0000 @@ -20,150 +20,97 @@ (* *) (**************************************************************************) -(* This is the panel to control the status of properties. *) -open Properties_status +(* This is the panel to control the status of properties. + [JS 2011/07/28] TODO: move it in the plug-in `report' *) + open Design open Cil_types -open Db_types +open Property_status type property = { - consolidated_tree : Consolidation_tree.t; module_name:string; function_name:string; kind:string; - status_states: State.t list; status_name:string; - status_bg:Gdk.color; - status_icon:string; + consolidated_status_name:string; + status_icon:Gtk_helper.Icon.kind; visible:bool; ip: Property.t; } -module M = struct - open Properties_status.Consolidation_tree - exception No_more_valid_status - exception Not_valid - let rec relies_on_valid_hyps_only t = - (* the consolidated status of [t] is valid iff at least one valid status of - [t] relies on valid hypothesis only. *) - let status = - (* put the valid status first *) - List.sort - (fun s1 s2 -> match s1.value, s2.value with - | (Checked { valid = True }, _), _ -> -1 - | _, (Checked { valid = True }, _) -> 1 - | _, _ -> 0) - t.status - in - let is_valid_status s = - (* return [true] iff each hypothesis of [s] is valid and relies itself - on valid hypothesis *) - try - List.iter - (fun h -> - match Properties_status.strongest h.property with - | Checked { valid = True }, _ -> - if not (relies_on_valid_hyps_only h) then raise Not_valid - | (Unknown | Checked { valid = False | Maybe }), _ -> - raise Not_valid) - s.hypothesis; - (* [TODO JS 2010/11/09] introduce cluster handling here *) - true - with Not_valid -> - false - in - (* The following assumes that valid status come first. *) - try - List.iter - (fun s -> match s.value with - | Checked { valid = True }, _ -> if is_valid_status s then raise Exit - | (Unknown | Checked { valid = False | Maybe }), _ -> - raise No_more_valid_status) - status; - false - with - | No_more_valid_status -> false - | Exit -> true -end -let relies_on_valid_hyps_only = M.relies_on_valid_hyps_only - -let rec make_property forest ~ip ~status_states ~status_name - ~module_name ~function_name = +let rec make_property ~ip ~status_name ~module_name ~function_name = try - let ctree = - List.find - (fun x -> Property.equal ip x.Consolidation_tree.property) - forest - in + let status = Consolidation.get ip in let function_name = match Property.get_kf ip with - | None -> (* Blob properties have lost this information*) function_name - | Some kf -> Pretty_utils.sfprintf "%a" Kernel_function.pretty_name kf - in - let status_states = List.map - (fun s -> snd s.Consolidation_tree.value) - ctree.Consolidation_tree.status + | None -> + (* [JS 2011/07/28] TODO: is it still possible? + some properties may have lost this information*) + function_name + | Some kf -> Pretty_utils.sfprintf "%a" Kernel_function.pretty kf in - let kind = State.get_name ctree.Consolidation_tree.state in - let status_bg= GDraw.color - (`NAME (if relies_on_valid_hyps_only ctree then "green" else "orange")) + let kind = + Pretty_utils.sfprintf "@[%a@]" Property.pretty ip in - let status_icon = - match Properties_status.strongest ip with - | Checked { valid = True }, _ -> "gtk-yes" - | Checked { valid = False }, _ -> "gtk-no" - | Checked { valid = Maybe }, _ -> "gtk-dialog-question" - | Unknown, _ -> "gtk-info" + let consolidated_status_name = + Pretty_utils.sfprintf "%a" Consolidation.pretty status in - { consolidated_tree = ctree; + let status_icon = Gtk_helper.Icon.Feedback (Feedback.get ip) in + { module_name = module_name; function_name = function_name; visible = true; - ip=ip; - kind=kind; - status_states = status_states; - status_name = status_name; - status_bg=status_bg; - status_icon=status_icon} + ip=ip; kind=kind; + status_name = status_name ; + consolidated_status_name = consolidated_status_name ; + status_icon = status_icon ; + } with Not_found -> - make_property [ Consolidation_tree.get ip ] - ~ip ~status_states ~status_name - ~module_name ~function_name - -let graph_window main_window title states ip = - if states <> [] then - let state_dependency_graph ~packing = - let f = - Extlib.temp_file_cleanup_at_exit - "framac_property_status_navigator_graph" "dot" - in - Properties_status.Consolidation_tree.dump - (Properties_status.Consolidation_tree.get_graph ip) - f; - snd (Dgraph.DGraphContainer.Dot.from_dot_with_commands ~packing f) - in - let height = int_of_float (float main_window#default_height *. 3. /. 4.) in - let width = int_of_float (float main_window#default_width *. 3. /. 4.) in - let window = - GWindow.window - ~width ~height ~title ~allow_shrink:true ~allow_grow:true - ~position:`CENTER () - in - let view = state_dependency_graph ~packing:window#add in - window#show (); - view#adapt_zoom () + make_property ~ip ~status_name ~module_name ~function_name + +let graph_window main_window title ip = + let state_dependency_graph ~packing = + let f = + try + Extlib.temp_file_cleanup_at_exit + "framac_property_status_navigator_graph" "dot" + with Extlib.Temp_file_error s -> + Gui_parameters.abort "cannot create temporary file: %s" s + in + Property_status.Consolidation_graph.dump + (Property_status.Consolidation_graph.get ip) + f; + snd (Dgraph.DGraphContainer.Dot.from_dot_with_commands ~packing f) + in + let height = int_of_float (float main_window#default_height *. 3. /. 4.) in + let width = int_of_float (float main_window#default_width *. 3. /. 4.) in + let window = + GWindow.window + ~width ~height ~title ~allow_shrink:true ~allow_grow:true + ~position:`CENTER () + in + let view = state_dependency_graph ~packing:window#add in + window#show (); + view#adapt_zoom () + +module Refreshers: sig + module OnlyCurrent: State_builder.Ref with type data = bool -module Refreshers: -sig module Ensures: State_builder.Ref with type data = bool - module RTE: State_builder.Ref with type data = bool module Preconditions: State_builder.Ref with type data = bool module Behaviors: State_builder.Ref with type data = bool module Assigns: State_builder.Ref with type data = bool + module From: State_builder.Ref with type data = bool module Assert: State_builder.Ref with type data = bool module Invariant: State_builder.Ref with type data = bool module Variant: State_builder.Ref with type data = bool + module Terminates: State_builder.Ref with type data = bool module StmtSpec: State_builder.Ref with type data = bool - module OnlyCurrent: State_builder.Ref with type data = bool + module Unreachable: State_builder.Ref with type data = bool + module Other: State_builder.Ref with type data = bool + module Axiomatic: State_builder.Ref with type data = bool +(*module Pragma: State_builder.Ref with type data = bool*) + module RteNotGenerated: State_builder.Ref with type data = bool + module RteGenerated: State_builder.Ref with type data = bool val pack: GPack.box -> unit val apply: unit -> unit @@ -174,60 +121,131 @@ let refreshers = ref [] let add_refresher f = refreshers := f::!refreshers - module Add(X: sig val name: string end) = struct + module Add (X: sig val name: string val hint: string end) = + struct + open Gtk_helper + let key_name = + Configuration.load (); + let s = String.copy X.name in + for i = 0 to String.length s - 1 do + let c = s.[i] in + if c < 'A' || c > 'z' || (c > 'Z' && c < 'a') then + s.[i] <- '_' + done; + "property_panel." ^ s + include State_builder.Ref (Datatype.Bool) (struct - let name = "show " ^ X.name - let dependencies = [] - let kind = `Internal - let default () = true + let name = "show " ^ X.name + let dependencies = [] + let kind = `Internal + let default () = + let v = Configuration.find_bool ~default:true key_name in + v end) - let add hb = add_refresher (Gtk_helper.on_bool hb X.name get set) + let set v = Configuration.set key_name (Configuration.ConfBool v); + set v + let add hb = add_refresher + (Gtk_helper.on_bool ~tooltip:X.hint hb X.name get set) end let apply () = List.iter (fun f -> f ()) !refreshers - module Preconditions = Add(struct let name = "preconditions" end) - module Ensures = Add(struct let name = "postconditions" end) - module RTE = Add(struct let name = "RTE" end) - module Behaviors = Add(struct let name = "behaviors" end) - module Assigns = Add(struct let name = "assigns" end) - module Assert = Add(struct let name = "assert" end) - module Invariant = Add(struct let name = "invariant" end) - module Variant = Add(struct let name = "variant" end) - module StmtSpec = Add(struct let name = "stmt contract" end) - module OnlyCurrent = Add(struct let name = "only selected" end) + module OnlyCurrent = Add( + struct let name = "Current function" + let hint = "Restrict properties to those of current function" end) + module Preconditions = Add( + struct let name = "Preconditions" + let hint = "Show functions preconditions" end) + module Ensures = Add( + struct let name = "Postconditions" + let hint = "Show functions postconditions" end) + module Behaviors = Add( + struct let name = "Behaviors" + let hint = "Show functions behaviors" end) + module Assigns = Add( + struct let name = "Assigns" + let hint = "Show functions assigns" end) + module From = Add( + struct let name = "From" + let hint = "Show functional dependencies in functions assigns" end) + module Assert = Add( + struct let name = "Assert" + let hint = "Show assertions" end) + module Invariant = Add( + struct let name = "Invariant" + let hint = "Show loop invariants" end) + module Variant = Add( + struct let name = "Variant" + let hint = "Show loop termination argument" end) + module Terminates = Add( + struct let name = "Terminates" + let hint = "Show functions termination clauses" end) + module StmtSpec = Add( + struct let name = "Stmt contract" + let hint = "Show statements contracts" end) + module Axiomatic = Add( + struct let name = "Axiomatic" + let hint = "Show global axiomatics" end) + module Unreachable = Add( + struct let name = "Unreachable" + let hint = "Show 'unreachable' hypotheses" end) + module Other = Add( + struct let name = "Other" + let hint = "Show other properties" end) + (*module Pragma = Add(struct let name = "pragma" end) *) + module RteNotGenerated = Add( + struct let name = "Non generated" + let hint = "Show RTEs assertions that remain to generate" end) + module RteGenerated = Add( + struct let name = "Generated" + let hint = "Show RTEs assertions that have been generated" end) let pack hb = + OnlyCurrent.add hb; Preconditions.add hb; Ensures.add hb; - RTE.add hb; Behaviors.add hb; Assigns.add hb; + From.add hb; Assert.add hb; Invariant.add hb; Variant.add hb; + Terminates.add hb; + Unreachable.add hb; StmtSpec.add hb; - OnlyCurrent.add hb + Axiomatic.add hb; + Other.add hb; + (*Pragma.add hb;*) + RteNotGenerated.add hb; + RteGenerated.add hb; end open Refreshers let make_panel (main_ui:main_window_extension_points) = - let container = GPack.vbox () + let container = GPack.hbox () in + + let sc_buttons = + GBin.scrolled_window ~vpolicy:`AUTOMATIC ~hpolicy:`NEVER () in - let module L = struct - type t = property - let column_list = new GTree.column_list - let custom_value (_:Gobject.g_type) _t ~column:_ : Gobject.basic = - assert false - end + let vb = GPack.vbox () in + let refresh_button = GButton.button ~label:"Refresh" ~packing:vb#pack () in + Refreshers.pack vb; + sc_buttons#add_with_viewport vb#coerce; + container#pack sc_buttons#coerce; + + let module MODEL = + Gtk_helper.MAKE_CUSTOM_LIST(struct type t = property end) in - let module MODEL = Gtk_helper.MAKE_CUSTOM_LIST(L) in let model = MODEL.custom_list () in let append m = if m.visible then model#insert m in let clear () = model#clear () in + (* TOOD: this avoids some problems when changing projects, where + the property navigator displays outdated information. A better solution + would be to projectify what is being displayed *) + Design.register_reset_extension (fun _ -> clear ()); let sc = GBin.scrolled_window ~vpolicy:`AUTOMATIC @@ -243,162 +261,129 @@ ignore (view#connect#row_activated ~callback:(fun path _col -> - match model#custom_get_iter path with - | Some {MODEL.finfo={status_states=l; ip = ip;}} -> - graph_window main_ui#main_window "Dependencies" l ip - | None -> ())); + match model#custom_get_iter path with + | Some { MODEL.finfo = { ip = ip } } -> + graph_window main_ui#main_window "Dependencies" ip + | None -> ())); view#selection#set_select_function (fun path currently_selected -> - if not currently_selected then - begin match model#custom_get_iter path with - | Some {MODEL.finfo={ip = ip;}} -> - (match Property.get_kf ip with - | Some kf -> - main_ui#file_tree#select_global (Kernel_function.get_vi kf) - (*TODO: select the Property.get_kinstr *) - | None -> ()) - | None -> () - end; - true); + if not currently_selected then + begin match model#custom_get_iter path with + | Some {MODEL.finfo={ip = ip;}} -> + ignore (main_ui#scroll (Pretty_source.PIP ip)) + | None -> () + end; + true); let top = `YALIGN 0.0 in - (* Module name column viewer *) - let module_name_renderer = GTree.cell_renderer_text [top] in - let m_module_name_renderer renderer (lmodel:GTree.model) iter = - let (path:Gtk.tree_path) = lmodel#get_path iter in - match model#custom_get_iter path with - | Some {MODEL.finfo={module_name=m}} -> - renderer#set_properties [`TEXT m] - | None -> () + let make_view_column renderer properties ~title = + let cview = MODEL.make_view_column model renderer properties ~title in + cview#set_resizable true; + ignore (view#append_column cview) in - let module_cview = GTree.view_column - ~title:"Module" ~renderer:(module_name_renderer,[]) () - in - module_cview#set_cell_data_func - module_name_renderer (m_module_name_renderer module_name_renderer); - module_cview#set_resizable true; - ignore (view#append_column module_cview); + + (* Module name column viewer *) + make_view_column (GTree.cell_renderer_text [top]) + (function{module_name=m} -> [`TEXT m]) + ~title:"Module"; (* Function name column viewer *) - let function_name_renderer = GTree.cell_renderer_text [top] in - let m_function_name_renderer renderer (lmodel:GTree.model) iter = - let (path:Gtk.tree_path) = lmodel#get_path iter in - match model#custom_get_iter path with - | Some {MODEL.finfo={function_name=m}} -> - renderer#set_properties [`TEXT m] - | None -> () - in - let function_cview = GTree.view_column - ~title:"Function" ~renderer:(function_name_renderer,[]) () - in - function_cview#set_cell_data_func - function_name_renderer (m_function_name_renderer function_name_renderer); - function_cview#set_resizable true; - ignore (view#append_column function_cview); + make_view_column (GTree.cell_renderer_text [top]) + (function{function_name=m} -> [`TEXT m]) + ~title:"Function"; (* Kind name column viewer *) - let kind_name_renderer = GTree.cell_renderer_text [top] in - let m_kind_name_renderer renderer (lmodel:GTree.model) iter = - let (path:Gtk.tree_path) = lmodel#get_path iter in - match model#custom_get_iter path with - | Some {MODEL.finfo={kind=k}} -> - renderer#set_properties [ `TEXT k ] - | None -> () - in - let kind_cview = GTree.view_column - ~title:"Kind" ~renderer:(kind_name_renderer,[]) () - in - kind_cview#set_cell_data_func - kind_name_renderer (m_kind_name_renderer kind_name_renderer); - kind_cview#set_resizable true; - ignore (view#append_column kind_cview); + make_view_column (GTree.cell_renderer_text [top]) + (function{kind=k} -> [`TEXT k]) + ~title:"Kind"; (* Status colored column viewer *) - let status_color_renderer = GTree.cell_renderer_pixbuf [top] in - let m_status_color_renderer renderer (lmodel:GTree.model) iter = - let (path:Gtk.tree_path) = lmodel#get_path iter in - match model#custom_get_iter path with - | Some {MODEL.finfo={status_bg=color;status_icon=status_icon}} -> - renderer#set_properties [`CELL_BACKGROUND_GDK color; - `STOCK_ID status_icon] - | None -> () - in - let status_color_cview = GTree.view_column - ~title:"Status" ~renderer:(status_color_renderer,[]) () - in - status_color_cview#set_cell_data_func - status_color_renderer (m_status_color_renderer status_color_renderer); - status_color_cview#set_resizable true; - ignore (view#append_column status_color_cview); - - (* Status name column viewer *) - let status_name_renderer = GTree.cell_renderer_text [top] in - let m_status_name_renderer renderer (lmodel:GTree.model) iter = - let (path:Gtk.tree_path) = lmodel#get_path iter in - match model#custom_get_iter path with - | Some {MODEL.finfo={status_name=m}} -> - renderer#set_properties [`TEXT m] - | None -> () - in - let status_cview = GTree.view_column - ~title:"Textual Status" ~renderer:(status_name_renderer,[]) () - in - status_cview#set_cell_data_func - status_name_renderer (m_status_name_renderer status_name_renderer); - status_cview#set_resizable true; - ignore (view#append_column status_cview); - view#set_model (Some model#coerce); + make_view_column (GTree.cell_renderer_pixbuf [top]) + (function {status_icon=status_icon} -> + [`PIXBUF (Gtk_helper.Icon.get status_icon)]) + ~title:"Status"; + + (* (Local) status name column viewer *) + make_view_column (GTree.cell_renderer_text [top]) + (function{status_name=k}-> [`TEXT k]) + ~title:"Local Status"; + + (* Consolidated status name column viewer *) + make_view_column (GTree.cell_renderer_text [top]) + (function{consolidated_status_name=k}-> [`TEXT k]) + ~title:"Consolidated Status"; - let hb = GPack.hbox ~packing:container#pack () in - Refreshers.pack hb; + view#set_model (Some model#coerce); - (* [VP 2011-01-29] seems like some ip do not have an associated option to - let them be visible. *) - let visible ip = - match ip with - Property.IPBlob _ -> false - | Property.IPPredicate(Property.PKRequires _,_,Kglobal,_) -> + (* [JS 2011-08-29] Be careful: that it is incorrect to mask some properties + when they are the only not-valid ones. In such a case, all is green in the + property panel implying that the verification task successfully ended, + while that is not true actually. + [BY 2011-09-31] JS: I'm not sure what you mean. Do you want a check + that supersedes all the other settings, and displays everything which + is not green? + *) + let visible ip = match ip with + | Property.IPOther _ -> Other.get () + | Property.IPUnreachable _ -> Unreachable.get () + | Property.IPBehavior (_,Kglobal,_) -> Behaviors.get () + | Property.IPBehavior (_,Kstmt _,_) -> Behaviors.get () && StmtSpec.get () + | Property.IPPredicate(Property.PKRequires _,_,Kglobal,_) -> Preconditions.get () - | Property.IPPredicate(Property.PKRequires _,_,Kstmt _,_) -> + | Property.IPPredicate(Property.PKRequires _,_,Kstmt _,_) -> Preconditions.get () && StmtSpec.get () - | Property.IPPredicate(Property.PKAssumes _,_,_,_) -> false - | Property.IPPredicate(Property.PKEnsures _,_,Kglobal,_) -> Ensures.get () - | Property.IPPredicate(Property.PKEnsures _,_,Kstmt _,_) -> + | Property.IPPredicate(Property.PKAssumes _,_,_,_) -> false + | Property.IPPredicate(Property.PKEnsures _,_,Kglobal,_) -> Ensures.get () + | Property.IPPredicate(Property.PKEnsures _,_,Kstmt _,_) -> Ensures.get() && StmtSpec.get() - | Property.IPPredicate(Property.PKTerminates,_,_,_) -> false - | Property.IPAxiom _ -> false - | Property.IPComplete _ -> false - | Property.IPDisjoint _ -> false - | Property.IPCodeAnnot(_,_,{annot_content = AAssert _}) -> Assert.get () - | Property.IPCodeAnnot(_,_,{annot_content = AInvariant _}) -> + | Property.IPPredicate(Property.PKTerminates,_,_,_) -> Terminates.get () + | Property.IPAxiom _ -> false + | Property.IPAxiomatic _ -> Axiomatic.get () && not (OnlyCurrent.get ()) + | Property.IPLemma _ -> Axiomatic.get () + | Property.IPComplete _ -> Behaviors.get () + | Property.IPDisjoint _ -> Behaviors.get () + | Property.IPCodeAnnot(_,_,{annot_content = AAssert _}) -> Assert.get () + | Property.IPCodeAnnot(_,_,{annot_content = AInvariant _}) -> Invariant.get () - | Property.IPCodeAnnot(_,_,{annot_content = APragma _}) -> false - | Property.IPCodeAnnot _ -> assert false - | Property.IPBehavior (_,Kglobal,_) -> Behaviors.get () - | Property.IPBehavior (_,Kstmt _,_) -> Behaviors.get () && StmtSpec.get () - | Property.IPAssigns (_,Kglobal,_,_) -> Assigns.get () - | Property.IPAssigns (_,Kstmt _,Property.Id_code_annot _,_) -> + | Property.IPCodeAnnot(_,_,{annot_content = APragma p}) -> + Logic_utils.is_property_pragma p (* currently always false. *) + | Property.IPCodeAnnot(_, _, _) -> assert false + | Property.IPAssigns (_,Kglobal,_,_) -> Assigns.get () + | Property.IPAssigns (_,Kstmt _,Property.Id_code_annot _,_) -> Assigns.get () - | Property.IPAssigns (_,Kstmt _,Property.Id_behavior _,_) -> + | Property.IPAssigns (_,Kstmt _,Property.Id_behavior _,_) -> Assigns.get() && StmtSpec.get() - | Property.IPFrom _ -> false - | Property.IPDecrease _ -> Variant.get () + | Property.IPFrom _ -> From.get () + | Property.IPDecrease _ -> Variant.get () in let fill_model () = - let status_string status (state: State.t option)= - match status with - | Unknown -> Pretty_utils.sfprintf "%a" Cil.d_annotation_status status - | Checked _ -> - assert (not (state = None)); - Pretty_utils.sfprintf "%a" Cil.d_annotation_status status - in - let get_states = function - | None -> [] - | Some s -> [ s ] - in - let forest= Properties_status.Consolidation_tree.get_all () in + let status_string s = Pretty_utils.sfprintf "%a" Property_status.pretty s in let files = Globals.FileIndex.get_files () in + (* add global annotations *) + let annot_by_files = + List.map + (fun f -> + Globals.FileIndex.get_global_annotations f, Filename.basename f) + files + in + let add_ip module_name function_name ip = + if visible ip then + let status = Property_status.get ip in + append + (make_property + ~module_name + ~function_name + ~status_name:(status_string status) + ~ip) + in + List.iter + (fun (l, f) -> + List.iter + (fun a -> + List.iter (add_ip f "") (Property.ip_of_global_annotation a)) + l) + annot_by_files; (* We only display the name of the file *) let files = List.map (fun file->(Globals.FileIndex.get_functions file,Filename.basename file)) @@ -406,84 +391,78 @@ in List.iter (fun (kfs, file_base) -> - let add_ip ip = - let status, state = Properties_status.strongest ip in + let add_ip ip = let function_name = (Extlib.may_map - (fun f -> Kernel_function.get_name f ^ ": ") ~dft:"" - (Property.get_kf ip)) - ^ (Extlib.may_map + (fun f -> Kernel_function.get_name f ^ ": ") ~dft:"" + (Property.get_kf ip)) + ^ (Extlib.may_map (fun b -> "behavior " ^ b.b_name ^ ": ") ~dft:"" (Property.get_behavior ip)) in - if visible ip then - append - (make_property - forest - ~module_name:file_base - ~function_name - ~status_states:(get_states state) - ~status_name:(status_string status state) - ~ip) + add_ip file_base function_name ip in - List.iter - (fun kf -> - if Kernel_function.is_definition kf - && (not (OnlyCurrent.get ()) || - let kfvi = Kernel_function.get_vi kf in - List.exists - (fun g -> match g with - | GFun (f,_) -> Cil_datatype.Varinfo.equal f.svar kfvi - | _ -> false) - main_ui#file_tree#selected_globals) - then begin - let rte_get_all_status = !Db.RteGen.get_all_status in - let kf_name = Kernel_function.get_name kf in - List.iter - (fun (rte_status, status_states, rte_status_get) -> - if RTE.get () then - append - (make_property forest - ~module_name:file_base - ~function_name:kf_name - ~status_states:[ status_states kf ] - ~status_name:(if rte_status_get kf then "Generated" - else "not Generated") - ~ip:(Property.ip_blob rte_status))) - (rte_get_all_status ()); - let add_spec spec code_annotations = - let ip_spec = Property.ip_of_spec kf Kglobal spec in - let ip_annot = - List.fold_right - (fun (stmt,loc_ca) acc -> - let ca = - match loc_ca with - | Before(User ca|AI(_,ca)) - | After(User ca | AI(_,ca)) -> ca - in - Property.ip_of_code_annot kf stmt ca @ acc) - code_annotations [] - in - List.iter add_ip ip_spec; - List.iter add_ip ip_annot; + List.iter + (fun kf -> + if (not (OnlyCurrent.get ()) || + let kfvi = Kernel_function.get_vi kf in + List.exists + (fun g -> match g with + | GFun (f,_) -> Cil_datatype.Varinfo.equal f.svar kfvi + | _ -> false) + main_ui#file_tree#selected_globals) + then begin + let rte_get_all_status = !Db.RteGen.get_all_status in + let kf_name = Kernel_function.get_name kf in + List.iter + (fun (rte_status, _, rte_status_get,_) -> + let st = rte_status_get kf in + match st, RteGenerated.get (), RteNotGenerated.get () + with + | true, true, _ + | false, _, true -> + append + (make_property + ~module_name:file_base + ~function_name:kf_name + ~status_name:(if st then "Generated" + else "not Generated") + ~ip:(Property.ip_other + (State.get_name rte_status) + None Kglobal)) + | true, false, _ + | false, _, false -> () + ) + (rte_get_all_status ()); + let add_spec spec code_annotations = + let ip_spec = Property.ip_of_spec kf Kglobal spec in + let ip_annot = + List.fold_right + (fun (stmt,loc_ca) acc -> + let ca = match loc_ca with | User ca|AI(_,ca) -> ca in + Property.ip_of_code_annot kf stmt ca @ acc) + code_annotations [] in - add_spec - (Kernel_function.get_spec kf) - (Kernel_function.code_annotations kf) - end) - kfs) + List.iter add_ip ip_spec; + List.iter add_ip ip_annot; + in + add_spec + (Kernel_function.get_spec kf) + (Kernel_function.code_annotations kf) + end) + kfs) (List.sort (fun (_, f1) (_, f2) -> String.compare f1 f2) files) in - let refresh_button = GButton.button ~label:"Refresh" ~packing:hb#add () in ignore (let callback _ = - main_ui#protect ~cancelable:false - (fun () -> - clear (); - Refreshers.apply (); - fill_model ()) - in - refresh_button#connect#released ~callback); + main_ui#protect ~cancelable:false + (fun () -> + clear (); + Refreshers.apply (); + fill_model ()) + in + refresh_button#connect#released ~callback); + (* To fill at startup: let (_:GtkSignal.id) = view#misc#connect#after#realize fill_model in *) let (_:int) = main_ui#lower_notebook#append_page @@ -492,65 +471,23 @@ in register_reset_extension (fun _ -> Refreshers.apply ()) - (* Graphical markers in text showing the status of properties. Aka. "bullets" in left margin *) -let highlighter (main_ui:Design.main_window_extension_points) = - let _pixbuf_from_stock stock = - main_ui#source_viewer#misc#render_icon ~size:`MENU stock - in - let make_marker name pixbuf = - main_ui#source_viewer#set_mark_category_pixbuf ~category:name (Some pixbuf) - in - make_marker "true" (Gtk_helper.Icon.get Gtk_helper.Icon.Check); - (* "true" used to be (pixbuf_from_stock `YES) *) - make_marker "implied" (Gtk_helper.Icon.get - Gtk_helper.Icon.Relies_on_valid_hyp); - make_marker "false" (Gtk_helper.Icon.get Gtk_helper.Icon.Failed); - make_marker "maybe" (Gtk_helper.Icon.get Gtk_helper.Icon.Maybe); - make_marker "nottried" (Gtk_helper.Icon.get Gtk_helper.Icon.Attach); - main_ui#source_viewer#set_show_line_marks true; - let mark_with_status (buffer:GSourceView2.source_buffer) start ip = - let status = Properties_status.strongest ip in - match fst status with - | Unknown -> - ignore(buffer#create_source_mark ~category:"nottried" - (buffer#get_iter_at_char start)) - | Checked {valid = v} -> - ignore(buffer#create_source_mark - ~category: (match v with - | True -> if - relies_on_valid_hyps_only (Consolidation_tree.get ip) - then - "true" - else - "implied" - | False -> "false" - | Maybe -> "maybe") - (buffer#get_iter_at_char start)) - in - fun (buffer:GSourceView2.source_buffer) localizable ~start ~stop:_ -> - buffer#remove_source_marks - (buffer#get_iter_at_char start) - (buffer#get_iter_at_char start) - () ; +let highlighter (buffer:GSourceView2.source_buffer) localizable ~start ~stop = match localizable with | Pretty_source.PIP (Property.IPPredicate (Property.PKAssumes _,_,_,_)) -> - (* Assumes clause do not get a bullet*) - () - | Pretty_source.PIP ip -> - (*Format.printf "MARK again:%d (STRONGEST='%a' ALL='%a')@." start - Cil.d_annotation_status - (fst (Properties_status.strongest ip)) - Properties_status.pretty_all ip;*) - mark_with_status buffer start ip + (* Assumes clause do not get a bullet: there is nothing + to prove about them.*) + () + | Pretty_source.PIP ppt -> + Design.Feedback.mark buffer ~start ~stop (Property_status.Feedback.get ppt) | Pretty_source.PGlobal _| Pretty_source.PVDecl _ | Pretty_source.PTermLval _| Pretty_source.PLval _ | Pretty_source.PStmt _ -> () let extend (main_ui:main_window_extension_points) = make_panel main_ui; - main_ui#register_source_highlighter (highlighter main_ui) + main_ui#register_source_highlighter highlighter let () = Design.register_extension extend diff -Nru frama-c-20110201+carbon+dfsg/src/gui/source_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/source_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/source_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/source_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -20,188 +20,38 @@ (* *) (**************************************************************************) -(** This file contains the source viewer muli-tabs widget window *) - open Pretty_source -type source_tab = { - tab_name : string; - select_line : int -> unit; +type tab = { + tab_name : string ; + tab_file : string ; + tab_page : int ; + tab_select : line:int -> unit ; } +type t = { + notebook : GPack.notebook; + file_index : (string,tab) Hashtbl.t; + name_index : (string,tab) Hashtbl.t; + mutable pages : int ; +} -module Q = Qstack.Make(struct - type t = GSourceView2.source_view - let equal x y = x == y - end) - - -type t = {notebook : GPack.notebook; - tbl : (string,source_tab) Hashtbl.t; - views : Q.t; } - -let get_notebook t = t.notebook - - -let set_current_view t n = - if (n>=0) && (n < (Q.length t.views)) then t.notebook#goto_page n - -let prepend_source_tab w titre = - Gui_parameters.debug "prepend_source_tab"; - (* insert one extra tab in the source window w, with label *) - let label = GMisc.label ~text:titre () in - let sw = GBin.scrolled_window - ~vpolicy:`AUTOMATIC - ~hpolicy:`AUTOMATIC - ~packing:(fun arg -> - ignore - (w.notebook#prepend_page ~tab_label:label#coerce arg)) - () +let make ?tab_pos ?packing () = + let notebook = GPack.notebook + ~scrollable:true ~show_tabs:true ?tab_pos ?packing () in - let window = (Source_viewer.make ~packing:sw#add) in - (* Remove default pango menu for textviews *) - ignore (window#event#connect#button_press ~callback: - (fun ev -> GdkEvent.Button.button ev = 3)); - Q.add window w.views; - w.notebook#goto_page 0; - window - -let get_nth_page (t:t) n = - let nb = t.notebook in - nb#get_nth_page n (* Deprecated *) - -let current_page (t:t) = - let nb = t.notebook in - nb#current_page - -let last_page t = Q.length t.views - 1 - -(* ABP and methods to manage this memory *) -let get_current_view (t:t) = - let nb = t.notebook in - let cp = nb#current_page in - Gui_parameters.debug "get_current_view: %d" cp; - Q.nth cp t.views - -let get_current_index (t:t) = - let cp = t.notebook#current_page in - Gui_parameters.debug "get_current_index: %d" cp; - cp - -let delete_view (t:t) cp = - let nb = t.notebook in - Gui_parameters.debug "delete_current_view - cur is page %d" cp; - Q.remove (Q.nth cp t.views) t.views; - nb#remove_page cp; - let last = pred (Q.length t.views) in - Gui_parameters.debug "Going to page (delete_current_view) %d" last; - nb#goto_page last - -(* delete within w the tab that contains window win *) -let delete_view_and_loc w win () = - Gui_parameters.debug "delete_view_and_loc "; - let idx = Q.idx win w.views in - delete_view w idx - -let delete_current_view t = delete_view t t.notebook#current_page - -let delete_all_views (t:t) = - Q.iter (fun _ -> t.notebook#remove_page 0) t.views; - Q.clear t.views - -let append_view (t:t) (v:GSourceView2.source_view) = - let nb = t.notebook in - let next = Q.length t.views in - let text = Printf.sprintf "Page %d" next in - let label = GMisc.label ~text:text () in - let sw = GBin.scrolled_window - ~vpolicy:`AUTOMATIC - ~hpolicy:`AUTOMATIC - ~packing:(fun arg -> - ignore - (nb#append_page ~tab_label:label#coerce arg)) () in - sw#add (v:>GObj.widget); - nb#goto_page next; - Gui_parameters.debug "Going to page (append_view) %d" next; - Q.add_at_end v t.views; - Gui_parameters.debug "append_view - nb pages is %d" (Q.length t.views); - Gui_parameters.debug "append_view - current nb page is %d" nb#current_page - -let get_nth_view t (n:int) = Q.nth n t.views - -let enable_popup (t:t) (b:bool) = - let nb = t.notebook in - nb#set_enable_popup b - -let set_scrollable (t:t) (b:bool) = - let nb = t.notebook in - nb#set_scrollable b - -(* get length of the current source_views list *) -let length t = Q.length t.views - - -let append_source_tab w titre = - Gui_parameters.debug "append_source_tab"; - (* insert one extra tab in the source window w, with some title *) - let composed_label = GPack.hbox () in - - let _ = GMisc.label ~text:(titre) ~packing:composed_label#add () in - - let cbutton = GButton.button ~packing:composed_label#add () in - - cbutton#set_use_stock false ; - cbutton#set_label "X"; - cbutton#misc#set_size_request ~width:20 ~height:20 (); - - let sw = GBin.scrolled_window - ~vpolicy:`AUTOMATIC - ~hpolicy:`AUTOMATIC - ~packing:(fun arg -> - ignore - (w.notebook#append_page ~tab_label:composed_label#coerce arg)) - (* - ~packing:(fun arg -> - ignore - (w.notebook#append_page ~tab_label:label#coerce arg)) *) - () - in - let window = (Source_viewer.make ~packing:sw#add) in - ignore - (cbutton#connect#clicked ~callback:(fun () -> delete_view_and_loc w window ())); - (* Remove default pango menu for textviews *) - ignore (window#event#connect#button_press ~callback: - (fun ev -> GdkEvent.Button.button ev = 3)); - Q.add_at_end window w.views; - let last = pred (Q.length w.views) in - w.notebook#goto_page last; (* THIS CALLS THE SWITCH_PAGE CALLBACK IMMEDIATELY! *) - window - -(* ABP end of additions *) - -let make_unpacked () = - { notebook = - (let nb = GPack.notebook ~scrollable:true ~show_tabs:true () - in - nb#set_enable_popup true;nb); - tbl = Hashtbl.create 7; - views = Q.create () + notebook#set_enable_popup true ; + { + notebook = notebook ; + file_index = Hashtbl.create 7; + name_index = Hashtbl.create 7; + pages = 0 ; } -let make ~packing = - { notebook = - (let nb = - GPack.notebook ~scrollable:true ~show_tabs:true ~packing () - in - nb#set_enable_popup true;nb); - tbl = Hashtbl.create 7; - views = Q.create ()} - (* Try to convert a source file either as UTF-8 or as locale. *) let try_convert s = try - if Glib.Utf8.validate s then s else - Glib.Convert.locale_to_utf8 s + if Glib.Utf8.validate s then s else Glib.Convert.locale_to_utf8 s with Glib.Convert.Error _ -> try Glib.Convert.convert_with_fallback @@ -217,7 +67,6 @@ Buffer.add_substring b buf 0 !len done - let with_file name ~f = try let ic = open_in_gen [Open_rdonly] 0o644 name in @@ -225,45 +74,52 @@ close_in ic (*; !flash_info ("Error: "^Printexc.to_string exn)*) with _exn -> () -let load_file ?title w ~filename ~line = - Gui_parameters.debug "Opening file %S line %d" filename line; - let filename_info = +let clear w = + begin + for i=1 to w.pages do w.notebook#remove_page 0 done ; + w.pages <- 0 ; + Hashtbl.clear w.file_index ; + Hashtbl.clear w.name_index ; + end + +let later f = ignore (Glib.Idle.add (fun () -> f () ; false)) + +let select_file w filename = + try + let tab = Hashtbl.find w.file_index filename in + later (fun () -> w.notebook#goto_page tab.tab_page) + with Not_found -> () + +let select_name w title = + try + let tab = Hashtbl.find w.name_index title in + later (fun () -> w.notebook#goto_page tab.tab_page) + with Not_found -> () + +let load_file w ?title ~filename ?(line=(-1)) () = + Gui_parameters.debug "Opening file %S line %d" filename line ; + let tab = begin - try Hashtbl.find w.tbl filename + try Hashtbl.find w.file_index filename with Not_found -> - let label = GMisc.label - ~text:(match title with None -> filename | Some s -> s) - () - in + let name = match title with None -> filename | Some s -> s in + let label = GMisc.label ~text:name () in let sw = GBin.scrolled_window - ~vpolicy:`AUTOMATIC - ~hpolicy:`AUTOMATIC + ~vpolicy:`AUTOMATIC + ~hpolicy:`AUTOMATIC ~packing:(fun arg -> ignore (w.notebook#append_page ~tab_label:label#coerce arg)) - () - in - let window = ((Source_viewer.make - ~packing:sw#add) - :> GText.view) - in - (* - ignore - (window#buffer#connect#mark_set - ~callback:(fun it mark -> - if Gobject.get_oid mark == Gobject.get_oid (GtkText.Buffer.get_insert window#buffer#as_buffer) then - Format.printf "File:%s Line:%d@." - filename - (succ it#line) - ));*) + () in + let window = ((Source_viewer.make ~packing:sw#add) :> GText.view) in let page_num = w.notebook#page_num sw#coerce in let b = Buffer.create 1024 in - with_file filename ~f:(input_channel b); + with_file filename ~f:(input_channel b) ; let s = try_convert (Buffer.contents b) in Buffer.reset b; let (buffer:GText.buffer) = window#buffer in buffer#set_text s; - let select_line line = + let select_line ~line = w.notebook#goto_page page_num; if line >= 0 then let it = buffer#get_iter (`LINE (line-1)) in @@ -271,16 +127,20 @@ let y = if buffer#line_count < 20 then 0.23 else 0.3 in window#scroll_to_mark ~use_align:true ~yalign:y `INSERT in - let result = { tab_name = filename; select_line = select_line;} - in - Hashtbl.add w.tbl filename result ; - result + let tab = { + tab_file = filename ; + tab_name = name ; + tab_select = select_line ; + tab_page = page_num ; + } in + w.pages <- succ page_num ; + Hashtbl.add w.file_index filename tab ; + Hashtbl.add w.name_index name tab ; + tab end in (* Runs this at idle priority to let the text be displayed before. *) - ignore (Glib.Idle.add - (fun () -> filename_info.select_line line;false(*do it once only*))) - + later (fun () -> tab.tab_select ~line) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/gui/source_manager.mli frama-c-20111001+nitrogen+dfsg/src/gui/source_manager.mli --- frama-c-20110201+carbon+dfsg/src/gui/source_manager.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/source_manager.mli 2011-10-10 08:38:27.000000000 +0000 @@ -20,54 +20,21 @@ (* *) (**************************************************************************) -(** This file contains the source viewer multi-tabs widget window *) +(** The source viewer multi-tabs widget window. *) type t -val make : packing:(GObj.widget -> unit) -> t +val make: + ?tab_pos:Gtk.Tags.position -> ?packing:(GObj.widget -> unit) -> unit -> t -val make_unpacked : unit -> t - -val load_file : ?title:string -> t -> filename:string -> line:int -> unit +val load_file: + t -> ?title:string -> filename:string -> ?line:int -> unit -> unit (** If [line] is 0 then the last line of the text is shown. - If [line] is less that 0 then no scrolling occurs. - If [title] is not provided the page title is the filename. - *) - -(** Lowlevel interface *) - -val get_notebook: t -> GPack.notebook - -val append_source_tab : t -> string -> GSourceView2.source_view - -val prepend_source_tab : t -> string -> GSourceView2.source_view - -val get_nth_page: t -> int -> GObj.widget - -val current_page: t -> int - -val last_page: t -> int - -val set_current_view: t -> int -> unit - -val get_current_view: t -> GSourceView2.source_view - -val get_current_index: t -> int - -val delete_current_view: t -> unit - -val delete_view: t -> int -> unit - -val delete_all_views: t -> unit - (** Delete all pages in the object *) - -val append_view: t -> GSourceView2.source_view -> unit - -val get_nth_view: t -> int -> GSourceView2.source_view - -val enable_popup : t -> bool -> unit - -val set_scrollable : t -> bool -> unit + If [line] is less that 0 then no scrolling occurs (default). + If [title] is not provided the page title is the filename. *) -val length: t -> int +val select_file: t -> string -> unit (** Selection by page filename *) +val select_name: t -> string -> unit (** Selection by page title *) +val clear : t -> unit + (** Remove all pages added by [load_file] *) diff -Nru frama-c-20110201+carbon+dfsg/src/gui/source_viewer.ml frama-c-20111001+nitrogen+dfsg/src/gui/source_viewer.ml --- frama-c-20110201+carbon+dfsg/src/gui/source_viewer.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/source_viewer.ml 2011-10-10 08:38:27.000000000 +0000 @@ -23,8 +23,8 @@ (* Build a read only text view for C source code. *) -let set_language_to_C (buffer:GSourceView2.source_buffer) = - let original_source_language_manager = +let set_language_to_C (buffer:GSourceView2.source_buffer) = + let original_source_language_manager = GSourceView2.source_language_manager ~default:true in let original_lang = @@ -36,23 +36,23 @@ | None -> Gui_parameters.warning "Mime type 'text/x-csrc' not found" end; buffer#set_highlight_syntax true - + let make ~packing = (* let d = GWindow.font_selection_dialog ~title:"tutu" ~show:true () in - d#selection#set_preview_text - (Format.sprintf "%s %s %s %s" + d#selection#set_preview_text + (Format.sprintf "%s %s %s %s" Utf8_logic.forall Utf8_logic.exists Utf8_logic.eq Utf8_logic.neq) ; *) - let original_source_window = + let original_source_window = GSourceView2.source_view ~show_line_numbers:true ~editable:false ~packing () in -(* let pixbuf = - original_source_window#misc#render_icon ~size:`MENU `DIALOG_WARNING - in +(* let pixbuf = + original_source_window#misc#render_icon ~size:`MENU `DIALOG_WARNING + in original_source_window#set_marker_pixbuf "warning" pixbuf; *) original_source_window#misc#set_name "source"; let original_source_buffer = original_source_window#source_buffer in @@ -65,11 +65,9 @@ (* very old gtksourceview do not have this property. *) end; original_source_window - - + + let buffer () = let original_source_buffer = GSourceView2.source_buffer () in set_language_to_C original_source_buffer; original_source_buffer - - diff -Nru frama-c-20110201+carbon+dfsg/src/gui/source_viewer.mli frama-c-20111001+nitrogen+dfsg/src/gui/source_viewer.mli --- frama-c-20110201+carbon+dfsg/src/gui/source_viewer.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/source_viewer.mli 2011-10-10 08:38:27.000000000 +0000 @@ -28,5 +28,3 @@ val buffer : unit -> GSourceView2.source_buffer (** @return the buffer displaying the pretty-printed AST. *) - - diff -Nru frama-c-20110201+carbon+dfsg/src/gui/warning_manager.ml frama-c-20111001+nitrogen+dfsg/src/gui/warning_manager.ml --- frama-c-20110201+carbon+dfsg/src/gui/warning_manager.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/warning_manager.ml 2011-10-10 08:38:27.000000000 +0000 @@ -22,105 +22,70 @@ open Log -type t = +type t = { widget: GTree.view; append : event -> unit; clear : unit -> unit;} -let make ~packing ~callback = - let module L = struct - type t = event - let column_list = new GTree.column_list - let message_list_scope_col = column_list#add Gobject.Data.caml - let message_list_channel_col = column_list#add Gobject.Data.string - let message_list_message_col = column_list#add Gobject.Data.string - let message_list_severity_col = column_list#add Gobject.Data.caml - - let scope = function - | None -> "Global" - | Some s -> Printf.sprintf "%s:%d" s.src_file s.src_line - - let custom_value (_:Gobject.g_type) t ~column : Gobject.basic = - match column with - | 0 -> (* scope *) `CAML (Obj.repr t.evt_source) - | 1 -> (* plugin *) `STRING (Some (String.capitalize t.evt_plugin)) - | 2 -> (* message *) `STRING (Some t.evt_message) - | 3 -> (* severity *) `CAML (Obj.repr t.evt_kind) - | _ -> assert false - end - in - let module MODEL = Gtk_helper.MAKE_CUSTOM_LIST(L) in - let message_list_list_store = MODEL.custom_list () in - let append m = message_list_list_store#insert m in - let clear () = message_list_list_store#clear () in - let sc = +let make ~packing ~callback = + let module MODEL = Gtk_helper.MAKE_CUSTOM_LIST(struct type t = event end) in + let model = MODEL.custom_list () in + let append m = model#insert m in + let clear () = model#clear () in + let scope = function + | None -> "Global" + | Some s -> Printf.sprintf "%s:%d" s.Lexing.pos_fname s.Lexing.pos_lnum + in + let sc = GBin.scrolled_window ~vpolicy:`AUTOMATIC ~hpolicy:`AUTOMATIC - ~packing + ~packing () in - let view:GTree.view = GTree.view + let view:GTree.view = GTree.view ~rules_hint:true ~headers_visible:false ~packing:sc#add () in - let model = message_list_list_store#coerce in let top = `YALIGN 0.0 in - let severity_renderer = GTree.cell_renderer_pixbuf [top;`XALIGN 0.5] in - let scope_renderer = GTree.cell_renderer_text [top] in - let plugin_renderer = GTree.cell_renderer_text [top] in - let message_renderer = GTree.cell_renderer_text [top] in - let m_severity_renderer renderer (model:GTree.model) iter = - let severity = model#get ~row:iter ~column:L.message_list_severity_col in - renderer#set_properties (match severity with - | Error -> [`STOCK_ID "gtk-dialog-error"] - | Warning -> [`STOCK_ID "gtk-dialog-warning"] - | _ -> [`STOCK_ID "gtk-dialog-info"]) - in - let m_scope_renderer renderer (model:GTree.model) iter = - let src = model#get ~row:iter ~column:L.message_list_scope_col in - renderer#set_properties [`TEXT (L.scope src)] - in - let m_plugin_renderer renderer (model:GTree.model) iter = - let plugin = model#get ~row:iter ~column:L.message_list_channel_col in - renderer#set_properties [`TEXT plugin] - in - let m_message_renderer renderer (model:GTree.model) iter = - let message = model#get ~row:iter ~column:L.message_list_message_col in - renderer#set_properties [`TEXT message] - in - let severity_col_view = GTree.view_column - ~title:"" ~renderer:(severity_renderer, []) () in - let scope_col_view = GTree.view_column - ~title:"Source" ~renderer:(scope_renderer, []) () in - let channel_col_view = GTree.view_column - ~title:"Plugin" ~renderer:(plugin_renderer, []) () in - let message_col_view = GTree.view_column - ~title:"Message" ~renderer:(message_renderer, []) () in - severity_col_view#set_cell_data_func - severity_renderer (m_severity_renderer severity_renderer) ; - scope_col_view#set_cell_data_func - scope_renderer (m_scope_renderer scope_renderer) ; - channel_col_view#set_cell_data_func - plugin_renderer (m_plugin_renderer plugin_renderer) ; - message_col_view#set_cell_data_func - message_renderer (m_message_renderer message_renderer) ; - + let severity_col_view = MODEL.make_view_column model + (GTree.cell_renderer_pixbuf [top;`XALIGN 0.5]) + (fun e -> match e with + | {evt_kind=Error} -> [`STOCK_ID "gtk-dialog-error"] + | {evt_kind=Warning} -> [`STOCK_ID "gtk-dialog-warning"] + | _ -> [`STOCK_ID "gtk-dialog-info"]) + ~title:"" + in + let scope_col_view = MODEL.make_view_column model + (GTree.cell_renderer_text [top]) + (fun {evt_source=src} -> [`TEXT (scope src)]) + ~title:"Source" + in + let channel_col_view = + MODEL.make_view_column model + (GTree.cell_renderer_text [top]) + (fun {evt_plugin=m} -> [`TEXT m]) + ~title:"Plugin" + in + let message_col_view = MODEL.make_view_column model + (GTree.cell_renderer_text [top]) + (fun {evt_message=m} -> [`TEXT m]) + ~title:"Message" + in ignore (view#append_column severity_col_view) ; ignore (view#append_column scope_col_view) ; ignore (view#append_column channel_col_view) ; ignore (view#append_column message_col_view) ; - - let on_message_activated (mess_view:GTree.view) tree_path _view_column = - let model = mess_view#model in - let row = model#get_iter tree_path in - let src = model#get ~row ~column:L.message_list_scope_col in - match src with - | None -> () - | Some s -> callback s.src_file s.src_line + + let on_message_activated tree_path _view_column = + let v = model#custom_get_iter tree_path in + match v with + | None | Some {MODEL.finfo={evt_source=None}} -> () + | Some {MODEL.finfo={evt_source=Some s}} -> + callback s in - ignore (view#connect#row_activated ~callback:(on_message_activated view)) ; - view#set_model (Some model); + ignore (view#connect#row_activated ~callback:on_message_activated); + view#set_model (Some model#coerce); {widget = view; append = append; diff -Nru frama-c-20110201+carbon+dfsg/src/gui/warning_manager.mli frama-c-20111001+nitrogen+dfsg/src/gui/warning_manager.mli --- frama-c-20110201+carbon+dfsg/src/gui/warning_manager.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/gui/warning_manager.mli 2011-10-10 08:38:27.000000000 +0000 @@ -25,8 +25,8 @@ type t (** Type of the widget containing the warnings. *) -val make : - packing:(GObj.widget -> unit) -> callback:(string -> int -> unit) -> t +val make : + packing:(GObj.widget -> unit) -> callback:(Lexing.position -> unit) -> t (** Build a new widget for storing the warnings. *) (*val set_font : t -> Pango.font_description -> unit*) diff -Nru frama-c-20110201+carbon+dfsg/src/impact/options.mli frama-c-20111001+nitrogen+dfsg/src/impact/options.mli --- frama-c-20110201+carbon+dfsg/src/impact/options.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/impact/options.mli 2011-10-10 08:38:30.000000000 +0000 @@ -22,13 +22,13 @@ include Plugin.S -module Pragma: Plugin.STRING_SET +module Pragma: Plugin.String_set (** Use pragmas of given function. *) -module Print: Plugin.BOOL +module Print: Plugin.Bool (** Print the impacted stmt on stdout. *) -module Slicing: Plugin.BOOL +module Slicing: Plugin.Bool (** Slicing from the impacted stmt. *) val is_on: unit -> bool diff -Nru frama-c-20110201+carbon+dfsg/src/impact/register_gui.ml frama-c-20111001+nitrogen+dfsg/src/impact/register_gui.ml --- frama-c-20110201+carbon+dfsg/src/impact/register_gui.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/impact/register_gui.ml 2011-10-10 08:38:30.000000000 +0000 @@ -29,17 +29,25 @@ include State_builder.Option_ref (Cil_datatype.Stmt) (struct - let name = "Impact_gui.SelectedStmt" - let dependencies = [ Ast.self ] - let kind = `Internal + let name = "Impact_gui.SelectedStmt" + let dependencies = [ Ast.self ] + let kind = `Internal end) -(* [JS 2010/01/31] clearing dependencies prevent journalisation to highlight - code when replaying *) -(* let set s = + + let set s = set s; - Project.clear ~selection:(State_selection.Dynamic.only_dependencies self) ()*) + Project.clear + ~selection:(State_selection.Dynamic.only_dependencies self) + (); end +let () = + Cmdline.run_after_extended_stage + (fun () -> + State_dependency_graph.Static.add_codependencies + ~onto:SelectedStmt.self + [ !Db.Pdg.self ]) + module Highlighted_stmt : sig val add: Kernel_function.t -> stmt -> unit val mem: Kernel_function.t -> stmt -> bool @@ -52,18 +60,18 @@ Kernel_function.Make_Table (Stmt.Set) (struct - let name = "Impact_gui.Highlighted_stmt" - let size = 7 - let dependencies = [ SelectedStmt.self ] + let name = "Impact_gui.Highlighted_stmt" + let size = 7 + let dependencies = [ SelectedStmt.self ] let kind = `Internal end) let add kf s = ignore (Tbl.memo - ~change:(fun set -> Stmt.Set.add s set) - (fun _ -> Stmt.Set.singleton s) - kf) + ~change:(fun set -> Stmt.Set.add s set) + (fun _ -> Stmt.Set.singleton s) + kf) let mem kf s = try @@ -76,16 +84,20 @@ end +(* Show or hide the 'Impact' column of the gui filetree. *) +let show_column = ref (fun () -> ()) + (* Are results shown? *) -module Enabled = - State_builder.Ref +module Enabled = struct + include State_builder.Ref (Datatype.Bool) (struct - let name = "Impact_gui.Enabled" - let dependencies = [] - let kind = `Internal - let default () = true + let name = "Impact_gui.State" + let dependencies = [] + let kind = `Internal + let default () = false end) +end (* Should perform slicing after impact? *) module Slicing = @@ -121,23 +133,29 @@ in let hilight kf s = if Highlighted_stmt.mem kf s then - tag "hilighed_impact" "green" + tag "hilighed_impact" "green" else - SelectedStmt.may - (fun sel -> if Cil_datatype.Stmt.equal sel s then - tag "selected_impact" "cyan") + SelectedStmt.may + (fun sel -> if Cil_datatype.Stmt.equal sel s then + tag "selected_impact" "cyan") in apply_on_stmt hilight loc -let compute_impact (main_ui:Design.main_window_extension_points) s = - let impact = !Db.Impact.from_stmt s in + +let impact_statement s = + let impact = Register.from_stmt s in SelectedStmt.set s; let add s = - Highlighted_stmt.add (snd (Kernel_function.find_from_sid s.sid)) s + Highlighted_stmt.add (Kernel_function.find_englobing_kf s) s in List.iter add impact; if Slicing.get () then !Db.Impact.slice impact; Enabled.set true; + impact + +let impact_statement_ui (main_ui:Design.main_window_extension_points) s = + ignore (!Db.Impact.from_stmt s); + !show_column (); main_ui#rehighlight () let impact_selector @@ -145,10 +163,10 @@ apply_on_stmt (fun _ s -> if button = 3 || FollowFocus.get () then - let callback () = compute_impact main_ui s in - ignore (popup_factory#add_item "_Impact analysis" ~callback); - if FollowFocus.get () then - ignore (Glib.Idle.add (fun () -> callback (); false))) + let callback () = ignore (impact_statement_ui main_ui s) in + ignore (popup_factory#add_item "_Impact analysis" ~callback); + if FollowFocus.get () then + ignore (Glib.Idle.add (fun () -> callback (); false))) localizable let impact_panel main_ui = @@ -159,9 +177,9 @@ GButton.button ~label:"Set selected" ~packing:(bbox#pack ~fill:false ~expand:true) () in - let do_select = apply_on_stmt (fun _ -> compute_impact main_ui) in + let do_select = apply_on_stmt (fun _ -> impact_statement_ui main_ui) in ignore (set_selected#connect#pressed - (fun () -> Design.apply_on_selected do_select)); + (fun () -> History.apply_on_selected do_select)); (* check buttons *) let add_check_button label active f = let b = GButton.check_button ~label ~active ~packing:w#pack () in @@ -170,7 +188,7 @@ in let enabled_button = add_check_button "Enable" (Enabled.get ()) - (fun b -> Enabled.set b#active; main_ui#rehighlight ()) + (fun b -> Enabled.set b#active; !show_column (); main_ui#rehighlight ()) in let slicing_button = add_check_button "Slicing after impact" (Slicing.get ()) @@ -183,11 +201,12 @@ (* panel refresh *) let refresh () = let sensitive_set_selected_button = ref false in - Design.apply_on_selected + History.apply_on_selected (apply_on_stmt (fun _ _ -> sensitive_set_selected_button := true)); set_selected#misc#set_sensitive !sensitive_set_selected_button; if Enabled.get () <> enabled_button#active then begin enabled_button#set_active (Enabled.get ()); + !show_column (); main_ui#rehighlight () end; slicing_button#set_active (Slicing.get ()); @@ -196,20 +215,23 @@ "Impact", w#coerce, Some refresh let file_tree_decorate (file_tree:Filetree.t) = - file_tree#append_pixbuf_column - "Impact" - (fun globs -> - let is_hilighted = function - | GFun ({svar = v }, _) -> - Highlighted_stmt.mem_kf (Globals.Functions.get v) - | _ -> false - in - let id = - (* lazyness of && is used for efficiency *) - if Enabled.get () && List.exists is_hilighted globs then "gtk-apply" - else "" - in - [ `STOCK_ID id ]) + show_column := + file_tree#append_pixbuf_column + ~title:"Impact" + (fun globs -> + let is_hilighted = function + | GFun ({svar = v }, _) -> + Highlighted_stmt.mem_kf (Globals.Functions.get v) + | _ -> false + in + let id = + (* lazyness of && is used for efficiency *) + if Enabled.get () && List.exists is_hilighted globs then "gtk-apply" + else "" + in + [ `STOCK_ID id ]) + (fun () -> Enabled.get ()); + !show_column () let main main_ui = main_ui#register_source_selector impact_selector; @@ -219,6 +241,16 @@ let () = Design.register_extension main +let () = + Db.register + (Db.Journalize + ("Impact.from_stmt", + Datatype.func Cil_datatype.Stmt.ty + (Datatype.list Cil_datatype.Stmt.ty))) + Impact.from_stmt + impact_statement + + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/impact/register.ml frama-c-20111001+nitrogen+dfsg/src/impact/register.ml --- frama-c-20110201+carbon+dfsg/src/impact/register.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/impact/register.ml 2011-10-10 08:38:30.000000000 +0000 @@ -23,7 +23,6 @@ open Cil open Cil_types open Cil_datatype -open Db_types open Db open Visitor open Options @@ -32,12 +31,25 @@ List.iter (fun s -> Format.fprintf fmt "@\nsid %d: %a" s.sid Cil.d_stmt s) a let from_stmt s = - let kf = snd (Kernel_function.find_from_sid s.sid) in - Dynamic.get - ~plugin:"Security_slicing" - "impact_analysis" - (Datatype.func2 Kernel_function.ty Stmt.ty (Datatype.list Stmt.ty)) - kf s + let kf = Kernel_function.find_englobing_kf s in + try + Dynamic.get + ~plugin:"Security_slicing" + "impact_analysis" + (Datatype.func2 Kernel_function.ty Stmt.ty (Datatype.list Stmt.ty)) + kf s + with + | Dynamic.Incompatible_type _ -> + error "versions of plug-ins `impact' and `Security_slicing' seem \ +incompatible.\nCheck the environement variable FRAMAC_PLUGIN.\n\ +Analysis discarded."; + [] + | Dynamic.Unbound_value _ -> + error "cannot access to plug-in `Security_slicing'.\n\ +Are you sure that it is loaded? Check the environement variable \ +FRAMAC_PLUGIN.\n\ +Analysis discarded."; + [] let compute_one_stmt s = debug "computing impact of statement %d" s.sid; @@ -52,7 +64,7 @@ let name = "impact slicing" in let slicing = !Db.Slicing.Project.mk_project name in let select sel ({ sid = id } as stmt) = - let _, kf = Kernel_function.find_from_sid id in + let kf = Kernel_function.find_englobing_kf stmt in debug ~level:3 "selecting sid %d (of %s)" id (Kernel_function.get_name kf); !Db.Slicing.Select.select_stmt sel ~spare:false stmt kf in @@ -69,12 +81,12 @@ List.fold_left (fun acc (s, a) -> match a with - | Before (User a) -> - (match a.annot_content with - | APragma (Impact_pragma IPstmt) -> f acc s - | APragma (Impact_pragma (IPexpr _)) -> - raise (Extlib.NotYetImplemented "impact pragmas: expr") - | _ -> assert false) + | User a -> + (match a.annot_content with + | APragma (Impact_pragma IPstmt) -> f acc s + | APragma (Impact_pragma (IPexpr _)) -> + raise (Extlib.NotYetImplemented "impact pragmas: expr") + | _ -> assert false) | _ -> assert false) let compute_pragmas () = @@ -85,9 +97,9 @@ (Project.current ()) (inplace_visit ()) method vstmt_aux s = pragmas := - List.map - (fun a -> s, a) - (Annotations.get_filter Logic_utils.is_impact_pragma s) + List.map + (fun a -> s, a) + (Annotations.get_filter Logic_utils.is_impact_pragma s) @ !pragmas; DoChildren end in @@ -95,11 +107,11 @@ Pragma.iter (fun s -> try - match (Globals.Functions.find_def_by_name s).fundec with - | Definition(f, _) -> ignore (visitFramacFunction visitor f) - | Declaration _ -> assert false + match (Globals.Functions.find_def_by_name s).fundec with + | Definition(f, _) -> ignore (visitFramacFunction visitor f) + | Declaration _ -> assert false with Not_found -> - fatal "function %s not found@." s); + abort "function %s not found." s); (* compute impact analyses on [!pragmas] *) let res = on_pragma (fun acc s -> compute_one_stmt s @ acc) [] !pragmas in if Options.Slicing.get () then ignore (slice res) @@ -121,11 +133,12 @@ Impact.compute_pragmas compute_pragmas; (* from_stmt *) - Db.register - (Db.Journalize - ("Impact.from_stmt", Datatype.func Stmt.ty (Datatype.list Stmt.ty))) - Impact.from_stmt - from_stmt; + if not !Config.is_gui then + Db.register + (Db.Journalize + ("Impact.from_stmt", Datatype.func Stmt.ty (Datatype.list Stmt.ty))) + Impact.from_stmt + from_stmt; (* slice *) Db.register (Db.Journalize diff -Nru frama-c-20110201+carbon+dfsg/src/inout/access_path.ml frama-c-20111001+nitrogen+dfsg/src/inout/access_path.ml --- frama-c-20110201+carbon+dfsg/src/inout/access_path.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/access_path.ml 2011-10-10 08:38:23.000000000 +0000 @@ -26,31 +26,30 @@ let pretty = let module M = - Base.Map.Make(struct - open Locations - include Datatype.Pair(Zone)(Location_Bits) - let pretty fmt (z, loc) = - Format.fprintf fmt "@[[Zone:%a@ Loc_bits:%a]@]" - Zone.pretty z - Location_Bits.pretty loc - end) + Base.Map.Make(struct + open Locations + include Datatype.Pair(Zone)(Location_Bits) + let pretty fmt (z, loc) = + Format.fprintf fmt "@[[Zone:%a@ Loc_bits:%a]@]" + Zone.pretty z + Location_Bits.pretty loc + end) in fun fmt m -> Format.fprintf fmt "Access_path:@\n%a@\n=============@\n" M.pretty m let compute state base_set = - let state = Relations_type.Model.value_state state in let q = Queue.create () in let result = ref Base.Map.empty in Base.Set.iter (fun elt -> Queue.add elt q) base_set; while not (Queue.is_empty q) do let current_base = Queue.take q in - let recip = Cvalue_type.Model.reciprocal_image current_base state in + let recip = Cvalue.Model.reciprocal_image current_base state in result := Base.Map.add current_base recip !result ; try Zone.fold_bases (fun base () -> - try ignore (Base.Map.find base !result) + try ignore (Base.Map.find base !result) with Not_found -> Queue.add base q) (fst recip) () @@ -74,27 +73,27 @@ if Inout_parameters.ForceAccessPath.get () then !Db.Semantic_Callgraph.topologically_iter_on_functions (fun kf -> - if Kernel_function.is_definition kf && !Db.Value.is_called kf then - let state = - Db.Value.get_state - (Cil_types.Kstmt (Kernel_function.find_first_stmt kf)) - in - let inputs = !Db.InOutContext.get_internal kf in - let s = !Db.Access_path.compute state - (Cvalue_type.Model.fold_base - (fun base acc -> Base.Set.add base acc) - (Relations_type.Model.value_state state) - Base.Set.empty) - in - Inout_parameters.result - "Filtered access_path for %a :@ %a@." - Kernel_function.pretty_name kf - !Db.Access_path.pretty - (!Db.Access_path.filter s - (Locations.Zone.filter_base - (fun b -> - not (Base.is_local b (Kernel_function.get_definition kf))) - inputs.Inout_type.over_inputs))) + if Kernel_function.is_definition kf && !Db.Value.is_called kf then + let state = + Db.Value.get_state + (Cil_types.Kstmt (Kernel_function.find_first_stmt kf)) + in + let inputs = !Db.Operational_inputs.get_internal kf in + let s = !Db.Access_path.compute state + (Cvalue.Model.fold_base + (fun base acc -> Base.Set.add base acc) + state + Base.Set.empty) + in + Inout_parameters.result + "Filtered access_path for %a :@ %a@." + Kernel_function.pretty kf + !Db.Access_path.pretty + (!Db.Access_path.filter s + (Locations.Zone.filter_base + (fun b -> + not (Base.is_local b (Kernel_function.get_definition kf))) + inputs.Inout_type.over_inputs))) let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/src/inout/context.ml frama-c-20111001+nitrogen+dfsg/src/inout/context.ml --- frama-c-20110201+carbon+dfsg/src/inout/context.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/context.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,425 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Cil_types -open Cil -open Db -open Db_types -open Locations -open Abstract_interp -open Abstract_value - -(* Computation of over-approximed operational inputs: - An acurate computation of these inputs needs the computation of - under-approximed outputs. -*) - -type compute_t = - { over_inputs : Zone.t ; - under_outputs : Zone.t } - -(* Initial value for the computation *) -let empty = - { - over_inputs = Zone.bottom; - under_outputs = Zone.bottom; - } - -let bottom = - { - over_inputs = Zone.bottom ; - under_outputs = Zone.top - } - -let join c1 c2 = - { over_inputs = Zone.join c1.over_inputs c2.over_inputs; - under_outputs = Zone.meet c1.under_outputs c2.under_outputs; - } - -let is_included c1 c2 = - Zone.is_included c1.over_inputs c2.over_inputs && - Zone.is_included c2.under_outputs c1.under_outputs - -let catenate c1 c2 = - { over_inputs = - Zone.join - c1.over_inputs - (Zone.diff c2.over_inputs c1.under_outputs); - under_outputs = Zone.link c1.under_outputs c2.under_outputs } - -let pretty fmt x = - Format.fprintf fmt - "@[Over-approximated operational inputs: %a@]@\n\ - @[Under-approximated operational outputs: %a@]" - Zone.pretty x.over_inputs - Zone.pretty x.under_outputs - - -let call_stack : kernel_function Stack.t = - Stack.create () - (* Stack of function being processed *) - -module Computer (REACH:sig - val stmt_can_reach : stmt -> stmt -> bool - end) = struct - let name = "InOut context" - - let debug = ref false - - let current_stmt = ref Kglobal - - let stmt_can_reach = REACH.stmt_can_reach - - let non_terminating_callees_inputs = ref Zone.bottom - - type t = compute_t - - let pretty = pretty - - module StmtStartData = - Dataflow.StmtStartData(struct type t = compute_t let size = 107 end) - - let display_one fmt k v = - Format.fprintf fmt "Statement: %d@\n" - k; - InOutContext.pretty fmt v - - let display fmt f = - Format.fprintf fmt "=========INOUT CONTEXT START=======@\n"; - Inthash.iter - (display_one fmt) - f; - Format.fprintf fmt "=========INOUT CONTEXT END=======@\n" - - let copy (d: t) = d - - let computeFirstPredecessor (s: stmt) data = - match s.skind with - | Switch (exp,_,_,_) - | If (exp,_,_,_) - | Return (Some exp, _) -> - let inputs = !From.find_deps_no_transitivity (Kstmt s) exp in - {data with - over_inputs = - Zone.join data.over_inputs - (Zone.diff inputs data.under_outputs)} - | _ -> data - - let combinePredecessors (s: stmt) ~old new_ = - let new_c = computeFirstPredecessor s new_ in - let result = join new_c old in - if is_included result old - then None - else Some result - - let resolv_func_vinfo ?deps kinstr funcexp = - !Value.expr_to_kernel_function ?deps kinstr funcexp - - let doInstr _stmt (i: instr) (_d: t) = - let kinstr = !current_stmt - in - let add_with_additional_var k j st = - let deps, looking_for = - !Value.lval_to_loc_with_deps - ~with_alarms:CilE.warn_none_mode - ~deps:j - kinstr - k - in - let new_inputs = - Zone.join st.over_inputs (Zone.diff deps st.under_outputs) in - let new_outputs = - if Locations.valid_cardinal_zero_or_one looking_for - then - (* There is only one modified zone. So, this is an exact output. - Add it into the under-approximed outputs. *) - Zone.link - st.under_outputs - (Locations.valid_enumerate_bits looking_for) - else st.under_outputs - in - { over_inputs = new_inputs; - under_outputs = new_outputs } - in - match i with - | Set (lv, exp, _) -> - Dataflow.Post - (fun state -> - let exp_inputs_deps = - !From.find_deps_no_transitivity kinstr exp - in - add_with_additional_var - lv - exp_inputs_deps - state) - | Call (lvaloption,funcexp,argl,_) -> - Dataflow.Post - (fun state -> - let funcexp_inputs, called_vinfos = - resolv_func_vinfo - ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - kinstr - funcexp - in - let acc_funcexp_inputs = - (* inputs used by [funcexp] and inputs - for the evaluation of [funcexp] *) - Zone.join funcexp_inputs state.over_inputs - in - let acc_funcexp_arg_inputs = - (* add the inputs of [argl] *) - List.fold_right - (fun arg inputs -> - let arg_inputs = !From.find_deps_no_transitivity kinstr arg - in Zone.join inputs arg_inputs) - argl - acc_funcexp_inputs - in - let state = { state with over_inputs = acc_funcexp_arg_inputs } in - let for_functions = - Kernel_function.Hptset.fold - (fun called_vinfo acc -> - let { Inout_type.over_inputs_if_termination = called_inputs_term; - under_outputs_if_termination = called_outputs ; - over_inputs = called_inputs} = - !Db.InOutContext.get_external called_vinfo - in - non_terminating_callees_inputs := - Zone.join - !non_terminating_callees_inputs - (Zone.diff called_inputs state.under_outputs); - let for_function = - { over_inputs = called_inputs_term; - under_outputs = called_outputs } - in - join for_function acc) - called_vinfos - bottom - in -(* Format.printf "functions: %a@." pretty for_functions; *) - let result = catenate state for_functions in - let result = - (* Treatment for the possible assignment of the call result *) - (match lvaloption with - | None -> result - | Some lv -> - add_with_additional_var - lv - Zone.bottom - result) - in result - ) - | _ -> Dataflow.Default - - let doStmt (s: stmt) (_d: t) = - current_stmt := Kstmt s; - Dataflow.SDefault - - let filterStmt (s:stmt) = - let state = Value.noassert_get_state (Kstmt s) in - Value.is_reachable state - - let doGuard s _e _t = - current_stmt := Kstmt s; - Dataflow.GDefault, Dataflow.GDefault - - let doEdge _ _ d = d - -end - -let get_using_prototype kf = - let state = Value.get_initial_state kf in - let behaviors = !Value.valid_behaviors kf state in - let assigns = Ast_info.merge_assigns behaviors in - let inputs = - !Value.assigns_to_zone_inputs_state state assigns - in -(* Format.printf "proto inputs from assigns: %a@." - Zone.pretty over_inputs_if_termination; *) - { Inout_type.under_outputs_if_termination = - Zone.bottom ; - over_inputs_if_termination = inputs; - over_inputs = inputs - } - -let compute_internal_using_prototype kf = - match kf.fundec with - | Definition _ -> assert false - | Declaration _ -> get_using_prototype kf - -let compute_internal_using_cfg kf = - let compute_for_definition kf f = - try - let module Computer = - Computer - (struct let stmt_can_reach = Stmts_graph.stmt_can_reach kf end) - in - let module Compute = Dataflow.ForwardsDataFlow(Computer) in - Stack.iter - (fun g -> if kf == g then begin - Inout_parameters.warning ~current:true - "ignoring recursive call detected in function %s during [inout context] computation." - (Kernel_function.get_name kf); - raise Exit - end) - call_stack; - Stack.push kf call_stack; - let res_if_termination = - match f.sbody.bstmts with - [] -> assert false - | start :: _ -> - let ret_id = Kernel_function.find_return kf in - Computer.StmtStartData.add - start.sid - (Computer.computeFirstPredecessor - start - empty); - Compute.compute [start]; - ignore (Stack.pop call_stack); - try - Computer.StmtStartData.find ret_id.sid - with Not_found -> bottom - in - - { Inout_type.over_inputs_if_termination = res_if_termination.over_inputs; - under_outputs_if_termination = res_if_termination.under_outputs ; - over_inputs = - let acc = Computer.non_terminating_callees_inputs - in - Computer.StmtStartData.iter - (fun _sid data -> acc := Zone.join data.over_inputs !acc); - !acc} - - with Exit -> - { Inout_type.over_inputs_if_termination = empty.over_inputs ; - under_outputs_if_termination = empty.under_outputs ; - over_inputs = empty.over_inputs - } - in - match kf.fundec with - | Declaration _ -> - invalid_arg - "compute_using_cfg cannot be called on library functions" - | Definition (f, _) -> - compute_for_definition kf f - - -module Internals = - Kf_state.Context - (struct - let name = "Internal inouts" - let dependencies = [ Value.self ] - let kind = `Correctness - end) - -let get_internal = - Internals.memo - (fun kf -> - !Value.compute (); - Inout_parameters.feedback "computing for function %a%s" - Kernel_function.pretty_name kf - (let s = ref "" in - Stack.iter - (fun kf -> s := !s^" <-"^ - (Pretty_utils.sfprintf "%a" Kernel_function.pretty_name kf)) - call_stack; - !s); - let res = - match kf.fundec with - | Definition _ -> - compute_internal_using_cfg kf - | Declaration _ -> - compute_internal_using_prototype kf - in - Inout_parameters.feedback "done for function %a" - Kernel_function.pretty_name kf; - res) - - let externalize ~with_formals kf = - Zone.filter_base (Db.accept_base ~with_formals kf) - -let raw_get_external ~with_formals kf = - let internals = get_internal kf in - let filter = externalize ~with_formals kf in - - { Inout_type.over_inputs_if_termination = - (let r = - filter internals.Inout_type.over_inputs_if_termination - in -(* Format.printf "filtered -> %a@." Zone.pretty r; *) - r); - under_outputs_if_termination = - filter internals.Inout_type.under_outputs_if_termination; - over_inputs = filter internals.Inout_type.over_inputs } - -module Externals = - Kf_state.Context - (struct - let name = "External inouts" - let dependencies = [ Internals.self ] - let kind = `Correctness - end) -let get_external = Externals.memo (raw_get_external ~with_formals:false) -let compute_external kf = ignore (get_external kf) - -module Externals_With_Formals = - Kf_state.Context - (struct - let name = "External inouts with formals" - let dependencies = [ Internals.self ] - let kind = `Correctness - end) -let get_external_with_formals = - Externals_With_Formals.memo (raw_get_external ~with_formals:true) -let compute_external_with_formals kf = ignore (get_external_with_formals kf) - - -let pretty_internal fmt kf = - Format.fprintf fmt "@[InOut (internal) for function %a:@\n%a@]@\n" - Kernel_function.pretty_name kf - InOutContext.pretty (get_internal kf) - -let pretty_external fmt kf = - Format.fprintf fmt "@[InOut for function %a:@\n%a@]@\n" - Kernel_function.pretty_name kf - InOutContext.pretty (get_external kf) - -let pretty_external_with_formals fmt kf = - Format.fprintf fmt "@[InOut (with formals) for function %a:@\n%a@]@\n" - Kernel_function.pretty_name kf - InOutContext.pretty (get_external_with_formals kf) - - -let () = - InOutContext.self_internal := Internals.self; - InOutContext.self_external := Externals.self; - InOutContext.get_internal := get_internal; - InOutContext.get_external := get_external; - InOutContext.compute := compute_external; - InOutContext.display := pretty_internal - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/inout/context.mli frama-c-20111001+nitrogen+dfsg/src/inout/context.mli --- frama-c-20110201+carbon+dfsg/src/inout/context.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/context.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -val pretty_internal: Format.formatter -> Db_types.kernel_function -> unit -val pretty_external_with_formals: Format.formatter -> Db_types.kernel_function -> unit - -(* -Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/inout/cumulative_analysis.ml frama-c-20111001+nitrogen+dfsg/src/inout/cumulative_analysis.ml --- frama-c-20110201+carbon+dfsg/src/inout/cumulative_analysis.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/cumulative_analysis.ml 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,166 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Db +open Visitor + +class virtual ['a] cumulative_visitor = object + inherit frama_c_inplace as self + + method specialize_state_on_call kf = + match self#current_stmt with + | Some ({ skind = Instr (Call (_, _, l, _)) } as stmt) -> + let at_stmt = Db.Value.get_stmt_state stmt in + !Db.Value.add_formals_to_state at_stmt kf l + | _ -> Value.get_initial_state kf + + method virtual compute_kf: kernel_function -> 'a + +end + +class type virtual ['a] cumulative_class = object + inherit ['a] cumulative_visitor + + method bottom: 'a + + method result: 'a + method join: 'a -> unit + + method compute_funspec : kernel_function -> 'a + + method clean_kf_result: kernel_function -> 'a -> 'a +end + + +module Make (X: + sig + val analysis_name: string + + type t + module T: Datatype.S with type t = t + + class virtual do_it: [t] cumulative_class + end) = +struct + + module Memo = + Kernel_function.Make_Table(X.T) + (struct + let name = "Memo " ^ X.analysis_name + let dependencies = [ Value.self ] + let kind = `Correctness + let size = 97 + end) + + class do_it_cached call_stack = object(self) + inherit X.do_it + + (* The cycle variables holds the list of functions that are + involved in a cycle As long as it is not empty, we known that + the results we are computing are not complete, and we do not memorize + them *) + val mutable cycle = Kernel_function.Hptset.empty + method private add_cycle s = cycle <- Kernel_function.Hptset.union s cycle + method cycle = cycle + + (* Computation using the body of a kernel function. The result is + automatically cached by the function if possible *) + method private compute_kf_with_def kf = + let f = Kernel_function.get_definition kf in + if List.exists (Kernel_function.equal kf) call_stack then ( + if Db.Value.ignored_recursive_call kf then + Inout_parameters.warning ~current:true + "During %s analysis of %a: ignoring probable recursive call." + X.analysis_name Kernel_function.pretty kf; + self#add_cycle (Kernel_function.Hptset.singleton kf); + self#bottom + ) + else + let computer = new do_it_cached (kf :: call_stack) in + ignore (visitFramacFunction (computer:>frama_c_visitor) f); + (* Results on all the statements of the function *) + let v = computer#result in + let v = computer#clean_kf_result kf v in + (* recursive calls detected during analysis of the statements*) + let cycle_aux = Kernel_function.Hptset.remove kf computer#cycle in + self#add_cycle cycle_aux; + if Kernel_function.Hptset.is_empty cycle then ( + (* No recursive calls, our results are correct *) + Inout_parameters.debug "Caching %s result for %a" + X.analysis_name Kernel_function.pretty kf; + Memo.add kf v; + ) else + Inout_parameters.debug + "Not caching %s result for %a because of cycle" + X.analysis_name Kernel_function.pretty kf; + v + + (* Computation and caching for a kernel function, using its spec *) + method private compute_kf_with_spec_generic kf = + try Memo.find kf + with Not_found -> + let r_glob = self#compute_funspec kf in + let r_glob = self#clean_kf_result kf r_glob in + Memo.add kf r_glob; + r_glob + + method compute_kf kf = + if !Db.Value.use_spec_instead_of_definition kf then + (* If only a declaration is available, or we are instructed to use + the spec, do so. If a current stmt is available (most of the times), + do not cache the results. Maybe [compute_funspec] will be able + to deliver a more precise result on this given statement *) + match self#current_stmt with + | None -> self#compute_kf_with_spec_generic kf + | Some _stmt -> self#compute_funspec kf + else + try Memo.find kf + with Not_found -> self#compute_kf_with_def kf + end + + let statement stmt = + let computer = new do_it_cached [] in + ignore (visitFramacStmt (computer:>frama_c_visitor) stmt); + assert (Kernel_function.Hptset.is_empty computer#cycle); + computer#result + + let expr stmt e = + let computer = new do_it_cached [] in + computer#push_stmt stmt; + ignore (visitFramacExpr (computer:>frama_c_visitor) e); + assert (Kernel_function.Hptset.is_empty computer#cycle); + computer#result + + let kernel_function kf = + let computer = new do_it_cached [] in + computer#join (computer#compute_kf kf); + assert (Kernel_function.Hptset.is_empty computer#cycle); + computer#result + +end + +(* +Local Variables: +compile-command: "LC_ALL=C make -C ../.. -j" +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/inout/cumulative_analysis.mli frama-c-20111001+nitrogen+dfsg/src/inout/cumulative_analysis.mli --- frama-c-20110201+carbon+dfsg/src/inout/cumulative_analysis.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/cumulative_analysis.mli 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,123 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** Implementation of a simple meta-analysis on top of the results of + the value analysis. This implementation correctly handles + memoization and apparent recursive calls during the value analysis. + + The underlying analysis is supposed to be cumulative at the level + of a kernel_function (its results are derived from the results on + all its statements), and mostly non-contextual (all the informations + can be gathered using a Cil visitor). +*) + + +(** Frama-C visitor for cumulative analyses: we add a few useful methods. + The method [compute_kf] must be used to add the effects of a call to the + given kernel function to the pool of results *) +class virtual ['a] cumulative_visitor : object + inherit Visitor.frama_c_inplace + + method specialize_state_on_call: kernel_function -> Db.Value.state + (** If the current statement is a call to the given function, + enrich the superposed memory state at this statement with + the formal arguments of this function. Useful to do an analysis + with a limited amount of context *) + + + method virtual compute_kf: kernel_function -> 'a + (** Virtual function to use when one needs to compute the effect + of a function call. This function carries implictly a context: + thus calling [self#compute_kf k1; self#compute_kf k2] + is different from calling one within the other *) +end + + +class type virtual ['a] cumulative_class = object + inherit ['a] cumulative_visitor + + method bottom: 'a + + (** Result of the analysis *) + method result: 'a + (** Adding partial results to the current ones *) + method join: 'a -> unit + + (** Function that computes and returns the partial results on a funspec. + May consult [self#current_stmt] to specialize itself, and return + partially contextual results *) + method compute_funspec : kernel_function -> 'a + + (** Assuming [v] are the results of the analysis for [f] (ie. the union + of the results on all the statements of [f], or [compute_funspec f] + if [f] has no body), [clean_kf_result k v] cleans those results + before storing them. Use for example to remove out-of-scope locals *) + method clean_kf_result: kernel_function -> 'a -> 'a +end + + + +module Make (X: + sig + val analysis_name: string + + (** Type of the results *) + type t + module T: Datatype.S with type t = t + + (** Class that implements the analysis. Must not deal with memoization, + as this is automatically done by the functor *) + class virtual do_it: [t] cumulative_class + end) : +sig + + (** Module that contains the memoized results *) + module Memo: sig val self: State.t end + + (** Class that implements a cached version of the above analysis. + Recursion in the dynamic call graphs are handled, provided the value + analysis terminated without detecting a real recursion *) + class do_it_cached: Kernel_function.t list -> + object + inherit X.do_it + + (** Internal methods that gives the functions for which a cycle + has been detected in the dynamic call-graph. Results cannot + be safely memoized if this set is not empty *) + method cycle: Kernel_function.Hptset.t + + (** Memoized version of the analysis of a kernel-function *) + method compute_kf: kernel_function -> X.t + end + + (** Effects of the given kernel_function, using memoization *) + val kernel_function: kernel_function -> X.t + + (** Effects of a statement, using memoization if it contains a function call*) + val statement: stmt -> X.t + + (** Effects of the given expression (wich is supposed to be at the given + statement *) + val expr: stmt -> exp -> X.t +end diff -Nru frama-c-20110201+carbon+dfsg/src/inout/derefs.ml frama-c-20111001+nitrogen+dfsg/src/inout/derefs.ml --- frama-c-20110201+carbon+dfsg/src/inout/derefs.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/derefs.ml 2011-10-10 08:38:23.000000000 +0000 @@ -23,127 +23,103 @@ open Cil_types open Cil open Db -open Db_types open Locations open Abstract_value open Abstract_interp -let call_stack = Stack.create () -exception Ignore -class do_it = object(self) - inherit nopCilVisitor as super +class virtual do_it_ = object(self) + inherit [Zone.t] Cumulative_analysis.cumulative_visitor as super val mutable derefs = Zone.bottom + method bottom = Zone.bottom + method result = derefs method join new_ = derefs <- Zone.join new_ derefs; -(* method vstmt s = - DoChildren -*) - method vlval (base,_ as lv) = begin match base with | Var _ -> () | Mem e -> - let state = - Value.get_state - (Kstmt (Cilutil.out_some self#current_stmt)) - in - let r = !Value.eval_expr ~with_alarms:CilE.warn_none_mode state e in - self#join (valid_enumerate_bits (loc_without_size_to_loc lv r)) + let state = + Value.get_state + (Kstmt (Cilutil.out_some self#current_stmt)) + in + let r = !Value.eval_expr ~with_alarms:CilE.warn_none_mode state e in + self#join + (valid_enumerate_bits ~for_writing:false + (loc_without_size_to_loc lv r)) end; DoChildren + method compute_funspec (_: kernel_function) = + Zone.bottom + + method clean_kf_result (_ : kernel_function) (r: Locations.Zone.t) = r + end -let statement stmt = - let computer = new do_it in - ignore (visitCilStmt (computer:>cilVisitor) stmt); - computer#result +module Analysis = Cumulative_analysis.Make( + struct + let analysis_name ="derefs" + + type t = Locations.Zone.t + module T = Locations.Zone + let bottom = Locations.Zone.bottom -module Internals = - Kf_state.Make - (struct - let name = "Internal derefs" - let dependencies = [ Value.self ] - let kind = `Correctness - end) + class virtual do_it = do_it_ +end) -let get_internal = - Internals.memo - (fun kf -> - match kf.fundec with - | Definition (f,_) -> - (try - Stack.iter - (fun g -> if kf == g then begin - Cil.warn - "recursive call detected during deref analysis of %a. Ignoring it is safe if the value analysis suceeded without problem." - Kernel_function.pretty_name kf; - raise Ignore - end - ) - call_stack; - - (* No deref to compute if the values were not computed for [kf] *) - (* if not (Value.is_accessible kf) then raise Ignore; *) - - Stack.push kf call_stack; - let computer = new do_it in - ignore (visitCilFunction (computer:>cilVisitor) f); - let _ = Stack.pop call_stack in - computer#result - with Ignore -> - Zone.bottom) - | Declaration _ -> - Zone.bottom) +let get_internal = Analysis.kernel_function let externalize _return fundec x = Zone.filter_base (fun v -> not (Base.is_formal_or_local v fundec)) x -module Externals = +module Externals = Kf_state.Make - (struct - let name = "External derefs" - let dependencies = [ Internals.self ] + (struct + let name = "External derefs" + let dependencies = [ Analysis.Memo.self ] let kind = `Correctness end) let get_external = - Externals.memo - (fun kf -> + Externals.memo + (fun kf -> !Value.compute (); if Kernel_function.is_definition kf then - externalize - (Kernel_function.find_return kf) - (Kernel_function.get_definition kf) - (get_internal kf) + try + externalize + (Kernel_function.find_return kf) + (Kernel_function.get_definition kf) + (get_internal kf) + with Kernel_function.No_Statement -> + assert false else - (* assume there is no deref for leaf functions *) - Zone.bottom) + (* assume there is no deref for leaf functions *) + Zone.bottom) let compute_external kf = ignore (get_external kf) let pretty_internal fmt kf = Format.fprintf fmt "@[Derefs (internal) for function %a:@\n@[ %a@]@]@\n" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Zone.pretty (get_internal kf) let pretty_external fmt kf = Format.fprintf fmt "@[Derefs for function %a:@\n@[ %a@]@]@\n" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Zone.pretty (get_external kf) let () = - Db.Derefs.self_internal := Internals.self; + Db.Derefs.self_internal := Analysis.Memo.self; Db.Derefs.self_external := Externals.self; Db.Derefs.get_internal := get_internal; Db.Derefs.get_external := get_external; Db.Derefs.compute := compute_external; Db.Derefs.display := pretty_external; - Db.Derefs.statement := statement + Db.Derefs.statement := Analysis.statement diff -Nru frama-c-20110201+carbon+dfsg/src/inout/derefs.mli frama-c-20111001+nitrogen+dfsg/src/inout/derefs.mli --- frama-c-20110201+carbon+dfsg/src/inout/derefs.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/derefs.mli 2011-10-10 08:38:23.000000000 +0000 @@ -20,6 +20,6 @@ (* *) (**************************************************************************) - -val pretty_external: Format.formatter -> Db_types.kernel_function -> unit -val compute_external: Db_types.kernel_function -> unit + +val pretty_external: Format.formatter -> Cil_types.kernel_function -> unit +val compute_external: Cil_types.kernel_function -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/inout/Inout.mli frama-c-20111001+nitrogen+dfsg/src/inout/Inout.mli --- frama-c-20110201+carbon+dfsg/src/inout/Inout.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/Inout.mli 2011-10-10 08:38:23.000000000 +0000 @@ -25,7 +25,7 @@ (** Inputs-outputs computations. *) (** No function is directly exported: they are registered in: - - {!Db.Inputs} for computations of non functionnal inputs; + - {!Db.Inputs} for computations of non functionnal inputs; - {!Db.Outputs} for computations of outputs; - - {!Db.InOutContext} for computation of inout context; and + - {!Db.Operational_inputs} for computation of inout context; and - {!Db.Derefs}. *) diff -Nru frama-c-20110201+carbon+dfsg/src/inout/inout_parameters.ml frama-c-20111001+nitrogen+dfsg/src/inout/inout_parameters.ml --- frama-c-20110201+carbon+dfsg/src/inout/inout_parameters.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/inout_parameters.ml 2011-10-10 08:38:23.000000000 +0000 @@ -33,7 +33,7 @@ (struct let option_name = "-deref" let help = "force deref computation (undocumented)" - let kind = `Tuning + let output_by_default = true end) module ForceAccessPath = @@ -41,47 +41,47 @@ (struct let option_name = "-access-path" let help = "force the access path information to be computed" - let kind = `Tuning + let output_by_default = true end) module ForceOut = Action (struct let option_name = "-out" - let help = "internal out display; this is an over-approximation of the set of written tsets" - let kind = `Tuning + let help = "Compute internal out. Those are an over-approximation of the set of written locations" + let output_by_default = true end) module ForceExternalOut = Action (struct let option_name = "-out-external" - let help = "external out display; this is an over-approximation of the set of written tsets excluding locals" - let kind = `Tuning + let help = "Compute external out. Those are an over-approximation of the set of written locations, excluding locals" + let output_by_default = true end) module ForceInput = - Action + Action (struct - let option_name = "-input" - let help = "display imperative inputs. Locals and function parameters are not displayed" - let kind = `Tuning + let option_name = "-input" + let help = "Compute imperative inputs. Locals and function parameters are not displayed" + let output_by_default = true end) module ForceInputWithFormals = Action (struct let option_name = "-input-with-formals" - let help = "display imperative inputs. Function parameters are displayed, locals are not" - let kind = `Tuning + let help = "Compute imperative inputs. Function parameters are displayed, locals are not" + let output_by_default = true end) module ForceInout = Action (struct let option_name = "-inout" - let help = "display operational inputs, an over-approximation of the set of locations whose initial value is used; and the sure outputs, an under-approximation of the set of the certainly written locations" - let kind = `Tuning + let help = "Compute operational inputs, an over-approximation of the set of locations whose initial value is used; and the sure outputs, an under-approximation of the set of the certainly written locations" + let output_by_default = true end) module ForceInoutExternalWithFormals = @@ -89,7 +89,7 @@ (struct let option_name = "-inout-with-formals" let help = "same as -inout but without local variables and with function parameters" - let kind = `Tuning + let output_by_default = true end) (* diff -Nru frama-c-20110201+carbon+dfsg/src/inout/inout_parameters.mli frama-c-20111001+nitrogen+dfsg/src/inout/inout_parameters.mli --- frama-c-20110201+carbon+dfsg/src/inout/inout_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/inout_parameters.mli 2011-10-10 08:38:23.000000000 +0000 @@ -22,16 +22,16 @@ include Plugin.S -module ForceAccessPath: Plugin.BOOL +module ForceAccessPath: Plugin.Bool (** undocumented *) -module ForceOut: Plugin.BOOL -module ForceExternalOut: Plugin.BOOL -module ForceInput: Plugin.BOOL -module ForceInputWithFormals: Plugin.BOOL -module ForceInout: Plugin.BOOL -module ForceInoutExternalWithFormals: Plugin.BOOL -module ForceDeref: Plugin.BOOL +module ForceOut: Plugin.Bool +module ForceExternalOut: Plugin.Bool +module ForceInput: Plugin.Bool +module ForceInputWithFormals: Plugin.Bool +module ForceInout: Plugin.Bool +module ForceInoutExternalWithFormals: Plugin.Bool +module ForceDeref: Plugin.Bool (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/inout/inputs.ml frama-c-20111001+nitrogen+dfsg/src/inout/inputs.ml --- frama-c-20110201+carbon+dfsg/src/inout/inputs.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/inputs.ml 2011-10-10 08:38:23.000000000 +0000 @@ -22,17 +22,15 @@ open Cil_types open Db -open Db_types open Locations open Visitor -let call_stack = Stack.create () -exception Ignore - -class do_it = object(self) - inherit frama_c_inplace as super +class virtual do_it_ = object(self) + inherit [Zone.t] Cumulative_analysis.cumulative_visitor as super val mutable inputs = Zone.bottom + method bottom = Zone.bottom + method result = inputs method join new_ = @@ -52,25 +50,25 @@ let deps,loc = !Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - self#current_kinstr - lv + ~deps:Zone.bottom + self#current_kinstr + lv in - let bits_loc = valid_enumerate_bits loc in + let bits_loc = valid_enumerate_bits ~for_writing:false loc in self#join deps; self#join bits_loc; Cil.SkipChildren - method do_assign lv = + method private do_assign lv = let deps,_loc = !Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - self#current_kinstr - lv + ~deps:Zone.bottom + self#current_kinstr + lv in (* Format.printf "do_assign deps:%a@." - Zone.pretty deps; *) + Zone.pretty deps; *) self#join deps; method vinst i = @@ -87,16 +85,15 @@ let deps_callees, callees = !Value.expr_to_kernel_function ~with_alarms:CilE.warn_none_mode - ~deps:(Some Zone.bottom) - self#current_kinstr exp + ~deps:(Some Zone.bottom) + self#current_kinstr exp in self#join deps_callees; Kernel_function.Hptset.iter - (fun kf -> self#join (!Db.Inputs.get_external kf)) - callees; + (fun kf -> self#join (self#compute_kf kf)) callees; List.iter - (fun exp -> ignore (visitFramacExpr (self:>frama_c_visitor) exp)) - args; + (fun exp -> ignore (visitFramacExpr (self:>frama_c_visitor) exp)) + args; Cil.SkipChildren | _ -> Cil.DoChildren end @@ -105,75 +102,44 @@ method vexpr exp = match exp.enode with | AddrOf lv | StartOf lv -> - let deps,_loc = - !Value.lval_to_loc_with_deps + let deps,_loc = + !Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - self#current_kinstr lv - in - self#join deps; - Cil.SkipChildren + ~deps:Zone.bottom + self#current_kinstr lv + in + self#join deps; + Cil.SkipChildren | _ -> Cil.DoChildren + method compute_funspec kf = + let state = self#specialize_state_on_call kf in + let behaviors = !Value.valid_behaviors kf state in + let assigns = Ast_info.merge_assigns behaviors in + !Value.assigns_to_zone_inputs_state state assigns + + method clean_kf_result (_ : kernel_function) (r: Locations.Zone.t) = r end -let statement stmt = - let computer = new do_it in - ignore (visitFramacStmt (computer:>frama_c_visitor) stmt); - computer#result - -let expr stmt e = - let computer = new do_it in - computer#push_stmt stmt; - ignore (visitFramacExpr (computer:>frama_c_visitor) e); - computer#result -module Internals = - Kf_state.Make - (struct - let name = "Internal inputs" - let dependencies = [ Value.self ] - let kind = `Correctness - end) +module Analysis = Cumulative_analysis.Make( + struct + let analysis_name ="inputs" + + type t = Locations.Zone.t + module T = Locations.Zone + let bottom = Locations.Zone.bottom -let get_internal = - Internals.memo - (fun kf -> - !Value.compute (); - match kf.fundec with - | Definition (f,_) -> - (try - Stack.iter - (fun g -> if kf == g then begin - Cil.warn - "recursive call detected during input analysis of %a. Ignoring it is safe if the value analysis suceeded without problem." - Kernel_function.pretty_name kf; - raise Ignore - end - ) - call_stack; - - (* No input to compute if the values were not computed for [kf] *) - (* if not (Value.is_accessible kf) then raise Ignore; *) - - Stack.push kf call_stack; - let computer = new do_it in - ignore (visitFramacFunction (computer:>frama_c_visitor) f); - let _ = Stack.pop call_stack in - computer#result - with Ignore -> - Zone.bottom) - | Declaration (_,_,_,_) -> - let state = Value.get_initial_state kf in - let behaviors = !Value.valid_behaviors kf state in - let assigns = Ast_info.merge_assigns behaviors in - !Value.assigns_to_zone_inputs_state state assigns) + class virtual do_it = do_it_ +end) + +let get_internal = Analysis.kernel_function module Externals = Kf_state.Make (struct let name = "External inputs" - let dependencies = [ Internals.self ] + let dependencies = [ Analysis.Memo.self ] let kind = `Correctness end) @@ -181,21 +147,21 @@ Externals.memo (fun kf -> Zone.filter_base - (Db.accept_base ~with_formals:false kf) - (get_internal kf)) + (Db.accept_base ~with_formals:false ~with_locals:false kf) + (get_internal kf)) let remove_locals_keep_formals fundec = match fundec with | Definition (fundec,_) -> Zone.filter_base - (fun v -> not (Base.is_local v fundec)) + (fun v -> not (Base.is_local v fundec)) | Declaration _ -> (fun v -> v) module With_formals = Kf_state.Make (struct let name = "Inputs with formals" - let dependencies = [ Internals.self ] + let dependencies = [ Analysis.Memo.self ] let kind = `Correctness end) @@ -203,23 +169,23 @@ Externals.memo (fun kf -> Zone.filter_base - (Db.accept_base ~with_formals:true kf) - (get_internal kf)) + (fun z -> Db.accept_base ~with_formals:true ~with_locals:false kf z) + (get_internal kf)) let compute_external kf = ignore (get_external kf) let pretty_external fmt kf = Format.fprintf fmt "@[Inputs for function %a:@\n@[ %a@]@]@\n" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Zone.pretty (get_external kf) let pretty_with_formals fmt kf = Format.fprintf fmt "@[Inputs (with formals) for function %a:@\n@[ %a@]@]@\n" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Zone.pretty (get_with_formals kf) let () = - Db.Inputs.self_internal := Internals.self; + Db.Inputs.self_internal := Analysis.Memo.self; Db.Inputs.self_external := Externals.self; Db.Inputs.self_with_formals := With_formals.self; Db.Inputs.get_internal := get_internal; @@ -228,8 +194,8 @@ Db.Inputs.compute := compute_external; Db.Inputs.display := pretty_external; Db.Inputs.display_with_formals := pretty_with_formals; - Db.Inputs.statement := statement; - Db.Inputs.expr := expr + Db.Inputs.statement := Analysis.statement; + Db.Inputs.expr := Analysis.expr (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/inout/inputs.mli frama-c-20111001+nitrogen+dfsg/src/inout/inputs.mli --- frama-c-20110201+carbon+dfsg/src/inout/inputs.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/inputs.mli 2011-10-10 08:38:23.000000000 +0000 @@ -20,6 +20,5 @@ (* *) (**************************************************************************) -val pretty_external: Format.formatter -> Db_types.kernel_function -> unit -val pretty_with_formals: Format.formatter -> Db_types.kernel_function -> unit - +val pretty_external: Format.formatter -> Cil_types.kernel_function -> unit +val pretty_with_formals: Format.formatter -> Cil_types.kernel_function -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/inout/kf_state.ml frama-c-20111001+nitrogen+dfsg/src/inout/kf_state.ml --- frama-c-20110201+carbon+dfsg/src/inout/kf_state.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/kf_state.ml 2011-10-10 08:38:23.000000000 +0000 @@ -23,7 +23,7 @@ module type S = sig type data val memo: - (Db_types.kernel_function -> data) -> Db_types.kernel_function -> data + (Cil_types.kernel_function -> data) -> Cil_types.kernel_function -> data val self: State.t end diff -Nru frama-c-20110201+carbon+dfsg/src/inout/kf_state.mli frama-c-20111001+nitrogen+dfsg/src/inout/kf_state.mli --- frama-c-20110201+carbon+dfsg/src/inout/kf_state.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/kf_state.mli 2011-10-10 08:38:23.000000000 +0000 @@ -23,7 +23,7 @@ module type S = sig type data val memo: - (Db_types.kernel_function -> data) -> Db_types.kernel_function -> data + (Cil_types.kernel_function -> data) -> Cil_types.kernel_function -> data val self: State.t end diff -Nru frama-c-20110201+carbon+dfsg/src/inout/operational_inputs.ml frama-c-20111001+nitrogen+dfsg/src/inout/operational_inputs.ml --- frama-c-20110201+carbon+dfsg/src/inout/operational_inputs.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/operational_inputs.ml 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,429 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil +open Db +open Locations +open Abstract_interp +open Abstract_value + +(* Computation of over-approximed operational inputs: + An acurate computation of these inputs needs the computation of + under-approximed outputs. +*) + +type compute_t = + { over_inputs : Zone.t ; + under_outputs : Zone.t } + +(* Initial value for the computation *) +let empty = + { + over_inputs = Zone.bottom; + under_outputs = Zone.bottom; + } + +let bottom = + { + over_inputs = Zone.bottom ; + under_outputs = Zone.top + } + +let join c1 c2 = + { over_inputs = Zone.join c1.over_inputs c2.over_inputs; + under_outputs = Zone.meet c1.under_outputs c2.under_outputs; + } + +let is_included c1 c2 = + Zone.is_included c1.over_inputs c2.over_inputs && + Zone.is_included c2.under_outputs c1.under_outputs + +let catenate c1 c2 = + { over_inputs = + Zone.join + c1.over_inputs + (Zone.diff c2.over_inputs c1.under_outputs); + under_outputs = Zone.link c1.under_outputs c2.under_outputs } + +let pretty fmt x = + Format.fprintf fmt + "@[Over-approximated operational inputs: %a@]@\n\ + @[Under-approximated operational outputs: %a@]" + Zone.pretty x.over_inputs + Zone.pretty x.under_outputs + + +let call_stack : kernel_function Stack.t = + Stack.create () + (* Stack of function being processed *) + +module Computer (REACH:sig + val stmt_can_reach : stmt -> stmt -> bool + end) = struct + let name = "InOut context" + + let debug = ref false + + let current_stmt = ref Kglobal + + let stmt_can_reach = REACH.stmt_can_reach + + let non_terminating_callees_inputs = ref Zone.bottom + + type t = compute_t + + let pretty = pretty + + module StmtStartData = + Dataflow.StartData(struct type t = compute_t let size = 107 end) + + let display_one fmt k v = + Format.fprintf fmt "Statement: %d@\n" + k; + Db.Operational_inputs.pretty fmt v + + let display fmt f = + Format.fprintf fmt "=========INOUT CONTEXT START=======@\n"; + Inthash.iter + (display_one fmt) + f; + Format.fprintf fmt "=========INOUT CONTEXT END=======@\n" + + let copy (d: t) = d + + let computeFirstPredecessor (s: stmt) data = + match s.skind with + | Switch (exp,_,_,_) + | If (exp,_,_,_) + | Return (Some exp, _) -> + let inputs = !From.find_deps_no_transitivity s exp in + {data with + over_inputs = + Zone.join data.over_inputs + (Zone.diff inputs data.under_outputs)} + | _ -> data + + let combinePredecessors (s: stmt) ~old new_ = + let new_c = computeFirstPredecessor s new_ in + let result = join new_c old in + if is_included result old + then None + else Some result + + let resolv_func_vinfo ?deps kinstr funcexp = + !Value.expr_to_kernel_function ?deps kinstr funcexp + + let doInstr stmt (i: instr) (_d: t) = + let kinstr = !current_stmt + in + let add_with_additional_var k j st = + let deps, looking_for = + !Value.lval_to_loc_with_deps + ~with_alarms:CilE.warn_none_mode + ~deps:j + kinstr + k + in + let new_inputs = + Zone.join st.over_inputs (Zone.diff deps st.under_outputs) in + let new_outputs = + if Locations.valid_cardinal_zero_or_one + ~for_writing:true + looking_for + then + (* There is only one modified zone. So, this is an exact output. + Add it into the under-approximed outputs. *) + Zone.link + st.under_outputs + (Locations.valid_enumerate_bits ~for_writing:true looking_for) + else st.under_outputs + in + { over_inputs = new_inputs; + under_outputs = new_outputs } + in + match i with + | Set (lv, exp, _) -> + Dataflow.Post + (fun state -> + let exp_inputs_deps = + !From.find_deps_no_transitivity stmt exp + in + add_with_additional_var + lv + exp_inputs_deps + state) + | Call (lvaloption,funcexp,argl,_) -> + Dataflow.Post + (fun state -> + let funcexp_inputs, called_vinfos = + resolv_func_vinfo + ~with_alarms:CilE.warn_none_mode + ~deps:Zone.bottom + kinstr + funcexp + in + let acc_funcexp_arg_inputs = + (* add the inputs of [argl] to the inputs of the + function expression *) + List.fold_right + (fun arg inputs -> + let arg_inputs = !From.find_deps_no_transitivity stmt arg + in Zone.join inputs arg_inputs) + argl + funcexp_inputs + in + let state = + catenate + state + { over_inputs = acc_funcexp_arg_inputs ; + under_outputs = Zone.bottom;} + in + let for_functions = + Kernel_function.Hptset.fold + (fun called_vinfo acc -> + let { Inout_type.over_inputs_if_termination = called_inputs_term; + under_outputs_if_termination = called_outputs ; + over_inputs = called_inputs} = + !Db.Operational_inputs.get_external called_vinfo + in + non_terminating_callees_inputs := + Zone.join + !non_terminating_callees_inputs + (Zone.diff called_inputs state.under_outputs); + let for_function = + { over_inputs = called_inputs_term; + under_outputs = called_outputs } + in + join for_function acc) + called_vinfos + bottom + in +(* Format.printf "functions: %a@." pretty for_functions; *) + let result = catenate state for_functions in + let result = + (* Treatment for the possible assignment of the call result *) + (match lvaloption with + | None -> result + | Some lv -> + add_with_additional_var + lv + Zone.bottom + result) + in result + ) + | _ -> Dataflow.Default + + let doStmt (s: stmt) (_d: t) = + current_stmt := Kstmt s; + Dataflow.SDefault + + let filterStmt (s:stmt) = + let state = Value.noassert_get_stmt_state s in + Value.is_reachable state + + let doGuard s _e _t = + current_stmt := Kstmt s; + Dataflow.GDefault, Dataflow.GDefault + + let doEdge _ _ d = d + +end + +let get_using_prototype kf = + let state = Value.get_initial_state kf in + let behaviors = !Value.valid_behaviors kf state in + let assigns = Ast_info.merge_assigns behaviors in + let inputs = + !Value.assigns_to_zone_inputs_state state assigns + in +(* Format.printf "proto inputs from assigns: %a@." + Zone.pretty over_inputs_if_termination; *) + { Inout_type.under_outputs_if_termination = + Zone.bottom ; + over_inputs_if_termination = inputs; + over_inputs = inputs + } + +let compute_internal_using_prototype kf = + match kf.fundec with + | Definition _ -> assert false + | Declaration _ -> get_using_prototype kf + +let compute_internal_using_cfg kf = + let compute_for_definition kf f = + try + let module Computer = + Computer + (struct let stmt_can_reach = Stmts_graph.stmt_can_reach kf end) + in + let module Compute = Dataflow.Forwards(Computer) in + Stack.iter + (fun g -> if kf == g then begin + if Db.Value.ignored_recursive_call kf then + Inout_parameters.warning ~current:true + "During inout context analysis of %a: ignoring probable recursive call." + Kernel_function.pretty kf; + raise Exit + end) + call_stack; + Stack.push kf call_stack; + let res_if_termination = + match f.sbody.bstmts with + [] -> assert false + | start :: _ -> + try + let ret_id = Kernel_function.find_return kf in + Computer.StmtStartData.add + start + (Computer.computeFirstPredecessor + start + empty); + Compute.compute [start]; + ignore (Stack.pop call_stack); + try Computer.StmtStartData.find ret_id with Not_found -> bottom + with Kernel_function.No_Statement-> + assert false + in + + { Inout_type.over_inputs_if_termination = res_if_termination.over_inputs; + under_outputs_if_termination = res_if_termination.under_outputs ; + over_inputs = + let acc = Computer.non_terminating_callees_inputs + in + Computer.StmtStartData.iter + (fun _sid data -> acc := Zone.join data.over_inputs !acc); + !acc} + + with Exit -> + { Inout_type.over_inputs_if_termination = empty.over_inputs ; + under_outputs_if_termination = empty.under_outputs ; + over_inputs = empty.over_inputs + } + in + match kf.fundec with + | Declaration _ -> + invalid_arg + "compute_using_cfg cannot be called on library functions" + | Definition (f, _) -> + compute_for_definition kf f + + +module Internals = + Kf_state.Context + (struct + let name = "Internal inouts" + let dependencies = [ Value.self ] + let kind = `Correctness + end) + +let get_internal = + Internals.memo + (fun kf -> + !Value.compute (); + Inout_parameters.feedback "computing for function %a%s" + Kernel_function.pretty kf + (let s = ref "" in + Stack.iter + (fun kf -> s := !s^" <-"^ + (Pretty_utils.sfprintf "%a" Kernel_function.pretty kf)) + call_stack; + !s); + let res = + match kf.fundec with + | Definition _ -> + compute_internal_using_cfg kf + | Declaration _ -> + compute_internal_using_prototype kf + in + Inout_parameters.feedback "done for function %a" + Kernel_function.pretty kf; + res) + + let externalize ~with_formals kf = + Zone.filter_base (Db.accept_base ~with_formals ~with_locals:false kf) + +let raw_get_external ~with_formals kf = + let internals = get_internal kf in + let filter = externalize ~with_formals kf in + + { Inout_type.over_inputs_if_termination = + (let r = + filter internals.Inout_type.over_inputs_if_termination + in +(* Format.printf "filtered -> %a@." Zone.pretty r; *) + r); + under_outputs_if_termination = + filter internals.Inout_type.under_outputs_if_termination; + over_inputs = filter internals.Inout_type.over_inputs } + +module Externals = + Kf_state.Context + (struct + let name = "External inouts" + let dependencies = [ Internals.self ] + let kind = `Correctness + end) +let get_external = Externals.memo (raw_get_external ~with_formals:false) +let compute_external kf = ignore (get_external kf) + +module Externals_With_Formals = + Kf_state.Context + (struct + let name = "External inouts with formals" + let dependencies = [ Internals.self ] + let kind = `Correctness + end) +let get_external_with_formals = + Externals_With_Formals.memo (raw_get_external ~with_formals:true) +let compute_external_with_formals kf = ignore (get_external_with_formals kf) + + +let pretty_internal fmt kf = + Format.fprintf fmt "@[InOut (internal) for function %a:@\n%a@]@\n" + Kernel_function.pretty kf + Db.Operational_inputs.pretty (get_internal kf) + +let pretty_external fmt kf = + Format.fprintf fmt "@[InOut for function %a:@\n%a@]@\n" + Kernel_function.pretty kf + Db.Operational_inputs.pretty (get_external kf) + +let pretty_external_with_formals fmt kf = + Format.fprintf fmt "@[InOut (with formals) for function %a:@\n%a@]@\n" + Kernel_function.pretty kf + Db.Operational_inputs.pretty (get_external_with_formals kf) + + +let () = + Db.Operational_inputs.self_internal := Internals.self; + Db.Operational_inputs.self_external := Externals.self; + Db.Operational_inputs.get_internal := get_internal; + Db.Operational_inputs.get_external := get_external; + Db.Operational_inputs.compute := compute_external; + Db.Operational_inputs.display := pretty_internal + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/inout/outputs.ml frama-c-20111001+nitrogen+dfsg/src/inout/outputs.ml --- frama-c-20110201+carbon+dfsg/src/inout/outputs.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/outputs.ml 2011-10-10 08:38:23.000000000 +0000 @@ -23,36 +23,34 @@ open Cil_types open Visitor open Db -open Db_types open Locations -let call_stack = Stack.create () -exception Ignore - -class do_it = object(self) - inherit Visitor.frama_c_inplace as super +class virtual do_it_ = object(self) + inherit [Zone.t] Cumulative_analysis.cumulative_visitor as super val mutable outs = Zone.bottom + method bottom = Zone.bottom + method result = outs method vstmt_aux s = match s.skind with - UnspecifiedSequence seq -> + | UnspecifiedSequence seq -> List.iter (fun (stmt,_,_,_,_) -> ignore(visitFramacStmt (self:>frama_c_visitor) stmt)) - seq; - Cil.SkipChildren + seq; + Cil.SkipChildren (* do not visit the additional lvals *) | _ -> super#vstmt_aux s method join new_ = outs <- Zone.join new_ outs; - method do_assign lv = + method private do_assign lv = let loc = !Value.lval_to_loc ~with_alarms:CilE.warn_none_mode - self#current_kinstr - lv + self#current_kinstr + lv in if not (Location_Bits.equal loc.loc Location_Bits.bottom) then @@ -62,117 +60,87 @@ Location_Bits.top then Inout_parameters.debug ~current:true - "Problem with %a@\nValue at this point:@\n%a" - !Ast_printer.d_lval lv - Value.pretty_state (Value.get_state self#current_kinstr) ; - let bits_loc = valid_enumerate_bits loc in + "Problem with %a@\nValue at this point:@\n%a" + !Ast_printer.d_lval lv + Value.pretty_state (Value.get_state self#current_kinstr) ; + let bits_loc = valid_enumerate_bits ~for_writing:true loc in self#join bits_loc end method vinst i = - begin match i with + if Value.is_reachable (Value.noassert_get_state self#current_kinstr) then + (* noassert needed for Eval.memoize. Not really satisfactory *) + begin + match i with | Set (lv,_,_) -> self#do_assign lv | Call (lv_opt,exp,_,_) -> (match lv_opt with None -> () | Some lv -> self#do_assign lv); let _, callees = - !Value.expr_to_kernel_function - ~with_alarms:CilE.warn_none_mode - ~deps:None - self#current_kinstr - exp - in + !Value.expr_to_kernel_function + ~with_alarms:CilE.warn_none_mode + ~deps:None + self#current_kinstr + exp + in Kernel_function.Hptset.iter - (fun kf -> self#join (!Db.Outputs.get_external kf)) callees + (fun kf -> self#join (self#compute_kf kf)) callees | _ -> () end; Cil.SkipChildren + method clean_kf_result kf r = + Zone.filter_base (Db.accept_base_internal kf) r + + method compute_funspec kf = + let state = self#specialize_state_on_call kf in + let behaviors = !Value.valid_behaviors kf state in + let assigns = Ast_info.merge_assigns behaviors in + (match assigns with + | WritesAny -> Zone.top + | Writes assigns -> + try + List.fold_left + (fun acc (loc,_) -> + let c = loc.it_content in + if (Logic_utils.is_result c) + then acc + else + let loc = + !Properties.Interp.loc_to_loc ~result:None state c + in + Zone.join acc + (Locations.valid_enumerate_bits ~for_writing:true loc)) + Zone.bottom + assigns + with Invalid_argument "not an lvalue" -> + Inout_parameters.warning ~current:true + "unsupported assigns clause for function %a; Ignoring it." + Kernel_function.pretty kf; + Zone.bottom) end -let statement stmt = - let computer = new do_it in - ignore (visitFramacStmt (computer:>frama_c_visitor) stmt); - computer#result +module Analysis = Cumulative_analysis.Make( + struct + let analysis_name ="outputs" + + type t = Locations.Zone.t + module T = Locations.Zone + let bottom = Locations.Zone.bottom -module Internals = - Kf_state.Make - (struct - let name = "Internal outs" - let dependencies = [ Value.self ] - let kind = `Correctness - end) + class virtual do_it = do_it_ +end) -let get_internal = - Internals.memo - (fun kf -> - !Value.compute (); - let result_with_spurious_locals = - match kf.fundec with - | Definition (f,_) -> - (try - Stack.iter - (fun g -> if kf == g then begin - Cil.warn - "recursive call detected during out analysis of %a. Ignoring it is safe if the value analysis suceeded without problem." - Kernel_function.pretty_name kf; - raise Ignore - end - ) - call_stack; - - (* No out to compute if the values were not computed for [kf] *) - (* if not (Value.is_accessible kf) then raise Ignore; *) - - Stack.push kf call_stack; - let computer = new do_it in - ignore (visitFramacFunction (computer:>frama_c_visitor) f); - let _ = Stack.pop call_stack in - computer#result - with Ignore -> Zone.bottom) - | Declaration (_,_,_,_) -> - let behaviors = - !Value.valid_behaviors kf (Value.get_initial_state kf) - in - let assigns = Ast_info.merge_assigns behaviors in - (match assigns with - WritesAny -> - (* [VP 2011-01-28] Should not be bottom, but top is likely to - lead to a quick degeneration. - *) - Zone.bottom - | Writes assigns -> - (try - let state = Value.get_initial_state kf in - List.fold_left - (fun acc (loc,_) -> - let c = loc.it_content in - if (Logic_utils.is_result c) - then acc - else - let loc = - !Properties.Interp.loc_to_loc ~result:None state c - in - Zone.join acc (Locations.valid_enumerate_bits loc)) - Zone.bottom - assigns - with Invalid_argument "not an lvalue" -> - Cil.warn - "unsupported assigns clause for function %a; Ignoring it." - Kernel_function.pretty_name kf; - Zone.bottom)) - in - Zone.filter_base (Db.accept_base_internal kf) result_with_spurious_locals - ) +let get_internal = Analysis.kernel_function let externalize kf x = - Zone.filter_base (Db.accept_base ~with_formals:false kf) x + Zone.filter_base (Db.accept_base ~with_formals:false ~with_locals:false kf) x module Externals = Kf_state.Make (struct let name = "External outs" - let dependencies = [ Internals.self ] + let dependencies = [ Analysis.Memo.self ] let kind = `Correctness end) @@ -182,7 +150,7 @@ let pretty_internal fmt kf = try Format.fprintf fmt "@[Out (internal) for function %a:@\n@[ %a@]@]@\n" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Zone.pretty (get_internal kf) with Not_found -> () @@ -190,20 +158,20 @@ let pretty_external fmt kf = try Format.fprintf fmt "@[Out (external) for function %a:@\n@[ %a@]@]@\n" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Zone.pretty (get_external kf) with Not_found -> () let () = - Db.Outputs.self_internal := Internals.self; + Db.Outputs.self_internal := Analysis.Memo.self; Db.Outputs.self_external := Externals.self; Db.Outputs.get_internal := get_internal; Db.Outputs.get_external := get_external; Db.Outputs.compute := (fun kf -> ignore (get_internal kf)); Db.Outputs.display := pretty_internal; Db.Outputs.display_external := pretty_external; - Db.Outputs.statement := statement + Db.Outputs.statement := Analysis.statement (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/inout/outputs.mli frama-c-20111001+nitrogen+dfsg/src/inout/outputs.mli --- frama-c-20110201+carbon+dfsg/src/inout/outputs.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/outputs.mli 2011-10-10 08:38:23.000000000 +0000 @@ -20,6 +20,5 @@ (* *) (**************************************************************************) -val pretty_external: Format.formatter -> Db_types.kernel_function -> unit -val pretty_internal: Format.formatter -> Db_types.kernel_function -> unit - +val pretty_external: Format.formatter -> Cil_types.kernel_function -> unit +val pretty_internal: Format.formatter -> Cil_types.kernel_function -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/inout/register.ml frama-c-20111001+nitrogen+dfsg/src/inout/register.ml --- frama-c-20110201+carbon+dfsg/src/inout/register.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/inout/register.ml 2011-10-10 08:38:23.000000000 +0000 @@ -20,13 +20,13 @@ (* *) (**************************************************************************) -let main _fmt = +let main _fmt = let forceout = Inout_parameters.ForceOut.get () in let forceexternalout = Inout_parameters.ForceExternalOut.get () in let forceinput = Inout_parameters.ForceInput.get () in let forceinout = Inout_parameters.ForceInout.get () in - let forceinoutwithformals = - Inout_parameters.ForceInoutExternalWithFormals.get () + let forceinoutwithformals = + Inout_parameters.ForceInoutExternalWithFormals.get () in let forcederef = Inout_parameters.ForceDeref.get () in let forceinputwithformals = Inout_parameters.ForceInputWithFormals.get () in @@ -35,28 +35,29 @@ then begin !Db.Semantic_Callgraph.topologically_iter_on_functions (fun kf -> - if Kernel_function.is_definition kf - then begin - if forceout - then Inout_parameters.result "%a" Outputs.pretty_internal kf ; - if forceexternalout - then Inout_parameters.result "%a" Outputs.pretty_external kf ; - if forceinput - then Inout_parameters.result "%a" Inputs.pretty_external kf; - if forcederef then begin - Derefs.compute_external kf; - Inout_parameters.result "%a" Derefs.pretty_external kf; - end; - if forceinout then - Inout_parameters.result "%a" Context.pretty_internal kf; - if forceinoutwithformals then - Inout_parameters.result "%a" - Context.pretty_external_with_formals kf; - if forceinputwithformals - then - Inout_parameters.result "%a" - Inputs.pretty_with_formals kf ; - end) + if Kernel_function.is_definition kf + then begin + if forceout + then Inout_parameters.result "%a" Outputs.pretty_internal kf ; + if forceexternalout + then Inout_parameters.result "%a" Outputs.pretty_external kf ; + if forceinput + then Inout_parameters.result "%a" Inputs.pretty_external kf; + if forcederef then begin + Derefs.compute_external kf; + Inout_parameters.result "%a" Derefs.pretty_external kf; + end; + if forceinout then + Inout_parameters.result "%a" + Operational_inputs.pretty_internal kf; + if forceinoutwithformals then + Inout_parameters.result "%a" + Operational_inputs.pretty_external_with_formals kf; + if forceinputwithformals + then + Inout_parameters.result "%a" + Inputs.pretty_with_formals kf ; + end) end let () = Db.Main.extend main @@ -67,4 +68,3 @@ compile-command: "make -C ../.. -j" End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/alarms.ml frama-c-20111001+nitrogen+dfsg/src/kernel/alarms.ml --- frama-c-20110201+carbon+dfsg/src/kernel/alarms.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/alarms.ml 2011-10-10 08:38:09.000000000 +0000 @@ -23,25 +23,13 @@ open Cil_types open Cil -type t = - | Division_alarm - | Memory_alarm - | Index_alarm - | Shift_alarm - | Pointer_compare_alarm - | Signed_overflow_alarm - | Using_nan_or_infinite_alarm - | Result_is_nan_or_infinite_alarm - | Separation_alarm - | Other_alarm - let pretty fmt al = Format.fprintf fmt "alarm caused by %s" (match al with | Division_alarm -> "a division" | Memory_alarm -> "a memory access" | Index_alarm -> "a memory access" (* TODO: separate a day when - the oracles are working *) + the oracles are working *) | Shift_alarm -> "a shift" | Signed_overflow_alarm -> "an overflow in signed integer arithmetic" | Pointer_compare_alarm -> "a pointer comparison" @@ -51,27 +39,30 @@ "incompatible accesses to the same zone in unspecified order" | Other_alarm -> "a safety concern") -type alarm = t * code_annotation * annot_status +type alarm = Cil_types.alarm * code_annotation module Alarm_datatype = Datatype.Make (struct + open Cil_datatype include Datatype.Serializable_undefined type t = alarm let name = "Alarms.Alarm_datatype" - let reprs = - List.map - (fun c -> Other_alarm, c, { status = Unknown }) - Cil_datatype.Code_annotation.reprs - let compare (a,l,_ : alarm) (a',l',_) = - let ca = Extlib.compare_basic a a' in + let reprs = List.map (fun c -> Other_alarm, c) Code_annotation.reprs + + (* this [compare] is very inefficient. Don't use it often. *) + let compare (a,l : alarm) (a',l') = + let ca = Alarm.compare a a' in if ca <> 0 then ca - (* Do not use Cil_datatype.Code_annotation.compare because we want - to compare the content of the annotation themselves, not the ids - (to avoid duplicating annotations) *) - else Pervasives.compare l.annot_content l'.annot_content + else + (* Do not use Cil_datatype.Code_annotation.compare because we want + to compare the content of the annotation themselves, not the ids + (to avoid duplicating annotations) + [JS 2011/06/15] Ok do not use it, but neither Pervasives.compare *) + Datatype.String.compare + (Marshal.to_string l.annot_content []) + (Marshal.to_string l'.annot_content []) let equal = Datatype.from_compare - let copy = Datatype.identity let mem_project = Datatype.never_any_project end) @@ -86,32 +77,38 @@ (Alarm_set) (struct let name = "alarms" - let dependencies = [] (* delayed in Ast *) + let dependencies = [ Ast.self ] let size = 7 let kind = `Internal end) let self = Alarms.self -let register ki to_add = +let register ~deps ki (atyp, annot as to_add) ?(status=Property_status.Dont_know) emitter = + let add old = + Alarms.replace ki (Alarm_set.add to_add old); + match ki with + | Kglobal -> + (* [JS 2011/07/05] where should the annotation be added? *) + Kernel.warning ~once:true ~current:true + "global alarm occured. Check the log below." + | Kstmt s -> + let kf = Kernel_function.find_englobing_kf s in + Annotations.add kf s deps (AI (atyp, annot)); + let p = Property.ip_of_code_annot kf s annot in + List.iter + (fun p -> Property_status.emit emitter ~hyps:[] p ~distinct:true status) + p + in try let old = Alarms.find ki in if Alarm_set.mem to_add old then false - else (Alarms.add ki (Alarm_set.add to_add old); - (*(match ki with - |Cil_types.Kstmt k -> - Format.eprintf "Got Id:%d@." k.Cil_types.sid - | _ -> Format.eprintf "Got GLOB@." - );*) - true) - + else begin + add old; + true + end with Not_found -> - (*(match ki with - |Cil_types.Kstmt k -> - Format.eprintf "Got Id:%d@." k.Cil_types.sid - | _ -> Format.eprintf "Got GLOB@." - );*) - Alarms.add ki (Alarm_set.singleton to_add); + add Alarm_set.empty; true let clear () = Alarms.clear () diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/alarms.mli frama-c-20111001+nitrogen+dfsg/src/kernel/alarms.mli --- frama-c-20110201+carbon+dfsg/src/kernel/alarms.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/alarms.mli 2011-10-10 08:38:09.000000000 +0000 @@ -20,36 +20,41 @@ (* *) (**************************************************************************) -(** Alarm Database. +(** Alarms Database for the value analysis. @plugin development guide *) -type t = - | Division_alarm - | Memory_alarm - | Index_alarm - | Shift_alarm - | Pointer_compare_alarm - | Signed_overflow_alarm - | Using_nan_or_infinite_alarm - | Result_is_nan_or_infinite_alarm - | Separation_alarm - | Other_alarm +(** Warning: the interface of this module will probably radically change soon. + Do not use it on stable code *) -type alarm = t * Cil_types.code_annotation * Cil_types.annot_status +open Cil_types + +type alarm = Cil_types.alarm * code_annotation module Alarm_datatype: Datatype.S with type t = alarm +(* [compare] and [equal] in this datatype are very inefficient. Don't use it + often. *) + +val pretty : Format.formatter -> Cil_types.alarm -> unit -val pretty : Format.formatter -> t -> unit -val register: Cil_types.kinstr -> alarm -> bool +(** Register the given alarm on the given statement. By default, + the alarm is emitted with status [Dont_know], and by the given emitter. + Return true if the given alarm has never been emitted before on the + same kinstr (without taking into consideration the status or + the emitter) *) +val register: + deps:State.t list -> + kinstr -> + alarm -> + ?status:Property_status.emitted_status -> + Emitter.t -> + bool val clear: unit -> unit -val iter: (Cil_types.kinstr -> alarm -> unit) -> unit +val iter: (kinstr -> alarm -> unit) -> unit -val fold: - (Cil_types.kinstr -> alarm -> 'a -> 'a) -> 'a -> 'a +val fold: (kinstr -> alarm -> 'a -> 'a) -> 'a -> 'a -val fold_kinstr: - Cil_types.kinstr -> (alarm -> 'a -> 'a) -> 'a -> 'a +val fold_kinstr: kinstr -> (alarm -> 'a -> 'a) -> 'a -> 'a val self: State.t diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/annotations.ml frama-c-20111001+nitrogen+dfsg/src/kernel/annotations.ml --- frama-c-20110201+carbon+dfsg/src/kernel/annotations.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/annotations.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,18 +22,18 @@ open Extlib open Cil_types -open Db_types open Cil -let get_code_annotation = function - | Before (User ca) | After (User ca) - | Before (AI (_,ca)) | After(AI(_,ca)) -> ca +let get_code_annotation = function | User ca | AI (_,ca) -> ca + +let get_annot_properties kf stmt a = + Property.ip_of_code_annot kf stmt (get_code_annotation a) module AnnotState = State_builder.Dashtbl (Dashtbl.Default_key_marshaler(Cil_datatype.Stmt)) (Dashtbl.Default_data_marshaler - (Kernel_datatype.Rooted_code_annotation_before_after)) + (Cil_datatype.Rooted_code_annotation)) (struct let name = "Annotations" let size = 17 @@ -42,29 +42,25 @@ let internal_kind = `Correctness end) +let () = + State_dependency_graph.Static.add_dependencies + ~from:AnnotState.self + [ Property_status.self ] + let get_name a = - let old = Parameters.UseUnicode.get () in - Parameters.UseUnicode.set false; - let s = - Pretty_utils.sfprintf - "%a" !Ast_printer.d_rooted_code_annotation_before_after a - in - Parameters.UseUnicode.set old; - s + Kernel.Unicode.without_unicode + (Pretty_utils.sfprintf "%a" !Ast_printer.d_rooted_code_annotation) a -let add stmt states a = AnnotState.add (get_name a) stmt states a +let add kf stmt states a = +(* Kernel.feedback "registering code annotation %a" + !Ast_printer.d_rooted_code_annotation a;*) + let p = get_annot_properties kf stmt a in + List.iter Property_status.register p; + AnnotState.add (get_name a) stmt states a -let add_assert stmt states ~before a = +let add_assert kf stmt states a = let a = User (Logic_const.new_code_annotation (AAssert ([],a))) in - add stmt states (if before then Before a else After a) - -let add_alarm stmt states ~before alarm a = - let a = AI (alarm, Logic_const.new_code_annotation (AAssert ([], a))) in - add stmt states (if before then Before a else After a) - -let reset_stmt = AnnotState.remove_all -let replace ~reset stmt states a = - AnnotState.replace (get_name a) ~reset stmt states a + add kf stmt states a let get = AnnotState.find_all_local let get_annotations = AnnotState.find_all_local_data @@ -80,6 +76,15 @@ let get_filter f stmt = List.filter (f $ get_code_annotation) (get_all_annotations stmt) +let reset_stmt ~reset kf stmt = + (* Kernel.feedback "reset stmt"; *) + List.iter + (fun a -> + let l = get_annot_properties kf stmt a in + List.iter Property_status.remove l) + (get_all_annotations stmt); + AnnotState.remove_all ~reset stmt + let iter = AnnotState.iter let iter_stmt = AnnotState.iter_key let single_iter_stmt f s = List.iter f (get_all_annotations s) @@ -88,7 +93,31 @@ let single_fold_stmt f s acc = List.fold_left (fun acc a -> f a acc) acc (get_all_annotations s) -let filter = AnnotState.filter +let filter ~reset f kf stmt = + let f stmt s a = + let keep = f stmt s a in + if not keep then begin + let l = get_annot_properties kf stmt a in + List.iter Property_status.remove l + end; + keep + in + AnnotState.filter ~reset f stmt + +let set_annot ?(reset=true) kf stmt states f = + let l = + single_fold_stmt + (fun a l -> + let old = get_annot_properties kf stmt a in + let a = f a in + let ppts = get_annot_properties kf stmt a in + Property_status.merge ~old ppts; + a :: l) + stmt + [] + in + AnnotState.remove_all ~reset stmt; + List.iter (fun a -> AnnotState.add (get_name a) stmt states a) l let self = AnnotState.self diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/annotations.mli frama-c-20111001+nitrogen+dfsg/src/kernel/annotations.mli --- frama-c-20110201+carbon+dfsg/src/kernel/annotations.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/annotations.mli 2011-10-10 08:38:09.000000000 +0000 @@ -25,40 +25,37 @@ @plugin development guide *) open Cil_types -open Db_types -val get_code_annotation: - rooted_code_annotation before_after -> code_annotation +val get_code_annotation: rooted_code_annotation -> code_annotation (** extract the undecorated [code_annotation] from an annotation. *) (* TODO: why a list here? *) -val add: stmt -> State.t list -> rooted_code_annotation before_after -> unit +val add: + kernel_function -> stmt -> State.t list -> rooted_code_annotation -> unit (** Associate one more annotation with the given stmt. The list is the states required for computing this binding. See {!State_builder.DASHTBL_OUTPUT.add} for details. + @modify Nitrogen-20111001 @modify Boron-20100401 *) -val add_assert: stmt -> State.t list -> before:bool -> predicate named -> unit +val add_assert: + kernel_function -> stmt -> State.t list -> predicate named -> unit (** Associate one more assertion annotation with the given stmt. The list is the states required for computing this binding. @modify Boron-20100401 + @modify Nitrogen-20111001 Argument [before] suppressed: it is always + before @plugin development guide *) -val add_alarm: - stmt -> State.t list -> before:bool -> Alarms.t -> predicate named -> unit - (** Associate one more alarm annotation with the given stmt. - The list is the states required for computing this binding. - @modify Boron-20100401 *) - -val replace: - reset:bool -> stmt -> State.t list -> rooted_code_annotation before_after -> +val set_annot: + ?reset:bool -> kernel_function -> stmt -> State.t list -> + (rooted_code_annotation -> rooted_code_annotation) -> unit - (** Associate the given annotation with the given stmt. - Previous annotations of this stmt disappear. - The list is the states required for computing this binding. - @modify Boron-20100401 *) +(** [replace ~reset kf stmt f] applies [f] on each annotation [a] associated + to the given [stmt] of [kf] in order to replace it by [f a]. + @since Nitrogen-20111001 *) -val reset_stmt: reset:bool -> stmt -> unit +val reset_stmt: reset:bool -> kernel_function -> stmt -> unit (** Erase all the annotations associated to the given stmt. [reset] is [true] iff all the dependencies of all the bindings of this statement must be cleared. @@ -66,83 +63,83 @@ val get: ?who: State.t list -> stmt -> State.t -> - (rooted_code_annotation before_after * State.t) list + (rooted_code_annotation * State.t) list (** Return all the bindings associated with the stmt and state. - See {!State_builder.DASHTBL_OUTPUT.find_all_local} for details. - @since Boron-20100401 *) + See {!State_builder.DASHTBL_OUTPUT.find_all_local} for details. + @since Boron-20100401 *) val get_annotations: ?who: State.t list -> stmt -> State.t -> - rooted_code_annotation before_after list + rooted_code_annotation list (** Return all the annotations associated with the stmt and state. - @since Boron-20100401 *) + @since Boron-20100401 *) val get_all: ?who: State.t list -> stmt -> - (rooted_code_annotation before_after * State.t) list + (rooted_code_annotation * State.t) list (** Return all the bindings associated with the stmt. - @modify Boron-20100401 *) + @modify Boron-20100401 *) val get_all_annotations: ?who: State.t list -> stmt -> - rooted_code_annotation before_after list + rooted_code_annotation list (** Return all the annotations associated with the stmt. - since Boron-20100401 *) + since Boron-20100401 *) val get_by_state: - stmt -> (State.t * rooted_code_annotation before_after list) list + stmt -> (State.t * rooted_code_annotation list) list (** Return all the annotations associated with the stmt - and sorted by states. - @since Boron-20100401 *) + and sorted by states. + @since Boron-20100401 *) val get_filter: - (code_annotation -> bool) -> stmt -> rooted_code_annotation before_after list + (code_annotation -> bool) -> stmt -> rooted_code_annotation list (** Returns all the annotation associated with the stmt that respects the given condition. Use it in conjunction with Logic_utils.is_* to retrieve a particular kind of annotations. *) val iter_stmt: - (State.t option -> rooted_code_annotation before_after * State.t -> unit) -> + (State.t option -> rooted_code_annotation * State.t -> unit) -> stmt -> unit (** Iterator on each bindings of the given statement. @since Boron-20100401 *) val single_iter_stmt: - (rooted_code_annotation before_after -> unit) -> stmt -> unit + (rooted_code_annotation -> unit) -> stmt -> unit (** Iterator on each annotations of the given statement. Multiple bindings are only applied once. @since Boron-20100401 *) val fold_stmt: - (State.t option -> rooted_code_annotation before_after * State.t -> 'a -> 'a) + (State.t option -> rooted_code_annotation * State.t -> 'a -> 'a) -> stmt -> 'a -> 'a (** Folder on each bindings of the given statement @since Boron-20100401 *) val single_fold_stmt: - (rooted_code_annotation before_after -> 'a -> 'a) -> stmt -> 'a -> 'a + (rooted_code_annotation -> 'a -> 'a) -> stmt -> 'a -> 'a (** Folder on each annotations of the given statement. Multiple bindings are only applied once. @since Boron-20100401 *) val iter: (stmt -> State.t option -> - rooted_code_annotation before_after * State.t -> unit) + rooted_code_annotation * State.t -> unit) -> unit (** Iterator on each bindings. @since Boron-20100401 *) val fold: (stmt -> State.t option -> - rooted_code_annotation before_after * State.t -> 'a -> 'a) + rooted_code_annotation * State.t -> 'a -> 'a) -> 'a -> 'a (** Folder on each bindings. @since Boron-20100401 *) val filter: reset:bool -> - (stmt -> State.t option -> rooted_code_annotation before_after -> bool) -> - stmt -> unit + (stmt -> State.t option -> rooted_code_annotation -> bool) -> + kernel_function -> stmt -> unit (** Filter the bindings associated to the given statement. See {!State_builder.DASHTBL_OUTPUT.filter} for details. @since Boron-20100401 *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/ast_info.ml frama-c-20111001+nitrogen+dfsg/src/kernel/ast_info.ml --- frama-c-20110201+carbon+dfsg/src/kernel/ast_info.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/ast_info.ml 2011-10-10 08:38:09.000000000 +0000 @@ -20,13 +20,10 @@ (* *) (**************************************************************************) -open Db_types open Cil_types open Cilutil open Cil -let pretty_vname fmt vi = !Ast_printer.d_ident fmt vi.vname - (* ************************************************************************** *) (** {2 Expressions} *) (* ************************************************************************** *) @@ -38,7 +35,7 @@ let rec possible_value_of_integral_const = function | CInt64 (i,_,_) -> Some i | CEnum {eival = e} -> possible_value_of_integral_expr e - | CChr c -> Some (Int64.of_int (Char.code c)) + | CChr c -> Some (My_bigint.of_int (Char.code c)) | _ -> None and possible_value_of_integral_expr e = @@ -60,13 +57,13 @@ let rec is_null_expr e = match (stripInfo e).enode with | Const c when is_integral_const c -> - value_of_integral_const c = Int64.zero + My_bigint.equal (value_of_integral_const c) My_bigint.zero | CastE(_,e) -> is_null_expr e | _ -> false let rec is_non_null_expr e = match (stripInfo e).enode with | Const c when is_integral_const c -> - value_of_integral_const c <> Int64.zero + not (My_bigint.equal (value_of_integral_const c) My_bigint.zero) | CastE(_,e) -> is_non_null_expr e | _ -> false @@ -84,11 +81,11 @@ ignore (Cil.visitCilTerm (object - inherit nopCilVisitor - method vterm_lval lv = - l := lv :: !l; - DoChildren - end) + inherit nopCilVisitor + method vterm_lval lv = + l := lv :: !l; + DoChildren + end) t); !l @@ -109,11 +106,11 @@ let is_trivial_rooted_assertion = function | User ca | AI(_, ca) -> is_trivial_annotation ca.annot_content +let behavior_assumes b = + Logic_const.pands (List.map Logic_const.pred_of_id_pred b.b_assumes) + let behavior_postcondition b k = - let assumes = - Logic_const.pold - (Logic_const.pands (List.map Logic_const.pred_of_id_pred b.b_assumes)) - in + let assumes = Logic_const.pold (behavior_assumes b) in let postcondition = Logic_const.pands (Extlib.filter_map (fun (x,_) -> x = k) @@ -122,28 +119,83 @@ Logic_const.pimplies (assumes,postcondition) let behavior_precondition b = - let assumes = Logic_const.pands (List.rev_map Logic_const.pred_of_id_pred b.b_assumes) - in - let requires =Logic_const.pands (List.rev_map Logic_const.pred_of_id_pred b.b_requires) + let assumes = behavior_assumes b in + let requires = Logic_const.pands + (List.rev_map Logic_const.pred_of_id_pred b.b_requires) in Logic_const.pimplies (assumes,requires) let precondition spec = Logic_const.pands (List.map behavior_precondition spec.spec_behavior) +(** find the behavior named [name] in the list *) +let get_named_bhv bhv_list name = + try Some (List.find (fun b -> b.b_name = name) bhv_list) + with Not_found -> None + +let get_behavior_names ~with_default spec = + let rec get_bhv_names lb = match lb with [] -> [] + | b::tlb -> + if Cil.is_default_behavior b + then (* do it later*) get_bhv_names tlb + else (b.b_name)::(get_bhv_names tlb) + in + let named_bhv = get_bhv_names spec.spec_behavior in + if with_default then Cil.default_behavior_name::named_bhv else named_bhv + +let get_named_bhv_assumes spec bhv_names = + let bhvs = match bhv_names with + | [] -> (* no names ==> all named behaviors *) + List.filter (fun b -> not (is_default_behavior b)) spec.spec_behavior + | _ -> + let rec get l = match l with [] -> [] + | name::tl -> + match get_named_bhv spec.spec_behavior name with + | None -> (* TODO: warn ? *) get tl + | Some b -> b::(get tl) + in + get bhv_names + in + List.map behavior_assumes bhvs + +let complete_behaviors spec bhv_names = + let bhv_assumes = get_named_bhv_assumes spec bhv_names in + Logic_const.pors bhv_assumes + +let disjoint_behaviors spec bhv_names = + let bhv_assumes = get_named_bhv_assumes spec bhv_names in + let mk_disj_bhv b1 b2 = (* ~ (b1 /\ b2) *) + let p = Logic_const.pands [b1; b2] in + Logic_const.pnot p + in + let do_one_with_list prop b lb = + let lp = List.map (mk_disj_bhv b) lb in + Logic_const.pands (prop::lp) + in + let rec do_list prop l = match l with [] -> prop + | b::tl -> + let prop = do_one_with_list prop b tl in + do_list prop tl + in + do_list Logic_const.ptrue bhv_assumes + let merge_assigns (l : funbehavior list) = let unguarded_behaviors = List.filter (fun l -> l.b_assumes = []) l in match unguarded_behaviors with | [] -> (* No unguarded behavior -> assigns evything *) WritesAny | l -> (* Let's check if there is an "assigns everything" *) - if List.exists (fun b -> b.b_assigns=WritesAny) l then WritesAny - else match l with - | [{b_assigns=r}] -> r - | {b_name=n;b_assigns=r}::_ -> - Cil.warn "keeping only assigns of behavior %s" n; - r - | [] -> assert false + if List.exists (fun b -> b.b_assigns=WritesAny) l then WritesAny + else match l with + | [] -> assert false + | [{b_assigns=r}] -> r + | {b_name=n;b_assigns=r}::q -> + (* Let's check if by chance all behaviors are in fact the same, + which occurs often with the current modus operandi of the kernel *) + if List.exists (fun b' -> b'.b_assigns != r) q then + Kernel.warning ~once:true ~current:true + "keeping only assigns of behavior %s" n; + r (* List.fold_left (fun a b -> Logic_utils.merge_assigns a b.b_assigns) [] l *) @@ -165,7 +217,7 @@ let rec is_null_term t = match t.term_node with | TConst c when is_integral_const c -> - value_of_integral_const c = Int64.zero + My_bigint.equal (value_of_integral_const c) My_bigint.zero | TCastE(_,t) -> is_null_term t | _ -> false @@ -184,13 +236,11 @@ (** {2 Annotations} *) (* ************************************************************************** *) -let before_after_content = function Before x | After x -> x - -let lift_annot_func f a = match before_after_content a with +let lift_annot_func f a = match a with | User p | AI (_,p) -> f p let lift_annot_list_func f l = - let add l x = match before_after_content x with + let add l x = match x with | User p | AI(_,p) -> p :: l in let l' = List.fold_left add [] l in @@ -222,9 +272,9 @@ let formal_args called_vinfo = match called_vinfo.vtype with | TFun (_,Some argl,_,_) -> - argl + argl | TFun _ -> - [] + [] | _ -> assert false let is_formal v fundec = @@ -261,16 +311,16 @@ let direct_array_size ty = match unrollType ty with | TArray(_ty,Some size,_,_) -> value_of_integral_expr size - | TArray(_ty,None,_,_) -> 0L + | TArray(_ty,None,_,_) -> My_bigint.zero | _ -> assert false let rec array_size ty = match unrollType ty with | TArray(elemty,Some _,_,_) -> - if isArrayType elemty then - Int64.mul (direct_array_size ty) (array_size elemty) - else direct_array_size ty - | TArray(_,None,_,_) -> 0L + if isArrayType elemty then + My_bigint.mul (direct_array_size ty) (array_size elemty) + else direct_array_size ty + | TArray(_,None,_,_) -> My_bigint.zero | _ -> assert false let direct_element_type ty = match unrollType ty with @@ -300,20 +350,31 @@ (** {2 Predefined} *) (* ************************************************************************** *) -let is_cea_function name = +let can_be_cea_function name = (String.length name >= 4 && - name.[0] = 'C' && name.[1] = 'E' && - name.[2] = 'A' && name.[3] = '_') || - ((String.length name >= 17) && - ( (String.sub name 0 17) = "Frama_C_show_each")) + name.[0] = 'C' && name.[1] = 'E' && name.[2] = 'A' && name.[3] = '_') + || + (String.length name >= 6 && + name.[0] = 'F' && name.[1] = 'r' && name.[2] = 'a' && + name.[3] = 'm' && name.[4] = 'a' && name.[5] = '_') + +let is_cea_function name = + (String.length name >= 4 && (String.sub name 0 4 = "CEA_" )) || + (String.length name >= 17 && (String.sub name 0 17 = "Frama_C_show_each" )) let is_cea_alloc_with_validity name = name = "Frama_C_alloc_size" let is_cea_dump_function name = name = "CEA_DUMP" || name = "Frama_C_dump_each" +let is_cea_dump_file_function name = + (String.length name >= 22 && + (String.sub name 0 22 = "Frama_C_dump_each_file" )) + let is_frama_c_builtin n = - is_cea_dump_function n || - is_cea_function n || - is_cea_alloc_with_validity n + can_be_cea_function n && + (is_cea_dump_function n || + is_cea_function n || + is_cea_alloc_with_validity n || + is_cea_dump_file_function n) let () = Cil.add_special_builtin_family is_frama_c_builtin diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/ast_info.mli frama-c-20111001+nitrogen+dfsg/src/kernel/ast_info.mli --- frama-c-20110201+carbon+dfsg/src/kernel/ast_info.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/ast_info.mli 2011-10-10 08:38:09.000000000 +0000 @@ -24,24 +24,18 @@ @plugin development guide *) open Cil_types -open Db_types - -val pretty_vname: Format.formatter -> Cil_types.varinfo -> unit (* ************************************************************************** *) (** {2 Annotations} *) (* ************************************************************************** *) -val before_after_content: 'a before_after -> 'a - val lift_annot_func: - (code_annotation -> 'a) -> rooted_code_annotation before_after -> 'a + (code_annotation -> 'a) -> rooted_code_annotation -> 'a (** lifts a function that operates on code_annotation up to the annotations used in Db. *) val lift_annot_list_func: - (code_annotation list -> 'a) -> - rooted_code_annotation before_after list -> 'a + (code_annotation list -> 'a) -> rooted_code_annotation list -> 'a (** lifts a function taking lists of code_annotation up to the annotations lists in Db. Ignores WP annotations. *) @@ -50,11 +44,11 @@ (* ************************************************************************** *) val is_integral_const: constant -> bool -val possible_value_of_integral_const: constant -> int64 option -val possible_value_of_integral_expr: exp -> int64 option -val value_of_integral_const: constant -> int64 -val value_of_integral_expr: exp -> int64 -val constant_expr: loc:location -> int64 -> exp +val possible_value_of_integral_const: constant -> My_bigint.t option +val possible_value_of_integral_expr: exp -> My_bigint.t option +val value_of_integral_const: constant -> My_bigint.t +val value_of_integral_expr: exp -> My_bigint.t +val constant_expr: loc:location -> My_bigint.t -> exp val is_null_expr: exp -> bool val is_non_null_expr: exp -> bool @@ -62,20 +56,24 @@ (** {2 Logical terms} *) (* ************************************************************************** *) -val possible_value_of_integral_term: term -> int64 option +val possible_value_of_integral_term: term -> My_bigint.t option val term_lvals_of_term: term -> term_lval list (** Return the list of all the term lvals of a given term. Purely syntactic function. *) val is_trivial_predicate: predicate -> bool -val is_trivial_rooted_assertion: Db_types.rooted_code_annotation -> bool +val is_trivial_rooted_assertion: rooted_code_annotation -> bool val is_trivial_named_predicate: predicate named -> bool val precondition : funspec -> predicate named (** @since Carbon-20101201 Builds the precondition from [b_assumes] and [b_requires] clauses. *) +val behavior_assumes : funbehavior -> predicate named + (** @since Nitrogen-20111001 + Builds the conjonction of the [b_assumes] *) + val behavior_precondition : funbehavior -> predicate named (** @since Carbon-20101201 Builds the precondition from [b_assumes] and [b_requires] clauses. *) @@ -84,11 +82,19 @@ (** @modify Boron-20100401 added termination kind as filtering argument. Builds the postcondition from [b_assumes] and [b_post_cond] clauses. *) +val disjoint_behaviors : funspec -> string list -> predicate named + (** @since Nitrogen-20111001 + Builds the [disjoint_behaviors] property for the behavior names *) + +val complete_behaviors : funspec -> string list -> predicate named + (** @since Nitrogen-20111001 + Builds the [disjoint_behaviors] property for the behavior names *) + val merge_assigns: funbehavior list -> identified_term assigns (** Returns the assigns of an unguarded behavior. *) val variable_term: location -> logic_var -> term -val constant_term: location -> int64 -> term +val constant_term: location -> My_bigint.t -> term val is_null_term: term -> bool (* ************************************************************************** *) @@ -116,8 +122,8 @@ val array_type: ?length:exp -> ?attr:attributes -> typ -> typ -val direct_array_size: typ -> int64 -val array_size: typ -> int64 +val direct_array_size: typ -> My_bigint.t +val array_size: typ -> My_bigint.t val direct_element_type: typ -> typ val element_type: typ -> typ val direct_pointed_type: typ -> typ @@ -134,7 +140,7 @@ module Function: sig val formal_args: varinfo -> (string * typ * attributes) list (** Returns the list of the named formal arguments of a function. - Never call on a variable of non functional type.*) + Never call on a variable of non functional type.*) val is_formal: varinfo -> fundec -> bool val is_local: varinfo -> fundec -> bool @@ -142,7 +148,7 @@ val is_formal_of_prototype: varinfo (* to check *) -> varinfo (* of the prototype *) -> bool (** [is_formal_of_prototype v f] returns [true] iff [f] is a prototype and - [v] is one of its formal parameters. *) + [v] is one of its formal parameters. *) val is_definition: cil_function -> bool val get_vi: cil_function -> varinfo @@ -154,11 +160,15 @@ (** {2 Predefined} *) (* ************************************************************************** *) +val can_be_cea_function : string -> bool val is_cea_function : string -> bool val is_cea_dump_function : string -> bool val is_cea_alloc_with_validity : string -> bool +val is_cea_dump_function : string -> bool +val is_cea_dump_file_function : string -> bool val is_frama_c_builtin : string -> bool + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/ast.ml frama-c-20111001+nitrogen+dfsg/src/kernel/ast.ml --- frama-c-20110201+carbon+dfsg/src/kernel/ast.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/ast.ml 2011-10-10 08:38:09.000000000 +0000 @@ -28,13 +28,14 @@ (struct let name = "AST" let dependencies = - [ Cil.selfMachine; - Parameters.SimplifyCfg.self; - Parameters.KeepSwitch.self; - Parameters.UnrollingLevel.self; - Parameters.Constfold.self; - Parameters.ReadAnnot.self; - Parameters.PreprocessAnnot.self; + [ Cil.selfMachine; + Kernel.SimplifyCfg.self; + Kernel.KeepSwitch.self; + Kernel.UnrollingLevel.self; + Kernel.Constfold.self; + Kernel.ReadAnnot.self; + Kernel.PreprocessAnnot.self; + Kernel.Files.self; Cil.selfFormalsDecl; ] let kind = `Internal @@ -44,13 +45,17 @@ let () = State_dependency_graph.Static.add_dependencies - ~from:self [ Cil.selfFormalsDecl; Alarms.self; Messages.self ]; + ~from:self [ Cil_datatype.Stmt.Hptset.self; + Cil_datatype.Varinfo.Hptset.self ]; + Cil.register_ast_dependencies self; Logic_env.init_dependencies self; -exception Bad_Initialisation of string +exception Bad_Initialization of string + +exception NoUntypedAst let default_initialization = - ref (fun () -> raise (Bad_Initialisation "Cil file not initialized")) + ref (fun () -> raise (Bad_Initialization "Cil file not initialized")) let set_default_initialization f = default_initialization := f @@ -68,23 +73,27 @@ let set_file file = let change old_file = if old_file == file then old_file - else raise (Bad_Initialisation "Too many initializations of the AST") + else raise (Bad_Initialization "Too many AST initializations") in ignore (memo ~change (fun () -> mark_as_computed (); file)) module UntypedFiles = struct + let compute_untyped () = + if not (is_computed()) then ignore (force_compute()) + else raise NoUntypedAst + include State_builder.Option_ref (Initial_datatype.List(Cil_datatype.Cabs_file)) (struct let name = "Untyped AST" let dependencies = (* the others delayed until file.ml *) - [ Cil.selfMachine; - self (* can't be computed without the AST *) ] + [ Cil.selfMachine; + self (* can't be computed without the AST *) ] let kind = `Internal end) - let get () = memo (fun () -> ignore (force_compute ()); get ()) + let get () = memo (fun () -> compute_untyped (); get ()) end diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/ast.mli frama-c-20111001+nitrogen+dfsg/src/kernel/ast.mli --- frama-c-20110201+carbon+dfsg/src/kernel/ast.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/ast.mli 2011-10-10 08:38:09.000000000 +0000 @@ -20,19 +20,29 @@ (* *) (**************************************************************************) -(** Access to the Cil AST which must be used from Frama-C. +(** Access to the CIL AST which must be used from Frama-C. @plugin development guide *) -exception Bad_Initialisation of string +exception Bad_Initialization of string (** May be raised by function {!get} below. *) +exception NoUntypedAst + (** Might be raised by {!UntypedFiles.get} below + @since Nitrogen-20111001 + *) + module UntypedFiles: sig val get: unit -> Cabs.file list (** The list of untyped AST that have been parsed. - @raise Bad_Initialization if neither {!File.init_from_c_files} - nor {!File.init_project_from_cil_file} nor {!File.init_from_cmdline} - was called before. *) + @raise Bad_Initialization if neither {!File.init_from_c_files} + nor {!File.init_project_from_cil_file} nor {!File.init_from_cmdline} + was called before. + @raise NoUntypedAst if no untyped AST is available. This is in + particular the case for projects obtained by code transformation from + original C files. + @modify Nitrogen-20111001 raise NoUntypedAst + *) val set: Cabs.file list -> unit (** Should not be used by casual users. *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/ast_printer.ml frama-c-20111001+nitrogen+dfsg/src/kernel/ast_printer.ml --- frama-c-20110201+carbon+dfsg/src/kernel/ast_printer.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/ast_printer.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,6 +22,7 @@ let d_ident = ref Format.pp_print_string let d_binop = ref Cil.d_binop +let d_relation = ref Cil.d_relation let d_exp = ref Cil.d_exp let d_var = ref Cil.d_var let d_lval = ref Cil.d_lval @@ -46,13 +47,11 @@ let d_predicate_named = ref Cil.d_predicate_named let d_code_annotation = ref Cil.d_code_annotation -let d_rooted_code_annotation_before_after = - ref (fun fmt a -> - match a with - | Db_types.Before p | Db_types.After p -> - match p with - | Db_types.User p - | Db_types.AI (_,p) -> Cil.d_code_annotation fmt p) +let d_rooted_code_annotation = + ref + (fun fmt p -> match p with + | Cil_types.User p + | Cil_types.AI (_,p) -> Cil.d_code_annotation fmt p) let d_funspec = ref Cil.d_funspec let d_annotation = ref Cil.d_annotation diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/ast_printer.mli frama-c-20111001+nitrogen+dfsg/src/kernel/ast_printer.mli --- frama-c-20110201+carbon+dfsg/src/kernel/ast_printer.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/ast_printer.mli 2011-10-10 08:38:09.000000000 +0000 @@ -29,6 +29,9 @@ (** Pretty prints a binary operator *) val d_binop: (Format.formatter -> binop -> unit) ref +(** Pretty prints a binary relation *) +val d_relation: (Format.formatter -> relation -> unit) ref + (** Pretty prints an identifier *) val d_ident: (Format.formatter -> string -> unit) ref @@ -86,9 +89,8 @@ val d_predicate_named: (Format.formatter -> predicate named -> unit) ref val d_code_annotation: (Format.formatter -> code_annotation -> unit) ref -val d_rooted_code_annotation_before_after: - (Format.formatter -> Db_types.rooted_code_annotation Db_types.before_after -> - unit) ref +val d_rooted_code_annotation: + (Format.formatter -> rooted_code_annotation -> unit) ref val d_funspec: (Format.formatter -> funspec -> unit) ref val d_annotation: (Format.formatter -> global_annotation -> unit) ref diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/boot.ml frama-c-20111001+nitrogen+dfsg/src/kernel/boot.ml --- frama-c-20110201+carbon+dfsg/src/kernel/boot.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/boot.ml 2011-10-10 08:38:09.000000000 +0000 @@ -24,18 +24,18 @@ @plugin development guide *) let run_plugins () = - if Parameters.TypeCheck.get () then + if Kernel.TypeCheck.get () then Ast.compute (); (* Printing files before anything else (in debug mode only) *) if Kernel.debug_atleast 1 then File.pretty_ast (); (* Syntactic constant folding before analysing files if required *) - if Parameters.Constfold.get () then + if Kernel.Constfold.get () then Cil.visitCilFileSameGlobals (Cil.constFoldVisitor true) (Ast.get ()); try Dynamic.Main.apply (); (* for Helium-compatibility purpose only *) Db.Main.apply (); (* Printing code if required, have to be done at end *) - if Parameters.PrintCode.get () then File.pretty_ast (); + if Kernel.PrintCode.get () then File.pretty_ast (); with Globals.No_such_entry_point msg -> Kernel.error "%s" msg @@ -54,7 +54,6 @@ (* Customisation of non-projectified CIL parameters. (projectified CIL parameters must be initialised with {!Cil.initCIL}). *) let boot_cil () = - Cabs2cil.forceRLArgEval := false; Cil.miscState.Cil.lineDirectiveStyle <- None; Cil.miscState.Cil.printCilAsIs <- Kernel.debug_atleast 1; Mergecil.ignore_merge_conflicts := true;; @@ -65,10 +64,10 @@ Sys.catch_break true; Cmdline.catch_toplevel_run ~f:(fun () -> - Journal.set_name (Parameters.Journal.Name.get ()); - ignore (Project.create "default"); - Cmdline.parse_and_boot - on_from_name (fun () -> !Db.Toplevel.run) run_plugins) + Journal.set_name (Kernel.Journal.Name.get ()); + ignore (Project.create "default"); + Cmdline.parse_and_boot + on_from_name (fun () -> !Db.Toplevel.run) run_plugins) ~at_normal_exit:Cmdline.run_normal_exit_hook ~quit:true ~on_error:Cmdline.run_error_exit_hook diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/cilE.ml frama-c-20111001+nitrogen+dfsg/src/kernel/cilE.ml --- frama-c-20110201+carbon+dfsg/src/kernel/cilE.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/cilE.ml 2011-10-10 08:38:09.000000000 +0000 @@ -26,157 +26,26 @@ open Cilutil open Cil -let debug = false - -let init_builtins () = - let add t1 t2 = - Logic_builtin.add - { bl_name = "\\pointer_comparable"; - bl_profile = [("p1", t1); ("p2", t2)]; - bl_type = None; - bl_params = []; - bl_labels = []; - (* TODO: give an explicit definition *) - } - in - let object_ptr = Ctype Cil.voidPtrType in - let fun_ptr = Ctype (TPtr(TFun(Cil.voidType,None,false,[]),[])) in - add object_ptr object_ptr; - add fun_ptr fun_ptr; - add object_ptr fun_ptr; - add fun_ptr object_ptr - -let () = Logic_env.Builtins.extend init_builtins - -let warn fmt = Cil.warn fmt -let warn_once fmt = - let b = Buffer.create 80 in - let bfmt = Format.formatter_of_buffer b in - Format.kfprintf - (function fmt -> - Format.pp_print_flush fmt (); - let fmt = Buffer.contents b in - Cil.warn ~once:true "%s" fmt - ) bfmt fmt - (* Cil.warn ~once:true fmt *) - -let log_once fmt = - let b = Buffer.create 80 in - let bfmt = Format.formatter_of_buffer b in - Format.kfprintf - (function fmt -> - Format.pp_print_flush fmt (); - let fmt = Buffer.contents b in - Cil.log ~once:true "%s" fmt - ) bfmt fmt - (* Cil.log ~once:true fmt *) - -let labels_table l = - let lbl_tbl = Hashtbl.create 17 in - let goto_changer = object - inherit nopCilVisitor - method vstmt s = - List.iter (function - | Label (l,_,_) -> Hashtbl.add lbl_tbl l s - | _ -> ()) - s.labels; - DoChildren - end - in - List.iter (fun x -> ignore (visitCilStmt goto_changer x)) l; - lbl_tbl - -let update_gotos sid_tbl block = - let goto_changer = object - inherit nopCilVisitor - method vstmt s = match s.skind with - | Goto(sref,loc) -> - (try - let new_stmt = Cil_datatype.Stmt.Map.find !sref sid_tbl in - ChangeTo (mkStmt (Goto (ref new_stmt,loc))) - with Not_found -> DoChildren) - | _ -> DoChildren - end - in - visitCilBlock goto_changer block - -let compact_body fundec = - let labels_moved = ref false in - let stmt_map = ref Cil_datatype.Stmt.Map.empty in - let add_labels s l old_stmt = - stmt_map := Cil_datatype.Stmt.Map.add old_stmt s !stmt_map ; - s.labels <- l @ s.labels; - labels_moved := true - in - let docompact(s1,s2) = match s1.skind, s2.skind with - (* remove skip *) - | Instr (Skip _), _ when s1.labels = [] -> - if debug then prerr_endline "[compact_body] skip/_"; - Some [s2] - | _, Instr (Skip _) when s2.labels = [] -> - if debug then prerr_endline "[compact_body] _/skip"; - Some [s1] - (* collapse useless blocks *) - | Block b1, Block b2 when b1.battrs = b2.battrs && (s2.labels = [] || b2.bstmts <> []) -> - if debug then prerr_endline "[compact_body] blck/blck"; - if s2.labels <> [] then begin - let fst_b2 = List.hd b2.bstmts in - add_labels fst_b2 s2.labels s2 - end; - b1.bstmts <- b1.bstmts@b2.bstmts; - Some [s1] - | Block b, _ when b.battrs = [] -> - if debug then prerr_endline "[compact_body] blck/instr"; - b.bstmts <- b.bstmts@[s2]; - Some [s1] - | _, Block b when b.battrs = [] && (s2.labels = [] || b.bstmts <> []) -> - if debug then prerr_endline "[compact_body] instr/blck"; - if s2.labels <> [] then begin - let fst_b = List.hd b.bstmts in - add_labels fst_b s2.labels s2 - end; - b.bstmts <- s1::b.bstmts; - Some [s2] - | _ -> None - in - let block = fundec.sbody in - (* Je pense que peepHole2 ne fonctionne pas correctement. - * Peut-être serait-il mieux de faire notre propre fonction... - * en plus, ça permettrait de combiner peepHole1 + peepHole2. - * Exemple : peepHole2 ( { { x = 1; skip; } return x; } ) - * -> { { x = 1; skip; return x; } } - * Anne. 12/07/2007. *) - block.bstmts <- peepHole2 ~agressive:true docompact block.bstmts; - let block = - if !labels_moved then update_gotos !stmt_map block - else block - in let rec get_stmts b = match b.bstmts with - | ({skind=Block blk}) :: [] -> - if debug then prerr_endline "[compact_body] block(block)"; - get_stmts blk - | _ -> b.bstmts - in fundec.sbody.bstmts <- get_stmts block - +(* ************************************************************************* *) +(* [JS 2011/03/11] All the below stuff manage warnings of the value analysis + plug-in. Refactoring required. *) +(* ************************************************************************* *) let current_stmt_tbl = let s = Stack.create () in Stack.push Kglobal s; s -let start_stmt ki = - Stack.push ki current_stmt_tbl +let start_stmt ki = Stack.push ki current_stmt_tbl let end_stmt () = - try - ignore (Stack.pop current_stmt_tbl) + try ignore (Stack.pop current_stmt_tbl) with Stack.Empty -> assert false let current_stmt () = - try - Stack.top current_stmt_tbl + try Stack.top current_stmt_tbl with Stack.Empty -> assert false - type syntactic_context = | SyNone | SyBinOp of Cil_types.binop * Cil_types.exp * Cil_types.exp @@ -211,178 +80,218 @@ let get_syntactic_context () = current_stmt (),!syntactic_context -let value_analysis_alarm_status () = - {status = Checked{emitter="value analysis"; valid = Maybe}} +let sc_kinstr_loc ki = + match ki with + | Kglobal -> (* can occur in case of obscure bugs (already happended) + with wacky initializers. Module Initial_state of + value analysis correctly positions the loc *) + assert (Cil_datatype.Kinstr.equal Kglobal + (fst (get_syntactic_context ()))); + CurrentLoc.get () + | Kstmt s -> Cil_datatype.Stmt.loc s + + +type warn_origin = { + warn_emitter: Emitter.t; + warn_deps: State.t list; +} + +let register_alarm ki alarm wo = + Alarms.register ~deps:wo.warn_deps ki alarm wo.warn_emitter + -type alarm_behavior = Aignore | Alog | Acall of (unit -> unit) +type alarm_behavior = Aignore | Alog of warn_origin | Acall of (unit -> unit) type warn_mode = {unspecified:alarm_behavior; others: alarm_behavior; imprecision_tracing:alarm_behavior} -let warn_all_mode = - {unspecified=Alog; others=Alog; imprecision_tracing=Alog} +let warn_all_mode wo = + {unspecified=Alog wo; others=Alog wo; imprecision_tracing=Alog wo} let warn_none_mode = {unspecified=Aignore; others=Aignore; imprecision_tracing=Aignore} +let stop_if_stop_at_first_alarm_mode () = + if (Kernel.StopAtFirstAlarm.get ()) + then exit 0 (* TODO: same mechanism as do_degenerate *) + let warn_div warn_mode = match warn_mode.others with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin - match get_syntactic_context () with - | _,SyNone -> () - | _,(SyUnOp _ | SyMem _ | SyMemLogic _ | SySep _) -> assert false - | ki,SyBinOp ((Div|Mod),_,exp_d) -> - let lexpr = Logic_utils.expr_to_term ~cast:true exp_d in - let annotation = + match get_syntactic_context () with + | _,SyNone -> () + | _,(SyUnOp _ | SyMem _ | SyMemLogic _ | SySep _) -> assert false + | ki,SyBinOp ((Div|Mod),_,exp_d) -> + let loc = exp_d.eloc in + let lexpr = Logic_utils.expr_to_term ~cast:true exp_d in + let annotation = Logic_const.new_code_annotation - (AAssert ([], - Logic_const.unamed (Prel (Rneq,lexpr, lzero())))) + (AAssert ([], + Logic_const.unamed ~loc (Prel (Rneq,lexpr, lzero())))) in - if Alarms.register - ki - (Alarms.Division_alarm,annotation,value_analysis_alarm_status ()) - then - warn "division by zero: %a" !Ast_printer.d_code_annotation annotation - |_,SyBinOp (_,_,_) -> assert false + if register_alarm ki (Division_alarm,annotation) wo then + Kernel.warning ~current:true + "@[division by zero:@ %a@]" + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () + |_,SyBinOp (_,_,_) -> assert false end -let warn_signed_overflow warn_mode e mn mx = +let warn_signed_overflow warn_mode mn mx = match warn_mode.others with - Aignore -> () + | Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> + let aux ki loc exp_l = + (match mn with + | Some mn -> + let lexpr = Logic_const.tinteger_s64 mn in + let p = Logic_const.prel ~loc (Rle, lexpr, exp_l) in + let annotation = + Logic_const.new_code_annotation (AAssert ([],p)) + in + if register_alarm ki (Signed_overflow_alarm,annotation)wo then + Kernel.warning ~current:true + "@[Signed overflow.@ %a@]" + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () + | None -> ()); + ( match mx with + | Some mx -> + let rexpr = Logic_const.tinteger_s64 mx in + let p = Logic_const.prel ~loc (Rle, exp_l, rexpr) in + let annotation = + Logic_const.new_code_annotation (AAssert ([],p)) + in + if register_alarm ki (Signed_overflow_alarm,annotation)wo then + Kernel.warning ~current:true + "@[Signed overflow.@ %a@]" + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () + | None -> ()); + in ( match get_syntactic_context () with - ki, _ -> - begin - let exp_l = - match e.enode with - | BinOp (op, l, r, _) -> - let l_l = Logic_utils.expr_to_term ~cast:true l in - let r_l = Logic_utils.expr_to_term ~cast:true r in - TBinOp (op, l_l, r_l) - | UnOp (op, ie, _) -> - let ie_l = Logic_utils.expr_to_term ~cast:true ie in - TUnOp (op, ie_l) - | _ -> - Format.printf "unexpected expression: %a@." d_exp e; - assert false - in - let exp_l = - Logic_const.term exp_l Linteger - in - ( match mn with - Some mn -> - let lexpr = Logic_const.tinteger_s64 mn in - let p = Logic_const.prel(Rle, lexpr, exp_l) in - let annotation = - Logic_const.new_code_annotation (AAssert ([],p)) - in - if Alarms.register ki - (Alarms.Signed_overflow_alarm,annotation, - value_analysis_alarm_status ()) - then - warn "Signed overflow. %a\n" - !Ast_printer.d_code_annotation annotation - | None -> ()); - ( match mx with - Some mx -> - let rexpr = Logic_const.tinteger_s64 mx in - let p = Logic_const.prel(Rle, exp_l, rexpr) in - let annotation = - Logic_const.new_code_annotation (AAssert ([],p)) - in - if Alarms.register ki - (Alarms.Signed_overflow_alarm,annotation, - value_analysis_alarm_status ()) - then - warn "Signed overflow. %a\n" - !Ast_printer.d_code_annotation annotation - | None -> ()); - end) + | ki, SyUnOp e -> + let te = Logic_utils.expr_to_term ~cast:false e in + aux ki e.eloc te + | ki, SyBinOp (op, l, r) -> + let loc = l.eloc in + let l_l = Logic_utils.expr_to_term ~cast:true l in + let r_l = Logic_utils.expr_to_term ~cast:true r in + let t = Logic_const.term ~loc (TBinOp (op, l_l, r_l)) Linteger in + aux ki loc t + | _ -> + assert false + ) let warn_shift warn_mode size = match warn_mode.others with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin match get_syntactic_context () with | _,SyNone -> () | _,(SyUnOp _ | SyMem _ | SyMemLogic _ | SySep _)-> assert false | ki,SyBinOp ((Shiftrt | Shiftlt),_,exp_d) -> - let lexpr = Logic_utils.expr_to_term ~cast:true exp_d in - let annotation = + let loc = exp_d.eloc in + let lexpr = Logic_utils.expr_to_term ~cast:true exp_d in + let annotation = + Logic_const.new_code_annotation + (AAssert + ([], + Logic_const.pand ~loc + (Logic_const.unamed ~loc (Prel (Rge,lexpr, lzero())), + Logic_const.unamed ~loc + (Prel (Rlt,lexpr, lconstant (My_bigint.of_int size)))))) + in + if register_alarm ki (Shift_alarm,annotation) wo then + Kernel.warning ~current:true + "@[invalid RHS operand for shift.@ %a@]" !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () + | _,SyBinOp(_,_,_) -> + assert false + end + +let warn_shift_left_positive warn_mode = + match warn_mode.others with + Aignore -> () + | Acall f -> f() + | Alog wo -> + begin + match get_syntactic_context () with + | _,SyNone -> () + | _,(SyUnOp _ | SyMem _ | SyMemLogic _ | SySep _)-> assert false + | ki,SyBinOp ((Shiftrt | Shiftlt),exp_l,_) -> + let loc = exp_l.eloc in + let lexpr = Logic_utils.expr_to_term ~cast:true exp_l in + let annotation = Logic_const.new_code_annotation (AAssert - ([], - Logic_const.pand - (Logic_const.unamed (Prel (Rge,lexpr, lzero())), - Logic_const.unamed - (Prel (Rlt,lexpr, lconstant (Int64.of_int size)))))) - in - if Alarms.register ki - (Alarms.Shift_alarm,annotation, value_analysis_alarm_status ()) - then - warn "invalid shift: %a" !Ast_printer.d_code_annotation annotation; - () + ([], + Logic_const.unamed ~loc (Prel (Rge,lexpr, lzero())))) + in + if register_alarm ki (Shift_alarm,annotation) wo then + Kernel.warning ~current:true + "@[invalid LHS operand for left shift.@ %a@]" !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () | _,SyBinOp(_,_,_) -> - assert false + assert false end let warn_mem warn_mode msg = match warn_mode.others with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin - let warn_term ki term = + let warn_term ki loc term = let annotation = Logic_const.new_code_annotation - (AAssert ([], Logic_const.unamed (Pvalid term))) + (AAssert ([], Logic_const.unamed ~loc (Pvalid term))) in - if Alarms.register ki - (Alarms.Memory_alarm, annotation,value_analysis_alarm_status ()) - then - warn "out of bounds %s. @[%a@]" msg - !Ast_printer.d_code_annotation annotation; + if register_alarm ki (Memory_alarm, annotation) wo then + Kernel.warning ~current:true "@[out of bounds %s.@ %a@]" msg + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () in match get_syntactic_context () with | _,SyNone -> () | _,(SyBinOp _ | SyUnOp _ | SySep _) -> assert false | ki,SyMem lv_d -> - let exp = - mkAddrOrStartOf ~loc:(Cil_datatype.Kinstr.loc ki) lv_d in + let loc = sc_kinstr_loc ki in + let exp = mkAddrOrStartOf ~loc lv_d in let term = Logic_utils.expr_to_term ~cast:true exp in - warn_term ki term; + warn_term ki loc term; (match lv_d with | Mem _,_ | _, (Index _ | Field _) -> () | _ -> Format.printf "ERR 937: %a@." d_lval lv_d ; assert false) | ki,SyMemLogic term -> - warn_term ki term + warn_term ki term.term_loc term end -let warn_index warn_mode msg = +let warn_index warn_mode msg index = match warn_mode.others with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin match get_syntactic_context () with | _,SyNone -> () | _,(SyMem _ | SyMemLogic _ | SyUnOp _ | SySep _) -> assert false | ki ,SyBinOp (IndexPI,e1,e2) -> + let loc = e1.eloc in let lexpr = Logic_utils.expr_to_term ~cast:true e1 in let rexpr = Logic_utils.expr_to_term ~cast:true e2 in - let p0 = Logic_const.prel(Rle, lzero(), lexpr) in - let p1 = Logic_const.prel(Rlt, lexpr, rexpr) in - let p = Logic_const.pand (p0,p1) in + let p0 = Logic_const.prel ~loc:lexpr.term_loc (Rle, lzero(), lexpr) in + let p1 = Logic_const.prel ~loc:rexpr.term_loc (Rlt, lexpr, rexpr) in + let p = Logic_const.pand ~loc (p0,p1) in let annotation = Logic_const.new_code_annotation (AAssert ([],p)) in - if Alarms.register ki - (Alarms.Index_alarm,annotation,value_analysis_alarm_status ()) - then - warn "%s out of bounds index. @[%a@]" - msg !Ast_printer.d_code_annotation annotation + if register_alarm ki (Index_alarm,annotation) wo then + Kernel.warning ~current:true "@[%s out of bounds index %s.@ %a@]" + msg index !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () | _,SyBinOp(_,_,_) -> assert false end @@ -396,18 +305,20 @@ let fct_ptr = Ctype cfct_ptr in let obj_ptr = Ctype Cil.voidPtrType in let discriminate t = + let loc = t.term_loc in match t.term_type with | Ctype ty -> (match Cil.unrollType ty with - TPtr(TFun _,_) -> - Logic_const.term (TCastE(cfct_ptr,t)) fct_ptr, fct_ptr + | TPtr(TFun _,_) -> + Logic_const.term ~loc (TCastE(cfct_ptr,t)) fct_ptr, fct_ptr | TPtr _ -> t, obj_ptr | TInt _ when Cil.isLogicZero t -> t, obj_ptr | TVoid _ | TInt _ | TFloat _ | TFun _ | TNamed _ | TComp _ | TEnum _ | TBuiltin_va_list _ | TArray _ -> - Logic_const.term (TCastE(Cil.voidPtrType,t)) obj_ptr, obj_ptr) - | _ -> Logic_const.term (TCastE(Cil.voidPtrType,t)) obj_ptr, obj_ptr + Logic_const.term ~loc (TCastE(voidPtrType,t)) obj_ptr, obj_ptr + ) + | _ -> Logic_const.term ~loc (TCastE(voidPtrType,t)) obj_ptr, obj_ptr in let t1, ty1 = discriminate t1 in @@ -416,12 +327,12 @@ try List.find (function - { l_profile = [v1; v2] } -> + | { l_profile = [v1; v2] } -> Logic_utils.is_same_type v1.lv_type ty1 && - Logic_utils.is_same_type v2.lv_type ty2 + Logic_utils.is_same_type v2.lv_type ty2 | _ -> false) preds with Not_found -> - Cilmsg.fatal "built-in predicate \\pointer_comparable not found" + Kernel.fatal "built-in predicate \\pointer_comparable not found" in Papp (pi, [], [t1;t2]) @@ -429,22 +340,22 @@ match warn_mode.others with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin match get_syntactic_context () with | _,SyNone -> () | _,(SyUnOp _ | SyMem _ | SyMemLogic _ | SySep _) -> assert false | ki,SyBinOp ((Eq|Ne|Ge|Le|Gt|Lt),exp_l,exp_r) -> + let loc = exp_l.eloc in let lexpr_l = Logic_utils.expr_to_term ~cast:true exp_l in let lexpr_r = Logic_utils.expr_to_term ~cast:true exp_r in - let annotation = Logic_const.new_code_annotation - (AAssert ([], Logic_const.unamed (comparable_pointers lexpr_l lexpr_r))) - in - if Alarms.register ki - (Alarms.Pointer_compare_alarm,annotation, - value_analysis_alarm_status ()) - then - warn "pointer comparison: %a" !Ast_printer.d_code_annotation annotation + let t = Logic_const.unamed ~loc (comparable_pointers lexpr_l lexpr_r) in + let annotation = Logic_const.new_code_annotation (AAssert ([], t)) in + if register_alarm ki (Pointer_compare_alarm,annotation) wo then + Kernel.warning ~current:true + "@[pointer comparison:@ %a@]" + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () | _,SyBinOp(_,_,_) -> assert false end @@ -462,77 +373,80 @@ match warn_mode.others with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin match get_syntactic_context () with | _,SyNone -> () | _,(SyBinOp _ | SyMem _ | SyMemLogic _ | SySep _) -> assert false | ki,SyUnOp (exp_r) -> - let annotation = - Logic_const.new_code_annotation - (AAssert - ([], Logic_const.unamed (result_nan_infinite exp_r))) - in - if Alarms.register ki - (Alarms.Result_is_nan_or_infinite_alarm,annotation, - value_analysis_alarm_status ()) - then - warn "float operation: %a" !Ast_printer. d_code_annotation annotation + let loc = exp_r.eloc in + let t = Logic_const.unamed ~loc (result_nan_infinite exp_r) in + let annotation = Logic_const.new_code_annotation (AAssert ([], t)) in + if register_alarm ki (Result_is_nan_or_infinite_alarm,annotation) wo then + Kernel.warning ~current:true ~once:true + "@[float operation:@ %a@]" + !Ast_printer. d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () end let warn_uninitialized warn_mode = match warn_mode.unspecified with - Aignore -> () + | Aignore -> () | Acall f -> f() - | Alog -> - begin + | Alog wo -> match get_syntactic_context () with | _,SyNone -> () | _,(SyBinOp _ | SyUnOp _ | SySep _ | SyMemLogic _) -> assert false - | _,SyMem lv_d -> - warn_once "accessing uninitialized left-value %a: assert(Ook)" d_lval lv_d - end + | ki,SyMem lv_d -> + let loc = sc_kinstr_loc ki in + let e = Cil.mkAddrOrStartOf ~loc lv_d in + let term = Logic_utils.expr_to_term ~cast:false e in + let annotation = + Logic_const.new_code_annotation + (AAssert ([], Logic_const.unamed ~loc (Pinitialized term))) + in + if register_alarm ki (Other_alarm, annotation) wo then + Kernel.warning ~current:true + "@[accessing uninitialized left-value:@ %a@]" + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () let warn_escapingaddr warn_mode = match warn_mode.unspecified with - Aignore -> () + | Aignore -> () | Acall f -> f() - | Alog -> - begin + | Alog _ -> match get_syntactic_context () with | _,SyNone -> () | _,(SyBinOp _ | SyUnOp _ | SySep _ | SyMemLogic _) -> assert false | _,SyMem lv_d -> - warn_once "accessing left-value %a that contains escaping addresses; assert(Ook)" d_lval lv_d - end + Kernel.warning ~once:true ~current:true + "@[accessing left-value %a@ that contains escaping addresses;@ assert(Ook)@]" + d_lval lv_d; + stop_if_stop_at_first_alarm_mode () let warn_separated warn_mode = match warn_mode.unspecified with Aignore -> () | Acall f -> f() - | Alog -> + | Alog wo -> begin match get_syntactic_context () with | _,SyNone -> () | _,(SyBinOp _ | SyUnOp _ | SyMem _ | SyMemLogic _) -> assert false | ki,SySep(lv1,lv2) -> + let loc = sc_kinstr_loc ki in let llv1 = Logic_utils.expr_to_term ~cast:true lv1 in let llv2 = Logic_utils.expr_to_term ~cast:true lv2 in - let alarm = - Logic_const.pseparated - ~loc:(Cil_datatype.Kinstr.loc ki) - [ llv1; llv2 ] - in - let annotation = + let alarm = Logic_const.pseparated ~loc [ llv1; llv2 ] in + let annotation = Logic_const.new_code_annotation (AAssert([],alarm)) in - if Alarms.register ki - (Alarms.Separation_alarm, annotation, - value_analysis_alarm_status ()) - then - warn - "undefined multiple accesses in expression. \ - assert \\separated(%a,%a);" d_exp lv1 d_exp lv2 + if register_alarm ki (Separation_alarm, annotation) wo then + Kernel.warning ~current:true + "@[undefined multiple accesses in expression.@ %a;@]" + !Ast_printer.d_code_annotation annotation; + stop_if_stop_at_first_alarm_mode () end (* diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/cilE.mli frama-c-20111001+nitrogen+dfsg/src/kernel/cilE.mli --- frama-c-20110201+carbon+dfsg/src/kernel/cilE.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/cilE.mli 2011-10-10 08:38:09.000000000 +0000 @@ -20,20 +20,13 @@ (* *) (**************************************************************************) -(** Cil Extension for Frama-C. +(** CIL Extension for Frama-C. @plugin development guide *) -(** Display a localized warning only once per location and per message. *) -val warn_once : ('a, Format.formatter, unit, unit) format4 -> 'a -(** Display a warning only once per message. *) -val log_once : ('a, Format.formatter, unit, unit) format4 -> 'a - -(*val compact_body : Cil_types.fundec -> unit*) - -(** Restore correct gotos after a statement substitution *) -val update_gotos : - Cil_types.stmt Cil_datatype.Stmt.Map.t -> Cil_types.block -> - Cil_types.block +(* ************************************************************************* *) +(* [JS 2011/03/11] All the below stuff manage warnings of the value analysis + plug-in. Refactoring required. *) +(* ************************************************************************* *) type syntactic_context = | SyNone @@ -51,33 +44,40 @@ val set_syntactic_context : syntactic_context -> unit val get_syntactic_context : unit -> Cil_types.kinstr*syntactic_context +type warn_origin = { + warn_emitter: Emitter.t; + warn_deps: State.t list; +} + type alarm_behavior = | Aignore (** pretend that the problematic values do not happen *) - | Alog + | Alog of warn_origin (** log the alarm using the global variable that has been set - with set_syntactic_context, and continue, - pretending that the problematic values do not happen *) + with set_syntactic_context, and continue, + pretending that the problematic values do not happen *) | Acall of (unit -> unit) (** call function -- in a future version, more information will be - passed to the function *) + passed to the function *) + +val stop_if_stop_at_first_alarm_mode : unit -> unit type warn_mode = { unspecified: alarm_behavior; others: alarm_behavior; imprecision_tracing: alarm_behavior } (** An argument of type [warn_mode] is required by some of the access - functions in {!Db.Value (the interface to the value analysis). This - argument tells what should be done with the various messages - that the value analysis emits during the call. - - Each [warn_mode] field indicates the expected treatment for one - category of message. These fields are not completely fixed - yet. However, you can still used functions {!warn_all_mode} and - {!warn_none_mode} below when you have to provide an argument of type - [warn_mode]. *) + functions in {!Db.Value} (the interface to the value analysis). This + argument tells what should be done with the various messages + that the value analysis emits during the call. + + Each [warn_mode] field indicates the expected treatment for one + category of message. These fields are not completely fixed + yet. However, you can still used functions {!warn_all_mode} and + {!warn_none_mode} below when you have to provide an argument of type + [warn_mode]. *) -val warn_all_mode : warn_mode +val warn_all_mode : warn_origin -> warn_mode (** Emit all messages, including alarms and informative messages regarding the loss of precision. *) @@ -86,12 +86,15 @@ val warn_div : warn_mode -> unit val warn_shift : warn_mode -> int -> unit +val warn_shift_left_positive : warn_mode -> unit val warn_mem_read : warn_mode -> unit val warn_mem_write : warn_mode -> unit -val warn_signed_overflow : warn_mode -> - Cil_types.exp -> - Int64.t option -> Int64.t option -> unit -val warn_index : warn_mode -> string -> unit +val warn_signed_overflow : warn_mode -> Int64.t option -> Int64.t option -> unit + +val warn_index : warn_mode -> string -> string -> unit +(** [warn_index w kind index] emite a warning signaling an out of bound + access of kind [kind] at the index [index]. +*) val warn_pointer_comparison : warn_mode -> unit val warn_result_nan_infinite : warn_mode -> unit val warn_uninitialized : warn_mode -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/cmdline.ml frama-c-20111001+nitrogen+dfsg/src/kernel/cmdline.ml --- frama-c-20110201+carbon+dfsg/src/kernel/cmdline.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/cmdline.ml 2011-10-10 08:38:09.000000000 +0000 @@ -59,8 +59,9 @@ (struct let channel = Log.kernel_channel_name let label = Log.kernel_label_name - let verbose_atleast n = !verbose_level_ref >= n - let debug_atleast n = !debug_level_ref >= n + (* eta-expansion required below *) + let verbose_atleast n = !kernel_verbose_atleast_ref n + let debug_atleast n = !kernel_debug_atleast_ref n end) include L @@ -78,15 +79,19 @@ "" let get_backtrace () = - try "The full backtrace is:\n" ^ Printexc_common_interface.get_backtrace () + try + "The full backtrace is:\n" ^ Printexc_common_interface.get_backtrace () with Printexc_common_interface.No_backtrace -> "No backtrace available (OCaml version is lower than 3.11.0)" let request_crash_report = - "Please report as 'crash' at http://bts.frama-c.com/\n\ - Note that a backtrace alone often does not have information to\n\ - understand the bug. Guidelines for reporting bugs are at:\n\ - http://bts.frama-c.com/dokuwiki/doku.php?id=mantis:frama-c:bug_reporting_guidelines\n" + Format.sprintf + "Please report as 'crash' at http://bts.frama-c.com/.\n\ + Your Frama-C version is %s.\n\ + Note that a version and a backtrace alone often does not have information\n\ + to understand the bug. Guidelines for reporting bugs are at:\n\ + http://bts.frama-c.com/dokuwiki/doku.php?id=mantis:frama-c:bug_reporting_guidelines\n" + Config.version let protect = function | Sys.Break -> "User Interruption (Ctrl-C)" @@ -155,7 +160,7 @@ | Sys.Break -> 2 | Log.FeatureRequest _ | Extlib.NotYetImplemented _ -> 3 | Log.AbortFatal _ -> 4 - | _ -> 127 + | _ -> 125 let bail_out_ref = ref (fun _ -> assert false) let bail_out () = @@ -169,9 +174,9 @@ at_normal_exit () with exn -> L.feedback - ~level:0 - "error occurring when exiting Frama-C: stopping exit procedure.\n%s@." - (protect exn); + ~level:0 + "error occurring when exiting Frama-C: stopping exit procedure.\n%s@." + (protect exn); exit 5 in let run_on_error () = @@ -179,10 +184,10 @@ on_error () with exn -> L.feedback - ~level:0 - "error occurring when handling error: stopping error handling \ + ~level:0 + "error occurring when handling error: stopping error handling \ procedure.\n%s@." - (protect exn); + (protect exn); exit 6 in let bail_out () = @@ -199,14 +204,14 @@ (if quit then bail_out else run_at_normal_exit) () with | Exit -> - bail_out () + bail_out () | exn when catch_at_toplevel exn -> - L.feedback ~level:0 "%s" (protect exn); - run_on_error (); - exit (exit_code exn) + L.feedback ~level:0 "%s" (protect exn); + run_on_error (); + exit (exit_code exn) | exn -> - run_on_error (); - raise exn + run_on_error (); + raise exn (* ************************************************************************* *) (** {2 Generic parsing way} *) @@ -247,31 +252,31 @@ let option, arg, explicit = get_option_and_arg option arg in let check_string_argname () = if not explicit && (arg = "" || arg.[0] = '-') then - raise_error option "requires a string as argument"; + raise_error option "requires a string as argument"; in try let setting = Hashtbl.find known_options option in let use_arg = match setting with - | Unit f -> - if explicit then raise_error option "does not accept any argument"; - f (); - false - | Int f -> - let n = - try int_of_string arg - with Failure _ -> - raise_error option "requires an integer as argument" - in - f n; - true - | String f -> - check_string_argname (); - f arg; - true - | String_list f -> - check_string_argname (); - f (Str.split (Str.regexp "[ \t]*,[ \t]*") arg); - true + | Unit f -> + if explicit then raise_error option "does not accept any argument"; + f (); + false + | Int f -> + let n = + try int_of_string arg + with Failure _ -> + raise_error option "requires an integer as argument" + in + f n; + true + | String f -> + check_string_argname (); + f arg; + true + | String_list f -> + check_string_argname (); + f (Str.split (Str.regexp "[ \t]*,[ \t]*") arg); + true in unknown_options, use_arg && not explicit, true with Not_found -> @@ -287,7 +292,7 @@ raise_error "-then-on" "requires a string as argument" | [ option ] -> let unknown, use_arg, is_used = - parse_one_option unknown_options option "" + parse_one_option unknown_options option "" in assert (not use_arg); unknown, (if is_used then succ nb_used else nb_used), None @@ -297,13 +302,13 @@ unknown_options, nb_used, Some (then_options, Some project_name) | option :: (arg :: next_options as arg_next) -> let unknown, use_arg, is_used = - parse_one_option unknown_options option arg + parse_one_option unknown_options option arg in let next = if use_arg then next_options else arg_next in go - unknown - (if is_used then succ nb_used else nb_used) - next + unknown + (if is_used then succ nb_used else nb_used) + next in try let unknown_options, nb_used, then_options = go [] 0 options_list in @@ -331,9 +336,9 @@ "-no-type", Unit (fun () -> use_type_ref := false); "-quiet", Unit (fun () -> - quiet_ref := true; - verbose_level_ref := 0; - debug_level_ref := 0); + quiet_ref := true; + verbose_level_ref := 0; + debug_level_ref := 0); "-verbose", Int (fun n -> verbose_level_ref := n); "-debug", Int (fun n -> debug_level_ref := n); "-kernel-verbose", Int (fun n -> kernel_verbose_level_ref := n); @@ -389,9 +394,9 @@ module Plugin: sig type t = private { name: string; - help: string; - short: string; - groups: (string, cmdline_option list ref) Hashtbl.t } + help: string; + short: string; + groups: (string, cmdline_option list ref) Hashtbl.t } val all_plugins: unit -> t list val add: ?short:string -> string -> help:string -> unit val add_group: ?memo:bool -> plugin:string -> string -> string * bool @@ -454,8 +459,8 @@ let check s = if Hashtbl.mem tbl s then - invalid_arg - (Format.sprintf "an option with the name %S is already registered." s) + invalid_arg + (Format.sprintf "an option with the name %S is already registered." s) let add s b = check s; @@ -532,22 +537,25 @@ let add_for_parsing option = Hashtbl.add options option.oname option let add name plugin ?(argname="") help ext_help setting = - L.debug ~level:4 "Cmdline: [%s] registers %S for stage %s" + L.debug ~level:4 "Cmdline: [%s] registers %S for stage %s." plugin name S.name; + let help = + Extlib.opt_map (fun x -> if x = "" then "undocumented" else x) help + in let o = { oname = name; argname = argname; - ohelp = help; ext_help = ext_help; setting = setting } + ohelp = help; ext_help = ext_help; setting = setting } in add_for_parsing o; Plugin.add_option plugin o let parse options_list = - L.debug ~level:3 "Parsing stage %s" S.name ; + L.feedback ~level:3 "parsing command line options of stage %S." S.name ; let options, nb_used, then_options = parse - (Hashtbl.fold (fun _ o acc -> (o.oname, o.setting) :: acc) options []) - S.then_expected - options_list + (Hashtbl.fold (fun _ o acc -> (o.oname, o.setting) :: acc) options []) + S.then_expected + options_list in let nb_used = nb_used + !nb_actions in if S.exclusive && nb_used > 1 then begin @@ -657,6 +665,7 @@ let use_cmdline_files = On_Files.extend let set_files used_loading l = + L.feedback ~level:3 "setting files from command lines."; List.iter (fun s -> if s = "" then error "" "has no name. What do you exactly have in mind?"; @@ -669,7 +678,7 @@ if List.length l > 0 then if used_loading then warning - "ignoring source files specified on the command line \ + "ignoring source files specified on the command line \ while loading a global initial context." else begin On_Files.apply l; @@ -710,6 +719,7 @@ + nb_used_loading + nb_used_config ; set_files (nb_used_loading > 0) files; + L.feedback ~level:3 "running plug-in mains."; play (); match then_options_extended with | None -> () @@ -733,10 +743,10 @@ provides the good one. *) (fun () -> play_in_toplevel - on_from_name - (nb_used_early + nb_used_extending) - play - options) + on_from_name + (nb_used_early + nb_used_extending) + play + options) (* ************************************************************************* *) (** {2 Help} @@ -746,35 +756,32 @@ (* ************************************************************************* *) let print_helpline fmt head help ext_help = - match help with - | None -> () - | Some help -> - let n = max 1 (19 - String.length head) in - Format.fprintf fmt "@[%s%s %t%t@]@\n" - head - (* let enough spaces *) - (String.make n ' ') - (* the description *) - (fun fmt -> - (* add a cutting point at each space *) - let cut_space fmt s = - let rec cut_list fmt = function - | [] -> () - | [ s ] -> Format.fprintf fmt "%s" s - | s :: tl -> Format.fprintf fmt "%s@ %a" s cut_list tl - in - cut_list fmt (Str.split (Str.regexp_string " ") s) - in - (* replace each '\n' by '@\n' (except for the last one) *) - let rec cut_newline fmt = function - | [] -> () - | [ s ] -> Format.fprintf fmt "%a" cut_space s - | s :: tl -> - Format.fprintf fmt "%a@\n%a" cut_space s cut_newline tl - in - cut_newline fmt (Str.split (Str.regexp_string "\n") help)) - (* the extended description *) - (fun fmt -> Format.fprintf fmt ext_help) + let n = max 1 (19 - String.length head) in + Format.fprintf fmt "@[%s%s %t%t@]@\n" + head + (* let enough spaces *) + (String.make n ' ') + (* the description *) + (fun fmt -> + (* add a cutting point at each space *) + let cut_space fmt s = + let rec cut_list fmt = function + | [] -> () + | [ s ] -> Format.fprintf fmt "%s" s + | s :: tl -> Format.fprintf fmt "%s@ %a" s cut_list tl + in + cut_list fmt (Str.split (Str.regexp_string " ") s) + in + (* replace each '\n' by '@\n' (except for the last one) *) + let rec cut_newline fmt = function + | [] -> () + | [ s ] -> Format.fprintf fmt "%a" cut_space s + | s :: tl -> + Format.fprintf fmt "%a@\n%a" cut_space s cut_newline tl + in + cut_newline fmt (Str.split (Str.regexp_string "\n") help)) + (* the extended description *) + (fun fmt -> Format.fprintf fmt ext_help) let print_option_help fmt o = if Plugin.is_option_alias o then begin @@ -783,23 +790,23 @@ let ty = let s = o.argname in if s = "" then - match o.setting with - | Unit _ -> "" - | Int _ -> " " - | String _ -> " " - | String_list _ -> " " + match o.setting with + | Unit _ -> "" + | Int _ -> " " + | String _ -> " " + | String_list _ -> " " else - " <" ^ s ^ ">" + " <" ^ s ^ ">" in let name = o.oname in - print_helpline fmt (name ^ ty) o.ohelp o.ext_help; - List.iter - (fun o -> - print_helpline fmt - (o.oname ^ ty) - (Some (" alias for option " ^ name)) - "") - (Plugin.find_option_aliases o); + Extlib.may + (fun h -> + print_helpline fmt (name ^ ty) h o.ext_help; + List.iter + (fun o -> + print_helpline fmt (o.oname ^ ty) (" alias for option " ^ name) "") + (Plugin.find_option_aliases o)) + o.ohelp; true let option_intro short = @@ -807,9 +814,9 @@ if short <> "" then begin let short = "-" ^ short in Format.sprintf - "Most options of the form '%s-option-name'@ and without any \ + "Most options of the form '%s-option-name'@ and without any \ parameter@ have an opposite with the name '%s-no-option-name'.@\n@\n" - short short + short short end else "" in @@ -822,47 +829,49 @@ let p = Plugin.find shortname in if p.Plugin.name <> "" then begin assert (p.Plugin.short <> ""); - Log.print_on_output "@[%s:@ %s@]@\n@[%s:@ %s@]@\n" - "Plug-in name" - p.Plugin.name - "Plug-in shortname" - shortname + Log.print_on_output + (fun fmt -> + Format.fprintf fmt "@[%s:@ %s@]@\n@[%s:@ %s@]@\n" + "Plug-in name" p.Plugin.name + "Plug-in shortname" shortname) end; Log.print_on_output - "@[@[%s:@ %s@]@\n@\n%s@\n@\n%s:@\n@\n@[%t@]@]@?" - "Description" - p.Plugin.help - (option_intro shortname) - "***** LIST OF AVAILABLE OPTIONS" (fun fmt -> - let print_options l = - List.fold_left - (fun b o -> - let b' = print_option_help fmt o in - b || b') - false - (List.sort (fun o1 o2 -> String.compare o1.oname o2.oname) l) - in - let printed = print_options !(Hashtbl.find p.Plugin.groups "") in - if printed then Format.pp_print_newline fmt (); - let sorted_groups = - List.sort - (fun (s1, _) (s2, _) -> String.compare s1 s2) - (Hashtbl.fold - (fun s l acc -> if s = "" then acc else (s, l) :: acc) - p.Plugin.groups - []) - in - match sorted_groups with - | [] -> () - | (s, o) :: l -> - Format.fprintf fmt "@[*** %s@]@\n@\n" (String.uppercase s); - ignore (print_options !o); - List.iter - (fun (s, l) -> - Format.fprintf fmt "@\n@[*** %s@]@\n@\n" (String.uppercase s); - ignore (print_options !l)) - l); + Format.fprintf fmt + "@[@[%s:@ %s@]@\n@\n%s@\n@\n%s:@\n@\n@[%t@]@]@?" + "Description" p.Plugin.help + (option_intro shortname) + "***** LIST OF AVAILABLE OPTIONS" + (fun fmt -> + let print_options l = + List.fold_left + (fun b o -> + let b' = print_option_help fmt o in + b || b') + false + (List.sort (fun o1 o2 -> String.compare o1.oname o2.oname) l) + in + let printed = print_options !(Hashtbl.find p.Plugin.groups "") in + if printed then Format.pp_print_newline fmt (); + let sorted_groups = + List.sort + (fun (s1, _) (s2, _) -> String.compare s1 s2) + (Hashtbl.fold + (fun s l acc -> if s = "" then acc else (s, l) :: acc) + p.Plugin.groups + []) + in + match sorted_groups with + | [] -> () + | (s, o) :: l -> + Format.fprintf fmt "@[*** %s@]@\n@\n" (String.uppercase s); + ignore (print_options !o); + List.iter + (fun (s, l) -> + Format.fprintf fmt "@\n@[*** %s@]@\n@\n" + (String.uppercase s); + ignore (print_options !l)) + l)); raise Exit let help () = @@ -870,29 +879,35 @@ List.iter (fun p -> if p.Plugin.name <> "" then f p) (List.sort - (fun p1 p2 -> String.compare p1.Plugin.name p2.Plugin.name) - (Plugin.all_plugins ())) + (fun p1 p2 -> + String.compare + (String.lowercase p1.Plugin.name) + (String.lowercase p2.Plugin.name)) + (Plugin.all_plugins ())) in Log.print_on_output - "@[%t@\n%t@\n@\n%s@\n@\n@[%t@]@]@?" - (fun fmt -> - Format.fprintf fmt "@[Usage: %s [options and files...]@]" Sys.argv.(0)) - (fun fmt -> + (fun fmt -> Format.fprintf fmt - "@[`%s -kernel-help' provides a description of the general options of frama-c@]" - Sys.argv.(0)) - "***** LIST OF AVAILABLE PLUG-INS" - (fun fmt -> - iter_on_plugins - (fun p -> - print_helpline - fmt - p.Plugin.name - (Some - (p.Plugin.help - ^ ";\n use -" ^ p.Plugin.short - ^ "-help for specific options.")) - "")); + "@[%t@\n%t@\n@\n%s@\n@\n@[%t@]@]@?" + (fun fmt -> + Format.fprintf fmt "@[Usage: %s [options and files...]@]" + Sys.argv.(0)) + (fun fmt -> + Format.fprintf fmt + "@[`%s -kernel-help' provides a description of the general \ +options of frama-c@]" + Sys.argv.(0)) + "***** LIST OF AVAILABLE PLUG-INS" + (fun fmt -> + iter_on_plugins + (fun p -> + print_helpline + fmt + p.Plugin.name + (p.Plugin.help + ^ ";\n use -" ^ p.Plugin.short + ^ "-help for specific options.") + ""))); raise Exit (* diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/cmdline.mli frama-c-20111001+nitrogen+dfsg/src/kernel/cmdline.mli --- frama-c-20110201+carbon+dfsg/src/kernel/cmdline.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/cmdline.mli 2011-10-10 08:38:09.000000000 +0000 @@ -29,8 +29,8 @@ type stage = Early | Extending | Extended | Exiting | Loading | Configuring (** The different stages, from the first to be executed to the last one. - @plugin development guide - @since Beryllium-20090601-beta1 *) + @plugin development guide + @since Beryllium-20090601-beta1 *) val run_after_early_stage: (unit -> unit) -> unit (** Register an action to be executed at the end of the early stage. @@ -43,7 +43,7 @@ @since Beryllium-20090901 *) val run_after_extended_stage: (unit -> unit) -> unit - (** Register an action to be executed at the end of the extending stage. + (** Register an action to be executed at the end of the extended stage. @plugin development guide @since Beryllium-20090901 *) @@ -101,10 +101,10 @@ on_error:(unit -> unit) -> unit (** Run [f]. When done, either call [at_normal_exit] if running [f] was ok; - or call [on_error] in other cases. - Set [quit] to [true] iff Frama-C must stop after running [f]. - @modify Boron-20100401 additional arguments. They are now - labelled *) + or call [on_error] in other cases. + Set [quit] to [true] iff Frama-C must stop after running [f]. + @modify Boron-20100401 additional arguments. They are now + labelled *) val at_normal_exit: (unit -> unit) -> unit (** Register a hook executed whenever Frama-C exits without error (the exit @@ -173,6 +173,7 @@ is used as the shortname. By convention, if the name and the shortname are equal to "", then the register "plug-in" is the Frama-C kernel itself. + @raise Invalid_argument if the same shortname is registered twice @since Beryllium-20090601-beta1 *) (** @since Beryllium-20090901 *) @@ -185,7 +186,7 @@ If [memo] is [false], cannot add twice a group with the same name. @return the group corresponding to the given name. Also return [true] iff the group has just been created. - @since Beryllium-20090901 *) + @since Beryllium-20090901 *) val name: t -> string (** @since Beryllium-20090901 *) end @@ -208,15 +209,15 @@ option_setting -> unit (** [add_option name ~plugin stage ~argname ~help setting] - adds a new option of the given [name] recognized by the command line of - Frama-C. If the [name] is the empty string, nothing is done. - [plugin] is the shortname of the plug-in. - [argname] is the name of the argument which can be used of the - helpiption [help]. Both of them are used by the help of the - registered option. If [help] is [None], then the option is not shown - in the help. - @since Beryllium-20090601-beta1 - @modify Carbon-20101201 *) + adds a new option of the given [name] recognized by the command line of + Frama-C. If the [name] is the empty string, nothing is done. + [plugin] is the shortname of the plug-in. + [argname] is the name of the argument which can be used of the + description [help]. Both of them are used by the help of the + registered option. If [help] is [None], then the option is not shown + in the help. + @since Beryllium-20090601-beta1 + @modify Carbon-20101201 *) val add_option_without_action: string -> @@ -242,7 +243,7 @@ (** [add_aliases orig plugin group aliases] adds a list of aliases to the given option name [orig]. @Invalid_argument if an alias name is the empty string - @since Carbon-20101202+dev *) + @since Carbon-20110201 *) (** {2 Special parameters} diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/command.ml frama-c-20111001+nitrogen+dfsg/src/kernel/command.ml --- frama-c-20110201+carbon+dfsg/src/kernel/command.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/command.ml 2011-10-10 08:38:09.000000000 +0000 @@ -50,12 +50,12 @@ Format.pp_print_string fmt line ; Format.pp_print_newline fmt () ; done - with + with | End_of_file -> - close_in cin + close_in cin | err -> - close_in cin ; - raise err + close_in cin ; + raise err let rec bincopy buffer cin cout = let s = String.length buffer in @@ -64,7 +64,7 @@ ( Pervasives.output cout buffer 0 n ; bincopy buffer cin cout ) else ( Pervasives.output cout "\n" 0 1 ; flush cout ) - + let on_inc file job = let inc = open_in file in try job inc ; close_in inc @@ -76,11 +76,11 @@ with e -> close_out out ; raise e let copy src tgt = - on_inc src + on_inc src (fun inc -> - on_out tgt - (fun out -> - bincopy (String.create 2048) inc out)) + on_out tgt + (fun out -> + bincopy (String.create 2048) inc out)) (* -------------------------------------------------------------------------- *) @@ -88,130 +88,130 @@ (* -------------------------------------------------------------------------- *) type process_result = Not_ready of (unit -> unit) | Result of Unix.process_status - + let full_command cmd args ~stdin ~stdout ~stderr = - let pid = - Unix.create_process cmd (Array.concat [[|cmd|];args]) stdin stdout stderr + let pid = + Unix.create_process cmd (Array.concat [[|cmd|];args]) stdin stdout stderr in let _,status = Unix.waitpid [Unix.WUNTRACED] pid in status let full_command_async cmd args ~stdin ~stdout ~stderr = - let pid = - Unix.create_process cmd (Array.concat [[|cmd|];args]) stdin stdout stderr + let pid = + Unix.create_process cmd (Array.concat [[|cmd|];args]) stdin stdout stderr in let last_result= ref(Not_ready (fun () -> Extlib.terminate_process pid)) in - (fun () -> - match !last_result with + (fun () -> + match !last_result with | Result _ as r -> r - | Not_ready _ as r -> - let child_id,status = - Unix.waitpid [Unix.WNOHANG; Unix.WUNTRACED] pid - in - if child_id = 0 then r - else (last_result := Result status; !last_result)) + | Not_ready _ as r -> + let child_id,status = + Unix.waitpid [Unix.WNOHANG; Unix.WUNTRACED] pid + in + if child_id = 0 then r + else (last_result := Result status; !last_result)) -let cleanup_and_fill b f = - match b with +let cleanup_and_fill b f = + match b with | None -> Extlib.safe_remove f - | Some b -> - try - let cin = open_in_bin f in - (try - while true do - Buffer.add_string b (input_line cin); - Buffer.add_char b '\n' - done - with _ -> ()); - close_in cin - with _ -> - Extlib.safe_remove f + | Some b -> + try + let cin = open_in_bin f in + (try + while true do + Buffer.add_string b (input_line cin); + Buffer.add_char b '\n' + done + with _ -> ()); + close_in cin + with _ -> + Extlib.safe_remove f let command_generic ~async ?stdout ?stderr cmd args = - let inf,inc = Filename.open_temp_file + let inf,inc = Filename.open_temp_file ~mode:[Open_binary;Open_rdonly; Open_trunc; Open_creat; Open_nonblock ] "in_" ".tmp" in - let outf,outc = Filename.open_temp_file + let outf,outc = Filename.open_temp_file ~mode:[Open_binary;Open_wronly; Open_trunc; Open_creat] "out_" ".tmp" in - let errf,errc = Filename.open_temp_file + let errf,errc = Filename.open_temp_file ~mode:[Open_binary;Open_wronly; Open_trunc; Open_creat] "out_" ".tmp" in let to_terminate = ref None in - let do_terminate () = + let do_terminate () = begin match !to_terminate with | None -> () | Some pid -> Extlib.terminate_process pid end; Extlib.safe_remove inf; - Extlib.safe_remove outf; + Extlib.safe_remove outf; Extlib.safe_remove errf in at_exit do_terminate; (* small memory leak : pending list of ref None ... *) let pid = Unix.create_process cmd (Array.concat [[|cmd|];args]) - (Unix.descr_of_out_channel inc) + (Unix.descr_of_out_channel inc) (Unix.descr_of_out_channel outc) (Unix.descr_of_out_channel errc) in to_terminate:= Some pid; close_out inc; close_out outc; close_out errc; - (*Format.printf "Generic run: %s " cmd; - Array.iter (fun s -> Format.printf "%s " s) args; - Format.printf "@.";*) + (*Format.printf "Generic run: %s " cmd; + Array.iter (fun s -> Format.printf "%s " s) args; + Format.printf "@.";*) let last_result= ref (Not_ready do_terminate) in let wait_flags = if async then [Unix.WNOHANG; Unix.WUNTRACED] - else [Unix.WUNTRACED] + else [Unix.WUNTRACED] in - (fun () -> - match !last_result with - | Result _p as r -> - (*Format.printf "Got result %d@." - (match _p with Unix.WEXITED x -> x | _ -> 99);*) - r - | Not_ready _ as r -> - let child_id,status = Unix.waitpid wait_flags pid in - if child_id = 0 then (assert async;r) - else ( - to_terminate := None; - (*Format.printf "Got (%s) result after wait %d@." - cmd (match status with Unix.WEXITED x -> x | _ -> 99);*) - last_result := Result status; - cleanup_and_fill stdout outf; - cleanup_and_fill stderr errf; - Extlib.safe_remove inf; - !last_result)) + (fun () -> + match !last_result with + | Result _p as r -> + (*Format.printf "Got result %d@." + (match _p with Unix.WEXITED x -> x | _ -> 99);*) + r + | Not_ready _ as r -> + let child_id,status = Unix.waitpid wait_flags pid in + if child_id = 0 then (assert async;r) + else ( + to_terminate := None; + (*Format.printf "Got (%s) result after wait %d@." + cmd (match status with Unix.WEXITED x -> x | _ -> 99);*) + last_result := Result status; + cleanup_and_fill stdout outf; + cleanup_and_fill stderr errf; + Extlib.safe_remove inf; + !last_result)) let command_async ?stdout ?stderr cmd args = command_generic ~async:true ?stdout ?stderr cmd args - + let command ?(timeout=0) ?stdout ?stderr cmd args = - if !Config.is_gui || timeout > 0 then + if !Config.is_gui || timeout > 0 then let f = command_generic ~async:true ?stdout ?stderr cmd args in let res = ref(Unix.WEXITED 99) in let elapsed = ref 0 in let running () = - match f () with - | Not_ready terminate -> + match f () with + | Not_ready terminate -> begin - try - !Db.progress () ; - if timeout > 0 && !elapsed > timeout then raise Db.Cancel ; - true - with Db.Cancel as e -> - terminate (); - raise e + try + !Db.progress () ; + if timeout > 0 && !elapsed > timeout then raise Db.Cancel ; + true + with Db.Cancel as e -> + terminate (); + raise e end - | Result r -> + | Result r -> res := r; false in while running () do Unix.sleep 1 done ; !res else let f = command_generic ~async:false ?stdout ?stderr cmd args in - match f () with + match f () with | Result r -> r | Not_ready _ -> assert false diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/command.mli frama-c-20111001+nitrogen+dfsg/src/kernel/command.mli --- frama-c-20110201+carbon+dfsg/src/kernel/command.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/command.mli 2011-10-10 08:38:09.000000000 +0000 @@ -20,6 +20,8 @@ (* *) (**************************************************************************) +(** Useful high-level system operations. *) + (* ************************************************************************* *) (** File Utilities *) (* ************************************************************************* *) @@ -28,16 +30,16 @@ val pp_to_file : string -> (Format.formatter -> unit) -> unit (** [pp_to_file file pp] runs [pp] on a formatter that writes into [file]. - The formatter is always properly flushed and closed on return. + The formatter is always properly flushed and closed on return. Exceptions in [pp] are re-raised after closing. *) - + val pp_from_file : Format.formatter -> string -> unit (** [pp_from_file fmt file] dumps the content of [file] into the [fmt]. Exceptions in [pp] are re-raised after closing. *) val bincopy : string -> in_channel -> out_channel -> unit - (** [copy buffer cin cout] reads [cin] until end-of-file - and copy it in [cout]. + (** [copy buffer cin cout] reads [cin] until end-of-file + and copy it in [cout]. [buffer] is a temporary string used during the copy. Recommanded size is [2048]. *) @@ -55,10 +57,10 @@ -> stderr:Unix.file_descr -> Unix.process_status (** Same arguments as {Unix.create_process} but returns only when - execution is complete. + execution is complete. @raise Sys_error when a system error occurs *) -type process_result = +type process_result = | Not_ready of (unit -> unit) | Result of Unix.process_status (** [Not_ready f] means that the child process is not yet finished and @@ -74,7 +76,7 @@ @return a function to call to check if the process execution is complete. You must call this function until it returns a Result - to prevent Zombie processes. + to prevent Zombie processes. @raise Sys_error when a system error occurs *) val command_async : @@ -89,7 +91,7 @@ to prevent Zombie processes. When this function returns a Result, the stdout and stderr of the child process will be filled into the arguments buffer. - @raise Sys_error when a system error occurs + @raise Sys_error when a system error occurs *) val command : @@ -101,7 +103,7 @@ (** Same arguments as {Unix.create_process}. When this function returns, the stdout and stderr of the child process will be filled into the arguments buffer. - @raise Sys_error when a system error occurs + @raise Sys_error when a system error occurs @raise Db.Cancel when the computation is interrupted or on timeout *) (* diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/config.ml frama-c-20111001+nitrogen+dfsg/src/kernel/config.ml --- frama-c-20110201+carbon+dfsg/src/kernel/config.ml 2011-02-07 14:02:38.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/config.ml 2011-10-10 08:56:36.000000000 +0000 @@ -1,13 +1,13 @@ (* This file is generated by Makefile. Do not modify. *) -let version = "Carbon-20110201" -let date = "Mon Feb 7 15:02:38 CET 2011" +let version = "Nitrogen-20111001" +let date = "Mon Oct 10 10:56:36 CEST 2011" let is_gui = ref false let ocamlc = "ocamlc.opt" let ocamlopt = "ocamlopt.opt" let datadir = try Sys.getenv "FRAMAC_SHARE" with Not_found -> "/usr/local/share/frama-c" let libdir = try Sys.getenv "FRAMAC_LIB" with Not_found -> "/usr/local/lib/frama-c" let plugin_dir = try Sys.getenv "FRAMAC_PLUGIN" with Not_found -> try (Sys.getenv "FRAMAC_LIB") ^ "/plugins" with Not_found -> "/usr/local/lib/frama-c/plugins" -let static_plugins = [ "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "RteGen"; "Report"; "From"; "Users"; "Constant_Propagation"; "Postdominators"; "Inout"; "Semantic_callgraph"; "Impact"; "Pdg"; "Scope"; "Sparecode"; "Slicing" ] +let static_plugins = [ "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "RteGen"; "From"; "Users"; "Constant_Propagation"; "Postdominators"; "Inout"; "Semantic_callgraph"; "Impact"; "Pdg"; "Scope"; "Sparecode"; "Slicing" ] let static_gui_plugins = [ "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "From"; "Impact"; "Scope"; "Slicing" ] -let compilation_unit_names = [ "unmarshal"; "unmarshal_nums"; "printexc_common_interface"; "dynlink_common_interface"; "structural_descr"; "type"; "descr"; "extlib"; "pretty_utils"; "hook"; "bag"; "bitvector"; "qstack"; "config"; "gui_init"; "log"; "cmdline"; "project_skeleton"; "datatype"; "journal"; "rangemap"; "state"; "state_dependency_graph"; "state_topological"; "state_selection"; "project"; "dashtbl"; "state_builder"; "cilmsg"; "alpha"; "clist"; "growArray"; "inthash"; "cil_datatype"; "cilutil"; "setWithNearest"; "cil_state_builder"; "utf8_logic"; "cilglobopt"; "machdep_x86_16"; "machdep_x86_32"; "machdep_x86_64"; "machdep_ppc_32"; "machdep_ppc_32_diab"; "machdep"; "cil_const"; "logic_env"; "escape"; "logic_const"; "cil"; "errorloc"; "cabs"; "expcompare"; "cabshelper"; "whitetrack"; "logic_utils"; "logic_builtin"; "logic_print"; "logic_parser"; "logic_lexer"; "lexerhack"; "mergecil"; "rmtmps"; "logic_typing"; "cprint"; "cabscond"; "cabsvisit"; "cabs2cil"; "clexer"; "cparser"; "logic_preprocess"; "patch"; "frontc"; "obfuscate"; "ciltools"; "callgraph"; "dataflow"; "dominators"; "oneret"; "cfg"; "usedef"; "liveness"; "reachingdefs"; "availexpslv"; "rmciltmps"; "deadcodeelim"; "zrapp"; "buckx"; "dynamic"; "ast_printer"; "ast_info"; "kernel_datatype"; "plugin"; "kernel"; "alarms"; "cilE"; "binary_cache"; "parameters"; "messages"; "ast"; "my_bigint"; "hptmap"; "hptset"; "abstract_interp"; "int_Base"; "unicode"; "bit_utils"; "subst"; "annotations"; "globals"; "kernel_function"; "service_graph"; "ival"; "base"; "base_Set_Lattice"; "origin"; "map_Lattice"; "abstract_value"; "locations"; "shifted_Location"; "path_lattice"; "int_Interv"; "int_Interv_Map"; "new_offsetmap"; "offsetmap"; "offsetmap_bitwise"; "lmap"; "lmap_bitwise"; "lmap_whole"; "function_Froms"; "cvalue_type"; "widen_type"; "relations_type"; "state_set"; "state_imp"; "stmts_graph"; "visitor"; "printer"; "unroll_loops"; "loop"; "property"; "properties_status"; "inout_type"; "pdgIndex"; "pdgTypes"; "pdgMarks"; "slicingInternals"; "slicingTypes"; "db"; "command"; "task"; "translate_lightweight"; "file"; "filter"; "special_hooks"; "widen"; "bit_model_access"; "logic_interp"; "infer_annotations"; "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "RteGen"; "Report"; "From"; "Users"; "Constant_Propagation"; "Postdominators"; "Inout"; "Semantic_callgraph"; "Impact"; "Pdg"; "Scope"; "Sparecode"; "Slicing"; "boot"; "dgraph"; "viewgraph"; "gui_parameters"; "gtk_form"; "gtk_helper"; "source_viewer"; "pretty_source"; "source_manager"; "warning_manager"; "filetree"; "launcher"; "menu_manager"; "design"; "analyses_manager"; "file_manager"; "project_manager"; "debug_manager"; "help_manager"; "property_navigator"; "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "From"; "Impact"; "Scope"; "Slicing" ] +let compilation_unit_names = [ "unmarshal"; "unmarshal_nums"; "printexc_common_interface"; "map_common_interface"; "dynlink_common_interface"; "structural_descr"; "type"; "descr"; "extlib"; "pretty_utils"; "hook"; "bag"; "bitvector"; "qstack"; "my_bigint"; "config"; "gui_init"; "log"; "cmdline"; "project_skeleton"; "datatype"; "journal"; "parameter"; "dynamic"; "rangemap"; "state"; "state_dependency_graph"; "state_topological"; "state_selection"; "project"; "dashtbl"; "state_builder"; "plugin"; "kernel"; "emitter"; "binary_cache"; "hptmap"; "hptset"; "cilmsg"; "alpha"; "clist"; "growArray"; "inthash"; "cil_datatype"; "cilutil"; "setWithNearest"; "cil_state_builder"; "utf8_logic"; "cilglobopt"; "machdep_x86_16"; "machdep_x86_32"; "machdep_x86_64"; "machdep_ppc_32"; "machdep"; "cil_const"; "logic_env"; "escape"; "logic_const"; "cil"; "errorloc"; "cabs"; "expcompare"; "cabshelper"; "whitetrack"; "logic_utils"; "logic_builtin"; "logic_print"; "logic_parser"; "logic_lexer"; "lexerhack"; "mergecil"; "rmtmps"; "logic_typing"; "cprint"; "cabscond"; "cabsvisit"; "cabs2cil"; "clexer"; "cparser"; "logic_preprocess"; "frontc"; "obfuscate"; "ciltools"; "callgraph"; "dataflow"; "dominators"; "oneret"; "cfg"; "usedef"; "liveness"; "reachingdefs"; "availexpslv"; "rmciltmps"; "deadcodeelim"; "buckx"; "ast_info"; "ast_printer"; "ast"; "property"; "property_status"; "annotations"; "globals"; "kernel_function"; "description"; "alarms"; "cilE"; "messages"; "abstract_interp"; "lattice_Interval_Set"; "int_Base"; "unicode"; "bit_utils"; "subst"; "service_graph"; "ival"; "base"; "base_Set_Lattice"; "origin"; "map_Lattice"; "abstract_value"; "locations"; "shifted_Location"; "path_lattice"; "int_Interv"; "int_Interv_Map"; "tr_offset"; "new_offsetmap"; "offsetmap"; "offsetmap_bitwise"; "lmap"; "lmap_bitwise"; "function_Froms"; "cvalue"; "widen_type"; "state_set"; "state_imp"; "stmts_graph"; "visitor"; "printer"; "unroll_loops"; "loop"; "inout_type"; "pdgIndex"; "pdgTypes"; "pdgMarks"; "slicingInternals"; "slicingTypes"; "db"; "command"; "task"; "translate_lightweight"; "file"; "filter"; "special_hooks"; "widen"; "bit_model_access"; "logic_interp"; "infer_annotations"; "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "RteGen"; "From"; "Users"; "Constant_Propagation"; "Postdominators"; "Inout"; "Semantic_callgraph"; "Impact"; "Pdg"; "Scope"; "Sparecode"; "Slicing"; "boot"; "dgraph"; "gui_parameters"; "gtk_form"; "gtk_helper"; "source_viewer"; "pretty_source"; "source_manager"; "book_manager"; "warning_manager"; "filetree"; "launcher"; "menu_manager"; "history"; "design"; "analyses_manager"; "file_manager"; "project_manager"; "debug_manager"; "help_manager"; "property_navigator"; "Occurrence"; "Metrics"; "Syntactic_callgraph"; "Value"; "From"; "Impact"; "Scope"; "Slicing" ] let dot = Some "dot" diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/db.ml frama-c-20111001+nitrogen+dfsg/src/kernel/db.ml --- frama-c-20110201+carbon+dfsg/src/kernel/db.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/db.ml 2011-10-10 08:38:09.000000000 +0000 @@ -24,7 +24,6 @@ open Cil_types open Cil open Cil_datatype -open Db_types open Extlib type 'a how_to_journalize = @@ -138,16 +137,16 @@ - over-approximation of zones whose input values are read by each function, State_builder.of sure outputs - under-approximation of zones written by each function. *) -module InOutContext = struct +module Operational_inputs = struct type t = Inout_type.t let self_internal = ref State.dummy let self_external = ref State.dummy - let compute = mk_fun "InOutContext.compute" - let display = mk_fun "InOutContext.display" - let get_internal = mk_fun "InOutContext.get_internal" - let get_external = mk_fun "InOutContext.get_external" - let statement = mk_fun "InOutContext.statement" - let expr = mk_fun "InOutContext.expr" + let compute = mk_fun "Operational_inputs.compute" + let display = mk_fun "Operational_inputs.display" + let get_internal = mk_fun "Operational_inputs.get_internal" + let get_external = mk_fun "Operational_inputs.get_external" + let statement = mk_fun "Operational_inputs.statement" + let expr = mk_fun "Operational_inputs.expr" let kinstr ki = match ki with | Kstmt s -> Some (!statement s) | Kglobal -> None @@ -186,21 +185,21 @@ (* ************************************************************************* *) module Value = struct - type state = Relations_type.Model.t - type t = Cvalue_type.V.t + type state = Cvalue.Model.t + type t = Cvalue.V.t let reset_deps self = Project.clear ~selection:(State_selection.Dynamic.only_dependencies self) () (* Arguments of the root function of the value analysis *) - module ListArgs = Datatype.List(Cvalue_type.V) + module ListArgs = Datatype.List(Cvalue.V) module FunArgs = State_builder.Option_ref (ListArgs) (struct - let name = "Db.Value.fun_args" + let name = "Db.Value.fun_args" let dependencies = - [ Ast.self; Parameters.LibEntry.self; Parameters.MainFunction.self] + [ Ast.self; Kernel.LibEntry.self; Kernel.MainFunction.self] let kind = `Internal end) @@ -211,18 +210,18 @@ (* This function is *not* journalized *) let fun_set_args = - let module L = Datatype.List(Cvalue_type.V) in + let module L = Datatype.List(Cvalue.V) in Journal.register "(failwith \"Function cannot be journalized: \ Db.Value.fun_set_args\" : _ -> unit)" (Datatype.func L.ty Datatype.unit) (fun l -> if - not - (Extlib.opt_equal ListArgs.equal (Some l) (FunArgs.get_option ())) + not + (Extlib.opt_equal ListArgs.equal (Some l) (FunArgs.get_option ())) then begin - reset_deps FunArgs.self; - FunArgs.set l - end) + reset_deps FunArgs.self; + FunArgs.set l + end) let fun_use_default_args = @@ -236,10 +235,10 @@ (* Initial memory state of the value analysis *) module VGlobals = State_builder.Option_ref - (Relations_type.Model) + (Cvalue.Model) (struct - let name = "Db.Value.Vglobals" - let dependencies = [Ast.self] + let name = "Db.Value.Vglobals" + let dependencies = [Ast.self] let kind = `Internal end) @@ -247,15 +246,15 @@ let globals_set_initial_state = Journal.register "(failwith \"Function cannot be journalized: \ Db.Value.globals_set_initial_state\" : _ -> unit)" - (Datatype.func Relations_type.Model.ty Datatype.unit) + (Datatype.func Cvalue.Model.ty Datatype.unit) (fun state -> - if not (Extlib.opt_equal Relations_type.Model.equal - (Some state) - (VGlobals.get_option ())) + if not (Extlib.opt_equal Cvalue.Model.equal + (Some state) + (VGlobals.get_option ())) then begin - reset_deps VGlobals.self; - VGlobals.set state - end) + reset_deps VGlobals.self; + VGlobals.set state + end) let globals_use_default_initial_state = @@ -274,14 +273,11 @@ let globals_use_supplied_state () = not (VGlobals.get_option () = None) + (* Do NOT add dependencies to Kernel parameters here, but at the top of + Value/Value_parameters *) let dependencies = [ Ast.self; - Parameters.MainFunction.self; - Parameters.LibEntry.self; Alarms.self; - Parameters.AbsoluteValidRange.self; - Parameters.Overflow.self; - Parameters.SafeArrays.self; Annotations.self; FunArgs.self; VGlobals.self; @@ -289,16 +285,28 @@ let size = 1789 module Table = - Cil_state_builder.Kinstr_hashtbl - (Relations_type.Model) + Cil_state_builder.Stmt_hashtbl + (Cvalue.Model) (struct - let name = "Value analysis results" - let size = size - let dependencies = dependencies + let name = "Value analysis results" + let size = size + let dependencies = dependencies let kind = `Correctness end) + + module AfterTable = + Cil_state_builder.Stmt_hashtbl(Cvalue.Model) + (struct + let name = "Value analysis after states" + let dependencies = [Table.self] + let kind = `Correctness + let size = size + end) + + let self = Table.self + let only_self = [ self ] let mark_as_computed = Journal.register "Db.Value.mark_as_computed" @@ -307,63 +315,111 @@ let is_computed () = Table.is_computed () + module Conditions_table = + Cil_state_builder.Stmt_hashtbl + (Datatype.Int) + (struct + let name = "Conditions statuses" + let size = 101 + let dependencies = only_self + let kind = `Correctness + end) + + let merge_conditions h = + Cil_datatype.Stmt.Hashtbl.iter + (fun stmt v -> + try + let old = Conditions_table.find stmt in + Conditions_table.replace stmt (old lor v) + with Not_found -> + Conditions_table.add stmt v) + h + + let mask_then = 1 + let mask_else = 2 + + let condition_truth_value s = + try + let i = Conditions_table.find s in + ((i land mask_then) <> 0, (i land mask_else) <> 0) + with Not_found -> false, false + + module RecursiveCallsFound = + State_builder.Set_ref + (Kernel_function.Set) + (struct + let name = "Db.Value.RecursiveCallsFound" + let dependencies = only_self + let kind = `Correctness + end) + + let ignored_recursive_call kf = + RecursiveCallsFound.mem kf + + let recursive_call_occurred kf = + RecursiveCallsFound.add kf + module Called_Functions = Cil_state_builder.Varinfo_hashtbl - (Relations_type.Model) + (Cvalue.Model) (struct - let name = "called_functions" - let size = 11 - let dependencies = [self] + let name = "called_functions" + let size = 11 + let dependencies = only_self let kind = `Internal end) +(* let pretty_table () = Table.iter (fun k v -> Kernel.log ~kind:Log.Debug - "GLOBAL TABLE at %a: %a@\n" + "GLOBAL TABLE at %a: %a@\n" Kinstr.pretty k - Relations_type.Model.pretty v) + Cvalue.Model.pretty v) let pretty_table_raw () = Kinstr.Hashtbl.iter (fun k v -> Kernel.log ~kind:Log.Debug - "GLOBAL TABLE at %a: %a@\n" + "GLOBAL TABLE at %a: %a@\n" Kinstr.pretty k - Relations_type.Model.pretty v) + Cvalue.Model.pretty v) +*) + + type callstack = (kernel_function * kinstr) list module Record_Value_Callbacks = Hook.Build (struct - type t = (kernel_function * kinstr) list * state Kinstr.Hashtbl.t + type t = (kernel_function * kinstr) list * (state Stmt.Hashtbl.t) Lazy.t end) module Record_Value_After_Callbacks = Hook.Build (struct - type t = (kernel_function * kinstr) list * state Stmt.Hashtbl.t + type t = (kernel_function * kinstr) list * (state Stmt.Hashtbl.t) Lazy.t end) module Record_Value_Superposition_Callbacks = Hook.Build (struct - type t = (kernel_function * kinstr) list * State_set.t Kinstr.Hashtbl.t + type t = (kernel_function * kinstr) list * (State_set.t Stmt.Hashtbl.t) Lazy.t end) module Call_Value_Callbacks = Hook.Build - (struct type t = state * (Db_types.kernel_function * kinstr) list end) + (struct type t = state * (kernel_function * kinstr) list end) - let update_table k v = + let update_table s v = try - let old = Table.find k in + let old = Table.find s in (* Hptmap.debug := true; *) - let joined = Relations_type.Model.join old v in + let joined = Cvalue.Model.join old v in (* Hptmap.debug := false; *) - Table.replace k joined; + Table.replace s joined; with - Not_found -> Table.add k v + Not_found -> Table.add s v let map2_while_possible f l1 l2 = let rec go l1 l2 acc = @@ -378,7 +434,7 @@ let vi = Kernel_function.get_vi kf in try let old = Called_Functions.find vi in - Called_Functions.replace vi (Relations_type.Model.join old state) + Called_Functions.replace vi (Cvalue.Model.join old state) with Not_found -> Called_Functions.add vi state @@ -386,24 +442,37 @@ try Called_Functions.find (Kernel_function.get_vi kf) with Not_found -> - Relations_type.Model.bottom + Cvalue.Model.bottom let valid_behaviors = mk_fun "Value.get_valid_behaviors" + let add_formals_to_state = mk_fun "add_formals_to_state" + + let noassert_get_stmt_state s = + try Table.find s with Not_found -> Cvalue.Model.bottom + + let noassert_get_state k = + match k with + | Kglobal -> globals_state () + | Kstmt s -> noassert_get_stmt_state s + + let get_stmt_state s = + assert (is_computed ()); (* this assertion fails during value analysis *) + noassert_get_stmt_state s + let get_state k = assert (is_computed ()); (* this assertion fails during value analysis *) - try Table.find k with Not_found -> Relations_type.Model.bottom + noassert_get_state k - let noassert_get_state k = - try Table.find k with Not_found -> Relations_type.Model.bottom + let is_reachable = Cvalue.Model.is_reachable - let is_accessible stmt = - let st = get_state stmt in - Relations_type.Model.is_reachable st + let is_accessible ki = + let st = get_state ki in + Cvalue.Model.is_reachable st - let is_reachable = Relations_type.Model.is_reachable + let is_reachable_stmt stmt = + Cvalue.Model.is_reachable (get_stmt_state stmt) - let is_reachable_stmt stmt = is_reachable (get_state (Kstmt stmt)) let is_called = mk_fun "Value.is_called" let callers = mk_fun "Value.callers" @@ -411,7 +480,7 @@ let access_location = mk_fun "Value.access_location" let find = - Relations_type.Model.find + Cvalue.Model.find ~with_alarms:CilE.warn_none_mode ~conflate_bottom:true @@ -422,9 +491,19 @@ let access_location_after = mk_fun "Value.access_location_after" let update = mk_fun "Value.update" + (** Type for a Value builtin function *) + type builtin_sig = + state -> + (Cil_types.exp * Cvalue.V.t * Cvalue.V_Offsetmap.t) list -> + (Cvalue.V_Offsetmap.t option * state * Locations.Location_Bits.Top_Param.t) + + exception Outside_builtin_possibilities let register_builtin = mk_fun "Value.record_builtin" let mem_builtin = mk_fun "Value.mem_builtin" + let use_spec_instead_of_definition = + mk_fun "Value.use_spec_instead_of_definition" + let eval_lval = ref (fun ~with_alarms:_ _ -> not_yet_implemented "Value.eval_lval") let eval_expr = @@ -438,60 +517,46 @@ let pretty_filter = mk_fun "Value.pretty_filter" - let pretty_state = Relations_type.Model.pretty - let pretty_state_without_null = Relations_type.Model.pretty_without_null + let pretty_state = Cvalue.Model.pretty + let pretty_state_without_null = Cvalue.Model.pretty_without_null - let pretty = Cvalue_type.V.pretty + let pretty = Cvalue.V.pretty let display fmt kf = let refilter base = match base with - Base.Var (v, _) -> + Base.Var (v, _) -> if v.vgenerated - then v.vname = "__retres" - else - ((not (Kernel_function.is_local v kf)) + then v.vname = "__retres" + else + ((not (Kernel_function.is_local v kf)) || List.exists (fun x -> x.vid = v.vid) (Kernel_function.get_definition kf).sbody.blocals ) | _ -> true in - let values = get_state (Kstmt (Kernel_function.find_return kf)) in try - let fst_values = get_state (Kstmt (Kernel_function.find_first_stmt kf)) in - if Relations_type.Model.is_reachable fst_values then begin - Format.fprintf fmt "@[Values for function %s:@\n" + let values = get_stmt_state (Kernel_function.find_return kf) in + let fst_values = get_stmt_state (Kernel_function.find_first_stmt kf) in + if Cvalue.Model.is_reachable fst_values + && not (Cvalue.Model.is_top fst_values) + then begin + Format.fprintf fmt "@[Values for function %s:@\n" (Kernel_function.get_name kf); - let try_to_filter = - not (Parameters.Dynamic.Bool.get "-mem-exec-all") && - (Datatype.String.Set.is_empty - (Parameters.Dynamic.StringSet.get "-mem-exec")) - in - if try_to_filter then - let outs = !Outputs.get_internal kf in - if Relations_type.Model.is_top values && - (Locations.Zone.equal Locations.Zone.top outs) - then Format.fprintf fmt "No information available@\n" - else - Relations_type.Model.pretty_filter fmt values outs refilter; - else - Relations_type.Model.pretty fmt values; - (* (match kf.internal_out with - | Some _ when try_to_filter -> - let outs = !Outputs.get_internal kf in - Relations_type.Model.pretty_filter fmt values outs - | _ -> if try_to_filter then - warn "whacky situation: displaying without filtering. You may have interrupted the computations."; - Relations_type.Model.pretty fmt values);*) - Format.fprintf fmt "@]@\n" - end + if Cvalue.Model.is_top values + then Format.fprintf fmt "NO INFORMATION" + else + let outs = !Outputs.get_internal kf in + Cvalue.Model.pretty_filter fmt values outs refilter; + Format.fprintf fmt "@]@\n" + end with Kernel_function.No_Statement -> () let display_globals fmt () = let values = globals_state () in - if Relations_type.Model.is_reachable values + if Cvalue.Model.is_reachable values then begin Format.fprintf fmt "@[Values of globals at initialization @\n"; - Relations_type.Model.pretty_without_null fmt values; + Cvalue.Model.pretty_without_null fmt values; Format.fprintf fmt "@]@\n" end @@ -506,9 +571,10 @@ let call_to_kernel_function call_stmt = match call_stmt.skind with | Instr (Call (_, fexp, _, _)) -> - let _, called_functions = !expr_to_kernel_function - ~with_alarms:CilE.warn_none_mode ~deps:None - (Kstmt call_stmt) fexp + let _, called_functions = + !expr_to_kernel_function + ~with_alarms:CilE.warn_none_mode ~deps:None + (Kstmt call_stmt) fexp in called_functions | _ -> raise Not_a_call @@ -526,22 +592,30 @@ exception Void_Function let find_return_loc kf = - let ki = Kernel_function.find_return kf in - let lval = match ki with - | { skind = Return (Some ({enode = Lval ((_ , offset) as lval)}), _) } -> - assert (offset = NoOffset) ; - lval - | { skind = Return (None, _) } -> raise Void_Function - | _ -> assert false - in !lval_to_loc (Kstmt ki) ~with_alarms:CilE.warn_none_mode lval + try + let ki = Kernel_function.find_return kf in + let lval = match ki with + | { skind = Return (Some ({enode = Lval ((_ , offset) as lval)}), _) } + -> + assert (offset = NoOffset) ; + lval + | { skind = Return (None, _) } -> raise Void_Function + | _ -> assert false + in + !lval_to_loc (Kstmt ki) ~with_alarms:CilE.warn_none_mode lval + with Kernel_function.No_Statement -> + (* [JS 2011/05/17] should be better to have another name for this + exception or another one since it is possible to have no return without + returning void (the case when the kf corresponds to a declaration *) + raise Void_Function exception Aborted let degeneration_occurred = ref (fun _kf _lv -> - if not (Parameters.Dynamic.Bool.get "-propagate-top") - then raise Aborted) + if not (Dynamic.Parameter.Bool.get "-propagate-top" ()) + then raise Aborted) end @@ -561,11 +635,11 @@ module Record_From_Callbacks = Hook.Build (struct - type t = - (Kernel_function.t Stack.t) * - Lmap_bitwise.From_Model.t Inthash.t * - (Kernel_function.t * Lmap_bitwise.From_Model.t) list - Kinstr.Hashtbl.t + type t = + (Kernel_function.t Stack.t) * + Lmap_bitwise.From_Model.t Stmt.Hashtbl.t * + (Kernel_function.t * Lmap_bitwise.From_Model.t) list + Stmt.Hashtbl.t end) module Callwise = struct @@ -598,7 +672,6 @@ exception Top = PdgTypes.Pdg.Top exception Bottom = PdgTypes.Pdg.Bottom - exception NotFound = PdgIndex.NotFound let self = ref State.dummy @@ -667,8 +740,8 @@ let extract = mk_fun "Pdg.extract" let pretty = ref (fun ?(bw:_) _ _ -> - ignore(bw); - not_yet_implemented "Pdg.pretty") + ignore(bw); + not_yet_implemented "Pdg.pretty") let pretty_node = mk_fun "Pdg.pretty_node" let pretty_key = mk_fun "Pdg.pretty_key" @@ -692,7 +765,7 @@ let rm_asserts = mk_fun "Datascope.rm_asserts" let get_defs = mk_fun "Datascope.get_defs" - type t_zones = Locations.Zone.t Inthash.t + type t_zones = Locations.Zone.t Stmt.Hashtbl.t let build_zones = mk_fun "Pdg.build_zones" let pretty_zones = mk_fun "Pdg.pretty_zones" let get_zones = mk_fun "Pdg.get_zones" @@ -725,7 +798,7 @@ let set_modes = ref (fun ?calls:_ ?callers:_ ?sliceUndef:_ ?keepAnnotations:_ - ?print:_ _ -> not_yet_implemented "Slicing.set_modes") + ?print:_ _ -> not_yet_implemented "Slicing.set_modes") (* TODO: merge with frama-c projects (?) *) module Project = struct @@ -737,10 +810,10 @@ let pretty = mk_fun "Slicing.Project.pretty" let print_extracted_project = ref (fun ?fmt:_ ~extracted_prj:_ -> - not_yet_implemented "Slicing.Project.print_extracted_project") + not_yet_implemented "Slicing.Project.print_extracted_project") let print_dot = ref (fun ~filename:_ ~title:_ _ -> - not_yet_implemented "Slicing.Project.print_dot") + not_yet_implemented "Slicing.Project.print_dot") let get_all = mk_fun "Slicing.Project.get_all" let get_project = mk_fun "Slicing.Project.get_project" @@ -765,7 +838,7 @@ let pretty = mk_fun "Slicing.Mark.pretty" let make = ref - (fun ~data:_ ~addr:_ ~ctrl:_ -> not_yet_implemented "Slicing.Mark.make") + (fun ~data:_ ~addr:_ ~ctrl:_ -> not_yet_implemented "Slicing.Mark.make") let is_bottom = mk_fun "Slicing.Mark.is_bottom" let is_spare = mk_fun "Slicing.Mark.is_spare" let is_ctrl = mk_fun "Slicing.Mark.is_ctrl" @@ -777,8 +850,8 @@ module Select = struct type t = SlicingTypes.sl_select let dyn_t = SlicingTypes.Sl_select.ty - type t_set = SlicingTypes.Fct_user_crit.t SlicingTypes.Sl_selects.t - module S = SlicingTypes.Sl_selects.Make(SlicingTypes.Fct_user_crit) + type t_set = SlicingTypes.Fct_user_crit.t Cil_datatype.Varinfo.Map.t + module S = Cil_datatype.Varinfo.Map.Make(SlicingTypes.Fct_user_crit) let dyn_t_set = S.ty let get_function = mk_fun "Slicing.Select.get_function" @@ -803,7 +876,7 @@ Journal.register "Db.Slicing.Select.empty_selects" dyn_t_set - SlicingTypes.Sl_selects.empty + Cil_datatype.Varinfo.Map.empty let add_to_selects_internal = mk_fun "Slicing.Select.add_to_selects_internal" let iter_selects_internal = @@ -945,9 +1018,9 @@ module To_zone = struct type t_ctx = - { state_opt: bool option; - ki_opt: (stmt * bool) option; - kf:Kernel_function.t } + { state_opt: bool option; + ki_opt: (stmt * bool) option; + kf:Kernel_function.t } let mk_ctx_func_contrat = mk_fun "Interp.To_zone.mk_ctx_func_contrat" let mk_ctx_stmt_contrat = mk_fun "Interp.To_zone.mk_ctx_stmt_contrat" let mk_ctx_stmt_annot = mk_fun "Interp.To_zone.mk_ctx_stmt_annot" @@ -955,8 +1028,8 @@ type t_zone_info = (t list) option type t_decl = Varinfo.Set.t type t_pragmas = - { ctrl: Stmt.Set.t; - stmt: Stmt.Set.t } + { ctrl: Stmt.Set.t; + stmt: Stmt.Set.t } let from_term = mk_fun "Interp.To_zone.from_term" let from_terms= mk_fun "Interp.To_zone.from_terms" let from_pred = mk_fun "Interp.To_zone.from_pred" @@ -973,49 +1046,9 @@ mk_fun "Properties.Interp.to_result_from_pred" end - let add_assert kf kinstr states ~before prop = - let interp_prop = User (!Interp.code_annot kf kinstr ~before prop) in - let localized = - if before then Before interp_prop else After interp_prop - in - Annotations.add kinstr states localized - - let add_alarm _kf ki states (alarm_type,annot,_status) = - let old_annots = - List.fold_left - (fun acc s -> Annotations.get_annotations ki s @ acc) [] states - in - if List.for_all - (function - | Before (AI (a_t,old_annot)) when a_t = alarm_type -> - not (Logic_utils.is_same_code_annotation old_annot annot) - | _ -> true) - old_annots - then begin - Annotations.add ki states (Before (AI (alarm_type,annot))); - (* TODO: use status*) - end - - module Status = - Properties_status.Make_updater - (struct - let name = "alarm" - let emitter = Alarms.self - end) - - let synchronize_alarms states = - Alarms.iter - (fun ki (_,ca,st as alarm) -> - match ki with - | Kglobal -> - CilE.warn_once "global alarm occured. Check the log above." - | Kstmt stmt -> - let kf = Kernel_function.find_englobing_kf in - add_alarm kf stmt states alarm; - let ip = Property.ip_of_code_annot (kf stmt) stmt ca in - List.iter (fun x -> Status.set x [] st.status) ip - ); - Alarms.clear () + let add_assert kf kinstr states prop = + let interp_prop = User (!Interp.code_annot kf kinstr prop) in + Annotations.add kf kinstr states interp_prop end @@ -1023,12 +1056,6 @@ (** {2 Others plugins} *) (* ************************************************************************* *) -module Miel = struct - let extract_all = mk_fun "Miel.extract_all" - let run_gui = mk_fun "Miel.run_gui" - let gui_present = ref false -end - module Impact = struct let compute_pragmas = mk_fun "Impact.compute_pragmas" let from_stmt = mk_fun "Impact.from_stmt" @@ -1051,6 +1078,11 @@ end module RteGen = struct + type status_accessor = + State.t + * (kernel_function -> State.t) + * (kernel_function -> bool) + * (kernel_function -> bool -> unit) let compute = mk_fun "RteGen.compute" let is_computed = mk_fun "RteGen.is_computed" let annotate_kf = mk_fun "RteGen.annotate_kf" @@ -1080,17 +1112,42 @@ let dump = mk_fun "Syntactic_callgraph.dump" end + +module PostdominatorsTypes = struct + exception Top + + module type Sig = sig + val compute: (kernel_function -> unit) ref + val stmt_postdominators: + (kernel_function -> stmt -> Stmt.Hptset.t) ref + val is_postdominator: + (kernel_function -> opening:stmt -> closing:stmt -> bool) ref + val display: (unit -> unit) ref + val print_dot : (string -> kernel_function -> unit) ref + end +end + + module Postdominators = struct let compute = mk_fun "Postdominators.compute" let is_postdominator : (kernel_function -> opening:stmt -> closing:stmt -> bool) ref = mk_fun "Postdominators.is_postdominator" - exception Top let stmt_postdominators = mk_fun "Postdominators.stmt_postdominators" let display = mk_fun "Postdominators.display" let print_dot = mk_fun "Postdominators.print_dot" end +module PostdominatorsValue = struct + let compute = mk_fun "PostdominatorsValue.compute" + let is_postdominator + : (kernel_function -> opening:stmt -> closing:stmt -> bool) ref + = mk_fun "PostdominatorsValue.is_postdominator" + let stmt_postdominators = mk_fun "PostdominatorsValue.stmt_postdominators" + let display = mk_fun "PostdominatorsValue.display" + let print_dot = mk_fun "PostdominatorsValue.print_dot" +end + module Dominators = struct let compute = mk_fun "Dominators.compute" let is_dominator @@ -1105,22 +1162,20 @@ module Metrics = struct type t = { sloc: int; - call_statements: int; - goto_statements: int; - assign_statements: int; - if_statements: int; - loop_statements: int; - mem_access: int; - functions_without_source: int Varinfo.Hashtbl.t; - functions_with_source: int Varinfo.Hashtbl.t; - (* ABP added 2 fields below for plugin metrics *) - function_definitions: int; - cyclos: int; + call_statements: int; + goto_statements: int; + assign_statements: int; + if_statements: int; + loop_statements: int; + mem_access: int; + functions_without_source: int Varinfo.Map.t; + functions_with_source: int Varinfo.Map.t; + (* ABP added 2 fields below for plugin metrics *) + function_definitions: int; + cyclos: int; } let compute = mk_fun "Metrics.compute" let pretty = mk_fun "Metrics.pretty" - let dump = mk_fun "Metrics.dump" - let last_result = mk_fun "Metrics.last_result" end (* ************************************************************************* *) @@ -1142,15 +1197,15 @@ try !Semantic_Callgraph.iter_on_callers (fun caller -> - let formal_or_local = - (Base.is_formal_or_local v (Kernel_function.get_definition caller)) - in - (*Format.printf "Caller of %s: %s variable %a formal_or_local: %b@." - (Kernel_function.get_name kf) - (Kernel_function.get_name f) - Base.pretty v - formal_or_local ;*) - if formal_or_local then raise Stop) + let formal_or_local = + (Base.is_formal_or_local v (Kernel_function.get_definition caller)) + in + (*Format.printf "Caller of %s: %s variable %a formal_or_local: %b@." + (Kernel_function.get_name kf) + (Kernel_function.get_name f) + Base.pretty v + formal_or_local ;*) + if formal_or_local then raise Stop) kf; false with Stop -> true @@ -1159,29 +1214,33 @@ Base.is_global v || (let fol = - match kf.Db_types.fundec with - | Db_types.Definition (fundec,_) -> - Base.is_formal_or_local v fundec - | Db_types.Declaration (_,vd,_,_) -> - (Base.is_formal_of_prototype v vd) - in + match kf.fundec with + | Definition (fundec,_) -> + Base.is_formal_or_local v fundec + | Declaration (_,vd,_,_) -> + (Base.is_formal_of_prototype v vd) + in (* Format.printf "accept_base_internal %s: variable %a formal_or_local: %b@." - (Kernel_function.get_name kf) - Base.pretty v - fol;*) + (Kernel_function.get_name kf) + Base.pretty v + fol;*) fol ) || is_local_or_formal_of_caller v kf - let accept_base ~with_formals kf v = + let accept_base ~with_formals ~with_locals kf v = Base.is_global v - || (with_formals && - match kf.Db_types.fundec with - | Db_types.Definition (fundec,_) -> - Base.is_formal v fundec - | Db_types.Declaration (_,vd,_,_) -> - (Base.is_formal_of_prototype v vd)) + || + (match with_formals, with_locals, kf.fundec with + | false, false, _ -> false + + | true, false, Definition (fundec,_) -> Base.is_formal v fundec + | false, true, Definition (fundec, _) -> Base.is_local v fundec + | true, true, Definition (fundec, _) -> Base.is_formal_or_local v fundec + | false, _, Declaration _ -> false + | true , _, Declaration (_, vd, _, _) -> Base.is_formal_of_prototype v vd + ) || is_local_or_formal_of_caller v kf (* to here *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/db.mli frama-c-20111001+nitrogen+dfsg/src/kernel/db.mli --- frama-c-20110201+carbon+dfsg/src/kernel/db.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/db.mli 2011-10-10 08:38:09.000000000 +0000 @@ -42,7 +42,7 @@ - {!Stmts_graph}: the statement graph - {!Loop}: (natural) loops - {!Visitor}: frama-c visitors - - {!Parameters}: general parameters of Frama-C (mostly set from the command + - {!Kernel}: general parameters of Frama-C (mostly set from the command line) *) @@ -50,7 +50,6 @@ open Cil open Cilutil open Cil_datatype -open Db_types (* ************************************************************************* *) (** {2 Registering} *) @@ -63,13 +62,13 @@ (** Journalize the value with the given name and type. *) | Journalization_not_required (** Journalization of this value is not required - (usually because it has no effect on the Frama-C global state). *) + (usually because it has no effect on the Frama-C global state). *) | Journalization_must_not_happen of string (** Journalization of this value should not happen - (usually because it is a low-level function: this function is always - called from a journalized function). - The string is the function name which is used for displaying suitable - error message. *) + (usually because it is a low-level function: this function is always + called from a journalized function). + The string is the function name which is used for displaying suitable + error message. *) val register: 'a how_to_journalize -> 'a ref -> 'a -> unit (** Plugins must register values with this function. *) @@ -91,12 +90,12 @@ val extend : (unit -> unit) -> unit (** Register a function to be called by the Frama-C main entry point. - @plugin development guide *) + @plugin development guide *) val play: (unit -> unit) ref (** Run all the Frama-C analyses. This function should be called only by - toplevels. - @since Beryllium-20090901 *) + toplevels. + @since Beryllium-20090901 *) (**/**) val apply: unit -> unit @@ -109,8 +108,8 @@ val run: ((unit -> unit) -> unit) ref (** Run a Frama-C toplevel playing the game given in argument (in - particular, applying the argument runs the analyses). - @since Beryllium-20090901 *) + particular, applying the argument runs the analyses). + @since Beryllium-20090901 *) end @@ -138,55 +137,89 @@ @see <../value/index.html> internal documentation. *) module Value : sig - type state = Relations_type.Model.t + type state = Cvalue.Model.t (** Internal state of the value analysis. *) - type t = Cvalue_type.V.t + type t = Cvalue.V.t (** Internal representation of a value. *) exception Aborted val self : State.t - (** Internal state of the value analysis from project viewpoints. - @plugin development guide *) + (** Internal state of the value analysis from projects viewpoint. + @plugin development guide *) val mark_as_computed: unit -> unit (** Indicate that the value analysis has been done already. *) val compute : (unit -> unit) ref (** Compute the value analysis using the entry point of the current - project. You may set it with {!Globals.set_entry_point}. - @raise Globals.No_such_entry_point if the entry point is incorrect + project. You may set it with {!Globals.set_entry_point}. + @raise Globals.No_such_entry_point if the entry point is incorrect @raise Db.Value.Incorrect_number_of_arguments if some arguments are specified for the entry point using {!Db.Value.fun_set_args}, and an incorrect number of them is given. - @plugin development guide *) + @plugin development guide *) val is_computed: unit -> bool (** Return [true] iff the value analysis has been done. - @plugin development guide *) + @plugin development guide *) module Table: - State_builder.Hashtbl with type key = kinstr and type data = state - (** Table containing the results of the value analysis. *) + State_builder.Hashtbl with type key = stmt and type data = state + (** Table containing the results of the value analysis, ie. + the state before the evaluation of each reachable statement. *) + + module AfterTable: + State_builder.Hashtbl with type key = stmt and type data = state + (** Table containing the state of the value analysis after the evaluation + of each reachable and evaluable statement. Filled only if + [Value_parameters.ResultsAfter] is set. *) val degeneration_occurred: (Cil_types.kinstr -> Cil_types.lval option -> unit) ref (** This hook is called by the value analysis in the seldom case a total degeneration occurs. *) + val ignored_recursive_call: kernel_function -> bool + (** This functions returns true if the value analysis found and ignored + a recursive call to this function during the analysis. *) + + val condition_truth_value: stmt -> bool * bool + (** Provided [stmt] is an 'if' construct, [fst (condition_truth_value stmt)] + (resp. snd) is true if and only if the condition of the 'if' has been + evaluated to true (resp. false) at least once during the analysis. *) + (** {3 Parameterization} *) - val register_builtin: - (string -> - (state -> (Cil_types.exp * t * Cvalue_type.V_Offsetmap.t) list -> - (Cvalue_type.V_Offsetmap.t option * state * Locations.Location_Bits.Top_Param.t)) -> - unit) ref - (** [!record_builtin name f] registers an abstract function [f] to use - everytime a C function named [name] is called in the program *) + exception Outside_builtin_possibilities - val mem_builtin: - (string -> bool) ref + (** Type for a Value builtin function *) + type builtin_sig = + (** Memory state at the beginning of the function *) + state -> + (** Args for the function: the expressions corresponding to the formals + of the functions at the call site, the actual value of those formals, + and a more precise view of those formals using offsetmaps (for eg. + structs) *) + (Cil_types.exp * Cvalue.V.t * Cvalue.V_Offsetmap.t) list -> + (** Result of the function *) + (Cvalue.V_Offsetmap.t option (** the value returned (ie. what is + after the 'return' C keyword). *) + * state (** the memory state after the function has been executed *) + * Locations.Location_Bits.Top_Param.t (** An over-approximation of the + zones in which local variables might have been written *)) + + val register_builtin: (string -> builtin_sig -> unit) ref + (** [!record_builtin name ?override f] registers an abstract function [f] + to use everytime a C function named [name] is called in the program. + See also option [-val-builtin] *) + + val mem_builtin: (string -> bool) ref + val use_spec_instead_of_definition: (kernel_function -> bool) ref + (** To be called by derived analyses to determine if they must use + the body of the function (if available), or only its spec. Used for + value builtins, and option -val-use-spec. *) (** {4 Arguments of the main function} *) @@ -244,6 +277,7 @@ val get_initial_state : kernel_function -> state val get_state : kinstr -> state + val get_stmt_state : stmt -> state val find : state -> Locations.location -> t @@ -264,7 +298,7 @@ val find_lv_plus : (with_alarms:CilE.warn_mode -> - Relations_type.Model.t -> Cil_types.exp -> + Cvalue.Model.t -> Cil_types.exp -> (Cil_types.lval * Ival.t) list) ref (** returns the list of all decompositions of [expr] into the sum an lvalue and an interval. *) @@ -287,10 +321,15 @@ exception Not_a_call val call_to_kernel_function : stmt -> Kernel_function.Hptset.t (** Return the functions that can be called from this call. - @raise Not_a_call if the statement is not a call. *) + @raise Not_a_call if the statement is not a call. *) val valid_behaviors: (kernel_function -> state -> funbehavior list) ref + val add_formals_to_state: (state -> kernel_function -> exp list -> state) ref + (** [add_formals_to_state state kf exps] evaluates [exps] in [state] + and binds them to the formal arguments of [kf] in the resulting + state *) + (** {3 Reachability} *) val is_accessible : kinstr -> bool @@ -302,13 +341,13 @@ exception Void_Function val find_return_loc : kernel_function -> Locations.location (** Return the location of the returned lvalue of the given function. - @raise Void_Function is the function does not return any value. *) + @raise Void_Function if the function does not return any value. *) val is_called: (kernel_function -> bool) ref val callers: (kernel_function -> (kernel_function*stmt list) list) ref (** @return the list of callers with their call sites. Each function is - present only once in the list. *) + present only once in the list. *) (** {3 State before a kinstr} *) @@ -320,20 +359,20 @@ val access_after : (kinstr -> lval -> t) ref (** @raise Not_found if the kinstr has no accessible successors. - @deprecated since Carbon-20101202+dev Use + @deprecated since Carbon-20110201 Use {Record_Value_After_Callbacks} or ask for a better interface if you need this functionality *) val access_location_after : (kinstr -> Locations.location -> t) ref (** @raise Not_found if the kinstr has no accessible successors. - @deprecated since Carbon-20101202+dev Use + @deprecated since Carbon-20110201 Use {Record_Value_After_Callbacks} or ask for a better interface if you need this functionality *) val lval_to_offsetmap_after : - (kinstr -> lval -> Cvalue_type.V_Offsetmap.t option) ref + (kinstr -> lval -> Cvalue.V_Offsetmap.t option) ref (** @raise Not_found if the kinstr has no accessible successors. - @deprecated since Carbon-20101202+dev Use + @deprecated since Carbon-20110201 Use {Record_Value_After_Callbacks} or ask for a better interface if you need this functionality *) @@ -360,11 +399,11 @@ val lval_to_offsetmap : ( kinstr -> lval -> with_alarms:CilE.warn_mode -> - Cvalue_type.V_Offsetmap.t option) ref + Cvalue.V_Offsetmap.t option) ref val lval_to_offsetmap_state : - (state -> lval -> Cvalue_type.V_Offsetmap.t option) ref - (** @since Carbon-20101202+dev *) + (state -> lval -> Cvalue.V_Offsetmap.t option) ref + (** @since Carbon-20110201 *) val lval_to_zone : (kinstr -> with_alarms:CilE.warn_mode -> lval -> Locations.Zone.t) ref @@ -378,18 +417,17 @@ (** {3 Callbacks} *) + type callstack = (kernel_function * kinstr) list + (** Actions to perform at end of each function analysis. *) module Record_Value_Callbacks: - Hook.Iter_hook with type param = (kernel_function * kinstr) list - * state Kinstr.Hashtbl.t + Hook.Iter_hook with type param = callstack * (state Stmt.Hashtbl.t) Lazy.t module Record_Value_Superposition_Callbacks: - Hook.Iter_hook with type param = (kernel_function * kinstr) list - * State_set.t Kinstr.Hashtbl.t + Hook.Iter_hook with type param = callstack * (State_set.t Stmt.Hashtbl.t) Lazy.t module Record_Value_After_Callbacks: - Hook.Iter_hook with type param = (kernel_function * kinstr) list - * state Stmt.Hashtbl.t + Hook.Iter_hook with type param = callstack * (state Stmt.Hashtbl.t) Lazy.t (** Actions to perform at each treatment of a "call" statement. @plugin development guide *) @@ -405,22 +443,32 @@ val display : Format.formatter -> kernel_function -> unit val display_globals : Format.formatter -> unit -> unit + (**/**) (** {3 Internal use only} *) val noassert_get_state : kinstr -> state (** To be used during the value analysis itself (instead of - {!get_state}). *) + {!get_state}). *) + val noassert_get_stmt_state : stmt -> state + (** To be used during the value analysis itself (instead of + {!get_stmt_state}). *) + + val recursive_call_occurred: kernel_function -> unit + + val merge_conditions: int Cil_datatype.Stmt.Hashtbl.t -> unit + val mask_then: int + val mask_else: int val initial_state_only_globals : (unit -> state) ref - val update_table : kinstr -> state -> unit + val update_table : stmt -> state -> unit val memoize : (kernel_function -> unit) ref (* val compute_call : (kernel_function -> call_kinstr:kinstr -> state -> (exp*t) list - -> Cvalue_type.V_Offsetmap.t option (** returned value of [kernel_function] *) * state) ref + -> Cvalue.V_Offsetmap.t option (** returned value of [kernel_function] *) * state) ref *) val merge_initial_state : kernel_function -> state -> unit (** Store an additional possible initial state for the given function as - well as its values for actuals. *) + well as its values for actuals. *) end (** Functional dependencies between function inputs and function outputs. @@ -434,12 +482,13 @@ val is_computed: (kernel_function -> bool) ref (** Check whether the from analysis has been performed for the given - function. - @return true iff the analysis has been performed *) + function. + @return true iff the analysis has been performed *) val get : (kernel_function -> Function_Froms.t) ref - val access : (Locations.Zone.t -> from_model -> Locations.Zone.t) ref - val find_deps_no_transitivity : (kinstr -> exp -> Locations.Zone.t) ref + val access : (Locations.Zone.t -> Lmap_bitwise.From_Model.t + -> Locations.Zone.t) ref + val find_deps_no_transitivity : (stmt -> exp -> Locations.Zone.t) ref val self: State.t ref (** @plugin development guide *) @@ -451,14 +500,15 @@ (** {3 Internal use only} *) val update : - (Locations.location -> Locations.Zone.t -> from_model -> from_model) ref + (Locations.location -> Locations.Zone.t -> Lmap_bitwise.From_Model.t + -> Lmap_bitwise.From_Model.t) ref module Record_From_Callbacks: Hook.Iter_hook with type param = Kernel_function.t Stack.t * - Lmap_bitwise.From_Model.t Inthash.t * + Lmap_bitwise.From_Model.t Stmt.Hashtbl.t * (Kernel_function.t * Lmap_bitwise.From_Model.t) list - Kinstr.Hashtbl.t + Stmt.Hashtbl.t module Callwise : sig val iter : ((kinstr -> Function_Froms.t -> unit) -> unit) ref @@ -475,7 +525,7 @@ (** Do not use yet. *) module Access_path : sig type t = (Locations.Zone.t * Locations.Location_Bits.t) Base.Map.t - val compute: (Relations_type.Model.t -> Base.Set.t -> t) ref + val compute: (Cvalue.Model.t -> Base.Set.t -> t) ref val filter: (t -> Locations.Zone.t -> t) ref val pretty: (Format.formatter -> t -> unit) ref end @@ -522,11 +572,11 @@ left values. *) val identified_term_zone_to_loc: - (result: Cil_types.varinfo option -> Value.state -> + (result: Cil_types.varinfo option -> Value.state -> Cil_types.identified_term -> Locations.location) ref (** @return a Locations.Location - @raise Invalid_argument in some cases. - @deprecated Carbon-20101201-beta2+dev + @raise Invalid_argument in some cases. + @deprecated Carbon-20110201 use [loc_to_loc (...) x.it_content] instead *) @@ -534,7 +584,7 @@ (result: Cil_types.varinfo option -> Value.state -> term -> Locations.location) ref (** @return a Locations.Location @raise Invalid_argument in some cases. Complain if you'd like - more cases to be treated. *) + more cases to be treated. *) val loc_to_offset: (result: Cil_types.varinfo option -> term -> Cil_types.offset list) ref @@ -568,24 +618,24 @@ module To_zone : sig type t_ctx = - {state_opt:bool option; - ki_opt:(stmt * bool) option; - kf:Kernel_function.t} + {state_opt:bool option; + ki_opt:(stmt * bool) option; + kf:Kernel_function.t} val mk_ctx_func_contrat: - (kernel_function -> state_opt:bool option -> t_ctx) ref + (kernel_function -> state_opt:bool option -> t_ctx) ref (** To build an interpretation context relative to function - contracts. *) + contracts. *) val mk_ctx_stmt_contrat: - (kernel_function -> stmt -> state_opt:bool option -> t_ctx) ref + (kernel_function -> stmt -> state_opt:bool option -> t_ctx) ref (** To build an interpretation context relative to statement - contracts. *) + contracts. *) val mk_ctx_stmt_annot: - (kernel_function -> stmt -> before:bool -> t_ctx) ref + (kernel_function -> stmt -> t_ctx) ref (** To build an interpretation context relative to statement - annotations. *) + annotations. *) type t = {before:bool ; ki:stmt ; zone:Locations.Zone.t} type t_zone_info = (t list) option @@ -594,7 +644,7 @@ type t_decl = Varinfo.Set.t type t_pragmas = - {ctrl: Stmt.Set.t ; (* related to //@ slice pragma ctrl/expr *) + {ctrl: Stmt.Set.t ; (* related to //@ slice pragma ctrl/expr *) stmt: Stmt.Set.t} (* related to statement assign and //@ slice pragma stmt *) @@ -615,10 +665,10 @@ [predicates] relative to the [ctx] of interpretation. *) val from_zones: - (identified_term list -> t_ctx -> t_zone_info * t_decl) ref + (identified_term list -> t_ctx -> t_zone_info * t_decl) ref (** Entry point to get zones needed to evaluate the list of - [predicates] relative to the [ctx] of interpretation. - @deprecated Carbon-20101201-beta2+dev + [predicates] relative to the [ctx] of interpretation. + @deprecated Carbon-20110201 use [from_terms (..) x.it_content] instead *) @@ -627,73 +677,55 @@ the [ctx] of interpretation. *) val from_stmt_annot: - (code_annotation -> before:bool -> stmt * kernel_function - -> (t_zone_info * t_decl) * t_pragmas) ref + (code_annotation -> stmt * kernel_function + -> (t_zone_info * t_decl) * t_pragmas) ref (** Entry point to get zones needed to evaluate annotations of this [stmt]. - @deprecated Carbon-20101201-beta2+dev + @deprecated Carbon-20110201 use [from_terms (..) x.it_content] instead *) val from_stmt_annots: - ((rooted_code_annotation before_after -> bool) option -> - stmt * kernel_function -> (t_zone_info * t_decl) * t_pragmas) ref + ((rooted_code_annotation -> bool) option -> + stmt * kernel_function -> (t_zone_info * t_decl) * t_pragmas) ref (** Entry point to get zones needed to evaluate annotations of this - [stmt]. *) + [stmt]. *) val from_func_annots: - (((stmt -> unit) -> kernel_function -> unit) -> - (rooted_code_annotation before_after -> bool) option -> - kernel_function -> (t_zone_info * t_decl) * t_pragmas) ref + (((stmt -> unit) -> kernel_function -> unit) -> + (rooted_code_annotation -> bool) option -> + kernel_function -> (t_zone_info * t_decl) * t_pragmas) ref (** Entry point to get zones needed to evaluate annotations of this [kf]. *) val code_annot_filter: - (rooted_code_annotation before_after -> - ai:bool -> user_assert:bool -> slicing_pragma:bool -> + (rooted_code_annotation -> + ai:bool -> user_assert:bool -> slicing_pragma:bool -> loop_inv:bool -> loop_var:bool -> others:bool -> bool) ref (** To quickly build an annotation filter *) end - - (** Does the interpretation of the predicate rely on the intepretation - of the term result? - @since Carbon-20101202+dev *) + + (** Does the interpretation of the predicate rely on the intepretation + of the term result? + @since Carbon-20110201 *) val to_result_from_pred: (predicate named -> bool) ref - + (** {3 Internal use only} *) val code_annot : - (kernel_function -> stmt -> before:bool -> string -> code_annotation) + (kernel_function -> stmt -> string -> code_annotation) ref end - (** {3 Alarms} *) - - val synchronize_alarms : State.t list -> unit - (** Transform current set of alarms into code properties. This has to be - called at the end of an alarm generator. By example, this is - automatically called at the end of {!Db.Value.compute}. - @modify Boron-20100401 takes as additional argument the - computation which adds the assert. *) - - val add_alarm : - kernel_function -> stmt -> State.t list -> Alarms.alarm - -> unit - (** Emit an alarm. {!synchronize_alarms} must be called as soon as one - need to see the alarms as properties to be checked on the code. - @modify Boron-20100401 takes as additional argument the - computation which adds the assert. *) - (** {3 Assertions} *) val add_assert: - kernel_function -> stmt -> State.t list -> before:bool -> - string -> unit + kernel_function -> stmt -> State.t list -> string -> unit (** @modify Boron-20100401 takes as additional argument the - computation which adds the assert. *) + computation which adds the assert. *) end @@ -707,41 +739,54 @@ val dump: (unit -> unit) ref end -(** Postdominators plugin. - @see <../postdominators/index.html> internal documentation. *) -module Postdominators: sig - val compute: (kernel_function -> unit) ref + + +(** Declarations common to the various postdominators-computing modules *) +module PostdominatorsTypes: sig exception Top - (** Used for {!stmt_postdominators} when the postdominators of a statement - cannot be computed. It means that there is no path from this - statement to the function return. *) + (** Used for postdominators-related functions, when the + postdominators of a statement cannot be computed. It means that + there is no path from this statement to the function return. *) + + module type Sig = sig + val compute: (kernel_function -> unit) ref - val stmt_postdominators: - (kernel_function -> stmt -> Stmt.Set.t) ref + val stmt_postdominators: + (kernel_function -> stmt -> Stmt.Hptset.t) ref (** @raise Top (see above) *) - val is_postdominator: - (kernel_function -> opening:stmt -> closing:stmt -> bool) ref + val is_postdominator: + (kernel_function -> opening:stmt -> closing:stmt -> bool) ref - val display: (unit -> unit) ref + val display: (unit -> unit) ref - val print_dot : (string -> kernel_function -> unit) ref - (** Print a representation of the postdominators in a dot file - * which name is [basename.function_name.dot]. *) + val print_dot : (string -> kernel_function -> unit) ref + (** Print a representation of the postdominators in a dot file + whose name is [basename.function_name.dot]. *) + end end +(** Syntaxic postdominators plugin. + @see <../postdominators/index.html> internal documentation. *) +module Postdominators: PostdominatorsTypes.Sig + +(** Postdominators using value analysis results. + @see <../postdominators/index.html> internal documentation. *) +module PostdominatorsValue: PostdominatorsTypes.Sig + + (** Dominators plugin. @see <../postdominators/index.html> internal documentation. *) module Dominators: sig val compute: (kernel_function -> unit) ref exception Top - (** Used for {!stmt_postdominators} when the postdominators of a statement - cannot be computed. It means that there is no path from this - statement to the function return. *) + (** Used for {!stmt_dominators} when the dominators of a statement + cannot be computed. It means that there is no path from the + entry point to this statement. *) - val stmt_dominators: (kernel_function -> stmt -> Stmt.Set.t) ref + val stmt_dominators: (kernel_function -> stmt -> Stmt.Hptset.t) ref (** @raise Top (see above) *) val is_dominator: @@ -750,8 +795,8 @@ val display: (unit -> unit) ref val print_dot : (string -> kernel_function -> unit) ref - (** Print a representation of the postdominators in a dot file - * which name is [basename.function_name.dot]. *) + (** Print a representation of the dominators in a dot file + whose name is [basename.function_name.dot]. *) end (** Runtime Error Annotation Generation plugin. @@ -764,20 +809,21 @@ val self: State.t ref val do_precond : (kernel_function -> unit) ref val do_all_rte : (kernel_function -> unit) ref - val get_all_status : - (unit -> (State.t * (kernel_function -> State.t) * (kernel_function -> bool)) list) ref - val get_precond_status : - (unit -> State.t * (kernel_function -> State.t) * (kernel_function -> bool)) ref - val get_signedOv_status : - (unit -> State.t * (kernel_function -> State.t) * (kernel_function -> bool)) ref - val get_divMod_status : - (unit -> State.t * (kernel_function -> State.t) * (kernel_function -> bool)) ref - val get_downCast_status : - (unit -> State.t * (kernel_function -> State.t) * (kernel_function -> bool)) ref - val get_memAccess_status : - (unit -> State.t * (kernel_function -> State.t) * (kernel_function -> bool)) ref - val get_unsignedOv_status : - (unit -> State.t * (kernel_function -> State.t) * (kernel_function -> bool)) ref + + type status_accessor = + State.t (* the state itself *) + * (kernel_function -> State.t) (* the state of the kf *) + * (kernel_function -> bool) (* get the value of the state of the kf *) + * (kernel_function -> bool -> unit) + (* set the value of the state of the kf*) + + val get_all_status : (unit -> status_accessor list) ref + val get_precond_status : (unit -> status_accessor) ref + val get_signedOv_status : (unit -> status_accessor) ref + val get_divMod_status : (unit -> status_accessor) ref + val get_downCast_status : (unit -> status_accessor) ref + val get_memAccess_status : (unit -> status_accessor) ref + val get_unsignedOv_status : (unit -> status_accessor) ref end (** Dump Properties-Status consolidation tree. *) @@ -792,20 +838,15 @@ val get : (Datatype.String.Set.t -> cast_intro:bool -> Project.t) ref (** Propagate constant into the functions given by name. note: the propagation is performed into all functions when the set is - empty; and casts can be introduced when [cast_intro] is true. *) + empty; and casts can be introduced when [cast_intro] is true. *) val compute: (unit -> unit) ref (** Propage constant into the functions given by the parameters (in the - same way that {!get}. Then pretty print the resulting program. - @since Beryllium-20090901 *) + same way that {!get}. Then pretty print the resulting program. + @since Beryllium-20090901 *) end -module Miel : sig - val extract_all : (unit -> unit) ref - val run_gui : (unit -> unit) ref - val gui_present : bool ref -end (** Impact analysis. @see <../impact/index.html> internal documentation. *) @@ -814,7 +855,7 @@ (** Compute the impact analysis from the impact pragma in the program. Print and slice the results according to the parameters -impact-print and -impact-slice. - @plugin development guide *) + @plugin development guide *) val from_stmt: (stmt -> stmt list) ref (** Compute the impact analysis of the given statement. @return the impacted statement *) @@ -845,18 +886,13 @@ exception Bottom (** Raised by most function when the PDG is Bottom because we can hardly do - nothing with it. It happens when the function is unreachable because we - have no information about it. *) + nothing with it. It happens when the function is unreachable because we + have no information about it. *) exception Top (** Raised by most function when the PDG is Top because we can hardly do - nothing with it. It happens when we didn't manage to compute it, for - instance for a variadic function. *) - - exception NotFound - (** Raised by the [find_xxx] functions when the searched element is not in - the PDG. The most common reason is when it is an unreachable - statement. *) + nothing with it. It happens when we didn't manage to compute it, for + instance for a variadic function. *) type t = PdgTypes.Pdg.t (** PDG type *) @@ -866,13 +902,13 @@ type t_node_key = PdgIndex.Key.t (** Those keys are used to identify elements of a function. - See {!module:PdgIndex.Key} - to know more about it and to get functions to build some keys. *) + See {!module:PdgIndex.Key} + to know more about it and to get functions to build some keys. *) type t_nodes_and_undef = ((t_node * Locations.Zone.t option) list * Locations.Zone.t option) - (** type for the return value of many [find_xxx] functions when the - answer can be a list of [(node, z_part)] and an [undef zone]. + (** type for the return value of many [find_xxx] functions when the + answer can be a list of [(node, z_part)] and an [undef zone]. For each node, [z_part] can specify which part of the node is used in terms of zone ([None] means all). *) @@ -892,139 +928,139 @@ val find_decl_var_node : (t -> Cil_types.varinfo -> t_node) ref (** Get the node corresponding the declaration of a local variable or a - formal parameter. - @raise NotFound if the variable is not declared in this function. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + formal parameter. + @raise Not_found if the variable is not declared in this function. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_ret_output_node : (t -> t_node) ref (** Get the node corresponding return stmt. - @raise NotFound if the ouptut state in unreachable - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the ouptut state in unreachable + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_output_nodes : (t -> PdgIndex.Signature.t_out_key -> t_nodes_and_undef) ref (** Get the nodes corresponding to a call output key in the called pdg. - @raise NotFound if the ouptut state in unreachable - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the ouptut state in unreachable + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_input_node : (t -> int -> t_node) ref (** Get the node corresponding to a given input (parameter). - @raise NotFound if the number is not an input number. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the number is not an input number. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_all_inputs_nodes : (t -> t_node list) ref (** Get the nodes corresponding to all inputs. - {!node_key} can be used to know their numbers. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + {!node_key} can be used to know their numbers. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_stmt_node : (t -> Cil_types.stmt -> t_node) ref (** Get the node corresponding to the statement. - It shouldn't be a call statement. + It shouldn't be a call statement. See also {!find_simple_stmt_nodes} or {!find_call_stmts}. - @raise NotFound if the given statement is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the given statement is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_simple_stmt_nodes : (t -> Cil_types.stmt -> t_node list) ref (** Get the nodes corresponding to the statement. - It is usualy composed of only one node (see {!find_stmt_node}), + It is usualy composed of only one node (see {!find_stmt_node}), except for call statement. Be careful that for block statements, it only retuns a node corresponding to the elementary stmt (see {!find_stmt_and_blocks_nodes} for more) - @raise NotFound if the given statement is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the given statement is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_stmt_and_blocks_nodes : (t -> Cil_types.stmt -> t_node list) ref (** Get the nodes corresponding to the statement like * {!find_simple_stmt_nodes} but also add the nodes of the enclosed * statements if [stmt] contains blocks. - @raise NotFound if the given statement is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the given statement is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_top_input_node : (t -> t_node) ref - (** @raise NotFound if there is no top input in the PDG. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + (** @raise Not_found if there is no top input in the PDG. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_entry_point_node : (t -> t_node) ref (** Find the node that represent the entry point of the function, i.e. the - higher level block. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + higher level block. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_location_nodes_at_stmt : - (t -> Cil_types.stmt -> before:bool -> Locations.Zone.t -> - t_nodes_and_undef) ref + (t -> Cil_types.stmt -> before:bool -> Locations.Zone.t + -> t_nodes_and_undef) ref (** Find the nodes that define the value of the location at the given - program point. Also return a zone that might be undefined at that - point. - @raise NotFound if the given statement is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + program point. Also return a zone that might be undefined at that + point. + @raise Not_found if the given statement is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_location_nodes_at_end : (t -> Locations.Zone.t -> t_nodes_and_undef) ref (** Same than {!find_location_nodes_at_stmt} for the program point located - at the end of the function. - @raise NotFound if the output state is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + at the end of the function. + @raise Not_found if the output state is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_location_nodes_at_begin : (t -> Locations.Zone.t -> t_nodes_and_undef) ref (** Same than {!find_location_nodes_at_stmt} for the program point located - at the beginning of the function. + at the beginning of the function. Notice that it can only find formal argument nodes. The remaining zone (implicit input) is returned as undef. - @raise NotFound if the output state is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Not_found if the output state is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_call_stmts: (kernel_function -> caller:kernel_function -> Cil_types.stmt list) ref (** Find the call statements to the function (can maybe be somewhere - else). - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + else). + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_call_ctrl_node : (t -> Cil_types.stmt -> t_node) ref - (** @raise NotFound if the call is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + (** @raise Not_found if the call is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_call_input_node : (t -> Cil_types.stmt -> int -> t_node) ref - (** @raise NotFound if the call is unreachable or has no such input. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + (** @raise Not_found if the call is unreachable or has no such input. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_call_output_node : (t -> Cil_types.stmt -> t_node) ref - (** @raise NotFound if the call is unreachable or has no output node. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + (** @raise Not_found if the call is unreachable or has no output node. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_code_annot_nodes : - (t -> before:bool -> Cil_types.stmt -> Cil_types.code_annotation -> + (t -> Cil_types.stmt -> Cil_types.code_annotation -> t_node list * t_node list * (t_nodes_and_undef option)) ref (** The result is composed of three parts : - * - the first part of the result are the control dependencies nodes - * of the annotation, - * - the second part is the list of declaration nodes of the variables - * used in the annotation; - * - the third part is similar to [find_location_nodes_at_stmt] result - * but for all the locations needed by the annotation. - * When the third part is globally [None], - * it means that we were not able to compute this information. - * @raise NotFound if the statement is unreachable. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + - the first part of the result are the control dependencies nodes + of the annotation, + - the second part is the list of declaration nodes of the variables + used in the annotation; + - the third part is similar to [find_location_nodes_at_stmt] result + but for all the locations needed by the annotation. + When the third part is globally [None], + it means that we were not able to compute this information. + @raise Not_found if the statement is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val find_fun_precond_nodes : (t -> Cil_types.predicate -> t_node list * (t_nodes_and_undef option)) ref @@ -1038,114 +1074,119 @@ (t -> Cil_types.term -> (t_node list * t_nodes_and_undef option)) ref (** Similar to [find_fun_precond_nodes] *) - (** {3 Propagation} *) + (** {3 Propagation} + See also [Pdg.mli] for more function that cannot be here because + they use polymorphic types. + **) val find_call_out_nodes_to_select : (t -> t_node list -> t -> Cil_types.stmt -> t_node list) ref (** [find_call_out_nodes_to_select pdg_called called_selected_nodes - pdg_caller call_stmt] - @return the call outputs nodes [out] such that - [find_output_nodes pdg_called out_key] - intersects [called_selected_nodes]. - *) + pdg_caller call_stmt] + @return the call outputs nodes [out] such that + [find_output_nodes pdg_called out_key] + intersects [called_selected_nodes]. *) val find_in_nodes_to_select_for_this_call : (t -> t_node list -> Cil_types.stmt -> t -> t_node list) ref (** [find_in_nodes_to_select_for_this_call - * pdg_caller caller_selected_nodes call_stmt pdg_called] - * @return the called input nodes such that the corresponding nodes - * in the caller intersect [caller_selected_nodes] *) + pdg_caller caller_selected_nodes call_stmt pdg_called] + @return the called input nodes such that the corresponding nodes + in the caller intersect [caller_selected_nodes] + @raise Not_found if the statement is unreachable. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) (** {3 Dependencies} *) val direct_dpds : (t -> t_node -> t_node list) ref (** Get the nodes to which the given node directly depend on. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_ctrl_dpds : (t -> t_node -> t_node list) ref (** Similar to {!direct_dpds}, but for control dependencies only. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_data_dpds : (t -> t_node -> t_node list) ref (** Similar to {!direct_dpds}, but for data dependencies only. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_addr_dpds : (t -> t_node -> t_node list) ref (** Similar to {!direct_dpds}, but for address dependencies only. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val all_dpds : (t -> t_node list -> t_node list) ref (** Transitive closure of {!direct_dpds} for all the given nodes. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val all_data_dpds : (t -> t_node list -> t_node list) ref (** Gives the data dependencies of the given nodes, and recursively, all - the dependencies of those nodes (regardless to their kind). - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + the dependencies of those nodes (regardless to their kind). + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val all_ctrl_dpds : (t -> t_node list -> t_node list) ref (** Similar to {!all_data_dpds} for control dependencies. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val all_addr_dpds : (t -> t_node list -> t_node list) ref (** Similar to {!all_data_dpds} for address dependencies. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_uses : (t -> t_node -> t_node list) ref (** build a list of all the nodes that have direct dependencies on the - given node. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + given node. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_ctrl_uses : (t -> t_node -> t_node list) ref (** Similar to {!direct_uses}, but for control dependencies only. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_data_uses : (t -> t_node -> t_node list) ref (** Similar to {!direct_uses}, but for data dependencies only. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val direct_addr_uses : (t -> t_node -> t_node list) ref (** Similar to {!direct_uses}, but for address dependencies only. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val all_uses : (t -> t_node list -> t_node list) ref (** build a list of all the nodes that have dependencies (even indirect) on - the given nodes. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + the given nodes. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val custom_related_nodes : ((t_node -> t_node list) -> t_node list -> t_node list) ref (** [custom_related_nodes get_dpds node_list] build a list, starting from - the node in [node_list], and recursively add the nodes given by the - function [get_dpds]. For this function to work well, it is important - that [get_dpds n] returns a subset of the nodes directly related to - [n], ie a subset of [direct_uses] U [direct_dpds]. - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + the node in [node_list], and recursively add the nodes given by the + function [get_dpds]. For this function to work well, it is important + that [get_dpds n] returns a subset of the nodes directly related to + [n], ie a subset of [direct_uses] U [direct_dpds]. + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) val iter_nodes : ((t_node -> unit) -> t -> unit) ref (** apply a given function to all the PDG nodes - @raise Bottom if given PDG is bottom. - @raise Top if the given pdg is top. *) + @raise Bottom if given PDG is bottom. + @raise Top if the given pdg is top. *) (** {3 Pretty printing} *) val extract : (t -> string -> unit) ref (** Pretty print pdg into a dot file. - @see <../pdg/index.html> PDG internal documentation. *) + @see <../pdg/index.html> PDG internal documentation. *) val pretty_node : (bool -> Format.formatter -> t_node -> unit) ref (** Pretty print information on a node : @@ -1167,7 +1208,7 @@ Alternatively, one can use [F_ProjMarks] below. *) module F_FctMarks (M:PdgMarks.T_Mark) : PdgMarks.T_Fct with type t_mark = M.t - and type t_call_info = M.t_call_info + and type t_call_info = M.t_call_info (* [F_ProjMarks] handle the full interprocedural propagation (cf. [Pdg.Register.F_Proj]) *) @@ -1185,7 +1226,7 @@ val get_data_scope_at_stmt : (kernel_function -> stmt -> lval -> Stmt.Set.t * - (Stmt.Set.t * Stmt.Set.t)) ref + (Stmt.Set.t * Stmt.Set.t)) ref (** * @raise Kernel_function.No_Definition if [kf] has no definition. * @return 3 statement sets related to the value of [lval] before [stmt] : @@ -1220,10 +1261,9 @@ (** {3 Zones} *) - type t_zones = Locations.Zone.t Inthash.t + type t_zones = Locations.Zone.t Stmt.Hashtbl.t val build_zones : - (kernel_function -> stmt -> lval -> Stmt.Set.t * t_zones) -ref + (kernel_function -> stmt -> lval -> Stmt.Set.t * t_zones) ref val pretty_zones : (Format.formatter -> t_zones -> unit) ref val get_zones : (t_zones -> Cil_types.stmt -> Locations.Zone.t) ref @@ -1243,7 +1283,7 @@ * (the current one if no project given). * The source project is not modified. * The result is in the returned new project. - * optional argument [new_proj_name] added @since Carbon-20101202+dev + * optional argument [new_proj_name] added @since Carbon-20110201 * *) end @@ -1253,9 +1293,9 @@ type t = (kinstr * lval) list val get: (varinfo -> t) ref (** Return the occurrences of the given varinfo. - An occurrence [ki, lv] is a left-value [lv] which uses the location of - [vi] at the position [ki]. - @plugin development guide *) + An occurrence [ki, lv] is a left-value [lv] which uses the location of + [vi] at the position [ki]. + @plugin development guide *) val get_last_result: (unit -> (t * varinfo) option) ref (** @return the last result computed by occurrence *) val print_all: (unit -> unit) ref @@ -1311,7 +1351,7 @@ val is_called : (t -> kernel_function -> bool) ref (** Return [true] iff the source function is called (even indirectly via - transitivity) from a [Slice.t]. *) + transitivity) from a [Slice.t]. *) val has_persistent_selection : (t -> kernel_function -> bool) ref (** return [true] iff the source function has persistent selection *) @@ -1359,7 +1399,7 @@ val is_directly_called_internal : (t -> kernel_function -> bool) ref (** Return [true] if the source function is directly (even via pointer - function) called from a [Slice.t]. *) + function) called from a [Slice.t]. *) end @@ -1380,27 +1420,27 @@ val compare : (t -> t -> int) ref (** A total ordering function similar to the generic structural - comparison function [compare]. + comparison function [compare]. Can be used to build a map from [t] marks to, for exemple, colors for - the GUI. *) + the GUI. *) val is_bottom : (t -> bool) ref (** [true] iff the mark is empty: it is the only case where the - associated element is invisible. *) + associated element is invisible. *) val is_spare : (t -> bool) ref (** Smallest visible mark. Usually used to mark element that need to be - visible for compilation purpose, not really for the selected - computations. *) + visible for compilation purpose, not really for the selected + computations. *) val is_data : (t -> bool) ref (** The element is used to compute selected data. - Notice that a mark can be [is_data] and/or [is_ctrl] and/or [is_addr] - at the same time. *) + Notice that a mark can be [is_data] and/or [is_ctrl] and/or [is_addr] + at the same time. *) val is_ctrl : (t -> bool) ref (** The element is used to control the program point of a selected - data. *) + data. *) val is_addr : (t -> bool) ref (** The element is used to compute the address of a selected data. *) @@ -1422,7 +1462,7 @@ val dyn_t : t Type.t (** For dynamic type checking and journalization. *) - type t_set = SlicingTypes.Fct_user_crit.t SlicingTypes.Sl_selects.t + type t_set = SlicingTypes.Fct_user_crit.t Cil_datatype.Varinfo.Map.t (** Set of colored selections. *) val dyn_t_set : t_set Type.t (** For dynamic type checking and journalization. *) @@ -1470,30 +1510,31 @@ val select_stmt_zone : (t_set -> Mark.t -> Locations.Zone.t -> before:bool -> stmt -> - kernel_function -> t_set) ref + kernel_function -> t_set) ref (** To select a zone value related to a statement. Note: add also a transparent selection on the whole statement. *) val select_stmt_term : - (t_set -> Mark.t -> term -> before:bool -> stmt -> - kernel_function -> t_set) ref + (t_set -> Mark.t -> term -> stmt -> + kernel_function -> t_set) ref (** To select a predicate value related to a statement. Note: add also a transparent selection on the whole statement. *) val select_stmt_pred : - (t_set -> Mark.t -> predicate named -> before:bool -> stmt -> - kernel_function -> t_set) ref + (t_set -> Mark.t -> predicate named -> stmt -> + kernel_function -> t_set) ref (** To select a predicate value related to a statement. Note: add also a transparent selection on the whole statement. *) val select_stmt_annot : - (t_set -> Mark.t -> spare:bool -> code_annotation -> before:bool -> stmt -> kernel_function -> t_set) ref + (t_set -> Mark.t -> spare:bool -> code_annotation -> stmt -> + kernel_function -> t_set) ref (** To select the annotations related to a statement. Note: add also a transparent selection on the whole statement. *) val select_stmt_annots : (t_set -> Mark.t -> spare:bool -> ai:bool -> user_assert:bool -> - slicing_pragma:bool -> loop_inv:bool -> loop_var:bool -> + slicing_pragma:bool -> loop_inv:bool -> loop_var:bool -> stmt -> kernel_function -> t_set) ref (** To select the annotations related to a statement. Note: add also a transparent selection on the whole statement. *) @@ -1534,11 +1575,11 @@ val select_func_calls_into : (t_set -> spare:bool -> kernel_function -> t_set) ref (** To select every calls to the given function without the selection of - its inputs/outputs. *) + its inputs/outputs. *) val select_func_annots : (t_set -> Mark.t -> spare:bool -> ai:bool -> user_assert:bool -> - slicing_pragma:bool -> loop_inv:bool -> loop_var:bool -> + slicing_pragma:bool -> loop_inv:bool -> loop_var:bool -> kernel_function -> t_set) ref (** To select the annotations related to a function. *) @@ -1578,8 +1619,8 @@ val select_min_call_internal : (kernel_function -> ?select:t -> stmt -> Mark.t -> t) ref (** Internally used to select a statement call without its - inputs/outputs so that it doesn't select the statements computing the - inputs of the called function as [select_stmt_internal] would do. + inputs/outputs so that it doesn't select the statements computing the + inputs of the called function as [select_stmt_internal] would do. Raise [Invalid_argument] when the [stmt] isn't a call. @raise SlicingTypes.NoPdg if ? *) @@ -1659,7 +1700,7 @@ val create : (Project.t -> kernel_function -> t) ref (** Used to get an empty slice (nothing selected) related to a - function. *) + function. *) val remove : (Project.t -> t -> unit) ref (** Remove the slice from the project. The slice shouldn't be called. *) @@ -1683,7 +1724,7 @@ Returns None when the statement mark is bottom, or else the statement isn't a call or else the statement is a call to one or several (via pointer) - source functions. *) + source functions. *) val get_called_funcs : (t -> stmt -> kernel_function list) ref (** To get the source functions called by the statement of a slice. @@ -1733,7 +1774,7 @@ val add_persistent_selection: (Project.t -> Select.t_set -> unit) ref (** Add a persistent selection request to all slices (already existing or - created later) of a function to the project requests. *) + created later) of a function to the project requests. *) val add_persistent_cmdline : (Project.t -> unit) ref (** Add persistent selection from the command line. *) @@ -1767,8 +1808,8 @@ val add_call_min_fun: (Project.t -> caller:Slice.t -> to_call:kernel_function -> unit) ref (** For each call to [to_call] in [caller] such so that, at least, it - will be visible at the end, ie. call either the source function or - one of [to_call] slice (depending on the [slicing_level]). *) + will be visible at the end, ie. call either the source function or + one of [to_call] slice (depending on the [slicing_level]). *) (** {3 Internal use only} *) @@ -1777,19 +1818,19 @@ val apply_next_internal: (Project.t -> unit) ref (** Internaly used to apply the first slicing request of the project list - and remove it from the list. + and remove it from the list. That may modify the contents of the remaing list. For exemple, new requests may be added to the list. *) val merge_slices: (Project.t -> Slice.t -> Slice.t -> replace:bool -> Slice.t) ref (** Build a new slice which marks is a merge of the two given slices. - [choose_call] requests are added to the project in order to choose - the called functions for this new slice. + [choose_call] requests are added to the project in order to choose + the called functions for this new slice. If [replace] is true, more requests are added to call this new - slice instead of the two original slices. When these requests will - be applied, the user will be able to remove those two slices using - [Db.Slicing.Slice.remove]. *) + slice instead of the two original slices. When these requests will + be applied, the user will be able to remove those two slices using + [Db.Slicing.Slice.remove]. *) val copy_slice: (Project.t -> Slice.t -> Slice.t) ref @@ -1805,7 +1846,7 @@ val propagate_user_marks : (Project.t -> unit) ref (** Apply pending request then propagate user marks to callers - recursively then apply pending requests *) + recursively then apply pending requests *) val pretty : (Format.formatter -> Project.t -> unit) ref (** For debugging... Pretty print the resquest list. *) @@ -1816,9 +1857,9 @@ (* TODO: move this sub-computation shared by from and inout to somewhere *) val accept_base : - with_formals:bool -> Db_types.kernel_function -> Base.t -> bool + with_formals:bool -> with_locals:bool -> kernel_function -> Base.t -> bool val accept_base_internal : - Db_types.kernel_function -> Base.t -> bool + kernel_function -> Base.t -> bool (** Signature common to inputs and outputs computations. *) @@ -1881,30 +1922,27 @@ State_builder.of sure outputs - under-approximation of zones written by each function. @see <../inout/Context.html> internal documentation. *) -module InOutContext : INOUT with type t = Inout_type.t +module Operational_inputs : INOUT with type t = Inout_type.t (** Metrics. @see <../metrics/Metrics.html> internal documentation. *) module Metrics : sig type t = { sloc: int; - call_statements: int; - goto_statements: int; - assign_statements: int; - if_statements: int; - loop_statements: int; - mem_access: int; - functions_without_source: int Varinfo.Hashtbl.t; - functions_with_source: int Varinfo.Hashtbl.t; - (* ABP added 2 fields below*) - function_definitions: int ; - cyclos:int; + call_statements: int; + goto_statements: int; + assign_statements: int; + if_statements: int; + loop_statements: int; + mem_access: int; + functions_without_source: int Varinfo.Map.t; + functions_with_source: int Varinfo.Map.t; + (* ABP added 2 fields below*) + function_definitions: int ; + cyclos:int; } - val compute: (unit -> unit) ref - val pretty: (Format.formatter -> unit) ref - val dump: (unit -> unit) ref - val last_result: (unit -> t) ref - (** @raise Not_found if there is no last result *) + val compute: (unit -> t) ref + val pretty: (Format.formatter -> t -> unit) ref end (**/**) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/db_types.mli frama-c-20111001+nitrogen+dfsg/src/kernel/db_types.mli --- frama-c-20110201+carbon+dfsg/src/kernel/db_types.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/db_types.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Type definitions for [Db] module. Each plugin may add its additional - types. - @plugin development guide *) - -open Cil_types -open Cil - -type from_model = Lmap_bitwise.From_Model.t - -(** Internal representation of decorated C functions *) -type cil_function = - | Definition of (fundec * location) (** defined function *) - | Declaration of (funspec * varinfo * varinfo list option * location) - (** Declaration(spec,f,args,loc) represents a leaf function [f] with - specification [spec] and arguments [args], at location [loc]. As - with the [TFun] constructor of {!Cil_types.typ}, the arg list is - optional, to distinguish [void f()] ([None]) from - [void f(void)] ([Some []]). *) - -type rooted_code_annotation = - | User of code_annotation - | AI of Alarms.t*code_annotation - -type 'a before_after = Before of 'a | After of 'a - -type stmts_graph = Graph.Imperative.Digraph.Concrete(Cil_datatype.Stmt).t - -(** Except field [fundec], do not used the other fields directly. - Prefer to use {!Kernel_function.find_return}, {!Kernel_function.get_spec} - and {!Stmts_graph.stmt_can_reach}. - @plugin development guide *) -type kernel_function = { - fundec : cil_function; - mutable return_stmt : stmt option; - mutable spec : funspec; - mutable stmts_graph : stmts_graph option; -} - -(* [VP] TODO: VLocal should be attached to a particular block, not a whole function. *) -type localisation = - VGlobal | VLocal of kernel_function | VFormal of kernel_function - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/dynamic.ml frama-c-20111001+nitrogen+dfsg/src/kernel/dynamic.ml --- frama-c-20110201+carbon+dfsg/src/kernel/dynamic.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/dynamic.ml 2011-10-10 08:38:09.000000000 +0000 @@ -21,7 +21,7 @@ (**************************************************************************) (* ************************************************************************* *) -(** {2 Gobal variables for paths} *) +(** {2 Global variables for paths} *) (* ************************************************************************* *) let no_default = ref false @@ -33,10 +33,9 @@ | true, _ -> [] | false, true -> (* The order is relevant: plugins are loaded - in reverse order of this list. *) + in reverse order of this list. *) [ Config.plugin_dir ; Filename.concat Config.plugin_dir "gui"] - | false, false -> - [ Config.plugin_dir ] + | false, false -> [ Config.plugin_dir ] let all_path = ref [] let bad_path : string list ref = ref [] @@ -62,10 +61,10 @@ match list_arg with | [ dir; error ] -> if not (List.mem dir (default_path ())) then begin - warning - "cannot search dynamic plugins inside directory `%s' (%s)." - dir error; - bad_path := dir :: !bad_path; + warning + "cannot search dynamic plugins inside directory `%s' (%s)." + dir error; + bad_path := dir :: !bad_path; end | [] | [ _ ] | _ :: _ :: _ :: _ -> raise (Sys_error s) @@ -82,7 +81,7 @@ not (is_lower_than_311 && Dynlink_common_interface.is_native) (* apply [f] to [x] iff dynlink is available *) -let dynlink_available f x = if is_dynlink_available then f x else () +let dynlink_available f x = if is_dynlink_available then f x (* ************************************************************************* *) (** {2 Paths} *) @@ -93,21 +92,35 @@ try ignore (Sys.readdir path); true with Sys_error s -> catch_sysreaddir s; false +let rec init_paths = + let todo = ref true in + fun () -> + if !todo then begin + todo := false; + List.iter (fun s -> ignore (add_path s)) (default_path ()) + end + (** Display debug message and add a path to list of search path *) -let add_path_list path = +and add_path_list path = feedback ~level:2 - "dynamic plug-ins are now also searched inside directory \"%s\"" path; + "dynamic plug-ins are now also searched inside directory `%s'" path; + init_paths (); all_path := path :: !all_path -let add_path path = +and add_path path = (* the lazyness of && is used below *) if not (List.mem path !all_path) && not (List.mem path !bad_path) && check_path path - then - add_path_list path + then begin + add_path_list path; + true + end else + false -let init_paths () = List.iter add_path (default_path ()) +let remove_last_path () = match !all_path with + | [] -> invalid_arg "Dynamic.remove_last_path" + | _ :: l -> all_path := l (* read_path is very similar to check_path but to check a path you must use Sys.readdir and use Sys.readdir after. To prevent two use of Sys.readdir, I @@ -123,69 +136,72 @@ (* ************************************************************************* *) module Loading_error_messages: sig - val add: string -> string -> string -> unit + val add: + string (* name *) -> string (* message *) -> string (* detail *) -> unit val print: unit -> unit end = struct - let tbl = Hashtbl.create 7 + let tbl = Datatype.String.Hashtbl.create 7 let add name msg details = let t = - try Hashtbl.find tbl msg + try Datatype.String.Hashtbl.find tbl msg with Not_found -> - let t = Hashtbl.create 7 in - Hashtbl.add tbl msg t; - t + let t = Datatype.String.Hashtbl.create 7 in + Datatype.String.Hashtbl.add tbl msg t; + t in - Hashtbl.replace t name details + Datatype.String.Hashtbl.replace t name details let print () = - Hashtbl.iter + Datatype.String.Hashtbl.iter (fun msg tbl -> - let len = Hashtbl.length tbl in - assert (len > 0); - if len = 1 then - Hashtbl.iter - (fun name details -> - let append fmt = - if verbose_atleast 2 then - Format.fprintf fmt "The exact failure is: %s." details - in - warning ~append "cannot load plug-in `%s' (%s)." name msg) - tbl - else - let append fmt = - let first = ref true in - let print (name, details) = - if verbose_atleast 2 then - Format.fprintf fmt "%s@;(%s)@\n" name details - else begin - if !first then Format.fprintf fmt "%s" name - else Format.fprintf fmt ";@;%s" name; - first := false - end - in - let l = Hashtbl.fold (fun n d acc -> (n, d) :: acc) tbl [] in - List.iter print (List.sort Extlib.compare_basic l) - in - warning ~append "cannot load %d plug-ins (%s).@\n" len msg) + let len = Datatype.String.Hashtbl.length tbl in + assert (len > 0); + if len = 1 then + Datatype.String.Hashtbl.iter + (fun name details -> + let append fmt = + if verbose_atleast 2 then + Format.fprintf fmt " The exact failure is: %s." details + in + warning ~append "cannot load plug-in `%s' (%s)." name msg) + tbl + else + let append fmt = + let first = ref true in + let print (name, details) = + if verbose_atleast 2 then + Format.fprintf fmt "%s@;(%s)@\n" name details + else begin + if !first then Format.fprintf fmt "%s" name + else Format.fprintf fmt ";@;%s" name; + first := false + end + in + let l = + Datatype.String.Hashtbl.fold + (fun n d acc -> (n, d) :: acc) tbl [] + in + List.iter print (List.sort Extlib.compare_basic l) + in + warning ~append "cannot load %d plug-ins (%s).@\n" len msg) tbl; - Hashtbl.clear tbl + Datatype.String.Hashtbl.clear tbl end module Modules : sig val register_once: string -> bool val unregister: string -> unit + val mem: string -> bool end = struct - module Names = Set.Make(String) + let module_names = ref Datatype.String.Set.empty + let forbidden_names = ref Datatype.String.Set.empty - let module_names = ref Names.empty - let forbidden_names = ref Names.empty - - let add s = module_names := Names.add s !module_names - let disable s = forbidden_names := Names.add s !forbidden_names + let add s = module_names := Datatype.String.Set.add s !module_names + let disable s = forbidden_names := Datatype.String.Set.add s !forbidden_names let () = List.iter add Config.static_plugins; @@ -193,25 +209,29 @@ List.iter disable Config.compilation_unit_names let register_once s = - if Names.mem s !module_names then + if Datatype.String.Set.mem s !module_names then false else begin - if Names.mem s !forbidden_names then begin - Loading_error_messages.add - (String.capitalize s) - "forbidden plug-in name" - "name already used by a Frama-C kernel file"; - false + if Datatype.String.Set.mem s !forbidden_names then begin + Loading_error_messages.add + (String.capitalize s) + "forbidden plug-in name" + "name already used by a Frama-C kernel file"; + false end else begin - add s; - true + add s; + true end end - let unregister s = module_names := Names.remove s !module_names + let unregister s = module_names := Datatype.String.Set.remove s !module_names + + let mem s = Datatype.String.Set.mem s !module_names end +let is_plugin_present = Modules.mem + (* ************************************************************************* *) (** {2 Loading of dynamic modules} *) (* ************************************************************************* *) @@ -235,6 +255,7 @@ end in try + feedback ~level:2 "loading plug-in %s" (String.capitalize module_name); Dynlink_common_interface.loadfile file with | Dynlink_common_interface.Error e -> @@ -250,11 +271,13 @@ | Dynlink_common_interface.Inconsistent_implementation _ | Dynlink_common_interface.Unavailable_unit _ -> error - (Format.sprintf "incompatible with %s" Config.version) - (Dynlink_common_interface.error_message e) + (Format.sprintf "incompatible with %s" Config.version) + (Dynlink_common_interface.error_message e) | Dynlink_common_interface.Unsafe_file -> assert false) | Sys_error _ as e -> error "system error" (Printexc.to_string e) + | Log.AbortError _ | Log.AbortFatal _ | Log.FeatureRequest _ as e -> + raise e | e -> fatal "unexpected exception %S" (Printexc.to_string e) @@ -267,9 +290,27 @@ let files= read_path path in List.exists (fun file -> Str.string_match regexp file 0) files in + let paths = !all_path in + let tried = ref false in List.iter - (fun path -> if check_path path then dynlink_file path name) - !all_path; + (fun p -> + if check_path p then begin + tried := true; + dynlink_file p name + end) + paths; + if not !tried then + Loading_error_messages.add + name + "plug-in not found" + (match paths with + | [] -> "no specified directory" + | [ p ] -> + Pretty_utils.sfprintf "plug-in not found in directory %s" p + | _ :: _ -> + Pretty_utils.sfprintf "plug-in not found in directories %a" + (Pretty_utils.pp_list Format.pp_print_string) + paths); Loading_error_messages.print () let extract_filename f = @@ -279,7 +320,10 @@ let load f = let name = Filename.basename (extract_filename f) in let dir = Filename.dirname f in - if Modules.register_once name then dynlink_file dir name; + if dir = Filename.current_dir_name && Filename.is_implicit f then + load_module_from_unknown_path f + else + if Modules.register_once name then dynlink_file dir name; Loading_error_messages.print () in dynlink_available load @@ -295,30 +339,32 @@ in let cmd = Format.sprintf "%s -w Ly -warn-error A -I %s%s%t -I %s %s" - (if Dynlink_common_interface.is_native then - Config.ocamlopt ^ " -shared -o " ^ gen_name - else - Config.ocamlc ^ " -c") - Config.libdir - (if !Config.is_gui then " -I +lablgtk2" - else "") - (fun () -> List.fold_left (fun acc s -> " -I " ^ s ^ acc) "" !all_path) - dir - ml_name + (if Dynlink_common_interface.is_native then + Config.ocamlopt ^ " -shared -o " ^ gen_name + else + Config.ocamlc ^ " -c") + Config.libdir + (if !Config.is_gui then " -I +lablgtk2" + else "") + (fun () -> List.fold_left (fun acc s -> " -I " ^ s ^ acc) "" !all_path) + dir + ml_name in feedback ~level:2 "executing command `%s'" cmd; let code = Sys.command cmd in if code <> 0 then abort "command `%s' failed" cmd else begin + let extended = add_path "." in load_module name; + if extended then remove_last_path (); let cleanup () = - feedback ~level:2 "Removing files generated when compiling %S" ml_name; - Extlib.safe_remove gen_name (* .cmo or .cmxs *); - Extlib.safe_remove (name ^ ".cmi"); - if Dynlink_common_interface.is_native then begin - Extlib.safe_remove (name ^ ".o"); - Extlib.safe_remove (name ^ ".cmx") - end + feedback ~level:2 "Removing files generated when compiling %S" ml_name; + Extlib.safe_remove gen_name (* .cmo or .cmxs *); + Extlib.safe_remove (name ^ ".cmi"); + if Dynlink_common_interface.is_native then begin + Extlib.safe_remove (name ^ ".o"); + Extlib.safe_remove (name ^ ".cmx") + end in at_exit cleanup end @@ -357,25 +403,26 @@ debug ~level:5 "registering dynamic function %s" name; let f = if journalize then - let comment fmt = - Format.fprintf fmt - "@[Applying@;dynamic@;functions@;%S@;of@;type@;%s@]" - name - (Type.name ty) - in - let jname = - Format.fprintf - Format.str_formatter - "@[Dynamic.get@;~plugin:%S@;%S@;%t@]@]" - plugin name - (Type.pp_ml_name ty Type.Call); - Format.flush_str_formatter () - in - Journal.register jname ty ~is_dyn:true ~comment f + let comment fmt = + Format.fprintf fmt + "@[Applying@;dynamic@;functions@;%S@;of@;type@;%s@]" + name + (Type.name ty) + in + let jname = + Format.fprintf + Format.str_formatter + "@[Dynamic.get@;~plugin:%S@;%S@;%t@]" + plugin name + (Type.pp_ml_name ty Type.Call); + Format.flush_str_formatter () + in + Journal.register jname ty ~is_dyn:true ~comment f else - f + f in - Tbl.add dynamic_values (plugin ^ "." ^ name) ty f + Tbl.add dynamic_values (plugin ^ "." ^ name) ty f; + f end else f @@ -384,12 +431,112 @@ let get ~plugin name ty = if Cmdline.use_type then begin - load_module_from_unknown_path plugin; + if plugin <> "" then load_module_from_unknown_path plugin; Tbl.find dynamic_values (plugin ^ "." ^ name) ty end else abort "cannot access value %s in the 'no obj' mode" name (* ************************************************************************* *) +(** {2 Specialised interface for parameters} *) +(* ************************************************************************* *) + +module Parameter = struct + + module type Common = sig + type t + val get: string -> unit -> t + val set: string -> t -> unit + val clear: string -> unit -> unit + val is_set: string -> unit -> bool + val is_default: string -> unit -> bool + end + + let get_name functor_name fct_name option_name = + Format.sprintf "Dynamic.Parameter.%s.%s %S" + functor_name fct_name option_name + + let get_parameter option_name = + get ~plugin:"" option_name Parameter.ty + + let apply modname name s ty1 ty2 = + get ~plugin:"" (get_name modname s name) (Datatype.func ty1 ty2) + + module Common(X: sig type t val modname:string val ty: t Type.t end ) = struct + type t = X.t + let ty = X.ty + let get name = apply X.modname name "get" Datatype.unit ty + let set name = apply X.modname name "set" ty Datatype.unit + let clear name = apply X.modname name "clear" Datatype.unit Datatype.unit + let is_set name = apply X.modname name "is_set" Datatype.unit Datatype.bool + let is_default name = + apply X.modname name "is_default" Datatype.unit Datatype.bool + end + + module Bool = struct + include Common + (struct type t = bool let ty = Datatype.bool let modname = "Bool"end ) + let on name = apply "Bool" name "on" Datatype.unit Datatype.unit + let off name = apply "Bool" name "off" Datatype.unit Datatype.unit + end + + module Int = struct + include Common + (struct type t = int let ty = Datatype.int let modname = "Int" end ) + let incr name = apply "Int" name "incr" Datatype.unit Datatype.unit + end + + module String = + Common + (struct + type t = string + let ty = Datatype.string + let modname = "String" + end) + + module StringSet = struct + include Common + (struct include Datatype.String.Set let modname = "StringSet" end) + let add name = apply "StringSet" name "add" Datatype.string Datatype.unit + let remove name = + apply "StringSet" name "remove" Datatype.string Datatype.unit + let is_empty name = + apply "StringSet" name "is_empty" Datatype.unit Datatype.bool + let iter name = + apply "StringSet" name "iter" + (Datatype.func Datatype.string Datatype.unit) Datatype.unit + end + + module StringList = struct + include Common + (struct + include Datatype.List(Datatype.String) + let modname = "StringList" + end) + let add name = apply "StringList" name "add" Datatype.string Datatype.unit + let remove name = + apply "StringList" name "remove" Datatype.string Datatype.unit + let is_empty name = + apply "StringList" name "is_empty" Datatype.unit Datatype.bool + let iter name = + apply "StringList" name "iter" + (Datatype.func Datatype.string Datatype.unit) Datatype.unit + end + +(* + module IndexedVal(X: sig val ty_name: string end) = struct + include Common(struct type t = string let ty = string end) + type value = Type.ty + let ty = Type.get_abstract X.ty_name + let add_choice name = + StringTbl.find tbl (name ^ ".add_choice") (func string (func ty unit)) + let get_val name = + StringTbl.find tbl (name ^ ".get_val") (func unit ty) () + end + *) + +end + +(* ************************************************************************* *) (** {2 Initialisation} *) (* ************************************************************************* *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/dynamic.mli frama-c-20111001+nitrogen+dfsg/src/kernel/dynamic.mli --- frama-c-20110201+carbon+dfsg/src/kernel/dynamic.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/dynamic.mli 2011-10-10 08:38:09.000000000 +0000 @@ -24,7 +24,9 @@ val default_path: unit -> string list +(* ************************************************************************* *) (** {2 Registration} *) +(* ************************************************************************* *) val register: plugin:string -> string -> 'a Type.t -> journalize:bool -> 'a -> 'a @@ -35,13 +37,15 @@ @modify Boron-20100401 add the labeled argument "plugin" @plugin development guide *) +(* ************************************************************************* *) (** {2 Access} *) +(* ************************************************************************* *) exception Incompatible_type of string exception Unbound_value of string val get: plugin:string -> string -> 'a Type.t -> 'a - (** [apply ~plugin name ty] returns the value registered with the name + (** [get ~plugin name ty] returns the value registered with the name [name], the type [ty] and the plug-in [plugin]. This plug-in will be loaded if required. @raise Unbound_value if the name is not registered @@ -49,25 +53,111 @@ with a compatible type @plugin development guide *) +val is_plugin_present: string -> bool +(** @return true iff the given plug-in is loaded and usable. + @since Nitrogen-20111001 *) + +(* ************************************************************************* *) +(** {2 Dedicated access to plug-in parameters} *) +(* ************************************************************************* *) + +(** Module to use for accessing parameters of plug-ins. + Assume that the plug-in is already loaded. *) +module Parameter : sig + + (** Set of common operations on parameters. *) + module type Common = sig + type t + val get: string -> unit -> t + val set: string -> t -> unit + val clear: string -> unit -> unit + val is_set: string -> unit -> bool + val is_default: string -> unit -> bool + end + + (** retrieve the representation of the corresponding parameter. *) + val get_parameter: string -> Parameter.t + + (**/**) + val get_name: string -> string -> string -> string + (** Not for casual users *) + (**/**) + + (** Boolean parameters. *) + module Bool: sig + include Common with type t = bool + val on: string -> unit -> unit + (** Set the parameter to [true]. *) + val off : string -> unit -> unit + (** Set the parameter to [false]. *) + end + + (** Integer parameters. *) + module Int : sig + include Common with type t = int + val incr : string -> unit -> unit + end + + (** String parameters. *) + module String : Common with type t = string + + (** Set of string parameters. *) + module StringSet : sig + include Common with type t = Datatype.String.Set.t + val add: string -> string -> unit + val remove: string -> string -> unit + val is_empty: string -> unit -> bool + val iter: string -> (string -> unit) -> unit + end + + (** List of string parameters. *) + module StringList : sig + include Common with type t = string list + val add: string -> string -> unit + val remove: string -> string -> unit + val is_empty: string -> unit -> bool + val iter: string -> (string -> unit) -> unit + end + +(* + module IndexedVal(X: sig val ty_name: string end) : sig + include Common with type t = string + type value + val add_choice: string -> string -> value -> unit + val get_val: string -> value + end +*) + +end + +(* ************************************************************************* *) (** {2 Kernel materials} *) +(* ************************************************************************* *) val object_file_extension: string (** Object file extension used when loading a module. See function {!load_module}. @since Boron-20100401 *) -val add_path: string -> unit - (** Add a path into the search paths. *) +val add_path: string -> bool +(** Add a path into the search paths, if it is not already in the list. + @return true iff the path is really added to the list. *) val load_module: string -> unit (** Load the module with the given name. The module is searched in - search paths. Do nothing if dynamic loading is not available. *) + search paths if the name is implicit (that is if the file name is relative + and does not start with an explicit reference to the current directory (./ + or ../ in Unix). Do nothing if dynamic loading is not available. + @modify Nitrogen-20111001 better strategy for searching modules *) val load_script: string -> unit (** Compile then load the OCaml script with the given name. The file is - searched in search paths. Do nothing if dynamic loading is not - available. - @since Beryllium-20090601-beta1 *) + searched in the current directory, next in search paths if the name is + implicit (that is if the file name is relative and does not start with an + explicit reference to the current directory (./ or ../ in Unix). Do + nothing if dynamic loading is not available. + @since Beryllium-20090601-beta1 + @modify Nitrogen-20111001 better strategy for searching modules *) val set_default: bool -> unit (** Search in all the default directories iff the parameter is [true]. @@ -77,8 +167,8 @@ val extend : (unit -> unit) -> unit (** Register a function to be called by the Frama-C main entry point. - @deprecated since Lithium-20081201. Replaced by {!Db.Main.extend}. - @deprecated Since Beryllium-20090601-beta1. Replaced by {!Db.Main}. *) + @deprecated since Lithium-20081201. Replaced by {!Db.Main.extend}. + @deprecated Since Beryllium-20090601-beta1. Replaced by {!Db.Main}. *) val apply: unit -> unit (** Apply entry points previously registered . *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/emitter.ml frama-c-20111001+nitrogen+dfsg/src/kernel/emitter.ml --- frama-c-20110201+carbon+dfsg/src/kernel/emitter.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/emitter.ml 2011-10-10 08:38:09.000000000 +0000 @@ -0,0 +1,327 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* Module [Kernel] is not usable here. Thus use this module to emit messages. *) +module Output = Project_skeleton.Output + +(**************************************************************************) +(** {2 Datatype} *) +(**************************************************************************) + +type emitter = + { e_name: string; + tuning_parameters: Parameter.t list; + correctness_parameters: Parameter.t list } + +include Datatype.Make_with_collections + (struct + open Datatype + type t = emitter + let name = "Emitter.t" + let rehash = identity + let structural_descr = Structural_descr.Abstract + let reprs = + [ { e_name = ""; + tuning_parameters = []; + correctness_parameters = [] } ] + let equal = ( == ) + let compare x y = if x == y then 0 else String.compare x.e_name y.e_name + let hash x = String.hash x.e_name + let copy x = x (* strings are immutable here *) + let pretty fmt x = Format.pp_print_string fmt x.e_name + let internal_pretty_code = undefined + let varname _ = assert false (* unused while [internal_pretty_code] + unimplemented *) + let mem_project = never_any_project + end) + +type usable_emitter = + { id: int; + u_name: string; + mutable used: bool; + mutable version: int; + (* maps below associate the parameter to its value (as a string) at the + time of using. *) + tuning_values: string Datatype.String.Map.t; + correctness_values: string Datatype.String.Map.t } + +let has_several_versions_ref = Extlib.mk_fun "has_several_versions" + +module Usable_emitter = struct + + include Datatype.Make_with_collections + (struct + open Datatype + type t = usable_emitter + let name = "Emitter.Usable_emitter.t" + let rehash = identity + let structural_descr = Structural_descr.Abstract + let reprs = + [ let p = Datatype.String.Map.empty in + { id = -1; + u_name = ""; + used = false; + version = -1; + tuning_values = p; + correctness_values = p } ] + let equal = ( == ) + let compare x y = if x == y then 0 else Datatype.Int.compare x.id y.id + let hash x = Datatype.Int.hash x.id + let copy x = x (* strings are immutable here *) + let pretty fmt x = + if !has_several_versions_ref x.u_name then + Format.fprintf fmt "%s (v%d)" x.u_name x.version + else + Format.pp_print_string fmt x.u_name + let internal_pretty_code = undefined + let varname _ = assert false (* unused while [internal_pretty_code] + unimplemented *) + let mem_project = never_any_project + end) + + let get_name e = e.u_name + let get_unique_name e = Pretty_utils.sfprintf "%a" pretty e + + let compare_with_emitter ue e = Datatype.String.compare ue.u_name e.e_name + + let correctness_parameters e = + Datatype.String.Map.fold (fun p _ acc -> p :: acc) e.correctness_values [] + + let tuning_parameters e = + Datatype.String.Map.fold (fun p _ acc -> p :: acc) e.tuning_values [] + + let pretty_parameter fmt ~tuning e s = + let map = if tuning then e.tuning_values else e.correctness_values in + let v = Datatype.String.Map.find s map in + Format.fprintf fmt "%s %s" s v + +end + +(**************************************************************************) +(** {2 Implementation for Plug-in Developers} *) +(**************************************************************************) + +let create name ~correctness ~tuning = + { e_name = name; + correctness_parameters = correctness; + tuning_parameters = tuning } + +let get_name e = e.e_name + +let correctness_parameters e = + List.map (fun p -> p.Parameter.name) e.correctness_parameters + +let tuning_parameters e = + List.map (fun p -> p.Parameter.name) e.tuning_parameters + +(**************************************************************************) +(** {2 State of all known emitters} *) +(**************************************************************************) + +module Id = State_builder.Counter(struct let name = "Emitter.Ids" end) + +(* For each emitter, the info required to be able to get the right usable + emitter. + + Use names of emitters as keys instead of emitters (compared by (==)) in order + to be safe when unmarshaling: if we use the emitter datatype, we need to + rehash the keys *) +module Emitters = + State_builder.Hashtbl + (Datatype.String.Hashtbl) + (Datatype.Pair + (Datatype.Ref(Usable_emitter)) (* current usable emitter with the + current parameter values *) + (Datatype.Ref(Usable_emitter.Set))) (* existing usables emitters with + the old parameter values *) + (struct + let name = "Emitter.Emitters" + let size = 7 + let kind = `Correctness + let dependencies = [ Id.self ] + end) + +type available_emitters = Emitters.Datatype.t + +let self = Emitters.self + +let has_several_versions s = + try + let _, set = Emitters.find s in + Usable_emitter.Set.cardinal !set > 1 + with Not_found -> + Kernel.fatal "Unknown emitter %s" s + +let () = has_several_versions_ref := has_several_versions + +(**************************************************************************) +(** {2 Kernel Internal Implementation} *) +(**************************************************************************) + +(* set the value of a parameter of an emitter *) +let update_usable_emitter tuning ~used usable_e param_name value = + let id = Id.next () in + let name = usable_e.u_name in + let add = Datatype.String.Map.add param_name value in + if tuning then + { id = id; + u_name = name; + used = used; + version = -1; (* delayed *) + tuning_values = add usable_e.tuning_values; + correctness_values = usable_e.correctness_values } + else + { id = id; + u_name = name; + used = used; + version = -1; (* delayed *) + tuning_values = usable_e.tuning_values; + correctness_values = add usable_e.correctness_values } + +exception Found of Usable_emitter.t + +let update_parameter tuning usable_e p = + let param_name = p.Parameter.name in + let value = Parameter.get_value p in + try + let _, set = Emitters.find usable_e.u_name in + try + Usable_emitter.Set.iter + (fun e -> + let map = if tuning then e.tuning_values else e.correctness_values in + let exists = + try + Datatype.String.equal + value + (Datatype.String.Map.find param_name map) + with Not_found -> + false + in + if exists then raise (Found e)) + !set; + (* we are setting the value of a parameter, but we are not sure yet that + the corresponding usable emitter will be used *) + let e = + update_usable_emitter tuning ~used:false usable_e param_name value + in + set := Usable_emitter.Set.add e !set; + e + with Found e -> + (* we already create an usable emitter with this value for this + parameter *) + e + with Not_found -> + (* we are creating the first usable emitter of the given name: + it is going to be used *) + update_usable_emitter tuning ~used:true usable_e param_name value + +let property_status_state = ref State.dummy + +let register_parameter tuning usable_e p = + (* TODO: the added dependency and hook are never removed, + even if the emitter is deleted. + In particular, [register_parameter] may be applied once by emitter **and** + by project, thus the same [update] may be hooked for the same emitter + several times (one for each project) *) + if not tuning then + State_dependency_graph.Static.add_dependencies + ~from:(State.get p.Parameter.name) + [ !property_status_state ]; + let usable_e = update_parameter tuning usable_e p in + let name = usable_e.u_name in + let update () = + if tuning then + try + let current, set = Emitters.find name in + let c = !current in + let v = c.version in + let new_e = update_parameter tuning c p in + if c.used then new_e.version <- v + 1 + else begin + set := Usable_emitter.Set.remove c !set; + new_e.version <- v + end; + current := new_e + with Not_found -> + (* in multi-sessions mode (e.g. save/load), the emitters could exist in + the previous session but not in the current one. In this case, there + is nothing to do. + + Additionnally, even if it still exists, it could be not yet restored + since the project library does not ensure that it restores the table + of emitters before the states of parameters. In such a case, it is + also possible to do nothing since the right table in the right state + is going to be restored. *) + () + in + (match p.Parameter.accessor with + (* factorisation requires GADT (will be in OCaml 3.13?) *) + | Parameter.Bool(a, _) -> + a.Parameter.add_set_hook (fun _ _ -> update ()) + | Parameter.Int(a, _) -> + a.Parameter.add_set_hook (fun _ _ -> update ()) + | Parameter.String(a, _) -> + a.Parameter.add_set_hook (fun _ _ -> update ()) + | Parameter.String_set a -> + a.Parameter.add_set_hook (fun _ _ -> update ()) + | Parameter.String_list a -> + a.Parameter.add_set_hook (fun _ _ -> update ())); + usable_e + +let create_usable_emitter e = + let id = Id.next () in + let usable_e = + { id = id; + u_name = e.e_name; + used = true; + version = -1; (* delayed *) + tuning_values = Datatype.String.Map.empty; + correctness_values = Datatype.String.Map.empty } + in + let usable_e = + List.fold_left (register_parameter true) usable_e e.tuning_parameters + in + let usable_e = + List.fold_left (register_parameter false) usable_e e.correctness_parameters + in + usable_e.version <- 1; + usable_e + +let get e = + let name = e.e_name in + try + let current, _ = Emitters.find name in + let c = !current in + c.used <- true; + c + with Not_found -> + let usable_e = create_usable_emitter e in + Emitters.add + name + (ref usable_e, ref (Usable_emitter.Set.singleton usable_e)); + usable_e + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/emitter.mli frama-c-20111001+nitrogen+dfsg/src/kernel/emitter.mli --- frama-c-20110201+carbon+dfsg/src/kernel/emitter.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/emitter.mli 2011-10-10 08:38:09.000000000 +0000 @@ -0,0 +1,83 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Emitter. An emitter is the Frama-C entity which is able to emit annotations + and property status. Thus you have to create (at least) one of your own if + you want to do such tasks. + @since Nitrogen-20111001 *) + +(**************************************************************************) +(** {2 API for Plug-ins Developers} *) +(**************************************************************************) + +type emitter + +include Datatype.S_with_collections with type t = emitter + +val create: + string -> correctness:Parameter.t list -> tuning:Parameter.t list -> t +(** [Emitter.create name ~correctness ~tuning] creates a new emitter with the + given name. The given parameters are the ones which impact the generated + annotations/status. A "correctness" parameter may fully change a generated + element when its value changes (for instance, a valid status + may become invalid and conversely). A "tuning" parameter may improve a + generated element when its value changes (for instance, a "dont_know" status + may become valid or invalid, but a valid status cannot become invalid) + @raise Invalid_argument if an emitter with the given name already exist *) + +val get_name: t -> string + +val correctness_parameters: t -> string list +val tuning_parameters: t -> string list + +(** Usable emitters are the ones which can really emit something. + Use {!get} to get the one corresponding to a (standard) emitter. *) +module Usable_emitter: sig + include Datatype.S_with_collections + val get_name: t -> string + val get_unique_name: t -> string + val compare_with_emitter: t -> emitter -> int + val correctness_parameters: t -> string list + val tuning_parameters: t -> string list + val pretty_parameter: Format.formatter -> tuning:bool -> t -> string -> unit +(** Pretty print the parameter (given by its name) with its value. + @raise Not_found if the parameter is not one of the given emitter *) +end + +(* ********************************************************************** *) +(** {2 Kernel Internal API} *) +(* ********************************************************************** *) + +val get: t -> Usable_emitter.t +(** Get the emitter which is really able to emit something. + This function must be called at the time of the emission. No action must + occur between the call to [get] and the emission (in particular no update + of any parameter of the emitter. *) + +val self: State.t +val property_status_state: State.t ref + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/file.ml frama-c-20111001+nitrogen+dfsg/src/kernel/file.ml --- frama-c-20110201+carbon+dfsg/src/kernel/file.ml 2011-02-07 13:53:53.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/file.ml 2011-10-10 08:38:09.000000000 +0000 @@ -23,7 +23,6 @@ open Cil_types open Cil open Cilutil -open Db_types open Extlib open Visitor open Pretty_utils @@ -34,7 +33,7 @@ string (* filename of the [.c] to preprocess *) * string (* Preprocessor command. [filename.c -o tempfilname.i] will be appended at the - end.*) + end.*) | NoCPP of string (** filename of a preprocessed [.c] *) | External of string * string (* file * name of plug-in that handles it *) @@ -49,13 +48,13 @@ let mem_project = Datatype.never_any_project let copy = Datatype.identity (* immutable strings *) let internal_pretty_code p_caller fmt t = - let pp fmt = match t with - | NoCPP s -> Format.fprintf fmt "@[File.NoCPP %S@]" s - | External (f,p) -> + let pp fmt = match t with + | NoCPP s -> Format.fprintf fmt "@[File.NoCPP %S@]" s + | External (f,p) -> Format.fprintf fmt "@[File.External (%S,%S)@]" f p - | NeedCPP (a,b) -> Format.fprintf fmt "@[File.NeedCPP (%S,%S)@]" a b - in - Type.par p_caller Type.Call fmt pp + | NeedCPP (a,b) -> Format.fprintf fmt "@[File.NeedCPP (%S,%S)@]" a b + in + Type.par p_caller Type.Call fmt pp end) include D @@ -80,7 +79,7 @@ else if the CPP environment variable is set, use it else the built-in "gcc -C -E -I." *) let get_preprocessor_command () = - let cmdline = Parameters.CppCommand.get() in + let cmdline = Kernel.CppCommand.get() in if cmdline <> "" then cmdline else try Sys.getenv "CPP" @@ -92,15 +91,14 @@ end else let suf = try - let suf_idx = String.rindex f '.' in - String.sub f suf_idx (String.length f - suf_idx) + let suf_idx = String.rindex f '.' in + String.sub f suf_idx (String.length f - suf_idx) with Not_found -> (* raised by String.rindex if '.' \notin f *) - "" + "" in if Hashtbl.mem check_suffixes suf then External (f, suf) else NeedCPP (f, cpp) - (* ************************************************************************* *) (** {2 Internal states} *) (* ************************************************************************* *) @@ -110,24 +108,25 @@ val register: t list -> unit val pre_register: t -> unit val is_computed: unit -> bool + val reset: unit -> unit end = struct module S = State_builder.List_ref (D) (struct - let dependencies = - [ Parameters.CppCommand.self; - Parameters.CppExtraArgs.self; - Parameters.Files.self ] - let name = "Files for preprocessing" + let dependencies = + [ Kernel.CppCommand.self; + Kernel.CppExtraArgs.self; + Kernel.Files.self ] + let name = "Files for preprocessing" let kind = `Internal end) let () = State_dependency_graph.Static.add_dependencies ~from:S.self - [ Ast.self; Ast.UntypedFiles.self ] + [ Ast.self; Ast.UntypedFiles.self; Cabshelper.Comments.self ] (* Allow to register files in advance, e.g. prolog files for plugins *) let pre_register file = @@ -136,7 +135,7 @@ let register files = if S.is_computed () then - raise (Ast.Bad_Initialisation "[File.register] Too many initializations"); + raise (Ast.Bad_Initialization "[File.register] Too many initializations"); let prev_files = S.get () in S.set (prev_files @ files); S.mark_as_computed () @@ -144,6 +143,10 @@ let get = S.get let is_computed () = S.is_computed () + let reset () = + let selection = State_selection.Static.with_dependencies S.self in + Project.clear ~selection () + end let get_all = Files.get @@ -153,14 +156,25 @@ (** {2 AST Integrity check} *) (*****************************************************************************) +let is_admissible_conversion e ot nt = + let ots = Cil.typeSigWithAttrs (fun _ -> []) ot in + let nts = Cil.typeSigWithAttrs (fun _ -> []) nt in + Cilutil.equals ots nts || + (match e.enode, Cil.unrollType nt with + | Const(CEnum { eihost = ei }), TEnum(ei',[]) -> ei.ename = ei'.ename + | _ -> false) + (* performs various consistency checks over a cil file. Code may vary depending on current development of the kernel and/or identified bugs. what is a short string indicating which AST is checked + + NB: some checks are performed on the CFG, so it must have been computed on + the file that is checked. *) -class check_file what: Visitor.frama_c_visitor = +class check_file_aux is_normalized what: Visitor.frama_c_visitor = let check_abort fmt = - Cil.fatal ("[AST Integrity Check]@ %s" ^^ fmt) what + Kernel.fatal ~current:true ("[AST Integrity Check]@ %s@ " ^^ fmt) what in let check_label s = let rec has_label = function @@ -225,7 +239,7 @@ match v.vlogic_var_assoc with None -> DoChildren | Some ({ lv_origin = Some v'} as lv) when v == v' -> - Cilmsg.debug "var %s(%d) has an associated %s(%d)" v.vname v.vid + Kernel.debug "var %s(%d) has an associated %s(%d)" v.vname v.vid lv.lv_name lv.lv_id; DoChildren | Some lv -> @@ -285,6 +299,9 @@ local_vars <- Varinfo.Set.empty; List.iter (fun x -> local_vars <- Varinfo.Set.add x local_vars) f.slocals; + let print_stmt fmt stmt = + Format.fprintf fmt "@[%a(%d)@]" !Ast_printer.d_stmt stmt stmt.sid + in let check f = if Stmt.Hashtbl.length switch_cases <> 0 then begin @@ -294,33 +311,85 @@ "In function %a, statement %a \ does not appear in body of switch while porting a \ case or default label." - Cil.d_var f.svar !Ast_printer.d_stmt x) - switch_cases - end; + Cil.d_var f.svar print_stmt x) + switch_cases + end; List.iter (fun stmt -> - try if Stmt.Hashtbl.find known_stmts stmt != stmt then - (check_abort - "Label %a in function %a \ + try + let stmt' = Stmt.Hashtbl.find known_stmts stmt in + if stmt' != stmt then + check_abort + "Label @[%a@]@ in function %a@ \ is not linked to the correct statement:@\n\ - statement in AST is %a(%d)@\n\ - statement referenced in goto is %a(%d)" - Cil.d_stmt - {stmt with skind = Instr (Skip (Stmt.loc stmt)) } - Cil.d_var f.svar - Cil.d_stmt (Stmt.Hashtbl.find known_stmts stmt) - (Stmt.Hashtbl.find known_stmts stmt).sid - Cil.d_stmt stmt stmt.sid - ) + statement in AST is %a@\n\ + statement referenced in goto is %a" + !Ast_printer.d_stmt + {stmt with skind = Instr (Skip (Stmt.loc stmt)) } + !Ast_printer.d_var f.svar print_stmt stmt' print_stmt stmt with Not_found -> - (check_abort - "Label %a in function %a \ + check_abort + "Label @[%a@]@ in function %a@ \ does not refer to an existing statement" - Cil.d_stmt - ({stmt with skind = Instr (Skip (Stmt.loc stmt)) }) - Cil.d_var f.svar)) + !Ast_printer.d_stmt + ({stmt with skind = Instr (Skip (Stmt.loc stmt)) }) + !Ast_printer.d_var f.svar) labelled_stmt; labelled_stmt <- []; + let check_one_stmt stmt _ = + let check_cfg_edge stmt' = + try + let ast_stmt = Stmt.Hashtbl.find known_stmts stmt' in + if ast_stmt != stmt' then + check_abort + "cfg info of statement %a in function %a \ + is not linked to correct statement:@\n\ + statement in AST is %a@\n\ + statement referenced in cfg info is %a" + print_stmt stmt !Ast_printer.d_var f.svar + print_stmt ast_stmt print_stmt stmt' + with Not_found -> + check_abort + "cfg info of statement %a in function %a does not \ + refer to an existing statement.@\n\ + Referenced statement is %a" + print_stmt stmt !Ast_printer.d_var f.svar print_stmt stmt' + in + List.iter check_cfg_edge stmt.succs; + List.iter check_cfg_edge stmt.preds; + match stmt.skind with + | Return _ -> + if stmt.succs <> [] then + check_abort + "return statement %a in function %a \ + has successors:@\n%a" + print_stmt stmt !Ast_printer.d_var f.svar + (Pretty_utils.pp_list ~sep:nl_sep print_stmt) stmt.succs + | Instr(Call (_, called, _, _)) + when hasAttribute "noreturn" (typeAttrs (typeOf called)) -> + if stmt.succs <> [] then + check_abort + "exit statement %a in function %a \ + has successors:@\n%a" + print_stmt stmt !Ast_printer.d_var f.svar + (Pretty_utils.pp_list ~sep:nl_sep print_stmt) stmt.succs + | Instr(Call (_, { enode = Lval(Var called,NoOffset)}, _, _)) + when hasAttribute "noreturn" called.vattr -> + if stmt.succs <> [] then + check_abort + "exit statement %a in function %a \ + has successors:@\n%a" + print_stmt stmt !Ast_printer.d_var f.svar + (Pretty_utils.pp_list ~sep:nl_sep print_stmt) stmt.succs + | _ -> + (* unnormalized code may not contain return statement, + leaving perfectly normal statements without succs. *) + if is_normalized && stmt.succs = [] then + check_abort + "statement %a in function %a has no successor." + print_stmt stmt !Ast_printer.d_var f.svar + in + Stmt.Hashtbl.iter check_one_stmt known_stmts; Stmt.Hashtbl.clear known_stmts; if not (Varinfo.Set.is_empty local_vars) then begin check_abort @@ -437,14 +506,14 @@ method vterm t = match t.term_node with | TLval _ -> - begin match t.term_type with - | Ctype ty -> + begin match t.term_type with + | Ctype ty -> ignore - (Cilmsg.verify (not (isVoidType ty)) + (Kernel.verify (not (isVoidType ty)) "logic term with void type:%a" d_term t); DoChildren - | _ -> DoChildren - end + | _ -> DoChildren + end | Tat(_,StmtLabel l) -> check_label !l; labelled_stmt <- !l::labelled_stmt; DoChildren @@ -455,7 +524,7 @@ method vglob_aux = function GCompTag(c,_) -> - Cilmsg.debug "Adding fields for type %s(%d)" c.cname c.ckey; + Kernel.debug "Adding fields for type %s(%d)" c.cname c.ckey; List.iter (fun x -> Fieldinfo.Hashtbl.add known_fields x x) c.cfields; DoChildren @@ -535,7 +604,7 @@ try if not (li == Logic_var.Hashtbl.find known_logic_info li.l_var_info) - then + then (check_abort "logic function %a information is \ not shared between declaration and use" !Ast_printer.d_ident li.l_var_info.lv_name) @@ -550,9 +619,39 @@ | Const (CEnum ei) -> self#check_ei ei | _ -> DoChildren + method vinst i = + match i with + | Call(_,{ enode = Lval(Var f, NoOffset)},args,_) -> + let (_,targs,is_variadic,_) = Cil.splitFunctionTypeVI f in + let rec aux l1 l2 = + match l1,l2 with + [],[] -> DoChildren + | _::_, [] -> + check_abort "call %a has too few arguments" !Ast_printer.d_instr i + | [],e::_ -> + if is_variadic then DoChildren + else + check_abort "call %a has too many arguments, starting from %a" + !Ast_printer.d_instr i !Ast_printer.d_exp e + | (_,ty1,_)::l1,arg::l2 -> + let ty2 = Cil.typeOf arg in + if not (is_admissible_conversion arg ty2 ty1) then + check_abort "in call %a, arg %a has type %a instead of %a" + !Ast_printer.d_instr i + !Ast_printer.d_exp arg + !Ast_printer.d_type ty2 + !Ast_printer.d_type ty1; + aux l1 l2 + in + (match targs with + None -> DoChildren + | Some targs -> aux targs args) + | _ -> DoChildren end +class check_file what = object inherit check_file_aux true what end + (* ************************************************************************* *) (** {2 Initialisations} *) (* ************************************************************************* *) @@ -567,49 +666,52 @@ let parse = function | NoCPP f -> if not (Sys.file_exists f) then - Kernel.abort "preprocessed file %S does not exist" f; + Kernel.abort "preprocessed file %S does not exist" f; Frontc.parse f () | NeedCPP (f, cmdl) -> if not (Sys.file_exists f) then - Kernel.abort "source file %S does not exist" f; - let ppf = Filename.temp_file (Filename.basename f) ".i" in + Kernel.abort "source file %S does not exist" f; + let ppf = + try Filename.temp_file (Filename.basename f) ".i" + with Sys_error s -> Kernel.abort "cannot create temporary file: %s" s + in let cmd supp_args in_file out_file = try (* Format.eprintf "-cpp-command=|%s|@\n" cmdl; *) (* look at the command line to find two "%s" or one "%1" and a "%2" - *) + *) let percent1 = String.index cmdl '%' in - (* Format.eprintf "-cpp-command percent1=%d@\n" percent1; + (* Format.eprintf "-cpp-command percent1=%d@\n" percent1; Format.eprintf "-cpp-command %%%c@\n" (String.get cmdl - (percent1+1)); *) + (percent1+1)); *) let percent2 = String.index_from cmdl (percent1+1) '%' in - (* Format.eprintf "-cpp-command percent2=%d@\n" percent2; + (* Format.eprintf "-cpp-command percent2=%d@\n" percent2; Format.eprintf "-cpp-command %%%c@\n" (String.get cmdl - (percent2+1)); *) + (percent2+1)); *) let file1, file2 = match String.get cmdl (percent1+1), String.get cmdl (percent2+1) with | '1', '2' -> in_file, out_file - (* "%1" followed by "%2" is used to printf 'ppf' after 'f' *) + (* "%1" followed by "%2" is used to printf 'ppf' after 'f' *) | '2', '1' -> out_file, in_file | _, _ -> raise (Invalid_argument "maybe a bad cpp command") in - let cmd1 = String.sub cmdl 0 percent1 in - (* Format.eprintf "-cpp-command cmd1=|%s|@\n" cmd1; *) + let cmd1 = String.sub cmdl 0 percent1 in + (* Format.eprintf "-cpp-command cmd1=|%s|@\n" cmd1; *) let cmd2 = - String.sub cmdl (percent1 + 2) (percent2 - (percent1 + 2)) - in - (* Format.eprintf "-cpp-command cmd2=|%s|@\n" cmd2; *) + String.sub cmdl (percent1 + 2) (percent2 - (percent1 + 2)) + in + (* Format.eprintf "-cpp-command cmd2=|%s|@\n" cmd2; *) let cmd3 = - String.sub cmdl (percent2 + 2) (String.length cmdl - (percent2 + 2)) + String.sub cmdl (percent2 + 2) (String.length cmdl - (percent2 + 2)) in - (* Format.eprintf "-cpp-command cmd3=|%s|@\n" cmd3; *) + (* Format.eprintf "-cpp-command cmd3=|%s|@\n" cmd3; *) Format.sprintf "%s%s %s %s%s%s" cmd1 (* using Filename.quote for filenames which contain space or - shell metacharacters *) - (Filename.quote file1) + shell metacharacters *) + (Filename.quote file1) supp_args cmd2 (Filename.quote file2) cmd3 with @@ -617,35 +719,35 @@ | Not_found -> Format.sprintf "%s %s -o %s %s" cmdl supp_args - (* using Filename.quote for filenames which contain space or - shell metacharacters *) - (Filename.quote out_file) (Filename.quote in_file) + (* using Filename.quote for filenames which contain space or + shell metacharacters *) + (Filename.quote out_file) (Filename.quote in_file) in let supp_args = - (Parameters.CppExtraArgs.get_set ~sep:" " ()) ^ - (if Parameters.ReadAnnot.get() && Parameters.PreprocessAnnot.get() - then " -dD" else "") + (Kernel.CppExtraArgs.get_set ~sep:" " ()) ^ + (if Kernel.ReadAnnot.get() && Kernel.PreprocessAnnot.get() + then " -dD" else "") in Kernel.feedback "@{preprocessing@} with \"%s %s %s\"" cmdl supp_args f; if Sys.command (cmd supp_args f ppf) <> 0 then begin - Extlib.safe_remove ppf; - Kernel.abort "failed to run: %s@\n\ + Extlib.safe_remove ppf; + Kernel.abort "failed to run: %s@\n\ you may set the CPP environment variable to select the proper \ preprocessor command or use the option \"-cpp-command\"." - (cmd supp_args f ppf); + (cmd supp_args f ppf); end; let ppf = - if Parameters.ReadAnnot.get() && Parameters.PreprocessAnnot.get() + if Kernel.ReadAnnot.get() && Kernel.PreprocessAnnot.get() then begin let ppf' = - try Logic_preprocess.file (cmd "") ppf - with Sys_error _ as e -> - Extlib.safe_remove ppf; - Kernel.abort "preprocessing of annotations failed (%s)" - (Printexc.to_string e) - in + try Logic_preprocess.file (cmd "") ppf + with Sys_error _ as e -> + Extlib.safe_remove ppf; + Kernel.abort "preprocessing of annotations failed (%s)" + (Printexc.to_string e) + in safe_remove_file ppf ; - ppf' + ppf' end else ppf in let (cil,(_,defs)) = Frontc.parse ppf () in @@ -654,10 +756,10 @@ (cil,(f,defs)) | External (f,suf) -> if not (Sys.file_exists f) then - Kernel.abort "file %S does not exist." f; + Kernel.abort "file %S does not exist." f; try Hashtbl.find check_suffixes suf f with Not_found -> - Kernel.abort "could not find a suitable plugin for parsing %s." f + Kernel.abort "could not find a suitable plugin for parsing %s." f (** Keep defined entry point even if not defined. This function is meant to be passed to {!Rmtmps.removeUnusedTemps}.*) @@ -665,26 +767,28 @@ Rmtmps.isDefaultRoot g || match g with GVarDecl(spec,v,_) -> - Parameters.MainFunction.get () = v.vname && + Kernel.MainFunction.get () = v.vname && not (is_empty_funspec spec) | _ -> false - let files_to_cil files = + (* BY 2011-05-10 Deactivated this mark_as_computed. Does not see to + do anything useful anymore, and causes problem with the self-recovering + gui (commit 13295) (* mark as computed early in case of a typing error occur: do not type check the erroneous program twice. *) - Ast.mark_as_computed (); + Ast.mark_as_computed (); *) let debug_globals files = let level = 6 in if Kernel.debug_atleast level then begin List.iter - (fun f -> - (* NB: don't use frama-C printer here, as the + (fun f -> + (* NB: don't use frama-C printer here, as the annotations tables are not filled yet. *) - List.iter - (fun g -> Kernel.debug ~level "%a" Cil.d_global g) - f.globals) - files + List.iter + (fun g -> Kernel.debug ~level "%a" Cil.d_global g) + f.globals) + files end in (* Parsing and merging must occur in the very same order. @@ -693,16 +797,16 @@ Kernel.feedback ~level:2 "parsing"; let files,cabs = List.fold_left - (fun (accf,accc) f -> + (fun (accf,accc) f -> try - let f,c = parse f in - f::accf, c::accc + let f,c = parse f in + f::accf, c::accc with exn when Cilmsg.had_errors () -> if Kernel.Debug.get () >= 1 then raise exn else - Kernel.abort "skipping file %S that has errors." (get_name f)) - ([],[]) - files + Kernel.abort "skipping file %S that has errors." (get_name f)) + ([],[]) + files in Ast.UntypedFiles.set cabs; debug_globals files; @@ -730,7 +834,7 @@ debug_globals files; Rmtmps.removeUnusedTemps ~isRoot:keep_entry_point merged_file; - if Parameters.UnspecifiedAccess.get() + if Kernel.UnspecifiedAccess.get() then begin let rec not_separated_offset offs1 offs2 = match offs1, offs2 with @@ -743,7 +847,7 @@ Cil.isInteger (Cil.constFold true i1), Cil.isInteger (Cil.constFold true i2) with Some c1, Some c2 -> - Int64.compare c1 c2 = 0 && + My_bigint.equal c1 c2 && not_separated_offset offs1 offs2 | None, _ | _, None -> true) | (Index _|Field _), (Index _|Field _) -> @@ -799,7 +903,7 @@ let remove_mod m l = List.filter (fun x -> not (List.exists (Lval.equal x) m)) - l + l in let not_separated_modified l1 l2 = List.fold_left @@ -821,7 +925,7 @@ end) (false, [], []) seq in if warn then - Kernel.warning ~current:true ~once:true + Kernel.warning ~current:true ~once:true "Unspecified sequence with side effect:@\n%a@\n" (Cil.printStmt my_stmt_print) s | _ -> ()); @@ -832,100 +936,123 @@ end; merged_file -let synchronize_source_annot kf = +let synchronize_source_annot has_new_stmt kf = match kf.fundec with - | Definition (fd,_) -> - let (visitor:cilVisitor) = object - inherit nopCilVisitor as super - val block_with_user_annots = ref None - val user_annots_for_next_stmt = ref [] - method vstmt st = - let stmt, father = match super#current_kinstr with - | Kstmt stmt -> - super#pop_stmt stmt; - let father = super#current_stmt in - super#push_stmt stmt; - stmt, father - | Kglobal -> assert false - in - let is_in_same_block () = match !block_with_user_annots,father with - | None, None -> true - | Some block, Some stmt_father when block == stmt_father -> true - | _, _ -> false - in - let synchronize_user_annot annot = - Annotations.add st [] (Before (User annot)) - in - let synchronize_previous_user_annots () = - if !user_annots_for_next_stmt <> [] - then begin - if is_in_same_block () - then - List.iter synchronize_user_annot - (List.sort - (fun x y -> x.annot_id - y.annot_id) - !user_annots_for_next_stmt) - else - Kernel.warning ~current:true ~once:true - "Ignoring previous annotation relative to next statement effects" ; - block_with_user_annots := None ; - user_annots_for_next_stmt := [] - end - in - let add_user_annot_for_next_stmt annot = - if !user_annots_for_next_stmt = [] - then - (block_with_user_annots := father; - user_annots_for_next_stmt := [annot]) - else if is_in_same_block () - then - user_annots_for_next_stmt := annot::!user_annots_for_next_stmt - else - begin - Kernel.warning ~current:true ~once:true - "Ignoring previous annotation relative to next statement effects" ; - block_with_user_annots := father; - user_annots_for_next_stmt := [annot] ; - end - in - assert (stmt == st) ; - assert (!block_with_user_annots = None - || !user_annots_for_next_stmt <> []); - - match st.skind with - | Instr (Code_annot (annot,_)) -> - (* Code annotation isn't considered as a real stmt. - So, previous annotations should be relative to the next stmt. - Only this [annot] may be synchronised to that stmt *) - (if match annot.annot_content with - | AStmtSpec _ - | APragma (Slice_pragma SPstmt | Impact_pragma IPstmt) -> - (* Annotation relative to the effect of next statement *) - true - | APragma _ | AAssert _ | AAssigns _ - | AInvariant _ | AVariant _ (* | ALoopBehavior _ *) -> - (* Annotation relative to the current control point *) - false - then (* To synchronize on the next statement *) - add_user_annot_for_next_stmt annot - else (* Synchronize this annotation on that statement *) - synchronize_user_annot annot); - super#vstmt st - | Loop (annot, _, _, _, _) -> - (* Synchronize previous annotations on that statement *) - synchronize_previous_user_annots () ; - (* Synchronize loop annotations on that statement *) - List.iter synchronize_user_annot - (List.sort (fun x y -> x.annot_id - y.annot_id) annot); - super#vstmt st - | _ -> - (* Synchronize previous annotations on that statement *) - synchronize_previous_user_annots () ; - super#vstmt st - end + | Definition (fd,_) -> + let (visitor:cilVisitor) = object + inherit nopCilVisitor as super + val block_with_user_annots = ref None + val user_annots_for_next_stmt = ref [] + method vstmt st = + let stmt, father = match super#current_kinstr with + | Kstmt stmt -> + super#pop_stmt stmt; + let father = super#current_stmt in + super#push_stmt stmt; + stmt, father + | Kglobal -> assert false + in + let is_in_same_block () = match !block_with_user_annots,father with + | None, None -> true + | Some block, Some stmt_father when block == stmt_father -> true + | _, _ -> false + in + let synchronize_user_annot a = Annotations.add kf st [] (User a) in + let synchronize_previous_user_annots () = + if !user_annots_for_next_stmt <> [] then begin + if is_in_same_block () + then begin + let my_annots = !user_annots_for_next_stmt in + let post_action st = + let treat_annot (has_contract,st as acc) annot = + if Logic_utils.is_contract annot then begin + if has_contract then begin + let new_stmt = + Cil.mkStmt ~valid_sid:true (Block (Cil.mkBlock [st])) + in + has_new_stmt := true; + Annotations.add kf new_stmt [] (User annot); + (true,new_stmt) + end else begin + Annotations.add kf st [] (User annot); + (true,st) + end + end else begin + Annotations.add kf st [] (User annot); + acc + end + in + let (_,st) = List.fold_left treat_annot (false,st) my_annots in + st + in + block_with_user_annots:=None; + user_annots_for_next_stmt:=[]; + ChangeDoChildrenPost(st,post_action) + end + else begin + Kernel.warning ~current:true ~once:true + "Ignoring previous annotation relative \ + to next statement effects" ; + block_with_user_annots := None ; + user_annots_for_next_stmt := []; + DoChildren + end + end else begin + block_with_user_annots := None ; + user_annots_for_next_stmt := []; + DoChildren; + end + in + let add_user_annot_for_next_stmt annot = + if !user_annots_for_next_stmt = [] then begin + block_with_user_annots := father; + user_annots_for_next_stmt := [annot] + end else if is_in_same_block () then + user_annots_for_next_stmt := annot::!user_annots_for_next_stmt + else begin + Kernel.warning ~current:true ~once:true + "Ignoring previous annotation relative to next statement \ +effects"; + block_with_user_annots := father; + user_annots_for_next_stmt := [annot] ; + end in - ignore (visitCilFunction visitor fd) - | Declaration _ -> () + assert (stmt == st) ; + assert (!block_with_user_annots = None + || !user_annots_for_next_stmt <> []); + match st.skind with + | Instr (Code_annot (annot,_)) -> + (* Code annotation isn't considered as a real stmt. + So, previous annotations should be relative to the next stmt. + Only this [annot] may be synchronised to that stmt *) + (if match annot.annot_content with + | AStmtSpec _ + | APragma (Slice_pragma SPstmt | Impact_pragma IPstmt) -> + (* Annotation relative to the effect of next statement *) + true + | APragma _ | AAssert _ | AAssigns _ + | AInvariant _ | AVariant _ (* | ALoopBehavior _ *) -> + (* Annotation relative to the current control point *) + false + then (* To synchronize on the next statement *) + add_user_annot_for_next_stmt annot + else (* Synchronize this annotation on that statement *) + synchronize_user_annot annot); + super#vstmt st + | Loop (annot, _, _, _, _) -> + (* Synchronize previous annotations on that statement *) + let res = synchronize_previous_user_annots () in + (* Synchronize loop annotations on that statement *) + List.iter synchronize_user_annot + (List.sort (fun x y -> x.annot_id - y.annot_id) annot); + res + | _ -> + (* Synchronize previous annotations on that statement *) + synchronize_previous_user_annots () ; + end + in + ignore (visitCilFunction visitor fd) + | Declaration _ -> () let register_global = function | GFun (fundec, loc) -> @@ -933,18 +1060,22 @@ Oneret.oneret fundec; (* Build the Control Flow Graph for all functions *) - if Parameters.SimplifyCfg.get () then begin - Cfg.prepareCFG ~keepSwitch:(Parameters.KeepSwitch.get ()) fundec; + if Kernel.SimplifyCfg.get () then begin + Cfg.prepareCFG ~keepSwitch:(Kernel.KeepSwitch.get ()) fundec; Cfg.clearCFGinfo fundec; Cfg.cfgFun fundec; end; - Globals.Functions.add (Db_types.Definition(fundec,loc)) + Globals.Functions.add (Definition(fundec,loc)) | GVarDecl (spec, ({vtype=typ } as f),loc) when isFunctionType typ -> (* global prototypes *) let args = try Some (Cil.getFormalsDecl f) with Not_found -> None in - Globals.Functions.add (Db_types.Declaration(spec,f,args,loc)) + (* Use a copy of the spec, as the original one will be erased by + AST cleanup. + *) + let spec = { spec with spec_variant = spec.spec_variant } in + Globals.Functions.add (Declaration(spec,f,args,loc)) | GVarDecl (_spec(*TODO*), ({vstorage=Extern} as vi),_) -> (* global variables declaration with no definitions *) Globals.Vars.add_decl vi @@ -1009,7 +1140,7 @@ *) b.battrs <- List.filter (function - (Attr("FRAMA_C_KEEP_BLOCK",[])) -> false + (Attr(l,[])) when l = Cabs2cil.frama_c_keep_block -> false | _ -> true) b.battrs; b @@ -1019,18 +1150,17 @@ ChangeDoChildrenPost(b,optim) method vglob_aux = function - GFun (f,_) -> f.sspec <- Cil.empty_funspec(); - (* uncomment if you dont want to treat scope of locals (see above)*) - (* f.sbody.blocals <- f.slocals; *) - DoChildren - | GVarDecl(s,_,_) -> - s.spec_behavior <- []; - s.spec_variant <- None; - s.spec_terminates <- None; - s.spec_complete_behaviors <- []; - s.spec_disjoint_behaviors <- []; - DoChildren - | _ -> DoChildren + | GFun (f,_) -> + (* No need to call [Kernel_function.set_spec] yet: will be done later *) + f.sspec <- Cil.empty_funspec (); + (* uncomment if you dont want to treat scope of locals (see above)*) + (* f.sbody.blocals <- f.slocals; *) + DoChildren + | GVarDecl(s,_,_) -> + (* No need to call [Kernel_function.set_spec] yet: will be done later *) + Logic_utils.clear_funspec s; + DoChildren + | _ -> DoChildren method vfile f = ChangeDoChildrenPost @@ -1045,7 +1175,8 @@ inherit Cil.nopCilVisitor method vvdec v = if v.vname <> v.vorig_name then begin - Cil.info "Variable %s has been renamed to %s" v.vorig_name v.vname + Kernel.result ~current:true + "Variable %s has been renamed to %s" v.vorig_name v.vname end; DoChildren end @@ -1053,11 +1184,11 @@ let prepare_cil_file file = Kernel.feedback ~level:2 "preparing the AST"; computeCFG ~clear_id:true file; - if Parameters.Files.Check.get() then begin + if Kernel.Files.Check.get() then begin Cil.visitCilFileSameGlobals - (new check_file "initial AST" :> Cil.cilVisitor) file; + (new check_file_aux false "initial AST" :> Cil.cilVisitor) file; end; - if Parameters.Files.Orig_name.get () then begin + if Kernel.Files.Orig_name.get () then begin Cil.visitCilFileSameGlobals print_renaming file end; (* Compute the list of functions and their CFG *) @@ -1073,21 +1204,27 @@ we must compute it again before annotation synchronisation *) Cfg.clearFileCFG ~clear_id:false file; Cfg.computeFileCFG file; - Globals.Functions.iter synchronize_source_annot; + let recompute = ref false in + Globals.Functions.iter (synchronize_source_annot recompute); + (* We might also introduce new blocks for synchronization. *) + if !recompute then begin + Cfg.clearFileCFG ~clear_id:false file; + Cfg.computeFileCFG file; + end; cleanup file; (* Check that normalization is correct. *) - if Parameters.Files.Check.get() then begin + if Kernel.Files.Check.get() then begin Cil.visitCilFileSameGlobals (new check_file "AST after normalization" :> Cil.cilVisitor) file; end; (* Unroll loops in file *) - Unroll_loops.compute (Parameters.UnrollingLevel.get ()) file; + Unroll_loops.compute (Kernel.UnrollingLevel.get ()) file; Cfg.clearFileCFG ~clear_id:false file; Cfg.computeFileCFG file; (* Annotate functions from declspec. *) Translate_lightweight.interprate file; (* Check that we start with a correct file. *) - if Parameters.Files.Check.get() then begin + if Kernel.Files.Check.get() then begin Cil.visitCilFileSameGlobals (new check_file "Ast as set in Frama-C's original state" :> Cil.cilVisitor) file; @@ -1117,8 +1254,8 @@ let selection = State_selection.Static.diff (State_selection.Static.diff - State_selection.full - (State_selection.Static.with_dependencies Cil.Builtin_functions.self)) + State_selection.full + (State_selection.Static.with_dependencies Cil.Builtin_functions.self)) (State_selection.Static.with_dependencies Ast.self) in Project.copy ~selection prj; @@ -1137,7 +1274,8 @@ - action_when_selected is the action to perform when the corresponding machine is set as current (i.e. defining the right architecture via Machdep.DEFINE) *) -let machdeps = + +let default_machdeps = [ "x86_16", (true, fun () -> let module M = Machdep.DEFINE(Machdep_x86_16) in ()); "x86_32", @@ -1146,33 +1284,45 @@ (true, fun () -> let module M = Machdep.DEFINE(Machdep_x86_64) in ()); "ppc_32", (true, fun () -> let module M = Machdep.DEFINE(Machdep_ppc_32) in ()); - "ppc_32_diab", - (false, fun () -> let module M = Machdep.DEFINE(Machdep_ppc_32_diab) in ()) ] -let pretty_machdeps fmt = +let machdeps = Datatype.String.Hashtbl.create 7 +let () = List.iter - (fun (x,(public,_)) -> if public then Format.fprintf fmt "@ %s" x) + (fun (s, c) -> Datatype.String.Hashtbl.add machdeps s c) + default_machdeps + +let new_machdep s p f = + if Datatype.String.Hashtbl.mem machdeps s then + invalid_arg (Format.sprintf "machdep `%s' already exists" s); + Datatype.String.Hashtbl.add machdeps s (p, f) + +let pretty_machdeps fmt = + Datatype.String.Hashtbl.iter + (fun x (public, _) -> if public then Format.fprintf fmt "@ %s" x) machdeps -let set_machdep () = match Parameters.Machdep.get () with - | "" -> () - | s when List.exists (fun x -> fst x = s) machdeps -> - (snd (List.assoc s machdeps)) () - | s -> - if s = "help" then begin - Kernel.feedback "supported machines are%t." pretty_machdeps; - end else begin - Kernel.error "unsupported machine %s. Try one of%t." s - pretty_machdeps; - end +let set_machdep () = + let m = Kernel.Machdep.get () in + try snd (Datatype.String.Hashtbl.find machdeps m) () + with Not_found -> + if m = "" then () + else if m = "help" then + Kernel.feedback "supported machines are%t." pretty_machdeps + else + Kernel.error "unsupported machine %s. Try one of%t." m + pretty_machdeps -let () = Cmdline.run_after_configuring_stage set_machdep +let () = Cmdline.run_after_configuring_stage set_machdep -let prepare_from_c_files () = +let init_cil () = Cil.initCIL (Logic_builtin.init()); Logic_env.Builtins.apply (); - Logic_env.prepare_tables (); + Logic_env.prepare_tables () + +(* Fill logic tables with builtins *) +let prepare_from_c_files () = + init_cil (); let files = Files.get () in (* Allow pre-registration of prolog files *) let cil = files_to_cil files in prepare_cil_file cil @@ -1182,7 +1332,8 @@ (* queue of visitor is filled below *) let set_annotation annot = visitCilAnnotation visitor annot in Project.on - ~selection:(State_selection.singleton Globals.Annotations.self) + ~selection: + (State_selection.Static.with_dependencies Globals.Annotations.self) prj (List.iter (fun (a,f) -> @@ -1190,18 +1341,18 @@ Globals.Annotations.add_generated (set_annotation a) else Globals.Annotations.add_user (set_annotation a))) - (Globals.Annotations.get_all()); + (Globals.Annotations.get_all ()); let file = Ast.get () in let file' = Cil.visitCilFileCopy visitor file in Project.on prj Cil.initCIL (fun () -> ()); computeCFG ~clear_id:false file'; Project.on ~selection:(State_selection.singleton Ast.self) prj Ast.set_file file'; - if Parameters.Files.Check.get() then + if Kernel.Files.Check.get() then Project.on prj (* eta-expansion required because of operations on the current project in - the class construtor *) + the class construtor *) (fun f -> Cil.visitCilFile (new check_file ("AST of " ^ prj.Project.name) :> Cil.cilVisitor) f) @@ -1211,7 +1362,7 @@ let selection = State_selection.Static.union (State_selection.Static.with_dependencies Cil.selfMachine) - (State_selection.Static.with_dependencies Parameters.Files.self) + (State_selection.Static.with_dependencies Kernel.Files.self) in let selection = State_selection.Static.diff @@ -1223,62 +1374,54 @@ let temp = Project.create "File.temp" in Project.copy ~selection:(Plugin.get_selection ()) ~src:temp prj; Project.remove ~project:temp (); - Project.on prj Logic_env.Builtins.apply (); + Project.on prj init_cil (); prepare_from_visitor prj visitor; prj let init_from_c_files files = - (* Fill logic tables with builtins *) - (match files with - | [] -> () - | _ -> Files.register files); + (match files with [] -> () | _ :: _ -> Files.register files); prepare_from_c_files () let init_from_cmdline () = let prj1 = Project.current () in - if Parameters.Files.Copy.get () then begin + if Kernel.Files.Copy.get () then begin let selection = State_selection.Static.diff (State_selection.Static.diff State_selection.full (State_selection.of_list - [ Cil.Builtin_functions.self; - Logic_env.Logic_info.self; + [ Cil.Builtin_functions.self; + Logic_env.Logic_info.self; Logic_env.Logic_builtin_used.self; - Logic_env.Logic_type_info.self; - Logic_env.Logic_ctor_info.self; - Globals.Annotations.self; - Globals.Vars.self; - Globals.Functions.self; - Ast.self; - ]) - ) + Logic_env.Logic_type_info.self; + Logic_env.Logic_ctor_info.self; + Globals.Annotations.self; + Globals.Vars.self; + Globals.Functions.self; + Ast.self; + ])) (State_selection.Static.with_dependencies Annotations.self) in let prj2 = Project.create_by_copy ~selection "debug_copy_prj" in Project.set_current prj2; end; - let files = Parameters.Files.get () in + let files = Kernel.Files.get () in if files = [] && not !Config.is_gui then Kernel.warning "no input file."; let files = List.map (fun s -> from_filename s) files in try init_from_c_files files; - if Parameters.Files.Check.get () then begin + if Kernel.Files.Check.get () then begin Cil.visitCilFile (new check_file "Copy of original AST" :> Cil.cilVisitor) (Ast.get()) end; - if Parameters.Files.Copy.get () then begin + if Kernel.Files.Copy.get () then begin Project.on prj1 fill_built_ins (); prepare_from_visitor prj1 (fun prj -> new Visitor.frama_c_copy prj); - let selection = - State_selection.of_list - [Cil.Sid.self; Cil.Eid.self; Cil_const.Vid.self ] - in - Project.copy ~selection prj1; Project.set_current prj1; end; - with Ast.Bad_Initialisation s -> - Kernel.fatal "bad initialisation: %s" s + with Ast.Bad_Initialization s -> + Kernel.fatal "@[Cannot initialize from C files@ \ + Kernel raised Bad_Initialization %s@]" s let init_from_cmdline = Journal.register @@ -1307,7 +1450,7 @@ let pp_ast = Cil.d_file (new Printer.print ()) in let ast = Ast.get () in (match fmt_opt with - | None -> Parameters.CodeOutput.output "%a" pp_ast ast + | None -> Kernel.CodeOutput.output (fun fmt -> pp_ast fmt ast) | Some fmt -> pp_ast fmt ast) let unjournalized_pretty prj (fmt_opt:Format.formatter option) () = @@ -1325,6 +1468,28 @@ let pretty_ast ?(prj=Project.current ()) ?fmt () = journalized_pretty_ast prj fmt () +let create_rebuilt_project_from_visitor ?(preprocess=false) prj_name visitor = + let prj = create_project_from_visitor prj_name visitor in + try + let f = + let name = "frama_c_project_" ^ prj_name ^ "_" in + let ext = if preprocess then ".c" else ".i" in + if Kernel.Debug.get () > 0 then Filename.temp_file name ext + else Extlib.temp_file_cleanup_at_exit name ext + in + let cout = open_out f in + let fmt = Format.formatter_of_out_channel cout in + unjournalized_pretty prj (Some fmt) (); + let redo () = +(* Kernel.feedback "redoing initialization on file %s" f;*) + Files.reset (); + init_from_c_files [ if preprocess then from_filename f else NoCPP f ] + in + Project.on prj redo (); + prj + with Extlib.Temp_file_error s | Sys_error s -> + Kernel.abort "cannot create temporary file: %s" s + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/file.mli frama-c-20111001+nitrogen+dfsg/src/kernel/file.mli --- frama-c-20110201+carbon+dfsg/src/kernel/file.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/file.mli 2011-10-10 08:38:09.000000000 +0000 @@ -26,8 +26,8 @@ type file = | NeedCPP of string * string (** The first string is the filename of the [.c] to preprocess. - The second one is the preprocessor command ([filename.c -o - tempfilname.i] will be appended at the end).*) + The second one is the preprocessor command ([filename.c -o + tempfilname.i] will be appended at the end).*) | NoCPP of string (** Already pre-processed file [.i] *) | External of string * string @@ -41,6 +41,18 @@ (** [new_file_type suffix func funcname] registers a new type of files (with corresponding suffix) as recognized by Frama-C through [func]. *) +val new_machdep: string -> bool -> (unit -> unit) -> unit +(** [new_machdep name public func] registers a new machdep name as recognized by + Frama-C through [func]. [public] must be set to [true] to display it in the + help displayed by [frama-c -machdep help]. The usual uses is + [Cmdline.run_after_loading_stage + (fun () -> File.new_machdep + "my_machdep" + true + (fun () -> let module M = Machdep.DEFINE(My_machdep_implem) in ()))] + @since Nitrogen-20111001 + @raise Invalid_argument if the given name already exists *) + val get_suffixes: unit -> string list (** @return the list of accepted suffixes of input source files @since Boron-20100401 *) @@ -95,12 +107,27 @@ @since Beryllium-20090601-beta1 @plugin development guide *) +val create_rebuilt_project_from_visitor: + ?preprocess:bool -> string -> (Project.t -> Visitor.frama_c_visitor) -> + Project.t +(** Like {!create_project_from_visitor}, but the new generated cil file is + generated into a temp .i or .c file according to [preprocess], then re-built + by Frama-C in the returned project. For instance, use this function if the + new cil file contains a constructor {!GText} as global. + + Not that the generation of a preprocessed C file may fail in some cases + (e.g. if it includes headers already included). Thus the generated file is + NOT preprocessed by default. + + @raise File_types.Bad_Initialization if called more than once. + @since Nitrogen-20111001 *) + val init_from_cmdline: unit -> unit - (** Initialize the cil file representation with the file given on the - command line. - Should be called at most once per project. - @raise File_types.Bad_Initialization if called more than once. - @plugin development guide *) +(** Initialize the cil file representation with the file given on the + command line. + Should be called at most once per project. + @raise File_types.Bad_Initialization if called more than once. + @plugin development guide *) (* ************************************************************************* *) (** {2 Pretty printing} *) @@ -109,7 +136,7 @@ val pretty_ast : ?prj:Project.t -> ?fmt:Format.formatter -> unit -> unit (** Print the project CIL file on the given Formatter. The default project is the current one. - The default formatter is [Parameters.CodeOutput.get_fmt ()]. + The default formatter is [Kernel.CodeOutput.get_fmt ()]. @raise File_types.Bad_Initialization if the file is no initialized. *) (* diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/globals.ml frama-c-20111001+nitrogen+dfsg/src/kernel/globals.ml --- frama-c-20110201+carbon+dfsg/src/kernel/globals.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/globals.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,7 +22,6 @@ open Cil_types open Cil_datatype -open Db_types open Cil open Ast_info @@ -40,6 +39,10 @@ | Definition(d, _) -> d.slocals | Declaration(_, _, _, _) -> [] +let find_first_stmt = Extlib.mk_fun "Globals.find_first_stmt" + +let find_enclosing_block = Extlib.mk_fun "Globals.find_enclosing_block" + module Vars = struct include Cil_state_builder.Varinfo_hashtbl @@ -56,9 +59,9 @@ let add vi info = ignore (memo - ~change:(fun info -> raise (AlreadyExists(vi, info))) - (fun _ -> info) - vi) + ~change:(fun info -> raise (AlreadyExists(vi, info))) + (fun _ -> info) + vi) let add_decl vi = add vi { init = None } @@ -68,28 +71,39 @@ exception Found of varinfo let find_from_astinfo name = function | VGlobal -> - (try - iter (fun v _ -> if v.vname = name then raise (Found v)); - raise Not_found - with Found v -> - v) + (try + iter (fun v _ -> if v.vname = name then raise (Found v)); + raise Not_found + with Found v -> + v) | VLocal kf -> - List.find (fun v -> v.vname = name) (get_locals kf) + List.find (fun v -> v.vname = name) (get_locals kf) | VFormal kf -> - List.find (fun v -> v.vname = name) (get_formals kf) + List.find (fun v -> v.vname = name) (get_formals kf) let get_astinfo vi = !get_astinfo_ref vi let pp_varinfo p fmt v = let name, loc = get_astinfo v in let pp fmt = - Format.fprintf fmt "Globals.Vars.find_from_astinfo %S %a" name - (Kernel_datatype.Localisation.internal_pretty_code Type.Call) loc + Format.fprintf fmt "@[Globals.Vars.find_from_astinfo@;%S@;%a@]" + name + (Cil_datatype.Localisation.internal_pretty_code Type.Call) loc in Type.par p Type.Call fmt pp let () = Varinfo.internal_pretty_code_ref := pp_varinfo + let iter_in_file_order f = + let treat_global = function + | GVar(vi,init,_) -> f vi init + | GVarDecl (_,vi,_) when not (Cil.isFunctionType vi.vtype) -> + f vi { init = None } + | GType _ | GCompTag _ | GCompTagDecl _ | GEnumTag _ | GEnumTagDecl _ + | GVarDecl _ | GFun _ | GAsm _ | GPragma _ | GText _ | GAnnot _ -> () + in + List.iter treat_global (Ast.get ()).globals + end (* ************************************************************************* *) @@ -100,11 +114,11 @@ module State = Cil_state_builder.Varinfo_hashtbl - (Kernel_datatype.Kernel_function) + (Cil_datatype.Kf) (struct - let name = "Functions" - let dependencies = [ Ast.self ] - let size = 17 + let name = "Functions" + let dependencies = [ Ast.self ] + let size = 17 let kind = `Internal end) @@ -113,8 +127,7 @@ (* Maintain an alphabetical ordering of the functions, so that iteration stays independent from vid numerotation scheme. NB: Might be possible to have a map from string to vi in order - to use the structure for find_by_name - *) + to use the structure for find_by_name *) module VarinfoAlphaOrderSet = struct let compare x y = let res = String.compare x.vname y.vname in @@ -147,12 +160,15 @@ let kind = `Internal end) + let set_spec = Extlib.mk_fun "Globals.Functions.set_spec" + let init_kernel_function f spec = - { fundec = f; return_stmt = None; - spec = {spec with spec_variant = spec.spec_variant}; - stmts_graph = None } + let default_spec = Cil.empty_funspec () in + let kf = { fundec = f; return_stmt = None; spec = default_spec } in + !set_spec kf (fun _ -> spec); + kf - let register_declaration action spec v l = + let fundec_of_decl spec v l = let args = try Some (getFormalsDecl v) with Not_found -> @@ -161,46 +177,53 @@ Some (getFormalsDecl v) with Not_found -> None (* function with 0 arg. See setFormalsDecl code for details *) - in - action - (fun v -> init_kernel_function (Declaration(spec, v, args, l)) spec) - v + in Declaration(spec, v, args, l) + + let register_declaration action spec v l = + action (fun v -> init_kernel_function (fundec_of_decl spec v l) spec) v let add_declaration = - register_declaration - (fun f v -> Iterator.add v; State.memo f v) + register_declaration (fun f v -> Iterator.add v; State.memo f v) - let replace_by_declaration = - register_declaration - (fun f v -> Iterator.add v; State.replace v (f v)) + let update_kf kf fundec spec = + kf.fundec <- fundec; + (*Kernel.feedback "Spec of function %a is registered as %a" + Cil_datatype.Kf.pretty kf !Ast_printer.d_funspec spec; *) + !set_spec kf (fun old -> Logic_utils.merge_funspec spec old; spec); + kf.return_stmt <- None + + let replace_by_declaration s v l= + (* Kernel.feedback "replacing %a by decl" Cil_datatype.Varinfo.pretty v; *) + if State.mem v then begin + let fundec = fundec_of_decl s v l in + let kf = State.find v in + update_kf kf fundec s + end else + register_declaration + (fun f v -> Iterator.add v; State.replace v (f v)) s v l let replace_by_definition spec f l = + (* Kernel.feedback "replacing %a" Cil_datatype.Varinfo.pretty f.svar; *) Iterator.add f.svar; - State.replace f.svar (init_kernel_function (Definition (f, l)) spec) + if State.mem f.svar then + update_kf (State.find f.svar) (Definition (f,l)) spec + else + State.replace f.svar (init_kernel_function (Definition (f, l)) spec) let add f = match f with - | Definition (n, _) -> - if Kernel.debug_atleast 1 then - Kernel.debug - "Register definition %a with specification \"%a\"@\n" - Ast_info.pretty_vname n.svar !Ast_printer.d_funspec n.sspec ; - (try - let my_spec = (State.find n.svar).spec in - Logic_utils.merge_funspec n.sspec my_spec - with Not_found -> - ()); - Iterator.add n.svar; - State.replace n.svar (init_kernel_function f n.sspec); - Parameters.MainFunction.set_possible_values - (n.svar.vname :: Parameters.MainFunction.get_possible_values ()) - | Declaration (spec, v,_,_) -> - if Kernel.debug_atleast 1 then - Kernel.debug - "Register declaration %a with specification \"%a\"@\n" - Ast_info.pretty_vname v !Ast_printer.d_funspec spec; - Iterator.add v; - State.replace v (init_kernel_function f spec) + | Definition (n, l) -> + Kernel.debug + "Register definition %a with specification \"%a\"@\n" + Varinfo.pretty_vname n.svar !Ast_printer.d_funspec n.sspec ; + replace_by_definition n.sspec n l; + Kernel.MainFunction.set_possible_values + (n.svar.vname :: Kernel.MainFunction.get_possible_values ()) + | Declaration (spec, v,_,l) -> + Kernel.debug + "Register declaration %a with specification \"%a\"@\n" + Varinfo.pretty_vname v !Ast_printer.d_funspec spec; + replace_by_declaration spec v l let iter f = Iterator.iter (fun v -> f (State.find v)) let fold f = Iterator.fold (fun v acc -> f (State.find v) acc) @@ -212,29 +235,40 @@ | Declaration _ -> ()) let get vi = + (*Kernel.feedback "get %a in %a" Cil_datatype.Varinfo.pretty vi + Project.pretty (Project.current()); *) if not (is_function_type vi) then raise Not_found; - let add v = add_declaration (empty_funspec ()) v v.vdecl in + let add v = + (*Kernel.feedback "adding empty fun for %a" + Cil_datatype.Varinfo.pretty vi; *) + add_declaration (empty_funspec ()) v v.vdecl + in State.memo add vi let get_params kf = match kf.fundec with | Definition(f,_loc) -> f.sformals | Declaration(_spec,_v,params,_loc) -> - match params with None -> [] | Some ls -> ls + match params with None -> [] | Some ls -> ls let get_vi kf = match kf.fundec with | Definition(f,_loc) -> f.svar | Declaration(_spec,v,_params,_loc) -> v - let get_glob_init ?(main_name="main") (fl: file) = - match fl.globinit with - | Some f -> get f.svar - | None -> - (* Create a function by calling [Cil.getGlobInit] and register it *) - let gif = getGlobInit ~main_name fl in - add (Definition (gif, Location.unknown)); - get gif.svar + let register kf = + let vi = get_vi kf in + let add _ = kf in + let change old_kf = + if old_kf != kf then + Kernel.fatal + "Trying to associate two distinct \ + kernel functions with same varinfo %a" + Cil_datatype.Varinfo.pretty vi + else old_kf + in + ignore (State.memo ~change add vi); + Iterator.add vi exception Found_kf of kernel_function @@ -251,9 +285,9 @@ let find_def_by_name fct_name = let f kf = if Function.is_definition kf.fundec - && Function.get_name kf.fundec = fct_name + && Function.get_name kf.fundec = fct_name then - raise (Found_kf kf) + raise (Found_kf kf) in try iter f; @@ -264,7 +298,7 @@ match ki with | Kglobal -> None | Kstmt s -> - try + try iter (fun kf -> match kf.fundec with @@ -276,7 +310,7 @@ raise (Found_kf kf) | Declaration _ -> ()); None - with Found_kf kf -> + with Found_kf kf -> Some kf let find_englobing_kf = @@ -290,23 +324,23 @@ if vi.vglob then VGlobal else begin if vi.vformal then begin - try - iter - (fun kf -> - if List.exists (fun v -> v.vname = vi.vname) (get_formals kf) - then raise (Found kf)); - assert false - with Found kf -> - VFormal kf + try + iter + (fun kf -> + if List.exists (fun v -> v.vname = vi.vname) (get_formals kf) + then raise (Found kf)); + assert false + with Found kf -> + VFormal kf end else begin - try - iter - (fun kf -> - if List.exists (fun v -> v.vname = vi.vname) (get_locals kf) - then raise (Found kf)); - assert false - with Found kf -> - VLocal kf + try + iter + (fun kf -> + if List.exists (fun v -> v.vname = vi.vname) (get_locals kf) + then raise (Found kf)); + assert false + with Found kf -> + VLocal kf end end @@ -326,28 +360,30 @@ State_builder.List_ref (Datatype.Pair(Global_annotation)(Datatype.Bool)) (struct - let name = name - let dependencies = [ Ast.self ] + let name = name + let dependencies = [ Ast.self ] let kind = `Internal end) let self = State.self + let () = + State_dependency_graph.Static.add_dependencies + ~from:self + [ Property_status.self ] + let get_all = State.get let add b annot = let l = State.get () in - State.set ((annot, b) :: l) + State.set ((annot, b) :: l); + List.iter Property_status.register (Property.ip_of_global_annotation annot) let add_user = add false let add_generated = add true let iter f = List.iter (fun (a, b) -> f a b) (State.get ()) - let replace_all f = - let l = State.get () in - State.set (List.map (fun (a, b) -> f a b) l) - end (* ************************************************************************* *) @@ -363,9 +399,9 @@ (Datatype.String.Hashtbl) (Datatype.Pair(Datatype.String)(Datatype.List(Global))) (struct - let name = name - let dependencies = [ Ast.self ] - let size = 7 + let name = name + let dependencies = [ Ast.self ] + let size = 7 let kind = `Internal end) @@ -374,13 +410,12 @@ iterGlobals (Ast.get ()) (fun glob -> - let file = (fst (Global.loc glob)).Lexing.pos_fname in - let f = Filename.basename file in - if Kernel.debug_atleast 1 then - Kernel.debug "Indexing in file %s the global in %s@." f file; - ignore - (S.memo - ~change:(fun (f,l) -> f, glob:: l) (fun _ -> f,[ glob ]) file)) + let f = (fst (Global.loc glob)).Lexing.pos_fname in + if Kernel.debug_atleast 1 then + Kernel.debug "Indexing global in file %s@." f; + ignore + (S.memo + ~change:(fun (f,l) -> f, glob:: l) (fun _ -> f,[ glob ]) f)) in State_builder.apply_once "FileIndex.compute" [ S.self ] compute @@ -390,7 +425,10 @@ let get_symbols ~filename = compute (); - try S.find (Filename.basename filename) with Not_found -> S.find filename + try S.find filename + with Not_found -> + (* ??? *) + S.find (Filename.basename filename) let find ~filename = let f,l = get_symbols ~filename in @@ -406,51 +444,65 @@ let l = try snd (S.find filename) with Not_found -> [] in List.fold_right (fun glob acc -> - let is_glob_varinfo x = - if x.vglob then - match x.vtype with + let is_glob_varinfo x = + if x.vglob then + match x.vtype with | TFun _ -> None | _ -> Some x - else - None - in - let is_glob_var v = match v with - | Cil_types.GVar (vi, _, _) -> + else + None + in + let is_glob_var v = match v with + | Cil_types.GVar (vi, _, _) -> is_glob_varinfo vi - | Cil_types.GVarDecl(_,vi, _) -> + | Cil_types.GVarDecl(_,vi, _) -> is_glob_varinfo vi - | _ -> None - in - match is_glob_var glob with - | None -> acc - | Some vi -> Varinfo.Set.add vi acc) - l + | _ -> None + in + match is_glob_var glob with + | None -> acc + | Some vi -> Varinfo.Set.add vi acc) + l Varinfo.Set.empty in Varinfo.Set.fold (fun vi acc -> (vi, Vars.find vi) :: acc) varinfo_set [] - let get_functions ~filename = + let get_global_annotations ~filename = + compute (); + let l = try snd (S.find filename) with Not_found -> [] in + List.fold_right + (fun glob acc -> match glob with + | Cil_types.GAnnot(g, _) -> g :: acc + | _ -> acc) + l + [] + + let get_functions ?(declarations=false) ~filename = compute (); let varinfo_set = let l = try snd (S.find filename) with Not_found -> [] in List.fold_right (fun glob acc -> - let is_func_varinfo x = - if x.vglob then - match x.vtype with - | TFun _ -> Some x - | _ -> None - else - None - in let is_func v = match v with - | Cil_types.GVarDecl(_,vi, _) -> - is_func_varinfo vi - | Cil_types.GFun(fundec, _) -> Some (fundec.svar) - | _ -> None - in match is_func glob with - | None -> acc - | Some vi -> Varinfo.Set.add vi acc) - l + let is_func v = match v with + | Cil_types.GFun(fundec, _) -> + Some (fundec.svar) + | Cil_types.GVarDecl(_,x, _) -> + if x.vglob then + match x.vtype with + | TFun _ -> + if declarations || + (match (Functions.get x).fundec with + Definition _ -> false | Declaration _ -> true) + then Some x + else None + | _ -> None + else + None + | _ -> None + in match is_func glob with + | None -> acc + | Some vi -> Varinfo.Set.add vi acc) + l Varinfo.Set.empty in Varinfo.Set.fold @@ -467,14 +519,14 @@ | Cil_types.GFun (fundec, _) -> if List.exists pred fundec.Cil_types.slocals then true else if List.exists pred fundec.Cil_types.sformals then - (is_param := true; true) + (is_param := true; true) else false | _ -> false in let file = (fst x.Cil_types.vdecl).Lexing.pos_fname in match List.find pred (snd (S.find file)) with | Cil_types.GFun (fundec, _) -> - Functions.get fundec.Cil_types.svar, !is_param + Functions.get fundec.Cil_types.svar, !is_param | _ -> assert (false) end @@ -488,35 +540,127 @@ let entry_point () = Ast.compute (); let kf_name, lib = - Parameters.MainFunction.get (), Parameters.LibEntry.get () + Kernel.MainFunction.get (), Kernel.LibEntry.get () in - try Functions.find_def_by_name kf_name, lib + try Functions.find_by_name kf_name, lib with Not_found -> raise (No_such_entry_point - (Format.sprintf - "cannot find entry point `%s'.@;\ + (Format.sprintf + "cannot find entry point `%s'.@;\ Please use option `-main' for specifying a valid entry point." - kf_name)) + kf_name)) let set_entry_point name lib = let clear_from_entry_point () = let selection = State_selection.Dynamic.union - (State_selection.Dynamic.only_dependencies Parameters.MainFunction.self) - (State_selection.Dynamic.only_dependencies Parameters.LibEntry.self) + (State_selection.Dynamic.only_dependencies Kernel.MainFunction.self) + (State_selection.Dynamic.only_dependencies Kernel.LibEntry.self) in Project.clear ~selection () in let has_changed = - lib <> Parameters.LibEntry.get () || name <> Parameters.MainFunction.get () + lib <> Kernel.LibEntry.get () || name <> Kernel.MainFunction.get () in if has_changed then begin - Parameters.MainFunction.unsafe_set name; - Parameters.LibEntry.unsafe_set lib; + Kernel.MainFunction.unsafe_set name; + Kernel.LibEntry.unsafe_set lib; clear_from_entry_point () end +module Comments_global_cache = + State_builder.Hashtbl + (Cil_datatype.Global.Hashtbl) + (Datatype.List(Datatype.String)) + (struct + let name = "Comments_global_cache" + let dependencies = [ Cabshelper.Comments.self; FileIndex.self ] + let kind = `Internal + let size = 17 + end) + +module Comments_stmt_cache = + State_builder.Hashtbl + (Cil_datatype.Stmt.Hashtbl) + (Datatype.List(Datatype.String)) + (struct + let name = "Comments_stmt_cache" + let dependencies = [ Cabshelper.Comments.self; FileIndex.self ] + let kind = `Internal + let size = 17 + end) + +let get_comments_global g = + let last_pos f = + { Lexing.pos_fname = f; + Lexing.pos_lnum = max_int; + Lexing.pos_cnum = max_int; + Lexing.pos_bol = max_int + } + in + let add g = + let my_loc = Cil_datatype.Global.loc g in + let file = (fst my_loc).Lexing.pos_fname in + let globs = FileIndex.get_symbols file in + let globs = List.sort + (fun g1 g2 -> + Cil_datatype.Location.compare + (Cil_datatype.Global.loc g1) + (Cil_datatype.Global.loc g2)) + globs + in + let rec find_prev l = + match l with + | [] -> + Kernel.fatal "Cannot find global %a in file %s" + !Ast_printer.d_global g file + | g' :: l when Cil_datatype.Global.equal g g' -> + { Lexing.pos_fname = file; + Lexing.pos_lnum = 1; + Lexing.pos_cnum = 0; + Lexing.pos_bol = 0; }, l = [] + | g' :: g'' :: [] when Cil_datatype.Global.equal g'' g -> + snd (Cil_datatype.Global.loc g'), l = [] + | _ :: l -> find_prev l + in + let first, is_last = find_prev globs in + match g with + GFun (f,_) -> + let kf = Functions.get f.svar in + let s = !find_first_stmt kf in + let last = fst (Cil_datatype.Stmt.loc s) in + let comments = Cabshelper.Comments.get (first,last) in + if is_last then begin + let first = snd my_loc in + let last = last_pos file in + comments @ (Cabshelper.Comments.get (first, last)) + end else comments + | _ -> + let last = if is_last then last_pos file else snd my_loc in + Cabshelper.Comments.get (first,last) + in Comments_global_cache.memo add g + +let get_comments_stmt s = + let add s = + let b = !find_enclosing_block s in + let rec find_prev l = + match l with + | [] -> + Kernel.fatal "Cannot find statement %d in its enclosing block" s.sid + | s' :: _ when Cil_datatype.Stmt.equal s s' -> + fst (Cil_datatype.Stmt.loc s') + | s' :: s'' :: _ when Cil_datatype.Stmt.equal s'' s -> + snd (Cil_datatype.Stmt.loc s') + | { skind = UnspecifiedSequence l1} :: l2 -> + find_prev ((List.map (fun (x,_,_,_,_) -> x) l1) @ l2) + | _::l -> find_prev l + in + let first = find_prev b.bstmts in + let last = snd (Cil_datatype.Stmt.loc s) in + Cabshelper.Comments.get (first,last) + in Comments_stmt_cache.memo add s + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/globals.mli frama-c-20111001+nitrogen+dfsg/src/kernel/globals.mli --- frama-c-20110201+carbon+dfsg/src/kernel/globals.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/globals.mli 2011-10-10 08:38:09.000000000 +0000 @@ -24,7 +24,12 @@ @plugin development guide *) open Cil_types -open Db_types + +(* Forward reference to functions defined in Kernel_function. Do not + use outside of this module. + *) +val find_first_stmt: (kernel_function -> stmt) ref +val find_enclosing_block: (stmt -> block) ref (** Globals variables. The AST should be computed before using this module @@ -44,6 +49,8 @@ val iter: (varinfo -> initinfo -> unit) -> unit val fold: (varinfo -> initinfo -> 'a -> 'a) -> 'a -> 'a + val iter_in_file_order: (varinfo -> initinfo -> unit) -> unit + (** {2 Setters} Functions of this section should not be called by casual users. *) @@ -74,13 +81,6 @@ val get_params: kernel_function -> varinfo list val get_vi: kernel_function -> varinfo - val get_glob_init: ?main_name:string -> file -> kernel_function - (** Similar to [Cil.getGlobInit], except it registers the newly created - function. - @deprecated using this function is incorrect since it modifies the - current AST (see Plug-in Development Guide, Section "Using Projects"). - @return the internal function for global initializations. *) - (** {2 Searching} *) val find_by_name : string -> kernel_function @@ -93,7 +93,6 @@ (** @deprecated since Carbon-20101201 Use [Kernel_function.find_englobing_kf] instead *) - (** {2 Iterators} *) val iter: (kernel_function -> unit) -> unit @@ -112,6 +111,9 @@ val replace_by_definition: funspec -> fundec -> location -> unit (**TODO: do not take a funspec as argument *) + val set_spec: (kernel_function -> (funspec -> funspec) -> unit) ref + + val register: kernel_function -> unit end (* ************************************************************************* *) @@ -131,14 +133,12 @@ val iter: (global_annotation -> bool -> unit) -> unit (** The boolean parameter of the given function is [true] iff the - annotation was generated. *) + annotation was generated. *) (** {2 Setters} *) val add_user: global_annotation -> unit val add_generated: global_annotation -> unit - val replace_all: - (global_annotation -> bool -> global_annotation * bool) -> unit end @@ -148,17 +148,17 @@ val self: State.t (** The state kind corresponding to the table of global C symbols. - @since Boron-20100401 *) + @since Boron-20100401 *) (** {2 Getters} *) val get_symbols : filename:string -> global list (** All global C symbols of the given module. - @since Boron-20100401 *) + @since Boron-20100401 *) val find : filename:string -> string * (global list) (** All global C symbols for valviewer. - The file name to display is returned, and the [global] list reversed. *) + The file name to display is returned, and the [global] list reversed. *) val get_files: unit -> string list (** Get the files list containing all [global] C symbols. *) @@ -168,14 +168,22 @@ val get_globals : filename:string -> (varinfo * initinfo) list (** Global variables of the given module for the kernel user interface *) - val get_functions : filename:string -> kernel_function list - (** Global functions of the given module for the kernel user interface *) + val get_global_annotations: filename:string -> global_annotation list + (** Global annotations of the given module for the kernel user interface + @since Nitrogen-20111001 *) + + val get_functions : + ?declarations:bool -> filename:string -> kernel_function list + (** Global functions of the given module for the kernel user interface. + If [declarations] is true, functions declared in a module but defined + in another module are only reported in the latter (default is false). + *) val kernel_function_of_local_var_or_param_varinfo : varinfo -> (kernel_function * bool) (** kernel_function where the local variable or formal parameter is - declared. The boolean result is true for a formal parameter. - @raise Not_found if the varinfo is a global one. *) + declared. The boolean result is true for a formal parameter. + @raise Not_found if the varinfo is a global one. *) end @@ -194,12 +202,46 @@ you don't have to catch it yourself, except if you do a specific work. *) val set_entry_point : string -> bool -> unit -(** [set_entry_point name lib] sets [Parameters.MainFunction] to [name] if - [lib] is [false] and [Parameters.LibEntry] to [name] if [lib] is [true]. +(** [set_entry_point name lib] sets [Kernel.MainFunction] to [name] if + [lib] is [false] and [Kernel.LibEntry] to [name] if [lib] is [true]. Moreover, clear the results of all the analysis which depend on - [Parameters.MainFunction] or [Parameters.LibEntry]. + [Kernel.MainFunction] or [Kernel.LibEntry]. @plugin development guide *) +(* ************************************************************************* *) +(** {2 Comments} *) +(* ************************************************************************* *) + +val get_comments_global: global -> string list +(** Gets a list of comments associated to the given global. This function + is useful only when -keep-comments is on. + + A comment is associated to a global if it occurs after + the declaration/definition of the preceding one in the file, before the end + of the current declaration/definition and does not occur in the + definition of a function. Note that this function is experimental and + may fail to associate comments properly. Use directly + {! Cabshelper.Comments.get} to retrieve comments in a given region. + (see {!Globals.get_comments_stmt} for retrieving comments associated to + a statement). + + @since Nitrogen-20111001 +*) + +val get_comments_stmt: stmt -> string list +(** Gets a list of comments associated to the given global. This function + is useful only when -keep-comments is on. + + A comment is associated to a global if it occurs after + the preceding statement and before the current statement ends (except for + the last statement in a block, to which statements occuring before the end + of the block are associated). Note that this function is experimental and + may fail to associate comments properly. Use directly + {! Cabshelper.Comments.get} to retrieve comments in a given region. + + @since Nitrogen-20111001 +*) + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/gui_init.ml frama-c-20111001+nitrogen+dfsg/src/kernel/gui_init.ml --- frama-c-20110201+carbon+dfsg/src/kernel/gui_init.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/gui_init.ml 2011-10-10 08:38:09.000000000 +0000 @@ -21,7 +21,7 @@ (**************************************************************************) (** Frama-C GUI early initialization. *) - + let () = Config.is_gui := true (* diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/journal.ml frama-c-20111001+nitrogen+dfsg/src/kernel/journal.ml --- frama-c-20110201+carbon+dfsg/src/kernel/journal.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/journal.ml 2011-10-10 08:38:09.000000000 +0000 @@ -58,7 +58,7 @@ type t = { sentence: Format.formatter -> unit; - raise_exn: bool } + raise_exn: bool } let sentences : t Queue.t = Queue.create () @@ -156,15 +156,15 @@ incr cpt; let suf = "_" ^ string_of_int !cpt in (try - let n = - Str.search_backward - (Str.regexp "_[0-9]+") - !filename - (String.length !filename - 1) - in - filename := Str.string_before !filename n ^ suf + let n = + Str.search_backward + (Str.regexp "_[0-9]+") + !filename + (String.length !filename - 1) + in + filename := Str.string_before !filename n ^ suf with Not_found -> - filename := !filename ^ suf); + filename := !filename ^ suf); get_filename false end else name @@ -207,12 +207,12 @@ module Binding: sig val add: 'a Type.t -> 'a -> string -> unit (** [add ty v var] binds the value [v] to the variable name [var]. Thus, - [pp ty v] prints [var] and not use the standard pretty printer. Very - useful to pretty print values with no associated pretty printer. *) + [pp ty v] prints [var] and not use the standard pretty printer. Very + useful to pretty print values with no associated pretty printer. *) exception Name_already_exists of string val add_once: 'a Type.t -> 'a -> string -> unit (** Same as function [add] above but raise the exception [Already_exists] - if the binding previously exists *) + if the binding previously exists *) val find: 'a Type.t -> 'a -> string end = struct @@ -247,7 +247,7 @@ if Cmdline.journal_enable && Cmdline.use_type then if Obj.tag (Obj.repr f) = Obj.closure_tag then Obj.magic - (fun y -> if !started then Obj.magic f y else raise (Not_writable name)) + (fun y -> if !started then Obj.magic f y else raise (Not_writable name)) else invalid_arg ("[Journal.never_write] " ^ name ^ " is not a closure") else @@ -261,9 +261,9 @@ let pp = Datatype.internal_pretty_code ty in if pp == Datatype.undefined then fatal - "no printer registered for value of type %s.@\n\ + "no printer registered for value of type %s.@\n\ Journalisation is not possible. Aborting" - (Type.name ty); + (Type.name ty); if pp == Datatype.pp_fail then Format.fprintf fmt @@ -310,22 +310,22 @@ if not (Type.equal ty Datatype.unit) then Format.fprintf fmt "let %t=@;" (fun fmt -> - let binding = - let varname = Datatype.varname ty in - match varname == Datatype.undefined, value with - | true, _ | _, None -> - "__" (* no binding nor value: ignore the result *) - | false, Some value -> - (* bind to a fresh variable name *) - let v = Obj.obj value in - let b = gen_binding (varname v) in - Binding.add ty v b; - b - in - Format.fprintf fmt "%s" binding; - (* add the return type for dynamic application *) - if is_dyn then Format.fprintf fmt "@;: %s" (Type.name ty) - else Format.fprintf fmt " "); + let binding = + let varname = Datatype.varname ty in + match varname == Datatype.undefined, value with + | true, _ | _, None -> + "__" (* no binding nor value: ignore the result *) + | false, Some value -> + (* bind to a fresh variable name *) + let v = Obj.obj value in + let b = gen_binding (varname v) in + Binding.add ty v b; + b + in + Format.fprintf fmt "%s" binding; + (* add the return type for dynamic application *) + if is_dyn then Format.fprintf fmt "@;: %s" (Type.name ty) + else Format.fprintf fmt " "); (* pretty print the sentence itself in a box *) Format.fprintf fmt "@[%t@]" f_acc; (* close the sentence *) @@ -368,33 +368,33 @@ let opt_arg = Type.Function.get_optional_argument ty in Obj.repr (fun (y:'a) -> - if !started then - (* prevent journalisation if you're journalizing another function *) - Obj.repr (Obj.obj x y) - else begin - let old_started = !started in - try - (* [started] prevents journalization of function call - inside another one *) - started := true; - (* apply the closure [x] to its argument [y] *) - let xy = Obj.obj x y in - started := old_started; - (* extend the continuation and continue *) - let f_acc = extend_continuation f_acc (pp a) opt_label opt_arg y in - journalize_function f_acc b is_dyn comment xy - with - | Not_writable name -> - started := old_started; - fatal - "a call to the function %S cannot be written in the journal" - name - | exn as e -> - let f_acc = extend_continuation f_acc (pp a) opt_label opt_arg y in - catch_exn f_acc is_dyn comment b exn; - started := old_started; - raise e - end) + if !started then + (* prevent journalisation if you're journalizing another function *) + Obj.repr (Obj.obj x y) + else begin + let old_started = !started in + try + (* [started] prevents journalization of function call + inside another one *) + started := true; + (* apply the closure [x] to its argument [y] *) + let xy = Obj.obj x y in + started := old_started; + (* extend the continuation and continue *) + let f_acc = extend_continuation f_acc (pp a) opt_label opt_arg y in + journalize_function f_acc b is_dyn comment xy + with + | Not_writable name -> + started := old_started; + fatal + "a call to the function %S cannot be written in the journal" + name + | exn as e -> + let f_acc = extend_continuation f_acc (pp a) opt_label opt_arg y in + catch_exn f_acc is_dyn comment b exn; + started := old_started; + raise e + end) end else begin if not !started then add_sentence f_acc is_dyn comment ~value:x ty; x diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/journal.mli frama-c-20111001+nitrogen+dfsg/src/kernel/journal.mli --- frama-c-20110201+carbon+dfsg/src/kernel/journal.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/journal.mli 2011-10-10 08:38:09.000000000 +0000 @@ -34,15 +34,15 @@ 'a -> 'a (** [register name ty ~comment ~is_dyn v] journalizes the value [v] - of type [ty] with the name [name]. [name] must exactly match the caml - long name of the value (i.e. "List.iter" and not "iter" even though the - module List is already opened). Journalisation of anonymous value is - not possible. + of type [ty] with the name [name]. [name] must exactly match the caml + long name of the value (i.e. "List.iter" and not "iter" even though the + module List is already opened). Journalisation of anonymous value is + not possible. - If the [comment] argument is set, the given pretty printer will be - applied in an OCaml comment when the function is journalized. + If the [comment] argument is set, the given pretty printer will be + applied in an OCaml comment when the function is journalized. - Set [is_dyn] to [true] to journalize a dynamic function. *) + Set [is_dyn] to [true] to journalize a dynamic function. *) val never_write: string -> 'a -> 'a (** [never_write name f] returns a closure [g] observationaly equal to [f] @@ -57,12 +57,12 @@ module Binding: sig val add: 'a Type.t -> 'a -> string -> unit (** [add ty v var] binds the value [v] to the variable name [var]. Thus, - [pp ty v] prints [var] and not use the standard pretty printer. Very - useful to pretty print values with no associated pretty printer. *) + [pp ty v] prints [var] and not use the standard pretty printer. Very + useful to pretty print values with no associated pretty printer. *) exception Name_already_exists of string val add_once: 'a Type.t -> 'a -> string -> unit (** Same as function [add] above but raise the exception [Already_exists] - if the binding previously exists *) + if the binding previously exists *) end (* ****************************************************************************) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/kernel_datatype.ml frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_datatype.ml --- frama-c-20110201+carbon+dfsg/src/kernel/kernel_datatype.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_datatype.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Db_types -open Cil_datatype - -module Rooted_code_annotation = - Datatype.Make - (struct - include Datatype.Serializable_undefined - type t = Db_types.rooted_code_annotation - let name = "rooted_code_annotation" - let reprs = - List.map (fun c -> User c) Code_annotation.reprs - let compare x y = match x, y with - | User a, User b - | AI(_, a), AI(_, b) -> Code_annotation.compare a b - | User _, AI _ -> -1 - | AI _, User _ -> 1 - let equal = Datatype.from_compare - let mem_project = Datatype.never_any_project - end) - -module Before_after_poly = - Datatype.Polymorphic - (struct - type 'a t = 'a before_after - let name ty = Type.name ty ^ " before_after" - let module_name = "kernel_datatype.Before_after" - let structural_descr _ = Structural_descr.Abstract - let reprs r = [ Before r; After r ] - let mk_compare f x y = match x, y with - | Before a, Before b -> f a b - | After a, After b -> f a b - | Before _, After _ -> -1 - | After _, Before _ -> 1 - let mk_equal = Datatype.undefined - let mk_hash = Datatype.undefined - let map f = - if f == Datatype.identity then Datatype.identity - else function Before a -> Before (f a) | After a -> After (f a) - let mk_internal_pretty_code = Datatype.undefined - let mk_pretty = Datatype.undefined - let mk_mem_project _ = Datatype.never_any_project - let mk_varname = Datatype.undefined - end) - -module Before_after = Before_after_poly.Make -module Rooted_code_annotation_before_after = - Before_after(Rooted_code_annotation) - -module Kernel_function = struct - let id kf = Ast_info.Function.get_id kf.fundec - include Datatype.Make_with_collections - (struct - type t = kernel_function - let name = "Kernel_function" - let structural_descr = Structural_descr.Abstract - let reprs = - [ { fundec = - Definition - (Cil.emptyFunction "@dummy@", Location.unknown); - return_stmt = None; - spec = Cil.empty_funspec (); - stmts_graph = None } ] - let compare k1 k2 = Datatype.Int.compare (id k1) (id k2) - let equal = (==) - let hash = id - let copy = Datatype.undefined - let rehash x = match x.fundec with - | Definition _ | Declaration (_, _, None, _)-> x - | Declaration (_, v, Some args, _) -> - Cil.unsafeSetFormalsDecl v args; - x - let get_name_kf kf = (Ast_info.Function.get_vi kf.fundec).Cil_types.vname - let internal_pretty_code p_caller fmt kf = - Type.par p_caller Type.Call fmt - (fun fmt -> - Format.fprintf fmt "@[Globals.Functions.find_by_name@;%S@]" - (get_name_kf kf)) - let pretty fmt kf = - Ast_info.pretty_vname fmt (Ast_info.Function.get_vi kf.fundec) - let mem_project = Datatype.never_any_project - let varname kf = "kf_" ^ (get_name_kf kf) - end) - -end - -(* ------------------------------------------------------------------------- *) -(* localisation *) -(* ------------------------------------------------------------------------- *) - -module Localisation = - Datatype.Make - (struct - include Datatype.Serializable_undefined - type t = localisation - let name = "kernel_datatype.Localisation" - let reprs = [ VGlobal ] - let internal_pretty_code p_caller fmt loc = - let pp s kf = - Type.par p_caller Type.Call fmt - (fun fmt -> - Format.fprintf fmt "@[%s@;%a@]" - s - (Kernel_function.internal_pretty_code Type.Call) - kf) - in - match loc with - | VGlobal -> Format.fprintf fmt "Db_types.VGlobal" - | VLocal kf -> pp "Db_types.VLocal" kf - | VFormal kf -> pp "Db_types.VFormal" kf - let mem_project = Datatype.never_any_project - end) - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/kernel_datatype.mli frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_datatype.mli --- frama-c-20110201+carbon+dfsg/src/kernel/kernel_datatype.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_datatype.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Datatypes of some useful kernel types. - @plugin development guide *) - -open Db_types - -module Rooted_code_annotation: - Datatype.S with type t = rooted_code_annotation - -module Before_after(A: Datatype.S) : - Datatype.S with type t = A.t before_after - -module Rooted_code_annotation_before_after: - Datatype.S with type t = rooted_code_annotation before_after - -module Kernel_function: sig - include Datatype.S_with_collections with type t = kernel_function - val id: t -> int -end - -module Localisation: Datatype.S with type t = localisation - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/kernel_function.ml frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_function.ml --- frama-c-20110201+carbon+dfsg/src/kernel/kernel_function.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_function.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,7 +22,7 @@ open Extlib open Cil_types -open Db_types +open Cil_datatype (* ************************************************************************* *) (** {2 Getters} *) @@ -30,10 +30,9 @@ let dummy () = { fundec = - Definition (Cil.emptyFunction "@dummy@", Cil_datatype.Location.unknown); + Definition (Cil.emptyFunction "@dummy@", Location.unknown); return_stmt = None; - spec = Cil.empty_funspec (); - stmts_graph = None } + spec = Cil.empty_funspec ()} let get_vi kf = Ast_info.Function.get_vi kf.fundec let get_id kf = (get_vi kf).vid @@ -69,7 +68,7 @@ (** {2 Kernel functions are comparable} *) (* ************************************************************************* *) -include Kernel_datatype.Kernel_function +include Cil_datatype.Kf (* ************************************************************************* *) (** {2 Searching} *) @@ -77,11 +76,7 @@ module Kf = State_builder.Option_ref - (Cil_datatype.Int_hashtbl.Make - (Datatype.Triple - (Kernel_datatype.Kernel_function) - (Cil_datatype.Stmt) - (Datatype.List(Cil_datatype.Block)))) + (Int_hashtbl.Make(Datatype.Triple(Kf)(Stmt)(Datatype.List(Block)))) (struct let name = "KF" let dependencies = [ Ast.self ] @@ -90,6 +85,11 @@ let self = Kf.self +let () = + State_dependency_graph.Static.add_dependencies + ~from:Kf.self + [ Property_status.self ] + let clear_sid_info () = Kf.clear () let compute () = @@ -98,10 +98,10 @@ let p = Ast.get () in let h = Inthash.create 97 in let visitor = object(self) - inherit Cil.nopCilVisitor - val mutable current_kf = None + inherit Cil.nopCilVisitor + val mutable current_kf = None val mutable opened_blocks = [] - method kf = match current_kf with None -> assert false | Some kf -> kf + method kf = match current_kf with None -> assert false | Some kf -> kf method vblock b = opened_blocks <- b :: opened_blocks; Cil.ChangeDoChildrenPost @@ -125,14 +125,16 @@ let find_from_sid sid = let table = compute () in - let kf,s,_ = Inthash.find table sid in + let kf, s, _ = Inthash.find table sid in s, kf +let () = Dataflow.stmt_of_sid := (fun sid -> fst (find_from_sid sid)) + let find_englobing_kf stmt = snd (find_from_sid stmt.sid) let blocks_closed_by_edge s1 s2 = - if not (List.exists (Cil_datatype.Stmt.equal s2) s1.succs) then + if not (List.exists (Stmt.equal s2) s1.succs) then raise (Invalid_argument "Kernel_function.edge_exits_block"); let table = compute () in try @@ -140,7 +142,10 @@ let _,_,b2 = Inthash.find table s2.sid in Kernel.debug ~level:2 "Blocks opened for stmt %a@\n%a@\nblocks opened for stmt %a@\n%a" - !Ast_printer.d_stmt s1 (Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep !Ast_printer.d_block) b1 !Ast_printer.d_stmt s2 (Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep !Ast_printer.d_block) b2; + !Ast_printer.d_stmt s1 + (Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep !Ast_printer.d_block) b1 + !Ast_printer.d_stmt s2 + (Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep !Ast_printer.d_block) b2; let rec aux acc = function [] -> acc | inner_block::others -> @@ -157,11 +162,15 @@ let (_,_,b) = Inthash.find table s.sid in List.hd b +let () = Globals.find_enclosing_block:= find_enclosing_block + let find_all_enclosing_blocks s = let table = compute () in let (_,_,b) = Inthash.find table s.sid in b exception Got_return of stmt +exception No_Statement + let find_return kf = match kf.return_stmt with | None -> @@ -179,18 +188,23 @@ assert false with Got_return s -> s in - let ki = find_return (get_definition kf) in - kf.return_stmt <- Some ki; - ki + (try + let ki = find_return (get_definition kf) in + kf.return_stmt <- Some ki; + ki + with No_Definition -> + raise No_Statement) | Some ki -> ki -exception No_Statement -let find_first_stmt kf = - try - List.hd ((get_definition kf).sbody.bstmts) - with No_Definition | Not_found -> - raise No_Statement +let get_stmts kf = + try (get_definition kf).sbody.bstmts with No_Definition | Not_found -> [] + +let find_first_stmt kf = match get_stmts kf with + | [] -> raise No_Statement + | s :: _ -> s + +let () = Globals.find_first_stmt := find_first_stmt exception Found_label of stmt ref let find_label kf label = @@ -206,7 +220,7 @@ | Case _ -> false | Default _ -> label="default") s.labels then raise (Found_label (ref s)); - Cil.DoChildren + Cil.DoChildren end method vexpr _ = Cil.SkipChildren method vtype _ = Cil.SkipChildren @@ -223,46 +237,46 @@ (** {2 CallSites} *) (* ************************************************************************* *) -module CallSite = Datatype.Pair(Kernel_datatype.Kernel_function)(Cil_datatype.Stmt) -module CallSites = Kernel_datatype.Kernel_function.Hashtbl -module KfCallers = State_builder.Option_ref(CallSites.Make(Datatype.List(CallSite))) - (struct - let name = "Kf.CallSites" - let dependencies = [ Ast.self ] - let kind = `Internal - end) +module CallSite = Datatype.Pair(Cil_datatype.Kf)(Stmt) +module CallSites = Cil_datatype.Kf.Hashtbl +module KfCallers = + State_builder.Option_ref(CallSites.Make(Datatype.List(CallSite))) + (struct + let name = "Kf.CallSites" + let dependencies = [ Ast.self ] + let kind = `Internal + end) let called_kernel_function fct = match fct.enode with - | Lval (Var vinfo,NoOffset) -> - (try Some(Globals.Functions.get vinfo) with Not_found -> None) + | Lval (Var vinfo,NoOffset) -> + (try Some(Globals.Functions.get vinfo) with Not_found -> None) | _ -> None - -class callsite_visitor hmap = -object(self) + +class callsite_visitor hmap = object (self) inherit Cil.nopCilVisitor val mutable current_kf = None method private kf = match current_kf with None -> assert false | Some kf -> kf (* Go into functions *) method vglob = function - | GFun(fd,_) -> - current_kf <- Some(Globals.Functions.get fd.svar) ; - Cil.DoChildren + | GFun(fd,_) -> + current_kf <- Some(Globals.Functions.get fd.svar) ; + Cil.DoChildren | _ -> Cil.SkipChildren (* Inspect stmt calls *) method vstmt stmt = match stmt.skind with | Instr(Call(_,fct,_,_)) -> - begin - match called_kernel_function fct with - | None -> Cil.SkipChildren - | Some ckf -> - let sites = try CallSites.find hmap ckf with Not_found -> [] in - CallSites.replace hmap ckf ((self#kf,stmt)::sites) ; - Cil.SkipChildren - end + begin + match called_kernel_function fct with + | None -> Cil.SkipChildren + | Some ckf -> + let sites = try CallSites.find hmap ckf with Not_found -> [] in + CallSites.replace hmap ckf ((self#kf,stmt)::sites) ; + Cil.SkipChildren + end | Instr _ -> Cil.SkipChildren | _ -> Cil.DoChildren @@ -274,9 +288,9 @@ let compute_callsites () = let ast = Ast.get () in - let hmap = CallSites.create 97 in + let hmap = CallSites.create 97 in let visitor = new callsite_visitor hmap in - Cil.visitCilFile (visitor :> Cil.cilVisitor) ast ; + Cil.visitCilFile (visitor :> Cil.cilVisitor) ast ; hmap let find_syntactic_callsites kf = @@ -321,13 +335,24 @@ let populate_spec = Extlib.mk_fun "Kernel_function.populate_spec" -let get_spec f = - if is_definition f then +let get_spec ?(populate=true) f = + if is_definition f || not populate then f.spec - else - ((* Do not overwrite an existing assign clause*) - !populate_spec f; - f.spec) + else begin + (* Do not overwrite an existing assigns clause*) + !populate_spec f; + (* Kernel.feedback + "Getting spec of %a: %a" pretty f !Ast_printer.d_funspec f.spec; *) + f.spec + end + +let set_spec kf f = + let get_ppts kf = Property.ip_of_spec kf Kglobal kf.spec in + let old = get_ppts kf in + kf.spec <- f kf.spec; + Property_status.merge ~old (get_ppts kf) + +let () = Globals.Functions.set_spec := set_spec let postcondition kf k = Logic_const.pands @@ -346,10 +371,10 @@ let def = get_definition kf in List.fold_left (fun acc stmt -> - Annotations.single_fold_stmt - (fun a acc -> (stmt, a) :: acc) - stmt - acc) + Annotations.single_fold_stmt + (fun a acc -> (stmt, a) :: acc) + stmt + acc) [] def.sallstmts with No_Definition -> @@ -361,7 +386,7 @@ List.fold_left (fun known_names stmt -> List.fold_left - (fun known_names spec -> + (fun known_names (_bhv,spec) -> (List.map (fun x -> x.b_name) spec.spec_behavior) @ known_names) known_names (Logic_utils.extract_contract @@ -370,7 +395,8 @@ (Annotations.get_all_annotations stmt)))) [] def.sallstmts - with No_Definition -> [] + with No_Definition -> + [] let spec_function_behaviors kf = List.map (fun x -> x.b_name) (get_spec kf).spec_behavior @@ -384,27 +410,34 @@ let name = name ^ "_" ^ (string_of_int i) in if List.mem name existing_behaviors then aux (i+1) else name - in if List.mem name existing_behaviors then aux 0 else name + in + if List.mem name existing_behaviors then aux 0 else name (* ************************************************************************* *) (** {2 Pretty printer} *) (* ************************************************************************* *) -let pretty_name fmt kf = Ast_info.pretty_vname fmt (get_vi kf) +let pretty_name = + Kernel.deprecated + "Kernel_function.pretty" + ~now:"Kernel_function.pretty" + pretty (* ************************************************************************* *) (** {2 Collections} *) (* ************************************************************************* *) -module Make_Table = - State_builder.Hashtbl(Kernel_datatype.Kernel_function.Hashtbl) +module Make_Table = State_builder.Hashtbl(Cil_datatype.Kf.Hashtbl) module Hptset = struct - include Hptset.Make(Kernel_datatype.Kernel_function) - (* [JS 2010/09/27] preserve the old behavior (before introducing generic - pretty printers *) - let pretty fmt = - iter (fun kf -> Format.fprintf fmt "@[%a@ @]" pretty_name kf) + let pretty_kf = pretty + + include Hptset.Make + (Cil_datatype.Kf) + (struct let v = [ [ ] ] end) + (struct let l = [ Ast.self ] end) + + let pretty fmt = Pretty_utils.pp_iter iter pretty_kf fmt end (* ************************************************************************* *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/kernel_function.mli frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_function.mli --- frama-c-20110201+carbon+dfsg/src/kernel/kernel_function.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/kernel_function.mli 2011-10-10 08:38:09.000000000 +0000 @@ -24,7 +24,6 @@ @plugin development guide *) open Cil_types -open Db_types (* ************************************************************************* *) (** {2 Kernel functions are comparable and hashable} *) @@ -45,7 +44,10 @@ function. *) val find_return : t -> stmt - (** Find the return statement of a kernel function. *) + (** Find the return statement of a kernel function. + @raise No_Statement is there is no return statement for the given + function. + @modify Nitrogen-20111001 may raise No_Statement*) val find_label : t -> string -> stmt ref (** Find a given label in a kernel function. @@ -87,8 +89,8 @@ val find_syntactic_callsites : t -> (t * stmt) list (** [callsites f] collect the statements where [f] is called. Same complexity as [find_from_sid]. - @return a list of [f',s] where function [f'] calls [f] at statement [stmt]. - @since Carbon-20101202+dev *) + @return a list of [f',s] where function [f'] calls [f] at statement [stmt]. + @since Carbon-20110201 *) (* ************************************************************************* *) (** {2 Checkers} *) @@ -144,14 +146,25 @@ (** {2 Specifications} *) (* ************************************************************************* *) -val get_spec: t -> funspec +val get_spec: ?populate:bool -> t -> funspec +(** [get_spec f] returns the spec of the function. You should use it instead of + [f.spec]. If [populate] is set to [false] (default is [true]), then you get + the spec without the default behavior generated when expected by the Frama-C + kernel (assuming that this behavior was not already generated). *) + +val set_spec: t -> (funspec -> funspec) -> unit +(** [set_spec kf how_to_modify] replaces the old spec [s] of [kf] by [f s]. + The function [s] is allowed to modify [s] in place and to return [s] at the + end. You must call this function to modify a spec and you must not modify + directly the 'spec' field of the record yourself. + @since Nitrogen-20111001 *) val postcondition : t -> Cil_types.termination_kind -> predicate named (** @modify Boron-20100401 added argument to select desired termination kind *) val precondition: t -> predicate named -val code_annotations: t -> (stmt*rooted_code_annotation before_after) list +val code_annotations: t -> (stmt * rooted_code_annotation) list val internal_function_behaviors: t -> string list (** @return the list of behavior names that are defined in statement contracts @@ -198,7 +211,8 @@ (* ************************************************************************* *) val pretty_name : Format.formatter -> t -> unit - (** Print the name of a kernel function. *) + (** Print the name of a kernel function. + @deprecated since Nitrogen-20111001 Use {!pretty} instead. *) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/kernel.ml frama-c-20111001+nitrogen+dfsg/src/kernel/kernel.ml --- frama-c-20110201+carbon+dfsg/src/kernel/kernel.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/kernel.ml 2011-10-10 08:38:09.000000000 +0000 @@ -20,20 +20,9 @@ (* *) (**************************************************************************) -module type Parameter_input = sig - include Plugin.Parameter_input - val module_name: string -end - -module type Parameter_input_with_arg = sig - include Plugin.Parameter_input_with_arg - val module_name: string -end - -module type COMPLEX_VALUE = sig - include Plugin.COMPLEX_VALUE - val module_name: string -end +(* ************************************************************************* *) +(** {2 Kernel as an almost standard plug-in} *) +(* ************************************************************************* *) let () = Plugin.register_kernel () @@ -47,6 +36,20 @@ include (P: Plugin.S) +(* ************************************************************************* *) +(** {2 Specialised functors for building kernel parameters} *) +(* ************************************************************************* *) + +module type Parameter_input = sig + include Plugin.Parameter_input + val module_name: string +end + +module type Parameter_input_with_arg = sig + include Plugin.Parameter_input_with_arg + val module_name: string +end + module Bool(X:sig include Parameter_input val default: bool end) = P.Bool(struct let () = Plugin.set_module_name X.module_name include X end) @@ -78,12 +81,840 @@ P.StringList (struct let () = Plugin.set_module_name X.module_name include X end) -module IndexedVal (V:COMPLEX_VALUE) = - P.IndexedVal - (struct let () = Plugin.set_module_name V.module_name include V end) +(* ************************************************************************* *) +(** {2 Installation Information} *) +(* ************************************************************************* *) + +let () = Plugin.set_group help +let () = Plugin.set_cmdline_stage Cmdline.Exiting +let () = Plugin.do_not_journalize () +module GeneralHelp = + False + (struct + let option_name = "-help" + let help = "display a general help" + let module_name = "GeneralHelp" + end) + +let run_help () = if GeneralHelp.get () then Cmdline.help () else Cmdline.nop +let () = Cmdline.run_after_exiting_stage run_help +let () = GeneralHelp.add_aliases [ "--help"; "-h" ] + +let () = Plugin.set_group help +let () = Plugin.set_cmdline_stage Cmdline.Early +module PrintVersion = + False + (struct + let option_name = "-version" + let module_name = "PrintVersion" + let help = "print version information" + end) +let () = PrintVersion.add_aliases [ "-v"; "--version" ] + +let () = Plugin.set_group help +let () = Plugin.set_cmdline_stage Cmdline.Early +module PrintShare = + False(struct + let option_name = "-print-share-path" + let module_name = "PrintShare" + let help = "print the Frama-C share path" + let kind = Parameter.Other + end) +let () = PrintShare.add_aliases [ "-print-path" ] + +let () = Plugin.set_group help +let () = Plugin.set_cmdline_stage Cmdline.Early +module PrintLib = + False(struct + let option_name = "-print-lib-path" + let module_name = "PrintLib" + let help = "print the path of the Frama-C kernel library" + let kind = Parameter.Other + end) +let () = PrintLib.add_aliases [ "-print-libpath" ] + +let () = Plugin.set_group help +let () = Plugin.set_cmdline_stage Cmdline.Early +module PrintPluginPath = + False + (struct + let option_name = "-print-plugin-path" + let module_name = "PrintPluginPath" + let help = + "print the path where the Frama-C dynamic plug-ins are searched into" + let kind = Parameter.Other + end) + +let () = Plugin.set_group help +let () = Plugin.set_negative_option_name "" +module DumpDependencies = + EmptyString + (struct + let module_name = "DumpDependencies" + let option_name = "-dump-dependencies" + let help = "" + let arg_name = "" + let kind = Parameter.Other + end) +let () = + at_exit + (fun () -> + if not (DumpDependencies.is_default ()) then + State_dependency_graph.Dynamic.dump (DumpDependencies.get ())) + +(* ************************************************************************* *) +(** {2 Output Messages} *) +(* ************************************************************************* *) + +let () = Plugin.set_group messages +let () = Plugin.do_not_projectify () +let () = Plugin.do_not_journalize () +let () = Plugin.set_cmdline_stage Cmdline.Early +let () = Plugin.do_iterate () +module GeneralVerbose = + Int + (struct + let default = 1 + let option_name = "-verbose" + let arg_name = "n" + let help = "general level of verbosity" + let module_name = "GeneralVerbose" + let kind = Parameter.Other + end) +let () = + (* line order below matters *) + GeneralVerbose.set_range ~min:0 ~max:max_int; + GeneralVerbose.add_set_hook (fun _ n -> Cmdline.verbose_level_ref := n); + GeneralVerbose.set !Cmdline.verbose_level_ref + +let () = Plugin.set_group messages +let () = Plugin.do_not_projectify () +let () = Plugin.do_not_journalize () +let () = Plugin.set_cmdline_stage Cmdline.Early +let () = Plugin.do_iterate () +module GeneralDebug = + Zero + (struct + let option_name = "-debug" + let arg_name = "n" + let help = "general level of debug" + let module_name = "GeneralDebug" + let kind = Parameter.Other + end) +let () = + (* line order below matters *) + GeneralDebug.set_range ~min:0 ~max:max_int; + GeneralDebug.add_set_hook + (fun old n -> + if n = 0 then decr Plugin.positive_debug_ref + else if old = 0 then incr Plugin.positive_debug_ref; + Cmdline.debug_level_ref := n); + GeneralDebug.set !Cmdline.debug_level_ref + +let () = Plugin.set_group messages +let () = Plugin.set_negative_option_name "" +let () = Plugin.set_cmdline_stage Cmdline.Early +let () = Plugin.do_iterate () +let () = Plugin.do_not_projectify () +let () = Plugin.do_not_journalize () +module Quiet = + Bool + (struct + let default = Cmdline.quiet + let option_name = "-quiet" + let module_name = "Quiet" + let help = "sets -verbose and -debug to 0" + let kind = Parameter.Other + end) +let () = + Quiet.add_set_hook + (fun _ b -> assert b; GeneralVerbose.set 0; GeneralDebug.set 0) + +let () = Plugin.set_group messages +let () = Plugin.do_not_journalize () +let () = Plugin.do_not_projectify () +module Unicode = struct + include True + (struct + let option_name = "-unicode" + let module_name = "Unicode" + let help = "use utf8 in messages" + let kind = Parameter.Other + end) + (* This function behaves nicely with the Gui, that detects if command-line + arguments have been set by the user at some point. One possible improvment + would be to bypass journalization entirely, but this requires an API + change in Plugin *) + let without_unicode f arg = + let old, default = get (), not (is_set ()) in + off (); + let r = f arg in + if default then clear () else set old; + r +end + +module UseUnicode = struct + include Unicode + let set = deprecated "UseUnicode.set" ~now:"Unicode.set" set + let on = deprecated "UseUnicode.on" ~now:"Unicode.on" on + let off = deprecated "UseUnicode.off" ~now:"Unicode.off" off + let get = deprecated "UseUnicode.get" ~now:"Unicode.get" get +end + +let () = Plugin.set_group messages +module Time = + EmptyString + (struct + let module_name = "Time" + let option_name = "-time" + let arg_name = "filename" + let help = "append user time and date to at exit" + let kind = Parameter.Other + end) + +let () = Plugin.set_group messages +let () = Plugin.set_negative_option_name "-do-not-collect-messages" +let () = Plugin.do_not_projectify () +let () = Plugin.set_cmdline_stage Cmdline.Early +module Collect_messages = + Bool + (struct + let module_name = "Collect_messages" + let option_name = "-collect-messages" + let help = "collect warning and error messages for displaying them in \ +the GUI (set by default iff the GUI is launched)" + let kind = Parameter.Other + let default = !Config.is_gui + (* ok: Config.is_gui already initialised by Gui_init *) + end) + +(* ************************************************************************* *) +(** {2 Input / Output Source Code} *) +(* ************************************************************************* *) + +let inout_source = add_group "Input/Output Source Code" + +let () = Plugin.set_group inout_source +module PrintCode = + False + (struct + let module_name = "PrintCode" + let option_name = "-print" + let help = "pretty print original code with its comments" + let kind = Parameter.Other + end) + +let () = Plugin.set_group inout_source +let () = Plugin.do_not_projectify () +module PrintComments = + False + (struct + let module_name = "PrintComments" + let option_name = "-keep-comments" + let help = "try to keep comments in C code" + let kind = Parameter.Other + end) + +module CodeOutput = struct + + let () = Plugin.set_group inout_source + include EmptyString + (struct + let module_name = "CodeOutput" + let option_name = "-ocode" + let arg_name = "filename" + let help = + "when printing code, redirects the output to file " + let kind = Parameter.Other + end) + + let streams = Hashtbl.create 7 + + let output job = + let file = get () in + if file = "" + then Log.print_delayed job + else + try + let fmt = + try fst (Hashtbl.find streams file) + with Not_found -> + let out = open_out file in + let fmt = Format.formatter_of_out_channel out in + Hashtbl.add streams file (fmt,out) ; fmt + in + job fmt + with Sys_error s -> + warning + "Fail to open file \"%s\" for code output@\nSystem error: %s.@\n\ + Code is output on stdout instead." file s ; + Log.print_delayed job + + let close_all () = + Hashtbl.iter + (fun file (fmt,cout) -> + try + Format.pp_print_flush fmt () ; + close_out cout ; + with Sys_error s -> + failure + "Fail to close output file \"%s\"@\nSystem error: %s." + file s) + streams + + let () = at_exit close_all + +end + +let () = Plugin.set_group inout_source +module FloatNormal = + False + (struct + let option_name = "-float-normal" + let module_name = "FloatNormal" + let help = "display floats with internal routine" + let kind = Parameter.Other + end) + +let () = Plugin.set_group inout_source +module FloatRelative = + False + (struct + let option_name = "-float-relative" + let module_name = "FloatRelative" + let help = "display float intervals as [lower_bound ++ width]" + let kind = Parameter.Other + end) + +let () = Plugin.set_group inout_source +module FloatHex = + False + (struct + let option_name = "-float-hex" + let module_name = "FloatHex" + let help = "display floats as hexadecimal" + let kind = Parameter.Other + end) + +let () = Plugin.set_group inout_source +module BigIntsHex = + Int(struct + let module_name = "BigIntsHex" + let option_name = "-big-ints-hex" + let arg_name = "max" + let help = "display integers larger than using hexadecimal \ +notation" + let kind = Parameter.Other + let default = -1 + end) + +(* ************************************************************************* *) +(** {2 Save/Load} *) +(* ************************************************************************* *) + +let saveload = add_group "Saving or Loading Data" + +let () = Plugin.set_group saveload +module SaveState = + EmptyString + (struct + let module_name = "SaveState" + let option_name = "-save" + let arg_name = "filename" + let help = "at exit, save the session into file " + let kind = Parameter.Other + end) + +let () = Plugin.set_group saveload +let () = Plugin.set_cmdline_stage Cmdline.Loading +module LoadState = + EmptyString + (struct + let module_name = "LoadState" + let option_name = "-load" + let arg_name = "filename" + let help = "load a previously-saved session from file " + let kind = Parameter.Other + end) + +let () = Plugin.set_group saveload +let () = Plugin.set_cmdline_stage Cmdline.Extending +module AddPath = + StringList + (struct + let option_name = "-add-path" + let module_name = "AddPath" + let arg_name = "p1, ..., pn" + let help = "prepend paths to dynamic plugins search path" + let kind = Parameter.Other + end) +let () = + AddPath.add_set_hook + (fun _ _ -> AddPath.iter (fun s -> ignore (Dynamic.add_path s))) + +let () = Plugin.set_group saveload +let () = Plugin.set_cmdline_stage Cmdline.Extending +module LoadModule = + StringSet + (struct + let option_name = "-load-module" + let module_name = "LoadModule" + let arg_name = "m1, ..., mn" + let help = "load the given modules dynamically" + let kind = Parameter.Other + end) +let () = + LoadModule.add_set_hook (fun _ _ -> LoadModule.iter Dynamic.load_module) + +let () = Plugin.set_group saveload +let () = Plugin.set_cmdline_stage Cmdline.Extending +module Dynlink = + True + (struct + let option_name = "-dynlink" + let module_name = "Dynlink" + let help = "load all the found dynamic plug-ins (default); \ +otherwise, ignore all plug-ins in default directories" + let kind = Parameter.Other + end) +let () = Dynlink.add_set_hook (fun _ -> Dynamic.set_default) + +let () = Plugin.set_group saveload +let () = Plugin.set_cmdline_stage Cmdline.Extending +module LoadScript = + StringSet + (struct + let option_name = "-load-script" + let module_name = "LoadScript" + let arg_name = "m1, ..., mn" + let help = "load the given OCaml scripts dynamically" + let kind = Parameter.Other + end) +let () = + LoadScript.add_set_hook (fun _ _ -> LoadScript.iter Dynamic.load_script) + +module Journal = struct + let () = Plugin.set_negative_option_name "-journal-disable" + let () = Plugin.set_cmdline_stage Cmdline.Early + let () = Plugin.set_group saveload + module Enable = struct + include Bool + (struct + let module_name = "Journal.Enable" + let default = Cmdline.journal_enable + let option_name = "-journal-enable" + let help = "dump a journal while Frama-C exit" + let kind = Parameter.Other + end) + let is_set () = Cmdline.journal_isset + end + let () = Plugin.set_group saveload + module Name = + String + (struct + let module_name = "Journal.Name" + let option_name = "-journal-name" + let default = Journal.get_name () + let arg_name = "s" + let help = + "set the filename of the journal (do not write any extension)" + let kind = Parameter.Other + end) +end + +(* ************************************************************************* *) +(** {2 Customizing Normalization} *) +(* ************************************************************************* *) + +let normalisation = add_group "Customizing Normalization" + +let () = Plugin.set_group normalisation +module UnrollingLevel = + Zero + (struct + let module_name = "UnrollingLevel" + let option_name = "-ulevel" + let arg_name = "l" + let help = "unroll loops n times (defaults to 0) before analyzes" + let kind = Parameter.Tuning + end) + +let () = Plugin.set_group normalisation +module Machdep = + EmptyString + (struct + let module_name = "Machdep" + let option_name = "-machdep" + let arg_name = "machine" + let help = "use as the current machine dependent configuration. Use -machdep help to see the list of available machines" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group normalisation +module ReadAnnot = + True(struct + let module_name = "ReadAnnot" + let option_name = "-annot" + let help = "read annotation" + let kind = Parameter.Other + end) + +let () = Plugin.set_group normalisation +module PreprocessAnnot = + False(struct + let module_name = "PreprocessAnnot" + let option_name = "-pp-annot" + let help = "pre-process annotations (if they are read)" + let kind = Parameter.Other + end) + +let () = Plugin.set_group normalisation +module CppCommand = + EmptyString + (struct + let module_name = "CppCommand" + let option_name = "-cpp-command" + let arg_name = "cmd" + let help = " is used to build the preprocessing command.\n\ +Default to $CPP environment variable or else \"gcc -C -E -I.\".\n\ +If unset, the command is built as follow:\n\ + CPP -o \n\ +%1 and %2 can be used into CPP string to mark the position of \ +and respectively" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group normalisation +module CppExtraArgs = + StringSet + (struct + let module_name = "CppExtraArgs" + let option_name = "-cpp-extra-args" + let arg_name = "args" + let help = "additional arguments passed to the preprocessor while \ +preprocessing the C code but not while preprocessing annotations" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group normalisation +let () = Plugin.set_negative_option_name "" +module TypeCheck = + False(struct + let module_name = "TypeCheck" + let option_name = "-typecheck" + let help = "only typechecks the source files" + let kind = Parameter.Other + end) + +let () = Plugin.set_group normalisation +module ContinueOnAnnotError = + False(struct + let module_name = "ContinueOnAnnotError" + let option_name = "-continue-annot-error" + let help = "When an annotation fails to type-check, just emits \ + a warning and discards the annotation instead of \ + generating an error (errors in C are still fatal)" + let kind = Parameter.Other + end) + +let () = Plugin.set_group normalisation +module SimplifyCfg = + False + (struct + let module_name = "SimplifyCfg" + let option_name = "-simplify-cfg" + let help = + "remove break, continue and switch statement before analyzes" + let kind = Parameter.Tuning + end) + +let () = Plugin.set_group normalisation +module KeepSwitch = + False(struct + let option_name = "-keep-switch" + let module_name = "KeepSwitch" + let help = "keep switch statements despite -simplify-cfg" + let kind = Parameter.Tuning + end) + +let () = Plugin.set_group normalisation +module Constfold = + False + (struct + let option_name = "-constfold" + let module_name = "Constfold" + let help = "fold all constant expressions in the code before analysis" + let kind = Parameter.Tuning + end) + +module Files = struct + + let () = Plugin.is_invisible () + include StringList + (struct + let option_name = "" + let module_name = "Files" + let arg_name = "" + let help = "" + let kind = Parameter.Correctness + end) + let () = Cmdline.use_cmdline_files set + + let () = Plugin.set_group normalisation + module Check = + False(struct + let option_name = "-check" + let module_name = "Files.Check" + let help = "performs consistency checks over cil files" + let kind = Parameter.Other + end) + + let () = Plugin.set_group normalisation + module Copy = + False(struct + let option_name = "-copy" + let module_name = "Files.Copy" + let help = + "always perform a copy of the original AST before analysis begin" + let kind = Parameter.Other + end) + + let () = Plugin.set_group normalisation + module Orig_name = + False(struct + let option_name = "-orig-name" + let module_name = "Files.Orig_name" + let help = "prints a message each time a variable is renamed" + let kind = Parameter.Other + end) + +end + +let () = Plugin.set_group normalisation +module AllowDuplication = + True(struct + let option_name = "-allow-duplication" + let module_name = "AllowDuplication" + let help = + "allow duplication of small blocks during normalization" + let kind = Parameter.Tuning + end) + +(** If false, the destination of a Call instruction should always have the + same type as the function's return type. Where needed, CIL will insert + a temporary to make this happen. + + If true, the destination type may differ from the return type, so there + is an implicit cast. This is useful for analyses involving [malloc], + because the instruction "T* x = malloc(...);" won't be broken into + two instructions, so it's easy to find the allocation type. + + This is false by default. Set to true to replicate the behavior + of CIL 1.3.5 and earlier. *) +let () = Plugin.set_group normalisation +module DoCollapseCallCast = + True(struct + let option_name = "-collapse-call-cast" + let module_name = "DoCollapseCallCast" + let help = + "Allow implicit cast between returned value of a function \ + and the lval it is assigned to." + let kind = Parameter.Tuning + end) + +let () = Plugin.set_group normalisation +module ForceRLArgEval = + False(struct + let option_name = "-force-rl-arg-eval" + let module_name = "ForceRLArgEval" + let help = "Force right to left evaluation order for \ + arguments of function calls" + let kind = Parameter.Tuning + end) + +let normalization_parameters = [ + ForceRLArgEval.parameter; + UnrollingLevel.parameter; + Machdep.parameter; + CppCommand.parameter; + CppExtraArgs.parameter; + SimplifyCfg.parameter; + KeepSwitch.parameter; + Constfold.parameter; + AllowDuplication.parameter; + DoCollapseCallCast.parameter; +] + +(* ************************************************************************* *) +(** {2 Analysis Options} *) +(* ************************************************************************* *) + +let analysis_options = add_group "Analysis Options" + +let () = Plugin.set_group analysis_options +module MainFunction = + String + (struct + let module_name = "MainFunction" + let default = "main" + let option_name = "-main" + let arg_name = "f" + let help = "set to name the entry point for analysis. Use -lib-entry \ +if this is not for a complete application. Defaults to main" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group analysis_options +module LibEntry = + False + (struct + let module_name = "LibEntry" + let option_name = "-lib-entry" + let help ="run analysis for an incomplete application e.g. an API call. See the -main option to set the entry point name" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group analysis_options +module UnspecifiedAccess = + False(struct + let module_name = "UnspecifiedAccess" + let option_name = "-unspecified-access" + let help = "assume that all read/write accesses occuring in unspecified order are not separated" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group analysis_options +module Overflow = + True(struct + let module_name = "Overflow" + let option_name = "-overflow" + let help = "assume that arithmetic operations overflow" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group analysis_options +module StopAtFirstAlarm = + False(struct + let module_name = "StopAtFirstAlarm" + let option_name = "-stop-at-first-alarm" + let help = "" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group analysis_options +module PreciseUnions = + False + (struct + let module_name = "PreciseUnions" + let option_name = "-precise-unions" + let help = "" + let kind = Parameter.Tuning + end) + +let () = Plugin.set_group analysis_options +module ArrayPrecisionLevel = + Int + (struct + let module_name = "ArrayPrecisionLevel" + let default = 200 + let option_name = "-plevel" + let arg_name = "n" + let help = "use as the precision level for arrays accesses. Array accesses are precise as long as the interval for the index contains less than n values. (defaults to 200)" + let kind = Parameter.Tuning + end) + +let () = Plugin.set_negative_option_name "-unsafe-arrays" +let () = Plugin.set_group analysis_options +module SafeArrays = + True + (struct + let module_name = "SafeArrays" + let option_name = "-safe-arrays" + let help = "for arrays that are fields inside structs, assume that accesses are in bounds" + let kind = Parameter.Correctness + end) + +let () = Plugin.set_group analysis_options +module AbsoluteValidRange = struct + module Info = struct + let option_name = "-absolute-valid-range" + let arg_name = "min-max" + let help = "min and max must be integers in decimal, hexadecimal (0x, 0X), octal (0o) or binary (0b) notation and fit in 64 bits. Assume that that all absolute addresses outside of the [min-max] range are invalid. In the absence of this option, all absolute addresses are assumed to be invalid" + let default = "" + let module_name = "AbsoluteValidRange" + let kind = Parameter.Correctness + end + include String(Info) + let is_set _x = assert false +end + +(* +let () = Plugin.set_group analysis_options +module FloatFlushToZero = + False + (struct + let option_name = "-float-flush-to-zero" + let help = "Floating-point operations flush to zero" + let module_name = "FloatFlushToZero" + let kind = Parameter.Correctness + end) +*) + +(* ************************************************************************* *) +(** {2 Others options} *) +(* ************************************************************************* *) + +let misc = add_group "Miscellaneous Options" + +let () = + Cmdline.add_option_without_action + "-then" + ~plugin:"" + ~group:(misc :> Cmdline.Group.t) + ~help:(Some "parse options before `-then' and execute Frama-C \ +accordingly, then parse options after `-then' and re-execute Frama-C") + ~ext_help:"" + () + +let () = + Cmdline.add_option_without_action + "-then-on" + ~plugin:"" + ~argname:"p" + ~group:(misc :> Cmdline.Group.t) + ~help:(Some "like `-then', but the second group of actions is executed \ +on project

    ") + ~ext_help:"" + () + +let () = Plugin.set_group misc +let () = Plugin.set_negative_option_name "" +let () = Plugin.set_cmdline_stage Cmdline.Early +module NoType = + Bool + (struct + let module_name = "NoType" + let default = not Cmdline.use_type + let option_name = "-no-type" + let help = "" + let kind = Parameter.Other + end) + +let () = Plugin.set_group misc +let () = Plugin.set_negative_option_name "" +let () = Plugin.set_cmdline_stage Cmdline.Early +module NoObj = + Bool + (struct + let module_name = "NoObj" + let default = not Cmdline.use_obj + let option_name = "-no-obj" + let help = "" + let kind = Parameter.Other + end) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/kernel.mli frama-c-20111001+nitrogen+dfsg/src/kernel/kernel.mli --- frama-c-20110201+carbon+dfsg/src/kernel/kernel.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/kernel.mli 2011-10-10 08:38:09.000000000 +0000 @@ -22,73 +22,255 @@ (** Provided services for kernel developers. *) +(* ************************************************************************* *) +(** {2 Log Machinery} *) +(* ************************************************************************* *) + include Plugin.S -(** Each parameter of functors used to registered a new kernel parameter must - have a module name. *) +(* ************************************************************************* *) +(** {2 Installation Information} *) +(* ************************************************************************* *) + +module PrintVersion: Plugin.Bool + (** Behavior of option "-version" *) + +module PrintShare: Plugin.Bool + (** Behavior of option "-print-share-path" *) + +module PrintLib: Plugin.Bool + (** Behavior of option "-print-lib-path" *) + +module PrintPluginPath: Plugin.Bool + (** Behavior of option "-print-plugin-path" *) + +(* ************************************************************************* *) +(** {2 Output Messages} *) +(* ************************************************************************* *) + +module GeneralVerbose: Plugin.Int + (** Behavior of option "-verbose" *) + +module GeneralDebug: Plugin.Int + (** Behavior of option "-debug" *) + +module Quiet: Plugin.Bool + (** Behavior of option "-quiet" *) -module type Parameter_input = sig - include Plugin.Parameter_input - val module_name: string +module Unicode: sig + include Plugin.Bool + val without_unicode: ('a -> 'b) -> 'a -> 'b + (** Execute the given function as if the option [-unicode] was not set. *) end +(** Behavior of option "-unicode" *) -module type Parameter_input_with_arg = sig - include Plugin.Parameter_input_with_arg - val module_name: string +module UseUnicode: Plugin.Bool + (** Behavior of option "-unicode" + @deprecated since Nitrogen-20111001 use module {!Unicode} instead. + @plugin development guide *) + +module Time: Plugin.String + (** Behavior of option "-time" *) + +module Collect_messages: Plugin.Bool +(** Behavior of option "-collect-messages" *) + +(* ************************************************************************* *) +(** {2 Input / Output Source Code} *) +(* ************************************************************************* *) + +module PrintCode : Plugin.Bool + (** Behavior of option "-print" *) + +module PrintComments: Plugin.Bool + (** Behavior of option "-keep-comments" *) + +(** Behavior of option "-ocode" *) +module CodeOutput : sig + include Plugin.String + val output: (Format.formatter -> unit) -> unit end -module type COMPLEX_VALUE = sig - include Plugin.COMPLEX_VALUE - val module_name: string +module FloatNormal: Plugin.Bool + (** Behavior of option "-float-normal" *) + +module FloatRelative: Plugin.Bool + (** Behavior of option "-float-relative" *) + +module FloatHex: Plugin.Bool + (** Behavior of option "-float-hex" *) + +module BigIntsHex: Plugin.Int + (** Behavior of option "-hexadecimal-big-integers" *) + +(* ************************************************************************* *) +(** {2 Save/Load} *) +(* ************************************************************************* *) + +module SaveState: Plugin.String + (** Behavior of option "-save" *) + +module LoadState: Plugin.String + (** Behavior of option "-load" *) + +module AddPath: Plugin.String_list + (** Behavior of option "-add-path" *) + +module LoadModule: Plugin.String_set + (** Behavior of option "-load-module" *) + +module LoadScript: Plugin.String_set + (** Behavior of option "-load-script" *) + +module Dynlink: Plugin.Bool + (** Behavior of option "-dynlink" *) + +(** Kernel for journalization. *) +module Journal: sig + + module Enable: Plugin.Bool + (** Behavior of option "-journal-enable" *) + + module Name: Plugin.String + (** Behavior of option "-journal-name" *) + end -module Bool - (X:sig - include Parameter_input - val default: bool - (** The default value of the parameter. So giving the option - [option_name] to Frama-C, change the value of the parameter to - [not default]. *) - end) : Plugin.BOOL +(* ************************************************************************* *) +(** {2 Customizing Normalization} *) +(* ************************************************************************* *) + +module UnrollingLevel: Plugin.Int + (** Behavior of option "-ulevel" *) + +(** Behavior of option "-machdep". + If function [set] is called, then {!File.prepare_from_c_files} must be + called for well preparing the AST. *) +module Machdep: Plugin.String + +module CppCommand: Plugin.String + (** Behavior of option "-cpp-command" *) + +module CppExtraArgs: Plugin.String_set + (** Behavior of option "-cpp-extra-args" *) -(** Build a boolean option initialized to [false]. - @plugin development guide *) -module False(X: Parameter_input) : Plugin.BOOL +module ReadAnnot: Plugin.Bool + (** Behavior of option "-read-annot" *) -(** Build a boolean option initialized to [true]. - @plugin development guide *) -module True(X: Parameter_input) : Plugin.BOOL +module PreprocessAnnot: Plugin.Bool + (** Behavior of option "-pp-annot" *) -(** Build an integer option. - @plugin development guide *) -module Int - (X: sig val default: int include Parameter_input_with_arg end) : Plugin.INT +module TypeCheck: Plugin.Bool + (** Behavior of option "-type-check" *) -(** Build an integer option initialized to [0]. - @plugin development guide *) -module Zero(X:Parameter_input_with_arg) : Plugin.INT +module ContinueOnAnnotError: Plugin.Bool + (** Behavior of option "-continue-annot-error" *) -(** Build a string option. - @plugin development guide *) -module String - (X: sig include Parameter_input_with_arg val default: string end) : - Plugin.STRING +module SimplifyCfg: Plugin.Bool + (** Behavior of option "-simplify-cfg" *) -(** Build a string option initialized to [""]. - @plugin development guide *) -module EmptyString(X: Parameter_input_with_arg) : Plugin.STRING +module KeepSwitch: Plugin.Bool + (** Behavior of option "-keep-switch" *) -(** Build an option as a set of strings, initialized to the empty set. *) -module StringSet(X: Parameter_input_with_arg) : Plugin.STRING_SET +module Constfold: Plugin.Bool + (** Behavior of option "-constfold" *) -(** Should not be used by casual users *) -module StringList(X: Parameter_input_with_arg) : Plugin.STRING_LIST +(** Analyzed files *) +module Files: sig -(** @plugin development guide *) -module IndexedVal (V:COMPLEX_VALUE) : Plugin.INDEXED_VAL with type value = V.t + include Plugin.String_list + (** List of files to analyse *) + + module Check: Plugin.Bool + (** Behavior of option "-check" *) + + module Copy: Plugin.Bool + (** Behavior of option "-copy" *) + + module Orig_name: Plugin.Bool + (** Behavior of option "-orig-name" *) + +end + +val normalization_parameters: Parameter.t list +(** All the normalization options that influence the AST (in particular, + changing one will reset the AST entirely *) + +(* ************************************************************************* *) +(** {3 Customizing cabs2cil options} *) +(* ************************************************************************* *) + +module AllowDuplication: Plugin.Bool + (** Behavior of option "-allow-duplication". *) + +module DoCollapseCallCast: Plugin.Bool + (** Behavior of option "-collapse-call-cast". *) + +module ForceRLArgEval: Plugin.Bool + (** Behavior of option "-force-rl-arg-eval". *) + +(* ************************************************************************* *) +(** {2 Analysis Behavior of options} *) +(* ************************************************************************* *) + +(** Behavior of option "-main". + + You should usually use {!Globals.entry_point} instead of + {!MainFunction.get} since the first one handles the case where the entry + point is invalid in the right way. *) +module MainFunction: sig + + include Plugin.String + + (** {2 Internal functions} + + Not for casual users. *) + + val unsafe_set: t -> unit + +end + +(** Behavior of option "-lib-entry". + + You should usually use {!Globals.entry_point} instead of + {!LibEntry.get} since the first one handles the case where the entry point + is invalid in the right way. *) +module LibEntry: sig + include Plugin.Bool + val unsafe_set: t -> unit (** Not for casual users. *) +end + +module UnspecifiedAccess: Plugin.Bool + (** Behavior of option "-unspecified-access" *) + +module ArrayPrecisionLevel: Plugin.Int + (** Temporary option to voluntarily approximate + results of accesses at an imprecise index + for the sake of speed. *) + +module PreciseUnions: Plugin.Bool + (** Temporary option to produce precise results + when accessing type-punned data. *) + +module Overflow: Plugin.Bool + (** Behavior of option "-overflow" *) + +module StopAtFirstAlarm: Plugin.Bool + (** Stop propagation at first alarm *) + +module SafeArrays: Plugin.Bool + (** Behavior of option "-safe-arrays" *) + +module AbsoluteValidRange: Plugin.String + (** Behavior of option "-absolute-valid-range" *) + +(* +module FloatFlushToZero: Plugin.Bool + (** Behavior of option "-float-flush-to-zero" *) +*) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/log.ml frama-c-20111001+nitrogen+dfsg/src/kernel/log.ml --- frama-c-20110201+carbon+dfsg/src/kernel/log.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/log.ml 2011-10-10 08:38:09.000000000 +0000 @@ -20,14 +20,12 @@ (* *) (**************************************************************************) -type source = { src_file : string ; src_line : int } - type kind = Result | Feedback | Debug | Warning | Error | Failure type event = { evt_kind : kind ; evt_plugin : string ; - evt_source : source option ; + evt_source : Lexing.position option ; evt_message : string ; } @@ -111,7 +109,7 @@ if is_locked t then failwith "Console is already locked" ; t.lock <- Locked ; - Format.make_formatter t.output t.flush + Format.make_formatter t.output t.flush ; end let unlock_terminal t fmt = @@ -126,12 +124,11 @@ t.delayed <- [] ; end -let print_on_output text = - Format.kfprintf - (unlock_terminal stdout) - (lock_terminal stdout) - text - +let print_on_output job = + let fmt = lock_terminal stdout in + try job fmt ; unlock_terminal stdout fmt + with error -> unlock_terminal stdout fmt ; raise error + (* -------------------------------------------------------------------------- *) (* --- Delayed Lock until first write --- *) (* -------------------------------------------------------------------------- *) @@ -144,11 +141,11 @@ let d_output d text k n = match !d with | Delayed t -> - t.lock <- Locked ; - d := Formatter( t.output , t.flush ) ; - t.output text k n + t.lock <- Locked ; + d := Formatter( t.output , t.flush ) ; + t.output text k n | Formatter(out,_) -> - out text k n + out text k n in let d_flush d () = match !d with @@ -157,11 +154,10 @@ in Format.make_formatter (d_output d) (d_flush d) -let print_delayed text = - Format.kfprintf - (unlock_terminal stdout) - (delayed_terminal stdout) - text +let print_delayed job = + let fmt = delayed_terminal stdout in + try job fmt ; unlock_terminal stdout fmt + with error -> unlock_terminal stdout fmt ; raise error (* -------------------------------------------------------------------------- *) (* --- Buffering Output --- *) @@ -197,10 +193,10 @@ let avail = String.length buffer.text in if req > avail then begin - let s = size_up req avail in - let t = String.create s in - String.blit buffer.text 0 t 0 buffer.pos ; - buffer.text <- t ; + let s = size_up req avail in + let t = String.create s in + String.blit buffer.text 0 t 0 buffer.pos ; + buffer.text <- t ; end ; String.blit text k buffer.text buffer.pos n ; buffer.pos <- buffer.pos + n ; @@ -265,38 +261,42 @@ let t = try String.index_from text p '\n' with Not_found -> (-1) in if t < 0 || t > q then begin - (* incomplete, last line *) - echo_line output prefix text p (q+1-p) ; - output "\n" 0 1 ; + (* incomplete, last line *) + echo_line output prefix text p (q+1-p) ; + output "\n" 0 1 ; end else begin - (* complete line *) - echo_line output prefix text p (t+1-p) ; - echo_lines output text (next_line prefix) (t+1) q ; + (* complete line *) + echo_line output prefix text p (t+1-p) ; + echo_lines output text (next_line prefix) (t+1) q ; end let echo_source output = function | None -> () | Some src -> - let s = Printf.sprintf "%s:%d:" src.src_file src.src_line in - output s 0 (String.length s) + let s = + Printf.sprintf "%s:%d:" src.Lexing.pos_fname src.Lexing.pos_lnum + in + output s 0 (String.length s) let do_echo terminal source prefix text p q = if p <= q then if delayed_echo terminal then - let s = String.sub text p (q+1-p) in - let job t = - echo_source t.output source ; - echo_lines t.output s prefix 0 (String.length s - 1) ; - t.flush () - in - terminal.delayed <- job :: terminal.delayed + begin + let s = String.sub text p (q+1-p) in + let job t = + echo_source t.output source ; + echo_lines t.output s prefix 0 (String.length s - 1) ; + t.flush () + in + terminal.delayed <- job :: terminal.delayed + end else begin - echo_source terminal.output source ; - echo_lines terminal.output text prefix p q ; - terminal.flush () + echo_source terminal.output source ; + echo_lines terminal.output text prefix p q ; + terminal.flush () end (* -------------------------------------------------------------------------- *) @@ -304,7 +304,9 @@ (* -------------------------------------------------------------------------- *) let current_loc = ref (fun () -> raise Not_found) -let set_current_source cloc = current_loc := cloc + +let set_current_source fpos = current_loc := fpos + let get_current_source () = !current_loc () type emitter = { @@ -392,7 +394,7 @@ (* --- Listeners --- *) (* -------------------------------------------------------------------------- *) -let do_fire e f = try f e with _ -> () +let do_fire e f = f e let iter_kind ?kind f ems = match kind with @@ -402,15 +404,15 @@ let iter_plugin ?plugin ?kind f = match plugin with | None -> - Hashtbl.iter - (fun _ s -> - match s with - | Created c -> iter_kind ?kind f c.emitters - | NotCreatedYet ems -> iter_kind ?kind f ems) - all_channels ; - iter_kind ?kind f default_emitters + Hashtbl.iter + (fun _ s -> + match s with + | Created c -> iter_kind ?kind f c.emitters + | NotCreatedYet ems -> iter_kind ?kind f ems) + all_channels ; + iter_kind ?kind f default_emitters | Some p -> - iter_kind ?kind f (get_emitters p) + iter_kind ?kind f (get_emitters p) let add_listener ?plugin ?kind demon = iter_plugin ?plugin ?kind (fun em -> em.listeners <- em.listeners @ [demon]) @@ -451,31 +453,31 @@ Format.kfprintf (fun fmt -> try - (match append with None -> () | Some k -> k fmt) ; - Format.pp_print_newline fmt () ; - Format.pp_print_flush fmt () ; - let p = trim_begin buffer in - let q = trim_end buffer in - if p <= q then - begin - let event = lazy { - evt_kind = kind ; - evt_plugin = c.plugin ; - evt_message = String.sub buffer.text p (q+1-p) ; - evt_source = source ; - } in - if not once || check_not_yet (Lazy.force event) then - begin - let e = c.emitters.(nth_kind kind) in - if echo && e.echo then - do_echo c.terminal source prefix buffer.text p q ; - fire_listeners emitwith e.listeners event - end - end ; - close_buffer c + (match append with None -> () | Some k -> k fmt) ; + Format.pp_print_newline fmt () ; + Format.pp_print_flush fmt () ; + let p = trim_begin buffer in + let q = trim_end buffer in + if p <= q then + begin + let event = lazy { + evt_kind = kind ; + evt_plugin = c.plugin ; + evt_message = String.sub buffer.text p (q+1-p) ; + evt_source = source ; + } in + if not once || check_not_yet (Lazy.force event) then + begin + let e = c.emitters.(nth_kind kind) in + if echo && e.echo then + do_echo c.terminal source prefix buffer.text p q ; + fire_listeners emitwith e.listeners event + end + end ; + close_buffer c with e -> - close_buffer c ; - raise e + close_buffer c ; + raise e ) buffer.formatter text let logwith c ~kind ~prefix ~source ~append ~echo f text = @@ -483,25 +485,25 @@ Format.kfprintf (fun fmt -> try - (match append with None -> () | Some k -> k fmt) ; - Format.pp_print_flush fmt () ; - let p = trim_begin buffer in - let q = trim_end buffer in - let event = lazy { - evt_kind = kind ; - evt_plugin = c.plugin ; - evt_message = if p<=q then String.sub buffer.text p (q+1-p) else "" ; - evt_source = source ; - } in - let e = c.emitters.(nth_kind kind) in - if echo && e.echo && p <= q then - do_echo c.terminal source prefix buffer.text p q ; - List.iter (do_fire (Lazy.force event)) e.listeners ; - close_buffer c ; - f event + (match append with None -> () | Some k -> k fmt) ; + Format.pp_print_flush fmt () ; + let p = trim_begin buffer in + let q = trim_end buffer in + let event = lazy { + evt_kind = kind ; + evt_plugin = c.plugin ; + evt_message = if p<=q then String.sub buffer.text p (q+1-p) else "" ; + evt_source = source ; + } in + let e = c.emitters.(nth_kind kind) in + if echo && e.echo && p <= q then + do_echo c.terminal source prefix buffer.text p q ; + List.iter (do_fire (Lazy.force event)) e.listeners ; + close_buffer c ; + f event with e -> - close_buffer c ; - raise e + close_buffer c ; + raise e ) buffer.formatter text let finally_raise e _ = raise e @@ -513,13 +515,13 @@ (* -------------------------------------------------------------------------- *) type 'a pretty_printer = - ?current:bool -> ?source:source -> + ?current:bool -> ?source:Lexing.position -> ?emitwith:(event -> unit) -> ?echo:bool -> ?once:bool -> ?append:(Format.formatter -> unit) -> ('a,formatter,unit) format -> 'a type ('a,'b) pretty_aborter = - ?current:bool -> ?source:source -> ?echo:bool -> + ?current:bool -> ?source:Lexing.position -> ?echo:bool -> ?append:(Format.formatter -> unit) -> ('a,formatter,unit,'b) format4 -> 'a @@ -527,11 +529,11 @@ | Some p -> p | None -> Label begin - match kind with - | Result | Debug | Feedback -> Printf.sprintf "[%s] " text - | Warning -> Printf.sprintf "[%s] warning: " text - | Error -> Printf.sprintf "[%s] user error: " text - | Failure -> Printf.sprintf "[%s] failure: " text + match kind with + | Result | Debug | Feedback -> Printf.sprintf "[%s] " text + | Warning -> Printf.sprintf "[%s] warning: " text + | Error -> Printf.sprintf "[%s] user error: " text + | Failure -> Printf.sprintf "[%s] failure: " text end let get_source current = function @@ -565,13 +567,13 @@ match Hashtbl.find all_channels e.evt_plugin with | NotCreatedYet _ -> raise Not_found | Created c -> - let n = String.length e.evt_message in - let prefix = get_prefix e.evt_kind e.evt_plugin None in - do_echo c.terminal e.evt_source prefix e.evt_message 0 (n-1) + let n = String.length e.evt_message in + let prefix = get_prefix e.evt_kind e.evt_plugin None in + do_echo c.terminal e.evt_source prefix e.evt_message 0 (n-1) with Not_found -> let msg = Format.sprintf "[unknown channel %s]:%s" - e.evt_plugin e.evt_message + e.evt_plugin e.evt_message in failwith msg (* ------------------------------------------------------------------------- *) @@ -583,10 +585,12 @@ val verbose_atleast : int -> bool val debug_atleast : int -> bool + val set_debug_keys : string list -> unit + val get_debug_keyset : unit -> string list val result : ?level:int -> 'a pretty_printer val feedback: ?level:int -> 'a pretty_printer - val debug : ?level:int -> 'a pretty_printer + val debug : ?level:int -> ?dkey:string -> 'a pretty_printer val warning : 'a pretty_printer val error : 'a pretty_printer val abort : ('a,'b) pretty_aborter @@ -627,10 +631,13 @@ let prefix_error = Label (Printf.sprintf "[%s] user error: " label) let prefix_warning = Label (Printf.sprintf "[%s] warning: " label) let prefix_failure = Label (Printf.sprintf "[%s] failure: " label) + let prefix_dkey = function + | None -> prefix_all + | Some key -> Prefix (Printf.sprintf "[%s:%s] " label key) let prefix_for = function | Result | Feedback | Debug -> - if debug_atleast 1 then prefix_all else prefix_first + if debug_atleast 1 then prefix_all else prefix_first | Error -> prefix_error | Warning -> prefix_warning | Failure -> prefix_failure @@ -679,11 +686,11 @@ text = if to_be_log verbose debug then logtext channel - ~kind - ~prefix:(prefix_for kind) - ~source:(get_source current source) - ~once ?emitwith ~echo ?append - text + ~kind + ~prefix:(prefix_for kind) + ~source:(get_source current source) + ~once ?emitwith ~echo ?append + text else nullprintf text let result @@ -691,11 +698,11 @@ ?emitwith ?(echo=true) ?(once=false) ?append text = if verbose_atleast level then logtext channel - ~kind:Result - ~prefix:(if debug_atleast 1 then prefix_all else prefix_first) - ~source:(get_source current source) - ~once ?emitwith ~echo ?append - text + ~kind:Result + ~prefix:(if debug_atleast 1 then prefix_all else prefix_first) + ~source:(get_source current source) + ~once ?emitwith ~echo ?append + text else nullprintf text let feedback @@ -703,23 +710,36 @@ ?emitwith ?(echo=true) ?(once=false) ?append text = if verbose_atleast level then logtext channel - ~kind:Feedback - ~prefix:(if debug_atleast 1 then prefix_all else prefix_first) - ~source:(get_source current source) - ~once ?emitwith ~echo ?append - text + ~kind:Feedback + ~prefix:(if debug_atleast 1 then prefix_all else prefix_first) + ~source:(get_source current source) + ~once ?emitwith ~echo ?append + text else nullprintf text + module Skey = Set.Make(String) + + let debug_keys = ref [] + let debug_keyset = ref Skey.empty + let debug_collect = ref false + let set_debug_keys ks = debug_keys := ks ; debug_collect := List.mem "?" ks + let get_debug_keyset () = Skey.elements !debug_keyset + let has_debug_key = function None -> false | Some k -> + if !debug_collect && not (Skey.mem k !debug_keyset) + then debug_keyset := Skey.add k !debug_keyset ; + List.mem k !debug_keys + let debug - ?(level=1) ?(current=false) ?source + ?(level=1) ?dkey ?(current=false) ?source ?emitwith ?(echo=true) ?(once=false) ?append text = - if debug_atleast level then + + if debug_atleast level || has_debug_key dkey then logtext channel - ~kind:Feedback - ~prefix:prefix_all - ~source:(get_source current source) - ~once ?emitwith ~echo ?append - text + ~kind:Feedback + ~prefix:(prefix_dkey dkey) + ~source:(get_source current source) + ~once ?emitwith ~echo ?append + text else nullprintf text let warning @@ -777,9 +797,9 @@ Format.kfprintf (fun _ -> true) null text else logwith channel - ~kind:Failure ~prefix:prefix_failure - ~source:(get_source current source) - ~echo ?append finally_false text + ~kind:Failure ~prefix:prefix_failure + ~source:(get_source current source) + ~echo ?append finally_false text let with_result f ?(current=false) ?source @@ -844,7 +864,6 @@ end -(* -------------------------------------------------------------------------- *) (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/log.mli frama-c-20111001+nitrogen+dfsg/src/kernel/log.mli --- frama-c-20110201+carbon+dfsg/src/kernel/log.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/log.mli 2011-10-10 08:38:09.000000000 +0000 @@ -30,19 +30,16 @@ type kind = Result | Feedback | Debug | Warning | Error | Failure (** @since Beryllium-20090601-beta1 *) -type source = { src_file : string ; src_line : int } - (** @since Beryllium-20090601-beta1 *) - type event = { evt_kind : kind ; evt_plugin : string ; - evt_source : source option ; + evt_source : Lexing.position option ; evt_message : string ; } (** @since Beryllium-20090601-beta1 *) type 'a pretty_printer = - ?current:bool -> ?source:source -> + ?current:bool -> ?source:Lexing.position -> ?emitwith:(event -> unit) -> ?echo:bool -> ?once:bool -> ?append:(Format.formatter -> unit) -> ('a,formatter,unit) format -> 'a @@ -62,7 +59,7 @@ @since Beryllium-20090601-beta1 *) type ('a,'b) pretty_aborter = - ?current:bool -> ?source:source -> ?echo:bool -> + ?current:bool -> ?source:Lexing.position -> ?echo:bool -> ?append:(Format.formatter -> unit) -> ('a,formatter,unit,'b) format4 -> 'a (** @since Beryllium-20090601-beta1 @@ -104,31 +101,42 @@ val debug_atleast : int -> bool (** @since Beryllium-20090601-beta1 *) + val set_debug_keys : string list -> unit + (** Keys for which debugging messages are printed by [debug] + with optional parameter [dkey]. + @since Nitrogen-20111001 *) + val get_debug_keyset : unit -> string list + (** Returns the registered debugging keys. + Only activated if ["?"] is member of the current debugging keys. + @since Nitrogen-20111001 *) + val result : ?level:int -> 'a pretty_printer (** Results of analysis. Default level is 1. - @since Beryllium-20090601-beta1 *) + @since Beryllium-20090601-beta1 *) val feedback : ?level:int -> 'a pretty_printer (** Progress and feedback. Level is tested against the verbose. - @since Beryllium-20090601-beta1 *) + @since Beryllium-20090601-beta1 *) - val debug : ?level:int -> 'a pretty_printer + val debug : ?level:int -> ?dkey:string -> 'a pretty_printer (** Debugging information dedicated to Plugin developpers. - Default level is 1. - @since Beryllium-20090601-beta1 *) + Default level is 1. The debugging key is used in message headers. + See also [set_debug_keys] and [set_debug_keyset]. + @since Beryllium-20090601-beta1 + @modify Nitrogen-20111001 Optional parameter [dkey] *) val warning : 'a pretty_printer (** Hypothesis and restrictions. - @since Beryllium-20090601-beta1 *) + @since Beryllium-20090601-beta1 *) val error : 'a pretty_printer (** user error: syntax/typing error, bad expected input, etc. - @since Beryllium-20090601-beta1 *) + @since Beryllium-20090601-beta1 *) val abort : ('a,'b) pretty_aborter (** user error stopping the plugin. @raise AbortError with the channel name. - @since Beryllium-20090601-beta1 *) + @since Beryllium-20090601-beta1 *) val failure : 'a pretty_printer (** internal error of the plug-in. *) @@ -136,28 +144,28 @@ val fatal : ('a,'b) pretty_aborter (** internal error of the plug-in. @raise AbortFatal with the channel name. - @since Beryllium-20090601-beta1 *) + @since Beryllium-20090601-beta1 *) val verify : bool -> ('a,bool) pretty_aborter (** If the first argument is [true], return [true] and do nothing else, - otherwise, send the message on the {i fatal} channel and return - [false]. + otherwise, send the message on the {i fatal} channel and return + [false]. - The intended usage is: [assert (verify e "Bla...") ;]. - @since Beryllium-20090601-beta1 *) + The intended usage is: [assert (verify e "Bla...") ;]. + @since Beryllium-20090601-beta1 *) val not_yet_implemented : ('a,formatter,unit,'b) format4 -> 'a (** raises [FeatureRequest] but {i do not} send any message. - If the exception is not catched, Frama-C displays a feature-request - message to the user. - @since Beryllium-20090901 *) + If the exception is not catched, Frama-C displays a feature-request + message to the user. + @since Beryllium-20090901 *) val deprecated: string -> now:string -> ('a -> 'b) -> ('a -> 'b) (** [deprecated s ~now f] indicates that the use of [f] of name [s] is now - deprecated. It should be replaced by [now]. - @return the given function itself - @since Lithium-20081201 in Extlib - @since Beryllium-20090902 *) + deprecated. It should be replaced by [now]. + @return the given function itself + @since Lithium-20081201 in Extlib + @since Beryllium-20090902 *) val with_result : (event -> 'b) -> ('a,'b) pretty_aborter (** @since Beryllium-20090601-beta1 *) @@ -173,14 +181,14 @@ val log : ?kind:kind -> ?verbose:int -> ?debug:int -> 'a pretty_printer (** Generic log routine. The default kind is [Result]. Use cases (with - [n,m > 0]): - - [log ~verbose:n]: emit the message only when verbosity level is - at least [n]. - - [log ~debug:n]: emit the message only when debugging level is - at least [n]. - - [log ~verbose:n ~debug:m]: any debugging or verbosity level is - sufficient. - @since Beryllium-20090901 *) + [n,m > 0]): + - [log ~verbose:n]: emit the message only when verbosity level is + at least [n]. + - [log ~debug:n]: emit the message only when debugging level is + at least [n]. + - [log ~verbose:n ~debug:m]: any debugging or verbosity level is + sufficient. + @since Beryllium-20090901 *) val with_log : (event -> 'b) -> ?kind:kind -> ('a,'b) pretty_aborter (** @since Beryllium-20090901 *) @@ -269,10 +277,14 @@ (** the reserved label name used by the Frama-C kernel. @since Beryllium-20090601-beta1 *) -val set_current_source : (unit -> source) -> unit - (** @since Beryllium-20090601-beta1 *) +(**/**) +val set_current_source : (unit -> Lexing.position) -> unit + (* Forward reference to the function returning the current location, + used when [~current:true] is set on printers. Currently set + in {Cil}. Not for the casual user. *) +(**/**) -val get_current_source : unit -> source +val get_current_source : unit -> Lexing.position (* -------------------------------------------------------------------------- *) (** {2 Terminal interface} @@ -296,20 +308,28 @@ (** This function has the same parameters as Format.make_formatter. @since Beryllium-20090901 *) -val print_on_output : ('a,Format.formatter,unit) format -> 'a +val print_on_output : (Format.formatter -> unit) -> unit (** Direct printing on output. Message echo is delayed until the output is finished. Then, the output is flushed and all pending message are echoed. Notification of listeners is not delayed, however. Can not be recursively invoked. - @since Beryllium-20090901 *) + @since Beryllium-20090901 + @modify Nitrogen-20111001 signature changed *) -val print_delayed : ('a,Format.formatter,unit) format -> 'a +val print_delayed : (Format.formatter -> unit) -> unit (** Direct printing on output. Same as [print_on_output], except that message echo is not delayed until text material is actually written. This gives an chance for formatters to emit messages before actual pretty printing. Can not be recursively invoked. - @since Beryllium-20090901 *) + @since Beryllium-20090901 + @modify Nitrogen-20111001 signature changed *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/loop.ml frama-c-20111001+nitrogen+dfsg/src/kernel/loop.ml --- frama-c-20110201+carbon+dfsg/src/kernel/loop.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/loop.ml 2011-10-10 08:38:09.000000000 +0000 @@ -21,7 +21,6 @@ (**************************************************************************) open Cil_types -open Db_types open Cil_datatype open Cil @@ -38,8 +37,7 @@ let kind = `Internal end) -let pretty_natural_loops fmt kf loops = - Format.fprintf fmt "Natural_loops for %s:@." (Kernel_function.get_name kf); +let pretty_natural_loops fmt loops = List.iter (fun (start,members) -> Format.fprintf fmt "Loop start: %d ( " start.sid; @@ -51,25 +49,23 @@ let loops = Natural_Loops.memo (fun kf -> - match kf.fundec with - | Declaration _ -> - [] - | Definition (cilfundec,_) -> - let dbg = Kernel.debug_atleast 1 in - if dbg then - Format.printf "COMPUTE NATURAL LOOPS FOR %S@." - (Kernel_function.get_name kf); - let dominators = Dominators.computeIDom cilfundec in + match kf.fundec with + | Declaration _ -> + [] + | Definition (cilfundec,_) -> + Kernel.debug "Compute natural loops for '%a'" + Kernel_function.pretty kf; + let dominators = Dominators.computeIDom cilfundec in (*if dbg then Format.printf "DONE COMPUTE NATURAL LOOPS IDOM FOR %S@." (Kernel_function.get_name kf);*) - let naturals = Dominators.findNaturalLoops cilfundec dominators in - if dbg then begin - Format.printf "DONE COMPUTE NATURAL LOOPS FOR %S@." - (Kernel_function.get_name kf); - pretty_natural_loops Format.std_formatter kf naturals; - end; - naturals) + let naturals = Dominators.findNaturalLoops cilfundec dominators in + Kernel.debug + "Done computing natural loops for '%a':@.%a" + Kernel_function.pretty kf + pretty_natural_loops naturals; + naturals + ) kf in loops @@ -149,7 +145,7 @@ (try ignore (visitCilFunction - (visitor :> cilVisitor) (Kernel_function.get_definition kf)); + (visitor :> cilVisitor) (Kernel_function.get_definition kf)); with Kernel_function.No_Definition -> ()); tbl @@ -162,9 +158,9 @@ Kernel_function.Make_Table (Result.Make(Stmt.Set)) (struct - let name = "LoopStmts" - let size = 97 - let dependencies = [ Ast.self ] + let name = "LoopStmts" + let size = 97 + let dependencies = [ Ast.self ] let kind = `Internal end) in diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/loop.mli frama-c-20111001+nitrogen+dfsg/src/kernel/loop.mli --- frama-c-20110201+carbon+dfsg/src/kernel/loop.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/loop.mli 2011-10-10 08:38:09.000000000 +0000 @@ -24,7 +24,6 @@ @plugin development guide *) open Cil_types -open Db_types exception No_such_while val get_loop_stmts : kernel_function -> stmt -> Cil_datatype.Stmt.Set.t diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/messages.ml frama-c-20111001+nitrogen+dfsg/src/kernel/messages.ml --- frama-c-20110201+carbon+dfsg/src/kernel/messages.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/messages.ml 2011-10-10 08:38:09.000000000 +0000 @@ -23,55 +23,63 @@ open Cil_types open Format +module DatatypeMessages = + Datatype.Make + (struct + include Datatype.Serializable_undefined + open Log + type t = event + let name = "message" + let reprs = + [ { evt_kind = Failure; + evt_plugin = ""; + evt_source = None; + evt_message = "" } ] + let mem_project = Datatype.never_any_project + end) + module Messages = - State_builder.Hashtbl - (Cil_datatype.Int_hashtbl) - (Datatype.Make - (struct - include Datatype.Serializable_undefined - open Log - type t = event - let name = "message" - let reprs = - [ { evt_kind = Failure; - evt_plugin = ""; - evt_source = None; - evt_message = "" } ] - let mem_project = Datatype.never_any_project - end)) + State_builder.List_ref + (DatatypeMessages) (struct let name = "message_table" - let size = 17 - let dependencies = [] + let dependencies = [ Ast.self ] + let kind = `Internal + end) +module NbMessages = + State_builder.Zero_ref + (struct + let name = "nb_messages" + let dependencies = [Messages.self] let kind = `Internal end) let self = Messages.self -let iter f = Messages.iter f +let add_message m = + NbMessages.set (NbMessages.get () + 1); + Messages.set (m :: Messages.get ()) + +let iter f = List.iter f (List.rev (Messages.get ())) +let dump_messages () = iter Log.echo let enable_collect = let not_yet = ref true in fun () -> if !not_yet then begin Kernel.debug "enable collection of error messages."; - let emit e = - let c = Messages.length () in - Messages.add c e ; - in - Log.add_listener ~kind:[ Log.Error; Log.Warning ] emit; + Log.add_listener ~kind:[ Log.Error; Log.Warning ] add_message; not_yet := false end let () = - let run () = if Parameters.Collect_messages.get () then enable_collect () in + let run () = if Kernel.Collect_messages.get () then enable_collect () in (* Set by the user on the command-line *) Cmdline.run_after_early_stage run; (* Set by a plugin *) Cmdline.run_after_configuring_stage run; ;; -let dump_messages () = Messages.iter (fun _ e -> Log.echo e) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/messages.mli frama-c-20111001+nitrogen+dfsg/src/kernel/messages.mli --- frama-c-20110201+carbon+dfsg/src/kernel/messages.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/messages.mli 2011-10-10 08:38:09.000000000 +0000 @@ -21,13 +21,13 @@ (**************************************************************************) (** Stored messages. Storing of messages can be changed using - {Parameters.Collect_messages.set} (at initialization time only); + {Kernel.Collect_messages.set} (at initialization time only); currently, only warning and error messages are stored if thus requested. *) -val iter: (int -> Log.event -> unit) -> unit - (** Iter over all stored messages. The messages are not passed in emission - order, but the [int] argument can be used to sort them if needed *) +val iter: (Log.event -> unit) -> unit + (** Iter over all stored messages. The messages are passed in emission order. + @modify Nitrogen-20111001 Messages are now passed in emission order. *) val dump_messages: unit -> unit (** Dump stored messages to standard channels *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/parameter.ml frama-c-20111001+nitrogen+dfsg/src/kernel/parameter.ml --- frama-c-20110201+carbon+dfsg/src/kernel/parameter.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/parameter.ml 2011-10-10 08:38:09.000000000 +0000 @@ -0,0 +1,101 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +type kind = Correctness | Tuning | Other + +type ('a, 'b) gen_accessor = + { get: unit -> 'a; + set: 'a -> unit; + add_set_hook: ('b -> 'b -> unit) -> unit; + add_update_hook: ('b -> 'b -> unit) -> unit } + +type 'a accessor = ('a, 'a) gen_accessor + +type typed_accessor = + | Bool of bool accessor * string option (** the negative option, if any *) + | Int of int accessor * (unit -> int * int) (** getting range *) + | String of string accessor * (unit -> string list) (** possible values *) + | String_set of (string, Datatype.String.Set.t) gen_accessor + | String_list of (string, string list) gen_accessor + +type parameter = + { name: string; + help: string; + accessor: typed_accessor; + is_set: unit -> bool } + +include + Datatype.Make_with_collections + (struct + type t = parameter + let name = "Parameter.t" + let rehash = Datatype.identity + let structural_descr = Structural_descr.Unknown + let reprs = + [ { name = "bool_opt"; + help = "dummy bool option"; + accessor = + Bool + ({get=(fun () -> false); + set = (fun _ -> ()); + add_set_hook = (fun _ -> ()); + add_update_hook = (fun _ -> ()) }, + None); + is_set = fun () -> false } + ] + let equal = (==) + let compare x y = if x == y then 0 else String.compare x.name y.name + let hash x = Datatype.String.hash x.name + let copy x = x (* The representation of the parameter is immutable *) + let pretty fmt x = Format.pp_print_string fmt x.name + let internal_pretty_code = Datatype.undefined + let varname _ = assert false + (* unused if internal_pretty_code undefined *) + let mem_project = Datatype.never_any_project + end) + +let parameters = Datatype.String.Hashtbl.create 97 + +let create ~name ~help ~accessor ~is_set = + let p = { name = name; help = help; accessor = accessor; is_set = is_set } in + (* parameter name unicity already checks in [Plugin]. *) + assert (not (Datatype.String.Hashtbl.mem parameters name)); + Datatype.String.Hashtbl.add parameters name p; + p + +let get = Datatype.String.Hashtbl.find parameters + +let pretty_value fmt p = match p.accessor with + | Bool(a, _) -> Format.fprintf fmt "%b" (a.get ()) + | Int(a, _) -> Format.fprintf fmt "%d" (a.get ()) + (* factorisation requires GADT (will be in OCaml 3.13?) *) + | String(a, _) -> Format.fprintf fmt "%s" (a.get ()) + | String_set a -> Format.fprintf fmt "%s" (a.get ()) + | String_list a -> Format.fprintf fmt "%s" (a.get ()) + +let get_value p = Pretty_utils.sfprintf "%a" pretty_value p + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/parameter.mli frama-c-20111001+nitrogen+dfsg/src/kernel/parameter.mli --- frama-c-20110201+carbon+dfsg/src/kernel/parameter.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/parameter.mli 2011-10-10 08:38:09.000000000 +0000 @@ -0,0 +1,87 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Parameter settable through a command line option. + @since Nitrogen-20111001 *) + +type ('a, 'b) gen_accessor = + { get: unit -> 'a; + set: 'a -> unit; + add_set_hook: ('b -> 'b -> unit) -> unit; + add_update_hook: ('b -> 'b -> unit) -> unit } + +type 'a accessor = ('a, 'a) gen_accessor + +type typed_accessor = + | Bool of bool accessor * string option (** the negative option, if any *) + | Int of int accessor * (unit -> int * int) (** getting range *) + | String of string accessor * (unit -> string list) (** possible values *) + | String_set of (string, Datatype.String.Set.t) gen_accessor + | String_list of (string, string list) gen_accessor + +type parameter = private + { name: string; (** Name of the option corresponding to the parameter. + It is exactly the state name of the option (see + {!State.get_name}). *) + help: string; (** Help message *) + accessor: typed_accessor; (** How to get and set the value of the + parameter *) + is_set: unit -> bool (** Is this option really set? *) } + +include Datatype.S_with_collections with type t = parameter + +val get: string -> t +(** Get the parameter from the option name. *) + +val get_value: t -> string +(** Get the current value of the parameter, as a string. *) + +(* TODO: to be removed. + Only present for compatibility reasons. + @deprecated Nitrogen-20111001 *) +type kind = + | Correctness (** setting the value of the parameter may change a property + status (from valid to invalid, or conversely), or may + change the semantics of a generated annotation. + Example: -machdep *) + | Tuning (** setting the value of the parameters may change the precision of + a property status (from don't know to valid/invalid, or + conversely), or may change a generated annotation while + preserving its semantics. + Example: -unrolling-level *) + | Other + +(**/**) +(** Not for casual users. Use API of {!Plugin} instead. *) +val create: + name:string -> + help:string -> + accessor:typed_accessor -> + is_set: (unit -> bool) -> + t +(**/**) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/parameters.ml frama-c-20111001+nitrogen+dfsg/src/kernel/parameters.ml --- frama-c-20110201+carbon+dfsg/src/kernel/parameters.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/parameters.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,925 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Bunch of values which may be initialized through command line. *) - -open Extlib - -(* ************************************************************************* *) -(** {2 General purpose options} *) -(* ************************************************************************* *) - -let check_range name ~min ~max = - Kernel.deprecated "check_range" ~now:"Plugin.Int.set_range" - (fun v -> - if v < min || v > max then - Kernel.abort - "invalid argument for %s option, not in range %d-%d" - name min max) - -(* ************************************************************************* *) -(** {2 Installation Information} *) -(* ************************************************************************* *) - -let () = Plugin.set_group Kernel.help -let () = Plugin.set_cmdline_stage Cmdline.Exiting -let () = Plugin.do_not_journalize () -module GeneralHelp = - Kernel.False - (struct - let option_name = "-help" - let help = "display a general help" - let module_name = "GeneralHelp" - let kind = `Irrelevant - end) - -let run_help () = if GeneralHelp.get () then Cmdline.help () else Cmdline.nop -let () = Cmdline.run_after_exiting_stage run_help -let () = GeneralHelp.add_aliases [ "--help"; "-h" ] - -let () = Plugin.set_group Kernel.help -let () = Plugin.set_cmdline_stage Cmdline.Early -module PrintVersion = - Kernel.False - (struct - let option_name = "-version" - let module_name = "PrintVersion" - let help = "print version information" - let kind = `Irrelevant - end) -let () = PrintVersion.add_aliases [ "-v"; "--version" ] - -let () = Plugin.set_group Kernel.help -let () = Plugin.set_cmdline_stage Cmdline.Early -module PrintShare = - Kernel.False(struct - let option_name = "-print-share-path" - let module_name = "PrintShare" - let help = "print the Frama-C share path" - let kind = `Irrelevant - end) -let () = PrintShare.add_aliases [ "-print-path" ] - -let () = Plugin.set_group Kernel.help -let () = Plugin.set_cmdline_stage Cmdline.Early -module PrintLib = - Kernel.False(struct - let option_name = "-print-lib-path" - let module_name = "PrintLib" - let help = "print the path of the Frama-C kernel library" - let kind = `Irrelevant - end) -let () = PrintLib.add_aliases [ "-print-libpath" ] - -let () = Plugin.set_group Kernel.help -let () = Plugin.set_cmdline_stage Cmdline.Early -module PrintPluginPath = - Kernel.False - (struct - let option_name = "-print-plugin-path" - let module_name = "PrintPluginPath" - let help = - "print the path where the Frama-C dynamic plug-ins are searched into" - let kind = `Irrelevant - end) - -let () = Plugin.set_group Kernel.help -let () = Plugin.set_negative_option_name "" -module DumpDependencies = - Kernel.EmptyString - (struct - let module_name = "DumpDependencies" - let option_name = "-dump-dependencies" - let help = "undocumented" - let arg_name = "" - let kind = `Irrelevant - end) -let () = - at_exit - (fun () -> - if not (DumpDependencies.is_default ()) then - State_dependency_graph.Dynamic.dump (DumpDependencies.get ())) - -(* ************************************************************************* *) -(** {2 Output Messages} *) -(* ************************************************************************* *) - -let () = Plugin.set_group Kernel.messages -let () = Plugin.do_not_projectify () -let () = Plugin.do_not_journalize () -let () = Plugin.set_cmdline_stage Cmdline.Early -let () = Plugin.is_visible () -module GeneralVerbose = - Kernel.Int - (struct - let default = 1 - let option_name = "-verbose" - let arg_name = "n" - let help = "general level of verbosity" - let module_name = "GeneralVerbose" - let kind = `Irrelevant - end) -let () = - (* line order below matters *) - GeneralVerbose.set_range ~min:0 ~max:max_int; - GeneralVerbose.add_set_hook (fun _ n -> Cmdline.verbose_level_ref := n); - GeneralVerbose.set !Cmdline.verbose_level_ref - -let () = Plugin.set_group Kernel.messages -let () = Plugin.do_not_projectify () -let () = Plugin.do_not_journalize () -let () = Plugin.set_cmdline_stage Cmdline.Early -let () = Plugin.is_visible () -module GeneralDebug = - Kernel.Zero - (struct - let option_name = "-debug" - let arg_name = "n" - let help = "general level of debug" - let module_name = "GeneralDebug" - let kind = `Irrelevant - end) -let () = - (* line order below matters *) - GeneralDebug.set_range ~min:0 ~max:max_int; - GeneralDebug.add_set_hook - (fun old n -> - if n = 0 then decr Plugin.positive_debug_ref - else if old = 0 then incr Plugin.positive_debug_ref; - Cmdline.debug_level_ref := n); - GeneralDebug.set !Cmdline.debug_level_ref - -let () = Plugin.set_group Kernel.messages -let () = Plugin.set_negative_option_name "" -let () = Plugin.set_cmdline_stage Cmdline.Early -let () = Plugin.is_visible () -let () = Plugin.do_not_projectify () -let () = Plugin.do_not_journalize () -module Quiet = - Kernel.Bool - (struct - let default = Cmdline.quiet - let option_name = "-quiet" - let module_name = "Quiet" - let help = "sets -verbose and -debug to 0" - let kind = `Irrelevant - end) -let () = - Quiet.add_set_hook - (fun _ b -> assert b; GeneralVerbose.set 0; GeneralDebug.set 0) - -let () = Plugin.set_group Kernel.messages -let () = Plugin.do_not_journalize () -let () = Plugin.do_not_projectify () -module UseUnicode = - Kernel.True - (struct - let option_name = "-unicode" - let module_name = "UseUnicode" - let help = "use utf8 in messages" - let kind = `Irrelevant - end) -let () = UseUnicode.add_set_hook (fun _ b -> Cil.print_utf8 := b) - -let () = Plugin.set_group Kernel.messages -module Time = - Kernel.EmptyString - (struct - let module_name = "Time" - let option_name = "-time" - let arg_name = "filename" - let help = "append user time and date to at exit" - let kind = `Irrelevant - end) - -let () = Plugin.set_group Kernel.messages -let () = Plugin.set_negative_option_name "-do-not-collect-messages" -let () = Plugin.do_not_projectify () -let () = Plugin.set_cmdline_stage Cmdline.Early -module Collect_messages = - Kernel.Bool - (struct - let module_name = "Collect_messages" - let option_name = "-collect-messages" - let help = "collect warning and error messages for displaying them in \ -the GUI (set by default iff the GUI is launched)" - let kind = `Irrelevant - let default = !Config.is_gui (* ok: Config.is_gui already initialised *) - end) - -(* ************************************************************************* *) -(** {2 Input / Output Source Code} *) -(* ************************************************************************* *) - -let inout_source = Kernel.add_group "Input/Output Source Code" - -let () = Plugin.set_group inout_source -module PrintCode = - Kernel.False - (struct - let module_name = "PrintCode" - let option_name = "-print" - let help = "pretty print original code with its comments" - let kind = `Irrelevant - end) - -let () = Plugin.set_group inout_source -module PrintComments = - Kernel.False(struct - let module_name = "PrintComments" - let option_name = "-keep-comments" - let help = "try to keep comments in C code" - let kind = `Irrelevant - end) -let () = - (* simple mirror *) - PrintComments.add_set_hook - (fun _old b -> Clexer.keepComments := b) ; - (* projectified mirror *) - Project.register_after_set_current_hook - ~user_only:false - (fun _ -> Clexer.keepComments := PrintComments.get ()) - -module CodeOutput = struct - - let () = Plugin.set_group inout_source - include Kernel.EmptyString - (struct - let module_name = "CodeOutput" - let option_name = "-ocode" - let arg_name = "filename" - let help = - "when printing code, redirects the output to file " - let kind = `Irrelevant - end) - - let streams = Hashtbl.create 7 - - let output msg = - let file = get () in - if file = "" - then Log.print_delayed msg - else - try - let fmt = - try fst (Hashtbl.find streams file) - with Not_found -> - let out = open_out file in - let fmt = Format.formatter_of_out_channel out in - Hashtbl.add streams file (fmt,out) ; fmt - in - Format.fprintf fmt msg - with Sys_error s -> - Kernel.warning - "Fail to open file \"%s\" for code output@\nSystem error: %s.@\n\ - Code is output on stdout instead." file s ; - Log.print_delayed msg - - let close_all () = - Hashtbl.iter - (fun file (fmt,cout) -> - try - Format.pp_print_flush fmt () ; - close_out cout ; - with Sys_error s -> - Kernel.failure - "Fail to close output file \"%s\"@\nSystem error: %s." - file s) - streams - - let () = at_exit close_all - -end - -let () = Plugin.set_group inout_source -module FloatNormal = - Kernel.False - (struct - let option_name = "-float-normal" - let module_name = "FloatNormal" - let help = "display floats with internal routine" - let kind = `Irrelevant - end) - -let () = Plugin.set_group inout_source -module FloatRelative = - Kernel.False - (struct - let option_name = "-float-relative" - let module_name = "FloatRelative" - let help = "display float intervals as [lower_bound ++ width]" - let kind = `Irrelevant - end) - -let () = Plugin.set_group inout_source -module FloatHex = - Kernel.False - (struct - let option_name = "-float-hex" - let module_name = "FloatHex" - let help = "display floats as hexadecimal" - let kind = `Irrelevant - end) - -(* ************************************************************************* *) -(** {2 Save/Load} *) -(* ************************************************************************* *) - -let saveload = Kernel.add_group "Saving or Loading Data" - -let () = Plugin.set_group saveload -module SaveState = - Kernel.EmptyString - (struct - let module_name = "SaveState" - let option_name = "-save" - let arg_name = "filename" - let help = "at exit, save the session into file " - let kind = `Irrelevant - end) - -let () = Plugin.set_group saveload -let () = Plugin.set_cmdline_stage Cmdline.Loading -module LoadState = - Kernel.EmptyString - (struct - let module_name = "LoadState" - let option_name = "-load" - let arg_name = "filename" - let help = "load a previously-saved session from file " - let kind = `Correctness - end) - -let () = Plugin.set_group saveload -let () = Plugin.set_cmdline_stage Cmdline.Extending -module AddPath = - Kernel.StringSet - (struct - let option_name = "-add-path" - let module_name = "AddPath" - let arg_name = "p1, ..., pn" - let help = "add paths which dynamic plugins are searched in" - let kind = `Irrelevant - end) -let () = AddPath.add_set_hook (fun _ _ -> AddPath.iter Dynamic.add_path) - -let () = Plugin.set_group saveload -let () = Plugin.set_cmdline_stage Cmdline.Extending -module LoadModule = - Kernel.StringSet - (struct - let option_name = "-load-module" - let module_name = "LoadModule" - let arg_name = "m1, ..., mn" - let help = "load the given modules dynamically" - let kind = `Irrelevant - end) -let () = - LoadModule.add_set_hook (fun _ _ -> LoadModule.iter Dynamic.load_module) - -let () = Plugin.set_group saveload -let () = Plugin.set_cmdline_stage Cmdline.Extending -module Dynlink = - Kernel.True - (struct - let option_name = "-dynlink" - let module_name = "Dynlink" - let help = "load all the found dynamic plug-ins (default); \ -otherwise, ignore all plug-ins in default directories" - let kind = `Irrelevant - end) -let () = Dynlink.add_set_hook (fun _ -> Dynamic.set_default) - -let () = Plugin.set_group saveload -let () = Plugin.set_cmdline_stage Cmdline.Extending -module LoadScript = - Kernel.StringSet(struct - let option_name = "-load-script" - let module_name = "LoadScript" - let arg_name = "m1, ..., mn" - let help = "load the given OCaml scripts dynamically" - let kind = `Irrelevant - end) -let () = - LoadScript.add_set_hook (fun _ _ -> LoadScript.iter Dynamic.load_script) - -module Journal = struct - let () = Plugin.set_negative_option_name "-journal-disable" - let () = Plugin.set_cmdline_stage Cmdline.Early - let () = Plugin.set_group saveload - module Enable = struct - include Kernel.Bool - (struct - let module_name = "Journal.Enable" - let default = Cmdline.journal_enable - let option_name = "-journal-enable" - let help = "dump a journal while Frama-C exit" - let kind = `Irrelevant - end) - let is_set () = Cmdline.journal_isset - end - let () = Plugin.set_group saveload - module Name = - Kernel.String - (struct - let module_name = "Journal.Name" - let option_name = "-journal-name" - let default = Journal.get_name () - let arg_name = "s" - let help = - "set the filename of the journal (do not write any extension)" - let kind = `Irrelevant - end) -end - -(* ************************************************************************* *) -(** {2 Customizing Normalization} *) -(* ************************************************************************* *) - -let normalisation = Kernel.add_group "Customizing Normalization" - -let () = Plugin.set_group normalisation -module UnrollingLevel = - Kernel.Zero - (struct - let module_name = "UnrollingLevel" - let option_name = "-ulevel" - let arg_name = "l" - let help = "unroll loops n times (defaults to 0) before analyzes" - let kind = `Tuning - end) - -let () = Plugin.set_group normalisation -module Machdep = - Kernel.EmptyString - (struct - let module_name = "Machdep" - let option_name = "-machdep" - let arg_name = "machine" - let help = "use as the current machine dependent configuration. Use -machdep help to see the list of available machines" - let kind = `Correctness - end) -let () = - State_dependency_graph.Static.add_dependencies - ~from:Machdep.self - [ Cil.selfMachine ] - -let () = Plugin.set_group normalisation -module ReadAnnot = - Kernel.True(struct - let module_name = "ReadAnnot" - let option_name = "-annot" - let help = "read annotation" - let kind = `Correctness - end) -let () = - Clexer.annot_char := '@'; - ReadAnnot.add_set_hook - (fun _ x -> - (* prevent the C lexer interpretation of comments *) - if x then Clexer.annot_char := '@' else Clexer.annot_char := '\000') - -let () = Plugin.set_group normalisation -module PreprocessAnnot = - Kernel.False(struct - let module_name = "PreprocessAnnot" - let option_name = "-pp-annot" - let help = "pre-process annotations (if they are read)" - let kind = `Correctness - end) - -let () = Plugin.set_group normalisation -module CppCommand = - Kernel.EmptyString - (struct - let module_name = "CppCommand" - let option_name = "-cpp-command" - let arg_name = "cmd" - let help = " is used to build the preprocessing command.\n\ -Default to $CPP environment variable or else \"gcc -C -E -I.\".\n\ -If unset, the command is built as follow:\n\ - CPP -o \n\ -%1 and %2 can be used into CPP string to mark the position of \ -and respectively" - let kind = `Correctness - end) - -let () = Plugin.set_group normalisation -module CppExtraArgs = - Kernel.StringSet - (struct - let module_name = "CppExtraArgs" - let option_name = "-cpp-extra-args" - let arg_name = "args" - let help = "additional arguments passed to the preprocessor while \ -preprocessing the C code but not while preprocessing annotations" - let kind = `Correctness - end) - -let () = Plugin.set_group normalisation -let () = Plugin.set_negative_option_name "" -module TypeCheck = - Kernel.False(struct - let module_name = "TypeCheck" - let option_name = "-typecheck" - let help = "only typechecks the source files" - let kind = `Tuning - end) - -let () = Plugin.set_group normalisation -module ContinueOnAnnotError = - Kernel.False(struct - let module_name = "ContinueOnAnnotError" - let option_name = "-continue-annot-error" - let help = "When an annotation fails to type-check, just emits \ - a warning and discards the annotation instead of \ - generating an error (errors in C are still fatal)" - let kind = `Tuning - end) -let () = - ContinueOnAnnotError.add_set_hook - (fun _ b -> - if b then - Cabshelper.continue_annot_error_set () - else Cabshelper.continue_annot_error_unset()) - -let () = Plugin.set_group normalisation -module SimplifyCfg = - Kernel.False - (struct - let module_name = "SimplifyCfg" - let option_name = "-simplify-cfg" - let help = - "remove break, continue and switch statement before analyzes" - let kind = `Tuning - end) - -let () = Plugin.set_group normalisation -module KeepSwitch = - Kernel.False(struct - let option_name = "-keep-switch" - let module_name = "KeepSwitch" - let help = "keep switch statements despite -simplify-cfg" - let kind = `Tuning - end) - -let () = Plugin.set_group normalisation -module Constfold = - Kernel.False - (struct - let option_name = "-constfold" - let module_name = "Constfold" - let help = "fold all constant expressions in the code before analysis" - let kind = `Tuning - end) - -module Files = struct - - let () = Plugin.is_invisible () - include Kernel.StringList - (struct - let option_name = "" - let module_name = "Files" - let arg_name = "" - let help = "" - let kind = `Correctness - end) - let () = Cmdline.use_cmdline_files set - - let () = Plugin.set_group normalisation - module Check = - Kernel.False(struct - let option_name = "-check" - let module_name = "Files.Check" - let help = "performs consistency checks over cil files" - let kind = `Irrelevant - end) - - let () = Plugin.set_group normalisation - module Copy = - Kernel.False(struct - let option_name = "-copy" - let module_name = "Files.Copy" - let help = - "always perform a copy of the original AST before analysis begin" - let kind = `Irrelevant - end) - - let () = Plugin.set_group normalisation - module Orig_name = - Kernel.False(struct - let option_name = "-orig-name" - let module_name = "Files.Orig_name" - let help = "prints a message each time a variable is renamed" - let kind = `Irrelevant - end) - -end - -let () = Plugin.set_group normalisation -module AllowDuplication = - Kernel.True(struct - let option_name = "-allow-duplication" - let module_name = "AllowDuplication" - let help = - "allow duplication of small blocks during normalization" - let kind = `Tuning - end) -let () = - AllowDuplication.add_set_hook (fun _ flag -> Cabs2cil.allowDuplication:=flag); - (* Ensures that there's no mismatch between default value in - Cabs2cil and here. - TODO: Store the state only here, and make Cabs2cil depend on Parameters - *) - AllowDuplication.set (AllowDuplication.get()) - -let () = Plugin.set_group normalisation -module DoCollapseCallCast = - Kernel.True(struct - let option_name = "-collapse-call-cast" - let module_name = "DoCollapseCallCast" - let help = - "Allow implicit cast between returned value of a function \ - and the lval it is assigned to." - let kind = `Tuning - end) -let () = - DoCollapseCallCast.add_set_hook - (fun _ flag -> Cabs2cil.doCollapseCallCast:=flag); - (* see AllowDuplication *) - DoCollapseCallCast.set (DoCollapseCallCast.get()) - -let () = Plugin.set_group normalisation -module ForceRLArgEval = - Kernel.False(struct - let option_name = "-force-rl-arg-eval" - let module_name = "ForceRLArgEval" - let help = "Force right to left evaluation order for \ - arguments of function calls" - let kind = `Correctness - end) -let () = - ForceRLArgEval.add_set_hook - (fun _ flag -> Cabs2cil.forceRLArgEval:= flag); - ForceRLArgEval.set (ForceRLArgEval.get()) - -(* ************************************************************************* *) -(** {2 Analysis Options} *) -(* ************************************************************************* *) - -let analysis_options = Kernel.add_group "Analysis Options" - -let () = Plugin.set_group analysis_options -module MainFunction = - Kernel.String - (struct - let module_name = "MainFunction" - let default = "main" - let option_name = "-main" - let arg_name = "f" - let help = "set to name the entry point for analysis. Use -lib-entry if this is not for a complete application. Defaults to main" - let kind = `Correctness - end) - -let () = Plugin.set_group analysis_options -module LibEntry = - Kernel.False - (struct - let module_name = "LibEntry" - let option_name = "-lib-entry" - let help ="run analysis for an incomplete application e.g. an API call. See the -main option to set the entry point name" - let kind = `Correctness - end) - -let () = Plugin.set_group analysis_options -module UnspecifiedAccess = - Kernel.False(struct - let module_name = "UnspecifiedAccess" - let option_name = "-unspecified-access" - let help = "assume that all read/write accesses occuring in unspecified order are not separated" - let kind = `Correctness - end) - -let () = Plugin.set_group analysis_options -module Overflow = - Kernel.True(struct - let module_name = "Overflow" - let option_name = "-overflow" - let help = "assume that arithmetic operations overflow" - let kind = `Correctness - end) - -let () = Plugin.set_negative_option_name "-unsafe-arrays" -let () = Plugin.set_group analysis_options -module SafeArrays = - Kernel.True - (struct - let module_name = "SafeArrays" - let option_name = "-safe-arrays" - let help = "for arrays that are fields inside structs, assume that accesses are in bounds" - let kind = `Correctness - end) - -let () = Plugin.set_group analysis_options -module AbsoluteValidRange = struct - module Info = struct - let option_name = "-absolute-valid-range" - let arg_name = "min-max" - let help = "min and max must be integers in decimal, hexadecimal (0x, 0X), octal (0o) or binary (0b) notation and fit in 64 bits. Assume that that all absolute addresses outside of the [min-max] range are invalid. In the absence of this option, all absolute addresses are assumed to be invalid" - let default = "" - let module_name = "AbsoluteValidRange" - let kind = `Correctness - end - include Kernel.String(Info) - let is_set _x = assert false -end - -let () = Plugin.set_group analysis_options -module FloatFlushToZero = - Kernel.False - (struct - let option_name = "-float-flush-to-zero" - let help = "Floating-point operations flush to zero" - let module_name = "FloatFlushToZero" - let kind = `Correctness - end) - -(* ************************************************************************* *) -(** {2 Others options} *) -(* ************************************************************************* *) - -let misc = Kernel.add_group "Miscellaneous Options" - -let () = - Cmdline.add_option_without_action - "-then" - ~plugin:"" - ~group:(misc :> Cmdline.Group.t) - ~help:(Some "parse options before `-then' and execute Frama-C \ -accordingly, then parse options after `-then' and re-execute Frama-C") - ~ext_help:"" - () - -let () = - Cmdline.add_option_without_action - "-then-on" - ~plugin:"" - ~argname:"p" - ~group:(misc :> Cmdline.Group.t) - ~help:(Some "like `-then', but the second group of actions is executed \ -on project

    ") - ~ext_help:"" - () - -let () = Plugin.set_group misc -let () = Plugin.set_negative_option_name "" -let () = Plugin.set_cmdline_stage Cmdline.Early -module NoType = - Kernel.Bool - (struct - let module_name = "NoType" - let default = not Cmdline.use_type - let option_name = "-no-type" - let help = "undocumented but disable some features" - let kind = `Irrelevant - end) - -let () = Plugin.set_group misc -let () = Plugin.set_negative_option_name "" -let () = Plugin.set_cmdline_stage Cmdline.Early -module NoObj = - Kernel.Bool - (struct - let module_name = "NoObj" - let default = not Cmdline.use_obj - let option_name = "-no-obj" - let help = "-no-type + disable some additional features" - let kind = `Irrelevant - end) - -(* ************************************************************************* *) -(** {2 Interface for dynamic plugins} *) -(* ************************************************************************* *) - -module Dynamic = struct - - module type Common = sig - type t - val get: string -> t - val set: string -> t -> unit - val clear: string -> unit -> unit - val is_set: string -> bool - val is_default: string -> bool - end - - let apply modname name s ty1 ty2 = - Dynamic.get - ~plugin:"" - (Plugin.dynamic_name modname s name) - (Datatype.func ty1 ty2) - - module Common(X: sig type t val modname:string val ty: t Type.t end ) = - struct - type t = X.t - let ty = X.ty - let get name = apply X.modname name "get" Datatype.unit ty () - let set name = apply X.modname name "set" ty Datatype.unit - let clear name = apply X.modname name "clear" Datatype.unit Datatype.unit - let is_set name = - apply X.modname name "is_set" Datatype.unit Datatype.bool () - let is_default name = - apply X.modname name "is_default" Datatype.unit Datatype.bool () - end - - module Bool = struct - include Common - (struct type t = bool let ty = Datatype.bool let modname = "Bool"end ) - let on name = apply "Bool" name "on" Datatype.unit Datatype.unit - let off name = apply "Bool" name "off" Datatype.unit Datatype.unit - end - - module Int = struct - include Common - (struct type t = int let ty = Datatype.int let modname = "Int" end ) - let incr name = apply "Int" name "incr" Datatype.unit Datatype.unit - end - - module String = - Common - (struct - type t = string - let ty = Datatype.string - let modname = "String" - end) - - module StringSet = struct - include Common - (struct include Datatype.String.Set let modname = "StringSet" end) - let add name = apply "StringSet" name "add" Datatype.string Datatype.unit - let remove name = - apply "StringSet" name "remove" Datatype.string Datatype.unit - let is_empty name = - apply "StringSet" name "is_empty" Datatype.unit Datatype.bool () - let iter name = - apply "StringSet" name "iter" - (Datatype.func Datatype.string Datatype.unit) Datatype.unit - end -(* - module IndexedVal(X: sig val ty_name: string end) = struct - include Common(struct type t = string let ty = string end) - type value = Type.ty - let ty = Type.get_abstract X.ty_name - let add_choice name = - StringTbl.find tbl (name ^ ".add_choice") (func string (func ty unit)) - let get_val name = - StringTbl.find tbl (name ^ ".get_val") (func unit ty) () - end - *) - -end - -(* ************************************************************************* *) -(** {2 Options which define context of analyses } *) -(* ************************************************************************* *) - -let get_selection_context () = - let has_dependencies s = - State_dependency_graph.Dynamic.G.out_degree - State_dependency_graph.Dynamic.graph - s - > 0 - in - (* automatically select all options which have some dependencies: - they have an impact of some analysis. *) - let states = - State_selection.Dynamic.fold - (fun s acc -> if has_dependencies s then s :: acc else acc) - (Plugin.get_selection ()) - [ Files.Check.self; Files.Copy.self ] - in - State_selection.of_list states - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/parameters.mli frama-c-20111001+nitrogen+dfsg/src/kernel/parameters.mli --- frama-c-20110201+carbon+dfsg/src/kernel/parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/parameters.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,310 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Kernel parameters and generic access to plug-in parameters. - @since Beryllium-20090601-beta1 *) - -open Plugin - -(* ************************************************************************* *) -(** {2 Generic access to plug-in parameters} *) -(* ************************************************************************* *) - -(** Module to use for accessing parameters of plug-ins. - Assume that the plug-in is already loaded. *) -module Dynamic : sig - - (** Set of common operations on parameters. *) - module type Common = sig - type t - val get: string -> t - val set: string -> t -> unit - val clear: string -> unit -> unit - val is_set: string -> bool - val is_default: string -> bool - end - - (** Boolean parameters. *) - module Bool: sig - include Common with type t = bool - val on: string -> unit -> unit - (** Set the parameter to [true]. *) - val off : string -> unit -> unit - (** Set the parameter to [false]. *) - end - - (** Integer parameters. *) - module Int : sig - include Common with type t = int - val incr : string -> unit -> unit - end - - (** String parameters. *) - module String : Common with type t = string - - (** Set of string parameters. *) - module StringSet : sig - include Common with type t = Datatype.String.Set.t - val add: string -> string -> unit - val remove: string -> string -> unit - val is_empty: string -> bool - val iter: string -> (string -> unit) -> unit - end -(* - module IndexedVal(X: sig val ty_name: string end) : sig - include Common with type t = string - type value - val add_choice: string -> string -> value -> unit - val get_val: string -> value - end -*) - -end - -(* ************************************************************************* *) -(** {2 General purpose options} *) -(* ************************************************************************* *) - -val check_range: string -> min:int -> max:int -> int -> unit - (** @since Beryllium-20090601-beta1 - @deprecated Beryllium-20090901 *) - -val get_selection_context: unit -> State_selection.t - (** Selection of all the parameters which define the context of analyses. *) - -(* ************************************************************************* *) -(** {2 Installation Information} *) -(* ************************************************************************* *) - -module PrintVersion: BOOL - (** Behavior of option "-version" *) - -module PrintShare: BOOL - (** Behavior of option "-print-share-path" *) - -module PrintLib: BOOL - (** Behavior of option "-print-lib-path" *) - -module PrintPluginPath: BOOL - (** Behavior of option "-print-plugin-path" *) - -(* ************************************************************************* *) -(** {2 Output Messages} *) -(* ************************************************************************* *) - -module GeneralVerbose: INT - (** Behavior of option "-verbose" *) - -module GeneralDebug: INT - (** Behavior of option "-debug" *) - -module Quiet: BOOL - (** Behavior of option "-quiet" *) - -module UseUnicode: BOOL - (** Behavior of option "-unicode" - @plugin development guide *) - -module Time: STRING - (** Behavior of option "-time" *) - -module Collect_messages: BOOL -(** Behavior of option "-collect-messages" *) - -(* ************************************************************************* *) -(** {2 Input / Output Source Code} *) -(* ************************************************************************* *) - -module PrintCode : BOOL - (** Behavior of option "-print" *) - -module PrintComments: BOOL - (** Behavior of option "-keep-comments" *) - -(** Behavior of option "-ocode" *) -module CodeOutput : sig - include STRING - val output: ('a,Format.formatter,unit) format -> 'a -end - -module FloatNormal: BOOL - (** Behavior of option "-float-normal" *) - -module FloatRelative: BOOL - (** Behavior of option "-float-relative" *) - -module FloatHex: BOOL - (** Behavior of option "-float-hex" *) - -(* ************************************************************************* *) -(** {2 Save/Load} *) -(* ************************************************************************* *) - -module SaveState: STRING - (** Behavior of option "-save" *) - -module LoadState: STRING - (** Behavior of option "-load" *) - -module AddPath: STRING_SET - (** Behavior of option "-add-path" *) - -module LoadModule: STRING_SET - (** Behavior of option "-load-module" *) - -module LoadScript: STRING_SET - (** Behavior of option "-load-script" *) - -module Dynlink: BOOL - (** Behavior of option "-dynlink" *) - -(** Parameters for journalization. *) -module Journal: sig - - module Enable: BOOL - (** Behavior of option "-journal-enable" *) - - module Name: STRING - (** Behavior of option "-journal-name" *) - -end - -(* ************************************************************************* *) -(** {2 Customizing Normalization} *) -(* ************************************************************************* *) - -module UnrollingLevel: INT - (** Behavior of option "-ulevel" *) - -(** Behavior of option "-machdep". - If function [set] is called, then {!File.prepare_from_c_files} must be - called for well preparing the AST. *) -module Machdep: STRING - -module CppCommand: STRING - (** Behavior of option "-cpp-command" *) - -module CppExtraArgs: STRING_SET - (** Behavior of option "-cpp-extra-args" *) - -module ReadAnnot: BOOL - (** Behavior of option "-read-annot" *) - -module PreprocessAnnot: BOOL - (** Behavior of option "-pp-annot" *) - -module TypeCheck: BOOL - (** Behavior of option "-type-check" *) - -module ContinueOnAnnotError: BOOL - (** Behavior of option "-continue-annot-error" *) - -module SimplifyCfg: BOOL - (** Behavior of option "-simplify-cfg" *) - -module KeepSwitch: BOOL - (** Behavior of option "-keep-switch" *) - -module Constfold: BOOL - (** Behavior of option "-constfold" *) - -(** Analyzed files *) -module Files: sig - - include STRING_LIST - (** List of files to analyse *) - - module Check: BOOL - (** Behavior of option "-check" *) - - module Copy: BOOL - (** Behavior of option "-copy" *) - - module Orig_name: BOOL - (** Behavior of option "-orig-name" *) - -end - -(* ************************************************************************* *) -(** {3 Customizing cabs2cil options} *) -(* ************************************************************************* *) - -module AllowDuplication: BOOL - (** Behavior of option "-allow-duplication". *) - -module DoCollapseCallCast: BOOL - (** Behavior of option "-collapse-call-cast". *) - -module ForceRLArgEval: BOOL - (** Behavior of option "-force-rl-arg-eval". *) - -(* ************************************************************************* *) -(** {2 Analysis Behavior of options} *) -(* ************************************************************************* *) - -(** Behavior of option "-main". - - You should usually use {!Globals.entry_point} instead of - {!MainFunction.get} since the first one handles the case where the entry - point is invalid in the right way. *) -module MainFunction: sig - - include STRING - - (** {2 Internal functions} - - Not for casual users. *) - - val unsafe_set: t -> unit - -end - -(** Behavior of option "-lib-entry". - - You should usually use {!Globals.entry_point} instead of - {!LibEntry.get} since the first one handles the case where the entry point - is invalid in the right way. *) -module LibEntry: sig - include BOOL - val unsafe_set: t -> unit (** Not for casual users. *) -end - -module UnspecifiedAccess: BOOL - (** Behavior of option "-unspecified-access" *) - -module Overflow: BOOL - (** Behavior of option "-overflow" *) - -module SafeArrays: BOOL - (** Behavior of option "-safe-arrays" *) - -module AbsoluteValidRange: Plugin.STRING - (** Behavior of option "-absolute-valid-range" *) - -module FloatFlushToZero: BOOL - (** Behavior of option "-float-flush-to-zero" *) - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/plugin.ml frama-c-20111001+nitrogen+dfsg/src/kernel/plugin.ml --- frama-c-20110201+carbon+dfsg/src/kernel/plugin.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/plugin.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,8 +22,11 @@ let positive_debug_ref = ref 0 -let deprecated_ref = ref (fun _ ~now:_ _ -> assert false) -let deprecated_ref2 = ref (fun _ ~now:_ _ -> assert false) +let empty_string = "" + +let dummy_deprecated = fun _ ~now:_ _ -> assert false +let deprecated_ref = ref dummy_deprecated +let deprecated_ref2 = ref dummy_deprecated (* Two distinct functions since type variables cannot be generalized. Okay: quite hackish :( *) @@ -47,46 +50,71 @@ let get_selection () = State_selection.of_list !selection let extend_selection s = selection := s :: !selection +let get_selection_context () = + let has_dependencies s = + State_dependency_graph.Dynamic.G.out_degree + State_dependency_graph.Dynamic.graph + s + > 0 + in + (* automatically select all options which have some dependencies: + they have an impact of some analysis. *) + let states = + State_selection.Dynamic.fold + (fun s acc -> if has_dependencies s then s :: acc else acc) + (get_selection ()) + [] + in + State_selection.of_list states + (* ************************************************************************* *) (** {2 Signatures} *) (* ************************************************************************* *) module type Parameter = sig type t + val parameter: Parameter.t val set: t -> unit val add_set_hook: (t -> t -> unit) -> unit + val add_update_hook: (t -> t -> unit) -> unit val get: unit -> t val clear: unit -> unit val is_default: unit -> bool - val is_set: unit -> bool val option_name: string include State_builder.S val equal: t -> t -> bool - val unsafe_set: t -> unit val add_aliases: string list -> unit val add_alias: string list -> unit + val is_set: unit -> bool + val unsafe_set: t -> unit end -module type BOOL = sig +module type Bool = sig include Parameter with type t = bool val on: unit -> unit val off: unit -> unit end -module type INT = sig +module type WithOutput = sig + include Bool + val set_output_dependencies: State.t list -> unit + val output: (unit -> unit) -> unit +end + +module type Int = sig include Parameter with type t = int val incr: unit -> unit val set_range: min:int -> max:int -> unit val get_range: unit -> int * int end -module type STRING = sig +module type String = sig include Parameter with type t = string val set_possible_values: string list -> unit val get_possible_values: unit -> string list end -module type GEN_STRING_SET = sig +module type String_collection = sig include Parameter val add: string -> unit val remove: string -> unit @@ -96,18 +124,18 @@ val exists: (string -> bool) -> bool end -module type STRING_SET = GEN_STRING_SET with type t = Datatype.String.Set.t -module type STRING_LIST = GEN_STRING_SET with type t = string list +module type String_set = String_collection with type t = Datatype.String.Set.t +module type String_list = String_collection with type t = string list -module type STRING_HASHTBL = sig - include GEN_STRING_SET with type t = Datatype.String.Set.t +module type String_hashtbl = sig + include String_collection with type t = Datatype.String.Set.t type value val find: string -> value end (** option interface *) -module type INDEXED_VAL = sig - include STRING +module type Indexed_val = sig + include String type value (** the real type for the option*) val add_choice: string -> value -> unit (** adds a new choice for the option. *) @@ -117,7 +145,6 @@ module type Parameter_input = sig val option_name: string val help: string - val kind: [> `Correctness | `Tuning | `Irrelevant ] end module type Parameter_input_with_arg = sig @@ -126,7 +153,7 @@ end (** input signature for [IndexedVal] *) -module type COMPLEX_VALUE = sig +module type Indexed_val_input = sig include Parameter_input_with_arg type t (** the type to be serialized *) val default_val: t (** the default value *) @@ -137,11 +164,12 @@ module type S = sig include Log.Messages val add_group: ?memo:bool -> string -> group - module Help: BOOL - module Verbose: INT - module Debug: INT + module Help: Bool + module Verbose: Int + module Debug: Int val help: group val messages: group + val parameters: unit -> Parameter.t list end module type General_services = sig @@ -154,24 +182,27 @@ (X:sig include Parameter_input val default: bool - end) : BOOL + end) : Bool - module Action(X: Parameter_input) : BOOL - module False(X: Parameter_input) : BOOL - module True(X: Parameter_input) : BOOL + module Action(X: Parameter_input) : Bool + module False(X: Parameter_input) : Bool + module True(X: Parameter_input) : Bool + + module WithOutput(X: sig include Parameter_input + val output_by_default: bool end) : WithOutput module Int - (X: sig val default: int include Parameter_input_with_arg end) : INT - module Zero(X:Parameter_input_with_arg) : INT + (X: sig val default: int include Parameter_input_with_arg end) : Int + module Zero(X:Parameter_input_with_arg) : Int module String - (X: sig include Parameter_input_with_arg val default: string end) : STRING - module EmptyString(X: Parameter_input_with_arg) : STRING + (X: sig include Parameter_input_with_arg val default: string end) : String + module EmptyString(X: Parameter_input_with_arg) : String - module StringSet(X: Parameter_input_with_arg) : STRING_SET - module StringList(X: Parameter_input_with_arg) : STRING_LIST + module StringSet(X: Parameter_input_with_arg) : String_set + module StringList(X: Parameter_input_with_arg) : String_list - module IndexedVal (V:COMPLEX_VALUE) : INDEXED_VAL with type value = V.t + module IndexedVal (V:Indexed_val_input) : Indexed_val with type value = V.t module StringHashtbl (X: Parameter_input_with_arg) @@ -180,7 +211,7 @@ val parse: string -> string * t val no_binding: string -> t end) : - STRING_HASHTBL with type value = V.t + String_hashtbl with type value = V.t end @@ -204,10 +235,6 @@ let is_kernel () = !kernel let reset_plugin () = kernel := false -(* ************************************************************************* *) -(** {2 Optional parameters of functors exported by Register} *) -(* ************************************************************************* *) - let cmdline_stage_ref = ref Cmdline.Configuring let set_cmdline_stage s = cmdline_stage_ref := s @@ -217,39 +244,48 @@ let negative_option_name_ref = ref None let set_negative_option_name s = negative_option_name_ref := Some s -let negative_option_help_ref = ref "" +let negative_option_help_ref = ref empty_string let set_negative_option_help s = negative_option_help_ref := s -let projectify_ref = ref true -let do_not_projectify () = projectify_ref := false - let must_save_ref = ref true let do_not_save () = must_save_ref := false -let optional_help_ref = ref ("": (unit, Format.formatter, unit) format) +let projectify_ref = ref true +let do_not_projectify () = + projectify_ref := false; + do_not_save () + +let empty_format = ("": (unit, Format.formatter, unit) format) +let optional_help_ref = ref empty_format let set_optional_help fmt = optional_help_ref := fmt -let module_name_ref = ref "" +let module_name_ref = ref empty_string let set_module_name s = module_name_ref := s let group_ref = ref Cmdline.Group.default let set_group s = group_ref := s -let is_visible_ref = ref None -let is_visible () = is_visible_ref := Some true -let is_invisible () = is_visible_ref := Some false +let do_iterate_ref = ref None +let do_iterate () = do_iterate_ref := Some true +let do_not_iterate () = do_iterate_ref := Some false + +let is_visible_ref = ref true +let is_invisible () = + is_visible_ref := false; + do_not_iterate () let reset () = cmdline_stage_ref := Cmdline.Configuring; journalize_ref := true; negative_option_name_ref := None; - negative_option_help_ref := ""; - optional_help_ref := ""; + negative_option_help_ref := empty_string; + optional_help_ref := empty_format; projectify_ref := true; must_save_ref := true; - module_name_ref := ""; + module_name_ref := empty_string; group_ref := Cmdline.Group.default; - is_visible_ref := None + do_iterate_ref := None; + is_visible_ref := true (* ************************************************************************* *) (** {2 Generic functors} *) @@ -257,20 +293,10 @@ let kernel_name = "kernel" -type 'a option_accessor = - { get: unit -> 'a ; set: 'a -> unit; is_set: unit -> bool } - -type kind = - | Bool of bool option_accessor * string option - | Int of int option_accessor * (unit -> int * int) - | String of string option_accessor * (unit -> string list) - | StringSet of string option_accessor - -type parameter = { o_name: string; o_help: string; o_kind: kind } type plugin = { p_name: string; p_help: string; - p_parameters: (string, parameter list) Hashtbl.t } + p_parameters: (string, Parameter.t list) Hashtbl.t } let plugins: plugin list ref = ref [] let iter_on_plugins f = @@ -284,26 +310,29 @@ in List.iter f (List.sort cmp !plugins) -(*let dynamic_plugin_name name = "Dynamic." ^ name -let dynamic_function_name funname statename = - funname ^ " \"" ^ statename ^ "\""*) -let dynamic_name functor_name fct_name option_name = - Format.sprintf "Parameters.Dynamic.%s.%s %S" - functor_name fct_name option_name +let get s = List.find (fun p -> p.p_name = s) !plugins + +let iter_on_this_parameter stage = match !do_iterate_ref, stage with + | Some false, _ + | None, (Cmdline.Early | Cmdline.Extending | Cmdline.Extended + | Cmdline.Exiting | Cmdline.Loading) -> + false + | Some true, _ | None, Cmdline.Configuring -> + true module Build (X:sig include Datatype.S - val default: unit -> t - val option_name: string - val functor_name: string - val kind: [> `Correctness | `Tuning | `Irrelevant ] + val default: unit -> t + val option_name: string + val functor_name: string end) = struct let is_dynamic = not !kernel_ongoing let projectify = !projectify_ref - let must_save = !must_save_ref && projectify + let must_save = !must_save_ref + let is_visible = !is_visible_ref let module_name = !module_name_ref let group = !group_ref @@ -312,9 +341,9 @@ let () = match !cmdline_stage_ref with | Cmdline.Early | Cmdline.Extending | Cmdline.Extended | Cmdline.Exiting | Cmdline.Loading -> - do_not_projectify () + do_not_projectify () | Cmdline.Configuring -> - () + () (* quite an inlining of [State_builder.Ref]; but handle [projectify_ref] *) module Option_state_builder @@ -343,7 +372,7 @@ let create = if projectify then create else (* do an alias *) get let clear x = if projectify then x := X.default () let set x = - if projectify then state := x (* else there is already an alias *) + if projectify then state := x (* else there is already an alias *) let is_default x = !x = (X.default ()) let clear_some_projects _ _ = false (* parameters cannot be projects *) end) @@ -360,36 +389,21 @@ end - module Internal_state = struct - - let pretty_value v = - if X.option_name = "" then "Input C files" - else - if Type.equal X.ty Datatype.bool - || Type.equal X.ty Datatype.int - || Type.equal X.ty Datatype.float - then - Pretty_utils.sfprintf "%s: %a" X.option_name X.pretty v - else X.option_name - - include Option_state_builder + module Internal_state = + Option_state_builder (struct - include X - let unique_name = X.option_name - let pretty_name = pretty_value (X.default ()) + include X + let kind = `Correctness (* TODO: to be removed later *) + let unique_name = X.option_name + let pretty_name = + if X.option_name = empty_string then "Input C files" + else X.option_name end) - let set v = - State.set_name self (pretty_value v); - set v - - end - include Internal_state let self = Internal_state.self type t = Internal_state.data - let () = extend_selection self let is_default () = X.equal (X.default ()) (Internal_state.get ()) @@ -397,22 +411,33 @@ module Is_set = Option_state_builder (struct - include D.Bool - let pretty_name = X.option_name ^ " is set" - let unique_name = pretty_name - let default () = false + include D.Bool + let pretty_name = X.option_name ^ " is set" + let unique_name = pretty_name + let default () = false let kind = `Internal end) let () = - State_dependency_graph.Static.add_dependencies ~from:Is_set.self [ self ] + State_dependency_graph.Static.add_dependencies ~from:Is_set.self [ self ]; + extend_selection Is_set.self + + module Set_hook = Hook.Build(struct type t = X.t * X.t end) + let add_set_hook f = Set_hook.extend (fun (old, x) -> f old x) - module Set_Hook = Hook.Build(struct type t = X.t * X.t end) - let add_set_hook f = Set_Hook.extend (fun (old, x) -> f old x) + let add_update_hook f = + add_set_hook f; + add_hook_on_update + (fun x -> + let old = get () in + let new_ = !x in + if not (X.equal old new_) then f old new_) let gen_journalized name ty set = let name = - if is_dynamic then dynamic_name X.functor_name name X.option_name - else "Parameters." ^ module_name ^ "." ^ name + if is_dynamic then + Dynamic.Parameter.get_name X.functor_name name X.option_name + else + "Kernel." ^ module_name ^ "." ^ name in if !journalize_ref then Journal.register ~is_dyn:is_dynamic name (D.func ty D.unit) set @@ -424,8 +449,8 @@ Is_set.set true; let old = Internal_state.get () in if not (X.equal x old) then begin - Internal_state.set x; - Set_Hook.apply (old, x) + Internal_state.set x; + Set_hook.apply (old, x) end in gen_journalized "unsafe_set" X.ty set @@ -435,15 +460,15 @@ Internal_state.set x; if projectify then begin (* [JS 2009/05/25] first clear the dependency and next apply the hooks - since these hooks may set some states in the dependencies *) + since these hooks may set some states in the dependencies *) let selection = - State_selection.Dynamic.diff - (State_selection.Dynamic.only_dependencies self) - (State_selection.singleton Is_set.self) + State_selection.Dynamic.diff + (State_selection.Dynamic.only_dependencies self) + (State_selection.singleton Is_set.self) in Project.clear ~selection () end; - Set_Hook.apply (old, x) + Set_hook.apply (old, x) let unjournalized_set x = Is_set.set true; @@ -454,11 +479,15 @@ (* [TODO] not very efficient since the test of modification is done twice. *) let set x = if not (X.equal x (Internal_state.get ())) then unguarded_set x - let clear = + let unguarded_clear = gen_journalized "clear" D.unit (fun () -> - force_set (X.default ()); - Is_set.set false) + force_set (X.default ()); + Is_set.set false) + + let clear () = + (* write this call in the journal if and only if there is something to do *) + if Is_set.get () || not (is_default ()) then unguarded_clear () let equal = X.equal @@ -466,19 +495,20 @@ if is_dynamic then let ty = D.func ty1 ty2 in Dynamic.register - ~plugin:"" - (dynamic_name X.functor_name name X.option_name) - ~journalize:false - ty - f + ~plugin:empty_string + (Dynamic.Parameter.get_name X.functor_name name X.option_name) + ~journalize:false + ty + f else f - let get, set, clear, is_set = + let get, set, clear, is_set, is_default = register_dynamic "get" D.unit X.ty Internal_state.get, register_dynamic "set" X.ty D.unit set, register_dynamic "clear" D.unit D.unit clear, - register_dynamic "is_set" D.unit D.bool Is_set.get + register_dynamic "is_set" D.unit D.bool Is_set.get, + register_dynamic "is_default" D.unit D.bool is_default let stage = !cmdline_stage_ref @@ -498,19 +528,23 @@ end) = struct + let parameters_ref : Parameter.t list ref = ref [] + let parameters () = !parameters_ref + let verbose_level = ref (fun () -> 1) let debug_level = ref (fun () -> 0) include Log.Register (struct let channel = - if is_kernel () then Log.kernel_channel_name else P.shortname + if is_kernel () then Log.kernel_channel_name else P.shortname let label = if is_kernel () then Log.kernel_label_name else P.shortname let debug_atleast level = !debug_level () >= level let verbose_atleast level = !verbose_level () >= level end) - let () = if is_kernel () then begin + let () = + if is_kernel () then begin deprecated_ref := deprecated; deprecated_ref2 := deprecated; Cmdline.kernel_verbose_atleast_ref := verbose_atleast; @@ -520,25 +554,20 @@ let plugin = let name = if is_kernel () then kernel_name else P.name in let tbl = Hashtbl.create 17 in - Hashtbl.add tbl "" []; + Hashtbl.add tbl empty_string []; { p_name = name; p_help = P.help; p_parameters = tbl } - let add_parameter group stage name help kind = - match !is_visible_ref, stage with - | Some false, _ - | None, - (Cmdline.Early | Cmdline.Extending | Cmdline.Extended - | Cmdline.Exiting | Cmdline.Loading) -> - () - | Some true, _ | None, Cmdline.Configuring -> - let parameter_groups = plugin.p_parameters in - let parameter = { o_name = name; o_help = help; o_kind = kind } in - try - let group_name = Cmdline.Group.name group in - let parameters = Hashtbl.find plugin.p_parameters group_name in - Hashtbl.replace parameter_groups group_name (parameter :: parameters) - with Not_found -> - assert false + let add_parameter group stage param = + if iter_on_this_parameter stage then begin + parameters_ref := param :: !parameters_ref; + let parameter_groups = plugin.p_parameters in + try + let group_name = Cmdline.Group.name group in + let parameters = Hashtbl.find plugin.p_parameters group_name in + Hashtbl.replace parameter_groups group_name (param :: parameters) + with Not_found -> + assert false + end let add_group ?memo name = let parameter_groups = plugin.p_parameters in @@ -547,7 +576,9 @@ g let () = - Cmdline.add_plugin P.name ~short:P.shortname ~help:P.help; + (try Cmdline.add_plugin P.name ~short:P.shortname ~help:P.help + with Invalid_argument s -> + abort "cannot register plug-in `%s': %s" P.name s); kernel_ongoing := is_kernel (); plugins := plugin :: !plugins @@ -560,10 +591,10 @@ include Build (struct - include Datatype.Bool - include X - let default () = default - let functor_name = "Bool" + include Datatype.Bool + include X + let default () = default + let functor_name = "Bool" end) let on = register_dynamic "on" D.unit D.unit (fun () -> set true) @@ -571,45 +602,57 @@ let generic_add_option name help value = Cmdline.add_option - name - ~plugin:P.shortname - ~group - ~help - ~ext_help:!optional_help_ref - stage - (Cmdline.Unit (fun () -> unguarded_set value)) + name + ~plugin:P.shortname + ~group + ~help + ~ext_help:!optional_help_ref + stage + (Cmdline.Unit (fun () -> unguarded_set value)) let default_message = " (set by default)" let add_option name = - let help = if X.default then X.help ^ default_message else X.help in - generic_add_option name (Some help) true + let help = match is_visible, X.default with + | false, (true | false) -> None + | true, true -> + let h = + if X.help = empty_string + then empty_string + else X.help ^ default_message in + Some h + | true, false -> Some X.help + in + generic_add_option name help true let negative_option_name name = let s = !negative_option_name_ref in match s with | None -> - let len = String.length P.shortname + 1 (* +1: the initial '-' *) in - if String.length name <= len || P.shortname = "" then - "-no" ^ name - else - let bef = Str.string_before name len in - if bef = "-" ^ P.shortname then - bef ^ "-no" ^ Str.string_after name len - else - "-no" ^ name + let len = String.length P.shortname + 1 (* +1: the initial '-' *) in + if String.length name <= len || P.shortname = empty_string then + "-no" ^ name + else + let bef = Str.string_before name len in + if bef = "-" ^ P.shortname then + bef ^ "-no" ^ Str.string_after name len + else + "-no" ^ name | Some s -> - assert (s <> ""); - s + assert (s <> empty_string); + s let add_negative_option name = let neg_name = negative_option_name name in - let mk_help s = Some (if X.default then s else s ^ default_message) in + let mk_help s = + if is_visible then Some (if X.default then s else s ^ default_message) + else None + in let neg_help = - match !negative_option_name_ref, !negative_option_help_ref with - | None, "" -> (* no user-specific config: no help *) None - | Some _, "" -> mk_help ("opposite of option \"" ^ name ^ "\"") - | _, s -> assert (s <> ""); mk_help s + match !negative_option_name_ref, !negative_option_help_ref with + | None, "" -> (* no user-specific config: no help *) None + | Some _, "" -> mk_help ("opposite of option \"" ^ name ^ "\"") + | _, s -> assert (s <> empty_string); mk_help s in generic_add_option neg_name neg_help false; neg_name @@ -620,17 +663,32 @@ let add_alias = deprecated "Plugin.add_alias" ~now:"Plugin.add_aliases" add_aliases - let () = + let parameter = add_option X.option_name; let negative_option = - match !negative_option_name_ref, stage with - | Some "", _ | None, Cmdline.Exiting -> None - | _ -> Some (add_negative_option X.option_name) + match !negative_option_name_ref, stage with + | Some "", _ | None, Cmdline.Exiting -> None + | _ -> Some (add_negative_option X.option_name) in - add_parameter - !group_ref stage Internal_state.name X.help - (Bool({ get = get; set = set; is_set = is_set}, negative_option)); - reset () + let accessor = + Parameter.Bool + ({ Parameter.get = get; set = set; + add_set_hook = add_set_hook; add_update_hook = add_update_hook }, + negative_option) + in + let p = + Parameter.create + ~name:Internal_state.name + ~help:X.help + ~accessor:accessor + ~is_set:is_set + in + add_parameter !group_ref stage p; + reset (); + if is_dynamic then + Dynamic.register + ~plugin:empty_string X.option_name Parameter.ty ~journalize:false p + else p end @@ -642,24 +700,29 @@ module Action(X: Parameter_input) = struct + (* [JS 2011/09/29] + The ugly hack seems to be required anymore neither for Value nor Wp. + Maybe it is time to remove it? :-) *) + (* do not save it but restore the "good" behavior when creating by copy *) let () = do_not_save () (* [JS 2011/01/19] Not saving this kind of options is a quite bad hack with several drawbacks (see Frama-C commits 2011/01/19, message of JS around 15 PM). I'm quite sure there is a better way to not display - results too many times (e.g. by using the "isset" flag). *) + results too many times (e.g. by using the "isset" flag). + That is also the origin of bug #687 *) include False(X) let () = Project.create_by_copy_hook - (fun src p -> - Project.copy - ~selection:(State_selection.singleton Is_set.self) ~src p; - let selection = State_selection.singleton self in - let opt = Project.on ~selection src get () in - if opt then Project.on ~selection p set true) + (fun src p -> + Project.copy + ~selection:(State_selection.singleton Is_set.self) ~src p; + let selection = State_selection.singleton self in + let opt = Project.on ~selection src get () in + if opt then Project.on ~selection p set true) end @@ -670,10 +733,10 @@ include Build (struct - include Datatype.Int - include X - let default () = default - let functor_name = "Int" + include Datatype.Int + include X + let default () = default + let functor_name = "Int" end) let incr = @@ -682,14 +745,14 @@ let add_option name = Cmdline.add_option - name - ~argname:X.arg_name - ~help:(Some X.help) - ~ext_help:!optional_help_ref - ~plugin:P.shortname - ~group - stage - (Cmdline.Int unguarded_set) + name + ~argname:X.arg_name + ~help:(if is_visible then Some X.help else None) + ~ext_help:!optional_help_ref + ~plugin:P.shortname + ~group + stage + (Cmdline.Int unguarded_set) let add_aliases = Cmdline.add_aliases X.option_name ~plugin:P.shortname ~group stage @@ -701,22 +764,37 @@ let set_range ~min ~max = range := min, max let get_range () = !range - let () = + let parameter = add_set_hook - (fun _ n -> - let min, max = !range in - if n < min then - abort - "argument of %s must be at least %d." Internal_state.name min; - if n > max then - abort - "argument of %s must be no more than %d." - Internal_state.name max); - add_parameter - !group_ref stage Internal_state.name X.help - (Int({ get = get; set = set; is_set = is_set }, get_range)); + (fun _ n -> + let min, max = !range in + if n < min then + abort + "argument of %s must be at least %d." Internal_state.name min; + if n > max then + abort + "argument of %s must be no more than %d." + Internal_state.name max); + let accessor = + Parameter.Int + ({ Parameter.get = get; set = set; + add_set_hook = add_set_hook; add_update_hook = add_update_hook }, + get_range) + in + let p = + Parameter.create + ~name:Internal_state.name + ~help:X.help + ~accessor + ~is_set:is_set + in + add_parameter !group_ref stage p; add_option X.option_name; - reset () + reset (); + if is_dynamic then + Dynamic.register + ~plugin:empty_string X.option_name Parameter.ty ~journalize:false p + else p end @@ -733,22 +811,22 @@ include Build (struct - include Datatype.String - include X - let default () = default - let functor_name = "String" + include Datatype.String + include X + let default () = default + let functor_name = "String" end) let add_option name = Cmdline.add_option - name - ~argname:X.arg_name - ~help:(Some X.help) - ~ext_help:!optional_help_ref - ~plugin:P.shortname - ~group - stage - (Cmdline.String unguarded_set) + name + ~argname:X.arg_name + ~help:(if is_visible then Some X.help else None) + ~ext_help:!optional_help_ref + ~plugin:P.shortname + ~group + stage + (Cmdline.String unguarded_set) let add_aliases = Cmdline.add_aliases X.option_name ~plugin:P.shortname ~group stage @@ -760,24 +838,39 @@ let set_possible_values s = possible_values := s let get_possible_values () = !possible_values - let () = + let parameter = add_set_hook - (fun _ s -> - match !possible_values with - | [] -> () - | v when List.mem s v -> () - | _ -> abort "invalid input %s for %s" s Internal_state.name); - add_parameter - !group_ref stage Internal_state.name X.help - (String({ get = get; set = set; is_set = is_set }, - get_possible_values)); + (fun _ s -> + match !possible_values with + | [] -> () + | v when List.mem s v -> () + | _ -> abort "invalid input %s for %s" s Internal_state.name); + let accessor = + Parameter.String + ({ Parameter.get = get; set = set; + add_set_hook = add_set_hook; add_update_hook = add_update_hook }, + get_possible_values) + in + let p = + Parameter.create + ~name:Internal_state.name + ~help:X.help + ~accessor + ~is_set + in + add_parameter !group_ref stage p; add_option X.option_name; - reset () + reset (); + if is_dynamic then + Dynamic.register + ~plugin:empty_string X.option_name Parameter.ty ~journalize:false p + else + p end module EmptyString(X: Parameter_input_with_arg) = - String(struct include X let default = "" end) + String(struct include X let default = empty_string end) (** {3 String set and string list} *) @@ -793,16 +886,16 @@ val fold: (string -> 'acc -> 'acc) -> t -> 'acc -> 'acc val iter: (string -> unit) -> t -> unit val exists: (string -> bool) -> t -> bool + val functor_name: string end) (X:Parameter_input_with_arg) = struct include Build (struct - let default () = S.empty - let functor_name = "StringSet" - include S - include X + let default () = S.empty + include S + include X end) let add = @@ -818,15 +911,18 @@ let guarded_set_set x = match split_set x with | [] when not (S.is_empty (get ())) -> - unguarded_set S.empty + unguarded_set S.empty | l -> - if not (List.for_all (fun s -> S.mem s (get ())) l) || - not (S.for_all (fun s -> List.mem s l) (get ())) - then - unguarded_set (List.fold_right S.add l S.empty) + if not (List.for_all (fun s -> S.mem s (get ())) l) || + not (S.for_all (fun s -> List.mem s l) (get ())) + then + unguarded_set (List.fold_right S.add l S.empty) let get_set ?(sep=", ") () = - S.fold (fun s acc -> if acc <> "" then s ^ sep ^ acc else s) (get ()) "" + S.fold + (fun s acc -> if acc <> empty_string then s ^ sep ^ acc else s) + (get ()) + empty_string let is_empty = let is_empty () = S.is_empty (get ()) in @@ -842,14 +938,14 @@ let add_option name = Cmdline.add_option - name - ~plugin:P.shortname - ~group - ~argname:X.arg_name - ~help:(Some X.help) - ~ext_help:!optional_help_ref - stage - (Cmdline.String_list (List.iter add)) + name + ~plugin:P.shortname + ~group + ~argname:X.arg_name + ~help:(if is_visible then Some X.help else None) + ~ext_help:!optional_help_ref + stage + (Cmdline.String_list (List.iter add)) let add_aliases = Cmdline.add_aliases X.option_name ~plugin:P.shortname ~group stage @@ -857,41 +953,94 @@ let add_alias = deprecated "Plugin.add_alias" ~now:"Plugin.add_aliases" add_aliases - let () = - add_parameter - !group_ref stage Internal_state.name X.help - (StringSet{ get = (fun () -> get_set ()); - set = guarded_set_set; - is_set = is_set }); + end + + module StringSet(X: Parameter_input_with_arg) = struct + + include Build_string_set + (struct + include Datatype.String.Set + let functor_name = "StringSet" + end) + (X) + + let parameter = + let accessor = + Parameter.String_set + { Parameter.get = get_set; + set = guarded_set_set; + add_set_hook = add_set_hook; + add_update_hook = add_update_hook } + in + let p = + Parameter.create + ~name:Internal_state.name + ~help:X.help + ~accessor:accessor + ~is_set:is_set + in + add_parameter !group_ref stage p; add_option X.option_name; - reset () + reset (); + if is_dynamic then + Dynamic.register + ~plugin:empty_string X.option_name Parameter.ty ~journalize:false p + else p end - module StringSet = Build_string_set(Datatype.String.Set) + module StringList(X: Parameter_input_with_arg) = struct - module StringList = - Build_string_set + include Build_string_set (struct - include Datatype.List(Datatype.String) - let empty = [] - let is_empty = equal [] - let add s l = s :: l - let remove s l = List.filter ((<>) s) l - let mem s = List.exists (((=) : string -> _) s) - let for_all = List.for_all - let fold = List.fold_right - let iter = List.iter - let exists = List.exists + include Datatype.List(Datatype.String) + let empty = [] + let is_empty = equal [] + let add s l = s :: l + let remove s l = List.filter ((<>) s) l + let mem s = List.exists (((=) : string -> _) s) + let for_all = List.for_all + let fold = List.fold_right + let iter = List.iter + let exists = List.exists + let functor_name = "StringList" end) + (X) + + let parameter = + let accessor = + Parameter.String_list + { Parameter.get = get_set; + set = guarded_set_set; + add_set_hook = add_set_hook; + add_update_hook = add_update_hook } + in + let p = + Parameter.create + ~name:Internal_state.name + ~help:X.help + ~accessor:accessor + ~is_set:is_set + in + add_parameter !group_ref stage p; + add_option X.option_name; + reset (); + if is_dynamic then + Dynamic.register + ~plugin:empty_string X.option_name Parameter.ty ~journalize:false p + else p + + end (** {3 Complex values indexed by strings} *) - module IndexedVal (V:COMPLEX_VALUE):INDEXED_VAL with type value = V.t = + module IndexedVal (V:Indexed_val_input) : Indexed_val with type value = V.t = struct type value = V.t + let is_dynamic = not !kernel_ongoing + let options = Hashtbl.create 13 let add_choice k v = Hashtbl.add options k v let () = add_choice V.default_key V.default_val @@ -903,23 +1052,17 @@ module StateAux = struct let name = V.option_name let unique_name = V.option_name - let kind = V.kind + let kind = `Correctness (* TODO: to be removed later *) let create = create type t = string ref let get () = !curr_choice let set s = - if s != get () then - if Hashtbl.mem options !s then - curr_choice := s - else - (* [JS 2009/05/25] well, quite difficult to use functor - Log.Register here without using a recursive module. - Maybe a lighter solution could be implemented. *) - Printf.eprintf - "Warning: %s: identifier %s is not a valid index for this \ -option. Option is unchanged.\n" V.option_name !s + if s != get () then + let v = !s in + if Hashtbl.mem options v then curr_choice := s + else abort "invalid input %s for %s" v V.option_name let copy s = ref !s let clear tbl = tbl := V.default_key @@ -941,16 +1084,25 @@ let get () = !(!curr_choice) let get_val () = Hashtbl.find options (get()) - module Set_Hook = Hook.Build(struct type t = string * string end) - let add_set_hook f = Set_Hook.extend (fun (old, x) -> f old x) + module Set_hook = Hook.Build(struct type t = string * string end) + let add_set_hook f = Set_hook.extend (fun (old, x) -> f old x) + + let add_update_hook f = + add_set_hook f; + add_hook_on_update + (fun x -> + (* this hook is applied just **before** the value is set *) + let old = get () in + let new_ = !x in + if old <> new_ then f old new_) let unguarded_set s = if Hashtbl.mem options s then begin - let old = !(!curr_choice) in - !curr_choice := s; - Set_Hook.apply (old, s) + let old = !(!curr_choice) in + !curr_choice := s; + Set_hook.apply (old, s) end else - warning + warning "identifier %s is not a valid index for parameter %s. \ Option is unchanged.\n" s V.option_name @@ -970,14 +1122,14 @@ let add_option name = Cmdline.add_option - name - ~plugin:P.shortname - ~group - ~argname:V.arg_name - ~help:(Some V.help) - ~ext_help:!optional_help_ref - stage - (Cmdline.String unguarded_set) + name + ~plugin:P.shortname + ~group + ~argname:V.arg_name + ~help:(if !is_visible_ref then Some V.help else None) + ~ext_help:!optional_help_ref + stage + (Cmdline.String unguarded_set) let add_aliases = Cmdline.add_aliases V.option_name ~plugin:P.shortname ~group stage @@ -991,9 +1143,28 @@ let option_name = V.option_name + let parameter = + let accessor = + Parameter.String + ({ Parameter.get = get; set = set; + add_set_hook = add_set_hook; add_update_hook = add_update_hook }, + (fun () -> [])) + in + let p = + Parameter.create + ~name:V.option_name + ~help:V.help + ~accessor + ~is_set:is_set + in + if is_dynamic then + Dynamic.register + ~plugin:empty_string V.option_name Parameter.ty ~journalize:false p + else p + let () = add_option V.option_name; - reset () + reset (); end @@ -1011,37 +1182,36 @@ module H = State_builder.Hashtbl - (Initial_Datatype.String.Hashtbl) - (V) - (struct - let name = X.option_name ^ " (hashtbl)" - let size = 7 - let dependencies = [ self ] + (Initial_Datatype.String.Hashtbl) + (V) + (struct + let name = X.option_name ^ " (hashtbl)" + let size = 7 + let dependencies = [ self ] let kind = `Internal - end) + end) type value = V.t let self = H.self - let parse k = + let parse () = iter - (fun s -> - let k, v = V.parse s in - H.add k v); - try H.find k - with Not_found -> - let v = V.no_binding k in - H.add k v; - v - - let find s = H.memo parse s - + (fun s -> + let k, v = V.parse s in + H.add k v); + H.mark_as_computed () + + let find s = + if not (H.is_computed ()) then parse (); + try H.find s + with Not_found -> V.no_binding s end (** {2 Generic options for each plug-in} *) - let prefix = if P.shortname = "" then "-kernel-" else "-" ^ P.shortname ^ "-" + let prefix = + if P.shortname = empty_string then "-kernel-" else "-" ^ P.shortname ^ "-" let help = add_group "Getting Information" @@ -1049,17 +1219,17 @@ let () = set_cmdline_stage Cmdline.Exiting let () = if is_kernel () then set_module_name "Help" module Help = - False(struct - let option_name = prefix ^ "help" - let help = - if is_kernel () then "help of the Frama-C kernel" - else "help of plug-in " ^ P.name - let kind = `Irrelevant - end) + False + (struct + let option_name = prefix ^ "help" + let help = + if is_kernel () then "help of the Frama-C kernel" + else "help of plug-in " ^ P.name + end) let () = Cmdline.run_after_exiting_stage (fun () -> - if Help.get () then Cmdline.plugin_help P.shortname else Cmdline.nop); + if Help.get () then Cmdline.plugin_help P.shortname else Cmdline.nop); Help.add_aliases [ prefix ^ "h" ] let messages = add_group "Output Messages" @@ -1068,7 +1238,7 @@ set_group messages; do_not_projectify (); do_not_journalize (); - is_visible (); + do_iterate (); if is_kernel () then begin set_cmdline_stage Cmdline.Early; set_module_name modname; @@ -1082,15 +1252,14 @@ module Verbose = struct include Int(struct - let default = !verbose_level () - let option_name = verbose_optname - let arg_name = "n" - let help = - (if is_kernel () then "level of verbosity for the Frama-C kernel" - else "level of verbosity for plug-in " ^ P.name) - ^ " (defaults to " ^ string_of_int default ^ ")" - let kind = `Irrelevant - end) + let default = !verbose_level () + let option_name = verbose_optname + let arg_name = "n" + let help = + (if is_kernel () then "level of verbosity for the Frama-C kernel" + else "level of verbosity for plug-in " ^ P.name) + ^ " (defaults to " ^ string_of_int default ^ ")" + end) let get () = if is_set () then get () else !Cmdline.verbose_level_ref let () = verbose_level := get; @@ -1103,27 +1272,74 @@ module Debug = struct include Int(struct - let default = !debug_level () - let option_name = debug_optname - let arg_name = "n" - let help = - (if is_kernel () then "level of debug for the Frama-C kernel" - else "level of debug for plug-in " ^ P.name) - ^ " (defaults to " ^ string_of_int default ^ ")" - let kind = `Irrelevant - end) + let default = !debug_level () + let option_name = debug_optname + let arg_name = "n" + let help = + (if is_kernel () then "level of debug for the Frama-C kernel" + else "level of debug for plug-in " ^ P.name) + ^ " (defaults to " ^ string_of_int default ^ ")" + end) let get () = if is_set () then get () else !Cmdline.debug_level_ref let () = debug_level := get; (* line order below matters *) set_range ~min:0 ~max:max_int; add_set_hook - (fun old n -> - if n = 0 then Pervasives.decr positive_debug_ref - else if old = 0 then Pervasives.incr positive_debug_ref); + (fun old n -> + if n = 0 then Pervasives.decr positive_debug_ref + else if old = 0 then Pervasives.incr positive_debug_ref); if is_kernel () then set Cmdline.kernel_debug_level end + (** Options that directly cause an output. *) + module WithOutput + (X: sig include Parameter_input val output_by_default: bool end) = + struct + + (* Requested command-line option *) + include False(X) + + (* Command-line option for output. *) + let () = set_group messages + module Output = + Bool(struct + let default = X.output_by_default + let option_name = X.option_name ^ "-print" + let help = "print results for option " ^ X.option_name + end) + + (* Boolean that indicates whether the results have never been output + in the current mode. As usual, change in dependencies automatically + reset the value *) + module ShouldOutput = + State_builder.True_ref(struct + let default = X.output_by_default + let kind = `Irrelevant + let dependencies = [] (* To be filled by the user when calling the + output function *) + let name = X.option_name ^ "ShouldOutput" + end) + + (* Output has been requested by the user. Set the "output should be + printed" boolean to true *) + let () = Output.add_set_hook (fun _ v -> if v then ShouldOutput.set true) + + let set_output_dependencies deps = + State_dependency_graph.Static.add_codependencies + ~onto:ShouldOutput.self + deps + + let output f = + (* Output only if our two booleans are at true *) + if Output.get () && ShouldOutput.get () then begin + (* One output will occur, do not output anything next time (unless + dependencies change, or the user requests it on the command-line) *) + ShouldOutput.set false; + f (); + end + end + let () = reset_plugin () end (* Register *) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/plugin.mli frama-c-20111001+nitrogen+dfsg/src/kernel/plugin.mli --- frama-c-20110201+carbon+dfsg/src/kernel/plugin.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/plugin.mli 2011-10-10 08:38:09.000000000 +0000 @@ -23,63 +23,59 @@ (** Provided plug-general services for plug-ins. @since Beryllium-20090601-beta1 *) -val at_normal_exit: (unit -> unit) -> unit - (** Now replaced by {!Cmdline.at_normal_exit}. - @since Beryllium-20090901 - @deprecated since Boron-20100401 *) - -val run_normal_exit_hook: unit -> unit - (** Now replaced by {!Cmdline.run_normal_exit_hook}. - @since Beryllium-20090901 - @deprecated since Boron-20100401 *) - +(* ************************************************************************* *) (** {2 Signatures} *) +(* ************************************************************************* *) type group = Cmdline.Group.t (** Group of parameters. @since Beryllium-20090901 *) -(** Generic outputs signatures of parameters. +(** Generic signature of a parameter. @plugin development guide *) module type Parameter = sig type t + (** Type of the parameter (an int, a string, etc). It is concrete for each + module implementing this signature. *) + + val parameter: Parameter.t + (** @since Nitrogen-20111001 *) val set: t -> unit (** Set the option. *) val add_set_hook: (t -> t -> unit) -> unit (** Add a hook to be called whenafter the function {!set} is called. - The first parameter of the hook is the old value of the parameter while - the second one is the new value. *) + The first parameter of the hook is the old value of the parameter while + the second one is the new value. *) + + val add_update_hook: (t -> t -> unit) -> unit + (** Add a hook to be called when the value of the parameter changes (by + calling {!set} or indirectly by the project library. The first parameter + of the hook is the old value of the parameter while the second one is the + new value. Note that it is **not** specified if the hook is applied just + before or just after the effective change. + @since Nitrogen-20111001 *) val get: unit -> t (** Option value (not necessarly set on the current command line). *) val clear: unit -> unit (** Set the option to its default value, that is the value if [set] was - never called. *) + never called. *) val is_default: unit -> bool (** Is the option equal to its default value? *) - val is_set: unit -> bool - (** Is the function {!set} has already been called since the last call to - function {!clear}? *) - val option_name: string (** Name of the option on the command-line - @since Carbon-20101202+dev *) + @since Carbon-20110201 *) include State_builder.S val equal: t -> t -> bool - (**/**) - val unsafe_set: t -> unit - (** Set but without clearing the dependencies.*) - (**/**) - val add_aliases: string list -> unit (** Add some aliases for this option. That is other option names which have exactly the same semantics that the initial option. @@ -87,13 +83,23 @@ val add_alias: string list -> unit (** Equivalent to [add_aliases]. - @deprecated since Carbon-20101202+dev *) + @deprecated since Carbon-20110201 *) + + (**/**) + val is_set: unit -> bool + (** Is the function {!set} has already been called since the last call to + function {!clear}? This function is for special uses and should mostly + never be used. *) + + val unsafe_set: t -> unit +(** Set but without clearing the dependencies.*) +(**/**) end (** Signature for a boolean parameter. @plugin development guide *) -module type BOOL = sig +module type Bool = sig include Parameter with type t = bool @@ -105,9 +111,25 @@ end +(** Signature for a boolean parameter that causes something to be output. + @plugin development guide *) +module type WithOutput = sig + include Bool + + val set_output_dependencies: State.t list -> unit + (** Set the dependecies for the output of the option. Two successive + calls to [output] below will cause only one output, unless some + of the supplied dependencies have changed between the two calls. *) + + val output: (unit -> unit) -> unit + (** To be used by the plugin to output the results of the option + in a controlled way. See [set_output_dependencies] details. *) +end + + (** Signature for an integer parameter. @plugin development guide *) -module type INT = sig +module type Int = sig include Parameter with type t = int @@ -116,33 +138,33 @@ val set_range: min:int -> max:int -> unit (** Set what is the possible range of values for this parameter. - @since Beryllium-20090901 *) + @since Beryllium-20090901 *) val get_range: unit -> int * int (** What is the possible range of values for this parameter. - @since Beryllium-20090901 *) + @since Beryllium-20090901 *) end (** Signature for a string parameter. @plugin development guide *) -module type STRING = sig +module type String = sig include Parameter with type t = string val set_possible_values: string list -> unit (** Set what are the acceptable values for this parameter. - If the given list is empty, then all values are acceptable. - @since Beryllium-20090901 *) + If the given list is empty, then all values are acceptable. + @since Beryllium-20090901 *) val get_possible_values: unit -> string list (** What are the acceptable values for this parameter. - If the returned list is empty, then all values are acceptable. - @since Beryllium-20090901 *) + If the returned list is empty, then all values are acceptable. + @since Beryllium-20090901 *) end (** Signature for a generic set of strings option. *) -module type GEN_STRING_SET = sig +module type String_collection = sig include Parameter @@ -157,7 +179,7 @@ val get_set: ?sep:string -> unit -> string (** Get a string which concatenates each string in the set with a - separator. The default separator is ", ". *) + separator. The default separator is ", ". *) val iter: (string -> unit) -> unit (** Iter on each string in the set. *) @@ -168,12 +190,12 @@ end -module type STRING_SET = GEN_STRING_SET with type t = Datatype.String.Set.t -module type STRING_LIST = GEN_STRING_SET with type t = string list +module type String_set = String_collection with type t = Datatype.String.Set.t +module type String_list = String_collection with type t = string list (** @since Boron-20100401 *) -module type STRING_HASHTBL = sig - include GEN_STRING_SET with type t = Datatype.String.Set.t +module type String_hashtbl = sig + include String_collection with type t = Datatype.String.Set.t type value (** @since Boron-20100401 *) val find: string -> value @@ -183,8 +205,8 @@ (** {3 Complex values indexed by strings} *) (** option interface *) -module type INDEXED_VAL = sig - include STRING +module type Indexed_val = sig + include String type value (** the real type for the option*) val add_choice: string -> value -> unit (** adds a new choice for the option. *) @@ -198,10 +220,8 @@ val option_name: string (** The name of the option *) val help: string - (** A description for this option (e.g. used by -help) *) - val kind: [> `Correctness | `Tuning | `Irrelevant ] -(** See {!State.kind} for a description of the possible values. - @since Carbon-20101201 *) +(** A description for this option (e.g. used by -help). + If [help = ""], then it has the special meaning "undocumented" *) end (** Minimal signature to implement for each parameter corresponding to an @@ -210,11 +230,11 @@ include Parameter_input val arg_name: string (** A standard name for the argument which may be used in the description. - If empty, a generic arg_name is generated. *) + If empty, a generic arg_name is generated. *) end (** input signature for [IndexedVal] *) -module type COMPLEX_VALUE = sig +module type Indexed_val_input = sig include Parameter_input_with_arg type t (** the type to be serialized *) val default_val: t (** the default value *) @@ -228,27 +248,39 @@ val add_group: ?memo:bool -> string -> group (** Create a new group inside the plug-in. - The given string must be different of all the other group names of this - plug-in if [memo] is [false]. + The given string must be different of all the other group names of this + plug-in if [memo] is [false]. If [memo] is [true] the function will either create a fresh group or return an existing group of the same name in the same plugin. [memo] defaults to [false] - @since Beryllium-20090901 *) + @since Beryllium-20090901 *) - module Help: BOOL - module Verbose: INT - module Debug: INT + module Help: Bool + module Verbose: Int + module Debug: Int val help: group (** The group containing option -*-help. - @since Boron-20100401 *) + @since Boron-20100401 *) val messages: group (** The group containing options -*-debug and -*-verbose. - @since Boron-20100401 *) + @since Boron-20100401 *) + + val parameters: unit -> Parameter.t list +(** List of parameters created by this plug-in. + @since Nitrogen-20111001 *) end +type plugin = private + { p_name: string; + p_help: string; + p_parameters: (string, Parameter.t list) Hashtbl.t } +(** Only iterable parameters (see {!do_iterate} and {!do_not_iterate}) are + registered in the field [p_parameters]. + @since Beryllium-20090901 *) + module type General_services = sig include S @@ -259,48 +291,59 @@ (X:sig include Parameter_input val default: bool - (** The default value of the parameter. So giving the option - [option_name] to Frama-C, change the value of the parameter to - [not default]. *) - end) : BOOL + (** The default value of the parameter. So giving the option + [option_name] to Frama-C, change the value of the parameter to + [not default]. *) + end) : Bool (** Build a boolean option initialized fo [false], that is not saved. *) - module Action(X: Parameter_input) : BOOL + module Action(X: Parameter_input) : Bool (** Build a boolean option initialized to [false]. @plugin development guide *) - module False(X: Parameter_input) : BOOL + module False(X: Parameter_input) : Bool (** Build a boolean option initialized to [true]. @plugin development guide *) - module True(X: Parameter_input) : BOOL + module True(X: Parameter_input) : Bool + + (** Build a boolean option initialized to [false]. The returned + [output] function must be used to display the results of this option. + The results will be displayed if [X.output_by_default] is [true], + or if option [-foo-print] is given by the user (where [foo] is + [X.option_name]). + @since Nitrogen-20111001 + @plugin development guide *) + module WithOutput + (X: sig include Parameter_input val output_by_default: bool end) : + WithOutput (** Build an integer option. @plugin development guide *) module Int - (X: sig val default: int include Parameter_input_with_arg end) : INT + (X: sig val default: int include Parameter_input_with_arg end) : Int (** Build an integer option initialized to [0]. @plugin development guide *) - module Zero(X:Parameter_input_with_arg) : INT + module Zero(X:Parameter_input_with_arg) : Int (** Build a string option. @plugin development guide *) module String - (X: sig include Parameter_input_with_arg val default: string end) : STRING + (X: sig include Parameter_input_with_arg val default: string end) : String (** Build a string option initialized to [""]. @plugin development guide *) - module EmptyString(X: Parameter_input_with_arg) : STRING + module EmptyString(X: Parameter_input_with_arg) : String (** Build an option as a set of strings, initialized to the empty set. *) - module StringSet(X: Parameter_input_with_arg) : STRING_SET + module StringSet(X: Parameter_input_with_arg) : String_set (** Should not be used by casual users *) - module StringList(X: Parameter_input_with_arg) : STRING_LIST + module StringList(X: Parameter_input_with_arg) : String_list (** @plugin development guide *) - module IndexedVal (V:COMPLEX_VALUE) : INDEXED_VAL with type value = V.t + module IndexedVal (V:Indexed_val_input) : Indexed_val with type value = V.t (** @since Boron-20100401 *) module StringHashtbl @@ -310,14 +353,16 @@ val parse: string -> string * t val no_binding: string -> t end) : - STRING_HASHTBL with type value = V.t + String_hashtbl with type value = V.t end +(* ************************************************************************* *) (** {2 Configuration of functor applications generating parameters} You can apply the below functions juste before applying one of the functors provided by the functor [Register] and generating a new parameter. *) +(* ************************************************************************* *) val set_cmdline_stage: Cmdline.stage -> unit (** Set the stage where the option corresponding to the parameter is @@ -325,22 +370,17 @@ @since Beryllium-20090601-beta1 *) val do_not_journalize: unit -> unit - (** Call this function in order to not journalize the parameter. - @since Beryllium-20090601-beta1 *) +(** Prevent journalization of the parameter. + @since Beryllium-20090601-beta1 *) val do_not_projectify: unit -> unit - (** Do not projectify the parameter. - @since Beryllium-20090601-beta1 *) +(** Prevent projectification of the parameter: its state is shared by all the + existing projects. Also imply {!do_not_save}. + @since Beryllium-20090601-beta1 *) val do_not_save: unit -> unit - (** Do not save the parameter. - @since Carbon-20101202+dev *) - -val register_kernel: unit -> unit - (** To be called just before {!Register} in order to activate a - special mode corresponding to registering some parts of the Frama-C - kernel and not a standard plug-in. - @since Beryllium-20090601-beta1 *) +(** Prevent serialization of the parameter. + @since Carbon-20110201 *) val set_negative_option_name: string -> unit (** For boolean parameters, set the name of the negative @@ -351,7 +391,7 @@ @since Beryllium-20090601-beta1 *) val set_negative_option_help: string -> unit - (** For boolean parameters, set the description of the negative +(** For boolean parameters, set the help message of the negative option generating automatically. Assume that the given string is non empty. @since Beryllium-20090601-beta1 *) @@ -361,27 +401,37 @@ @since Beryllium-20090601-beta1 *) val set_group: group -> unit - (** Change the group of the parameter. +(** Affect a group to the parameter. @since Beryllium-20090901 *) +val is_invisible: unit -> unit +(** Prevent the help to list the parameter. Also imply {!do_not_iterate}. + @since Carbon-20101201 + @modify Nitrogen-20111001 does not appear in the help *) + +val do_iterate: unit -> unit +(** Ensure that {!iter_on_plugins} is applied to this parameter. By default + only parameters corresponding to options registered at the + {!Cmdline.Configuring} stage are iterable. + @since Nitrogen-20111001 *) + +val do_not_iterate: unit -> unit +(** Prevent {!iter_on_plugins} to be applied on the parameter. By default, only + parameters corresponding to options registered at the + {!Cmdline.Configuring} stage are iterable. + @since Nitrogen-20111001 *) + +(**/**) + +val register_kernel: unit -> unit +(** Begin to register parameters of the kernel. Not for casual users. + @since Beryllium-20090601-beta1 *) + val set_module_name: string -> unit - (** This function must be called if and only if the next functor application - generates a new **kernel** parameter. So this function should not be used - by plug-in developer. The given argument must be the module name - corresponding to the parameter. *) - -val is_visible: unit -> unit - (** This function must be called in order to allow the parameter created - by the next functor application to be accessible through function - {!iter_on_plugins}. By default, only the parameter corresponding to an - option registered at the {!Cmdline.Configuring} stage are visible. - @since Boron-20100401 *) +(** For **kernel** parameters, set the name of the module name corresponding to + the parameter. Not for casual users. *) -val is_invisible: unit -> unit - (** This function must be called in order to forbid the parameter created by - the next function application to be accessible through function - {!iter_on_plugins}. - @since Carbon-20101201 *) +(**/**) (** Functors for generating plug-ins parameters. *) module Register @@ -392,29 +442,14 @@ end) : General_services +(* ************************************************************************* *) (** {2 Handling groups of parameters} *) +(* ************************************************************************* *) -type 'a option_accessor = private - { get: unit -> 'a; set: 'a -> unit; is_set: unit -> bool } - -type kind = private - | Bool of - bool option_accessor * string option (** the negative option, if any *) - | Int of int option_accessor * (unit -> int * int) (** getting range *) - | String of - string option_accessor * (unit -> string list) (** possible values *) - | StringSet of string option_accessor (** Comma separated string list *) - -type parameter = private { o_name: string; o_help: string; o_kind: kind } - (** @since Beryllium-20090901 *) - -type plugin = private - { p_name: string; - p_help: string; - p_parameters: (string, parameter list) Hashtbl.t } - (** Only visible parameters (see {!is_visible}) are registered in the field - [p_parameters]. - @since Beryllium-20090901 *) +val get: string -> plugin +(** Get a plug-in from its shortname. + Not very efficient yet. + @since Nitrogen-20111001 *) val iter_on_plugins: (plugin -> unit) -> unit (** Iterate on each registered plug-ins. @@ -424,20 +459,27 @@ (** Selection of all the settable parameters. @plugin development guide *) +val get_selection_context: unit -> State_selection.t +(** Selection of all the parameters which may have an impact on some + analysis. *) + val positive_debug_ref: int ref (** Not for casual users. @since Boron-20100401 *) -(* -val dynamic_plugin_name: string -> string - (** Not for casual users. - @since Boron-20100401 *) -val dynamic_function_name: string -> string -> string - (** Not for casual users. - @since Boron-20100401 *) - *) +(* ************************************************************************* *) +(** {2 Deprecated API} *) +(* ************************************************************************* *) -val dynamic_name: string -> string -> string -> string +val at_normal_exit: (unit -> unit) -> unit + (** Now replaced by {!Cmdline.at_normal_exit}. + @since Beryllium-20090901 + @deprecated since Boron-20100401 *) + +val run_normal_exit_hook: unit -> unit + (** Now replaced by {!Cmdline.run_normal_exit_hook}. + @since Beryllium-20090901 + @deprecated since Boron-20100401 *) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/printer.ml frama-c-20111001+nitrogen+dfsg/src/kernel/printer.ml --- frama-c-20110201+carbon+dfsg/src/kernel/printer.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/printer.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,7 +22,6 @@ open Cil_types open Cil -open Db_types open Extlib open Pretty_utils @@ -142,40 +141,55 @@ super#pVDecl fmt vi method pGlobal fmt glob = + if Kernel.PrintComments.get () then begin + let comments = Globals.get_comments_global glob in + Pretty_utils.pp_list + ~sep:"@\n" ~suf:"@\n" + (fun fmt s -> Format.fprintf fmt "/* %s */" s) fmt comments + end; + (* Out of tree global annotations are pretty printed before the first + variable declaration of the first function definition. *) (match glob with | GVarDecl _ when first_function_definition -> first_function_definition <- false; self#pretty_global_annot fmt - | GFun _ -> is_fun_def <- true + | GFun _ -> + if first_function_definition then + begin + first_function_definition <- false; + self#pretty_global_annot fmt + end; + is_fun_def <- true | _ -> ()); super#pGlobal fmt glob (* TODO: make it a public method, with a new class type specific to Frama-C*) method private pInsertedAnnotation fmt ca = - match Ast_info.before_after_content ca with + match ca with | User ca -> - Format.fprintf fmt "%a" self#pCode_annot ca + Format.fprintf fmt "%a" self#pCode_annot ca | AI(_,ca) -> - Format.fprintf fmt "%a@\n // synthesized@\n" self#pCode_annot ca + Format.fprintf fmt "%a@\n // synthesized@\n" self#pCode_annot ca method private pLoopAnnotations fmt annots = if annots <> [] then begin let annots = List.sort compare_annotations annots in - Pretty_utils.pp_open_block fmt "/*@@ " ; + Pretty_utils.pp_open_block fmt "/*@@ " ; Pretty_utils.pp_list ~sep:Pretty_utils.nl_sep - self#pInsertedAnnotation + self#pInsertedAnnotation fmt annots ; - Pretty_utils.pp_close_block fmt "*/@\n" ; + Pretty_utils.pp_close_block fmt "*/@\n" ; end method private pAnnotations fmt annots = + let annots = List.sort compare_annotations annots in Pretty_utils.pp_list ~pre:Pretty_utils.no_sep ~sep:Pretty_utils.no_sep ~suf:Pretty_utils.no_sep (fun fmt annot -> - Pretty_utils.pp_open_block fmt "/*@@ " ; + Pretty_utils.pp_open_block fmt "/*@@ " ; self#pInsertedAnnotation fmt annot; Pretty_utils.pp_close_block fmt "*/@\n") fmt @@ -191,48 +205,38 @@ (* print the Cabscond, if any *) Cabscond.pp_comment fmt s ; - + if Kernel.PrintComments.get () then begin + let comments = Globals.get_comments_stmt s in + Pretty_utils.pp_list + ~sep:"@\n" ~suf:"@\n" (fun fmt s -> Format.fprintf fmt "/* %s */" s) + fmt comments + end; if verbose then Format.fprintf fmt "/*sid:%d*/@ " s.sid ; (* print the annotations *) let all_annot = List.sort - Kernel_datatype.Rooted_code_annotation_before_after.compare - (Annotations.get_all_annotations s) + Cil_datatype.Rooted_code_annotation.compare + (Annotations.get_all_annotations s) in match all_annot with | [] -> self#pStmtKind next fmt s.skind | [ a ] when is_skip s.skind -> - Format.fprintf fmt "@[/*@@@ %a */@] %a" - (self#pInsertedAnnotation) a - (self#pStmtKind next) s.skind ; + Format.fprintf fmt "@[/*@@@ %a */@] %a" + (self#pInsertedAnnotation) a + (self#pStmtKind next) s.skind ; | _ -> - let loop_annot, stmt_annot = - List.partition - (Ast_info.lift_annot_func Logic_utils.is_loop_annot) - all_annot - in - let annot_before,annot_after = - List.partition - (function Before _ -> true | After _ -> false) - stmt_annot - in - let loop_annot_before, loop_annot_after = - List.partition - (function Before _ -> true | After _ -> false) - loop_annot - in - begin - let s_block = annot_after <> [] || loop_annot_after <> [] in - if s_block then Pretty_utils.pp_open_block fmt "{" ; - self#pAnnotations fmt annot_before ; - self#pLoopAnnotations fmt loop_annot_before ; - if s.ghost then Pretty_utils.pp_open_block fmt "/*@@ ghost " ; - self#pStmtKind next fmt s.skind; - if s.ghost then Pretty_utils.pp_close_block fmt "@ */@\n" ; - self#pLoopAnnotations fmt loop_annot_after ; - self#pAnnotations fmt annot_after ; - if s_block then Pretty_utils.pp_close_block fmt "}" ; - end + let loop_annot, stmt_annot = + List.partition + (Ast_info.lift_annot_func Logic_utils.is_loop_annot) + all_annot + in + begin + self#pAnnotations fmt stmt_annot ; + self#pLoopAnnotations fmt loop_annot ; + if s.ghost then Pretty_utils.pp_open_block fmt "/*@@ ghost " ; + self#pStmtKind next fmt s.skind; + if s.ghost then Pretty_utils.pp_close_block fmt "@ */@\n" ; + end method requireBraces blk = match blk.blocals with @@ -241,21 +245,12 @@ match blk.bstmts with | [ _ ] | [] when blk.battrs = [] && blk.blocals = [] -> false | _ -> - match self#current_stmt with - | None -> false - | Some stmt -> Annotations.get_all stmt <> [] + match self#current_stmt with + | None -> false + | Some stmt -> Annotations.get_all stmt <> [] end | _ -> true - - (** Get the comment out of a location if there is one *) - method pLineDirective ?(forcefile=false) fmt l = - super#pLineDirective ~forcefile fmt l; - if Parameters.PrintComments.get () then - List.iter - (fun c -> Format.fprintf fmt "/* %s@ */@\n" c) - (Zrapp.get_comments l) - initializer logic_printer_enabled <- false; verbose <- Kernel.debug_atleast 1 diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/special_hooks.ml frama-c-20111001+nitrogen+dfsg/src/kernel/special_hooks.ml --- frama-c-20110201+carbon+dfsg/src/kernel/special_hooks.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/special_hooks.ml 2011-10-10 08:38:09.000000000 +0000 @@ -21,47 +21,44 @@ (**************************************************************************) let version () = - if Parameters.PrintVersion.get () then begin - Log.print_on_output "Version: %s@\n\ + if Kernel.PrintVersion.get () then begin + Log.print_on_output + (fun fmt -> Format.fprintf fmt "Version: %s@\n\ Compilation date: %s@\n\ Share path: %s (may be overridden with FRAMAC_SHARE variable)@\n\ Library path: %s (may be overridden with FRAMAC_LIB variable)@\n\ Plug-in paths: %t(may be overridden with FRAMAC_PLUGIN variable)@." - Config.version Config.date Config.datadir Config.libdir - (fun fmt -> List.iter (fun s -> Format.fprintf fmt "%s " s) - (Dynamic.default_path ())); + Config.version Config.date Config.datadir Config.libdir + (fun fmt -> List.iter + (fun s -> Format.fprintf fmt "%s " s) + (Dynamic.default_path ())) + ); raise Cmdline.Exit end let () = Cmdline.run_after_early_stage version -let print_sharepath () = - if Parameters.PrintShare.get () then begin - Log.print_on_output "%s%!" Config.datadir; +let print_path get dir () = + if get () then begin + Log.print_on_output (fun fmt -> Format.fprintf fmt "%s%!" dir) ; raise Cmdline.Exit end + +let print_sharepath = print_path Kernel.PrintShare.get Config.datadir let () = Cmdline.run_after_early_stage print_sharepath -let print_libpath () = - if Parameters.PrintLib.get () then begin - Log.print_on_output "%s%!" Config.libdir; - raise Cmdline.Exit - end +let print_libpath = print_path Kernel.PrintLib.get Config.libdir let () = Cmdline.run_after_early_stage print_libpath -let print_pluginpath () = - if Parameters.PrintPluginPath.get () then begin - Log.print_on_output "%s%!" Config.plugin_dir; - raise Cmdline.Exit - end +let print_pluginpath = print_path Kernel.PrintPluginPath.get Config.plugin_dir let () = Cmdline.run_after_early_stage print_pluginpath (* Time *) let time () = - let filename = Parameters.Time.get () in + let filename = Kernel.Time.get () in if filename <> "" then let oc = open_out_gen - [ Open_append; Open_creat; Open_binary] 0b111100100 filename + [ Open_append; Open_creat; Open_binary] 0b111100100 filename in let {Unix.tms_utime = time } = Unix.times () in let now = Unix.localtime (Unix.time ()) in @@ -79,9 +76,9 @@ (* Save Frama-c on disk if required *) let save_binary () = - let filename = Parameters.SaveState.get () in + let filename = Kernel.SaveState.get () in if filename <> "" then begin - Parameters.SaveState.clear (); + Kernel.SaveState.clear (); try Project.save_all filename with Project.IOError s -> Kernel.error "problem while saving to file %s (%s)." filename s @@ -90,7 +87,7 @@ (* Load Frama-c from disk if required *) let load_binary () = - let filename = Parameters.LoadState.get () in + let filename = Kernel.LoadState.get () in if filename <> "" then begin try Project.load_all filename @@ -101,7 +98,7 @@ let () = Cmdline.at_normal_exit - (fun _ -> match Parameters.Files.get () with + (fun _ -> match Kernel.Files.get () with | [] -> () | _ :: _ -> Ast.compute ()) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/special_hooks.mli frama-c-20111001+nitrogen+dfsg/src/kernel/special_hooks.mli --- frama-c-20110201+carbon+dfsg/src/kernel/special_hooks.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/special_hooks.mli 2011-10-10 08:38:09.000000000 +0000 @@ -20,7 +20,7 @@ (* *) (**************************************************************************) -(** Nothing is export: just register some special hooks for Frama-C. +(** Nothing is export: just register some special hooks for Frama-C. @since Beryllium-20090601-beta1 *) (* diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/stmts_graph.ml frama-c-20111001+nitrogen+dfsg/src/kernel/stmts_graph.ml --- frama-c-20110201+carbon+dfsg/src/kernel/stmts_graph.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/stmts_graph.ml 2011-10-10 08:38:09.000000000 +0000 @@ -20,20 +20,79 @@ (* *) (**************************************************************************) -(* $Id: stmts_graph.ml,v 1.23 2008-10-13 12:56:47 uid530 Exp $ *) - open Cil_types open Cil -open Db_types -open Cilutil +open Cil_datatype -module SG = Graph.Imperative.Digraph.Concrete(Cil_datatype.Stmt) +(* This is a reimplementation of ocamlgraph Path.Check. Instead of using + an hashtbl containing couples of stmts, we use an association map + to hptmap from stmts to bool. This enforces a lot of sharing, which + is very useful when stmt_can_reach is called on a lot of pairs *) +module PathChecker = +struct + + module HV = Hashtbl.Make(Stmt) + module HptmapStmtBool = Hptmap.Make + (struct include Stmt let id s = s.sid end) + (struct include Datatype.Bool let tag b = if b then 1 else 0 end) + (Hptmap.Comp_unused) + (struct let v = [ [] ] end) + (struct let l = [ Ast.self ] end) + module HashStmtHptmapStmtBool = Stmt.Hashtbl.Make(HptmapStmtBool) + + (* this a cache containing the path tests already computed *) + type path_checker = HptmapStmtBool.t Stmt.Hashtbl.t + + let create () = Stmt.Hashtbl.create 17 + + let find_assoc_with_default pc v = + try Stmt.Hashtbl.find pc v with Not_found -> HptmapStmtBool.empty + + let add_to_cache pc v1 v2 b = + let assoc = find_assoc_with_default pc v1 in + let assoc' = HptmapStmtBool.add v2 b assoc in + Stmt.Hashtbl.replace pc v1 assoc' + + let check_path pc v1 v2 = + let assoc = find_assoc_with_default pc v1 in + try HptmapStmtBool.find v2 assoc + with Not_found -> + (* the path is not in cache; we check it with Dijkstra *) + let visited = HV.create 97 in + let q = Queue.create () in + let rec loop () = + if Queue.is_empty q then begin + add_to_cache pc v1 v2 false; + false + end else begin + let v = Queue.pop q in + add_to_cache pc v1 v true; + if Stmt.equal v v2 then + true + else begin + if not (HV.mem visited v) then begin + HV.add visited v (); + List.iter (fun v' -> Queue.add v' q) v.succs + end; + loop () + end + end + in + Queue.add v1 q; + loop () -module PathChecker = Graph.Path.Check(SG) +end -(* For transitive closure -module Classic = Graph.Oper.I(StmtsGraph) -*) +(* The kf is no longer useful, but we need to do a partial application anyway *) +let stmt_can_reach _kf = + let cache = PathChecker.create () in + let check = PathChecker.check_path cache in + fun s1 s2 -> + (*Kernel.debug ~level:4 "CHECK PATH %d->%d@\n" s1.sid s2.sid;*) + check s1 s2 + + +module SG = Graph.Imperative.Digraph.Concrete(Stmt) module TP = struct include SG @@ -51,13 +110,15 @@ | Goto _ -> Format.sprintf "%s <%d>\n" (pretty_raw_stmt s) s.sid | Break _ -> Format.sprintf "BREAK <%d>" s.sid | Continue _ -> Format.sprintf "CONTINUE <%d>" s.sid - | If(e,_,_,_) -> Pretty_utils.sfprintf "IF <%d>\n%a" s.sid !Ast_printer.d_exp e + | If(e,_,_,_) -> + Pretty_utils.sfprintf "IF <%d>\n%a" s.sid !Ast_printer.d_exp e | Switch _ -> Format.sprintf "SWITCH <%d>" s.sid | Loop _ -> Format.sprintf "WHILE(1) <%d>" s.sid | Block _ -> Format.sprintf "BLOCK <%d>" s.sid | TryExcept _ -> Format.sprintf "TRY EXCEPT <%d>" s.sid | TryFinally _ -> Format.sprintf "TRY FINALLY <%d>" s.sid - | UnspecifiedSequence _ -> Format.sprintf "UnspecifiedSequence <%d>" s.sid) + | UnspecifiedSequence _ -> + Format.sprintf "UnspecifiedSequence <%d>" s.sid) let vertex_attributes s = match s.skind with @@ -77,7 +138,7 @@ module GPrint = Graph.Graphviz.Dot(TP) -class stmt_graph_builder nb_stmt = object +class stmt_graph_builder = object inherit nopCilVisitor val graph = SG.create () method result = graph @@ -89,17 +150,16 @@ end let compute_stmtgraph_func func = - let nb_stmt = List.length func.sallstmts in - let o = new stmt_graph_builder nb_stmt in + let o = new stmt_graph_builder in ignore (visitCilFunction (o:>cilVisitor) func); if Kernel.debug_atleast 1 then begin Kernel.debug - "Function %a: Nb vertex: %d Nb edges:%d See file '%s_cfg.dot'.@\n" - !Ast_printer.d_ident func.svar.vname - (SG.nb_edges o#result) - (SG.nb_vertex o#result) - func.svar.vname; + "Function %a: Nb vertex: %d Nb edges:%d See file '%s_cfg.dot'.@\n" + !Ast_printer.d_ident func.svar.vname + (SG.nb_edges o#result) + (SG.nb_vertex o#result) + func.svar.vname; let oc = open_out (func.svar.vname^"_cfg.dot") in GPrint.output_graph oc o#result; close_out oc; @@ -107,34 +167,35 @@ (* Classic.add_transitive_closure ~reflexive:true o#result*) o#result -let compute_stmtgraph kf = - match kf.fundec with - | Definition (f,_) -> - (match kf.stmts_graph with - | None -> - let g = compute_stmtgraph_func f in - kf.stmts_graph <- Some g - | Some _ -> ()) - | Declaration _ -> () - -let check_path g = - let internal = PathChecker.create g in - PathChecker.check_path internal - -let get_graph kf = match kf.stmts_graph with - | None -> - compute_stmtgraph kf; - (match kf.stmts_graph with None -> assert false | Some f -> f); - | Some f -> - f - -let stmt_can_reach kf s1 s2 = - Kernel.debug ~level:4 "CHECK PATH %d->%d@\n" s1.sid s2.sid; - check_path (get_graph kf) s1 s2 +module StmtsGraphTbl= + State_builder.Hashtbl + (Kernel_function.Hashtbl) + (Datatype.Make + (struct + include Datatype.Serializable_undefined + type t = SG.t + let name = "Stmts_Graph.SG.t" + let reprs = [ SG.create () ] + let mem_project = Datatype.never_any_project + end)) + (struct + let name = "StmtsGraphTbl" + let kind = `Internal + let size = 17 + let dependencies = [ Ast.self ] + end) + +let get_graph kf = + StmtsGraphTbl.memo + (fun kf -> match kf.fundec with + | Definition (f,_) -> + compute_stmtgraph_func f + | Declaration _ -> assert false) + kf module Reachable_Stmts = Cil_state_builder.Stmt_hashtbl - (Cil_datatype.Stmt) + (Stmt) (struct let name = "reachable_stmts" let size = 97 @@ -149,12 +210,207 @@ Reachable_Stmts.find_all s else begin SG.iter_succ - (fun s' -> - Reachable_Stmts.add s s'; - List.iter (Reachable_Stmts.add s) (apply s')) - g - s; + (fun s' -> + Reachable_Stmts.add s s'; + List.iter (Reachable_Stmts.add s) (apply s')) + g + s; Reachable_Stmts.find_all s end in apply s + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) +(** Store for each statement, the set of the statements it is composed of. + For a simple statement (not containing blocks), it is only the statement + itself. *) +module StmtStmts = + Cil_state_builder.Stmt_hashtbl + (Stmt.Set) + (struct + let name = "StmtStmts" + let size = 142 + let dependencies = [ Ast.self ] + let kind = `Internal + end) + +let rec get_block_stmts blk = + let add stmts s = Stmt.Set.union (get_stmt_stmts s) stmts in + List.fold_left add Stmt.Set.empty blk.bstmts + +and get_stmt_stmts s = + let compute_stmt_stmts s = match s.skind with + | Instr _ | Return _ -> Stmt.Set.singleton s + | Continue _ | Break _ | Goto _ -> Stmt.Set.singleton s + | Block b | Switch (_, b, _, _) | Loop (_, b, _, _, _) -> + Stmt.Set.add s (get_block_stmts b) + | UnspecifiedSequence seq -> + let b = Cil.block_from_unspecified_sequence seq in + Stmt.Set.add s (get_block_stmts b) + | If (_, b1, b2, _) -> + let stmts = + Stmt.Set.union (get_block_stmts b1)(get_block_stmts b2) + in Stmt.Set.add s stmts + | TryExcept (_, _, _, _) | TryFinally (_, _, _) -> + Extlib.not_yet_implemented "exception handling" + in + StmtStmts.memo compute_stmt_stmts s + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) + +module EdgeDatatype = Datatype.Pair (Stmt)(Stmt) +module EdgesDatatype = Datatype.List (EdgeDatatype) + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) +(** Store for each statement [s], the elements in its statements that + are ways out of [s], split by termination kind : + [Normal | Breaks | Continues | Returns + Goto] + Notice that [Exits] is not here since it cannot be determined directly : + every call possibly have an [Exits] termination. *) + +type waysout = { normal : EdgesDatatype.t ; + breaks : EdgesDatatype.t ; + continues : EdgesDatatype.t ; + returns : EdgesDatatype.t ; + gotos : EdgesDatatype.t ; +} +let empty_waysout = { normal = []; breaks = []; continues = []; + returns = []; gotos = [] } + +module WaysOutDatatype = + Datatype.Make + (struct + include Datatype.Undefined (* TODO: unmarshal ? *) + type t = waysout + let reprs = [ empty_waysout ] + let name = "WaysOut" + let mem_project = Datatype.never_any_project + end) + +module StmtWaysOut = + Cil_state_builder.Stmt_hashtbl (WaysOutDatatype) + (struct + let name = "StmtWaysOut" + let size = 142 + let dependencies = [ StmtStmts.self ] + let kind = `Internal + end) + +let compute_stmts_out_edges stmts = + let do_s s waysout = + (* if [s] has a successor [s'] which is not in [stmt] statements, + * add [s,s'] *) + let add s acc = + let do_succ acc s' = + if Stmt.Set.mem s' stmts then acc + else (s, s')::acc + in List.fold_left do_succ acc s.succs + in match s.skind with + | Continue _ -> { waysout with continues = add s waysout.continues } + | Break _ -> { waysout with breaks = add s waysout.breaks } + | Return _ -> { waysout with returns = add s waysout.returns } + | Goto _ -> + begin + match s.succs with + | { skind = Return _ }::[] -> + { waysout with returns = add s waysout.returns } + | _ -> { waysout with gotos = add s waysout.gotos } + end + | _ -> { waysout with normal = add s waysout.normal } + in + Stmt.Set.fold do_s stmts empty_waysout + +let merge_waysout waysout = + waysout.normal @ waysout.breaks @ waysout.continues @ + waysout.returns @ waysout.gotos + +let select_waysout termination_kind waysout = + match termination_kind with + | Some Normal -> waysout.normal + | Some Breaks -> waysout.breaks + | Some Continues -> waysout.continues + | Some Returns -> waysout.returns + | None (* Goto *) -> waysout.gotos + | Some Exits -> + invalid_arg "[get_stmt_out_edges] doesn't handle [Exits] termination_kind" + +let compute_stmt_out_edges stmt = + compute_stmts_out_edges (get_stmt_stmts stmt) + +let get_stmt_out_edges termination_kind stmt = + let waysout = StmtWaysOut.memo compute_stmt_out_edges stmt in + select_waysout termination_kind waysout + +let get_all_stmt_out_edges s = + let waysout = StmtWaysOut.memo compute_stmt_out_edges s in + merge_waysout waysout + +let compute_block_out_edges blk = + compute_stmts_out_edges (get_block_stmts blk) + +let get_all_block_out_edges blk = + let waysout = compute_block_out_edges blk in + merge_waysout waysout + +let get_block_out_edges termination_kind blk = + let waysout = compute_block_out_edges blk in + select_waysout termination_kind waysout + +let get_all_stmt_last_stmts s = + List.map fst (get_all_stmt_out_edges s) + +let get_all_block_last_stmts b = + List.map fst (get_all_block_out_edges b) + +let get_stmt_last_stmts tk s = + List.map fst (get_stmt_out_edges tk s) + +let get_block_last_stmts tk b = + List.map fst (get_block_out_edges tk b) + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) +module StmtWaysIn = + Cil_state_builder.Stmt_hashtbl + (Datatype.List (EdgeDatatype)) + (struct + let name = "StmtWaysIn" + let size = 142 + let dependencies = [ StmtStmts.self ] + let kind = `Internal + end) + +let compute_stmts_in_edges stmts = + let add s acc = + let do_pred acc s' = + if (Stmt.Set.mem s' stmts) then acc else (s',s)::acc + in List.fold_left do_pred acc s.preds + in Stmt.Set.fold add stmts [] + +let compute_stmt_entry_stmts stmt = + compute_stmts_in_edges (get_stmt_stmts stmt) + +let get_stmt_in_edges s = + StmtWaysIn.memo compute_stmt_entry_stmts s + +let get_block_in_edges blk = + compute_stmts_in_edges (get_block_stmts blk) + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) + +let loop_preds s = match s.skind with + | Loop _ -> + let loop_stmts = get_stmt_stmts s in + let back_edges, entry = + List.partition (fun s -> Stmt.Set.mem s loop_stmts) s.preds + in + entry, back_edges + | _ -> + invalid_arg "[loop_preds] not a loop" + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/stmts_graph.mli frama-c-20111001+nitrogen+dfsg/src/kernel/stmts_graph.mli --- frama-c-20110201+carbon+dfsg/src/kernel/stmts_graph.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/stmts_graph.mli 2011-10-10 08:38:09.000000000 +0000 @@ -20,16 +20,63 @@ (* *) (**************************************************************************) -(* $Id: stmts_graph.mli,v 1.11 2008-11-18 12:13:41 uid568 Exp $ *) - -(** Statements graph. +(** Statements graph. @plugin development guide *) -open Db_types open Cil_types +open Cil_datatype val stmt_can_reach: kernel_function -> stmt -> stmt -> bool (** [stmt_can_reach kf s1 s2] is [true] iff the control flow can reach [s2] starting at [s1] in function [kf]. *) val reachable_stmts: kernel_function -> stmt -> stmt list + +(** Get the statements that compose [s]. For a simple statement (not containing + blocks), it is only the statement itself. *) +val get_stmt_stmts : stmt -> Stmt.Set.t +val get_block_stmts : block -> Stmt.Set.t + +(** Find the last statements in [s], meaning that if [s'] is in the returned + statements, [s'] is in [s] statements, but a least one of its successor is + not. *) +val get_all_stmt_last_stmts : stmt -> stmt list +val get_all_block_last_stmts : block -> stmt list + +(** Subset of [get_all_stmt_last_stmts] according to [termination_kind]. + [termination_kind = None] means [Goto]. + @raise Invalid_argument for [termination_kind = Some Exits] since + every call possibly have an [Exits] termination: it should be handled + differently. *) +val get_stmt_last_stmts : termination_kind option -> stmt -> stmt list +val get_block_last_stmts : termination_kind option -> block -> stmt list + +(** Find the entry edges that go inside [s] statements, +* meaning that if the pair [(s1,s2)] is in the returned information, +* [s2] is a successor of [s1] and [s2] is in [s] statements, but [s1] is not. +* @since Nitrogen-20111001 +**) +val get_stmt_in_edges : stmt -> (stmt * stmt) list +val get_block_in_edges : block -> (stmt * stmt) list + +(** Like [get_stmt_in_edges] but for edges going out of [s] statements. +* Similar to [get_all_stmt_last_stmts] but gives the edge information +* instead of just the first statement. +* @since Nitrogen-20111001 +*) +val get_all_stmt_out_edges : stmt -> (stmt * stmt) list +val get_all_block_out_edges : block -> (stmt * stmt) list + +(** Split the loop predecessors into: + - the entry point : coming for outside the loop + - the back edges. + Notice that there might be nothing in the entry point when the loop if the + first statement. + @raise Invalid_argument if the statement is not a loop. *) +val loop_preds : stmt -> stmt list * stmt list + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/task.ml frama-c-20111001+nitrogen+dfsg/src/kernel/task.ml --- frama-c-20110201+carbon+dfsg/src/kernel/task.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/task.ml 2011-10-10 08:38:09.000000000 +0000 @@ -44,10 +44,10 @@ end = struct - type 'a process = + type 'a process = | Ping of (unit -> 'a running) - | Done of 'a status * 'a running - (* Invariant : Done(x,y) => y==Finished x *) + | Done of 'a status * 'a running + (* Invariant : Done(x,y) => y==Finished x *) type 'a t = 'a process ref @@ -58,19 +58,19 @@ let ping task = match !task with | Done(_,run) -> run - | Ping p -> - let run = try p () with e -> Finished(Failed e) in - match run with - | Finished r -> task := Done(r,run) ; run - | Running _ -> run + | Ping p -> + let run = try p () with e -> Finished(Failed e) in + match run with + | Finished r -> task := Done(r,run) ; run + | Running _ -> run let cancel t = match ping t with - | Running kill -> - begin - try kill () ; t := finished Canceled - with e -> t := finished (Failed e) - end + | Running kill -> + begin + try kill () ; t := finished Canceled + with e -> t := finished (Failed e) + end | Finished _ -> () type ('a,'b) seq = @@ -80,15 +80,15 @@ let bind t k = let pinger step () = match !step with - | Last t -> ping t - | Seq(t,k) -> - match ping t with - | Running kill -> Running kill (* 'a conversion *) - | Finished r -> - let t' = try k r with e -> result (Failed e) in - if r <> Canceled - then ( step := Last t' ; ping t' ) - else ( cancel t' ; Finished Canceled ) + | Last t -> ping t + | Seq(t,k) -> + match ping t with + | Running kill -> Running kill (* 'a conversion *) + | Finished r -> + let t' = try k r with e -> result (Failed e) in + if r <> Canceled + then ( step := Last t' ; ping t' ) + else ( cancel t' ; Finished Canceled ) in async (pinger (ref (Seq(t,k)))) end @@ -112,11 +112,11 @@ (Format.formatter_of_buffer buffer) text let bind = Monad.bind -let sequence t f = +let sequence t f = bind t (function - | Result r -> f r - | Failed e -> raised e - | Canceled -> canceled ()) + | Result r -> f r + | Failed e -> raised e + | Canceled -> canceled ()) let wait = Running (fun () -> ()) let stop = Finished(Result()) @@ -124,7 +124,7 @@ let todo job = sequence nop job let call f x = Monad.async (fun () -> Finished(Result(f x))) -let finally t cb = +let finally t cb = let kill k cb () = try k () ; cb Canceled with e -> cb (Failed e) @@ -135,7 +135,7 @@ | Running k -> Running (kill k cb) in Monad.async (pinger t) -let callback t cb = +let callback t cb = let kill k cb () = try k () ; cb Canceled with e -> cb (Failed e) @@ -172,8 +172,8 @@ let cancel = Monad.cancel let rec wait task = - let run = - try !Db.progress () ; Monad.ping task + let run = + try !Db.progress () ; Monad.ping task with Db.Cancel -> Finished Canceled in match run with @@ -187,33 +187,33 @@ let debug = true let command ?(timeout=0) ?stdout ?stderr cmd args = - let hang_on = - if timeout > 0 - then Unix.time () +. float_of_int timeout + let hang_on = + if timeout > 0 + then Unix.time () +. float_of_int timeout else 0.0 in Kernel.debug "exec '@[%t'@]" (fun fmt -> Format.pp_print_string fmt cmd ; Array.iter - (fun c -> Format.fprintf fmt "@ %s" c) args) ; + (fun c -> Format.fprintf fmt "@ %s" c) args) ; let async = Command.command_async ?stdout ?stderr cmd args in let pinger () = try match async () with - | Command.Not_ready kill -> - if timeout > 0 && Unix.time () > hang_on then - begin - Kernel.debug "timeout '%s'" cmd ; - kill () ; Finished Canceled - end - else Running kill - | Command.Result (Unix.WEXITED s) -> - Kernel.debug "exit '%s' [%d]" cmd s ; - Finished (Result s) - | Command.Result (Unix.WSIGNALED s|Unix.WSTOPPED s) -> - Kernel.debug "signal '%s' [%d]" cmd s ; - Finished Canceled - with e -> + | Command.Not_ready kill -> + if timeout > 0 && Unix.time () > hang_on then + begin + Kernel.debug "timeout '%s'" cmd ; + kill () ; Finished Canceled + end + else Running kill + | Command.Result (Unix.WEXITED s) -> + Kernel.debug "exit '%s' [%d]" cmd s ; + Finished (Result s) + | Command.Result (Unix.WSIGNALED s|Unix.WSTOPPED s) -> + Kernel.debug "signal '%s' [%d]" cmd s ; + Finished Canceled + with e -> Kernel.debug "failure '%s' [%s]" cmd (Printexc.to_string e) ; Finished (Failed e) in Monad.async pinger @@ -224,8 +224,16 @@ type callbacks = (unit -> unit) list +(* Invariant: + + terminated + (length running) + Sum ( length queue.(i) ) == scheduled + +*) + type server = { queue : unit task Queue.t array ; + mutable scheduled : int ; + mutable terminated : int ; mutable running : unit task list ; mutable procs : int ; mutable activity : callbacks ; @@ -233,18 +241,19 @@ mutable stop : callbacks ; } -let fire callbacks = +let fire callbacks = List.iter (fun f -> try f () with _ -> ()) callbacks let server ?(stages=1) ?(procs=4) () = { queue = Array.init stages (fun _ -> Queue.create ()) ; running = [] ; procs = procs ; + scheduled = 0 ; terminated = 0 ; activity = [] ; start = [] ; stop = [] ; } -let on_idle = ref - (fun f -> try +let on_idle = ref + (fun f -> try while f () do Extlib.usleep 50000 (* wait for 50ms *) done with Db.Cancel -> ()) @@ -253,11 +262,6 @@ let on_server_start s cb = s.start <- s.start @ [cb] let on_server_stop s cb = s.stop <- s.stop @ [cb] -let load s = - Array.fold_left - (fun w q -> w + Queue.length q) - (List.length s.running) s.queue - let cancel_all server = begin Array.iter (Queue.iter cancel) server.queue ; @@ -265,8 +269,14 @@ end let spawn server ?(stage=0) task = - Queue.push task server.queue.(stage) - + begin + Queue.push task server.queue.(stage) ; (* queue(i) ++ *) + server.scheduled <- succ server.scheduled ; (* scheduled ++ *) + end (* invariant holds *) + +let scheduled s = s.scheduled +let terminated s = s.terminated + let alive task = match Monad.ping task with | Running _ -> true @@ -275,27 +285,40 @@ let schedule server q = try while List.length server.running < server.procs do - let task = Queue.take q in - if alive task then server.running <- task :: server.running + let task = Queue.take q in (* queue ++ *) + if alive task + then server.running <- task :: server.running + (* running++ => invariant holds *) + else server.terminated <- succ server.terminated + (* terminated++ => invariant holds *) done with Queue.Empty -> () let rec run server () = begin - server.running <- List.filter alive server.running ; + server.running <- List.filter + (fun task -> + if alive task then true + else + ( (* running -- ; terminated ++ => invariant preserved *) + server.terminated <- succ server.terminated ; false ) + ) server.running ; Array.iter (schedule server) server.queue ; - try - !Db.progress () ; + try + !Db.progress () ; fire server.activity ; - let continue = server.running <> [] in - if not continue then fire server.stop ; - continue + if server.running <> [] then true else + begin + fire server.stop ; + server.scheduled <- 0 ; + server.terminated <- 0 ; + false + end with _ -> (* Db.Cancel ... *) cancel_all server ; run server () end let launch server = - if server.running = [] && load server > 0 + if server.scheduled > server.terminated then ( fire server.start ; !on_idle (run server) ) - diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/task.mli frama-c-20111001+nitrogen+dfsg/src/kernel/task.mli --- frama-c-20110201+carbon+dfsg/src/kernel/task.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/task.mli 2011-10-10 08:38:09.000000000 +0000 @@ -21,9 +21,9 @@ (**************************************************************************) (* ------------------------------------------------------------------------ *) -(** - * High Level Interface to Command. - * @since Carbon-20101201 +(** + * High Level Interface to Command. + * @since Carbon-20101201 **) (* ------------------------------------------------------------------------ *) @@ -63,10 +63,10 @@ (** The task that immediately finishes with provided status *) val bind : 'a task -> ('a status -> 'b task) -> 'b task - (** - [bind t k] first runs [t]. Then, when [t] exit with status [s], + (** + [bind t k] first runs [t]. Then, when [t] exit with status [s], it starts task [k s]. - + Remark: If [t] was cancelled, [k s] is still evaluated, but immediately canceled as well. This allows [finally]-like behaviors to be implemented. To evaluate [k r] only when [t] terminates normally, @@ -75,7 +75,7 @@ val sequence : 'a task -> ('a -> 'b task) -> 'b task (** [sequence t k] first runs [t]. If [t] terminates with [Result r], - then task [k r] is started. + then task [k r] is started. Otherwise, failure or cancelation of [t] is returned. *) val todo : (unit -> 'a task) -> 'a task @@ -83,7 +83,7 @@ val finally : 'a task -> ('a status -> unit) -> 'a task (** [finally t cb] runs task [t] and {i always} calls [cb s] when [t] exits - with status [s]. Then [s] is returned. If the callback [cb] + with status [s]. Then [s] is returned. If the callback [cb] raises an exception, the returned status is emitted. *) val callback : 'a task -> ('a status -> unit) -> unit task @@ -119,18 +119,18 @@ type server -val server : - ?stages:int -> - ?procs:int -> +val server : + ?stages:int -> + ?procs:int -> unit -> server (** Creates a server of commands. - @param stages number of queues in the server. + @param stages number of queues in the server. Stage 0 tasks are issued first. Default is 1. @param procs maximum number of running tasks. Default is 4. *) val spawn : server -> ?stage:int -> unit task -> unit - (** Schedules a task on the server. + (** Schedules a task on the server. The task is not immediately started. *) val launch : server -> unit @@ -145,14 +145,15 @@ val on_server_activity : server -> (unit -> unit) -> unit (** Idle server callback *) val on_server_start : server -> (unit -> unit) -> unit (** On-start server callback *) val on_server_stop : server -> (unit -> unit) -> unit (** On-stop server callback *) -val load : server -> int (** Number of scheduled process *) + +val scheduled : server -> int (** Number of scheduled process *) +val terminated : server -> int (** Number of terminated process *) (** {1 GUI Configuration} *) val on_idle : ((unit -> bool) -> unit) ref (** Typically modified by GUI. - [!on_idle f] should repeatedly calls [f] until it returns [false]. + [!on_idle f] should repeatedly calls [f] until it returns [false]. Default implementation rely on [Unix.sleep 1] and [Db.progress]. See also [Gtk_helper] module implementation. *) - diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/unicode.ml frama-c-20111001+nitrogen+dfsg/src/kernel/unicode.ml --- frama-c-20110201+carbon+dfsg/src/kernel/unicode.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/unicode.ml 2011-10-10 08:38:09.000000000 +0000 @@ -20,5 +20,5 @@ (* *) (**************************************************************************) -let inset_string () = - if Parameters.UseUnicode.get () then Utf8_logic.inset else "IN" +let inset_string () = + if Kernel.Unicode.get () then Utf8_logic.inset else "IN" diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/unroll_loops.ml frama-c-20111001+nitrogen+dfsg/src/kernel/unroll_loops.ml --- frama-c-20110201+carbon+dfsg/src/kernel/unroll_loops.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/unroll_loops.ml 2011-10-10 08:38:09.000000000 +0000 @@ -20,21 +20,25 @@ (* *) (**************************************************************************) -(* Syntactic loop unrolling *) +(** Syntactic loop unrolling. *) open Cil_types open Cil open Cil_datatype -open Db_types open Visitor let fresh = let counter = ref (-1) in - fun () -> + fun ?loc ?prefix () -> decr counter; - Label (Format.sprintf "unrolling_%d_loop" (- !counter), - (CurrentLoc.get ()), - false) + let prefix = match prefix with None -> "" | Some s -> s ^ "_" + and loc, orig = match loc with + | None -> CurrentLoc.get (), false + | Some loc -> loc, true + in + Label (Format.sprintf "%sunrolling_%d_loop" prefix (- !counter), + loc, + orig) let copy_var = let counter = ref (-1) in @@ -76,22 +80,35 @@ in Visitor.visitFramacStmt visit (* Deep copy of a statement taking care of local gotos and labels. *) -let rec copy_stmt - fundec break_continue_must_change label_table calls_tbl stmt - = +let rec copy_stmt kf break_continue_must_change label_tbl calls_tbl stmt = let result = - { labels=[]; sid=0; succs=[]; preds=[]; skind=stmt.skind; ghost=stmt.ghost} + { labels = []; + sid = Sid.next (); + succs = []; + preds = []; + skind = stmt.skind; + ghost = stmt.ghost} in - let new_labels,label_tbl,sid = - let new_label = fresh () in - let sid = Sid.next () in - let new_acc = - List.fold_left - (fun acc _ -> Stmt.Map.add stmt result acc) - label_table + let new_labels,label_tbl = + if stmt.labels = [] then + [], label_tbl + else + let new_tbl = Stmt.Map.add stmt result label_tbl + and new_labels = + List.fold_left + (fun lbls -> function + | Label (s, loc, gen) -> + (if gen + then fresh ~prefix:s () + else fresh ~prefix:s ~loc () + ) :: lbls + + | Case _ | Default _ as lbl -> lbl :: lbls + ) + [] stmt.labels in - [ new_label ], new_acc, sid + new_labels, new_tbl in let new_calls_tbl = match stmt.skind with | Instr(Call _) -> Stmt.Map.add stmt result calls_tbl @@ -99,49 +116,43 @@ in let new_stmkind,new_label_tbl, new_calls_tbl = copy_stmtkind - fundec break_continue_must_change label_tbl new_calls_tbl stmt.skind + kf break_continue_must_change label_tbl new_calls_tbl stmt.skind in if stmt.labels <> [] then result.labels <- new_labels; - result.sid <-sid; result.skind <- new_stmkind; let new_annots = Annotations.fold_stmt (fun s (annot,_) acc -> - (*Format.printf "Adding annots to %d@." result.sid;*) - let new_annot = - let content = match Ast_info.before_after_content annot with - | User a -> User(Logic_const.refresh_code_annotation a) - | AI(c, a) -> AI(c, Logic_const.refresh_code_annotation a) - in - match annot with - | Before _ -> Before content - | After _ -> After content - in - (new_annot, match s with None -> [] | Some s -> [ s ]) :: acc) + (*Format.printf "Adding annots to %d@." result.sid;*) + let new_annot = + match annot with + | User a -> User(Logic_const.refresh_code_annotation a) + | AI(c, a) -> AI(c, Logic_const.refresh_code_annotation a) + in + (new_annot, match s with None -> [] | Some s -> [ s ]) :: acc) stmt [] in - List.iter (fun (a, dep) -> Annotations.add result dep a) new_annots; + List.iter (fun (a, dep) -> Annotations.add kf result dep a) new_annots; result, new_label_tbl, new_calls_tbl - and copy_stmtkind - fundec break_continue_must_change label_tbl calls_tbl stkind = + and copy_stmtkind kf break_continue_must_change label_tbl calls_tbl stkind = match stkind with |(Instr _ | Return _ | Goto _) as keep -> keep,label_tbl,calls_tbl | If (exp,bl1,bl2,loc) -> CurrentLoc.set loc; let new_block1,label_tbl,calls_tbl = - copy_block fundec break_continue_must_change label_tbl calls_tbl bl1 + copy_block kf break_continue_must_change label_tbl calls_tbl bl1 in let new_block2,label_tbl,calls_tbl = - copy_block fundec break_continue_must_change label_tbl calls_tbl bl2 + copy_block kf break_continue_must_change label_tbl calls_tbl bl2 in If(exp,new_block1,new_block2,loc),label_tbl,calls_tbl | Loop (a,bl,loc,_,_) -> CurrentLoc.set loc; let new_block,label_tbl,calls_tbl = copy_block - fundec + kf None (* from now on break and continue can be kept *) label_tbl calls_tbl @@ -150,20 +161,20 @@ Loop (a,new_block,loc,None,None),label_tbl,calls_tbl | Block bl -> let new_block,label_tbl,calls_tbl = - copy_block fundec break_continue_must_change label_tbl calls_tbl bl + copy_block kf break_continue_must_change label_tbl calls_tbl bl in Block (new_block),label_tbl,calls_tbl | UnspecifiedSequence seq -> let change_calls lst calls_tbl = List.map - (fun x -> ref (Stmt.Map.find !x calls_tbl)) lst + (fun x -> ref (Stmt.Map.find !x calls_tbl)) lst in let new_seq,label_tbl,calls_tbl = List.fold_left (fun (seq,label_tbl,calls_tbl) (stmt,modified,writes,reads,calls) -> let stmt,label_tbl,calls_tbl = copy_stmt - fundec break_continue_must_change label_tbl calls_tbl stmt + kf break_continue_must_change label_tbl calls_tbl stmt in (stmt,modified,writes,reads,change_calls calls calls_tbl)::seq, label_tbl,calls_tbl) @@ -187,35 +198,53 @@ | Switch (e,block,stmts,loc) -> (* from now on break and continue can be kept *) let new_block,new_label_tbl,calls_tbl = - copy_block fundec None label_tbl calls_tbl block + copy_block kf None label_tbl calls_tbl block in - Switch(e,new_block,stmts,loc),new_label_tbl,calls_tbl + let stmts' = List.map (fun s -> Stmt.Map.find s new_label_tbl) stmts in + Switch(e,new_block,stmts',loc),new_label_tbl,calls_tbl | TryFinally _ | TryExcept _ -> assert false - - - and copy_block fundec break_continue_must_change label_tbl calls_tbl bl = + and copy_block kf break_continue_must_change label_tbl calls_tbl bl = let new_stmts,label_tbl,calls_tbl = List.fold_left - (fun (block_l,label_tbl,calls_tbl) v -> + (fun (block_l,label_tbl,calls_tbl) v -> let new_block,label_tbl,calls_tbl = - copy_stmt fundec break_continue_must_change label_tbl calls_tbl v + copy_stmt kf break_continue_must_change label_tbl calls_tbl v in new_block::block_l, label_tbl,calls_tbl) - ([],label_tbl,calls_tbl) bl.bstmts + ([],label_tbl,calls_tbl) + bl.bstmts in let new_locals = List.map (copy_var ()) bl.blocals in + let fundec = + try Kernel_function.get_definition kf + with Kernel_function.No_Definition -> assert false + in fundec.slocals <- fundec.slocals @ new_locals; - let new_block = mkBlock - (List.rev_map - (refresh_vars new_locals bl.blocals) - new_stmts) + let new_block = + mkBlock (List.rev_map (refresh_vars new_locals bl.blocals) new_stmts) in new_block.blocals <- new_locals; new_block,label_tbl,calls_tbl + +let update_gotos sid_tbl block = + let goto_changer = + object + inherit nopCilVisitor + method vstmt s = match s.skind with + | Goto(sref,loc) -> + (try + let new_stmt = Cil_datatype.Stmt.Map.find !sref sid_tbl in + ChangeTo (mkStmt (Goto (ref new_stmt,loc))) + with Not_found -> DoChildren) + | _ -> DoChildren + end + in + visitCilBlock goto_changer block + (* Update to take into account annotations*) class do_it (times:int) = object(self) inherit Visitor.generic_frama_c_visitor @@ -235,9 +264,10 @@ let filter (b,_ as elt) p = match (b,p) with | false, Unroll_level {term_node=TConst (CInt64(v,_,_))} -> - true, Int64.to_int v + true, My_bigint.to_int v | true, Unroll_level _ -> - ignore (CilE.warn_once "ignoring unrolling directive (directive already defined)"); + Kernel.warning ~once:true ~current:true + "ignoring unrolling directive (directive already defined)"; elt | _, _ -> elt @@ -259,7 +289,7 @@ in let current_continue = ref (mk_continue ()) in (*Assuming unrolling was enough a test generator could do: - Annotations.add_assert s [] ~before:true + Annotations.add_assert s [] ~before:true {name=["KILLBRACNH"]; loc=Cil_datatype.Location.unknown; content= Pfalse @@ -272,13 +302,13 @@ (* calls tbl is internal. No need to fix references afterwards here. *) copy_block - (Extlib.the self#current_func) + (Extlib.the self#current_kf) (Some (break_lbl_stmt,!current_continue)) Stmt.Map.empty Stmt.Map.empty block in - let updated_block = CilE.update_gotos label_tbl new_block in + let updated_block = update_gotos label_tbl new_block in current_continue := mk_continue (); (match updated_block.blocals with [] -> new_stmts:= updated_block.bstmts @ !new_stmts; diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/unroll_loops.mli frama-c-20111001+nitrogen+dfsg/src/kernel/unroll_loops.mli --- frama-c-20110201+carbon+dfsg/src/kernel/unroll_loops.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/unroll_loops.mli 2011-10-10 08:38:09.000000000 +0000 @@ -0,0 +1,31 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Syntactic loop unrolling. *) + +val compute : int -> Cil_types.file -> unit + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/visitor.ml frama-c-20111001+nitrogen+dfsg/src/kernel/visitor.ml --- frama-c-20110201+carbon+dfsg/src/kernel/visitor.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/visitor.ml 2011-10-10 08:38:09.000000000 +0000 @@ -23,7 +23,6 @@ open Extlib open Cil open Cil_types -open Db_types let is_definition v = Ast_info.Function.is_definition (Globals.Functions.get v).fundec @@ -39,8 +38,8 @@ method vstmt_aux: Cil_types.stmt -> Cil_types.stmt visitAction method vglob_aux: Cil_types.global -> Cil_types.global list visitAction method vrooted_code_annotation: - Db_types.rooted_code_annotation -> - Db_types.rooted_code_annotation list visitAction + rooted_code_annotation -> + rooted_code_annotation list visitAction method is_annot_before: bool method current_kf: kernel_function option method set_current_kf: kernel_function -> unit @@ -52,7 +51,8 @@ redefined in inherited classes, while the corresponding ones from {!Cil.cilVisitor} {b must} retain their values as defined here. Otherwise, annotations may not be visited properly. *) -class generic_frama_c_visitor prj behavior: frama_c_visitor = +class internal_generic_frama_c_visitor + current_kf prj behavior: frama_c_visitor = let childrenRooted_code_annotation (vis:frama_c_visitor) rca = match rca with @@ -68,24 +68,22 @@ (fun x -> x) vis#vrooted_code_annotation childrenRooted_code_annotation ca in - object(self) inherit genericCilVisitor ~prj behavior as super (* top of the stack indicates if we are before or after the current statement. *) val before = Stack.create () - val mutable current_kf = None - - method frama_c_plain_copy = new generic_frama_c_visitor prj behavior + method frama_c_plain_copy = + new internal_generic_frama_c_visitor current_kf prj behavior method plain_copy_visitor = (self#frama_c_plain_copy :> Cil.cilVisitor) - method set_current_kf kf = current_kf <- Some kf + method set_current_kf kf = current_kf := Some kf - method reset_current_kf () = current_kf <- None + method reset_current_kf () = current_kf := None - method current_kf = current_kf + method current_kf = !current_kf method is_annot_before = Stack.is_empty before (* global annotation *) || Stack.top before @@ -95,14 +93,6 @@ method private vstmt stmt = let annots = Annotations.get_all_annotations stmt in let res = self#vstmt_aux stmt in - let abefore,aafter = - List.fold_left - (fun (b, a) x -> match x with - | Before x -> x :: b, a - | After x -> b, x :: a) - ([], []) - annots - in let compare_rooted x y = let id1 = match x with User ca | AI(_,ca) -> ca.annot_id in let id2 = match y with User ca | AI(_,ca) -> ca.annot_id in @@ -110,8 +100,7 @@ (* Annotations will be visited and more importantly added in the same order as they were in the original AST. *) in - let abefore = List.sort compare_rooted abefore in - let aafter = List.sort compare_rooted aafter in + let abefore = List.sort compare_rooted annots in let make_children_annot vis = Stack.push true before; let res_before, remove_before = @@ -140,120 +129,134 @@ ([],[]) abefore in - ignore (Stack.pop before); Stack.push false before; - let aafter' = - List.flatten - (List.map - (visitRooted_code_annotation (vis:>frama_c_visitor)) aafter) - in - let res_after = - List.filter - (fun x -> not (Ast_info.is_trivial_rooted_assertion x) && - not (List.memq x aafter)) - aafter' - in - let remove_after = - List.filter (fun x -> not (List.memq x aafter')) aafter - in - ignore(Stack.pop before); - (res_before, res_after, remove_before @ remove_after) + ignore (Stack.pop before); + (res_before, remove_before) in - let change_stmt stmt (res_before, res_after, remove) = - if (res_before <> [] || res_after <> [] || remove <> []) then begin -(* Format.printf "adding before: %d@\nadding after: %d@\nremoving %d@." - (List.length res_before) - (List.length res_after) - (List.length remove);*) - let add_annot = Annotations.add stmt [] in + let change_stmt stmt (res_before, remove) = + if (res_before <> [] || remove <> []) then begin + let kf = Extlib.the self#current_kf in + let new_kf = Cil.get_kernel_function self#behavior kf in Queue.add (fun () -> - if remove <> [] then - Annotations.filter ~reset:true - (fun _ _ annot -> - not - (List.memq (Ast_info.before_after_content annot) remove)) + let add_annot = Annotations.add new_kf stmt [] in + if remove <> [] then + Annotations.filter + ~reset:true + (fun _ _ annot -> not (List.memq annot remove)) + kf stmt; - List.iter (fun x -> add_annot (Before x)) (List.rev res_before); - List.iter (fun x -> add_annot (After x)) res_after) + List.iter add_annot (List.rev res_before)) self#get_filling_actions end in - let post_action stmt = change_stmt stmt (make_children_annot self); stmt in + let post_action f stmt = + let annots = make_children_annot self in + let stmt = f stmt in + change_stmt stmt annots; stmt + in let copy stmt = change_stmt stmt (make_children_annot self#frama_c_plain_copy); stmt in + let plain_post = post_action (fun x -> x) in match res with | SkipChildren -> res | JustCopy -> JustCopyPost copy | JustCopyPost f -> JustCopyPost (f $ copy) - | DoChildren -> ChangeDoChildrenPost (stmt, post_action) + | DoChildren -> ChangeDoChildrenPost (stmt, plain_post) | ChangeTo _ | ChangeToPost _ -> res | ChangeDoChildrenPost (stmt,f) -> - ChangeDoChildrenPost (stmt, f $ post_action) + ChangeDoChildrenPost (stmt, post_action f) method vstmt_aux _ = DoChildren method vglob_aux _ = DoChildren method vglob g = - let has_kf = - match g with - GVarDecl(_,v,_) when isFunctionType v.vtype -> - self#set_current_kf (Globals.Functions.get v); true - | GFun(f,_) -> self#set_current_kf (Globals.Functions.get f.svar); true - | _ -> false + let fundec, has_kf = match g with + | GVarDecl(_,v,_) when isFunctionType v.vtype -> + let v = Cil.get_original_varinfo self#behavior v in + let kf = Globals.Functions.get v in + (* Just make a copy of current kernel function in case it is needed *) + let new_kf = Cil.memo_kernel_function self#behavior kf in + if Cil.is_copy_behavior self#behavior then + new_kf.spec <- Cil.empty_funspec (); + self#set_current_kf kf; + None, true + | GFun(f,_) -> + let v = Cil.get_original_varinfo self#behavior f.svar in + let kf = Globals.Functions.get v in + let new_kf = Cil.memo_kernel_function self#behavior kf in + if Cil.is_copy_behavior self#behavior then + new_kf.spec <- Cil.empty_funspec (); + self#set_current_kf kf; + Some f, true + | _ -> None, false in let res = self#vglob_aux g in let make_funspec () = match g with - GVarDecl(_,v,_) when isFunctionType v.vtype -> - if not (is_definition v) then begin - let spec' = visitCilFunspec (self:> cilVisitor) - (Extlib.the current_kf).spec in - Some spec' - end - else None + | GVarDecl(_,v,_) when isFunctionType v.vtype -> + let v = Cil.get_original_varinfo self#behavior v in + if not (is_definition v) then begin + let spec = (Extlib.the self#current_kf).spec in + let spec' = visitCilFunspec (self:> cilVisitor) spec in + Some spec' + end else + None | GFun _ -> let spec' = visitCilFunspec (self:> cilVisitor) - (Extlib.the current_kf).spec in + (Extlib.the self#current_kf).spec + in Some spec' | _ -> None in let get_spec () = match g with GVarDecl(_,v,_) when isFunctionType v.vtype -> + let v = Cil.get_original_varinfo self#behavior v in if not (is_definition v) then begin - Some (Extlib.the current_kf).spec - end - else None (* visited in the corresponding definition *) - | GFun _ -> Some (Extlib.the current_kf).spec + Some (Extlib.the self#current_kf).spec + end + else None (* visited in the corresponding definition *) + | GFun _ -> Some (Extlib.the self#current_kf).spec | _ -> None in let change_glob ng spec = let cond = is_copy_behavior self#behavior in match ng with - GVar(vi,init,_) -> + | GVar(vi,init,_) -> if cond then - Queue.add (fun () -> Globals.Vars.add vi init) + Queue.add + (fun () -> Globals.Vars.add vi init) self#get_filling_actions | GVarDecl(_,v,l) when isFunctionType v.vtype -> let spec = match spec with None -> Cil.empty_funspec () | Some spec -> spec in - let orig_spec = (Extlib.the current_kf).spec in + let kf = Extlib.the self#current_kf in + let orig_spec = kf.spec in + let new_kf = Cil.get_kernel_function self#behavior kf in if cond || (not (Cil.is_empty_funspec spec) && not (Cil.is_empty_funspec orig_spec) && spec != orig_spec) then - Queue.add + Queue.add (fun () -> + (* NB: we can't really know whether v is associated to new_kf, + but if this is not the case, it is the responsibility of the + child visitor to properly update kf table while doing its + own transformations. + *) + Globals.Functions.register new_kf; Globals.Functions.replace_by_declaration spec v l) - self#get_filling_actions; + self#get_filling_actions; - | GVarDecl (_,({vstorage=Extern} as v),_) -> + | GVarDecl (_,({vstorage=Extern} as v),_) (* when not (isFunctionType + v.vtype *) -> if cond then - Queue.add (fun () -> Globals.Vars.add_decl v) + Queue.add + (fun () -> Globals.Vars.add_decl v) self#get_filling_actions | GFun(f,l) -> if cond then begin @@ -262,29 +265,35 @@ None -> Cil.empty_funspec () | Some spec -> spec in - Queue.add - (fun () -> - Kernel.debug - "@[Adding definition %s (vid: %d) for project %s@\n\ + let new_kf = + Cil.get_kernel_function self#behavior (Extlib.the self#current_kf) + in + Queue.add + (fun () -> + Kernel.debug + "@[Adding definition %s (vid: %d) for project %s@\n\ body: %a@\n@]@." - f.svar.vname f.svar.vid + f.svar.vname f.svar.vid (Project.get_name (Project.current())) !Ast_printer.d_block f.sbody ; - if is_definition f.svar then - failwith - "trying to redefine an existing kernel function" - else - Globals.Functions.replace_by_definition spec f l - ) - self#get_filling_actions + Globals.Functions.register new_kf; + Globals.Functions.replace_by_definition spec f l) + self#get_filling_actions end | _ -> () in let post_action g = let spec = lazy (make_funspec ()) in + Extlib.may self#set_current_func fundec; List.iter (fun g -> change_glob g (Lazy.force spec)) g; if has_kf then self#reset_current_kf(); + Extlib.may (fun _ -> self#reset_current_func ()) fundec; + g + in + let post_change_to g = + List.iter (fun g -> change_glob g None) g; + if has_kf then self#reset_current_kf(); g in match res with @@ -294,14 +303,15 @@ | JustCopy -> JustCopyPost post_action | JustCopyPost f -> JustCopyPost (f $ post_action) | DoChildren -> ChangeDoChildrenPost([g],post_action) - | ChangeTo l -> - List.iter (fun g -> change_glob g None) l; - if has_kf then self#reset_current_kf(); - res - | ChangeToPost (l,f) -> ChangeToPost (l, f $ post_action) - | ChangeDoChildrenPost (g,f) -> ChangeDoChildrenPost (g, f $ post_action) + | ChangeTo l -> ChangeToPost (l,post_change_to) + | ChangeToPost (l,f) -> ChangeToPost (l, f $ post_change_to) + | ChangeDoChildrenPost (g,f) -> ChangeDoChildrenPost (g, post_action $ f) end +class generic_frama_c_visitor prj bhv = + let current_kf = ref None in + internal_generic_frama_c_visitor current_kf prj bhv + class frama_c_copy prj = generic_frama_c_visitor prj (copy_visit ()) class frama_c_inplace = @@ -404,6 +414,10 @@ let p' = visitCilPredicateNamed (vis:>cilVisitor) p in vis#fill_global_tables; p' +let visitFramacIdPredicate vis p = + let p' = visitCilIdPredicate (vis:>cilVisitor) p in + vis#fill_global_tables; p' + let visitFramacPredicates vis p = let p' = visitCilPredicates (vis:>cilVisitor) p in vis#fill_global_tables; p' @@ -420,6 +434,10 @@ let t' = visitCilTermLhost (vis:>cilVisitor) t in vis#fill_global_tables; t' +let visitFramacTermLval vis t = + let t' = visitCilTermLval (vis:>cilVisitor) t in + vis#fill_global_tables; t' + let visitFramacLogicInfo vis l = let l' = visitCilLogicInfo (vis:>cilVisitor) l in vis#fill_global_tables; l' diff -Nru frama-c-20110201+carbon+dfsg/src/kernel/visitor.mli frama-c-20111001+nitrogen+dfsg/src/kernel/visitor.mli --- frama-c-20110201+carbon+dfsg/src/kernel/visitor.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/kernel/visitor.mli 2011-10-10 08:38:09.000000000 +0000 @@ -21,7 +21,6 @@ (**************************************************************************) open Cil_types -open Db_types (** Frama-C visitors dealing with projects. @plugin development guide *) @@ -61,11 +60,11 @@ method vstmt_aux: stmt -> stmt Cil.visitAction (** Replacement of vstmt. - @plugin development guide*) + @plugin development guide*) method vglob_aux: global -> global list Cil.visitAction (** Replacement of vglob. - @plugin development guide*) + @plugin development guide*) method vrooted_code_annotation: rooted_code_annotation -> @@ -74,15 +73,14 @@ method is_annot_before: bool (** Used to tell if we're visiting an annotation placed - before current statement. - @raise Error if not called while visiting a statement. *) + before current statement. + @raise Error if not called while visiting a statement. *) method current_kf: kernel_function option (** link to the kernel function currently being visited. {b NB:} for copy visitors, the link is to the original kf (anyway, the new kf is created only after the visit is over) *) - method set_current_kf: kernel_function -> unit (** Internal use only. *) @@ -184,11 +182,16 @@ val visitFramacPredicateNamed: frama_c_visitor -> predicate named -> predicate named +val visitFramacIdPredicate: + frama_c_visitor -> identified_predicate -> identified_predicate + val visitFramacPredicates: frama_c_visitor -> identified_predicate list -> identified_predicate list val visitFramacTerm: frama_c_visitor -> term -> term +val visitFramacTermLval: frama_c_visitor -> term_lval -> term_lval + val visitFramacTermLhost: frama_c_visitor -> term_lhost -> term_lhost val visitFramacTermOffset: frama_c_visitor -> term_offset -> term_offset diff -Nru frama-c-20110201+carbon+dfsg/src/lib/bad_dynlink_311_or_higher.ml frama-c-20111001+nitrogen+dfsg/src/lib/bad_dynlink_311_or_higher.ml --- frama-c-20110201+carbon+dfsg/src/lib/bad_dynlink_311_or_higher.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/bad_dynlink_311_or_higher.ml 2011-10-10 08:38:24.000000000 +0000 @@ -35,32 +35,32 @@ let is_native = Dynlink.is_native -let adapt_filename = +let adapt_filename = if is_native then fail "adapt_filename" else Dynlink.adapt_filename let loadfile = if is_native then fail "loadfile" else Dynlink.loadfile -let loadfile_private = +let loadfile_private = if is_native then fail "loadfile_private" else Dynlink.loadfile_private -let allow_unsafe_modules = - if is_native then fail "allow_unsafe_modules" +let allow_unsafe_modules = + if is_native then fail "allow_unsafe_modules" else Dynlink.allow_unsafe_modules let init = if is_native then fail "init" else Dynlink.init -let clear_available_units = - if is_native then fail "clear_available_units" +let clear_available_units = + if is_native then fail "clear_available_units" else Dynlink.clear_available_units -let add_available_units = +let add_available_units = if is_native then fail "add_available_units" else Dynlink.add_available_units -let add_interfaces = +let add_interfaces = if is_native then fail "add_interfaces" else Dynlink.add_interfaces -let default_available_units = - if is_native then fail "default_available_units" +let default_available_units = + if is_native then fail "default_available_units" else Dynlink.default_available_units let prohibit = if is_native then fail "prohibit" else Dynlink.prohibit @@ -84,10 +84,10 @@ exception Error = Dynlink.Error -let error_message = +let error_message = if is_native then fail "error_message" else Dynlink.error_message -let digest_interface = +let digest_interface = if is_native then fail "digest_interface" else Dynlink.digest_interface (* diff -Nru frama-c-20110201+carbon+dfsg/src/lib/bag.ml frama-c-20111001+nitrogen+dfsg/src/lib/bag.ml --- frama-c-20110201+carbon+dfsg/src/lib/bag.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/bag.ml 2011-10-10 08:38:24.000000000 +0000 @@ -115,14 +115,14 @@ | Add(x,ts) -> let pos,neg = partition f ts in if f x then add x pos , neg else pos , add x neg - | List xs -> + | List xs -> let pos,neg = List.partition f xs in list pos , list neg | Concat(a,b) -> let apos,aneg = partition f a in let bpos,bneg = partition f b in concat apos bpos , concat aneg bneg - + let rec is_empty = function | Empty | List [] -> true | Add(_,_) | Elt _ | List _ -> false @@ -134,5 +134,5 @@ | Add(x,t) -> if is_empty t then Some x else None | Concat(a,b) -> match singleton a with - | Some x -> if is_empty b then Some x else None - | None -> if is_empty a then singleton b else None + | Some x -> if is_empty b then Some x else None + | None -> if is_empty a then singleton b else None diff -Nru frama-c-20110201+carbon+dfsg/src/lib/bag.mli frama-c-20111001+nitrogen+dfsg/src/lib/bag.mli --- frama-c-20110201+carbon+dfsg/src/lib/bag.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/bag.mli 2011-10-10 08:38:24.000000000 +0000 @@ -21,7 +21,7 @@ (**************************************************************************) (** List with constant-time concat operation. - @since Carbon-20101201 + @since Carbon-20101201 *) type 'a t @@ -29,7 +29,7 @@ val empty : 'a t val elt : 'a -> 'a t val add : 'a -> 'a t -> 'a t -val list : 'a list -> 'a t +val list : 'a list -> 'a t val ulist : 'a t list -> 'a t val concat : 'a t -> 'a t -> 'a t @@ -47,4 +47,3 @@ val is_empty : 'a t -> bool val singleton : 'a t -> 'a option - diff -Nru frama-c-20110201+carbon+dfsg/src/lib/binary_cache.ml frama-c-20111001+nitrogen+dfsg/src/lib/binary_cache.ml --- frama-c-20110201+carbon+dfsg/src/lib/binary_cache.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/binary_cache.ml 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,455 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module MemoryFootprint = + State_builder.Int_ref + (struct + let name = "Binary_cache.MemoryFootprint" + let dependencies = [] + let kind = `Internal + let default () = 2 + end) + +let get_size () = + match MemoryFootprint.get () with + 1 -> 512 + | 2 -> 1024 + | _ -> 2048 + +module type Cacheable = +sig + type t + val hash : t -> int + val sentinel : t + val equal : t -> t -> bool +end + +module type Result = +sig + type t + val sentinel : t +end + +module Array_2 = +struct + type ('a, 'b) t + + let (clear : ('a, 'b) t -> 'a -> 'b -> unit) + = fun t a b -> + let t = Obj.repr t in + let size2 = Obj.size t in + let i = ref 0 in + while (!i < size2) + do + let base = !i in + Obj.set_field t (base) (Obj.repr a); + Obj.set_field t (base+1) (Obj.repr b); + i := base + 2; + done + + let (make : int -> 'a -> 'b -> ('a, 'b) t) + = fun size a b -> + let size2 = 2 * size in + let t = Obj.obj (Obj.new_block 0 size2) in + clear t a b; + t + + let (set : ('a, 'b) t -> int -> 'a -> 'b -> unit) + = fun t i a b -> + let t = Obj.repr t in + let base = 2 * i in + Obj.set_field t (base) (Obj.repr a); + Obj.set_field t (base+1) (Obj.repr b) + + let (get0 : + ('a, 'b) t -> int -> 'a) + = fun t i -> + let t = Obj.repr t in + let base = 2 * i in + Obj.obj (Obj.field t (base)) + + let (get1 : ('a, 'b) t -> int -> 'b) + = fun t i -> + let t = Obj.repr t in + let base = 2 * i in + Obj.obj (Obj.field t (base+1)) +end + +module Array_3 = +struct + type ('a, 'b, 'c) t + + let (clear : ('a, 'b, 'c) t -> + 'a -> 'b -> 'c -> unit) + = fun t a b c -> + let t = Obj.repr t in + let size3 = Obj.size t in + let i = ref 0 in + while (!i < size3) + do + let base = !i in + Obj.set_field t (base) (Obj.repr a); + Obj.set_field t (base+1) (Obj.repr b); + Obj.set_field t (base+2) (Obj.repr c); + i := base + 3; + done + + let (make : int -> 'a -> 'b -> 'c -> ('a, 'b, 'c) t) + = fun size a b c -> + let size3 = 3 * size in + let t = Obj.obj (Obj.new_block 0 size3) in + clear t a b c; + t + + let (set : ('a, 'b, 'c) t -> int -> 'a -> 'b -> 'c -> unit) + = fun t i a b c -> + let t = Obj.repr t in + let base = 3 * i in + Obj.set_field t (base) (Obj.repr a); + Obj.set_field t (base+1) (Obj.repr b); + Obj.set_field t (base+2) (Obj.repr c) + + let (get0 : + ('a, 'b, 'c) t -> int -> 'a) + = fun t i -> + let t = Obj.repr t in + let base = 3 * i in + Obj.obj (Obj.field t (base)) + + let (get1 : ('a, 'b, 'c) t -> int -> 'b) + = fun t i -> + let t = Obj.repr t in + let base = 3 * i in + Obj.obj (Obj.field t (base+1)) + + let (get2 : + ('a, 'b, 'c) t -> int -> 'c) + = fun t i -> + let t = Obj.repr t in + let base = 3 * i in + Obj.obj (Obj.field t (base+2)) +end + +module Array_7 = +struct + type ('a, 'b, 'c, 'd, 'e, 'f, 'g) t + + let (clear : ('a , 'b , 'c , 'd , 'e , 'f , 'g) t -> + 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> unit) + = fun t a b c d e f g -> + let t = Obj.repr t in + let size7 = Obj.size t in + let i = ref 0 in + while (!i < size7) + do + let base = !i in + Obj.set_field t (base) (Obj.repr a); + Obj.set_field t (base+1) (Obj.repr b); + Obj.set_field t (base+2) (Obj.repr c); + Obj.set_field t (base+3) (Obj.repr d); + Obj.set_field t (base+4) (Obj.repr e); + Obj.set_field t (base+5) (Obj.repr f); + Obj.set_field t (base+6) (Obj.repr g); + i := base + 7; + done + + let (make : int -> 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> + ('a , 'b , 'c , 'd , 'e , 'f , 'g) t) + = fun size a b c d e f g -> + let size7 = 7 * size in + let t = Obj.obj (Obj.new_block 0 size7) in + clear t a b c d e f g; + t + + let (set : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> + 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> unit) + = fun t i a b c d e f g -> + let t = Obj.repr t in + let base = 7 * i in + Obj.set_field t (base) (Obj.repr a); + Obj.set_field t (base+1) (Obj.repr b); + Obj.set_field t (base+2) (Obj.repr c); + Obj.set_field t (base+3) (Obj.repr d); + Obj.set_field t (base+4) (Obj.repr e); + Obj.set_field t (base+5) (Obj.repr f); + Obj.set_field t (base+6) (Obj.repr g) + + let (get0 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'a) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base)) + + let (get1 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'b) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base+1)) + + let (get2 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'c) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base+2)) + + let (get3 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'd) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base+3)) + + let (get4 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'e) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base+4)) + + let (get5 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'f) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base+5)) + + let (get6 : + ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'g) + = fun t i -> + let t = Obj.repr t in + let base = 7 * i in + Obj.obj (Obj.field t (base+6)) + +end + +module Make_Symetric (H: Cacheable) (R: Result) = +struct + let size = get_size () + let cache = Array_3.make size H.sentinel H.sentinel R.sentinel + + let mask = pred size + + let clear () = + Array_3.clear cache H.sentinel H.sentinel R.sentinel + + let hash = H.hash + + let merge f a0 a1 = + let a0, a1, h0, h1 = + let h0 = hash a0 in + let h1 = hash a1 in + if h0 < h1 + then a0, a1, h0, h1 + else a1, a0, h1, h0 + in + let has = h1 lsl 5 - h1 + h0 + in + let has = has land mask in + + if H.equal (Array_3.get0 cache has) a0 + && H.equal (Array_3.get1 cache has) a1 + then begin +(* Format.printf "Cache O@."; *) + Array_3.get2 cache has + end + else + let result = f a0 a1 in +(* Format.printf "Cache N@."; *) + Array_3.set cache has a0 a1 result; + result +end + + +module Make_Asymetric (H: Cacheable) (R: Result) = +struct + let size = 1024 (*get_size ()*) + let cache = Array_3.make size H.sentinel H.sentinel R.sentinel + + let mask = pred size + + let clear () = + Array_3.clear cache H.sentinel H.sentinel R.sentinel + + let merge f a0 a1 = + let h0 = H.hash a0 in + let h1 = H.hash a1 in + let has = h1 lsl 5 - h1 + h0 + in + let has = has land mask in + + if H.equal (Array_3.get0 cache has) a0 + && H.equal (Array_3.get1 cache has) a1 + then begin +(* Format.printf "Cache O@."; *) + Array_3.get2 cache has + end + else + let result = f a0 a1 in +(* Format.printf "Cache N@."; *) + Array_3.set cache has a0 a1 result; + result +end + +module Array_Bit = +struct + let make size = + let size = (size + 7) lsr 3 in + String.make size (char_of_int 0) + + let get s i = + let c = i lsr 3 in + let b = 1 lsl (i land 7) in + (Char.code s.[c]) land b <> 0 + + let set s i v = + let c = i lsr 3 in + let b = 1 lsl (i land 7) in + let oldcontents = Char.code s.[c] in + let newcontents = + if v + then b lor oldcontents + else + let mask = lnot b in + oldcontents land mask + in + s.[c] <- Char.chr newcontents +end + +module Make_Binary (H0: Cacheable) (H1: Cacheable) = +struct + let size = get_size() + let cache = Array_2.make size H0.sentinel H1.sentinel + let result = Array_Bit.make size + let mask = pred size + + let clear () = + Array_2.clear cache H0.sentinel H1.sentinel + + let merge f a0 a1 = + let has = + let h0 = H0.hash a0 in + let h1 = H1.hash a1 in + 599 * h0 + h1 + in + let has = has land mask in + + if H0.equal (Array_2.get0 cache has) a0 + && H1.equal (Array_2.get1 cache has) a1 + then begin +(* Format.printf "Cache O@."; *) + Array_Bit.get result has + end + else + let r = f a0 a1 in +(* Format.printf "Cache N@."; *) + Array_2.set cache has a0 a1; + Array_Bit.set result has r; + r +end + +module Make_Symetric_Binary (H0: Cacheable) = +struct + let size = get_size() + let cache = Array_2.make size H0.sentinel H0.sentinel + let result = Array_Bit.make size + let mask = pred size + + let clear () = + Array_2.clear cache H0.sentinel H0.sentinel + + let hash = H0.hash + + let merge f a0 a1 = + let a0, a1, h0, h1 = + let h0 = hash a0 in + let h1 = hash a1 in + if h0 < h1 + then a0, a1, h0, h1 + else a1, a0, h1, h0 + in + let has = h1 lsl 5 - h1 + h0 + in + let has = has land mask in + + if H0.equal (Array_2.get0 cache has) a0 + && H0.equal (Array_2.get1 cache has) a1 + then begin +(* Format.printf "Cache O@."; *) + Array_Bit.get result has + end + else + let r = f a0 a1 in +(* Format.printf "Cache N@."; *) + Array_2.set cache has a0 a1; + Array_Bit.set result has r; + r +end + +module Make_Het1_1_4 (H0: Cacheable) (H1: Cacheable) (H2: Cacheable) (R: Result) = +struct + let size = get_size () + let cache = + Array_7.make size + H0.sentinel H1.sentinel + H2.sentinel H2.sentinel H2.sentinel H2.sentinel + R.sentinel + + let mask = pred size + + let clear () = + Array_7.clear cache + H0.sentinel H1.sentinel + H2.sentinel H2.sentinel H2.sentinel H2.sentinel + R.sentinel + + let merge f a0 a1 a2 a3 a4 a5 = + let has = H0.hash a0 + 4909 * (H1.hash a1) + + 127 * (H2.hash a2) + 971 * (H2.hash a3) + + 31 * (H2.hash a4) + 7907 * (H2.hash a5) + in + let has = has land mask in + if H0.equal (Array_7.get0 cache has) a0 + && H1.equal (Array_7.get1 cache has) a1 + && H2.equal (Array_7.get2 cache has) a2 + && H2.equal (Array_7.get3 cache has) a3 + && H2.equal (Array_7.get4 cache has) a4 + && H2.equal (Array_7.get5 cache has) a5 + then begin +(* Format.printf "Cache O@."; *) + Array_7.get6 cache has + end + else + let result = f () in +(* Format.printf "Cache N@."; *) + Array_7.set cache has a0 a1 a2 a3 a4 a5 result; + result +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/binary_cache.mli frama-c-20111001+nitrogen+dfsg/src/lib/binary_cache.mli --- frama-c-20110201+carbon+dfsg/src/lib/binary_cache.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/binary_cache.mli 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,74 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + +module MemoryFootprint : State_builder.Ref with type data = int + +module type Cacheable = sig + type t + val hash : t -> int + val sentinel : t + val equal : t -> t -> bool +end + +module type Result = sig + type t + val sentinel : t +end + +module Make_Symetric(H : Cacheable)(R : Result): sig + val clear : unit -> unit + val merge : (H.t -> H.t -> R.t) -> H.t -> H.t -> R.t +end + +module Make_Asymetric(H : Cacheable)(R : Result): sig + val clear : unit -> unit + val merge : (H.t -> H.t -> R.t) -> H.t -> H.t -> R.t +end + +module Make_Binary(H0 : Cacheable)(H1 : Cacheable): sig + val clear : unit -> unit + val merge : (H0.t -> H1.t -> bool) -> H0.t -> H1.t -> bool +end + +module Make_Symetric_Binary(H0 : Cacheable): sig + val clear : unit -> unit + val merge : (H0.t -> H0.t -> bool) -> H0.t -> H0.t -> bool +end + +module Make_Het1_1_4 + (H0 : Cacheable)(H1 : Cacheable)(H2 : Cacheable) (R : Result): +sig + val clear : unit -> unit + val merge : + (unit -> R.t) -> H0.t -> H1.t -> H2.t -> H2.t -> H2.t -> H2.t -> R.t +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/bitvector.ml frama-c-20111001+nitrogen+dfsg/src/lib/bitvector.ml --- frama-c-20110201+carbon+dfsg/src/lib/bitvector.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/bitvector.ml 2011-10-10 08:38:24.000000000 +0000 @@ -39,7 +39,7 @@ (fun x -> let n = ref 0 in for k=0 to 7 do - if x land (1 lsl k) > 0 then incr n + if x land (1 lsl k) > 0 then incr n done ; n ) @@ -68,7 +68,7 @@ let set s k = let p = k lsr 3 in - if p >= String.length s then + if p >= String.length s then raise (Invalid_argument "Bitvector.set") ; let r = k land 7 in let b = int_of_char s.[p] lor (1 lsl r) in @@ -76,7 +76,7 @@ let clear s k = let p = k lsr 3 in - if p >= String.length s then + if p >= String.length s then raise (Invalid_argument "Bitvector.clear") ; let r = k land 7 in let b = int_of_char s.[p] land (lnot (1 lsl r)) in @@ -113,20 +113,20 @@ if b-a < 8 then for i=a to b do set s i done else - let p = + let p = let i = a land 7 in let p0 = a lsr 3 in if i=0 then p0 else - (* Sets bits i..7 of p0 *) - let x = int_of_char s.[p0] lor high.(i-1) in - s.[p0] <- char_of_int x ; succ p0 + (* Sets bits i..7 of p0 *) + let x = int_of_char s.[p0] lor high.(i-1) in + s.[p0] <- char_of_int x ; succ p0 in - let q = + let q = let j = b land 7 in let q0 = b lsr 3 in if j=7 then q0 else - (* Sets bits 0..j of q0 *) - let x = int_of_char s.[q0] lor low.(j) in - s.[q0] <- char_of_int x ; pred q0 + (* Sets bits 0..j of q0 *) + let x = int_of_char s.[q0] lor low.(j) in + s.[q0] <- char_of_int x ; pred q0 in for i=p to q do s.[i] <- '\255' done diff -Nru frama-c-20110201+carbon+dfsg/src/lib/bitvector.mli frama-c-20111001+nitrogen+dfsg/src/lib/bitvector.mli --- frama-c-20110201+carbon+dfsg/src/lib/bitvector.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/bitvector.mli 2011-10-10 08:38:24.000000000 +0000 @@ -40,5 +40,5 @@ (** Bit vector, as blocs of 8-bits separated by space, first bits to last bits from left to right. *) -val pp_bits : Format.formatter -> int -> unit +val pp_bits : Format.formatter -> int -> unit (** 0b... format, for bytes only, most significant bits on left. *) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/dynlink_common_interface.mli frama-c-20111001+nitrogen+dfsg/src/lib/dynlink_common_interface.mli --- frama-c-20110201+carbon+dfsg/src/lib/dynlink_common_interface.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/dynlink_common_interface.mli 2011-10-10 08:38:24.000000000 +0000 @@ -28,9 +28,9 @@ val loadfile : string -> unit (** In bytecode: load the given bytecode object file ([.cmo] file) or - bytecode library file ([.cma] file), and link it with the running + bytecode library file ([.cma] file), and link it with the running program. In native code: load the given OCaml plugin file (usually - [.cmxs]), and link it with the running + [.cmxs]), and link it with the running program. All toplevel expressions in the loaded compilation units are evaluated. No facilities are provided to @@ -99,6 +99,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/dynlink_lower_311_byte.ml frama-c-20111001+nitrogen+dfsg/src/lib/dynlink_lower_311_byte.ml --- frama-c-20110201+carbon+dfsg/src/lib/dynlink_lower_311_byte.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/dynlink_lower_311_byte.ml 2011-10-10 08:38:24.000000000 +0000 @@ -20,7 +20,7 @@ (* *) (**************************************************************************) -(* Implementation of [Dynlink_common_interface] compatible with +(* Implementation of [Dynlink_common_interface] compatible with ocamlc < 3.11 *) module type OldDynlink = sig @@ -37,7 +37,7 @@ let is_native = false let adapt_filename x = x -type linking_error = +type linking_error = | Undefined_global of string | Unavailable_primitive of string | Uninitialized_global of string @@ -69,7 +69,7 @@ | Corrupted_interface s -> Dynlink.Corrupted_interface s | File_not_found s -> Dynlink.File_not_found s | Cannot_open_dll s -> Dynlink.Cannot_open_dll s - | Inconsistent_implementation _ -> assert false + | Inconsistent_implementation _ -> assert false let from_dynlink_linking_error = function | Dynlink.Undefined_global s -> Undefined_global s @@ -81,13 +81,13 @@ | Dynlink.Inconsistent_import s -> Inconsistent_import s | Dynlink.Unavailable_unit s -> Unavailable_unit s | Dynlink.Unsafe_file -> Unsafe_file - | Dynlink.Linking_error(s, l) -> + | Dynlink.Linking_error(s, l) -> Linking_error(s, from_dynlink_linking_error l) | Dynlink.Corrupted_interface s -> Corrupted_interface s | Dynlink.File_not_found s -> File_not_found s | Dynlink.Cannot_open_dll s -> Cannot_open_dll s -let stub_error f x = +let stub_error f x = try f x with Dynlink.Error e -> raise (Error (from_dynlink_error e)) let init = stub_error init diff -Nru frama-c-20110201+carbon+dfsg/src/lib/extlib.ml frama-c-20111001+nitrogen+dfsg/src/lib/extlib.ml --- frama-c-20110201+carbon+dfsg/src/lib/extlib.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/extlib.ml 2011-10-10 08:38:24.000000000 +0000 @@ -77,6 +77,11 @@ | [a] -> a | _ -> invalid_arg "Extlib.as_singleton" +let rec last = function + | [] -> invalid_arg "Extlib.last" + | [a] -> a + | _ :: l -> last l + let filter_out f ls = List.filter (fun x -> not (f x)) ls let filter_map filter f l = @@ -84,6 +89,11 @@ [] -> [] | x::tl -> if filter x then f x :: aux tl else aux tl in aux l +let filter_map' f filter l= + let rec aux = function + | [] -> [] + | x::tl -> let x' = f x in if filter x' then x' :: aux tl else aux tl + in aux l let product_fold f acc e1 e2 = List.fold_left @@ -109,15 +119,26 @@ let c = cmp_elt v1 v2 in if c = 0 then list_compare cmp_elt r1 r2 else c -let list_of_opt = +let list_of_opt = function | None -> [] | Some x -> [x] +let rec find_opt f = function + | [] -> raise Not_found + | e :: q -> + match f e with + | None -> find_opt f q + | Some v -> v + +let iteri f l = let i = ref 0 in List.iter (fun x -> f !i x; incr i) l + (* ************************************************************************* *) (** {2 Options} *) (* ************************************************************************* *) +let has_some = function None -> false | Some _ -> true + let may f = function | None -> () | Some x -> f x @@ -135,6 +156,10 @@ | None -> None | Some x -> Some (f x) +let opt_bind f = function + | None -> None + | Some x -> f x + let opt_filter f = function | None -> None | (Some x) as o -> if f x then o else None @@ -165,7 +190,7 @@ let c1 = counter () in let res = f x in let c2 = counter () in - Format.printf "Time%s: %d@." + Format.printf "Time%s: %d@." (match msg with None -> "" | Some s -> " of " ^ s) (c2 - c1); res @@ -173,13 +198,30 @@ let time ?msg f x = gentime getperfcount ?msg f x let time1024 ?msg f x = gentime getperfcount1024 ?msg f x -external address_of_value: 'a -> int = "address_of_value" +(* The two functions below are not exported right now *) +let time' name f = + let cpt = ref 0 in + fun x -> + let b = getperfcount () in + let res = f x in + let e = getperfcount () in + let diff = e - b in + cpt := !cpt + diff; + Format.eprintf "timing of %s: %d (%d)@." name !cpt diff; + res + +let time2 name f = + let cpt = ref 0 in + fun x y -> + let b = getperfcount () in + let res = f x y in + let e = getperfcount () in + let diff = e - b in + cpt := !cpt + diff; + Format.eprintf "timing of %s: %d (%d)@." name !cpt diff; + res -external terminate_process: int -> unit = "terminate_process" - (* In src/buckx/buckx_c.c *) - -external usleep: int -> unit = "ml_usleep" - (* In src/buckx/buckx_c.c ; man usleep for details. *) +external address_of_value: 'a -> int = "address_of_value" (* ************************************************************************* *) (** {2 Exception catcher} *) @@ -204,17 +246,22 @@ try Array.iter (fun a -> - let f = Printf.sprintf "%s/%s" d a in - if Sys.is_directory f then safe_remove_dir f else safe_remove f + let f = Printf.sprintf "%s/%s" d a in + if Sys.is_directory f then safe_remove_dir f else safe_remove f ) (Sys.readdir d) ; Unix.rmdir d with Unix.Unix_error _ | Sys_error _ -> () let cleanup_at_exit f = at_exit (fun () -> safe_remove f) +exception Temp_file_error of string + let temp_file_cleanup_at_exit s1 s2 = - let (file,out) = Filename.open_temp_file s1 s2 in - (try close_out out with Unix.Unix_error _ -> ()) ; + let file, out = + try Filename.open_temp_file s1 s2 + with Sys_error s -> raise (Temp_file_error s) + in + (try close_out out with Unix.Unix_error _ -> ()); at_exit (fun () -> safe_remove file) ; file @@ -228,12 +275,20 @@ dir with Unix.Unix_error _ -> if limit < 0 then - let msg = - Printf.sprintf "Impossible to create temporary directory ('%s')" dir - in failwith msg + let msg = + Printf.sprintf "Impossible to create temporary directory ('%s')" dir + in + raise (Temp_file_error msg) else - try_dir_cleanup_at_exit (pred limit) base - in try_dir_cleanup_at_exit 10 base + try_dir_cleanup_at_exit (pred limit) base + in + try_dir_cleanup_at_exit 10 base + +external terminate_process: int -> unit = "terminate_process" + (* In src/buckx/buckx_c.c *) + +external usleep: int -> unit = "ml_usleep" + (* In src/buckx/buckx_c.c ; man usleep for details. *) (* ************************************************************************* *) (** Strings *) @@ -250,6 +305,12 @@ (* ************************************************************************* *) external compare_basic: 'a -> 'a -> int = "%compare" + + +let pretty_position fmt p = + Format.fprintf fmt "" + p.Lexing.pos_fname p.Lexing.pos_lnum p.Lexing.pos_bol p.Lexing.pos_cnum + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/lib/extlib.mli frama-c-20111001+nitrogen+dfsg/src/lib/extlib.mli --- frama-c-20110201+carbon+dfsg/src/lib/extlib.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/extlib.mli 2011-10-10 08:38:24.000000000 +0000 @@ -75,10 +75,18 @@ (** returns the unique element of a singleton list. @raise Invalid_argument on a non singleton list. *) +val last: 'a list -> 'a + (** returns the last element of a list. + @raise Invalid_argument on an empty list + @since Nitrogen-20111001 + *) + + val filter_out: ('a -> bool) -> 'a list -> 'a list (** Filter out elements that pass the test *) val filter_map: ('a -> bool) -> ('a -> 'b) -> 'a list -> 'b list +val filter_map': ('a -> 'b) -> ('b -> bool) -> 'a list -> 'b list (** Combines [filter] and [map]. *) val product_fold: ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a @@ -107,10 +115,30 @@ @since Carbon-20111201-beta2+dev *) +val find_opt : ('a -> 'b option) -> 'a list -> 'b + (** [find_option p l] returns the value [p e], [e] being the first + element of [l] such that [p e] is not [None]. Raise [Not_found] if there + is no such value the list l. + + @since Nitrogen-20111001 + *) + +val iteri: (int -> 'a -> unit) -> 'a list -> unit + (** Same as iter, but the function to be applied take also as argument the + index of the element (starting from 0) + @since Nitrogen-20111001 + *) + + (* ************************************************************************* *) (** {2 Options} *) (* ************************************************************************* *) +(** [true] iff its argument is [Some x] + @since Nitrogen-20111001 +*) +val has_some: 'a option -> bool + val may: ('a -> unit) -> 'a option -> unit val may_map: ('a -> 'b) -> ?dft:'b -> 'a option -> 'b @@ -120,6 +148,12 @@ val opt_map: ('a -> 'b) -> 'a option -> 'b option +(** [opt_bind f x] returns [None] if [x] is [None] and [f y] if is [Some y] + (monadic bind) + @since Nitrogen-20111001 +*) +val opt_bind: ('a -> 'b option) -> 'a option -> 'b option + val opt_filter: ('a -> bool) -> 'a option -> 'a option val the: 'a option -> 'a @@ -172,11 +206,17 @@ program exits (except if exit is caused by a signal). If [file] does not exist, nothing happens. *) +exception Temp_file_error of string + val temp_file_cleanup_at_exit: string -> string -> string (** Similar to [Filename.temp_file] except that the temporary file will be - deleted at the end of the execution (see above). *) + deleted at the end of the execution (see above). + @raise Temp_file_error if the temp file cannot be created. + @modify Nitrogen-20111001 may now raise Temp_file_error *) val temp_dir_cleanup_at_exit: string -> string +(** @raise Temp_file_error if the temp dir cannot be created. + @modify Nitrogen-20111001 may now raise Temp_file_error *) val safe_remove: string -> unit (** Tries to delete a file and never fails. *) @@ -199,6 +239,12 @@ it easier to find incorrect uses of the latter *) external compare_basic: 'a -> 'a -> int = "%compare" +(* ************************************************************************* *) +(** Printing Lexing.position *) +(* ************************************************************************* *) + +val pretty_position: Format.formatter -> Lexing.position -> unit + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/lib/hook.mli frama-c-20111001+nitrogen+dfsg/src/lib/hook.mli --- frama-c-20110201+carbon+dfsg/src/lib/hook.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/hook.mli 2011-10-10 08:38:24.000000000 +0000 @@ -41,8 +41,8 @@ val apply: param -> result (** Apply all the functions of the hook on the given parameter. - These functions are applied from the least recently entered to the most - recently entered.*) + These functions are applied from the least recently entered to the most + recently entered.*) val is_empty: unit -> bool (** Is no function already registered in the hook? *) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/hptset.ml frama-c-20111001+nitrogen+dfsg/src/lib/hptset.ml --- frama-c-20110201+carbon+dfsg/src/lib/hptset.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/hptset.ml 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,165 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module type S = sig + type elt + include Datatype.S + val empty: t + val is_empty: t -> bool + val mem: elt -> t -> bool + val add: elt -> t -> t + val singleton: elt -> t + val remove: elt -> t -> t + val elements: t -> elt list + val union: t -> t -> t + val inter: t -> t -> t + val diff: t -> t -> t + val subset: t -> t -> bool + val iter: (elt -> unit) -> t -> unit + val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a + val for_all: (elt -> bool) -> t -> bool + val exists: (elt -> bool) -> t -> bool + val filter: (elt -> bool) -> t -> t + val partition: (elt -> bool) -> t -> t * t + val cardinal: t -> int + val min_elt: t -> elt + val max_elt: t -> elt + val contains_single_elt: t -> elt option + val choose: t -> elt + val split: elt -> t -> t * bool * t +end + +module type Id_Datatype = sig + include Datatype.S + val id: t -> int +end + +module Make(X: Id_Datatype) + (Initial_Values : sig val v : X.t list list end) + (Datatype_deps: sig val l : State.t list end) + = struct + + include + Hptmap.Make + (X) + (struct include Datatype.Unit let tag () = 0 end) + (Hptmap.Comp_unused) + (struct let v = List.map (List.map (fun k -> k, ())) Initial_Values.v end) + (Datatype_deps) + + type elt = X.t + + let add k = add k () + let iter f = iter (fun x () -> f x) + let fold f = fold (fun x () -> f x) + + let elements s = fold (fun h t -> h::t) s [] + + let contains_single_elt s = + match is_singleton s with + Some (k, _v) -> Some k + | None -> None + + let min_elt s = + fst (min_binding s) + + let max_elt s = + fst (max_binding s) + + let choose = min_elt + + let filter f s = fold (fun x acc -> if f x then add x acc else acc) s empty + + let partition f s = + fold + (fun x (w, wo) -> if f x then add x w, wo else w, add x wo) s (empty, empty) + + let mem x s = try find x s; true with Not_found -> false + + let diff s1 s2 = + fold (fun x acc -> if mem x s2 then acc else add x acc) s1 empty + + let inter s1 s2 = + fold (fun x acc -> if mem x s1 then add x acc else acc) s2 empty +(* let inter = time2 "inter" inter *) + + let binary_unit _ _ = () + + let union = + symetric_merge + ~cache:("Hptset.union", 12) + ~decide_none:binary_unit + ~decide_some:binary_unit +(* let union = time2 "union" union *) + + let singleton x = add x empty + + exception Elt_found + + let exists f s = + try + iter (fun x -> if f x then raise Elt_found) s; + false + with Elt_found -> + true + + let for_all f s = + try + iter (fun x -> if not (f x) then raise Elt_found) s; + true + with Elt_found -> + false + + exception Not_incl + + let subset = + generic_is_included + Not_incl + ~cache:("Hptset.subset", 12) + ~decide_fst:(fun _ () -> raise Not_incl) + ~decide_snd:binary_unit + ~decide_both:binary_unit + + let subset s1 s2 = try subset s1 s2 ; true with Not_incl -> false + (* let subset = time2 "subset" subset *) + + let cardinal s = fold (fun _ acc -> acc + 1) s 0 + (* let cardinal = time "cardinal" cardinal *) + + let pretty = + if X.pretty == Datatype.undefined then + Datatype.undefined + else + Pretty_utils.pp_iter + ~pre:"@[{" ~sep:",@ " ~suf:"}@]" iter X.pretty + + let split key t = + let l, pres, r = split key t in + l, pres <> None, r + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/hptset.mli frama-c-20111001+nitrogen+dfsg/src/lib/hptset.mli --- frama-c-20110201+carbon+dfsg/src/lib/hptset.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/hptset.mli 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,153 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Sets over ordered types. + + This module implements the set data structure. + All operations over sets + are purely applicative (no side-effects). *) + +(** Input signature of the functor {!Set.Make}. *) +module type Id_Datatype = sig + include Datatype.S + val id: t -> int +end + +(** Output signature of the functor {!Set.Make}. *) +module type S = sig + + type elt + (** The type of the set elements. *) + + include Datatype.S + (** The datatype of sets. *) + + val empty: t + (** The empty set. *) + + val is_empty: t -> bool + (** Test whether a set is empty or not. *) + + val mem: elt -> t -> bool + (** [mem x s] tests whether [x] belongs to the set [s]. *) + + val add: elt -> t -> t + (** [add x s] returns a set containing all elements of [s], + plus [x]. If [x] was already in [s], [s] is returned unchanged. *) + + val singleton: elt -> t + (** [singleton x] returns the one-element set containing only [x]. *) + + val remove: elt -> t -> t + (** [remove x s] returns a set containing all elements of [s], + except [x]. If [x] was not in [s], [s] is returned unchanged. *) + + val elements: t -> elt list + + val union: t -> t -> t + (** Set union. *) + + val inter: t -> t -> t + (** Set intersection. *) + + (** Set difference. *) + val diff: t -> t -> t +(* + val compare: t -> t -> int + (** Total ordering between sets. Can be used as the ordering function + for doing sets of sets. *) +*) + + val subset: t -> t -> bool + (** [subset s1 s2] tests whether the set [s1] is a subset of + the set [s2]. *) + + val iter: (elt -> unit) -> t -> unit + (** [iter f s] applies [f] in turn to all elements of [s]. + The elements of [s] are presented to [f] in increasing order + with respect to the ordering over the type of the elements. *) + + val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a + (** [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)], + where [x1 ... xN] are the elements of [s], in increasing order. *) + + val for_all: (elt -> bool) -> t -> bool + (** [for_all p s] checks if all elements of the set + satisfy the predicate [p]. *) + + val exists: (elt -> bool) -> t -> bool + (** [exists p s] checks if at least one element of + the set satisfies the predicate [p]. *) + + val filter: (elt -> bool) -> t -> t + (** [filter p s] returns the set of all elements in [s] + that satisfy predicate [p]. *) + + val partition: (elt -> bool) -> t -> t * t + (** [partition p s] returns a pair of sets [(s1, s2)], where + [s1] is the set of all the elements of [s] that satisfy the + predicate [p], and [s2] is the set of all the elements of + [s] that do not satisfy [p]. *) + + + val cardinal: t -> int + (** Return the number of elements of a set. *) + + val min_elt: t -> elt + (** Return the smallest element of the given set + (with respect to the [Ord.compare] ordering), or raise + [Not_found] if the set is empty. *) + + val max_elt: t -> elt + (** Same as {!Set.S.min_elt}, but returns the largest element of the + given set. *) + + val contains_single_elt: t -> elt option + + val choose: t -> elt + (** Return one element of the given set, or raise [Not_found] if + the set is empty. Which element is chosen is unspecified, + but equal elements will be chosen for equal sets. *) + + val split: elt -> t -> t * bool * t + (** [split x s] returns a triple [(l, present, r)], where + [l] is the set of elements of [s] that are + strictly less than [x]; + [r] is the set of elements of [s] that are + strictly greater than [x]; + [present] is [false] if [s] contains no element equal to [x], + or [true] if [s] contains an element equal to [x]. *) +end + +module Make(X: Id_Datatype) + (Initial_Values : sig val v : X.t list list end) + (Datatype_deps: sig val l : State.t list end) : + sig + include S with type elt = X.t + val self : State.t + end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/map_312_or_higher.ml frama-c-20111001+nitrogen+dfsg/src/lib/map_312_or_higher.ml --- frama-c-20110201+carbon+dfsg/src/lib/map_312_or_higher.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/map_312_or_higher.ml 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,31 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module type S = Map.S + +module Make(Ord:Map.OrderedType) = Map.Make(Ord) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/map_312_or_higher.mli frama-c-20111001+nitrogen+dfsg/src/lib/map_312_or_higher.mli --- frama-c-20110201+carbon+dfsg/src/lib/map_312_or_higher.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/map_312_or_higher.mli 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Wrapper for [Map] compatible with all OCaml versions. + @since Nitrogen-20111001 *) + +module type S = Map.S + +module Make(Ord:Map.OrderedType): Map.S with type key = Ord.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/map_common_interface.ml frama-c-20111001+nitrogen+dfsg/src/lib/map_common_interface.ml --- frama-c-20110201+carbon+dfsg/src/lib/map_common_interface.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/map_common_interface.ml 2011-10-10 08:56:36.000000000 +0000 @@ -0,0 +1,31 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module type S = Map.S + +module Make(Ord:Map.OrderedType) = Map.Make(Ord) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/map_common_interface.mli frama-c-20111001+nitrogen+dfsg/src/lib/map_common_interface.mli --- frama-c-20110201+carbon+dfsg/src/lib/map_common_interface.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/map_common_interface.mli 2011-10-10 08:56:36.000000000 +0000 @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Wrapper for [Map] compatible with all OCaml versions. + @since Nitrogen-20111001 *) + +module type S = Map.S + +module Make(Ord:Map.OrderedType): Map.S with type key = Ord.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/map_lower_312.ml frama-c-20111001+nitrogen+dfsg/src/lib/map_lower_312.ml --- frama-c-20110201+carbon+dfsg/src/lib/map_lower_312.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/map_lower_312.ml 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module type S = +sig + include Map.S + val merge: (key -> 'a option -> 'b option -> 'c option) -> + 'a t -> 'b t -> 'c t +end + +module Make(Ord:Map.OrderedType): (S with type key = Ord.t) = + struct + include Map.Make(Ord) + let merge f m1 m2 = + let traverse_first k v1 acc = + let v2 = try Some (find k m2) with Not_found -> None in + match f k (Some v1) v2 with + | None -> acc + | Some v -> add k v acc + in + let traverse_snd k v2 acc = + if mem k acc then acc + else + match f k None (Some v2) with + | None -> acc + | Some v -> add k v acc + in + fold traverse_snd m2 (fold traverse_first m1 empty) + end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/map_lower_312.mli frama-c-20111001+nitrogen+dfsg/src/lib/map_lower_312.mli --- frama-c-20110201+carbon+dfsg/src/lib/map_lower_312.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/map_lower_312.mli 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,38 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Wrapper for [Map] compatible with all OCaml versions. + @since Nitrogen-20111001 *) + +module type S = sig + include Map.S + val merge: + (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t +end + +module Make(Ord:Map.OrderedType): S with type key = Ord.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/my_bigint.ml.bigint frama-c-20111001+nitrogen+dfsg/src/lib/my_bigint.ml.bigint --- frama-c-20110201+carbon+dfsg/src/lib/my_bigint.ml.bigint 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/my_bigint.ml.bigint 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,425 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +type t = Big_int.big_int +module M = struct +let my_int64_of_big_int i = Int64.of_string (Big_int.string_of_big_int i) +let my_big_int_of_int64 i = Big_int.big_int_of_string (Int64.to_string i) +(* Will be used if Big_int.int64_of_big_int does not exist. This is the case + in OCaml <= 3.10.2. Otherwise the [include Big_int] at the end of this file + will redefine it to the standard optimal version... *) +let int64_of_big_int = my_int64_of_big_int +let big_int_of_int64 = my_big_int_of_int64 + +include Big_int +(* ...except these functions are buggy before Ocaml 3.11.1 with 32bits wordsize: + ( PR#4792 and PR#4804) + So in that case, their standard optimal version is not used. *) +let int64_of_big_int, big_int_of_int64 = + if (Sys.word_size = 32) && (Sys.ocaml_version < "3.11.1") + then my_int64_of_big_int, my_big_int_of_int64 + else int64_of_big_int, big_int_of_int64 + +let equal = eq_big_int + +let compare = compare_big_int + +(* Nb of significant digits in a "word" of Big_int. *) +let nb_digits_of_big_int = + let r = + let rec nb_digits y = + if 1 = num_digits_big_int (power_int_positive_int 2 y) + then nb_digits (y + 1) + else y + in nb_digits 1 + in r + +let base = power_int_positive_int 2 nb_digits_of_big_int +let base16bits = power_int_positive_int 2 16 + + +(* If X is such that x + = let f a x =(a * base) + x in List.fold_left f 0 X, + and Y such that y + = let f a y =(a * base) + y in List.fold_left f 0 Y, + we have map2_base base op x y = + let f a x y =(a * base) + (op x y) in List.fold_left f 0 X Y +*) +let map2_base b op x y = + let rec map2_base_rec a x y = + let (qx, mx) = quomod_big_int x b + and (qy, my) = quomod_big_int y b + in let res_m = op mx my + and res_q = + if (eq_big_int zero_big_int qx) + && (eq_big_int zero_big_int qy) + then a + else map2_base_rec a qx qy + in add_big_int (mult_big_int res_q b) res_m + in map2_base_rec zero_big_int x y + + +let bitwise_op_positive_big_int op x y = + assert (ge_big_int x zero_big_int); + assert (ge_big_int y zero_big_int); + let g = + let f u v = assert(is_int_big_int u) ; + assert(is_int_big_int v) ; + let r = op (int_of_big_int u) (int_of_big_int v) + in big_int_of_int (r) + in map2_base base16bits f + in let r = map2_base base g x y + in assert (ge_big_int r zero_big_int); + r + +let lnot_big_int w = minus_big_int (succ_big_int w) + +let shift_left_big_int x y = (* idem multiplication *) + mult_big_int x (power_int_positive_big_int 2 y) + +let shift_right_big_int x y = (* idem division rounding to -oo *) + div_big_int x (power_int_positive_big_int 2 y) + +let power_two = + let h = Hashtbl.create 7 in + fun k -> + try + Hashtbl.find h k + with Not_found -> + let p = power_int_positive_int 2 k in + Hashtbl.add h k p; + p + +let two_power y = + try + let k = int_of_big_int y in + power_two k + with Failure _ -> assert false + +let log_shift_right_big_int x y = (* no meaning for negative value of x *) + if (lt_big_int x zero_big_int) + then raise (Invalid_argument "log_shift_right_big_int") + else shift_right_big_int x y + +let bitwise_op_big_int op x y = + let (positive_x, op_sx) = + if gt_big_int zero_big_int x + then (lnot_big_int x, (fun u v -> op (lnot u) v)) + else (x, op) + in let (positive_y, op_sx_sy) = + if gt_big_int zero_big_int y + then (lnot_big_int y, (fun u v -> op_sx u (lnot v))) + else (y, op_sx) + in let (positive_op_map, op_map) = + if 0 = (op_sx_sy 0 0) + then (op_sx_sy, (fun w -> w)) + else ((fun u v -> lnot (op_sx_sy u v)), lnot_big_int) + in op_map (bitwise_op_positive_big_int positive_op_map positive_x positive_y) + + +let land_big_int = bitwise_op_big_int (land) +let lor_big_int = bitwise_op_big_int (lor) +let lxor_big_int = bitwise_op_big_int (lxor) + +(* Get the value encoded from the 'first' to 'last' bit of 'x' : + Shift right 'x' and apply a mask on it. + The result is: div (mod x (2**(last+1))) (2**first) *) +let bitwise_extraction first_bit last_bit x = + assert (first_bit <= last_bit);(* first_bit <= last_bit *) + assert (first_bit >= 0); (* first_bit >= 0 *) + let q = div_big_int x (power_int_positive_int 2 first_bit) in + let r = mod_big_int q (power_int_positive_int 2 (1 + last_bit - first_bit)) in + r + +let minus_one_big_int = minus_big_int unit_big_int +let thirty_two_big_int = big_int_of_int 32 + + +(* To export *) + + let small_nums = Array.init 33 (fun i -> big_int_of_int i) + + let zero = zero_big_int + let one = unit_big_int + let minus_one = minus_big_int unit_big_int + let two = small_nums.(2) + let four = small_nums.(4) + let eight = small_nums.(8) + let thirtytwo = small_nums.(32) + let onethousand = big_int_of_int 1000 + let billion_one = big_int_of_int 1_000_000_001 + + let is_zero v = (sign_big_int v) = 0 + + let rem = mod_big_int + let div = div_big_int + let mul = mult_big_int + + let sub = sub_big_int + + let abs = abs_big_int + let succ = succ_big_int + let pred = pred_big_int + let neg = minus_big_int + + let add = add_big_int + + let hash c = + let i = + try + int_of_big_int c + with Failure _ -> int_of_big_int (rem c billion_one) + in + 197 + i + + let shift_right_logical = log_shift_right_big_int + let shift_right = shift_right_big_int + let shift_left = shift_left_big_int + + let logand = land_big_int + let lognot = lnot_big_int + let logor = lor_big_int + let logxor = lxor_big_int + + let le = le_big_int + let lt = lt_big_int + let ge = ge_big_int + let gt = gt_big_int + + let to_int v = + try int_of_big_int v + with Failure "int_of_big_int" -> assert false + let of_int i = + if 0 <= i && i <= 32 + then small_nums.(i) + else big_int_of_int i + + (* for the two functions below wait until the minimum supported + OCaml version is after: + http://caml.inria.fr/mantis/print_bug_page.php?bug_id=4792 + *) + let of_int64 i = big_int_of_string (Int64.to_string i) + let to_int64 i = Int64.of_string (string_of_big_int i) + let max_int64 = of_int64 Int64.max_int + let min_int64 = of_int64 Int64.min_int + let bits_of_max_float = of_int64 (Int64.bits_of_float max_float) + let bits_of_most_negative_float = + of_int64 (Int64.bits_of_float (-. max_float)) + + let of_string = big_int_of_string + let to_string = string_of_big_int + let to_float = float_of_big_int + let of_float _ = assert false + + let minus_one = pred zero + + let two_power_60 = power_two 60 + let two_power_64 = power_two 64 + + let add_2_64 x = add two_power_64 x + + let pretty ?(hexa=false) fmt v = + let rec aux v = + if gt v two_power_60 then + let quo, rem = quomod_big_int v two_power_60 in + aux quo; + Format.fprintf fmt "%015LX" (to_int64 rem) + else + Format.fprintf fmt "%LX" (to_int64 v) + in + if hexa then + if equal v zero then Format.pp_print_string fmt "0" + else if gt v zero then (Format.pp_print_string fmt "0x"; aux v) + else (Format.pp_print_string fmt "-0x"; aux (minus_big_int v)) + else + Format.pp_print_string fmt (to_string v) + + let is_one v = equal one v + let pos_div = div + + let pos_rem = rem + let native_div = div + + let c_div u v = + let bad_div = div u v in + if (lt u zero) && not (is_zero (rem u v)) + then + if lt v zero + then pred bad_div + else succ bad_div + else bad_div + + + let c_rem u v = + sub u (mul v (c_div u v)) + + let cast ~size ~signed ~value = + let factor = two_power size in + let mask = two_power (sub size one) in + + if (not signed) then pos_rem value factor + else + if equal (logand mask value) zero + then logand value (pred mask) + else + logor (lognot (pred mask)) value + + let two_power = two_power + + let power_two = power_two + + let extract_bits ~start ~stop v = + assert (ge start zero && ge stop start); + (*Format.printf "%a[%a..%a]@\n" pretty v pretty start pretty stop;*) + let r = bitwise_extraction (to_int start) (to_int stop) v in + (*Format.printf "%a[%a..%a]=%a@\n" pretty v pretty start pretty stop pretty r;*) + r + + let is_even v = is_zero (logand one v) + + (** [pgcd u 0] is allowed and returns [u] *) + let pgcd u v = + let r = + if is_zero v + then u + else gcd_big_int u v in + r + + let ppcm u v = + if u = zero || v = zero + then zero + else native_div (mul u v) (pgcd u v) + + let length u v = succ (sub v u) + + let min = min_big_int + let max = max_big_int + + let round_down_to_zero v modu = + mul (pos_div v modu) modu + + (** [round_up_to_r m r modu] is the smallest number [n] such that + [n]>=[m] and [n] = [r] modulo [modu] *) + let round_up_to_r ~min:m ~r ~modu = + add (add (round_down_to_zero (pred (sub m r)) modu) r) modu + + (** [round_down_to_r m r modu] is the largest number [n] such that + [n]<=[m] and [n] = [r] modulo [modu] *) + let round_down_to_r ~max:m ~r ~modu = + add (round_down_to_zero (sub m r) modu) r + + let to_num = Num.num_of_big_int + + (* only for x >= 0 *) + let popcount x = + let rec aux x acc = + if is_zero x + then acc + else + let acc = acc + (to_int (logand x one)) in + aux (shift_right x one) acc + in + aux x 0 +end + +module type S = sig + val equal : t -> t -> bool + val compare : t -> t -> int + val le : t -> t -> bool + val ge : t -> t -> bool + val lt : t -> t -> bool + val gt : t -> t -> bool + val add : t -> t -> t + + val sub : t -> t -> t + + val mul : t -> t -> t + + val native_div : t -> t -> t + val rem : t -> t -> t + val pos_div : t -> t -> t + val c_div : t -> t -> t + + val c_rem : t -> t -> t + + val cast: size:t -> signed:bool -> value:t -> t + val abs : t -> t + val one : t + val two : t + val four : t + val onethousand : t + val minus_one : t + val is_zero : t -> bool + val is_one : t -> bool + val pgcd : t -> t -> t + val ppcm : t -> t -> t + val min : t -> t -> t + val max : t -> t -> t + val length : t -> t -> t (** b - a + 1 *) + val of_int : int -> t + val of_float : float -> t + val of_int64 : Int64.t -> t + val to_int64 : t -> int64 + val to_int : t -> int + val to_float : t -> float + val neg : t -> t + + val succ : t -> t + val pred : t -> t + val round_up_to_r : min:t -> r:t -> modu:t -> t + val round_down_to_r : max:t -> r:t -> modu:t -> t + val pos_rem : t -> t -> t + val shift_left : t -> t -> t + val shift_right : t -> t -> t + val logand : t -> t -> t + val logor : t -> t -> t + val logxor : t -> t -> t + val lognot : t -> t + val power_two : int -> t + val two_power : t -> t + val extract_bits : start:t -> stop:t -> t -> t + + val small_nums : t array + val zero : t + val eight : t + val thirtytwo : t + val div : t -> t -> t + + val billion_one : t + val hash : t -> int + val shift_right_logical : t -> t -> t + + val max_int64 : t + val min_int64 : t + val bits_of_max_float : t + val bits_of_most_negative_float : t + val of_string : string -> t + val to_string : t -> string + + val add_2_64 : t -> t + val is_even : t -> bool + val round_down_to_zero : t -> t -> t + val power_int_positive_int: int -> int -> t + val to_num : t -> Num.num + val popcount: t -> int +end +include M diff -Nru frama-c-20110201+carbon+dfsg/src/lib/my_bigint.mli frama-c-20111001+nitrogen+dfsg/src/lib/my_bigint.mli --- frama-c-20110201+carbon+dfsg/src/lib/my_bigint.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/my_bigint.mli 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,110 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Sane abstract interface to module [Big_int]. *) + +type t + +module type S = sig + val equal : t -> t -> bool + val compare : t -> t -> int + val le : t -> t -> bool + val ge : t -> t -> bool + val lt : t -> t -> bool + val gt : t -> t -> bool + val add : t -> t -> t + val sub : t -> t -> t + val mul : t -> t -> t + val native_div : t -> t -> t + val rem : t -> t -> t + val pos_div : t -> t -> t + val c_div : t -> t -> t + val c_rem : t -> t -> t + val cast: size:t -> signed:bool -> value:t -> t + val abs : t -> t + val one : t + val two : t + val four : t + val onethousand : t + val minus_one : t + val is_zero : t -> bool + val is_one : t -> bool + val pgcd : t -> t -> t + val ppcm : t -> t -> t + val min : t -> t -> t + val max : t -> t -> t + val length : t -> t -> t (** b - a + 1 *) + val of_int : int -> t + val of_float : float -> t + val of_int64 : Int64.t -> t + val to_int64 : t -> int64 + val to_int : t -> int + val to_float : t -> float + val neg : t -> t + val succ : t -> t + val pred : t -> t + val round_up_to_r : min:t -> r:t -> modu:t -> t + val round_down_to_r : max:t -> r:t -> modu:t -> t + val pos_rem : t -> t -> t + val shift_left : t -> t -> t + val shift_right : t -> t -> t + val logand : t -> t -> t + val logor : t -> t -> t + val logxor : t -> t -> t + val lognot : t -> t + val power_two : int -> t + val two_power : t -> t + val extract_bits : start:t -> stop:t -> t -> t + + val small_nums : t array + val zero : t + val eight : t + val thirtytwo : t + val div : t -> t -> t + + val billion_one : t + val hash : t -> int + val shift_right_logical : t -> t -> t + + val max_int64 : t + val min_int64 : t + val bits_of_max_float : t + val bits_of_most_negative_float : t + val of_string : string -> t + val to_string : t -> string + val add_2_64 : t -> t + val is_even : t -> bool + val round_down_to_zero : t -> t -> t + val power_int_positive_int: int -> int -> t + val to_num : t -> Num.num + val popcount: t -> int +end +include S +val pretty : ?hexa:bool -> t Pretty_utils.formatter + +module M : S + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/my_bigint.ml.zarith frama-c-20111001+nitrogen+dfsg/src/lib/my_bigint.ml.zarith --- frama-c-20110201+carbon+dfsg/src/lib/my_bigint.ml.zarith 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/my_bigint.ml.zarith 2011-10-10 08:38:24.000000000 +0000 @@ -0,0 +1,314 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +type t = Big_int_Z.big_int +module M = struct + +include Big_int_Z + +let equal = Z.equal + +let compare = Z.compare + +let shift_left_big_int x y = + Z.shift_left x (Z.to_int y) + +let shift_right_big_int x y = + Z.shift_right x (Z.to_int y) + +let power_two k = + Z.shift_left Z.one k +(* + let h = Hashtbl.create 7 in + fun k -> + try + Hashtbl.find h k + with Not_found -> + let p = power_int_positive_int 2 k in + Hashtbl.add h k p; + p +*) + +let two_power y = + try + let k = int_of_big_int y in + power_two k + with Failure _ -> assert false + +let log_shift_right_big_int x y = (* no meaning for negative value of x *) + if (lt_big_int x zero_big_int) + then raise (Invalid_argument "log_shift_right_big_int") + else shift_right_big_int x y + +let popcount = Z.popcount + +(* To export *) + + let small_nums = Array.init 33 (fun i -> big_int_of_int i) + + let zero = zero_big_int + let one = unit_big_int + let minus_one = minus_big_int unit_big_int + let two = Z.of_int 2 + let four = Z.of_int 4 + let eight = Z.of_int 8 + let thirtytwo = Z.of_int 32 + let onethousand = Z.of_int 1000 + let billion_one = Z.of_int 1_000_000_001 + let two_power_60 = power_two 60 + let two_power_64 = power_two 64 + + let is_zero v = (sign_big_int v) = 0 + + let rem = mod_big_int + let div = div_big_int + let mul = mult_big_int + + let sub = sub_big_int + + let abs = abs_big_int + let succ = succ_big_int + let pred = pred_big_int + let neg = minus_big_int + + let add = add_big_int + + + let max_int_z = Z.of_int max_int + + let hash c = + try + int_of_big_int c + with Failure _ -> Z.to_int (Z.logand max_int_z c) + + let shift_right_logical = log_shift_right_big_int + let shift_right = shift_right_big_int + let shift_left = shift_left_big_int + + let logand = Z.logand + let lognot = Z.lognot + let logor = Z.logor + let logxor = Z.logxor + + let le = le_big_int + let lt = lt_big_int + let ge = ge_big_int + let gt = gt_big_int + + let to_int v = + try Z.to_int v + with Z.Overflow -> assert false + + let of_int = Z.of_int + + let of_int64 = Z.of_int64 + let to_int64 = Z.to_int64 + + let max_int64 = of_int64 Int64.max_int + let min_int64 = of_int64 Int64.min_int + let bits_of_max_float = of_int64 (Int64.bits_of_float max_float) + let bits_of_most_negative_float = + of_int64 (Int64.bits_of_float (-. max_float)) + + let of_string = big_int_of_string + let to_string = string_of_big_int + let to_float = float_of_big_int + let of_float _ = assert false + + let add_2_64 x = add two_power_64 x + + let pretty ?(hexa=false) fmt v = + let rec aux v = + if gt v two_power_60 then + let quo, rem = quomod_big_int v two_power_60 in + aux quo; + Format.fprintf fmt "%015LX" (to_int64 rem) + else + Format.fprintf fmt "%LX" (to_int64 v) + in + if hexa then + if equal v zero then Format.pp_print_string fmt "0" + else if gt v zero then (Format.pp_print_string fmt "0x"; aux v) + else (Format.pp_print_string fmt "-0x"; aux (minus_big_int v)) + else + Format.pp_print_string fmt (to_string v) + + let is_one v = equal one v + let pos_div = div + + let pos_rem = rem + let native_div = div + + let c_div u v = + let bad_div = div u v in + if (lt u zero) && not (is_zero (rem u v)) + then + if lt v zero + then pred bad_div + else succ bad_div + else bad_div + + + + let c_rem u v = + sub u (mul v (c_div u v)) + + + let cast ~size ~signed ~value = + if (not signed) + then + let factor = two_power size in logand value (pred factor) + else + let mask = two_power (sub size one) in + let p_mask = pred mask in + if equal (logand mask value) zero + then logand value p_mask + else + logor (lognot p_mask) value + + let length u v = succ (sub v u) + + let extract_bits ~start ~stop v = + assert (ge start zero && ge stop start); + (*Format.printf "%a[%a..%a]@\n" pretty v pretty start pretty stop;*) + let r = Z.extract v (to_int start) (to_int (length start stop)) in + (*Format.printf "%a[%a..%a]=%a@\n" pretty v pretty start pretty stop pretty r;*) + r + + let is_even v = is_zero (logand one v) + + (** [pgcd u 0] is allowed and returns [u] *) + let pgcd u v = + let r = + if is_zero v + then u + else gcd_big_int u v in + r + + let ppcm u v = + if u = zero || v = zero + then zero + else native_div (mul u v) (pgcd u v) + + let min = min_big_int + let max = max_big_int + + let round_down_to_zero v modu = + mul (pos_div v modu) modu + + (** [round_up_to_r m r modu] is the smallest number [n] such that + [n]>=[m] and [n] = [r] modulo [modu] *) + let round_up_to_r ~min:m ~r ~modu = + add (add (round_down_to_zero (pred (sub m r)) modu) r) modu + + (** [round_down_to_r m r modu] is the largest number [n] such that + [n]<=[m] and [n] = [r] modulo [modu] *) + let round_down_to_r ~max:m ~r ~modu = + add (round_down_to_zero (sub m r) modu) r + + let to_num b = + Num.num_of_big_int + (Big_int.big_int_of_string (Big_int_Z.string_of_big_int b)) +end +module type S = sig + val equal : t -> t -> bool + val compare : t -> t -> int + val le : t -> t -> bool + val ge : t -> t -> bool + val lt : t -> t -> bool + val gt : t -> t -> bool + val add : t -> t -> t + + val sub : t -> t -> t + + val mul : t -> t -> t + + val native_div : t -> t -> t + val rem : t -> t -> t + val pos_div : t -> t -> t + val c_div : t -> t -> t + + val c_rem : t -> t -> t + + val cast: size:t -> signed:bool -> value:t -> t + val abs : t -> t + val one : t + val two : t + val four : t + val onethousand : t + val minus_one : t + val is_zero : t -> bool + val is_one : t -> bool + val pgcd : t -> t -> t + val ppcm : t -> t -> t + val min : t -> t -> t + val max : t -> t -> t + val length : t -> t -> t (** b - a + 1 *) + val of_int : int -> t + val of_float : float -> t + val of_int64 : Int64.t -> t + val to_int64 : t -> int64 + val to_int : t -> int + val to_float : t -> float + val neg : t -> t + + val succ : t -> t + val pred : t -> t + val round_up_to_r : min:t -> r:t -> modu:t -> t + val round_down_to_r : max:t -> r:t -> modu:t -> t + val pos_rem : t -> t -> t + val shift_left : t -> t -> t + val shift_right : t -> t -> t + val logand : t -> t -> t + val logor : t -> t -> t + val logxor : t -> t -> t + val lognot : t -> t + val power_two : int -> t + val two_power : t -> t + val extract_bits : start:t -> stop:t -> t -> t + + val small_nums : t array + val zero : t + val eight : t + val thirtytwo : t + val div : t -> t -> t + + val billion_one : t + val hash : t -> int + val shift_right_logical : t -> t -> t + + val max_int64 : t + val min_int64 : t + val bits_of_max_float : t + val bits_of_most_negative_float : t + val of_string : string -> t + val to_string : t -> string + + val add_2_64 : t -> t + val is_even : t -> bool + val round_down_to_zero : t -> t -> t + val power_int_positive_int: int -> int -> t + val to_num : t -> Num.num + val popcount: t -> int +end +include M + diff -Nru frama-c-20110201+carbon+dfsg/src/lib/no_dynlink_opt.ml frama-c-20111001+nitrogen+dfsg/src/lib/no_dynlink_opt.ml --- frama-c-20110201+carbon+dfsg/src/lib/no_dynlink_opt.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/no_dynlink_opt.ml 2011-10-10 08:38:24.000000000 +0000 @@ -20,7 +20,7 @@ (* *) (**************************************************************************) -(* Implementation of [Dynlink_common_interface] compatible with +(* Implementation of [Dynlink_common_interface] compatible with ocamlopt < 3.11 *) module type OldDynlink = sig diff -Nru frama-c-20110201+carbon+dfsg/src/lib/pretty_utils.ml frama-c-20111001+nitrogen+dfsg/src/lib/pretty_utils.ml --- frama-c-20110201+carbon+dfsg/src/lib/pretty_utils.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/pretty_utils.ml 2011-10-10 08:38:24.000000000 +0000 @@ -55,15 +55,18 @@ let pp_list ?(pre=format_of_string "@[") ?(sep=format_of_string "") + ?(last=sep) ?(suf=format_of_string "@]") pp_elt f l = - let rec aux f l = - match l with - [] -> () - | e::l -> Format.fprintf f "%(%)%a%a" sep pp_elt e aux l - in match l with - [] -> () - | e::l -> Format.fprintf f "%(%)%a%a%(%)" pre pp_elt e aux l suf + let rec aux f = function + | [] -> assert false + | [ e ] -> Format.fprintf f "%a" pp_elt e + | [ e1; e2 ] -> Format.fprintf f "%a%(%)%a" pp_elt e1 last pp_elt e2 + | e :: l -> Format.fprintf f "%a%(%)%a" pp_elt e sep aux l + in + match l with + | [] -> () + | _ :: _ as l -> Format.fprintf f "%(%)%a%(%)" pre aux l suf let pp_array ?(pre=format_of_string "@[") @@ -73,17 +76,17 @@ match xs with | [| |] -> () | xs -> - begin - Format.fprintf f pre ; - pp_elt f 0 xs.(0) ; - for i = 1 to Array.length xs - 1 do - Format.fprintf f sep ; - pp_elt f i xs.(i) ; - done ; - Format.fprintf f suf ; - end + begin + Format.fprintf f pre ; + pp_elt f 0 xs.(0) ; + for i = 1 to Array.length xs - 1 do + Format.fprintf f sep ; + pp_elt f i xs.(i) ; + done ; + Format.fprintf f suf ; + end -let pp_iter +let pp_iter ?(pre=format_of_string "@[") ?(sep=format_of_string "") ?(suf=format_of_string "@]") @@ -108,23 +111,23 @@ let escape_underscores = Str.global_replace (Str.regexp_string "_") "__" -let pp_flowlist ?(left="(") ?(sep=",") ?(right=")") f out = +let pp_flowlist ?(left=format_of_string "(") ?(sep=format_of_string ",") ?(right=format_of_string ")") f out = function - | [] -> Format.fprintf out "%s%s" left right + | [] -> Format.fprintf out "%(%)%(%)" left right | x::xs -> - begin - Format.fprintf out "@[%s%a" left f x ; - List.iter (fun x -> Format.fprintf out "%s@,%a" sep f x) xs ; - Format.fprintf out "%s@]" right ; - end + begin + Format.fprintf out "@[%(%)%a" left f x ; + List.iter (fun x -> Format.fprintf out "%(%)@,%a" sep f x) xs ; + Format.fprintf out "%(%)@]" right ; + end -let pp_blocklist ?(left="{") ?(right="}") f out = +let pp_blocklist ?(left=format_of_string "{") ?(right=format_of_string "}") f out = function - | [] -> Format.fprintf out "%s%s" left right + | [] -> Format.fprintf out "%(%)%(%)" left right | xs -> - Format.fprintf out "@[%s@[" left ; - List.iter (fun x -> Format.fprintf out "@ %a" f x) xs ; - Format.fprintf out "@]@ %s@]" right + Format.fprintf out "@[%(%)@[" left ; + List.iter (fun x -> Format.fprintf out "@ %a" f x) xs ; + Format.fprintf out "@]@ %(%)@]" right let pp_open_block out msg = Format.fprintf out ("@[@[" ^^ msg) @@ -135,11 +138,11 @@ Format.fprintf fmt "@[(**" ; let out newlined fmt s k n = for i=k to k+n-1 do - if !newlined then - ( Format.fprintf fmt "@\n * " ; newlined := false ) ; - if s.[i] = '\n' - then newlined := true - else Format.pp_print_char fmt s.[i] + if !newlined then + ( Format.fprintf fmt "@\n * " ; newlined := false ) ; + if s.[i] = '\n' + then newlined := true + else Format.pp_print_char fmt s.[i] done in let nwl = ref true in @@ -151,6 +154,6 @@ (* Local Variables: -compile-command: "make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/pretty_utils.mli frama-c-20111001+nitrogen+dfsg/src/lib/pretty_utils.mli --- frama-c-20110201+carbon+dfsg/src/lib/pretty_utils.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/pretty_utils.mli 2011-10-10 08:38:24.000000000 +0000 @@ -20,92 +20,96 @@ (* *) (**************************************************************************) +(** Pretty-printer utilities. *) + +(* ********************************************************************** *) (** {2 pretty-printing to a string} *) +(* ********************************************************************** *) -(** similar as Format.sprintf, but %a are allowed in the formatting string*) val sfprintf: ('a,Format.formatter,unit,string) format4 -> 'a +(** similar as Format.sprintf, but %a are allowed in the formatting string*) val to_string: (Format.formatter -> 'a -> unit) -> 'a -> string (** {2 separators} *) -(** do nothing *) val no_sep: (unit,Format.formatter,unit) format +(** do nothing *) -(** a breakable space *) val space_sep: (unit,Format.formatter,unit) format +(** a breakable space *) -(** forces a newline *) val nl_sep: (unit,Format.formatter,unit) format +(** forces a newline *) -(** transforms every space in a string in breakable spaces.*) val pp_print_string_fill : Format.formatter -> string -> unit +(** transforms every space in a string in breakable spaces.*) -(** opens a new formatting box. *) val open_box: (unit,Format.formatter,unit) format +(** opens a new formatting box. *) -(** close a formatting box. *) val close_box: (unit,Format.formatter,unit) format +(** close a formatting box. *) val escape_underscores : string -> string +(* ********************************************************************** *) (** {2 pretty printers for standard types} *) +(* ********************************************************************** *) type sformat = (unit,Format.formatter,unit) Pervasives.format type 'a formatter = Format.formatter -> 'a -> unit type ('a,'b) formatter2 = Format.formatter -> 'a -> 'b -> unit +val pp_list: ?pre:sformat -> ?sep:sformat -> ?last:sformat -> ?suf:sformat -> (** pretty prints a list. The optional arguments stands for -- the prefix to output before a non-empty list (default: open a box) -- the separator between two elements (default: nothing) -- the suffix to output after a non-empty list (default: close box) -*) -val pp_list: ?pre:sformat -> ?sep:sformat -> ?suf:sformat -> + - the prefix to output before a non-empty list (default: open a box) + - the separator between two elements (default: nothing) + - the last separator to be put just before the last element (default:sep) + - the suffix to output after a non-empty list (default: close box) *) 'a formatter -> 'a list formatter -(** pretty prints an array. The optional arguments stands for -- the prefix to output before a non-empty list (default: open a box) -- the separator between two elements (default: nothing) -- the suffix to output after a non-empty list (default: close box) -*) val pp_array: ?pre:sformat -> ?sep:sformat -> ?suf:sformat -> (int,'a) formatter2 -> 'a array formatter +(** pretty prints an array. The optional arguments stands for + - the prefix to output before a non-empty list (default: open a box) + - the separator between two elements (default: nothing) + - the suffix to output after a non-empty list (default: close box) *) -(** pretty prints any structure using an iterator on it. The argument - [pre] (resp. [suf]) is output before (resp. after) the iterator - is started (resp. has ended). The optional argument [sep] is output bewteen - two calls to the ['a formatter]. Default: open a box for [pre], close - a box for [suf], nothing for [sep] -*) val pp_iter: ?pre:sformat -> ?sep:sformat -> ?suf:sformat -> (('a -> unit) -> 'b -> unit) -> 'a formatter -> 'b formatter +(** pretty prints any structure using an iterator on it. The argument + [pre] (resp. [suf]) is output before (resp. after) the iterator + is started (resp. has ended). The optional argument [sep] is output bewteen + two calls to the ['a formatter]. Default: open a box for [pre], close + a box for [suf], nothing for [sep]. *) - - -(** pretty-prints an optional value. Prefix and suffix default to nothing. - Nothing is printed if the option is None. -*) val pp_opt: ?pre:sformat -> ?suf:sformat -> 'a formatter -> 'a option formatter +(** pretty-prints an optional value. Prefix and suffix default to nothing. + Nothing is printed if the option is [None]. *) -(** pp_cond cond f s pretty-prints s if cond is true and the optional - pr_false, which defaults to nothing, otherwise *) val pp_cond: ?pr_false:sformat -> bool -> sformat formatter +(** [pp_cond cond f s] pretty-prints [s] if cond is [true] and the optional + pr_false, which defaults to nothing, otherwise *) +val pp_flowlist: + ?left:sformat -> ?sep:sformat -> ?right:sformat -> 'a formatter -> + 'a list formatter - -val pp_flowlist : ?left:string -> ?sep:string -> ?right:string -> 'a formatter -> 'a list formatter -val pp_blocklist : ?left:string -> ?right:string -> 'a formatter -> 'a list formatter +val pp_blocklist: + ?left:sformat -> ?right:sformat -> 'a formatter -> 'a list formatter val pp_open_block : Format.formatter -> ('a,Format.formatter,unit) format -> 'a val pp_close_block : Format.formatter -> ('a,Format.formatter,unit) format -> 'a -(** pretty-prints its contents inside an '(** ... **)' horizontal block trailed with '*' *) val pp_trail : 'a formatter -> 'a formatter +(** pretty-prints its contents inside an '(** ... **)' horizontal block trailed + with '*' *) (* Local Variables: -compile-command: "make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/lib/printexc_311_or_higher.ml frama-c-20111001+nitrogen+dfsg/src/lib/printexc_311_or_higher.ml --- frama-c-20110201+carbon+dfsg/src/lib/printexc_311_or_higher.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/printexc_311_or_higher.ml 2011-10-10 08:38:24.000000000 +0000 @@ -22,6 +22,7 @@ include Printexc exception No_backtrace +let has_backtrace = true let () = record_backtrace true (* diff -Nru frama-c-20110201+carbon+dfsg/src/lib/printexc_common_interface.ml frama-c-20111001+nitrogen+dfsg/src/lib/printexc_common_interface.ml --- frama-c-20110201+carbon+dfsg/src/lib/printexc_common_interface.ml 2011-02-07 14:02:38.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/printexc_common_interface.ml 2011-10-10 08:56:36.000000000 +0000 @@ -22,6 +22,7 @@ include Printexc exception No_backtrace +let has_backtrace = true let () = record_backtrace true (* diff -Nru frama-c-20110201+carbon+dfsg/src/lib/printexc_common_interface.mli frama-c-20111001+nitrogen+dfsg/src/lib/printexc_common_interface.mli --- frama-c-20110201+carbon+dfsg/src/lib/printexc_common_interface.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/printexc_common_interface.mli 2011-10-10 08:38:24.000000000 +0000 @@ -49,37 +49,40 @@ exception No_backtrace +val has_backtrace: bool +(** [true] if the backtrace feature is available (ocaml >= 3.11) *) + val print_backtrace: out_channel -> unit (** [Printexc.print_backtrace oc] prints an exception backtrace on the output channel [oc]. The backtrace lists the program locations where the most-recently raised exception was raised - and where it was propagated through function calls. + and where it was propagated through function calls. - @raise No_backtrace if this feature is not available + @raise No_backtrace if this feature is not available (OCaml < 3.11). *) val get_backtrace: unit -> string (** [Printexc.get_backtrace ()] returns a string containing the same exception backtrace that [Printexc.print_backtrace] would - print. + print. - @raise No_backtrace if this feature is not available + @raise No_backtrace if this feature is not available (OCaml < 3.11). *) val record_backtrace: bool -> unit (** [Printexc.record_backtrace b] turns recording of exception backtraces on (if [b = true]) or off (if [b = false]). Initially, backtraces are not recorded, unless the [b] flag is given to the program - through the [OCAMLRUNPARAM] variable. + through the [OCAMLRUNPARAM] variable. - @raise No_backtrace if this feature is not available + @raise No_backtrace if this feature is not available (OCaml < 3.11). *) val backtrace_status: unit -> bool (** [Printexc.backtrace_status()] returns [true] if exception - backtraces are currently recorded, [false] if not. + backtraces are currently recorded, [false] if not. - @raise No_backtrace if this feature is not available + @raise No_backtrace if this feature is not available (OCaml < 3.11). *) (* diff -Nru frama-c-20110201+carbon+dfsg/src/lib/printexc_lower_311.ml frama-c-20111001+nitrogen+dfsg/src/lib/printexc_lower_311.ml --- frama-c-20110201+carbon+dfsg/src/lib/printexc_lower_311.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/printexc_lower_311.ml 2011-10-10 08:38:24.000000000 +0000 @@ -22,6 +22,7 @@ include Printexc exception No_backtrace +let has_backtrace = false let print_backtrace _ = raise No_backtrace let get_backtrace () = raise No_backtrace let record_backtrace _ = raise No_backtrace diff -Nru frama-c-20110201+carbon+dfsg/src/lib/qstack.ml frama-c-20111001+nitrogen+dfsg/src/lib/qstack.ml --- frama-c-20110201+carbon+dfsg/src/lib/qstack.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/qstack.ml 2011-10-10 08:38:24.000000000 +0000 @@ -56,10 +56,10 @@ match t.first, t.last with | [], [] -> raise Empty | [], _ :: _ -> - transfer t; - (match t.first with - | [] -> assert false - | x :: _ -> x) + transfer t; + (match t.first with + | [] -> assert false + | x :: _ -> x) | x :: _, _ -> x let mem x t = diff -Nru frama-c-20110201+carbon+dfsg/src/lib/qstack.mli frama-c-20111001+nitrogen+dfsg/src/lib/qstack.mli --- frama-c-20110201+carbon+dfsg/src/lib/qstack.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/qstack.mli 2011-10-10 08:38:24.000000000 +0000 @@ -21,7 +21,7 @@ (**************************************************************************) (** Mutable stack in which it is possible to add data at the end (like a queue) - and to manage non top elements. + and to handle non top elements. Current implementation is double linked list. *) module type DATA = sig @@ -40,14 +40,14 @@ val singleton: D.t -> t (** Create a new qstack with a single element. - @since Boron-20100401 *) + @since Boron-20100401 *) val is_empty: t -> bool (** Test whether the stack is empty or not. *) val clear: t -> unit (** Remove all the elements of a stack. *) - + val add: D.t -> t -> unit (** Add at the beginning of the stack. Complexity: O(1). *) @@ -56,63 +56,63 @@ val top: t -> D.t (** Return the top element of the stack. Raise [Empty] if the stack is - empty. Complexity: amortized O(1). *) + empty. Complexity: amortized O(1). *) val mem: D.t -> t -> bool (** Return [true] if the data exists in the stack and [false] otherwise. - Complexity: O(n). *) + Complexity: O(n). *) val filter: (D.t -> bool) -> t -> D.t list - (** Return all data of the stack satisfying the specified predicate. - The order of the data in the input stack is preserved. - Not tail recursive. *) + (** Return all data of the stack satisfying the specified predicate. + The order of the data in the input stack is preserved. + Not tail recursive. *) val find: (D.t -> bool) -> t -> D.t - (** Return the first data of the stack satisfying the specified predicate. + (** Return the first data of the stack satisfying the specified predicate. @raise Not_found if there is no such data in the stack *) - + val remove: D.t -> t -> unit - (** Remove an element from the stack. - Complexity: O(n). *) + (** Remove an element from the stack. + Complexity: O(n). *) val move_at_top: D.t -> t -> unit (** Move the element [x] at the top of the stack [s]. - Complexity: O(n). - @raise Invalid_argument if [not (mem x s)]. *) + Complexity: O(n). + @raise Invalid_argument if [not (mem x s)]. *) val move_at_end: D.t -> t -> unit (** Move the element [x] at the end of the stack [s]. - Complexity: O(n). - @raise Invalid_argument if [not (mem x s)]. - @since Beryllium-20090901 *) + Complexity: O(n). + @raise Invalid_argument if [not (mem x s)]. + @since Beryllium-20090901 *) val iter: (D.t -> unit) -> t -> unit - (** Iter on all the elements from the top to the end of the stack. - Not tail recursive. *) + (** Iter on all the elements from the top to the end of the stack. + Not tail recursive. *) val map: (D.t -> D.t) -> t -> unit (** Replace in-place all the elements of the stack by mapping the old one. - Not tail recursive. - @since Beryllium-20090901 *) + Not tail recursive. + @since Beryllium-20090901 *) val fold: ('a -> D.t -> 'a) -> 'a -> t -> 'a - (** Fold on all the elements from the top to the end of the stack. - Not tail recursive. *) + (** Fold on all the elements from the top to the end of the stack. + Not tail recursive. *) val nth: int -> t -> D.t (** @return the n-th element of the stack, if any. - @raise Invalid_argument if there is not enough element in the stack. - @since Beryllium-20090901 *) + @raise Invalid_argument if there is not enough element in the stack. + @since Beryllium-20090901 *) val length: t -> int (** @return the length of the stack - @since Beryllium-20090901 *) + @since Beryllium-20090901 *) - val idx: D.t -> t -> int + val idx: D.t -> t -> int (** @return the index of the element in the stack @raise Not_found if the element is not in the stack This function is not tail recursive - @since Beryllium-20090901 *) + @since Beryllium-20090901 *) end diff -Nru frama-c-20110201+carbon+dfsg/src/lib/rangemap.ml frama-c-20111001+nitrogen+dfsg/src/lib/rangemap.ml --- frama-c-20110201+carbon+dfsg/src/lib/rangemap.ml 2011-02-07 13:53:58.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/rangemap.ml 2011-10-10 08:38:24.000000000 +0000 @@ -106,22 +106,22 @@ let x_in_table = Weak.get x_table x_ind in let d_in_table = Weak.get d_table d_ind in let x = match x_in_table with - | Some x_in_table when Ord.equal x x_in_table -> - (* Format.eprintf "cache found@." ; *) - x_in_table - | _ -> - (* Format.eprintf "cache failed@." ; *) - Weak.set x_table x_ind (Some x); - x + | Some x_in_table when Ord.equal x x_in_table -> + (* Format.eprintf "cache found@." ; *) + x_in_table + | _ -> + (* Format.eprintf "cache failed@." ; *) + Weak.set x_table x_ind (Some x); + x in let d = match d_in_table with - | Some d_in_table when Value.equal d d_in_table -> - (* Format.eprintf "cache found@." ; *) - d_in_table - | _ -> - (* Format.eprintf "cache failed@." ; *) - Weak.set d_table d_ind (Some d); - d + | Some d_in_table when Value.equal d d_in_table -> + (* Format.eprintf "cache found@." ; *) + d_in_table + | _ -> + (* Format.eprintf "cache failed@." ; *) + Weak.set d_table d_ind (Some d); + d in let hl = height l and hr = height r in let hashl = hash l and hashr = hash r in @@ -171,7 +171,7 @@ | Node(l, v, d, r, _, _) -> let c = Ord.compare x v in if c = 0 then - create l x data r + create l x data r else if c < 0 then bal (add x data l) v d r else @@ -461,12 +461,12 @@ | Node(l, v, d, r, _, _) -> let compar = o v in let accu1 = match compar with - | Match | Above -> fold_range o f l accu - | Below -> accu + | Match | Above -> fold_range o f l accu + | Below -> accu in let accu2 = match compar with - | Match -> f v d accu1 - | Above | Below -> accu1 + | Match -> f v d accu1 + | Above | Below -> accu1 in match compar with | Match | Below -> fold_range o f r accu2 @@ -500,9 +500,9 @@ | Node(l,k,v,r,_, _) -> if o k then begin - try - lowest_binding_above o l - with No_such_binding -> k,v + try + lowest_binding_above o l + with No_such_binding -> k,v end else lowest_binding_above o r | Empty -> raise No_such_binding @@ -519,28 +519,42 @@ let r = Recursive.create () let structural_descr = Structure - (Sum - [| [| Recursive r; - Ord.packed_descr; - Value.packed_descr; - Recursive r; - p_int; - p_int |] |] ) + (Sum + [| [| recursive_pack r; + Ord.packed_descr; + Value.packed_descr; + recursive_pack r; + p_int; + p_int |] |] ) let () = Recursive.update r structural_descr let reprs = List.fold_left - (fun acc k -> - List.fold_left - (fun acc v -> (Node(Empty, k, v, Empty, 0, 0)) :: acc) - acc - Value.reprs) - [ Empty ] - Ord.reprs + (fun acc k -> + List.fold_left + (fun acc v -> (Node(Empty, k, v, Empty, 0, 0)) :: acc) + acc + Value.reprs) + [ Empty ] + Ord.reprs let equal = equal let compare = compare let hash = hash let rehash = Datatype.identity - let copy = Datatype.undefined + let copy = + if Ord.copy == Datatype.undefined || Value.copy == Datatype.undefined + then Datatype.undefined + else + let rec aux = + function + | Empty -> Empty + | Node (l,x,d,r,_,_) -> + let l = aux l in + let x = Ord.copy x in + let d = Value.copy d in + let r = aux r in + create l x d r + in aux + let internal_pretty_code = Datatype.undefined let pretty = Datatype.undefined let varname = Datatype.undefined @@ -560,4 +574,3 @@ compile-command: "make -C ../.." End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/lib/rangemap.mli frama-c-20111001+nitrogen+dfsg/src/lib/rangemap.mli --- frama-c-20110201+carbon+dfsg/src/lib/rangemap.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/lib/rangemap.mli 2011-10-10 08:38:24.000000000 +0000 @@ -169,7 +169,7 @@ for each [k] present in either [m1] and [m2], [v_i] being [Some (find k m_i)] if [k] is in [m_i], and [None] otherwise (for [i=1] or [i=2]) *) - + val exists2: (key -> value option -> value option -> bool) -> t -> t -> bool (** [exists2 f m1 m2] returns true if and only there exists [k] present in [m1] or [m2] such that [f k v1 v2] holds, @@ -201,7 +201,7 @@ val fold_range: (key -> fuzzy_order) -> - (key -> Value.t -> Value.t -> Value.t) -> t -> Value.t -> Value.t + (key -> Value.t -> 'a -> 'a) -> t -> 'a -> 'a val height: t -> int diff -Nru frama-c-20110201+carbon+dfsg/src/logic/description.ml frama-c-20111001+nitrogen+dfsg/src/logic/description.ml --- frama-c-20110201+carbon+dfsg/src/logic/description.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/description.ml 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,250 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Property +open Cil_types + +let pp_loc fmt loc = + let file = Filename.basename (fst loc).Lexing.pos_fname in + let line = (fst loc).Lexing.pos_lnum in + if file <> "." && file <> "" && line > 0 then + Format.fprintf fmt "file %s, line %d" file line + else + Format.fprintf fmt "generated" + +let goto_stmt stmt = + let rec goto_label = function + | [] -> Printf.sprintf "s%04d" stmt.sid + | Label(a,_,true)::_ -> a + | _::labels -> goto_label labels + in goto_label stmt.labels + +let rec stmt_labels = function + | Label(a,_,true) :: ls -> a :: stmt_labels ls + | Label _ :: ls -> stmt_labels ls + | Case(e,_) :: ls -> + let cvalue = (Cil.constFold true e) in + Pretty_utils.sfprintf "case %a" !Ast_printer.d_exp cvalue + :: stmt_labels ls + | Default _ :: ls -> + "default" :: stmt_labels ls + | [] -> [] + +let pp_labels fmt stmt = + match stmt_labels stmt.labels with + | [] -> () + | ls -> Format.fprintf fmt " '%s'" (String.concat "," ls) + +let pp_idpred fmt idpred = + if idpred.ip_name <> [] + then Format.fprintf fmt "'%s'" (String.concat "," idpred.ip_name) + else Format.fprintf fmt "(%a)" pp_loc idpred.ip_loc + +let pp_froms fmt (region:identified_term from list) = + if region = [] then Format.fprintf fmt "nothing" + else + let names = + List.concat (List.map (fun (t,_deps) -> t.it_content.term_name) region) + in + if names <> [] then Format.fprintf fmt "'%s'" (String.concat "," names) + else + match region with + | [] -> assert false + | (x, _) :: _ -> Format.fprintf fmt "(%a)" pp_loc x.it_content.term_loc + +let pp_bhv fmt bhv = + if not (Cil.is_default_behavior bhv) then + Format.fprintf fmt " for '%s'" bhv.b_name + +let pp_bhvs fmt = function + | [] -> Format.fprintf fmt "" + | b::bs -> + Format.fprintf fmt "@['%s'" b ; + List.iter (fun b -> Format.fprintf fmt ",@ '%s'" b) bs ; + Format.fprintf fmt "@]" + +let pp_for fmt = function + | [] -> () + | bs -> Format.fprintf fmt " for '%s'" (String.concat "," bs) + +let pp_named fmt nx = + if nx.name <> [] then Format.fprintf fmt " '%s'" (String.concat "," nx.name) + +let pp_code_annot fmt ca = + match ca.annot_content with + | AAssert(bs,np) -> Format.fprintf fmt "assertion%a%a" pp_for bs pp_named np + | AInvariant(bs,_,np) -> + Format.fprintf fmt "invariant%a%a" pp_for bs pp_named np + | AAssigns(bs,_) -> Format.fprintf fmt "assigns%a" pp_for bs + | APragma _ -> Format.pp_print_string fmt "pragma" + | AVariant _ -> Format.pp_print_string fmt "variant" + | AStmtSpec _ -> Format.pp_print_string fmt "block contract" + +let pp_stmt fmt stmt = + match stmt.skind with + | Instr (Call(_,{enode=Lval(Var v,_)},_,loc)) -> + Format.fprintf fmt "call '%s' (%a)" v.vname pp_loc loc + | Instr (Set(_,_,loc)|Call(_,_,_,loc)) -> + Format.fprintf fmt "instruction (%a)" pp_loc loc + | Instr (Asm(_,_,_,_,_,loc)) -> + Format.fprintf fmt "assembly%a (%a)" pp_labels stmt pp_loc loc + | Instr (Skip(_,loc)) -> + Format.fprintf fmt "program point%a (%a)" + pp_labels stmt pp_loc (loc,loc) + | Instr (Code_annot(ca,loc)) -> + Format.fprintf fmt "%a (%a)" pp_code_annot ca pp_loc loc + | Return(_,loc) -> Format.fprintf fmt "return (%a)" pp_loc loc + | Goto(s,loc) -> Format.fprintf fmt "goto %s (%a)" (goto_stmt !s) pp_loc loc + | Break loc -> Format.fprintf fmt "break (%a)" pp_loc loc + | Continue loc -> Format.fprintf fmt "continue (%a)" pp_loc loc + | If(_,_,_,loc) -> Format.fprintf fmt "if-then-else (%a)" pp_loc loc + | Switch(_,_,_,loc) -> Format.fprintf fmt "switch (%a)" pp_loc loc + | Loop(_,_,loc,_,_) -> Format.fprintf fmt "loop (%a)" pp_loc loc + | Block _ -> Format.fprintf fmt "block%a" pp_labels stmt + | UnspecifiedSequence _ -> Format.fprintf fmt "instruction%a" pp_labels stmt + | TryFinally(_,_,loc) | TryExcept(_,_,_,loc) -> + Format.fprintf fmt "try-catch (%a)" pp_loc loc + +let pp_kf fmt = function + | None -> () + | Some kf -> Format.fprintf fmt " in '%s'" (Kernel_function.get_name kf) + +let pp_kinstr fmt = function + | Kglobal -> () + | Kstmt s -> Format.fprintf fmt " at %a" pp_stmt s + +let pp_predicate fmt = function + | PKRequires bhv -> + Format.fprintf fmt "Pre-condition%a" pp_bhv bhv + | PKAssumes bhv -> + Format.fprintf fmt "Assumption%a" pp_bhv bhv + | PKEnsures(bhv,Normal) -> + Format.fprintf fmt "Post-condition%a" pp_bhv bhv + | PKEnsures(bhv,Breaks) -> + Format.fprintf fmt "Breaking-condition%a" pp_bhv bhv + | PKEnsures(bhv,Continues) -> + Format.fprintf fmt "Continue-condition%a" pp_bhv bhv + | PKEnsures(bhv,Returns) -> + Format.fprintf fmt "Return-condition%a" pp_bhv bhv + | PKEnsures(bhv,Exits) -> + Format.fprintf fmt "Exit-condition%a" pp_bhv bhv + | PKTerminates -> + Format.fprintf fmt "Termination-condition" + +let pp_opt doit pp fmt x = if doit then pp fmt x +let pp_context kfopt fmt = function + | None -> () + | Some kf -> + match kfopt with + | `Always -> + Format.fprintf fmt " in '%s'" (Kernel_function.get_name kf) + | `Never -> () + | `Context kf0 -> + if not (Kernel_function.equal kf0 kf) then + Format.fprintf fmt " of '%s'" (Kernel_function.get_name kf) + +let rec pp_prop kfopt kiopt fmt = function + | IPAxiom s -> Format.fprintf fmt "Axiom '%s'" s + | IPLemma s -> Format.fprintf fmt "Lemma '%s'" s + | IPAxiomatic (s,_) -> Format.fprintf fmt "Axiomatic '%s'" s + | IPOther(s,kf,ki) -> Format.fprintf fmt "%s%a%a" s + (pp_context kfopt) kf (pp_opt kiopt pp_kinstr) ki + | IPPredicate(kind,kf,Kglobal,idpred) -> + Format.fprintf fmt "%a %a%a" + pp_predicate kind + pp_idpred idpred + (pp_context kfopt) (Some kf) + | IPPredicate(kind,_,ki,idpred) -> + Format.fprintf fmt "%a %a%a" + pp_predicate kind + pp_idpred idpred + pp_kinstr ki + | IPBehavior(_,ki,bhv) -> + if Cil.is_default_behavior bhv then + Format.fprintf fmt "Default behavior%a" (pp_opt kiopt pp_kinstr) ki + else + Format.fprintf fmt "Behavior '%s'%a" + bhv.b_name + (pp_opt kiopt pp_kinstr) ki + | IPComplete(_,ki,bs) -> + Format.fprintf fmt "Complete behaviors %a%a" + pp_bhvs bs + (pp_opt kiopt pp_kinstr) ki + | IPDisjoint(_,ki,bs) -> + Format.fprintf fmt "Disjoint behaviors %a%a" + pp_bhvs bs + (pp_opt kiopt pp_kinstr) ki + | IPCodeAnnot(_,_,{annot_content=AAssert(bs,np)}) -> + Format.fprintf fmt "Assertion%a%a (%a)" + pp_for bs + pp_named np + pp_loc np.loc + | IPCodeAnnot(_,_,{annot_content=AInvariant(bs,_,np)}) -> + Format.fprintf fmt "Invariant%a%a (%a)" + pp_for bs + pp_named np + pp_loc np.loc + | IPCodeAnnot(_,stmt,_) -> + Format.fprintf fmt "Annotation %a" pp_stmt stmt + | IPAssigns(kf,Kglobal,Id_behavior bhv,region) -> + Format.fprintf fmt "Assigns%a %a%a" + pp_bhv bhv + pp_froms region + (pp_context kfopt) (Some kf) + | IPFrom (kf,Kglobal,Id_behavior bhv,depend) -> + Format.fprintf fmt "Froms%a %a%a" + pp_bhv bhv + pp_froms [depend] + (pp_context kfopt) (Some kf) + | IPAssigns(_,ki,Id_behavior bhv,region) -> + Format.fprintf fmt "Assigns%a %a%a" + pp_bhv bhv + pp_froms + region (pp_opt kiopt pp_kinstr) ki + | IPFrom (_,ki,Id_behavior bhv,depend) -> + Format.fprintf fmt "Froms%a %a%a" + pp_bhv bhv + pp_froms [depend] + (pp_opt kiopt pp_kinstr) ki + | IPAssigns(_,_,Id_code_annot _,region) -> + Format.fprintf fmt "Loop assigns %a" pp_froms region + | IPFrom(_,_,Id_code_annot _,depend) -> + Format.fprintf fmt "Loop froms %a" pp_froms [depend] + | IPDecrease(_,Kglobal,_,_) -> + Format.fprintf fmt "Recursion variant" + | IPDecrease(_,Kstmt stmt,_,_) -> + Format.fprintf fmt "Loop variant at %a" pp_stmt stmt + | IPUnreachable ( UStmt(_,stmt) ) -> + Format.fprintf fmt "Unreachable %a" pp_stmt stmt + | IPUnreachable ( UProperty ip ) -> + Format.fprintf fmt "%a is unreachable" (pp_prop kfopt kiopt) ip + +type kf = [ `Always | `Never | `Context of kernel_function ] + +let pp_property = pp_prop `Always true +let pp_localized ~kf ~ki = pp_prop kf ki + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/description.mli frama-c-20111001+nitrogen+dfsg/src/logic/description.mli --- frama-c-20110201+carbon+dfsg/src/logic/description.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/description.mli 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Module for Describing items of Source and Properties. + @since Nitrogen-20111001 *) + +open Cil_types + +val pp_loc : Format.formatter -> location -> unit +(** prints "" or "generated" *) + +val pp_stmt : Format.formatter -> stmt -> unit +(** prints " ()" *) + +val pp_kinstr : Format.formatter -> kinstr -> unit +(** prints nothing for global, or " at " *) + +val pp_idpred : Format.formatter -> identified_predicate -> unit +(** prints the "''" or the "()" of the predicate *) + +val pp_froms : Format.formatter -> identified_term from list -> unit +(** prints message "nothing" or the "''" or the "()" of the + relation *) + +val pp_for : Format.formatter -> string list -> unit +(** prints nothing or " for 'b1,...,bn'" *) + +val pp_bhv : Format.formatter -> funbehavior -> unit +(** prints nothing for default behavior, and " for 'b'" otherwize *) + +val pp_property : Format.formatter -> Property.t -> unit +(** prints an identified property *) + +type kf = [ `Always | `Never | `Context of kernel_function ] + +val pp_localized : kf:kf -> ki:bool -> Format.formatter -> Property.t -> unit +(** prints more-or-less localized property *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/infer_annotations.ml frama-c-20111001+nitrogen+dfsg/src/logic/infer_annotations.ml --- frama-c-20110201+carbon+dfsg/src/logic/infer_annotations.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/infer_annotations.ml 2011-10-10 08:38:23.000000000 +0000 @@ -25,7 +25,6 @@ open Cil open Cil_types open Db -open Db_types open Logic_const let assigns_from_prototype vi = @@ -40,7 +39,7 @@ List.partition (fun vi -> isPointerType vi.vtype) formals in (* Remove pointer to pointer types and pointer to void *) let pointer_args = - List.filter + List.filter (fun vi -> not (isVoidPtrType vi.vtype || isPointerType (typeOf_pointed vi.vtype))) pointer_args in @@ -54,8 +53,8 @@ let loc = v.vdecl in match get_length typ with [AInt length] -> - let low = Logic_const.tinteger ~loc 0 in - let high = Logic_const.tinteger ~loc (length - 1) in + let low = Logic_const.tinteger ~loc ~ikind:IInt 0 in + let high = Logic_const.tinteger ~loc ~ikind:IInt (length - 1) in let range = Logic_const.trange ~loc (Some low,Some high) in let shift = Logic_const.term ~loc (TBinOp(PlusPI,tvar(cvar_to_lvar v),range)) @@ -102,157 +101,188 @@ List.map (fun content -> content, From inputs) to_assign in match rtyp with - | TVoid _ -> - (* assigns all pointer args from basic args and - content of pointer args *) - Writes arguments - | _ -> (* assigns result from basic args and content of pointer args *) - let loc = vi.vdecl in - Writes - ((Logic_const.new_identified_term - (Logic_const.tat ~loc - (Logic_const.tresult ~loc rtyp, - Logic_const.post_label)),From inputs):: arguments) + | TVoid _ -> + (* assigns all pointer args from basic args and content of pointer args *) + Writes arguments + | _ -> + (* assigns result from basic args and content of pointer args *) + let loc = vi.vdecl in + Writes + ((Logic_const.new_identified_term + (Logic_const.tat ~loc + (Logic_const.tresult ~loc rtyp, + Logic_const.post_label)),From inputs):: arguments) let is_frama_c_builtin name = (Ast_info.is_frama_c_builtin name) || (!Db.Value.mem_builtin name) +(* No need to call [Kernel_function.set_spec] here: update manually done *) let populate_funspec kf = assert (not (Kernel_function.is_definition kf)); let name = Kernel_function.get_name kf in - let generated_assigns = - lazy (assigns_from_prototype (Kernel_function.get_vi kf)) + let generated_assigns = + lazy (assigns_from_prototype (Kernel_function.get_vi kf)) in - let default_behavior = lazy (Cil.find_default_behavior kf.spec) - (* Do not call Kernel_function.get_spec: this would make an infinite recursion.*) - in - let generated_behavior () = - {b_name = "generated"; b_post_cond = [] ; - b_assumes = []; - b_requires = []; - b_assigns = Lazy.force generated_assigns; - b_extended = [];} - in - match kf.spec.spec_behavior with - | [] -> (* there is no initial specification -> use generated_behavior *) + let default_behavior = lazy (Cil.find_default_behavior kf.spec) in + (* Do not call Kernel_function.get_spec: this would make an infinite + recursion. *) + let generated_behavior () = + { b_name = "generated"; + b_post_cond = [] ; + b_assumes = []; + b_requires = []; + b_assigns = Lazy.force generated_assigns; + b_extended = [] } + in + let modify_spec (spec:funspec) = + let spec_behavior = spec.spec_behavior in + (match spec_behavior with + | [] -> + (* there is no initial specification -> use generated_behavior *) if not (is_frama_c_builtin name) then begin - CilE.log_once + Kernel.warning ~once:true "No code for function %a, default assigns generated" - Kernel_function.pretty_name kf; + Kernel_function.pretty kf; end; - kf.spec.spec_behavior <- [generated_behavior ()] - | _ -> + spec.spec_behavior <- [ generated_behavior () ] + | _ :: _ -> let assigns_of_behaviors bhvs_set = - List.fold_left - (fun acc b -> - List.fold_left - (fun acc a -> - match a.b_assigns, acc with - WritesAny, a | a, WritesAny -> a - | Writes l1, Writes l2 -> Writes (l1@l2)) - acc b) - WritesAny - bhvs_set + let res = + List.fold_left + (List.fold_left + (fun acc a -> match a.b_assigns, acc with + | WritesAny, a | a, WritesAny -> a + | Writes l1, Writes l2 -> Writes (l1 @ l2))) + WritesAny + bhvs_set + in + match res with + | WritesAny -> Lazy.force generated_assigns + | Writes _ -> res in (* Note-1: - looking at sets of complete behaviors: - if there is one of these sets - such that all of its behaviors have an assigns clause, - no assigns clause (equivalent to assigns everything) + looking at sets of complete behaviors: + if there is one of these sets + such that all of its behaviors have an assigns clause, + no assigns clause (equivalent to assigns everything) shoud be generated. *) - let complete_behaviors_with_assigns = - List.fold_left - (fun acc bhv_names -> + let complete_behaviors_with_assigns = + List.fold_left + (fun acc bhv_names -> try - let bhvs = match bhv_names with - | [] -> (* clause: complete behaviors; *) - List.filter - (fun b -> - if not (Cil.is_default_behavior b) then + let bhvs = match bhv_names with + | [] -> + (* clause: complete behaviors; *) + List.filter + (fun b -> + if not (Cil.is_default_behavior b) then if (b.b_assigns = WritesAny) then - (* there is one behavior without assigns clause *) + (* there is one behavior without assigns clause *) raise Not_found else true else false) - kf.spec.spec_behavior - | _ -> (* clause: complete behaviors bhvs; *) - List.map - (fun x -> - let b = - List.find (fun b -> b.b_name = x) kf.spec.spec_behavior - in + spec_behavior + | _ :: _ -> + (* clause: complete behaviors bhvs; *) + List.map + (fun x -> + let b = List.find (fun b -> b.b_name = x) spec_behavior in if (b.b_assigns = WritesAny) then - (* there is one behavior without any assigns clause *) + (* there is one behavior without any assigns clause *) raise Not_found; - b) bhv_names - in bhvs::acc (* all behaviors of bhvs have an assigns clause *) - with Not_found -> acc) + b) + bhv_names + in + (* all behaviors of bhvs have an assigns clause *) + bhvs :: acc + with Not_found -> + acc) [] kf.spec.spec_complete_behaviors in - (* Note-2: - If in such case a more accurate assigns clauses - needs to be generated, - it can be done without using the prototype, - but only from the union of the assigns clauses of that set. *) - let generated_assigns,new_assigns = + (* Note-2: If in such case a more accurate assigns clauses needs to be + generated, it can be done without using the prototype, but only from + the union of the assigns clauses of that set. + *) + let generated_assigns,new_assigns = match complete_behaviors_with_assigns with - | [] -> - generated_assigns, - lazy (assigns_of_behaviors [kf.spec.spec_behavior]) - | _ -> - let new_assigns = + | [] -> + let assigns_of_behavior = + lazy (assigns_of_behaviors [ spec_behavior ]) + in + let generated_assigns = + (* If all named behaviors have assigns clause, take the union + of locations as the assigns clause, even if it is not + advertised as complete behaviors. Not more arbitrary than + using prototype to infer assigns. + *) + if + List.for_all + (fun b -> + Cil.is_default_behavior b || b.b_assigns <> WritesAny) + spec_behavior + then assigns_of_behavior + else generated_assigns + in + generated_assigns, assigns_of_behavior + | _ -> + let new_assigns = lazy (assigns_of_behaviors complete_behaviors_with_assigns) - in new_assigns, new_assigns + in + new_assigns, new_assigns in + let register_assigns b a = b.b_assigns <- a in if not (is_frama_c_builtin name) then begin - (* Generates an "assigns" clause to behaviors without "assigns" clause *) - let set_assigns behavior = - match behavior.b_assigns with - | WritesAny -> - let new_assigns = - if Cil.is_default_behavior behavior then begin - CilE.log_once - "No code for function %a, default assigns generated" - Kernel_function.pretty_name kf; - Lazy.force generated_assigns - end else begin - match Lazy.force default_behavior with - | None -> - CilE.log_once - "No code for function %a, default assigns generated \ + (* Generates an "assigns" clause to behaviors without "assigns" + clause *) + let set_assigns behavior = match behavior.b_assigns with + | WritesAny -> + let new_assigns = + if Cil.is_default_behavior behavior then begin + Kernel.warning ~once:true + "No code for function %a, default assigns generated for \ +default behavior" + Kernel_function.pretty kf; + Lazy.force generated_assigns + end else begin + match Lazy.force default_behavior with + | None -> + Kernel.warning ~once:true + "No code for function %a, default assigns generated \ for behavior %s" - Kernel_function.pretty_name kf - behavior.b_name ; - Lazy.force generated_assigns - | Some a -> - CilE.log_once - "No code for function %a, default assigns used \ + Kernel_function.pretty kf behavior.b_name; + Lazy.force generated_assigns + | Some a -> + Kernel.warning ~once:true + "No code for function %a, default assigns used \ for behavior %s" - Kernel_function.pretty_name kf - behavior.b_name; - a.b_assigns - end - in - behavior.b_assigns <- new_assigns - | _ -> () + Kernel_function.pretty kf + behavior.b_name; + a.b_assigns + end + in + register_assigns behavior new_assigns + | _ -> () in - List.iter set_assigns kf.spec.spec_behavior; + List.iter set_assigns spec_behavior; end; - if List.for_all (fun {b_assumes=a} -> a<>[]) kf.spec.spec_behavior - then - let generated_behavior = generated_behavior () in - begin match Lazy.force new_assigns with + if List.for_all (fun {b_assumes=a} -> a <> []) spec_behavior then begin + match Lazy.force new_assigns with | WritesAny -> () - | l -> generated_behavior.b_assigns <- l; - end; - kf.spec.spec_behavior <- generated_behavior::kf.spec.spec_behavior - + | l -> + let generated_behavior = generated_behavior () in + register_assigns generated_behavior l; + spec.spec_behavior <- generated_behavior :: spec.spec_behavior + end); + spec + in + Kernel_function.set_spec kf modify_spec + let () = Kernel_function.populate_spec := populate_funspec (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/infer_annotations.mli frama-c-20111001+nitrogen+dfsg/src/logic/infer_annotations.mli --- frama-c-20110201+carbon+dfsg/src/logic/infer_annotations.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/infer_annotations.mli 2011-10-10 08:38:23.000000000 +0000 @@ -22,6 +22,4 @@ (* *) (**************************************************************************) -(*i $Id: infer_annotations.mli,v 1.9 2008-04-01 09:25:21 uid568 Exp $ i*) - (** This is empty on purpose. *) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/logic_interp.ml frama-c-20111001+nitrogen+dfsg/src/logic/logic_interp.ml --- frama-c-20110201+carbon+dfsg/src/logic/logic_interp.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/logic_interp.ml 2011-10-10 08:38:23.000000000 +0000 @@ -26,12 +26,7 @@ open Cil_types open Cilutil open Cil_datatype -open Db -open Db_types -open Logic_typing -open Extlib open Ast_info -open Visitor exception Error of Cil_types.location * string @@ -51,40 +46,48 @@ in cvar_to_lvar vi -let code_annot kf stmt ~before:_ s = +let code_annot kf stmt s = let file = Ast.get () in let loc = snd (Cabshelper.currentLoc ()) in let pa = match Logic_lexer.annot (loc, s) with | Logic_ptree.Acode_annot (_,a) -> a | _ -> - error (Stmt.loc stmt) - "Syntax error (expecting a code annotation)" + error (Stmt.loc stmt) + "Syntax error (expecting a code annotation)" in let module LT = Logic_typing.Make (struct - let annonCompFieldName = Cabs2cil.annonCompFieldName - let conditionalConversion = Cabs2cil.logicConditionalConversion + let anonCompFieldName = Cabs2cil.anonCompFieldName + let conditionalConversion = Cabs2cil.logicConditionalConversion - let find_macro _ = raise Not_found + let find_macro _ = raise Not_found - let find_var x = find_var kf stmt file x + let find_var x = find_var kf stmt file x - let find_enum_tag _ = assert false (*TODO*) + let find_enum_tag _ = assert false (*TODO*) - let find_comp_type ~kind:_ _s = assert false (*TODO*) + let find_comp_type ~kind:_ _s = assert false (*TODO*) let find_comp_field info s = let field = Cil.getCompField info s in Field(field,NoOffset) - let find_type _s = assert false (*TODO*) + let find_type _s = assert false (*TODO*) - let find_label s = Kernel_function.find_label kf s + let find_label s = Kernel_function.find_label kf s include Logic_env - let add_logic_function = - add_logic_function_gen Logic_utils.is_same_logic_profile + let add_logic_function = + add_logic_function_gen Logic_utils.is_same_logic_profile + + let integral_cast ty t = + raise + (Failure + (Pretty_utils.sfprintf + "term %a has type %a, but %a is expected." + Cil.d_term t Cil.d_logic_type Linteger Cil.d_type ty)) + end) in LT.code_annot (Stmt.loc stmt) @@ -101,30 +104,37 @@ let module LT = Logic_typing.Make (struct - let annonCompFieldName = Cabs2cil.annonCompFieldName - let integralPromotion = Cabs2cil.integralPromotion - let arithmeticConversion = Cabs2cil.arithmeticConversion - let conditionalConversion = Cabs2cil.logicConditionalConversion + let anonCompFieldName = Cabs2cil.anonCompFieldName + let integralPromotion = Cabs2cil.integralPromotion + let arithmeticConversion = Cabs2cil.arithmeticConversion + let conditionalConversion = Cabs2cil.logicConditionalConversion - let find_macro _ = raise Not_found + let find_macro _ = raise Not_found - let find_var x = find_var kf stmt file x + let find_var x = find_var kf stmt file x - let find_enum_tag _x = assert false (*TODO*) + let find_enum_tag _x = assert false (*TODO*) - let find_comp_type ~kind:_ _s = assert false (*TODO*) + let find_comp_type ~kind:_ _s = assert false (*TODO*) let find_comp_field info s = let field = Cil.getCompField info s in Field(field,NoOffset) - let find_type _s = assert false (*TODO*) + let find_type _s = assert false (*TODO*) - let find_label s = Kernel_function.find_label kf s + let find_label s = Kernel_function.find_label kf s include Logic_env - let add_logic_function = - add_logic_function_gen Logic_utils.is_same_logic_profile + let add_logic_function = + add_logic_function_gen Logic_utils.is_same_logic_profile + let integral_cast ty t = + raise + (Failure + (Pretty_utils.sfprintf + "term %a has type %a, but %a is expected." + Cil.d_term t Cil.d_logic_type Linteger Cil.d_type ty)) + end) in @@ -136,7 +146,7 @@ | _ -> error (Stmt.loc stmt) "Syntax error (expecting an lvalue)" (* may raise [Invalid_argument "not an lvalue"] *) -let error_lval () = raise (Invalid_argument "not an lvalue") +let error_lval () = invalid_arg "not an lvalue" (* Force conversion from terms to expressions by returning, along with * the result, a map of the sub-terms that could not be converted as @@ -211,28 +221,28 @@ | Ctype (TArray _) -> add_opaque_term t empty_term_env | _ -> let lv,env = force_term_lval_to_lval tlv in Lval lv, env) | TAddrOf tlv -> - let lv,env = force_term_lval_to_lval tlv in AddrOf lv, env + let lv,env = force_term_lval_to_lval tlv in AddrOf lv, env | TStartOf tlv -> - let lv,env = force_term_lval_to_lval tlv in StartOf lv, env + let lv,env = force_term_lval_to_lval tlv in StartOf lv, env | TSizeOfE t' -> - let e,env = force_term_to_exp t' in SizeOfE e, env + let e,env = force_term_to_exp t' in SizeOfE e, env | TAlignOfE t' -> - let e,env = force_term_to_exp t' in AlignOfE e, env + let e,env = force_term_to_exp t' in AlignOfE e, env | TUnOp(unop,t') -> - let e,env = force_term_to_exp t' in - UnOp(unop,e,logic_type_to_typ t.term_type), env + let e,env = force_term_to_exp t' in + UnOp(unop,e,logic_type_to_typ t.term_type), env | TBinOp(binop,t1,t2) -> - let e1,env1 = force_term_to_exp t1 in - let e2,env2 = force_term_to_exp t2 in - let env = merge_term_env env1 env2 in - BinOp(binop,e1,e2,logic_type_to_typ t.term_type), env + let e1,env1 = force_term_to_exp t1 in + let e2,env2 = force_term_to_exp t2 in + let env = merge_term_env env1 env2 in + BinOp(binop,e1,e2,logic_type_to_typ t.term_type), env | TSizeOfStr string -> SizeOfStr string, empty_term_env | TConst constant -> Const constant, empty_term_env | TCastE(ty,t') -> - let e,env = force_term_to_exp t' in CastE(ty,e), env + let e,env = force_term_to_exp t' in CastE(ty,e), env | TAlignOf ty -> AlignOf ty, empty_term_env | TSizeOf ty -> SizeOf ty, empty_term_env - | Tapp _ | TDataCons _ | Tif _ | Told _ | Tat _ | Tbase_addr _ + | Tapp _ | TDataCons _ | Tif _ | Tat _ | Tbase_addr _ | Tblock_length _ | Tnull | TCoerce _ | TCoerceE _ | TUpdate _ | Tlambda _ | Ttypeof _ | Ttype _ | Tcomprehension _ | Tunion _ | Tinter _ | Tempty_set | Trange _ | Tlet _ @@ -250,12 +260,12 @@ and force_term_lhost_to_lhost lhost = match lhost with | TVar v -> begin match v.lv_origin with - | Some v -> Var v, empty_term_env - | None -> - begin match v.lv_type with - | Ctype _ty -> add_opaque_var v empty_term_env - | _ -> add_opaque_term_lhost lhost empty_term_env - end + | Some v -> Var v, empty_term_env + | None -> + begin match v.lv_type with + | Ctype _ty -> add_opaque_var v empty_term_env + | _ -> add_opaque_term_lhost lhost empty_term_env + end end | TMem t -> let e,env = force_term_to_exp t in @@ -288,10 +298,10 @@ | Info _ -> assert false | Const c -> TConst c | Lval(Var v,NoOffset as lv) -> - begin try (Varinfo.Map.find v env.terms).term_node - with Not_found -> - TLval(force_back_lval_to_term_lval env lv) - end + begin try (Varinfo.Map.find v env.terms).term_node + with Not_found -> + TLval(force_back_lval_to_term_lval env lv) + end | Lval lv -> TLval(force_back_lval_to_term_lval env lv) | SizeOf ty -> TSizeOf ty | SizeOfE e -> TSizeOfE(internal_force_back env e) @@ -300,8 +310,8 @@ | AlignOfE e -> TAlignOfE(internal_force_back env e) | UnOp(op,e,_) -> TUnOp(op,internal_force_back env e) | BinOp(op,e1,e2,_) -> - TBinOp(op, - internal_force_back env e1, internal_force_back env e2) + TBinOp(op, + internal_force_back env e1, internal_force_back env e2) | CastE(ty,e) -> TCastE(ty,internal_force_back env e) | AddrOf lv -> TAddrOf(force_back_lval_to_term_lval env lv) | StartOf lv -> TStartOf(force_back_lval_to_term_lval env lv) @@ -322,12 +332,12 @@ and force_back_lhost_to_term_lhost env = function | Var v -> begin try - let logv = Varinfo.Map.find v env.vars in - logv.lv_type <- Ctype v.vtype; - TVar logv + let logv = Varinfo.Map.find v env.vars in + logv.lv_type <- Ctype v.vtype; + TVar logv with Not_found -> - try Varinfo.Map.find v env.term_lhosts - with Not_found -> TVar(cvar_to_lvar v) + try Varinfo.Map.find v env.term_lhosts + with Not_found -> TVar(cvar_to_lvar v) end | Mem e -> TMem(force_back_exp_to_term env e) @@ -349,7 +359,7 @@ | AlignOfE e -> TAlignOfE(force_exp_to_term e) | UnOp(op,e,_) -> TUnOp(op,force_exp_to_term e) | BinOp(op,e1,e2,_) -> - TBinOp(op, force_exp_to_term e1, force_exp_to_term e2) + TBinOp(op, force_exp_to_term e1, force_exp_to_term e2) | CastE(ty,e) -> TCastE(ty,force_exp_to_term e) | AddrOf lv -> TAddrOf(force_lval_to_term_lval lv) | StartOf lv -> TStartOf(force_lval_to_term_lval lv) @@ -367,8 +377,8 @@ TField(fi,force_offset_to_term_offset off) | Index(idx,off) -> TIndex( - force_exp_to_term idx, - force_offset_to_term_offset off) + force_exp_to_term idx, + force_offset_to_term_offset off) and force_lhost_to_term_lhost = function | Var v -> TVar(cvar_to_lvar v) @@ -384,29 +394,29 @@ let pnode = match (stripInfo e).enode with | Info _ -> assert false | Const c -> - begin match possible_value_of_integral_const c with - | Some i -> if i = 0L then Pfalse else Ptrue - | None -> assert false - end + begin match possible_value_of_integral_const c with + | Some i -> if My_bigint.equal i My_bigint.zero then Pfalse else Ptrue + | None -> assert false + end | UnOp(LNot,e',_) -> Pnot(force_exp_to_predicate e') | BinOp(LAnd,e1,e2,_) -> - Pand(force_exp_to_predicate e1,force_exp_to_predicate e2) + Pand(force_exp_to_predicate e1,force_exp_to_predicate e2) | BinOp(LOr,e1,e2,_) -> - Por(force_exp_to_predicate e1,force_exp_to_predicate e2) + Por(force_exp_to_predicate e1,force_exp_to_predicate e2) | BinOp(op,e1,e2,_) -> - let rel = match op with - | Lt -> Rlt - | Gt -> Rgt - | Le -> Rle - | Ge -> Rge - | Eq -> Req - | Ne -> Rneq - | _ -> assert false - in - Prel(rel,force_exp_to_term e1,force_exp_to_term e2) + let rel = match op with + | Lt -> Rlt + | Gt -> Rgt + | Le -> Rle + | Ge -> Rge + | Eq -> Req + | Ne -> Rneq + | _ -> assert false + in + Prel(rel,force_exp_to_term e1,force_exp_to_term e2) | Lval _ | CastE _ | AddrOf _ | StartOf _ | UnOp _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ -> - assert false + assert false in { name = []; loc = e.eloc; content = pnode; } @@ -424,31 +434,31 @@ and make_comprehension ts = let ts = match ts.term_node with TLval(ts',offs) when no_range_offset offs -> - (match ts' with - | TMem { term_type = Ltype ({lt_name = "set"},[_])} -> ts - | TMem _ | TVar _ | TResult _ -> + (match ts' with + | TMem { term_type = Ltype ({lt_name = "set"},[_])} -> ts + | TMem _ | TVar _ | TResult _ -> { ts with term_type = Logic_const.type_of_element ts.term_type} - ) + ) | _ -> ts in let loc = ts.term_loc in let ts = List.fold_left (fun ts (v,t1opt,t2opt) -> - let vt = variable_term loc v in - let popt = match t1opt,t2opt with - | None,None -> None - | Some t1,None -> Some(predicate t1.term_loc (Prel(Rle,t1,vt))) - | None,Some t2 -> Some(predicate t2.term_loc (Prel(Rle,vt,t2))) - | Some t1,Some t2 -> - let p1 = predicate t1.term_loc (Prel(Rle,t1,vt)) in - let p2 = predicate t2.term_loc (Prel(Rle,vt,t2)) in + let vt = variable_term loc v in + let popt = match t1opt,t2opt with + | None,None -> None + | Some t1,None -> Some(predicate t1.term_loc (Prel(Rle,t1,vt))) + | None,Some t2 -> Some(predicate t2.term_loc (Prel(Rle,vt,t2))) + | Some t1,Some t2 -> + let p1 = predicate t1.term_loc (Prel(Rle,t1,vt)) in + let p2 = predicate t2.term_loc (Prel(Rle,vt,t2)) in let loc = (fst t1.term_loc, snd t2.term_loc) in - Some(predicate loc (Pand(p1,p2))) - in + Some(predicate loc (Pand(p1,p2))) + in (* NB: no need to update the type, as it is already a set of terms (for well-formed terms at least) *) - { ts with term_node = Tcomprehension(ts,[v],popt) } + { ts with term_node = Tcomprehension(ts,[v],popt) } ) ts !ranges in ranges := []; @@ -467,23 +477,23 @@ method vterm_offset tsoff = match tsoff with | TIndex ({ term_node =Trange(t1opt,t2opt)} as t,tsoff') -> - let v = make_temp_logic_var Linteger in - add_range v t1opt t2opt; - let vt = variable_term t.term_loc v in - ChangeDoChildrenPost (TIndex(vt,tsoff'), fun x -> x) + let v = make_temp_logic_var Linteger in + add_range v t1opt t2opt; + let vt = variable_term t.term_loc v in + ChangeDoChildrenPost (TIndex(vt,tsoff'), fun x -> x) | TNoOffset | TIndex _ | TField _ -> DoChildren end let from_range_to_comprehension behavior prj file = let visitor = new fromRangeToComprehension behavior prj in - visitFramacFile visitor file + Visitor.visitFramacFile visitor file let range_to_comprehension t = - let visitor = - new fromRangeToComprehension (Cil.copy_visit ()) (Project.current ()) - in - visitFramacTerm visitor t + let visitor = + new fromRangeToComprehension (Cil.copy_visit ()) (Project.current ()) + in + Visitor.visitFramacTerm visitor t class fromComprehensionToRange behavior prj = @@ -495,42 +505,42 @@ let vars = ref Logic_var.Set.empty in ignore (visitCilTerm - (object - inherit nopCilVisitor - method vterm = function - | { term_node = + (object + inherit nopCilVisitor + method vterm = function + | { term_node = TBinOp(PlusPI,_ts,{term_node=TLval(TVar v,TNoOffset)})} -> - vars := Logic_var.Set.add v !vars; - DoChildren - | _ -> DoChildren - method vterm_offset = function - | TIndex({term_node=TLval(TVar v,TNoOffset)},_tsoff) -> - vars := Logic_var.Set.add v !vars; - DoChildren - | _ -> DoChildren - end) - ts); + vars := Logic_var.Set.add v !vars; + DoChildren + | _ -> DoChildren + method vterm_offset = function + | TIndex({term_node=TLval(TVar v,TNoOffset)},_tsoff) -> + vars := Logic_var.Set.add v !vars; + DoChildren + | _ -> DoChildren + end) + ts); !vars in let bounds_of_variable v popt = let error () = - Cilmsg.fatal "Cannot identify bounds for variable %a" - !Ast_printer.d_ident v.lv_name + Kernel.fatal "Cannot identify bounds for variable %a" + !Ast_printer.d_ident v.lv_name in let rec bounds p = match p.content with | Prel(Rle, {term_node = TLval(TVar v',TNoOffset)}, t) - when Logic_var.equal v v' -> - None, Some t + when Logic_var.equal v v' -> + None, Some t | Prel(Rle, t, {term_node = TLval(TVar v',TNoOffset)}) - when Logic_var.equal v v' -> - Some t, None + when Logic_var.equal v v' -> + Some t, None | Pand(p1,p2) -> - begin match bounds p1, bounds p2 with - | (Some t1, None),(None, Some t2) | (None, Some t2),(Some t1, None) -> - Some t1, Some t2 - | _ -> error () - end + begin match bounds p1, bounds p2 with + | (Some t1, None),(None, Some t2) | (None, Some t2),(Some t1, None) -> + Some t1, Some t2 + | _ -> error () + end | _ -> error () in match popt with None -> None, None | Some p -> bounds p @@ -548,11 +558,11 @@ method vterm t = match t.term_node with | Tcomprehension(ts,[v],popt) -> - let index_vars = index_variables_of_term ts in - (* Only accept for now comprehension on index variables *) - if Logic_var.Set.mem v index_vars then begin - let t1opt,t2opt = bounds_of_variable v popt in - add_range v t1opt t2opt; + let index_vars = index_variables_of_term ts in + (* Only accept for now comprehension on index variables *) + if Logic_var.Set.mem v index_vars then begin + let t1opt,t2opt = bounds_of_variable v popt in + add_range v t1opt t2opt; has_set_type <- false; ChangeTo (visitCilTerm (self :> cilVisitor) ts) end else begin @@ -560,16 +570,16 @@ DoChildren end | TBinOp(PlusPI,base,{term_node=TLval(TVar v,TNoOffset)}) -> - begin try - let low,high = Logic_var.Hashtbl.find ranges v in - let range = Logic_const.trange (low,high) in + begin try + let low,high = Logic_var.Hashtbl.find ranges v in + let range = Logic_const.trange (low,high) in let res = { t with term_node = TBinOp(PlusPI,base,range); term_type = Logic_const.make_set_type t.term_type } in - ChangeDoChildrenPost (res, fun x -> has_set_type <- true; x) - with Not_found -> DoChildren end + ChangeDoChildrenPost (res, fun x -> has_set_type <- true; x) + with Not_found -> DoChildren end | TBinOp(bop,t1,t2) -> has_set_type <- false; @@ -663,7 +673,7 @@ else SkipChildren | _ -> has_set_type <- false; - ChangeDoChildrenPost (t,self#propagate_set_type) + ChangeDoChildrenPost (t,self#propagate_set_type) method vterm_lval (lh,lo) = let lh' = visitCilTermLhost (self:>Cil.cilVisitor) lh in @@ -674,37 +684,37 @@ method vterm_lhost = function | TVar v -> - if Logic_var.Hashtbl.mem ranges v then begin - Format.eprintf "vterm_lhost: Found: v = %s@." v.lv_name; - assert false - end; - DoChildren + if Logic_var.Hashtbl.mem ranges v then begin + Format.eprintf "vterm_lhost: Found: v = %s@." v.lv_name; + assert false + end; + DoChildren | _ -> DoChildren method vterm_offset off = match off with | TIndex({term_node=TLval(TVar v,TNoOffset)} as idx,off') -> - begin try - let t1opt,t2opt = Logic_var.Hashtbl.find ranges v in - let trange = Trange(t1opt,t2opt) in + begin try + let t1opt,t2opt = Logic_var.Hashtbl.find ranges v in + let trange = Trange(t1opt,t2opt) in let toff = - TIndex - ({ idx with + TIndex + ({ idx with term_node = trange; term_type = Logic_const.make_set_type idx.term_type }, - off') + off') in - ChangeDoChildrenPost (toff, fun x -> x) - with Not_found -> - DoChildren end + ChangeDoChildrenPost (toff, fun x -> x) + with Not_found -> + DoChildren end | TIndex _ | TNoOffset | TField _ -> - DoChildren + DoChildren end let from_comprehension_to_range behavior prj file = let visitor = new fromComprehensionToRange behavior prj in - visitFramacFile visitor file + Visitor.visitFramacFile visitor file (* Expect conversion to be possible on all sub-terms, otherwise raise an error. *) @@ -715,9 +725,9 @@ let create_const_list loc kind low high = let rec aux acc i = - if Int64.compare i low < 0 then acc + if My_bigint.lt i low then acc else - aux (new_exp ~loc (Const (CInt64 (i,kind,None)))::acc) (Int64.pred i) + aux (new_exp ~loc (Const (CInt64 (i,kind,None)))::acc) (My_bigint.pred i) in aux [] high let range low high = @@ -733,23 +743,29 @@ | _ -> error_lval() let rec loc_lval_to_lval ~result (lh, lo) = - product (fun x y -> (x,y)) + Extlib.product + (fun x y -> (x,y)) (loc_lhost_to_lhost ~result lh) (loc_offset_to_offset ~result lo) + and loc_lhost_to_lhost ~result = function | TVar lvar -> [Var (logic_var_to_var lvar)] | TMem lterm -> List.map (fun x -> Mem x) (loc_to_exp ~result lterm) | TResult _ -> ( match result with - None -> error_lval() + None -> error_lval() | Some v -> [Var v]) + and loc_offset_to_offset ~result = function | TNoOffset -> [NoOffset] | TField (fi, lo) -> List.map (fun x -> Field (fi,x)) (loc_offset_to_offset ~result lo) | TIndex (lexp, lo) -> - product (fun x y -> Index(x,y)) - (loc_to_exp ~result lexp) (loc_offset_to_offset ~result lo) + Extlib.product + (fun x y -> Index(x,y)) + (loc_to_exp ~result lexp) + (loc_offset_to_offset ~result lo) + and loc_to_exp ~result {term_node = lnode ; term_type = ltype; term_loc = loc} = match lnode with | TLval lv -> @@ -767,9 +783,10 @@ (fun x -> new_exp ~loc (UnOp (unop, x, logic_type_to_typ ltype))) (loc_to_exp ~result lexp) | TBinOp (binop, lexp1, lexp2) -> - product + Extlib.product (fun x y -> new_exp ~loc (BinOp (binop, x,y, logic_type_to_typ ltype))) - (loc_to_exp ~result lexp1) (loc_to_exp ~result lexp2) + (loc_to_exp ~result lexp1) + (loc_to_exp ~result lexp2) | TSizeOfStr string -> [new_exp ~loc (SizeOfStr string)] | TConst constant -> [new_exp ~loc (Const constant)] | TCastE (typ, lexp) -> @@ -784,15 +801,13 @@ | Tunion l -> List.concat (List.map (loc_to_exp ~result) l) | Tempty_set -> [] | Tinter _ | Tcomprehension _ -> error_lval() - | Told ({term_node = TAddrOf (TVar _, TNoOffset)} as taddroflval) - | Tat ({term_node = TAddrOf (TVar _, TNoOffset)} as taddroflval, _) -> + | Tat ({term_node = TAddrOf (TVar _, TNoOffset)} as taddroflval, _) -> loc_to_exp ~result taddroflval (* additional constructs *) | Tapp _ | Tlambda _ | Trange _ | Tlet _ | TDataCons _ | Tif _ - | Told _ | Tat _ | Tbase_addr _ | Tblock_length _ @@ -810,85 +825,89 @@ | Tinter _ -> error_lval() (* TODO *) | Tcomprehension _ -> error_lval() | TSizeOfE _ | TAlignOfE _ | TUnOp _ | TBinOp _ | TSizeOfStr _ - | TConst _ | TCastE _ | TAlignOf _ | TSizeOf _ | Tapp _ | Tif _ | Told _ + | TConst _ | TCastE _ | TAlignOf _ | TSizeOf _ | Tapp _ | Tif _ | Tat _ | Tbase_addr _ | Tblock_length _ | Tnull | Trange _ | TCoerce _ | TCoerceE _ | TDataCons _ | TUpdate _ | Tlambda _ | Ttypeof _ | Ttype _ | Tlet _ -> error_lval () +(* This function fails with "not an lvalue" much too often, and is + replaced by another function in value/eval_logic.ml. It is left + here in case someones decides to deactivate the value analysis *) let loc_to_loc ~result state content = let unprotected content = let lvals = loc_to_lval ~result content in List.fold_left (fun acc lval -> - let loc = !Db.Value.lval_to_loc_state state lval in - let s = loc.Locations.size in - assert (Locations.loc_equal acc Locations.loc_bottom || - Int_Base.equal s acc.Locations.size); - Locations.make_loc - (Locations.Location_Bits.join - loc.Locations.loc - acc.Locations.loc) - s) + let loc = !Db.Value.lval_to_loc_state state lval in + let s = loc.Locations.size in + assert (Locations.loc_equal acc Locations.loc_bottom || + Int_Base.equal s acc.Locations.size); + Locations.make_loc + (Locations.Location_Bits.join + loc.Locations.loc + acc.Locations.loc) + s) Locations.loc_bottom - lvals + lvals in begin try unprotected content with Invalid_argument "not an lvalue" as e -> - let t = content.term_node in - begin match t with - TLval (TVar v, _o) -> - let c_v = logic_var_to_var v in - let base = Base.find c_v in - let loc = - Locations.Location_Bits.inject_top_origin - Origin.top - (Locations.Location_Bits.Top_Param.O.singleton base) - - in - Locations.make_loc loc Int_Base.top - | TLval (TMem {term_node=TBinOp((IndexPI|PlusPI) , - t1,_o1)}, - _o2) -> - let deref_lvals = - !Db.Properties.Interp.loc_to_lval ~result:None t1 - in - (* Format.printf "input: %a@." - Cvalue_type.V.pretty input_contents ; *) - let deref_loc = - List.fold_left - (fun acc lv -> - let loc = - !Db.Value.lval_to_loc_state state lv - in - Locations.Location_Bits.join loc.Locations.loc acc) - Locations.Location_Bits.bottom - deref_lvals - in - let deref_loc = - Locations.Location_Bits.topify_arith_origin deref_loc - in - let loc_bytes = - Relations_type.Model.find - ~conflate_bottom:true - ~with_alarms:CilE.warn_none_mode - state - (Locations.make_loc deref_loc Int_Base.top) - in - let loc = - Locations.make_loc - (Locations.loc_bytes_to_loc_bits loc_bytes) - Int_Base.top - in - loc - | _ -> raise e - end + let t = content.term_node in + begin match t with + | TLval (TVar v, _o) -> + let c_v = logic_var_to_var v in + let base = Base.find c_v in + let loc = + Locations.Location_Bits.inject_top_origin + Origin.top + (Locations.Location_Bits.Top_Param.O.singleton base) + + in + Locations.make_loc loc Int_Base.top + | TLval (TMem {term_node = + TBinOp((IndexPI|PlusPI), + ({ term_node = TCastE (_, t1) } | t1),_o1)}, + _o2) -> + let deref_lvals = + !Db.Properties.Interp.loc_to_lval ~result:None t1 + in + (* Format.printf "input: %a@." + Cvalue.V.pretty input_contents ; *) + let deref_loc = + List.fold_left + (fun acc lv -> + let loc = + !Db.Value.lval_to_loc_state state lv + in + Locations.Location_Bits.join loc.Locations.loc acc) + Locations.Location_Bits.bottom + deref_lvals + in + let deref_loc = + Locations.Location_Bits.topify_arith_origin deref_loc + in + let loc_bytes = + Cvalue.Model.find + ~conflate_bottom:true + ~with_alarms:CilE.warn_none_mode + state + (Locations.make_loc deref_loc Int_Base.top) + in + let loc = + Locations.make_loc + (Locations.loc_bytes_to_loc_bits loc_bytes) + Int_Base.top + in + loc + | _ -> raise e + end end -let identified_term_zone_to_loc ~result state t = - loc_to_loc ~result state t.it_content +let identified_term_zone_to_loc ~result state t = + !Db.Properties.Interp.loc_to_loc ~result state t.it_content let rec loc_to_offset ~result loc = let rec aux h = @@ -907,7 +926,7 @@ | Tempty_set -> h,[] | Trange _ | TAddrOf _ | TSizeOfE _ | TAlignOfE _ | TUnOp _ | TBinOp _ | TSizeOfStr _ - | TConst _ | TCastE _ | TAlignOf _ | TSizeOf _ | Tapp _ | Tif _ | Told _ + | TConst _ | TCastE _ | TAlignOf _ | TSizeOf _ | Tapp _ | Tif _ | Tat _ | Tbase_addr _ | Tblock_length _ | Tnull | TCoerce _ | TCoerceE _ | TDataCons _ | TUpdate _ | Tlambda _ | Ttypeof _ | Ttype _ | Tcomprehension _ | Tinter _ | Tlet _ @@ -938,7 +957,7 @@ (t, fun x -> ignore (Stack.pop is_under_pre); Logic_const.tat ~loc (x, Logic_const.old_label)) - | Tat _ | Told _ -> JustCopy + | Tat _ -> JustCopy (* User is supposed to know what she's doing with logic labels. Don't mess with her. *) @@ -979,194 +998,224 @@ (** Utilities to identify [Locations.Zone.t] involved into [rooted_code_annotation]. *) module To_zone : sig - type t_ctx = Properties.Interp.To_zone.t_ctx + + type t_ctx = Db.Properties.Interp.To_zone.t_ctx + val mk_ctx_func_contrat: kernel_function -> state_opt:bool option -> t_ctx - (** [mk_ctx_func_contrat] to define an interpretation context related to [kernel_function] contracts. - The control point of the interpretation is defined as follow: - - pre-state if [state_opt=Some true] - - post-state if [state_opt=Some false] - - pre-state with possible reference to the post-state if [state_opt=None] - *) - val mk_ctx_stmt_contrat: kernel_function -> stmt -> state_opt:bool option -> t_ctx - (** [mk_ctx_stmt_contrat] to define an interpretation context related to [stmt] contracts. - The control point of the interpretation is defined as follow: - - pre-state if [state_opt=Some true] - - post-state if [state_opt=Some false] - - pre-state with possible reference to the post-state if [state_opt=None] - *) - val mk_ctx_stmt_annot: kernel_function -> stmt -> before:bool -> t_ctx - (** [mk_ctx_stmt_annot] to define an interpretation context related to an annotation. - The control point of the interpretation is defined as follow: - - before the [stmt] if [before=true] - - after the [stmt] if [before=false] - *) - type t = Properties.Interp.To_zone.t - type t_zone_info = Properties.Interp.To_zone.t_zone_info + (** [mk_ctx_func_contrat] to define an interpretation context related to + [kernel_function] contracts. + The control point of the interpretation is defined as follow: + - pre-state if [state_opt=Some true] + - post-state if [state_opt=Some false] + - pre-state with possible reference to the post-state if + [state_opt=None]. *) + + val mk_ctx_stmt_contrat: + kernel_function -> stmt -> state_opt:bool option -> t_ctx + (** [mk_ctx_stmt_contrat] to define an interpretation context related to + [stmt] contracts. + The control point of the interpretation is defined as follow: + - pre-state if [state_opt=Some true] + - post-state if [state_opt=Some false] + - pre-state with possible reference to the post-state if + [state_opt=None]. *) + + val mk_ctx_stmt_annot: kernel_function -> stmt -> t_ctx + (** [mk_ctx_stmt_annot] to define an interpretation context related to an + annotation attached before the [stmt]. *) + + type t = Db.Properties.Interp.To_zone.t + type t_zone_info = Db.Properties.Interp.To_zone.t_zone_info type t_decl = Varinfo.Set.t - type t_pragmas = Properties.Interp.To_zone.t_pragmas + type t_pragmas = Db.Properties.Interp.To_zone.t_pragmas val not_yet_implemented : string ref + val from_term: term -> t_ctx -> (t_zone_info * t_decl) (** Entry point to get zones - needed to evaluate the [term] relative to the [ctx] of interpretation. *) + needed to evaluate the [term] relative to the [ctx] of + interpretation. *) + val from_terms: term list -> t_ctx -> (t_zone_info * t_decl) (** Entry point to get zones - needed to evaluate the list of [terms] relative to the [ctx] of interpretation. *) + needed to evaluate the list of [terms] relative to the [ctx] of + interpretation. *) + val from_pred: predicate named -> t_ctx -> (t_zone_info * t_decl) (** Entry point to get zones - needed to evaluate the [predicate] relative to the [ctx] of interpretation. *) + needed to evaluate the [predicate] relative to the [ctx] of + interpretation. *) + val from_preds: predicate named list -> t_ctx -> (t_zone_info * t_decl) (** Entry point to get zones - needed to evaluate the list of [predicates] relative to the [ctx] of interpretation. *) + needed to evaluate the list of [predicates] relative to the [ctx] of + interpretation. *) + val from_zone: identified_term -> t_ctx -> (t_zone_info * t_decl) (** Entry point to get zones - needed to evaluate the list of [predicates] relative to the [ctx] of interpretation. *) + needed to evaluate the list of [predicates] relative to the [ctx] of + interpretation. *) + val from_zones: identified_term list -> t_ctx -> (t_zone_info * t_decl) (** Entry point to get zones - needed to evaluate the list of [predicates] relative to the [ctx] of interpretation. *) - val from_stmt_annot: code_annotation -> before:bool -> (stmt * kernel_function) -> (t_zone_info * t_decl) * t_pragmas - (** Entry point to get zones - needed to evaluate code annotations of this [stmt]. *) + needed to evaluate the list of [predicates] relative to the [ctx] of + interpretation. *) + + val from_stmt_annot: + code_annotation -> (stmt * kernel_function) -> + (t_zone_info * t_decl) * t_pragmas + (** Entry point to get zones needed to evaluate code annotations of this + [stmt]. *) + val from_stmt_annots: - ((rooted_code_annotation before_after) -> bool) option -> + (rooted_code_annotation -> bool) option -> (stmt * kernel_function) -> (t_zone_info * t_decl) * t_pragmas - (** Entry point to get zones - needed to evaluate code annotations of this [stmt]. *) + (** Entry point to get zones needed to evaluate code annotations of this + [stmt]. *) + val from_func_annots: ((stmt -> unit) -> kernel_function -> unit) -> - ((rooted_code_annotation before_after) -> bool) option -> + (rooted_code_annotation -> bool) option -> kernel_function -> (t_zone_info * t_decl) * t_pragmas - (** Entry point to get zones - needed to evaluate code annotations of this [kf]. *) + (** Entry point to get zones needed to evaluate code annotations of this + [kf]. *) + val code_annot_filter: - (rooted_code_annotation before_after) -> ai:bool -> + rooted_code_annotation -> ai:bool -> user_assert:bool -> slicing_pragma:bool -> loop_inv:bool -> loop_var:bool -> others:bool -> bool (** To quickly build a annotation filter *) end - = struct - exception NotYetImplemented of string - type t_ctx = Properties.Interp.To_zone.t_ctx - let mk_ctx_func_contrat kf ~state_opt = - { Properties.Interp.To_zone.state_opt = state_opt; - ki_opt = None; - kf = kf } - let mk_ctx_stmt_contrat kf ki ~state_opt = - { Properties.Interp.To_zone.state_opt=state_opt; - ki_opt= Some(ki, false); - kf = kf } - let mk_ctx_stmt_annot kf ki ~before = - { Properties.Interp.To_zone.state_opt = Some before; - ki_opt = Some(ki, true); - kf = kf } - type t = Properties.Interp.To_zone.t - type t_zone_info = Properties.Interp.To_zone.t_zone_info - type t_decl = Varinfo.Set.t - type t_pragmas = Properties.Interp.To_zone.t_pragmas - let empty_pragmas = - { Properties.Interp.To_zone.ctrl = Stmt.Set.empty; - stmt = Stmt.Set.empty } - let other_zones = Stmt.Hashtbl.create 7 - let locals = ref Varinfo.Set.empty - let pragmas = ref empty_pragmas - - let zone_result = ref (Some other_zones) - let not_yet_implemented = ref "" - - let add_top_zone not_yet_implemented_msg = match !zone_result with - | None -> (* top zone *) () - | Some other_zones -> - Stmt.Hashtbl.clear other_zones; - not_yet_implemented := not_yet_implemented_msg; - zone_result := None - - let add_result ~before ki zone = match !zone_result with - | None -> (* top zone *) () - | Some other_zones -> - let zone_true, zone_false = - try Stmt.Hashtbl.find other_zones ki - with Not_found -> Locations.Zone.bottom, Locations.Zone.bottom - in - Stmt.Hashtbl.replace other_zones - ki - (if before then Locations.Zone.join zone_true zone, zone_false - else zone_true, Locations.Zone.join zone_false zone) - - let get_result () = - let result = - let zones = match !zone_result with - | None -> - (* clear references for the next time when giving the result. - * Notice that other_zones has been cleared in [add_top_zone]. *) - zone_result := Some other_zones; - None - | Some other_zones -> - let z = - Stmt.Hashtbl.fold - (fun ki (zone_true, zone_false) other_zones -> - let add before zone others = - if Locations.Zone.equal Locations.Zone.bottom zone then - others - else - { Properties.Interp.To_zone.before=before; - ki = ki; - zone=zone} :: others - in - add true zone_true (add false zone_false other_zones)) - other_zones - [] - in - (* clear table for the next time when giving the result *) - Stmt.Hashtbl.clear other_zones; - Some z - in zones, !locals + = +struct + + exception NotYetImplemented of string + type t_ctx = Db.Properties.Interp.To_zone.t_ctx + + let mk_ctx_func_contrat kf ~state_opt = + { Db.Properties.Interp.To_zone.state_opt = state_opt; + ki_opt = None; + kf = kf } + + let mk_ctx_stmt_contrat kf ki ~state_opt = + { Db.Properties.Interp.To_zone.state_opt=state_opt; + ki_opt= Some(ki, false); + kf = kf } + + let mk_ctx_stmt_annot kf ki = + { Db.Properties.Interp.To_zone.state_opt = Some true; + ki_opt = Some(ki, true); + kf = kf } + + type t = Db.Properties.Interp.To_zone.t + type t_zone_info = Db.Properties.Interp.To_zone.t_zone_info + type t_decl = Varinfo.Set.t + type t_pragmas = Db.Properties.Interp.To_zone.t_pragmas + + let empty_pragmas = + { Db.Properties.Interp.To_zone.ctrl = Stmt.Set.empty; + stmt = Stmt.Set.empty } + + let other_zones = Stmt.Hashtbl.create 7 + let locals = ref Varinfo.Set.empty + let pragmas = ref empty_pragmas + + let zone_result = ref (Some other_zones) + let not_yet_implemented = ref "" + + let add_top_zone not_yet_implemented_msg = match !zone_result with + | None -> (* top zone *) () + | Some other_zones -> + Stmt.Hashtbl.clear other_zones; + not_yet_implemented := not_yet_implemented_msg; + zone_result := None + + let add_result ~before ki zone = match !zone_result with + | None -> (* top zone *) () + | Some other_zones -> + let zone_true, zone_false = + try Stmt.Hashtbl.find other_zones ki + with Not_found -> Locations.Zone.bottom, Locations.Zone.bottom in - (* clear references for the next time when giving the result *) - locals := Varinfo.Set.empty ; - result - - let get_annot_result () = - let annot_result = (get_result ()), !pragmas in - (* clear references for the next time when giving the result *) - pragmas := empty_pragmas ; - annot_result - - (** Logic_var utility: *) - let extract_locals logicvars = - Logic_var.Set.fold - (fun lv cvars -> match lv.lv_origin with - | None -> cvars - | Some cvar -> - if cvar.Cil_types.vglob then cvars - else Varinfo.Set.add cvar cvars) - logicvars - Varinfo.Set.empty - - (** Term utility: - Extract C local variables occuring into a [term]. *) - let extract_locals_from_term term = - extract_locals (extract_free_logicvars_from_term term) - - (** Predicate utility: - Extract C local variables occuring into a [term]. *) - let extract_locals_from_pred pred = - extract_locals (extract_free_logicvars_from_predicate pred) - - type abs_label = | AbsLabel_here - | AbsLabel_pre - | AbsLabel_post - | AbsLabel_stmt of stmt - - class populate_zone before_opt ki_opt kf = - (* interpretation from the - * - pre-state if [before_opt=Some true] - * - post-state if [before_opt=Some false] - * - pre-state with possible reference to the post-state if [before_opt=None] - * of a property relative to - * - the contract of function [kf] when [ki_opt=None] - * otherwise [ki_opt=Some(ki, code_annot)], - * - the contract of the statement [ki] when [code_annot=false] - * - the annotation of the statement [ki] when [code_annot=true] - *) + Stmt.Hashtbl.replace other_zones + ki + (if before then Locations.Zone.join zone_true zone, zone_false + else zone_true, Locations.Zone.join zone_false zone) + + let get_result () = + let result = + let zones = match !zone_result with + | None -> + (* clear references for the next time when giving the result. + Note that other_zones has been cleared in [add_top_zone]. *) + zone_result := Some other_zones; + None + | Some other_zones -> + let z = + Stmt.Hashtbl.fold + (fun ki (zone_true, zone_false) other_zones -> + let add before zone others = + if Locations.Zone.equal Locations.Zone.bottom zone then + others + else + { Db.Properties.Interp.To_zone.before = before; + ki = ki; + zone = zone} :: others + in + add true zone_true (add false zone_false other_zones)) + other_zones + [] + in + (* clear table for the next time when giving the result *) + Stmt.Hashtbl.clear other_zones; + Some z + in zones, !locals + in + (* clear references for the next time when giving the result *) + locals := Varinfo.Set.empty ; + result + + let get_annot_result () = + let annot_result = (get_result ()), !pragmas in + (* clear references for the next time when giving the result *) + pragmas := empty_pragmas ; + annot_result + + (** Logic_var utility: *) + let extract_locals logicvars = + Logic_var.Set.fold + (fun lv cvars -> match lv.lv_origin with + | None -> cvars + | Some cvar -> + if cvar.Cil_types.vglob then cvars + else Varinfo.Set.add cvar cvars) + logicvars + Varinfo.Set.empty + + (** Term utility: + Extract C local variables occuring into a [term]. *) + let extract_locals_from_term term = + extract_locals (extract_free_logicvars_from_term term) + + (** Predicate utility: + Extract C local variables occuring into a [term]. *) + let extract_locals_from_pred pred = + extract_locals (extract_free_logicvars_from_predicate pred) + + type abs_label = | AbsLabel_here + | AbsLabel_pre + | AbsLabel_post + | AbsLabel_stmt of stmt + + class populate_zone before_opt ki_opt kf = + (* interpretation from the + - pre-state if [before_opt=Some true] + - post-state if [before_opt=Some false] + - pre-state with possible reference to the post-state if + [before_opt=None] of a property relative to + - the contract of function [kf] when [ki_opt=None] + otherwise [ki_opt=Some(ki, code_annot)], + - the contract of the statement [ki] when [code_annot=false] + - the annotation of the statement [ki] when [code_annot=true] *) object(self) inherit Visitor.generic_frama_c_visitor (Project.current()) @@ -1176,8 +1225,11 @@ method private get_ctrl_point () = let get_fct_entry_point () = (* TODO: to replace by true, None *) - true, (try Some (Kernel_function.find_first_stmt kf) - with Kernel_function.No_Statement -> None) (* raised when [kf] has no code. *) + true, + (try Some (Kernel_function.find_first_stmt kf) + with Kernel_function.No_Statement -> + (* raised when [kf] has no code. *) + None) in let get_ctrl_point dft = let before = Extlib.may_map (fun before -> before) ~dft before_opt in @@ -1197,7 +1249,7 @@ | AbsLabel_post -> get_ctrl_point false in (* TODO: the method should be able to return result directly *) match result with - | current_before, Some current_ki -> current_before, current_ki + | current_before, Some current_stmt -> current_before, current_stmt | _ -> raise (NotYetImplemented "[logic_interp] clause related to a function contract") @@ -1216,49 +1268,78 @@ fun x -> match ki_opt,before_opt with (* function contract *) - | None,Some true -> failwith ("The use of the label Old is forbiden inside clauses related the pre-state of function contracts.") + | None,Some true -> + failwith "The use of the label Old is forbiden inside clauses \ + related the pre-state of function contracts." | None,None - | None,Some false -> self#change_label AbsLabel_pre x (* refers to the pre-state of the contract. *) - (* statement contract *) - | Some (_ki,false),Some true -> failwith ("The use of the label Old is forbiden inside clauses related the pre-state of statement contracts.") + | None,Some false -> + (* refers to the pre-state of the contract. *) + self#change_label AbsLabel_pre x + (* statement contract *) + | Some (_ki,false),Some true -> + failwith "The use of the label Old is forbiden inside clauses \ +related the pre-state of statement contracts." | Some (ki,false),None - | Some (ki,false),Some false -> self#change_label (AbsLabel_stmt ki) x (* refers to the pre-state of the contract. *) - (* code annotation *) + | Some (ki,false),Some false -> + (* refers to the pre-state of the contract. *) + self#change_label (AbsLabel_stmt ki) x + (* code annotation *) | Some (_ki,true),None - | Some (_ki,true),Some _ -> self#change_label AbsLabel_pre x (* refers to the pre-state of the function contract. *) + | Some (_ki,true),Some _ -> + (* refers to the pre-state of the function contract. *) + self#change_label AbsLabel_pre x method private change_label_to_post: 'a.'a -> 'a visitAction = - fun x -> (* allowed when [before_opt=None] for function/statement contracts *) + fun x -> + (* allowed when [before_opt=None] for function/statement contracts *) match ki_opt,before_opt with (* function contract *) - | None,Some _ -> failwith ("Function contract where the use of the label Post is forbiden.") - | None,None -> self#change_label AbsLabel_post x (* refers to the post-state of the contract. *) - (* statement contract *) - | Some (_ki,false),Some _ -> failwith ("Statement contract where the use of the label Post is forbiden.") - | Some (_ki,false),None -> self#change_label AbsLabel_post x (* refers to the pre-state of the contract. *) - (* code annotation *) - | Some (_ki,true), _ -> failwith ("The use of the label Post is forbiden inside code annotations.") + | None,Some _ -> + failwith "Function contract where the use of the label Post is \ + forbiden." + | None,None -> + (* refers to the post-state of the contract. *) + self#change_label AbsLabel_post x + (* statement contract *) + | Some (_ki,false),Some _ -> + failwith "Statement contract where the use of the label Post is \ +forbiden." + | Some (_ki,false),None -> + (* refers to the pre-state of the contract. *) + self#change_label AbsLabel_post x + (* code annotation *) + | Some (_ki,true), _ -> + failwith "The use of the label Post is forbiden inside code \ +annotations." method private change_label_to_pre: 'a.'a -> 'a visitAction = fun x -> match ki_opt with (* function contract *) - | None -> failwith ("The use of the label Pre is forbiden inside function contracts.") - (* statement contract *) - (* code annotation *) - | Some _ -> self#change_label AbsLabel_pre x (* refers to the pre-state of the function contract. *) + | None -> + failwith "The use of the label Pre is forbiden inside function \ +contracts." + (* statement contract *) + (* code annotation *) + | Some _ -> + (* refers to the pre-state of the function contract. *) + self#change_label AbsLabel_pre x method private change_label_to_stmt: 'a.stmt -> 'a -> 'a visitAction = fun stmt x -> match ki_opt with (* function contract *) - | None -> failwith ("the use of C labels is forbiden inside clauses related function contracts.") - (* statement contract *) - (* code annotation *) - | Some _ -> self#change_label (AbsLabel_stmt stmt) x (* refers to the state at the C label of the statement [stmt]. *) + | None -> + failwith "the use of C labels is forbiden inside clauses related \ +function contracts." + (* statement contract *) + (* code annotation *) + | Some _ -> + (* refers to the state at the C label of the statement [stmt]. *) + self#change_label (AbsLabel_stmt stmt) x method vpredicate p = match p with - | Pold _ | Pat (_, LogicLabel (_,"Old")) -> self#change_label_to_old p + | Pat (_, LogicLabel (_,"Old")) -> self#change_label_to_old p | Pat (_, LogicLabel (_,"Here")) -> self#change_label_to_here p | Pat (_, LogicLabel (_,"Pre")) -> self#change_label_to_pre p | Pat (_, LogicLabel (_,"Post")) -> self#change_label_to_post p @@ -1266,8 +1347,8 @@ | Pat (_, LogicLabel (_,s)) -> failwith ("unknown logic label" ^ s) | Pfresh _ -> - raise (NotYetImplemented ("[logic_interp] \\fresh()")) - (* assert false *) (*VP: can't we do something better? *) + raise (NotYetImplemented "[logic_interp] \\fresh()") + (* assert false *) (*VP: can't we do something better? *) | _ -> DoChildren method vterm t = @@ -1277,15 +1358,15 @@ let exp = try (* to be removed *) !Db.Properties.Interp.term_to_exp ~result:None t with Invalid_argument str -> - raise (NotYetImplemented ("[logic_interp] "^ str)) + raise (NotYetImplemented ("[logic_interp] " ^ str)) in let current_before, current_ki = self#get_ctrl_point () in let loc = try (* to be removed *) - !Db.From.find_deps_no_transitivity (Kstmt current_ki) exp + !Db.From.find_deps_no_transitivity current_ki exp with Invalid_argument str -> - raise (NotYetImplemented ("[logic_interp] "^ str)) + raise (NotYetImplemented ("[logic_interp] " ^ str)) in add_result current_before current_ki loc; SkipChildren - | Told _ | Tat (_, LogicLabel (_,"Old")) -> self#change_label_to_old t + | Tat (_, LogicLabel (_,"Old")) -> self#change_label_to_old t | Tat (_, LogicLabel (_,"Here")) -> self#change_label_to_here t | Tat (_, LogicLabel (_,"Pre")) -> self#change_label_to_pre t | Tat (_, LogicLabel (_,"Post")) -> self#change_label_to_post t @@ -1300,14 +1381,15 @@ relative to the [ctx] of interpretation. *) let from_term term ctx = (* [VP 2011-01-28] TODO: factorize from_terms and from_term, and use - * a more functional setting. - *) + a more functional setting. *) (try - ignore(visitFramacTerm (new populate_zone - ctx.Properties.Interp.To_zone.state_opt - ctx.Properties.Interp.To_zone.ki_opt - ctx.Properties.Interp.To_zone.kf) term) - with NotYetImplemented msg -> add_top_zone msg) ; + ignore(Visitor.visitFramacTerm + (new populate_zone + ctx.Db.Properties.Interp.To_zone.state_opt + ctx.Db.Properties.Interp.To_zone.ki_opt + ctx.Db.Properties.Interp.To_zone.kf) term) + with NotYetImplemented msg -> + add_top_zone msg) ; locals := Varinfo.Set.union (extract_locals_from_term term) !locals; get_result () @@ -1316,13 +1398,15 @@ relative to the [ctx] of interpretation. *) let from_terms terms ctx = let f x = - (try - ignore(visitFramacTerm (new populate_zone - ctx.Properties.Interp.To_zone.state_opt - ctx.Properties.Interp.To_zone.ki_opt - ctx.Properties.Interp.To_zone.kf) x) - with NotYetImplemented msg -> add_top_zone msg) ; - locals := Varinfo.Set.union (extract_locals_from_term x) !locals + (try + ignore(Visitor.visitFramacTerm + (new populate_zone + ctx.Db.Properties.Interp.To_zone.state_opt + ctx.Db.Properties.Interp.To_zone.ki_opt + ctx.Db.Properties.Interp.To_zone.kf) x) + with NotYetImplemented msg -> + add_top_zone msg) ; + locals := Varinfo.Set.union (extract_locals_from_term x) !locals in List.iter f terms; get_result () @@ -1331,13 +1415,14 @@ needed to evaluate the [pred] relative to the [ctx] of interpretation. *) let from_pred pred ctx = - (try - ignore(visitFramacPredicateNamed - (new populate_zone - ctx.Properties.Interp.To_zone.state_opt - ctx.Properties.Interp.To_zone.ki_opt - ctx.Properties.Interp.To_zone.kf) pred) - with NotYetImplemented msg -> add_top_zone msg) ; + (try + ignore(Visitor.visitFramacPredicateNamed + (new populate_zone + ctx.Db.Properties.Interp.To_zone.state_opt + ctx.Db.Properties.Interp.To_zone.ki_opt + ctx.Db.Properties.Interp.To_zone.kf) pred) + with NotYetImplemented msg -> + add_top_zone msg) ; locals := Varinfo.Set.union (extract_locals_from_pred pred) !locals; get_result () @@ -1346,13 +1431,15 @@ relative to the [ctx] of interpretation. *) let from_preds preds ctx = let f pred = - (try - ignore(visitFramacPredicateNamed - (new populate_zone ctx.Properties.Interp.To_zone.state_opt - ctx.Properties.Interp.To_zone.ki_opt - ctx.Properties.Interp.To_zone.kf) pred) - with NotYetImplemented msg -> add_top_zone msg) ; - locals := Varinfo.Set.union (extract_locals_from_pred pred) !locals + (try + ignore(Visitor.visitFramacPredicateNamed + (new populate_zone + ctx.Db.Properties.Interp.To_zone.state_opt + ctx.Db.Properties.Interp.To_zone.ki_opt + ctx.Db.Properties.Interp.To_zone.kf) pred) + with NotYetImplemented msg -> + add_top_zone msg) ; + locals := Varinfo.Set.union (extract_locals_from_pred pred) !locals in List.iter f preds; get_result () @@ -1365,64 +1452,66 @@ (** Entry point to get the list of [ki] * [Locations.Zone.t] needed to evaluate the list of [zones] relative to the [ctx] of interpretation. *) - let from_zones zones ctx = + let from_zones zones ctx = from_terms (List.map (fun x -> x.it_content) zones) ctx (** Used by annotations entry points. *) - let get_zone_from_annot a before (ki,kf) loop_body_opt = + let get_zone_from_annot a (ki,kf) loop_body_opt = assert (!pragmas = empty_pragmas); (* check before modification. Anne.*) - let get_zone_from_term b k x = - (try - ignore - (visitFramacTerm - (new populate_zone (Some b) (Some (k, true)) kf) x) - with NotYetImplemented msg -> add_top_zone msg) ; + let get_zone_from_term k x = + (try + ignore + (Visitor.visitFramacTerm + (new populate_zone (Some true) (Some (k, true)) kf) x) + with NotYetImplemented msg -> + add_top_zone msg) ; (* to select the declaration of the variables *) locals := Varinfo.Set.union (extract_locals_from_term x) !locals - and get_zone_from_pred b k x = - (try + and get_zone_from_pred k x = + (try ignore - (visitFramacPredicateNamed - (new populate_zone (Some b) (Some (k,true)) kf) x) - with NotYetImplemented msg -> add_top_zone msg) ; + (Visitor.visitFramacPredicateNamed + (new populate_zone (Some true) (Some (k,true)) kf) x) + with NotYetImplemented msg -> + add_top_zone msg) ; (* to select the declaration of the variables *) locals := Varinfo.Set.union (extract_locals_from_pred x) !locals in match a with | APragma (Slice_pragma (SPexpr term) | Impact_pragma (IPexpr term)) -> (* to preserve the interpretation of the pragma *) - get_zone_from_term before ki term; + get_zone_from_term ki term; (* to select the reachability of the pragma *) pragmas := - { !pragmas with Properties.Interp.To_zone.ctrl = - Stmt.Set.add ki !pragmas.Properties.Interp.To_zone.ctrl } + { !pragmas with Db.Properties.Interp.To_zone.ctrl = + Stmt.Set.add ki !pragmas.Db.Properties.Interp.To_zone.ctrl } | APragma (Slice_pragma SPctrl) -> (* to select the reachability of the pragma *) pragmas := { !pragmas with - Properties.Interp.To_zone.ctrl = - Stmt.Set.add ki !pragmas.Properties.Interp.To_zone.ctrl } + Db.Properties.Interp.To_zone.ctrl = + Stmt.Set.add ki !pragmas.Db.Properties.Interp.To_zone.ctrl } | APragma (Slice_pragma SPstmt | Impact_pragma IPstmt) -> (* to preserve the effect of the statement *) pragmas := { !pragmas with - Properties.Interp.To_zone.stmt = - Stmt.Set.add ki !pragmas.Properties.Interp.To_zone.stmt} + Db.Properties.Interp.To_zone.stmt = + Stmt.Set.add ki !pragmas.Db.Properties.Interp.To_zone.stmt} | AAssert (_behav,pred) -> (* to preserve the interpretation of the assertion *) - get_zone_from_pred before ki pred; + get_zone_from_pred ki pred; | AInvariant (_behav,true,pred) -> (* loop invariant *) - (* WARNING this is obsolete *) - (* [JS 2010/09/02] TODO: so what is the right way to do? *) + (* WARNING this is obsolete *) + (* [JS 2010/09/02] TODO: so what is the right way to do? *) (* to preserve the interpretation of the loop invariant *) - get_zone_from_pred true (Extlib.the loop_body_opt) pred; + get_zone_from_pred (Extlib.the loop_body_opt) pred; | AInvariant (_behav,false,pred) -> (* code invariant *) (* to preserve the interpretation of the code invariant *) - get_zone_from_pred before ki pred; + get_zone_from_pred ki pred; | AVariant (term,_) -> (* to preserve the interpretation of the variant *) - get_zone_from_term true (Extlib.the loop_body_opt) term; + get_zone_from_term (Extlib.the loop_body_opt) term; | APragma (Loop_pragma (Unroll_level term)) -> (* to select the declaration of the variables *) locals := Varinfo.Set.union (extract_locals_from_term term) !locals @@ -1430,16 +1519,16 @@ | APragma (Loop_pragma (Widen_variables terms)) -> (* to select the declaration of the variables *) List.iter - (fun term -> + (fun term -> locals := Varinfo.Set.union (extract_locals_from_term term) !locals) terms | AAssigns (_, WritesAny) -> () | AAssigns (_, Writes l) -> (* loop assigns *) let get_zone x = - get_zone_from_term true (Extlib.the loop_body_opt) x.it_content + get_zone_from_term (Extlib.the loop_body_opt) x.it_content in - List.iter - (fun (zone,deps) -> + List.iter + (fun (zone,deps) -> get_zone zone; match deps with FromAny -> () @@ -1450,41 +1539,36 @@ (** Used by annotations entry points. *) let get_zone_from_annotation a stmt loop_body_opt = - let before,a = match a with - | Before a -> true, a - | After a -> false, a - in match a with - | User a - | AI (_,a) -> - get_zone_from_annot a.annot_content before stmt loop_body_opt + | User a + | AI (_,a) -> get_zone_from_annot a.annot_content stmt loop_body_opt (** Used by annotations entry points. *) let get_from_stmt_annots code_annot_filter ((ki, _kf) as stmt) = Extlib.may - (fun caf -> + (fun caf -> let loop_body_opt = match ki.skind with | Loop(_, { bstmts = body :: _ }, _, _, _) -> Some body | _ -> None in Annotations.single_iter_stmt (fun a -> - if caf a then get_zone_from_annotation a stmt loop_body_opt) + if caf a then get_zone_from_annotation a stmt loop_body_opt) ki) - code_annot_filter + code_annot_filter (** Used by annotations entry points. *) - let from_ki_annot annot ~before ((ki, _kf) as stmt) = + let from_ki_annot annot ((ki, _kf) as stmt) = let real_ki = match ki.skind with Loop(_,{bstmts = loop_entry::_},_,_,_) -> Some loop_entry | _ -> None in - get_zone_from_annot annot.annot_content before stmt real_ki + get_zone_from_annot annot.annot_content stmt real_ki (** Entry point to get the list of [ki] * [Locations.Zone.t] needed to evaluate the code annotations related to this [stmt]. *) - let from_stmt_annot annot ~before stmt = - from_ki_annot annot ~before stmt; + let from_stmt_annot annot stmt = + from_ki_annot annot stmt; get_annot_result () (** Entry point to get the list of [ki] * [Locations.Zone.t] @@ -1503,30 +1587,27 @@ (** To quickly build a annotation filter *) let code_annot_filter annot ~ai ~user_assert ~slicing_pragma - ~loop_inv ~loop_var ~others = - let a = match annot with - | Before a -> a - | After a -> a - in let code_annot_filter a = + ~loop_inv ~loop_var ~others = + let code_annot_filter a = match a with - | APragma (Slice_pragma _) -> slicing_pragma - | AAssert _ -> user_assert - | AVariant _ -> loop_var - | AInvariant(_behav,true,_pred) -> loop_inv - | AInvariant(_,false,_) -> others - | AAssigns _ -> others -(* - | ALoopBehavior(_behav,_invs,_assigns) -> - loop_inv || others (* CORRECT ???? *) -*) - | APragma (Loop_pragma _)| APragma (Impact_pragma _) -> others - | AStmtSpec _ (* TODO: statement contract *) -> false - in match a with - | User a -> code_annot_filter a.annot_content - | AI _ -> ai + | APragma (Slice_pragma _) -> slicing_pragma + | AAssert _ -> user_assert + | AVariant _ -> loop_var + | AInvariant(_behav,true,_pred) -> loop_inv + | AInvariant(_,false,_) -> others + | AAssigns _ -> others + (* + | ALoopBehavior(_behav,_invs,_assigns) -> + loop_inv || others (* CORRECT ???? *) + *) + | APragma (Loop_pragma _)| APragma (Impact_pragma _) -> others + | AStmtSpec _ (* TODO: statement contract *) -> false + in match annot with + | User a -> code_annot_filter a.annot_content + | AI _ -> ai end -exception Prune +exception Prune let to_result_from_pred p = let visitor = object (_self) @@ -1537,61 +1618,71 @@ method vterm_lhost t = match t with | TResult _ -> raise Prune - | _ -> DoChildren + | _ -> DoChildren end - in (try - ignore(visitFramacPredicateNamed visitor p); - false - with | Prune -> true) + in + (try + ignore(Visitor.visitFramacPredicateNamed visitor p); + false + with Prune -> + true) let () = - Properties.Interp.code_annot := code_annot; - Properties.Interp.lval := lval; - Properties.Interp.expr := expr; - Properties.Interp.term_lval_to_lval := term_lval_to_lval; - Properties.Interp.term_to_exp := term_to_exp; - - Properties.Interp.force_term_to_exp := force_term_to_exp; - Properties.Interp.force_back_exp_to_term := force_back_exp_to_term; - Properties.Interp.force_term_lval_to_lval := force_term_lval_to_lval; - Properties.Interp.force_back_lval_to_term_lval := force_back_lval_to_term_lval; - Properties.Interp.force_term_offset_to_offset := force_term_offset_to_offset; - Properties.Interp.force_back_offset_to_term_offset := force_back_offset_to_term_offset; - - Properties.Interp.force_exp_to_term := force_exp_to_term; - Properties.Interp.force_lval_to_term_lval := force_lval_to_term_lval; - Properties.Interp.force_exp_to_predicate := force_exp_to_predicate; - Properties.Interp.force_exp_to_assertion := force_exp_to_assertion; - - Properties.Interp.from_range_to_comprehension := from_range_to_comprehension; - Properties.Interp.from_comprehension_to_range := from_comprehension_to_range; - - Properties.Interp.term_to_lval := term_to_lval; - Properties.Interp.range_to_comprehension := range_to_comprehension; - Properties.Interp.term_offset_to_offset := term_offset_to_offset; - - Properties.Interp.loc_to_lval := loc_to_lval; - Properties.Interp.loc_to_offset := loc_to_offset; - Properties.Interp.loc_to_exp := loc_to_exp; - Properties.Interp.loc_to_loc := loc_to_loc; - Properties.Interp.identified_term_zone_to_loc := identified_term_zone_to_loc; - - Properties.Interp.To_zone.code_annot_filter := To_zone.code_annot_filter; - Properties.Interp.To_zone.mk_ctx_func_contrat := To_zone.mk_ctx_func_contrat; - Properties.Interp.To_zone.mk_ctx_stmt_contrat := To_zone.mk_ctx_stmt_contrat; - Properties.Interp.To_zone.mk_ctx_stmt_annot := To_zone.mk_ctx_stmt_annot; - - Properties.Interp.To_zone.from_term := To_zone.from_term; - Properties.Interp.To_zone.from_terms := To_zone.from_terms; - Properties.Interp.To_zone.from_pred := To_zone.from_pred; - Properties.Interp.To_zone.from_preds := To_zone.from_preds; - Properties.Interp.To_zone.from_stmt_annot := To_zone.from_stmt_annot; - Properties.Interp.To_zone.from_stmt_annots := To_zone.from_stmt_annots; - Properties.Interp.To_zone.from_func_annots := To_zone.from_func_annots; + Db.Properties.Interp.code_annot := code_annot; + Db.Properties.Interp.lval := lval; + Db.Properties.Interp.expr := expr; + Db.Properties.Interp.term_lval_to_lval := term_lval_to_lval; + Db.Properties.Interp.term_to_exp := term_to_exp; + + Db.Properties.Interp.force_term_to_exp := force_term_to_exp; + Db.Properties.Interp.force_back_exp_to_term := force_back_exp_to_term; + Db.Properties.Interp.force_term_lval_to_lval := force_term_lval_to_lval; + Db.Properties.Interp.force_back_lval_to_term_lval := + force_back_lval_to_term_lval; + Db.Properties.Interp.force_term_offset_to_offset := + force_term_offset_to_offset; + Db.Properties.Interp.force_back_offset_to_term_offset := + force_back_offset_to_term_offset; + + Db.Properties.Interp.force_exp_to_term := force_exp_to_term; + Db.Properties.Interp.force_lval_to_term_lval := force_lval_to_term_lval; + Db.Properties.Interp.force_exp_to_predicate := force_exp_to_predicate; + Db.Properties.Interp.force_exp_to_assertion := force_exp_to_assertion; + + Db.Properties.Interp.from_range_to_comprehension := + from_range_to_comprehension; + Db.Properties.Interp.from_comprehension_to_range := + from_comprehension_to_range; + + Db.Properties.Interp.term_to_lval := term_to_lval; + Db.Properties.Interp.range_to_comprehension := range_to_comprehension; + Db.Properties.Interp.term_offset_to_offset := term_offset_to_offset; + + Db.Properties.Interp.loc_to_lval := loc_to_lval; + Db.Properties.Interp.loc_to_offset := loc_to_offset; + Db.Properties.Interp.loc_to_exp := loc_to_exp; + Db.Properties.Interp.loc_to_loc := loc_to_loc; + Db.Properties.Interp.identified_term_zone_to_loc := + identified_term_zone_to_loc; + + Db.Properties.Interp.To_zone.code_annot_filter := To_zone.code_annot_filter; + Db.Properties.Interp.To_zone.mk_ctx_func_contrat := + To_zone.mk_ctx_func_contrat; + Db.Properties.Interp.To_zone.mk_ctx_stmt_contrat := + To_zone.mk_ctx_stmt_contrat; + Db.Properties.Interp.To_zone.mk_ctx_stmt_annot := To_zone.mk_ctx_stmt_annot; + + Db.Properties.Interp.To_zone.from_term := To_zone.from_term; + Db.Properties.Interp.To_zone.from_terms := To_zone.from_terms; + Db.Properties.Interp.To_zone.from_pred := To_zone.from_pred; + Db.Properties.Interp.To_zone.from_preds := To_zone.from_preds; + Db.Properties.Interp.To_zone.from_stmt_annot := To_zone.from_stmt_annot; + Db.Properties.Interp.To_zone.from_stmt_annots := To_zone.from_stmt_annots; + Db.Properties.Interp.To_zone.from_func_annots := To_zone.from_func_annots; - Properties.Interp.to_result_from_pred := to_result_from_pred; + Db.Properties.Interp.to_result_from_pred := to_result_from_pred; (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/logic/logic_interp.mli frama-c-20111001+nitrogen+dfsg/src/logic/logic_interp.mli --- frama-c-20110201+carbon+dfsg/src/logic/logic_interp.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/logic_interp.mli 2011-10-10 08:38:23.000000000 +0000 @@ -22,16 +22,23 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + (* TODO: remove the module Properties from Db and export directly the functions from here. *) open Cil_types -open Db_types module To_zone : sig val not_yet_implemented : string ref end +(* [JS 2011/06/09] seem to be unused. + Be careful: require to call Kernel_function.set_spec if the new funspec is + put into a kernel function. *) (** returns a copy of the spec in which all formals in an ensures clause are guarded by an \at(x,Old). *) val formals_in_ensures: kernel_function -> funspec diff -Nru frama-c-20110201+carbon+dfsg/src/logic/properties_status.ml frama-c-20111001+nitrogen+dfsg/src/logic/properties_status.ml --- frama-c-20110201+carbon+dfsg/src/logic/properties_status.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/properties_status.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,684 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version v2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Cil_types -open Db_types -module H = Hashtbl (* [Hashtbl] redefined by [Property] *) -open Property - -let emitters = H.create 7 - -let max_state s1 s2 = - if s2 = State.dummy || H.mem emitters s1 then s1 else s2 - -let strongest_status fold = - fold - (fun (s, st1 as acc) (x, st2 as v) -> match s, x with - | Unknown, _ -> v - | Checked _, Unknown -> acc - | Checked {valid=v1}, Checked {valid=v2} -> - match v1, v2 with - | False, True -> - Kernel.debug "Inconsistent status: %a/%a" - Cil.d_annotation_status s - Cil.d_annotation_status x; - acc - | True, False -> - Kernel.debug "Inconsistent status: %a/%a" - Cil.d_annotation_status s - Cil.d_annotation_status x; - v - | True, Maybe | False, Maybe -> acc - | Maybe, True | Maybe, False -> v - | True, True | False, False | Maybe, Maybe -> s, max_state st1 st2) - (Unknown, State.dummy) - -let weakest_status l = - List.fold_left - (fun acc x -> match acc, x with - | Unknown, _ | _,Unknown -> Unknown - | Checked {valid=v1} as c1, (Checked {valid=v2} as c2) -> - match v1, v2 with - | True, _ -> c2 - | _, True -> c1 - | Maybe, _ -> c1 - | _, Maybe-> c2 - | False, False -> c1) - (Checked {valid=True; emitter="nothing to prove"}) - l - -(* this function must be called on an identified_property and code_annotation - which are already known to be tied to the same statement. - It performs too many tests: all identified_properties belonging to a - spec can be directly tied to the stmtspec since there is at most one per - statement. *) -let ip_is_in_code_annot annot ca = - match annot, ca.annot_content with - | IPBlob _, _ -> false - | IPPredicate(PKAssumes _,_,_,_), AStmtSpec _ -> true - | IPPredicate(PKAssumes _,_,_,_), _ -> false - | IPPredicate(PKEnsures _,_,_,_), AStmtSpec _ -> true - | IPPredicate(PKEnsures _,_,_,_), _ -> false - | IPPredicate(PKTerminates,_,_,_), AStmtSpec _ -> true - | IPPredicate(PKTerminates,_,_,_), _ -> false - | IPPredicate(PKRequires _,_,_,_), AStmtSpec _ -> true - | IPPredicate(PKRequires _,_,_,_), _ -> false - | IPAxiom _,_ -> false - | IPComplete(_,_,_), AStmtSpec _ -> true - | IPComplete(_,_,_), _ -> false - | IPDisjoint(_,_,_), AStmtSpec _ -> true - | IPDisjoint _, _ -> false - | IPAssigns (_,_,Id_behavior _,_), AStmtSpec _ -> true - | IPAssigns (_,_,Id_behavior _,_),_ -> false - | IPAssigns (_,_,Id_code_annot ca1,_), _ -> ca1.annot_id = ca.annot_id - | IPFrom (_,_,Id_behavior _,_), AStmtSpec _ -> true - | IPFrom (_,_,Id_behavior _,_),_ -> false - | IPFrom (_,_,Id_code_annot ca1,_), _ -> ca1.annot_id = ca.annot_id - | IPDecrease (_,_,None,_), AStmtSpec _ -> true - | IPDecrease (_,_,None,_), _ -> false - | IPDecrease (_,_,Some ca1,_),_ -> ca1.annot_id = ca.annot_id - | IPBehavior (_,_,_), AStmtSpec _ -> true - | IPBehavior _,_ -> false - | IPCodeAnnot (_,_,ca1),_ -> ca1.annot_id = ca.annot_id - -let get_dependencies annot = match get_kinstr annot with - | Kglobal -> [] - | Kstmt stmt -> - List.fold_left - (fun acc (a, s) -> match a with - | Before (User ca | AI(_, ca)) - | After (User ca | AI(_, ca)) -> - if ip_is_in_code_annot annot ca then s :: acc - else acc) - [] - (Annotations.get_all stmt) - -(* mutually recursive modules cannot be safely evaluated here *) -module Ref_graph = struct - let create_and_add_state = ref (fun ~clear:_ ~name:_ ~deps:_ -> assert false) - let add_state = ref (fun _ -> assert false) - let remove_state = ref (fun ~reset:_ _ -> assert false) - let self = ref State.dummy -end - -module Dash = - Dashtbl.Make - (struct - open Ref_graph - let create_and_add_state ~clear ~name ~deps = - !create_and_add_state ~clear ~name ~deps - let add_state s = !add_state s - let remove_state ~reset s = !remove_state ~reset s - let self = self - let internal_kind = `Correctness - end) - (Dashtbl.Default_key_marshaler(Datatype.Unit)) - (Dashtbl.Default_data_marshaler - (Datatype.Ref(Cil_datatype.Annotation_status))) - (struct let name = "Properties_status.Dash" end) - -module Status = - State_builder.Dashtbl - (struct - include Property - type marshaled = t - let marshal = function - | IPBlob s -> ip_axiom ("$" ^ State.get_unique_name s) - | x -> x - let unmarshal = function - | IPAxiom s when try s.[0] = '$' with Invalid_argument _ -> false -> - ip_blob (State.get (String.sub s 1 (String.length s - 1))) - | x -> x - let marshaler = marshal, unmarshal - let equal_marshaled = equal - let hash_marshaled = hash - end) - (Dash) - (struct - let name = "property status" - let size = 7 - let dependencies = [ Ast.self ] - let kind = `Internal - let internal_kind = `Correctness - end) - -let () = - Ref_graph.create_and_add_state := Status.Graph.create_and_add_state; - Ref_graph.add_state := Status.Graph.add_state; - Ref_graph.remove_state := Status.Graph.remove_state; - Ref_graph.self := !Status.Graph.self - -(* Rebuild dependencies for the internal dashtables *) -let () = - Project.register_after_load_hook - (fun () -> - Status.iter - (fun _ _ (d, _) -> - Dash.iter - (fun _ s (_, s') -> - assert (not (State.is_dummy s')); - let from = - match s with - | None -> [ !Status.Graph.self ] - | Some s -> [ s; !Status.Graph.self ] - in - State_dependency_graph.Dynamic.add_codependencies ~onto:s' from) - d)) - -let get_name annot = - let old = Parameters.UseUnicode.get () in - Parameters.UseUnicode.set false; - let s = Pretty_utils.sfprintf "%a" Property.pretty annot in - Parameters.UseUnicode.set old; - s - -let rec generic_memo f ?who annot = - match f ?who annot with - | [] -> - let h = Dash.create 7 in - Status.add (get_name annot) annot (get_dependencies annot) h; - generic_memo f ?who annot - | [ x ] -> - x - | _ :: _ :: _ -> - assert false - -let memo_tbl = generic_memo Status.find_all_data -let memo_state_tbl = generic_memo Status.find_all_states -let memo_tbl_full = generic_memo Status.find_all - -let get_all ?who annot = - let h = memo_tbl annot in - List.map (!) (Dash.find_all_data ?who h ()) - -(* when getting the strongest status of a behavior, we need to update its - dependencies which are automatically computed by getters (see function - [get] of [Make_updater]) *) -let get_all_behavior_ref = ref [] - -let strongest annot = - let status, state = match annot with - | IPBehavior _ -> - let l = List.map (fun f -> f annot) !get_all_behavior_ref in - strongest_status - (fun f acc -> - List.fold_left - (fun acc b -> f acc b) - acc - l) - | _ -> - let h = memo_tbl annot in - strongest_status - (fun f acc -> Dash.fold (fun _ _ (v, s) acc -> f acc (!v, s)) h acc) - in - status, if State.is_dummy state then None else Some state - -let get_state prop state = Status.find_state prop state - -module Consolidation_tree = struct - - type 'a value = - { value: 'a; - hypothesis: forest; - dependencies: State.t value list } - - and t = - { property: identified_property; - state: State.t; - mutable status: (annotation_status * State.t) value list } - - and forest = t list - - type vertex = - | Property of t - | State of State.t value - | Status of (annotation_status * State.t) value - - let state_of_vertex = function - | Property p -> p.state - | Status s -> snd s.value - | State s -> s.value - - module Visited = H.Make(State) - - let get_binding visited annot (dash, dash_state) properties = - let visit_property p s l b = -(* Format.printf "visiting ppt %S: %d@." (State.name s) (List.length l);*) - try - match Visited.find visited s with - | Property v as p, old_b -> - assert (not old_b && b && v.status = []); - v.status <- l; - Visited.replace visited s (p, b); - v - | _ -> - assert false - with Not_found -> - let v = { property = p; state = s; status = l } in - Visited.replace visited s (Property v, b); - v - in - let rec get_hyps_deps s = - State_dependency_graph.Dynamic.G.fold_pred - (fun s (hyps, deps) -> - try - match Visited.find visited s with - | Property p, _ -> - (if State.equal p.state dash_state then hyps else p :: hyps), - deps - | State s, _ -> hyps, s :: deps - | Status _, _ -> assert false - with Not_found -> - (* break mutually recursive states *) - Visited.add - visited - s - (State { value = s; hypothesis = []; dependencies = [] }, true); - let v = visit_state s in - hyps, v :: deps) - State_dependency_graph.Dynamic.graph - s - ([], []) - and visit_state s = - let h, d = get_hyps_deps s in - let v = { value = s; hypothesis = h; dependencies = d } in - Visited.replace visited s (State v, true); - v - in - let visit_status s v = - let h, d = get_hyps_deps s in - let v = { value = v, s; hypothesis = h; dependencies = d } in - Visited.add visited s (Status v, true); - v - in - let annot_codependencies = - State_selection.Dynamic.only_codependencies dash_state - in - let get_status dash = - Dash.fold - (fun () _ (status, status_state) acc -> - if Visited.mem visited status_state then - acc - else begin - match !status with - | Unknown -> - Visited.add - visited - status_state - (Status - { value = Unknown, - status_state; hypothesis = []; - dependencies = [] }, - true); - acc (* do not add [v] *) - | Checked _ as status -> - State_selection.Dynamic.iter_in_order - (fun s -> - if not (Visited.mem visited s) then - try - match Status.find_key s with - (* [s] corresponds to a property never seen yet *) - | [] -> assert false - | (p, _) :: tl -> - (* each property of the list should be the same *) - assert - (List.for_all - (fun (p', _) -> Property.equal p p') tl); - ignore (visit_property p s [] false) - with Not_found -> - (* [s] does not correspond to any property *) - ignore (visit_state s)) - (State_selection.Dynamic.union - (State_selection.Dynamic.only_codependencies status_state) - annot_codependencies); - visit_status status_state status :: acc - end) - dash - [] - in - try - match Visited.find visited dash_state with - (* [annot] already visited as an hypothesis of another property: - only update its status. *) - | Property p, false -> - visit_property p.property p.state (get_status dash) true :: properties - | Property p, true -> p :: properties - | (State _ | Status _), _ -> - assert false - with Not_found -> - (* [annot] never visited *) - let s = get_status dash in - visit_property annot dash_state s true :: properties - - let rec get_property visited annot = - let dash_and_state = memo_tbl_full annot in - let properties = get_binding visited annot dash_and_state [] in - Visited.iter - (fun _ v -> match v with - | _, true -> () (* already done *) - | Property p, false -> - (* update it *) - ignore (get_property visited p.property) - | (State _ | Status _), false -> assert false) - visited; - match properties with - | [] | _ :: _ :: _ -> assert false - | [ p ] -> p - - let get annot = get_property (Visited.create 17) annot - - let get_all () = - let visited = Visited.create 17 in - Status.fold - (fun a _ dash_and_state acc -> get_binding visited a dash_and_state acc) - [] - - type edge = And | Or - - module G = - Graph.Persistent.Digraph.ConcreteLabeled - (struct - type t = vertex - let compare x y = match x, y with - | Property p1, Property p2 -> State.compare p1.state p2.state - | Status s1, Status s2 -> - State.compare (snd s1.value) (snd s2.value) - | State s1, State s2 -> State.compare s1.value s2.value - | Property _, (State _ | Status _) -> -1 - | (State _ | Status _), Property _ -> 1 - | State _, Status _ -> -1 - | Status _, State _ -> 1 - let equal x y = compare x y = 0 - let hash = function - | Property p -> H.hash (0, State.hash p.state) - | State s -> H.hash (1, State.hash s.value) - | Status s -> H.hash (2, State.hash (snd s.value)) - end) - (struct - type t = edge - let default = And - let compare : edge -> edge -> int = Extlib.compare_basic - end) - - let rec add_property visited g p = - let state = p.state in - if Visited.mem visited state then - g - else begin - Visited.add visited state (); - let pp = Property p in - let status = p.status in - match status with - | [] -> - G.add_vertex g pp - | _ :: _ -> - List.fold_left - (fun g s -> - let g = G.add_edge_e g (pp, Or, Status s) in - add_status visited g s) - g - status - end - - and add_status visited g s = - let state = snd s.value in - assert (not (Visited.mem visited state)); - Visited.add visited state (); - let ss = Status s in - let g = - List.fold_left - (fun g h -> - let g = G.add_edge_e g (ss, And, Property h) in - add_property visited g h) - g - s.hypothesis - in - List.fold_left - (fun g d -> - let g = G.add_edge_e g (ss, And, State d) in - add_state visited g d) - g - s.dependencies - - (* could be merged with [add_status] in OCaml 3.12: - requires polymorphic recursion *) - and add_state visited g s = - let state = s.value in - if Visited.mem visited state then - g - else begin - Visited.add visited state (); - let ss = State s in - let g = - List.fold_left - (fun g h -> - let g = G.add_edge_e g (ss, And, Property h) in - add_property visited g h) - g - s.hypothesis - in - List.fold_left - (fun g d -> - let g = G.add_edge_e g (ss, And, State d) in - add_state visited g s) - g - s.dependencies - end - - let generic_get_graph f = - let t = f () in - let g = List.fold_left (add_property (Visited.create 17)) G.empty t in - let module R = - State_dependency_graph.Remove_useless_states - (G)(struct let kind v = State.kind (state_of_vertex v) end) - in - R.get g - - let get_full_graph () = generic_get_graph get_all - let get_graph p = generic_get_graph (fun () -> [ get p ]) - - let dump graph dot_file = - let module Dot = - Graph.Graphviz.Dot - (struct - include G - let status_color = function - | Checked { valid = False } -> 0xff0000 - | Checked { valid = True } -> 0x00ff00 - | Unknown | Checked { valid = Maybe } -> 0xffa500 (* orange *) - let graph_attributes _ = [(* `Ratio (`Float 0.25)*) ] - let vertex_name s = - "\"" ^ State.get_unique_name (state_of_vertex s) ^ "\"" - let vertex_attributes s = - let label s = `Label (String.escaped (State.get_name s)) in - match s with - | Property p -> - let s = p.state in - assert (State.kind s = `Correctness); - let fontcolor = status_color (fst (strongest p.property)) in - [ label s; `Color 0x4682b4; `Fontcolor fontcolor; - `Shape `Diamond; `Style `Filled ] - | Status status -> - let v, s = status.value in - assert (State.kind s = `Correctness); - let color = status_color v in - [ label s; `Color color; `Style `Filled; `Shape `Box ] - | State s -> - let s = s.value in - match State.kind s with - | `Irrelevant -> - Kernel.abort - "State %s is not relevant here" - (State.get_name s) - | `Internal | `Proxy `Internal -> - [ `Label ""; `Height 0.; `Width 0.; `Style `Filled ] - | `Tuning -> [ label s; `Style `Dotted ] - | `Correctness | `Proxy `Correctness -> - [ label s; `Color 0xb0c4de; `Style `Filled ] - let edge_attributes (_src, lab, dst) = - let s = state_of_vertex dst in - match State.kind s with - | `Internal | `Proxy `Internal -> - [ `Constraint false; `Arrowhead `None ] - | `Tuning - | `Correctness | `Proxy `Correctness -> - (match lab with - | And -> - let c = 0x8b4513 in - [ `Label "AND"; `Color c; `Fontcolor c; `Style `Bold ] - | Or -> - let c = 0x228b22 in - [ `Label "OR"; `Color c; `Fontcolor c; `Style `Bold ]) - | `Irrelevant -> - Kernel.abort - "State %s is not relevant here" - (State.get_name s) - let default_vertex_attributes _ = [] - let default_edge_attributes _ = [] - let get_subgraph _ = None - end) - in - let cout = open_out dot_file in - Dot.output_graph cout graph; - close_out cout - -end - -let pretty_all fmt annot = - let all_status = - let h = memo_tbl annot in - List.fold_left - (fun acc s -> match !s with Unknown -> acc | Checked _ as s -> s :: acc) - [] - (Dash.find_all_data h ()) - in - Pretty_utils.pp_list ~sep:";" Cil.d_annotation_status fmt all_status - -module Make_updater - (P: sig - val name: string - val emitter: State.t - end) = -struct - - let () = H.add emitters P.emitter () - - let get_name annot s = - let old = Parameters.UseUnicode.get () in - Parameters.UseUnicode.set false; - let status_name = function - | False -> "Invalid" - | True -> "Valid" - | Maybe -> "Maybe" - in - let s = match s with - | Unknown -> - Pretty_utils.sfprintf "Unknown: %a" Property.pretty annot - | Checked c -> -(* assert (c.emitter = State.name P.emitter);*) - Pretty_utils.sfprintf "%s for %s: %a" - (status_name c.valid) - c.emitter - Property.pretty annot - in - Parameters.UseUnicode.set old; - s - - let get_state_hypothesis hyps = - List.fold_left - (fun acc h -> memo_state_tbl h :: acc) - [ P.emitter ] - hyps - - let full_update must_add annot hyps f = - let h, hs = memo_tbl_full annot in - match Dash.find_all_local h () P.emitter with - | [] -> - let new_s = f Unknown in - if must_add || new_s <> Unknown then begin - let state_hyps = get_state_hypothesis hyps in - (* TODO: should detect more general cycles in the dependency graph *) - if List.exists (State.equal hs) state_hyps then - Kernel.fatal - "inconsistency detected: property %a depends of itself." - Property.pretty annot; - Dash.add - h - (get_name annot new_s) - () - (hs :: state_hyps) - (ref new_s) - end; - new_s - | [ d, s ] -> - (* TODO: does not try yet to update the hypothesis: - Should we do? *) - d := f !d; - let new_d = !d in - State.set_name s (get_name annot new_d); - new_d - | _ :: _ :: _ -> - assert false - - let rec compute_behavior kf st b = - let all_ip = Property.ip_post_cond_of_behavior kf st b in - let all_status = List.map get all_ip in - weakest_status all_status - - and get annot = match annot with - | IPBehavior(kf, st, b) -> - let post_conds = Property.ip_post_cond_of_behavior kf st b in - full_update false annot post_conds (fun _ -> compute_behavior kf st b) - | _ -> - full_update false annot [] (fun x -> x) - - let () = - get_all_behavior_ref := - (fun annot -> - let status = get annot in - let h = memo_tbl annot in - let state = - try Dash.find_state h () P.emitter - with Not_found -> - assert (status = Unknown); - State.dummy - in - status, state) - :: !get_all_behavior_ref - - let update annot hyps f = - match annot with - | IPBehavior _ -> Kernel.fatal "cannot modify a behavior status" - | _ -> full_update true annot hyps f - - let set annot hyps status = - ignore (full_update true annot hyps (fun _ -> status)) - -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/properties_status.mli frama-c-20111001+nitrogen+dfsg/src/logic/properties_status.mli --- frama-c-20110201+carbon+dfsg/src/logic/properties_status.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/properties_status.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version v2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Status of properties. - @since Boron-20100401 *) - -open Cil_types -open Db_types - -val get_all: - ?who:State.t list -> Property.t -> annotation_status list - (** For a given annotation, get all the status set by each plug-in. - @since Carbon-20101201 *) - -val strongest: Property.t -> annotation_status * State.t option - (** Checks status consistency according to the following - partial order: [Unknown < Maybe < True] and [Maybe < False] - @return the most precise status available for the - property according to the above partial order. - In case of consistent multiple status, the most recent - is returned. - The returned state is the one associated with the returned status itself. - @since Carbon-20101201 *) - -val get_state : Property.t -> State.t -> State.t - (** Get the state associated to the given key and state. - @raise Not_found if there is no such binding - @since Carbon-20101201 *) - -val pretty_all: Format.formatter -> Property.t -> unit - (** Pretty print all the status of a given annotation. - @since Carbon-20101201 *) - -module Consolidation_tree : sig - - type 'a value = private - { value: 'a; - hypothesis: forest; - dependencies: State.t value list } - - and t = private - { property: Property.t; - state: State.t; - mutable status: (annotation_status * State.t) value list } - - and forest = t list - - val get_all: unit -> forest - val get: Property.t -> t - - type vertex = - | Property of t - | State of State.t value - | Status of (annotation_status * State.t) value - - val state_of_vertex: vertex -> State.t - - type edge = And | Or - - module G: Graph.Sig.G with type V.t = vertex - and type E.label = edge - and type E.t = vertex * edge * vertex - val get_full_graph: unit -> G.t - val get_graph: Property.t -> G.t - - val dump: G.t -> string -> unit - -end - -(** Apply this functor in order to be able to modify status of annotations - within a plug-in. - @since Carbon-20101201 *) -module Make_updater - (P: sig - val name: string (** Plug-in name. *) - val emitter: State.t - end) : -sig - - val set: - Property.t -> Property.t list -> annotation_status -> - unit - (** Set the status of an annotation. - Do not reset the dependencies of this status. - @since Carbon-20101201 *) - - val update: - Property.t -> - Property.t list -> - (annotation_status -> annotation_status) -> - annotation_status - (** Update the status of a given annotation according to the old - status. Do not reset the dependencies of this status. - @since Carbon-20101201 *) - -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/property.ml frama-c-20111001+nitrogen+dfsg/src/logic/property.ml --- frama-c-20110201+carbon+dfsg/src/logic/property.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/property.ml 2011-10-10 08:38:23.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,16 +15,12 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) -(** Status of properties. - @since Boron-20100401 *) - open Cil_types -open Db_types open Cil_datatype type behavior_or_loop = @@ -35,7 +29,7 @@ type identified_complete = kernel_function * kinstr * string list type identified_disjoint = identified_complete -type identified_code_annotation = +type identified_code_annotation = kernel_function * stmt * code_annotation type identified_assigns = @@ -48,9 +42,9 @@ kernel_function * kinstr * behavior_or_loop - * (identified_term * identified_term list) + * (identified_term from (* * identified_term list *) ) -type identified_decrease = +type identified_decrease = kernel_function * kinstr * code_annotation option * term variant type identified_behavior = kernel_function * kinstr * funbehavior @@ -76,280 +70,388 @@ type identified_predicate = predicate_kind * kernel_function * kinstr * Cil_types.identified_predicate -type identified_spec = kernel_function * kinstr * funspec +type identified_unreachable = + | UStmt of kernel_function * stmt + | UProperty of identified_property + +and identified_axiomatic = string * identified_property list -type identified_property = - | IPBlob of State.t (* an unidentified property *) +and identified_property = | IPPredicate of identified_predicate | IPAxiom of string + | IPAxiomatic of identified_axiomatic + | IPLemma of string + | IPBehavior of identified_behavior | IPComplete of identified_complete | IPDisjoint of identified_disjoint | IPCodeAnnot of identified_code_annotation - | IPBehavior of identified_behavior | IPAssigns of identified_assigns | IPFrom of identified_from | IPDecrease of identified_decrease + | IPUnreachable of identified_unreachable + | IPOther of string * kernel_function option * kinstr -let get_kinstr = function - | IPBlob _ -> Kglobal - | IPPredicate (_,_,ki,_) -> ki - | IPAxiom _ -> Kglobal - | IPCodeAnnot (_,ki,_) -> Kstmt ki - | IPComplete (_,ki,_) -> ki - | IPDisjoint(_,ki,_) -> ki - | IPAssigns (_,ki,_,_) -> ki - | IPFrom(_,ki,_,_) -> ki +let rec get_kinstr = function + | IPPredicate (_,_,ki,_) + | IPBehavior(_, ki, _) + | IPComplete (_,ki,_) + | IPDisjoint(_,ki,_) + | IPAssigns (_,ki,_,_) + | IPFrom(_,ki,_,_) | IPDecrease (_,ki,_,_) -> ki - | IPBehavior(_,ki,_) -> ki - -let get_kf = function - | IPBlob _ -> None - | IPPredicate (_,kf,_,_) -> Some kf - | IPAxiom _ -> None - | IPCodeAnnot (kf,_,_) -> Some kf - | IPComplete (kf,_,_) -> Some kf - | IPDisjoint(kf,_,_) -> Some kf - | IPAssigns(kf,_,_,_) -> Some kf - | IPFrom(kf,_,_,_) -> Some kf - | IPDecrease (kf,_,_,_) -> Some kf - | IPBehavior(kf,_,_) -> Some kf + | IPUnreachable (UStmt(_, s)) -> Kstmt s + | IPUnreachable (UProperty ppt) -> get_kinstr ppt + | IPAxiom _ + | IPAxiomatic _ + | IPLemma _ -> Kglobal + | IPOther(_,_,ki) -> ki + | IPCodeAnnot (_,s,_) -> Kstmt s + +let rec get_kf = function + | IPPredicate (_,kf,_,_) + | IPBehavior(kf, _, _) + | IPCodeAnnot (kf,_,_) + | IPComplete (kf,_,_) + | IPDisjoint(kf,_,_) + | IPAssigns(kf,_,_,_) + | IPFrom(kf,_,_,_) + | IPDecrease (kf,_,_,_) + | IPUnreachable (UStmt (kf, _)) -> Some kf + | IPUnreachable(UProperty ppt) -> get_kf ppt + | IPAxiom _ + | IPAxiomatic _ + | IPLemma _ -> None + | IPOther(_,kf,_) -> kf let get_pk_behavior = function - | PKRequires b -> Some b - | PKAssumes b -> Some b - | PKEnsures (b,_) -> Some b + | PKRequires b | PKAssumes b | PKEnsures (b,_) -> Some b | PKTerminates -> None let get_behavior = function - | IPBlob _ -> None | IPPredicate (pk,_,_,_) -> get_pk_behavior pk - | IPAxiom _ -> None - | IPCodeAnnot (_,_,_) -> None - | IPComplete (_,_,_) -> None - | IPDisjoint(_,_,_) -> None - | IPAssigns(_,_,Id_behavior b,_) -> Some b - | IPAssigns(_,_,Id_code_annot _,_) -> None + | IPBehavior(_, _, b) -> Some b + | IPAssigns(_,_,Id_behavior b,_) | IPFrom(_,_,Id_behavior b,_) -> Some b - | IPFrom(_,_,Id_code_annot _,_) -> None - | IPDecrease (_,_,_,_) -> None - | IPBehavior(_,_,b) -> Some b + | IPAssigns(_,_,Id_code_annot _,_) + | IPFrom(_,_,Id_code_annot _,_) + | IPAxiom _ + | IPAxiomatic _ + | IPLemma _ + | IPCodeAnnot (_,_,_) + | IPComplete (_,_,_) + | IPDisjoint(_,_,_) + | IPDecrease _ + | IPUnreachable _ + | IPOther _ -> None include Datatype.Make_with_collections (struct + + include Datatype.Serializable_undefined - include Datatype.Undefined type t = identified_property let name = "identified property" - let reprs = [ IPBlob State.dummy ] + let reprs = [ IPAxiom "" ] let mem_project = Datatype.never_any_project - let hash = - let hash_bhv_loop = function - | Id_behavior b -> (0,Hashtbl.hash b.b_name) - | Id_code_annot ca -> (1,ca.annot_id) - in - function - | IPBlob x -> Hashtbl.hash (0, State.hash x) + let equal_opt eq a b = + match a,b with + | None,None -> true + | Some _,None | None,Some _ -> false + | Some x , Some y -> eq x y + + let compare_opt cmp a b = + match a,b with + | None,None -> 0 + | None,Some _ -> (-1) + | Some _,None -> 1 + | Some x,Some y -> cmp x y + + let rec pretty fmt = function + | IPPredicate (kind,_,_,p) -> + Format.fprintf fmt "%a@ %a" + pretty_predicate_kind kind Cil.d_identified_predicate p + | IPAxiom s -> Format.fprintf fmt "axiom@ %s" s + | IPAxiomatic(s, _) -> Format.fprintf fmt "axiomatic@ %s" s + | IPLemma s -> Format.fprintf fmt "lemma@ %s" s + | IPBehavior(_kf, ki, b) -> + if Cil.is_default_behavior b then + Format.pp_print_string fmt "default behavior" + else + Format.fprintf fmt "behavior %s" b.b_name; + (match ki with + | Kstmt s -> Format.fprintf fmt " for statement %d" s.sid + | Kglobal -> ()) + | IPCodeAnnot(_, _, a) -> Cil.d_code_annotation fmt a + | IPComplete(_, _, l) -> + Format.fprintf fmt "complete@ %a" + (Pretty_utils.pp_list ~sep:"," + (fun fmt s -> Format.fprintf fmt "@ %s" s)) + l + | IPDisjoint(_, _, l) -> + Format.fprintf fmt "disjoint@ %a" + (Pretty_utils.pp_list ~sep:"," + (fun fmt s -> Format.fprintf fmt " %s" s)) + l + | IPAssigns(_, _, _, l) -> Cil.d_assigns fmt (Writes l) + | IPFrom (_,_,_, f) -> Cil.d_from fmt f + | IPDecrease(_, _, None,v) -> Cil.d_decreases fmt v + | IPDecrease(_, _, _,v) -> Cil.d_loop_variant fmt v + | IPUnreachable(UStmt(_, stmt)) -> + Format.fprintf fmt "unreachable stmt %a" Cil.d_stmt stmt + | IPUnreachable(UProperty p) -> + Format.fprintf fmt "unreachable property %a" pretty p + | IPOther(s,_,_) -> Format.pp_print_string fmt s + + let rec hash = + let hash_bhv_loop = function + | Id_behavior b -> (0, Hashtbl.hash b.b_name) + | Id_code_annot ca -> (1, ca.annot_id) + in + function | IPPredicate (_,_,_,x) -> Hashtbl.hash (1, x.ip_id) | IPAxiom x -> Hashtbl.hash (2, x) - | IPCodeAnnot(_,_, ca) -> Hashtbl.hash (3, ca.annot_id) + | IPAxiomatic x -> Hashtbl.hash (3, x) + | IPLemma x -> Hashtbl.hash (4, x) + | IPCodeAnnot(_,_, ca) -> Hashtbl.hash (5, ca.annot_id) | IPComplete(f, ki, x) -> - Hashtbl.hash (4, Kernel_function.hash f, Kinstr.hash ki, x) + Hashtbl.hash (6, Kf.hash f, Kinstr.hash ki, x) | IPDisjoint(f, ki, x) -> - Hashtbl.hash (5, Kernel_function.hash f, Kinstr.hash ki, x) + Hashtbl.hash(7, Kf.hash f, Kinstr.hash ki, x) | IPAssigns(f, ki, b, _l) -> - Hashtbl.hash - (6, Kernel_function.hash f, Kinstr.hash ki, hash_bhv_loop b) - | IPFrom(kf,ki,b,(t,_)) -> + Hashtbl.hash (8, Kf.hash f, Kinstr.hash ki, hash_bhv_loop b) + | IPFrom(kf,ki,b,(t,_)) -> Hashtbl.hash - (7, Kernel_function.hash kf, Kinstr.hash ki, - hash_bhv_loop b, Cil_datatype.Identified_term.hash t) + (9, Kf.hash kf, Kinstr.hash ki, + hash_bhv_loop b, Identified_term.hash t) | IPDecrease(kf, ki, _ca, _v) -> - (* At most one loop variant per statement anyway, no - need to discriminate against the code annotation itself - *) - Hashtbl.hash (8, Kernel_function.hash kf, Kinstr.hash ki) - | IPBehavior(kf, ki, b) -> - Hashtbl.hash (9, Kernel_function.hash kf, Kinstr.hash ki, b.b_name) - - let equal p1 p2 = - let eq_bhv (f1,ki1,b1) (f2,ki2,b2) = - Kernel_function.equal f1 f2 && Kinstr.equal ki1 ki2 + (* At most one loop variant per statement anyway, no + need to discriminate against the code annotation itself *) + Hashtbl.hash (10, Kf.hash kf, Kinstr.hash ki) + | IPBehavior(kf, s, b) -> + Hashtbl.hash (11, Kf.hash kf, Kinstr.hash s, b.b_name) + | IPUnreachable(UStmt(_, s)) -> Hashtbl.hash(12, Stmt.hash s) + | IPUnreachable(UProperty p) -> Hashtbl.hash(13, hash p) + | IPOther(s,_,_) -> Hashtbl.hash (14, s) + + let rec equal p1 p2 = + let eq_bhv (f1,ki1,b1) (f2,ki2,b2) = + Kf.equal f1 f2 && Kinstr.equal ki1 ki2 && (match b1, b2 with - | Id_code_annot ca1, Id_code_annot ca2 -> - ca1.annot_id = ca2.annot_id - | Id_behavior b1, Id_behavior b2 -> b1.b_name = b2.b_name - | Id_code_annot _, Id_behavior _ - | Id_behavior _, Id_code_annot _ -> false) - in - match p1, p2 with - | IPBlob s1, IPBlob s2 -> State.equal s1 s2 + | Id_code_annot ca1, Id_code_annot ca2 -> + ca1.annot_id = ca2.annot_id + | Id_behavior b1, Id_behavior b2 -> b1.b_name = b2.b_name + | Id_code_annot _, Id_behavior _ + | Id_behavior _, Id_code_annot _ -> false) + in + match p1, p2 with | IPPredicate (_,_,_,s1), IPPredicate (_,_,_,s2) -> s1.ip_id = s2.ip_id - | IPAxiom s1, IPAxiom s2 -> s1 = s2 + | IPAxiom s1, IPAxiom s2 + | IPAxiomatic(s1, _), IPAxiomatic(s2, _) + | IPLemma s1, IPLemma s2 -> s1 = s2 | IPCodeAnnot(_,_,ca1), IPCodeAnnot(_,_,ca2) -> ca1.annot_id = ca2.annot_id | IPComplete(f1, ki1, x1), IPComplete(f2, ki2, x2) | IPDisjoint(f1, ki1, x1), IPDisjoint(f2, ki2, x2) -> - Kernel_function.equal f1 f2 && Kinstr.equal ki1 ki2 && x1 = x2 + Kf.equal f1 f2 && Kinstr.equal ki1 ki2 && x1 = x2 | IPAssigns (f1, ki1, b1, _), IPAssigns (f2, ki2, b2, _) -> eq_bhv (f1,ki1,b1) (f2,ki2,b2) - | IPFrom (f1,ki1,b1,(t1,_)), IPFrom (f2, ki2,b2,(t2,_)) -> + | IPFrom (f1,ki1,b1,(t1,_)), IPFrom (f2, ki2,b2,(t2,_)) -> eq_bhv (f1,ki1,b1) (f2,ki2,b2) && t1.it_id = t2.it_id | IPDecrease(f1, ki1, _, _), IPDecrease(f2, ki2, _, _) -> - Kernel_function.equal f1 f2 && Kinstr.equal ki1 ki2 - | IPBehavior(f1, ki1, b1), IPBehavior(f2, ki2, b2) -> - Kernel_function.equal f1 f2 - && Kinstr.equal ki1 ki2 - && b1.b_name = b2.b_name - | (IPBlob _ | IPPredicate _ | IPAxiom _ | IPCodeAnnot _ - | IPComplete _ | IPDisjoint _ | IPAssigns _ | IPFrom _ - | IPDecrease _ | IPBehavior _ ), _ -> false - - let compare x y = - let cmp_bhv (f1,ki1,b1) (f2,ki2,b2) = - let n = Kernel_function.compare f1 f2 in + Kf.equal f1 f2 && Kinstr.equal ki1 ki2 + | IPUnreachable(UStmt(_, s1)), IPUnreachable(UStmt(_, s2)) -> + Stmt.equal s1 s2 + | IPUnreachable(UProperty p1), IPUnreachable(UProperty p2) -> + equal p1 p2 + | IPBehavior(f1, k1, b1), IPBehavior(f2, k2, b2) -> + Kf.equal f1 f2 + && Kinstr.equal k1 k2 + && Datatype.String.equal b1.b_name b2.b_name + | IPOther(s1,kf1,ki1), IPOther(s2,kf2,ki2) -> + Datatype.String.equal s1 s2 + && Kinstr.equal ki1 ki2 + && equal_opt Kf.equal kf1 kf2 + | (IPPredicate _ | IPAxiom _ | IPAxiomatic _ | IPLemma _ + | IPCodeAnnot _ | IPComplete _ | IPDisjoint _ | IPAssigns _ + | IPFrom _ | IPDecrease _ | IPBehavior _ | IPUnreachable _ + | IPOther _ ), _ -> false + + let rec compare x y = + let cmp_bhv (f1,ki1,b1) (f2,ki2,b2) = + let n = Kf.compare f1 f2 in if n = 0 then let n = Kinstr.compare ki1 ki2 in if n = 0 then match b1, b2 with | Id_behavior b1, Id_behavior b2 -> - Datatype.String.compare b1.b_name b2.b_name + Datatype.String.compare b1.b_name b2.b_name | Id_code_annot ca1, Id_code_annot ca2 -> - Datatype.Int.compare ca1.annot_id ca2.annot_id - | Id_behavior _, Id_code_annot _ -> -1 - | Id_code_annot _, Id_behavior _ -> 1 - else n - else n - in - match x, y with - | IPBlob s1, IPBlob s2 -> State.compare s1 s2 + Datatype.Int.compare ca1.annot_id ca2.annot_id + | Id_behavior _, Id_code_annot _ -> -1 + | Id_code_annot _, Id_behavior _ -> 1 + else n + else n + in + match x, y with | IPPredicate (_,_,_,s1), IPPredicate (_,_,_,s2) -> Datatype.Int.compare s1.ip_id s2.ip_id - | IPAxiom s1, IPAxiom s2 -> String.compare s1 s2 | IPCodeAnnot(_,_,ca1), IPCodeAnnot(_,_,ca2) -> Datatype.Int.compare ca1.annot_id ca2.annot_id + | IPBehavior(f1, k1, b1), IPBehavior(f2, k2, b2) -> + cmp_bhv (f1, k1, Id_behavior b1) (f2, k2, Id_behavior b2) | IPComplete(f1, ki1, x1), IPComplete(f2, ki2, x2) | IPDisjoint(f1, ki1, x1), IPDisjoint(f2, ki2, x2) -> - let n = Kernel_function.compare f1 f2 in + let n = Kf.compare f1 f2 in if n = 0 then let n = Kinstr.compare ki1 ki2 in - if n = 0 then Extlib.compare_basic x1 x2 else n + if n = 0 then Extlib.compare_basic x1 x2 else n else n | IPAssigns (f1, ki1, b1, _), IPAssigns (f2, ki2, b2, _) -> cmp_bhv (f1,ki1,b1) (f2,ki2,b2) - | IPFrom (f1,ki1,b1,(t1,_)), IPFrom(f2,ki2,b2,(t2,_)) -> + | IPFrom (f1,ki1,b1,(t1,_)), IPFrom(f2,ki2,b2,(t2,_)) -> let n = cmp_bhv (f1,ki1,b1) (f2,ki2,b2) in - if n = 0 then Cil_datatype.Identified_term.compare t1 t2 else n + if n = 0 then Identified_term.compare t1 t2 else n | IPDecrease(f1, ki1,_,_), IPDecrease(f2, ki2,_,_) -> - let n = Kernel_function.compare f1 f2 in + let n = Kf.compare f1 f2 in if n = 0 then Kinstr.compare ki1 ki2 else n - | IPBehavior(f1, ki1, b1), IPBehavior(f2, ki2, b2) -> - cmp_bhv (f1,ki1, Id_behavior b1) (f2,ki2,Id_behavior b2) + | IPUnreachable(UStmt(_, s1)), IPUnreachable(UStmt(_, s2)) -> + Stmt.compare s1 s2 + | IPUnreachable(UProperty p1), IPUnreachable(UProperty p2) -> + compare p1 p2 + | IPAxiom s1, IPAxiom s2 + | IPAxiomatic(s1, _), IPAxiomatic(s2, _) + | IPLemma s1, IPLemma s2 -> + Datatype.String.compare s1 s2 + | IPOther(s1,kf1,ki1), IPOther(s2,kf2,ki2) -> + let s = Datatype.String.compare s1 s2 in + if s <> 0 then s else + let s = compare_opt Kf.compare kf1 kf2 in + if s <> 0 then s else + Kinstr.compare ki1 ki2 | x, y -> - let nb = function - | IPPredicate _ -> 1 - | IPAssigns (_, _, _, _) -> 2 - | IPDecrease _ -> 3 - | IPAxiom _ -> 4 - | IPCodeAnnot _ -> 5 - | IPBehavior _ -> 6 - | IPComplete (_, _, _) -> 7 - | IPDisjoint (_, _, _) -> 8 - | IPBlob _ -> 9 + (* [JS 2011/07/20] very dangerous pattern matching *) + let nb = function + | IPPredicate _ -> 1 + | IPAssigns (_, _, _, _) -> 2 + | IPDecrease _ -> 3 + | IPAxiom _ -> 4 + | IPAxiomatic _ -> 5 + | IPLemma _ -> 6 + | IPCodeAnnot _ -> 7 + | IPComplete (_, _, _) -> 8 + | IPDisjoint (_, _, _) -> 9 | IPFrom _ -> 10 + | IPBehavior _ -> 11 + | IPUnreachable _ -> 12 + | IPOther _ -> 13 in Datatype.Int.compare (nb x) (nb y) - let pretty fmt = function - | IPBlob s -> Format.fprintf fmt "%s" (State.get_name s) - | IPPredicate (kind,_,_,p) -> - Format.fprintf fmt "%a %a" - pretty_predicate_kind kind Cil.d_identified_predicate p - | IPAxiom s -> Format.fprintf fmt "axiom %s" s - | IPCodeAnnot(_, _, a) -> Cil.d_code_annotation fmt a - | IPComplete(_, _, l) -> - Format.fprintf fmt "complete %a" - (Pretty_utils.pp_list (fun fmt s -> Format.fprintf fmt " %s" s)) - l - | IPDisjoint(_, _, l) -> - Format.fprintf fmt "disjoint %a" - (Pretty_utils.pp_list (fun fmt s -> Format.fprintf fmt " %s" s)) - l - | IPAssigns(_, _, _, l) -> Cil.d_assigns fmt (Writes l) - | IPFrom (_,_,_,(b,f)) -> Cil.d_from fmt (b,From f) - | IPDecrease(_, _, _,_) -> Format.fprintf fmt "decrease: " - | IPBehavior(_, _, b) -> Format.fprintf fmt "behavior %s" b.b_name - end) - -let ip_of_behavior kf st b = IPBehavior(kf,st,b) + +(* [JS 2011/08/04] seem to be dead code *) +(*let short_pretty fmt = function + | IPPredicate (kind, kf,_,_) -> + Format.fprintf fmt "%a of function %a" + pretty_predicate_kind kind Kf.pretty kf + | IPAxiom s -> Format.fprintf fmt "axiom %s" s + | IPLemma s -> Format.fprintf fmt "lemma %s" s + | IPCodeAnnot(_, _, a) -> + Format.pp_print_string fmt + (match a.annot_content with + | AAssert _ -> "assertion" + | AStmtSpec _ -> "stmt contract" + | AInvariant _ -> "invariant" + | AVariant _ -> "variant" + | AAssigns _ -> "assigns" + | APragma _ -> "pragma") + | IPComplete(kf, Kglobal, _) -> + Format.fprintf fmt "complete behavior of function %a" Kf.pretty kf + | IPComplete(_, Kstmt _, _) -> Format.fprintf fmt "complete behavior" + | IPDisjoint(kf, Kglobal, _) -> + Format.fprintf fmt "disjoint behavior of function %a" Kf.pretty kf + | IPDisjoint(_, Kstmt _, _) -> Format.fprintf fmt "disjoint behavior" + | IPAssigns(kf, Kglobal, _, _) -> + Format.fprintf fmt "assigns of function %a" Kf.pretty kf + | IPAssigns(_, Kstmt _, _, _) -> Format.pp_print_string fmt "assigns" + | IPFrom _ -> Format.pp_print_string fmt "from" + | IPDecrease(kf, Kglobal, None,_) -> + Format.fprintf fmt "decrease of function %a" Kf.pretty kf + | IPDecrease(_, Kstmt _, None,_) -> Format.pp_print_string fmt "decrease" + | IPDecrease(_, _, _,_) -> Format.pp_print_string fmt "loop variant" + | IPNotacsl s -> Format.pp_print_string fmt s + *) + +let ip_other s kf ki = IPOther(s,kf,ki) +let ip_unreachable_stmt kf ki = IPUnreachable(UStmt(kf, ki)) +let ip_unreachable_ppt p = IPUnreachable(UProperty p) let ip_of_ensures kf st b (k,p) = IPPredicate (PKEnsures(b,k),kf,st,p) let ip_ensures_of_behavior kf st b = List.map (ip_of_ensures kf st b) b.b_post_cond -let ip_of_assigns kf st loc a = - match a with - WritesAny -> None - | Writes a -> Some (IPAssigns (kf,st,loc,a)) +let ip_of_assigns kf st loc = function + | WritesAny -> None + | Writes [(a,_)] when Logic_utils.is_result a.it_content -> + (* We're only assigning the result (with dependencies), but no + global variables, this amounts to \nothing. + *) + Some (IPAssigns (kf, st, loc, [])) + | Writes a -> Some (IPAssigns (kf,st,loc,a)) -let ip_assigns_of_behavior kf st b = +let ip_assigns_of_behavior kf st b = ip_of_assigns kf st (Id_behavior b) b.b_assigns -let ip_of_from kf st loc (b,f) = - match f with - FromAny -> None - | From f -> Some (IPFrom (kf,st, loc, (b,f))) - - -let ip_from_of_behavior kf st b = - match b.b_assigns with - | WritesAny -> [] - | Writes l -> - let treat_from acc from = - match ip_of_from kf st (Id_behavior b) from with - None -> acc - | Some ip -> ip::acc - in - List.fold_left treat_from [] l - -let ip_assigns_of_code_annot kf st ca = - match ca.annot_content with - | AAssigns (_,a) -> - ip_of_assigns kf st (Id_code_annot ca) a - | _ -> None +let ip_of_from kf st loc from = IPFrom (kf,st, loc, from) -let ip_from_of_code_annot kf st ca = - match ca.annot_content with - | AAssigns(_,WritesAny) -> [] - | AAssigns (_,Writes l) -> - let treat_from acc from = - match ip_of_from kf st (Id_code_annot ca) from with - None -> acc - | Some ip -> ip::acc - in - List.fold_left treat_from [] l - | _ -> [] +let ip_from_of_behavior kf st b = match b.b_assigns with + | WritesAny -> [] + | Writes l -> + let treat_from acc (out, froms) = match froms with + | FromAny -> acc + | From _ -> + let ip = ip_of_from kf st (Id_behavior b) (out, froms) in + ip :: acc + in + List.fold_left treat_from [] l + +let ip_assigns_of_code_annot kf st ca = match ca.annot_content with + | AAssigns (_,a) -> ip_of_assigns kf st (Id_code_annot ca) a + | _ -> None + +let ip_from_of_code_annot kf st ca = match ca.annot_content with + | AAssigns(_,WritesAny) -> [] + | AAssigns (_,Writes l) -> + let treat_from acc (out, froms) = match froms with FromAny -> acc + | From _ -> + let ip = ip_of_from kf st (Id_code_annot ca) (out, froms) in ip::acc + in + List.fold_left treat_from [] l + | _ -> [] let ip_post_cond_of_behavior kf st b = - ip_ensures_of_behavior kf st b + ip_ensures_of_behavior kf st b @ (Extlib.list_of_opt (ip_assigns_of_behavior kf st b)) @ ip_from_of_behavior kf st b +let ip_of_behavior kf s b = IPBehavior(kf, s, b) + let ip_of_requires kf st b p = IPPredicate (PKRequires b,kf,st,p) -let ip_requires_of_behavior kf st b = +let ip_requires_of_behavior kf st b = List.map (ip_of_requires kf st b) b.b_requires let ip_of_assumes kf st b p = IPPredicate (PKAssumes b,kf,st,p) -let ip_assumes_of_behavior kf st b = +let ip_assumes_of_behavior kf st b = List.map (ip_of_assumes kf st b) b.b_assumes let ip_all_of_behavior kf st b = - ip_requires_of_behavior kf st b + ip_of_behavior kf st b + :: ip_requires_of_behavior kf st b @ ip_assumes_of_behavior kf st b @ ip_post_cond_of_behavior kf st b @@ -365,10 +467,9 @@ let ip_of_terminates kf st p = IPPredicate(PKTerminates,kf,st,p) -let ip_terminates_of_spec kf st s = - match s.spec_terminates with - None -> None - | Some p -> Some (ip_of_terminates kf st p) +let ip_terminates_of_spec kf st s = match s.spec_terminates with + | None -> None + | Some p -> Some (ip_of_terminates kf st p) let ip_of_decreases kf st d = IPDecrease(kf,st,None,d) @@ -386,35 +487,75 @@ @ (Extlib.list_of_opt (ip_decreases_of_spec kf st s)) let ip_axiom s = IPAxiom s - -let ip_blob s = IPBlob s +let ip_lemma s = IPLemma s let ip_of_code_annot kf ki ca = let st = Kstmt ki in match ca.annot_content with - | AAssert _ | AInvariant _ -> - [IPCodeAnnot(kf, ki, ca)] - | AStmtSpec s -> ip_of_spec kf st s - | AVariant t -> [IPDecrease (kf,st,(Some ca),t)] - | AAssigns _ -> - (Extlib.list_of_opt (ip_assigns_of_code_annot kf st ca)) - @ ip_from_of_code_annot kf st ca - | APragma _ -> [IPCodeAnnot (kf,ki,ca)] - -let ip_of_code_annot_single kf ki ca = - match ip_of_code_annot kf ki ca with - [] -> - Kernel.error - "@[Cannot find a property to extract from code annotation@\n%a@]" - Cil.d_code_annotation ca; - raise (Invalid_argument "ip_of_code_annot_single") - | [ip] -> ip - | ip::_ -> - Kernel.warning - "@[Choosing one of multiple properties associated \ + | AAssert _ | AInvariant _ -> [ IPCodeAnnot(kf, ki, ca) ] + | AStmtSpec (_bhv,s) -> + (* [JS 2011/08/29] seem to be incorrect since it does not use the behavior + while [ip_of_spec] keeps all behaviors *) + ip_of_spec kf st s + | AVariant t -> [ IPDecrease (kf,st,(Some ca),t) ] + | AAssigns _ -> + Extlib.list_of_opt (ip_assigns_of_code_annot kf st ca) + @ ip_from_of_code_annot kf st ca + | APragma p when Logic_utils.is_property_pragma p -> + [ IPCodeAnnot (kf,ki,ca) ] + | APragma _ -> [] + +let ip_of_code_annot_single kf ki ca = match ip_of_code_annot kf ki ca with + | [] -> + (* [JS 2011/06/07] using Kernel.error here seems very strange. + Actually it is incorrect in case of pragma which is not a property (see + function ip_of_code_annot above. *) + Kernel.error + "@[cannot find a property to extract from code annotation@\n%a@]" + Cil.d_code_annotation ca; + raise (Invalid_argument "ip_of_code_annot_single") + | [ ip ] -> ip + | ip :: _ -> + Kernel.warning + "@[choosing one of multiple properties associated \ to code annotation@\n%a@]" - Cil.d_code_annotation ca; - ip + Cil.d_code_annotation ca; + ip + +(* Must ensure that the first property is the best one in order to represent + the annotation (see ip_of_global_annotation_single) *) +let ip_of_global_annotation a = + let rec aux acc = function + | Daxiomatic(name, l, _) -> + let ppts = List.fold_left aux [] l in + IPAxiomatic(name, ppts) :: (ppts @ acc) + | Dlemma(name, true, _, _,_, _) -> ip_axiom name :: acc + | Dlemma(name, false, _, _, _, _) -> ip_lemma name :: acc + | Dinvariant(l, _) -> + (* TODO *) + Kernel.warning "ignoring status of global invariant `%s'" + l.l_var_info.lv_name; + acc + | Dtype_annot(l, _) -> + (* TODO *) + Kernel.warning "ignoring status of type invariant `%s'" + l.l_var_info.lv_name; + acc + | Dmodel_annot(l, _) -> + (* TODO *) + Kernel.warning "ignoring status of model `%s'" l.l_var_info.lv_name; + acc + | Dfun_or_pred(_) | Dvolatile _ | Dtype _ -> + (* no associated status for these annotations *) + acc + in + aux [] a + +let ip_of_global_annotation_single a = match ip_of_global_annotation a with + | [] -> None + | ip :: _ -> + (* the first one is the good one, see ip_of_global_annotation *) + Some ip (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/logic/property.mli frama-c-20111001+nitrogen+dfsg/src/logic/property.mli --- frama-c-20110201+carbon+dfsg/src/logic/property.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/property.mli 2011-10-10 08:38:23.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,7 +15,7 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) @@ -26,43 +24,50 @@ @since Carbon-20101201 *) open Cil_types -open Db_types + +(**************************************************************************) +(** {2 Type declarations} *) +(**************************************************************************) + +(* [JS 20110607] TODO: redesigned the type below in order to: + - use private records instead of tuples whenever possible + - extend identified_property to any possible annotations + - design more consistent type + For instance, + - why code annotations are represented so differently? + - why type [behavior_or_loop] does not contain "assigns" somewhere in its + name? + - why this last type cannot be private? *) (** assigns can belong either to a contract or a loop annotation *) -type behavior_or_loop = - Id_behavior of funbehavior +type behavior_or_loop = (* private *) + | Id_behavior of funbehavior | Id_code_annot of code_annotation type identified_complete = kernel_function * kinstr * string list -type identified_disjoint = identified_complete +type identified_disjoint = identified_complete (** Only AAssert, AInvariant, or APragma. Other code annotations are - dispatched as identified_property of their own. -*) -type identified_code_annotation = - kernel_function * stmt * code_annotation + dispatched as identified_property of their own. *) +type identified_code_annotation = kernel_function * stmt * code_annotation type identified_assigns = - kernel_function - * kinstr - * behavior_or_loop - * identified_term from list + kernel_function * kinstr * behavior_or_loop * identified_term from list type identified_from = kernel_function * kinstr * behavior_or_loop - * (identified_term * identified_term list) + * (identified_term from (* * identified_term list *) ) -type identified_decrease = +type identified_decrease = kernel_function * kinstr * code_annotation option * term variant (** code_annotation is None for decreases and [Some { AVariant }] for - loop variant. - *) + loop variant. *) type identified_behavior = kernel_function * kinstr * funbehavior -type predicate_kind = +type predicate_kind = private | PKRequires of funbehavior | PKAssumes of funbehavior | PKEnsures of funbehavior * termination_kind @@ -71,191 +76,186 @@ type identified_predicate = predicate_kind * kernel_function * kinstr * Cil_types.identified_predicate -type identified_spec = kernel_function * kinstr * funspec +type identified_unreachable = + | UStmt of kernel_function * stmt + | UProperty of identified_property + +and identified_axiomatic = string * identified_property list -type identified_property = private - | IPBlob of State.t (* an unidentified property *) +and identified_property = private | IPPredicate of identified_predicate | IPAxiom of string + | IPAxiomatic of identified_axiomatic + | IPLemma of string + | IPBehavior of identified_behavior | IPComplete of identified_complete | IPDisjoint of identified_disjoint | IPCodeAnnot of identified_code_annotation - | IPBehavior of identified_behavior | IPAssigns of identified_assigns | IPFrom of identified_from | IPDecrease of identified_decrease + | IPUnreachable of identified_unreachable + | IPOther of string * kernel_function option * kinstr include Datatype.S_with_collections with type t = identified_property -(** {2 Builders} *) +(* [JS 2011/08/04] seem to be unused *) +(*val short_pretty: Format.formatter -> t -> unit*) -(** Builds an IPBehavior. - @since Carbon-20101201-beta2+dev -*) -val ip_of_behavior: - kernel_function -> kinstr -> funbehavior -> identified_property +(**************************************************************************) +(** {2 Smart constructors} *) +(**************************************************************************) + +val ip_other: string -> kernel_function option -> kinstr -> identified_property +(** Create a non-standard property. + @since Nitrogen-20111001 *) + +val ip_unreachable_stmt: kernel_function -> stmt -> identified_property +(** @since Carbon-20110201 *) + +val ip_unreachable_ppt: identified_property -> identified_property +(** @since Carbon-20110201 *) (** IPPredicate of a single requires. - @since Carbon-20101201-beta2+dev -*) + @since Carbon-20110201 *) val ip_of_requires: - kernel_function -> kinstr -> funbehavior -> + kernel_function -> kinstr -> funbehavior -> Cil_types.identified_predicate -> identified_property -(** Builds the IPPredicate corresponding to requires of a behavior. - @since Carbon-20101201-beta2+dev -*) +(** Builds the IPPredicate corresponding to requires of a behavior. + @since Carbon-20110201 *) val ip_requires_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property list (** IPPredicate of a single assumes. - @since Carbon-20101201-beta2+dev -*) + @since Carbon-20110201 *) val ip_of_assumes: - kernel_function -> kinstr -> funbehavior -> + kernel_function -> kinstr -> funbehavior -> Cil_types.identified_predicate -> identified_property -(** Builds the IPPredicate corresponding to assumes of a behavior. - @since Carbon-20101201-beta2+dev -*) +(** Builds the IPPredicate corresponding to assumes of a behavior. + @since Carbon-20110201 *) val ip_assumes_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property list -(** IPPredicate of single ensures. - @since Carbon-20101201-beta2+dev -*) +(** IPPredicate of single ensures. + @since Carbon-20110201 *) val ip_of_ensures: - kernel_function -> kinstr -> funbehavior -> + kernel_function -> kinstr -> funbehavior -> (termination_kind * Cil_types.identified_predicate) -> identified_property -(** Builds the IPPredicate PKEnsures corresponding to a behavior. - @since Carbon-20101201-beta2+dev -*) -val ip_ensures_of_behavior: +(** Builds the IPPredicate PKEnsures corresponding to a behavior. + @since Carbon-20110201 *) +val ip_ensures_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property list -(** Builds the corresponding IPAssigns. - @since Carbon-20101201-beta2+dev -*) +(** Builds the corresponding IPAssigns. + @since Carbon-20110201 *) val ip_of_assigns: - kernel_function -> kinstr -> + kernel_function -> kinstr -> behavior_or_loop -> identified_term assigns -> identified_property option -(** Builds IPAssigns for a contract (if not WritesAny) - @since Carbon-20101201-beta2+dev -*) +(** Builds IPAssigns for a contract (if not WritesAny) + @since Carbon-20110201 *) val ip_assigns_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property option -(** Builds the corresponding IPFrom. - @since Carbon-20101201-beta2+dev -*) +(** Builds the corresponding IPFrom. + @since Carbon-20110201 *) val ip_of_from: - kernel_function -> kinstr -> - behavior_or_loop -> identified_term from -> identified_property option + kernel_function -> kinstr -> + behavior_or_loop -> identified_term from -> identified_property -(** Builds IPFrom for a contract (if not ReadsAny) - @since Carbon-20101201-beta2+dev -*) +(** Builds IPFrom for a contract (if not ReadsAny) + @since Carbon-20110201 *) val ip_from_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property list -(** Builds IPAssigns for a loop annotation (if not WritesAny) - @since Carbon-20101201-beta2+dev -*) +(** Builds IPAssigns for a loop annotation (if not WritesAny) + @since Carbon-20110201 *) val ip_assigns_of_code_annot: kernel_function -> kinstr -> code_annotation -> identified_property option -(** Builds IPFrom for a loop annotation(if not ReadsAny) - @since Carbon-20101201-beta2+dev -*) +(** Builds IPFrom for a loop annotation(if not ReadsAny) + @since Carbon-20110201 *) val ip_from_of_code_annot: kernel_function -> kinstr -> code_annotation -> identified_property list (** Builds all IP related to the post-conditions (including assigns and from) - @since Carbon-20101201-beta2+dev -*) + @since Carbon-20110201 *) val ip_post_cond_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property list -(** Builds all IP related to a behavior. - @since Carbon-20101201-beta2+dev -*) +(** Builds an IP for the post-conditions (including assigns and from) + of the behavior. + @since Carbon-20110201 *) +val ip_of_behavior: + kernel_function -> kinstr -> funbehavior -> identified_property + +(** Builds all IP related to a behavior. + @since Carbon-20110201 *) val ip_all_of_behavior: kernel_function -> kinstr -> funbehavior -> identified_property list -(** Builds IPComplete. - @since Carbon-20101201-beta2+dev -*) +(** Builds IPComplete. + @since Carbon-20110201 *) val ip_of_complete: kernel_function -> kinstr -> string list -> identified_property -(** Builds IPComplete of a given spec. - @since Carbon-20101201-beta2+dev -*) +(** Builds IPComplete of a given spec. + @since Carbon-20110201 *) val ip_complete_of_spec: kernel_function -> kinstr -> funspec -> identified_property list -(** Builds IPDisjoint. - @since Carbon-20101201-beta2+dev -*) +(** Builds IPDisjoint. + @since Carbon-20110201 *) val ip_of_disjoint: kernel_function -> kinstr -> string list -> identified_property -(** Builds IPDisjoint of a given spec. - @since Carbon-20101201-beta2+dev -*) +(** Builds IPDisjoint of a given spec. + @since Carbon-20110201 *) val ip_disjoint_of_spec: kernel_function -> kinstr -> funspec -> identified_property list val ip_of_terminates: - kernel_function -> kinstr -> + kernel_function -> kinstr -> Cil_types.identified_predicate -> identified_property -(** Builds IPTerminates of a given spec. - @since Carbon-20101201-beta2+dev -*) +(** Builds IPTerminates of a given spec. + @since Carbon-20110201 *) val ip_terminates_of_spec: kernel_function -> kinstr -> funspec -> identified_property option (** Builds IPDecrease - @since Carbon-20101201-beta2+dev -*) + @since Carbon-20110201 *) val ip_of_decreases: kernel_function -> kinstr -> term variant -> identified_property -(** Builds IPDecrease of a given spec. - @since Carbon-20101201-beta2+dev -*) +(** Builds IPDecrease of a given spec. + @since Carbon-20110201 *) val ip_decreases_of_spec: kernel_function -> kinstr -> funspec -> identified_property option - -(** Builds all IP of post-conditions related to a spec. - @since Carbon-20101201-beta2+dev -*) -val ip_post_cond_of_spec: +(** Builds all IP of post-conditions related to a spec. + @since Carbon-20110201 *) +val ip_post_cond_of_spec: kernel_function -> kinstr -> funspec -> identified_property list -(** Builds all IP related to a spec. - @since Carbon-20101201-beta2+dev -*) +(** Builds all IP related to a spec. + @since Carbon-20110201 *) val ip_of_spec: kernel_function -> kinstr -> funspec -> identified_property list -(** Builds an IPAxiom. - @since Carbon-20101201-beta2+dev -*) +(** Builds an IPAxiom. + @since Carbon-20110201 *) val ip_axiom: string -> identified_property -(** Builds an IPBlob. - @since Carbon-20101201-beta2+dev -*) -val ip_blob: State.t -> identified_property +val ip_lemma: string -> identified_property +(** Build an IPLemma. + @since Nitrogen-20111001 *) -(** Builds all IP related to a given code annotation. \ - @since Carbon-20101201-beta2+dev -*) +(** Builds all IP related to a given code annotation. + @since Carbon-20110201 *) val ip_of_code_annot: kernel_function -> stmt -> code_annotation -> identified_property list @@ -264,12 +264,20 @@ assert, invariant, variant, pragma. @raise Invalid_argument if the resulting code annotation has an empty set of identified property - @since Carbon-20101201-beta2+dev -*) + @since Carbon-20110201 *) val ip_of_code_annot_single: kernel_function -> stmt -> code_annotation -> identified_property +val ip_of_global_annotation: global_annotation -> identified_property list +(** @since Nitrogen-20111001 *) + +val ip_of_global_annotation_single: + global_annotation -> identified_property option +(** @since Nitrogen-20111001 *) + +(**************************************************************************) (** {2 getters} *) +(**************************************************************************) val get_kinstr: identified_property -> kinstr val get_kf: identified_property -> kernel_function option diff -Nru frama-c-20110201+carbon+dfsg/src/logic/property_status.ml frama-c-20111001+nitrogen+dfsg/src/logic/property_status.ml --- frama-c-20110201+carbon+dfsg/src/logic/property_status.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/property_status.ml 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,1415 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* INRIA (Institut National de Recherche en Informatique et en *) +(* Automatique) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version v2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(**************************************************************************) +(** {3 Datatypes} *) +(**************************************************************************) + +module Caml_hashtbl = Hashtbl +open Emitter + +module Emitted = struct + type t = True | False_if_reachable | False_and_reachable | Dont_know +end +type emitted_status = Emitted.t = + True | False_if_reachable | False_and_reachable | Dont_know + +module Emitted_status = + Datatype.Make_with_collections + (struct + type t = emitted_status + include Datatype.Serializable_undefined + let name = "Property_status.emitted_status" + let reprs = [ True; False_if_reachable; False_and_reachable; Dont_know ] + let mem_project = Datatype.never_any_project + let pretty fmt s = + Format.fprintf fmt "%s" + (match s with + | True -> "VALID" + | False_if_reachable | False_and_reachable -> "**NOT** VALID" + | Dont_know -> "unknown") + let compare (s1:t) s2 = Pervasives.compare s1 s2 + let equal (s1:t) s2 = s1 = s2 + let hash (s:t) = Caml_hashtbl.hash s + end) + +type emitter_with_properties = + { emitter: Usable_emitter.t; + properties: Property.t list; + logical_consequence: bool } + +module Emitter_with_properties = + Datatype.Make_with_collections + (struct + type t = emitter_with_properties + let name = "Property_status.emitter" + let rehash = Datatype.identity + let structural_descr = Structural_descr.Abstract + let reprs = + List.fold_left + (fun acc e -> + { emitter = e; + properties = Property.reprs; + logical_consequence = false } + :: acc) + [] + Usable_emitter.reprs + + let equal x y = Usable_emitter.equal x.emitter y.emitter + let compare x y = Usable_emitter.compare x.emitter y.emitter + let hash x = Caml_hashtbl.hash x.emitter + + let copy = Datatype.undefined + let pretty fmt e = Usable_emitter.pretty fmt e.emitter + let internal_pretty_code = Datatype.undefined + let varname _ = assert false (* unused while [internal_pretty_code] + unimplemented *) + let mem_project = Datatype.never_any_project + end) + +type inconsistent = + { valid: emitter_with_properties list; + invalid: emitter_with_properties list } + +module Local = struct + type t = + | Never_tried + | Best of emitted_status * emitter_with_properties list + | Inconsistent of inconsistent +end + +type status = Local.t = + | Never_tried + | Best of emitted_status * emitter_with_properties list + | Inconsistent of inconsistent + +module L = Datatype.Make + (struct + type t = status + include Datatype.Serializable_undefined + let name = "Property_status.t" + let reprs = + let l = Emitter_with_properties.reprs in + [ Never_tried; Best(True, []); Inconsistent { valid = l; invalid = l } ] + let mem_project = Datatype.never_any_project + let pretty fmt s = + let pp_emitters fmt l = + Pretty_utils.pp_list ~sep:", " ~last:" and " + Emitter_with_properties.pretty fmt l + in + match s with + | Never_tried -> Format.fprintf fmt "no verification attempted" + | Best(Dont_know as s, l) -> + Format.fprintf fmt "@[%a@ @[(%a tried%s to verify@ \ +but could not decide)@]@]" + Emitted_status.pretty s + pp_emitters l + (match l with [] | [ _ ] -> "" | _ :: _ -> " each") + | Best(True | False_if_reachable | False_and_reachable as s, l) -> + Format.fprintf fmt "%a according to %a%s" + Emitted_status.pretty s + pp_emitters l + (match l with + | [] -> assert false + | { properties = [] } :: _ -> "" + | { properties = _ :: _ } :: _ -> " (under hypotheses)") + | Inconsistent i -> + Format.fprintf fmt "@[inconsistent status:@ \ +@[%a according to %a@]@ \ +@[but %a according to %a@]" + Emitted_status.pretty True pp_emitters i.valid + Emitted_status.pretty False_if_reachable pp_emitters i.invalid + end) +include L + +(**************************************************************************) +(** {3 Projectified tables} *) +(**************************************************************************) + +let register_as_kernel_logical_consequence_ref = + Extlib.mk_fun "register_as_kernel_logical_consequence_ref" + +(* property -> emitter -> emitted_t + + Quick access to emitted_t required in order to emit quickly the new status + according to the old one. *) +module Status : sig + type tbl = Emitted_status.t Emitter_with_properties.Hashtbl.t + val self: State.t + val add: Property.t -> tbl -> unit + val find: Property.t -> tbl + val mem: Property.t -> bool + val remove: Property.t -> unit + val iter: (Property.t -> tbl -> unit) -> unit + val fold: (Property.t -> tbl -> 'a -> 'a) -> 'a -> 'a +end = struct + + let state_dependencies = + [ Ast.self; + Emitter.self + (* the other dependencies are postponed: + grep Property_status.self to find them *) ] + + (* this list is computed after defining [self] *) + let static_dependencies = ref [] + + let must_clear_all () = + let sel = Project.get_current_selection () in + try + List.iter + (fun s -> if State_selection.mem sel s then raise Exit) + !static_dependencies; + false + with Exit -> + true + + let create () = Property.Hashtbl.create 97 + + let state = ref (create ()) + + module Tbl = Emitter_with_properties.Hashtbl.Make(Emitted_status) + type tbl = Tbl.t + + module D = Property.Hashtbl.Make(Tbl) + + (* standard projectified hashtbl, but an ad-hoc function 'clear' *) + include State_builder.Register + (D) + (struct + type t = tbl Property.Hashtbl.t + let create = create + let clear tbl = + if must_clear_all () then + (* full clear *) + Property.Hashtbl.clear tbl + else + (* AST and annotations are unchanged: + keep properties as keys, but clear associated tables *) + Property.Hashtbl.iter + (fun p h -> + Emitter_with_properties.Hashtbl.clear h; + !register_as_kernel_logical_consequence_ref p) + tbl + let get () = !state + let set x = state := x + let clear_some_projects _f _h = false + end) + (struct + let dependencies = state_dependencies + let unique_name = "Property_status" + let name = "Property_status" + let kind = `Correctness + end) + + (* compute which states always impact this one (i.e. [self]) *) + let () = + let get_dependencies () = + State_dependency_graph.Static.G.fold_pred + (fun s acc -> s :: acc) + State_dependency_graph.Static.graph + self + [] + in + Cmdline.run_after_early_stage + (fun () -> static_dependencies := get_dependencies ()) + + let add key v = Property.Hashtbl.add !state key v + let find key = Property.Hashtbl.find !state key + let mem key = Property.Hashtbl.mem !state key + let remove key = Property.Hashtbl.remove !state key + let iter f = Property.Hashtbl.iter f !state + let fold f acc = Property.Hashtbl.fold f !state acc + +end + +let self = Status.self +let () = Emitter.property_status_state := self + +let iter f = Status.iter (fun p _ -> f p) +let fold f = Status.fold (fun p _ -> f p) + +let auto_emitter = Emitter.create "Frama-C kernel" ~correctness:[] ~tuning:[] + +(* ok to be computed once right now since there is no parameter dependency *) +let usable_auto_emitter = Emitter.get auto_emitter + +let auto_emitter_with_ppts = + { emitter = usable_auto_emitter; + (* other fields not used as index *) + properties = []; + logical_consequence = false } + +let clear_consolidation = Extlib.mk_fun "clear_consolidation" + +(**************************************************************************) +(** {3 Unconsolidated property status} *) +(**************************************************************************) + +exception Inconsistent_emitted_status of emitted_status * emitted_status + +(* @return [true] if the strongest is the first parameter. [false] otherwise. + In case of equality, return [false]. + @raise Inconsistent_emitted_status if the check fails *) +let check_strongest_emitted x y = match x, y with + | True, (False_if_reachable | False_and_reachable) + | (False_if_reachable | False_and_reachable), True -> + raise (Inconsistent_emitted_status (x, y)) + | Dont_know, (True | False_if_reachable | False_and_reachable | Dont_know) + | True, True + | False_if_reachable, (False_and_reachable | False_if_reachable) + | False_and_reachable, False_and_reachable + -> false + | (True | False_if_reachable | False_and_reachable), Dont_know + | False_and_reachable, False_if_reachable + -> true + +(* [strenghten emitter emitted_status status] gets [status] and updates it + according to [emitted_status] (which was emitted by [emitter]): that returns + the strongest status between them, or an inconsistency if any. *) +let strenghten emitter emitted_status status = + match status, emitted_status with + | Never_tried, (True | False_if_reachable | False_and_reachable | Dont_know) + -> + (* was not tried, but now we have tried :) *) + Best(emitted_status, [ emitter ]) + | Best(s, l), s2 when s = s2 -> + (* status are equal: update the emitters *) + Best(s, emitter :: l) + | Best(s, l), s2 (* when s <> emitted_status *) -> + (try + let first = check_strongest_emitted s s2 in + if first then + (* the old one is the strongest, keep it *) + status + else + (* the new one is the strongest, replace the old one *) + Best(emitted_status, [ emitter ]) + with Inconsistent_emitted_status _ -> + (* inconsistency detected *) + (match s with + | True -> + assert (emitted_status = False_if_reachable + || emitted_status = False_and_reachable); + (* the old one is valid, but the new one is invalid *) + Inconsistent { valid = l; invalid = [ emitter ] } + | False_if_reachable | False_and_reachable -> + assert (emitted_status = True); + (* the old one is invalid, but the new one is valid *) + Inconsistent { valid = [ emitter ]; invalid = l } + | Dont_know -> assert false)) + | Inconsistent i, True -> + (* was already inconsistent and the new one is valid: update the valid + field *) + Inconsistent { i with valid = emitter :: i.valid } + | Inconsistent i, (False_if_reachable | False_and_reachable) -> + (* was already inconsistent and the new one is invalid: update the invalid + field *) + Inconsistent { i with invalid = emitter :: i.invalid } + | Inconsistent _, Dont_know -> + (* was already inconsistent, but the new one gets no new info: ignore it *) + status + +(* @return [true] if one must keep the status of the first parameter. + [false] otherwise. In case of equality, return [false]. *) +let merge_distinct_emitted x y = match x, y with + | False_and_reachable, False_if_reachable + | (False_if_reachable | False_and_reachable), (True | Dont_know) + | Dont_know, True -> true + | (True | False_if_reachable | Dont_know), + (False_if_reachable | False_and_reachable) + | False_and_reachable, False_and_reachable + | (True | Dont_know), Dont_know + | True, True -> false + +let rec register ppt = + (*Kernel.feedback "REGISTERING %a in %a" Property.pretty ppt + Project.pretty (Project.current ());*) + if Status.mem ppt then + Kernel.fatal "trying to register twice property `%a'.\n\ +That is forbidden (kernel invariant broken)." + Property.pretty ppt; + let h = Emitter_with_properties.Hashtbl.create 7 in + Status.add ppt h; + register_as_kernel_logical_consequence ppt + +(* the functions below and this one MUST be synchronized *) +and register_as_kernel_logical_consequence ppt = match ppt with + | Property.IPAxiom _ + | Property.IPPredicate(Property.PKAssumes _, _, _, _) -> + (* always valid: logical consequence of the empty conjunction *) + logical_consequence auto_emitter ppt [] + | Property.IPAxiomatic(_, l) -> logical_consequence auto_emitter ppt l + | Property.IPBehavior(kf, ki, b) -> + (* logical consequence of its postconditions *) + logical_consequence + auto_emitter ppt (Property.ip_post_cond_of_behavior kf ki b) + | Property.IPUnreachable(Property.UProperty p) -> + (match Property.get_kf p with + | None -> + (* invalid: global properties are always reachable *) + emit_invalid ppt + | Some kf -> + (* cannot use module [Kernel_function] nor [Globals] here *) + let f = kf.Cil_types.fundec in + if Ast_info.Function.is_definition f then + if Ast_info.Function.get_name f = Kernel.MainFunction.get () then + (* preconditions and assumes of the main are always reachable *) + (match p with + | Property.IPPredicate + ((Property.PKRequires _ | Property.PKAssumes _), _, _, _) -> + emit_invalid ppt + | _ -> ())) + | Property.IPOther _ | Property.IPUnreachable(Property.UStmt _) + | Property.IPPredicate _ | Property.IPCodeAnnot _ | Property.IPComplete _ + | Property.IPDisjoint _ | Property.IPAssigns _ | Property.IPFrom _ + | Property.IPDecrease _ | Property.IPLemma _ -> + () + +(* the functions above and below MUST be synchronized *) +and is_kernel_logical_consequence ppt = match ppt with + | Property.IPAxiom _ + | Property.IPAxiomatic _ + | Property.IPPredicate(Property.PKAssumes _, _, _, _) + | Property.IPBehavior(_, _, _) -> + true + | Property.IPUnreachable(Property.UProperty p) -> + (match Property.get_kf p with + | None -> true + | Some kf -> + (* cannot use module [Kernel_function] nor [Globals] here *) + let f = kf.Cil_types.fundec in + if Ast_info.Function.is_definition f then + if Ast_info.Function.get_name f = Kernel.MainFunction.get () then + (* preconditions and assumes of the main are always reachable *) + match p with + | Property.IPPredicate + ((Property.PKRequires _ | Property.PKAssumes _), _, _, _) -> + true + | _ -> false + else + false + else + false) + | Property.IPOther _ | Property.IPUnreachable(Property.UStmt _) + | Property.IPPredicate _ | Property.IPCodeAnnot _ | Property.IPComplete _ + | Property.IPDisjoint _ | Property.IPAssigns _ | Property.IPFrom _ + | Property.IPDecrease _ | Property.IPLemma _ -> + false + +and unsafe_emit_and_get e ~hyps ~auto ppt ?(distinct=false) s = + try + let by_emitter = Status.find ppt in + let emitter = + { emitter = Emitter.get e; + properties = hyps; + logical_consequence = auto } + in + let emit s = + (* do not use Hashtbl.replace, see OCaml BTS #5349 *) + Emitter_with_properties.Hashtbl.remove by_emitter emitter; + !clear_consolidation (); + (match s with + | True | Dont_know | False_and_reachable -> + Emitter_with_properties.Hashtbl.add by_emitter emitter s; + | False_if_reachable -> + let unreach_ppt = Property.ip_unreachable_ppt ppt in + if is_kernel_logical_consequence unreach_ppt then + emit_invalid unreach_ppt; + Emitter_with_properties.Hashtbl.add + by_emitter + { emitter with properties = unreach_ppt :: hyps } + s); + s + in + (try + if auto then + (* registering again a logical consequence because dependencies change, + thus erase the previous (now erroneous) calculus *) + emit s + else + let old_s = Emitter_with_properties.Hashtbl.find by_emitter emitter in + let first = + (if distinct then merge_distinct_emitted + else check_strongest_emitted) + s + old_s + in + if first then emit s else old_s + with Not_found -> + emit s) + with Not_found -> + (* assume that all ACSL properties are registered, except non-ACSL and + conjunctions ones (but conjunctions are automatically computed and so + already registered) *) + match ppt with + | Property.IPOther _ | Property.IPUnreachable _ -> + register ppt; + unsafe_emit_and_get e ~hyps ~auto ppt ~distinct s + | Property.IPPredicate _ | Property.IPCodeAnnot _ | Property.IPComplete _ + | Property.IPDisjoint _ | Property.IPAssigns _ | Property.IPFrom _ + | Property.IPDecrease _ | Property.IPBehavior _ + | Property.IPAxiom _ | Property.IPAxiomatic _ | Property.IPLemma _ -> + Kernel.fatal "unregistered property %a" Property.pretty ppt + +and logical_consequence e ppt hyps = + ignore (unsafe_emit_and_get e ~hyps ~auto:true ppt Dont_know) + +and emit_invalid ppt = + ignore + (unsafe_emit_and_get auto_emitter ~hyps:[] ~auto:true ppt + False_and_reachable) + +let () = + register_as_kernel_logical_consequence_ref := + register_as_kernel_logical_consequence + +let emit_and_get e ~hyps ppt ?distinct s = + (match ppt with + | Property.IPBehavior _ | Property.IPAxiom _ | Property.IPAxiomatic _ + | Property.IPPredicate (Property.PKAssumes _, _, _, _) -> + Kernel.fatal + "only the kernel should set the status of property %a" + Property.pretty + ppt + | Property.IPPredicate _ | Property.IPCodeAnnot _ | Property.IPComplete _ + | Property.IPDisjoint _ | Property.IPAssigns _ | Property.IPFrom _ + | Property.IPDecrease _ | Property.IPLemma _ | Property.IPUnreachable _ + | Property.IPOther _ -> ()); + unsafe_emit_and_get e ~hyps ~auto:false ppt ?distinct s + +let emit e ~hyps ppt ?distinct s = ignore (emit_and_get e ~hyps ppt ?distinct s) + +let remove ppt = +(* Kernel.feedback "REMOVING %a in %a" Property.pretty ppt + Project.pretty (Project.current ());*) + Status.remove ppt + +let merge ~old l = + let property_id fmt p = + Format.fprintf fmt "%a(%d)" Property.pretty p (Property.hash p) + in + (*Kernel.feedback "MERGING ###%a###@\nWITH ###%a###" + (Pretty_utils.pp_list ~sep:"\n###" property_id) old + (Pretty_utils.pp_list ~sep:"\n###" property_id) l; *) + let old_h = Property.Hashtbl.create 17 in + List.iter + (fun p -> + assert (Kernel.verify (Status.mem p) "Unknown property %a" property_id p); + Property.Hashtbl.add old_h p ()) + old; + List.iter + (fun p -> + if Property.Hashtbl.mem old_h p then begin + (* [p] belongs to both lists *) + (*Kernel.feedback "UNCHANGED %a" Property.pretty p;*) + Property.Hashtbl.remove old_h p; + (* if [p] was a logical consequence, its dependencies may change *) + register_as_kernel_logical_consequence p + end else begin + (* [p] belongs only to the new list *) + (*Kernel.feedback "ADD %a" Property.pretty p;*) + register p + end) + l; + (* remove the properties which are not in the new list *) + Property.Hashtbl.iter + (fun p () -> + (* Kernel.feedback "REMOVE %a" Property.pretty p; *) + remove p) + old_h + +let conjunction s1 s2 = match s1, s2 with + (* order does matter *) + | False_and_reachable, _ | _, False_and_reachable -> False_and_reachable + | False_if_reachable, _ | _, False_if_reachable -> False_if_reachable + | Dont_know, _ | _, Dont_know -> Dont_know + | True, True -> True + +let is_not_verifiable_but_valid ppt status = match status with + | Never_tried | Best(Dont_know, _) -> + (match ppt with + | Property.IPOther _ -> + (* Non-ACSL properties are not verifiable *) + false + | Property.IPUnreachable _ -> false + | _ -> + match Property.get_kf ppt with + | None -> false + | Some kf -> + (* cannot use module [Kernel_function] nor [Globals] here *) + let f = kf.Cil_types.fundec in + if Ast_info.Function.is_definition f then + false + else + (* postconditions of functions without code are not verifiable *) + match ppt with + | Property.IPPredicate + ((Property.PKEnsures _ | Property.PKTerminates), _, _, _) + | Property.IPAssigns _ + | Property.IPFrom _ -> true + | _ -> false) + | Best((True | False_if_reachable | False_and_reachable), _) + | Inconsistent _ -> + false + +let rec compute_automatic_status e properties = + let local_get p = + (* get the status of this emitter [e], not the best status, + except if the emitter is the kernel itself *) + if Emitter.Usable_emitter.compare_with_emitter e.emitter auto_emitter = 0 + then match get p with + | Never_tried | Inconsistent _ -> Dont_know + | Best(s, _) -> s + else + try + let by_emitter = Status.find p in + try Emitter_with_properties.Hashtbl.find by_emitter e + with Not_found -> + (* try to know if the kernel automatically computes a status *) + try + Emitter_with_properties.Hashtbl.find + by_emitter + auto_emitter_with_ppts + with Not_found -> + Dont_know + with Not_found -> + (* assume that all ACSL properties are registered, + except non-ACSL ones *) + match p with + | Property.IPOther _ | Property.IPUnreachable _ -> + register p; + Dont_know + | Property.IPBehavior _ + | Property.IPPredicate _ | Property.IPCodeAnnot _ + | Property.IPComplete _ | Property.IPDisjoint _ + | Property.IPAssigns _ | Property.IPFrom _ | Property.IPDecrease _ + | Property.IPAxiom _ | Property.IPAxiomatic _ | Property.IPLemma _ -> + Kernel.fatal "unregistered property %a" Property.pretty p + in + let local_get p = + let s = local_get p in + if is_not_verifiable_but_valid p (Best(s, [])) then + True + else + s + in + List.fold_left (fun s p -> conjunction s (local_get p)) True properties + +and get ppt = + try + let by_emitter = Status.find ppt in + Emitter_with_properties.Hashtbl.fold + (fun e s acc -> + let s, tried = + if e.logical_consequence && Emitted_status.equal s Dont_know then + let ppts = e.properties in + let new_s = compute_automatic_status e ppts in + match new_s with + | True | False_if_reachable | False_and_reachable -> + (* the status is now known: register it *) + Emitter_with_properties.Hashtbl.replace by_emitter e new_s; + new_s, true + | Dont_know -> + (* no change *) + new_s, + (* there is a status for this logical consequence iff + there is a status for one of its hypotheses *) + List.exists (fun p -> get p <> Never_tried) ppts + else + s, true + in + if tried then strenghten e s acc else acc) + by_emitter + Never_tried + with Not_found -> + (* assume that all ACSL properties are registered, except non-ACSL ones *) + match ppt with + | Property.IPOther _ | Property.IPUnreachable _ -> + register ppt; + if is_kernel_logical_consequence ppt then get ppt else Never_tried + | Property.IPBehavior _ + | Property.IPPredicate _ | Property.IPCodeAnnot _ | Property.IPComplete _ + | Property.IPDisjoint _ | Property.IPAssigns _ | Property.IPFrom _ + | Property.IPDecrease _ + | Property.IPAxiom _ | Property.IPAxiomatic _ | Property.IPLemma _ -> + Kernel.fatal "trying to get status of unregistered property `%a'.\n\ +That is forbidden (kernel invariant broken)." + Property.pretty ppt + +(* local alias: too much local definitions of get implies name clashes *) +let get_status = get + +let automatically_proven ppt = + is_kernel_logical_consequence ppt + && + (* nobody else tried to prove it *) + try + let by_emitter = Status.find ppt in + try + Emitter_with_properties.Hashtbl.iter + (fun e _ -> + if Emitter.Usable_emitter.compare_with_emitter + e.emitter auto_emitter <> 0 + then raise Exit) + by_emitter; + true + with Exit -> + false + with Not_found -> + true + +(**************************************************************************) +(** {3 Consolidated property status} *) +(**************************************************************************) + +module Consolidation = struct + + type pending = + Property.Set.t Usable_emitter.Map.t Usable_emitter.Map.t + + type consolidated_status = + | Never_tried + | Considered_valid + | Valid of Usable_emitter.Set.t + | Valid_under_hyp of pending + | Unknown of pending + | Invalid of Emitter.Usable_emitter.Set.t + | Invalid_under_hyp of pending + | Invalid_but_dead of pending + | Valid_but_dead of pending + | Unknown_but_dead of pending + | Inconsistent of string + + module D = Datatype.Make + (struct + type t = consolidated_status + include Datatype.Serializable_undefined + let name = "Property_status.consolidated_status" + let reprs = + [ Never_tried; + Considered_valid; + Valid Usable_emitter.Set.empty; + Valid_under_hyp Usable_emitter.Map.empty; + Unknown Usable_emitter.Map.empty; + Invalid Usable_emitter.Set.empty; + Invalid_under_hyp Usable_emitter.Map.empty; + Invalid_but_dead Usable_emitter.Map.empty; + Valid_but_dead Usable_emitter.Map.empty; + Unknown_but_dead Usable_emitter.Map.empty; + Inconsistent "" ] + + let mem_project = Datatype.never_any_project + let pretty fmt s = + let pp_emitters f fmt l = + Pretty_utils.pp_list ~sep:", " ~last:" and " f fmt l + in + match s with + | Never_tried -> Format.fprintf fmt "no verification attempted" + | Considered_valid -> + Format.fprintf fmt + "no verification attempted, but considered %a by external review" + Emitted_status.pretty Emitted.True + | Valid set | Invalid set -> + Format.fprintf fmt "%a according to %a" + Emitted_status.pretty + (match s with + | Valid _ -> Emitted.True + | Invalid _ -> Emitted.False_and_reachable + | _ -> assert false) + (pp_emitters Usable_emitter.pretty) + (Usable_emitter.Set.elements set) + | Valid_under_hyp map | Invalid_under_hyp map -> + let l = Usable_emitter.Map.fold (fun e _ acc -> e :: acc) map [] in + Format.fprintf fmt "@[%a@ @[(%a according to %a, but properties \ +remain to be verified)@]@]" + Emitted_status.pretty Emitted.Dont_know + Emitted_status.pretty + (match s with + | Valid_under_hyp _ -> Emitted.True + | Invalid_under_hyp _ -> Emitted.False_and_reachable + | _ -> assert false) + (pp_emitters Usable_emitter.pretty) l + | Unknown map -> + let l = Usable_emitter.Map.fold (fun e _ acc -> e :: acc) map [] in + Format.fprintf fmt "@[%a@ @[(%a tried%s to verify@ \ +but could not decide)@]@]" + Emitted_status.pretty Emitted.Dont_know + (pp_emitters Usable_emitter.pretty) l + (match l with [] | [ _ ] -> "" | _ :: _ -> " each") + | Valid_but_dead map + | Invalid_but_dead map + | Unknown_but_dead map -> + let l = Usable_emitter.Map.fold (fun e _ acc -> e :: acc) map [] in + Format.fprintf fmt "%a according to %a, but it is dead anyway" + Emitted_status.pretty + (match s with + | Valid_but_dead _ -> Emitted.True + | Invalid_but_dead _ -> Emitted.False_and_reachable + | Unknown_but_dead _ -> Emitted.Dont_know + | _ -> assert false) + (pp_emitters Usable_emitter.pretty) l + | Inconsistent msg -> + Format.fprintf fmt "inconsistency detected:\n%s.\n\ +Check your axiomatics and implicit hypotheses." + msg + end) + include D + + module Consolidated_status = + State_builder.Hashtbl + (Property.Hashtbl) + (D) + (struct + let name = "Consolidated_status" + let dependencies = [ Status.self ] + let size = 97 + let kind = `Correctness + end) + + let auto_status_emitter l = + Usable_emitter.Map.add usable_auto_emitter l Usable_emitter.Map.empty + + let merge_property e ppt map = + try + let set = Usable_emitter.Map.find e map in + Usable_emitter.Map.add e (Property.Set.add ppt set) map + with Not_found -> + Usable_emitter.Map.add e (Property.Set.singleton ppt) map + + let merge_properties e set map = + try + let set2 = Usable_emitter.Map.find e map in + Usable_emitter.Map.add e (Property.Set.union set set2) map + with Not_found -> + assert (not (Property.Set.is_empty set)); + Usable_emitter.Map.add e set map + + let flatten_map init map = + Usable_emitter.Map.fold + (fun _ -> Usable_emitter.Map.fold merge_properties) + map + init + + let flatten_set init h set = + Usable_emitter.Set.fold (fun e map -> merge_property e h map) set init + + let reduce_hypothesis_status ppt = function + | Never_tried | Inconsistent _ -> + let singleton_map v = + Usable_emitter.Map.add + usable_auto_emitter + v + Usable_emitter.Map.empty + in + Unknown (singleton_map (singleton_map (Property.Set.singleton ppt))) + | Invalid_under_hyp m -> Unknown m + | Considered_valid + | Valid _ -> Valid Emitter.Usable_emitter.Set.empty + | Invalid_but_dead m + | Valid_but_dead m + | Unknown_but_dead m -> + (* Must keep where are invalidities, thus keep the map. + But anyway, each of these three "dead" status are consolidated in the + same way *) + Valid_but_dead m + | Valid_under_hyp m + | Unknown m -> Unknown m + | Invalid _ as s -> s + + (* s1 = consolidated status of previous hypotheses; + s2 = consolidated status of hypothesis h; + e is the emitter of s2 for property h + issues are the issues already computed + compute: + - consolidated status of (h1 /\ h2) + - where are the issues and who finds them *) + let hypotheses_conjunction issues h s1 s2 = match s1, s2 with + (* order of patterns does matter *) + | _, Never_tried + | Considered_valid, _ | _, Considered_valid + | Valid_under_hyp _, _ | _, Valid_under_hyp _ + | Inconsistent _, _ | _, Inconsistent _ + | Invalid_under_hyp _, _ | _, Invalid_under_hyp _ + | Invalid_but_dead _, _ | _, Invalid_but_dead _ + | Unknown_but_dead _, _ | _, Unknown_but_dead _ -> + (* handle at callsite *) + assert false + | Never_tried, Unknown m -> + (* first status encountered: keep the issues of the first hypothesis *) + assert (Usable_emitter.Map.is_empty issues); + Unknown Usable_emitter.Map.empty, flatten_map issues m + | Never_tried, (Valid _ | Valid_but_dead _) -> + (* first status encountered: no issue with the first hypothesis *) + assert (Usable_emitter.Map.is_empty issues); + Valid Usable_emitter.Set.empty, issues + | Invalid set1, Invalid set2 -> + assert (Usable_emitter.Set.is_empty set1); + Invalid Usable_emitter.Set.empty, flatten_set issues h set2 + | _, Invalid set -> + Invalid Usable_emitter.Set.empty, + flatten_set Usable_emitter.Map.empty h set + | Invalid set, _ -> + assert (Usable_emitter.Set.is_empty set); + Invalid Usable_emitter.Set.empty, issues + | Unknown m1, Unknown m2 -> + assert (Usable_emitter.Map.is_empty m1); + Unknown Usable_emitter.Map.empty, flatten_map issues m2 + | Unknown m, (Valid _ | Valid_but_dead _) + | (Valid _ | Valid_but_dead _), Unknown m -> + Unknown Usable_emitter.Map.empty, + flatten_map issues m + | (Valid _ | Valid_but_dead _), (Valid _ | Valid_but_dead _) -> + assert (Usable_emitter.Map.is_empty issues); + Valid Usable_emitter.Set.empty, issues + + let singleton_map e m = Usable_emitter.Map.add e m Usable_emitter.Map.empty + + (* compute the best status [s] and add the emitter [e] if it computes [s] *) + let choose_best_emitter old_status e (status, issues) = + match old_status, status with + | _, Never_tried + | Considered_valid, _ | _, Considered_valid + | Valid_under_hyp _, _ | _, Valid_under_hyp _ + | Invalid_under_hyp _, _ | _, Invalid_under_hyp _ + | Valid_but_dead _, _ | _, Valid_but_dead _ + | Unknown_but_dead _, _ | _, Unknown_but_dead _ + | Inconsistent _, _ | _, Inconsistent _ + | Invalid _, _ (* the current best status cannot be invalid, but + invalid_but_dead instead *) + | _, Invalid_but_dead _ (* the last computed status cannot be + invalid_but_dead, but invalid instead *) + -> + Kernel.fatal "@[[Property_status] invariant of consolidation broken:@ \ +either status %a or %a not allowed when choosing the best emitter@]" + pretty old_status + pretty status + + (* first status encountered: keep it *) + | Never_tried, Valid _ -> Valid (Usable_emitter.Set.singleton e) + | Never_tried, Invalid _ -> Invalid_but_dead (singleton_map e issues) + | Never_tried, Unknown _ -> Unknown (singleton_map e issues) + + (* the old computed status remains the best one *) + | (Valid _ | Invalid_but_dead _), Unknown _ -> + old_status + + (* [e] is the best *) + | Unknown _, Valid _ -> Valid (Usable_emitter.Set.singleton e) + | Unknown _, Invalid _ -> Invalid_but_dead (singleton_map e issues) + + (* [e] is as good as the previous best emitter *) + | Valid set, Valid _ -> Valid (Usable_emitter.Set.add e set) + | Invalid_but_dead m, Invalid _ -> + Invalid_but_dead (Usable_emitter.Map.add e issues m) + | Unknown m, Unknown _ -> Unknown (Usable_emitter.Map.add e issues m) + + (* Inconsistency! *) + | Invalid_but_dead m, Valid _ -> + assert (Usable_emitter.Map.is_empty issues); + Inconsistent + (let l = Usable_emitter.Map.fold (fun e _ acc -> e :: acc) m [] in + Pretty_utils.sfprintf + "@[Valid for: %a (at least).@\n\ +Invalid for: %a.@]" + Usable_emitter.pretty e + (Pretty_utils.pp_list ~sep:", " ~last:" and " Usable_emitter.pretty) + l) + | Valid set, Invalid _ -> + Inconsistent + (let l = Usable_emitter.Set.elements set in + Pretty_utils.sfprintf + "@[Valid for: %a.@\n\ +Invalid for: %a (at least).@]" + (Pretty_utils.pp_list ~sep:", " ~last:" and " Usable_emitter.pretty) + l + Usable_emitter.pretty + e) + + let mk_issue e ppt = + Usable_emitter.Map.add + e + (Property.Set.singleton ppt) + Usable_emitter.Map.empty + + let issues_without_emitter issues = + Usable_emitter.Map.fold + (fun _ -> Usable_emitter.Map.fold Usable_emitter.Map.add) + issues + Usable_emitter.Map.empty + + let hyp_issues emitters issues = + let m = issues_without_emitter issues in + List.fold_left + (fun acc ep -> Usable_emitter.Map.add ep.emitter m acc) + Usable_emitter.Map.empty + emitters + + let local_hyp_issues emitters ppt issues = + let m = issues_without_emitter issues in + List.fold_left + (fun acc ep -> + let e = ep.emitter in + Usable_emitter.Map.add e (merge_property e ppt m) acc) + Usable_emitter.Map.empty + emitters + + let merge_hypotheses_and_local_status ppt hyps_status local_status = + match hyps_status, local_status with + + (* impossible cases: handle at callsite *) + | Never_tried, _ + | Considered_valid, _ + | Valid_under_hyp _, _ + | Invalid_under_hyp _, _ + | Valid_but_dead _, _ + | Unknown_but_dead _, _ + | Invalid _, _ + | _, Local.Never_tried -> + Kernel.fatal "@[[Property_status] invariant of consolidation broken:@ \ +either status %a or %a not allowed when merging status@]" + pretty hyps_status + L.pretty local_status + + (* status of hypotheses = valid; + filter emitters by the one for which hypotheses are valid *) + | Valid set, Best(Emitted.Dont_know, _) -> + let mk e = mk_issue e ppt in + let map = + Usable_emitter.Set.fold + (fun e -> Usable_emitter.Map.add e (mk e)) + set + Usable_emitter.Map.empty + in + Unknown map + | Valid _, Best(Emitted.True, _) -> + hyps_status + | Valid set, + Best((Emitted.False_and_reachable | Emitted.False_if_reachable), _) -> + Invalid set + | Valid set, (Local.Inconsistent i as s) -> + let mk = + let internal_map = + Usable_emitter.Map.add + usable_auto_emitter + (Property.Set.singleton ppt) + Usable_emitter.Map.empty + in + List.fold_left + (fun acc ep -> + let e = ep.emitter in + if Usable_emitter.Set.mem e set then + Usable_emitter.Map.add e internal_map acc + else + acc) + Usable_emitter.Map.empty + in + let valid_map = mk i.valid in + let invalid_map = mk i.invalid in + (* something strange locally appears: the only way that there is no + global inconsistency if that this program point is actually dead *) + if Usable_emitter.Map.is_empty valid_map then begin + assert (not (Usable_emitter.Map.is_empty invalid_map)); + Invalid_but_dead invalid_map + end else + if Usable_emitter.Map.is_empty invalid_map then Valid_but_dead valid_map + else Inconsistent (Pretty_utils.sfprintf "%a" L.pretty s) + + (* status of hypotheses = invalid (encoded by invalid_but_dead) *) + | Invalid_but_dead m, + Best((Emitted.False_and_reachable | Emitted.False_if_reachable), _) -> + Invalid_but_dead m + | Invalid_but_dead m, Best(Emitted.True, _) -> + Valid_but_dead m + | Invalid_but_dead m, (Best(Emitted.Dont_know, _) | Local.Inconsistent _) -> + Unknown_but_dead m + + (* status of hypotheses = dont_know *) + | Unknown m, Best(Emitted.True, _) -> + Valid_under_hyp m + | Unknown m, Best((Emitted.False_if_reachable + | Emitted.False_and_reachable), _) -> + Invalid_under_hyp m + | Unknown m, Best(Emitted.Dont_know, emitters) -> + Unknown (local_hyp_issues emitters ppt m) + | Unknown m, Local.Inconsistent _ -> + Unknown m + + (* status of hypotheses = inconsistent *) + | Inconsistent _, _ -> hyps_status + + let visited_ppt = Property.Hashtbl.create 97 + + let rec memo_consolidated ppt = + Consolidated_status.memo + (fun ppt -> + if Property.Hashtbl.mem visited_ppt ppt then begin + (* Inconsistent "mutual dependency with one of its hypothesis"*) + (* [JS 2011/09/14] the above line [Inconsistent ...] is the correct + one, but... temporary allow crazy plug-ins to declare cycles + without any verification *) + Considered_valid + end else begin + Property.Hashtbl.add visited_ppt ppt (); + let status = get ppt in + let consolidated_status = + if is_not_verifiable_but_valid ppt status then + Considered_valid + else + match status with + | Local.Never_tried -> Never_tried + | Best(_, l) as local -> + let status = consolidated_emitters l in + (* Kernel.feedback "status of hypotheses of %a: %a" + Property.pretty ppt + pretty hyps_status;*) + let s = merge_hypotheses_and_local_status ppt status local in + (* Kernel.feedback "consolidated status of %a: %a" + Property.pretty ppt + pretty s;*) + s + | Local.Inconsistent { valid = valid; invalid = invalid } + as local -> + let hyps_status = consolidated_emitters (valid @ invalid) in + merge_hypotheses_and_local_status ppt hyps_status local + in + (* [JS 2011/09/14] uncomment the following lines when + re-implementing the fully correct solution with inconsistency *) +(* try + (* was previously added during its own calculus + in case of mutual dependency *) + Consolidated_status.find ppt + with Not_found ->*) + consolidated_status + end) + ppt + + and consolidated_emitters l = + (* [l] is the list of the best emitters of the local status of [ppt]. + As they emit the same local status, we only choose the best one according + to the status of their hypotheses. *) + let status = + List.fold_left + (fun current_status e -> + let (s, issues) = + (* compute the status of conjunction of hypotheses of [e], + with related issues *) + List.fold_left + (fun (status, issues) h -> + let s = memo_consolidated h in + let s = reduce_hypothesis_status h s in + (* Kernel.feedback "status of hypothesis %a (for %a): %a" + Property.pretty h + Property.pretty ppt + pretty s;*) + hypotheses_conjunction issues h status s) + (Never_tried, Usable_emitter.Map.empty) + e.properties + in + let hyps_status = match s with + | Never_tried -> + (* if no hypothesis, status of hypotheses must be valid *) + Valid (Usable_emitter.Set.singleton usable_auto_emitter) + | Valid _ | Invalid _ | Unknown _ -> s + | Considered_valid | Inconsistent _ + | Valid_under_hyp _ | Invalid_under_hyp _ + | Valid_but_dead _ | Invalid_but_dead _ | Unknown_but_dead _ -> + Kernel.fatal "@[[Property_status] invariant of consolidation \ +broken:@ status %a not allowed when simplifying hypothesis status@]" + pretty s + + in + let cur = + choose_best_emitter current_status e.emitter (hyps_status, issues) + in + (* Kernel.feedback + "status of hypotheses for emitter `%a': %a" + Usable_emitter.pretty e.emitter pretty s; + Kernel.feedback "current best status: %a" pretty cur;*) + cur) + Never_tried + l + in + match status with + | Never_tried -> + (* if no hypothesis, status of hypotheses must be valid *) + Valid (Usable_emitter.Set.singleton usable_auto_emitter) + | _ -> status + + let get ppt = + let s = memo_consolidated ppt in + Property.Hashtbl.clear visited_ppt; + s + + let get_conjunction ppts = + let tmp = Property.ip_other "$Feedback.tmp$" None Cil_types.Kglobal in + logical_consequence auto_emitter tmp ppts ; + let s = get tmp in + Status.remove tmp ; + Consolidated_status.remove tmp ; + s + +end + +module Feedback = struct + + type t = + | Never_tried + | Considered_valid + | Valid + | Valid_under_hyp + | Unknown + | Invalid + | Invalid_under_hyp + | Invalid_but_dead + | Valid_but_dead + | Unknown_but_dead + | Inconsistent + + let from_consolidation = function + | Consolidation.Never_tried -> Never_tried + | Consolidation.Considered_valid -> Considered_valid + | Consolidation.Valid _ -> Valid + | Consolidation.Valid_under_hyp _ -> Valid_under_hyp + | Consolidation.Unknown _ -> Unknown + | Consolidation.Invalid _ -> Invalid + | Consolidation.Invalid_under_hyp _ -> Invalid_under_hyp + | Consolidation.Invalid_but_dead _ -> Invalid_but_dead + | Consolidation.Valid_but_dead _ -> Valid_but_dead + | Consolidation.Unknown_but_dead _ -> Unknown_but_dead + | Consolidation.Inconsistent _ -> Inconsistent + + let get p = from_consolidation (Consolidation.get p) + let get_conjunction l = from_consolidation (Consolidation.get_conjunction l) + +end + +(**************************************************************************) +(** {3 Consolidation graph} *) +(**************************************************************************) + +module Consolidation_graph = struct + + type v = + | Property of Property.t + | Emitter of string + | Tuning_parameter of string + | Correctness_parameter of string + + module Vertex = struct + + type t = v + + let compare v1 v2 = match v1, v2 with + | Property p1, Property p2 -> Property.compare p1 p2 + | Emitter s1, Emitter s2 -> String.compare s1 s2 + | Tuning_parameter s1, Tuning_parameter s2 + | Correctness_parameter s1, Correctness_parameter s2 -> + String.compare s1 s2 + | Property _, _ + | Emitter _, (Tuning_parameter _ | Correctness_parameter _) + | Tuning_parameter _, Correctness_parameter _ -> 1 + | _, _ -> -1 + + let equal v1 v2 = compare v1 v2 = 0 + + let hash = function + | Property p -> Caml_hashtbl.hash (0, Property.hash p) + | Emitter s -> Caml_hashtbl.hash (1, s) + | Tuning_parameter s -> Caml_hashtbl.hash (2, s) + | Correctness_parameter s -> Caml_hashtbl.hash (3, s) + + end + + module Edge = struct + + include Datatype.Option_with_collections + (Emitted_status) + (struct let module_name = "Property_status.Consolidation_graph.Edge" end) + + let default = None + + end + + module G = Graph.Persistent.Digraph.ConcreteLabeled(Vertex)(Edge) + module G_oper = Graph.Oper.P(G) + + module Graph_by_property = + State_builder.Hashtbl + (Property.Hashtbl) + (Datatype.Make + (struct + type t = G.t + let name = "consolidation graph" + let reprs = [ G.empty ] + include Datatype.Serializable_undefined + end)) + (struct + let name = "Consolidation graph" + let size = 97 + let kind = `Correctness + let dependencies = [ Consolidation.Consolidated_status.self ] + end) + + type t = G.t + + let get_parameter_string ~tuning e s = + Pretty_utils.sfprintf + "%t" + (fun fmt -> Usable_emitter.pretty_parameter fmt ~tuning e s) + + let already_done = Property.Hashtbl.create 17 + + let rec get ppt = + Graph_by_property.memo + (fun ppt -> + (* [JS 2011/07/21] Only the better proof is added on the graph. For + instance, if the consolidated status is valid thanks to WP, it does + not show the dont_know proof tried by Value. *) + if Property.Hashtbl.mem already_done ppt then G.empty + else begin + Property.Hashtbl.add already_done ppt (); + let v_ppt = Property ppt in + (* adding the property *) + let g = G.add_vertex G.empty v_ppt in + match get_status ppt with + | Never_tried -> g + | Best(s, emitters) -> + get_emitters g v_ppt s emitters + | Inconsistent i -> + let g = get_emitters g v_ppt True i.valid in + get_emitters g v_ppt False_and_reachable i.invalid + end) + ppt + + and get_emitters g v_ppt s l = + List.fold_left + (fun g e -> + let emitter = e.emitter in + let v_e = Emitter (Usable_emitter.get_unique_name emitter) in + (* adding the emitter with its computed status *) + let g = G.add_edge_e g (v_ppt, Some s, v_e) in + let g = + (* adding the tuning parameters *) + List.fold_left + (fun g p -> + let s = get_parameter_string ~tuning:true emitter p in + G.add_edge g v_e (Tuning_parameter s)) + g + (Usable_emitter.tuning_parameters emitter) + in + let g = + (* adding the correctness parameters *) + List.fold_left + (fun g p -> + let s = get_parameter_string ~tuning:false emitter p in + G.add_edge g v_e (Correctness_parameter s)) + g + (Usable_emitter.correctness_parameters emitter) + in + (* adding the hypotheses *) + List.fold_left + (fun g h -> + let g' = get h in + let union = G.fold_edges_e (fun e g -> G.add_edge_e g e) g g' in + G.add_edge union v_ppt (Property h)) + g + e.properties) + g + l + + let get ppt = + let g = get ppt in + Property.Hashtbl.clear already_done; + g + + let dump graph dot_file = + let module Dot = Graph.Graphviz.Dot + (struct + + include G + + let emitted_status_color = function + | True -> 0x00ff00 (* green *) + | False_if_reachable | False_and_reachable -> 0xff0000 (* red *) + | Dont_know -> 0xffa500 (* orange *) + + let status_color = function + | Never_tried -> 0x00ffff (* cyan *) + | Best(s, _) -> emitted_status_color s + | Inconsistent _ -> 0x808080 (* gray *) + + let graph_attributes _ = [] + + let vname v = + let s = match v with + | Property p -> Pretty_utils.sfprintf "%a" Property.pretty p + | Emitter s | Tuning_parameter s | Correctness_parameter s -> s + in String.escaped s + + (* TODO: potential issue here if 2 distincts properties share + the same vertex name ==> dot merges them into the same vertex. *) + let vertex_name v = Pretty_utils.sfprintf "\"%s\"" (vname v) + + let label v = `Label (vname v) + + let vertex_attributes = function + | Property p as v -> + let color = status_color (get_status p) in + [ label v; `Color color; `Shape `Box; `Style `Filled ] + | Emitter _ as v -> + [ label v; `Shape `Diamond; `Color 0xb0c4de; `Style `Filled ] + | Tuning_parameter _ as v -> + [ label v; `Style `Dotted; `Color 0xb0c4de; ] + | Correctness_parameter _ as v -> [ label v; `Color 0xb0c4de ] + + let edge_attributes e = match E.label e with + | None -> [] + | Some s -> + let c = emitted_status_color s in + [ `Color c; `Fontcolor c; `Style `Bold ] + + let default_vertex_attributes _ = [] + let default_edge_attributes _ = [] + let get_subgraph _ = None + end) + in + (* TODO: removing dot_file *) + let cout = open_out dot_file in + Kernel.Unicode.without_unicode (Dot.output_graph cout) graph; + close_out cout + +end + +let () = + (* would also clear the memoized consolidation graph *) + clear_consolidation := + fun () -> + Consolidation.Consolidated_status.clear (); + Consolidation_graph.Graph_by_property.clear () + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/property_status.mli frama-c-20111001+nitrogen+dfsg/src/logic/property_status.mli --- frama-c-20110201+carbon+dfsg/src/logic/property_status.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/property_status.mli 2011-10-10 08:38:23.000000000 +0000 @@ -0,0 +1,244 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* INRIA (Institut National de Recherche en Informatique et en *) +(* Automatique) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version v2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Status of properties. + @since Nitrogen-20111001 *) + +(* ************************************************************************ *) +(** {2 Local status} + + A local status (shortly, a status) of a property is a status directly set + by an emitter. Thus a property may have several distinct status according to + who attempts the verification. *) +(* ************************************************************************ *) + +(* ************************************************************************ *) +(** {3 Emitting a status} *) +(* ************************************************************************ *) + +(** Type of status emitted by analyzers. Each Property is attached to a program + point [s] and implicitely depends on an execution path from the program + entry point to [s]. It also depends on an explicit set of hypotheses [H] + indicating when emitting the property (see function {!emit}). *) +type emitted_status = + | True (** for each execution path [ep] from the program entry point to [s], + the formula (/\_{h in H} h) ==> P(ep) is true *) + | False_if_reachable (** for each execution path [ep] from the program entry + point to [s], the formula (/\_{h in H} h) ==> P(ep) + is false *) + | False_and_reachable (** it exists an execution path [ep] from the program + entry point to [s] such that the formula (/\_{h in + H} h) ==> P(ep) is false *) + | Dont_know (** any other case *) + +module Emitted_status: Datatype.S with type t = emitted_status + +exception Inconsistent_emitted_status of emitted_status * emitted_status + +val emit: + Emitter.t -> hyps:Property.t list -> Property.t -> ?distinct:bool -> + emitted_status -> unit +(** [emit e ~hyps p s] indicates that the status of [p] is [s], is emitted by + [e], and is based on the list of hypothesis [hyps]. If [e] previously + emitted another status [s'], it must be emitted with the same hypotheses and + a consistency check is performed between [s] and [s'] and the best (by + default the strongest) status is kept. If [distinct] is [true] (default is + [false]), then we consider than the given property may merge into one single + point several distinct statuses. The strategy for computing the best + status is changed accordingly. One example when [~distinct:true] is required + is when emitting a status for a pre-condition of a function [f] since the + status associated to a pre-condition [p] merges all statuses of [p] at each + callsite of the function [f]. + @return the kept status. + @raise Inconsistent_emitted_status when emiting False after emiting True or + conversely *) + +val emit_and_get: + Emitter.t -> hyps:Property.t list -> Property.t -> ?distinct:bool -> + emitted_status -> emitted_status +(** Like {!emit} but also returns the computed status. *) + +val logical_consequence: Emitter.t -> Property.t -> Property.t list -> unit +(** [logical_consequence e ppt list] indicates that the emitter [e] considers + that [ppt] is a logical consequence of the conjunction of properties + [list]. Thus it lets the kernel automatically computes it: [e] must not call + functions [emit*] itself on this property, but the kernel ensures that the + status will be up-to-date when getting it. *) + +val self: State.t +(** The state which stores the computed status. *) + +(* ************************************************************************ *) +(** {3 Getting a (local) status} *) +(* ************************************************************************ *) + +type emitter_with_properties = private + { emitter: Emitter.Usable_emitter.t; + properties: Property.t list; + logical_consequence: bool (** Is the emitted status automatically + infered? *) } + +type inconsistent = private + { valid: emitter_with_properties list; + invalid: emitter_with_properties list } + +(** Type of known precise status of a property. *) +type status = private + | Never_tried (** Nobody tries to verify the property *) + | Best of + emitted_status (** The know precise status *) + * emitter_with_properties list (** who attempt the verification + under which hypotheses *) + | Inconsistent of inconsistent (** someone says the property is valid and + someone else says it is invalid. *) + +include Datatype.S with type t = status + +val get: Property.t -> status +(** @return the most precise status and all its emitters. *) + +(* ************************************************************************ *) +(** {2 Consolidated status} *) +(* ************************************************************************ *) + +(** Consolidation of a property status according to the (consolidated) status of + the hypotheses of the property. *) +module Consolidation: sig + + (** who do the job and, for each of them, who find which issues. *) + type pending = + Property.Set.t Emitter.Usable_emitter.Map.t Emitter.Usable_emitter.Map.t + + type consolidated_status = private + | Never_tried + (** Nobody tries to verify the property. + The argument is for internal use only *) + + | Considered_valid + (** Nobody succeeds to verifiy the property, but it is expected to be + verified by another way (manual review, ...) *) + + | Valid of Emitter.Usable_emitter.Set.t + (** The verification of this property is fully done. No work to + do anymore for this property. The argument is the emitters who did the + job. *) + + | Valid_under_hyp of pending + (** The verification of this property is locally done, but it remains + properties to verify in order to close the + work. *) + + | Unknown of pending + (** The verification of this property is not finished: the property itself + remains to verify and it may also remain other pending properties. + NB: the pendings contains the property itself. *) + + | Invalid of Emitter.Usable_emitter.Set.t + (** The verification of this property is fully done. All its hypotheses have + been verified, but it is false: that is a true bug. *) + + | Invalid_under_hyp of pending + (** This property is locally false, but it remains properties to verify in + order to be sure that is a bug. *) + + | Invalid_but_dead of pending + (** This property is locally false, but there is other bugs in hypotheses *) + + | Valid_but_dead of pending + (** This property is locally true, but there is bugs in hypotheses *) + + | Unknown_but_dead of pending + (** This property is locally unknown, but there is other bugs in + hypotheses *) + + | Inconsistent of string + (** Inconsistency detected when computing the consolidated status. + The string explains what is the issue for the end-user. *) + + include Datatype.S with type t = consolidated_status + + val get: Property.t -> t + val get_conjunction: Property.t list -> t + +end + +(** Lighter version than Consolidation *) +module Feedback: sig + + (** Same constructor than Consolidation.t, without argument. *) + type t = + | Never_tried + | Considered_valid + | Valid + | Valid_under_hyp + | Unknown + | Invalid + | Invalid_under_hyp + | Invalid_but_dead + | Valid_but_dead + | Unknown_but_dead + | Inconsistent + + val get: Property.t -> t + val get_conjunction: Property.t list -> t + +end + +(** See the consolidated status of a property in a graph, which all its + dependencies and their consolidated status. *) +module Consolidation_graph: sig + type t + val get: Property.t -> t + val dump: t -> string -> unit +end + +(* ************************************************************************* *) +(** {2 Access to the registered properties} *) +(* ************************************************************************* *) + +val iter: (Property.t -> unit) -> unit +val fold: (Property.t -> 'a -> 'a) -> 'a -> 'a + +(* ************************************************************************* *) +(** {2 API not for casual users} *) +(* ************************************************************************* *) + +val register: Property.t -> unit +(** Register the given property. It must not be already registered. *) + +val remove: Property.t -> unit + +val merge: old:Property.t list -> Property.t list -> unit +(** [merge old new] registers properties in [new] which are not in [old] and + removes properties in [old] which are not in [new]. *) + +val automatically_proven: Property.t -> bool +(** Is the status of the given property only automatically handled by the + kernel? *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/translate_lightweight.ml frama-c-20111001+nitrogen+dfsg/src/logic/translate_lightweight.ml --- frama-c-20110201+carbon+dfsg/src/logic/translate_lightweight.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/translate_lightweight.ml 2011-10-10 08:38:23.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,20 +15,13 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) open Cil_types -open Genlex open Cil -open Cilutil -open Ast_info -open Cil_datatype -open Extlib -open Db_types -open Visitor let mkterm tnode ty loc = { term_node = tnode; @@ -38,24 +29,29 @@ term_type = ty; term_name = [] } -let term_of_var v= variable_term v.vdecl (cvar_to_lvar v) +let term_of_var v= Ast_info.variable_term v.vdecl (cvar_to_lvar v) class annotateFunFromDeclspec = let recover_from_attr_param params attrparam = let rec aux = function | AInt i -> - constant_term Location.unknown (Int64.of_int i) + Ast_info.constant_term + Cil_datatype.Location.unknown (My_bigint.of_int i) | AUnOp(Neg,AInt i) -> - constant_term Location.unknown (Int64.of_int (-i)) + Ast_info.constant_term + Cil_datatype.Location.unknown (My_bigint.of_int (-i)) | AStr s | ACons(s,[]) -> - begin try - let v = List.find (fun v -> v.vname = s) params in - term_of_var v - with Not_found -> failwith "No recovery" end + begin try + let v = List.find (fun v -> v.vname = s) params in + term_of_var v + with Not_found -> failwith "No recovery" end | ABinOp(bop,attr1,attr2) -> - mkterm (TBinOp(bop,aux attr1,aux attr2)) Linteger Location.unknown + mkterm + (TBinOp(bop,aux attr1,aux attr2)) + Linteger + Cil_datatype.Location.unknown | ACons _ | ASizeOf _ | ASizeOfE _ @@ -75,9 +71,9 @@ let recover_from_attribute params attr = match attr with | Attr(name,attrparams) -> - begin try - Some(name, List.map (recover_from_attr_param params) attrparams) - with Failure "No recovery" -> None end + begin try + Some(name, List.map (recover_from_attr_param params) attrparams) + with Failure "No recovery" -> None end | AttrAnnot _ -> None in @@ -85,47 +81,47 @@ let annotate_var params acc v = List.fold_left (fun acc attr -> - match recover_from_attribute params attr with - | None -> acc - | Some(name,args) -> - if name = "valid" || name = "valid_range" then - let p = match name with - | "valid" -> - assert (args = []); - let ts = Logic_const.tvar (cvar_to_lvar v) in - Pvalid(ts) - | "valid_range" -> - let t1,t2 = match args with - | [ t1; t2 ] -> t1,t2 - | _ -> assert false - in - Pvalid_range(term_of_var v,t1,t2) - | _ -> assert false - in - let app = - Logic_const.new_predicate (Logic_const.unamed p) - in - app :: acc - else - try - let p = - match Logic_env.find_all_logic_functions name with - | [i] -> i - | _ -> raise Not_found - (* - error "[Jessie] Rewrite: cannot find logic function %s@." name; - raise Exit - *) - in - assert (List.length p.l_profile = List.length(args) + 1); - assert (List.length p.l_labels <= 1); - let args = term_of_var v :: args in - let app = - Logic_const.new_predicate - (Logic_const.unamed (Papp(p,[],args))) - in - app :: acc - with Not_found -> acc + match recover_from_attribute params attr with + | None -> acc + | Some(name,args) -> + if name = "valid" || name = "valid_range" then + let p = match name with + | "valid" -> + assert (args = []); + let ts = Logic_const.tvar (cvar_to_lvar v) in + Pvalid(ts) + | "valid_range" -> + let t1,t2 = match args with + | [ t1; t2 ] -> t1,t2 + | _ -> assert false + in + Pvalid_range(term_of_var v,t1,t2) + | _ -> assert false + in + let app = + Logic_const.new_predicate (Logic_const.unamed p) + in + app :: acc + else + try + let p = + match Logic_env.find_all_logic_functions name with + | [i] -> i + | _ -> raise Not_found + (* + error "[Jessie] Rewrite: cannot find logic function %s@." name; + raise Exit + *) + in + assert (List.length p.l_profile = List.length(args) + 1); + assert (List.length p.l_labels <= 1); + let args = term_of_var v :: args in + let app = + Logic_const.new_predicate + (Logic_const.unamed (Papp(p,[],args))) + in + app :: acc + with Not_found -> acc ) acc (typeAttrs v.vtype) in @@ -135,60 +131,65 @@ let req = List.fold_left (annotate_var params) [] params in if req <> [] then (* add [req] to [b_requires] of default behavior *) - let funspec = Kernel_function.get_spec kf in let return_ty = getReturnType v.vtype in let loc = v.vdecl in let behavior = Cil.mk_behavior ~requires:req () in - funspec.spec_behavior <- Logic_utils.merge_behaviors ~silent:false funspec.spec_behavior [behavior] ; - let insert_spec behavior = - let ens = - List.fold_left - (fun acc attr -> - match recover_from_attribute params attr with - | None -> acc - | Some(name,args) -> - if name = "valid" || name = "valid_range" then - let p = match name with - | "valid" -> - assert (args = []); - let ts = Logic_const.tresult ~loc return_ty in - Pvalid(ts) - | "valid_range" -> - let t1,t2 = match args with - | [ t1; t2 ] -> t1,t2 - | _ -> assert false - in - let res = Logic_const.tresult ~loc return_ty in - Pvalid_range(res,t1,t2) - | _ -> assert false - in - let app = - Logic_const.new_predicate (Logic_const.unamed p) - in - (Normal,app) :: acc - else - try - let p = - match Logic_env.find_all_logic_functions name with - | [i] -> i - | _ -> assert false - in - assert (List.length p.l_profile = List.length(args) + 1); - assert (List.length p.l_labels <= 1); - let res = Logic_const.tresult ~loc return_ty in - let args = res :: args in - let app = - Logic_const.new_predicate - (Logic_const.unamed (Papp(p,[],args))) - in - (Normal,app) :: acc - with Not_found -> acc) - behavior.b_post_cond - (typeAttrs return_ty) - in - behavior.b_post_cond <- ens - in - List.iter insert_spec funspec.spec_behavior + Kernel_function.set_spec + kf + (fun spec -> + spec.spec_behavior <- + Logic_utils.merge_behaviors + ~silent:false spec.spec_behavior [ behavior ] ; + let insert_spec behavior = + let ens = + List.fold_left + (fun acc attr -> + match recover_from_attribute params attr with + | None -> acc + | Some(name,args) -> + if name = "valid" || name = "valid_range" then + let p = match name with + | "valid" -> + assert (args = []); + let ts = Logic_const.tresult ~loc return_ty in + Pvalid(ts) + | "valid_range" -> + let t1,t2 = match args with + | [ t1; t2 ] -> t1,t2 + | _ -> assert false + in + let res = Logic_const.tresult ~loc return_ty in + Pvalid_range(res,t1,t2) + | _ -> assert false + in + let app = + Logic_const.new_predicate (Logic_const.unamed p) + in + (Normal, app) :: acc + else + try + let p = + match Logic_env.find_all_logic_functions name with + | [i] -> i + | _ -> assert false + in + assert (List.length p.l_profile = List.length args + 1); + assert (List.length p.l_labels <= 1); + let res = Logic_const.tresult ~loc return_ty in + let args = res :: args in + let app = + Logic_const.new_predicate + (Logic_const.unamed (Papp(p,[],args))) + in + (Normal,app) :: acc + with Not_found -> acc) + behavior.b_post_cond + (typeAttrs return_ty) + in + behavior.b_post_cond <- ens; + in + List.iter insert_spec spec.spec_behavior; + spec) in object @@ -196,41 +197,47 @@ (Project.current ()) (Cil.inplace_visit ()) as super method vglob_aux = function - | GFun(f,_) -> - annotate_fun f.svar; - SkipChildren - | GVarDecl(_,v,_) - | GVar(v,_,_) (*as g*) -> - if isFunctionType v.vtype && not v.vdefined then - annotate_fun v; - SkipChildren - (* ) - else - let inv = annotate_var [] [] v in - let postaction gl = - match inv with [] -> gl | _ -> - (* Define a global string invariant *) - let inv = - List.map (fun p -> Logic_const.unamed p.ip_content) inv - in - let p = Logic_const.new_predicate (Logic_const.pands inv) in - let globinv = - Cil_const.make_logic_info (unique_logic_name ("valid_" ^ v.vname)) - in - globinv.l_labels <- [ LogicLabel "Here" ]; - globinv.l_body <- LBpred (predicate v.vdecl p.ip_content); - attach_globaction - (fun () -> Logic_utils.add_logic_function globinv); - gl @ [GAnnot(Dinvariant globinv,v.vdecl)] - in - ChangeDoChildrenPost ([g], postaction) - *) - | GAnnot _ -> DoChildren - | GCompTag _ | GType _ | GCompTagDecl _ | GEnumTagDecl _ - | GEnumTag _ | GAsm _ | GPragma _ | GText _ -> - SkipChildren + | GFun(f,_) -> + annotate_fun f.svar; + SkipChildren + | GVarDecl(_,v,_) + | GVar(v,_,_) (*as g*) -> + if isFunctionType v.vtype && not v.vdefined then + annotate_fun v; + SkipChildren + (* ) + else + let inv = annotate_var [] [] v in + let postaction gl = + match inv with [] -> gl | _ -> + (* Define a global string invariant *) + let inv = + List.map (fun p -> Logic_const.unamed p.ip_content) inv + in + let p = Logic_const.new_predicate (Logic_const.pands inv) in + let globinv = + Cil_const.make_logic_info (unique_logic_name ("valid_" ^ v.vname)) + in + globinv.l_labels <- [ LogicLabel "Here" ]; + globinv.l_body <- LBpred (predicate v.vdecl p.ip_content); + attach_globaction + (fun () -> Logic_utils.add_logic_function globinv); + gl @ [GAnnot(Dinvariant globinv,v.vdecl)] + in + ChangeDoChildrenPost ([g], postaction) + *) + | GAnnot _ -> DoChildren + | GCompTag _ | GType _ | GCompTagDecl _ | GEnumTagDecl _ + | GEnumTag _ | GAsm _ | GPragma _ | GText _ -> + SkipChildren end let interprate file = let visitor = new annotateFunFromDeclspec in - visitFramacFile visitor file + Visitor.visitFramacFile visitor file + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/logic/translate_lightweight.mli frama-c-20111001+nitrogen+dfsg/src/logic/translate_lightweight.mli --- frama-c-20110201+carbon+dfsg/src/logic/translate_lightweight.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/logic/translate_lightweight.mli 2011-10-10 08:38:23.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,13 +15,17 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) -(*****************************************************************************) -(* Annotate files interpreting lightweight annotations *) -(*****************************************************************************) +(** Annotate files interpreting lightweight annotations. *) val interprate : Cil_types.file -> unit + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/abstract_value.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/abstract_value.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/abstract_value.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/abstract_value.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,11 +20,17 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please write a .mli and + document it. *) + open Abstract_interp module Unhashconsed_Int_Intervals = struct - include Make_Lattice_Interval_Set (Int) + include Lattice_Interval_Set let fold_enum ~split_non_enumerable f v acc = ignore (split_non_enumerable); @@ -36,13 +42,14 @@ let pretty_typ typ fmt i = let typ = match typ with - Some t -> t + Some t -> t | None -> Cil_types.TArray - (Cil_types.TInt(Cil_types.IUChar,[]), - Some (Cil.kinteger64 - ~loc:(Cil.CurrentLoc.get ()) - Cil_types.IULongLong 922337203685477580L + (Cil_types.TInt(Cil_types.IUChar,[]), + Some (Cil.kinteger64 + ~loc:(Cil.CurrentLoc.get ()) + Cil_types.IULongLong + (My_bigint.of_int64 922337203685477580L) (* See Cuoq for rational *)), Cil.empty_size_cache (), []) @@ -52,29 +59,27 @@ | Set s -> if s=[] then Format.fprintf fmt "BottomISet" else begin - let pp_one fmt (b,e)= - assert (Int.le b e) ; - ignore (Bit_utils.pretty_bits typ - ~use_align:false - ~align:Int.zero - ~rh_size:Int.one - ~start:b ~stop:e fmt) in - let pp_stmt fmt r = Format.fprintf fmt "%a;@ " pp_one r in - match s with - | [] -> Format.pp_print_string fmt "{}" - | [r] -> pp_one fmt r - | s -> - Format.fprintf fmt "@[{" ; - List.iter (pp_stmt fmt) s ; - Format.fprintf fmt "}@]" ; + let pp_one fmt (b,e)= + assert (Int.le b e) ; + ignore (Bit_utils.pretty_bits typ + ~use_align:false + ~align:Int.zero + ~rh_size:Int.one + ~start:b ~stop:e fmt) in + let pp_stmt fmt r = Format.fprintf fmt "%a;@ " pp_one r in + match s with + | [] -> Format.pp_print_string fmt "{}" + | [r] -> pp_one fmt r + | s -> + Format.fprintf fmt "@[{" ; + List.iter (pp_stmt fmt) s ; + Format.fprintf fmt "}@]" ; end let from_ival_int ival int = - let max_elt_int = Parameters.Dynamic.Int.get "-plevel" in + let max_elt_int = Kernel.ArrayPrecisionLevel.get() in let max_elt = Int.of_int max_elt_int in - let add_offset x acc = - join (inject_one ~value:x ~size:int) acc - in + let add_offset x acc = join (inject_one ~value:x ~size:int) acc in match ival with | Ival.Top(None, _, _, _) | Ival.Top(_, None, _, _) | Ival.Float _ -> top @@ -83,32 +88,33 @@ then inject_one ~value:mn ~size:(Int.add (Int.sub mx mn) int) else let elts = Int.native_div (Int.sub mx mn) m in - if Int.gt elts max_elt then + if Int.gt elts max_elt then begin (* too many elements to enumerate *) - (ignore (CilE.warn_once "more than %d(%a) elements to enumerate. Approximating." - max_elt_int - Int.pretty elts); - top) - else Int.fold add_offset ~inf:mn ~sup:mx ~step:m bottom + Kernel.result ~once:true ~current:true + "more than %d(%a) elements to enumerate. Approximating." + max_elt_int + Int.pretty elts; + top + end else Int.fold add_offset ~inf:mn ~sup:mx ~step:m bottom | Ival.Set(s) -> - Ival.O.fold - add_offset - s - bottom + Array.fold_right + add_offset + s + bottom let from_ival_size ival size = match size with | Int_Base.Top -> top | Int_Base.Bottom -> assert false | Int_Base.Value int -> - from_ival_int ival int + from_ival_int ival int let inject_zero_max size = match size with | Int_Base.Top -> top | Int_Base.Bottom -> assert false | Int_Base.Value int -> - inject_one ~value:Int.zero ~size:int + inject_one ~value:Int.zero ~size:int let diff x y = if is_included x y then bottom else x @@ -119,17 +125,17 @@ match intervs with Top -> top | Set l -> - inject (List.map (fun (bi,ei) -> (Int.add bi x,Int.add ei x)) l) + inject (List.map (fun (bi,ei) -> (Int.add bi x,Int.add ei x)) l) let shift_ival intervs ival = match ival with Ival.Top _ | Ival.Float _ -> top | Ival.Set s -> - Ival.O.fold - (fun x acc -> - join acc (shift_int64 x intervs)) - s - bottom + Array.fold_right + (fun x acc -> + join acc (shift_int64 x intervs)) + s + bottom end module Int_Intervals = struct @@ -162,8 +168,8 @@ type t = tt let equal = equal_internal let hash = hash_internal - let pretty = pretty - let id = name + let pretty = pretty + let id = name end) let table = IntIntervalsHashtbl.create 139 @@ -193,23 +199,23 @@ include Datatype.Make (struct - type t = tt - let structural_descr = - Structural_descr.t_record - [| Structural_descr.p_int; - Unhashconsed_Int_Intervals.packed_descr; - Structural_descr.p_int |] - let reprs = [ top; bottom ] - let name = "Abstract_value.Int_Intervals" - let compare = compare - let equal = ( == ) - let copy = Datatype.undefined - let hash x = x.h - let rehash x = wrap x.v - let internal_pretty_code = Datatype.undefined - let pretty = pretty - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project + type t = tt + let structural_descr = + Structural_descr.t_record + [| Structural_descr.p_int; + Unhashconsed_Int_Intervals.packed_descr; + Structural_descr.p_int |] + let reprs = [ top; bottom ] + let name = "Abstract_value.Int_Intervals" + let compare = compare + let equal = ( == ) + let copy = Datatype.undefined + let hash x = x.h + let rehash x = wrap x.v + let internal_pretty_code = Datatype.undefined + let pretty = pretty + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project end) let fold_enum ~split_non_enumerable f v acc = diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/binary_cache.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/binary_cache.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/binary_cache.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/binary_cache.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,405 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -module MemoryFootprint = - State_builder.Int_ref - (struct - let name = "Binary_cache.MemoryFootprint" - let dependencies = [] - let kind = `Internal - let default () = 2 - end) - -let get_size () = - match MemoryFootprint.get () with - 1 -> 512 - | 2 -> 1024 - | _ -> 2048 - -module type Cacheable = -sig - type t - val hash : t -> int - val sentinel : t - val equal : t -> t -> bool -end - -module type Result = -sig - type t - val sentinel : t -end - -module Array_2 = -struct - type ('a, 'b) t - - let (clear : ('a, 'b) t -> 'a -> 'b -> unit) - = fun t a b -> - let t = Obj.repr t in - let size2 = Obj.size t in - let i = ref 0 in - while (!i < size2) - do - let base = !i in - Obj.set_field t (base) (Obj.repr a); - Obj.set_field t (base+1) (Obj.repr b); - i := base + 2; - done - - let (make : int -> 'a -> 'b -> ('a, 'b) t) - = fun size a b -> - let size2 = 2 * size in - let t = Obj.obj (Obj.new_block 0 size2) in - clear t a b; - t - - let (set : ('a, 'b) t -> int -> 'a -> 'b -> unit) - = fun t i a b -> - let t = Obj.repr t in - let base = 2 * i in - Obj.set_field t (base) (Obj.repr a); - Obj.set_field t (base+1) (Obj.repr b) - - let (get0 : - ('a, 'b) t -> int -> 'a) - = fun t i -> - let t = Obj.repr t in - let base = 2 * i in - Obj.obj (Obj.field t (base)) - - let (get1 : ('a, 'b) t -> int -> 'b) - = fun t i -> - let t = Obj.repr t in - let base = 2 * i in - Obj.obj (Obj.field t (base+1)) -end - -module Array_3 = -struct - type ('a, 'b, 'c) t - - let (clear : ('a, 'b, 'c) t -> - 'a -> 'b -> 'c -> unit) - = fun t a b c -> - let t = Obj.repr t in - let size3 = Obj.size t in - let i = ref 0 in - while (!i < size3) - do - let base = !i in - Obj.set_field t (base) (Obj.repr a); - Obj.set_field t (base+1) (Obj.repr b); - Obj.set_field t (base+2) (Obj.repr c); - i := base + 3; - done - - let (make : int -> 'a -> 'b -> 'c -> ('a, 'b, 'c) t) - = fun size a b c -> - let size3 = 3 * size in - let t = Obj.obj (Obj.new_block 0 size3) in - clear t a b c; - t - - let (set : ('a, 'b, 'c) t -> int -> 'a -> 'b -> 'c -> unit) - = fun t i a b c -> - let t = Obj.repr t in - let base = 3 * i in - Obj.set_field t (base) (Obj.repr a); - Obj.set_field t (base+1) (Obj.repr b); - Obj.set_field t (base+2) (Obj.repr c) - - let (get0 : - ('a, 'b, 'c) t -> int -> 'a) - = fun t i -> - let t = Obj.repr t in - let base = 3 * i in - Obj.obj (Obj.field t (base)) - - let (get1 : ('a, 'b, 'c) t -> int -> 'b) - = fun t i -> - let t = Obj.repr t in - let base = 3 * i in - Obj.obj (Obj.field t (base+1)) - - let (get2 : - ('a, 'b, 'c) t -> int -> 'c) - = fun t i -> - let t = Obj.repr t in - let base = 3 * i in - Obj.obj (Obj.field t (base+2)) -end - -module Array_7 = -struct - type ('a, 'b, 'c, 'd, 'e, 'f, 'g) t - - let (clear : ('a , 'b , 'c , 'd , 'e , 'f , 'g) t -> - 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> unit) - = fun t a b c d e f g -> - let t = Obj.repr t in - let size7 = Obj.size t in - let i = ref 0 in - while (!i < size7) - do - let base = !i in - Obj.set_field t (base) (Obj.repr a); - Obj.set_field t (base+1) (Obj.repr b); - Obj.set_field t (base+2) (Obj.repr c); - Obj.set_field t (base+3) (Obj.repr d); - Obj.set_field t (base+4) (Obj.repr e); - Obj.set_field t (base+5) (Obj.repr f); - Obj.set_field t (base+6) (Obj.repr g); - i := base + 7; - done - - let (make : int -> 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> - ('a , 'b , 'c , 'd , 'e , 'f , 'g) t) - = fun size a b c d e f g -> - let size7 = 7 * size in - let t = Obj.obj (Obj.new_block 0 size7) in - clear t a b c d e f g; - t - - let (set : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> - 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> unit) - = fun t i a b c d e f g -> - let t = Obj.repr t in - let base = 7 * i in - Obj.set_field t (base) (Obj.repr a); - Obj.set_field t (base+1) (Obj.repr b); - Obj.set_field t (base+2) (Obj.repr c); - Obj.set_field t (base+3) (Obj.repr d); - Obj.set_field t (base+4) (Obj.repr e); - Obj.set_field t (base+5) (Obj.repr f); - Obj.set_field t (base+6) (Obj.repr g) - - let (get0 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'a) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base)) - - let (get1 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'b) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base+1)) - - let (get2 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'c) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base+2)) - - let (get3 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'd) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base+3)) - - let (get4 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'e) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base+4)) - - let (get5 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'f) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base+5)) - - let (get6 : - ('a, 'b, 'c, 'd, 'e, 'f, 'g) t -> int -> 'g) - = fun t i -> - let t = Obj.repr t in - let base = 7 * i in - Obj.obj (Obj.field t (base+6)) - -end - -module Make_Symetric (H: Cacheable) (R: Result) = -struct - let size = get_size () - let cache = Array_3.make size H.sentinel H.sentinel R.sentinel - - let mask = pred size - - let clear () = - Array_3.clear cache H.sentinel H.sentinel R.sentinel - - let hash = H.hash - - let merge f a0 a1 = - let a0, a1, h0, h1 = - let h0 = hash a0 in - let h1 = hash a1 in - if h0 < h1 - then a0, a1, h0, h1 - else a1, a0, h1, h0 - in - let has = h1 lsl 5 - h1 + h0 - in - let has = has land mask in - - if H.equal (Array_3.get0 cache has) a0 - && H.equal (Array_3.get1 cache has) a1 - then begin -(* Format.printf "Cache O@."; *) - Array_3.get2 cache has - end - else - let result = f a0 a1 in -(* Format.printf "Cache N@."; *) - Array_3.set cache has a0 a1 result; - result -end - - -module Make_Asymetric (H: Cacheable) (R: Result) = -struct - let size = 1024 (*get_size ()*) - let cache = Array_3.make size H.sentinel H.sentinel R.sentinel - - let mask = pred size - - let clear () = - Array_3.clear cache H.sentinel H.sentinel R.sentinel - - let merge f a0 a1 = - let h0 = H.hash a0 in - let h1 = H.hash a1 in - let has = h1 lsl 5 - h1 + h0 - in - let has = has land mask in - - if H.equal (Array_3.get0 cache has) a0 - && H.equal (Array_3.get1 cache has) a1 - then begin -(* Format.printf "Cache O@."; *) - Array_3.get2 cache has - end - else - let result = f () in -(* Format.printf "Cache N@."; *) - Array_3.set cache has a0 a1 result; - result -end - -module Array_Bit = -struct - let make size = - let size = (size + 7) lsr 3 in - String.make size (char_of_int 0) - - let get s i = - let b = 1 lsl (i land 7) in - let c = i lsr 3 in - (Char.code s.[c]) land b <> 0 - - let set s i v = - let b = 1 lsl (i land 7) in - let mask = lnot b in - let b = if v then b else 0 in - let c = i lsr 3 in - s.[c] <- Char.chr (((Char.code s.[c]) land mask) lor b) -end - -module Make_Binary (H0: Cacheable) (H1: Cacheable) = -struct - let size = get_size() - let cache = Array_2.make size H0.sentinel H1.sentinel - let result = Array_Bit.make size - let mask = pred size - - let clear () = - Array_2.clear cache H0.sentinel H1.sentinel - - let merge f a0 a1 = - let has = - let h0 = H0.hash a0 in - let h1 = H1.hash a1 in - 599 * h0 + h1 - in - let has = has land mask in - - if H0.equal (Array_2.get0 cache has) a0 - && H1.equal (Array_2.get1 cache has) a1 - then begin -(* Format.printf "Cache O@."; *) - Array_Bit.get result has - end - else - let r = f () in -(* Format.printf "Cache N@."; *) - Array_2.set cache has a0 a1; - Array_Bit.set result has r; - r -end - -module Make_Het1_1_4 (H0: Cacheable) (H1: Cacheable) (H2: Cacheable) (R: Result) = -struct - let size = get_size () - let cache = - Array_7.make size - H0.sentinel H1.sentinel - H2.sentinel H2.sentinel H2.sentinel H2.sentinel - R.sentinel - - let mask = pred size - - let clear () = - Array_7.clear cache - H0.sentinel H1.sentinel - H2.sentinel H2.sentinel H2.sentinel H2.sentinel - R.sentinel - - let merge f a0 a1 a2 a3 a4 a5 = - let has = H0.hash a0 + 4909 * (H1.hash a1) + - 127 * (H2.hash a2) + 971 * (H2.hash a3) + - 31 * (H2.hash a4) + 7907 * (H2.hash a5) - in - let has = has land mask in - if H0.equal (Array_7.get0 cache has) a0 - && H1.equal (Array_7.get1 cache has) a1 - && H2.equal (Array_7.get2 cache has) a2 - && H2.equal (Array_7.get3 cache has) a3 - && H2.equal (Array_7.get4 cache has) a4 - && H2.equal (Array_7.get5 cache has) a5 - then begin -(* Format.printf "Cache O@."; *) - Array_7.get6 cache has - end - else - let result = f () in -(* Format.printf "Cache N@."; *) - Array_7.set cache has a0 a1 a2 a3 a4 a5 result; - result -end diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/binary_cache.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/binary_cache.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/binary_cache.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/binary_cache.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -module MemoryFootprint : State_builder.Ref with type data = int - -module type Cacheable = -sig - type t - val hash : t -> int - val sentinel : t - val equal : t -> t -> bool -end - -module type Result = -sig - type t - val sentinel : t -end - -module Make_Symetric : - functor (H : Cacheable) -> functor (R : Result) -> - sig - val clear : unit -> unit - val merge : (H.t -> H.t -> R.t) -> H.t -> H.t -> R.t - end - -module Make_Asymetric : - functor (H : Cacheable) -> functor (R : Result) -> - sig - val clear : unit -> unit - val merge : (unit -> R.t) -> H.t -> H.t -> R.t - end - -module Make_Binary : - functor (H0 : Cacheable) -> functor (H1 : Cacheable) -> - sig - val clear : unit -> unit - val merge : (unit -> bool) -> H0.t -> H1.t -> bool - end - -module Make_Het1_1_4 : -functor (H0 : Cacheable) -> - functor (H1 : Cacheable) -> - functor (H2 : Cacheable) -> - functor (R : Result) -> -sig - val clear : unit -> unit - val merge : - (unit -> R.t) -> - H0.t -> H1.t -> H2.t -> H2.t -> H2.t -> H2.t -> R.t -end - diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/bit_model_access.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/bit_model_access.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/bit_model_access.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/bit_model_access.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,114 +20,124 @@ (* *) (**************************************************************************) -(* $Id: bit_model_access.ml,v 1.22 2008-04-01 09:25:21 uid568 Exp $ *) - open Db (* Update the associated value [new_v] to an lvalue [lv] in [mem] *) let update_from looking_for new_v mem = - let exact = Locations.valid_cardinal_zero_or_one looking_for in - (*Format.printf "Update is exact : %b %a\n" exact + let exact = + Locations.valid_cardinal_zero_or_one ~for_writing:true looking_for + in + (*Format.printf "Update is exact : %b %a\n" exact Locations.pretty looking_for;*) - (Lmap_bitwise.From_Model.add_binding - exact mem (Locations.valid_enumerate_bits looking_for) new_v) + (Lmap_bitwise.From_Model.add_binding + exact + mem + (Locations.valid_enumerate_bits ~for_writing:true looking_for) + new_v) let access_from looking_for mem = - let r = Lmap_bitwise.From_Model.find - mem + let r = Lmap_bitwise.From_Model.find + mem looking_for in r -let access_value_of_lval kinstr lv = +let access_value_of_lval kinstr lv = let state = Value.get_state kinstr in snd (!Value.eval_lval ~with_alarms:CilE.warn_none_mode None state lv) -let access_value_of_expr kinstr e = +let access_value_of_expr kinstr e = let state = Value.get_state kinstr in !Value.eval_expr ~with_alarms:CilE.warn_none_mode state e let access_value_of_location kinstr loc = let state = Value.get_state kinstr in - Value.find state loc + Value.find state loc -let access_value_of_lval_after ki lv = - match ki with - | Cil_types.Kstmt {Cil_types.succs = (_::_ ) as l} -> - let result = - List.fold_left - (fun acc s -> +let access_value_of_lval_after ki lv = + match ki with + | Cil_types.Kstmt {Cil_types.succs = (_::_ ) as l} -> + let result = + List.fold_left + (fun acc s -> let ks = Cil_types.Kstmt s in - Cvalue_type.V.join (access_value_of_lval ks lv) acc) - Cvalue_type.V.bottom + Cvalue.V.join (access_value_of_lval ks lv) acc) + Cvalue.V.bottom l in begin match Bit_utils.sizeof_lval lv with | Int_Base.Bottom -> assert false | Int_Base.Top -> result - | Int_Base.Value size -> - Cvalue_type.V.anisotropic_cast ~size result + | Int_Base.Value size -> + Cvalue.V.anisotropic_cast ~size result end | _ -> raise Not_found -let access_offsetmap_of_lval_after ki lv = - match ki with - | Cil_types.Kstmt {Cil_types.succs = (_::_ ) as l} -> - let result = - List.fold_left - (fun acc s -> +let access_offsetmap_of_lval_after ki lv = + match ki with + | Cil_types.Kstmt {Cil_types.succs = (_::_ ) as l} -> + let result = + List.fold_left + (fun acc s -> let ks = Cil_types.Kstmt s in - let state = Db.Value.get_state ks in - let loc = Locations.valid_part - (!Db.Value.lval_to_loc_state state lv) - in - let offsetmap = -(* try *) - Relations_type.Model.copy_offsetmap - ~with_alarms:CilE.warn_none_mode loc state -(* with Lmap.Cannot_copy -> - let _,exp = !Value.eval_lval ~with_alarms:CilE.warn_none_mode None state lv in - if Cvalue_type.V.is_bottom exp - then None - else - Some (Cvalue_type.V_Offsetmap.update_ival - ~with_alarms:CilE.warn_none_mode - ~validity:Base.All - ~offsets:Ival.zero - ~exact:true - ~size:(Abstract_interp.Int.of_int (Cil.bitsSizeOf (Cil.typeOfLval lv))) - Cvalue_type.V_Offsetmap.empty - (Cvalue_type.V_Or_Uninitialized.initialized exp)) + let state = Db.Value.get_state ks in + let loc = + Locations.valid_part ~for_writing:false + (!Db.Value.lval_to_loc_state state lv) + in + let offsetmap = +(* try *) + Cvalue.Model.copy_offsetmap + ~with_alarms:CilE.warn_none_mode loc state +(* with Lmap.Cannot_copy -> + let _,exp = !Value.eval_lval ~with_alarms:CilE.warn_none_mode None state lv in + if Cvalue.V.is_bottom exp + then None + else + Some (Cvalue.V_Offsetmap.update_ival + ~with_alarms:CilE.warn_none_mode + ~validity:Base.All + ~offsets:Ival.zero + ~exact:true + ~size:(Abstract_interp.Int.of_int (Cil.bitsSizeOf (Cil.typeOfLval lv))) + Cvalue.V_Offsetmap.empty + (Cvalue.V_Or_Uninitialized.initialized exp)) *) - in - match acc, offsetmap with - | None, x | x , None -> x - | Some acc, Some offsetmap -> - Some (snd (Cvalue_type.V_Offsetmap.join acc offsetmap))) + in + match acc, offsetmap with + | None, x | x , None -> x + | Some acc, Some offsetmap -> + Some (snd (Cvalue.V_Offsetmap.join acc offsetmap))) None l in result | _ -> raise Not_found -let access_value_of_location_after ki loc = - match ki with - | Cil_types.Kstmt {Cil_types.succs=(_::_ ) as l} -> - List.fold_left - (fun acc s -> +let access_value_of_location_after ki loc = + match ki with + | Cil_types.Kstmt {Cil_types.succs=(_::_ ) as l} -> + List.fold_left + (fun acc s -> let ks = Cil_types.Kstmt s in - Cvalue_type.V.join (access_value_of_location ks loc) acc) - Cvalue_type.V.bottom + Cvalue.V.join (access_value_of_location ks loc) acc) + Cvalue.V.bottom l | _ -> raise Not_found (* Register functions in the kernel *) -let () = +let () = From.update := update_from; - From.access := access_from; + From.access := access_from; Value.access := access_value_of_lval; Value.access_after := access_value_of_lval_after; Value.access_location_after := access_value_of_location_after; Value.access_location := access_value_of_location; Value.access_expr := access_value_of_expr; Value.lval_to_offsetmap_after := access_offsetmap_of_lval_after + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/bit_model_access.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/bit_model_access.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/bit_model_access.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/bit_model_access.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,5 +20,11 @@ (* *) (**************************************************************************) -(* Nothing is exported directly. +(** Empty on purpose. Functions are registered in the kernel. *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/cvalue.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/cvalue.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/cvalue.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/cvalue.ml 2011-10-10 08:38:30.000000000 +0000 @@ -0,0 +1,1211 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* types of values *) +open Cil +open Abstract_interp +open Abstract_value +open Locations +open CilE + +module V = struct + + include Location_Bytes + + exception Not_based_on_null + + let project_ival m = + try + let k, v = find_lonely_key m in + if not (Base.is_null k) + then raise Not_based_on_null + else v + with Not_found -> raise Not_based_on_null + + let types = Hashtbl.create 7;; + + let pretty_int_range fmt print_ampamp typname lv v = + let v = project_ival v in + ( match Ival.min_and_max v with + Some mn, Some mx -> + if Int.equal mn mx + then begin + print_ampamp(); + Format.fprintf fmt "*(%s*)%s == %a" + typname + lv + Int.pretty mn + end + else begin + print_ampamp(); + Format.fprintf fmt "%a <= *(%s*)%s && *(%s*)%s <= %a" + Int.pretty mn + typname + lv + typname + lv + Int.pretty mx; + end + | _ -> ()) + + let pretty_float_range fmt print_ampamp typname lv v = + let use_hex = true in + let v = project_ival v in + let v = Ival.project_float v in + let mn, mx = Ival.Float_abstract.min_and_max_float v in + if Ival.F.equal mn mx + then begin + print_ampamp(); + Format.fprintf fmt "*(%s*)%s == %a" + typname + lv + (Ival.F.pretty_normal ~use_hex) mn + end + else begin + print_ampamp(); + Format.fprintf fmt "%a <= *(%s*)%s && *(%s*)%s <= %a" + (Ival.F.pretty_normal ~use_hex) mn + typname + lv + typname + lv + (Ival.F.pretty_normal ~use_hex) mx; + end + + let () = + Hashtbl.add types 1 + [inject_ival (Ival.inject_range + (Some Int.zero) (Some (Int.of_int 255))), + "unsigned char", pretty_int_range; + inject_ival (Ival.inject_range + (Some (Int.of_int (-128))) (Some (Int.of_int 127))), + "char", pretty_int_range]; + Hashtbl.add types 2 + [inject_ival (Ival.inject_range + (Some Int.zero) (Some (Int.of_int 65535))), + "unsigned short", pretty_int_range; + inject_ival (Ival.inject_range + (Some (Int.of_int (-32768))) (Some (Int.of_int 32767))), + "short", pretty_int_range]; + Hashtbl.add types 4 + [ top_float, + "float", pretty_float_range; + inject_ival (Ival.inject_range + (Some Int.zero) (Some (Int.of_string "4294967295"))), + "unsigned int", pretty_int_range; + inject_ival (Ival.inject_range + (Some (Int.of_string "-2147483648")) + (Some (Int.of_string "2147483647"))), + "int", pretty_int_range]; + Hashtbl.add types 8 + [ top_float, + "double", pretty_float_range]; + () + + let pretty_c_assert print_ampamp lv s_bytes fmt v = + try + let candidate_types = Hashtbl.find types s_bytes in + let rec find_typ l = + match l with + [] -> () + | (range, _, _) :: t when not (is_included v range) -> + find_typ t + | (_range, typname, pr) :: _ -> + pr fmt print_ampamp typname lv v + + in + find_typ candidate_types + with Not_based_on_null -> () + + let force_float kind v = + try + let i = project_ival v in + let f, fi = Ival.force_float kind i in + f, inject_ival (fi) + with Not_based_on_null -> + true, topify_arith_origin v + + let is_imprecise v = + match v with + | Top _ -> true + | _ -> false + + let is_topint v = equal top_int v + + let is_bottom v = equal bottom v + + + let is_isotropic v = + match v with + | Top _ -> true + | Map _ -> is_topint v || is_bottom v || is_zero v + + let contains_zero loc = + try + let is_valid_offset base offset = + match base with + Base.Null -> + if Ival.contains_zero offset then raise Base.Not_valid_offset + | _ -> + let bits_offset = Ival.scale (Bit_utils.sizeofchar()) offset in + Base.is_valid_offset ~for_writing:false Int.zero base bits_offset + in + match loc with + | Location_Bytes.Top _ -> true + | Location_Bytes.Map m -> + Location_Bytes.M.iter is_valid_offset m; + false + with + | Int_Base.Error_Top | Int_Base.Error_Bottom + | Base.Not_valid_offset -> true + + let contains_non_zero v = + not ((equal v bottom) || (is_zero v)) + + let of_char c = inject_ival (Ival.of_int (Char.code c)) + + let of_int64 i = inject_ival (Ival.of_int64 i) + + let subdiv_float_interval ~size v = + try + let v_ival = project_ival v in + let ival1, ival2 = Ival.subdiv_float_interval ~size v_ival in + inject_ival ival1, inject_ival ival2 + with Not_based_on_null -> assert false + + let compare_bound ival_compare_bound l1 l2 = + try + let f1 = project_ival l1 in + let f2 = project_ival l2 in + ival_compare_bound f1 f2 + with Not_based_on_null -> assert false + + let compare_min_float = compare_bound Ival.compare_min_float + let compare_max_float = compare_bound Ival.compare_max_float + let compare_min_int = compare_bound Ival.compare_min_int + let compare_max_int = compare_bound Ival.compare_max_int + + let filter_comparison ival_filter e1 ~cond_expr = + let r = + match e1 with + | Top _ -> e1 + | Map m1 -> + try + let k,v2 = find_lonely_key cond_expr in + let v1 = find_or_bottom k m1 in + let r = Map (add_or_bottom k (ival_filter v1 v2) m1) in + if (not (Base.equal k Base.null)) && + (ival_filter == Ival.filter_ge || ival_filter == Ival.filter_gt) + then diff_if_one r singleton_zero + else r + with Not_found -> e1 + in +(* Format.printf "filter_comparison %a %a -> %a@." + pretty e1 pretty cond_expr pretty r; *) + r + + let filter_comparison_float float_filter e1 ~cond_expr = + try + let v1 = project_ival e1 in + let v2 = project_ival cond_expr in + inject_ival (float_filter v1 v2) + with Not_based_on_null -> e1 + + let filter_le e1 ~cond_expr = filter_comparison Ival.filter_le e1 ~cond_expr + let filter_ge e1 ~cond_expr = filter_comparison Ival.filter_ge e1 ~cond_expr + let filter_lt e1 ~cond_expr = filter_comparison Ival.filter_lt e1 ~cond_expr + let filter_gt e1 ~cond_expr = filter_comparison Ival.filter_gt e1 ~cond_expr + + let filter_le_float allmodes ~typ_loc e1 ~cond_expr = + filter_comparison_float + (Ival.filter_le_float allmodes ~typ_loc) + e1 + ~cond_expr + let filter_ge_float allmodes ~typ_loc e1 ~cond_expr = + filter_comparison_float + (Ival.filter_ge_float allmodes ~typ_loc) + e1 ~cond_expr + let filter_lt_float allmodes ~typ_loc e1 ~cond_expr = + filter_comparison_float + (Ival.filter_lt_float allmodes ~typ_loc) + e1 + ~cond_expr + let filter_gt_float allmodes ~typ_loc e1 ~cond_expr = + filter_comparison_float + (Ival.filter_gt_float allmodes ~typ_loc) + e1 + ~cond_expr + + let pretty fmt v = + (*Format.printf "@[HERE@.@]";*) + let pretty_org fmt org = + if not (Origin.is_top org) then + Format.fprintf fmt "@ @[(origin: %a)@]" Origin.pretty org + in + match v with + | Top (Top_Param.Top, a) -> + Format.fprintf fmt "{{ ANYTHING%a }}" + pretty_org a + | Top (t, a) -> + Format.fprintf fmt "{{ garbled mix of &%a%a }}" + Top_Param.pretty t + pretty_org a + | Map m -> + try + Ival.pretty fmt (project_ival v) + with + | Not_based_on_null -> + let print_binding fmt k v = + if Ival.equal Ival.singleton_zero v + then Format.fprintf fmt "@[&%a@]" Base.pretty k + else + Format.fprintf fmt "@[&%a +@ %a@]" + Base.pretty k Ival.pretty v + in + Pretty_utils.pp_iter + ~pre:"@[{{ " ~suf:" }}@]" ~sep:" ;@ " + (fun pp map -> M.iter (fun k v -> pp (k, v)) map) + (fun fmt (k, v) -> print_binding fmt k v) + fmt m + +(* Returns the list of non NULL Base.t that have a null offset in the map. + The boolean is true iff the result is exact. Otherwise it is + under-approximated. *) + let find_exact_base_without_offset v = match v with + | Top _ -> [],false + | Map m -> + let exact = ref true in + let result = ref [] in + let get_binding k v = + if Ival.equal Ival.singleton_zero v + then result := k::!result + else exact := false + in + M.iter get_binding m; + !result,!exact + + let inject_int (v:Int.t) = + inject_ival (Ival.inject_singleton v) + + let interp_boolean ~contains_zero ~contains_non_zero = + match contains_zero, contains_non_zero with + | true, true -> zero_or_one + | true, false -> singleton_zero + | false, true -> singleton_one + | false, false -> bottom + + let add v1 v2 = + try + Location_Bytes.location_shift (project_ival v1) v2 + with Not_based_on_null -> + try + Location_Bytes.location_shift (project_ival v2) v1 + with + Not_based_on_null -> + join + (topify_arith_origin v1) + (topify_arith_origin v2) + + (* compute [e1+factor*e2] using C semantic for +, i.e. + [ptr+v] is [add_untyped sizeof_in_octets( *ptr) ptr v] *) + let add_untyped factor e1 e2 = + try + if Int_Base.equal factor (Int_Base.minus_one) + then + (* Either e1 and e2 have the same base, and it's a substraction + of pointers, or e2 is really an integer *) + let b1, o1 = Location_Bytes.find_lonely_key e1 in + let b2, o2 = Location_Bytes.find_lonely_key e2 in + if Base.compare b1 b2 <> 0 then raise Not_found; + inject_ival (Ival.sub o1 o2) + else begin + if not (Int_Base.equal factor (Int_Base.one)) + then raise Not_found; (* cannot multiply a pointer *) + add e1 e2 + end + with Not_found -> + (* we end up here if the only way left to make this + addition is to convert e2 to an integer *) + try + let right = Ival.scale_int64base factor (project_ival e2) + in Location_Bytes.location_shift right e1 + with Not_based_on_null -> (* from [project_ival] *) + join (topify_arith_origin e1) (topify_arith_origin e2) + + let rec check_equal positive e1 e2 = + let one,zero = + if positive then Ival.singleton_one, Ival.singleton_zero else + Ival.singleton_zero, Ival.singleton_one + in + inject_ival + (if (equal e1 e2) && (cardinal_zero_or_one e1) + then one + else + if intersects e1 e2 + then Ival.zero_or_one + else zero) + + let compare_min_max min max = + match min, max with + | None,_ -> -1 + | _,None -> -1 + | Some min, Some max -> Int.compare min max + + let compare_max_min max min = + match max, min with + | None,_ -> 1 + | _,None -> 1 + | Some max, Some min -> Int.compare max min + + let do_le min1 max1 min2 max2 = + if compare_max_min max1 min2 <= 0 then singleton_one + else if compare_min_max min1 max2 > 0 then singleton_zero + else zero_or_one + + let do_ge min1 max1 min2 max2 = + do_le min2 max2 min1 max1 + + let do_lt min1 max1 min2 max2 = + if compare_max_min max1 min2 < 0 then singleton_one + else if compare_min_max min1 max2 >= 0 then singleton_zero + else zero_or_one + + let do_gt min1 max1 min2 max2 = + do_lt min2 max2 min1 max1 + + let comparisons _info ~signed f e1 e2 = + let r = + try + let k1,v1 = find_lonely_key e1 in + let k2,v2 = find_lonely_key e2 in + if not (Base.equal k1 k2) + then begin + if (not signed) + then begin + let e1_zero = equal e1 singleton_zero in + let e2_zero = equal e2 singleton_zero in + if (e1_zero && (f == do_le || f == do_lt)) + || (e2_zero && (f == do_ge || f == do_gt)) + then singleton_one + else if (e2_zero && (f == do_le || f == do_lt)) + || (e1_zero && (f == do_ge || f == do_gt)) + then singleton_zero + else zero_or_one + end + else zero_or_one + end + else Ival.compare_C f v1 v2 + with Not_found -> + zero_or_one + in +(* Format.printf "comparisons %a %a %a@." + pretty e1 pretty e2 pretty r; *) + r + + + let cast_float v = + try + let i = project_ival v in + let b, i = Ival.cast_float i in + false, b, inject_ival i + with + Not_based_on_null -> + true, true, topify_arith_origin v + + let cast ~with_alarms ~size ~signed expr = + try + let i = project_ival expr in + inject_ival (Ival.cast ~size ~signed ~value:i) + with + | Not_based_on_null -> + if Int.compare size (Int.of_int (Bit_utils.sizeofpointer ())) >= 0 + || (match expr with Top _ -> true | _ -> false) + then expr + else begin + if is_bottom expr || is_imprecise expr then expr + else begin + (match with_alarms.imprecision_tracing with + | Aignore -> () + | Acall f -> f () + | Alog _ -> + Kernel.warning ~once:true ~current:true + "casting address to a type smaller than sizeof(void*): \ +@[%a@]" + Location_Bytes.pretty expr); + topify_arith_origin expr + end + end + + let import_function ~topify_arith_origin ~with_alarms info f e1 e2 = + try + let v1 = project_ival e1 in + let v2 = project_ival e2 in + inject_ival (f v1 v2) + with Not_based_on_null -> + (match with_alarms.imprecision_tracing with + | Aignore -> () + | Acall f -> f () + | Alog _ -> + match e1,e2 with + | Map _, Map _ -> + Kernel.warning ~once:true ~current:true + "Operation %a %s %a incurs a loss of precision" + pretty e1 + info + pretty e2 + | _ -> ()); + join (topify_arith_origin e1) (topify_arith_origin e2) + + + let arithmetic_function = import_function ~topify_arith_origin + + let unary_arithmetic_function ~with_alarms info f e1 = + try + let v1 = project_ival e1 in + inject_ival (f v1) + with Not_based_on_null -> + (match with_alarms.imprecision_tracing with + | Aignore -> () + | Acall f -> f () + | Alog _ -> match e1 with + | Map _ -> + Kernel.warning ~once:true ~current:true + "Operation %s %a incurs a loss of precision" + info pretty e1 + | _ -> ()); + topify_arith_origin e1 + + let cast_float_to_int ~signed ~size v = + try + let v1 = project_ival v in + let alarm_use_as_float, alarm_overflow, r = + Ival.cast_float_to_int ~signed ~size v1 + in + alarm_use_as_float, alarm_overflow, inject_ival r + with Not_based_on_null -> + true, true, topify_arith_origin v + + let cast_int_to_float ~with_alarms rounding_mode v = + unary_arithmetic_function ~with_alarms "integer conversion to float" + (fun i -> + let ok, r = Ival.cast_int_to_float rounding_mode i in + if not ok then + Kernel.warning ~current:true ~once:true + "TODO: overflow in integer conversion to float"; + r) + v + + let div ~with_alarms e1 e2 = + if equal e2 singleton_one + then e1 + else begin + if (with_alarms.others <> Aignore) && contains_zero e2 then CilE.warn_div with_alarms; + arithmetic_function ~with_alarms "/" Ival.div e1 e2 + end + + let c_rem ~with_alarms e1 e2 = + if (with_alarms.others <> Aignore) && contains_zero e2 then CilE.warn_div with_alarms; + arithmetic_function ~with_alarms "%" Ival.c_rem e1 e2 + + (** Warn about overflow iff [size] is not [None]. Beware when calling + this function *) + let shift_left ~topify_arith_origin ~with_alarms ~size e1 e2 = + let default () = + begin + try + let size = Extlib.opt_map Int.of_int size in + import_function + ~topify_arith_origin + ~with_alarms + "<<" + (Ival.shift_left ~size) e1 e2 + with Not_found -> + join (topify_arith_origin e1) (topify_arith_origin e2) + end + in + match size with + | None -> default () + | Some size -> + let size_int = Int.of_int size in + let valid_range_rhs = + inject_ival + (Ival.inject_range + (Some Int.zero) + (Some (Int.pred size_int))) + in + let valid_range_lhs = + inject_ival + (Ival.inject_range + (Some Int.zero) + None) + in + if (with_alarms.others <> Aignore) + then begin + if not (is_included e2 valid_range_rhs) + then warn_shift with_alarms size; + if not (is_included e1 valid_range_lhs) + then warn_shift_left_positive with_alarms; + end; + if not ((intersects e2 valid_range_rhs) && + (intersects e1 valid_range_lhs)) + then bottom + else default () + + + let oper_on_values ~with_alarms info f v1 v2 = + arithmetic_function with_alarms info (Ival.apply_set f) v1 v2 + + + let shift_right ~with_alarms ~size e1 e2 = + let default () = + begin + try + let size = Extlib.opt_map Int.of_int size in + arithmetic_function ~with_alarms ">>" + (Ival.shift_right ~size) e1 e2 + with Not_found -> + join (topify_arith_origin e1) (topify_arith_origin e2) + end + in + match size with + | None -> default () + | Some size -> + let size_int = Int.of_int size in + let valid_range = + inject_ival (Ival.inject_range (Some Int.zero) + (Some (Int.pred size_int))) + in + if not (intersects e2 valid_range) then begin + warn_shift with_alarms size; + if with_alarms.others <> Aignore then + Kernel.warning ~once:true ~current:true + "invalid shift of %a-bit value by %a. \ +This path is assumed to be dead." + Int.pretty size_int + pretty e2; + bottom + end else begin + if (with_alarms.others <> Aignore) + && not (is_included e2 valid_range) + then warn_shift with_alarms size; + default () + end + + let bitwise_and ~signed ~size e1 e2 = + let bitwise_and_pointer_ival p _ival = + Location_Bytes.location_shift + (Ival.inject_top None (Some Int.zero) Int.zero Int.one) + p + in + try + let v1 = project_ival e1 in + try + let v2 = project_ival e2 in + let result = Ival.bitwise_and ~signed ~size v1 v2 + in + inject_ival result + with Not_based_on_null -> + bitwise_and_pointer_ival e2 v1 + with Not_based_on_null -> + try + let v2 = project_ival e2 in + bitwise_and_pointer_ival e1 v2 + with Not_based_on_null -> + join (topify_arith_origin e1) (topify_arith_origin e2) + + let bitwise_or ~topify_arith_origin ~size e1 e2 = + try + let v1 = project_ival e1 in + let v2 = project_ival e2 in + let result = Ival.bitwise_or ~size v1 v2 + in + inject_ival result + with Not_based_on_null -> + join (topify_arith_origin e1) (topify_arith_origin e2) + + let extract_bits ~start ~stop v = + try + let i = project_ival v in + false, inject_ival (Ival.extract_bits ~start ~stop i) + with + | Not_based_on_null -> + if is_imprecise v + then false, v + else true, topify_misaligned_read_origin v + + let big_endian_merge_bits ~conflate_bottom ~total_length ~length ~value ~offset acc = + if is_bottom acc || is_bottom value + then begin + if conflate_bottom + then + bottom + else + join + (topify_misaligned_read_origin acc) + (topify_misaligned_read_origin value) + end + else + let total_length_i = Int.of_int total_length in + assert (Int.le (Int.add length offset) total_length_i); + let result = + bitwise_or + ~topify_arith_origin:topify_misaligned_read_origin + ~size:total_length + (shift_left + ~topify_arith_origin:topify_misaligned_read_origin + ~with_alarms:warn_none_mode + ~size:(Some total_length) + value + (inject_ival (Ival.inject_singleton (Int.sub (Int.sub total_length_i offset) length)))) + acc + in +(* Format.printf "big_endian_merge_bits : total_length:%d length:%a value:%a offset:%a acc:%a GOT:%a@." + total_length + Int.pretty length + pretty value + Int.pretty offset + pretty acc + pretty result; *) + result + + let little_endian_merge_bits ~conflate_bottom ~total_length ~value + ~offset acc = + if is_bottom acc || is_bottom value + then begin + if conflate_bottom + then + bottom + else + join + (topify_misaligned_read_origin acc) + (topify_misaligned_read_origin value) + end + else + let result = + bitwise_or + ~topify_arith_origin:topify_misaligned_read_origin + ~size:total_length + (shift_left + ~topify_arith_origin:topify_misaligned_read_origin + ~with_alarms:warn_none_mode + ~size:(Some total_length) + value + (inject_ival (Ival.inject_singleton offset))) + acc + in + (*Format.printf "le merge_bits : total_length:%d value:%a offset:%a acc:%a GOT:%a@." + total_length pretty value Int.pretty offset pretty acc pretty result;*) + result + + let all_values ~size v = + (Kernel.Overflow.get ()) && + try + let i = project_ival v in + Ival.all_values ~size i + with Not_based_on_null -> false + + let anisotropic_cast ~size v = + if all_values ~size v then top_int else v + + let create_all_values ~modu ~signed ~size = + inject_ival (Ival.create_all_values ~modu ~signed ~size) + + let bitwise_or = bitwise_or ~topify_arith_origin + let shift_left = shift_left ~topify_arith_origin + + let has_sign_problems v = + not (is_included top_int v || is_included v top_float) + +end + +module V_Or_Uninitialized = struct + + type un_t = + | C_uninit_esc of V.t + | C_uninit_noesc of V.t + | C_init_esc of V.t + | C_init_noesc of V.t + + type tt = un_t + + let mask_init = 2 + let mask_noesc = 1 + + let is_initialized flags = (flags land mask_init) <> 0 + let is_noesc flags = (flags land mask_noesc) <> 0 + + let get_v = function + | C_uninit_esc v + | C_uninit_noesc v + | C_init_esc v + | C_init_noesc v -> v + + let get_flags : tt -> int = fun v -> Obj.tag (Obj.repr v) + + let create : int -> V.t -> tt = fun flags v -> + match flags with + | 0 -> C_uninit_esc v + | 1 -> C_uninit_noesc v + | 2 -> C_init_esc v + | 3 -> C_init_noesc v + | _ -> assert false + + let project x = get_v x + +(* let (==>) = (fun x y -> (not x) || y) *) + + type widen_hint = V.widen_hint + let widen wh t1 t2 = + create (get_flags t2) (V.widen wh (get_v t1) (get_v t2)) + + let equal t1 t2 = + (get_flags t1) = (get_flags t2) && + V.equal (get_v t1) (get_v t2) + + exception Error_Bottom + exception Error_Top + + let join t1 t2 = +(* + { + initialized = t1.initialized && t2.initialized; + no_escaping_adr = t1.no_escaping_adr && t2.no_escaping_adr; + v = V.join t1.v t2.v + } +*) + create + ((get_flags t1) land (get_flags t2)) + (V.join (get_v t1) (get_v t2)) + + let narrow t1 t2 = +(* {initialized = t1.initialized || t2.initialized; + no_escaping_adr = t1.no_escaping_adr || t2.no_escaping_adr; + v = V.narrow t1.v t2.v + } +*) + create + ((get_flags t1) lor (get_flags t2)) + (V.narrow (get_v t1) (get_v t2)) + + let link t1 t2 = + create + ((get_flags t1) land (get_flags t2)) + (V.link (get_v t1) (get_v t2)) + + let meet t1 t2 = + create + ((get_flags t1) lor (get_flags t2)) + (V.meet (get_v t1) (get_v t2)) + + let bottom = C_init_noesc V.bottom + let top = C_uninit_esc V.top + + let uninitialized = C_uninit_noesc V.bottom + let initialized v = C_init_noesc v + + let escaping_addr = C_init_esc V.bottom + + let is_included t1 t2 = +(* (t2.initialized ==> t1.initialized) && + (t2.no_escaping_adr ==> t1.no_escaping_adr) && + V.is_included t1.v t2.v +*) + let flags1 = get_flags t1 in + let flags2 = get_flags t2 in + (lnot flags2) lor flags1 = -1 && + V.is_included (get_v t1) (get_v t2) + + let is_included_exn t1 t2 = + if not (is_included t1 t2) + then raise Abstract_interp.Is_not_included + + let intersects _t1 _t2 = + assert false +(* + ((not t2.initialized) && (not t1.initialized)) || + ((not t2.no_escaping_adr) && (not t1.no_escaping_adr)) || + V.intersects t1.v t2.v +*) + + let pretty fmt t = + let flags = get_flags t in + let no_escaping_adr = is_noesc flags in + let initialized = is_initialized flags in + let v = get_v t in + if initialized && no_escaping_adr + then V.pretty fmt v + else if equal t uninitialized + then Format.fprintf fmt "UNINITIALIZED" + else if equal t escaping_addr + then Format.fprintf fmt "ESCAPINGADDR" + else if initialized && not no_escaping_adr + then Format.fprintf fmt "%a or ESCAPINGADDR" V.pretty v + else if (not initialized) && no_escaping_adr + then Format.fprintf fmt "%a or UNINITIALIZED" V.pretty v + else Format.fprintf fmt "%a or UNINITIALIZED or ESCAPINGADDR" V.pretty v + + let cardinal_zero_or_one t = + match t with + C_init_noesc v -> V.cardinal_zero_or_one v + | C_init_esc v | C_uninit_noesc v -> V.is_bottom v + | C_uninit_esc _ -> false + + let cardinal_less_than t b = + match t with + C_init_noesc v -> V.cardinal_less_than v b + | _ -> raise Abstract_interp.Not_less_than + + let tag t = (get_flags t) * 4513 + (V.tag (get_v t)) + + include Datatype.Make + (struct + type t = tt (* = | C_uninit_esc of V.t + | C_uninit_noesc of V.t + | C_init_esc of V.t + | C_init_noesc of V.t *) + let name = "Cvalue.V_Or_Uninitialized" + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum + [| [| V.packed_descr |]; + [| V.packed_descr |]; + [| V.packed_descr |]; + [| V.packed_descr |] |]) + let reprs = + List.fold_left + (fun acc v -> + List.fold_left + (fun acc v -> + List.fold_left + (fun acc v -> C_uninit_noesc v :: acc) + (C_uninit_esc v :: acc) + V.reprs) + (C_init_noesc v :: acc) + V.reprs) + (List.map (fun v -> C_init_esc v) V.reprs) + V.reprs + let hash = tag + let equal = equal + let compare = Datatype.undefined + let copy = Datatype.undefined + let rehash = Datatype.identity + let pretty = pretty + let internal_pretty_code = Datatype.undefined + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project + end) + + module Top_Param = V.Top_Param + + let is_isotropic t = V.is_isotropic (get_v t) + + let cast ~with_alarms ~size ~signed t = + create (get_flags t) (V.cast ~with_alarms ~size ~signed (get_v t)) + + let extract_bits ~start ~stop t = + let inform_extract_pointer_bits, v = + V.extract_bits ~start ~stop (get_v t) + in + inform_extract_pointer_bits, + create (get_flags t) v + + let little_endian_merge_bits ~conflate_bottom ~total_length ~value ~offset t = + create + ((get_flags t) land (get_flags value)) + (V.little_endian_merge_bits ~conflate_bottom + ~total_length ~value:(get_v value) ~offset + (get_v t)) + + let big_endian_merge_bits ~conflate_bottom ~total_length ~length ~value ~offset t = + create + ((get_flags t) land (get_flags value)) + (V.big_endian_merge_bits ~conflate_bottom + ~total_length ~length + ~value:(get_v value) + ~offset + (get_v t)) + + let topify_merge_origin t = + create + (get_flags t) + (V.topify_merge_origin (get_v t)) + + let topify_arith_origin t = + create + (get_flags t) + (V.topify_arith_origin (get_v t)) + + let topify_misaligned_read_origin t = + create + (get_flags t) + (V.topify_misaligned_read_origin (get_v t)) + + let topify_with_origin o t = + create + (get_flags t) + (V.topify_with_origin o (get_v t)) + + let anisotropic_cast ~size t = + create + (get_flags t) + (V.anisotropic_cast ~size (get_v t)) + + let inject_top_origin o t = + C_init_noesc (V.inject_top_origin o t) + + let under_topify t = + create + (get_flags t) + (V.under_topify (get_v t)) + + let of_char c = C_init_noesc (V.of_char c) + let of_int64 c = C_init_noesc (V.of_int64 c) + + let singleton_zero = C_init_noesc (V.singleton_zero) + + let unspecify_escaping_locals is_local t = + let flags = get_flags t in + let flags = flags land mask_init + (* clear noesc flag *) + in + let locals, v = + V.remove_escaping_locals is_local (get_v t) + in + locals, create flags v + + let change_initialized init v = match init, v with + | true, C_uninit_esc v -> C_init_esc v + | true, C_uninit_noesc v -> C_init_noesc v + | true, _ -> v + | false, C_init_esc v -> C_uninit_esc v + | false, C_init_noesc v -> C_uninit_noesc v + | false, _ -> v + + let pretty_c_assert prampamp lv s fmt v = + V.pretty_c_assert prampamp lv s fmt (get_v v) + +end + +module V_Offsetmap = Offsetmap.Make(V_Or_Uninitialized) + +(* +module R_V = +struct + include V +end + +module C_Offsetmap = Offsetmap.Make(R_V) +*) + +module V_Offsetmap_ext = V_Offsetmap +(*struct + type y = V_Offsetmap.y + type widen_hint = V_Offsetmap.widen_hint + type t = V_Offsetmap.t * V_Offsetmap.t + type tt = t + + let pretty fmt (o,c) = + V_Offsetmap.pretty fmt o + + let pretty_typ typ fmt (o,c) = + V_Offsetmap.pretty_typ typ fmt o + + let pretty_debug _ = assert false + + let equal (o1, c1) (o2, c2) = + V_Offsetmap.equal o1 o2 && C_Offsetmap.equal c1 c2 + + let empty = V_Offsetmap.empty, C_Offsetmap.empty + + let is_empty = equal empty + + module Datatype = + Project.Datatype.Register + (struct + type t = tt + let rehash = assert false + let copy _ = assert false (* TODO *) + let before_load () = () + let after_load () = assert false + let name = Project.Datatype.Name.extend "ext" V_Offsetmap.Datatype.name + let dependencies = [ V_Offsetmap.Datatype.self ] + end) +end*) + +module Partial_lmap = Lmap.Make_LOffset(V_Or_Uninitialized)(V_Offsetmap_ext) + +module Default_offsetmap = struct + + let initialized_var_table = Cil_datatype.Varinfo.Hashtbl.create 17 + + let create_initialized_var varinfo validity initinfo = + Cil_datatype.Varinfo.Hashtbl.add + initialized_var_table varinfo initinfo; + Base.create_initialized varinfo validity + + let default_offsetmap base = match base with + | Base.Initialized_Var (v,_) -> + (try Cil_datatype.Varinfo.Hashtbl.find initialized_var_table v + with Not_found -> + V_Offsetmap.empty) + | Base.Var _ -> + begin + match Base.validity base with + Base.All -> + let upb = Bit_utils.max_bit_address () in + V_Offsetmap.add_internal + (Int.zero, upb) + (Int.zero, Int.one, V_Or_Uninitialized.uninitialized) + V_Offsetmap.empty + | Base.Known (mn, mx) | Base.Unknown (mn, mx) -> + if Int.ge mx mn + then + V_Offsetmap.add_internal + (mn, mx) + (Int.zero, Int.one, V_Or_Uninitialized.uninitialized) + V_Offsetmap.empty + else + V_Offsetmap.empty + | Base.Periodic (mn, mx, p) -> + assert (Int.is_zero mn); + let upb = Int.pred p in + assert (Int.ge mx upb); + V_Offsetmap.add_internal + (Int.zero, upb) + (Int.zero, Int.one, V_Or_Uninitialized.bottom) + V_Offsetmap.empty + end + | Base.Null -> V_Offsetmap.empty + | Base.String (_,e) -> V_Offsetmap.from_cstring (Base.get_string e) +end + +module Model = struct + + include Partial_lmap.Make(Default_offsetmap) + type y = V.t + + let join x y = snd (join x y) + + let reduce_equality state _l _r = state + + let pretty_c_assert fmt m = + Format.fprintf fmt "@["; + (match m with + Bottom -> Format.fprintf fmt "0" + | Map m -> + let first = ref true in + let print_ampamp () = + if !first + then + first := false + else + Format.fprintf fmt "@\n&& "; + in + LBase.iter + (fun base offs -> + match base with + Base.Var(v,_) -> + let typ = unrollType v.Cil_types.vtype in + let name = v.Cil_types.vname in + V_Offsetmap.pretty_c_assert_typ name typ print_ampamp fmt offs + | _ -> ()) + m + | Top -> Format.fprintf fmt "1"); + Format.fprintf fmt "@]" + + let find_unspecified = find ~conflate_bottom:false + + let find ~conflate_bottom ~with_alarms x y = + let v = find ~conflate_bottom ~with_alarms x y in + let v_v = V_Or_Uninitialized.get_v v in + let bottom = V.is_bottom v_v in + let flags = V_Or_Uninitialized.get_flags v in + + (* distasteful FIXME *) if conflate_bottom then begin + if not (V_Or_Uninitialized.is_initialized flags) + then warn_uninitialized with_alarms; + if not (V_Or_Uninitialized.is_noesc flags) + then warn_escapingaddr with_alarms; + end; + + if with_alarms.unspecified <> Aignore && + bottom && + not (V_Or_Uninitialized.is_initialized flags && + V_Or_Uninitialized.is_noesc flags ) + then begin + match with_alarms.unspecified with + | Aignore -> assert false + | Acall f -> f () + | Alog _ -> + Kernel.warning ~current:true ~once:true + "completely undefined value in %a." + Locations.pretty y; + end; + v_v + + let has_been_initialized base state = + try + let o = find_base base state in + V_Offsetmap.is o V_Or_Uninitialized.uninitialized + with Not_found -> true + + let add_binding_not_initialized acc loc = + add_binding ~with_alarms:warn_none_mode ~exact:true acc loc (V_Or_Uninitialized.uninitialized) + + let add_binding_unspecified acc loc v = + add_binding ~with_alarms:warn_none_mode ~exact:true acc loc v + + let add_binding ~with_alarms ~exact acc loc value = + add_binding ~with_alarms ~exact acc loc (V_Or_Uninitialized.initialized value) + + let reduce_binding ~with_alarms acc loc value = + reduce_binding ~with_alarms acc loc (V_Or_Uninitialized.initialized value) + + let create_initial ~base ~v ~modu ~state = + create_initial ~base ~v:(V_Or_Uninitialized.initialized v) ~modu ~state + + let uninitialize_locals blocks state = + List.fold_left + (fun acc block -> + List.fold_left + (fun acc vi -> + let base = Base.create_varinfo vi in + remove_base base acc) + acc + block.Cil_types.blocals) + state + blocks + + let clear_state_from_locals fundec state = + let locals = List.map Base.create_varinfo fundec.Cil_types.slocals in + let formals = List.map Base.create_varinfo fundec.Cil_types.sformals in + let cleanup acc v = remove_base v acc in + let result = List.fold_left cleanup state locals in + List.fold_left cleanup result formals + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/cvalue.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/cvalue.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/cvalue.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/cvalue.mli 2011-10-10 08:38:30.000000000 +0000 @@ -0,0 +1,373 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + +open Abstract_interp +open Locations + +module V : + sig + module M : + sig + type key = Base.t + type leaf_annot = Location_Bytes.M.leaf_annot + type branch_annot = Location_Bytes.M.branch_annot + type tt = Location_Bytes.M.tt = private + | Empty + | Leaf of key * Ival.t * leaf_annot + | Branch of int * int * tt * tt * branch_annot + type t = tt + val iter : (Base.t -> Ival.t -> unit) -> t -> unit + val find : key -> t -> Ival.t + val fold : (Base.t -> Ival.t -> 'a -> 'a) -> t -> 'a -> 'a + end + module Top_Param : Lattice_Set + with type O.elt = Base.t + and type O.t = Location_Bytes.Top_Param.O.t + type z = + Location_Bytes.z = + | Top of Location_Bytes.Top_Param.t * Origin.t + | Map of M.t + exception Error_Top + exception Error_Bottom + + include Lattice + with type t = z + and type widen_hint = + Location_Bytes.Top_Param.widen_hint * (Base.t -> Ival.widen_hint) + val top_float : t + val top_single_precision_float : t + val is_zero : t -> bool + val hash : t -> int + val zero_or_one : t + val singleton_zero : t + val singleton_one : t + val topify_arith_origin : t -> t + val topify_misaligned_read_origin : t -> t + val topify_merge_origin : t -> t + val under_topify : t -> t + val top_int : t + val find_or_bottom : Base.t -> M.t -> Ival.t + val add_or_bottom : Base.t -> Ival.t -> M.t -> M.t + val inject : Base.t -> Ival.t -> t + val inject_ival : Ival.t -> t + val inject_top_origin : Origin.t -> Location_Bytes.Top_Param.O.t -> t + val fold_enum : split_non_enumerable:int -> (t -> 'a -> 'a) -> t -> 'a -> 'a + val splitting_cardinal_less_than : + split_non_enumerable:int -> t -> int -> int + val cardinal_zero_or_one : t -> bool + val cardinal_less_than : t -> int -> int + val find_exclusive : Base.t -> t -> Ival.t + val split : Base.t -> t -> Ival.t * t + exception Not_all_keys + val get_keys_exclusive : Ival.t -> t -> Base.t list + val find_lonely_binding : t -> Base.t * Ival.t + val find_lonely_key : t -> Base.t * Ival.t + val diff : t -> t -> t + val diff_if_one : t -> t -> t + val location_shift : Ival.t -> t -> t + val fold_i : (Base.t -> Ival.t -> 'a -> 'a) -> t -> 'a -> 'a + val fold_bases : (Base.t -> 'a -> 'a) -> t -> 'a -> 'a + val top_leaf_origin : unit -> t + val topify_with_origin : Origin.t -> t -> t + val may_reach : Base.t -> t -> bool + val cached_fold : + cache:string * int -> + temporary:bool -> + f:(Base.t -> Ival.t -> 'a) -> + projection:(Base.t -> Ival.t) -> + joiner:('a -> 'a -> 'a) -> empty:'a -> t -> 'a + val contains_addresses_of_locals : (M.key -> bool) -> t -> bool + val remove_escaping_locals : + (M.key -> bool) -> t -> Location_Bytes.Top_Param.t * t + val contains_addresses_of_any_locals : t -> bool + val iter_on_strings : + skip:Base.t option -> + (Base.t -> string -> int -> int -> unit) -> t -> unit + exception Not_based_on_null + val project_ival : t -> Ival.t + val types : + (int, + (t * string * + (Format.formatter -> (unit -> unit) -> string -> string -> t -> unit)) + list) + Hashtbl.t + val pretty_int_range : + Format.formatter -> (unit -> 'a) -> string -> string -> t -> unit + val pretty_float_range : + Format.formatter -> (unit -> 'a) -> string -> string -> t -> unit + val pretty_c_assert : + (unit -> unit) -> string -> int -> Format.formatter -> t -> unit + val force_float : Cil_types.fkind -> t -> bool * t + val is_imprecise : z -> bool + val is_topint : t -> bool + val is_bottom : t -> bool + val is_isotropic : z -> bool + val contains_zero : Location_Bytes.z -> bool + val contains_non_zero : t -> bool + val of_char : char -> t + val subdiv_float_interval : size:int -> t -> t * t + val compare_bound : (Ival.t -> Ival.t -> 'a) -> t -> t -> 'a + val compare_min_float : t -> t -> int + val compare_max_float : t -> t -> int + val compare_min_int : t -> t -> int + val compare_max_int : t -> t -> int + val filter_comparison : + (Ival.t -> Ival.t -> Ival.t) -> z -> cond_expr:t -> z + val filter_comparison_float : + (Ival.t -> Ival.t -> Ival.t) -> t -> cond_expr:t -> t + val filter_le : z -> cond_expr:t -> z + val filter_ge : z -> cond_expr:t -> z + val filter_lt : z -> cond_expr:t -> z + val filter_gt : z -> cond_expr:t -> z + val filter_le_float : + bool -> typ_loc:Cil_types.typ -> t -> cond_expr:t -> t + val filter_ge_float : + bool -> typ_loc:Cil_types.typ -> t -> cond_expr:t -> t + val filter_lt_float : + bool -> typ_loc:Cil_types.typ -> t -> cond_expr:t -> t + val filter_gt_float : + bool -> typ_loc:Cil_types.typ -> t -> cond_expr:t -> t + val pretty : Format.formatter -> z -> unit + val find_exact_base_without_offset : z -> Base.t list * bool + val inject_int : Int.t -> t + val interp_boolean : contains_zero:bool -> contains_non_zero:bool -> t + val add : t -> Location_Bytes.t -> Location_Bytes.t + val add_untyped : + Int_Base.t -> + Location_Bytes.t -> Location_Bytes.t -> t + val check_equal : bool -> t -> t -> t + val compare_min_max : + Int.t option -> Int.t option -> int + val compare_max_min : + Int.t option -> Int.t option -> int + val do_le: Int.t option -> Int.t option -> Int.t option -> Int.t option -> t + val do_ge: Int.t option -> Int.t option -> Int.t option -> Int.t option -> t + val do_lt: Int.t option -> Int.t option -> Int.t option -> Int.t option -> t + val do_gt: Int.t option -> Int.t option -> Int.t option -> Int.t option -> t + val comparisons: + string -> + signed:bool -> + (Int.t option -> Int.t option -> Int.t option -> Int.t option -> t) -> + t -> t -> t + val cast_float : t -> bool * bool * t + val cast : + with_alarms:CilE.warn_mode -> + size:Int.t -> signed:bool -> t -> t + val import_function : + topify_arith_origin:(t -> t) -> + with_alarms:CilE.warn_mode -> + string -> (Ival.t -> Ival.t -> Ival.t) -> t -> t -> t + val arithmetic_function : + with_alarms:CilE.warn_mode -> + string -> (Ival.t -> Ival.t -> Ival.t) -> t -> t -> t + val unary_arithmetic_function : + with_alarms:CilE.warn_mode -> string -> (Ival.t -> Ival.t) -> t -> t + val cast_float_to_int : signed:bool -> size:int -> t -> bool * bool * t + val cast_int_to_float : + with_alarms:CilE.warn_mode -> + Ival.Float_abstract.rounding_mode -> t -> t + val div : with_alarms:CilE.warn_mode -> t -> t -> t + val c_rem : with_alarms:CilE.warn_mode -> t -> t -> t + val oper_on_values : + with_alarms:CilE.warn_mode -> + string -> + (Int.t -> + Int.t -> Int.t ) -> + t -> t -> t + val shift_right : + with_alarms:CilE.warn_mode -> size:int option -> t -> z -> t + val bitwise_and : signed:bool -> size:int -> t -> t -> t + val extract_bits : + start:Int.t -> + stop:Int.t -> t -> bool * t + val big_endian_merge_bits : + conflate_bottom:bool -> + total_length:int -> + length:My_bigint.t -> value:t -> offset:My_bigint.t -> t -> t + val little_endian_merge_bits : + conflate_bottom:bool -> + total_length:int -> value:t -> offset:Int.t -> t -> t + val all_values : size:Int.t -> t -> bool + val anisotropic_cast : size:Int.t -> t -> t + val create_all_values : + modu:Int.t -> signed:bool -> size:int -> t + val bitwise_or : size:int -> t -> t -> t + val shift_left : + with_alarms:CilE.warn_mode -> size:int option -> z -> z -> t + val has_sign_problems : t -> bool + end + + +module V_Or_Uninitialized : + sig + type un_t = + C_uninit_esc of V.t + | C_uninit_noesc of V.t + | C_init_esc of V.t + | C_init_noesc of V.t + include Lattice_With_Isotropy.S with type t = un_t + and + type widen_hint = Locations.Location_Bytes.widen_hint + + val initialized : V.t -> un_t + val change_initialized : bool -> un_t -> un_t + val get_v : un_t -> V.t + val get_flags : un_t -> int + val unspecify_escaping_locals : + (V.M.key -> bool) -> un_t -> Location_Bytes.Top_Param.t * un_t + val is_initialized : int -> bool + val is_noesc : int -> bool + end + +module V_Offsetmap: + Offsetmap.S with type y = V_Or_Uninitialized.t + and type widen_hint = V_Or_Uninitialized.widen_hint + and type t = Offsetmap.Make(V_Or_Uninitialized).t + +module V_Offsetmap_ext: + Offsetmap.S with type y = V_Or_Uninitialized.t + and type widen_hint = V_Or_Uninitialized.widen_hint + and type t = Offsetmap.Make(V_Or_Uninitialized).t + +(* +module Partial_lmap : Lmap.Location_map + with type y = V_Or_Uninitialized.t + and type widen_hint_offsetmap = V_Or_Uninitialized.widen_hint + and type loffset = V_Offsetmap_ext.t + and module Make = Lmap.Make_LOffset(V_Or_Uninitialized)(V_Offsetmap_ext).Make +*) + +module Default_offsetmap : + sig + val initialized_var_table : V_Offsetmap.t Cil_datatype.Varinfo.Hashtbl.t + val create_initialized_var : + Cil_datatype.Varinfo.Hashtbl.key -> + Base.validity -> V_Offsetmap.t -> Base.t + val default_offsetmap : Base.t -> V_Offsetmap.t + end + +module Model : + sig + module LBase : + sig + type t (* = Lmap.Make_LOffset(V_Or_Uninitialized)(V_Offsetmap_ext).Make(Default_offsetmap).LBase.t *) + val iter : (Base.base -> V_Offsetmap_ext.t -> unit) -> t -> unit + end + type tt = (* Partial_lmap.Make(Default_offsetmap).tt = *) private + | Bottom + | Top + | Map of LBase.t + include Datatype.S with type t = tt + type widen_hint = + bool * Base.Set.t * (Base.t -> V_Or_Uninitialized.widen_hint) + val inject : Base.t -> V_Offsetmap_ext.t -> t + val add_offsetmap : Base.t -> V_Offsetmap_ext.t -> t -> t + val pretty_without_null : Format.formatter -> t -> unit + val pretty_filter : + Format.formatter -> t -> Zone.t -> (Base.t -> bool) -> unit + val is_included : t -> t -> bool + val top : t + val is_top : t -> bool + val empty_map : t + val is_empty_map : t -> bool + val bottom : t + val is_reachable : t -> bool + val widen : widen_hint -> t -> t -> bool * t + val filter_base : (Base.t -> bool) -> t -> t + val find_base : Base.t -> t -> V_Offsetmap_ext.t + val remove_base : Base.t -> t -> t + val copy_paste : + with_alarms:CilE.warn_mode -> location -> location -> t -> t + val paste_offsetmap : + with_alarms:CilE.warn_mode -> + from:V_Offsetmap_ext.t -> + dst_loc:Location_Bits.t -> + start:Int.t -> + size:Int.t -> exact:bool -> t -> t + val copy_offsetmap : + with_alarms:CilE.warn_mode -> + location -> t -> V_Offsetmap_ext.t option + val is_included_by_location_enum : t -> t -> Zone.t -> bool + val fold : + size:Int.t -> + (location -> V_Or_Uninitialized.t -> 'a -> 'a) -> t -> 'a -> 'a + val fold_single_bindings : + size:Int.t -> + (location -> V_Or_Uninitialized.t -> 'a -> 'a) -> t -> 'a -> 'a + val fold_base : (Base.t -> 'a -> 'a) -> t -> 'a -> 'a + val fold_base_offsetmap : + (Base.t -> V_Offsetmap_ext.t -> 'a -> 'a) -> t -> 'a -> 'a + val find_offsetmap_for_location : + Location_Bits.t -> t -> V_Offsetmap_ext.t + val add_whole : location -> V_Or_Uninitialized.t -> t -> t + val remove_whole : location -> t -> t + val comp_prefixes : t -> t -> unit + type subtree (* = + Lmap.Make_LOffset(V_Or_Uninitialized)(V_Offsetmap_ext).Make(Default_offsetmap).subtree *) + val find_prefix : t -> Hptmap.prefix -> subtree option + val hash_subtree : subtree -> int + val equal_subtree : subtree -> subtree -> bool + val reciprocal_image : + Base.t -> t -> Zone.t * Location_Bits.t + exception Error_Bottom + val cached_fold : + f:(Base.t -> V_Offsetmap_ext.t -> 'a) -> + cache:string * int -> + temporary:bool -> joiner:('a -> 'a -> 'a) -> empty:'a -> t -> 'a + val cached_map : + f:(Base.t -> V_Offsetmap_ext.t -> V_Offsetmap_ext.t) -> + cache:string * int -> temporary:bool -> t -> t + exception Found_prefix of Hptmap.prefix * subtree * subtree + type y = V.t + val join : t -> t -> t + val reduce_equality : t -> location -> location -> t + val pretty_c_assert : Format.formatter -> t -> unit + val find_unspecified : + with_alarms:CilE.warn_mode -> t -> location -> V_Or_Uninitialized.t + val find : + conflate_bottom:bool -> + with_alarms:CilE.warn_mode -> t -> location -> V.t + val has_been_initialized : Base.t -> t -> bool + val add_binding_not_initialized : t -> location -> t + val add_binding_unspecified : + t -> location -> V_Or_Uninitialized.t -> t + val add_binding : + with_alarms:CilE.warn_mode -> + exact:bool -> t -> location -> V.t -> t + val reduce_binding : + with_alarms:CilE.warn_mode -> t -> location -> V.t -> t + val create_initial : + base:Base.t -> v:V.t -> modu:Int.t -> state:t -> t + val uninitialize_locals : Cil_types.block list -> t -> t + val clear_state_from_locals : Cil_types.fundec -> t -> t + end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/cvalue_type.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/cvalue_type.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/cvalue_type.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/cvalue_type.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,1026 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(* types of values *) -open Cil -open Abstract_interp -open Abstract_value -open Locations -open CilE - -module V = struct - - include Location_Bytes - - let pretty_c_assert _lv _s _fmt _v = () - - let project x = x - - let is_imprecise v = - match v with - | Top _ -> true - | _ -> false - - let is_topint v = - let r = equal top_int v in -(* Format.printf "v=%x (%a); top_int=%x (%a)@." - (Extlib.address_of_value v) pretty v - (Extlib.address_of_value top_int) pretty top_int;*) - assert - (match v with - | Map(M.Leaf(Base.Null, Ival.Top(None, None, re, m), _)) - when Int.is_zero re && Int.equal Int.one m -> r - | _ -> not r); - r - - let is_bottom v = - let r = equal bottom v in - assert (match v with Map M.Empty -> r | _ -> not r); - r - - let is_isotropic v = - match v with - | Top _ -> true - | Map _ -> is_topint v || is_bottom v || is_zero v - - let contains_zero loc = - try - let is_valid_offset base offset = - match base with - Base.Null -> - if Ival.contains_zero offset then raise Base.Not_valid_offset - | _ -> - let bits_offset = Ival.scale (Bit_utils.sizeofchar()) offset in - Base.is_valid_offset Int.zero base bits_offset - in - match loc with - | Location_Bytes.Top _ -> true - | Location_Bytes.Map m -> - Location_Bytes.M.iter is_valid_offset m; - false - with - | Int_Base.Error_Top | Int_Base.Error_Bottom - | Base.Not_valid_offset -> true - - let contains_non_zero v = - not ((equal v bottom) || (is_zero v)) - - let of_char c = inject_ival (Ival.of_int (Char.code c)) - - exception Not_based_on_null - - let project_ival m = - try - let k, v = find_lonely_key m in - if not (Base.is_null k) - then raise Not_based_on_null - else v - with Not_found -> raise Not_based_on_null - - let subdiv_float_interval v = - try - let v_ival = project_ival v in - let ival1, ival2 = Ival.subdiv_float_interval v_ival in - inject_ival ival1, inject_ival ival2 - with Not_based_on_null -> assert false - - let compare_bound ival_compare_bound l1 l2 = - try - let f1 = project_ival l1 in - let f2 = project_ival l2 in - ival_compare_bound f1 f2 - with Not_based_on_null -> assert false - - let compare_min_float = compare_bound Ival.compare_min_float - let compare_max_float = compare_bound Ival.compare_max_float - let compare_min_int = compare_bound Ival.compare_min_int - let compare_max_int = compare_bound Ival.compare_max_int - - let filter_comparison ival_filter e1 ~cond_expr = - match e1 with - | Top _ -> e1 - | Map m1 -> - try - let k,v2 = find_lonely_key cond_expr in - let v1 = find_or_bottom k m1 in - Map (add_or_bottom k (ival_filter v1 v2) m1) - with Not_found -> e1 - - let filter_comparison_float float_filter e1 ~cond_expr = - try - let v1 = project_ival e1 in - let v2 = project_ival cond_expr in - inject_ival (float_filter v1 v2) - with Not_based_on_null -> e1 - - let filter_le e1 ~cond_expr = filter_comparison Ival.filter_le e1 ~cond_expr - let filter_ge e1 ~cond_expr = filter_comparison Ival.filter_ge e1 ~cond_expr - let filter_lt e1 ~cond_expr = filter_comparison Ival.filter_lt e1 ~cond_expr - let filter_gt e1 ~cond_expr = filter_comparison Ival.filter_gt e1 ~cond_expr - - let filter_le_float e1 ~cond_expr = - filter_comparison_float Ival.filter_le_float e1 ~cond_expr - let filter_ge_float e1 ~cond_expr = - filter_comparison_float Ival.filter_ge_float e1 ~cond_expr - let filter_lt_float allmodes ~typ_loc e1 ~cond_expr = - filter_comparison_float - (Ival.filter_lt_float allmodes ~typ_loc) - e1 - ~cond_expr - let filter_gt_float allmodes ~typ_loc e1 ~cond_expr = - filter_comparison_float - (Ival.filter_gt_float allmodes ~typ_loc) - e1 - ~cond_expr - - let pretty fmt v = - (*Format.printf "@[HERE@.@]";*) - let pretty_org fmt org = - if not (Origin.is_top org) then - Format.fprintf fmt " (origin: %a)" Origin.pretty org - in - match v with - | Top (Top_Param.Top, a) -> - Format.fprintf fmt "{{ ANYTHING%a }}" - pretty_org a - | Top (t, a) -> - Format.fprintf fmt "{{ garbled mix of &%a%a }}" - Top_Param.pretty t - pretty_org a - | Map m -> - try - Ival.pretty fmt (project_ival v) - with - | Not_based_on_null -> - let print_binding k v = - if Ival.equal Ival.singleton_zero v - then Format.fprintf fmt " &%a ;" Base.pretty k - else - Format.fprintf fmt " &%a + %a ;" - Base.pretty k Ival.pretty v - in - Format.fprintf fmt "{{"; - (M.iter print_binding) m; - Format.fprintf fmt "}}" - -(* Returns the list of non NULL Base.t that have a null offset in the map. - The boolean is true iff the result is exact. Otherwise it is - under-approximated. *) - let find_exact_base_without_offset v = match v with - | Top _ -> [],false - | Map m -> - let exact = ref true in - let result = ref [] in - let get_binding k v = - if Ival.equal Ival.singleton_zero v - then result := k::!result - else exact := false - in - M.iter get_binding m; - !result,!exact - - let inject_int (v:Int.t) = - inject_ival (Ival.inject_singleton v) - - let interp_boolean ~contains_zero ~contains_non_zero = - match contains_zero, contains_non_zero with - | true, true -> zero_or_one - | true, false -> singleton_zero - | false, true -> singleton_one - | false, false -> bottom - - let add v1 v2 = - try - Location_Bytes.location_shift (project_ival v1) v2 - with Not_based_on_null -> - try - Location_Bytes.location_shift (project_ival v2) v1 - with - Not_based_on_null -> - join - (topify_arith_origin v1) - (topify_arith_origin v2) - - (* compute [e1+factor*e2] using C semantic for +, i.e. - [ptr+v] is [add_untyped sizeof_in_octets( *ptr) ptr v] *) - let add_untyped factor e1 e2 = - try - if Int_Base.equal factor (Int_Base.minus_one) - then - (* Either e1 and e2 have the same base, and it's a substraction - of pointers, or e2 is really an integer *) - let b1, o1 = Location_Bytes.find_lonely_key e1 in - let b2, o2 = Location_Bytes.find_lonely_key e2 in - if Base.compare b1 b2 <> 0 then raise Not_found; - inject_ival (Ival.sub o1 o2) - else begin - if not (Int_Base.equal factor (Int_Base.one)) - then raise Not_found; (* cannot multiply a pointer *) - add e1 e2 - end - with Not_found -> - (* we end up here if the only way left to make this - addition is to convert e2 to an integer *) - try - let right = Ival.scale_int64base factor (project_ival e2) - in Location_Bytes.location_shift right e1 - with Not_based_on_null -> (* from [project_ival] *) - join (topify_arith_origin e1) (topify_arith_origin e2) - - let rec check_equal positive e1 e2 = - let one,zero = - if positive then Ival.singleton_one, Ival.singleton_zero else - Ival.singleton_zero, Ival.singleton_one - in - let result = inject_ival - (if cardinal_zero_or_one e1 && - cardinal_zero_or_one e2 && - (equal e1 e2) - then one - else - if intersects e1 e2 - (* [intersects] gives an exact answer *) - then Ival.zero_or_one - else zero) - in - (* Format.printf "check_equal: positive:%b e1=%a e2=%a result=%a@\n" - positive - pretty e1 - pretty e2 - pretty result - ;*) - result - - let compare_min_max min max = - match min,max with - | None,_ -> -1 - | _,None -> -1 - | Some min, Some max -> Int.compare min max - - let compare_max_min max min = - match max,min with - | None,_ -> 1 - | _,None -> 1 - | Some max, Some min -> Int.compare max min - - let do_le min1 max1 min2 max2 = - if compare_max_min max1 min2 <= 0 then singleton_one - else if compare_min_max min1 max2 > 0 then singleton_zero - else zero_or_one - - let do_ge min1 max1 min2 max2 = - do_le min2 max2 min1 max1 - - let do_lt min1 max1 min2 max2 = - if compare_max_min max1 min2 < 0 then singleton_one - else if compare_min_max min1 max2 >= 0 then singleton_zero - else zero_or_one - - let do_gt min1 max1 min2 max2 = - do_lt min2 max2 min1 max1 - - let comparisons _info f e1 e2 = - try - let k1,v1 = find_lonely_key e1 in - let k2,v2 = find_lonely_key e2 in - if Base.compare k1 k2 <> 0 - then zero_or_one - else Ival.compare_C f v1 v2 - with Not_found -> - zero_or_one - - let cast_float v = - try - let i = project_ival v in - let b, i = Ival.cast_float i in - false, b, inject_ival i - with - Not_based_on_null -> - true, true, topify_arith_origin v - - let cast ~with_alarms ~size ~signed expr = - try - let i = project_ival expr in - inject_ival (Ival.cast ~size ~signed ~value:i) - with - | Not_based_on_null -> - if Int.compare size (Int.of_int (Bit_utils.sizeofpointer ())) >= 0 - || (match expr with Top _ -> true | _ -> false) - then expr - else begin - if is_bottom expr || is_imprecise expr then expr - else begin - (match with_alarms.imprecision_tracing with - | Aignore -> () - | Acall f -> f () - | Alog -> CilE.warn_once - "casting address to a type smaller than sizeof(void*): @[%a@]" - Location_Bytes.pretty expr); - topify_arith_origin expr - end - end - - let import_function ~topify_arith_origin ~with_alarms info f e1 e2 = - try - let v1 = project_ival e1 in - let v2 = project_ival e2 in - inject_ival (f v1 v2) - with Not_based_on_null -> - (match with_alarms.imprecision_tracing with - | Aignore -> () - | Acall f -> f () - | Alog -> - match e1,e2 with - | Map _, Map _ -> - CilE.warn_once "Operation %a %s %a incurs a loss of precision" - pretty e1 - info - pretty e2 - | _ -> ()); - join (topify_arith_origin e1) (topify_arith_origin e2) - - - let arithmetic_function = import_function ~topify_arith_origin - - let unary_arithmetic_function ~with_alarms info f e1 = - try - let v1 = project_ival e1 in - inject_ival (f v1) - with Not_based_on_null -> - (match with_alarms.imprecision_tracing with - | Aignore -> () - | Acall f -> f () - | Alog -> match e1 with - | Map _ -> - warn_once "Operation %s %a incurs a loss of precision" - info pretty e1 - | _ -> ()); - topify_arith_origin e1 - - let cast_float_to_int ~signed ~size v = - try - let v1 = project_ival v in - let alarm_use_as_float, alarm_overflow, r = - Ival.cast_float_to_int ~signed ~size v1 - in - alarm_use_as_float, alarm_overflow, inject_ival r - with Not_based_on_null -> - true, true, topify_arith_origin v - - let cast_int_to_float ~with_alarms rounding_mode v = - unary_arithmetic_function ~with_alarms "integer conversion to float" - (fun i -> - let ok, r = Ival.cast_int_to_float rounding_mode i in - if not ok then warn_once "TODO: overflow in integer conversion to float"; - r) - v - - let div ~with_alarms e1 e2 = - if equal e2 singleton_one - then e1 - else begin - if (with_alarms.others <> Aignore) && contains_zero e2 then CilE.warn_div with_alarms; - arithmetic_function ~with_alarms "/" Ival.div e1 e2 - end - - let c_rem ~with_alarms e1 e2 = - if (with_alarms.others <> Aignore) && contains_zero e2 then CilE.warn_div with_alarms; - arithmetic_function ~with_alarms "%" Ival.c_rem e1 e2 - - let shift_left ~topify_arith_origin ~with_alarms ~size e1 e2 = - let size_int = Int.of_int size in - let valid_range = - inject_ival (Ival.inject_range (Some Int.zero) (Some (Int.pred size_int))) - in - if not (intersects e2 valid_range) then begin - (warn_shift with_alarms size; - if (with_alarms.others <> Aignore) then warn_once - "invalid shift of %a-bit value by %a. This path is assumed to be dead." - Int.pretty size_int - pretty e2); - bottom - end else - match e2 with - | Top _ -> - warn_shift with_alarms size; - join (topify_arith_origin e1) (topify_arith_origin e2) - | Map m -> - begin - if (with_alarms.others <> Aignore) - && not (is_included e2 valid_range) - then warn_shift with_alarms size; - try - let e2 = inject_ival (M.find Base.null m) in - import_function - ~topify_arith_origin - ~with_alarms - "<<" - (Ival.shift_left ~size:size_int) e1 e2 - with Not_found -> - join (topify_arith_origin e1) (topify_arith_origin e2) - end - - let oper_on_values ~with_alarms info f v1 v2 = - arithmetic_function with_alarms info (Ival.apply_set info f) v1 v2 - - let shift_right ~with_alarms ~size ~signed:_ e1 e2 = - let size_int = Int.of_int size in - let valid_range = - inject_ival (Ival.inject_range (Some Int.zero) (Some (Int.pred size_int))) - in - if not (intersects e2 valid_range) then begin - (warn_shift with_alarms size; - if (with_alarms.others <> Aignore) then - warn_once - "invalid shift of %a-bit value by %a. This path is assumed to be dead." - Int.pretty size_int - pretty e2); - bottom - end else - match e2 with - | Top _ -> warn_shift with_alarms size; - join (topify_arith_origin e1) (topify_arith_origin e2) - | Map m -> - begin - if (with_alarms.others <> Aignore) - && not (is_included e2 valid_range) - then CilE.warn_shift with_alarms size; - try - let e2 = inject_ival (M.find Base.null m) in - arithmetic_function ~with_alarms ">>" - (Ival.shift_right ~size:size_int) e1 e2 - with Not_found -> - join (topify_arith_origin e1) (topify_arith_origin e2) - end - - let bitwise_and ~signed ~size e1 e2 = - let bitwise_and_pointer_ival p _ival = - Location_Bytes.location_shift - (Ival.inject_top None (Some Int.zero) Int.zero Int.one) - p - in - try - let v1 = project_ival e1 in - try - let v2 = project_ival e2 in - let result = Ival.bitwise_and ~signed ~size v1 v2 - in - inject_ival result - with Not_based_on_null -> - bitwise_and_pointer_ival e2 v1 - with Not_based_on_null -> - try - let v2 = project_ival e2 in - bitwise_and_pointer_ival e1 v2 - with Not_based_on_null -> - join (topify_arith_origin e1) (topify_arith_origin e2) - - let bitwise_or ~topify_arith_origin ~size e1 e2 = - try - let v1 = project_ival e1 in - let v2 = project_ival e2 in - let result = Ival.bitwise_or ~size v1 v2 - in - inject_ival result - with Not_based_on_null -> - join (topify_arith_origin e1) (topify_arith_origin e2) - - let extract_bits ~start ~stop v = - try - let i = project_ival v in - false, inject_ival (Ival.extract_bits ~start ~stop i) - with - | Not_based_on_null -> - if is_imprecise v - then false, v - else true, topify_misaligned_read_origin v - - let big_endian_merge_bits ~conflate_bottom:_ ~total_length ~length ~value ~offset acc = - if equal acc bottom || equal value bottom - then bottom - else - let total_length_i = Int.of_int total_length in - assert (Int.le (Int.add length offset) total_length_i); - let result = - bitwise_or - ~topify_arith_origin:topify_misaligned_read_origin - ~size:total_length - (shift_left - ~topify_arith_origin:topify_misaligned_read_origin - ~with_alarms:warn_none_mode - ~size:total_length - value - (inject_ival (Ival.inject_singleton (Int.sub (Int.sub total_length_i offset) length)))) - acc - in -(* Format.printf "big_endian_merge_bits : total_length:%d length:%a value:%a offset:%a acc:%a GOT:%a@." - total_length - Int.pretty length - pretty value - Int.pretty offset - pretty acc - pretty result; *) - result - - let little_endian_merge_bits ~conflate_bottom ~total_length ~value - ~offset acc = - if equal acc bottom || equal value bottom - then begin - if conflate_bottom - then - bottom - else - join - (topify_misaligned_read_origin acc) - (topify_misaligned_read_origin value) - end - else - let result = - bitwise_or - ~topify_arith_origin:topify_misaligned_read_origin - ~size:total_length - (shift_left - ~topify_arith_origin:topify_misaligned_read_origin - ~with_alarms:warn_none_mode - ~size:total_length - value - (inject_ival (Ival.inject_singleton offset))) - acc - in - (*Format.printf "le merge_bits : total_length:%d value:%a offset:%a acc:%a GOT:%a@." - total_length pretty value Int.pretty offset pretty acc pretty result;*) - result - - let all_values ~size v = - (Parameters.Overflow.get ()) && - try - let i = project_ival v in - Ival.all_values ~size i - with Not_based_on_null -> false - - let anisotropic_cast ~size v = - if all_values ~size v then top_int else v - - let create_all_values ~modu ~signed ~size = - inject_ival (Ival.create_all_values ~modu ~signed ~size) - - let bitwise_or = bitwise_or ~topify_arith_origin - let shift_left = shift_left ~topify_arith_origin - - let has_sign_problems v = - not (is_included top_int v || is_included v top_float) - -end - -module V_Or_Uninitialized = struct - -(* type t = { initialized : bool; - no_escaping_adr : bool; - v : V.t} *) - - type tt = - | C_uninit_esc of V.t - | C_uninit_noesc of V.t - | C_init_esc of V.t - | C_init_noesc of V.t - - let mask_init = 2 - let mask_noesc = 1 - - let is_initialized flags = (flags land mask_init) <> 0 - let is_noesc flags = (flags land mask_noesc) <> 0 - - let get_v : tt -> V.t = fun v -> Obj.obj (Obj.field (Obj.repr v) 0) - let get_flags : tt -> int = fun v -> Obj.tag (Obj.repr v) - - let create : int -> V.t -> tt = fun flags v -> - match flags with - | 0 -> C_uninit_esc v - | 1 -> C_uninit_noesc v - | 2 -> C_init_esc v - | 3 -> C_init_noesc v - | _ -> assert false - - let project x = V.project (get_v x) - -(* let (==>) = (fun x y -> (not x) || y) *) - - let is_included_actual_generic b1 b2 instanciation t1 t2 = - let flags1 = get_flags t1 in - let flags2 = get_flags t2 in - if (lnot flags2) lor flags1 = -1 - (* (t2.initialized ==> t1.initialized) - && (t2.no_escaping_adr ==> t1.no_escaping_adr) *) - then - V.is_included_actual_generic b1 b2 instanciation (get_v t1) (get_v t2) - else raise Abstract_interp.Is_not_included - - type widen_hint = V.widen_hint - let widen wh t1 t2 = - create (get_flags t2) (V.widen wh (get_v t1) (get_v t2)) - - let equal t1 t2 = - (get_flags t1) = (get_flags t2) && - V.equal (get_v t1) (get_v t2) - - exception Error_Bottom - exception Error_Top - - let join t1 t2 = -(* - { - initialized = t1.initialized && t2.initialized; - no_escaping_adr = t1.no_escaping_adr && t2.no_escaping_adr; - v = V.join t1.v t2.v - } -*) - create - ((get_flags t1) land (get_flags t2)) - (V.join (get_v t1) (get_v t2)) - - let narrow t1 t2 = -(* {initialized = t1.initialized || t2.initialized; - no_escaping_adr = t1.no_escaping_adr || t2.no_escaping_adr; - v = V.narrow t1.v t2.v - } -*) - create - ((get_flags t1) lor (get_flags t2)) - (V.narrow (get_v t1) (get_v t2)) - - let link t1 t2 = - create - ((get_flags t1) land (get_flags t2)) - (V.link (get_v t1) (get_v t2)) - - let meet t1 t2 = - create - ((get_flags t1) lor (get_flags t2)) - (V.meet (get_v t1) (get_v t2)) - - let bottom = C_init_noesc V.bottom - let top = C_uninit_esc V.top - - let uninitialized = C_uninit_noesc V.bottom - let initialized v = C_init_noesc v - - let is_included t1 t2 = -(* (t2.initialized ==> t1.initialized) && - (t2.no_escaping_adr ==> t1.no_escaping_adr) && - V.is_included t1.v t2.v -*) - let flags1 = get_flags t1 in - let flags2 = get_flags t2 in - (lnot flags2) lor flags1 = -1 && - V.is_included (get_v t1) (get_v t2) - - let is_included_exn t1 t2 = - if not (is_included t1 t2) - then raise Abstract_interp.Is_not_included - - let intersects _t1 _t2 = - assert false -(* - ((not t2.initialized) && (not t1.initialized)) || - ((not t2.no_escaping_adr) && (not t1.no_escaping_adr)) || - V.intersects t1.v t2.v -*) - - let pretty fmt t = - let flags = get_flags t in - let no_escaping_adr = is_noesc flags in - let initialized = is_initialized flags in - let v = get_v t in - if initialized && no_escaping_adr - then V.pretty fmt v - else if equal t uninitialized - then Format.fprintf fmt "UNINITIALIZED" - else if initialized && not no_escaping_adr - then Format.fprintf fmt "%a or ESCAPINGADDR" V.pretty v - else if (not initialized) && no_escaping_adr - then Format.fprintf fmt "%a or UNINITIALIZED" V.pretty v - else Format.fprintf fmt "%a or UNINITIALIZED or ESCAPINGADDR" V.pretty v - - let cardinal_zero_or_one t = - match t with - C_init_noesc v -> V.cardinal_zero_or_one v - | C_init_esc v | C_uninit_noesc v -> V.is_bottom v - | C_uninit_esc _ -> false - - let cardinal_less_than t b = - match t with - C_init_noesc v -> V.cardinal_less_than v b - | _ -> raise Abstract_interp.Not_less_than - - let tag t = (get_flags t) * 4513 + (V.tag (get_v t)) - - include Datatype.Make - (struct - type t = tt (* = | C_uninit_esc of V.t - | C_uninit_noesc of V.t - | C_init_esc of V.t - | C_init_noesc of V.t *) - let name = "Cvalue_type.V_Or_Uninitialized" - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum - [| [| V.packed_descr |]; - [| V.packed_descr |]; - [| V.packed_descr |]; - [| V.packed_descr |] |]) - let reprs = - List.fold_left - (fun acc v -> - List.fold_left - (fun acc v -> - List.fold_left - (fun acc v -> C_uninit_noesc v :: acc) - (C_uninit_esc v :: acc) - V.reprs) - (C_init_noesc v :: acc) - V.reprs) - (List.map (fun v -> C_init_esc v) V.reprs) - V.reprs - let hash = tag - let equal = equal - let compare = Datatype.undefined - let copy = Datatype.undefined - let rehash = Datatype.identity - let pretty = pretty - let internal_pretty_code = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) - - module Top_Param = V.Top_Param - - let is_isotropic t = V.is_isotropic (get_v t) - - let cast ~with_alarms ~size ~signed t = - create (get_flags t) (V.cast ~with_alarms ~size ~signed (get_v t)) - - let extract_bits ~start ~stop t = - let inform_extract_pointer_bits, v = - V.extract_bits ~start ~stop (get_v t) - in - inform_extract_pointer_bits, - create (get_flags t) v - - let little_endian_merge_bits ~conflate_bottom ~total_length ~value ~offset t = - create - ((get_flags t) land (get_flags value)) - (V.little_endian_merge_bits ~conflate_bottom - ~total_length ~value:(get_v value) ~offset - (get_v t)) - - let big_endian_merge_bits ~conflate_bottom ~total_length ~length ~value ~offset t = - create - ((get_flags t) land (get_flags value)) - (V.big_endian_merge_bits ~conflate_bottom - ~total_length ~length - ~value:(get_v value) - ~offset - (get_v t)) - - let topify_merge_origin t = - create - (get_flags t) - (V.topify_merge_origin (get_v t)) - - let topify_arith_origin t = - create - (get_flags t) - (V.topify_arith_origin (get_v t)) - - let topify_misaligned_read_origin t = - create - (get_flags t) - (V.topify_misaligned_read_origin (get_v t)) - - let topify_with_origin o t = - create - (get_flags t) - (V.topify_with_origin o (get_v t)) - - let anisotropic_cast ~size t = - create - (get_flags t) - (V.anisotropic_cast ~size (get_v t)) - - let inject_top_origin o t = - C_init_noesc (V.inject_top_origin o t) - - let under_topify t = - create - (get_flags t) - (V.under_topify (get_v t)) - - let of_char c = C_init_noesc (V.of_char c) - - let singleton_zero = C_init_noesc (V.singleton_zero) - - let unspecify_escaping_locals is_local t = -(* - {initialized = t.initialized; - no_escaping_adr = false; - v = V.remove_escaping_locals is_local (get_v t)} -*) - let flags = get_flags t in - let flags = flags land mask_init in - create flags (V.remove_escaping_locals is_local (get_v t)) - - let pretty_c_assert _lv _s _fmt _v = () - -end - -module V_Offsetmap = Offsetmap.Make(V_Or_Uninitialized) - -(* -module R_V = -struct - include V -end - -module C_Offsetmap = Offsetmap.Make(R_V) -*) - -module V_Offsetmap_ext = V_Offsetmap -(*struct - type y = V_Offsetmap.y - type widen_hint = V_Offsetmap.widen_hint - type t = V_Offsetmap.t * V_Offsetmap.t - type tt = t - - let pretty fmt (o,c) = - V_Offsetmap.pretty fmt o - - let pretty_typ typ fmt (o,c) = - V_Offsetmap.pretty_typ typ fmt o - - let pretty_debug _ = assert false - - let equal (o1, c1) (o2, c2) = - V_Offsetmap.equal o1 o2 && C_Offsetmap.equal c1 c2 - - let empty = V_Offsetmap.empty, C_Offsetmap.empty - - let is_empty = equal empty - - module Datatype = - Project.Datatype.Register - (struct - type t = tt - let rehash = assert false - let copy _ = assert false (* TODO *) - let before_load () = () - let after_load () = assert false - let name = Project.Datatype.Name.extend "ext" V_Offsetmap.Datatype.name - let dependencies = [ V_Offsetmap.Datatype.self ] - end) -end*) - -module Partial_lmap = Lmap.Make_LOffset(V_Or_Uninitialized)(V_Offsetmap_ext) - -module Default_offsetmap = struct - - let initialized_var_table = Cil_datatype.Varinfo.Hashtbl.create 17 - - let create_initialized_var varinfo validity initinfo = - Cil_datatype.Varinfo.Hashtbl.add - initialized_var_table varinfo initinfo; - Base.create_initialized varinfo validity - - let default_offsetmap base = match base with - | Base.Initialized_Var (v,_) -> - (try Cil_datatype.Varinfo.Hashtbl.find initialized_var_table v - with Not_found -> - V_Offsetmap.empty) - | Base.Var _ -> - begin - match Base.validity base with - Base.All -> - let upb = Bit_utils.max_bit_address () in - V_Offsetmap.add_internal - (Int.zero, upb) - (Int.zero, Int.one, V_Or_Uninitialized.uninitialized) - V_Offsetmap.empty - | Base.Known (mn, mx) | Base.Unknown (mn, mx) -> - if Int.ge mx mn - then - V_Offsetmap.add_internal - (mn, mx) - (Int.zero, Int.one, V_Or_Uninitialized.uninitialized) - V_Offsetmap.empty - else - V_Offsetmap.empty - | Base.Periodic (mn, mx, p) -> - assert (Int.is_zero mn); - let upb = Int.pred p in - assert (Int.ge mx upb); - V_Offsetmap.add_internal - (Int.zero, upb) - (Int.zero, Int.one, V_Or_Uninitialized.bottom) - V_Offsetmap.empty - end - | Base.Null - | Base.Cell_class _ -> V_Offsetmap.empty - | Base.String (_,s) -> V_Offsetmap.from_string s -end - -module Model = struct - - include Partial_lmap.Make(Default_offsetmap) - type y = V.t - - let pretty_c_assert fmt m = - Format.fprintf fmt "@["; - (match m with - Bottom -> Format.fprintf fmt "0" - | Map m -> - let first = ref true in - let print_ampamp () = - if !first - then - first := false - else - Format.fprintf fmt "@\n&& "; - in - LBase.iter - (fun base offs -> - match base with - Base.Var(v,_) -> - let typ = unrollType v.Cil_types.vtype in - let name = v.Cil_types.vname in - V_Offsetmap.pretty_c_assert_typ name typ print_ampamp fmt offs - | _ -> ()) - m - | Top -> Format.fprintf fmt "1"); - Format.fprintf fmt "@]" - - let find_unspecified = find ~conflate_bottom:true - - let find ~conflate_bottom ~with_alarms x y = - let v = find ~conflate_bottom ~with_alarms x y in - let v_v = V_Or_Uninitialized.get_v v in - let bottom = V.is_bottom v_v in - let flags = V_Or_Uninitialized.get_flags v in - if conflate_bottom - then begin - if not (V_Or_Uninitialized.is_initialized flags) - then warn_uninitialized with_alarms; - if not (V_Or_Uninitialized.is_noesc flags) - then warn_escapingaddr with_alarms; - end; - - if with_alarms.unspecified <> Aignore && - bottom && - not (V_Or_Uninitialized.is_initialized flags && - V_Or_Uninitialized.is_noesc flags ) - then begin - match with_alarms.unspecified with - Aignore -> assert false - | Acall f -> f() - | Alog -> - warn_once - "completely undefined value in %a." - Locations.pretty y; - end; - v_v - - let add_binding_unspecified acc loc = - add_binding ~with_alarms:warn_none_mode ~exact:true acc loc (V_Or_Uninitialized.uninitialized) - - let add_binding ~with_alarms ~exact acc loc value = - add_binding ~with_alarms ~exact acc loc (V_Or_Uninitialized.initialized value) - - let reduce_binding ~with_alarms acc loc value = - reduce_binding ~with_alarms acc loc (V_Or_Uninitialized.initialized value) - - let create_initial ~base ~v ~modu ~state = - create_initial ~base ~v:(V_Or_Uninitialized.initialized v) ~modu ~state -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/function_Froms.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/function_Froms.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/function_Froms.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/function_Froms.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,12 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please write a .mli and + document it. *) + open Locations type tt = @@ -43,13 +49,13 @@ let pretty_with_type typ fmt { deps_return = r; deps_table = t } = let (rt_typ,_,_,_) = Cil.splitFunctionType typ in if Cil.isVoidType rt_typ then - Format.fprintf fmt "@[@[@;<2 0>@[%a@]@]@]@\n" + Format.fprintf fmt "@[@[@;<2 0>@[%a@]@]@]" Lmap_bitwise.From_Model.pretty t else if Lmap_bitwise.From_Model.LOffset.is_empty r then - Format.fprintf fmt "@[@[@;<2 0>@[%a@]\\result FROM \\nothing@]@]@\n" + Format.fprintf fmt "@[@[@;<2 0>@[%a@]\\result FROM \\nothing@]@]" Lmap_bitwise.From_Model.pretty t else - Format.fprintf fmt "@[@[@;<2 0>@[%a@]\\result%a@]@]@\n" + Format.fprintf fmt "@[@[@;<2 0>@[%a@]\\result%a@]@]" Lmap_bitwise.From_Model.pretty t (Lmap_bitwise.From_Model.LOffset.pretty_with_type (Some rt_typ)) r @@ -66,18 +72,18 @@ (struct type t = tt let reprs = - List.fold_left - (fun acc o -> - List.fold_left - (fun acc m -> { deps_return = o; deps_table = m } :: acc) - acc - Lmap_bitwise.From_Model.reprs) - [] - Lmap_bitwise.From_Model.LOffset.reprs + List.fold_left + (fun acc o -> + List.fold_left + (fun acc m -> { deps_return = o; deps_table = m } :: acc) + acc + Lmap_bitwise.From_Model.reprs) + [] + Lmap_bitwise.From_Model.LOffset.reprs let structural_descr = - Structural_descr.t_record - [| Lmap_bitwise.From_Model.LOffset.packed_descr; - Lmap_bitwise.From_Model.packed_descr |] + Structural_descr.t_record + [| Lmap_bitwise.From_Model.LOffset.packed_descr; + Lmap_bitwise.From_Model.packed_descr |] let name = "Function_Froms" let hash = hash let compare = Datatype.undefined diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/hptset.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/hptset.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/hptset.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/hptset.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -module type S = sig - type elt - include Datatype.S - val empty: t - val is_empty: t -> bool - val mem: elt -> t -> bool - val add: elt -> t -> t - val singleton: elt -> t - val remove: elt -> t -> t - val elements: t -> elt list - val union: t -> t -> t - val inter: t -> t -> t - val diff: t -> t -> t - val subset: t -> t -> bool - val iter: (elt -> unit) -> t -> unit - val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a - val for_all: (elt -> bool) -> t -> bool - val exists: (elt -> bool) -> t -> bool - val filter: (elt -> bool) -> t -> t -(* val partition: (elt -> bool) -> t -> t * t*) - val cardinal: t -> int - val min_elt: t -> elt -(* val max_elt: t -> elt -*) - val contains_single_elt: t -> elt option -(* val choose: t -> elt - val split: elt -> t -> t * bool * t*) -end - -module type Id_Datatype = sig - include Datatype.S - val id: t -> int -end - -module Make(X: Id_Datatype) = struct - - include - Hptmap.Make - (X) - (struct include Datatype.Unit let tag () = 0 end) - (Hptmap.Comp_unused) - (struct let v = [] end) - - type elt = X.t - - external getperfcount : unit -> int = "getperfcount" - - let time name f = - let cpt = ref 0 in - fun x -> - let b = getperfcount () in - let res = f x in - let e = getperfcount () in - let diff = e - b in - cpt := !cpt + diff; - Format.eprintf "timing of %s: %d (%d)@." name !cpt diff; - res - - let time2 name f = - let cpt = ref 0 in - fun x y -> - let b = getperfcount () in - let res = f x y in - let e = getperfcount () in - let diff = e - b in - cpt := !cpt + diff; - Format.eprintf "timing of %s: %d (%d)@." name !cpt diff; - res - - let add k = add k () - let iter f = iter (fun x () -> f x) - let fold f = fold (fun x () -> f x) - - let elements s = fold (fun h t -> h::t) s [] - - let contains_single_elt s = - match is_singleton s with - Some (k, _v) -> Some k - | None -> None - - let min_elt s = - fst (min_binding s) - - let filter f s = fold (fun x acc -> if f x then add x acc else acc) s empty - - let mem x s = try find x s; true with Not_found -> false - - let diff s1 s2 = - fold (fun x acc -> if mem x s2 then acc else add x acc) s1 empty - - let inter s1 s2 = - fold (fun x acc -> if mem x s1 then add x acc else acc) s2 empty -(* let inter = time2 "inter" inter*) - - let binary_unit _ _ = () - - let union = - symetric_merge - ~cache:("Hptset.union", 12) - ~decide_none:binary_unit - ~decide_some:binary_unit - -(* generic_merge ~cache:("Hptset.union", 12) ~decide:(fun _ _ _ -> ()) *) -(* let union = time2 "union" union*) - - let singleton x = add x empty - - exception Elt_found - - let exists f s = - try - iter (fun x -> if f x then raise Elt_found) s; - false - with Elt_found -> - true - - let for_all f s = - try - iter (fun x -> if not (f x) then raise Elt_found) s; - true - with Elt_found -> - false - - (* completely sub-optimal: subset should be divide-and-conquer *) - let subset s1 s2 = not (exists (fun x -> not (mem x s2)) s1) -(* let subset = time2 "subset" subset*) - - let cardinal s = fold (fun _ acc -> acc + 1) s 0 -(* let cardinal = time "cardinal" cardinal*) - -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/hptset.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/hptset.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/hptset.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/hptset.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,149 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Sets over ordered types. - - This module implements the set data structure. - All operations over sets - are purely applicative (no side-effects). *) - -(** Input signature of the functor {!Set.Make}. *) -module type Id_Datatype = sig - include Datatype.S - val id: t -> int -end - -(** Output signature of the functor {!Set.Make}. *) -module type S = sig - - type elt - (** The type of the set elements. *) - - include Datatype.S - (** The datatype of sets. *) - - val empty: t - (** The empty set. *) - - val is_empty: t -> bool - (** Test whether a set is empty or not. *) - - val mem: elt -> t -> bool - (** [mem x s] tests whether [x] belongs to the set [s]. *) - - val add: elt -> t -> t - (** [add x s] returns a set containing all elements of [s], - plus [x]. If [x] was already in [s], [s] is returned unchanged. *) - - val singleton: elt -> t - (** [singleton x] returns the one-element set containing only [x]. *) - - val remove: elt -> t -> t - (** [remove x s] returns a set containing all elements of [s], - except [x]. If [x] was not in [s], [s] is returned unchanged. *) - - val elements: t -> elt list - - val union: t -> t -> t - (** Set union. *) - - val inter: t -> t -> t - (** Set intersection. *) - - (** Set difference. *) - val diff: t -> t -> t -(* - val compare: t -> t -> int - (** Total ordering between sets. Can be used as the ordering function - for doing sets of sets. *) -*) - - val subset: t -> t -> bool - (** [subset s1 s2] tests whether the set [s1] is a subset of - the set [s2]. *) - - val iter: (elt -> unit) -> t -> unit - (** [iter f s] applies [f] in turn to all elements of [s]. - The elements of [s] are presented to [f] in increasing order - with respect to the ordering over the type of the elements. *) - - val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a - (** [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)], - where [x1 ... xN] are the elements of [s], in increasing order. *) - - val for_all: (elt -> bool) -> t -> bool - (** [for_all p s] checks if all elements of the set - satisfy the predicate [p]. *) - - val exists: (elt -> bool) -> t -> bool - (** [exists p s] checks if at least one element of - the set satisfies the predicate [p]. *) - - val filter: (elt -> bool) -> t -> t - (** [filter p s] returns the set of all elements in [s] - that satisfy predicate [p]. *) -(* - val partition: (elt -> bool) -> t -> t * t - (** [partition p s] returns a pair of sets [(s1, s2)], where - [s1] is the set of all the elements of [s] that satisfy the - predicate [p], and [s2] is the set of all the elements of - [s] that do not satisfy [p]. *) - -*) - val cardinal: t -> int - (** Return the number of elements of a set. *) - - val min_elt: t -> elt - (** Return the smallest element of the given set - (with respect to the [Ord.compare] ordering), or raise - [Not_found] if the set is empty. *) -(* - val max_elt: t -> elt - (** Same as {!Set.S.min_elt}, but returns the largest element of the - given set. *) -*) - val contains_single_elt: t -> elt option - -(* - val choose: t -> elt - (** Return one element of the given set, or raise [Not_found] if - the set is empty. Which element is chosen is unspecified, - but equal elements will be chosen for equal sets. *) - - val split: elt -> t -> t * bool * t - (** [split x s] returns a triple [(l, present, r)], where - [l] is the set of elements of [s] that are - strictly less than [x]; - [r] is the set of elements of [s] that are - strictly greater than [x]; - [present] is [false] if [s] contains no element equal to [x], - or [true] if [s] contains an element equal to [x]. *) -*) -end - -module Make(X: Id_Datatype) : S with type elt = X.t - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/inout_type.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/inout_type.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/inout_type.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/inout_type.ml 2011-10-10 08:38:30.000000000 +0000 @@ -34,14 +34,14 @@ let structural_descr = Structural_descr.t_record [| Locations.Zone.packed_descr; - Locations.Zone.packed_descr; - Locations.Zone.packed_descr |] + Locations.Zone.packed_descr; + Locations.Zone.packed_descr |] let reprs = List.map (fun z -> - { over_inputs_if_termination = z; - under_outputs_if_termination = z; - over_inputs = z }) + { over_inputs_if_termination = z; + under_outputs_if_termination = z; + over_inputs = z }) Locations.Zone.reprs let name = "Inout_type" let hash diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/int_Interv_Map.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/int_Interv_Map.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/int_Interv_Map.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/int_Interv_Map.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,12 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please write a .mli and + document it. *) + open Abstract_interp open Abstract_value @@ -40,14 +46,17 @@ lowest_binding_above o m let pretty pretty_v fmt m = - Format.fprintf fmt "{"; - iter - (fun (bi,ei) v -> - Format.fprintf fmt "[%a..%a] -> %a ;@ " - Int.pretty bi Int.pretty ei - pretty_v v) - m; - Format.fprintf fmt "}" + Pretty_utils.pp_iter + ~pre:"@[{" + ~suf:"}@]" + ~sep:" ;@ " + (fun pp map -> iter (fun bi_ei v -> pp (bi_ei, v)) map) + (fun fmt ((bi, ei), v) -> + Format.fprintf fmt "[%a..%a] -> %a" + Int.pretty bi Int.pretty ei + pretty_v v) + fmt + m let enlarge_to_right ~extend_right same_values ei new_vv acc = if extend_right then @@ -56,7 +65,7 @@ match concerned_intervals Int_Interv.fuzzy_order (s_ei,s_ei) acc with [] -> acc,ei | [(ba,ea) as a,vva] -> - assert (Int.equal ba s_ei); + assert (Int.equal ba s_ei); if same_values vva new_vv then (remove a acc),ea else acc,ei @@ -68,7 +77,7 @@ same_values ei new_vv ((_,ei1),vv1) acc = if Int.gt ei1 ei then (* Part of the previous binding remains - on the right-hand-side *) + on the right-hand-side *) if extend_right && same_values vv1 new_vv then (* same value -> merge keys *) acc,ei1 @@ -92,7 +101,7 @@ ((bi1,_),vv1) acc = if Int.lt bi1 bi then (* Part of the previous binding remains - on the left-hand-side *) + on the left-hand-side *) if extend_left && same_values vv1 new_vv then (* same value -> merge keys *) acc,bi1 @@ -111,58 +120,58 @@ let result = match concerned_intervals with | [] -> let acc,new_bi = - enlarge_to_left ~extend_left same_values bi new_vv m in + enlarge_to_left ~extend_left same_values bi new_vv m in let acc,new_ei = - enlarge_to_right ~extend_right same_values ei new_vv acc in + enlarge_to_right ~extend_right same_values ei new_vv acc in Some(new_bi, new_ei, acc) | [((bi1, ei1) as i1, vv1) as binding1] -> - let cond_start = Int.le bi1 bi in - let cond_end = Int.ge ei1 ei in - let cond_same = same_values vv1 new_vv in - if (cond_start && cond_end && cond_same && extend_right && extend_left) - then None (* nothing to do, the new interval is included in the - previous one and the old and new values are the same*) - else begin - let result1 = remove i1 m in - let result2,new_bi = - handle_leftmost_itv - same_values ~extend_left bi new_vv binding1 result1 - in - let result3,new_ei = - handle_rightmost_itv + let cond_start = Int.le bi1 bi in + let cond_end = Int.ge ei1 ei in + let cond_same = same_values vv1 new_vv in + if (cond_start && cond_end && cond_same && extend_right && extend_left) + then None (* nothing to do, the new interval is included in the + previous one and the old and new values are the same*) + else begin + let result1 = remove i1 m in + let result2,new_bi = + handle_leftmost_itv + same_values ~extend_left bi new_vv binding1 result1 + in + let result3,new_ei = + handle_rightmost_itv ~extend_right - same_values ei new_vv binding1 result2 - in - Some(new_bi, new_ei, result3) - end + same_values ei new_vv binding1 result2 + in + Some(new_bi, new_ei, result3) + end | ((_bi1, _ei1), _vv1 as binding1)::tail -> - let result1 = - List.fold_right - (fun (i1,_) acc -> remove i1 acc) - concerned_intervals - m - in + let result1 = + List.fold_right + (fun (i1,_) acc -> remove i1 acc) + concerned_intervals + m + in (* part of the last interval might remain on the right *) - let result2,new_ei = - handle_rightmost_itv + let result2,new_ei = + handle_rightmost_itv ~extend_right - same_values ei new_vv binding1 result1 - in - let rec f l acc = - match l with - | [] -> assert false - (* at least 2 elements in [concerned_intervals] *) - | [(_bi1, _ei1), _vv1 as binding1] -> - (* part of the first interval might remain on the left *) - handle_leftmost_itv ~extend_left - same_values bi new_vv binding1 acc - | ((_bi1, _ei1), _vv1)::tail -> - (* the middle intervals are completely covered : ignore + same_values ei new_vv binding1 result1 + in + let rec f l acc = + match l with + | [] -> assert false + (* at least 2 elements in [concerned_intervals] *) + | [(_bi1, _ei1), _vv1 as binding1] -> + (* part of the first interval might remain on the left *) + handle_leftmost_itv ~extend_left + same_values bi new_vv binding1 acc + | ((_bi1, _ei1), _vv1)::tail -> + (* the middle intervals are completely covered : ignore former values *) - f tail acc - in - let result3,new_bi = f tail result2 in - Some(new_bi, new_ei, result3) + f tail acc + in + let result3,new_bi = f tail result2 in + Some(new_bi, new_ei, result3) in (* if not (extend_right && extend_left) then (match result with None -> Format.printf "Cleanup...NONE@\n" diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/int_Interv.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/int_Interv.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/int_Interv.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/int_Interv.ml 2011-10-10 08:38:30.000000000 +0000 @@ -40,7 +40,7 @@ let reprs = List.fold_left (fun acc n1 -> - List.fold_left (fun acc n2 -> (n1, n2) :: acc) acc Int.reprs) + List.fold_left (fun acc n2 -> (n1, n2) :: acc) acc Int.reprs) [] Int.reprs @@ -52,10 +52,10 @@ Int.equal (snd x) (snd y) then 0 else begin - (*Format.printf "Comparaison d'intervalles non comparables [%a..%a] et [%a..%a]@\n@\n" - Int.pretty (fst x) Int.pretty (snd x) + (*Format.printf "Comparaison d'intervalles non comparables [%a..%a] et [%a..%a]@\n@\n" + Int.pretty (fst x) Int.pretty (snd x) Int.pretty (fst y) Int.pretty (snd y);*) - raise Cannot_compare_intervals + raise Cannot_compare_intervals end let hash (x, y) = Int.hash x + 7 * Int.hash y @@ -77,15 +77,15 @@ ( match concerned with [] -> raise Is_not_included | ((_bj,ej),_) :: _ -> - if Int.gt ei ej then raise Is_not_included); + if Int.gt ei ej then raise Is_not_included); let rec check_joint concerned = match concerned with - [] -> assert false + [] -> assert false | [(bj,_ej),_] -> - if Int.lt bi bj then raise Is_not_included + if Int.lt bi bj then raise Is_not_included | ((bj,_ej),_) :: ((((_bk,ek),_)::_) as tail) -> - if not (Int.equal bj (Int.succ ek)) then raise Is_not_included; - check_joint tail + if not (Int.equal bj (Int.succ ek)) then raise Is_not_included; + check_joint tail in check_joint concerned diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/int_Interv.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/int_Interv.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/int_Interv.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/int_Interv.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + exception Cannot_compare_intervals include Datatype.S with type t = Abstract_interp.Int.t * Abstract_interp.Int.t diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/lmap_bitwise.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_bitwise.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/lmap_bitwise.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_bitwise.ml 2011-10-10 08:38:30.000000000 +0000 @@ -66,7 +66,10 @@ val fold_base : (Base.t -> LOffset.t -> 'a -> 'a) -> t -> 'a -> 'a val map2 : ((bool * y) option -> (bool * y) option -> bool * y) -> t -> t -> t - val copy_paste : f:(bool * y -> bool * y) -> location -> location -> t -> t + val copy_paste : + with_alarms:CilE.warn_mode -> + f:(bool * y -> bool * y) -> + location -> location -> t -> t exception Zone_unchanged val find_or_unchanged : t -> Zone.t -> y @@ -88,9 +91,9 @@ end module LBase = struct - include Hptmap.Make(Base)(LOffset)(Hptmap.Comp_unused)(struct let v = [[]] end) + include Hptmap.Make(Base)(LOffset)(Hptmap.Comp_unused)(struct let v = [[]] end)(struct let l = [ Ast.self ] end) let find_or_default base m = - try find base m with Not_found -> LOffset.empty + try find base m with Not_found -> LOffset.empty end type tt = Top | Map of LBase.t @@ -113,7 +116,7 @@ Top -> Format.fprintf fmt "@[FROMTOP@]" | Map m -> Format.fprintf fmt "@["; - (LBase.iter + (LBase.iter (fun base offs -> Format.fprintf fmt "%a@[%a@]@," Base.pretty base @@ -125,37 +128,37 @@ include Datatype.Make (struct - type t = tt - let reprs = Top :: List.map (fun b -> Map b) LBase.reprs - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| LBase.packed_descr |] |]) - let name = LOffset.name ^ " lmap_bitwise" - let hash = hash - let equal = equal - let compare = Datatype.undefined - let pretty = pretty - let internal_pretty_code = Datatype.undefined - let rehash = Datatype.identity - let copy = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project + type t = tt + let reprs = Top :: List.map (fun b -> Map b) LBase.reprs + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum [| [| LBase.packed_descr |] |]) + let name = LOffset.name ^ " lmap_bitwise" + let hash = hash + let equal = equal + let compare = Datatype.undefined + let pretty = pretty + let internal_pretty_code = Datatype.undefined + let rehash = Datatype.identity + let copy = Datatype.undefined + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project end) let fold f m acc = match m with - | Top -> raise Cannot_fold + | Top -> raise Cannot_fold | Map m -> - LBase.fold - (fun k offsetmap acc -> - LOffset.fold - (fun itvs v acc -> - let loc = Zone.inject k itvs in - f loc v acc) - offsetmap - acc) - m - acc + LBase.fold + (fun k offsetmap acc -> + LOffset.fold + (fun itvs v acc -> + let loc = Zone.inject k itvs in + f loc v acc) + offsetmap + acc) + m + acc let fold_base f m acc= match m with @@ -165,13 +168,13 @@ let add_interval ~exact varid itv v map = let offsetmap_orig = try - LBase.find varid map + LBase.find varid map with Not_found -> - LOffset.empty + LOffset.empty in let new_offsetmap = (if exact then LOffset.add else LOffset.add_approximate) - itv v offsetmap_orig + itv v offsetmap_orig in LBase.add varid new_offsetmap map @@ -180,34 +183,34 @@ | Zone.Top (Zone.Top_Param.Top, _),_|_,Top -> Top | Zone.Top (Zone.Top_Param.Set s, _), Map m -> let result = - let treat_base base acc = - let offsetmap_orig = - try - LBase.find base m - with Not_found -> - LOffset.empty - in - let new_offsetmap = - LOffset.add_iset ~exact Int_Intervals.top v offsetmap_orig - in - LBase.add base new_offsetmap acc - in - Zone.Top_Param.O.fold treat_base s (treat_base Base.null m) + let treat_base base acc = + let offsetmap_orig = + try + LBase.find base m + with Not_found -> + LOffset.empty + in + let new_offsetmap = + LOffset.add_iset ~exact Int_Intervals.top v offsetmap_orig + in + LBase.add base new_offsetmap acc + in + Zone.Top_Param.O.fold treat_base s (treat_base Base.null m) in Map result | Zone.Map _, Map m -> let result = - let treat_offset varid offs m = - let offsetmap_orig = - try - LBase.find varid m - with Not_found -> - LOffset.empty - in - let new_offsetmap = - LOffset.add_iset ~exact offs v offsetmap_orig - in LBase.add varid new_offsetmap m - in - Zone.fold_i treat_offset loc m + let treat_offset varid offs m = + let offsetmap_orig = + try + LBase.find varid m + with Not_found -> + LOffset.empty + in + let new_offsetmap = + LOffset.add_iset ~exact offs v offsetmap_orig + in LBase.add varid new_offsetmap m + in + Zone.fold_i treat_offset loc m in Map result let join m1 m2 = @@ -215,29 +218,29 @@ Top, _ | _, Top -> Top | Map m1, Map m2 -> let treat_base varid offsmap1 acc = - let offsmap = - try - let offsmap2 = LBase.find varid m2 in - LOffset.join offsmap1 offsmap2 - with Not_found -> - LOffset.joindefault offsmap1 - in - LBase.add varid offsmap acc + let offsmap = + try + let offsmap2 = LBase.find varid m2 in + LOffset.join offsmap1 offsmap2 + with Not_found -> + LOffset.joindefault offsmap1 + in + LBase.add varid offsmap acc in let all_m1 = LBase.fold treat_base m1 LBase.empty in let result = - LBase.fold - (fun varid offsmap2 acc -> - try - ignore (LBase.find varid m1); - acc - with Not_found -> - LBase.add - varid - (LOffset.joindefault offsmap2) - acc) - m2 - all_m1 + LBase.fold + (fun varid offsmap2 acc -> + try + ignore (LBase.find varid m1); + acc + with Not_found -> + LBase.add + varid + (LOffset.joindefault offsmap2) + acc) + m2 + all_m1 in Map result in @@ -253,12 +256,12 @@ Top | Map m1, Map m2 -> let treat_base varid offsmap1 acc = - let offsmap_result = + let offsmap_result = try let offsmap2 = LBase.find varid m2 in - LOffset.map2 f offsmap1 offsmap2 - with Not_found -> - LOffset.map (fun x -> f (Some x) None) offsmap1 + LOffset.map2 f offsmap1 offsmap2 + with Not_found -> + LOffset.map (fun x -> f (Some x) None) offsmap1 in LBase.add varid offsmap_result acc @@ -273,7 +276,7 @@ with Not_found -> let offsetmap = LOffset.map (fun x -> f None (Some x)) offsmap2 - in + in LBase.add varid offsetmap acc) m2 all_m1 @@ -299,7 +302,7 @@ with Not_found -> LOffset.is_included_exn LOffset.empty offs2 in - try + try LBase.iter treat_offset1 m1; LBase.iter treat_offset2 m2; true @@ -310,12 +313,12 @@ let r1 = join x y in let r2 = map2 - (fun x y -> - match x,y with - | Some (bx, x), Some (by, y) -> bx || by, V.join x y - | Some (_, x), None | None, Some (_, x) -> true, x - | None, None -> assert false) - x y + (fun x y -> + match x,y with + | Some (bx, x), Some (by, y) -> bx || by, V.join x y + | Some (_, x), None | None, Some (_, x) -> true, x + | None, None -> assert false) + x y in if not (is_included r1 r2 && is_included r2 r1) then begin @@ -356,9 +359,9 @@ Top -> Top | Map m -> let result = - LBase.fold (fun k v acc -> if f k then LBase.add k v acc else acc) - m - LBase.empty + LBase.fold (fun k v acc -> if f k then LBase.add k v acc else acc) + m + LBase.empty in Map result @@ -372,9 +375,9 @@ let base = Base.create_varinfo v in let (i1,i2) = match Base.validity base with - | Base.Periodic(i1, _, p) -> - assert (Int.is_zero i1); - i1, Int.pred p + | Base.Periodic(i1, _, p) -> + assert (Int.is_zero i1); + i1, Int.pred p | Base.Unknown (i1,i2) | Base.Known(i1,i2) -> (i1,i2) | Base.All -> assert false (* not supposed to happen for a local*) @@ -393,7 +396,7 @@ Zone.Top _, _ | _, Top -> LOffset.empty | Zone.Map _, Map m -> let treat_offset varid offs acc = - let default = V.default varid in + let default = V.default varid in let offsetmap = try LBase.find varid m @@ -410,16 +413,16 @@ | Zone.Top _, _ | _, Top -> V.top | Zone.Map _, Map m -> let treat_offset varid offs acc = - let default = V.default varid in - let offsetmap = - try - LBase.find varid m - with Not_found -> - LOffset.empty - in - V.join - (LOffset.find_iset default (V.defaultall varid) offs offsetmap) - acc + let default = V.default varid in + let offsetmap = + try + LBase.find varid m + with Not_found -> + LOffset.empty + in + V.join + (LOffset.find_iset default (V.defaultall varid) offs offsetmap) + acc in Zone.fold_i treat_offset loc V.bottom @@ -429,34 +432,34 @@ match loc, m with | Zone.Top _, _ | _, Top -> V.top | Zone.Map _, Map m -> - let treat_offset varid offs (zone,unchanged) = - let default = V.default varid in - let offsetmap, this_base_unchanged = - try - LBase.find varid m, false - with Not_found -> - LOffset.empty, true - in - let new_zone = - V.join - (LOffset.find_iset default (V.defaultall varid) offs offsetmap) - zone - in - new_zone, (this_base_unchanged && unchanged) + let treat_offset varid offs (zone,unchanged) = + let default = V.default varid in + let offsetmap, this_base_unchanged = + try + LBase.find varid m, false + with Not_found -> + LOffset.empty, true + in + let new_zone = + V.join + (LOffset.find_iset default (V.defaultall varid) offs offsetmap) + zone + in + new_zone, (this_base_unchanged && unchanged) in let zone, unchanged = Zone.fold_i treat_offset loc (V.bottom, true) in - if unchanged then raise Zone_unchanged; - zone + if unchanged then raise Zone_unchanged; + zone let copy_offsetmap ~f src_loc m = let result = begin - begin + begin try let size = Int_Base.project src_loc.size in - begin + begin let treat_src k_src i_src (acc : LOffset.t option) = - let validity = Base.validity k_src in + let validity = Base.validity k_src in try let offsetmap_src = LBase.find_or_default k_src m in (* Format.printf @@ -467,25 +470,25 @@ Ival.fold (fun start acc -> let stop = Int.pred (Int.add start size) in - match validity with - | Base.Periodic _ -> - raise Bitwise_cannot_copy - | (Base.Known (b,e) | Base.Unknown (b,e)) when Int.lt start b - || Int.gt stop e -> - acc - | Base.Known _ | Base.All | Base.Unknown _ -> - let default = V.default k_src in - let copy = - LOffset.real_copy ~f:(Some (f, default)) - offsetmap_src start stop - in - let r = match acc with - | None -> Some copy - | Some acc -> let r = LOffset.join copy acc in - if LOffset.is_empty r then - raise Not_found; + match validity with + | Base.Periodic _ -> + raise Bitwise_cannot_copy + | (Base.Known (b,e) | Base.Unknown (b,e)) when Int.lt start b + || Int.gt stop e -> + acc + | Base.Known _ | Base.All | Base.Unknown _ -> + let default = V.default k_src in + let copy = + LOffset.real_copy ~f:(Some (f, default)) + offsetmap_src start stop + in + let r = match acc with + | None -> Some copy + | Some acc -> let r = LOffset.join copy acc in + if LOffset.is_empty r then + raise Not_found; Some r - in r) + in r) i_src acc with @@ -504,15 +507,15 @@ (*CilE.warn_once "reading unknown location(2)@ @[%a@]" Location_Bits.pretty src_loc.loc;*) LOffset.empty - end - with - | Location_Bits.Error_Top (* from Location_Bits.fold *) - | Not_less_than (* from Ival.cardinal_less_than *) - | Int_Base.Error_Top (* from Int_Base.project *) - | Ival.Error_Top (* from Ival.fold *) -> - LOffset.empty + end + with + | Location_Bits.Error_Top (* from Location_Bits.fold *) + | Not_less_than (* from Ival.cardinal_less_than *) + | Int_Base.Error_Top (* from Int_Base.project *) + | Ival.Error_Top (* from Ival.fold *) -> + LOffset.empty - end + end end in (* Format.printf "copy_offsetmap: m:%a src:%a result:%a@\n" @@ -522,58 +525,59 @@ result -(* TODO: in order for copy_paste to be able to handle a semi-valid [dst_loc], - this function needs to have a ~with_alarms argument *) - let paste_offsetmap map_to_copy dst_loc start size m = + let paste_offsetmap ~with_alarms map_to_copy dst_loc start size m = let dst_is_exact = - Locations.valid_cardinal_zero_or_one - (Locations.make_loc dst_loc (Int_Base.inject size)) + Locations.valid_cardinal_zero_or_one ~for_writing:true + (Locations.make_loc dst_loc (Int_Base.inject size)) in let stop = Int.pred (Int.add start size) in let had_non_bottom = ref false in - let plevel = Parameters.Dynamic.Int.get "-plevel" in + let plevel = (Kernel.ArrayPrecisionLevel.get()) in let treat_dst k_dst i_dst (acc_lmap : LBase.t) = - let validity = Base.validity k_dst in - let offsetmap_dst = LBase.find_or_default k_dst m in - let new_offsetmap = - try - ignore - (Ival.cardinal_less_than i_dst plevel); - Ival.fold - (fun start_to acc -> - let stop_to = Int.pred (Int.add start_to size) in - match validity with - | Base.Periodic _ -> - raise Bitwise_cannot_copy - | Base.Known (b,e) | Base.Unknown (b,e) when Int.lt start_to b || Int.gt stop_to e -> - CilE.warn_mem_write CilE.warn_all_mode; - acc - | Base.Known _ | Base.All | Base.Unknown _ -> - had_non_bottom := true; - (if dst_is_exact - then LOffset.copy_paste ~f:None - else LOffset.copy_merge) - map_to_copy - start - stop - start_to - acc) - i_dst - offsetmap_dst - with Not_less_than -> - raise Bitwise_cannot_copy - in - LBase.add k_dst new_offsetmap acc_lmap + if Base.is_read_only k_dst + then acc_lmap + else + let validity = Base.validity k_dst in + let offsetmap_dst = LBase.find_or_default k_dst m in + let new_offsetmap = + try + ignore + (Ival.cardinal_less_than i_dst plevel); + Ival.fold + (fun start_to acc -> + let stop_to = Int.pred (Int.add start_to size) in + match validity with + | Base.Periodic _ -> + raise Bitwise_cannot_copy + | Base.Known (b,e) | Base.Unknown (b,e) + when Int.lt start_to b || Int.gt stop_to e -> + CilE.warn_mem_write with_alarms; + acc + | Base.Known _ | Base.All | Base.Unknown _ -> + had_non_bottom := true; + (if dst_is_exact + then LOffset.copy_paste ~f:None + else LOffset.copy_merge) + map_to_copy + start + stop + start_to + acc) + i_dst + offsetmap_dst + with Not_less_than -> + raise Bitwise_cannot_copy + in + LBase.add k_dst new_offsetmap acc_lmap in try let result = Location_Bits.fold_i treat_dst dst_loc m in - if not !had_non_bottom - then begin - ignore (CilE.warn_once - "all target addresses were invalid. This path is assumed to be dead."); + if !had_non_bottom then result + else begin + Kernel.warning ~once:true ~current:true + "all target addresses were invalid. This path is assumed to be dead."; assert false - end - else result + end with Location_Bits.Error_Top -> (* from Location_Bits.fold_i *) raise Bitwise_cannot_copy @@ -589,18 +593,18 @@ try let size = Int_Base.project src_loc.size in let result = - copy_offsetmap ~f src_loc mm + copy_offsetmap ~f src_loc mm in paste_offsetmap result dst_loc.loc Int.zero size mm with | Int_Base.Error_Top (* from Int_Base.project *) -> - raise Bitwise_cannot_copy + raise Bitwise_cannot_copy - let copy_paste ~f src_loc dst_loc mm = + let copy_paste ~with_alarms ~f src_loc dst_loc mm = let res = match mm with - Top -> Top - | Map mm -> Map (copy_paste_map ~f src_loc dst_loc mm) + Top -> Top + | Map mm -> Map (copy_paste_map ~with_alarms ~f src_loc dst_loc mm) in (* Format.printf "Lmap.copy_paste orig: %a from src:%a to dst:%a result:%a@\n" pretty mm diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/lmap_bitwise.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_bitwise.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/lmap_bitwise.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_bitwise.mli 2011-10-10 08:38:30.000000000 +0000 @@ -59,7 +59,7 @@ val map_and_merge : (y -> y) -> t -> t -> t (** [map_and_merge f m1 m2] maps [f] on values in [m1] and [add_exact] - all elements of the mapped [m1] to [m2] *) + all elements of the mapped [m1] to [m2] *) val filter_base : (Base.t -> bool) -> t -> t val find : t -> Zone.t -> y @@ -72,17 +72,20 @@ val fold : (Zone.t -> bool * y -> 'a -> 'a) -> t -> 'a -> 'a (** [fold f m] folds a function [f] on bindings in [m]. Each binding - associates to a zone a boolean representing the possibility that the - zone was not modified, and a value of type y. May raise - [Cannot_fold]. *) + associates to a zone a boolean representing the possibility that the + zone was not modified, and a value of type y. May raise + [Cannot_fold]. *) val fold_base : (Base.t -> LOffset.t -> 'a -> 'a) -> t -> 'a -> 'a val map2 : ((bool * y) option -> (bool * y) option -> bool * y) -> t -> t -> t (** like for [fold], the boolean in [bool * y] indicates if it is possible - that the zone was not modified *) + that the zone was not modified *) - val copy_paste : f:(bool * y -> bool * y) -> location -> location -> t -> t + val copy_paste : + with_alarms:CilE.warn_mode -> + f:(bool * y -> bool * y) -> + location -> location -> t -> t (** This function takes a function [f] to be applied to each bit of the read slice. Otherwise, it has the same specification as [copy_paste] for [Location_map.copy_paste]. It may raise diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/lmap.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/lmap.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap.ml 2011-10-10 08:38:30.000000000 +0000 @@ -35,16 +35,15 @@ module Make (Default_offsetmap : sig val default_offsetmap : Base.t -> loffset end) : sig - module LBase : - sig + module LBase : + sig type t val iter : (Base.base -> loffset -> unit) -> t -> unit end type tt = private Bottom | Top | Map of LBase.t - include Datatype.S with type t = tt + include Datatype.S with type t = tt type widen_hint = bool * Base.Set.t * (Base.t -> widen_hint_offsetmap) - type instanciation = Location_Bytes.t Base.Map.t val inject : Base.t -> loffset -> t @@ -62,17 +61,16 @@ val join : t -> t -> location list * t val is_included : t -> t -> bool - val is_included_actual_generic : - Zone.t -> t -> t -> instanciation val top: t + val is_top: t -> bool (** Empty map. Casual users do not need this.*) val empty_map : t val is_empty_map : t -> bool (** Every location is associated to [VALUE.bottom] in [bottom]. - This state can be reached only in dead code. *) + This state can be reached only in dead code. *) val bottom : t val is_reachable : t -> bool @@ -88,14 +86,19 @@ val reduce_binding : with_alarms:CilE.warn_mode -> t -> location -> y -> t - val copy_paste : location -> location -> t -> t + val copy_paste : + with_alarms:CilE.warn_mode -> location -> location -> t -> t val paste_offsetmap : - loffset -> Location_Bits.t -> Int.t -> Int.t -> t -> t + with_alarms:CilE.warn_mode -> + from:loffset -> + dst_loc:Location_Bits.t -> + start:Int.t -> + size:Int.t -> + exact:bool -> + t -> t val copy_offsetmap : with_alarms:CilE.warn_mode -> location -> t -> loffset option - val compute_actual_final_from_generic : - t -> t -> Zone.t -> instanciation -> t*Location_Bits.Top_Param.t val is_included_by_location_enum : t -> t -> Zone.t -> bool @@ -104,18 +107,18 @@ val fold: size:Int.t -> (location -> y -> 'a -> 'a) -> t -> 'a -> 'a (** @raise [Invalid_argument "Lmap.fold"] if one location is not aligned - or of size different of [size]. *) + or of size different of [size]. *) val fold_single_bindings: size:Int.t -> (location -> y -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_base f m] calls [f] on all bases bound to non top offsetmaps in - the non bottom map [m]. - @raise [Error_Bottom] if [m] is bottom.*) + the non bottom map [m]. + @raise [Error_Bottom] if [m] is bottom.*) val fold_base : (Base.t -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_base_offsetmap f m] calls [f] on all bases bound to non top - offsetmaps in the non bottom map [m]. - @raise [Error_Bottom] if [m] is bottom.*) + offsetmaps in the non bottom map [m]. + @raise [Error_Bottom] if [m] is bottom.*) val fold_base_offsetmap : (Base.t -> loffset -> 'a -> 'a) -> t -> 'a -> 'a val find_offsetmap_for_location : Location_Bits.t -> t -> loffset @@ -129,8 +132,8 @@ val equal_subtree : subtree -> subtree -> bool (** [reciprocal_image m b] is the set of bits in the map [m] that may lead - to Top([b]) and the location in [m] where one may read an address - [b]+_ *) + to Top([b]) and the location in [m] where one may read an address + [b]+_ *) val reciprocal_image : Base.t -> t -> Zone.t*Location_Bits.t (* val create_initialized_var : @@ -180,19 +183,19 @@ module LBase = struct module Comp = - struct - let f base offsetmap = - match Base.validity base with - Base.Known (b, e) | Base.Unknown (b, e) when - Int.lt (Int.sub e b) Int.onethousand -> - LOffset.cardinal_zero_or_one (Base.validity base) offsetmap - | Base.Known _ | Base.Unknown _ - | Base.Periodic _ | Base.All -> false - - let compose a b = a && b - let e = true - let default = true - end + struct + let f base offsetmap = + match Base.validity base with + Base.Known (b, e) | Base.Unknown (b, e) when + Int.lt (Int.sub e b) Int.onethousand -> + LOffset.cardinal_zero_or_one (Base.validity base) offsetmap + | Base.Known _ | Base.Unknown _ + | Base.Periodic _ | Base.All -> false + + let compose a b = a && b + let e = true + let default = true + end module Initial_Values = struct let v = [ [] ] end @@ -201,28 +204,30 @@ (LOffset) (Comp) (Initial_Values) + (struct let l = [ Ast.self ] end) + let add k v m = - if LOffset.equal v (default_offsetmap k) then + if LOffset.equal v (default_offsetmap k) then remove k m - else add k v m + else add k v m let find_or_default varid map = - try - find varid map - with Not_found -> default_offsetmap varid + try + find varid map + with Not_found -> default_offsetmap varid end exception Found_prefix = LBase.Found_prefix type tt = - | Bottom + | Bottom | Top | Map of LBase.t let equal m1 m2 = match m1, m2 with - | Bottom, Bottom -> true + | Bottom, Bottom -> true | Top, Top -> true | Map m1, Map m2 -> m1 == m2 | _ -> false @@ -235,7 +240,7 @@ type subtree = LBase.subtree let find_prefix m p = match m with - Map m -> LBase.find_prefix m p + Map m -> LBase.find_prefix m p | Top | Bottom -> None let equal_subtree = LBase.equal_subtree let hash_subtree = LBase.hash_subtree @@ -249,8 +254,6 @@ | Bottom, (Top | Map _) | Top, Map _ -> -1 | Map _, (Top | Bottom) | Top, Bottom -> 1 - type instanciation = Location_Bytes.t Base.Map.t - let empty_map = Map LBase.empty let hash = function @@ -261,39 +264,40 @@ let pretty fmt m = Format.fprintf fmt "@["; (match m with - Bottom -> Format.fprintf fmt "NOT ACCESSIBLE" + Bottom -> Format.fprintf fmt "NOT ACCESSIBLE" | Map m -> LBase.iter (fun base offs -> - let typ = Base.typeof base in - Format.fprintf fmt "@[%a@[%a@]@\n@]" Base.pretty base + let typ = Base.typeof base in + Format.fprintf fmt "@[%a@[%a@]@\n@]" Base.pretty base (LOffset.pretty_typ typ) offs) m | Top -> Format.fprintf fmt "NO INFORMATION"); Format.fprintf fmt "@]" include Datatype.Make - (struct - type t = tt - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| LBase.packed_descr |] |]) - let name = LOffset.name ^ " lmap" - let reprs = Bottom :: Top :: List.map (fun b -> Map b) LBase.reprs - let equal = equal - let compare = compare - let hash = hash - let pretty = pretty - let internal_pretty_code = Datatype.undefined - let rehash = Datatype.identity - let copy = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) + (struct + type t = tt + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum [| [| LBase.packed_descr |] |]) + let name = LOffset.name ^ " lmap" + let reprs = Bottom :: Top :: List.map (fun b -> Map b) LBase.reprs + let equal = equal + let compare = compare + let hash = hash + let pretty = pretty + let internal_pretty_code = Datatype.undefined + let rehash = Datatype.identity + let copy = Datatype.undefined + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project + end) let () = Type.set_ml_name ty None let top = Top let bottom = Bottom + let is_top x = equal top x exception Error_Bottom @@ -307,8 +311,8 @@ add_offsetmap base offsetmap empty_map let is_empty_map = function - Bottom -> assert false - | Top -> assert false + Bottom -> assert false + | Top -> assert false | Map m -> LBase.is_empty m let filter_base f m = @@ -317,8 +321,8 @@ | Bottom -> assert false | Map m -> Map - (LBase.fold - (fun k v acc -> if f k then LBase.add k v acc else acc) + (LBase.fold + (fun k v acc -> if f k then LBase.add k v acc else acc) m LBase.empty) @@ -363,16 +367,16 @@ | Top -> Format.fprintf fmt "NO INFORMATION" | Map m -> let filter_it base _itvs () = - if refilter base - then + if refilter base + then let offs = LBase.find_or_default base m in Format.fprintf fmt "@[%a@[%a@]@\n@]" Base.pretty base (LOffset.pretty_typ (Base.typeof base)) offs in - try - Zone.fold_topset_ok filter_it filter () - with Zone.Error_Top -> + try + Zone.fold_topset_ok filter_it filter () + with Zone.Error_Top -> Format.fprintf fmt "Cannot filter: dumping raw memory (including unchanged variables)@\n%a@\n" pretty mm @@ -387,65 +391,68 @@ Bottom -> assert false | Top -> assert false | Map map -> - try - let varid, ival = Location_Bits.find_lonely_binding loc.loc in - let b = Ival.project_int ival in - let size = Int_Base.project loc.size in - let offsetmap_orig = LBase.find_or_default varid map in - Map - (LBase.add - varid - (LOffset.add_whole (b, Int.pred(Int.add b size)) v offsetmap_orig) - map) - with - Ival.Not_Singleton_Int -> assert false - | Not_found -> - Format.printf "add_whole:Not_found; loc=%a@." - Locations.pretty loc; - raise Not_a_proper_location - | Int_Base.Error_Top -> Format.printf "add_whole:Int_Base" ; - raise Not_a_proper_location + try + let varid, ival = Location_Bits.find_lonely_binding loc.loc in + let b = Ival.project_int ival in + let size = Int_Base.project loc.size in + let offsetmap_orig = LBase.find_or_default varid map in + Map + (LBase.add + varid + (LOffset.add_whole (b, Int.pred(Int.add b size)) v offsetmap_orig) + map) + with + Ival.Not_Singleton_Int -> assert false + | Not_found -> + Format.printf "add_whole:Not_found; loc=%a@." + Locations.pretty loc; + raise Not_a_proper_location + | Int_Base.Error_Top -> Format.printf "add_whole:Int_Base" ; + raise Not_a_proper_location let remove_whole loc map = match map with Bottom -> assert false | Top -> assert false | Map map -> - try - let size = Int_Base.project loc.size in - let treat_base base ival acc = - let offsetmap_orig = LBase.find_or_default base map in - match ival with - | Ival.Set o -> - let offsetmap = - Ival.O.fold - (fun offs acc -> - LOffset.remove_whole - (offs, Int.pred(Int.add offs size)) - acc) - o - offsetmap_orig - in - LBase.add base offsetmap acc - | Ival.Top (Some min,Some max,_r,_modu) -> - let offsetmap = - LOffset.remove_whole - (min, Int.pred(Int.add max size)) - offsetmap_orig - in - LBase.add base offsetmap acc - | Ival.Top (_,_,_,_) -> - LBase.remove base acc - | Ival.Float _ -> assert false - in - let new_map = - Location_Bits.fold_i treat_base loc.loc map - in - Map new_map - with - Int_Base.Error_Top -> assert false - - let add_binding_offsetmap ~with_alarms ~exact varid offsets size v map = + try + let size = Int_Base.project loc.size in + let treat_base base ival acc = + let offsetmap_orig = LBase.find_or_default base map in + match ival with + | Ival.Set o -> + let o = Ival.set_of_array o in + let offsetmap = + Ival.O.fold + (fun offs acc -> + LOffset.remove_whole + (offs, Int.pred(Int.add offs size)) + acc) + o + offsetmap_orig + in + LBase.add base offsetmap acc + | Ival.Top (Some min,Some max,_r,_modu) -> + let offsetmap = + LOffset.remove_whole + (min, Int.pred(Int.add max size)) + offsetmap_orig + in + LBase.add base offsetmap acc + | Ival.Top (_,_,_,_) -> + LBase.remove base acc + | Ival.Float _ -> assert false + in + let new_map = + Location_Bits.fold_i treat_base loc.loc map + in + Map new_map + with + Int_Base.Error_Top -> assert false + + let add_binding_offsetmap ~reducing ~with_alarms ~exact varid offsets size v map = + if (not reducing) && (Base.is_read_only varid) + then raise Offsetmap.Result_is_bottom; match size with | Int_Base.Top -> let offsetmap_orig = LBase.find_or_default varid map in @@ -465,13 +472,13 @@ offsets;*) let validity = Base.validity varid in begin - match validity with + match validity with | Base.Unknown _ -> CilE.warn_mem_write with_alarms | _ -> () end; let new_offsetmap = LOffset.update_ival ~with_alarms ~validity - ~exact ~offsets ~size offsetmap_orig v + ~exact ~offsets ~size offsetmap_orig v in LBase.add varid new_offsetmap map @@ -482,7 +489,7 @@ | Map mem -> Map (LBase.add base (LOffset.create_initial ~v ~modu) mem) - let add_binding ~with_alarms ~exact initial_mem {loc=loc ; size=size } v = + let add_binding ?reducing:(reducing=false) ~with_alarms ~exact initial_mem {loc=loc ; size=size } v = (*Format.printf "add_binding: loc:%a@\n" Location_Bits.pretty loc;*) if V.equal v V.bottom then Bottom else match initial_mem with @@ -492,73 +499,80 @@ let result = (match loc with | Location_Bits.Top (Location_Bits.Top_Param.Top, orig) -> - (match with_alarms.imprecision_tracing with + (match with_alarms.imprecision_tracing with | Aignore -> () | Acall f -> f () - | Alog -> warn_once - "writing at a completely unknown address because of @[%a@]@\nAborting." - Origin.pretty orig); - warn_mem_write with_alarms; - (* Format.printf "dumping memory : %a@\n" pretty initial_mem;*) - top (* the map where every location maps to top *) + | Alog _ -> + Kernel.warning ~current:true ~once:true + "writing at a completely unknown address because of \ + @[%a@]@\nAborting." + Origin.pretty orig); + warn_mem_write with_alarms; + (* Format.printf "dumping memory : %a@\n" pretty initial_mem;*) + top (* the map where every location maps to top *) | Location_Bits.Top (Location_Bits.Top_Param.Set set, origin) -> - warn_mem_write with_alarms; - let treat_base varid acc = - match Base.validity varid with - | (Base.Known (b,e)|Base.Unknown (b,e)) when Int.lt e b -> - acc - | Base.Unknown _ | Base.Known _ | Base.Periodic _ - | Base.All -> - let offsetmap = LBase.find_or_default varid mem in - let offsetmap = - LOffset.overwrite offsetmap v origin - in - LBase.add varid offsetmap acc - in - let result = - Map (Location_Bits.Top_Param.O.fold treat_base set - (treat_base Base.null mem)) - in - (* Format.printf "debugging add_binding topset, loc =%a, result=%a@." - Location_Bits.pretty loc - pretty result; *) - result + warn_mem_write with_alarms; + let treat_base varid acc = + if (not reducing) && (Base.is_read_only varid) + then acc + else + match Base.validity varid with + | (Base.Known (b,e)|Base.Unknown (b,e)) when Int.lt e b -> + acc + | Base.Unknown _ | Base.Known _ | Base.Periodic _ + | Base.All -> + let offsetmap = LBase.find_or_default varid mem in + let offsetmap = + LOffset.overwrite offsetmap v origin + in + LBase.add varid offsetmap acc + in + let result = + Map (Location_Bits.Top_Param.O.fold treat_base set + (treat_base Base.null mem)) + in + (* Format.printf "debugging add_binding topset, loc =%a, result=%a@." + Location_Bits.pretty loc + pretty result; *) + result | Location_Bits.Map loc_map -> - (* Format.printf "add_binding size:%a@\n" - Int_Base.pretty size;*) - let had_non_bottom = ref false in - let result = Location_Bits.M.fold - (fun varid offsets map -> - try + (* Format.printf "add_binding size:%a@\n" + Int_Base.pretty size;*) + let had_non_bottom = ref false in + let result = Location_Bits.M.fold + (fun varid offsets map -> + try let r = - add_binding_offsetmap + add_binding_offsetmap ~reducing ~with_alarms ~exact - varid - offsets - size - v - map - in + varid + offsets + size + v + map + in had_non_bottom := true; r with Offsetmap.Result_is_bottom -> CilE.warn_mem_write with_alarms; map) - loc_map - mem - in - if !had_non_bottom - then Map result - else begin + loc_map + mem + in + if !had_non_bottom + then Map result + else begin (match with_alarms.imprecision_tracing with - (* another field would be appropriate here TODO *) + (* another field would be appropriate here TODO *) | Aignore -> () | Acall f -> f () - | Alog -> warn_once - "all target addresses were invalid. This path is assumed to be dead."); + | Alog _ -> + Kernel.warning ~current:true ~once:true + "all target addresses were invalid. This path is \ +assumed to be dead."); bottom - end) + end) in result @@ -567,101 +581,107 @@ match mem with | Bottom -> V.bottom | Top | Map _ -> - let find_base base = - ( match mem with - Map mem -> LBase.find_or_default base mem - | Top -> LOffset.empty - | Bottom -> assert false ) - in - let handle_imprecise_base base acc = - let validity = Base.validity base in - begin - match validity with - | Base.All -> () - | Base.Known _ | Base.Unknown _ | Base.Periodic _ -> - CilE.warn_mem_read with_alarms - end; - let offsetmap = find_base base in - let new_v = - LOffset.find_imprecise_entire_offsetmap - ~validity - offsetmap - in - V.join new_v acc - in + let find_base base = + ( match mem with + Map mem -> LBase.find_or_default base mem + | Top -> LOffset.empty + | Bottom -> assert false ) + in + let handle_imprecise_base base acc = + let validity = Base.validity base in + begin + match validity with + | Base.All -> () + | Base.Known _ | Base.Unknown _ | Base.Periodic _ -> + CilE.warn_mem_read with_alarms + end; + let offsetmap = find_base base in + let new_v = + LOffset.find_imprecise_entire_offsetmap + ~validity + offsetmap + in + V.join new_v acc + in begin match loc with - | Location_Bits.Top (topparam,_orig) -> - assert (size <> Int_Base.bottom); - begin try - Location_Bits.Top_Param.fold - handle_imprecise_base - topparam - (handle_imprecise_base Base.null V.bottom) - with Location_Bits.Top_Param.Error_Top -> V.top - end - | Location_Bits.Map loc_map -> - begin match size with - | Int_Base.Bottom -> V.bottom - | Int_Base.Top -> - begin try - Location_Bits.M.fold - (fun base _offsetmap acc -> - handle_imprecise_base base acc) - loc_map - V.bottom - with Location_Bits.Top_Param.Error_Top -> V.top - end - | Int_Base.Value size -> - Location_Bits.M.fold - (fun base offsets acc -> - let validity = Base.validity base in - begin - match validity with - | Base.Unknown _ -> CilE.warn_mem_read with_alarms - | _ -> () - end; - let offsetmap = find_base base in - (*Format.printf "offsetmap(%a):%a@\noffsets:%a@\nsize:%a@\n" - Base.pretty base - (LOffset.pretty None) offsetmap - Ival.pretty offsets - Int.pretty size;*) - let new_v = - LOffset.find_ival - ~conflate_bottom - ~validity - ~with_alarms - offsets - offsetmap - size - in - (* Format.printf "find got:%a@\n" V.pretty new_v; *) - V.join new_v acc) - loc_map - V.bottom - end - end + | Location_Bits.Top (topparam,_orig) -> + assert (size <> Int_Base.bottom); + begin try + Location_Bits.Top_Param.fold + handle_imprecise_base + topparam + (handle_imprecise_base Base.null V.bottom) + with Location_Bits.Top_Param.Error_Top -> V.top + end + | Location_Bits.Map loc_map -> + begin match size with + | Int_Base.Bottom -> V.bottom + | Int_Base.Top -> + begin try + Location_Bits.M.fold + (fun base _offsetmap acc -> + handle_imprecise_base base acc) + loc_map + V.bottom + with Location_Bits.Top_Param.Error_Top -> V.top + end + | Int_Base.Value size -> + Location_Bits.M.fold + (fun base offsets acc -> + let validity = Base.validity base in + begin + match validity with + | Base.Unknown _ -> CilE.warn_mem_read with_alarms + | _ -> () + end; + let offsetmap = find_base base in + (*Format.printf "offsetmap(%a):%a@\noffsets:%a@\nsize:%a@\n" + Base.pretty base + (LOffset.pretty None) offsetmap + Ival.pretty offsets + Int.pretty size;*) + let new_v = + LOffset.find_ival + ~conflate_bottom + ~validity + ~with_alarms + offsets + offsetmap + size + in + (* Format.printf "find got:%a@\n" V.pretty new_v; *) + V.join new_v acc) + loc_map + V.bottom + end + end in result -(* XXXXXXXXX bug with uninitialized values *) +(* XXXXXXXXX bug with uninitialized values ? *) let reduce_binding ~with_alarms initial_mem ({loc=_loc ; size=_size } as l) v = assert - (if not (Locations.valid_cardinal_zero_or_one l) - then begin - Format.printf "Internal error 835; debug info:@\n%a@." - Locations.pretty l; - false - end - else - true); + (if not (Locations.valid_cardinal_zero_or_one ~for_writing:false l) + then begin + Format.printf "Internal error 835; debug info:@\n%a@." + Locations.pretty l; + false + end + else + true); let v_old = find ~conflate_bottom:true ~with_alarms initial_mem l in - let v = V.narrow v_old v in - add_binding ~exact:true - ~with_alarms - initial_mem l v + if V.equal v v_old + then initial_mem + else + let v = V.narrow v_old v in + add_binding ~reducing:true ~exact:true + ~with_alarms + initial_mem l v + + let add_binding = add_binding ~reducing:false + (* Format.printf "reduce_binding: loc:%a@\n" Location_Bits.pretty loc; if V.equal v V.bottom then None else @@ -670,43 +690,43 @@ | Some mem -> (match loc, size with | Location_Bits.Map loc_map, Int_Base.Value size -> - Format.printf "reduce_bindi@."; - assert (Location_Bits.cardinal_zero_or_one loc); - begin - try - let map = - Location_Bits.M.fold - (fun varid offsets map -> - let old_offsetmap = LBase.find varid map in - let new_offsetmap = - LOffset.reduce - offsets - ~size - v - old_offsetmap - in - Format.printf "reduce_binding: %a =====> %a@." - LOffset.pretty old_offsetmap - LOffset.pretty new_offsetmap; - LBase.add varid new_offsetmap map - ) - loc_map - mem - in - Some map - with Offsetmap.Result_is_bottom -> + Format.printf "reduce_bindi@."; + assert (Location_Bits.cardinal_zero_or_one loc); + begin + try + let map = + Location_Bits.M.fold + (fun varid offsets map -> + let old_offsetmap = LBase.find varid map in + let new_offsetmap = + LOffset.reduce + offsets + ~size + v + old_offsetmap + in + Format.printf "reduce_binding: %a =====> %a@." + LOffset.pretty old_offsetmap + LOffset.pretty new_offsetmap; + LBase.add varid new_offsetmap map + ) + loc_map + mem + in + Some map + with Offsetmap.Result_is_bottom -> (match with_alarms.imprecision_tracing with - (* another field would be appropriate here TODO *) + (* another field would be appropriate here TODO *) | Aignore -> () | Acall f -> f () | Alog -> warn_once - "Reducing state to bottom. This path is assumed to be dead."); + "Reducing state to bottom. This path is assumed to be dead."); bottom - | Offsetmap.Result_is_same -> initial_mem + | Offsetmap.Result_is_same -> initial_mem - end - | Location_Bits.Top _,_ | _, (Int_Base.Top | Int_Base.Bottom) -> - assert false) + end + | Location_Bits.Top _,_ | _, (Int_Base.Top | Int_Base.Bottom) -> + assert false) *) @@ -722,7 +742,7 @@ | Some mem -> match loc with | Location_Bits.Top _ -> - LBase.fold + LBase.fold (fun _varid offsetmap acc -> LOffset.concerned_bindings_ival ~offsetmap ~offsets:Ival.top ~size:Int.one acc) @@ -730,7 +750,7 @@ [] | Location_Bits.Map loc_map -> Location_Bits.M.fold - (fun varid offsets acc -> + (fun varid offsets acc -> let offsets,size = match size with | Int_Base.Top -> Ival.top,Int.one @@ -740,8 +760,8 @@ let offsetmap = LBase.find_or_default varid mem in LOffset.concerned_bindings_ival ~offsetmap ~offsets ~size acc) - loc_map - [] + loc_map + [] in result *) let join_internal = @@ -749,7 +769,7 @@ snd (LOffset.join v1 (default_offsetmap base)) in let decide_some v1 v2 = - snd (LOffset.join v1 v2) + snd (LOffset.join v1 v2) in let symetric_merge = LBase.symetric_merge ~cache:("lmap",65536) ~decide_none ~decide_some in @@ -760,14 +780,14 @@ (* Format.printf "lmap join@." ; *) let result = match mm1, mm2 with - Bottom,m | m,Bottom -> [], m + Bottom,m | m,Bottom -> [], m | Top, _ | _, Top -> [], Top | Map m1, Map m2 -> - if m1 == m2 - then [], mm1 - else - let r = join_internal m1 m2 in - r + if m1 == m2 + then [], mm1 + else + let r = join_internal m1 m2 in + r in (* Format.printf "lmap.join %a %a -ZZZZ-> %a@." pretty mm1 @@ -792,12 +812,12 @@ fun (m1:t) (m2:t) -> match m1,m2 with Bottom,_ -> true | _,Bottom -> false - | _, Top -> true | Top, _ -> false + | _, Top -> true | Top, _ -> false | Map m1,Map m2 -> - try + try generic_is_included m1 m2; true - with + with Is_not_included -> false let find_offsetmap_for_location loc m = @@ -825,107 +845,29 @@ (LOffset.pretty None) result;*) result - (* [is_included_actual_generic bases actual generic] - returns [i] if the hidden variables of [generic] can - be instanciated with an instanciation [i] so that [actual] - is included in "[i(generic)]". Raises [Is_not_included] - if the instanciation was not found. *) - let is_included_actual_generic inouts (actual:t) (generic:t) = - match actual, generic with - | Bottom, _ -> Base.Map.empty - | _, Bottom -> raise Is_not_included - | Top, _ | _, Top -> assert false - | Map actual_m, Map generic_m -> - let bases = - try - Zone.fold_bases - Base.Set.add - inouts - Base.Set.empty - with Zone.Error_Top -> raise Is_not_included - in - let q = ref bases in - let instanciation = ref Base.Map.empty in - while not (Base.Set.is_empty !q) - do -(* Format.printf - "Lmap.is_included_actual_generic queue: %a@\n inst %a@\n" - Base.Set.pretty !q - (Base.Poly_map.pretty Location_Bytes.pretty) !instanciation; *) - try - let base = Base.Set.choose !q in -(* Format.printf "Lmap.is_included_actual_generic elt: %a@\n" - Base.pretty base;*) - q := Base.Set.remove base !q; - let unreduced_actual = - if Base.is_hidden_variable base then - let instance = - Base.Map.find base !instanciation - in - let instance_bits = loc_bytes_to_loc_bits instance in - find_offsetmap_for_location - instance_bits - actual - else - LBase.find_or_default base actual_m - in - let unreduced_generic = LBase.find_or_default base generic_m in - let offsmap_actual, offsmap_generic = - match inouts with - | Zone.Map m -> - let int_intervals = Zone.find_or_bottom base m in - LOffset.reduce_by_int_intervals - unreduced_actual - int_intervals, - LOffset.reduce_by_int_intervals - unreduced_generic - int_intervals - | Zone.Top _ -> - unreduced_actual, unreduced_generic - in - -(* Format.printf - "Lmap.is_included_actual_generic offsmap_actual: %a@\n" - (LOffset.pretty_debug) offsmap_actual; *) -(* Format.printf - "Lmap.is_included_actual_generic offsmap_generic: %a@\n" - (LOffset.pretty_debug) offsmap_generic;*) - LOffset.is_included_actual_generic - bases - q - instanciation - offsmap_actual - offsmap_generic; -(* Format.printf - "Lmap.is_included_actual_generic: There was inclusion@\n" *) - with Not_found (* from Base.Poly_map.find *) -> () - (* we'll do [base] when it is instanciated *) - done; - !instanciation - let is_included_by_location_enum m1 m2 locs = if Zone.equal locs Zone.bottom then true else match locs with | Zone.Top _ -> is_included m1 m2 | Zone.Map locs -> match m1, m2 with - | Top, _ | _, Top -> assert false + | Top, _ | _, Top -> assert false | Bottom ,_ -> assert false | _, Bottom -> assert false | Map m1, Map m2 -> let treat_offset varid offs2 = - try - ignore (Zone.find_or_bottom varid locs); - (* at this point varid is present in locs *) + try + ignore (Zone.find_or_bottom varid locs); + (* at this point varid is present in locs *) let offs1 = LBase.find_or_default varid m1 in LOffset.is_included_exn offs1 offs2 with Not_found -> () (* varid not in locs *) in try - LBase.iter treat_offset m2; - true + LBase.iter treat_offset m2; + true with - Is_not_included -> false + Is_not_included -> false (* let top = empty @@ -956,13 +898,13 @@ if fixed then (m_done, LBase.remove key m_remain) else - let new_off = LOffset.widen (wh_hints key) offs1 offs2 - in + let new_off = LOffset.widen (wh_hints key) offs1 offs2 + in LBase.add key new_off m_done, LBase.empty) - wh_key_set - (m2, m2) + wh_key_set + (m2, m2) in - let fixed_for_all_wh_key = not (LBase.is_empty m_remain) in + let fixed_for_all_wh_key = not (LBase.is_empty m_remain) in (* Format.printf "widening (widen_other_keys=%b, fixed_for_all_wh_key %b)@." widen_other_keys fixed_for_all_wh_key; *) if widen_other_keys @@ -970,7 +912,7 @@ let other_keys_widened = Map (LBase.fold - (fun base offs2 acc -> + (fun base offs2 acc -> (* Format.printf "widening also on key %a@." Base.pretty base; *) let offs1 = LBase.find_or_default base m1 in @@ -978,8 +920,8 @@ LOffset.widen (wh_hints base) offs1 offs2 in LBase.add base new_off acc) - m_remain - m_done) + m_remain + m_done) in true, other_keys_widened else @@ -987,103 +929,105 @@ in result -(* TODO: in order for copy_paste to be able to handle a semi-valid [dst_loc], - this function needs to have a ~with_alarms argument *) - let paste_offsetmap map_to_copy dst_loc start size m = + let paste_offsetmap ~with_alarms ~from:map_to_copy ~dst_loc ~start ~size ~exact m = match m with | Bottom | Top -> assert false | Map m -> - let dst_is_exact = - Locations.valid_cardinal_zero_or_one - (Locations.make_loc dst_loc (Int_Base.inject size)) - in - let stop = Int.pred (Int.add start size) in - let had_non_bottom = ref false in - let plevel = Parameters.Dynamic.Int.get "-plevel" in - let treat_dst k_dst i_dst (acc_lmap : LBase.t) = - let validity = Base.validity k_dst in - let offsetmap_dst = LBase.find_or_default k_dst m in - let new_offsetmap = + let dst_is_exact = + exact && + Locations.valid_cardinal_zero_or_one ~for_writing:true + (Locations.make_loc dst_loc (Int_Base.inject size)) + in + let stop = Int.pred (Int.add start size) in + let had_non_bottom = ref false in + let plevel = Kernel.ArrayPrecisionLevel.get() in + let treat_dst k_dst i_dst (acc_lmap : LBase.t) = + if Base.is_read_only k_dst + then acc_lmap + else + let validity = Base.validity k_dst in + let offsetmap_dst = LBase.find_or_default k_dst m in + let new_offsetmap = + try + ignore (Ival.cardinal_less_than i_dst plevel); + Ival.fold + (fun start_to acc -> + let stop_to = Int.pred (Int.add start_to size) in + match validity with + | Base.Periodic _ -> raise Cannot_copy + | Base.Known (b,e) + | Base.Unknown (b,e) + when Int.lt start_to b || Int.gt stop_to e -> + CilE.warn_mem_write with_alarms; + acc + | Base.Known _ | Base.All | Base.Unknown _ -> + had_non_bottom := true; + (if dst_is_exact then LOffset.copy_paste + else LOffset.copy_merge) + map_to_copy + start + stop + start_to + acc) + i_dst + offsetmap_dst + with Not_less_than -> + raise Cannot_copy + in + LBase.add k_dst new_offsetmap acc_lmap + in try - ignore (Ival.cardinal_less_than i_dst plevel); - Ival.fold - (fun start_to acc -> - let stop_to = Int.pred (Int.add start_to size) in - match validity with - | Base.Periodic _ -> raise Cannot_copy - | Base.Known (b,e) - | Base.Unknown (b,e) when Int.lt start_to b || Int.gt stop_to e -> - CilE.warn_mem_write CilE.warn_all_mode; - acc - | Base.Known _ | Base.All | Base.Unknown _ -> - had_non_bottom := true; - (if dst_is_exact then LOffset.copy_paste - else LOffset.copy_merge) - map_to_copy - start - stop - start_to - acc) - i_dst - offsetmap_dst - with Not_less_than -> - raise Cannot_copy - in - LBase.add k_dst new_offsetmap acc_lmap - in - try - let result = Location_Bits.fold_i treat_dst dst_loc m in - if not !had_non_bottom - then begin - ignore (CilE.warn_once - "all target addresses were invalid. This path is assumed to be dead."); - bottom - end - else Map result - with Location_Bits.Error_Top -> (* from Location_Bits.fold_i *) - raise Cannot_copy + let result = Location_Bits.fold_i treat_dst dst_loc m in + if !had_non_bottom then Map result + else begin + Kernel.warning ~once:true ~current:true + "all target addresses were invalid. This path is assumed to be dead."; + bottom + end + with Location_Bits.Error_Top -> (* from Location_Bits.fold_i *) + raise Cannot_copy let copy_offsetmap ~with_alarms src_loc mm = match mm with | Bottom -> None | Top -> Some LOffset.empty | Map m -> - begin + begin try let size = Int_Base.project src_loc.size in - try + try begin let treat_src k_src i_src (acc : LOffset.t option) = - let validity = Base.validity k_src in + let validity = Base.validity k_src in let offsetmap_src = LBase.find_or_default k_src m in - let copy = - LOffset.copy_ival - ~validity - ~with_alarms - i_src - offsetmap_src - size - in - match acc with - | None -> Some copy - | Some acc -> - let r = snd (LOffset.join copy acc) in - if LOffset.is_empty r then - raise Not_found; + let copy = + LOffset.copy_ival + ~validity + ~with_alarms + i_src + offsetmap_src + size + in + match acc with + | None -> Some copy + | Some acc -> + let r = snd (LOffset.join copy acc) in + if LOffset.is_empty r then + raise Not_found; Some r in Location_Bits.fold_i treat_src src_loc.loc None - end + end with - | Location_Bits.Error_Top (* from Location_Bits.fold *) + | Location_Bits.Error_Top (* from Location_Bits.fold *) | Cannot_copy (* from LOffset.copy_ival *) -> - let v = - find ~conflate_bottom:false ~with_alarms - mm src_loc - in + let v = + find ~conflate_bottom:false ~with_alarms + mm src_loc + in Some - (LOffset.update_ival + (LOffset.update_ival ~with_alarms:warn_none_mode ~validity:Base.All ~exact:true @@ -1091,13 +1035,13 @@ ~size LOffset.empty v) - with - | Int_Base.Error_Top (* from Int_Base.project *) -> + with + | Int_Base.Error_Top (* from Int_Base.project *) -> Some LOffset.empty end - let copy_paste src_loc dst_loc mm = + let copy_paste ~with_alarms src_loc dst_loc mm = assert (Int_Base.equal src_loc.size dst_loc.size ); (* temporary fix *) @@ -1108,14 +1052,14 @@ try let size = Int_Base.project src_loc.size in let result = - copy_offsetmap ~with_alarms:warn_none_mode src_loc mm in + copy_offsetmap ~with_alarms:warn_none_mode src_loc mm in match result with | Some result -> - paste_offsetmap result dst_loc.loc Int.zero size mm + paste_offsetmap with_alarms result dst_loc.loc Int.zero size true mm | None -> bottom with | Int_Base.Error_Top (* from Int_Base.project *) -> - raise Cannot_copy + raise Cannot_copy let fold ~size f m acc = match m with @@ -1177,93 +1121,6 @@ m acc - let compute_actual_final_from_generic - actual_orig generic_final filter instanciation = - match generic_final with - | Bottom -> - Bottom, (* the called function does not terminate *) - Location_Bits.Top_Param.bottom - | Top -> assert false - | Map generic_finalcontent -> - let actual_orig = - match actual_orig with - Map x -> x - | Bottom | Top -> assert false - in - try - let result, clobbered = - Zone.fold_i - (fun base itvs (acc,clobbered_acc) -> - let new_offsetmap = - LBase.find_or_default base generic_finalcontent - in - let new_acc = - if Base.is_hidden_variable base - then - let instance = - try - Base.Map.find base instanciation - with Not_found -> - Format.printf - "Internal error: hidden variable %a appears in generic state but not in instanciation@." - Base.pretty base; - assert false - in - let instance_bits = loc_bytes_to_loc_bits instance in - begin try - let instance_base, instance_offset = - Location_Bits.find_lonely_binding instance_bits - in - let instance_offset = Ival.project_int instance_offset in - let original_offsetmap = - LBase.find_or_default instance_base actual_orig - in - let shifted_original = - LOffset.shift (Int.neg instance_offset) - original_offsetmap - in - let merged_offsetmap = - LOffset.merge_by_itv - shifted_original - new_offsetmap - itvs - in - let shifted_back_result = - LOffset.shift - instance_offset - merged_offsetmap - in - (* Format.printf "caffg: shifted original:%a@\nnew:%a@\nresult:%a@\n" - (LOffset.pretty None) shifted_original - (LOffset.pretty None) new_offsetmap - (LOffset.pretty None) shifted_back_result; *) - LBase.add instance_base shifted_back_result acc - with Not_found | Ival.Not_Singleton_Int -> - assert false (* TODO: is it possible to be more general?*) - end - else begin - let original_offsemap = - LBase.find_or_default base actual_orig - in - let merged_offsetmap = - LOffset.merge_by_itv original_offsemap new_offsetmap itvs - in - LBase.add base merged_offsetmap acc - end - in - new_acc, - Location_Bits.Top_Param.join - (Location_Bits.Top_Param.inject_singleton base) - clobbered_acc) - filter - (actual_orig,Location_Bits.Top_Param.bottom) - in - Map result, clobbered - with Zone.Error_Top -> - generic_final, (* [filter] is [top] *) - Location_Bits.Top_Param.top - - let reciprocal_image base m = (*: Base.t -> t -> Zone.t*Location_Bits.t*) match m with | Bottom -> assert false @@ -1287,19 +1144,20 @@ | Top -> assert false | Bottom -> raise Error_Bottom | Map mm -> - (cached_f mm) + (cached_f mm) let cached_map ~f ~cache ~temporary = let cached_f = LBase.cached_map ~f ~cache ~temporary in function - Bottom -> Bottom + Bottom -> Bottom | Top -> assert false | Map mm -> - Map (cached_f mm) + Map (cached_f mm) end + end (* diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/lmap.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/lmap.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap.mli 2011-10-10 08:38:30.000000000 +0000 @@ -38,18 +38,17 @@ module Make (Default_offsetmap: sig val default_offsetmap : Base.t -> loffset end): sig - module LBase : - sig + module LBase : + sig type t val iter : (Base.base -> loffset -> unit) -> t -> unit end type tt = private Bottom | Top | Map of LBase.t - include Datatype.S with type t = tt + include Datatype.S with type t = tt type widen_hint = bool * Base.Set.t * (Base.t -> widen_hint_offsetmap) - type instanciation = Location_Bytes.t Base.Map.t val inject : Base.t -> loffset -> t @@ -66,9 +65,9 @@ val join : t -> t -> location list * t val is_included : t -> t -> bool - val is_included_actual_generic : Zone.t -> t -> t -> instanciation val top: t + val is_top: t -> bool (** Empty map. Casual users do not need this.*) val empty_map : t @@ -96,20 +95,29 @@ which everything present in [src] has been copied onto [dst]. [src] and [dst] must have the same size. The write operation is exact iff [dst] is exact. - @raise Cannot_copy if copy is not possible. *) - val copy_paste : location -> location -> t -> t + @raise Cannot_copy if copy is not possible. *) + val copy_paste : + with_alarms:CilE.warn_mode -> location -> location -> t -> t + + (** [paste_offsetmap ~from:offmap ~dst_loc ~start ~size ~exact m] + copies [size] bits starting at [start] in [offmap], and pastes + them at [dst_loc] in [m]. The copy is exact if and only if + [dst_loc] is exact, and [exact is true] - (** @raise Cannot_copy if copy is not possible. *) + @raise Cannot_copy if copy is not possible. *) val paste_offsetmap : - loffset -> Location_Bits.t -> Int.t -> Int.t -> t -> t + with_alarms:CilE.warn_mode -> + from:loffset -> + dst_loc:Location_Bits.t -> + start:Int.t -> + size:Int.t -> + exact:bool -> + t -> t (** May return [None] as a bottom loffset. *) val copy_offsetmap : with_alarms:CilE.warn_mode -> Locations.location -> t -> loffset option - val compute_actual_final_from_generic : - t -> t -> Locations.Zone.t -> instanciation -> t*Location_Bits.Top_Param.t - val is_included_by_location_enum : t -> t -> Locations.Zone.t -> bool (** @raise Invalid_argument if one location is not aligned or of size @@ -118,13 +126,13 @@ val fold : size:Int.t -> (location -> y -> 'a -> 'a) -> t -> 'a -> 'a (** @raise Invalid_argument "Lmap.fold" if one location is not aligned - or of size different of [size]. - @raise Error_Bottom if [m] is bottom. *) + or of size different of [size]. + @raise Error_Bottom if [m] is bottom. *) val fold_single_bindings : size:Int.t -> (location -> y -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_base f m] calls [f] on all bases bound to non top - offsetmaps in the non bottom map [m]. + offsetmaps in the non bottom map [m]. @raise Error_Bottom if [m] is bottom. *) val fold_base : (Base.t -> 'a -> 'a) -> t -> 'a -> 'a @@ -147,6 +155,7 @@ to Top([b]) and the location in [m] where one may read an address [b]+_ *) val reciprocal_image : Base.t -> t -> Zone.t*Location_Bits.t + (* val create_initialized_var : Cil_types.varinfo -> Base.validity -> loffset -> Base.t @@ -176,10 +185,10 @@ module Make_LOffset (VALUE:Lattice_With_Isotropy.S) (LOffset:Offsetmap.S with type y = VALUE.t - and type widen_hint = VALUE.widen_hint) : + and type widen_hint = VALUE.widen_hint) : Location_map with type y = VALUE.t - and type widen_hint_offsetmap = VALUE.widen_hint - and type loffset = LOffset.t + and type widen_hint_offsetmap = VALUE.widen_hint + and type loffset = LOffset.t (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/lmap_whole.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_whole.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/lmap_whole.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_whole.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,975 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Abstract_interp -open Abstract_value -open Locations -open CilE - -exception Cannot_copy - -module Make_LOffset - (V:Lattice_With_Isotropy.S)(LOffset:Offsetmap.S with type y = V.t) = -struct - - type y = V.t - type widen_hint_offsetmap = V.widen_hint -(* module LOffset = Offsetmap.Make(V) *) - - module Make - (Default_offsetmap: sig val default_offsetmap : Base.t -> LOffset.t end) = - struct - - open Default_offsetmap - - module LBase = struct - - include Hptmap.Make - (Base) - (LOffset) - (Hptmap.Comp_unused) - (struct let v = [ [] ] end) - - let add k v m = - if LOffset.equal v (default_offsetmap k) then - remove k m - else add k v m - - let find_or_default varid map = - try - find varid map - with Not_found -> default_offsetmap varid - end - - include Datatype.Option(LBase) (* [None] is bottom *) - - type instanciation = Location_Bytes.t Base.Map.t - - let empty = Some LBase.empty - - let pretty fmt m = - Format.fprintf fmt "@["; - (match m with None -> Format.fprintf fmt "NOT ACCESSIBLE" - | Some m -> - LBase.iter - (fun base offs -> - Format.fprintf fmt "@[%a@[%a@]@\n@]" Base.pretty base - (LOffset.pretty_typ (Base.typeof base)) offs) - m); - Format.fprintf fmt "@]" - - let top = empty - let bottom = None - - let inject base offsetmap = - let result = - Some (LBase.add base offsetmap LBase.empty) - in -(* Format.printf "%a %a -YYYY-> %a@." - Base.pretty base - LOffset.pretty offsetmap - pretty result ; *) - result - - let is_empty = function - None -> assert false - | Some m -> LBase.is_empty m - - let filter_base f m = - match m with None -> None - | Some m -> - Some - (LBase.fold - (fun k v acc -> if f k then LBase.add k v acc else acc) - m - LBase.empty) - - let find_base (vi:LBase.key) (m:t) = - match m with - | None -> raise Not_found - | Some m -> LBase.find vi m - - let is_reachable t = - match t with - None -> false - | Some _ -> true - - - - let pretty_without_null fmt m = - Format.fprintf fmt "@["; - (match m with None -> Format.fprintf fmt "NOT ACCESSIBLE" - | Some m -> - LBase.iter - (fun base offs -> - if not (Base.is_null base) then - Format.fprintf fmt "@[%a@[%a@]@\n@]" Base.pretty base - (LOffset.pretty_typ (Base.typeof base)) offs) - m); - Format.fprintf fmt "@]" - - - (* Display only locations in [filter]. Enforce the display of Top for - bases not in [m] but in [filter] *) - let pretty_filter fmt mm filter = - Format.fprintf fmt "@["; - (match mm with - | None -> Format.fprintf fmt "NON TERMINATING FUNCTION" - | Some m -> - let filter_it base _itvs () = - let offs = LBase.find_or_default base m in - Format.fprintf fmt "@[%a@[%a@]@\n@]" - Base.pretty base - (LOffset.pretty_typ (Base.typeof base)) offs - in - try - Zone.fold_topset_ok filter_it filter () - with Zone.Error_Top -> - Format.fprintf fmt - "Cannot filter: dumping raw memory (including unchanged variables)@\n%a@\n" - pretty mm - ); - Format.fprintf fmt "@]" - - - exception Not_a_proper_location - - let add_whole loc v map = - match map with - None -> assert false - | Some map -> - try - let varid, ival = Location_Bits.find_lonely_binding loc.loc in - let b = Ival.project_int ival in - let size = Int_Base.project loc.size in - let offsetmap_orig = LBase.find_or_default varid map in - Some - (LBase.add - varid - (LOffset.add_whole (b, Int.pred(Int.add b size)) v offsetmap_orig) - map) - with - Ival.Not_Singleton_Int -> assert false - | Not_found -> - Format.printf "add_whole:Not_found; loc=%a@." - Locations.pretty loc; - raise Not_a_proper_location - | Int_Base.Error_Top -> Format.printf "add_whole:Int_Base" ; - raise Not_a_proper_location - - let remove_whole loc map = - match map with - None -> assert false - | Some map -> - try - let size = Int_Base.project loc.size in - let treat_base base ival acc = - let offsetmap_orig = LBase.find_or_default base map in - match ival with - | Ival.Set o -> - let offsetmap = - Ival.O.fold - (fun offs acc -> - LOffset.remove_whole - (offs, Int.pred(Int.add offs size)) - acc) - o - offsetmap_orig - in - LBase.add base offsetmap acc - | Ival.Top (Some min,Some max,_r,_modu) -> - let offsetmap = - LOffset.remove_whole - (min, Int.pred(Int.add max size)) - offsetmap_orig - in - LBase.add base offsetmap acc - | Ival.Top (_,_,_,_) -> - LBase.remove base acc - | Ival.Float _ -> assert false - in - let new_map = - Location_Bits.fold_i treat_base loc.loc map - in - Some new_map - with - Int_Base.Error_Top -> empty - - let add_binding_offsetmap ~with_alarms ~exact varid offsets size v map = - match size with - | Int_Base.Top -> - let offsetmap_orig = LBase.find_or_default varid map in - let new_offsetmap = - LOffset.overwrite offsetmap_orig v - (Origin.Arith (LocationSetLattice.currentloc_singleton())) - in - LBase.add varid new_offsetmap map - - | Int_Base.Bottom -> assert false - | Int_Base.Value size -> - assert (Int.gt size Int.zero); - let offsetmap_orig = LBase.find_or_default varid map in - (*Format.printf "add_binding_offsetmap varid:%a offset:%a@\n" - Base.pretty varid - Ival.pretty - offsets;*) - let validity = Base.validity varid in - begin - match validity with - | Base.Unknown _ -> CilE.warn_mem_write with_alarms - | _ -> () - end; - let new_offsetmap = - LOffset.update_ival ~with_alarms ~validity - ~exact ~offsets ~size offsetmap_orig v - in - LBase.add varid new_offsetmap map - - let create_initial ~base ~v ~modu ~state = - match state with - | None -> state - | Some mem -> - Some (LBase.add base (LOffset.create_initial ~v ~modu) mem) - - let add_binding ~with_alarms ~exact initial_mem {loc=loc ; size=size } v = - (*Format.printf "add_binding: loc:%a@\n" Location_Bits.pretty loc;*) - if V.equal v V.bottom then None else - match initial_mem with - | None -> initial_mem - | Some mem -> - let result = - (match loc with - | Location_Bits.Top (Location_Bits.Top_Param.Top, orig) -> - (match with_alarms.imprecision_tracing with - | Aignore -> () - | Acall f -> f () - | Alog -> warn_once - "writing at a completely unknown address because of @[%a@]@\nAborting." - Origin.pretty orig); - CilE.warn_mem_write with_alarms; - (* Format.printf "dumping memory : %a@\n" pretty initial_mem;*) - empty (* the map where every location maps to top *) - | Location_Bits.Top (Location_Bits.Top_Param.Set set, origin) -> - warn_mem_write with_alarms; - let treat_base varid acc = - match Base.validity varid with - | Base.Known (b,e)| Base.Unknown (b,e) when Int.lt e b -> acc - | Base.Unknown _ | Base.Known _ | Base.All - | Base.Periodic _ -> - let offsetmap = LBase.find_or_default varid mem in - let offsetmap = - LOffset.overwrite offsetmap v origin - in - LBase.add varid offsetmap acc - in - let result = - Some (Location_Bits.Top_Param.O.fold treat_base set - (treat_base Base.null mem)) - in - (* Format.printf "debugging add_binding topset, loc =%a, result=%a@." - Location_Bits.pretty loc - pretty result; *) - result - | Location_Bits.Map loc_map -> - (* Format.printf "add_binding size:%a@\n" - Int_Base.pretty size;*) - let had_non_bottom = ref false in - let result = Location_Bits.M.fold - (fun varid offsets map -> - try - let r = - add_binding_offsetmap - ~with_alarms - ~exact - varid - offsets - size - v - map - in - had_non_bottom := true; - r - with Offsetmap.Result_is_bottom -> - warn_mem_write with_alarms; - (* Cil.warn "out-of-bound update"; - Format.printf "base:%a offsets:%a@." - Base.pretty varid - Ival.pretty offsets; *) - map) - loc_map - mem - in - if !had_non_bottom then Some result else begin - (match with_alarms.imprecision_tracing with - | Aignore -> () - | Acall f -> f () - | Alog -> warn_once - "all target addresses were invalid. This path is assumed to be dead."); - bottom - end) - in - result - - let find ~with_alarms mem ({ loc = loc ; size = size } as _sloc) = - let result = - match mem with - | None -> V.bottom - | Some mem -> - match size with - | Int_Base.Top -> V.top - | Int_Base.Bottom -> V.bottom - | Int_Base.Value size -> - match loc with - | Location_Bits.Top (topparam,_orig) -> - let f varid acc = - (*Format.eprintf "Vid:%a@." Base.pretty varid;*) - let validity = Base.validity varid in - begin - match validity with - | Base.Unknown _ -> CilE.warn_mem_read with_alarms - | _ -> () - end; - let offsetmap = - LBase.find_or_default varid mem - in - let new_v = - LOffset.find_ival - ~conflate_bottom:true - ~validity - ~with_alarms - Ival.top - offsetmap - size - in - (*Format.eprintf "Vid:%a=%a@." Base.pretty varid V.pretty new_v;*) - V.join new_v acc - in - begin try - Location_Bits.Top_Param.fold - f - topparam - (f Base.null V.bottom) - with Location_Bits.Top_Param.Error_Top -> V.top - end - | Location_Bits.Map loc_map -> - Location_Bits.M.fold - (fun varid offsets acc -> - let validity = Base.validity varid in - begin - match validity with - | Base.Unknown _ -> CilE.warn_mem_read with_alarms - | _ -> () - end; - let offsetmap = - LBase.find_or_default varid mem - in - (*Format.printf "offsetmap(%a):%a@\noffsets:%a@\nsize:%a@\n" - Base.pretty varid - (LOffset.pretty None) offsetmap - Ival.pretty offsets - Int.pretty size;*) - let new_v = - LOffset.find_ival - ~conflate_bottom:true - ~validity - ~with_alarms - offsets - offsetmap - size - in - (* Format.printf "find got:%a@\n" V.pretty new_v; *) - V.join new_v acc) - loc_map - V.bottom - in - if V.equal result V.bottom then begin - (* ignore (CilE.warn_once "no legal value found. This branch should be dead. Degenerating."); - Reactivate this warning when this is a not a user access (from GUI) - *) - V.bottom - end - else result - - let concerned_bindings mem { loc = loc ; size = size } = - let result = - match mem with - | None -> [] - | Some mem -> - match loc with - | Location_Bits.Top _ -> - LBase.fold - (fun _varid offsetmap acc -> - LOffset.concerned_bindings_ival - ~offsetmap ~offsets:Ival.top ~size:Int.one acc) - mem - [] - | Location_Bits.Map loc_map -> - Location_Bits.M.fold - (fun varid offsets acc -> - let offsets,size = - match size with - | Int_Base.Top -> Ival.top,Int.one - | Int_Base.Bottom -> assert false - | Int_Base.Value size -> offsets,size - in - let offsetmap = LBase.find_or_default varid mem in - LOffset.concerned_bindings_ival - ~offsetmap ~offsets ~size acc) - loc_map - [] - in result - - let join_internal = - let decide_none base v1 = - snd (LOffset.join v1 (default_offsetmap base)) - in - let decide_some v1 v2 = - snd (LOffset.join v1 v2) - in - let symetric_merge = - LBase.symetric_merge ~cache:("lmap",65536) ~decide_none ~decide_some in - fun m1 m2 -> - Some (symetric_merge m1 m2) - - let join mm1 mm2 = - let result = - match mm1, mm2 with - None,m | m,None -> m - | Some m1, Some m2 -> - if m1 == m2 - then mm1 - else - let r = join_internal m1 m2 in - r - in -(* Format.printf "lmap.join %a %a -ZZZZ-> %a@." - pretty mm1 - pretty mm2 - pretty result;*) - result - -let is_included = - let decide_fst base v1 = - LOffset.is_included_exn v1 (default_offsetmap base) - in - let decide_snd base v2 = - LOffset.is_included_exn (default_offsetmap base) v2 - in - let decide_both = LOffset.is_included_exn - in - let generic_is_included = - LBase.generic_is_included Abstract_interp.Is_not_included - ~cache:("lmap", 16384) - ~decide_fst ~decide_snd ~decide_both - in - fun (m1:t) (m2:t) -> - match m1,m2 with - None,_ -> true | _,None -> false - | Some m1,Some m2 -> - try - generic_is_included m1 m2; - true - with - Is_not_included -> false - - let find_offsetmap_for_location loc m = - let result = try - match m with - | None -> assert false - | Some m -> - Cilutil.out_some - (Location_Bits.fold_i - (fun varid offsets acc -> - LOffset.shift_ival - (Ival.neg offsets) - (LBase.find_or_default varid m) - acc) - loc - None) - with - | Location_Bits.Error_Top (* from [LocBits.fold] *) - | Offsetmap.Found_Top (* from [LOffset.shift_ival] *) - -> LOffset.empty - in - (*Format.printf "find_offsetmap_for_location:%a@\nLEADS TO %a@\n" - Location_Bits.pretty loc - (LOffset.pretty None) result;*) - result - - (* [is_included_actual_generic bases actual generic] - returns [i] if the hidden variables of [generic] can - be instanciated with an instanciation [i] so that [actual] - is included in "[i(generic)]". Raises [Is_not_included] - if the instanciation was not found. *) - let is_included_actual_generic inouts (actual:t) (generic:t) = - match actual, generic with - | None, _ -> Base.Map.empty - | _, None -> raise Is_not_included - | Some actual_m, Some generic_m -> - let bases = - Zone.fold_bases - Base.Set.add - inouts - Base.Set.empty - in - let q = ref bases in - let instanciation = ref Base.Map.empty in - while not (Base.Set.is_empty !q) - do -(* Format.printf - "Lmap.is_included_actual_generic queue: %a@\n inst %a@\n" - Base.Set.pretty !q - (Base.Poly_map.pretty Location_Bytes.pretty) !instanciation; *) - try - let base = Base.Set.choose !q in -(* Format.printf "Lmap.is_included_actual_generic elt: %a@\n" - Base.pretty base;*) - q := Base.Set.remove base !q; - let unreduced_actual = - if Base.is_hidden_variable base - then - let instance = - Base.Map.find base !instanciation - in - let instance_bits = loc_bytes_to_loc_bits instance in - find_offsetmap_for_location - instance_bits - actual - else - LBase.find_or_default base actual_m - in - let unreduced_generic = LBase.find_or_default base generic_m in - let offsmap_actual, offsmap_generic = - match inouts with - | Zone.Map m -> - let int_intervals = Zone.find_or_bottom base m in - LOffset.reduce_by_int_intervals - unreduced_actual - int_intervals, - LOffset.reduce_by_int_intervals - unreduced_generic - int_intervals - | Zone.Top _ -> - unreduced_actual, unreduced_generic - in - -(* Format.printf - "Lmap.is_included_actual_generic offsmap_actual: %a@\n" - (LOffset.pretty_debug) offsmap_actual; *) -(* Format.printf - "Lmap.is_included_actual_generic offsmap_generic: %a@\n" - (LOffset.pretty_debug) offsmap_generic;*) - LOffset.is_included_actual_generic - bases - q - instanciation - offsmap_actual - offsmap_generic; -(* Format.printf - "Lmap.is_included_actual_generic: There was inclusion@\n" *) - with Not_found (* from Base.Poly_map.find *) -> () - (* we'll do [base] when it is instanciated *) - done; - !instanciation - - let is_included_by_location_enum m1 m2 locs = - if Zone.equal locs Zone.bottom then true - else match locs with - | Zone.Top _ -> is_included m1 m2 - | Zone.Map locs -> - match m1, m2 with - | None ,_ -> assert false - | _, None -> assert false - | Some m1, Some m2 -> - let treat_offset varid offs2 = - try - ignore (Zone.find_or_bottom varid locs); - (* at this point varid is present in locs *) - let offs1 = LBase.find_or_default varid m1 - in LOffset.is_included_exn offs1 offs2 - with Not_found -> () (* varid not in locs *) - in - try - LBase.iter treat_offset m2; - true - with - Is_not_included -> false - - let top = empty - - let bottom = None - - (* Precondition : m1 <= m2 *) - type widen_hint = bool * Base.Set.t * (Base.t -> widen_hint_offsetmap) - let widen (widen_other_keys, wh_key_set, wh_hints) r1 r2 = - let result = match r1,r2 with - | None,None -> false, None - | _,None -> assert false (* thanks to precondition *) - | None, m -> false, m - | Some m1,Some m2 -> - let m_done, m_remain = - (* [m_done] = widened state on keys of [wh_key_set]. - if a widening is performed for one of them, - [m_remain] will be empty. - *) - Base.Set.fold - (fun key (m_done, m_remain) -> - let offs2 = LBase.find_or_default key m2 in - let offs1 = LBase.find_or_default key m1 in - let fixed = LOffset.is_included offs2 offs1 in - (* Format.printf "key=%a, fixed=%b@." - Base.pretty key fixed; *) - if fixed - then (m_done, LBase.remove key m_remain) - else - let new_off = LOffset.widen (wh_hints key) offs1 offs2 - in - LBase.add key new_off m_done, LBase.empty) - wh_key_set - (m2, m2) - in let fixed_for_all_wh_key = not (LBase.is_empty m_remain) in - (* Format.printf "widening (widen_other_keys=%b, fixed_for_all_wh_key %b)@." - widen_other_keys fixed_for_all_wh_key; *) - if widen_other_keys - then - let other_keys_widened = - Some - (LBase.fold - (fun base offs2 acc -> - (* Format.printf "widening also on key %a@." - Base.pretty base; *) - let offs1 = LBase.find_or_default base m1 in - let new_off = - LOffset.widen (wh_hints base) offs1 offs2 - in - LBase.add base new_off acc) - m_remain - m_done) - in - true, other_keys_widened - else - fixed_for_all_wh_key, Some m_done - in - result - -(* TODO: in order for copy_paste to be able to handle a semi-valid [dst_loc], - this function needs to have a ~with_alarms argument *) - let paste_offsetmap map_to_copy dst_loc start size m = - let m = Cilutil.out_some m in - let dst_is_exact = - Locations.valid_cardinal_zero_or_one - (Locations.make_loc dst_loc (Int_Base.inject size)) - in - let stop = Int.pred (Int.add start size) in - let had_non_bottom = ref false in - let plevel = Parameters.Dynamic.Int.get "-plevel" in - let treat_dst k_dst i_dst (acc_lmap : LBase.t) = - let validity = Base.validity k_dst in - let offsetmap_dst = LBase.find_or_default k_dst m in - let new_offsetmap = - try - ignore (Ival.cardinal_less_than i_dst plevel); - Ival.fold - (fun start_to acc -> - let stop_to = Int.pred (Int.add start_to size) in - match validity with - | Base.Periodic _ -> raise Cannot_copy - | Base.Known (b,e) | Base.Unknown (b,e) when Int.lt start_to b || Int.gt stop_to e -> - CilE.warn_mem_write CilE.warn_all_mode; - acc - | Base.Known _ | Base.All | Base.Unknown _ -> - had_non_bottom := true; - (if dst_is_exact then LOffset.copy_paste - else LOffset.copy_merge) - map_to_copy - start - stop - start_to - acc) - i_dst - offsetmap_dst - with Not_less_than -> - raise Cannot_copy - in - LBase.add k_dst new_offsetmap acc_lmap - in - try - let result = Location_Bits.fold_i treat_dst dst_loc m in - if not !had_non_bottom - then begin - ignore (CilE.warn_once - "all target addresses were invalid. This path is assumed to be dead."); - bottom - end - else Some result - with Location_Bits.Error_Top -> (* from Location_Bits.fold_i *) - raise Cannot_copy - - let copy_offsetmap src_loc mm = - let result = - begin - let m = Cilutil.out_some mm in - begin - try - let size = Int_Base.project src_loc.size in - begin - let treat_src k_src i_src (acc : LOffset.t option) = - let validity = Base.validity k_src in - try - let offsetmap_src = LBase.find_or_default k_src m in - (* Format.printf - "copy_offsetmap/treat_src k_src:%a i_src:%a@\n" - Base.pretty k_src - Ival.pretty i_src;*) - ignore (Ival.cardinal_less_than i_src 100); - Ival.fold - (fun start acc -> - let stop = Int.pred (Int.add start size) in - match validity with - | Base.Periodic _ -> - raise Not_less_than - | Base.Known (b,e) | Base.Unknown (b,e) when Int.lt start b - || Int.gt stop e -> - acc - | Base.Known _ | Base.All | Base.Unknown _ -> - let copy = - LOffset.copy_offsmap offsetmap_src start stop - in - let r = match acc with - | None -> Some copy - | Some acc -> - let r = snd (LOffset.join copy acc) in - if LOffset.is_empty r then - raise Not_found; - Some r - in r) - i_src - acc - with - | Not_found (* from [LOffset.is_empty] *) - -> - (*CilE.warn_once "reading top in %a. Look above for origin." - Location_Bits.pretty src_loc.loc;*) - Some LOffset.empty - | Not_less_than (* from [Ival.cardinal_less_than] *)-> - (*CilE.warn_once "approximating lval assignment";*) - raise Cannot_copy - in - try - Location_Bits.fold_i treat_src src_loc.loc None - with Location_Bits.Error_Top -> - Some LOffset.empty - end - with - | Location_Bits.Error_Top (* from Location_Bits.fold *) - | Not_less_than (* from Ival.cardinal_less_than *) - | Int_Base.Error_Top (* from Int_Base.project *) - | Ival.Error_Top (* from Ival.fold *) -> - Some LOffset.empty - - end - end - in - (* Format.printf "copy_offsetmap: mm:%a src:%a result:%a@\n" - pretty mm - Locations.pretty src_loc - pretty result; *) - result - - - let copy_paste src_loc dst_loc mm = - assert (Int_Base.equal src_loc.size dst_loc.size ); - -(* temporary fix *) - if not (Locations.can_be_accessed src_loc - && Locations.can_be_accessed dst_loc) - then raise Cannot_copy; - - try - let size = Int_Base.project src_loc.size in - let result = - copy_offsetmap src_loc mm in - match result with - | Some result -> - paste_offsetmap result dst_loc.loc Int.zero size mm - | None -> bottom - with - | Int_Base.Error_Top (* from Int_Base.project *) -> - raise Cannot_copy - - - let fold ~size f m acc = - match m with - | None -> acc - | Some m -> - try - LBase.fold - (fun k v acc -> - LOffset.fold_whole - ~size - (fun ival size v acc -> - let loc = Location_Bits.inject k ival in - f (make_loc loc (Int_Base.inject size)) v acc) - v - acc) - m - acc - with Invalid_argument "Offsetmap.Make.fold" -> - raise (Invalid_argument "Lmap.fold") - - let fold_single_bindings ~size f m acc = - match m with - | None -> acc - | Some m -> - try - LBase.fold - (fun k v acc -> - LOffset.fold_single_bindings - ~size - (fun ival size v acc -> - let loc = Location_Bits.inject k ival in - f (make_loc loc (Int_Base.inject size)) v acc) - v - acc) - m - acc - with Invalid_argument "Offsetmap.Make.fold" -> - raise (Invalid_argument "Lmap.fold") - - let fold_base f m acc = - match m with - | None -> acc - | Some m -> - LBase.fold - (fun k _ acc -> f k acc) - m - acc - - let compute_actual_final_from_generic - actual_orig generic_final filter instanciation = - match generic_final with - | None -> None (* the called function does not terminate *) - | Some generic_finalcontent -> - let actual_orig = Cilutil.out_some actual_orig in - try - Some - (Zone.fold_i - (fun base itvs acc -> - let new_offsetmap = - LBase.find_or_default base generic_finalcontent - in - if Base.is_hidden_variable base then - let instance = - try Base.Map.find base instanciation - with Not_found -> - Format.printf "Internal error: hidden variable %a appears in generic state but not in instanciation@." - Base.pretty base; - assert false - in - let instance_bits = loc_bytes_to_loc_bits instance in - begin try - let instance_base, instance_offset = - Location_Bits.find_lonely_binding instance_bits - in - let instance_offset = Ival.project_int instance_offset in - let original_offsetmap = - LBase.find_or_default instance_base actual_orig - in - let shifted_original = - LOffset.shift (Int.neg instance_offset) - original_offsetmap - in - let merged_offsetmap = - LOffset.merge_by_itv - shifted_original - new_offsetmap - itvs - in - let shifted_back_result = - LOffset.shift - instance_offset - merged_offsetmap - in - (* Format.printf "caffg: shifted original:%a@\nnew:%a@\nresult:%a@\n" - (LOffset.pretty None) shifted_original - (LOffset.pretty None) new_offsetmap - (LOffset.pretty None) shifted_back_result; *) - LBase.add instance_base shifted_back_result acc - with Not_found | Ival.Not_Singleton_Int -> - assert false (* TODO: is it possible to be more general?*) - end - else begin - let original_offsemap = - LBase.find_or_default base actual_orig - in - let merged_offsetmap = - LOffset.merge_by_itv original_offsemap new_offsetmap itvs - in - LBase.add base merged_offsetmap acc - end) - filter - actual_orig) - with Zone.Error_Top -> generic_final (* [filter] is [top] *) - - - let reciprocal_image base m = (*: Base.t -> t -> Zone.t*Location_Bits.t*) - match m with - | None -> assert false - | Some m -> - if Base.is_null base then Zone.top,Location_Bits.top - else - LBase.fold - (fun b offs (acc1,acc2) -> - let interv_set,ival = LOffset.reciprocal_image offs base in - let acc1 = Zone.join acc1 (Zone.inject b interv_set) in - let acc2 = Location_Bits.join acc2 (Location_Bits.inject b ival) in - acc1,acc2) - m - (Zone.bottom,Location_Bits.bottom) - - exception Error_Bottom - - let cached_fold ~f ~cache ~temporary ~joiner ~empty = - let cached_f = LBase.cached_fold ~f ~cache ~temporary ~joiner ~empty - in - function - None -> raise Error_Bottom - | Some mm -> - (cached_f mm) - - - let cached_map ~f ~cache ~temporary = - let cached_f = LBase.cached_map ~f ~cache ~temporary - in - function - None -> None - | Some mm -> - Some (cached_f mm) - - end -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/lmap_whole.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_whole.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/lmap_whole.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/lmap_whole.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Functor making map for whole values with locations as keys *) - -open Abstract_interp -open Abstract_value -open Locations - -exception Cannot_copy - -module Make_LOffset - (VALUE:Lattice_With_Isotropy.S) - (LOffset : Offsetmap.S with type y = VALUE.t - and type widen_hint = VALUE.widen_hint) : -sig - - type y = VALUE.t (** type of the values associated to the locations *) - type widen_hint_offsetmap = VALUE.widen_hint -(* module LOffset : Offsetmap.S with type y = y - and type widen_hint = widen_hint_offsetmap -*) - - module Make - (Default_offsetmap : sig val default_offsetmap : Base.t -> LOffset.t end) : - sig - - include Datatype.S (** the datype of a map *) - - type widen_hint = bool * Base.Set.t * (Base.t -> widen_hint_offsetmap) - type instanciation = Location_Bytes.t Base.Map.t - - val inject : Base.t -> LOffset.t -> t - - val pretty_without_null : Format.formatter -> t -> unit - val pretty_filter : - Format.formatter -> - t -> Locations.Zone.t -> unit - val add_binding : - with_alarms:CilE.warn_mode -> exact:bool -> t -> location -> y -> t - - val find : - with_alarms:CilE.warn_mode -> t -> location -> y - - val concerned_bindings : t -> location -> y list - - val join : t -> t -> t - val is_included : t -> t -> bool - val is_included_actual_generic : Zone.t -> t -> t -> instanciation - - (** Every location is associated to [VALUE.top] in [empty].*) - val empty : t - val is_empty : t -> bool - - (** Every location is associated to [VALUE.bottom] in [bottom]. - This state can be reached only in dead code. *) - val bottom : t - val is_reachable : t -> bool - - val widen : widen_hint-> t -> t -> (bool * t) - val filter_base : (Base.t -> bool) -> t -> t - - (** @raise Not_found if the varid is not present in the map *) - val find_base : Base.t -> t -> LOffset.t - - (** [copy_paste src dst state] returns a modified version of [state] in - which everything present in [src] has been copied onto [dst]. [src] and - [dst] must have the same size. The write operation is exact iff [dst] - is exact. May raise [Cannot_copy]. *) - val copy_paste : location -> location -> t -> t - - (** @raise Cannot_copy when ... *) - val paste_offsetmap : - LOffset.t -> Location_Bits.t -> Int.t -> Int.t -> t -> t - - (** May return [None] as a bottom LOffset.t - @raise Cannot_copy when ...*) - val copy_offsetmap : Locations.location -> t -> LOffset.t option - - val compute_actual_final_from_generic : - t -> t -> Locations.Zone.t -> instanciation -> t - - val is_included_by_location_enum : t -> t -> Locations.Zone.t -> bool - - (** @raise Invalid_argument "Lmap.fold" if one location is not aligned - or of size different of [size]. *) - val fold : size:Int.t -> (location -> y -> 'a -> 'a) -> t -> 'a -> 'a - - (** @raise Invalid_argument "Lmap.fold" if one location is not aligned - or of size different of [size].*) - val fold_single_bindings : - size:Int.t -> (location -> y -> 'a -> 'a) -> t -> 'a -> 'a - - (** [fold_base f m] calls [f] on all bases bound to non top values in [m] *) - val fold_base : (Base.t -> 'a -> 'a) -> t -> 'a -> 'a - - val find_offsetmap_for_location : Location_Bits.t -> t -> LOffset.t - val add_whole: location -> y -> t -> t - val remove_whole: location -> t -> t - - (** [reciprocal_image m b] is the set of bits in the map [m] that may lead - to Top([b]) and the location in [m] where one may read an address - [b]+_ *) - val reciprocal_image : Base.t -> t -> Zone.t*Location_Bits.t - (* - val create_initialized_var : - Cil_types.varinfo -> Base.validity -> LOffset.t -> Base.t - *) - val create_initial : - base:Base.t -> - v:y -> - modu:Int.t -> - state:t -> t - - val cached_fold : - f:(Base.t -> LOffset.t -> 'a) -> - cache:string * int -> temporary:bool -> - joiner:('a -> 'a -> 'a) -> empty:'a -> t -> 'a - - val cached_map : - f:(Base.t -> LOffset.t -> LOffset.t) -> - cache:string * int -> temporary:bool -> - t -> t - - end - -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/locations.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/locations.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/locations.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/locations.ml 2011-10-10 08:38:30.000000000 +0000 @@ -27,19 +27,22 @@ module Initial_Values = struct let v = [ [Base.null,Ival.singleton_zero]; - [Base.null,Ival.singleton_one]; - [Base.null,Ival.zero_or_one]; - [Base.null,Ival.top]; - [Base.null,Ival.top_float]; - [] ] + [Base.null,Ival.singleton_one]; + [Base.null,Ival.zero_or_one]; + [Base.null,Ival.top]; + [Base.null,Ival.top_float]; + [Base.null,Ival.top_single_precision_float]; + [] ] end -module BaseSetLattice = Make_Hashconsed_Lattice_Set(Base) +module BaseSetLattice = Make_Hashconsed_Lattice_Set(Base)(Base.Hptset) module MapLattice = Map_Lattice.Make (Base)(BaseSetLattice)(Ival)(Initial_Values)(struct let zone = false end) +module HT = Hashtbl + module Location_Bytes = struct include MapLattice @@ -69,10 +72,9 @@ let top_leaf_origin () = Top(Top_Param.top, - (Origin.Leaf (LocationSetLattice.currentloc_singleton()))) + (Origin.Leaf (LocationSetLattice.currentloc_singleton()))) let topify_with_origin o v = - let result = match v with | Top (s,a) -> Top (s, Origin.join a o) @@ -80,12 +82,6 @@ | Map m -> if is_bottom v then v else inject_top_origin o (get_bases m) - in -(* Format.printf "topify_with_origin : %a %a -> %a@." - Origin.pretty o - pretty v - pretty result;*) - result let get_bases m = match m with @@ -100,6 +96,41 @@ | Base.Known _ | Base.Unknown _ | Base.All -> true with Not_found -> false + let iter_on_strings = + let z = "\000" in + fun ~skip f l -> + match l with + | Top _ -> + assert false + | Map m -> + M.iter + (fun base offs -> + match skip with + Some base_to_skip when Base.equal base base_to_skip -> () + | _ -> + match base with + Base.String (_, strid) -> + let str = + match Base.get_string strid with + | Base.CSString s -> s + | Base.CSWstring _ -> + failwith "Unimplemented: wide strings" + in + let strz = str ^ z in + let len = String.length str in + let range = + Ival.inject_range + (Some Int.zero) + (Some (Int.of_int len)) + in + let roffs = Ival.narrow range offs in + Ival.fold + (fun i () -> f base strz (Int.to_int i) len) + roffs + () + | _ -> ()) + m + let under_topify v = match v with | Top _ -> v @@ -120,65 +151,11 @@ topify_with_origin (Origin.Arith (LocationSetLattice.currentloc_singleton())) v - let is_included_actual_generic bases q instanciation v1 v2 = - let null_1, v1 = split Base.null v1 in - let null_2, v2 = split Base.null v2 in - Ival.is_included_exn null_1 null_2; - try - (*Format.printf "LB.is_included_actual_generic: v1: %a v2: %a@\n" - pretty v1 - pretty v2; *) - let base, offs = find_lonely_key v2 in - if Base.is_hidden_variable base - then begin - (* Format.printf "LB.is_included_actual_generic: hidden var %a@\n" - Base.pretty base; *) - try - let base_val = Base.Map.find base !instanciation in - if not (cardinal_zero_or_one base_val) - then raise Is_not_included; - if not (equal v1 (location_shift offs base_val)) - then raise Is_not_included; - with Not_found -> - (* check non-aliasing condition between, on the one hand, - the new value for the hidden variable [base] - and on the other hand, the generic in/outs of the function - plus already instanciated hidden variables*) - fold_bases - (fun b () -> - if Base.Set.mem b bases then raise Is_not_included; - Base.Map.fold - (fun _bi vi () -> - fold_bases - (fun vib () -> - (* Format.printf "comparing bases %a %a@." - Base.pretty b - Base.pretty vib;*) - if Base.compare b vib = 0 - then raise Is_not_included) - vi - ()) - !instanciation - ()) - v1 - (); - let new_val = location_shift (Ival.neg offs) v1 in - instanciation := - Base.Map.add base new_val !instanciation; - (* Format.printf "LB.is_included_actual_generic: %a in? %a@\n" - Base.pretty base - BaseSet.pretty bases; *) - if Base.Set.mem base bases then q := Base.Set.add base !q - end - else is_included_exn v1 v2 - with Not_found (* from find_lonely_key *) -> - is_included_exn v1 v2 - let may_reach base loc = if Base.is_null base then true else match loc with | Top (toparam,_) -> - Top_Param.is_included (Top_Param.inject_singleton base) toparam + Top_Param.is_included (Top_Param.inject_singleton base) toparam | Map m -> try ignore (M.find base m); true @@ -206,27 +183,33 @@ assert (match loc with | Top (Top_Param.Top,_) -> true | Top (Top_Param.Set _top_param,_orig) -> - false + false | Map _ -> false); true (** TODO: merge with above function *) let remove_escaping_locals is_local v = match v with - | Top (Top_Param.Top,_) -> v + | Top (Top_Param.Top as t,_) -> t, v | Top (Top_Param.Set topparam,orig) -> - inject_top_origin - orig - (Top_Param.O.filter - (fun base -> not (is_local base)) - topparam) + let locals, nonlocals = + Top_Param.O.partition + is_local + topparam + in + (Top_Param.inject locals), inject_top_origin orig nonlocals | Map m -> - Map (M.fold (fun base _ acc -> - if is_local base then - M.remove base acc - else acc) - m - m) + let locals, clean_map = + M.fold + (fun base _ (locals, m as acc) -> + if is_local base + then + (Top_Param.O.add base locals), M.remove base m + else acc) + m + (Top_Param.O.empty, m) + in + (Top_Param.inject locals), Map clean_map let contains_addresses_of_any_locals = let f base _offsets = Base.is_any_formal_or_local base in @@ -247,10 +230,45 @@ assert (match loc with | Top (Top_Param.Top,_) -> true | Top (Top_Param.Set _top_param,_orig) -> - false + false | Map _ -> false); true + exception Found_overlap + + let partially_overlaps_table = HT.create 7 + let () = + Project.register_todo_before_clear + (fun _ -> HT.clear partially_overlaps_table) + + let partially_overlaps size mm1 mm2 = + match mm1, mm2 with + | Top (_,_), Top (_,_) -> true + | Top _, (Map _ as m) | (Map _ as m), Top _ -> not (equal m bottom) + | Map m1, Map m2 -> + let size_int = Int.to_int size in + try + let map_partially_overlaps = + try + HT.find partially_overlaps_table size_int + with Not_found -> + let f = + M.generic_symetric_existential_predicate + Found_overlap + ~decide_one:(fun _ _ -> ()) + ~decide_both: + (fun x y -> + if Ival.partially_overlaps size x y + then raise Found_overlap) + in + HT.add partially_overlaps_table size_int f; + f + in + map_partially_overlaps m1 m2; + false + with + Found_overlap -> true + end module Location_Bits = Location_Bytes @@ -272,14 +290,14 @@ let pretty fmt m = match m with | Top (Top_Param.Top,a) -> - Format.fprintf fmt "ANYTHING(origin:%a)" - Origin.pretty a + Format.fprintf fmt "ANYTHING(origin:%a)" + Origin.pretty a | Top (s,a) -> - Format.fprintf fmt "Unknown(%a, origin:%a)" - Top_Param.pretty s - Origin.pretty a + Format.fprintf fmt "Unknown(%a, origin:%a)" + Top_Param.pretty s + Origin.pretty a | Map _ when equal m bottom -> - Format.fprintf fmt "\\nothing" + Format.fprintf fmt "\\nothing" | Map off -> let print_binding fmt (k, v) = Format.fprintf fmt "@[%a%a@]" @@ -292,19 +310,19 @@ let pretty_caml fmt m = match m with | Top (Top_Param.Top,a) -> - assert false (* TODO *) + assert false (* TODO *) | Top (s,a) -> - assert false (* TODO *) + assert false (* TODO *) | Map _ when equal m bottom -> - Format.fprintf "Locations.Zone.bottom" + Format.fprintf "Locations.Zone.bottom" | Map off -> - Format.fprintf "Locations.Zone.inject_list ["; - let print_binding k v = - Format.fprintf fmt "@[%a,@ %a;@,]@ " - Base.pretty_caml k + Format.fprintf "Locations.Zone.inject_list ["; + let print_binding k v = + Format.fprintf fmt "@[%a,@ %a;@,]@ " + Base.pretty_caml k Int_Intervals.pretty_caml v - in - (M.iter print_binding) off + in + (M.iter print_binding) off *) let out_some_or_bottom zone = match zone with @@ -322,17 +340,17 @@ let result = match m1,m2 with | Map _, Map _ -> - intersects m1 m2 + intersects m1 m2 | Top (toparam, _), m | m, Top (toparam, _) -> - (equal m bottom) || - let f base () = - if Top_Param.is_included (Top_Param.inject_singleton base) toparam - then raise Found_inter - in - try - fold_bases f m (); - false - with Found_inter | Error_Top -> true + (equal m bottom) || + let f base () = + if Top_Param.is_included (Top_Param.inject_singleton base) toparam + then raise Found_inter + in + try + fold_bases f m (); + false + with Found_inter | Error_Top -> true in result @@ -355,27 +373,6 @@ { loc : Location_Bits.t; size : Int_Base.t } -module Location = - Datatype.Make - (struct - include Datatype.Serializable_undefined - type t = location - let structural_descr = - Structural_descr.t_record - [| Location_Bits.packed_descr; Int_Base.packed_descr |] - let reprs = - List.fold_left - (fun acc l -> - List.fold_left - (fun acc n -> { loc = l; size = n } :: acc) - acc - Int_Base.reprs) - [] - Location_Bits.reprs - let name = "Locations.Location" - let mem_project = Datatype.never_any_project - end) - let can_be_accessed {loc=loc;size=size} = try let size = Int_Base.project size in @@ -386,9 +383,9 @@ (fun varid offset -> match Base.validity varid with | Base.Known (min_valid,max_valid) - | Base.Unknown (min_valid,max_valid) - | Base.Periodic (min_valid, max_valid, _) - -> + | Base.Unknown (min_valid,max_valid) + | Base.Periodic (min_valid, max_valid, _) + -> let min = Ival.min_int offset in begin match min with | None -> raise Not_valid @@ -421,24 +418,24 @@ | Base.Not_valid_offset -> false -let is_valid = is_valid_param Base.is_valid_offset +let is_valid ~for_writing = is_valid_param (Base.is_valid_offset ~for_writing) let is_valid_or_function = is_valid_param (fun size base offs -> if Base.is_function base then (if Ival.is_zero offs then () else raise Base.Not_valid_offset) - else Base.is_valid_offset size base offs) + else Base.is_valid_offset ~for_writing:false size base offs) exception Found_two -let valid_cardinal_zero_or_one {loc=loc;size=size} = +let valid_cardinal_zero_or_one ~for_writing {loc=loc;size=size} = Location_Bits.equal Location_Bits.bottom loc || let found_one = let already = ref false in function () -> - if !already then raise Found_two; - already := true + if !already then raise Found_two; + already := true in try let size = Int_Base.project size in @@ -447,26 +444,28 @@ | Location_Bits.Map m -> Location_Bits.M.iter (fun base offset -> - let inter = - match Base.validity base with - | Base.Known (min_valid,max_valid) - | Base.Unknown (min_valid,max_valid) - | Base.Periodic (min_valid,max_valid, _) - -> - let itv = - Ival.inject_range - (Some min_valid) - (Some (Int.succ (Int.sub max_valid size))) - in - Ival.narrow itv offset - | Base.All -> offset - in - if Ival.cardinal_zero_or_one inter - then begin - if not (Ival.equal inter Ival.bottom) - then found_one () - end - else raise Found_two) + if not (Base.is_read_only base && for_writing) + then + ( let inter = + match Base.validity base with + | Base.Known (min_valid,max_valid) + | Base.Unknown (min_valid,max_valid) + | Base.Periodic (min_valid,max_valid, _) + -> + let itv = + Ival.inject_range + (Some min_valid) + (Some (Int.succ (Int.sub max_valid size))) + in + Ival.narrow itv offset + | Base.All -> offset + in + if Ival.cardinal_zero_or_one inter + then begin + if not (Ival.is_bottom inter) + then found_one () + end + else raise Found_two)) m; true with @@ -482,8 +481,9 @@ match x with | Location_Bytes.Map _ -> begin try - Location_Bytes.map_offsets - (Ival.scale (Bit_utils.sizeofchar())) x + Location_Bytes.map_offsets + (Ival.scale (Bit_utils.sizeofchar())) + x with Location_Bytes.Error_Top -> assert false end | Location_Bytes.Top _ -> x @@ -518,7 +518,7 @@ let size_of_varinfo v = try let s = bitsSizeOf v.vtype in - let s = Big_int.big_int_of_int s in + let s = Int.of_int s in s with Cil.SizeOfError _ as e -> Kernel.debug ~once:true "Variable %a has no size" !Ast_printer.d_var v; @@ -569,111 +569,122 @@ Format.fprintf fmt "%a (size:%a)" Location_Bits.pretty loc Int_Base.pretty size +let pretty_loc = pretty -let valid_enumerate_bits ({loc = loc_bits; size = size} as _arg)= -(* Format.printf "valid_enumerate_bits:%a@\n" pretty _arg; *) +let valid_enumerate_bits ~for_writing ({loc = loc_bits; size = size} as _arg)= + (* Format.printf "valid_enumerate_bits:%a@\n" pretty _arg; *) let result = match loc_bits with - | Location_Bits.Top (Location_Bits.Top_Param.Top, _) -> Zone.top - | Location_Bits.Top (Location_Bits.Top_Param.Set s, _) -> - let compute_offset base acc = + | Location_Bits.Top (Location_Bits.Top_Param.Top, _) -> Zone.top + | Location_Bits.Top (Location_Bits.Top_Param.Set s, _) -> + let compute_offset base acc = + if for_writing && Base.is_read_only base + then acc + else let valid_offset = match Base.validity base, size with | (Base.Known (min_valid,max_valid) - | Base.Unknown (min_valid,max_valid) - | Base.Periodic (min_valid, max_valid, _)), - Int_Base.Value size -> -(* Format.printf "min_valid:%a@\nmax_valid:%a@." - Int.pretty min_valid - Int.pretty max_valid; *) - let max_valid = Int.succ (Int.sub max_valid size) in - Ival.inject_range (Some min_valid) (Some max_valid) + | Base.Unknown (min_valid,max_valid) + | Base.Periodic (min_valid, max_valid, _)), + Int_Base.Value size -> + (* Format.printf "min_valid:%a@\nmax_valid:%a@." + Int.pretty min_valid + Int.pretty max_valid; *) + let max_valid = Int.succ (Int.sub max_valid size) in + Ival.inject_range (Some min_valid) (Some max_valid) | _,Int_Base.Bottom -> assert false - | Base.All,_ | _,Int_Base.Top -> Ival.top - in - if Ival.equal Ival.bottom valid_offset - then acc - else + | Base.All,_ | _,Int_Base.Top -> Ival.top + in + if Ival.is_bottom valid_offset + then acc + else let valid_offset = - Int_Intervals.from_ival_size valid_offset size - in + Int_Intervals.from_ival_size valid_offset size + in Zone.M.add base valid_offset acc - in - Zone.inject_map - (Location_Bits.Top_Param.O.fold compute_offset s Zone.M.empty) - | Location_Bits.Map m -> - let compute_offset base offs acc = + in + Zone.inject_map + (Location_Bits.Top_Param.O.fold compute_offset s Zone.M.empty) + | Location_Bits.Map m -> + let compute_offset base offs acc = + if for_writing && Base.is_read_only base + then acc + else let valid_offset = match Base.validity base, size with | (Base.Known (min_valid,max_valid) - |Base.Unknown (min_valid,max_valid) - |Base.Periodic (min_valid, max_valid, _)), - Int_Base.Value size -> - let max_valid = Int.succ (Int.sub max_valid size) in -(* Format.printf "min_valid:%a@\nmax_valid:%a@." - Int.pretty min_valid - Int.pretty max_valid; *) - Ival.meet - (Ival.inject_range (Some min_valid) (Some max_valid)) - offs - | (Base.All|Base.Unknown _|Base.Known _|Base.Periodic _),_ -> offs - in - if Ival.equal Ival.bottom valid_offset - then acc - else + |Base.Unknown (min_valid,max_valid) + |Base.Periodic (min_valid, max_valid, _)), + Int_Base.Value size -> + let max_valid = Int.succ (Int.sub max_valid size) in + (* Format.printf "min_valid:%a@\nmax_valid:%a@." + Int.pretty min_valid + Int.pretty max_valid; *) + Ival.meet + (Ival.inject_range (Some min_valid) (Some max_valid)) + offs + | (Base.All|Base.Unknown _|Base.Known _|Base.Periodic _),_ -> offs + in + if Ival.is_bottom valid_offset + then acc + else let valid_offset = Int_Intervals.from_ival_size valid_offset size in Zone.M.add base valid_offset acc - in - Zone.inject_map - (Location_Bits.M.fold compute_offset m Zone.M.empty) + in + Zone.inject_map + (Location_Bits.M.fold compute_offset m Zone.M.empty) in -(* Format.printf "valid_enumerate_bits leads to %a@\n" Zone.pretty result; *) - result + (* Format.printf "valid_enumerate_bits leads to %a@\n" Zone.pretty result; *) + result let zone_of_varinfo var = - valid_enumerate_bits (loc_of_varinfo var) + valid_enumerate_bits ~for_writing:false (loc_of_varinfo var) (** [valid_part l] is an over-approximation of the valid part of the location [l] *) -let valid_part ({loc = loc; size = size } as l) = +let valid_part ~for_writing ({loc = loc; size = size } as l) = (* Format.printf "valid_part: loc=%a@." pretty l;*) match loc with | Location_Bits.Top _ -> l | Location_Bits.Map m -> let compute_offset base offs acc = let valid_offset = - match Base.validity base, size with - | (Base.Known (min_valid,max_valid) - |Base.Unknown (min_valid,max_valid) - |Base.Periodic (min_valid, max_valid, _)), - Int_Base.Value size -> - let max_valid = Int.succ (Int.sub max_valid size) in -(* Format.printf "min_valid:%a@\nmax_valid:%a@." - Int.pretty min_valid - Int.pretty max_valid; *) - let valid_ival = - Ival.inject_range (Some min_valid) (Some max_valid) - in - let result = Ival.narrow offs valid_ival in -(* Format.printf "base:%a offs:%a valid:%a result:%a@." - Base.pretty base - Ival.pretty offs - Ival.pretty valid_ival - Ival.pretty result; *) - result - - | (Base.All|Base.Unknown _|Base.Known _|Base.Periodic _),_ -> offs - in - if Ival.equal Ival.bottom valid_offset - then acc - else + if for_writing && (Base.is_read_only base) + then Ival.bottom + else + ( match Base.validity base, size with + | (Base.Known (min_valid,max_valid) + |Base.Unknown (min_valid,max_valid) + |Base.Periodic (min_valid, max_valid, _)), + Int_Base.Value size -> + let max_valid = Int.succ (Int.sub max_valid size) in + (* Format.printf "min_valid:%a@\nmax_valid:%a@." + Int.pretty min_valid + Int.pretty max_valid; *) + let valid_ival = + Ival.inject_range (Some min_valid) (Some max_valid) + in + let result = Ival.narrow offs valid_ival in + (* Format.printf "base:%a offs:%a valid:%a result:%a@." + Base.pretty base + Ival.pretty offs + Ival.pretty valid_ival + Ival.pretty result; *) + result + + | (Base.All|Base.Unknown _|Base.Known _|Base.Periodic _),_ -> + offs) + in + if Ival.is_bottom valid_offset + then acc + else Location_Bits.M.add base valid_offset acc in let loc = - Location_Bits.inject_map + Location_Bits.inject_map (Location_Bits.M.fold compute_offset m Location_Bits.M.empty) - in - make_loc loc size + in + make_loc loc size (** [invalid_part l] is an over-approximation of the invalid part of the location [l] *) @@ -684,13 +695,13 @@ let invalid_part ({loc = loc; size = size } as l) = try let result = - Location_Bits.fold_enum - (fun loc_bits acc -> - if not (can_be_accessed (make_loc loc_bits size)) - then Location_Bits.join loc_bits acc - else acc) - loc - Location_Bits.bottom + Location_Bits.fold_enum + (fun loc_bits acc -> + if not (can_be_accessed (make_loc loc_bits size)) + then Location_Bits.join loc_bits acc + else acc) + loc + Location_Bits.bottom in make_loc result size with Location_Bits.Error_Top -> l *) @@ -707,9 +718,9 @@ (fun (bi,ei) acc -> let width = Int.length bi ei in if Int.lt width size - then acc + then acc else - Ival.inject_range (Some bi) (Some (Int.length size ei))) + Ival.inject_range (Some bi) (Some (Int.length size ei))) (Zone.find_or_bottom base zone_m) Ival.bottom in @@ -720,6 +731,29 @@ make_loc result size with Location_Bits.Error_Top -> initial +module Location = + Datatype.Make + (struct + include Datatype.Serializable_undefined + type t = location + let structural_descr = + Structural_descr.t_record + [| Location_Bits.packed_descr; Int_Base.packed_descr |] + let reprs = + List.fold_left + (fun acc l -> + List.fold_left + (fun acc n -> { loc = l; size = n } :: acc) + acc + Int_Base.reprs) + [] + Location_Bits.reprs + let name = "Locations.Location" + let mem_project = Datatype.never_any_project + let equal = loc_equal + let pretty = pretty_loc + end) + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/locations.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/locations.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/locations.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/locations.mli 2011-10-10 08:38:30.000000000 +0000 @@ -34,12 +34,12 @@ module M : sig type key = Base.t - type leaf_annot - type branch_annot + type leaf_annot + type branch_annot type tt = private - | Empty - | Leaf of key * Ival.t * leaf_annot - | Branch of int * int * tt * tt * branch_annot + | Empty + | Leaf of key * Ival.t * leaf_annot + | Branch of int * int * tt * tt * branch_annot type t = tt val iter : (Base.t -> Ival.t -> unit) -> t -> unit val find : key -> t -> Ival.t @@ -54,16 +54,18 @@ include Lattice with type t = z and type widen_hint = - Top_Param.widen_hint * (Base.t -> Ival.widen_hint) + Top_Param.widen_hint * (Base.t -> Ival.widen_hint) val top_float : t + val top_single_precision_float : t val is_zero : t -> bool + val is_bottom : t -> bool val hash : t -> int val zero_or_one : t val singleton_zero : t (** the set containing only the value corresponding to the - C expression [0] *) + C expression [0] *) val singleton_one : t (** the set containing only the value [1] *) @@ -82,16 +84,18 @@ val inject_top_origin : Origin.t -> Top_Param.O.t -> t (** [inject_top_origin origin p] creates a top with origin [origin] - and additional information [param] *) + and additional information [param] *) val fold_enum : split_non_enumerable:int -> (t -> 'a -> 'a) -> t -> 'a -> 'a val splitting_cardinal_less_than : split_non_enumerable:int -> t -> int -> int + val cardinal_zero_or_one : t -> bool + val cardinal_less_than : t -> int -> int val find_exclusive : Base.t -> t -> Ival.t (** [find_exclusive k m] returns [v] if [m] contains only the binding [k] - -> [v]. - @raise Not_exclusive otherwise. *) + -> [v]. + @raise Not_exclusive otherwise. *) val split : Base.t -> t -> Ival.t * t exception Not_all_keys @@ -107,9 +111,6 @@ val topify_with_origin : Origin.t -> t -> t - val is_included_actual_generic : - Base.Set.t -> Base.Set.t ref -> t Base.Map.t ref -> t -> t -> unit - val may_reach : Base.t -> t -> bool (** [may_reach base loc] is true if [base] might be accessed from [loc]. *) @@ -124,7 +125,7 @@ [is_local] returns [true] *) - val remove_escaping_locals : (M.key -> bool) -> t -> t + val remove_escaping_locals : (M.key -> bool) -> t -> Top_Param.t * t (** TODO: merge with above function [remove_escaping_locals is_local v] removes from [v] information associated with bases for which [is_local] returns [true]. @@ -132,7 +133,10 @@ val contains_addresses_of_any_locals : t -> bool (** [contains_addresses_of_any_locals loc] returns [true] iff [loc] contains - the adress of a local variable or of a formal variable. *) + the adress of a local variable or of a formal variable. *) + + val iter_on_strings : + skip:Base.t option -> (Base.t -> string -> int -> int -> unit) -> t -> unit end @@ -173,18 +177,18 @@ val diff : t -> t -> t (** Over-approximation of difference. [arg2] needs to be exact or an - under_approximation. *) + under_approximation. *) val diff_if_one : t -> t -> t (** Over-approximation of difference. [arg2] can be an - over-approximation. *) + over-approximation. *) exception Error_Bottom exception Error_Top val find_exclusive : Base.t -> t -> Ival.t (** [find_exclusive k m] returns [v] if [m] contains only the binding [k] - -> [v]. @raise Not_exclusive otherwise. *) + -> [v]. @raise Not_exclusive otherwise. *) val is_relationable: t -> bool @@ -193,11 +197,13 @@ val intersects : t -> t -> bool (** [intersects t1 t2] is true iff [t1] and [t2] have a nonempty - intersection *) + intersection *) + + val partially_overlaps : Abstract_interp.Int.t -> t -> t -> bool val inject_top_origin : Origin.t -> Top_Param.O.t -> t (** [inject_top_origin origin p] creates a top with origin [origin] - and additional information [param] *) + and additional information [param] *) val topify_arith_origin : t -> t type widen_hint @@ -251,7 +257,7 @@ val diff_if_one : t -> t -> t (** Over-approximation of difference. [arg2] can be an - over-approximation. *) + over-approximation. *) exception Error_Bottom exception Error_Top @@ -260,7 +266,7 @@ val find_exclusive : Base.t -> t -> Int_Intervals.t (** [find_exclusive k m] returns [v] if [m] contains only the binding [k] - -> [v]. + -> [v]. @raise Not_exclusive otherwise. *) val find_lonely_key : t -> Base.t * Int_Intervals.t @@ -295,27 +301,27 @@ val filter_base : (Base.t -> bool) -> t -> t (** [filter_base] can't raise Error_Top since it filters bases of [Top - bases]. Note: the filter may give an over-approximation (in the case - [Top Top]). *) + bases]. Note: the filter may give an over-approximation (in the case + [Top Top]). *) val fold_bases : (Base.t -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_bases] folds also bases of [Top bases]. - @raise Error_Top in the case [Top Top]. *) + @raise Error_Top in the case [Top Top]. *) val get_bases : t -> Top_Param.t val fold_i : (Base.t -> Int_Intervals.t -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_i f l acc] folds [l] by base. - @raise Error_Top in the cases [Top Top], [Top bases]. *) + @raise Error_Top in the cases [Top Top], [Top bases]. *) val fold_topset_ok : (Base.t -> Int_Intervals.t -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_i f l acc] folds [l] by base. - @raise Error_Top in the case [Top Top]. *) + @raise Error_Top in the case [Top Top]. *) val fold_enum_by_base : (t -> 'a -> 'a) -> t -> 'a -> 'a (** [fold_enum_by_base f l acc] folds [l] by base. It applies [f] to a - partition of [l] by bases. - @raise Error_Top in the case [Top Top], [Top bases]. *) + partition of [l] by bases. + @raise Error_Top in the case [Top Top], [Top bases]. *) val out_some_or_bottom : t option -> t @@ -354,12 +360,12 @@ val loc_size : location -> Int_Base.t val can_be_accessed : location -> bool -val is_valid : location -> bool +val is_valid : for_writing:bool -> location -> bool val is_valid_or_function : location -> bool val cardinal_zero_or_one : location -> bool -val valid_cardinal_zero_or_one : location -> bool +val valid_cardinal_zero_or_one : for_writing:bool -> location -> bool -val valid_part : location -> location +val valid_part : for_writing:bool -> location -> location val invalid_part : location -> location val pretty : Format.formatter -> location -> unit @@ -374,7 +380,7 @@ Cil_types.lval -> Location_Bytes.t -> location val loc_bits_to_loc : Cil_types.lval -> Location_Bits.t -> location -val valid_enumerate_bits : location -> Zone.t +val valid_enumerate_bits : for_writing:bool -> location -> Zone.t (** @plugin development guide *) val zone_of_varinfo : varinfo -> Zone.t (** @since Carbon-20101201 *) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/new_offsetmap.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/new_offsetmap.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/new_offsetmap.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/new_offsetmap.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,10 +20,7 @@ (* *) (**************************************************************************) - -module Bint = Abstract_interp.Int -;; - +module Bint = Abstract_interp.Int;; (* module Int for use with these offsetmaps is basically int64 @@ -66,8 +63,8 @@ (** [round_up_to_r m r modu] is the smallest number [n] such that [n]>=[m] and [n] = [r] modulo [modu] *) - let round_up_to_r ~min:m ~r ~modu = - add (add (round_down_to_zero (pred (sub m r)) modu) r) modu + let round_up_to_r ~min ~r ~modu = + add (add (round_down_to_zero (pred (sub min r)) modu) r) modu (** [round_down_to_r m r modu] is the largest number [n] such that [n]<=[m] and [n] = [r] modulo [modu] *) @@ -90,20 +87,20 @@ type tt = | Empty (* min, the lower bound of the key interval, is always zero because - trees are relative. + trees are relative. - max * - offset_left * subtree_left * - offset_right * subtree_right * - rem * modu * value * - tag + max * + offset_left * subtree_left * + offset_right * subtree_right * + rem * modu * value * + tag *) | Node of - Int.t * - Int.t * tt * - Int.t * tt * - Int.t * Int.t * V.t * - int + Int.t * + Int.t * tt * + Int.t * tt * + Int.t * Int.t * V.t * + int let equal t1 t2 = t1 == t2 @@ -132,48 +129,46 @@ pretty_offset "" (Int.add curr_off offr) ppf subr; ;; + let pretty ppf = pretty_offset "0" Int.zero ppf ;; - let pretty ppf = pretty_offset "0" Int.zero ppf - ;; - - include + include (struct let hash t = match t with - Empty -> 311 + Empty -> 311 | Node(_,_,_,_,_,_,_,_,tag) -> tag let rehash_ref = ref (fun _ -> assert false) module D = Datatype.Make (struct - type t = tt - let name = V.name ^ " newoffsetmap" - let reprs = [ Empty ] - open Structural_descr - let r = Recursive.create () - let structural_descr = - Structure - (Sum - [| [| p_int64; - p_int64; - Recursive r; - p_int64; - Recursive r; - p_int64; - p_int64; - V.packed_descr; - p_int |] |]) - let () = Recursive.update r structural_descr - let equal = equal - let hash = hash - let compare = Datatype.undefined - let rehash x = !rehash_ref x - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let pretty = pretty - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project + type t = tt + let name = V.name ^ " newoffsetmap" + let reprs = [ Empty ] + open Structural_descr + let r = Recursive.create () + let structural_descr = + Structure + (Sum + [| [| p_int64; + p_int64; + recursive_pack r; + p_int64; + recursive_pack r; + p_int64; + p_int64; + V.packed_descr; + p_int |] |]) + let () = Recursive.update r structural_descr + let equal = equal + let hash = hash + let compare = Datatype.undefined + let rehash x = !rehash_ref x + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let pretty = pretty + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project end) include D @@ -186,61 +181,59 @@ | Empty, Empty -> true | Node _, Empty | Empty, Node _ -> false | Node (max1, offl1, subl1, offr1, subr1, rem1, modu1, v1, _), - Node (max2, offl2, subl2, offr2, subr2, rem2, modu2, v2, _) + Node (max2, offl2, subl2, offr2, subr2, rem2, modu2, v2, _) -> - Int.equal rem1 rem2 && - Int.equal modu1 modu2 && + Int.equal rem1 rem2 && + Int.equal modu1 modu2 && Int.equal max1 max2 && - Int.equal offl1 offl2 && + Int.equal offl1 offl2 && Int.equal offr1 offr2 && - V.equal v1 v2 && + V.equal v1 v2 && subl1 == subl2 && - subr1 == subr2 + subr1 == subr2 let hash_internal t = match t with - Empty -> 97 + Empty -> 97 | Node (max, offl, subl, offr, subr, rem, modu, v, _) -> - let h = Int.hash max in - let h = 31 * h + Int.hash offl in - let h = 31 * h + hash subl in - let h = 31 * h + Int.hash offr in - let h = 31 * h + hash subr in - let h = 31 * h + Int.hash rem in - let h = 31 * h + Int.hash modu in - let h = 31 * h + V.hash v in - h + let h = Int.hash max in + let h = 31 * h + Int.hash offl in + let h = 31 * h + hash subl in + let h = 31 * h + Int.hash offr in + let h = 31 * h + hash subr in + let h = 31 * h + Int.hash rem in + let h = 31 * h + Int.hash modu in + let h = 31 * h + V.hash v in + h module NewoHashconsTbl = State_builder.Hashconsing_tbl - (struct - include D - let hash_internal = hash_internal - let equal_internal = equal_internal - let initial_values = [] - end) - (struct + (struct + include D + let hash_internal = hash_internal + let equal_internal = equal_internal + let initial_values = [] + end) + (struct let name = name let dependencies = [ Ast.self ] let size = 137 let kind = `Internal - end) + end) let counter = ref 0 - let wrap tentative_new_node = + let nNode (a,b,c,d,e,f,g,h) = + let tentative_new_node = Node(a,b,c,d,e,f,g,h,!counter) in let hashed_node = NewoHashconsTbl.merge tentative_new_node in if hashed_node != tentative_new_node then incr counter; hashed_node - let nNode (a,b,c,d,e,f,g,h) = - let tentative_new_node = Node(a,b,c,d,e,f,g,h,!counter) in - wrap tentative_new_node - let rehash_node x = match x with | Empty -> empty - | Node _ -> wrap x + | Node _ -> + NewoHashconsTbl.merge x let () = rehash_ref := rehash_node @@ -255,15 +248,15 @@ let equal_vv (rem1, modu1, v1) (rem2, modu2, v2) = Int.equal rem1 rem2 && - Int.equal modu1 modu2 && - V.equal v1 v2 + Int.equal modu1 modu2 && + V.equal v1 v2 ;; let get_vv node curr_off = match node with | Empty -> assert false | Node (_, _, _, _, _, remrel, modu, v, _) -> - let rem = Int.pos_rem (Int.add remrel curr_off) modu in + let rem = Int.pos_rem (Int.add remrel curr_off) modu in rem, modu, v ;; @@ -279,7 +272,6 @@ max ;; - let is_above min1 max1 min2 max2 = let signature_interval min max = Int.logand (Int.logxor (Int.pred min) max) Int.max_int in @@ -287,11 +279,11 @@ ;; - (** Zippers : Offset of a node * Node * continuation of the zipper *) type zipper = | End | Right of Int.t * t * zipper | Left of Int.t * t * zipper;; + (** Zippers : Offset of a node * Node * continuation of the zipper *) exception End_reached;; exception Empty_tree;; @@ -302,12 +294,12 @@ | End -> printf "@ E@." | Right (o, Node(max, _, _, _, _subr, _, _, _, _),z ) -> fprintf ppf "@[ [%a,%a] R@\n%a@]" - Int.pretty o - Int.pretty (Int.add o max) + Int.pretty o + Int.pretty (Int.add o max) aux z | Left (o, Node(max, _, _, _, _subr, _, _, _, _),z ) -> fprintf ppf "@[ [%a,%a] L@\n%a@]" - Int.pretty o + Int.pretty o Int.pretty (Int.add o max) aux z | Right (_, Empty, _) | Left (_, Empty, _) -> assert false @@ -324,11 +316,11 @@ | Right (offset, Node(max, offl, subl, _offr, _subr, rem, modu, v, _), z) -> rezip z offset - (nNode (max, offl, subl, Int.sub curr_off offset, node, rem, modu, v)) + (nNode (max, offl, subl, Int.sub curr_off offset, node, rem, modu, v)) | Left (offset, Node(max, _offl, _subl, offr, subr, rem, modu, v, _), z) -> rezip z offset - (nNode (max, Int.sub curr_off offset, node, offr, subr, rem, modu, v)) + (nNode (max, Int.sub curr_off offset, node, offr, subr, rem, modu, v)) | Right (_, Empty, _) | Left (_, Empty, _) -> assert false ;; @@ -352,9 +344,8 @@ rightmost_child new_offset (Right (curr_off, node, zipper)) subr ;; - - (** Move to the right of the current node - Uses a zipper for that + (** Move to the right of the current node. + Uses a zipper for that. *) let rec move_right curr_off node zipper = match node with @@ -370,16 +361,27 @@ | Left (offset, tree, z) -> offset, tree, z in unzip_until_left zipper end - | Empty -> - assert false + | Empty -> assert false ;; + type imp_zipper = { + mutable offset: Int.t; + mutable node: t; + mutable zipper: zipper; + };; + + let imp_move_right imp_z = + let o, n, z = move_right imp_z.offset imp_z.node imp_z.zipper in + imp_z.offset <- o; + imp_z.node <- n; + imp_z.zipper <- z; + ;; + (** Folding and iterating from the leftmost node to the rightmost one If t = n0 fold f t i = f n2 (f n0 (f n1 i)) / \ iter f t = f n1; fn0; f n2; n1 n2 *) - let fold_offset f o t = assert (not (is_empty t)); let o, n, z = leftmost_child o End t in @@ -408,7 +410,7 @@ | Node (max, _, _, _, _, r, m, v, _) -> begin let abs_max = Int.add max o in - let abs_r = Int.pos_rem (Int.add r o) m in + let abs_r = Int.pos_rem (Int.add r o) m in f o abs_max abs_r m v; try let no, nt, nz = move_right o t z in @@ -480,29 +482,20 @@ Format.fprintf ppf "@\n"; ;; - let pretty_debug ppf = pretty_debug_offset Int.zero ppf - ;; + let pretty_debug ppf = pretty_debug_offset Int.zero ppf ;; - let print_offset o t = pretty_debug_offset o Format.std_formatter t - ;; + let print_offset o t = pretty_debug_offset o Format.std_formatter t ;; let fprint ppf t = iter (fun min max r m v -> pretty_node ppf min max r m v) t; Format.fprintf ppf "@."; ;; - let print t = - let ppf = Format.std_formatter in fprint ppf t - ;; - - - + let print t = let ppf = Format.std_formatter in fprint ppf t ;; (** Given interval [min, max], returns the subtree starting at this - interval - raises Interval_not_found (min, max) when failing - *) - + interval. + Raises Interval_not_found (min, max) when failing. *) exception Interval_not_found of Int.t * Int.t;; let subtree_from_interval min max tree_offset tree = @@ -528,9 +521,8 @@ (** Smart constructor for nodes: - glues the node being allocated to potential candidates if needed - (i.e. leftmost node of right subtree - and rightmost node of left subtree) + it glues the node being allocated to potential candidates if needed + (i.e. leftmost node of right subtree and rightmost node of left subtree), *) let make_node curr_off max offl subl offr subr rem modu v = @@ -548,7 +540,7 @@ match nr with | Node (nmax, _, nsubl , noffr, nsubr, nrelrem, nmodu, nv, _) -> assert (is_empty nsubl); - let nrem = Int.pos_rem (Int.add nrelrem offset) nmodu in + let nrem = Int.pos_rem (Int.add nrelrem offset) nmodu in if equal_vv (nrem, nmodu, nv) curr_vv && (Int.equal (Int.pos_rem offset modu) rem) then @@ -572,13 +564,13 @@ match nl with | Node (nmax, noffl, nsubl , _, noffr, nrelrem, nmodu, nv, _) -> assert (is_empty noffr); - let nrem = Int.pos_rem (Int.add nrelrem offset) nmodu in + let nrem = Int.pos_rem (Int.add nrelrem offset) nmodu in if equal_vv (nrem, nmodu, nv) curr_vv && (Int.equal (Int.rem curr_off modu) rem) then ( - let new_curr_offl, new_subl = rezip zl (Int.add offset noffl) nsubl - in - let succ_nmax = Int.succ nmax in + let new_curr_offl, new_subl = + rezip zl (Int.add offset noffl) nsubl in + let succ_nmax = Int.succ nmax in let lmax = Int.add max succ_nmax in let new_offl = Int.sub new_curr_offl offset in let new_offr = Int.add offr succ_nmax in @@ -608,65 +600,64 @@ let sz = Int.sub max min in make_node min sz Int.zero empty (Int.succ sz) empty rem modu v | Node (nmax, noffl, nsubl, noffr, nsubr, nremrel, nmodu, nv, _) -> - let nrem = Int.pos_rem (Int.add nremrel curr_off) nmodu in - let abs_min = curr_off - and abs_max = Int.add nmax curr_off in - if max < abs_min then + let nrem = Int.pos_rem (Int.add nremrel curr_off) nmodu in + let abs_min = curr_off + and abs_max = Int.add nmax curr_off in + if max < abs_min then begin if is_above min max abs_min abs_max then let new_offr = Int.sub abs_min min in (*Format.printf "add to the left above@."; *) make_node min (Int.sub max min) Int.zero empty - new_offr tree rem modu v + new_offr tree rem modu v else begin - (* Format.printf "L@ co:%a@ t:%a@ [%a...%a]@.@." - Int.pretty curr_off - (pretty_offset curr_off) tree - Int.pretty min Int.pretty max - ; *) - let new_curr_offl, new_node = + (* Format.printf "L@ co:%a@ t:%a@ [%a...%a]@.@." + Int.pretty curr_off + (pretty_offset curr_off) tree + Int.pretty min Int.pretty max + ; *) + let new_curr_offl, new_node = aux_add (Int.add curr_off noffl) nsubl - in - let new_offl = Int.sub new_curr_offl curr_off in - make_node + in + let new_offl = Int.sub new_curr_offl curr_off in + make_node curr_off nmax new_offl new_node noffr nsubr nrem nmodu nv end end - else - begin + else + begin if is_above min max abs_min abs_max then begin - (* Format.printf "add to the right ABOVE@."; *) - let new_offl = Int.sub abs_min min in - (* Format.printf "1 %a %a@." Int.pretty (Int.sub max curr_off) - Int.pretty new_offl; *) - let new_max = Int.sub max min in - (* Format.printf "add_node :[%a %a] o:%a t:%a@." - Int.pretty min Int.pretty new_max - Int.pretty new_offl pretty_debug tree; - *) - make_node - min new_max new_offl tree (Int.succ new_max) empty rem modu v + (* Format.printf "add to the right ABOVE@."; *) + let new_offl = Int.sub abs_min min in + (* Format.printf "1 %a %a@." Int.pretty (Int.sub max curr_off) + Int.pretty new_offl; *) + let new_max = Int.sub max min in + (* Format.printf "add_node :[%a %a] o:%a t:%a@." + Int.pretty min Int.pretty new_max + Int.pretty new_offl pretty_debug tree; + *) + make_node + min new_max new_offl tree (Int.succ new_max) empty rem modu v end else begin - (* Format.printf "add to the right Not ABOVE@."; *) - let new_curr_offr, new_node = - aux_add (Int.add curr_off noffr) nsubr - in - let new_offr = Int.sub new_curr_offr abs_min in - make_node abs_min nmax noffl nsubl new_offr new_node nrem - nmodu nv + (* Format.printf "add to the right Not ABOVE@."; *) + let new_curr_offr, new_node = + aux_add (Int.add curr_off noffr) nsubr + in + let new_offr = Int.sub new_curr_offr abs_min in + make_node abs_min nmax noffl nsubl new_offr new_node nrem + nmodu nv end end in aux_add curr_off tree ;; - - (** Translation functions *) + (** Translation functions to and fro old offstemaps, *) let to_list t = List.rev (fold (fun min max r m v y -> (min, max, r, m, v) :: y) t []) @@ -695,20 +686,14 @@ check (Int.add curr_off offr) subr; ;; - - - (** Inclusion functions *) - - (** Are the values of t1 included in those of t2 - t1 and t2 must cover exactly the same range - (see the 2 first assertions) - The offset is absolute + (** Are the values of t1 included in those of t2 ? + t1 and t2 must cover exactly the same range (see the 2 first assertions). + The offset is absolute. *) let nc_is _included_generic_exn v_is_included_exn o1 t1 o2 t2 = - assert ( o1 = o2); (* Is n1 included in n2 ? *) @@ -742,8 +727,8 @@ let abs_min2 = o2 in let abs_max1 = Int.add o1 max1 in let abs_max2 = Int.add o2 max2 in - let r1 = Int.pos_rem (Int.add r1rel o1) m1 in - let r2 = Int.pos_rem (Int.add r2rel o2) m2 in + let r1 = Int.pos_rem (Int.add r1rel o1) m1 in + let r2 = Int.pos_rem (Int.add r2rel o2) m2 in if abs_min1 = abs_min2 then begin @@ -849,9 +834,9 @@ if (r1 = r2 && m1 = m2) || V.is_isotropic v1 || V.is_isotropic v2 then v_is_included_exn v1 v2 - else raise Abstract_interp.Is_not_included - - in let is_included_node_exn (amin1 : int64) (amax1 : int64) r1 m1 v1 + else raise Abstract_interp.Is_not_included + in + let is_included_node_exn (amin1 : int64) (amax1 : int64) r1 m1 v1 amin2 amax2 r2 m2 v2 mabs_min mabs_max = if V.is_isotropic v1 || V.is_isotropic v2 then v_is_included_exn v1 v2 @@ -869,10 +854,9 @@ else raise Abstract_interp.Is_not_included in let rec node_included o1 t1 o2 t2 = - - (* Format.printf "*nodeINC @.t1: %a@. t2: %a@." - (pretty_offset o1) t1 (pretty_offset o2) t2 ; - *) + (* Format.printf "*nodeINC @.t1: %a@. t2: %a@." + (pretty_offset o1) t1 (pretty_offset o2) t2 ; + *) if t1 == t2 then () else match t1, t2 with @@ -888,8 +872,8 @@ let ol2 = Int.add o2 offl2 in let or1 = Int.add o1 offr1 in let or2 = Int.add o2 offr2 in - let r1 = Int.pos_rem (Int.add r1rel o1) m1 in - let r2 = Int.pos_rem (Int.add r2rel o2) m2 in + let r1 = Int.pos_rem (Int.add r1rel o1) m1 in + let r2 = Int.pos_rem (Int.add r2rel o2) m2 in if amax1 < amin2 then begin node_included o1 t1 ol2 subl2; @@ -968,20 +952,20 @@ in node_included o1 t1 o2 t2 ;; - - let is_included o1 t1 o2 t2 = + let is_included t1 t2 = try - is_included_generic_exn V.is_included_exn o1 t1 o2 t2; + is_included_generic_exn V.is_included_exn Int.zero t1 Int.zero t2; true with Abstract_interp.Is_not_included -> false ;; - (** Joins two trees with no overlapping intervals *) + (** Joins two trees with no overlapping intervals. *) + let rec union t1_curr_off t1 t2_curr_off t2 = -(* Format.printf "Union t1:%a t2:%a@." - (pretty_offset t1_curr_off) t1 - (pretty_offset t2_curr_off) t2; -*) + (* Format.printf "Union t1:%a t2:%a@." + (pretty_offset t1_curr_off) t1 + (pretty_offset t2_curr_off) t2; + *) match t1, t2 with | Empty, Empty -> assert (t1_curr_off = t2_curr_off); @@ -994,9 +978,9 @@ and labs_max = Int.add lmax t1_curr_off and rabs_min = t2_curr_off and rabs_max = Int.add rmax t2_curr_off - in - let lrem = Int.pos_rem (Int.add lremrel t1_curr_off) lmodu in - let rrem = Int.pos_rem (Int.add rremrel t2_curr_off) rmodu in + in + let lrem = Int.pos_rem (Int.add lremrel t1_curr_off) lmodu in + let rrem = Int.pos_rem (Int.add rremrel t2_curr_off) rmodu in if is_above labs_min labs_max rabs_min rabs_max then (* t2 is on the right of t1 *) @@ -1019,115 +1003,112 @@ end ;; - - (** Merge two trees of same number of nodes - *) + (** Merge two trees with the same number of nodes. *) let rec merge f o1 t1 o2 t2 lopt = match t1, t2 with - | _, _ when (t1 == t2 && o1 = o2) -> o1, t1 - | Empty, Empty -> assert false - | Node _, Empty -> assert false - | Empty, Node _ -> assert false - | Node (max1, offl1, subl1, offr1, subr1, rem1rel, modu1, v1, _), + | _, _ when (t1 == t2 && o1 = o2) -> o1, t1 + | Empty, Empty -> assert false + | Node _, Empty -> assert false + | Empty, Node _ -> assert false + | Node (max1, offl1, subl1, offr1, subr1, rem1rel, modu1, v1, _), Node (max2, offl2, subl2, offr2, subr2, rem2rel, modu2, v2, _) -> - let abs_min1 = o1 - and abs_max1 = Int.add max1 o1 - and abs_min2 = o2 - and abs_max2 = Int.add max2 o2 - in - let rem1 = Int.pos_rem (Int.add rem1rel o1) modu1 in - let rem2 = Int.pos_rem (Int.add rem2rel o2) modu2 in - if abs_min2 > abs_max1 then - if is_above abs_min1 abs_max1 abs_min2 abs_max2 - then (* t2 is on the right of t1 *) - let off, t = merge f (Int.add o1 offr1) subr1 o2 t2 lopt in - make_node o1 max1 offl1 subl1 - (Int.sub off o1) t rem1 modu1 v1 - else(* t1 is on the left of t2 *) - begin - (* Format.printf "t2:[%a %a] %a @.t1:[%a %a] %a@." Int.pretty - abs_min2 Int.pretty abs_max2 (pretty_debug_offset o2) t2 - Int.pretty abs_min1 - Int.pretty abs_max1 (pretty_debug_offset o1) t1; *) - (* assert (is_above abs_min2 abs_max2 abs_min1 abs_max1); *) - let off, t = merge f o1 t1 (Int.add o2 offl2) subl2 lopt in - make_node o2 max2 (Int.sub off o2) t offr2 subr2 rem2 modu2 + let abs_min1 = o1 + and abs_max1 = Int.add max1 o1 + and abs_min2 = o2 + and abs_max2 = Int.add max2 o2 + in + let rem1 = Int.pos_rem (Int.add rem1rel o1) modu1 in + let rem2 = Int.pos_rem (Int.add rem2rel o2) modu2 in + if abs_min2 > abs_max1 then + if is_above abs_min1 abs_max1 abs_min2 abs_max2 + then (* t2 is on the right of t1 *) + let off, t = merge f (Int.add o1 offr1) subr1 o2 t2 lopt in + make_node o1 max1 offl1 subl1 + (Int.sub off o1) t rem1 modu1 v1 + else(* t1 is on the left of t2 *) + begin + (* Format.printf "t2:[%a %a] %a @.t1:[%a %a] %a@." Int.pretty + abs_min2 Int.pretty abs_max2 (pretty_debug_offset o2) t2 + Int.pretty abs_min1 + Int.pretty abs_max1 (pretty_debug_offset o1) t1; *) + (* assert (is_above abs_min2 abs_max2 abs_min1 abs_max1); *) + let off, t = merge f o1 t1 (Int.add o2 offl2) subl2 lopt in + make_node o2 max2 (Int.sub off o2) t offr2 subr2 rem2 modu2 v2 - end - else if abs_min1 > abs_max2 then - if is_above abs_min1 abs_max1 abs_min2 abs_max2 - then + end + else if abs_min1 > abs_max2 then + if is_above abs_min1 abs_max1 abs_min2 abs_max2 + then (* t2 is on the left of t1 *) - let off, t = merge f (Int.add o1 offl1) subl1 o2 t2 lopt in - make_node o1 max1 (Int.sub off o1) t offr1 subl1 - rem1 modu1 v1 - else - begin + let off, t = merge f (Int.add o1 offl1) subl1 o2 t2 lopt in + make_node o1 max1 (Int.sub off o1) t offr1 subl1 + rem1 modu1 v1 + else + begin assert (is_above abs_min2 abs_max2 abs_min1 abs_max1); - (* t1 is on the right of t2 *) + (* t1 is on the right of t2 *) let off, t = merge f o1 t1 (Int.add o2 offr2) subr2 lopt in make_node o2 max2 offl2 subl2 (Int.sub off o2) t rem2 modu2 v2 + end + else + (* here n1 \inter n2 <> \emptyset: + -compute the intersection interval: middle_abs_min, middle_abs_max + - add the rest of the nodes to their left/right subtree + depending on the size of the node + - add the new node in the merged left subtree + and plug the merged right tree in + *) + let (curr_offl, left_t), middle_abs_min = + let abs_offl1 = Int.add o1 offl1 + and abs_offl2 = Int.add o2 offl2 in + if abs_min1 = abs_min2 then + merge f abs_offl1 subl1 abs_offl2 subl2 lopt, abs_min1 + else if abs_min1 < abs_min2 then + let new_offl1, new_subl1 = + add_node abs_min1 (Int.pred abs_min2) + rem1 modu1 v1 abs_offl1 subl1 + in merge f new_offl1 new_subl1 abs_offl2 subl2 lopt + , abs_min2 + else + begin + assert (abs_min1 > abs_min2); + let new_offl2, new_subl2 = + add_node abs_min2 (Int.pred abs_min1) rem2 modu2 + v2 abs_offl2 subl2 + in merge f abs_offl1 subl1 new_offl2 new_subl2 lopt + , abs_min1 end - else - (* here n1 \inter n2 <> \emptyset: - -compute the intersection interval: middle_abs_min, middle_abs_max - - add the rest of the nodes to their left/right subtree - depending on the size of the node - - add the new node in the merged left subtree - and plug the merged right tree in - *) - let (curr_offl, left_t), middle_abs_min = - let abs_offl1 = Int.add o1 offl1 - and abs_offl2 = Int.add o2 offl2 in - if abs_min1 = abs_min2 then - merge f abs_offl1 subl1 abs_offl2 subl2 lopt, abs_min1 - else if abs_min1 < abs_min2 then - let new_offl1, new_subl1 = - add_node abs_min1 (Int.pred abs_min2) - rem1 modu1 v1 abs_offl1 subl1 - in merge f new_offl1 new_subl1 abs_offl2 subl2 lopt - , abs_min2 - else - begin - assert (abs_min1 > abs_min2); - let new_offl2, new_subl2 = - add_node abs_min2 (Int.pred abs_min1) rem2 modu2 - v2 abs_offl2 subl2 - in merge f abs_offl1 subl1 new_offl2 new_subl2 lopt - , abs_min1 - end - in - let (curr_offr, right_t), middle_abs_max = - let abs_offr1 = Int.add o1 offr1 - and abs_offr2 = Int.add o2 offr2 in - if abs_max1 = abs_max2 then - merge f abs_offr1 subr1 - abs_offr2 subr2 lopt, abs_max1 - else if abs_max1 < abs_max2 then - let new_offr2, new_subr2 = - add_node - (Int.succ abs_max1) abs_max2 rem2 modu2 v2 abs_offr2 subr2 in - (*Format.printf "HERE3:%a:%a@." Int.pretty new_offr2 pretty new_subr2;*) - merge f abs_offr1 subr1 new_offr2 new_subr2 lopt, - abs_max1 - else - begin - assert (abs_max1 > abs_max2); - let min = (Int.succ abs_max2) in - let new_offr1, new_subr1 = - add_node min abs_max1 rem1 modu1 v1 abs_offr1 subr1 in - merge f new_offr1 new_subr1 abs_offr2 subr2 lopt, abs_max2 - end - in + in + let (curr_offr, right_t), middle_abs_max = + let abs_offr1 = Int.add o1 offr1 + and abs_offr2 = Int.add o2 offr2 in + if abs_max1 = abs_max2 then + merge f abs_offr1 subr1 + abs_offr2 subr2 lopt, abs_max1 + else if abs_max1 < abs_max2 then + let new_offr2, new_subr2 = + add_node + (Int.succ abs_max1) abs_max2 rem2 modu2 v2 abs_offr2 subr2 in + merge f abs_offr1 subr1 new_offr2 new_subr2 lopt, + abs_max1 + else + begin + assert (abs_max1 > abs_max2); + let min = (Int.succ abs_max2) in + let new_offr1, new_subr1 = + add_node min abs_max1 rem1 modu1 v1 abs_offr1 subr1 in + merge f new_offr1 new_subr1 abs_offr2 subr2 lopt, abs_max2 + end + in - let rem, modu, v, _l = f middle_abs_min middle_abs_max - rem1 modu1 v1 rem2 modu2 v2 lopt - in - let curr_offl, left_t = - add_node middle_abs_min middle_abs_max rem modu v curr_offl left_t - in union curr_offl left_t curr_offr right_t + let rem, modu, v, _l = f middle_abs_min middle_abs_max + rem1 modu1 v1 rem2 modu2 v2 lopt + in + let curr_offl, left_t = + add_node middle_abs_min middle_abs_max rem modu v curr_offl left_t + in union curr_offl left_t curr_offr right_t ;; let merge f o1 t1 o2 t2 = @@ -1156,157 +1137,105 @@ (** Joining two trees with possible overlapping intervals *) let join t1 t2 = merge f_join Int.zero t1 Int.zero t2 ;; - - - (* Poached from orginal offsetmap - *) - type interval_or_set = - | Set of Ival.O.t - | Interval of - Abstract_interp.Int.t * Abstract_interp.Int.t * Abstract_interp.Int.t - - let empty_interval_or_set = Set (Ival.O.empty) - - open CilE - - let reduce_ival_by_bound ~read ~with_alarms ival size bound_min bound_max = - let max_in_bound = - Abstract_interp.Int.succ (Abstract_interp.Int.sub bound_max size) in - let is_in_bound x = match x with - | Ival.Top (mn,mx,r,m) -> - let out, new_mn = - match mn with - | Some mn when (Abstract_interp.Int.ge mn bound_min) -> false, mn - | _ -> - true, - (Abstract_interp.Int.round_up_to_r ~r ~modu:m ~min:bound_min) - in - let out, new_mx = - match mx with - | Some mx when (Abstract_interp.Int.le mx max_in_bound) -> out, mx - | _ -> - true, - (Abstract_interp.Int.round_down_to_r ~r ~modu:m - ~max:max_in_bound) - in - if out then - (if read - then warn_mem_read with_alarms - else warn_mem_write with_alarms); - if Abstract_interp.Int.le new_mn new_mx - then Interval(new_mn, new_mx, m) - else empty_interval_or_set - | _ -> assert false - in - match ival with - | Ival.Top (_mn,_mx,_r,_m) -> is_in_bound ival - | Ival.Float _ -> is_in_bound Ival.top - | Ival.Set s -> - Set(Ival.O.fold - (fun offset acc -> - let pseudo_interval = - Ival.Top(Some offset, - Some offset, - Abstract_interp.Int.zero, - Abstract_interp.Int.one) - in - match is_in_bound pseudo_interval with - Interval _ -> Ival.O.add offset acc - | _ -> acc) - s - Ival.O.empty) - ;; - - (* Given an integer i -- the ith bit, find the interval it belongs to (thus its node) - Returns: the zipper to navigate from the root to the node found and the node itself + (* Given an integer i, + find the interval the ith bit belongs to (thus its node) + Returns: the zipper to navigate from the root to the node found, + and the node itself *) exception Bit_Not_found let find_bit_offset i zipper offset tree = - let rec aux_find tree curr_off z = - match tree with - | Empty -> raise Bit_Not_found - | Node (max, offl, subl, offr, subr, _, _modu, _v, _) -> - let abs_max = Int.add curr_off max in - if (Int.ge i curr_off) && (Int.le i abs_max) - then (z, curr_off, tree) - else if Int.lt i curr_off then - aux_find subl (Int.add curr_off offl) (Left(curr_off, tree, z)) - else - begin - assert (Int.gt i abs_max); - aux_find subr (Int.add curr_off offr) (Right(curr_off, tree, z)) - end - in - aux_find tree offset zipper - ;; + let rec aux_find tree curr_off z = + match tree with + | Empty -> raise Bit_Not_found + | Node (max, offl, subl, offr, subr, _, _modu, _v, _) -> + let abs_max = Int.add curr_off max in + if (Int.ge i curr_off) && (Int.le i abs_max) + then (z, curr_off, tree) + else if Int.lt i curr_off + then + aux_find subl (Int.add curr_off offl) (Left(curr_off, tree, z)) + else begin + assert (Int.gt i abs_max); + aux_find subr (Int.add curr_off offr) (Right(curr_off, tree, z)) + end + in + aux_find tree offset zipper + ;; - let find_bit = fun x y -> find_bit_offset x End Int.zero y - ;; + let find_bit = fun x y -> find_bit_offset x End Int.zero y ;; (* Go to next interval containing the ival Assumes the ival we look for is greater than what we have in the first node *) - let fforward_bit b zipper offset node = - assert ( - (Int.gt b (Int.add offset (get_max node))) || - Int.lt b offset - ); - let rec unzip_until_left zipper old_offset old_node = - match zipper with - | End -> old_offset, old_node, End - | Right (o, t, z) -> unzip_until_left z o t - | Left (offset, tree, z) -> offset, tree, z - in - let rec check_next_node z offset node = - let o', t', z' = unzip_until_left z offset node in - match z' with - | End -> find_bit_offset b z' o' t' - | _ -> - if (Int.lt b o') then find_bit_offset b z offset node - else check_next_node z' o' t' - in check_next_node zipper offset node - ;; + let fforward_bit b zipper offset node = + assert ( + (Int.gt b (Int.add offset (get_max node))) || + Int.lt b offset + ); + let rec unzip_until_left zipper old_offset old_node = + match zipper with + | End -> old_offset, old_node, End + | Right (o, t, z) -> unzip_until_left z o t + | Left (offset, tree, z) -> offset, tree, z + in + let rec check_next_node z offset node = + let o', t', z' = unzip_until_left z offset node in + match z' with + | End -> find_bit_offset b z' o' t' + | _ -> + if (Int.lt b o') then find_bit_offset b z offset node + else check_next_node z' o' t' + in check_next_node zipper offset node + ;; (* The following two functions ending with _big_int were poached from the original offsetmap *) - let extract_bits_big_int ~start ~stop ~modu v = - assert (Abstract_interp.Int.le start stop && - Abstract_interp.Int.le stop modu); - let start,stop = - if Cil.theMachine.Cil.little_endian then - start,stop - else - let mmodu = Abstract_interp.Int.pred modu in - Abstract_interp.Int.sub mmodu stop,Abstract_interp.Int.sub mmodu start - in - V.extract_bits ~start ~stop v - ;; + let extract_bits_big_int ~start ~stop ~modu v = + assert (if Abstract_interp.Int.le start stop && + Abstract_interp.Int.le stop modu + then true + else ( Format.printf "ebbi start %a stop %a modu %a@." + Abstract_interp.Int.pretty start + Abstract_interp.Int.pretty stop + Abstract_interp.Int.pretty modu; + false)); + let start,stop = + if Cil.theMachine.Cil.little_endian then + start,stop + else + let mmodu = Abstract_interp.Int.pred modu in + Abstract_interp.Int.sub mmodu stop,Abstract_interp.Int.sub mmodu start + in + V.extract_bits ~start ~stop v + ;; - let extract_bits ~start ~stop ~modu v = - extract_bits_big_int - ~start:(Int.to_big_int start) - ~stop:(Int.to_big_int stop) - ~modu:(Int.to_big_int modu) v - ;; + let extract_bits ~start ~stop ~modu v = + extract_bits_big_int + ~start:(Int.to_big_int start) + ~stop:(Int.to_big_int stop) + ~modu:(Int.to_big_int modu) v + ;; - let merge_bits_big_int ~offset ~length ~value ~total_length acc = + let merge_bits_big_int ~conflate_bottom ~offset ~length ~value + ~total_length acc = assert (let total_length_i = Abstract_interp.Int.of_int total_length in - Abstract_interp.Int.le (Abstract_interp.Int.add length offset) + Abstract_interp.Int.le (Abstract_interp.Int.add length offset) total_length_i); if Cil.theMachine.Cil.little_endian then - V.little_endian_merge_bits - ~conflate_bottom:true (* TODO *) + V.little_endian_merge_bits + ~conflate_bottom ~offset ~value ~total_length acc else - V.big_endian_merge_bits - ~conflate_bottom:true (* TODO *) + V.big_endian_merge_bits + ~conflate_bottom ~offset ~value ~total_length ~length acc ;; - let merge_bits ~offset ~length ~value ~total_length acc = + let merge_bits ~conflate_bottom ~offset ~length ~value ~total_length acc = merge_bits_big_int + ~conflate_bottom ~offset:(Int.to_big_int offset) ~length:(Int.to_big_int length) ~value @@ -1314,198 +1243,216 @@ ;; (* - is the offset where the reading has begun (ie the global - read start) - is the total size we want to read from - and refers to the current node to be read - is the current state of accumulated reads + [offset] is the offset where the read has begun (ie the global read start). + [size] is the total size we want to read from [offset]. + [curr_off] and [node] refers to the current node to be read. + [acc] is the current state of accumulated reads. *) - let extract_bits_and_stitch ~offset ~size curr_off node acc = + let extract_bits_and_stitch ~conflate_bottom ~offset ~size curr_off node acc = let r= let rem, modu, v = get_vv node curr_off in let abs_max = Int.add curr_off (get_max node) in (* last bit to be read, be it in the current node or one of its successors *) let max_bit = Int.pred (Int.add offset size) in - - let _node_length = Int.succ (get_max node) in let extract_single_step min acc = assert (not (V.is_isotropic v)); - let interval_offset = Int.sub min offset in + let interval_offset = Int.sub min offset in let merge_offset = if Int.ge interval_offset Int.zero then interval_offset else Int.zero in let start = Int.pos_rem (Int.sub min rem) modu in - let modu_end = Int.pred modu in + let modu_end = if rem = Int.zero then Int.pred modu else Int.pred rem in (* where do we stop reading ? - either at the end of the current slice (min + modu - 1) or + either at the end of the current slice (round_up_to_r min) or at the end of the interval (abs_max) *) let read_end = - Int.min (Int.min (Int.add min modu_end) abs_max) max_bit in + Int.min + (Int.min (Int.round_up_to_r ~min ~r:modu_end ~modu) abs_max) + max_bit + in let stop = Int.pos_rem (Int.sub read_end rem) modu in - Format.printf "Single step: merge offset %Ld length %Ld \ +(* Format.printf "Single step: merge offset %Ld length %Ld \ start %Ld stop %Ld total length %Ld offset %Ld max bit %Ld\ @\n current offset %Ld Rem %Ld modu %Ld V %a@." merge_offset (Int.length start stop) start stop size offset max_bit - curr_off rem modu V.pretty v - ; + curr_off rem modu V.pretty v ;*) let _inform_extract_pointer_bits, read_bits = - extract_bits ~start ~stop ~modu v + extract_bits ~start ~stop ~modu v + in + let result = + merge_bits ~conflate_bottom + ~offset:merge_offset ~length:(Int.length start stop) + ~value:read_bits ~total_length:(Int.to_int size) acc in - merge_bits ~offset:merge_offset ~length:(Int.length start stop) - ~value:read_bits ~total_length:(Int.to_int size) acc + read_end, result in + let start = Int.max offset curr_off + and stop = Int.min max_bit abs_max in if V.is_isotropic v then - let start = Int.max offset curr_off - and stop = Int.min max_bit abs_max in let interval_offset = Int.sub rem start (* ? *) in let merge_offset = if Int.lt interval_offset Int.zero then Int.zero else interval_offset - in merge_bits ~offset:merge_offset + in merge_bits ~conflate_bottom ~offset:merge_offset ~length:(Int.length start stop) - ~value:v ~total_length:(Int.to_int size) acc + ~value:v ~total_length:(Int.to_int size) acc else - let start_point = ref (Int.max curr_off offset) - and end_point = Int.min max_bit abs_max in + let start_point = ref start in let acc = ref acc in - while Int.le !start_point end_point do - - acc := extract_single_step !start_point !acc; - start_point := Int.add !start_point modu; + while Int.le !start_point stop do + let read_end, result = + extract_single_step !start_point !acc; + in + acc := result; + start_point := Int.succ read_end; done; !acc; in - Format.printf "extract_bits_and_stitch istart@ %Ld@ size %Ld\ +(* Format.printf "extract_bits_and_stitch istart@ %Ld@ size %Ld\ coff %Ld abs_max %Ld val %a@\n acc %a res %a@." offset size curr_off (Int.add curr_off (get_max node)) - V.pretty (get_v node) V.pretty acc V.pretty r; + V.pretty (get_v node) V.pretty acc V.pretty r; *) r ;; + (* First and last bits are included in the interval *) + let imprecise_find first_bit last_bit tree = + let rec aux tree_offset tree = + match tree with + | Empty -> V.bottom + | Node (max, offl, subl, offr, subr, _rrel, _m, v, _) -> + let abs_max = Int.add max tree_offset in + let subl_value = + if Int.lt first_bit tree_offset then + let subl_abs_offset = Int.add tree_offset offl in + aux subl_abs_offset subl + else V.bottom + in + let subr_value = + if Int.gt last_bit abs_max then + let subr_abs_offset = Int.add tree_offset offr in + aux subr_abs_offset subr + else V.bottom + in + let current_node_value = + if Int.lt last_bit tree_offset || Int.gt first_bit abs_max + then V.bottom + else V.topify_misaligned_read_origin v + in + V.join subl_value (V.join subr_value current_node_value) + in + aux Int.zero tree (* Searches for all intervals of the rangemap contained in the the interval [offset, offset + size - 1]. Assumes the rangemap is rooted at offset 0. *) - let find ~with_alarms offset size tree period_read_ahead = + let find ~with_alarms ~conflate_bottom offset size tree period_read_ahead = ignore(with_alarms); (* FIXME *) let offset64 = Int.from_big_int offset in let size64 = Int.from_big_int size in let period_read_ahead = Int.from_big_int period_read_ahead in let z, cur_off, root = find_bit offset64 tree in match root with - | Empty -> assert false - (* Not_found has been raised by_find_bit in this case *) + | Empty -> + (* Bit_Not_found has been raised by find_bit in this case *) + assert false | Node (max, _, _, _, _subr, rrel, m, v, _) -> - let r = Int.pos_rem (Int.add rrel cur_off) m in + let r = Int.pos_rem (Int.add rrel cur_off) m in let isize = Int.pred (Int.add offset64 size64) in let nsize = Int.add cur_off max in - let isotropic = V.is_isotropic v in + let isotropic = V.is_isotropic v in if - (Int.le isize nsize) && + (Int.le isize nsize) && (isotropic || - ((Int.equal m size64) && Int.equal (Int.pos_rem offset64 m) r)) + ((Int.equal m size64) && Int.equal (Int.pos_rem offset64 m) r)) then begin - let read_ahead = - if isotropic || (Int.is_zero (Int.rem period_read_ahead m)) - then Some (Int.to_big_int nsize) - else None - in - read_ahead, v - end + let read_ahead = + if isotropic || (Int.is_zero (Int.rem period_read_ahead m)) + then Some (Int.to_big_int nsize) + else None + in + read_ahead, v + end else let acc = ref V.singleton_zero in - let cur_root = ref root in - let cur_off = ref cur_off in - let cur_zip = ref z in - while (Int.le !cur_off isize) do - let (* _inform_extract_pointer_bits,*) v = - extract_bits_and_stitch - ~offset:offset64 ~size:size64 - !cur_off !cur_root !acc - in + let impz = { node = root; offset = cur_off; zipper = z; } in + while (Int.le impz.offset isize) do + let (* _inform_extract_pointer_bits,*) v = + extract_bits_and_stitch ~conflate_bottom + ~offset:offset64 ~size:size64 + impz.offset impz.node !acc + in acc := v; - if (Int.add !cur_off (get_max !cur_root)) >= isize - then - cur_off := Int.max_int (* end the loop *) + if (Int.add impz.offset (get_max impz.node)) >= isize + then impz.offset <- Int.max_int (* end the loop *) else (* Nominal behavior: do next binding *) - begin - let o, t, z = move_right !cur_off !cur_root !cur_zip in - cur_root := t; - cur_zip := z; - cur_off := o; - end + imp_move_right impz done; None, !acc ;; - -(* - Finds the value associated to a set of bit offsets represented as an ival -*) - let find_ival ~validity ~with_alarms offsets tree size = + (* Finds the value associated to a set of bit offsets represented as an ival. + *) + let find_ival ~conflate_bottom ~validity ~with_alarms ival tree size = let filtered_by_bound = - match validity with - | Base.Known (bound_min,bound_max) - | Base.Unknown (bound_min,bound_max) - | Base.Periodic (bound_min,bound_max,_) -> - reduce_ival_by_bound ~read:true ~with_alarms - offsets size bound_min bound_max - | Base.All -> begin - match offsets with - | Ival.Top (Some mn,Some mx,_r,m) -> Interval(mn, mx, m) - | Ival.Top (None,_,_,_) | Ival.Top (_,None,_,_) | - Ival.Float _ -> - raise Not_found (* return top *) - | Ival.Set o -> Set o - end + try + Tr_offset.filter_by_bound_for_reading + ~with_alarms ival size validity + with + Tr_offset.Unbounded -> raise Not_found (* return top *) in let result = match filtered_by_bound with - | Interval(mn, mx, m) -> - let r = Abstract_interp.Int.pos_rem mn m in + | Tr_offset.Interval(mn, mx, m) -> + let r = Abstract_interp.Int.pos_rem mn m in let mn = ref mn in let acc = ref V.bottom in - let pred_size = Abstract_interp.Int.pred size in + let pred_size = Abstract_interp.Int.pred size in while Abstract_interp.Int.le !mn mx do - let read_ahead, v = find ~with_alarms !mn size tree m in + let read_ahead, v = + find ~conflate_bottom ~with_alarms !mn size tree m + in acc := V.join v !acc; - let naive_next = Abstract_interp.Int.add !mn m in + let naive_next = Abstract_interp.Int.add !mn m in mn := - match read_ahead with - None -> naive_next - | Some read_ahead -> - let max = Abstract_interp.Int.sub read_ahead pred_size in - let aligned_b = - Abstract_interp.Int.round_down_to_r ~max ~r ~modu:m in - Abstract_interp.Int.max naive_next aligned_b + match read_ahead with + None -> naive_next + | Some read_ahead -> + let max = Abstract_interp.Int.sub read_ahead pred_size in + let aligned_b = + Abstract_interp.Int.round_down_to_r ~max ~r ~modu:m in + Abstract_interp.Int.max naive_next aligned_b done; !acc - | Set s -> + | Tr_offset.Set s -> Ival.O.fold (fun offset acc -> let _, new_value = - find ~with_alarms offset size tree Abstract_interp.Int.zero - in + find ~conflate_bottom ~with_alarms + offset size tree Abstract_interp.Int.zero + in let result = V.join acc new_value in if V.equal result V.top then raise Not_found; - result; - ) s V.bottom + result) + s + V.bottom + | Tr_offset.Imprecise(mn, mx) -> + imprecise_find (Int.from_big_int mn) (Int.from_big_int mx) tree in result ;; - - (* Keep the tree under a given limit offset *) + (* Keep the part of the tree under a given limit offset. *) let rec keep_below offset curr_off tree = match tree with @@ -1592,12 +1539,12 @@ let z, o, t = find_bit_offset offset End curr_off tree in let left_tree = ref t2 in let left_offset = ref off2 in - let cur_root, cur_off, cur_zip = ref t, ref o, ref z in - while Int.le !cur_off abs_max do - match !cur_root with + let impz = { node = t; offset = o; zipper = z; } in + while Int.le impz.offset abs_max do + match impz.node with | Empty -> assert false | Node (max, _offl, _subl, _offr, _subr, rrel, m_node, v_node, _) -> - let rabs_node = Int.pos_rem (Int.add !cur_off rrel) m_node in + let rabs_node = Int.pos_rem (Int.add impz.offset rrel) m_node in (* Format.printf "rabs:%Ld rabs_node:%Ld coff:%Ld rrel:%Ld@." rabs rabs_node !cur_off rrel; *) let new_r, new_m, new_v = @@ -1606,12 +1553,12 @@ then let new_r, new_m = if v_is_isotropic - then rabs_node, m_node + then rabs_node, m_node else rabs, size - in - let cast_v = - V.anisotropic_cast ~size:(Int.to_big_int new_m) (V.join v_node v) - in + in + let cast_v = + V.anisotropic_cast ~size:(Int.to_big_int new_m) (V.join v_node v) + in new_r, new_m, cast_v else @@ -1619,26 +1566,21 @@ let new_rem = 0L and new_modu = 1L in new_rem, new_modu, new_value in - let node_abs_max = Int.add !cur_off max in + let node_abs_max = Int.add impz.offset max in let end_reached, write_max = if Int.ge node_abs_max abs_max then true, abs_max else false, node_abs_max in let new_left_offset, new_left_tree = add_node - (Int.max !cur_off offset) + (Int.max impz.offset offset) write_max new_r new_m new_v !left_offset !left_tree in left_tree := new_left_tree; left_offset := new_left_offset; - if not end_reached then - let new_o, new_t, new_z = move_right !cur_off !cur_root !cur_zip in - cur_off := new_o; - cur_root := new_t; - cur_zip := new_z; - else - cur_off := Int.max_int + if not end_reached then imp_move_right impz + else impz.offset <- Int.max_int done; union !left_offset !left_tree off1 t1 ;; @@ -1670,7 +1612,7 @@ with value v, every period *) let update_ival ~left_cover ~right_cover ~exact - ~mn ~mx ~period ~size curr_off tree v = + ~mn ~mx ~period ~size tree v = assert(mx >= mn); (* Format.printf "update_ival tree: %a %Ld %Ld exact:%B v:%a@." (pretty_offset curr_off) tree mn mx exact @@ -1678,12 +1620,17 @@ let r = Int.pos_rem mn period in let rec aux_update_ival left_cover right_cover mn mx curr_off tree = let f () = +(* Format.printf "aux_update_ival ( %a %a in@\n%a@." + Int.pretty mn + Int.pretty mx + pretty tree; *) + let r = match tree with | Empty -> curr_off, empty | Node (max, offl, subl, offr, subr, r_node, m_node, v_node, _) -> (* Look at the cache if min_cover and max_cover are true *) -(* Format.printf "aux_update_ival: %Ld %Ld %B %B@." - mn mx left_cover right_cover; *) +(* Format.printf "aux_update_ival: %Ld %Ld %B %B@." + mn mx left_cover right_cover; *) let abs_offl = Int.add offl curr_off in let abs_offr = Int.add offr curr_off in @@ -1712,7 +1659,7 @@ let new_mn, left_cover, undone = if Int.lt new_mn mn then mn, false, None - else new_mn, true, Some (Int.add new_mn period) + else new_mn, true, Some (Int.sub new_mn period) in let o, t = aux_update_ival left_cover right_cover new_mn mx abs_offr subr @@ -1721,8 +1668,12 @@ in let o, t = - add_node curr_off (Int.add curr_off max) (Int.pos_rem r_node m_node) - m_node v_node new_offl new_subl in + add_node + curr_off + (Int.add curr_off max) + (Int.pos_rem r_node m_node) + m_node v_node new_offl new_subl + in let curr_off, tree = union o t new_offr new_subr in match undone_left, undone_right with | Some min, Some max -> @@ -1732,16 +1683,20 @@ (pretty_offset !o) !t min max size; *) - if Int.equal size period - then - let abs_max = Int.pred (Int.add size max) in + if Int.equal size period + then + let abs_max = Int.pred (Int.add size max) in +(* Format.printf "minmaxsize %a %a %a@." + Int.pretty min + Int.pretty max + Int.pretty size; *) update ~offset:min ~abs_max ~size curr_off tree v - else + else let offset = ref min in let o = ref curr_off in let t = ref tree in while Int.le !offset max do - let abs_max = Int.pred (Int.add size !offset) in + let abs_max = Int.pred (Int.add size !offset) in let o', t' = update ~offset:!offset ~abs_max ~size !o !t v in o := o'; @@ -1754,6 +1709,11 @@ | Some _, None | None, Some _ | None, None -> curr_off, tree + in +(* Format.printf "aux_update_ival ) %a %a@." + Int.pretty mn + Int.pretty mx; *) + r in match left_cover, right_cover, exact with | true, true, false -> @@ -1762,26 +1722,122 @@ | _, _, _ -> f () in - aux_update_ival left_cover right_cover mn mx curr_off tree + let _, t = aux_update_ival left_cover right_cover mn mx Int.zero tree in + t ;; - let update_ival min max ~exact ~mn ~mx ~period ~size curr_off tree v = + let update_ival min max ~exact ~mn ~mx ~period ~size tree v = let r = Int.pos_rem mn period in let m1 = Int.round_up_to_r ~r ~min ~modu:period in let left_cover = Int.equal m1 mn in let m2 = Int.round_down_to_r ~r ~max ~modu:period in let right_cover = Int.equal m2 mx in - update_ival ~left_cover ~right_cover ~exact ~mn ~mx ~period ~size curr_off - tree v +(* try *) + update_ival ~left_cover ~right_cover ~exact ~mn ~mx ~period ~size tree v +(* with e -> + Format.printf "UPDATE_IVAL %a %a %B %a %a %a %a %a %a@." + Int.pretty min + Int.pretty max + exact + Int.pretty mn + Int.pretty mx + Int.pretty period + Int.pretty size + pretty tree + V.pretty v; + raise e*) + ;; + +(* TODO: do something about the read ahead *) + let copy_single offset tree size _period_read_ahead = + let z, cur_off, root = find_bit offset tree in + let cur_copy_offset = ref offset in + let impz = { node = root; offset = cur_off; zipper = z; } in + let acc = ref empty in + let iend = Int.pred (Int.add offset size) in + while + (match impz.node with + | Empty -> + (* Bit_Not_found has been raised by find_bit in this case *) + assert false + | Node (max, _, _, _, _subr, rrel, m, v, _) -> + let nend = Int.add impz.offset max in + let new_abs_end = Int.sub (Int.max iend nend) offset in + let o, t = add_node (Int.sub !cur_copy_offset offset) new_abs_end + (Int.add impz.offset rrel) m v Int.zero !acc in + assert (o = Int.zero); + acc := t; + let cond = Int.gt iend nend in + if cond then begin + imp_move_right impz; + cur_copy_offset := impz.offset; + end; + cond) + do (); + done; + None, !acc (* FIXME here : see TODO above *) ;; + let copy_ival ~with_alarms ~validity ival tree size = + let filtered_by_bound = + try Tr_offset.filter_by_bound_for_reading ~with_alarms ival size validity + with Tr_offset.Unbounded -> raise Not_found (* return top *) + in + let result = + match filtered_by_bound with + | Tr_offset.Interval(mn, mx, m) -> + let r = Abstract_interp.Int.pos_rem mn m in + let mn = ref mn in + let acc_tree = ref empty in + let pred_size = Abstract_interp.Int.pred size in + while Abstract_interp.Int.le !mn mx do + let read_ahead, new_tree = + copy_single + (Int.from_big_int !mn) + tree + (Int.from_big_int size) None + in + let o, t = join !acc_tree new_tree in + assert (o = Int.zero); + acc_tree := t; + let naive_next = Abstract_interp.Int.add !mn m in + mn := match read_ahead with + | None -> naive_next + | Some read_ahead -> + let max = Abstract_interp.Int.sub read_ahead pred_size in + let aligned_b = + Abstract_interp.Int.round_down_to_r ~max ~r ~modu:m in + Abstract_interp.Int.max naive_next aligned_b + ; + done; + !acc_tree + | Tr_offset.Set s -> + Ival.O.fold + (fun offset acc_tree -> + let _, t = + copy_single + (Int.from_big_int offset) + tree + (Int.from_big_int size) + None + in + let o, t = + join acc_tree t + in + assert (o = Int.zero); + t) + s + empty + | Tr_offset.Imprecise(_mn, _mx) -> assert false (* TODO *) + in + result + ;; end - - -(* module Test = Make (Cvalue_type.V) ;; +(* Below is some code for testing purposes : do not remove for now *) +(* module Test = Make (Cvalue.V) ;; * - * open Cvalue_type.V + * open Cvalue.V * open Int * open Test * diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/new_offsetmap.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/new_offsetmap.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/new_offsetmap.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/new_offsetmap.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,8 @@ (* *) (**************************************************************************) +(** Maps from intervals to values (aka rangemaps). +*) module Int : sig type t = int64 @@ -31,7 +33,7 @@ sig type t type y - + val empty : t val is_empty: t -> bool val equal_vv : Int.t * Int.t * V.t -> Int.t * Int.t * V.t -> bool @@ -49,10 +51,8 @@ val iter_offset : (Int.t -> int64 -> Int.t -> Int.t -> V.t -> 'a) -> Int.t -> t -> unit val iter : (Int.t -> int64 -> Int.t -> Int.t -> V.t -> 'a) -> t -> unit -(** - Common folding and iteration operations -*) - + (** Common folding and iteration operations, *) + val pretty_node : Format.formatter -> int64 -> int64 -> int64 -> int64 -> V.t -> unit val pretty_offset : int64 -> Format.formatter -> t -> unit @@ -62,11 +62,7 @@ val print_offset : int64 -> t -> unit val fprint : Format.formatter -> t -> unit val print : t -> unit -(* Some printing functions - Some might need to be deprecated -*) - - + (* Some printing functions. Some might need to be deprecated,*) exception Interval_not_found of Int.t * Int.t val subtree_from_interval : Int.t -> Int.t -> Int.t -> t -> Int.t * t @@ -79,22 +75,28 @@ * t val is_included_generic_exn : (V.t -> V.t -> 'a) -> Int.t -> t -> Int.t -> t -> unit - val is_included : Int.t -> t -> Int.t -> t -> bool + val is_included : t -> t -> bool val join : t -> t -> int64 * t - val find_ival : + val find_ival : + conflate_bottom:bool -> validity:Base.validity -> with_alarms:CilE.warn_mode -> Ival.t -> t -> Abstract_interp.Int.t -> V.t - (** Find a set of intervals in a given rangemap - *) - + (** Find a set of intervals in a given rangemap. *) + + val imprecise_find: Int.t -> Int.t -> t -> V.t + (** imprecise_find [first_bit] [last_bit] [offsetmap] returns the value found + in the interval ([first_bit], [last_bit]) in [offsetmap]. + If the interval ([first_bit], [last_bit]) spans multiple intervals in + [offsetmap], all the values found are joined together. *) + val update_ival : int64 -> int64 -> exact:bool -> mn:Int.t -> mx:Int.t -> - period:Int.t -> size:Int.t -> Int.t -> t -> V.t -> Int.t * t + period:Int.t -> size:Int.t -> t -> V.t -> t (** Update a set of intervals in a given rangemap rooted a given offset. all offsets starting from mn ending in mx must be updated with value v, every period with a given size. @@ -102,5 +104,13 @@ Return a pair: offset, tree where the tree root begins at offset *) + val copy_ival: + with_alarms:CilE.warn_mode -> + validity:Base.validity -> + Ival.tt -> t -> My_bigint.t + -> t + (** [shift_ival with_alarms validity ival size tree] creates a new offsetmap + from the intervals [ival] of size [size]. + This offsetmap is rooted at zero (this is a new base for the values). + *) end - diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap_bitwise.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap_bitwise.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap_bitwise.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap_bitwise.ml 2011-10-10 08:38:30.000000000 +0000 @@ -56,9 +56,9 @@ let equal m1 m2 = match m1, m2 with Degenerate v1, Degenerate v2 -> - V.equal v1 v2 + V.equal v1 v2 | Map mm1, Map mm2 -> - equal_map mm1 mm2 + equal_map mm1 mm2 | Map _, Degenerate _ | Degenerate _, Map _ -> false let compare = @@ -79,29 +79,29 @@ let pretty_with_type typ fmt m = match m with Degenerate v -> - Format.fprintf fmt "@[[..] FROM @[%a@]@]" - V.pretty v + Format.fprintf fmt "@[[..] FROM @[%a@]@]" + V.pretty v | Map m -> - let first = ref true in - let pretty_binding fmt (bi,ei) (default,v) = + let first = ref true in + let pretty_binding fmt (bi,ei) (default,v) = let pp_left fmt = function | None -> - Format.fprintf fmt ":%a..%a" - Int.pretty bi Int.pretty ei + Format.fprintf fmt ":%a..%a" + Int.pretty bi Int.pretty ei | Some typ -> - ignore (Bit_utils.pretty_bits typ - ~use_align:false ~align:Int.zero ~rh_size:Int.one - ~start:bi ~stop:ei fmt) + ignore (Bit_utils.pretty_bits typ + ~use_align:false ~align:Int.zero ~rh_size:Int.one + ~start:bi ~stop:ei fmt) in - if !first then first := false else Format.fprintf fmt "@," ; + if !first then first := false else Format.fprintf fmt "@," ; Format.fprintf fmt "@[%a FROM @[%a@]%s@]" - pp_left typ V.pretty v + pp_left typ V.pretty v (if default then " (and SELF)" else "") - - in - Format.fprintf fmt "@["; - M.iter (pretty_binding fmt) m; - Format.fprintf fmt "@]" + + in + Format.fprintf fmt "@["; + M.iter (pretty_binding fmt) m; + Format.fprintf fmt "@]" let pretty = pretty_with_type None @@ -111,12 +111,12 @@ let name = V.name ^ " offsetmap_bitwise" let structural_descr = Structural_descr.Structure - (Structural_descr.Sum [| [| M.packed_descr |]; [| V.packed_descr |] |]) + (Structural_descr.Sum [| [| M.packed_descr |]; [| V.packed_descr |] |]) let reprs = List.fold_left - (fun acc m -> Map m :: acc) - (List.map (fun v -> Degenerate v) V.reprs) - M.reprs + (fun acc m -> Map m :: acc) + (List.map (fun v -> Degenerate v) V.reprs) + M.reprs let equal = equal let hash = tag let compare = compare @@ -138,47 +138,47 @@ match m with Degenerate v -> v | Map m -> - let concerned_intervals = - M.concerned_intervals Int_Interv.fuzzy_order i m - in - let treat_mid_interval (_bk,ek) (bl,_el) acc = + let concerned_intervals = + M.concerned_intervals Int_Interv.fuzzy_order i m + in + let treat_mid_interval (_bk,ek) (bl,_el) acc = (* Format.printf "treat_mid_itv: ek:%a bl:%a@\n" Int.pretty ek Int.pretty bl; *) let s_ek = Int.succ ek in if Int.lt s_ek bl then - V.join (default s_ek (Int.pred bl)) acc + V.join (default s_ek (Int.pred bl)) acc else acc - in + in (*let concerned_intervals = List.rev concerned_intervals in*) - match concerned_intervals with - [] -> default bi ei - | ((_bk,ek),_)::_ -> - let implicit_right = - if Int.gt ei ek - then default (Int.succ ek) ei - else V.bottom - in - let rec implicit_mid_and_left list acc = - match list with - | [(bl,_el),_] -> - if Int.lt bi bl - then V.join acc (default bi (Int.pred bl)) - else acc - | (k,_)::(((l,_)::_) as tail) -> - treat_mid_interval k l (implicit_mid_and_left tail acc) - | [] -> assert false - in - let implicit = - implicit_mid_and_left concerned_intervals implicit_right - in - (* now add the explicit values *) - List.fold_left - (function acc -> function ((bi,ei),(d,v)) -> - let valu = V.join v acc in - if d then (V.join valu (default bi ei)) else valu - ) - implicit - concerned_intervals + match concerned_intervals with + [] -> default bi ei + | ((_bk,ek),_)::_ -> + let implicit_right = + if Int.gt ei ek + then default (Int.succ ek) ei + else V.bottom + in + let rec implicit_mid_and_left list acc = + match list with + | [(bl,_el),_] -> + if Int.lt bi bl + then V.join acc (default bi (Int.pred bl)) + else acc + | (k,_)::(((l,_)::_) as tail) -> + treat_mid_interval k l (implicit_mid_and_left tail acc) + | [] -> assert false + in + let implicit = + implicit_mid_and_left concerned_intervals implicit_right + in + (* now add the explicit values *) + List.fold_left + (function acc -> function ((bi,ei),(d,v)) -> + let valu = V.join v acc in + if d then (V.join valu (default bi ei)) else valu + ) + implicit + concerned_intervals let find_intervs default intervs m = Int_Intervals.fold (fun itv acc -> V.join (find default itv m) acc) @@ -189,14 +189,14 @@ (bx = by) && (V.equal x y ) let add_map_internal i v map = (* FIXME (?) Fails to stick the writing binding - with neighbors if applicable *) + with neighbors if applicable *) match M.cleanup_overwritten_bindings same_values i v map with | None -> map | Some(new_bi, new_ei, cleaned_m) -> (* Add the new binding *) - let result = M.add (new_bi,new_ei) v cleaned_m in - result + let result = M.add (new_bi,new_ei) v cleaned_m in + result let merge_map m1 m2 = M.fold (fun k v acc -> add_map_internal k v acc) m1 m2 @@ -206,7 +206,7 @@ match m with | Degenerate v1 -> Degenerate (V.join tv v1) | Map map -> - Map (add_map_internal i v map) + Map (add_map_internal i v map) (** exact add *) let add i v m = add_internal i (false,v) m @@ -215,60 +215,60 @@ match m with | Degenerate v1 -> Degenerate (V.join v v1) | Map map -> - let concerned_intervals = - M.concerned_intervals Int_Interv.fuzzy_order i map - in - let treat_interval (acc, right_bound) ((b1, e1), (d1, v1)) = - let acc, restricted_e1 = - if Int.lt e1 right_bound - then begin (* there is a hole *) - let i_hole = (Int.succ e1, right_bound) in - add_internal i_hole (true, v) acc, e1 - end - else acc, Int.min e1 e - in - let restricted_b1 = Int.max b1 b in - let restricted_i1 = restricted_b1, restricted_e1 in - add_internal restricted_i1 (d1,V.join v1 v) acc, Int.pred restricted_b1 - in - let acc, right_bound = List.fold_left treat_interval (m, e) concerned_intervals - in - let result = - if Int.le b right_bound - then begin (* there is a hole *) - let i_hole = (b, right_bound) in - add_internal i_hole (true, v) acc - end - else acc - in -(* Format.printf "bitwise add_approximate@\ninterval:%a..%a value:%a@\nstate%a@\nresult: %a@." - Int.pretty b Int.pretty e - V.pretty v - pretty m - pretty result;*) - result + let concerned_intervals = + M.concerned_intervals Int_Interv.fuzzy_order i map + in + let treat_interval (acc, right_bound) ((b1, e1), (d1, v1)) = + let acc, restricted_e1 = + if Int.lt e1 right_bound + then begin (* there is a hole *) + let i_hole = (Int.succ e1, right_bound) in + add_internal i_hole (true, v) acc, e1 + end + else acc, Int.min e1 e + in + let restricted_b1 = Int.max b1 b in + let restricted_i1 = restricted_b1, restricted_e1 in + add_internal restricted_i1 (d1,V.join v1 v) acc, Int.pred restricted_b1 + in + let acc, right_bound = List.fold_left treat_interval (m, e) concerned_intervals + in + let result = + if Int.le b right_bound + then begin (* there is a hole *) + let i_hole = (b, right_bound) in + add_internal i_hole (true, v) acc + end + else acc + in +(* Format.printf "bitwise add_approximate@\ninterval:%a..%a value:%a@\nstate%a@\nresult: %a@." + Int.pretty b Int.pretty e + V.pretty v + pretty m + pretty result;*) + result (* - let new_v = - List.fold_left - (fun vacc (_,(_,v)) -> - (V.join vacc v)) - v - concerned_intervals - in - let d = + let new_v = + List.fold_left + (fun vacc (_,(_,v)) -> + (V.join vacc v)) + v + concerned_intervals + in + let d = try Int_Interv.check_coverage i concerned_intervals; List.fold_left (fun acc ((_,_),(d,_)) -> acc || d) false concerned_intervals with Is_not_included -> true - in - add_internal i (d, new_v) m + in + add_internal i (d, new_v) m *) let collapse m = match m with | Degenerate v -> v | Map map -> - M.fold (fun _ (_,v) acc -> V.join acc v) map V.bottom + M.fold (fun _ (_,v) acc -> V.join acc v) map V.bottom let find_iset default alldefault is m = let result = @@ -280,15 +280,15 @@ if s = [] then V.bottom else begin - match m with - | Degenerate v -> - List.fold_left - (fun acc i -> V.join acc (default (fst i) (snd i))) - v s - | Map _ -> - let f acc i = V.join acc (find default i m) in - List.fold_left f V.bottom s - end + match m with + | Degenerate v -> + List.fold_left + (fun acc i -> V.join acc (default (fst i) (snd i))) + v s + | Map _ -> + let f acc i = V.join acc (find default i m) in + List.fold_left f V.bottom s + end in (* Format.printf "find_iset %a %a@\nresult:%a@." Int_Intervals.pretty is pretty m V.pretty result; *) result @@ -300,19 +300,19 @@ Degenerate (V.join v (collapse m)) end else begin - let s = Int_Intervals.project_set is in - match m with - | Degenerate v1 -> Degenerate (V.join v v1) - | Map _ -> - let result = - List.fold_left - (fun acc i -> - (if exact then add else add_approximate) - i v acc) - m - s - in - result + let s = Int_Intervals.project_set is in + match m with + | Degenerate v1 -> Degenerate (V.join v v1) + | Map _ -> + let result = + List.fold_left + (fun acc i -> + (if exact then add else add_approximate) + i v acc) + m + s + in + result end let joindefault_internal = @@ -322,19 +322,19 @@ let fold f m acc = match m with | Degenerate v -> - f Int_Intervals.top (true,v) acc + f Int_Intervals.top (true,v) acc | Map m -> - M.fold - (fun i v acc -> - f (Int_Intervals.inject [i]) v acc) - m - acc + M.fold + (fun i v acc -> + f (Int_Intervals.inject [i]) v acc) + m + acc let map_map f m = M.fold (fun i v acc -> add_map_internal i (f v) acc) (* [pc] add_internal could be replaced by a more efficient - function that assumes there are no bindings above i *) + function that assumes there are no bindings above i *) m M.empty @@ -356,7 +356,7 @@ match m with Degenerate _ -> m | Map m -> - Map (joindefault_internal m) + Map (joindefault_internal m) let map2 (f : (bool * V.t) option -> (bool * V.t) option -> bool * V.t) @@ -366,184 +366,184 @@ let result = match mm1, mm2 with | Degenerate(v), m | m, Degenerate(v) -> - Degenerate (snd (f (Some (true, v)) (Some (true, collapse m)))) + Degenerate (snd (f (Some (true, v)) (Some (true, collapse m)))) | Map(m1), Map(m2) -> - (*Format.printf "map2: m1:@\n%a@\nm2:@\n%a@\n" - pretty mm1 pretty mm2;*) - let compute_remains_m1_and_merge m1 acc = - let remains = - map_map - (fun vv -> f (Some vv) None) - m1 - in - merge_map remains acc - in - let compute_remains_m2_and_merge m2 acc = -(* check_map_contiguity(acc); *) - let remains = map_map - (fun vv -> f None (Some vv)) - m2 - in -(* check_map_contiguity(remains); *) - let result = merge_map remains acc in -(* check_map_contiguity(result);*) - result - in - let rec out_out (b1,_e1 as i1) v1 m1 (b2, _e2 as i2) v2 m2 acc = - (*Format.printf "out_out: b1=%a e1=%a b2=%a e2=%a@\n" + (*Format.printf "map2: m1:@\n%a@\nm2:@\n%a@\n" + pretty mm1 pretty mm2;*) + let compute_remains_m1_and_merge m1 acc = + let remains = + map_map + (fun vv -> f (Some vv) None) + m1 + in + merge_map remains acc + in + let compute_remains_m2_and_merge m2 acc = +(* check_map_contiguity(acc); *) + let remains = map_map + (fun vv -> f None (Some vv)) + m2 + in +(* check_map_contiguity(remains); *) + let result = merge_map remains acc in +(* check_map_contiguity(result);*) + result + in + let rec out_out (b1,_e1 as i1) v1 m1 (b2, _e2 as i2) v2 m2 acc = + (*Format.printf "out_out: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2; *) -(* check_map_contiguity(acc);*) - let result = - if Int.lt b1 b2 - then in_out i1 v1 m1 i2 v2 m2 acc - else if Int.gt b1 b2 - then out_in i1 v1 m1 i2 v2 m2 acc - else (* b1 = b2 *) - in_in i1 v1 m1 i2 v2 m2 acc - in -(* check_map_contiguity(result);*) - result - and in_out (b1,e1 as i1) v1 m1 (b2, _e2 as i2) v2 m2 acc = +(* check_map_contiguity(acc);*) + let result = + if Int.lt b1 b2 + then in_out i1 v1 m1 i2 v2 m2 acc + else if Int.gt b1 b2 + then out_in i1 v1 m1 i2 v2 m2 acc + else (* b1 = b2 *) + in_in i1 v1 m1 i2 v2 m2 acc + in +(* check_map_contiguity(result);*) + result + and in_out (b1,e1 as i1) v1 m1 (b2, _e2 as i2) v2 m2 acc = (*Format.printf "in_out: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2; *) -(* check_map_contiguity(acc);*) +(* check_map_contiguity(acc);*) assert (Int.gt b2 b1); - let result = - let pb2 = Int.pred b2 in - let new_v = f (Some v1) None in - if Int.lt pb2 e1 - then begin (* -> in_in *) - let new_acc = add_map_internal (b1,pb2) new_v acc in - in_in (b2,e1) v1 m1 i2 v2 m2 new_acc - end - else begin - let new_acc = add_map_internal i1 new_v acc in - try - let (new_i1, new_v1) = M.lowest_binding m1 in - let new_m1 = M.remove new_i1 m1 in - if Int.lt e1 pb2 - then (* -> out_out *) - out_out new_i1 new_v1 new_m1 i2 v2 m2 new_acc - else (* pb2 = e1 *) - (* -> in_or_out_in *) - in_or_out_in new_i1 new_v1 new_m1 i2 v2 m2 new_acc - with M.Empty_rangemap -> - compute_remains_m2_and_merge (add_map_internal i2 v2 m2) new_acc - end - in -(* check_map_contiguity(result);*) - result - and out_in (b1,_e1 as i1) v1 m1 (b2, e2 as i2) v2 m2 acc = + let result = + let pb2 = Int.pred b2 in + let new_v = f (Some v1) None in + if Int.lt pb2 e1 + then begin (* -> in_in *) + let new_acc = add_map_internal (b1,pb2) new_v acc in + in_in (b2,e1) v1 m1 i2 v2 m2 new_acc + end + else begin + let new_acc = add_map_internal i1 new_v acc in + try + let (new_i1, new_v1) = M.lowest_binding m1 in + let new_m1 = M.remove new_i1 m1 in + if Int.lt e1 pb2 + then (* -> out_out *) + out_out new_i1 new_v1 new_m1 i2 v2 m2 new_acc + else (* pb2 = e1 *) + (* -> in_or_out_in *) + in_or_out_in new_i1 new_v1 new_m1 i2 v2 m2 new_acc + with M.Empty_rangemap -> + compute_remains_m2_and_merge (add_map_internal i2 v2 m2) new_acc + end + in +(* check_map_contiguity(result);*) + result + and out_in (b1,_e1 as i1) v1 m1 (b2, e2 as i2) v2 m2 acc = (* Format.printf "out_in: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 - Int.pretty e1 - Int.pretty b2 - Int.pretty e2; *) -(* check_map_contiguity(acc);*) + Int.pretty e1 + Int.pretty b2 + Int.pretty e2; *) +(* check_map_contiguity(acc);*) assert (Int.lt b2 b1); - let result = - let pb1 = Int.pred b1 in - let new_v = f None (Some v2) in - if Int.lt pb1 e2 - then begin (* -> in_in *) - let new_acc = add_map_internal (b2,pb1) new_v acc in - in_in i1 v1 m1 (b1,e2) v2 m2 new_acc - end - else begin - let new_acc = add_map_internal i2 new_v acc in - try - let (new_i2, new_v2) = M.lowest_binding m2 in - let new_m2 = M.remove new_i2 m2 in - if Int.lt e2 pb1 - then (* -> out_out *) - out_out i1 v1 m1 new_i2 new_v2 new_m2 new_acc - else (* pb1 = e2 *) - (* -> in_in_or_out *) - in_in_or_out i1 v1 m1 new_i2 new_v2 new_m2 new_acc - with M.Empty_rangemap -> - compute_remains_m1_and_merge (add_map_internal i1 v1 m1) new_acc - end - in -(* check_map_contiguity(result);*) - result - and in_in_or_out (b1,_e1 as i1) v1 m1 (b2,_e2 as i2) v2 m2 acc = - (*Format.printf "in_in_or_out: b1=%a e1=%a b2=%a e2=%a@\n" - Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2;*) + let result = + let pb1 = Int.pred b1 in + let new_v = f None (Some v2) in + if Int.lt pb1 e2 + then begin (* -> in_in *) + let new_acc = add_map_internal (b2,pb1) new_v acc in + in_in i1 v1 m1 (b1,e2) v2 m2 new_acc + end + else begin + let new_acc = add_map_internal i2 new_v acc in + try + let (new_i2, new_v2) = M.lowest_binding m2 in + let new_m2 = M.remove new_i2 m2 in + if Int.lt e2 pb1 + then (* -> out_out *) + out_out i1 v1 m1 new_i2 new_v2 new_m2 new_acc + else (* pb1 = e2 *) + (* -> in_in_or_out *) + in_in_or_out i1 v1 m1 new_i2 new_v2 new_m2 new_acc + with M.Empty_rangemap -> + compute_remains_m1_and_merge (add_map_internal i1 v1 m1) new_acc + end + in +(* check_map_contiguity(result);*) + result + and in_in_or_out (b1,_e1 as i1) v1 m1 (b2,_e2 as i2) v2 m2 acc = + (*Format.printf "in_in_or_out: b1=%a e1=%a b2=%a e2=%a@\n" + Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2;*) (if Int.equal b1 b2 then in_in else (assert (Int.lt b1 b2);in_out)) i1 v1 m1 i2 v2 m2 acc - and in_or_out_in (b1,_e1 as i1) v1 m1 (b2,_e2 as i2) v2 m2 acc = - (*Format.printf "in_or_out_in: b1=%a e1=%a b2=%a e2=%a@\n" - Int.pretty b1 - Int.pretty e1 - Int.pretty b2 - Int.pretty e2;*) + and in_or_out_in (b1,_e1 as i1) v1 m1 (b2,_e2 as i2) v2 m2 acc = + (*Format.printf "in_or_out_in: b1=%a e1=%a b2=%a e2=%a@\n" + Int.pretty b1 + Int.pretty e1 + Int.pretty b2 + Int.pretty e2;*) (if Int.equal b1 b2 then in_in else (assert (Int.gt b1 b2);out_in)) i1 v1 m1 i2 v2 m2 acc - and in_in_e1_first (_b1, e1 as i1) _v1 m1 (_b2, e2) v2 m2 acc new_v12 = + and in_in_e1_first (_b1, e1 as i1) _v1 m1 (_b2, e2) v2 m2 acc new_v12 = (*Format.printf "in_in_e1_first: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2; *) - assert (Int.lt e1 e2); - let new_acc = add_map_internal i1 new_v12 acc in - let new_i2 = (Int.succ e1,e2) in - try - let (new_i1, new_v1) = M.lowest_binding m1 in - let new_m1 = M.remove new_i1 m1 in - in_or_out_in new_i1 new_v1 new_m1 new_i2 v2 m2 new_acc - with M.Empty_rangemap -> - compute_remains_m2_and_merge - (add_map_internal new_i2 v2 m2) new_acc - and in_in_e2_first (_b1, e1) v1 m1 (_b2, e2 as i2) _v2 m2 acc new_v12= + assert (Int.lt e1 e2); + let new_acc = add_map_internal i1 new_v12 acc in + let new_i2 = (Int.succ e1,e2) in + try + let (new_i1, new_v1) = M.lowest_binding m1 in + let new_m1 = M.remove new_i1 m1 in + in_or_out_in new_i1 new_v1 new_m1 new_i2 v2 m2 new_acc + with M.Empty_rangemap -> + compute_remains_m2_and_merge + (add_map_internal new_i2 v2 m2) new_acc + and in_in_e2_first (_b1, e1) v1 m1 (_b2, e2 as i2) _v2 m2 acc new_v12= (*Format.printf "in_in_e2_first: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2; *) - assert (Int.lt e2 e1); - let new_acc = add_map_internal i2 new_v12 acc in - let new_i1 = (Int.succ e2,e1) in - try - let (new_i2, new_v2) = M.lowest_binding m2 in - let new_m2 = M.remove new_i2 m2 in - in_in_or_out new_i1 v1 m1 new_i2 new_v2 new_m2 new_acc - with M.Empty_rangemap -> - compute_remains_m1_and_merge - (add_map_internal new_i1 v1 m1) new_acc - and in_in_same_end (_b1, e1 as i1) _v1 m1 (_b2, e2) _v2 m2 acc new_v12= - (*Format.printf "in_in_same_end: b1=%a e1=%a b2=%a e2=%a@\n" + assert (Int.lt e2 e1); + let new_acc = add_map_internal i2 new_v12 acc in + let new_i1 = (Int.succ e2,e1) in + try + let (new_i2, new_v2) = M.lowest_binding m2 in + let new_m2 = M.remove new_i2 m2 in + in_in_or_out new_i1 v1 m1 new_i2 new_v2 new_m2 new_acc + with M.Empty_rangemap -> + compute_remains_m1_and_merge + (add_map_internal new_i1 v1 m1) new_acc + and in_in_same_end (_b1, e1 as i1) _v1 m1 (_b2, e2) _v2 m2 acc new_v12= + (*Format.printf "in_in_same_end: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2; *) - assert (Int.equal e1 e2); + assert (Int.equal e1 e2); - let acc = add_map_internal i1 new_v12 acc in + let acc = add_map_internal i1 new_v12 acc in try - let (new_i1, new_v1) = M.lowest_binding m1 in - let new_m1 = M.remove new_i1 m1 in - try - let (new_i2, new_v2) = M.lowest_binding m2 in - let new_m2 = M.remove new_i2 m2 in - out_out new_i1 new_v1 new_m1 new_i2 new_v2 new_m2 acc - with M.Empty_rangemap -> - compute_remains_m1_and_merge m1 acc - with M.Empty_rangemap -> - compute_remains_m2_and_merge m2 acc - and in_in (b1, e1 as i1) v1 m1 (b2, e2 as i2) v2 m2 acc = - (*Format.printf "in_in: b1=%a e1=%a b2=%a e2=%a@\n" + let (new_i1, new_v1) = M.lowest_binding m1 in + let new_m1 = M.remove new_i1 m1 in + try + let (new_i2, new_v2) = M.lowest_binding m2 in + let new_m2 = M.remove new_i2 m2 in + out_out new_i1 new_v1 new_m1 new_i2 new_v2 new_m2 acc + with M.Empty_rangemap -> + compute_remains_m1_and_merge m1 acc + with M.Empty_rangemap -> + compute_remains_m2_and_merge m2 acc + and in_in (b1, e1 as i1) v1 m1 (b2, e2 as i2) v2 m2 acc = + (*Format.printf "in_in: b1=%a e1=%a b2=%a e2=%a@\n" Int.pretty b1 Int.pretty e1 Int.pretty b2 Int.pretty e2; *) assert (Int.equal b1 b2); - let new_v12 = f (Some v1) (Some v2) in - (if Int.gt e1 e2 - then in_in_e2_first - else if Int.lt e1 e2 - then in_in_e1_first - else in_in_same_end) - i1 v1 m1 i2 v2 m2 acc new_v12 - in - try - let i1, v1 = M.lowest_binding m1 in - try - let i2, v2 = M.lowest_binding m2 in - let new_m1 = M.remove i1 m1 in - let new_m2 = M.remove i2 m2 in - Map (out_out i1 v1 new_m1 i2 v2 new_m2 M.empty) - with M.Empty_rangemap -> mm1 - with M.Empty_rangemap -> mm2 + let new_v12 = f (Some v1) (Some v2) in + (if Int.gt e1 e2 + then in_in_e2_first + else if Int.lt e1 e2 + then in_in_e1_first + else in_in_same_end) + i1 v1 m1 i2 v2 m2 acc new_v12 + in + try + let i1, v1 = M.lowest_binding m1 in + try + let i2, v2 = M.lowest_binding m2 in + let new_m1 = M.remove i1 m1 in + let new_m2 = M.remove i2 m2 in + Map (out_out i1 v1 new_m1 i2 v2 new_m2 M.empty) + with M.Empty_rangemap -> mm1 + with M.Empty_rangemap -> mm2 in (* check_contiguity(result);*) result @@ -551,55 +551,55 @@ let rec check_inter offs1 offs2 = let check bi ei = let concerned_intervals = - M.concerned_intervals - Int_Interv.fuzzy_order (bi,ei) offs2 + M.concerned_intervals + Int_Interv.fuzzy_order (bi,ei) offs2 in List.iter - (fun (_,(b,_v)) -> if not b then raise Is_not_included) - concerned_intervals + (fun (_,(b,_v)) -> if not b then raise Is_not_included) + concerned_intervals in let f (bi,ei) _ acc = match acc with - None -> - (* (* now we do something about -**..bi *) - if Int.neq bi Int.min_int - then check Int.min_int (Int.pred bi);*) - Some ei + None -> + (* (* now we do something about -**..bi *) + if Int.neq bi Int.min_int + then check Int.min_int (Int.pred bi);*) + Some ei | Some ek -> - let pbi = Int.pred bi in - if Int.lt ek pbi - then check (Int.succ ek) pbi; - Some ei + let pbi = Int.pred bi in + if Int.lt ek pbi + then check (Int.succ ek) pbi; + Some ei in match M.fold f offs1 None with | None -> () | Some _ek -> - (* if Int.lt ek Int.max_int - then check (Int.succ ek) Int.max_int *) + (* if Int.lt ek Int.max_int + then check (Int.succ ek) Int.max_int *) () let is_included_exn offs1 offs2 = if offs1 != offs2 then match offs1, offs2 with | Map offs1, Map offs2 -> - let treat_itv (_bi, _ei as i) (di,vi) = - let concerned_intervals = - M.concerned_intervals Int_Interv.fuzzy_order i offs2 - in - Int_Interv.check_coverage i concerned_intervals; - List.iter - (fun ((_bj, _ej),(dj,vj)) -> - if di && (not dj) then raise Is_not_included; - if not (V.is_included vi vj) then raise Is_not_included) - concerned_intervals - in - M.iter treat_itv offs1 ; - check_inter offs1 offs2 + let treat_itv (_bi, _ei as i) (di,vi) = + let concerned_intervals = + M.concerned_intervals Int_Interv.fuzzy_order i offs2 + in + Int_Interv.check_coverage i concerned_intervals; + List.iter + (fun ((_bj, _ej),(dj,vj)) -> + if di && (not dj) then raise Is_not_included; + if not (V.is_included vi vj) then raise Is_not_included) + concerned_intervals + in + M.iter treat_itv offs1 ; + check_inter offs1 offs2 | Degenerate _v1, Map _offs2 -> raise Is_not_included | _, Degenerate v2 -> - if not (V.is_included (collapse offs1) v2) - then raise Is_not_included + if not (V.is_included (collapse offs1) v2) + then raise Is_not_included let is_included m1 m2 = try is_included_exn m1 m2; true with @@ -611,12 +611,12 @@ *) if mm1 == mm2 then mm1 else let result = map2 - (fun v1 v2 -> match v1,v2 with - | None, None -> assert false - | Some v , None | None, Some v -> true, snd v - | Some v1, Some v2 -> + (fun v1 v2 -> match v1,v2 with + | None, None -> assert false + | Some v , None | None, Some v -> true, snd v + | Some v1, Some v2 -> (fst v1 || fst v2), (V.join (snd v1) (snd v2))) - mm1 mm2 + mm1 mm2 in (* check_contiguity(result);*) result @@ -656,27 +656,27 @@ let offset = Int.sub start_to start in let current = ref start in let f, treat_empty_space = - match f with - Some (f, default) -> f, - (fun acc i -> - let src_b = !current in - if My_bigint.le_big_int i src_b - then acc - else - let src_e = Int.pred i in - let dest_itv = Int.add (!current) offset, Int.add src_e offset in - (* Format.printf "treat_empty ib=%a ie=%a@." - Int.pretty src_b - Int.pretty src_e;*) - add_map_internal dest_itv (f (true, default src_b src_e)) acc) + match f with + Some (f, default) -> f, + (fun acc i -> + let src_b = !current in + if Int.le i src_b + then acc + else + let src_e = Int.pred i in + let dest_itv = Int.add (!current) offset, Int.add src_e offset in + (* Format.printf "treat_empty ib=%a ie=%a@." + Int.pretty src_b + Int.pretty src_e;*) + add_map_internal dest_itv (f (true, default src_b src_e)) acc) | None -> (fun x -> x), (fun acc _i -> acc) in let treat_interval ((b,_) as i,v) acc = - let acc = treat_empty_space acc b in + let acc = treat_empty_space acc b in let new_vv = f v in let src_b, src_e = Int_Interv.clip_itv ss i in let dest_i = Int.add src_b offset, Int.add src_e offset in - current := Int.succ src_e; + current := Int.succ src_e; (*Format.printf "treat_itv: ib=%a ie=%a v=%a dib=%a die=%a@." Int.pretty (fst i) Int.pretty (snd i) V.pretty v @@ -700,19 +700,19 @@ match from, _to with Map from, Map _to -> Map (copy_paste_map ~f from start stop start_to _to) | _, _ -> - let collapse_from = collapse from in - let value_from = - ( match f with - Some (f,_default) -> - (snd (f (true,collapse_from))) - | None -> collapse_from ) - in - Degenerate (V.join value_from (collapse _to)) + let collapse_from = collapse from in + let value_from = + ( match f with + Some (f,_default) -> + (snd (f (true,collapse_from))) + | None -> collapse_from ) + in + Degenerate (V.join value_from (collapse _to)) let copy_merge from start stop start_to _to = let old_value = copy_paste ~f:None - _to start_to + _to start_to (Int.sub (Int.add start_to stop) start) start empty in diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap_bitwise.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap_bitwise.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap_bitwise.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap_bitwise.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + open Abstract_interp open Abstract_value @@ -70,3 +75,9 @@ val tag: t -> int end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,7 +20,6 @@ (* *) (**************************************************************************) -(* Offsets encoding *) open Abstract_interp open Abstract_value open CilE @@ -38,7 +37,7 @@ val tag : t -> int val empty : t val is_empty : t -> bool - val pretty_c_assert_typ : + val pretty_c_assert_typ : string -> Cil_types.typ -> (unit->unit) -> Format.formatter -> t -> unit val pretty_typ : Cil_types.typ option -> Format.formatter -> t -> unit val pretty_debug : Format.formatter -> t -> unit @@ -46,13 +45,6 @@ val is_included : t -> t -> bool val is_included_exn : t -> t -> unit val is_included_exn_generic : (y -> y -> unit) -> t -> t -> unit - val is_included_actual_generic : - Base.Set.t -> - Base.Set.t ref -> - Locations.Location_Bytes.t Base.Map.t ref -> - t -> - t -> - unit val join : t -> t -> (Int.t * Int.t) list * t val widen : widen_hint -> t -> t -> t val find_ival : @@ -66,7 +58,7 @@ val concerned_bindings_ival : offsets:Ival.t -> offsetmap:t -> size:Int.t -> y list -> y list (** Returns the list of the values associated to at least one bit of the - ival. For this function Top is not a binding ! *) + ival. For this function Top is not a binding ! *) val update_ival : with_alarms:CilE.warn_mode -> validity:Base.validity -> @@ -78,10 +70,10 @@ val overwrite : t -> y -> Origin.t -> t val over_intersection : t -> t -> t (** An over-approximation of the intersection. The arguments can not be - arbitrary offsetmaps: the algorithm would be too complicated. The - provided algorithm should work fine with offsetmaps that correspond to - the relation view and the memory view of the same analysed code. *) - val from_string : string -> t + arbitrary offsetmaps: the algorithm would be too complicated. The + provided algorithm should work fine with offsetmaps that correspond to + the relation view and the memory view of the same analysed code. *) + val from_cstring : Base.cstring -> t val add_internal : itv -> Int.t * Int.t * y -> t -> t val add_whole : itv -> y -> t -> t val remove_whole : itv -> t -> t @@ -95,8 +87,8 @@ (itv -> (Int.t * Int.t * y) -> 'a -> 'a) -> t -> 'a -> 'a val shift_ival : Ival.t -> t -> t option -> t option (** [shift_ival shift o acc] returns the join of [acc] and - of [o] shifted by all values in [shift]. - Raises [Found_Top] when the result is [Top]. *) + of [o] shifted by all values in [shift]. + Raises [Found_Top] when the result is [Top]. *) val copy_paste : t -> Int.t -> Int.t -> Int.t -> t -> t val copy_merge : t -> Int.t -> Int.t -> Int.t -> t -> t val copy_offsmap : t -> Int.t -> Int.t -> t @@ -109,14 +101,15 @@ val sized_zero : size_in_bits:Int.t -> t val reciprocal_image : t -> Base.t -> Int_Intervals.t * Ival.t (** [reciprocal_image m b] is the set of bits in the offsetmap [m] - that may lead to Top([b]) and the set of offsets in [m] - where one can read an address [b]+_ *) + that may lead to Top([b]) and the set of offsets in [m] + where one can read an address [b]+_ *) val create_initial: v:y -> modu:Int.t -> t val reduce_by_int_intervals: t -> Abstract_value.Int_Intervals.t -> t - val top_stuff : (y -> bool) -> (y -> y) -> t -> t + val top_stuff : (y -> bool) -> (y -> 'a * y) -> ('a -> 'a -> 'a) -> 'a -> t -> 'a * t val iter_contents : (y -> unit) -> t -> Int.t -> unit (** Iter on the contents of offsetmap of given size *) val fold : (Int.t * Int.t -> Int.t * Int.t * y -> 'a -> 'a) -> t -> 'a -> 'a + val is : t -> y -> bool end module Build(V:Lattice_With_Isotropy.S) = struct @@ -149,62 +142,44 @@ let shift s v = M.shift s v - let types = Hashtbl.create 7;; - - let () = - Hashtbl.add types 1 "char"; - Hashtbl.add types 2 "short"; - Hashtbl.add types 4 "int"; - Hashtbl.add types 8 "long long"; - () - let pretty_c_assert_typ name _typ print_ampamp fmt offs = - let is_first = ref true in - let next () = - if !is_first then begin - is_first:=false; - print_ampamp (); - Format.fprintf fmt " ( "; - end - else Format.fprintf fmt " || "; - in let pretty_binding (bk,ek) (offst,modu,v) = - if Int.is_zero (Int.rem bk Int.eight) - && (Int.equal (Int.pos_rem bk modu) offst) + if Int.is_zero (Int.rem bk Int.eight) + && (Int.equal (Int.pos_rem bk modu) offst) then - let ek = Int.succ ek in - if Int.is_zero (Int.rem ek Int.eight) - then - let s = Int.sub ek bk in - if (V.is_isotropic v || Int.equal s modu) - then - let s_bytes = Int.div s Int.eight in - let s_bytes = try Int.to_int s_bytes with _ -> assert false in - try - let typname = Hashtbl.find types s_bytes in - let lv = - Format.sprintf "*(%s *)((unsigned char*)&%s+%d)" - typname - name - s_bytes - in - next(); - V.pretty_c_assert lv s fmt v - with Not_found -> () - else () - else () + let ek = Int.succ ek in + if Int.is_zero (Int.rem ek Int.eight) + then + + let step = if V.is_isotropic v then 1 else (Int.to_int modu) / 8 in + let start = ref ((Int.to_int bk) / 8) in + let ek = Int.to_int ek in + let ek = ek / 8 in + while !start < ek do + let lv = + if !start = 0 + then + Format.sprintf "&%s" name + else + Format.sprintf "((unsigned char*)&%s+%d)" + name + !start + in + V.pretty_c_assert print_ampamp lv step fmt v; + start := !start + step + done; + else () else () in - M.iter pretty_binding offs; - if not !is_first then Format.fprintf fmt " ) " + M.iter pretty_binding offs let pretty_debug fmt m = M.pretty (fun fmt (r,m,v) -> - Format.fprintf fmt "{r=%a;m=%a;v=%a}" - Int.pretty r - Int.pretty m - V.pretty v) + Format.fprintf fmt "{r=%a;m=%a;v=%a}" + Int.pretty r + Int.pretty m + V.pretty v) fmt m @@ -260,26 +235,26 @@ Format.fprintf fmt "@[" ; (* Print left-member and return misalign condition *) let force_misalign = - match typ with + match typ with | None -> Format.fprintf fmt "[rbits %a to %a]" - Int.pretty bk Int.pretty ek ; - (* misalign condition: *) + Int.pretty bk Int.pretty ek ; + (* misalign condition: *) not ((Int.equal (Int.rem bk modu) offs) && (Int.equal (Int.sub ek bk) (Int.pred modu))) && not (V.is_isotropic v) | Some typ -> - (* returns misalign condition. *) + (* returns misalign condition. *) Bit_utils.pretty_bits typ - ~use_align:(not (V.is_isotropic v)) - ~align:offs ~rh_size:modu ~start:bk ~stop:ek fmt + ~use_align:(not (V.is_isotropic v)) + ~align:offs ~rh_size:modu ~start:bk ~stop:ek fmt in Format.fprintf fmt " %s@ @[%a@]" inset_utf8 V.pretty v ; - if force_misalign + if force_misalign then - Format.fprintf fmt " %s %a%%%a " - (if (Int.equal (Int.rem bk modu) offs) + Format.fprintf fmt " %s %a%%%a " + (if (Int.equal (Int.rem bk modu) offs) && (Int.equal (Int.rem (Int.succ ek) modu) offs) then "repeated" else "misaligned") @@ -306,32 +281,33 @@ let conv = Int.to_int64 in fold_internal ( fun (a, b) (r, m, v) (c, acc) -> - if Int.equal c Int.minus_one && not (Int.is_zero a) - then raise Not_translatable; - let acc = - if Int.equal (Int.succ c) a then acc - else raise Not_translatable -(* let _, acc1 = New.add_node +(* Format.printf "translating %a %a@." + Int.pretty a Int.pretty b; *) + let acc = + if not (Int.equal (Int.succ c) a) + then snd (New.add_node (conv (Int.succ c)) (conv (Int.pred a)) - Int64.zero Int64.one V.top Int64.zero acc - in acc1 *) - in + Int64.zero Int64.one V.top Int64.zero acc) + else acc + in let o, t = New.add_node (conv a) (conv b) (conv r) (conv m) v Int64.zero acc in assert (o = Int64.zero); - (Int.of_int64 o), t + b, t ) - omap (Int.minus_one, (New.empty)) + omap (Int.minus_one, New.empty) ;; +let translate_from_old omap = snd (translate_from_old omap) + let reciprocal_image m base = let treat_binding (bi,ei as itv) (r,modu,v) (acc1,acc2) = let acc1 = if Locations.Location_Bytes.may_reach base (V.project v) then Int_Intervals.join acc1 (Int_Intervals.inject [itv]) else acc1 in - let acc2 = + let acc2 = if (Locations.Location_Bytes.intersects (Locations.Location_Bytes.inject base Ival.top) (V.project v)) @@ -339,15 +315,15 @@ then let first = Int.round_up_to_r ~min:bi ~r ~modu in let last = - Int.mul - (Int.pred (Int.div (Int.succ (Int.sub ei first)) modu)) - modu - in + Int.mul + (Int.pred (Int.div (Int.succ (Int.sub ei first)) modu)) + modu + in if Int.lt last Int.zero then acc2 else - Ival.join - acc2 - (Ival.inject_top (Some first) (Some (Int.add first last)) r modu) + Ival.join + acc2 + (Ival.inject_top (Some first) (Some (Int.add first last)) r modu) else acc2 in acc1,acc2 @@ -378,7 +354,7 @@ let merge_bits ~offset ~length ~value ~total_length acc = assert ( let total_length_i = Int.of_int total_length in - Int.le (Int.add length offset) total_length_i); + Int.le (Int.add length offset) total_length_i); if Cil.theMachine.Cil.little_endian then V.little_endian_merge_bits ~offset ~value ~total_length acc else @@ -392,67 +368,67 @@ let total_length = Int.to_int (Int.length bi ei) in let treat_concerned_interval - ((b1,e1),(offs,modu,v)) (acc_inform, acc_value) = - (* Format.printf "find debugging bi:%a ei:%a b1:%a e1:%a@." - Int.pretty bi Int.pretty ei - Int.pretty b1 Int.pretty e1; *) + ((b1,e1),(offs,modu,v)) (acc_inform, acc_value) = + (* Format.printf "find debugging bi:%a ei:%a b1:%a e1:%a@." + Int.pretty bi Int.pretty ei + Int.pretty b1 Int.pretty e1; *) let treat_value offs1 (acc_inform, acc_value) = - (* Format.printf "find treat_value debugging offs:%a@." - Int.pretty offs; *) + (* Format.printf "find treat_value debugging offs:%a@." + Int.pretty offs; *) let offset = Int.sub offs1 bi in let offset,start = - if Int.lt offset Int.zero - then + if Int.lt offset Int.zero + then Int.zero, Int.neg offset else - offset, Int.zero + offset, Int.zero in let stop = Int.pred modu in let stop = let end_ = Int.min (Int.pred (Int.add offs1 modu)) e1 in let over = Int.sub end_ ei in if Int.gt over Int.zero - then + then Int.sub stop over else - stop + stop in - assert (not (V.is_isotropic v)); + assert (not (V.is_isotropic v)); let inform_extract_pointer_bits, value = extract_bits ~start ~stop ~modu v in - inform_extract_pointer_bits || acc_inform, + inform_extract_pointer_bits || acc_inform, merge_bits ~conflate_bottom ~offset ~length:(Int.length start stop) - ~value ~total_length acc_value + ~value ~total_length acc_value in let length =Int.length b1 e1 in if V.is_isotropic v then begin - if conflate_bottom && V.equal V.bottom v then raise Bottom_found; - let offs_start = Int.max b1 bi in - let offs_stop = Int.min e1 ei in - let offset = Int.sub offs bi in - let offset = - if Int.lt offset Int.zero then Int.zero else offset - in - acc_inform, - merge_bits ~offset ~length:(Int.length offs_start offs_stop) - ~conflate_bottom - ~value:v ~total_length acc_value - end + if conflate_bottom && V.equal V.bottom v then raise Bottom_found; + let offs_start = Int.max b1 bi in + let offs_stop = Int.min e1 ei in + let offset = Int.sub offs bi in + let offset = + if Int.lt offset Int.zero then Int.zero else offset + in + acc_inform, + merge_bits ~offset ~length:(Int.length offs_start offs_stop) + ~conflate_bottom + ~value:v ~total_length acc_value + end else if (Int.is_zero (Int.rem length modu)) && (Int.equal (Int.rem b1 modu) offs) then - Int.fold - treat_value - ~inf:(Int.max b1 (Int.round_down_to_r ~max:bi ~r:offs ~modu)) - ~sup:(Int.min e1 ei) - ~step:modu + Int.fold + treat_value + ~inf:(Int.max b1 (Int.round_down_to_r ~max:bi ~r:offs ~modu)) + ~sup:(Int.min e1 ei) + ~step:modu (acc_inform, acc_value) else - acc_inform, + acc_inform, V.join - (V.topify_misaligned_read_origin v) - acc_value + (V.topify_misaligned_read_origin v) + acc_value in List.fold_right treat_concerned_interval @@ -474,48 +450,48 @@ in match concerned_intervals with | [(b,e),(offs,modu,v)] -> - if (Int.le b bi) && (Int.ge e ei) then - let isotropic = V.is_isotropic v in + if (Int.le b bi) && (Int.ge e ei) then + let isotropic = V.is_isotropic v in if isotropic || ((Int.equal modu (Int.length bi ei)) && (Int.equal (Int.rem bi modu) offs)) then - let read_ahead = - if Int.is_zero (Int.rem period_read_ahead modu) - then Some e - else None - in - false, read_ahead, v + let read_ahead = + if Int.is_zero (Int.rem period_read_ahead modu) + then Some e + else None + in + false, read_ahead, v else - let inform, v = - if (* [(bi-offs)/modu = (ei-offs)/modu] - i.e. [bi] and [ei] are in the same slice. *) - Int.equal - (Int.pos_div (Int.sub bi offs) modu) - (Int.pos_div (Int.sub ei offs) modu) + let inform, v = + if (* [(bi-offs)/modu = (ei-offs)/modu] + i.e. [bi] and [ei] are in the same slice. *) + Int.equal + (Int.pos_div (Int.sub bi offs) modu) + (Int.pos_div (Int.sub ei offs) modu) then - extract_bits - ~start:(Int.pos_rem (Int.sub bi offs) modu) - ~stop:(Int.pos_rem (Int.sub ei offs) modu) - ~modu - v - else - extract_bits_and_stitch - ~conflate_bottom - i concerned_intervals - (* the result depends on several instances of - the same repeated value but is completely covered*) - in - inform, None, v + extract_bits + ~start:(Int.pos_rem (Int.sub bi offs) modu) + ~stop:(Int.pos_rem (Int.sub ei offs) modu) + ~modu + v + else + extract_bits_and_stitch + ~conflate_bottom + i concerned_intervals + (* the result depends on several instances of + the same repeated value but is completely covered*) + in + inform, None, v else - false, None, V.top (* the result depends on unbound bits *) + false, None, V.top (* the result depends on unbound bits *) | [] -> false, None, V.top | _ -> - let inform, v = - extract_bits_and_stitch - ~conflate_bottom i concerned_intervals - in - inform, None, v + let inform, v = + extract_bits_and_stitch + ~conflate_bottom i concerned_intervals + in + inform, None, v let find_imprecise bi ei m = assert (Int.le bi ei); @@ -527,11 +503,11 @@ Int_Interv.check_coverage (bi,ei) concerned_intervals; List.fold_left (fun acc (_, (_,_,v)) -> - V.join - acc - ( if V.is_isotropic v - then v - else V.topify_misaligned_read_origin v ) ) + V.join + acc + ( if V.is_isotropic v + then v + else V.topify_misaligned_read_origin v ) ) V.bottom concerned_intervals with Is_not_included (* from check_coverage *) -> V.top @@ -539,7 +515,7 @@ let add_if_not_default i (_,_,v as vv) (m:t) = let result = if V.equal v V.top then m else - M.add i vv m + M.add i vv m in result @@ -548,21 +524,22 @@ let cardinal_zero_or_one validity offsetmap = let r = match validity with - | Base.All | Base.Periodic _ -> false + | Base.All -> false + | Base.Periodic (min, max, _) | Base.Known(min, max) | Base.Unknown(min, max) -> - begin try - let up_to = - M.fold - (fun (bi,ei) (_r,_m,v) min -> - if Int.gt bi min then raise More_than_one; - if not (V.cardinal_zero_or_one v) then raise More_than_one; - (Int.succ ei)) - offsetmap - min - in - Int.gt up_to max - with More_than_one -> false - end + begin try + let up_to = + M.fold + (fun (bi,ei) (_r,_m,v) min -> + if Int.gt bi min then raise More_than_one; + if not (V.cardinal_zero_or_one v) then raise More_than_one; + (Int.succ ei)) + offsetmap + min + in + Int.gt up_to max + with More_than_one -> false + end in r @@ -571,34 +548,34 @@ | Base.All -> V.top | Base.Periodic _ -> assert false (* TODO *) | Base.Known (bound_min,bound_max) | Base.Unknown (bound_min,bound_max) - when Int.lt bound_max bound_min -> - V.bottom + when Int.lt bound_max bound_min -> + V.bottom | Base.Known (bound_min,bound_max) | Base.Unknown (bound_min,bound_max) -> - let next = ref bound_min in - try - let r = - M.fold - (fun (bi,ei) (_r,_m,v) acc -> - if Int.equal bi !next - then begin - next := Int.succ ei; - V.join - acc - ( if V.is_isotropic v - then v - else V.topify_misaligned_read_origin v ) - end - else begin - assert (Int.gt bi !next); - raise Found_Top - end;) - m - V.bottom - in - if Int.gt !next bound_max - then r - else V.top - with Found_Top -> V.top + let next = ref bound_min in + try + let r = + M.fold + (fun (bi,ei) (_r,_m,v) acc -> + if Int.equal bi !next + then begin + next := Int.succ ei; + V.join + acc + ( if V.is_isotropic v + then v + else V.topify_misaligned_read_origin v ) + end + else begin + assert (Int.gt bi !next); + raise Found_Top + end;) + m + V.bottom + in + if Int.gt !next bound_max + then r + else V.top + with Found_Top -> V.top (* Merge neighboring values with the inserted value if necessary.*) let add_internal ((bi,ei) as i) (_new_offs,_new_modu,v as new_vv) m = @@ -628,24 +605,25 @@ Int.pretty new_bi Int.pretty new_ei (pretty None) cleaned_m;*) (* Add the new binding *) - let result = add_if_not_default (new_bi,new_ei) new_vv cleaned_m in - result + let result = add_if_not_default (new_bi,new_ei) new_vv cleaned_m in + result - let top_stuff f topify offsm = + let top_stuff f topify join_locals acc_locals offsm = assert (not (is_empty offsm)); M.fold - (fun (_,_ as i) (r,m,v) acc -> - assert (Int.lt r m); - assert (Int.le Int.zero r); - assert (if V.is_isotropic v then Int.is_one m else true); + (fun (_,_ as i) (r,m,v) (acc_locals, acc_o as acc) -> + assert (Int.lt r m); + assert (Int.le Int.zero r); + assert (if V.is_isotropic v then Int.is_one m else true); assert (not (V.equal V.top v)); - if f v - then - let topified_v = topify v in - add_internal i (r, m, topified_v) acc - else acc) - offsm + if f v + then + let locals, topified_v = topify v in + (join_locals acc_locals locals), + add_internal i (r, m, topified_v) acc_o + else acc) offsm + (acc_locals, offsm) (* Highest level insertion. [add (be, ei) v m] inserts [v] in [m] at interval [be,ei] assuming the @@ -674,7 +652,7 @@ let new_v = V.narrow old_v v in if (V.equal v new_v) then raise Result_is_same; - M.add i (rem, modu, v) (M.remove i m) + M.add i (rem, modu, v) (M.remove i m) with Int_Interv.Cannot_compare_intervals -> raise Result_is_same @@ -693,11 +671,11 @@ (* [start_aligned] is equal to [offs] modulo [modu] *) let result1 = if not (Int.equal start_aligned be) - then begin -(* Format.printf "split_interval:treat_misaligned:be=%Ld en=%Ld@\n" - be (Int.pred start_aligned);*) + then begin +(* Format.printf "split_interval:treat_misaligned:be=%Ld en=%Ld@\n" + be (Int.pred start_aligned);*) treat_misaligned be (Int.pred start_aligned) acc - end + end else acc in let last_aligned = @@ -712,11 +690,11 @@ in let result3 = if not (Int.equal last_aligned en) - then begin -(* Format.printf "split_interval:treat_misaligned:be=%Ld en=%Ld@\n" - (Int.succ last_aligned) en;*) + then begin +(* Format.printf "split_interval:treat_misaligned:be=%Ld en=%Ld@\n" + (Int.succ last_aligned) en;*) treat_misaligned (Int.succ last_aligned) en result2 - end + end else result2 in (* Format.printf "split_interval:finished@\n";*) @@ -725,7 +703,7 @@ let map ~treat_aligned ~treat_misaligned:_ (m:t) = let result = M.fold - (fun (be,en) (offs1, modu1, v1) acc -> + (fun (be,en) (offs1, modu1, v1) acc -> let treat_aligned ~inf ~sup acc = let new_itv = (inf,sup) in let v2 = treat_aligned v1 in @@ -734,8 +712,8 @@ let treat_misaligned _be1 _en1 _acc = assert false in split_interval be en offs1 modu1 ~treat_aligned ~treat_misaligned acc) - m - empty + m + empty in result let is_instance_one_itv (itv1,_triple1) offsetmap2 = @@ -760,12 +738,27 @@ let e = pred (b + char_width) in add (Int.of_int b, Int.of_int e) (V.singleton_zero) !r + let from_wstring s = + let pwchar_width = + Int.of_int (pred (Cil.bitsSizeOf Cil.theMachine.Cil.wcharType)) + in + let addw (b,acc) wchar = + let e = Int.add b pwchar_width in + Int.succ e, (add (b, e) (V.of_int64 wchar) acc) + in + snd (List.fold_left addw (Int.zero,empty) s) + + let from_cstring cs = + match cs with + Base.CSWstring w -> from_wstring w + | Base.CSString s -> from_string s + let is_included_exn_generic v_is_included_exn m1 m2 = (* Format.printf "Offsetmap.is_included_exn_generic %a@\nIN %a@\n" (pretty None) m1 (pretty None) m2 ; *) (* if m1 != m2 then -- done by caller *) M.iter - (fun (bi,ei as i) (offs2, modu2, v2) -> + (fun (bi,ei as i) (offs2, modu2, v2) -> let itvs1 = M.concerned_intervals Int_Interv.fuzzy_order i m1 in begin match itvs1 with @@ -780,43 +773,32 @@ (* [m1] has top for something present in [m2] *) v_is_included_exn v1 v2; (* raise Is_not_included if [v2] does not include [v1] *) - if not (V.is_isotropic v2) - then begin + if not (V.is_isotropic v2) + then begin if (not (V.is_isotropic v1)) - && not ((Int.equal offs1 offs2 && - Int.equal modu1 modu2)) + && not ((Int.equal offs1 offs2 && + Int.equal modu1 modu2)) then raise Is_not_included; (* The alignment is different *) if not (Int.equal bx bi) && - (not (Int.is_zero (Int.rem (Int.sub bx offs1) modu1))) + (not (Int.is_zero (Int.rem (Int.sub bx offs1) modu1))) then raise Is_not_included; if not (Int.equal ex ei) && - (not (Int.is_zero - (Int.rem (Int.sub (Int.pred offs1) ex) modu1))) + (not (Int.is_zero + (Int.rem (Int.sub (Int.pred offs1) ex) modu1))) then raise Is_not_included; (* the interval [i] is covered by pieces only in [m1], which is less precise than what is in [m2] *) - end; + end; Int.succ ex) itvs1 - bi)) + bi)) m2 (* ;Format.printf "Offsetmap.is_included_exn_generic : WAS included@\n" *) let is_included_exn = is_included_exn_generic V.is_included_exn - let is_included_actual_generic bases q instanciation actual formal = - let v_is_included v1 v2 = -(* try *) - V.is_included_actual_generic bases q instanciation v1 v2 -(* with Is_not_included -> - Format.printf "Not included : %a %a@." - V.pretty v1 V.pretty v2; ignore (assert false) ; - raise Is_not_included*) - in - is_included_exn_generic v_is_included actual formal - (* For all k,v in m2, v contains (find k m1). This is correct only because the default value is top. *) let is_included m1 m2 = @@ -837,12 +819,10 @@ true with Is_not_included -> false in - let _, t1 = translate_from_old m1 - and _, t2 = translate_from_old m2 in - let o1 = Int64.zero - and o2 = Int64.zero in + let t1 = translate_from_old m1 + and t2 = translate_from_old m2 in - let rnew = is_included o1 t1 o2 t2 + let rnew = New.is_included t1 t2 in if r <> rnew then @@ -850,9 +830,9 @@ Format.printf "*** ISINC@ %b %b @.m1: %a@.t1: %a@.m2: %a@.t2: %a@." r rnew pretty_compare m1 - (pretty_offset o1) t1 + New.pretty t1 pretty_compare m2 - (pretty_offset o2) t2 ; + New.pretty t2 ; (assert false) end else r @@ -870,14 +850,14 @@ let r = if m1 == m2 then m1 else begin M.fold - (fun (be,en) (offs1, modu1, v1 as triple1) acc -> + (fun (be,en) (offs1, modu1, v1 as triple1) acc -> let itvs2 = M.concerned_intervals Int_Interv.fuzzy_order (be,en) m2 in List.fold_left (fun acc ((xb,xe),(offs2,modu2,v2 as triple2)) -> - let inter_b = Int.max xb be in - let inter_e = Int.min en xe in + let inter_b = Int.max xb be in + let inter_e = Int.min en xe in let do_topify acc = add_internal (inter_b,inter_e) (Int.zero, Int.one, @@ -887,22 +867,22 @@ acc in let treat_misaligned _be2 _en2 acc = - if Int_Int_V.equal triple1 triple2 - then add_internal (inter_b,inter_e) triple1 acc - else if Int.equal offs1 offs2 && Int.equal modu1 modu2 - then - add_internal (inter_b,inter_e) - (offs1,modu1,f ~size:modu1 ~offs:None v1 v2) acc - else if V.is_isotropic v1 - then + if Int_Int_V.equal triple1 triple2 + then add_internal (inter_b,inter_e) triple1 acc + else if Int.equal offs1 offs2 && Int.equal modu1 modu2 + then + add_internal (inter_b,inter_e) + (offs1,modu1,f ~size:modu1 ~offs:None v1 v2) acc + else if V.is_isotropic v1 + then add_internal (inter_b,inter_e) (offs2,modu2,f ~size:modu2 ~offs:None v1 v2) acc else if V.is_isotropic v2 - then + then add_internal (inter_b,inter_e) (offs1,modu1,f ~size:modu1 ~offs:None v1 v2) acc else do_topify acc - in + in if V.is_isotropic v1 then let treat_aligned ~inf ~sup acc = let new_itv = (inf,sup) in @@ -926,8 +906,8 @@ else do_topify acc) acc itvs2) - m1 - empty + m1 + empty end in (*Format.printf "join/widen V1:%a V2:%a leads to %a@\n" (pretty None) m1 (pretty None) m2 (pretty None) r @@ -938,12 +918,12 @@ let joined = V.join v w in let joined = V.anisotropic_cast ~size joined in ( match offs with - Some offs when - V.cardinal_zero_or_one v && V.cardinal_zero_or_one w - && (not (V.cardinal_zero_or_one joined)) - && (!ex_singletons_card < relations_extract_limit) -> - incr ex_singletons_card; - ex_singletons := (offs, size) :: !ex_singletons + Some offs when + V.cardinal_zero_or_one v && V.cardinal_zero_or_one w + && (not (V.cardinal_zero_or_one joined)) + && (!ex_singletons_card < relations_extract_limit) -> + incr ex_singletons_card; + ex_singletons := (offs, size) :: !ex_singletons | _ -> ()); joined in @@ -969,117 +949,117 @@ let over_intersection m1 m2 = (* Format.printf "over_intersection:@\n%a@\nand@\n%a@." - (pretty None) m1 - (pretty None) m2; *) + (pretty None) m1 + (pretty None) m2; *) let rec over_intersection_rec continue acc = try - let (_b1, _e1 as itv1),v1 = M.find_above continue m1 in - try - let (_b2, _e2 as itv2),v2 = M.find_above continue m2 in - treat_the_lowest_binding itv1 v1 itv2 v2 acc - with M.No_such_binding -> - (* m2 is finished *) - (M.fold - (fun (bi, ei as itv) vv (_cont, acc) -> - if Int.ge bi continue - then ei, M.add itv vv acc - else ei, acc) - m1 - (continue, acc)) + let (_b1, _e1 as itv1),v1 = M.find_above continue m1 in + try + let (_b2, _e2 as itv2),v2 = M.find_above continue m2 in + treat_the_lowest_binding itv1 v1 itv2 v2 acc + with M.No_such_binding -> + (* m2 is finished *) + (M.fold + (fun (bi, ei as itv) vv (_cont, acc) -> + if Int.ge bi continue + then ei, M.add itv vv acc + else ei, acc) + m1 + (continue, acc)) with M.No_such_binding -> - (* m1 is finished *) - (M.fold - (fun (bi, ei as itv) vv (_cont, acc) -> - if Int.ge bi continue - then ei, M.add itv vv acc - else ei, acc) - m2 - (continue, acc)) + (* m1 is finished *) + (M.fold + (fun (bi, ei as itv) vv (_cont, acc) -> + if Int.ge bi continue + then ei, M.add itv vv acc + else ei, acc) + m2 + (continue, acc)) and treat_the_lowest_binding (b1,_e1 as itv1) (_,_,_v1 as v1) (b2,_e2 as itv2) (_,_,_v2 as v2) acc = (* Format.printf "treat_the_lowest_binding: %a..%a -> %a %a..%a -> %a@." - Int.pretty b1 Int.pretty _e1 V.pretty _v1 - Int.pretty b2 Int.pretty _e2 V.pretty _v2; *) + Int.pretty b1 Int.pretty _e1 V.pretty _v1 + Int.pretty b2 Int.pretty _e2 V.pretty _v2; *) let itv, vv, first_m, other_m = - if Int.lt b1 b2 - then itv1,v1,m1,m2 - else itv2,v2,m2,m1 + if Int.lt b1 b2 + then itv1,v1,m1,m2 + else itv2,v2,m2,m1 in treat_lowest_binding itv vv first_m other_m acc and treat_lowest_binding - (b, e as itv) (offs,modu,v as vv) first_m other_m acc = + (b, e as itv) (offs,modu,v as vv) first_m other_m acc = let concerned_intervals = - M.concerned_intervals Int_Interv.fuzzy_order itv other_m + M.concerned_intervals Int_Interv.fuzzy_order itv other_m in let treat_interval ((bc, ec as _itvc), (offsc,moduc,vc as vvc)) - (next, acc) = - (* Format.printf "treat_interval: %a..%a -> %a, continue=%a@." - Int.pretty bc Int.pretty ec V.pretty vc - Int.pretty next;*) - let acc = - if Int.equal bc next - then acc - else begin - (* add a binding to vv in the result where there is no - binding in other_m *) - assert (Int.lt next bc); - M.add (next, Int.pred bc) vv acc - end - in - let same_align = Int.equal moduc modu && Int.equal offsc offs in - if (not (Int.is_one moduc)) && - (not (Int.is_one modu)) && - (not same_align) - then begin - Format.printf "An assumption made for the implementation of this tool turns out to be invalid. Please report the appearance of this message. If possible, please provide a reasonably-sized example that provokes it. The correctness of the computations is not affected and the analysis will continue\n"; - raise Not_aligned - end; - let inter_vv = - if same_align - then (offs, modu, V.narrow v vc) - else (Int.zero, Int.one, - V.narrow (V.under_topify v) (V.under_topify vc)) - in - let over_reach = Int.gt ec e in - let actual_end = - if over_reach - then e - else ec - in - let new_next = Int.succ actual_end in - let new_acc = M.add (bc, actual_end) inter_vv acc in - if over_reach - then (* if we arrive here, we are necessarily treating - the last interval in the list, but we have to - chain to the treatment of the over-reaching part *) - raise (Continue_here( (new_next,ec), vvc, other_m, first_m, new_acc)) - else - new_next, new_acc + (next, acc) = + (* Format.printf "treat_interval: %a..%a -> %a, continue=%a@." + Int.pretty bc Int.pretty ec V.pretty vc + Int.pretty next;*) + let acc = + if Int.equal bc next + then acc + else begin + (* add a binding to vv in the result where there is no + binding in other_m *) + assert (Int.lt next bc); + M.add (next, Int.pred bc) vv acc + end + in + let same_align = Int.equal moduc modu && Int.equal offsc offs in + if (not (Int.is_one moduc)) && + (not (Int.is_one modu)) && + (not same_align) + then begin + Format.printf "An assumption made for the implementation of this tool turns out to be invalid. Please report the appearance of this message. If possible, please provide a reasonably-sized example that provokes it. The correctness of the computations is not affected and the analysis will continue\n"; + raise Not_aligned + end; + let inter_vv = + if same_align + then (offs, modu, V.narrow v vc) + else (Int.zero, Int.one, + V.narrow (V.under_topify v) (V.under_topify vc)) + in + let over_reach = Int.gt ec e in + let actual_end = + if over_reach + then e + else ec + in + let new_next = Int.succ actual_end in + let new_acc = M.add (bc, actual_end) inter_vv acc in + if over_reach + then (* if we arrive here, we are necessarily treating + the last interval in the list, but we have to + chain to the treatment of the over-reaching part *) + raise (Continue_here( (new_next,ec), vvc, other_m, first_m, new_acc)) + else + new_next, new_acc in try - let next, acc = - List.fold_right treat_interval concerned_intervals (b,acc) - in - let acc = - if Int.gt next e - then acc - else M.add (next, e) vv acc - in - over_intersection_rec (Int.succ e) acc + let next, acc = + List.fold_right treat_interval concerned_intervals (b,acc) + in + let acc = + if Int.gt next e + then acc + else M.add (next, e) vv acc + in + over_intersection_rec (Int.succ e) acc with Continue_here(itv, vvc, other_m, first_m, new_acc) -> - treat_lowest_binding itv vvc other_m first_m new_acc + treat_lowest_binding itv vvc other_m first_m new_acc in let result = try - let itv1, v1 = M.lowest_binding m1 in - try - let itv2, v2 = M.lowest_binding m2 in - snd (treat_the_lowest_binding itv1 v1 itv2 v2 empty) - with M.Empty_rangemap -> - (* m2 is empty *) - m1 + let itv1, v1 = M.lowest_binding m1 in + try + let itv2, v2 = M.lowest_binding m2 in + snd (treat_the_lowest_binding itv1 v1 itv2 v2 empty) + with M.Empty_rangemap -> + (* m2 is empty *) + m1 with M.Empty_rangemap -> - (* m1 is empty *) - m2 + (* m1 is empty *) + m2 in (* Format.printf "over_intersection:@\n%a@\nand@\n%a@\n->@\n%a@." (pretty None) m1 @@ -1094,7 +1074,7 @@ (Format.printf "Non commuting join %a@\n with %a@\n leads to %a@\n and %a@\n" pretty m1 pretty m2 - pretty r1 pretty r2; + pretty r1 pretty r2; false)); singletons, r1 ;; @@ -1126,54 +1106,54 @@ let add_approximate_including_spaces mn mx r m size v existing_offsetmap = let treat_itv (b,e as itv) (rem,modu,value as vv) acc= if (Int.lt e mn) - || (Int.ge b (Int.add mx size)) + || (Int.ge b (Int.add mx size)) then (* non intersecting interval *) - add_internal itv vv acc + add_internal itv vv acc else begin - let acc,new_b = - if Int.lt b mn - then + let acc,new_b = + if Int.lt b mn + then (add_internal - (b,Int.pred mn) - vv - acc, + (b,Int.pred mn) + vv + acc, mn) - else acc,b - in - let acc,new_e = - if Int.gt e (Int.pred (Int.add mx size)) - then + else acc,b + in + let acc,new_e = + if Int.gt e (Int.pred (Int.add mx size)) + then let mx = Int.add mx size in let acc = add_internal (mx,e) vv acc in acc, Int.pred mx - else acc,e - in + else acc,e + in let new_r,new_modu,cond = - if Int.equal m size - then + if Int.equal m size + then if (Int.equal r rem && Int.equal m modu) || V.is_isotropic value - then r,m,true + then r,m,true else Int.zero,Int.one,false else begin assert (Int.lt size m); - let number = Int.succ (Int.div (Int.sub mx mn) m) in - warn_once - "more than %d(%a) locations to update in array. Approximating." - (Parameters.Dynamic.Int.get "-plevel") - Int.pretty number; - Int.zero,Int.one,false + let number = Int.succ (Int.div (Int.sub mx mn) m) in + Kernel.result ~current:true ~once:true + "more than %d(%a) locations to update in array. Approximating." + (Kernel.ArrayPrecisionLevel.get()) + Int.pretty number; + Int.zero,Int.one,false end in let new_v = - (if cond - then - V.anisotropic_cast ~size:new_modu - (V.join v value) - else - V.join - (V.topify_misaligned_read_origin v) - (V.topify_misaligned_read_origin value)) - in + (if cond + then + V.anisotropic_cast ~size:new_modu + (V.join v value) + else + V.join + (V.topify_misaligned_read_origin v) + (V.topify_misaligned_read_origin value)) + in add_internal (new_b,new_e) (new_r,new_modu,new_v) @@ -1188,20 +1168,20 @@ let add_approximate offset size v offsetmap_orig = if V.is_isotropic v then begin - let e_max = Int.add offset (Int.pred size) in - let concerned_intervals = - M.concerned_intervals - Int_Interv.fuzzy_order - (offset, e_max) - offsetmap_orig - in - let treat_itv acc ((b,e), (rem,modu,value)) = - let new_b = Int.max b offset in - let new_e = Int.min e e_max in - let new_v = V.join v value in - add_internal (new_b, new_e) (rem, modu, new_v) acc - in - List.fold_left treat_itv offsetmap_orig concerned_intervals + let e_max = Int.add offset (Int.pred size) in + let concerned_intervals = + M.concerned_intervals + Int_Interv.fuzzy_order + (offset, e_max) + offsetmap_orig + in + let treat_itv acc ((b,e), (rem,modu,value)) = + let new_b = Int.max b offset in + let new_e = Int.min e e_max in + let new_v = V.join v value in + add_internal (new_b, new_e) (rem, modu, new_v) acc + in + List.fold_left treat_itv offsetmap_orig concerned_intervals end else add_approximate_including_spaces offset offset @@ -1215,8 +1195,8 @@ let v = V.topify_with_origin o v in M.fold (fun itv (_offs,_modu,bound_v) acc -> - let new_v = V.join (V.topify_with_origin o bound_v) v in - add_internal itv (Int.zero, Int.one, new_v) acc) + let new_v = V.join (V.topify_with_origin o bound_v) v in + add_internal itv (Int.zero, Int.one, new_v) acc) offsetmap_orig empty @@ -1224,147 +1204,18 @@ is known only as an interval of integers modulo *) let add_top_binding_offsetmap mn mx r m size v existing_offsetmap = let number = Int.succ (Int.div (Int.sub mx mn) m) in - let plevel = Parameters.Dynamic.Int.get "-plevel" in + let plevel = (Kernel.ArrayPrecisionLevel.get()) in if Int.le number (Int.of_int plevel) && (Int.gt m size) then Int.fold - (fun offs acc -> add_approximate offs size v acc) - ~inf:mn - ~sup:mx - ~step:m - existing_offsetmap + (fun offs acc -> add_approximate offs size v acc) + ~inf:mn + ~sup:mx + ~step:m + existing_offsetmap else add_approximate_including_spaces mn mx r m size v existing_offsetmap - type interval_or_set = - Set of Ival.O.t - | Interval of Int.t * Int.t * Int.t - | Imprecise of Int.t * Int.t - - let empty_interval_or_set = Set (Ival.O.empty) - - exception Unbounded - - let reduce_ival_by_bound ival size validity = - let pred_size = Int.pred size in - match validity with - | Base.All -> begin (* no clipping can be performed *) - match ival with - | Ival.Top (Some mn,Some mx,_r,m) -> - let result = - if Int.lt m size - then Imprecise(mn, Int.add mx pred_size) - else Interval(mn, mx, m) - in - true, (false, result) - | Ival.Top (None,_,_,_) - | Ival.Top (_,None,_,_) - | Ival.Float _ -> - raise Unbounded - | Ival.Set o -> true, (false, Set o) - end - | Base.Known (bound_min, bound_max) | Base.Unknown (bound_min, bound_max) - | Base.Periodic (bound_min, bound_max, _) -> - let max_in_bound = Int.sub bound_max pred_size in - let is_in_bound x = match x with - | Ival.Top (mn,mx,r,modu) -> - let out, new_mn = - match mn with - | Some mn when (Int.ge mn bound_min) -> false, mn - | _ -> true, Int.round_up_to_r ~r ~modu ~min:bound_min - in - let out, new_mx = - match mx with - | Some mx when (Int.le mx max_in_bound) -> out, mx - | _ -> true, Int.round_down_to_r ~r ~modu ~max:max_in_bound - in - let itv_or_set = - if Int.le new_mn new_mx - then begin - if Int.lt modu size - then Imprecise(new_mn, Int.add new_mx pred_size) - else Interval(new_mn, new_mx, modu) - end - else empty_interval_or_set - in - out, itv_or_set - | _ -> assert false - in - let out, reduced_bounds as result = - begin match ival with - | Ival.Top (_mn,_mx,_r,_m) -> is_in_bound ival - | Ival.Float _ -> is_in_bound Ival.top - | Ival.Set s -> - let out, set = - Ival.O.fold - (fun offset (out_acc, reduced_acc) -> - let pseudo_interval = - Ival.Top(Some offset, Some offset,Int.zero, Int.one) - in - let out, _reduced = is_in_bound pseudo_interval in - out || out_acc, - if out - then reduced_acc - else Ival.O.add offset reduced_acc) - s - (false, Ival.O.empty) - in - (out, Set set) - end - in - match validity with - | Base.Periodic(_, _, p) -> - assert (Int.is_zero bound_min); - let reduced_bounds = - match reduced_bounds with - | Imprecise (mn, mx) -> - if Int.equal (Int.pos_div mn p) (Int.pos_div mx p) - then Imprecise (Int.pos_rem mn p, Int.pos_rem mx p) - else Imprecise (bound_min, Int.pred p) - | Set s -> - let treat_offset offset acc = - let new_offset = Int.pos_rem offset p in - if Int.gt (Int.add new_offset size) p - then raise Unbounded - else -(* Format.printf "old offset: %a mx: %a period: %a new: %a@." - Int.pretty offset - Int.pretty bound_max - Int.pretty p - Int.pretty new_offset; *) - Ival.O.add new_offset acc - in - begin - try - Set (Ival.O.fold treat_offset s Ival.O.empty) - with Unbounded -> Imprecise (bound_min, Int.pred p) - end - | Interval(lb, _ub, mo) -> - if Int.is_zero (Int.pos_rem mo p) - then Set (Ival.O.singleton (Int.pos_rem lb p)) - else begin - Format.printf "Interval %a %a %a@." - Int.pretty lb - Int.pretty _ub - Int.pretty mo; - Imprecise (bound_min, Int.pred p) - end - in - false, (out, reduced_bounds) - | _ -> true, result - - let filter_by_bound_for_reading ~with_alarms ival size validity = - let _, (out, filtered_by_bound) = reduce_ival_by_bound ival size validity in - if out then warn_mem_read with_alarms; - filtered_by_bound - - let filter_by_bound_for_writing ~exact ~with_alarms ival size validity = - let still_exact, (out, filtered_by_bound) = - reduce_ival_by_bound ival size validity - in - if out then warn_mem_write with_alarms; - (exact && still_exact), filtered_by_bound - let create_initial ~v ~modu = let vv = if V.is_isotropic v then Int.zero,Int.one,v else Int.zero,modu,v @@ -1374,120 +1225,143 @@ let find_ival ~conflate_bottom ~validity ~with_alarms offsets offsetmap size = (*Format.eprintf "find_ival: %a in %a@." Ival.pretty offsets pretty offsetmap;*) + let r = try let filtered_by_bound = - filter_by_bound_for_reading ~with_alarms offsets size validity + Tr_offset.filter_by_bound_for_reading ~with_alarms offsets size validity in let inform = ref false in let value = ref V.bottom in let pred_size = Int.pred size in let find_and_accumulate offset period_read_ahead = let itv = offset, Int.add offset pred_size in - let new_inform, read_ahead, new_value = - find ~conflate_bottom itv offsetmap period_read_ahead - in - let new_value = V.join new_value !value in - value := new_value; - inform := !inform || new_inform; - if V.equal new_value V.top - then Some Int.billion_one - else read_ahead + let new_inform, read_ahead, new_value = + find ~conflate_bottom itv offsetmap period_read_ahead + in + let new_value = V.join new_value !value in + value := new_value; + inform := !inform || new_inform; + if V.equal new_value V.top + then Some (Bit_utils.max_bit_size()) + else read_ahead in begin match filtered_by_bound with - | Imprecise (mn, mx) -> - value := find_imprecise mn mx offsetmap - | Interval (mn, mx, m) -> - assert(Int.gt m pred_size); - let current = ref mn in - let r = Int.pos_rem mn m in - while Int.le !current mx do - let read_ahead = find_and_accumulate !current m in - let next = Int.add !current m in - let cursor = - match read_ahead with - None -> next - | Some e -> - let max = Int.sub e pred_size in - let aligned_b = Int.round_down_to_r ~max ~r ~modu:m in - if Int.ge aligned_b next - then aligned_b - else next - in - current := cursor - done; - | Set s -> + | Tr_offset.Imprecise (mn, mx) -> + value := find_imprecise mn mx offsetmap + | Tr_offset.Interval (mn, mx, m) -> + assert(Int.gt m pred_size); + let current = ref mn in + let r = Int.pos_rem mn m in + while Int.le !current mx do + let read_ahead = find_and_accumulate !current m in + let next = Int.add !current m in + let cursor = + match read_ahead with + None -> next + | Some e -> + let max = Int.sub e pred_size in + let aligned_b = Int.round_down_to_r ~max ~r ~modu:m in + if Int.ge aligned_b next + then aligned_b + else next + in + current := cursor + done; + | Tr_offset.Set s -> (*Format.eprintf "find_ival(Set) %a@." Ival.pretty (Ival.Set s);*) - Ival.O.iter (fun x -> ignore (find_and_accumulate x Int.zero)) s; + Ival.O.iter (fun x -> ignore (find_and_accumulate x Int.zero)) s; + end; + if !inform then begin + match with_alarms.imprecision_tracing with + | Aignore -> () + | Acall f -> f () + | Alog _ -> + Kernel.warning ~current:true ~once:true + "extracting bits of a pointer"; end; - if !inform - then begin - match with_alarms.imprecision_tracing with - | Aignore -> () - | Acall f -> f () - | Alog -> CilE.warn_once "extracting bits of a pointer"; - end; !value - with Unbounded -> V.top -(* + with Tr_offset.Unbounded -> V.top + in + if M.is_empty offsetmap && not (V.equal V.top r) then + Kernel.debug ~once:true "%a+%a, size %a, %s, validity %a, result %a" + (M.pretty Int_Int_V.pretty) offsetmap Ival.pretty offsets Int.pretty size (if conflate_bottom then "conflate" else "") Base.pretty_validity validity V.pretty r; + r + let find_ival ~conflate_bottom ~validity ~with_alarms offsets offsetmap size = let result_old = find_ival ~conflate_bottom ~validity ~with_alarms offsets offsetmap size in - try - let _, new_omap = translate_from_old offsetmap in - let new_result = New.find_ival ~validity ~with_alarms offsets new_omap size in - if not (V.equal result_old new_result) then - Format.printf "FIND_IVAL: XXXXXXXX@\n ival:%a size:%a@\n Old: %a@\nNew: %a@\n %a@. " - Ival.pretty offsets Int.pretty size - V.pretty result_old V.pretty new_result - New.pretty new_omap; - result_old - with - | Not_translatable -> -(* Format.printf "NOT TRANSLATED %a@." - pretty offsetmap; -*) result_old - | Not_found -> result_old - | New.End_reached -> result_old + if (not (Kernel.PreciseUnions.get())) || V.cardinal_zero_or_one result_old + then result_old + else + try +(* + Format.printf "DO:@\nconflate_bottom:%B ival:%a size:%a@\n Old: %a@. " + conflate_bottom + Ival.pretty offsets Int.pretty size + V.pretty result_old; *) + let new_omap = translate_from_old offsetmap in + let new_result = New.find_ival ~conflate_bottom ~validity ~with_alarms offsets new_omap size in + if not (V.is_included new_result result_old) + then begin + Format.printf "Please report@\nFIND_IVAL:@\nconflate_bottom:%B ival:%a size:%a@\nOld: %a@\nNew: %a@\n %a@." + conflate_bottom + Ival.pretty offsets Int.pretty size + V.pretty result_old V.pretty new_result + New.pretty new_omap; + assert false + end; + new_result + with + | Not_translatable -> + if not (is_empty offsetmap) + then + Format.printf "NOT TRANSLATED %a@." + pretty offsetmap; + result_old + | Not_found -> + Format.printf "GOT Not_found %a@." + pretty offsetmap; + result_old let update_ival ~with_alarms ~validity ~exact ~offsets ~size offsetmap_orig v = (* Format.printf "update_ival got: %a %a %a@\n" - Ival.pretty offsets - Int.pretty size - pretty offsetmap_orig; *) + Ival.pretty offsets + Int.pretty size + pretty offsetmap_orig; *) try let exact, reduced = - filter_by_bound_for_writing ~with_alarms ~exact offsets size validity + Tr_offset.filter_by_bound_for_writing ~with_alarms ~exact offsets size validity in let fold_set s = - Ival.O.fold - (fun offset acc -> - let itv = offset, Int.pred(Int.add offset size) in + Ival.O.fold + (fun offset acc -> + let itv = offset, Int.pred(Int.add offset size) in let new_offsetmap = (if exact - then add itv v acc - else add_approximate offset size v acc) + then add itv v acc + else add_approximate offset size v acc) in new_offsetmap) - s - offsetmap_orig + s + offsetmap_orig in match reduced with - | Imprecise (mn, mx) -> - let v = V.topify_misaligned_read_origin v in - add_imprecise mn mx v offsetmap_orig - | Interval(mn, mx, m) -> + | Tr_offset.Imprecise (mn, mx) -> + let v = V.topify_misaligned_read_origin v in + add_imprecise mn mx v offsetmap_orig + | Tr_offset.Interval(mn, mx, m) -> begin let res = - add_top_binding_offsetmap - mn mx (Int.pos_rem mn m) m - size v offsetmap_orig in -(* try - let o1, t1 = translate_from_old res in - assert (Int.is_zero o1); - let new_off, new_omap = translate_from_old offsetmap_orig in + add_top_binding_offsetmap + mn mx (Int.pos_rem mn m) m + size v offsetmap_orig in +(* + try + let t1 = translate_from_old res in + let new_omap = translate_from_old offsetmap_orig in if New.is_empty new_omap then raise Not_translatable; let min, max = match validity with @@ -1506,21 +1380,20 @@ and mx = Int.to_int64 mx and period = Int.to_int64 m and size = Int.to_int64 size - and off = Int.to_int64 new_off - and o1 = Int.to_int64 o1 in - let o2, t2 = - New.update_ival min max exact mn mx period size off new_omap v + let t2 = + New.update_ival min max exact mn mx period size new_omap v in - if not (New_offsetmap.Int.equal o2 o1 && New.equal t1 t2) then + if not (New.is_included t2 t1) then ( Format.fprintf Format.std_formatter "arg:%a@.ival:%a v:%a@." pretty offsetmap_orig Ival.pretty offsets V.pretty v ; - Format.fprintf Format.std_formatter "Old:%a@." (New.pretty_offset o1) t1; - Format.fprintf Format.std_formatter "New:%a@." (New.pretty_offset o2) t2; + Format.fprintf Format.std_formatter "Old:%a@." New.pretty t1; + Format.fprintf Format.std_formatter "New:%a@." New.pretty t2; + assert false ); res with @@ -1528,21 +1401,23 @@ res end - | Set o when not (Ival.O.is_empty o) -> fold_set o - | Set _ -> - if exact - then raise Result_is_bottom - else offsetmap_orig + | Tr_offset.Set o when not (Ival.O.is_empty o) -> fold_set o + | Tr_offset.Set _ -> + if exact + then raise Result_is_bottom + else offsetmap_orig with - Unbounded -> - (match with_alarms.imprecision_tracing with + Tr_offset.Unbounded -> + (match with_alarms.imprecision_tracing with | Aignore -> () | Acall f -> f () - | Alog -> warn_once "Writing at unbounded offset: approximating"); - overwrite - offsetmap_orig - v - (Origin.Arith (LocationSetLattice.currentloc_singleton())) + | Alog _ -> + Kernel.warning ~once:true ~current:true + "Writing at unbounded offset: approximating"); + overwrite + offsetmap_orig + v + (Origin.Arith (LocationSetLattice.currentloc_singleton())) (* returns the list of the values associated to at least one bit of the ival. For this function Top is not a binding ! *) @@ -1564,14 +1439,15 @@ offsetmap in List.fold_left - (fun acc (_,(_,_,v)) -> v::acc) - acc - concerned_itv + (fun acc (_,(_,_,v)) -> v::acc) + acc + concerned_itv end | Ival.Set s -> - Ival.O.fold - (fun offset acc -> - let itv = offset, Int.pred(Int.add offset size) in + let s = Ival.set_of_array s in + Ival.O.fold + (fun offset acc -> + let itv = offset, Int.pred(Int.add offset size) in let concerned_itv = M.concerned_intervals Int_Interv.fuzzy_order itv offsetmap in @@ -1636,12 +1512,12 @@ add_internal dest_i new_vv acc in let read_ahead = - match concerned_itv with - [(bc,ec), (_rc,mc,_vc)] when Int.le bc start && Int.gt ec stop && - Int.is_zero (Int.pos_rem period_read_ahead mc) - -> - Some ec - | _ -> None + match concerned_itv with + [(bc,ec), (_rc,mc,_vc)] when Int.le bc start && Int.gt ec stop && + Int.is_zero (Int.pos_rem period_read_ahead mc) + -> + Some ec + | _ -> None in read_ahead, List.fold_left treat_interval empty concerned_itv @@ -1651,53 +1527,53 @@ offsetmap;*) try let filtered_by_bound = - filter_by_bound_for_reading ~with_alarms offsets size validity + Tr_offset.filter_by_bound_for_reading ~with_alarms offsets size validity in let pred_size = Int.pred size in let i0 = Int.zero, pred_size in let value = ref (M.add i0 (Int.zero, Int.one, V.bottom) empty) in let find_and_accumulate offset period_read_ahead = let end_ = Int.add offset pred_size in - let read_ahead, new_value = - copy_offsmap offsetmap offset end_ period_read_ahead - in - let _, new_value = join new_value !value in - value := new_value; - read_ahead + let read_ahead, new_value = + copy_offsmap offsetmap offset end_ period_read_ahead + in + let _, new_value = join new_value !value in + value := new_value; + read_ahead in begin match filtered_by_bound with - | Imprecise(mn ,mx) -> - let v = find_imprecise mn mx offsetmap in - value := - add_if_not_default - i0 - (Int.zero, Int.one, v) - empty - | Interval(mn, mx, m) -> - assert (Int.gt m pred_size); - let current = ref mn in - let r = Int.pos_rem mn m in - while Int.le !current mx do - let read_ahead = find_and_accumulate !current m in - let next = Int.add !current m in - let cursor = - match read_ahead with - None -> next - | Some e -> - let max = Int.sub e pred_size in - let aligned_b = Int.round_down_to_r ~max ~r ~modu:m in - if Int.ge aligned_b next - then aligned_b - else next - in - current := cursor - done; - | Set s -> + | Tr_offset.Imprecise(mn ,mx) -> + let v = find_imprecise mn mx offsetmap in + value := + add_if_not_default + i0 + (Int.zero, Int.one, v) + empty + | Tr_offset.Interval(mn, mx, m) -> + assert (Int.gt m pred_size); + let current = ref mn in + let r = Int.pos_rem mn m in + while Int.le !current mx do + let read_ahead = find_and_accumulate !current m in + let next = Int.add !current m in + let cursor = + match read_ahead with + None -> next + | Some e -> + let max = Int.sub e pred_size in + let aligned_b = Int.round_down_to_r ~max ~r ~modu:m in + if Int.ge aligned_b next + then aligned_b + else next + in + current := cursor + done; + | Tr_offset.Set s -> (*Format.eprintf "find_ival(Set) %a@." Ival.pretty (Ival.Set s);*) - Ival.O.iter (fun x -> ignore (find_and_accumulate x Int.zero)) s; + Ival.O.iter (fun x -> ignore (find_and_accumulate x Int.zero)) s; end; !value - with Unbounded -> empty + with Tr_offset.Unbounded -> empty let copy_offsmap from start stop = snd (copy_offsmap from start stop Int.zero) @@ -1715,7 +1591,7 @@ let fold_whole ~size f m acc = let result = M.fold - (fun (be,en) (offs1, modu1, v1) acc -> + (fun (be,en) (offs1, modu1, v1) acc -> if (V.is_isotropic v1 ==> not (Int.is_zero (Int.pos_rem (Int.succ (Int.sub en be)) size))) @@ -1748,9 +1624,9 @@ let fold_single_bindings ~size f m acc = let f_adj ival size v acc = Ival.fold_enum ~split_non_enumerable:(-1) - (fun i acc -> f i size v acc) - ival - acc + (fun i acc -> f i size v acc) + ival + acc in fold_whole ~size f_adj m acc @@ -1759,6 +1635,7 @@ (* Approximating because we do no want to shift with too many values *) | Ival.Set s -> + let s = Ival.set_of_array s in Ival.O.fold (fun v acc -> let shifted = shift v m in @@ -1779,13 +1656,13 @@ try M.fold (fun itv vv acc -> - let itv_iset = Int_Intervals.inject [itv] in - let inter = Int_Intervals.meet itv_iset iset in - Int_Intervals.fold - (fun itv acc -> - M.add itv vv acc) - inter - acc) + let itv_iset = Int_Intervals.inject [itv] in + let inter = Int_Intervals.meet itv_iset iset in + Int_Intervals.fold + (fun itv acc -> + M.add itv vv acc) + inter + acc) offsetmap empty with Int_Intervals.Error_Top (* from Int_Intervals.fold *) -> @@ -1802,6 +1679,17 @@ let fold f m = M.fold f m + exception Other + + let is m v = + let f _k (_,_,v1) acc = + if acc || not (V.equal v v1) then raise Other; + true + in + try + M.fold f m false + with Other -> false + end module Make(V:Lattice_With_Isotropy.S) = struct @@ -1820,7 +1708,7 @@ let empty = { v = M.empty; tag = 0 } - let pretty_c_assert_typ _ = assert false + let pretty_c_assert_typ s t f fmt v = M.pretty_c_assert_typ s t f fmt v.v let pretty_typ t fmt v = M.pretty_typ t fmt v.v let pretty fmt v = M.pretty fmt v.v @@ -1832,7 +1720,7 @@ type t = tt let name = name let structural_descr = - Structural_descr.t_record [| M.packed_descr; Structural_descr.p_int |] + Structural_descr.t_record [| M.packed_descr; Structural_descr.p_int |] let reprs = List.map (fun m -> { v = m; tag = -1 }) M.M.reprs let equal = ( == ) let compare = compare @@ -1849,10 +1737,10 @@ module OffsetmapHashconsTbl = State_builder.Hashconsing_tbl (struct - include D - let equal_internal = equal_internal - let hash_internal = hash_internal - let initial_values = [ empty ] + include D + let equal_internal = equal_internal + let hash_internal = hash_internal + let initial_values = [ empty ] end) (struct let name = name @@ -1892,15 +1780,6 @@ let () = Project.register_todo_before_clear (fun _ -> SymetricCache.clear ()) let join m1 m2 = - if !Hptmap.debug - then Format.printf "Offsetmap join %a@@%d %a@@%d@." - pretty m1 (Extlib.address_of_value m1) - pretty m2 (Extlib.address_of_value m2); - if !Hptmap.debug - then Format.printf "Cached Offsetmap.join %d@@%d %d@@%d@." - (tag m1) (Extlib.address_of_value m1) - (tag m2) (Extlib.address_of_value m2) - ; if m1 == m2 then [],m1 else let compute x y = @@ -1914,24 +1793,24 @@ let pretty_compare fmt v = M.pretty_compare fmt v.v module Cacheable = - struct - type t = tt - let hash = tag - let equal = (==) - let sentinel = empty - end + struct + type t = tt + let hash = tag + let equal = (==) + let sentinel = empty + end module Cache = Binary_cache.Make_Binary(Cacheable)(Cacheable) let () = Project.register_todo_before_clear (fun _ -> Cache.clear ()) + let compute_is_included m1 m2 = + M.is_included m1.v m2.v + let is_included m1 m2 = if m1 == m2 then true else - let m1v = m1.v in - let m2v = m2.v in - let compute () = M.is_included m1v m2v in - Cache.merge compute m1 m2 + Cache.merge compute_is_included m1 m2 let is_included_exn m1 m2 = if not (is_included m1 m2) then raise Is_not_included @@ -1943,16 +1822,13 @@ let find i v = M.find i v.v - let cardinal_zero_or_one v o = + let cardinal_zero_or_one v o = M.cardinal_zero_or_one v o.v (* TODO: cache *) let find_imprecise_entire_offsetmap ~validity offsetmap = M.find_imprecise_entire_offsetmap ~validity offsetmap.v - let is_included_actual_generic a b c v1 v2 = - M.is_included_actual_generic a b c v1.v v2.v - let widen w v1 v2 = wrap (M.widen w v1.v v2.v) let find_ival ~conflate_bottom ~validity ~with_alarms a v @@ -1970,8 +1846,8 @@ let over_intersection v1 v2 = wrap (M.over_intersection v1.v v2.v) - let from_string s = - wrap (M.from_string s) + let from_cstring s = + wrap (M.from_cstring s) let add_whole itv y t = wrap (M.add_whole itv y t.v) @@ -2032,14 +1908,18 @@ let reduce_by_int_intervals v a = wrap (M.reduce_by_int_intervals v.v a) - let top_stuff condition topify om = - wrap (M.top_stuff condition topify om.v) + let top_stuff condition topify join_locals acc_locals om = + let locals, r = + M.top_stuff condition topify join_locals acc_locals om.v + in + locals, wrap r let iter_contents f o size = M.iter_contents f o.v size let fold f v = M.fold f v.v + let is m v = M.is m.v v end (* diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/offsetmap.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/offsetmap.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + open Abstract_interp open Abstract_value @@ -41,7 +46,7 @@ val empty : t val is_empty : t -> bool - val pretty_c_assert_typ : + val pretty_c_assert_typ : string -> Cil_types.typ -> (unit->unit) -> Format.formatter -> t -> unit val pretty_typ : Cil_types.typ option -> Format.formatter -> t -> unit val pretty_debug : Format.formatter -> t -> unit @@ -55,14 +60,6 @@ val is_included_exn : t -> t -> unit val is_included_exn_generic : (y -> y -> unit) -> t -> t -> unit - val is_included_actual_generic : - Base.Set.t -> - Base.Set.t ref -> - Locations.Location_Bytes.t Base.Map.t ref -> - t -> - t -> - unit - val join : t -> t -> (Int.t * Int.t) list * t val widen : widen_hint -> t -> t -> t @@ -78,7 +75,7 @@ val concerned_bindings_ival : offsets:Ival.t -> offsetmap:t -> size:Int.t -> y list -> y list (** accumulates the list of the values associated to at - least one bit of the ival. For this function Top is not a binding! *) + least one bit of the ival. For this function Top is not a binding! *) val update_ival : with_alarms:CilE.warn_mode -> @@ -91,15 +88,15 @@ val overwrite : t -> y -> Origin.t -> t (** [overwrite m v o] computes the offsetmap resulting from writing - [v] potentially anywhere in [m] *) + [v] potentially anywhere in [m] *) val over_intersection : t -> t -> t (** An over-approximation of the intersection. The arguments can not be - arbitrary offsetmaps: the algorithm would be too complicated. The - provided algorithm should work fine with offsetmaps that correspond to - the relation view and the memory view of the same analysed code. *) + arbitrary offsetmaps: the algorithm would be too complicated. The + provided algorithm should work fine with offsetmaps that correspond to + the relation view and the memory view of the same analysed code. *) - val from_string : string -> t + val from_cstring : Base.cstring -> t val add_internal : itv -> Int.t * Int.t * y -> t -> t val add_whole : itv -> y -> t -> t val remove_whole : itv -> t -> t @@ -117,8 +114,8 @@ val shift_ival : Ival.t -> t -> t option -> t option (** [shift_ival shift o acc] returns the join of [acc] and - of [o] shifted by all values in [shift]. - Raises [Found_Top] when the result is [Top]. *) + of [o] shifted by all values in [shift]. + Raises [Found_Top] when the result is [Top]. *) val copy_paste : t -> Int.t -> Int.t -> Int.t -> t -> t val copy_merge : t -> Int.t -> Int.t -> Int.t -> t -> t @@ -134,20 +131,22 @@ val reciprocal_image : t -> Base.t -> Int_Intervals.t * Ival.t (** [reciprocal_image m b] is the set of bits in the offsetmap [m] - that may lead to Top([b]) and the set of offsets in [m] - where one can read an address [b]+_ *) + that may lead to Top([b]) and the set of offsets in [m] + where one can read an address [b]+_ *) val create_initial: v:y -> modu:Int.t -> t val reduce_by_int_intervals: t -> Abstract_value.Int_Intervals.t -> t - val top_stuff : (y -> bool) -> (y -> y) -> t -> t + val top_stuff : + (y -> bool) -> (y -> 'a * y) -> ('a -> 'a -> 'a) -> 'a -> t -> 'a * t val iter_contents : (y -> unit) -> t -> Int.t -> unit (** Iter on the contents of offsetmap of given size *) val fold : (Int.t * Int.t -> Int.t * Int.t * y -> 'a -> 'a) -> t -> 'a -> 'a + val is : t -> y -> bool end module Make(V : Lattice_With_Isotropy.S): diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/path_lattice.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/path_lattice.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/path_lattice.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/path_lattice.ml 2011-10-10 08:38:30.000000000 +0000 @@ -63,8 +63,8 @@ fprintf fmt "*%a" pretty_precise p | Union (sl,p) -> fprintf fmt "%a | *(%a)" - Shifted_Location.pretty sl - pretty_precise p + Shifted_Location.pretty sl + pretty_precise p let pretty fmt p = match p with @@ -78,11 +78,12 @@ let rec topify v = match v with - | Location (ls) -> (valid_enumerate_bits ls.Shifted_Location.l) + | Location (ls) -> + valid_enumerate_bits ~for_writing:false ls.Shifted_Location.l | Union(ls,p) -> Zone.join - (valid_enumerate_bits ls.Shifted_Location.l) - (topify p) + (valid_enumerate_bits ~for_writing:false ls.Shifted_Location.l) + (topify p) exception Shifted_locations_unjoinable @@ -104,40 +105,42 @@ match t1,t2 with | Location (sl1), Location (sl2) -> begin try - Precise (Location (try_join_shifted_loc sl1 sl2)) - with Shifted_locations_unjoinable -> - Top (Zone.join - (valid_enumerate_bits sl1.Shifted_Location.l) - (valid_enumerate_bits sl2.Shifted_Location.l)) + Precise (Location (try_join_shifted_loc sl1 sl2)) + with Shifted_locations_unjoinable -> + Top + (Zone.join + (valid_enumerate_bits ~for_writing:false sl1.Shifted_Location.l) + (valid_enumerate_bits ~for_writing:false sl2.Shifted_Location.l)) end | Location sl, (Union (sl1,t2) as u) | (Union (sl1,t2) as u), Location sl -> begin try - Precise (Union (try_join_shifted_loc sl sl1, t2)) - with Shifted_locations_unjoinable -> - Top (Zone.join - (valid_enumerate_bits (sl.Shifted_Location.l)) - (topify u)) + Precise (Union (try_join_shifted_loc sl sl1, t2)) + with Shifted_locations_unjoinable -> + Top + (Zone.join + (valid_enumerate_bits ~for_writing:false (sl.Shifted_Location.l)) + (topify u)) end | Union ({Shifted_Location.l = l1} as u1, p1), Union ({Shifted_Location.l = l2} as u2, p2) -> begin match join_precise p1 p2 with | Top t -> - Top - (Zone.join t - (Zone.join - (valid_enumerate_bits l1) - (valid_enumerate_bits l2))) + Top + (Zone.join t + (Zone.join + (valid_enumerate_bits ~for_writing:false l1) + (valid_enumerate_bits ~for_writing:false l2))) | Precise p -> - begin try - Precise (Union (try_join_shifted_loc u1 u2, p)) - with Shifted_locations_unjoinable -> - Top - (Zone.join (topify p) - (Zone.join - (valid_enumerate_bits l1) - (valid_enumerate_bits l2))) - end + begin try + Precise (Union (try_join_shifted_loc u1 u2, p)) + with Shifted_locations_unjoinable -> + Top + (Zone.join (topify p) + (Zone.join + (valid_enumerate_bits ~for_writing:false l1) + (valid_enumerate_bits ~for_writing:false l2))) + end end let join t1 t2 = @@ -152,7 +155,7 @@ Shifted_Location.is_included s1 s2 | Union (s1, t1), Union (s2, t2) -> Shifted_Location.is_included s1 s2 && - is_included_precise t1 t2 + is_included_precise t1 t2 | Union (_, t), Location _ -> assert (not (is_bottom_precise t)); false @@ -168,6 +171,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/path_lattice.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/path_lattice.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/path_lattice.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/path_lattice.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,22 +20,24 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + type precise_path = private | Location of Shifted_Location.t | Union of Shifted_Location.t * precise_path - + type path = private Top of Locations.Zone.t | Precise of precise_path - (* include Abstract_interp.Lattice with type t = path *) - - (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/relations_type.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/relations_type.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/relations_type.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/relations_type.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,1673 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Locations -open Abstract_interp -open Abstract_value -open Cvalue_type - -(* To be raised whenever we need to fall back to values computations *) -exception Use_Main_Memory - -module V_Offsetmap_For_Relations = Offsetmap.Make(V) - -module Partial_lmap = Lmap_whole.Make_LOffset(V)(V_Offsetmap_For_Relations) - -module Relation_between = - Partial_lmap.Make - (struct let default_offsetmap _ = V_Offsetmap_For_Relations.empty end) - -module Cluster = struct - - type tt = - { id : int; (* unique identifier *) - size : Int.t; (* size of the values that are in the relation *) - contents : V_Offsetmap.t; - (* optional offsetmap. Only makes sense if - size = sizeofpointer(), and (with some exceptions), - when the values in rel are not integers *) - rel : Relation_between.t; - (* maps the values in the relation to an offset indicating - their position wrt each other *) - virtual_to_real : Location_Bits.t } - - let compare x y = Datatype.Int.compare x.id y.id - let equal x y = x.id = y.id - let hash t = t.id - - let rel_at_least_2 ~rel ~size = - try - let counter = Relation_between.fold - ~size - (fun k v counter -> - assert (if V.cardinal_zero_or_one v then - true - else - (Format.printf "k:%a@.v:%a@." - Locations.pretty k - V.pretty v; - false) - ); - let card = Location_Bits.cardinal_less_than k.loc 2 in - card + counter) - rel - 0 - in - counter >= 2 - with - | Invalid_argument "Lmap.fold" -> assert false - | Not_less_than -> true - - let has_information cluster = - (not (Relation_between.is_empty cluster.rel)) && - ( rel_at_least_2 ~size:cluster.size ~rel:cluster.rel || - not (V_Offsetmap.is_empty cluster.contents)) - - let pretty fmt c = - Format.fprintf fmt "[[%d: rel=%a virtual_to_real:%a contents=%a]]" c.id - Relation_between.pretty c.rel - Location_Bits.pretty c.virtual_to_real - V_Offsetmap.pretty c.contents - - let cluster_counter = ref 0 - - let make ~size ~contents ~rel ~virtual_to_real = - assert (not (Location_Bits.cardinal_zero_or_one virtual_to_real)); - let new_count = succ !cluster_counter in - if new_count = 0 - then begin - Format.printf "Internal limit reached. Please report@."; - exit 1; - end; - cluster_counter := new_count; - let c = - { id = new_count; - size = size; - contents = contents; - rel = rel; - virtual_to_real = virtual_to_real } - in - assert (if not (has_information c) - then begin - Cil.warning "Internal error while creating cluster %a@." - pretty c; - false - end - else true); - c - - exception Stop - exception No_more_cluster - - let filter_base f c = - let keep_content = - try - Location_Bits.fold_i - (fun k _v _acc -> if not (f k) then raise Stop) - c.virtual_to_real - (); - true - with Stop | Location_Bits.Error_Top -> false - in - let new_rel = Relation_between.filter_base f c.rel in - let new_contents = - if keep_content then - c.contents - else - V_Offsetmap.empty - in - if not (has_information { c with rel = new_rel ; contents = new_contents }) - then raise No_more_cluster - else make - ~size:c.size - ~contents:new_contents - ~virtual_to_real:c.virtual_to_real - ~rel:new_rel - - include Datatype.Make_with_collections - (struct - type t = tt - let name = "Relation_types.Cluster" - let structural_descr = - Structural_descr.t_tuple - [| Structural_descr.p_int; - Int.packed_descr; - V_Offsetmap.packed_descr; - Relation_between.packed_descr; - Location_Bits.packed_descr |] - let reprs = - List.fold_left - (fun acc o -> - List.fold_left - (fun acc r -> - List.fold_left - (fun acc l -> - { id = -1; - size = Int.zero; - contents = o; - rel = r; - virtual_to_real = l } - :: acc) - acc - Location_Bits.reprs) - acc - Relation_between.reprs) - [] - V_Offsetmap.reprs - let hash = hash - let compare = compare - let equal = equal - let pretty = pretty - let rehash = Datatype.identity -(* let module H = - Hashtbl.Make(struct - type t = tt - let hash c = c.id - let equal c d = c.id = d.id - end) - in - let rehash_table = H.create 17 in - fun c -> - try - H.find rehash_table c; - c - with Not_found -> - cluster_counter := Extlib.max_cpt c.id !cluster_counter; - H.add rehash_table c (); - c*) - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) - -end - -type cluster_info = No_cluster | Cluster of Cluster.t | Bottom_cluster - -module Cluster_Info = struct - - module Top_Param = VarinfoSetLattice - type widen_hint = unit - - let hash v = - match v with - No_cluster -> 1975 - | Bottom_cluster -> 19751 - | Cluster c -> c.Cluster.id - - let tag = hash - - let compare x y = - match x, y with - No_cluster, No_cluster | Bottom_cluster, Bottom_cluster -> 0 - | No_cluster, _ -> 1 - | _, No_cluster -> -1 - | Bottom_cluster, _ -> 1 - | _, Bottom_cluster -> -1 - | Cluster c1, Cluster c2 -> Datatype.Int.compare c1.Cluster.id c2.Cluster.id - - let equal x y = compare x y = 0 - - let pretty fmt v = match v with - | No_cluster -> Format.fprintf fmt "NoCluster" - | Bottom_cluster -> Format.fprintf fmt "BottomCluster" - | Cluster c -> Cluster.pretty fmt c - - include Datatype.Make - (struct - type t = cluster_info - let name = "Relation_types.Cluster_Info" - let reprs = - No_cluster - :: Bottom_cluster - :: List.map (fun c -> Cluster c) Cluster.reprs - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| Cluster.packed_descr |] |]) - let hash = hash - let equal = equal - let compare = compare - let pretty = pretty - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) - - let project _ = assert false - - let join x y = - match x, y with - Bottom_cluster, Bottom_cluster -> Bottom_cluster - | Bottom_cluster, x | x, Bottom_cluster -> x - | Cluster xx, Cluster yy when xx.Cluster.id = yy.Cluster.id -> x - | _ -> No_cluster - let meet _ _ = Bottom_cluster - - let default _base _b _e = No_cluster - let defaultall _base = No_cluster - - let cardinal_less_than _ = assert false - let cardinal_zero_or_one = function - Cluster _ -> true - | Bottom_cluster -> assert false - | No_cluster -> false - - let link _ = assert false (* Not implemented yet. *) - let narrow _ = assert false (* Not implemented yet. *) - let widen _ = assert false (* Not implemented yet. *) - - let little_endian_merge_bits ~conflate_bottom:_ ~total_length:_ ~value:_ ~offset:_ _ = No_cluster - let big_endian_merge_bits ~conflate_bottom:_ ~total_length:_ ~length:_ ~value:_ ~offset:_ _ = No_cluster - - let intersects _ = assert false - let is_included _ = assert false - let is_included_exn _ = assert false - let is_included_actual_generic _ = assert false - let top = No_cluster - let inject_top_origin _ = assert false - let top_absolute_origin () = top - let top_int = top - let of_char _ = top - - let bottom = Bottom_cluster - - exception Error_Bottom - exception Error_Top - - let all_values ~size:_ _ = assert false - - let anisotropic_cast ~size:_ s = - (*Format.printf "Size for anisotropic cast:%a@\n" Int.pretty size;*) - s - let topify _ = top - let under_topify _ = assert false - let topify_misaligned_read_origin = topify - let topify_arith_origin = topify - let topify_merge_origin = topify - let topify_with_origin _ = topify - let cast ~with_alarms:_ ~size:_ ~signed:_ _ = assert false - let is_isotropic x = equal x top - - exception Cannot_extract - let extract_bits ~start:_ ~stop:_ _ = - raise Cannot_extract -end - -let same_clusters c cluster = c.Cluster.id = cluster.Cluster.id - -let same_clusterinfo_cluster cinfo cluster = - match cinfo with - | Cluster c when same_clusters c cluster -> true - | _ -> false - -(* -module type Participation_Map_S = sig - include Lmap.Location_map with type y = cluster_info - val add_binding : t -> Locations.location -> y -> t - val find : t -> Locations.location -> y -end -*) -(* Each location in the map is associated to a single cluster. - A binding must be present for every location that belongs to rel field of - one of the clusters in the map. *) -module Participation_Map = struct - - module Cluster_Info_plus = - struct - include Cluster_Info - let singleton_zero = top - let pretty fmt c = match c with - | Cluster c -> Format.fprintf fmt "C:%d" c.Cluster.id - | No_cluster -> Format.fprintf fmt "C:no" - | Bottom_cluster -> Format.fprintf fmt "C:bottom" - let pretty_c_assert _lv _s _fmt _v = assert false - end - - module Cluster_Info_Offsetmap = Offsetmap.Make(Cluster_Info_plus) - - module Partial_Participation_Map = - Lmap_whole.Make_LOffset(Cluster_Info_plus)(Cluster_Info_Offsetmap) - - open Partial_Participation_Map - - include - Make(struct let default_offsetmap _ = Cluster_Info_Offsetmap.empty end) - - let add_binding s x = - assert (Location_Bits.is_relationable x.loc); - add_binding s ~exact:true x - - - let add_whole loc v m = - assert (Location_Bits.is_relationable loc.loc); - add_whole loc v m - - let find m l = - try - find ~with_alarms:CilE.warn_none_mode m l - with Cluster_Info.Cannot_extract -> No_cluster - -end - -type tt = - { participation_map : Participation_Map.t; - all_clusters : Cluster.Set.t } - -let pretty_tt fmt v = - Format.fprintf fmt - "PartMap:%a@\nClusters=%a@\n" - Participation_Map.pretty v.participation_map - (fun fmt () -> - Cluster.Set.iter - (fun c -> Format.fprintf fmt "Cluster:%a@\n" Cluster.pretty c) - v.all_clusters) - () - -let empty_tt = - { participation_map = Participation_Map.empty; - all_clusters = Cluster.Set.empty} - -let index_cluster_into_participation_map cluster pmap = - let copy_loc loc _ acc = -(* Format.printf "copy_loc size:%a@\n" Int_Base.pretty lc.Cluster.size;*) - Participation_Map.add_whole loc (Cluster cluster) acc - in - Relation_between.fold_single_bindings - ~size:cluster.Cluster.size - copy_loc - cluster.Cluster.rel - pmap - -let remove_cluster_from_participation_map cluster pmap = - let copy_loc loc _ acc = - Participation_Map.remove_whole loc acc - in - Relation_between.fold_single_bindings - ~size:cluster.Cluster.size - copy_loc - cluster.Cluster.rel - pmap - -let check_tt map = - Cluster.Set.fold - (fun c () -> - Relation_between.fold - ~size:c.Cluster.size - (fun loc _ () -> - match Participation_Map.find map.participation_map loc with - Cluster other_c when Cluster.equal c other_c -> - () - | _ -> - Format.printf "Relation_type.check_tt %a@." - pretty_tt map; - assert false) - c.Cluster.rel - ()) - map.all_clusters - () - - -let add_new_cluster new_cluster map = - let new_participation_map = - index_cluster_into_participation_map - new_cluster - map.participation_map - in - let new_all_clusters = Cluster.Set.add new_cluster map.all_clusters in - let result = - { participation_map = new_participation_map; - all_clusters = new_all_clusters; } - in - assert (check_tt result; true); - result - - - - - -(* precondition : the locations involved in new_cluster must include - all the locations involved in old_cluster *) -let replace_cluster ~old_cluster ~new_cluster map = - let new_participation_map = - index_cluster_into_participation_map - new_cluster - map.participation_map - in - let new_all_clusters = - Cluster.Set.add - new_cluster - (Cluster.Set.remove old_cluster map.all_clusters) - in - let result = - { participation_map = new_participation_map; - all_clusters = new_all_clusters; } - in - assert (check_tt result; true); - result - -let remove_cluster ~old_cluster map = - let new_participation_map = - remove_cluster_from_participation_map - old_cluster - map.participation_map - in - let new_all_clusters = Cluster.Set.remove old_cluster map.all_clusters in - let result = - { participation_map = new_participation_map; - all_clusters = new_all_clusters; } - in - assert (check_tt result; true); - result - -(* -let replace_cluster ~old_cluster ~new_cluster map = - add_new_cluster new_cluster (remove_cluster ~old_cluster map) -*) - -let virtual_to_real main_memory loc = - loc_bytes_to_loc_bits - (Model.find ~conflate_bottom:true ~with_alarms:CilE.warn_none_mode - main_memory loc) - -exception Tt_not_included - -let is_included_rel tt1 c2 = - let f loc v2 acc = - match acc with - | None -> - begin - match Participation_Map.find tt1.participation_map loc with - Cluster c1 -> - if Int.compare c2.Cluster.size c1.Cluster.size <> 0 - then raise Tt_not_included; - let v1 = - Relation_between.find ~with_alarms:CilE.warn_none_mode - c1.Cluster.rel loc - in - let diff = V.add_untyped (Int_Base.minus_one) v2 v1 in - let diff_ival = V.project_ival diff in - if not (Ival.cardinal_zero_or_one diff_ival) - then raise Tt_not_included; - Some (c1,diff) - | No_cluster -> raise Tt_not_included - | Bottom_cluster -> assert false - end - | Some(c1,d) -> - let v1 = Relation_between.find ~with_alarms:CilE.warn_none_mode c1.Cluster.rel loc in - let diff = V.add_untyped (Int_Base.minus_one) v2 v1 in - if not (V.equal d diff ) - then raise Tt_not_included; - acc - in - try - match (Relation_between.fold - ~size:c2.Cluster.size - f - c2.Cluster.rel - None) with - | None -> assert false - | Some v -> v - with V.Not_based_on_null -> raise Tt_not_included - -let is_included_offsetmap diff c1 c2 = -(* if not (V.is_zero diff) - then begin - Format.printf "Calling is_included_offsetmap diff:%a c1:%a c2:%a@\n" - V.pretty diff - Cluster.pretty c1 - Cluster.pretty c2; - end; *) - try - let varid, offs = V.find_lonely_key diff in - assert (Base.is_null varid); - let offs = Int.mul (Bit_utils.sizeofchar()) (Ival.project_int offs) in - let shifted_c2 = - V_Offsetmap.shift offs c2.Cluster.contents - in -(* if not (V.is_zero diff) - then - Format.printf "shifted_c2:%a@\n" - (V_Offsetmap_For_Relations.pretty None) shifted_c2; *) - V_Offsetmap.is_included - c1.Cluster.contents - shifted_c2; - with - Not_found | Ival.Not_Singleton_Int -> assert false - -let is_included_tt tt1 tt2 = - (*Format.printf "is_included_tt@ @[%a@]@ @[%a@]===@\n" - pretty_tt tt1 - pretty_tt tt2;*) - let check_cluster c2 = - (*Format.printf "is_included_tt->check_cluster@ @[%a@]@\n" - Cluster.pretty c2;*) - let c1,diff = is_included_rel tt1 c2 in - if not (is_included_offsetmap diff c1 c2) - then raise Tt_not_included - in - try - Cluster.Set.iter check_cluster tt2.all_clusters; - true - with Tt_not_included -> - false - -let find_hint h k = - try Int.Hashtbl.find h k - with Not_found -> [] - -let join (m1 : tt) (m2 : tt) = - let f cluster1 cluster2 acc = - if not (Int.equal cluster1.Cluster.size cluster2.Cluster.size) - then acc - else (* Clusters have the same size for the values *) - (* if cluster1.Cluster.id = cluster2.Cluster.id then ((*variables de cluster2*),cluster2)::acc - else -- optimisation qui nécessite de réfléchir pour être activée *) - let h = Int.Hashtbl.create 7 in - Relation_between.fold_single_bindings - ~size:cluster1.Cluster.size - (fun loc1 v1 _acc -> - let v2 = - Relation_between.find ~with_alarms:CilE.warn_none_mode - cluster2.Cluster.rel - loc1 - in - if Location_Bytes.cardinal_zero_or_one v2 then - let delta = V.add_untyped - Int_Base.minus_one - v1 v2 - in - try - let delta_i = - Ival.project_int - (V.project_ival delta) - in - Int.Hashtbl.replace h delta_i (loc1::(find_hint h delta_i)) - with - | V.Not_based_on_null - | Ival.Not_Singleton_Int -> ()) - cluster1.Cluster.rel - (); - let create_subcluster - offs locs acc = - let offs = Int.mul offs (Bit_utils.sizeofchar()) in - (* if not (Int.is_zero offs) then - Format.printf "shift:%a@\n" Int.pretty offs; *) - let _,new_contents = - V_Offsetmap.join - (V_Offsetmap.shift offs cluster1.Cluster.contents) - cluster2.Cluster.contents - in - match locs with - | [] -> assert false (* Int.Hashtbl.fold should not call this function - on the empty list *) - | [_] when V_Offsetmap.is_empty new_contents -> - (* there is no information in this cluster. *) - acc - | _ -> - let new_rel = - List.fold_left - (fun acc loc -> - Location_Bits.fold_enum - ~split_non_enumerable:(-1) - (fun loc_no_size acc -> - let loc = make_loc loc_no_size loc.size in - let v = Relation_between.find - ~with_alarms:CilE.warn_none_mode - cluster2.Cluster.rel - loc - in - assert (Location_Bits.cardinal_zero_or_one loc.loc); - Relation_between.add_whole loc v acc) - loc.loc - acc) - Relation_between.empty - locs - in - let new_virtual_to_real = - Location_Bits.join - (Location_Bits.location_shift - (Ival.inject_singleton (Int.neg offs)) - cluster1.Cluster.virtual_to_real) - cluster2.Cluster.virtual_to_real - in - let new_cluster = - Cluster.make - ~size:cluster1.Cluster.size - ~contents:new_contents - ~rel:new_rel - ~virtual_to_real:new_virtual_to_real - in - add_new_cluster new_cluster acc - in - Int.Hashtbl.fold create_subcluster h acc - in - let final_state = - Cluster.Set.fold - (fun cluster1 acc -> - Cluster.Set.fold - (fun cluster2 acc -> - f cluster1 cluster2 acc) - m2.all_clusters - acc - ) - m1.all_clusters - empty_tt - in - (* Format.printf "relation join:%a %a -> %a@\n" - pretty_tt m1 - pretty_tt m2 - pretty_tt final_state; *) - final_state - -module type Model_S = sig - include Datatype.S - type widen_hint = Model.widen_hint - type cluster - val is_reachable : t -> bool - val pretty_c_assert : Format.formatter -> t -> unit - val pretty_without_null : Format.formatter -> t -> unit - val pretty_filter : - Format.formatter -> t -> Zone.t -> (Base.t -> bool) -> unit - val join : t -> t -> t - val find : - conflate_bottom:bool -> - with_alarms:CilE.warn_mode -> - t -> - location -> - Location_Bytes.t - val find_unspecified : with_alarms:CilE.warn_mode -> t -> location -> - Cvalue_type.V_Or_Uninitialized.t - - val add_binding : - with_alarms:CilE.warn_mode -> - exact:bool -> - t -> - location -> - Location_Bytes.t -> - t - val add_binding_unspecified : t -> location -> t - - val reduce_binding : t -> location -> Location_Bytes.t -> t - val is_included : t -> t -> bool - val is_included_actual_generic : - Zone.t -> t -> t -> Location_Bytes.t Base.Map.t - val widen : widen_hint -> t -> t -> (bool * t) - val bottom : t - val inject : Model.t -> t - val empty_map : t - val top : t - val is_top: t -> bool - val value_state : t -> Model.t - val drop_relations : t -> t - val filter_base : (Base.t -> bool) -> t -> t - val remove_base : Base.t -> t -> t - val clear_state_from_locals : Cil_types.fundec -> t -> t - val uninitialize_locals: Cil_types.block list -> t -> t - val compute_actual_final_from_generic : - t -> t -> Zone.t -> Model.instanciation -> t * Location_Bits.Top_Param.t - val is_included_by_location_enum : t -> t -> Zone.t -> bool - - val find_mem : location -> Int_Base.t -> - Ival.t -> t -> V.t - val add_mem : location -> Int_Base.t -> - Ival.t -> t -> V.t -> cluster list * t - val propagate_change_from_real_to_virt : - protected_clusters:cluster list -> location -> t -> V.t -> t - - val add_equality : ?offset:Ival.t -> t -> location -> location -> t - val reduce_equality : t -> location -> location -> t - val compute_diff : t -> location -> location -> V.t - val shift_location : t -> location -> Ival.t -> V.t -> t - val find_base : Base.t -> t -> V_Offsetmap.t - val create_initial : base:Base.t -> - v:V.t -> - modu:Int.t -> - state:t -> t - - val paste_offsetmap : - Cvalue_type.V_Offsetmap.t -> Location_Bits.t -> Int.t -> Int.t -> t -> t - val copy_paste : location -> location -> t -> t - val copy_from_virtual : - location -> - Ival.t -> - Int.t -> t -> Cvalue_type.V_Offsetmap.t - val copy_offsetmap : with_alarms:CilE.warn_mode -> - Locations.location -> t -> Cvalue_type.V_Offsetmap.t option - - val comp_prefixes: t -> t -> unit - val find_prefix : t -> Hptmap.prefix -> Cvalue_type.Model.subtree option - -end - -module Model : Model_S with type t = Cvalue_type.Model.t * tt = struct - - type model = Cvalue_type.Model.t * tt - type widen_hint = Model.widen_hint - type cluster = Cluster.t - - let is_reachable (x,_) = Model.is_reachable x - - let create_initial ~base ~v ~modu ~state:(s,r) = - (Model.create_initial ~base ~v ~modu ~state:s),r - - let copy_offsetmap ~with_alarms l (x,_) = - Model.copy_offsetmap ~with_alarms l x - - let pretty fmt (x,y) = - Model.pretty fmt x; - if Kernel.debug_atleast 1 then pretty_tt fmt y - - let pretty_c_assert fmt (x,_) = - Model.pretty_c_assert fmt x - - let pretty_without_null fmt (x,y) = - Model.pretty_without_null fmt x; - if Kernel.debug_atleast 1 then pretty_tt fmt y - - let pretty_filter fmt (x,_y) outs refilter = - Model.pretty_filter fmt x outs refilter - - let join (a,b as f) (c,d as s) = - let result = - if not (is_reachable f) then s - else if not (is_reachable s) then f - else - let _l,value_state = Model.join a c in - value_state, join b d - in - (*Format.printf "f:%a@\ns:%a@\nresult:%a@\n" - pretty f pretty s pretty result;*) - (*Format.printf "Rtype.Model.join finished@.";*) - result - - let find_base vi (t,_) = Model.find_base vi t - - let value_state (x,_y) = x - - let find_unspecified ~with_alarms (x,_) loc = Model.find_unspecified ~with_alarms x loc - - let find ~conflate_bottom ~with_alarms (x,_) loc = - Model.find ~conflate_bottom ~with_alarms x loc - - let bottom = Model.bottom, empty_tt - let top = Model.top, empty_tt - let empty_map = Model.empty_map, empty_tt - - let is_top (a,_) = Model.equal a Model.top - let inject s = s, empty_tt - - let add_binding ~with_alarms ~exact (s,rel) left v = - let r = Model.add_binding ~with_alarms ~exact s left v in - r, rel - - let add_binding_unspecified (s,rel) left = - Model.add_binding_unspecified s left, - rel - - let is_included (a,a') (b,b') = - Model.is_included a b && (is_included_tt a' b') - - let equal (a,a') (b,b') = - Model.equal a b && - (is_included_tt a' b') && (is_included_tt b' a') - (* TODO: make more efficient *) - - let is_included_actual_generic inouts (a,a') (b,b') = - assert (a' = empty_tt); - assert (b' = empty_tt); - Model.is_included_actual_generic inouts a b - - let widen wh (a,a') (b,b') = - let tt = if is_included_tt b' a' then a' else empty_tt in - let flag, values = - Model.widen wh a b - in - flag,(values, tt) - - let paste_offsetmap map_to_copy dst_loc start size (a, a') = - let result = - Model.paste_offsetmap map_to_copy dst_loc start size a - in - if Model.is_reachable result then result, a' else bottom - - let copy_paste loc1 loc2 (a, a') = - Model.copy_paste loc1 loc2 a, a' - - let drop_relations (a,_a') = a, empty_tt - - let comp_prefixes (a, _) (b, _) = Model.comp_prefixes a b - let find_prefix (a, _) prefix = Model.find_prefix a prefix - - let copy_from_virtual - sub_left_loc - (target_offset : Ival.t) target_size (_main, map) = - let losize = Int_Base.inject (Int.of_int(Bit_utils.sizeofpointer())) in - let treat_one_exact_location l acc = - assert (Location_Bits.cardinal_zero_or_one l); - let loc = make_loc l losize in - let cluster = - Participation_Map.find map.participation_map loc - in - match cluster with - | Bottom_cluster - | No_cluster -> (* no cluster for loc -> use main memory *) - raise Use_Main_Memory; - | Cluster c -> - let cluster_offset = - Relation_between.find ~with_alarms:CilE.warn_none_mode c.Cluster.rel loc - in - try - let cluster_offset = V.project_ival cluster_offset in -(* Format.printf "cluster_o:%a target_o:%a@\n" - Ival.pretty cluster_offset Ival.pretty target_offset; *) - let cluster_offset = - Ival.scale (Bit_utils.sizeofchar()) cluster_offset in - let actual_offset = - Ival.sub target_offset cluster_offset - in - let real = - Location_Bits.location_shift actual_offset - c.Cluster.virtual_to_real - in - if not (Locations.can_be_accessed - (Locations.make_loc real (Int_Base.inject target_size))) - then raise Lmap.Cannot_copy; - try - let f offs acc = - let copy = - V_Offsetmap.copy_offsmap - c.Cluster.contents - offs (Int.pred (Int.add offs target_size)) - in - match acc with - | None -> Some copy - | Some acc -> - Some(snd (V_Offsetmap.join copy acc)) - in - Ival.fold f actual_offset acc - with Int_Base.Error_Top -> raise Use_Main_Memory; - with V.Not_based_on_null -> - raise Use_Main_Memory - in - try - Cilutil.out_some - (Location_Bits.fold_enum - ~split_non_enumerable:(-1) - treat_one_exact_location - sub_left_loc.loc - None) - with Location_Bits.Error_Top -> raise Use_Main_Memory - - let hash (a, _b) = Model.hash a (*+ 97*hash b*) - - let filter_base_tt f a = - Cluster.Set.fold - (fun cl acc -> try add_new_cluster (Cluster.filter_base f cl) acc - with Cluster.No_more_cluster -> acc) - a.all_clusters - empty_tt - - let filter_base f (a,a') = - Model.filter_base f a, - filter_base_tt f a' - - let remove_base b (a,a') = - assert (a' == empty_tt); - Model.remove_base b a, - empty_tt - - let clear_state_from_locals fundec (state,r) = - let locals = List.map Base.create_varinfo fundec.Cil_types.slocals in - let formals = List.map Base.create_varinfo fundec.Cil_types.sformals in - let cleanup acc v = Cvalue_type.Model.remove_base v acc in - let result = List.fold_left cleanup state locals in - List.fold_left cleanup result formals, - filter_base_tt (fun v -> not (Base.is_formal_or_local v fundec)) r -(* - List.iter cleanup - filter_base - (fun v -> not (Base.is_formal_or_local v fundec)) - state -*) - - let uninitialize_locals blocks (state,r) = - let locals = - List.fold_left - (fun acc block -> - List.fold_left - (fun acc vi -> (Locations.loc_of_varinfo vi) :: acc) - acc - block.Cil_types.blocals) - [] - blocks - in - let state' = - List.fold_left Cvalue_type.Model.add_binding_unspecified state locals - in - let r' = filter_base_tt (fun v -> not (List.exists - (Base.is_block_local v) blocks)) r - in - (state', r') - - let compute_actual_final_from_generic (a,_a') (b,_b') loc instanciation = - let a,b = Model.compute_actual_final_from_generic a b loc instanciation in - (a,empty_tt),b - - let is_included_by_location_enum (a,_a') (b,_b') loc = - Model.is_included_by_location_enum a b loc - - let find_mem - (loc : Locations.location) - (target_size : Int_Base.t) - (target_offset : Ival.t) - (_main_memory, map : model) = - let losize = loc.size in - let treat_one_exact_location l acc = - assert (Location_Bits.cardinal_zero_or_one l); - let loc = make_loc l losize in - let cluster = Participation_Map.find map.participation_map loc - in - match cluster with - | Bottom_cluster - | No_cluster -> (* no cluster for loc -> use main memory *) - raise Use_Main_Memory; - | Cluster c -> - let cluster_offset = - Relation_between.find ~with_alarms:CilE.warn_none_mode - c.Cluster.rel - loc - in - try - let cluster_offset = - Ival.scale (Bit_utils.sizeofchar()) - (V.project_ival cluster_offset) - in - let actual_offset = - Ival.sub target_offset cluster_offset - in - let real = - Location_Bits.location_shift actual_offset - c.Cluster.virtual_to_real - in - (* Format.printf "cluster_offs:%a@\ntarget_offset:%a@\nreal:%a@\n" - Ival.pretty cluster_offset - Ival.pretty target_offset - Location_Bits.pretty real;*) - if not (Locations.can_be_accessed (Locations.make_loc real target_size)) - then raise Use_Main_Memory; - try - let target_size = Int_Base.project target_size in - let acc = V_Or_Uninitialized.initialized acc in - let r = - V_Or_Uninitialized.get_v - (V_Or_Uninitialized.join - (V_Offsetmap.find_ival - ~conflate_bottom:true - ~validity:Base.All - ~with_alarms:CilE.warn_none_mode - (* anyway, there is no validity *) - actual_offset c.Cluster.contents target_size) - acc - ) - in - (*Format.printf "find_mem: %a@\n" V.pretty r;*) - r - with Int_Base.Error_Top - (* suppressed this exception from find_ival. - Wondering if it could come from somewhere else - | Not_found (* from LOffset.find_ival *) *) - -> raise Use_Main_Memory - with V.Not_based_on_null -> raise Use_Main_Memory - in - try - let r = Location_Bits.fold_enum - ~split_non_enumerable:(-1) - treat_one_exact_location - loc.loc - V.bottom - in - (*Format.printf "find_mem(result): %a@\n" V.pretty r;*) - r - with - | Ival.Error_Top -> assert false - | Location_Bits.Error_Top -> V.top - - - let add_mem - (loc : Locations.location) - (target_size : Int_Base.t) - (target_offset : Ival.t) - (main, map as _orig: Model.t * tt) - (value : V.t) = - let virtual_to_real = virtual_to_real main loc in - assert (Location_Bits.cardinal_zero_or_one loc.loc); - let real_loc = - (Location_Bits.location_shift target_offset virtual_to_real) - in - let exact_real_loc = - Location_Bits.cardinal_zero_or_one real_loc - (* (Locations.valid_cardinal_zero_or_one real_loc) *) - in - (* main,map is the state in which the assignment has been - naively treated. Now we try to improve on that: *) - let target_size = - try Int_Base.project target_size - with Int_Base.Error_Top -> assert false - in - let loc_size = - try Int_Base.project loc.size - with Int_Base.Error_Top -> assert false - in - let result = - let clusterlist = - Participation_Map.concerned_bindings - map.participation_map - loc - in - (*Format.printf "ONC+E_CLuster(before): loc=%a@\n" Location_Bits.pretty loc.loc;*) - let protected_clusters,improved_relations = - match clusterlist with - | [] -> (* no cluster: create a new one *) - let exact = Ival.cardinal_zero_or_one target_offset in - if exact_real_loc || not exact then - (* exact_virtual_to_real: virtual_to_real is so precise that it is not - needed to create a cluster. - not exact: we don't have enough information to create a cluster *) - [],map - else - let contents = - V_Offsetmap.update_ival - ~with_alarms:CilE.warn_none_mode - ~validity:Base.All - ~exact - ~offsets:target_offset - ~size:target_size - V_Offsetmap.empty - (V_Or_Uninitialized.initialized value) - in - if V_Offsetmap.is_empty contents - then [], map - else - let rel = Relation_between.add_whole - loc - V.singleton_zero - Relation_between.empty - in - let new_cluster = - Cluster.make - ~contents - ~size:loc_size - ~rel - ~virtual_to_real - in - [new_cluster],add_new_cluster new_cluster map - - | [Cluster c] - when same_clusterinfo_cluster - (Participation_Map.find map.participation_map loc) c -> - (* one "just right" cluster: modify it *) - if exact_real_loc then [], map else - let exact = Ival.cardinal_zero_or_one target_offset in - let intrinsic_offset = - Relation_between.find ~with_alarms:CilE.warn_none_mode c.Cluster.rel loc - in - begin try - let intrinsic_offset = - Ival.scale (Bit_utils.sizeofchar()) - (V.project_ival intrinsic_offset) - in - assert (Ival.cardinal_zero_or_one intrinsic_offset); - let offset = Ival.sub target_offset intrinsic_offset in - (*Format.printf "offset AAAA:%a@\n" Ival.pretty offset;*) - let contents = - V_Offsetmap.update_ival - ~with_alarms:CilE.warn_none_mode - ~validity:Base.All - ~exact - ~offsets:offset - ~size:target_size - c.Cluster.contents - (V_Or_Uninitialized.initialized value) - in - let new_cluster = - Cluster.make - ~contents - ~size:loc_size - ~rel:c.Cluster.rel - ~virtual_to_real:c.Cluster.virtual_to_real - in - [new_cluster],replace_cluster ~new_cluster ~old_cluster:c map - with V.Not_based_on_null -> [],map - end - | _ -> - (* was this state cleaned up properly before calling add_mem? - At least it doesn't look so... *) - Format.printf "state not cleaned up?@\nloc=%a@\nstate=%a@\n" - Locations.pretty loc - pretty_tt map; - assert false - in - let result_state = main,improved_relations - in - protected_clusters,result_state - in - (*Format.printf "add_mem loc:%a@\nadd_mem target_size:%a - add_mem target_offset:%a@\nadd_mem initial:%a@\nadd_mem result:%a@\n" - Location_Bits.pretty loc.loc - Int.pretty target_size - Ival.pretty target_offset - pretty orig pretty (snd result);*) - result - - exception No_information - let propagate_change_from_real_to_virt ~protected_clusters loc m value = - let main_mem,m = m in - let result = - match loc.loc with - | Location_Bits.Top _ -> main_mem,empty_tt - | Location_Bits.Map locm -> - (* [pc 06/2006] the next two bindings should be deforested *) - let invalidated_clusters = - Participation_Map.concerned_bindings m.participation_map loc - in - let invalidated_clusters = - List.fold_right - (function Cluster c -> Cluster.Set.add c | _ -> assert false) - invalidated_clusters - Cluster.Set.empty - in - let m = - Cluster.Set.fold - (fun cluster acc -> - if List.exists (Cluster.equal cluster) protected_clusters - then acc - else - let new_rel = - Relation_between.remove_whole - loc - cluster.Cluster.rel - in - let can_be_removed = not (Cluster.has_information - { cluster with Cluster.rel = new_rel }) - in - if can_be_removed - then remove_cluster ~old_cluster:cluster acc - else - let new_cluster = - Cluster.make - ~size:cluster.Cluster.size - ~contents:cluster.Cluster.contents - ~virtual_to_real:cluster.Cluster.virtual_to_real - ~rel:new_rel - in replace_cluster ~new_cluster ~old_cluster:cluster acc) - invalidated_clusters - m - in - let size = - try - Int_Base.project loc.size - with Int_Base.Error_Top -> assert false (* TODO *) - in - let treat_cluster cluster acc = - (*Format.printf "treat_cluster(start): %a@\n" - V.pretty value;*) - try - let new_cluster = - if List.exists (Cluster.equal cluster) - protected_clusters - then - cluster - else - let treat_base base offsets acc = - try - let offsets_in_loc = - Location_Bits.M.find base locm - in - let new_offsets = - Ival.sub offsets_in_loc offsets - in -(* Format.printf "treat_cluster: %a %a@." - Base.pretty base - V.pretty value; *) - V_Offsetmap.update_ival - ~with_alarms:CilE.warn_none_mode - ~validity:Base.All - ~exact:false - ~size - ~offsets:new_offsets - acc - (V_Or_Uninitialized.initialized value) - with Not_found (*from Location_Bits.M.find *) -> - (* Format.printf "treat_cluster(not_found): %a@\n" - V.pretty value;*) - acc - in - let contents = - try Location_Bits.fold_i - treat_base - cluster.Cluster.virtual_to_real - cluster.Cluster.contents - with Location_Bits.Error_Top -> - V_Offsetmap.empty - in - if Cluster.has_information {cluster with Cluster.contents = contents } then - Cluster.make - ~size:cluster.Cluster.size - ~contents - ~rel:cluster.Cluster.rel - ~virtual_to_real:cluster.Cluster.virtual_to_real - else raise No_information - in - { all_clusters = Cluster.Set.add new_cluster acc.all_clusters; - participation_map = - index_cluster_into_participation_map new_cluster acc.participation_map } - with No_information -> acc - in - main_mem, - Cluster.Set.fold - treat_cluster - m.all_clusters - empty_tt - in -(* Format.printf - "propagate_change_from_real_to_virt:loc:%a@\nval:%a@\norig state:%a@\nresult: %a@\n" - Location_Bits.pretty loc.loc - V.pretty value - pretty (main_mem,m) - pretty result; -*) - result - - let reduce_binding (main, map as _state) left value = - assert (Locations.valid_cardinal_zero_or_one left); - let left = Locations.valid_part left in - match left.size with - | Int_Base.Bottom -> assert false - | Int_Base.Value _ when - (Location_Bits.cardinal_zero_or_one left.loc) -> - (* could do better : if left.loc is made of several locations, - all of which are in the same cluster *) - begin match Participation_Map.find map.participation_map left with - | Cluster c -> -(* Format.printf "cluster: %a@." - Cluster.pretty c ; *) - let left_offset = - Relation_between.find ~with_alarms:CilE.warn_none_mode c.Cluster.rel left - in - let value = V.add left_offset value in - let update_loc loc offs acc = - let reduced_value = - V.add_untyped (Int_Base.minus_one) value offs - in - Model.reduce_binding ~with_alarms:CilE.warn_none_mode - acc loc reduced_value - in - let improved_main = - Relation_between.fold_single_bindings - ~size:c.Cluster.size - update_loc - c.Cluster.rel - main - in - improved_main, map - | _ -> - Model.reduce_binding ~with_alarms:CilE.warn_none_mode - main left value, - map - end - | _ -> - Model.reduce_binding ~with_alarms:CilE.warn_none_mode - main left value, - map - - (* [offset] must be in bytes *) - let add_equality ?offset (main,map as state) left right = - (*Format.printf "add_equality left:%a right:%a@\nstate:%a@\n" - Locations.pretty left Locations.pretty right - pretty state;*) - match left.size with - | Int_Base.Bottom -> assert false - | Int_Base.Value size when - (Location_Bits.is_relationable left.loc) - && Int_Base.equal left.size right.size - && not (Zone.intersects - (valid_enumerate_bits left) - (valid_enumerate_bits right)) -> - begin match Participation_Map.find map.participation_map right with - | Cluster c -> - let offset_right = - Relation_between.find ~with_alarms:CilE.warn_none_mode c.Cluster.rel right - in - let offset = - match offset with - None -> offset_right - | Some o -> - V.location_shift o offset_right - in - assert (if V.cardinal_zero_or_one offset - then true - else (Format.printf "State at error point:%a@\n" - pretty state; false)); - let new_cluster = Cluster.make - ~rel:(Relation_between.add_whole - left - offset - c.Cluster.rel) - ~contents:c.Cluster.contents - ~size - ~virtual_to_real:c.Cluster.virtual_to_real - in - main, (replace_cluster ~new_cluster ~old_cluster:c map) - | No_cluster -> - let clusterlist = - Participation_Map.concerned_bindings - map.participation_map - right - in - - let virtual_to_real = virtual_to_real main right in - if (Location_Bits.cardinal_zero_or_one virtual_to_real) || - clusterlist <> [] - then state - else begin - let offset = - match offset with - None -> V.singleton_zero - | Some o -> V.inject_ival o - in - assert (V.cardinal_zero_or_one offset); - let rel = - (Relation_between.add_whole - left - offset - (Location_Bits.fold_enum - ~split_non_enumerable:(-1) - (fun loc acc -> - let locsize = Locations.make_loc loc right.size - in - Relation_between.add_whole - locsize - V.singleton_zero - acc) - right.loc - Relation_between.empty)) - in - let new_cluster = - (* ( try *) - Cluster.make ~size ~virtual_to_real ~rel - ~contents: V_Offsetmap.empty - (* - with _e -> - Format.printf "debugging add_equality rel=%a left=%a right=%a@." - Relation_between.pretty rel - Locations.pretty left Locations.pretty right; - raise _e ) *) - in - (* Format.printf "add_equality new_cluster:%a@\n" - Cluster.pretty new_cluster; *) - main,(add_new_cluster new_cluster map) - end - | Bottom_cluster -> assert false - end - | Int_Base.Top | Int_Base.Value _ -> state - - - (* TODO : detect unsatisfiability and reduce to bottom *) - let reduce_equality (main,map as state) left right = - (*Format.printf "reduce_equality left:%a right:%a@\n" - Locations.pretty left Locations.pretty right;*) - match left.size with - | Int_Base.Bottom -> assert false - | Int_Base.Value size when - (Location_Bits.cardinal_zero_or_one left.loc) - && Int_Base.equal left.size right.size - && not (Zone.intersects - (valid_enumerate_bits left) - (valid_enumerate_bits right)) -> - (match Participation_Map.find map.participation_map right - with - | Cluster c -> - if - (Participation_Map.concerned_bindings map.participation_map left) - = [] - then - let rel = - Relation_between.add_whole - left - (Relation_between.find ~with_alarms:CilE.warn_none_mode c.Cluster.rel right) - c.Cluster.rel - in - let new_cluster = - Cluster.make - ~rel - ~contents:c.Cluster.contents - ~size - ~virtual_to_real:c.Cluster.virtual_to_real - in - main, (replace_cluster ~new_cluster ~old_cluster:c map) - else - ( match Participation_Map.find map.participation_map left with - | Cluster cleft -> - if cleft.Cluster.id <> c.Cluster.id - then try - let delta = - V.add_untyped - Int_Base.minus_one - (Relation_between.find ~with_alarms:CilE.warn_none_mode - c.Cluster.rel right) - (Relation_between.find ~with_alarms:CilE.warn_none_mode - cleft.Cluster.rel left) - in - assert (V.cardinal_zero_or_one delta); - let rel = - Relation_between.fold_single_bindings - ~size - (fun loc v acc -> - let new_v = - V.add_untyped Int_Base.one - v - delta - in - Relation_between.add_whole loc new_v acc) - cleft.Cluster.rel - c.Cluster.rel -(* NB: this wouldn't have to be the _single_binding kind of fold but - add_whole currently doesn't support non-exact locations *) - in -(* Format.printf "rel:%a@." - Relation_between.pretty rel;*) - let delta = Ival.project_int (V.project_ival delta) in - let offset = Int.neg (Int.mul (Bit_utils.sizeofchar()) delta) - in - let shifted_left_content = - V_Offsetmap.shift offset - cleft.Cluster.contents (* FIXME *) - in -(* Format.printf "left_content:%a shifted_left_content:%a right=%a@." - V_Offsetmap.pretty cleft.Cluster.contents - V_Offsetmap.pretty shifted_left_content - V_Offsetmap.pretty c.Cluster.contents;*) - let contents = - V_Offsetmap.over_intersection - c.Cluster.contents - shifted_left_content - in - let new_cluster = - Cluster.make - ~rel - ~contents - ~size - ~virtual_to_real:c.Cluster.virtual_to_real - (* FIXME : use over-intersection of virtual_to_reals *) - in - let map = remove_cluster ~old_cluster:c map in - main, (replace_cluster ~new_cluster ~old_cluster:cleft map) - with V.Not_based_on_null -> - (* from project_ival *) state - else - state - | _ -> state) - | Bottom_cluster -> assert false - | No_cluster -> - match Participation_Map.find map.participation_map left - with - | Cluster c when - [] = (Participation_Map.concerned_bindings - map.participation_map - right) -> - let l = - Relation_between.find ~with_alarms:CilE.warn_none_mode c.Cluster.rel left - in - let rel = - Relation_between.add_whole - right - l - c.Cluster.rel - in -(* Format.printf "left:%a right:%a l:%a rel:%a@." - Locations.pretty left - Locations.pretty right - Location_Bytes.pretty l - Relation_between.pretty rel; *) - let new_cluster = - Cluster.make - ~rel - ~contents:c.Cluster.contents - ~size - ~virtual_to_real:c.Cluster.virtual_to_real - in - main, (replace_cluster ~new_cluster ~old_cluster:c map) - | Bottom_cluster -> assert false - | Cluster _ | No_cluster -> state) - | _ -> state - - (* result is in bytes *) - let compute_diff (_,map) left right = -(* Format.printf "compute_diff called@\n";*) - let result = - match Participation_Map.find map.participation_map right, right.size with - | Cluster cr, Int_Base.Value s when Int.equal s cr.Cluster.size -> - begin match Participation_Map.find map.participation_map left with - | Cluster cl when same_clusters cl cr -> - V.add_untyped (Int_Base.minus_one) - (Relation_between.find - ~with_alarms:CilE.warn_none_mode - cl.Cluster.rel - right) - (Relation_between.find - ~with_alarms:CilE.warn_none_mode - cl.Cluster.rel - left) - | _ -> raise Use_Main_Memory - end - | _ -> raise Use_Main_Memory - in - (* Format.printf "compute_diff returns %a@\n" V.pretty result;*) - result - - (* [offset] is in bytes *) - let shift_location ((main,map) as initial) loc offset right = - let offset = Ival.neg offset in - match Participation_Map.find map.participation_map loc, loc.size with - | Cluster cr, Int_Base.Value s when - Int.equal s cr.Cluster.size - && Location_Bits.cardinal_zero_or_one loc.loc - && Ival.cardinal_zero_or_one offset - && (try - let base,_ = Location_Bits.find_lonely_key loc.loc in - Location_Bits.fold_bases - (fun b () -> if Base.compare base b = 0 then raise Exit) - cr.Cluster.virtual_to_real (); - true - with | Exit | Location_Bits.Error_Top -> false - | Not_found -> assert false)-> - (*Format.printf "cluster to shift:%a@.offset: %a@." Cluster.pretty cr - Ival.pretty offset ;*) - let protected_cluster = - Cluster.make - ~size:cr.Cluster.size - ~contents:cr.Cluster.contents - ~rel:(Relation_between.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - cr.Cluster.rel loc - (Location_Bytes.location_shift - offset - (Relation_between.find ~with_alarms:CilE.warn_none_mode cr.Cluster.rel loc))) - ~virtual_to_real:cr.Cluster.virtual_to_real - in - (* Format.printf "protected_cluster:%a@\n" Cluster.pretty protected_cluster;*) - let initial = main,replace_cluster - ~new_cluster:protected_cluster - ~old_cluster:cr - map - in - (*Format.printf "intial_state:%a@\n" pretty initial;*) - let result = propagate_change_from_real_to_virt - ~protected_clusters:[protected_cluster] - loc - initial - right - in - (*Format.printf "cleaned_state:%a@\n" pretty result;*) - result - | _ -> propagate_change_from_real_to_virt ~protected_clusters:[] loc initial right - - include Datatype.Make - (struct - type t = model - let name = "Relations_type.Model" - let structural_descr = - Structural_descr.t_tuple - [| Cvalue_type.Model.packed_descr; - Structural_descr.pack - (Structural_descr.t_record - [| Participation_Map.packed_descr; - Cluster.Set.packed_descr |]) |] - let reprs = - List.map - (fun m -> - m, - { participation_map = Participation_Map.empty; - all_clusters = Cluster.Set.empty }) - Cvalue_type.Model.reprs - let hash = hash - let equal = equal - let compare = Datatype.undefined - let pretty = pretty - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.pp_fail - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) - -end - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/relations_type.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/relations_type.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/relations_type.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/relations_type.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Internal state representation of the value analysis. *) - -open Locations -open Abstract_interp -open Abstract_value - -exception Use_Main_Memory - (** To be raised whenever we need to fall back to value analysis *) -type tt - -module type Model_S = sig - - (** {3 Datatypes} *) - - include Datatype.S - type widen_hint = Cvalue_type.Model.widen_hint - type cluster - - (** {3 ...} *) - - val is_reachable : t -> bool - val pretty_c_assert : Format.formatter -> t -> unit - val pretty_without_null : Format.formatter -> t -> unit - val pretty_filter : - Format.formatter -> t -> Zone.t -> (Base.t -> bool) -> unit - val join : t -> t -> t - - val find : - conflate_bottom:bool -> - with_alarms:CilE.warn_mode -> t -> location -> Location_Bytes.t - - val find_unspecified : with_alarms:CilE.warn_mode -> t -> location -> - Cvalue_type.V_Or_Uninitialized.t - - val add_binding : - with_alarms:CilE.warn_mode -> exact:bool -> t -> location -> - Location_Bytes.t -> t - val add_binding_unspecified : t -> location -> t - - val reduce_binding : t -> location -> Location_Bytes.t -> t - val is_included : t -> t -> bool - val is_included_actual_generic : - Zone.t -> t -> t -> Location_Bytes.t Base.Map.t - val widen : widen_hint -> t -> t -> (bool * t) - val bottom : t - val inject : Cvalue_type.Model.t -> t - val empty_map : t - val top : t - val is_top: t -> bool - val value_state : t -> Cvalue_type.Model.t - - val drop_relations : t -> t - val filter_base : (Base.t -> bool) -> t -> t - val remove_base : Base.t -> t -> t - val clear_state_from_locals : Cil_types.fundec -> t -> t - val uninitialize_locals: Cil_types.block list -> t -> t - - val compute_actual_final_from_generic : - t -> t -> Zone.t -> Cvalue_type.Model.instanciation -> - t * Location_Bits.Top_Param.t - - val is_included_by_location_enum : t -> t -> Zone.t -> bool - - val find_mem : location -> Int_Base.t -> Ival.t -> t -> Cvalue_type.V.t - (** computes the value of [*location] *) - - val add_mem : - location -> Int_Base.t -> Ival.t -> t -> Cvalue_type.V.t -> - cluster list * t - (** add an information about the value of [*location] *) - - val propagate_change_from_real_to_virt : - protected_clusters:cluster list -> location -> t -> Cvalue_type.V.t -> t - (** clean up relation about [location] (call this function each time - location has changed) *) - - val add_equality : ?offset:Ival.t -> t -> location -> location -> t - val reduce_equality : t -> location -> location -> t - val compute_diff : t -> location -> location -> Cvalue_type.V.t - - val shift_location : t -> location -> Ival.t -> Cvalue_type.V.t -> t - - val find_base : Base.t -> t -> Cvalue_type.V_Offsetmap.t - (** @raise Not_found when the vid is not in the map *) - - val create_initial : base:Base.t -> - v:Cvalue_type.V.t -> - modu:Int.t -> - state:t -> t - (** Overwrites [base] in [state] with an initialized offsetmap filled - with repetitions of the value [v] of size [modu]. *) - - (** {3 Copy / paste} *) - - val paste_offsetmap : - Cvalue_type.V_Offsetmap.t -> Location_Bits.t -> Int.t -> Int.t -> t -> t - (** @raise Lmap.Cannot_copy when copying is not possible. *) - - val copy_paste : location -> location -> t -> t - (** @raise Lmap.Cannot_copy when copying is not possible. *) - - val copy_from_virtual : - location -> - Ival.t -> - Int.t -> t -> Cvalue_type.V_Offsetmap.t - (** @raise Lmap.Cannot_copy when copying is not possible. *) - - val copy_offsetmap : with_alarms:CilE.warn_mode -> - Locations.location -> t -> Cvalue_type.V_Offsetmap.t option - - val comp_prefixes: t -> t -> unit - val find_prefix : t -> Hptmap.prefix -> Cvalue_type.Model.subtree option - -end - -module Model : Model_S with type t = Cvalue_type.Model.t * tt - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/shifted_Location.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/shifted_Location.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/shifted_Location.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/shifted_Location.ml 2011-10-10 08:38:30.000000000 +0000 @@ -26,14 +26,14 @@ type t = { l : Locations.location ; offset : Ival.t } let bottom = { l = Locations.loc_bottom ; offset = Ival.bottom } - + let make l d = - if Locations.loc_equal l Locations.loc_bottom || - Ival.equal d Ival.bottom + if Locations.loc_equal l Locations.loc_bottom || + Ival.is_bottom d then bottom else { l = l ; offset = d } - -let equal ls1 ls2 = + +let equal ls1 ls2 = Locations.loc_equal ls1.l ls2.l&& Ival.equal ls1.offset ls2.offset let is_bottom ls = @@ -48,3 +48,9 @@ Int_Base.equal l1.size l2.size && Location_Bits.is_included l1.loc l2.loc && Ival.is_included ls1.offset ls2.offset + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/shifted_Location.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/shifted_Location.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/shifted_Location.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/shifted_Location.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + type t = private { l : Locations.location; offset : Ival.t; } val bottom : t @@ -28,3 +33,9 @@ val is_bottom : t -> bool val pretty : Format.formatter -> t -> unit val is_included : t -> t -> bool + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/state_imp.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/state_imp.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/state_imp.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/state_imp.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,36 +20,36 @@ (* *) (**************************************************************************) -module Sindexed = +module Sindexed = Hashtbl.Make (struct - type t = Cvalue_type.Model.subtree - let hash = Cvalue_type.Model.hash_subtree - let equal = Cvalue_type.Model.equal_subtree + type t = Cvalue.Model.subtree + let hash = Cvalue.Model.hash_subtree + let equal = Cvalue.Model.equal_subtree end) let sentinel = Sindexed.create 1 -type t = - { mutable t : Relations_type.Model.t Sindexed.t ; +type t = + { mutable t : Cvalue.Model.t Sindexed.t ; mutable p : Hptmap.prefix ; - mutable o : Relations_type.Model.t list ; + mutable o : Cvalue.Model.t list ; } -let fold f acc { t = t ; o = o } = +let fold f acc { t = t ; o = o } = List.fold_left f (Sindexed.fold (fun _k v a -> f a v) t acc) o -let iter f { t = t ; o = o } = +let iter f { t = t ; o = o } = Sindexed.iter (fun _k v -> f v) t; List.iter f o - + exception Found let empty () = { t = sentinel ; p = Hptmap.sentinel_prefix ; o = [] } let is_empty t = t.t == sentinel && t.o = [] -let exists f s = +let exists f s = try iter (fun v -> if f v then raise Found) s; false @@ -62,72 +62,70 @@ iter (fun state -> Format.fprintf fmt "set contains %a@\n" - Relations_type.Model.pretty state) + Cvalue.Model.pretty state) s let add_to_list v s = - if + if List.exists - (fun e -> Relations_type.Model.is_included v e) + (fun e -> Cvalue.Model.is_included v e) s then raise Unchanged; (* let nl, ns = filter - (fun e -> not (Relations_type.Model.is_included e v)) + (fun e -> not (Cvalue.Model.is_included e v)) w in *) v :: s -let rec add_exn v s = - if not (Relations_type.Model.is_reachable v) +let rec add_exn v s = + if not (Cvalue.Model.is_reachable v) then raise Unchanged; - if s.t == sentinel + if s.t == sentinel then begin - match s.o with - [ v1 ; v2 ] when - not (Cvalue_type.Model.equal - (Relations_type.Model.value_state v1) - (Relations_type.Model.value_state v2)) -> - begin - try - Relations_type.Model.comp_prefixes v1 v2; - s.o <- add_to_list v s.o - with - Cvalue_type.Model.Found_prefix (p, subtree1, subtree2) -> + match s.o with + [ v1 ; v2 ] when + not (Cvalue.Model.equal v1 v2) -> + begin + try + Cvalue.Model.comp_prefixes v1 v2; + s.o <- add_to_list v s.o + with + Cvalue.Model.Found_prefix (p, subtree1, subtree2) -> (* - Format.printf "COMP h1 %d@." - (Cvalue_type.Model.hash_subtree subtree1); - Format.printf "COMP h2 %d@." - (Cvalue_type.Model.hash_subtree subtree2); + Format.printf "COMP h1 %d@." + (Cvalue.Model.hash_subtree subtree1); + Format.printf "COMP h2 %d@." + (Cvalue.Model.hash_subtree subtree2); *) - let t = Sindexed.create 13 in - Sindexed.add t subtree1 v1; - Sindexed.add t subtree2 v2; - s.t <- t; - s.p <- p; - s.o <- []; - add_exn v s - end - | _ -> s.o <- add_to_list v s.o + let t = Sindexed.create 13 in + Sindexed.add t subtree1 v1; + Sindexed.add t subtree2 v2; + s.t <- t; + s.p <- p; + s.o <- []; + add_exn v s + end + | _ -> s.o <- add_to_list v s.o end else begin - let subtree = Relations_type.Model.find_prefix v s.p in + let subtree = Cvalue.Model.find_prefix v s.p in begin match subtree with - None -> s.o <- add_to_list v s.o + None -> s.o <- add_to_list v s.o | Some subtree -> - let candidates = Sindexed.find_all s.t subtree in -(* Format.printf "COMP indexed %d %d@." - (List.length candidates) - (List.length s.o); *) - let v_incl = Relations_type.Model.is_included v in - if List.exists v_incl candidates - || List.exists v_incl s.o - then raise Unchanged - else Sindexed.add s.t subtree v + let candidates = Sindexed.find_all s.t subtree in +(* Format.printf "COMP indexed %d %d@." + (List.length candidates) + (List.length s.o); *) + let v_incl = Cvalue.Model.is_included v in + if List.exists v_incl candidates + || List.exists v_incl s.o + then raise Unchanged + else Sindexed.add s.t subtree v end end -let merge_into sa sb = +let merge_into sa sb = let unchanged = ref true in let f e = try @@ -140,7 +138,7 @@ if !unchanged then raise Unchanged; result -let merge_set_into set sb = +let merge_set_into set sb = let unchanged = ref true in let f e = try @@ -154,55 +152,45 @@ result let merge_set_return_new set sb = - let f e acc = + let f acc e = try add_exn e sb ; e :: acc with Unchanged -> acc in - let result = State_set.fold f set [] in + let result = State_set.fold f [] set in State_set.of_list result - + let add v s = try add_exn v s with Unchanged -> () -let singleton v = - let r = empty () in - add v r; +let singleton v = + let r = empty () in + add v r; r let join s = fold - Relations_type.Model.join - Relations_type.Model.bottom + Cvalue.Model.join + Cvalue.Model.bottom s -let join_dropping_relations s = - Relations_type.Model.inject - (fold - (fun x y -> - snd (Cvalue_type.Model.join (Relations_type.Model.value_state y) x)) - Cvalue_type.Model.bottom - s) +let join_dropping_relations = join let fold f acc s = fold (fun acc v -> f v acc) s acc let to_set i = - Sindexed.fold + Sindexed.fold (fun _k v a -> State_set.unsafe_add v a) i.t (State_set.of_list i.o) - - - (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j 4" +compile-command: "make -C ../.." End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/state_imp.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/state_imp.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/state_imp.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/state_imp.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,36 +20,39 @@ (* *) (**************************************************************************) -(* $Id: state_set.mli,v 1.6 2009-02-24 17:53:39 uid527 Exp $ *) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) type t exception Unchanged val pretty : Format.formatter -> t -> unit -val add : Relations_type.Model.t -> t -> unit -val fold : ( Relations_type.Model.t -> 'a -> 'a) -> t -> 'a -> 'a -val iter : (Relations_type.Model.t -> unit) -> t -> unit +val add : Cvalue.Model.t -> t -> unit +val fold : ( Cvalue.Model.t -> 'a -> 'a) -> t -> 'a -> 'a +val iter : (Cvalue.Model.t -> unit) -> t -> unit val merge_into : t -> t -> unit val merge_set_into : State_set.t -> t -> unit val merge_set_return_new : State_set.t -> t -> State_set.t -val join : t -> Relations_type.Model.t -val join_dropping_relations : t -> Relations_type.Model.t -val exists : (Relations_type.Model.t -> bool) -> t -> bool +val join : t -> Cvalue.Model.t +val join_dropping_relations : t -> Cvalue.Model.t +val exists : (Cvalue.Model.t -> bool) -> t -> bool val is_empty : t -> bool val length : t -> int val empty : unit -> t -val singleton : Relations_type.Model.t -> t +val singleton : Cvalue.Model.t -> t val to_set : t -> State_set.t (* -val filter : (Relations_type.Model.t -> bool) -> t -> t +val filter : (Cvalue.Model.t -> bool) -> t -> t val length : t -> int -val nth : t -> int -> Relations_type.Model.t +val nth : t -> int -> Cvalue.Model.t *) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/state_set.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/state_set.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/state_set.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/state_set.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,74 +20,50 @@ (* *) (**************************************************************************) -module Sindexed = - Hashtbl.Make - (struct - type t = Cvalue_type.Model.subtree - let hash = Cvalue_type.Model.hash_subtree - let equal = Cvalue_type.Model.equal_subtree - end) - -let sentinel = Sindexed.create 1 - -type t = - { t : Relations_type.Model.t Sindexed.t ; - o : Relations_type.Model.t list } - -let fold f acc { t = t ; o = o } = - List.fold_left f (Sindexed.fold (fun _k v a -> f a v) t acc) o - -let of_list l = { t = sentinel ; o = l } - -let iter f { t = t ; o = o } = - Sindexed.iter (fun _k v -> f v) t; - List.iter f o - +type t = Cvalue.Model.t list + +let obviously_terminates = false + +let fold = List.fold_left + +let of_list l = l + +let iter = List.iter + exception Found -let empty = { t = sentinel ; o = [] } +let empty = [] -let is_empty t = t.t == sentinel && t.o = [] +let is_empty t = t = empty -let exists f s = - try - iter (fun v -> if f v then raise Found) s; - false - with Found -> true +let exists = List.exists -let length s = List.length s.o + Sindexed.length s.t +let length = List.length exception Unchanged let pretty fmt s = iter (fun state -> Format.fprintf fmt "set contains %a@\n" - Relations_type.Model.pretty state) + Cvalue.Model.pretty state) s -let add_to_list v s = - if - List.exists - (fun e -> Relations_type.Model.is_included v e) - s +let add_to_list v s = + if (not (Cvalue.Model.is_reachable v)) + || ((not obviously_terminates) && + (List.exists + (fun e -> Cvalue.Model.is_included v e) + s)) then raise Unchanged; -(* let nl, ns = - filter - (fun e -> not (Relations_type.Model.is_included e v)) - w - in *) v :: s -let add_exn v s = - if not (Relations_type.Model.is_reachable v) - then raise Unchanged; - { s with o = add_to_list v s.o } +let add_exn v s = add_to_list v s -let merge_into sa sb = +let merge_into sa sb = let unchanged = ref true in let f acc e = try - let r = add_exn e acc in + let r = add_exn e acc in unchanged := false; r with Unchanged -> @@ -98,35 +74,25 @@ result -let add v s = +let add v s = try - add_exn v s + add_exn v s with Unchanged -> s -let unsafe_add v s = { s with o = v :: s.o } +let unsafe_add v s = v :: s let singleton v = add v empty let join s = fold - Relations_type.Model.join - Relations_type.Model.bottom + Cvalue.Model.join + Cvalue.Model.bottom s -let join_dropping_relations s = - Relations_type.Model.inject - (fold - (fun x y -> - snd (Cvalue_type.Model.join (Relations_type.Model.value_state y) x)) - Cvalue_type.Model.bottom - s) - -let fold f acc s = fold (fun acc v -> f v acc) s acc - +let join_dropping_relations = join (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j 4" +compile-command: "make -C ../.." End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/state_set.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/state_set.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/state_set.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/state_set.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,35 +20,39 @@ (* *) (**************************************************************************) -(* $Id: state_set.mli,v 1.6 2009-02-24 17:53:39 uid527 Exp $ *) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) type t exception Unchanged val pretty : Format.formatter -> t -> unit -val add : Relations_type.Model.t -> t -> t -val unsafe_add : Relations_type.Model.t -> t -> t -val fold : ( Relations_type.Model.t -> 'a -> 'a) -> t -> 'a -> 'a -val iter : (Relations_type.Model.t -> unit) -> t -> unit +val add : Cvalue.Model.t -> t -> t +val unsafe_add : Cvalue.Model.t -> t -> t +val fold : ('a -> Cvalue.Model.t -> 'a) -> 'a -> t -> 'a +val iter : (Cvalue.Model.t -> unit) -> t -> unit val merge_into : t -> t -> t -val join : t -> Relations_type.Model.t -val join_dropping_relations : t -> Relations_type.Model.t -val exists : (Relations_type.Model.t -> bool) -> t -> bool +val join : t -> Cvalue.Model.t +val join_dropping_relations : t -> Cvalue.Model.t +val exists : (Cvalue.Model.t -> bool) -> t -> bool val is_empty : t -> bool val length : t -> int val empty : t -val singleton : Relations_type.Model.t -> t -val of_list : Relations_type.Model.t list -> t +val singleton : Cvalue.Model.t -> t +val of_list : Cvalue.Model.t list -> t (* -val filter : (Relations_type.Model.t -> bool) -> t -> t +val filter : (Cvalue.Model.t -> bool) -> t -> t val length : t -> int -val nth : t -> int -> Relations_type.Model.t +val nth : t -> int -> Cvalue.Model.t *) + (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/tr_offset.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/tr_offset.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/tr_offset.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/tr_offset.ml 2011-10-10 08:38:30.000000000 +0000 @@ -0,0 +1,161 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Abstract_interp +open Abstract_value +open CilE + +type t = + Set of Ival.O.t + | Interval of Int.t * Int.t * Int.t + | Imprecise of Int.t * Int.t + +exception Unbounded + +let empty = Set (Ival.O.empty) + +let reduce_ival_by_bound ival size validity = + let pred_size = Int.pred size in + match validity with + | Base.All -> begin (* no clipping can be performed *) + match ival with + | Ival.Top (Some mn,Some mx,_r,m) -> + let result = + if Int.lt m size + then Imprecise(mn, Int.add mx pred_size) + else Interval(mn, mx, m) + in + true, (false, result) + | Ival.Top (None,_,_,_) + | Ival.Top (_,None,_,_) + | Ival.Float _ -> + raise Unbounded + | Ival.Set o -> true, (false, Set (Ival.set_of_array o)) + end + | Base.Known (bound_min, bound_max) | Base.Unknown (bound_min, bound_max) + | Base.Periodic (bound_min, bound_max, _) -> + let max_in_bound = Int.sub bound_max pred_size in + let is_in_bound x = match x with + | Ival.Top (mn,mx,r,modu) -> + let out, new_mn = + match mn with + | Some mn when (Int.ge mn bound_min) -> false, mn + | _ -> true, Int.round_up_to_r ~r ~modu ~min:bound_min + in + let out, new_mx = + match mx with + | Some mx when (Int.le mx max_in_bound) -> out, mx + | _ -> true, Int.round_down_to_r ~r ~modu ~max:max_in_bound + in + let itv_or_set = + if Int.le new_mn new_mx + then begin + if Int.lt modu size + then Imprecise(new_mn, Int.add new_mx pred_size) + else Interval(new_mn, new_mx, modu) + end + else empty + in + out, itv_or_set + | _ -> assert false + in + let out, reduced_bounds as result = + begin match ival with + | Ival.Top (_mn,_mx,_r,_m) -> is_in_bound ival + | Ival.Float _ -> is_in_bound Ival.top + | Ival.Set s -> + let s = Ival.set_of_array s in + let out, set = + Ival.O.fold + (fun offset (out_acc, reduced_acc) -> + let pseudo_interval = + Ival.Top(Some offset, Some offset,Int.zero, Int.one) + in + let out, _reduced = is_in_bound pseudo_interval in + out || out_acc, + if out + then reduced_acc + else Ival.O.add offset reduced_acc) + s + (false, Ival.O.empty) + in + (out, Set set) + end + in + match validity with + | Base.Periodic(_, _, p) -> + assert (Int.is_zero bound_min); + let reduced_bounds = + match reduced_bounds with + | Imprecise (mn, mx) -> + if Int.equal (Int.pos_div mn p) (Int.pos_div mx p) + then Imprecise (Int.pos_rem mn p, Int.pos_rem mx p) + else Imprecise (bound_min, Int.pred p) + | Set s -> + let treat_offset offset acc = + let new_offset = Int.pos_rem offset p in + if Int.gt (Int.add new_offset size) p + then raise Unbounded + else + (* Format.printf "old offset: %a mx: %a period: %a new: %a@." + Int.pretty offset + Int.pretty bound_max + Int.pretty p + Int.pretty new_offset; *) + Ival.O.add new_offset acc + in + begin + try + Set (Ival.O.fold treat_offset s Ival.O.empty) + with Unbounded -> Imprecise (bound_min, Int.pred p) + end + | Interval(lb, _ub, mo) -> + if Int.is_zero (Int.pos_rem mo p) + then Set (Ival.O.singleton (Int.pos_rem lb p)) + else begin + Format.printf "Interval %a %a %a@." + Int.pretty lb + Int.pretty _ub + Int.pretty mo; + Imprecise (bound_min, Int.pred p) + end + in + false, (out, reduced_bounds) + | _ -> true, result + + let filter_by_bound_for_reading ~with_alarms ival size validity = + let _, (out, filtered_by_bound) = reduce_ival_by_bound ival size validity in + if out then warn_mem_read with_alarms; + filtered_by_bound + + let filter_by_bound_for_writing ~exact ~with_alarms ival size validity = + let still_exact, (out, filtered_by_bound) = + reduce_ival_by_bound ival size validity + in + if out then warn_mem_write with_alarms; + (exact && still_exact), filtered_by_bound + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/tr_offset.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/tr_offset.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/tr_offset.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/tr_offset.mli 2011-10-10 08:38:30.000000000 +0000 @@ -0,0 +1,48 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + +type t = + Set of Ival.O.t + | Interval of Abstract_interp.Int.t * Abstract_interp.Int.t * + Abstract_interp.Int.t + | Imprecise of Abstract_interp.Int.t * Abstract_interp.Int.t +exception Unbounded +val empty : t +val reduce_ival_by_bound : + Ival.tt -> My_bigint.t -> Base.validity -> bool * (bool * t) +val filter_by_bound_for_reading : + with_alarms:CilE.warn_mode -> Ival.tt -> My_bigint.t -> Base.validity -> t +val filter_by_bound_for_writing : + exact:bool -> + with_alarms:CilE.warn_mode -> + Ival.tt -> My_bigint.t -> Base.validity -> bool * t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/widen.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/widen.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/widen.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/widen.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,13 +20,14 @@ (* *) (**************************************************************************) -open Cil +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please write a mli and + document it. *) + open Cil_types open Cil_datatype -open Db -open Db_types -open Abstract_value -open Visitor class widen_visitor kf init_widen_hints init_enclosing_loop_info = object (* visit all sub-expressions from [kf] definition *) @@ -47,8 +48,8 @@ (* Format.printf "Look at widening variables.\n" ; *) let visitor = new widen_visitor kf widen_hints enclosing_loop_info in - ignore (visitFramacBlock visitor bl); - SkipChildren + ignore (Visitor.visitFramacBlock visitor bl); + Cil.SkipChildren in begin match s.skind with | Loop (_, bl, _, _, _) -> @@ -75,30 +76,30 @@ (vid::lv, lt) | _ -> (lv, t::lt) in - begin match List.fold_left f ([], []) l with + begin match List.fold_left f ([], []) l with | (lv, []) -> (* the annotation is empty or else, - there are only variables *) + there are only variables *) let var_hints = - List.fold_left - (fun s x -> Base.Set.add x s) - Base.Set.empty - lv + List.fold_left + (fun s x -> Base.Set.add x s) + Base.Set.empty + lv in List.iter (fun widening_stmt -> widen_hints := Widen_type.add_var_hints - widening_stmt - var_hints - !widen_hints) + widening_stmt + var_hints + !widen_hints) widening_stmts; is_pragma_widen_variables := true | (_lv, _lt) -> - ignore - (CilE.warn_once - "could not interpret loop pragma relative to widening variables") + Kernel.warning ~once:true ~current:true + "could not interpret loop pragma relative to widening \ + variables" end | Widen_hints l -> let f (lv, lnum, lt) t = @@ -108,7 +109,7 @@ let vid = Base.create_varinfo vi in (vid::lv, lnum, lt) | { term_node= TConst (CInt64(v,_,_))} -> - let v = Ival.Widen_Hints.V.of_int64 v + let v = Ival.Widen_Hints.V.of_int64 (My_bigint.to_int64 v) in (lv, v::lnum, lt) | _ -> (lv, lnum, t::lt) in begin match List.fold_left f ([], [], []) l with @@ -126,19 +127,20 @@ widening_stmts) lv | _ -> - ignore (CilE.warn_once "could not interpret loop pragma relative to widening hint") + Kernel.warning ~once:true ~current:true + "could not interpret loop pragma relative to widening hint" end | _ -> () in List.iter f l_pragma ; if not !is_pragma_widen_variables then - let loop = - try Loop.get_loop_stmts kf s - with Loop.No_such_while -> assert false - in + let loop = + try Loop.get_loop_stmts kf s + with Loop.No_such_while -> assert false + in (* There is no Widen_variables pragma for this loop. *) infer_widen_variables bl (Some (widening_stmts, loop)) else - DoChildren + Cil.DoChildren | If (exp, bl_then, bl_else, _) -> begin match enclosing_loop_info with @@ -152,7 +154,7 @@ ({skind = Break _; succs = [stmt]}| {skind = Goto ({contents=stmt},_)})::_} when not (Stmt.Set.mem stmt loop_stmts) -> - let varinfos = extract_varinfos_from_exp exp + let varinfos = Cil.extract_varinfos_from_exp exp in let var_hints = Varinfo.Set.fold (fun vi lv -> @@ -172,50 +174,58 @@ | _ -> ()) [bl_then ; bl_else] end; - DoChildren ; - | _ -> DoChildren + Cil.DoChildren + | _ -> + Cil.DoChildren end ; end method vexpr (e:exp) = begin let with_succ v = [v ; Ival.Widen_Hints.V.succ v] and with_pred v = [Ival.Widen_Hints.V.pred v ; v ] - and with_s_p_ v = [(Ival.Widen_Hints.V.pred v) ; v ; (Ival.Widen_Hints.V.succ v)] + and with_s_p_ v = [Ival.Widen_Hints.V.pred v; v; Ival.Widen_Hints.V.succ v] and default_visit e = match Cil.isInteger e with - | Some _int64 -> (* - let v = Ival.Widen_Hints.V.of_int64 int64 - in widen_hints := Db.Widen_Hints.add_to_all v !widen_hints ; - *) - SkipChildren - | _ -> DoChildren + | Some _int64 -> + (* + let v = Ival.Widen_Hints.V.of_int64 int64 + in widen_hints := Db.Widen_Hints.add_to_all v !widen_hints ; + *) + Cil.SkipChildren + | _ -> + Cil.DoChildren and comparison_visit add1 add2 e1 e2 = let add key set = let hints = - List.fold_right - Ival.Widen_Hints.add - set - Ival.Widen_Hints.empty + List.fold_right + Ival.Widen_Hints.add + set + Ival.Widen_Hints.empty in (*Format.printf "Adding widen hint %a for base %a@\n" Ival.Widen_Hints.pretty hints Base.pretty key;*) - widen_hints := Widen_type.add_num_hints None (Widen_type.VarKey key) hints !widen_hints + widen_hints := + Widen_type.add_num_hints + None (Widen_type.VarKey key) hints !widen_hints in begin - let e1,e2 = constFold true e1, constFold true e2 in + let e1,e2 = Cil.constFold true e1, Cil.constFold true e2 in match (Cil.isInteger e1, Cil.isInteger e2, e1, e2) with | Some int64, _, - _, {enode=(CastE(_, { enode=Lval (Var varinfo, _)})|Lval (Var varinfo, _))}-> - add - (Base.create_varinfo varinfo) - (add1 (Ival.Widen_Hints.V.of_int64 int64)); - SkipChildren + _, {enode=(CastE(_, { enode=Lval (Var varinfo, _)}) + | Lval (Var varinfo, _))}-> + add + (Base.create_varinfo varinfo) + (add1 int64); + Cil.SkipChildren | _, Some int64, - {enode=(CastE(_, { enode=Lval (Var varinfo, _)})|Lval (Var varinfo, _))}, _ -> - add - (Base.create_varinfo varinfo) - (add2 (Ival.Widen_Hints.V.of_int64 int64)); - SkipChildren - | _ -> DoChildren + {enode=(CastE(_, { enode=Lval (Var varinfo, _)}) + | Lval (Var varinfo, _))}, _ -> + add + (Base.create_varinfo varinfo) + (add2 int64); + Cil.SkipChildren + | _ -> + Cil.DoChildren end in match e.enode with @@ -223,10 +233,10 @@ | BinOp (Gt, e2, e1, _) | BinOp (Le, e2, e1, _) | BinOp (Ge, e1, e2, _) -> - comparison_visit with_succ with_pred e1 e2 + comparison_visit with_succ with_pred e1 e2 | BinOp (Eq, e1, e2, _) | BinOp (Ne, e1, e2, _) -> - comparison_visit with_s_p_ with_s_p_ e1 e2 + comparison_visit with_s_p_ with_s_p_ e1 e2 | _ -> default_visit e end end @@ -238,10 +248,10 @@ | Declaration _ -> default_widen_hints | Definition (fd,_) -> begin - let widen_hints = ref default_widen_hints - in let visitor = new widen_visitor kf widen_hints None - in ignore (visitFramacFunction visitor fd) ; - !widen_hints + let widen_hints = ref default_widen_hints in + let visitor = new widen_visitor kf widen_hints None in + ignore (Visitor.visitFramacFunction visitor fd); + !widen_hints end end in widen_hints diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/widen_type.ml frama-c-20111001+nitrogen+dfsg/src/memory_state/widen_type.ml --- frama-c-20110201+carbon+dfsg/src/memory_state/widen_type.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/widen_type.ml 2011-10-10 08:38:30.000000000 +0000 @@ -20,9 +20,6 @@ (* *) (**************************************************************************) -open Cil -open Cil_types -open Abstract_value open Cil_datatype module Widen_hint_bases = Base.Map.Make(Ival.Widen_Hints) @@ -35,26 +32,26 @@ (struct include Datatype.Serializable_undefined type t = - Ival.Widen_Hints.t - * Ival.Widen_Hints.t - * Widen_hint_bases.t - * Widen_hint_stmts.t + Ival.Widen_Hints.t + * Ival.Widen_Hints.t + * Widen_hint_bases.t + * Widen_hint_stmts.t let name = "widen types" let structural_descr = Structural_descr.t_tuple - [| Ival.Widen_Hints.packed_descr; - Ival.Widen_Hints.packed_descr; - Widen_hint_bases.packed_descr; - Widen_hint_stmts.packed_descr |] + [| Ival.Widen_Hints.packed_descr; + Ival.Widen_Hints.packed_descr; + Widen_hint_bases.packed_descr; + Widen_hint_stmts.packed_descr |] let reprs = List.map - (fun wh -> wh, wh, Base.Map.empty, Stmt.Map.empty) - Ival.Widen_Hints.reprs + (fun wh -> wh, wh, Base.Map.empty, Stmt.Map.empty) + Ival.Widen_Hints.reprs let mem_project = Datatype.never_any_project end)) (* map from Base.t to Ival.Widen_Hints.t *) -type var_key = Default | All | VarKey of Cvalue_type.V.M.key +type var_key = Default | All | VarKey of Cvalue.V.M.key let hints_from_key (forced_hints, default_hints, var_map) var_key = let widen_hints = @@ -63,10 +60,10 @@ with Not_found -> default_hints in Ival.Widen_Hints.union forced_hints hints - in (* Format.printf "WIDEN_HINT widen a var_key %a -> %a @\n" + in (* Format.printf "WIDEN_HInt widen a var_key %a -> %a @\n" Base.pretty var_key Ival.Widen_Hints.pretty widen_hints; *) - Cvalue_type.V.Top_Param.O.empty, fun _ -> widen_hints + Cvalue.V.Top_Param.O.empty, fun _ -> widen_hints let hints_from_keys stmt_key @@ -116,7 +113,7 @@ try Base.Map.find var_key var_map with Not_found -> Ival.Widen_Hints.empty in - Ival.Widen_Hints.union hints previous_hints + Ival.Widen_Hints.union hints previous_hints in forced_hints, default_hints, @@ -129,7 +126,7 @@ try Stmt.Map.find stmt_key stmt_map with Not_found -> Base.Map.empty in - add_merge var_key hints previous_var_map + add_merge var_key hints previous_var_map in forced_hints, default_hints, diff -Nru frama-c-20110201+carbon+dfsg/src/memory_state/widen_type.mli frama-c-20111001+nitrogen+dfsg/src/memory_state/widen_type.mli --- frama-c-20110201+carbon+dfsg/src/memory_state/widen_type.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/memory_state/widen_type.mli 2011-10-10 08:38:30.000000000 +0000 @@ -20,6 +20,11 @@ (* *) (**************************************************************************) +(** Undocumented. + Do not use this module if you don't know what you are doing. *) + +(* [JS 2011/10/03] To the authors/users of this module: please document it. *) + include Datatype.S (** Key for the first map : from Base.t to Ival.Widen_Hints.t *) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/css_html.ml frama-c-20111001+nitrogen+dfsg/src/metrics/css_html.ml --- frama-c-20110201+carbon+dfsg/src/metrics/css_html.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/css_html.ml 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,149 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let css = "\ +body {\ + display:block;\ + position: relative;\ + left: 5%;\ + width: 90%;\ + font-family: Georgia, Times, serif;\ + font-size: 10pt; /* base size */\ + min-height: 30em;\ + background: #ffffff;\ + color: #444444;\ +}\ +\ +h1 {\ + font-family: Optima, Verdana, Arial, sans;\ + font-size: 1.6em;\ + font-weight: normal;\ + color: black;\ + margin: 0.4em 0em 0.4em 0em;\ + padding: 0.4em 0em 0em 1em;\ + border-bottom: thin solid #404040;\ +}\ +\ +h2 {\ + font-family: Optima, Verdana, Arial, sans;\ + font-size: 1.2em;\ + font-weight: normal;\ + color: black;\ + margin: 0.4em 0em 0.4em 0em;\ + padding: 0.4em 0em 0em 1em;\ + border-bottom: thin dotted #404040;\ +}\ +\ +h3 {\ + font-family: Optima, Verdana, Arial, sans;\ + font-size: 1.2em;\ + font-weight: normal;\ + color: black;\ + margin: 0.4em 0em 0.4em 0em;\ + padding: 0.4em 0em 0em 1em;\ +}\ +\ +td {\ + text-align: center;\ + border: thin solid black; \ +}\ +\ +th { \ + text-align: center;\ + font-weight: normal;\ + color: black;\ + border: thin solid black; \ + padding: 3pt;\ + background-color: #bfb4b4;\ +}\ + \ +td.entry { \ + text-align: left;\ + font-weight: normal;\ + color: black;\ + border: thin solid black; \ + padding: 3pt;\ + background-color: #e8e8e8 ;\ +}\ +td.stat { \ + text-align: center;\ + color: black;\ + border: thin solid black; \ + padding: 3pt;\ + width: 20%; \ +}\ + \ +td.result { \ + text-align: center;\ + color: black;\ + border: thin solid black; \ + padding: 3pt;\ + background-color: #AFC7C7 ;\ +}\ +\ +tr {}\ +\ +caption {\ + caption-side: bottom;\ +}\ +\ +table {\ + border: medium solid black;\ + width: 90%; \ +}\ +\ +div.graph {\ + text-align: center;\ +}\ +\ +ul.horizontal {\ + padding:0;\ + margin:0;\ + list-style-type:none;\ + }\ +\ +li.horizontal {\ + margin-left:1.5em;\ + float:left; /*pour IE*/\ + }\ +\ +span {\ + font-weight: bold;\ +}\ +\ +a.varinfo, span.vdecl a.varinfo_fun {\ + text-decoration: none;\ +}\ +\ +a.varinfo, a.varinfo_fun {\ + color: #000;\ +}\ +\ +h3.back {\ + font-family: Optima, Verdana, Arial, sans;\ + padding-top: 2em;\ +}\ +\ +h3.back a {\ + color:black;\ +}\ +" diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_base.ml frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_base.ml --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_base.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_base.ml 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,361 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cabs +open Cil_types (* vname, vaddrof *) +open Cil_datatype +open Db.Metrics (* sloc, call_statements, .... *) +open Format +;; + +(* Formatting html with Format.formatters *) +let html_tag_functions = + let mark_open_tag t = Format.sprintf "<%s>" t + and mark_close_tag t = + try + let index = String.index t ' ' in + Format.sprintf "" (String.sub t 0 index) + with + | Not_found -> Format.sprintf "" t + and print_open_tag _ = () + and print_close_tag _ = () + in + { Format.mark_open_tag = mark_open_tag; + Format.mark_close_tag = mark_close_tag; + Format.print_open_tag = print_open_tag; + Format.print_close_tag = print_close_tag; + } +;; + +exception No_suffix;; +let get_suffix filename = + try + let slen = String.length filename in + let last_idx = pred slen in + let last_dot_idx = String.rindex_from filename last_idx '.' in + if last_dot_idx < last_idx then + String.sub filename (succ last_dot_idx) (slen - last_dot_idx - 1) + else "" + with + | Not_found -> raise No_suffix +;; + +type output_type = + | Html + | Text +;; + +let get_file_type filename = + try + match get_suffix filename with + | "html" | "htm" -> Html + | "txt" | "text" -> Text + | s -> + Metrics_parameters.Metrics.fatal + "Unknown file extension %s. Cannot produce output.@." s + with + | No_suffix -> + Metrics_parameters.Metrics.fatal + "File %s has no suffix. Cannot produce output.@." filename +;; + +(** Common utilities *) +module VInfoMap = struct + include Map.Make ( + struct + let compare v1 v2 = Pervasives.compare v1.vname v2.vname;; + type t = Cil_types.varinfo + end + ) + + let map_cardinal (map:'a t) = + fold (fun _funcname _ cardinal -> succ cardinal) map 0 ;; + + + let to_varinfo_map vmap = + fold (fun k v mapacc -> Varinfo.Map.add k v mapacc) vmap Varinfo.Map.empty + ;; +end +;; + +(** Record type to compute cyclomatic complexity *) +type my_metrics = { + cfile_name : string; + cfunc_name : string; + cslocs: int; + cifs: int; + cloops: int; + ccalls: int; + cgotos: int; + cassigns: int; + cexits: int; + cfuncs: int; + cptrs: int; + cdecision_points: int; +} +;; + +let empty_metrics = + { cfile_name = ""; + cfunc_name = ""; + cslocs = 0; + cifs = 0; + cloops = 0; + ccalls = 0; + cgotos = 0; + cassigns = 0; + cexits = 0; + cfuncs = 0; + cptrs = 0; + cdecision_points = 0; + } +;; + +(* Compute cyclomatic complexity of a given metrics record *) +let cyclo metrics = + metrics.cdecision_points - metrics.cexits + 2 +(* metrics.cifs - metrics.cexits + metrics.cloops + (2 * metrics.cfuncs) *) +;; + +(* Pretty print metrics as text eg. in stdout *) +let pp_my_metrics fmt metrics = + let format_heading fmt () = + if metrics.cfile_name = "" && metrics.cfunc_name = "" then + (* It is a global metrics *) + Format.fprintf fmt "Global metrics" + else Format.fprintf fmt "Stats for function <%s/%s>" + metrics.cfile_name metrics.cfunc_name + in + Format.fprintf fmt "@[\ + %a @ \ + ----------------------@ \ + #assigns = %d@ \ + #calls = %d@ \ + #exits = %d@ \ + #funcs = %d@ \ + #gotos = %d@ \ + #ifs = %d@ \ + #loops = %d@ \ + #pointer dereferencings = %d@ \ + #decision points = %d@ \ + #slocs = %d@ \ + cyclomatic complexity = %d@ \ + @]" + format_heading () + metrics.cassigns metrics.ccalls + metrics.cexits metrics.cfuncs + metrics.cgotos metrics.cifs + metrics.cloops metrics.cptrs + metrics.cdecision_points + metrics.cslocs (cyclo metrics) + ;; + +(* Dummy utility functions for pretty printing simple types *) +let pp_strg fmt s = Format.fprintf fmt "%s" s +and pp_int fmt n = Format.fprintf fmt "%d" n +;; + +type cell_type = + | Classic + | Entry + | Stat + | Result +;; + +let cell_type_to_string = function + | Entry -> "entry" + | Stat -> "stat" + | Result -> "result" + | Classic -> "classic" +;; + +let pp_cell_type_html fmt cell_type = + Format.fprintf fmt "class=\"%s\"" (cell_type_to_string cell_type) +;; + +(* Pretty print a HTML cell given a pretty printing function [pp_fun] + and a value [pp_arg] +*) +let pp_cell cell_type pp_fun fmt pp_arg = + Format.fprintf fmt "@{%a@}" + pp_cell_type_html cell_type + pp_fun pp_arg +;; + +let pp_cell_default = pp_cell Classic;; + +let pp_metrics_as_html_row fmt metrics = + Format.fprintf fmt "\ + @[\ + @{@[@ \ + @[%a@ %a@ %a@ %a@ %a@ %a@ %a@ %a@ %a@ @]@]\ + @}@ @]" + (pp_cell Entry pp_strg) metrics.cfunc_name + (pp_cell_default pp_int) metrics.cifs + (pp_cell_default pp_int) metrics.cassigns + (pp_cell_default pp_int) metrics.cloops + (pp_cell_default pp_int) metrics.ccalls + (pp_cell_default pp_int) metrics.cgotos + (pp_cell_default pp_int) metrics.cptrs + (pp_cell_default pp_int) metrics.cexits + (pp_cell Result pp_int) (cyclo metrics) +;; + + +(* Storing and sharing metrics result *) +let name = "metrics";; + +module DatatypeMetrics = + Datatype.Make + (struct + include Datatype.Serializable_undefined + type t = Db.Metrics.t + let name = name + let structural_descr = Structural_descr.Abstract + let reprs = + [ { sloc = -1; + call_statements = -1; + goto_statements = -1; + assign_statements = -1; + if_statements = -1; + loop_statements = -1; + mem_access = -1; + functions_without_source = Varinfo.Map.empty; + functions_with_source = Varinfo.Map.empty; + function_definitions = -1; + cyclos = -1 } ] + let mem_project = Datatype.never_any_project + end) + + +(** Other pretty-printing and formatting utilities *) +let pretty_set iter fmt s = + Format.fprintf fmt "@["; + iter + (fun f n -> + Format.fprintf fmt "%s %s(%d call%s);@ " + f.Cil_types.vname + (if f.vaddrof then "(address taken) " else "") + n (if n > 1 then "s" else "")) + s; + Format.fprintf fmt "@]" +;; + +let pretty_varinfomap fmt s = + Format.fprintf fmt "@["; + VInfoMap.iter + (fun f n -> + Format.fprintf fmt "%s %s (%d call%s);@ " + f.Cil_types.vname + (if f.vaddrof then "(address taken) " else "") + n (if n > 1 then "s" else "")) + s; + Format.fprintf fmt "@]" +;; +let is_entry_point vinfo times_called = + times_called = 0 && not vinfo.vaddrof +;; + +let number_entry_points fold fs = + fold + (fun fvinfo n acc -> if is_entry_point fvinfo n then succ acc else acc) + fs 0 +;; + +let pretty_entry_points iter fmt fs = + let print fmt = + iter + (fun fvinfo n -> + if is_entry_point fvinfo n + then Format.fprintf fmt "%s;@ " fvinfo.vname) + in + Format.fprintf fmt "@[%a@]" print fs; +;; + +let map_cardinal_varinfomap (map:'a Varinfo.Map.t) = + Varinfo.Map.fold + (fun _funcname _ cardinal -> succ cardinal) + map 0 +;; + +let pretty fmt m = + Format.fprintf fmt + "@[@[** Defined functions (%d):@ \ + @[%a@]@]@ @ \ + @[** Undefined functions (%d):@ \ + @[%a@]@]@ @ \ + @[** Potential entry points (%d):@ \ + @[%a@]@]@ @ \ + SLOC: %d@ \ + Number of if statements: %d@ \ + Number of assignments: %d@ \ + Number of loops: %d@ \ + Number of calls: %d@ \ + Number of gotos: %d@ \ + Number of pointer access: %d@ \ + @]" + (map_cardinal_varinfomap m.functions_with_source) + (pretty_set Varinfo.Map.iter) m.functions_with_source + (map_cardinal_varinfomap m.functions_without_source) + (pretty_set Varinfo.Map.iter) m.functions_without_source + (number_entry_points Varinfo.Map.fold m.functions_with_source) + (pretty_entry_points Varinfo.Map.iter) m.functions_with_source + m.sloc + m.if_statements + m.assign_statements + m.loop_statements + m.call_statements + m.goto_statements + m.mem_access +;; + +(* Utilities for CIL ASTs *) + +let file_of_vinfodef fvinfo = + let kf = Globals.Functions.get fvinfo in + let decl_loc1, _decl_loc2 = + match kf.fundec with + | Definition (_, loc) -> loc + | Declaration (_, _, _, loc) -> loc + in decl_loc1.Lexing.pos_fname +;; + +let file_of_fundef (fun_dec: Cil_types.fundec) = + file_of_vinfodef fun_dec.svar +;; + +(* Utilities for Cabs ASTs *) + +let extract_fundef_name sname = + match sname with + | _spec, (the_name, _, _, _) -> the_name +;; + +let get_filename fdef = + match fdef with + | Cabs.FUNDEF(_, _, _, (loc1, _), _loc2) -> loc1.Lexing.pos_fname + | _ -> assert false +;; + +let consider_function vinfo = + not (!Db.Value.mem_builtin vinfo.vname + || Ast_info.is_frama_c_builtin vinfo.vname) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_base.mli frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_base.mli --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_base.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_base.mli 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,121 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module DatatypeMetrics: Datatype.S with type t = Db.Metrics.t + +val html_tag_functions: Format.formatter_tag_functions;; +(** Tag functions handling html tags for Format *) + +type my_metrics = { + cfile_name : string; (* Filename *) + cfunc_name : string; (* Function name if applicable, eg. not in the case of + global metrics + *) + cslocs: int; (* Lines of code w.r.t. statements *) + cifs: int; (* If / cases of switch *) + cloops: int; (* Loops: for, while, do...while *) + ccalls: int; (* Function calls *) + cgotos: int; (* Gotos *) + cassigns: int; (* Assignments *) + cexits: int; (* Exit points: return *) + cfuncs: int; (* Functions defined: 1 in the case of a single function, + possibly more in the case of a file + *) + cptrs: int; (* Access to pointers *) + cdecision_points: int; (* Decision points of the program: ifs, + switch cases, exception handlers, ... *) +} +(** Storing metrics information *) + +val empty_metrics: my_metrics;; +(** Initial empty values for metrics computing. *) + +val cyclo: my_metrics -> int;; +(** Compute cyclomatic complexity from my_metrics record type. *) + +val pp_my_metrics: Format.formatter -> my_metrics -> unit;; +val pp_metrics_as_html_row: Format.formatter -> my_metrics -> unit;; +(** Pretty printers for metrics as text or html. *) + + +module VInfoMap: sig + include Map.S with type key = Cil_types.varinfo +(* This should be removed whenever 3.12 will be the oldest + OCaml version used and replaced by Map.cardinal. +*) + val map_cardinal: 'a t -> int;; + (** Cardinal of a VInfoMap *) + + val to_varinfo_map: 'a t -> 'a Cil_datatype.Varinfo.Map.t +end +;; +(** Local varinfo map where the comparison function is the lexicographic one on + their respectives names.*) + +val map_cardinal_varinfomap: 'a Cil_datatype.Varinfo.Map.t -> int;; + +val pretty_set : + ((Cil_types.varinfo -> int -> unit) -> 'a -> 'b) -> + Format.formatter -> 'a -> unit +;; +(** Pretty print a varinfo set *) + +val number_entry_points : + ((Cil_types.varinfo -> int -> int -> int) -> 'a -> int -> 'b) -> 'a -> 'b +;; + +val pretty_entry_points : + ((Cil_types.varinfo -> int -> unit) -> 'a -> unit) -> Format.formatter -> + 'a -> unit +;; + +val pretty : Format.formatter -> DatatypeMetrics.t -> unit;; +(** Pretty print results *) + +val file_of_vinfodef: Cil_types.varinfo -> string;; +(** Get the filename where the definition of a varinfo occurs *) + +val file_of_fundef: Cil_types.fundec -> string;; +(** Get the filename containing the function definition *) + +val extract_fundef_name: Cabs.single_name -> string;; +val get_filename: Cabs.definition -> string;; + +type output_type = + | Html + | Text +;; +(** Type of the generated report file. + Automatically set according to the file extension. +*) + +val get_file_type: string -> output_type;; +(** get_file_type [extension] sets the output type according to [extension]. + Raise an error if [extension] is not among supported extensions or is empty. +*) + +val consider_function: Cil_types.varinfo -> bool +(** consider_function [vinfo] returns false if the varinfo is not a function we + are interested in. + For example, builtins should not be part of the analysis and return false. + Skip them using this auxiliary function. +*) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_cabs.ml frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cabs.ml --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_cabs.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cabs.ml 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,647 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Implementation of cyclomatic complexity measures on CAbs' AST *) +open Cabs +open Cil_datatype +open Metrics_base +open Metrics_parameters +;; + + +class metricsCabsVisitor = object(self) + inherit Cabsvisit.nopCabsVisitor + + (* Global metrics store for this Cabs AST *) + val global_metrics = ref empty_metrics + (* Local metrics in computation *) + val local_metrics = ref empty_metrics + + (* Was last statement a case ? *) + val was_case = ref false + + (* Local metrics are kept stored after computation in this map of maps. + Its storing hierachy is as follows: filename -> function_name -> metrics *) + val mutable metrics_map: + (my_metrics Datatype.String.Map.t) Datatype.String.Map.t = + Datatype.String.Map.empty + + val functions_no_source: (string, int)Hashtbl.t = Hashtbl.create 97 + val functions_with_source: (string, int)Hashtbl.t = Hashtbl.create 97 + val mutable standalone = true + + (* Getters/setters *) + method functions_no_source = functions_no_source + method functions_with_source = functions_with_source + method set_standalone v = standalone <- v + method get_metrics = !global_metrics + method private update_metrics_map filename strmap = + metrics_map <- Datatype.String.Map.add filename strmap metrics_map + + (* Utility methods to increase metrics counts *) + method private incr_slocs metrics = + metrics := {!metrics with cslocs = succ !metrics.cslocs;} + + method private incr_assigns metrics = + metrics := {!metrics with cassigns = succ !metrics.cassigns;} + + method private incr_calls metrics = + metrics := {!metrics with ccalls = succ !metrics.ccalls;} + + method private incr_exits metrics = + metrics := {!metrics with cexits = succ !metrics.cexits;} + + method private incr_funcs metrics = + metrics := {!metrics with cfuncs = succ !metrics.cfuncs;} + + method private incr_gotos metrics = + metrics := {!metrics with cgotos = succ !metrics.cgotos;} + + method private incr_ifs metrics = + metrics := {!metrics with cifs = succ !metrics.cifs;} + + method private incr_loops metrics = + metrics := {!metrics with cloops = succ !metrics.cloops;} + + method private incr_ptrs metrics = + metrics := {!metrics with cptrs = succ !metrics.cptrs;} + + method private incr_dpoints metrics = + metrics := {!metrics with cdecision_points = succ !metrics.cdecision_points;} + + method private incr_both_metrics f = + f global_metrics; + f local_metrics + + method add_to_functions_with_source (funcname:string) = + Hashtbl.add functions_with_source funcname 0; + Hashtbl.remove functions_no_source funcname; + + method private record_and_clear metrics = + let filename = metrics.cfile_name + and funcname = metrics.cfunc_name in + (try + let fun_tbl = Datatype.String.Map.find filename metrics_map in + self#update_metrics_map filename + (Datatype.String.Map.add funcname !local_metrics fun_tbl); + with + | Not_found -> + let new_stringmap = + Datatype.String.Map.add funcname !local_metrics Datatype.String.Map.empty in + self#update_metrics_map filename new_stringmap; + ); + local_metrics := empty_metrics; + + method vdef def = + match def with + | FUNDEF (_, sname, _, _, _) -> + begin + let funcname = Metrics_base.extract_fundef_name sname in + local_metrics := + {!local_metrics with + cfile_name = get_filename def; + cfunc_name = funcname; + cfuncs = 1; (* Only one function is indeed being defined here *)}; + Metrics.debug + ~level:1 "Definition of function %s encountered@." funcname; + self#incr_funcs global_metrics; + self#add_to_functions_with_source funcname; + (* On return record the analysis of the function. *) + Cil.ChangeDoChildrenPost + ([def], + fun _ -> + begin + if !local_metrics <> empty_metrics + then self#record_and_clear !local_metrics; + [def] + end + ); + end + | DECDEF _ + | TYPEDEF _ + | ONLYTYPEDEF _ + | GLOBASM _ + | PRAGMA _ + | LINKAGE _ + | TRANSFORMER _ + | EXPRTRANSFORMER _ + | GLOBANNOT _ -> Cil.DoChildren; + + method vexpr expr = + (match expr.expr_node with + | NOTHING -> () + | UNARY (unop, _) -> + begin + match unop with + | PREINCR + | POSINCR + | PREDECR + | POSDECR -> self#incr_both_metrics self#incr_assigns + | MINUS + | PLUS + | NOT + | BNOT -> () + | MEMOF -> self#incr_both_metrics self#incr_ptrs + | ADDROF -> () + end + | LABELADDR _ -> () + | BINARY (bop, _, _) -> + begin + match bop with + | ADD | SUB | MUL | DIV | MOD + | BAND | BOR | XOR + | SHL | SHR | EQ | NE | LT + | GT | LE | GE -> () + | AND | OR -> self#incr_both_metrics self#incr_dpoints + | ASSIGN + | ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN + | DIV_ASSIGN | BOR_ASSIGN | XOR_ASSIGN + | SHL_ASSIGN | SHR_ASSIGN | BAND_ASSIGN + | MOD_ASSIGN -> + self#incr_both_metrics self#incr_assigns; + end + | CAST _ -> () + | CALL _ -> self#incr_both_metrics self#incr_calls; + | QUESTION _ -> + self#incr_both_metrics self#incr_dpoints; + self#incr_both_metrics self#incr_ifs; + | COMMA _ + | CONSTANT _ + | PAREN _ + | VARIABLE _ + | EXPR_SIZEOF _ + | TYPE_SIZEOF _ + | EXPR_ALIGNOF _ + | TYPE_ALIGNOF _ + | INDEX _ + | MEMBEROF _ + | MEMBEROFPTR _ + | GNU_BODY _ + | EXPR_PATTERN _ -> ()); + Cil.DoChildren + + (* Allows to count only one control-flow branch per case lists *) + method private set_case stmt = + match stmt.stmt_node with + | CASERANGE _ | CASE _ -> was_case := true; + | DEFAULT _ + | _ -> was_case := false + + method vstmt stmt = + self#incr_both_metrics self#incr_slocs; + (match stmt.stmt_node with + | DEFAULT _ -> () (* The default case is not counted as a path choice + point *) + | CASERANGE _ + | CASE _ -> + if not !was_case then self#incr_both_metrics self#incr_dpoints; + | IF _ -> + self#incr_both_metrics self#incr_ifs; + self#incr_both_metrics self#incr_dpoints; + | NOP _ + | COMPUTATION _ + | BLOCK _ -> () + (* Next 3 are all loop instructions *) + | WHILE _ + | DOWHILE _ + | FOR _ -> + self#incr_both_metrics self#incr_loops; + self#incr_both_metrics self#incr_dpoints; + | BREAK _ + | CONTINUE _ -> () + | RETURN _ -> self#incr_both_metrics self#incr_exits; + | SWITCH _ -> () + | LABEL _ -> () + | GOTO _ + | COMPGOTO _ -> self#incr_both_metrics self#incr_gotos; + | DEFINITION _ + | ASM _ + | SEQUENCE _ + | TRY_EXCEPT _ + | TRY_FINALLY _ + | CODE_ANNOT _ + | CODE_SPEC _ -> ()); + self#set_case stmt; + Cil.DoChildren + + method private stats_of_filename filename = + try Datatype.String.Map.find filename metrics_map + with + | Not_found -> + Metrics.fatal "Metrics for file %s not_found@." filename + + method pp_file_metrics fmt filename = + Format.fprintf fmt "@[%a@]" + (fun fmt filename -> + let fun_tbl = self#stats_of_filename filename in + Datatype.String.Map.iter (fun _fun_name fmetrics -> + Format.fprintf fmt "@ %a" pp_my_metrics fmetrics) + fun_tbl; + ) filename + + method pp_detailed_text_metrics fmt () = + Datatype.String.Map.iter + (fun filename _func_tbl -> + Format.fprintf fmt "%a" self#pp_file_metrics filename) metrics_map + +end +;; + + +(** Halstead metrics computation *) +module Halstead = struct +(* We follow http://www.verifysoft.com/en_halstead_metrics.html + for the classification of operands and operators + operands = ids, typenames, typespecs, constants +*) + +let update_val value key tbl = + try + let v = Hashtbl.find tbl key in + Hashtbl.replace tbl key (v + value); + with + | Not_found -> Hashtbl.add tbl key value +;; + +let update_val_incr key tbl = update_val 1 key tbl;; + +type operand_tbl = { + var_tbl : (string, int) Hashtbl.t; + cst_tbl : (Cabs.constant, int) Hashtbl.t; +} +;; + +type operator_tbl = { + knownop_tbl : (string, int) Hashtbl.t; + otherop_tbl : (string, int) Hashtbl.t; + reserved_tbl : (string, int) Hashtbl.t; + tspec_tbl : (Cabs.typeSpecifier, int) Hashtbl.t; +} +;; + +type halstead_metrics = { + distinct_operators: int; + distinct_operands: int; + total_operators: int; + total_operands: int; +} +;; + +let id_from_init iname = + match (fst iname) with + | s, _, _, _ -> s +;; + +class halsteadCabsVisitor = object(self) + + inherit Cabsvisit.nopCabsVisitor + + val operand_tbl = { + var_tbl = Hashtbl.create 7; + cst_tbl = Hashtbl.create 7; + } + + val operator_tbl = { + knownop_tbl = Hashtbl.create 7; + otherop_tbl = Hashtbl.create 7; + reserved_tbl = Hashtbl.create 7; + tspec_tbl = Hashtbl.create 7; + } + + method get_operator_tbl () = operator_tbl + method get_operand_tbl () = operand_tbl + + method add_paren () = + update_val_incr "(" operator_tbl.otherop_tbl; + update_val_incr ")" operator_tbl.otherop_tbl; + + method vexpr e = + match e.Cabs.expr_node with + | UNARY _ -> + let unop = fst (Cprint.get_operator e) in + update_val_incr unop operator_tbl.knownop_tbl; + Cil.DoChildren; + | BINARY _ -> + let binop = fst (Cprint.get_operator e) in + update_val_incr binop operator_tbl.knownop_tbl; + Cil.DoChildren; + | QUESTION _ -> + update_val_incr "?" operator_tbl.otherop_tbl; + update_val_incr ":" operator_tbl.otherop_tbl; + Cil.DoChildren; + | COMMA elist -> + let n = List.length elist in + if (n > 1) then + update_val (n - 1) "," operator_tbl.otherop_tbl; + Cil.DoChildren; + | CONSTANT c -> + update_val_incr c operand_tbl.cst_tbl; + Cil.DoChildren; + | PAREN _ -> + self#add_paren (); + Cil.DoChildren; + | VARIABLE s -> + update_val_incr s operand_tbl.var_tbl; + Cil.DoChildren; + | EXPR_SIZEOF _ -> + update_val_incr "sizeof" operator_tbl.reserved_tbl; + Cil.DoChildren; + | TYPE_SIZEOF _ -> + update_val_incr "sizeof" operator_tbl.reserved_tbl; + Cil.DoChildren; + | INDEX _ -> + update_val_incr "[]" operator_tbl.otherop_tbl; + Cil.DoChildren; + | _ -> Cil.DoChildren; + + + method vstmt s = + let reserved rstr = + update_val_incr rstr operator_tbl.reserved_tbl; + Cil.DoChildren; + in + match s.Cabs.stmt_node with + | BLOCK _ -> + update_val_incr "{" operator_tbl.otherop_tbl; + update_val_incr "}" operator_tbl.otherop_tbl; + Cil.DoChildren; + | SEQUENCE _ -> + print_string "seq\n"; + update_val_incr ";" operator_tbl.otherop_tbl; + Cil.DoChildren; + | IF _ -> self#add_paren (); reserved "if"; + | WHILE _ -> self#add_paren (); reserved "while"; + | DOWHILE _ -> + update_val_incr "do" operator_tbl.reserved_tbl; + self#add_paren (); + reserved "while"; + | FOR _ -> + self#add_paren (); + update_val 2 ";" operator_tbl.otherop_tbl; + reserved "for"; + | BREAK _ -> reserved "break"; + | CONTINUE _ -> reserved "continue"; + | RETURN _ -> reserved "return"; + | SWITCH _ -> self#add_paren (); reserved "switch"; + | CASE _ -> reserved "case"; + | CASERANGE _ -> + update_val_incr "..." operator_tbl.otherop_tbl; + update_val 2 ";" operator_tbl.otherop_tbl; + reserved "case"; + | DEFAULT _ -> reserved "default"; + | LABEL _ -> + update_val_incr ":" operator_tbl.otherop_tbl; + Cil.DoChildren; + | GOTO (s, _) -> + let lname = Format.sprintf "label_%s" s in + update_val_incr lname operand_tbl.var_tbl; + reserved "goto"; + + | COMPGOTO _ -> + update_val_incr "*" operator_tbl.otherop_tbl; + reserved "goto"; + + | DEFINITION _ -> Cil.DoChildren; + | ASM _ -> reserved "asm"; + | TRY_EXCEPT _ -> + update_val_incr "except" operator_tbl.reserved_tbl; + reserved "try"; + | TRY_FINALLY _ -> + update_val_incr "finally" operator_tbl.reserved_tbl; + reserved "try"; + | _ -> Cil.DoChildren; + + method vtypespec tspec = + update_val_incr tspec operator_tbl.tspec_tbl; + Cil.DoChildren; + + method vspec spec = + let reserved rstr = + update_val_incr rstr operator_tbl.reserved_tbl; + in + let do_spec s = + match s with + | SpecTypedef -> reserved "typedef" + | SpecInline -> reserved "inline" + | SpecStorage AUTO -> reserved "auto" + | SpecStorage STATIC -> reserved "static" + | SpecStorage EXTERN -> reserved "extern" + | SpecStorage REGISTER -> reserved "register" + | SpecCV CV_CONST -> reserved "const" + | SpecCV CV_VOLATILE -> reserved "volatile" + | SpecCV CV_RESTRICT -> reserved "restrict" + | _ -> () + in List.iter do_spec spec; Cil.DoChildren; + + method vdecltype tdecl = + match tdecl with + | JUSTBASE -> + Cil.SkipChildren; + | PARENTYPE _ -> + self#add_paren (); + Cil.DoChildren; + | ARRAY _ -> + update_val_incr "array" operator_tbl.reserved_tbl; + Cil.DoChildren; + | PTR _ -> + update_val_incr "*" operator_tbl.otherop_tbl; + Cil.DoChildren; + | PROTO _ -> + Cil.SkipChildren; + + + method vinitexpr ie = + ( match ie with + | COMPOUND_INIT l -> + let n = List.length l in + if n > 0 then + update_val n "," operator_tbl.otherop_tbl; + | _ -> ()); + Cil.DoChildren + + method vblock b = + if b.bstmts <> [] then ( + let n = List.length b.bstmts in + update_val n ";" operator_tbl.otherop_tbl); + if b.battrs <> [] then + update_val (List.length b.battrs) "," operator_tbl.otherop_tbl; + Cil.DoChildren; + + method vdef d = + match d with + | FUNDEF (bl, (_, (fname, dtype, _, nloc)), b, loc1, loc2) -> + Cil.ChangeDoChildrenPost( + [FUNDEF(bl, ([], (fname, dtype, [], nloc)), b, loc1, loc2)], + fun x -> x) + + | DECDEF (_, (_, name_list), _) -> + let n = + List.fold_left + (fun acc n -> + update_val_incr (id_from_init n) operand_tbl.var_tbl; + acc + 1 ) + (-1) name_list in + begin + assert(n >= 0); + if (n > 0) then update_val n "," operator_tbl.otherop_tbl; + Cil.DoChildren; + end + + | _ -> Cil.DoChildren + +end +;; + + + +let compose _x1 y1 (x2, y2) = (1 + x2), (y1 + y2);; +let fold x y = Hashtbl.fold compose x y;; + +let compute_operators operator_tbl = + let x, y = + fold operator_tbl.tspec_tbl ( + fold operator_tbl.otherop_tbl ( + fold operator_tbl.reserved_tbl ( + fold operator_tbl.knownop_tbl (0,0)))) + in (float_of_int x), (float_of_int y) +;; + +let compute_operands operand_tbl = + let x, y = + fold operand_tbl.cst_tbl ( + fold operand_tbl.var_tbl (0,0)) + in (float_of_int x), (float_of_int y) +;; + +let pp_metrics ppf cabs_visitor = + (* Compute the metrics from the informations gathered by the visitor. *) + let operator_tbl = cabs_visitor#get_operator_tbl () in + let operand_tbl = cabs_visitor#get_operand_tbl () in + let distinct_operators, total_operators = compute_operators operator_tbl + and distinct_operands, total_operands = compute_operands operand_tbl in + let program_length = total_operands +. total_operators in + let vocabulary_size = distinct_operands +. distinct_operators in + let log2 x = (Pervasives.log x) /. (Pervasives.log 2.0) in + let program_volume = program_length *. (log2 vocabulary_size) in + let difficulty_level = + (distinct_operators /. 2.) *. (total_operands /. distinct_operands) in + let program_level = 1. /. difficulty_level in + let effort_to_implement = program_volume *. difficulty_level in + let time_to_implement = effort_to_implement /. 18. in + let bugs_delivered = (effort_to_implement ** (2./.3.)) /. 3000. in + let minutes = (int_of_float time_to_implement) / 60 in + let hours, minutes = minutes / 60, minutes mod 60 in + + let dummy_cst cst = + { expr_loc = (Lexing.dummy_pos, Lexing.dummy_pos); + expr_node = CONSTANT cst; + } + and simple_pp_htbl ppf htbl = + Hashtbl.iter (fun k v -> Format.fprintf ppf "%s: %d@ " k v) htbl in + (* Halstead metrics' bugs delivered statistics is said to be underapproximated + for C. Hence the "lower bound" commentary on the output next to "bugs + delivered". + *) + Format.fprintf ppf + "@[\ + Halstead metrics@ \ + ----------------@ \ + Distinct operators: %d@ \ + Total operators: %d@ \ + Distinct operands: %d@ \ + Total operands: %d@ \ + Program length: %d@ \ + Vocabulary size: %d@ \ + Program volume: %.2f@ \ + Difficulty level: %.2f@ \ + Program level: %.2f@ \ + Effort to implement: %.2f@ \ + Time to implement (s): %.2f (%dh %dmin)@ \ + Bugs delivered (lower bound): %.2f@ @ \ + \ + Global statistics (Halstead)@ \ + ----------------------------@ \ + @[** Operators@ \ + %a%a%a%a@]@ \ + @[** Operands @ \ + %a%a@]@ \ + @]" + (int_of_float distinct_operators) + (int_of_float total_operators) + (int_of_float distinct_operands) + (int_of_float total_operands) + (int_of_float program_length) + (int_of_float vocabulary_size) + program_volume difficulty_level + program_level effort_to_implement time_to_implement + hours minutes + bugs_delivered + (* Operators table *) + simple_pp_htbl operator_tbl.reserved_tbl + simple_pp_htbl operator_tbl.otherop_tbl + simple_pp_htbl operator_tbl.knownop_tbl + (fun ppf htbl -> + Hashtbl.iter + (fun k v -> + Format.fprintf ppf "%a: %d@ " Cprint.print_type_spec k v) htbl) + operator_tbl.tspec_tbl + simple_pp_htbl operand_tbl.var_tbl + (fun ppf htbl -> + Hashtbl.iter + (fun k v -> + Format.fprintf ppf "%a: %d@ " Cprint.print_expression (dummy_cst k) v) + htbl) + operand_tbl.cst_tbl; +;; + +let compute_metrics () = + (* Run the visitor on all files *) + let cabs_files = Ast.UntypedFiles.get () in + let cabs_visitor = new halsteadCabsVisitor in + List.iter (fun file -> + ignore (Cabsvisit.visitCabsFile (cabs_visitor:>Cabsvisit.cabsVisitor) file)) + cabs_files + ; + Metrics.result "%a" pp_metrics cabs_visitor; +;; +end + +let compute_on_cabs () = + try + let cabs_files = Ast.UntypedFiles.get () in + let cabs_visitor = new metricsCabsVisitor in + List.iter (fun file -> + Metrics.debug ~level:2 "Compute Cabs metrics for file %s@." (fst file); + ignore (Cabsvisit.visitCabsFile (cabs_visitor:>Cabsvisit.cabsVisitor) file); + ) + cabs_files + ; + if Metrics_parameters.ByFunction.get () then + Metrics.result "@[Cabs:@ %a@]" cabs_visitor#pp_detailed_text_metrics (); + Halstead.compute_metrics (); + with + | Ast.NoUntypedAst -> + Metrics.warning + "@[ Project has no untyped AST. Only metrics over normalized CIL \ + AST are available. \ + @]@." + ;; diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_cabs.mli frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cabs.mli --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_cabs.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cabs.mli 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Metrics computing on Cabs + + Syntactic metrics usually makes more sense on Cabs as they + reference the original program. + + However, one loses CIL facilities for this purpose. Thus, working + on Cabs is less developer-friendly. +*) + + +(** Main entry point to compute various metrics on Cabs AST + instead of CIL AST. +*) +val compute_on_cabs: unit -> unit;; diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_cilast.ml frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cilast.ml --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_cilast.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cilast.ml 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,480 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_datatype +open Cil_types +open Db.Metrics +open Metrics_base +open Metrics_parameters +;; + + +(** Syntactic metrics + ================= + The goal is to collect various (syntactic) information about the source code + (slocs, assignments, loops, ...). + From those one can compute McCabe's cyclomatic complexity. +*) +class type sloc_visitor = object + inherit Visitor.generic_frama_c_visitor + + (* Get the number of times a function has been called if it has been + defined (fundef) or not (fundecl). + *) + method fundecl_calls: int Metrics_base.VInfoMap.t + method fundef_calls: int Metrics_base.VInfoMap.t + + (* Get the computed metris *) + method get_metrics: Metrics_base.my_metrics + + (* Print the metrics of a file [string] to a formatter + Yields a fatal error if the file does not exist (or has no metrics). + *) + method pp_file_metrics: Format.formatter -> string -> unit + + method pp_detailed_text_metrics: Format.formatter -> unit + (** Print results of all file and functions to the given formatter as text *) + + method print_stats: Format.formatter -> unit + (** Print computed metrics to a formatter *) +end + +(* Various metrics computing visitor on Cil AST. + These metrics are a necessary step to compute cyclomatic complexity. +*) +class slocVisitor : sloc_visitor = object(self) + inherit Visitor.frama_c_inplace + + (* Global metrics store for this Cil AST *) + val global_metrics = ref empty_metrics + (* Local metrics in computation *) + val local_metrics = ref empty_metrics + + (* Local metrics are kept stored after computation in this map of maps. + Its storing hierachy is as follows: filename -> function_name -> metrics + *) + val mutable metrics_map: + (my_metrics Datatype.String.Map.t) Datatype.String.Map.t = + Datatype.String.Map.empty + + val fundecl_calls: int VInfoMap.t ref = ref VInfoMap.empty; + val fundef_calls: int VInfoMap.t ref = ref VInfoMap.empty; + + (* Getters/setters *) + method fundecl_calls = !fundecl_calls + method fundef_calls = !fundef_calls + method get_metrics = !global_metrics + + method private update_metrics_map filename strmap = + metrics_map <- Datatype.String.Map.add filename strmap metrics_map + + (* Utility methods to increase metrics counts *) + method private incr_slocs metrics = + metrics := {!metrics with cslocs = succ !metrics.cslocs;} + + method private incr_assigns metrics = + metrics := {!metrics with cassigns = succ !metrics.cassigns;} + + method private incr_calls metrics = + metrics := {!metrics with ccalls = succ !metrics.ccalls;} + + method private incr_exits metrics = + metrics := {!metrics with cexits = succ !metrics.cexits;} + + method private incr_funcs metrics = + metrics := {!metrics with cfuncs = succ !metrics.cfuncs;} + + method private incr_gotos metrics = + metrics := {!metrics with cgotos = succ !metrics.cgotos;} + + method private incr_ifs metrics = + metrics := {!metrics with cifs = succ !metrics.cifs;} + + method private incr_loops metrics = + metrics := {!metrics with cloops = succ !metrics.cloops;} + + method private incr_ptrs metrics = + metrics := {!metrics with cptrs = succ !metrics.cptrs;} + + method private incr_dpoints metrics = + metrics := {!metrics with cdecision_points = succ !metrics.cdecision_points;} + + method private incr_both_metrics f = + f global_metrics; + f local_metrics + + method private add_map map vinfo value = + map := VInfoMap.add vinfo value !map + + method private stats_of_filename filename = + try Datatype.String.Map.find filename metrics_map + with + | Not_found -> + Metrics.fatal "Metrics for file %s not_found@." filename + + method pp_file_metrics fmt filename = + Format.fprintf fmt "@[%a@]" + (fun fmt filename -> + let fun_tbl = self#stats_of_filename filename in + Datatype.String.Map.iter (fun _fun_name fmetrics -> + Format.fprintf fmt "@ %a" pp_my_metrics fmetrics) + fun_tbl; + ) filename + + method pp_detailed_text_metrics fmt = + Datatype.String.Map.iter + (fun filename _func_tbl -> + Format.fprintf fmt "%a" self#pp_file_metrics filename) metrics_map + + method print_stats fmt = + Format.pp_set_formatter_tag_functions fmt Metrics_base.html_tag_functions; + Format.pp_set_tags fmt true; + let pr_hdr fmt hdr_name = + Format.fprintf fmt "@{%s@}" hdr_name in + Datatype.String.Map.iter + (fun filename func_tbl -> + Metrics.result ~level:2 "%a" self#pp_file_metrics filename; + if func_tbl <> Datatype.String.Map.empty then + begin + Format.fprintf fmt + "@[@{

    %s@}
    @ \ + @{\ + @[@ \ + @[@{@ \ + @{@[@ \ + %a@ %a@ %a@ %a@ %a@ %a@ %a@ %a@ %a@ @]@}@ \ + %a@ \ + @}@]@]@ @} \ + @]@ " + filename + pr_hdr "Function" pr_hdr "#If stmts" pr_hdr "#Assignments" + pr_hdr "#Loops" pr_hdr "#Calls" pr_hdr "#Gotos" + pr_hdr "#Pointer dereferencing" pr_hdr "#Exits" + pr_hdr "Cyclomatic value" + (fun fmt fun_tbl -> + Datatype.String.Map.iter + (fun _funcname func_metrics -> + Format.fprintf fmt "%a" pp_metrics_as_html_row func_metrics; + ) fun_tbl + ) func_tbl; + end + else Metrics.warning "Filename <%s> has no functions@." filename + ) metrics_map; + +(* Save the local metrics currently computed. + Clears it before starting a new metrics computation (e.g. when entering a new + function definition. + Global metrics are never reset as they define metrics on the whole Cil.file. +*) + method private record_and_clear_function_metrics metrics = + let filename = metrics.cfile_name + and funcname = metrics.cfunc_name in + (try + let fun_tbl = Datatype.String.Map.find filename metrics_map in + self#update_metrics_map filename + (Datatype.String.Map.add funcname !local_metrics fun_tbl); + with + | Not_found -> + let new_stringmap = + Datatype.String.Map.add funcname !local_metrics Datatype.String.Map.empty in + self#update_metrics_map filename new_stringmap; + ); + local_metrics := empty_metrics; + + method vvdec vi = + if Cil.isFunctionType vi.vtype && consider_function vi then begin + (* If this function is only declared, and has never been seen before, + we place it into the no_source table. Defined functions are dealt + with in vfunc method *) + if not (self#is_defined_function vi) && + not (VInfoMap.mem vi !fundecl_calls) + then + self#add_map fundecl_calls vi 0; + + end; + Cil.SkipChildren + + method vfunc fdec = + if consider_function fdec.svar then + begin + (* Here, we get to a fundec definition.this function has a body, + let's put it to the "function with source" table. *) + local_metrics := + {!local_metrics with + cfile_name = file_of_fundef fdec; + cfunc_name = fdec.svar.vname; + cfuncs = 1; (* Only one function is indeed being defined here *)}; + self#incr_funcs global_metrics; + let fvinfo = fdec.svar in + (if not (VInfoMap.mem fvinfo !fundef_calls) then + (* Never seen before, including never been called *) + self#add_map fundef_calls fvinfo 0); + (* On return record the analysis of the function. *) + Cil.ChangeDoChildrenPost + (fdec, + fun _ -> + begin + if !local_metrics <> empty_metrics + then self#record_and_clear_function_metrics !local_metrics; + fdec; + end + ); + end + else Cil.SkipChildren + + method vlval (host, _) = + begin + match host with + | Mem _ -> self#incr_both_metrics (self#incr_ptrs); + | _ -> () + end; + Cil.DoChildren + + method vstmt s = + self#incr_both_metrics (self#incr_slocs); + begin + match s.skind with + | If _ -> + (self#incr_both_metrics (self#incr_ifs); + self#incr_both_metrics (self#incr_dpoints);) + | Loop _ -> self#incr_both_metrics (self#incr_loops); + | Goto _ -> self#incr_both_metrics (self#incr_gotos); + | Return _ -> self#incr_both_metrics (self#incr_exits); + | Switch (_, _, _slist, _) -> () + (* The catching block is one more possible flow alternative *) + | TryFinally _ + | TryExcept _ -> self#incr_both_metrics (self#incr_dpoints); + | _ -> () + end; + (* Default cases are not path choice points, as normal labels. + Non-default cases are ... just like if statements. + *) + let rec has_case_label labels = + match labels with + | (Case _) :: _-> + self#incr_both_metrics (self#incr_dpoints); + | _ :: labels -> has_case_label labels + | [] -> () + in has_case_label s.labels; + Cil.DoChildren + + method vexpr e = + begin + (* Logical ands and ors are lazy and generate two different paths *) + match e.enode with + | BinOp ((LAnd | LOr), _, _, _) -> + self#incr_both_metrics (self#incr_dpoints); + | _ -> () + end; + Cil.DoChildren + + method private is_defined_function (v:varinfo) = + try + let kf = Globals.Functions.get v in + Kernel_function.is_definition kf + with + | Not_found -> Metrics.abort "Function %s not found in the ast" v.vname + + method private image (glob:global) = + (* extract just the name of the global , for printing purposes *) + match glob with + | GVar (v, _, _) -> v.vname ^ " (GVar) " + | GVarDecl (_, v, _) -> v.vname ^ " (GVarDecl) " + | GFun (fdec, _) -> fdec.svar.vname ^ " (GFun) " + | GType (ty, _) -> ty.tname + | GCompTag (ci, _) | GCompTagDecl (ci, _) -> ci.cname + | GEnumTagDecl (ei, _) | GEnumTag (ei, _) -> ei.ename + | GAsm (_, _) | GPragma _ | GText _ -> "" + | GAnnot (an,_) -> + begin + match an with + | Dfun_or_pred (li, _) -> li.l_var_info.lv_name + | Dvolatile (_, _, _, _) -> " (Volatile) " + | Daxiomatic (s, _, _) -> s + | Dtype (lti, _) -> lti.lt_name + | Dlemma (ln, _, _, _, _, _) -> ln + | Dinvariant (toto, _) -> toto.l_var_info.lv_name + | Dtype_annot (ta, _) -> ta.l_var_info.lv_name + | Dmodel_annot (ta, _) -> ta.l_var_info.lv_name + end + + method private images (globs:global list) = + (* extract just the names of the globals, for printing purposes *) + let les_images = List.map self#image globs in + String.concat "," les_images + + method vinst i = + begin match i with + | Call(_, e, _, _) -> + self#incr_both_metrics (self#incr_calls); + (match e.enode with + | Lval(Var vinfo, NoOffset) -> + if consider_function vinfo then + begin + let update_call_map funcmap = + self#add_map funcmap vinfo + (1 + try VInfoMap.find vinfo !funcmap with Not_found-> 0) + in + if self#is_defined_function vinfo + then update_call_map fundef_calls + else update_call_map fundecl_calls + end + | _ -> ()); + | Set _ -> + self#incr_both_metrics (self#incr_assigns); + | _ -> () + end; + Cil.DoChildren + +end +;; + +let dump_html fmt cil_visitor = + (* Activate tagging for html *) + Format.pp_set_formatter_tag_functions fmt html_tag_functions; + Format.pp_set_tags fmt true; + + let pr_row s fmt n = + Format.fprintf fmt + "@{@[@ \ + @{
    %s@}@ \ + @{%d@}@]@ @} " s n + in + let pr_stats fmt visitor = + let metrics = visitor#get_metrics in + Format.fprintf fmt "@[@{%a@}@]" + (fun fmt metrics -> + List.iter2 (fun text value -> pr_row text fmt value) + ["SLOC"; "Number of if statements"; "Number of assignments"; + "Number of loops"; "Number of calls"; "Number of gotos"; + "Number of pointer accesses";] + [metrics.cslocs; metrics.cifs; metrics.cassigns; + metrics.cloops; metrics.ccalls; metrics.cgotos; + metrics.cptrs;]) metrics + in + let pr_prelude fmt cil_visitor = + Format.fprintf fmt "@[\ + @{
    @ \ + @{

    @{Metrics@}@}@ \ + @{

    Synthetic results@}@
    @ \ + @{Defined function(s)@} (%d):
    @ \ + @[  %a@]@
    @
    @ \ + @{Undefined function(s)@} (%d):@
    @ \ + @[  %a@]@
    @
    @ \ + @{Potential entry point(s)@} (%d):@
    @ \ + @[  %a@]@
    @
    @ \ + @}@]" + (VInfoMap.map_cardinal cil_visitor#fundef_calls) + (Metrics_base.pretty_set VInfoMap.iter) cil_visitor#fundef_calls + (VInfoMap.map_cardinal cil_visitor#fundecl_calls) + (Metrics_base.pretty_set VInfoMap.iter) cil_visitor#fundecl_calls + (Metrics_base.number_entry_points VInfoMap.fold + cil_visitor#fundef_calls) + (Metrics_base.pretty_entry_points VInfoMap.iter) + cil_visitor#fundef_calls + in + let pr_detailed_results fmt cil_visitor = + Format.fprintf fmt "@[\ + @{
    \ + @[@ \ + @{

    Detailed results@}@ \ + @[%a@ @]\ + @]@}" + (fun fmt cil_visitor -> cil_visitor#print_stats fmt) cil_visitor + in + Format.fprintf fmt "@[\ + @ \ + @{@ \ + @{@ \ + @{%s@}@ \ + <meta content=\"text/html; charset=iso-8859-1\" \ + http-equiv=\"Content-Type\"/>@ \ + @{<style type=\"text/css\">%s@}@ \ + @}@ \ + @{<body>\ + @[<v 2>@ \ + %a@ \ + %a@ \ + %a@ \ + @]@}@}@]@?" + "Metrics" + Css_html.css + pr_prelude cil_visitor + pr_stats cil_visitor + pr_detailed_results cil_visitor; +;; + +let metrics_to_result (cil_visitor : slocVisitor) = + let metrics = cil_visitor#get_metrics in + { call_statements = metrics.ccalls; + goto_statements = metrics.cgotos; + assign_statements = metrics.cassigns; + if_statements = metrics.cifs; + mem_access = metrics.cptrs; + loop_statements = metrics.cloops; + function_definitions = metrics.cfuncs; + sloc = metrics.cslocs; + functions_without_source = + VInfoMap.to_varinfo_map cil_visitor#fundecl_calls; + functions_with_source = + VInfoMap.to_varinfo_map cil_visitor#fundef_calls; + cyclos = Metrics_base.cyclo metrics + }; +;; + +let compute_on_cilast () = + let file = Ast.get () in + (* Do as before *) + let cil_visitor = new slocVisitor in + Visitor.visitFramacFileSameGlobals + (cil_visitor:>Visitor.frama_c_visitor) file; + if Metrics_parameters.ByFunction.get () then + Metrics.result "@[<v 0>Cil AST@ %t@]" cil_visitor#pp_detailed_text_metrics; + let r = metrics_to_result cil_visitor in + (* Print the result to file if required *) + let out_fname = OutputFile.get () in + begin + if out_fname <> "" then + try + let oc = open_out_bin out_fname in + let fmt = Format.formatter_of_out_channel oc in + (match Metrics_base.get_file_type out_fname with + | Html -> dump_html fmt cil_visitor + | Text -> + Format.fprintf fmt "@[<v 0>%t@ %a@]" + cil_visitor#pp_detailed_text_metrics + Metrics_base.pretty r + ); + close_out oc; + with Sys_error _ -> + Metrics.failure "Cannot open file %s.@." out_fname + end; + r + +;; + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_cilast.mli frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cilast.mli --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_cilast.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_cilast.mli 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Visitor to compute various syntactic metrics. + In particular, it fetches all necessary informations to compute + cyclomatic complexity . +*) +class type sloc_visitor = object + inherit Visitor.generic_frama_c_visitor + + (* Get the number of times a function has been called if it has been + defined (fundef) or not (fundecl). + *) + method fundecl_calls: int Metrics_base.VInfoMap.t + method fundef_calls: int Metrics_base.VInfoMap.t + + (* Get the computed metris *) + method get_metrics: Metrics_base.my_metrics + + (* Print the metrics of a file [string] to a formatter + Yields a fatal error if the file does not exist (or has no metrics). + *) + method pp_file_metrics: Format.formatter -> string -> unit + + method pp_detailed_text_metrics: Format.formatter -> unit + (** Print results of all file and functions to the given formatter as text *) + + method print_stats: Format.formatter -> unit +(** Print computed metrics to a formatter *) +end + +class slocVisitor: sloc_visitor + +(** Compute metrics on whole CIL AST *) +val compute_on_cilast: unit -> Db.Metrics.t;; diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_coverage.ml frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_coverage.ml --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_coverage.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_coverage.ml 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,322 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + + +class coverageAuxVisitor prj = object(self) + inherit Visitor.generic_frama_c_visitor prj (Cil.inplace_visit ()) + + (* Visit the body and the spec of a function *) + method private visit_function vi = + if Metrics_base.consider_function vi then + let kf = Globals.Functions.get vi in + let self = (self :> Visitor.frama_c_visitor) in + (* Visit the spec. There might be references to function pointers in + the assigns *) + let spec = Kernel_function.get_spec ~populate:false kf in + ignore (Visitor.visitFramacFunspec self spec); + (try + (* Visit the body if we have one *) + let fundec = Kernel_function.get_definition kf in + ignore (Visitor.visitFramacFunction self fundec); + with Kernel_function.No_Definition -> ()) + + (* Visit the initializer of the given var, if it exists, and returns it *) + method private visit_non_function_var vi = + try + (* Visit the initializer if there is one *) + let init = Globals.Vars.find vi in + match init with + | { init = None } -> None + | { init = Some init } -> + ignore (Visitor.visitFramacInit (self:>Visitor.frama_c_visitor) + vi NoOffset init); + Some init + with Not_found -> (* not a global *) None + +end + +(* Reachability metrics: from a given compute a conservative estimation + of the functions that can be transitively called *) +class callableFunctionsVisitor prj = object(self) + inherit coverageAuxVisitor prj as super + + (* Functions reachable syntactically *) + val mutable callable = Varinfo.Set.empty + + (* All globals initializers visited *) + val mutable initializers = [] + method initializers = initializers + + (* All varinfos visited so far. Used to avoid looping *) + val visited = Varinfo.Hashtbl.create 17 + (* Varinfos remaining to visit *) + val todo = Stack.create () + + method already_seen vi = + Varinfo.Hashtbl.mem visited vi + + (* Each time we see a variable, mark it as to be visited. If it is a function, + consider it is called *) + method vvrbl vi = + if not (self#already_seen vi) then begin + if Cil.isFunctionType vi.vtype then + callable <- Varinfo.Set.add vi callable; + Stack.push vi todo; + end; + Cil.SkipChildren (* no children anyway *) + + method visit_non_function_var vi = + let r = super#visit_non_function_var vi in + (match r with + | None -> () + | Some init -> initializers <- (vi, init) :: initializers + ); + r + + method compute vi = + (* Initialisation *) + Stack.clear todo; + Stack.push vi todo; + Varinfo.Hashtbl.clear visited; + callable <- Varinfo.Set.singleton vi; + (* Reach fixpoint *) + while not (Stack.is_empty todo) do + let vi = Stack.pop todo in + if not (self#already_seen vi) then + begin + Metrics_parameters.Metrics.debug "Coverage: visiting %s" vi.vname; + Varinfo.Hashtbl.add visited vi (); + if Cil.isFunctionType vi.vtype + then self#visit_function vi + else ignore (self#visit_non_function_var vi) + end; + done; + callable + +end + +class deadCallsVisitor fmt ~syntactic ~semantic initializers prj = + let unseen = Varinfo.Set.diff syntactic semantic in +object(self) + inherit coverageAuxVisitor prj + + val mutable current_initializer = None + + (* When an unseen function is reachable by the body of a function reached, + or inside an initializer, display the information *) + method private reached_vi vi = + if Metrics_base.consider_function vi && Varinfo.Set.mem vi unseen then + match self#current_kf with + | None -> + (match current_initializer with + | None -> assert false + | Some vinit -> + Format.fprintf fmt + "@[<h>Initializer of %s references %s (at %a)@]@ " + vinit.vname vi.vname Location.pretty vi.vdecl + ) + | Some f -> + if Varinfo.Set.mem (Kernel_function.get_vi f) semantic then + let mess = + match self#current_stmt with + | Some {skind = Instr (Call (_, {enode = Lval (Var v, _)}, _, _))} + when Varinfo.equal v vi -> "calls" + | _ -> "references" + in + Format.fprintf fmt + "@[<h>Function %a %s %s (at %a)@]@ " + Kernel_function.pretty f mess vi.vname + Location.pretty (Cil.CurrentLoc.get ()) + + method vvrbl vi = + if Cil.isFunctionType vi.vtype then self#reached_vi vi; + Cil.SkipChildren (* no children anyway *) + + + method compute_and_print = + if not (Varinfo.Set.is_empty unseen) || initializers <> [] then begin + Format.fprintf fmt "@[<v>References to non analyzed functions@ \ + ------------------------------------@ "; + Varinfo.Set.iter self#visit_function semantic; + List.iter (fun (vinit, init) -> + current_initializer <- Some vinit; + ignore (Visitor.visitFramacInit + (self:>Visitor.frama_c_visitor) + vinit NoOffset init); + current_initializer <- None; + ) initializers; + Format.fprintf fmt "@]" + end + +end + +class coverageByFun prj = object + inherit Visitor.generic_frama_c_visitor prj (Cil.inplace_visit ()) + + val mutable total = 0 + val mutable value = 0 + + method vstmt s = + total <- total + 1; + if Db.Value.is_reachable_stmt s then value <- value + 1; + Cil.DoChildren + + method result = (total, value) +end + +let compute_coverage_by_fun semantic = + let one_fun vi acc = + try + let kf = Globals.Functions.get vi in + let dec = Kernel_function.get_definition kf in + let vis = new coverageByFun (Project.current ()) in + ignore (Visitor.visitFramacFunction (vis :> Visitor.frama_c_visitor) dec); + let (total, value) = vis#result in + let percent = (float_of_int value) /. (float_of_int total) *. 100. in + (kf, total, value, percent) :: acc + with Kernel_function.No_Definition -> acc + in + let res = Varinfo.Set.fold one_fun semantic [] in + List.sort (fun (_, _, _, p1) (_, _, _, p2) -> compare p2 p1) res + + +let pp_unreached_calls fmt ~syntactic ~semantic initializers = + let v = new deadCallsVisitor fmt ~syntactic ~semantic initializers + (Project.current ()) in + v#compute_and_print + +let compute_syntactic kf = + let vis = new callableFunctionsVisitor (Project.current ()) in + let res = vis#compute (Kernel_function.get_vi kf) in + res, vis#initializers + +let compute_semantic () = + assert (Db.Value.is_computed ()); + let res = ref Varinfo.Set.empty in + (* Just iter on all the functions and consult the appropriate table *) + Globals.Functions.iter + (fun kf -> + if !Db.Value.is_called kf then + res := Varinfo.Set.add (Kernel_function.get_vi kf) !res + ); + !res + + +let pp_fun_set_by_file fmt set = + let add_binding map filename fvinfo = + let set = + try + let x = Datatype.String.Map.find filename map in + Varinfo.Set.add fvinfo x + with Not_found -> Varinfo.Set.add fvinfo Varinfo.Set.empty + in Datatype.String.Map.add filename set map + in + let map = + Varinfo.Set.fold + (fun fvinfo acc -> + if Metrics_base.consider_function fvinfo then + let fname = Metrics_base.file_of_vinfodef fvinfo in + add_binding acc fname fvinfo + else acc + ) set Datatype.String.Map.empty + in + Format.fprintf fmt "@[<v 0>"; + Datatype.String.Map.iter + (fun fname fvinfoset -> + Format.fprintf fmt "@[<hov 2><%s>:@ %a@]@ " fname + (fun fmt vinfoset -> + Varinfo.Set.iter + (fun vinfo -> + Format.fprintf fmt "%a;@ " !Ast_printer.d_var vinfo) + vinfoset) + fvinfoset + ) map; + Format.fprintf fmt "@]" +;; + +let pp_value_coverage () = + assert (Db.Value.is_computed ()); + let semantic = compute_semantic () in + let main = fst (Globals.entry_point ()) in + let syntactic, initializers = compute_syntactic main in + let unseen = Varinfo.Set.diff syntactic semantic in + let unseen_num = Varinfo.Set.cardinal unseen in + let nsyn = Varinfo.Set.cardinal syntactic + and nsem = Varinfo.Set.cardinal semantic in + let percent = (float_of_int nsem) /. (float_of_int nsyn) *. 100.0 in + (fun fmt -> + Format.fprintf fmt "@[<v 0>\ + Value coverage statistics@ \ + -------------------------@ \ + Syntactically reachable functions = %d@ \ + Semantically reached functions = %d@ \ + Coverage estimation = %.1f%% @ " + nsyn nsem percent; + if unseen_num > 0 then + Format.fprintf fmt "@ @[<v 2>Unseen functions (%d) =@ %a@]" + unseen_num pp_fun_set_by_file unseen; + Format.fprintf fmt "@]" + ), + (fun fmt -> + pp_unreached_calls fmt ~syntactic ~semantic initializers) +;; + +let pp_reached_from_function fmt kf = + let syntactic, _ = compute_syntactic kf in + let title = Pretty_utils.sfprintf "%a: %d" + Kernel_function.pretty kf (Varinfo.Set.cardinal syntactic) + in + Format.fprintf fmt "@[<v 0>\ + Functions syntactically reachable from %s@ \ + ---------------------------------------%s@ \ + %a@]" title (String.make (String.length title) '-') + pp_fun_set_by_file syntactic + +let pp_stmts_reached_by_function fmt = + let semantic = compute_semantic () in + let l = compute_coverage_by_fun semantic in + let sum_total, sum_value = List.fold_left + (fun (at, av) (_, t, v, _) -> at+t, av+v) (0, 0) l in + let percent = 100. *. (float_of_int sum_value) /. (float_of_int sum_total) in + Format.fprintf fmt "@[<v 0>\ + Statements analyzed by Value@ \ + ----------------------------@ \ + %d stmts in analyzed functions, %d stmts analyzed (%.1f%%)@ " + sum_total sum_value percent; + List.iter (fun (kf, total, _, percent) -> + Format.fprintf fmt "%a: %.1f%% (%d stmts)@ " + Kernel_function.pretty kf percent total + ) l; + Format.fprintf fmt "@]" + + +(* Reexport a simpler function *) +let compute_syntactic kf = fst (compute_syntactic kf) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_coverage.mli frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_coverage.mli --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_coverage.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_coverage.mli 2011-10-10 08:38:28.000000000 +0000 @@ -0,0 +1,44 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val compute_syntactic: Kernel_function.t -> Cil_datatype.Varinfo.Set.t +(** List of functions that can be syntactically reached from the function *) + +val compute_semantic: unit -> Cil_datatype.Varinfo.Set.t +(** Functions analyzed by the value analysis *) + +val pp_reached_from_function: Format.formatter -> Kernel_function.t -> unit +(** Pretty-print the functions that can be syntactically reached from the + parameter *) + +val pp_value_coverage: + unit -> (Format.formatter -> unit) * (Format.formatter -> unit) +(** Return two fonctions that pretty-print the coverage reached by the value + analysis wrt. the functions syntactically reachable from main *) + +val pp_stmts_reached_by_function: Format.formatter -> unit + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_parameters.ml frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_parameters.ml --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_parameters.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_parameters.ml 2011-10-10 08:38:28.000000000 +0000 @@ -20,34 +20,73 @@ (* *) (**************************************************************************) -include Plugin.Register +module Metrics = Plugin.Register (struct let name = "metrics" let shortname = "metrics" let help = "syntactic metrics" end) -module Print = - False +let plugin_name = "Metrics";; + +module Enabled = + Metrics.WithOutput (struct - let option_name = "-metrics" - let help = " print some metrics on stdout" - let kind = `Tuning + let option_name = "-metrics" + let help = "activate metrics computation" + let output_by_default = true end) -module Dump = - EmptyString +module ByFunction = + Metrics.False (struct - let option_name = "-metrics-dump" - let arg_name = "" - let help = "print some metrics into the specified file" - let kind = `Tuning + let option_name = "-metrics-by-function" + let help = "also compute metrics on a per-function basis" + let output_by_default = true end) -let is_on () = Print.get () || not (Dump.is_default ()) +module OutputFile = + Metrics.EmptyString + (struct + let option_name = "-metrics-output" + let arg_name = "filename" + let help = "print some metrics into the specified file; \ + the output format is recognized through the extension." + end) + +module ValueCoverage = + Metrics.WithOutput ( + struct + let option_name = "-metrics-value-cover" + let help = "estimate value analysis coverage w.r.t. \ + to reachable syntactic definitions" + let output_by_default = true + end) + +module AST_type = + Metrics.String + (struct + let option_name = "-metrics-ast" + let arg_name = "[cabs | cil]" + let help = "apply metrics to Cabs or CIL AST." + let default = "cil" + end + ) + +let () = AST_type.set_possible_values ["cil"; "cabs"] + +module SyntacticallyReachable = + Metrics.StringSet + (struct + let option_name = "-metrics-cover" + let arg_name = "f1,..,fn" + let help = "compute an overapproximation of the functions reachable from \ + f1,..,fn." + end + ) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/metrics_parameters.mli frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_parameters.mli --- frama-c-20110201+carbon+dfsg/src/metrics/metrics_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/metrics_parameters.mli 2011-10-10 08:38:28.000000000 +0000 @@ -20,21 +20,34 @@ (* *) (**************************************************************************) -open Plugin +module Metrics: Plugin.S -(** Pretty print metrics on stdout *) -module Print: BOOL +module Enabled: Plugin.WithOutput +(** Activate metrics *) -(** Pretty print metrics on the given file *) -module Dump: STRING +module ByFunction: Plugin.Bool +(** Activate metrics by function *) -(** Have metrics to be computed? *) -val is_on: unit -> bool +module ValueCoverage: Plugin.WithOutput +(** Give an estimation about value analysis code penetration. + Only works on CIL AST. *) + +module AST_type: Plugin.String +(** Set the ASTs on which the metrics should be computetd *) + +module OutputFile: Plugin.String +(** Pretty print metrics to the given file. + The output format will be recognized through the extension. + Supported extensions are: + "html" or "htm" for HTML + "txt" or "text" for text +*) -include Log.Messages +module SyntacticallyReachable: Plugin.String_set +(** List of functions for which we compute the functions they may call *) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/register_gui.ml frama-c-20111001+nitrogen+dfsg/src/metrics/register_gui.ml --- frama-c-20110201+carbon+dfsg/src/metrics/register_gui.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/register_gui.ml 2011-10-10 08:38:28.000000000 +0000 @@ -20,49 +20,38 @@ (* *) (**************************************************************************) -(* ABP added *) open Cil_types open Visitor open Pretty_source open Kernel_function +open Metrics_base +;; -class cyclo_class (main_ui:Design.main_window_extension_points) = -object(self) +class cyclo_class (main_ui:Design.main_window_extension_points) = object(self) val mutable fct_to_check = (GText "") method get_data = - let checker = (new Register.slocVisitor) in - checker#set_standalone false; - Metrics_parameters.debug "beginning of cyclo check"; - ignore (visitFramacGlobal - (checker :> frama_c_visitor) - fct_to_check); - checker#sloc, - checker#ifs, - checker#assigns, - checker#loops, - checker#calls, - checker#gotos, - checker#mem_access, - (checker#ifs + checker#loops) - checker#exits + 2 + let checker = (new Metrics_cilast.slocVisitor) in + Metrics_parameters.Metrics.debug ~level:2 "Beginning of cyclo check@."; + ignore (visitFramacGlobal (checker :> frama_c_visitor) fct_to_check); + checker#get_metrics (* 2 becomes "2*checker#funcs" in the general case *) method insert_text (buffer: GText.buffer) = let iter = buffer#get_iter `START in - let data = self#get_data in - let (slocs,ifs,assigns,loops,calls, gotos, mems,cyclos) = data in - buffer#insert ~iter (string_of_int slocs); - buffer#insert ~iter (string_of_int ifs); - buffer#insert ~iter (string_of_int assigns); - buffer#insert ~iter (string_of_int loops); - buffer#insert ~iter (string_of_int calls); - buffer#insert ~iter (string_of_int gotos); - buffer#insert ~iter (string_of_int mems); - buffer#insert ~iter (string_of_int cyclos) + let metrics_data = self#get_data in + buffer#insert ~iter (string_of_int metrics_data.cslocs); + buffer#insert ~iter (string_of_int metrics_data.cifs); + buffer#insert ~iter (string_of_int metrics_data.cassigns); + buffer#insert ~iter (string_of_int metrics_data.cloops); + buffer#insert ~iter (string_of_int metrics_data.ccalls); + buffer#insert ~iter (string_of_int metrics_data.cgotos); + buffer#insert ~iter (string_of_int metrics_data.cptrs); + buffer#insert ~iter (string_of_int (cyclo metrics_data)) method do_cyclo (main_ui:Design.main_window_extension_points) = - Metrics_parameters.debug "Cyclo"; + Metrics_parameters.Metrics.debug "Cyclo"; (* create a small results window *) let dialog = GWindow.window ~title:"Measure" @@ -75,22 +64,21 @@ dialog#set_transient_for main_ui#main_window#as_window; let a_vbox = GPack.vbox ~packing:dialog#add () in ignore (dialog#event#connect#delete - ~callback:(fun _ -> dialog#misc#hide (); - true)); - let data = self#get_data in - let (slocs, ifs, assigns, loops, calls, gotos, mems, cyclos) = data in + ~callback:(fun _ -> dialog#misc#hide (); + true)); + let metrics_data = self#get_data in let add_label msg n = let text = msg ^ string_of_int n in ignore (GMisc.label ~text ~packing:a_vbox#add ()) in - add_label "Lines of source code: " slocs; - add_label "# of if statements: " ifs; - add_label "# of assignments: " assigns; - add_label "# of loops: " loops; - add_label "# of function calls: " calls; - add_label "# of gotos: " gotos; - add_label "# of indirect memory accesses: " mems; - add_label "Cyclomatic complexity: " cyclos; + add_label "Lines of source code: " metrics_data.cslocs; + add_label "# of if statements: " metrics_data.cifs; + add_label "# of assignments: " metrics_data.cassigns; + add_label "# of loops: " metrics_data.cloops; + add_label "# of function calls: " metrics_data.ccalls; + add_label "# of gotos: " metrics_data.cgotos; + add_label "# of indirect memory accesses: " metrics_data.cptrs; + add_label "Cyclomatic complexity: " (cyclo metrics_data); let close_button = GButton.button ~stock:`OK ~packing:a_vbox#add () in close_button#set_border_width 10; ignore (close_button#connect#clicked ~callback:dialog#misc#hide); @@ -100,53 +88,60 @@ method display_localizable localizable () = begin match localizable with - | PVDecl (Some kf,_) -> (* Process only the function selected *) - begin - (* Get the global of this function *) - fct_to_check <- (get_global kf); - self#do_cyclo main_ui; - end - | _ -> () + | PVDecl (Some kf,_) -> (* Process only the function selected *) + begin + (* Get the global of this function *) + fct_to_check <- (get_global kf); + self#do_cyclo main_ui; + end + | _ -> () end method cyclo_selector (popup_factory:GMenu.menu GMenu.factory) _main_ui ~button localizable = - Metrics_parameters.debug "cyclo_selector"; + Metrics_parameters.Metrics.debug "cyclo_selector"; if button = 3 then match localizable with - | PVDecl (Some _, _) -> - let callback () = - Metrics_parameters.debug "cyclo_selector - callback"; + | PVDecl (Some _, _) -> + let callback () = + Metrics_parameters.Metrics.debug "cyclo_selector - callback"; self#display_localizable localizable () - in - ignore (popup_factory#add_item "Metrics" ~callback:callback) - | _ -> () + in + ignore (popup_factory#add_item "Metrics" ~callback:callback) + | _ -> () initializer main_ui#register_source_selector self#cyclo_selector - end (* ABP end *) let make_bi_label (parent:GPack.box) l1 = - let container = GPack.hbox ~packing:parent#pack () in - let t = GMisc.label ~text:l1 ~xalign:0.0 - ~packing:(container#pack ~expand:false ~fill:false) - () - in - Gtk_helper.old_gtk_compat t#set_width_chars 7; - let l = GMisc.label ~selectable:true ~xalign:0.0 ~text:"" - ~packing:(container#pack ~expand:true) - () - in - l + let container = GPack.hbox ~packing:parent#pack () in + let t = GMisc.label ~text:l1 ~xalign:0.0 + ~packing:(container#pack ~expand:false ~fill:false) + () + in + Gtk_helper.old_gtk_compat t#set_width_chars 7; + let label = GMisc.label ~selectable:true ~xalign:0.0 ~text:"" + ~packing:(container#pack ~expand:true) + () + in label let make_hbox (parent:GPack.box) = - GPack.hbox ~homogeneous:true ~packing:parent#pack () + GPack.hbox ~homogeneous:true ~packing:parent#pack () + +module LastResult = + State_builder.Option_ref + (DatatypeMetrics) + (struct + let dependencies = [ Ast.self ] + let name = name + let kind = `Internal + end) +;; let make_panel _main_ui = let w = GPack.vbox ~width:120 () in - let update_button = let w = make_hbox w in GButton.button (* ~stock:`REFRESH *) ~label:"Measure" @@ -156,22 +151,22 @@ let box = make_hbox w in (* Sloc *) - let sloc_label = make_bi_label box "sloc:" in + let sloc_label = make_bi_label box "Slocs:" in (* Calls *) - let calls_label = make_bi_label box "calls:" in + let calls_label = make_bi_label box "Calls:" in let box = make_hbox w in (* If *) - let if_label = make_bi_label box "if:" in + let if_label = make_bi_label box "If:" in (* while *) - let loops_label = make_bi_label box "loops:" in + let loops_label = make_bi_label box "Loops:" in let box = make_hbox w in (* Goto *) - let goto_label = make_bi_label box "goto:" in + let goto_label = make_bi_label box "Goto:" in (* assign *) - let assign_label = make_bi_label box "assigns:" in + let assign_label = make_bi_label box "Assigns:" in let box = make_hbox w in (* Mem *) @@ -185,7 +180,7 @@ let proto_label = make_bi_label box "Proto:" in let box = make_hbox w in - (* cyclomatric complexity *) + (* cyclomatic complexity *) let cyclo_label = make_bi_label box "Cyclo:" in let _placeholder2 = make_bi_label box "" in @@ -213,8 +208,8 @@ sloc = sloc; functions_without_source = fws; functions_with_source = fs; - cyclos = cycl; } - = !Db.Metrics.last_result () + cyclos = cycl; } + = LastResult.get () in update_button#misc#set_sensitive false; sloc_label#set_text (string_of_int sloc); @@ -225,9 +220,8 @@ assign_label#set_text (string_of_int assigns); mem_label#set_text (string_of_int mem_access); func_label#set_text - (string_of_int (Cil_datatype.Varinfo.Hashtbl.length fs)); - proto_label#set_text - (string_of_int(Cil_datatype.Varinfo.Hashtbl.length fws)); + (string_of_int (Metrics_base.map_cardinal_varinfomap fs)); + proto_label#set_text (string_of_int(map_cardinal_varinfomap fws)); cyclo_label#set_text (string_of_int cycl) with Not_found -> update_button#misc#set_sensitive true ; @@ -235,7 +229,7 @@ in ignore (update_button#connect#clicked - (fun () -> !Db.Metrics.compute (); fill ())); + (fun () -> LastResult.set (!Db.Metrics.compute ()); fill ())); "Metrics", w#coerce, Some fill let gui (main_ui:Design.main_window_extension_points) = diff -Nru frama-c-20110201+carbon+dfsg/src/metrics/register.ml frama-c-20111001+nitrogen+dfsg/src/metrics/register.ml --- frama-c-20110201+carbon+dfsg/src/metrics/register.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/metrics/register.ml 2011-10-10 08:38:28.000000000 +0000 @@ -20,613 +20,71 @@ (* *) (**************************************************************************) -open Format -open Cil -open Cil_types -open Cil_datatype -open Db.Metrics - -let name = "metrics" - -type int8 = int*int*int*int*int*int*int*int - -module LastResult = - State_builder.Option_ref - (Datatype.Make - (struct - include Datatype.Serializable_undefined - type t = Db.Metrics.t - let name = name - let structural_descr = Structural_descr.Abstract - let reprs = - [ { sloc = -1; - call_statements = -1; - goto_statements = -1; - assign_statements = -1; - if_statements = -1; - loop_statements = -1; - mem_access = -1; - functions_without_source = Varinfo.Hashtbl.create 7; - functions_with_source = Varinfo.Hashtbl.create 7; - (* ABP added 2 fields below*) - function_definitions = -1; - cyclos = -1 } ] - let mem_project = Datatype.never_any_project - end)) - (struct - let dependencies = [ Ast.self ] - let name = name - let kind = `Internal - end) - -let pretty_set fmt s = - Format.fprintf fmt "@["; - Varinfo.Hashtbl.iter - (fun f n -> - Format.fprintf fmt "%s %s (%d call%s);@ " - f.vname - (if f.vaddrof then "(address taken)" else "") - n (if n > 1 then "s" else "")) - s; - Format.fprintf fmt "@]" - -let number_entry_points fs = - Varinfo.Hashtbl.fold - (fun f n acc -> if n = 0 && not f.vaddrof then succ acc else acc) - fs - 0 - -let pretty_entry_points fmt fs = - let print = - Varinfo.Hashtbl.iter - (fun f n -> - if n = 0 && not f.vaddrof then Format.fprintf fmt "%s;@ " f.vname) - in - Format.fprintf fmt "@["; - print fs; - Format.fprintf fmt "@]" - -let pretty fmt = - let m = LastResult.get () in - Format.fprintf fmt - "@[Defined function (%d):@\n @[%a@]@\nUndefined functions (%d):@\n @[%a@]@\nPotential entry points (%d):@\n @[%a@]@\nSLOC: %d@\nNumber of if statements: %d@\nNumber of assignments: %d@\nNumber of loops: %d@\nNumber of calls: %d@\nNumber of gotos: %d@\nNumber of pointer access: %d@]" - (Varinfo.Hashtbl.length m.functions_with_source) - pretty_set m.functions_with_source - (Varinfo.Hashtbl.length m.functions_without_source) - pretty_set m.functions_without_source - (number_entry_points m.functions_with_source) - pretty_entry_points m.functions_with_source - m.sloc - m.if_statements - m.assign_statements - m.loop_statements - m.call_statements - m.goto_statements - m.mem_access - -let dump () = - let filename = Metrics_parameters.Dump.get () in - try - let cout = open_out_bin filename in - let fmt = Format.formatter_of_out_channel cout in - pretty fmt; - close_out cout - with Sys_error _ as e -> - Metrics_parameters.warning "Cannot open file \"%s\" for dumping metrics: %s" - filename (Printexc.to_string e) - -let null_position : Lexing.position = - { Lexing.pos_fname = ""; pos_lnum = 0; pos_bol = 0; pos_cnum = 0 } - -let null_location : Cil_types.location = (null_position, null_position) - -let fun_equal (a:global) (b:global) = - match a with - GFun (af,_) -> - begin - match b with - GFun (bf,_) -> (af == bf) - | _ -> false - end - | _ -> false - -let file_of glob = - (* returns the file name to which belongs glob *) - let res = ref "" in - let all_files = Globals.FileIndex.get_files () in - begin - for j = 0 to (List.length all_files)-1 do - let f = (List.nth all_files j) in - let (_,globs) = Globals.FileIndex.find f in - for i = 0 to (List.length globs)-1 do - let elt = ((List.nth globs i) :> global) in - if (fun_equal elt glob) then - res:=f - done - done; - !res - end - -let image_int8 (a:int8) = - let (a1,a2,a3,a4,a5,a6,a7,a8) = a in - "(" ^ (string_of_int a1) ^ "," ^ - (string_of_int a2) ^ "," ^ - (string_of_int a3) ^ "," ^ - (string_of_int a4) ^ "," ^ - (string_of_int a5) ^ "," ^ - (string_of_int a6) ^ "," ^ - (string_of_int a7) ^ "," ^ - (string_of_int a8) ^ ")" - -let plus (a:int8) (b:int8) = - let (a1,a2,a3,a4,a5,a6,a7,a8) = a in - let (b1,b2,b3,b4,b5,b6,b7,b8) = b in - (a1+b1,a2+b2,a3+b3,a4+b4,a5+b5,a6+b6,a7+b7,a8+b8) - -class slocVisitor = object(self) - inherit Visitor.generic_frama_c_visitor - (Project.current ()) (Cil.inplace_visit ()) - val mutable current_file_name:string = "" - val mutable current_function_name:string = "" - val mutable sloc = 0 - val mutable ifs = 0 - val mutable loops = 0 - val mutable calls = 0 - val mutable gotos = 0 - val mutable assigns = 0 - val mutable exits = 0 - val mutable funcs = 0 - (* table of all statistics per module and per function: - stats(file,f) = (#ifs, #assign, #loop, #calls, #gotos, #pointers, #exits, cyclo) - *) - val mutable stats: - (string*string*(int*int*int*int*int*int*int*int)) list ref = ref [] - - method stats_of_fic f = - (* get only the stats that are relative to file fic. remove them - from stats and return them *) - let prop element = - let (fic,_,_) = element in - (f=fic) - in - let (good, bad) = (List.partition prop !stats) in - stats <- ref bad; - good - - method complete_stats () = - (* When using this visitor no cyclomatic complexity is calculated - during the traversal of the AST. It has to be calculated AFTER - cisiting the entire global function. We revisit on site every tuple - of stats and calculate the last item. *) - let tout = !stats in - if tout <> [] then - let res = ref [] in - let do_it e = - let (fic,func,(a,b,c,d,e,f,g,h)) = e in - begin - if h <> 0 then - prerr_endline "metrics.complete_stats ERROR"; - res := List.append !res [(fic,func,(a,b,c,d,e,f,g,a+c-g+2))] - end - in List.iter do_it tout; - stats := !res - - method print_stats fmt = - let print_item e = - let _, func, (a,b,c,d,e,f,g,h) = e in - Metrics_parameters.debug - "stats: func: %s@\n\ -val: ifs %d@\n\ - assigns %d@\n\ - loops %d@\n\ - calls %d@\n\ - gotos %d@\n\ - mems %d@\n\ - exits %d@\n\ - cyclo %d" - func a b c d e f g h; - fprintf fmt "<tr>\n"; - fprintf fmt "<td> %s </td>\n" func; - fprintf fmt "<td> %d </td>\n" a; - fprintf fmt "<td> %d </td>\n" b; - fprintf fmt "<td> %d </td>\n" c; - fprintf fmt "<td> %d </td>\n" d; - fprintf fmt "<td> %d </td>\n" e; - fprintf fmt "<td> %d </td>\n" f; - fprintf fmt "<td> %d </td>\n" g; - fprintf fmt "<td> %d </td>\n" h; - fprintf fmt "</tr>\n"; - in - while List.length !stats > 0 do - let first = List.hd !stats in - let (fic,_,_) = first in - let fic_stats = (self#stats_of_fic fic) in - (* print header specific to fic *) - fprintf fmt "<h3> %s </h3>\n" fic; - fprintf fmt " <br>\n"; - fprintf fmt "<table style=\"width: 252px; height: 81px;\" border=\"1\">\n"; - fprintf fmt " <tbody>\n"; - fprintf fmt " <tr>\n"; - fprintf fmt " <th>Function</th>\n"; - fprintf fmt " <th>#If stmts<br>\n"; - fprintf fmt " <th>#Assignments<br>\n"; - fprintf fmt " <th>#Loops<br>\n"; - fprintf fmt " <th>#Calls<br>\n"; - fprintf fmt " <th>#Gotos<br>\n"; - fprintf fmt " <th>#Pointer accesses<br>\n"; - fprintf fmt " <th>#Exits<br>\n"; - fprintf fmt " <th>Cyclomatic value<br>\n"; - fprintf fmt " </th>\n"; - fprintf fmt " </tr>\n"; - List.iter print_item fic_stats; - (* print trailer specific to fic *) - fprintf fmt " </tbody>\n"; - fprintf fmt "</table>\n" - done - - method add_item (a:string) (b:string) (c:int8) l = - (* add a new item to the list stats *) - if (List.length l) = 0 then - [(a,b,c)] - else (* there's at least 1 element *) - let premier = (List.hd l) in - let (x,y,z) = premier in - let reste = (List.tl l) in - if (x,y)=(a,b) then - List.append [(x,y,(plus c z))] reste - else - List.append [premier] (self#add_item a b c reste) - - method add_stat (a,b,c) = - (* add one new item to stats *) - stats := (self#add_item a b c !stats) - - method assigns = assigns - method calls = calls - method gotos = gotos - method loops = loops - method ifs = ifs - method exits = exits - method funcs = funcs - val mutable standalone = true - method set_standalone v = begin standalone <- v end - val mutable mem_access = 0 - method mem_access = mem_access - val functions_no_source = Varinfo.Hashtbl.create 97 - val functions_with_source = Varinfo.Hashtbl.create 97 - method functions_no_source = functions_no_source - method functions_with_source = functions_with_source - method vvdec vi = - if isFunctionType vi.vtype then - if not (Varinfo.Hashtbl.mem functions_with_source vi) then - Varinfo.Hashtbl.replace functions_no_source vi - (try Varinfo.Hashtbl.find functions_no_source vi with Not_found -> 0); - DoChildren - - method vfunc fdec = - current_file_name <- file_of (GFun (fdec, null_location)); - current_function_name <- fdec.svar.vname; - self#add_stat (current_file_name,current_function_name,(0,0,0,0,0,0,0,0)); - funcs <- funcs+1; - let n = - try - let n = Varinfo.Hashtbl.find functions_no_source fdec.svar in - Varinfo.Hashtbl.remove functions_no_source fdec.svar; - n - with Not_found -> - 0 - in - let n = - try Varinfo.Hashtbl.find functions_with_source fdec.svar + n - with Not_found -> n - in - Varinfo.Hashtbl.replace functions_with_source fdec.svar n; - DoChildren - - method vlval (host,_) = - begin - match host with - | Mem _ -> mem_access <- mem_access + 1; - self#add_stat (current_file_name,current_function_name,(0,0,0,0,0,1,0,0)) - | _ -> () - end; - DoChildren - - method sloc = sloc - method vstmt s = - sloc <- sloc + 1 ; - begin match s.skind with - | If _ -> - ifs <- ifs + 1; - self#add_stat (current_file_name,current_function_name,(1,0,0,0,0,0,0,0)) - | Loop _ -> - loops <- loops + 1; - self#add_stat (current_file_name,current_function_name,(0,0,1,0,0,0,0,0)) - | Goto _ -> - gotos <- gotos + 1; - self#add_stat (current_file_name,current_function_name,(0,0,0,0,1,0,0,0)) - | Return _ -> - exits <- exits + 1; - self#add_stat (current_file_name,current_function_name,(0,0,0,0,0,0,1,0)) - | _ -> () - end; - DoChildren - - method find_global_function (v:varinfo) = - (* return a pair (found,spec_or_body) *) - let found:bool ref = ref false in - let spec:bool ref = ref false in - iterGlobals (Ast.get()) ( - function glob -> - match glob with - | GFun (s,_) -> (* function with code *) - if (s.svar==v) then found:=true;spec:=false - | GVarDecl (_,s,_) -> (* function w/o code *) - if (s==v) then found:=true;spec:=true - | _ -> ()); - (!found,!spec) - - method image (glob:global) = - (* extract just the name of the global , for printing purposes *) - match glob with - | GVar (v,_,_) -> v.vname ^ " (GVar) " - | GVarDecl (_,v,_) -> v.vname ^ " (GVarDecl) " - | GFun (fdec, _) -> fdec.svar.vname ^ " (GFun) " - | GType (ty, _) -> ty.tname - | GCompTag (ci, _) | GCompTagDecl (ci, _) -> ci.cname - | GEnumTagDecl (ei,_) | GEnumTag (ei,_) -> ei.ename - | GAsm (_,_) | GPragma _ | GText _ -> "" - | GAnnot (an,_) -> - match an with - Dfun_or_pred (li,_) -> li.l_var_info.lv_name - | Daxiomatic (s,_,_) -> s - | Dtype (lti,_) -> lti.lt_name - | Dlemma (ln, _, _, _, _, _) -> ln - | Dinvariant (toto,_) -> toto.l_var_info.lv_name - | Dtype_annot (ta,_) -> ta.l_var_info.lv_name - - method images (globs:global list) = - (* extract just the names of the globals, for printing purposes *) - let les_images = List.map self#image globs in - String.concat "," les_images - - method print_all = - prerr_endline ("* print_all"); - let all_files = Globals.FileIndex.get_files () in - let print_one fic = - let (_,glob) = Globals.FileIndex.find fic in - prerr_endline ("* " ^ fic ^ " : " ^ (self#images glob)) - in - List.iter print_one all_files - - method vinst i = - begin match i with - | Call(_, e, _, _) -> - calls <- calls + 1; - self#add_stat (current_file_name,current_function_name,(0,0,0,1,0,0,0,0)); - (match e.enode with - | Lval(Var v, NoOffset) -> - let next tbl = - Varinfo.Hashtbl.replace tbl v (succ (Varinfo.Hashtbl.find tbl v)) - in - begin - try next functions_with_source; - with Not_found -> - try next functions_no_source; - with Not_found -> - (* if this iterator is called on a specific global - function only, it might not find the target of this call - so we check if this function is w/ or w/o source and - add 1 to the number of calls accordingly. - *) - (* self#print_all; *) - if not standalone then - let (ya,codeless) = self#find_global_function v in - if ya then - begin - if codeless then - Varinfo.Hashtbl.replace functions_with_source v 0 - else - Varinfo.Hashtbl.replace functions_no_source v 0 - end - else - Metrics_parameters.fatal "Got no source for %s" v.vname - else - Metrics_parameters.fatal "Got no source for %s" v.vname - end - | _ -> ()); - DoChildren - | Set _ -> - assigns <- succ assigns; - self#add_stat (current_file_name,current_function_name,(0,1,0,0,0,0,0,0)); - DoChildren - | _ -> DoChildren - end - -end - -(* This may be used to generate code associated to prototypes. - -let find_lvals_to_assign vi = - let rec rec_find_lvals lval = - let typ = typeOfLval lval in - if isArithmeticType typ then [lval] - else if isPointerType typ then - rec_find_lvals (mkMem ~addr:(Lval lval) ~off:NoOffset) - else assert false - in - if isPointerType vi.vtype then - (* find the lvals of basic types *) - rec_find_lvals (mkMem ~addr:(Lval (Var vi,NoOffset)) ~off:NoOffset) - else [] - -let make_body_from_prototype vi = - vi.vstorage <- NoStorage; - let new_fundec = - { svar = vi; - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - sspec = {requires = None; - assigns = None; - ensures = None; - decreases = None} - } - in - (* formal might have no name, let's fix the type to generate a name:*) - vi.vtype <- begin match vi.vtype with - | TFun (typ, None, b, attr) -> vi.vtype - | TFun (typ, Some args, b, attr) -> - let counter = ref 0 in - let named_args = - List.map - (fun (n,t,a) -> - (if n= "" then - begin incr counter; - "Frama_C_formals_"^(string_of_int !counter) - end - else n), - t,a) - args - in - TFun (typ, Some named_args, b, attr) - | _ -> assert false - end; - setFunctionTypeMakeFormals new_fundec vi.vtype; - let fresh_global = GFun (new_fundec,vi.vdecl) in - let fresh_volatile = - makeLocalVar - new_fundec - "Frama_C_entropy_source" - (typeAddAttributes [Attr ("volatile",[])] (TInt(IULongLong, [])) ) - in - let volatile_lval = Lval(Var fresh_volatile,NoOffset) in - List.iter (fun formal -> - let lvals_to_assign = find_lvals_to_assign formal in - let stmts = - List.map - (fun lval_to_assign -> - mkStmtOneInstr - (Set (lval_to_assign, - volatile_lval, - vi.vdecl))) - lvals_to_assign - in - let conditional - new_fundec.sbody.bstmts <- new_fundec.sbody.bstmts@stmts; - ) - new_fundec.sformals; - - Format.printf "Made: <@\n %a@\n>@." d_global fresh_global; - new_fundec - -class turn_prototype_into_body protos_vi turn_into = object(self) - inherit nopCilVisitor - - method vglob glob = - match glob with - | GVarDecl (fspec, vi, loc) when Cil_datatype.Varinfo.Set.mem vi protos_vi -> - assert (isFunctionType vi.vtype); - ChangeTo [GFun(make_body_from_prototype vi,loc)] +open Metrics_base +open Metrics_parameters - | _ -> SkipChildren +let () = Enabled.set_output_dependencies + [Ast.self; AST_type.self; OutputFile.self; SyntacticallyReachable.self] -end +let syntactic () = + begin + match AST_type.get () with + | "cil" -> + let r = !Db.Metrics.compute () in + Metrics.result + "@[<v 0>Syntactic metrics@ \ + -----------------@ %a@]" + !Db.Metrics.pretty r -*) + (* Cabs metrics are experimental. unregistered, unjournalized *) + | "cabs" -> Metrics_cabs.compute_on_cabs () + + | _ -> assert false (* the possible values are checked by the kernel*) + end; -let compute () = - let file = Ast.get () in - let v = new slocVisitor in - v#set_standalone true; (* measure the entire code *) - visitCilFileSameGlobals (v:>cilVisitor) file; - v#complete_stats (); - LastResult.set - { call_statements = v#calls; - goto_statements = v#gotos; - assign_statements = v#assigns; - if_statements = v#ifs; - mem_access = v#mem_access; - loop_statements = v#loops; - function_definitions = v#funcs; - sloc = v#sloc; - functions_without_source = v#functions_no_source; - functions_with_source = v#functions_with_source; - cyclos = (v#ifs +v#loops) - v#exits +2*v#funcs - }; - (* print results on HTML file *) - let cout = open_out "metrics.html" in - let fmt = formatter_of_out_channel cout in - (* header *) - fprintf fmt "<!DOCTYPE HTML PUBLIC >\n"; - fprintf fmt "<html>\n"; - fprintf fmt "<head>\n"; - fprintf fmt "</head>\n"; - fprintf fmt "<body>\n"; - fprintf fmt "<div style=\"text-align: left;\">\n"; - fprintf fmt "<h1><span style=\"font-weight: bold;\">Metrics</span></h1>\n"; - fprintf fmt "<h2>Synthetic results</h2>\n"; - fprintf fmt "<br>\n"; - (* *) (* global stats *) - fprintf fmt "<span style=\"font-weight: bold;\">Defined function</span> (%d):<br>\n" - (Varinfo.Hashtbl.length v#functions_with_source); - (* *) - fprintf fmt "@[  %a@]@ <br>\n" pretty_set v#functions_with_source; - fprintf fmt "<br>\n"; - fprintf fmt "<span style=\"font-weight: bold;\">Undefined functions</span> (%d):<br>\n" (Varinfo.Hashtbl.length v#functions_no_source); - (* *) - fprintf fmt "@[  %a@]@ <br>\n" pretty_set v#functions_no_source; - fprintf fmt "<br>\n"; - (* *) - fprintf fmt "<span style=\"font-weight: bold;\">Potential entry points</span> (%d):<br>\n" (number_entry_points v#functions_with_source); - (* *) - fprintf fmt "@[  %a@]@ <br>\n" pretty_entry_points v#functions_with_source; - fprintf fmt "<br>\n"; - (* TBD other gloabl stats *) - fprintf fmt "<span style=\"font-weight: bold;\">SLOC:</span> (%d)<br>\n" v#sloc; - fprintf fmt "<span style=\"font-weight: bold;\">Number of if statements:</span> (%d)<br>\n" v#ifs; - fprintf fmt "<span style=\"font-weight: bold;\">Number of assignments:</span> (%d)<br>\n" v#assigns; - fprintf fmt "<span style=\"font-weight: bold;\">Number of loops:</span> (%d)<br>\n" v#loops; - fprintf fmt "<span style=\"font-weight: bold;\">Number of calls:</span> (%d)<br>\n" v#calls; - fprintf fmt "<span style=\"font-weight: bold;\">Number of gotos:</span> (%d)<br>\n" v#gotos; - fprintf fmt "<span style=\"font-weight: bold;\">Number of pointer access:</span> (%d)<br>\n" v#mem_access; - fprintf fmt "<br>\n"; - fprintf fmt "<h2>Detailed results</h2>\n"; - fprintf fmt "<br>\n"; - (* detailed stats *) - v#print_stats fmt; - close_out cout; - Metrics_parameters.feedback "Metrics printed to file metrics.html" + SyntacticallyReachable.iter + (fun s -> + try let kf = Globals.Functions.find_by_name s in + Metrics.result "%a" Metrics_coverage.pp_reached_from_function kf + with Not_found -> Metrics.error "Unknown function %s" s + ); +;; + + +let () = ValueCoverage.set_output_dependencies [Db.Value.self] + +let value () = + !Db.Value.compute (); + if Db.Value.is_computed () then begin + let f1, f2 = Metrics_coverage.pp_value_coverage () in + Metrics.result "%t" f1; + Metrics.result "%t" f2; + Metrics.result "%t" Metrics_coverage.pp_stmts_reached_by_function; + end +;; let main () = - if Metrics_parameters.is_on () then begin - !Db.Metrics.compute (); - if Metrics_parameters.Print.get () then - Metrics_parameters.result "Syntactic metrics@\n %t" !Db.Metrics.pretty; - if Metrics_parameters.Dump.get () <> "" then - !Db.Metrics.dump () - end + if Enabled.get () then Enabled.output syntactic; + if ValueCoverage.get () then ValueCoverage.output value; +;; + +(* Main entry points *) let () = Db.Main.extend main +(* Register some functions in Frama-C's DB *) let () = - Db.register + Db.register (Db.Journalize - ("Metrics.compute", Datatype.func Datatype.unit Datatype.unit)) - Db.Metrics.compute compute; + ("Metrics.compute", Datatype.func Datatype.unit DatatypeMetrics.ty)) + Db.Metrics.compute Metrics_cilast.compute_on_cilast; + Db.register (Db.Journalize - ("Metrics.pretty", Datatype.func Datatype.formatter Datatype.unit)) + ("Metrics.pretty", Datatype.func Datatype.formatter + (Datatype.func DatatypeMetrics.ty Datatype.unit))) Db.Metrics.pretty pretty; - Db.register - (Db.Journalize ("Metrics.dump", Datatype.func Datatype.unit Datatype.unit)) - Db.Metrics.dump dump; - Db.register Db.Journalization_not_required - Db.Metrics.last_result LastResult.get - +;; (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/misc/bit_utils.ml frama-c-20111001+nitrogen+dfsg/src/misc/bit_utils.ml --- frama-c-20110201+carbon+dfsg/src/misc/bit_utils.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/bit_utils.ml 2011-10-10 08:38:28.000000000 +0000 @@ -41,24 +41,21 @@ (Int.of_int (8+sizeofpointer ()))) -let max_bit_address () = Int.pred (Int.power_two (sizeofpointer ()+7)) let max_bit_size () = Int.power_two (7+(sizeofpointer ())) +let max_bit_address () = Int.pred (max_bit_size()) let warn_if_zero ty r = if r = 0 then - (ignore - (Cil.error - "size of '%a' is zero. Check target code or Frama-C -machdep option." - !Ast_printer.d_type ty); - exit 1;); + Kernel.abort + "size of '%a' is zero. Check target code or Frama-C -machdep option." + !Ast_printer.d_type ty; r (** [sizeof ty] is the size of [ty] in bits. This function may return [Int_Base.top]. *) let sizeof ty = (match ty with - | TVoid _ -> - CilE.warn_once "using size of 'void'" + | TVoid _ -> Kernel.warning ~current:true ~once:true "using size of 'void'" | _ -> ()) ; try Int_Base.inject (Int.of_int (bitsSizeOf ty)) with SizeOfError _ -> @@ -68,8 +65,7 @@ [Int_Base.top]. *) let osizeof ty = (match ty with - | TVoid _ -> - CilE.warn_once "using size of 'void'" + | TVoid _ -> Kernel.warning ~once:true ~current:true "using size of 'void'" | _ -> ()) ; try Int_Base.inject (Int.of_int (warn_if_zero ty (bitsSizeOf ty) / 8)) @@ -81,9 +77,8 @@ meaningful. [true] means that the type is signed. *) let is_signed_int_enum_pointer ty = match unrollType ty with - | TInt (k,_) -> Cil.isSigned k + | TInt (k,_) | TEnum ({ekind=k},_) -> Cil.isSigned k | TPtr _ -> false - | TEnum _ -> theMachine.enum_are_signed | TFloat _ | TFun _ | TBuiltin_va_list _ | TVoid _ | TArray _ | TComp _ | TNamed _ -> raise Neither_Int_Nor_Enum_Nor_Pointer @@ -122,8 +117,8 @@ | TArray(typ,_,_,_) -> sizeof typ | _ -> Kernel.abort "TYPE IS: %a (unrolled as %a)" - !Ast_printer.d_type typ - !Ast_printer.d_type (unrollType typ) + !Ast_printer.d_type typ + !Ast_printer.d_type (unrollType typ) (** Returns the size of the type pointed by a pointer type in bytes. Never call it on a non pointer type. *) @@ -180,7 +175,7 @@ let raw_bits c start stop = let cond = env.use_align && ((not (Int.equal (Int.pos_rem start env.rh_size) align)) - || (not (Int.equal req_size env.rh_size))) + || (not (Int.equal req_size env.rh_size))) in Format.fprintf env.fmt "[%sbits %a to %a]%s" (if Kernel.debug_atleast 1 then String.make 1 c else "") @@ -205,14 +200,14 @@ | Other -> Int.of_int (bitsSizeOf typ) | Bitfield i -> Int.of_int64 i in - (if Int.is_zero start + (if Int.is_zero start && Int.equal size req_size then (** pretty print a full offset *) (if not env.use_align || - (Int.equal start align && Int.equal env.rh_size size) - then () - else (env.misaligned <- true ; - Format.pp_print_char env.fmt '#')) + (Int.equal start align && Int.equal env.rh_size size) + then () + else (env.misaligned <- true ; + Format.pp_print_char env.fmt '#')) else raw_bits 'b' start stop) @@ -244,16 +239,16 @@ else stop in let new_bfinfo = match field.fbitfield with - | None -> Other - | Some i -> Bitfield (Int.to_int64 (Int.of_int i)) + | None -> Other + | Some i -> Bitfield (Int.to_int64 (Int.of_int i)) in - let new_align = Int.pos_rem (Int.sub align start_o) env.rh_size in + let new_align = Int.pos_rem (Int.sub align start_o) env.rh_size in if Int.le new_start new_stop then - NamedField( field.fname , - new_bfinfo , field.ftype , - new_align , new_start , new_stop ) :: acc + NamedField( field.fname , + new_bfinfo , field.ftype , + new_align , new_start , new_stop ) :: acc else - acc) + acc) [] compinfo.cfields in @@ -272,42 +267,42 @@ else if Int.le succ_stop_o start then acc else if Int.gt start_o last_field_offset then (* found a hole *) - (RawField('c', last_field_offset,Int.pred start_o)::s, + (RawField('c', last_field_offset,Int.pred start_o)::s, succ_stop_o) else - (s,succ_stop_o) - ) - (full_fields_to_print,start) + (s,succ_stop_o) + ) + (full_fields_to_print,start) compinfo.cfields else full_fields_to_print, Int.zero in let overflowing = if compinfo.cstruct && Int.le succ_last stop - then RawField('o',Int.max start succ_last,stop)::non_covered + then RawField('o',Int.max start succ_last,stop)::non_covered else non_covered in let pretty_one_field = function - | NamedField(name,bf,ftyp,align,start,stop) -> - Format.fprintf env.fmt ".%a" !Ast_printer.d_ident name ; - pretty_bits_internal env bf ftyp ~align ~start ~stop - | RawField(c,start,stop) -> - Format.pp_print_char env.fmt '.' ; - raw_bits c start stop - in - let rec pretty_all_fields = function - | [] -> () - | f::fs -> - pretty_all_fields fs ; - pretty_one_field f ; - Format.pp_print_string env.fmt "; " - in - match overflowing with - | [] -> Format.pp_print_string env.fmt "{}" - | [f] -> pretty_one_field f - | fs -> - Format.pp_print_char env.fmt '{' ; - pretty_all_fields fs ; - Format.pp_print_char env.fmt '}' + | NamedField(name,bf,ftyp,align,start,stop) -> + Format.fprintf env.fmt ".%a" !Ast_printer.d_ident name ; + pretty_bits_internal env bf ftyp ~align ~start ~stop + | RawField(c,start,stop) -> + Format.pp_print_char env.fmt '.' ; + raw_bits c start stop + in + let rec pretty_all_fields = function + | [] -> () + | f::fs -> + pretty_all_fields fs ; + pretty_one_field f ; + Format.pp_print_string env.fmt "; " + in + match overflowing with + | [] -> Format.pp_print_string env.fmt "{}" + | [f] -> pretty_one_field f + | fs -> + Format.pp_print_char env.fmt '{' ; + pretty_all_fields fs ; + Format.pp_print_char env.fmt '}' end | TArray (typ, _, _, _) -> @@ -330,9 +325,9 @@ ~align:new_align ~start:rem_start_size ~stop:rem_stop_size - else if Int.equal (Int.rem start env.rh_size) align - && (Int.is_zero (Int.rem size env.rh_size)) - then + else if Int.equal (Int.rem start env.rh_size) align + && (Int.is_zero (Int.rem size env.rh_size)) + then let pred_size = Int.pred size in let start_full_case = if Int.is_zero rem_start_size then start_case @@ -345,45 +340,45 @@ let first_part = if Int.is_zero rem_start_size then [] else [ArrayPart(start_case,start_case, - typ,align,rem_start_size,pred_size)] + typ,align,rem_start_size,pred_size)] in let middle_part = if Int.lt stop_full_case start_full_case then [] else [ArrayPart(start_full_case,stop_full_case, - typ,align,Int.zero,pred_size)] + typ,align,Int.zero,pred_size)] in let last_part = if Int.equal rem_stop_size pred_size - then [] + then [] else [ArrayPart(stop_case,stop_case, - typ,align,Int.zero,rem_stop_size)] + typ,align,Int.zero,rem_stop_size)] + in + let do_part = function + | ArrayPart(start_index,stop_index,typ,align,start,stop) -> + if Int.equal start_index stop_index then + Format.fprintf env.fmt "[%a]" + Int.pretty start_index + else + Format.fprintf env.fmt "[%a..%a]" + Int.pretty start_index + Int.pretty stop_index ; + pretty_bits_internal env Other typ ~align ~start ~stop + in + let rec do_all_parts = function + | [] -> () + | p::ps -> + do_part p ; + Format.pp_print_string env.fmt "; " ; + do_all_parts ps in - let do_part = function - | ArrayPart(start_index,stop_index,typ,align,start,stop) -> - if Int.equal start_index stop_index then - Format.fprintf env.fmt "[%a]" - Int.pretty start_index - else - Format.fprintf env.fmt "[%a..%a]" - Int.pretty start_index - Int.pretty stop_index ; - pretty_bits_internal env Other typ ~align ~start ~stop - in - let rec do_all_parts = function - | [] -> () - | p::ps -> - do_part p ; - Format.pp_print_string env.fmt "; " ; - do_all_parts ps - in - match first_part @ middle_part @ last_part with - | [] -> Format.pp_print_string env.fmt "{}" - | [p] -> do_part p - | ps -> - Format.pp_print_char env.fmt '{' ; - do_all_parts ps ; - Format.pp_print_char env.fmt '}' ; + match first_part @ middle_part @ last_part with + | [] -> Format.pp_print_string env.fmt "{}" + | [p] -> do_part p + | ps -> + Format.pp_print_char env.fmt '{' ; + do_all_parts ps ; + Format.pp_print_char env.fmt '}' ; else raw_bits 'a' start stop @@ -407,6 +402,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/misc/bit_utils.mli frama-c-20111001+nitrogen+dfsg/src/misc/bit_utils.mli --- frama-c-20110201+carbon+dfsg/src/misc/bit_utils.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/bit_utils.mli 2011-10-10 08:38:28.000000000 +0000 @@ -20,19 +20,18 @@ (* *) (**************************************************************************) -(* $Id: bit_utils.mli,v 1.11 2008-07-02 15:28:19 uid568 Exp $ *) - (** Some bit manipulations. *) open Cil_types -val sizeofchar: unit -> My_bigint.big_int +val sizeofchar: unit -> My_bigint.t (** [sizeof(char)] in bits *) val sizeofpointer: unit -> int (** [sizeof(char* )] in bits *) -val memory_size: unit -> My_bigint.big_int +val memory_size: unit -> My_bigint.t + (** Size of the addressable memory with pointers of size [sizeofpointer()] *) val sizeof: typ -> Int_Base.t (** [sizeof ty] is the size of [ty] in bits. This function may return @@ -41,11 +40,11 @@ val osizeof: typ -> Int_Base.t (** [osizeof ty] is the size of [ty] in bytes. This function may return [Int_Base.top]. *) - + exception Neither_Int_Nor_Enum_Nor_Pointer val is_signed_int_enum_pointer: typ -> bool - (** [true] means that the type is signed. + (** [true] means that the type is signed. @raise Neither_Int_Nor_Enum_Nor_Pointer if the sign of the type is not meaningful. *) @@ -79,13 +78,13 @@ (** {2 Pretty printing} *) -val pretty_bits: - typ -> +val pretty_bits: + typ -> use_align:bool -> - align:My_bigint.big_int -> - rh_size:My_bigint.big_int -> - start:My_bigint.big_int -> - stop:My_bigint.big_int -> Format.formatter -> bool + align:My_bigint.t -> + rh_size:My_bigint.t -> + start:My_bigint.t -> + stop:My_bigint.t -> Format.formatter -> bool (** Pretty prints a range of bits in a type for the user. Tries to find field names and array indexes, whenever possible. *) diff -Nru frama-c-20110201+carbon+dfsg/src/misc/filter.ml frama-c-20111001+nitrogen+dfsg/src/misc/filter.ml --- frama-c-20110201+carbon+dfsg/src/misc/filter.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/filter.ml 2011-10-10 08:38:28.000000000 +0000 @@ -20,20 +20,24 @@ (* *) (**************************************************************************) -open Db_types open Cil open Cil_types module FC_file = File (* overwritten by Cil_datatype *) open Cil_datatype open Extlib +let dkey = "filter" + +let debug1 fmt = Kernel.debug ~dkey fmt +let debug2 fmt = Kernel.debug ~dkey ~level:2 fmt + module type T_RemoveInfo = sig type t_proj type t_fct exception EraseAssigns - val fct_info : t_proj -> Db_types.kernel_function -> t_fct list + val fct_info : t_proj -> kernel_function -> t_fct list val fct_name : varinfo -> t_fct -> string @@ -43,8 +47,7 @@ val inst_visible : t_fct -> stmt -> bool val label_visible : t_fct -> stmt -> label -> bool - val annotation_visible: t_fct -> stmt -> before:bool -> - code_annotation -> bool + val annotation_visible: t_fct -> stmt -> code_annotation -> bool val fun_precond_visible : t_fct -> predicate -> bool val fun_postcond_visible : t_fct -> predicate -> bool @@ -53,14 +56,15 @@ val fun_deps_visible : t_fct -> identified_term -> bool val called_info : (t_proj * t_fct) -> stmt -> - (Db_types.kernel_function * t_fct) option + (kernel_function * t_fct) option val res_call_visible : t_fct -> stmt -> bool - val result_visible : Db_types.kernel_function -> t_fct -> bool + val result_visible : kernel_function -> t_fct -> bool end module F (Info : T_RemoveInfo) : sig val build_cil_file : string -> Info.t_proj -> Project.t + end = struct type t = (string, Cil_types.varinfo) Hashtbl.t @@ -69,12 +73,28 @@ let mk_skip loc = Instr (Skip loc) let mk_stmt_skip st = mk_skip (Stmt.loc st) + let make_new_kf tbl kf v = + try + Cil_datatype.Varinfo.Hashtbl.find tbl v + with Not_found -> + let fundec = + match kf.fundec with + | Definition(f,l) -> Definition ( { f with svar = v },l) + | Declaration(_,_,arg,l) -> + Declaration(Cil.empty_funspec(),v,arg,l) + in + let kf = + { fundec = fundec; spec = Cil.empty_funspec(); return_stmt = None } + in + Cil_datatype.Varinfo.Hashtbl.add tbl v kf; kf + let rec can_skip keep_stmts stmt = + stmt.labels = [] && match stmt.skind with | Instr (Skip _) -> - Kernel.debug ~level:2 "@[Statement %d: can%s skip@]@." stmt.sid + debug2 "@[Statement %d: can%s skip@]@." stmt.sid (if Stmt.Set.mem stmt keep_stmts then "'t" else ""); - not (Stmt.Set.mem stmt keep_stmts) && stmt.labels = [] + not (Stmt.Set.mem stmt keep_stmts) | Block b -> is_empty_block keep_stmts b | UnspecifiedSequence seq -> is_empty_unspecified_sequence keep_stmts seq | _ -> false @@ -85,20 +105,27 @@ and is_empty_unspecified_sequence keep_stmts seq = List.for_all ((can_skip keep_stmts) $ (fun (x,_,_,_,_)->x)) seq - let rec mk_new_block keep_stmts s b loc = + let rec mk_new_block keep_stmts s blk loc = (* vblock has already cleaned up the statements (removed skip, etc...), * but now the block can still be empty or include only one statement. *) - match b.bstmts with - | [] | _ when is_empty_block keep_stmts b -> + match blk.bstmts with + | [] | _ when is_empty_block keep_stmts blk -> + (* don't care about local variables since the block is empty. *) mk_new_stmt s (mk_skip loc) - | stmt :: [] -> (* one statement only *) - begin match stmt.skind with - | Block b -> mk_new_block keep_stmts s b loc - | UnspecifiedSequence seq -> - mk_new_unspecified_sequence keep_stmts s seq loc - | _ -> mk_new_stmt s stmt.skind + | { labels = [] } as s1 :: [] -> + (* one statement only, and no label *) + begin + match s1.skind with + | Block b -> + (* drop blk, but keep local declarations. *) + b.blocals <- b.blocals @ blk.blocals; + mk_new_block keep_stmts s b loc + | UnspecifiedSequence seq when blk.blocals = [] -> + mk_new_unspecified_sequence keep_stmts s seq loc + | _ when blk.blocals = [] -> mk_new_stmt s s1.skind + | _ -> mk_new_stmt s (Block blk) end - | _ -> mk_new_stmt s (Block b) + | _ -> mk_new_stmt s (Block blk) (* same as above, but for unspecified sequences. *) and mk_new_unspecified_sequence keep_stmts s seq loc = @@ -109,7 +136,9 @@ | _ when is_empty_unspecified_sequence keep_stmts seq -> mk_new_stmt s (mk_skip loc) | [stmt,_,_,_,_] -> (* one statement only *) - begin match stmt.skind with + begin + if stmt.labels <> [] then s.labels <- s.labels @ stmt.labels; + match stmt.skind with | UnspecifiedSequence seq -> mk_new_unspecified_sequence keep_stmts s seq loc | Block b -> mk_new_block keep_stmts s b loc @@ -117,12 +146,51 @@ end | _ -> mk_new_stmt s (UnspecifiedSequence seq) - let rec filter_labels finfof st labels = match labels with - | [] -> [] - | l :: labs -> - if Info.label_visible finfof st l - then l::(filter_labels finfof st labs) - else filter_labels finfof st labs + let add_label_if_needed mk_label finfo s = + let rec pickLabel = function + | [] -> None + | Label _ as lab :: _ when Info.label_visible finfo s lab -> Some lab + | _ :: rest -> pickLabel rest + in match pickLabel s.labels with + | Some _ -> None + | None -> + let label = mk_label (Cil_datatype.Stmt.loc s) in + debug2 "add label to sid:%d : %a" s.sid Cil.d_label label; + s.labels <- label::s.labels; + Some label + + let rm_break_cont ?(cont=true) ?(break=true) mk_label finfo blk = + let change loc s = + let dest = match s.succs with dest::_ -> dest | [] -> assert false in + let new_l = add_label_if_needed mk_label finfo dest in + mk_new_stmt s (Goto (ref dest, loc)); + debug2 "changed break/continue into @[%a@]@." + !Ast_printer.d_stmt s; + new_l + in + let rec rm_aux cont break s = + match s.skind with + | Break loc when break && Info.inst_visible finfo s -> + let _ = change loc s in () + | Continue loc when cont && Info.inst_visible finfo s -> + let _ = change loc s in () + | Instr _ | Return _ | Break _ | Continue _ | Goto _ -> () + | If (_, bthen, belse, _) -> + List.iter (rm_aux cont break) bthen.bstmts; + List.iter (rm_aux cont break) belse.bstmts; + | Block blk -> + List.iter (rm_aux cont break) blk.bstmts + | UnspecifiedSequence seq -> + let blk = Cil.block_from_unspecified_sequence seq in + List.iter (rm_aux cont break) blk.bstmts + | Loop _ -> (* don't go inside : break and continue change meaning*) + () + | Switch (_, blk, _, _) -> + (* if change [continue] do it, but stop changing [break] *) + if cont then + let break = false in List.iter (rm_aux cont break) blk.bstmts + | TryFinally _ | TryExcept _ -> (* TODO ? *) () + in List.iter (rm_aux cont break) blk.bstmts (** filter [params] according to [ff] input visibility. * Can be used to slice both the parameters, the call arguments, @@ -146,8 +214,7 @@ let name = Info.fct_name fct_var finfo in try let ff_var = Hashtbl.find fun_vars name in - Kernel.debug ~level:2 - "[filter:ff_var] Use fct var %s:%d@." ff_var.vname ff_var.vid; + debug2 "[ff_var] Use fct var %s:%d@." ff_var.vname ff_var.vid; ff_var with Not_found -> let ff_var = Cil.copyVarinfo fct_var name in @@ -155,33 +222,71 @@ Cil.setReturnTypeVI ff_var Cil.voidType; (* Notice that we don't have to filter the parameter types here : * they will be update by [Cil.setFormals] later on. *) - Kernel.debug ~level:2 "[filter:ff_var] Mem fct var %s:%d@." - ff_var.vname ff_var.vid; + debug2 "[ff_var] Mem fct var %s:%d@." + ff_var.vname ff_var.vid; Hashtbl.add fun_vars name ff_var; ff_var - let optim_if keep_stmts s cond_opt bthen belse loc = + let optim_if keep_stmts s_orig s cond_opt bthen belse loc = let empty_then = is_empty_block keep_stmts bthen in let empty_else = is_empty_block keep_stmts belse in - Kernel.debug ~level:2 "[filter:optim_if] sid:%d with \ - %s cond, %s empty then, %s empty else@." - s.sid + debug2 "[optim_if] @[sid:%d (orig:%d)@ \ + with %s cond, %s empty then, %s empty else@]@." + s.sid s_orig.sid (if cond_opt = None then "no" else "") (if empty_then then "" else "not") (if empty_else then "" else "not"); - match cond_opt, empty_then, empty_else with - | _, true,true -> (* both blocks empty -> skip *) - mk_new_stmt s (mk_skip loc) - | None, false, true -> (* no cond and else empty -> block then *) - (mk_new_block keep_stmts s bthen loc) - | None, true, false -> (* no cond and then empty -> block else *) - (mk_new_block keep_stmts s belse loc) - | Some cond, _, _ -> - let skind = If (cond, bthen, belse, loc) in - (mk_new_stmt s skind) - | None, false, false -> - let skind = If (Cil.zero ~loc, bthen, belse, loc) in - (mk_new_stmt s skind) + match cond_opt with + | Some cond -> + if empty_then && empty_else then mk_new_stmt s (mk_skip loc) + else (* cond visible and something in blocks : keep if *) + mk_new_stmt s (If (cond, bthen, belse, loc)) + | None -> (* no cond *) + let go_then, go_else = Db.Value.condition_truth_value s_orig in + debug2 + "[condition_truth_value] can go in then = %b - can go in else =%b@." + go_then go_else; + match go_then, empty_then, go_else, empty_else with + | _, true, _, true -> (* both blocks empty -> skip *) + mk_new_stmt s (mk_skip loc) + | true, false, false, true -> + (* else empty and always go to then -> block then *) + mk_new_block keep_stmts s bthen loc + | false, true, true, false -> + (* then empty and always go to else -> block else *) + mk_new_block keep_stmts s belse loc + | false, false, true, _ -> + (* always goes in the 'else' branch, + * but the then branch is not empty : *) + mk_new_stmt s (If (Cil.zero ~loc, bthen, belse, loc)) + | true, false, false, false -> + (* always goes in the 'then' branch, + * but the else branch is not empty : + *) + mk_new_stmt s (If (Cil.one ~loc, bthen, belse, loc)) + | true, true, false, false -> + (* always goes in the 'then' empty branch, + * but the else branch is not empty : + * build (if (0) belse else empty. + *) + mk_new_stmt s (If (Cil.zero ~loc, belse, bthen, loc)) + | true, false, true, false + | false, false, false, false -> + (* if both go_then and go_else are true: + * can go in both branch but don't depend on cond ? + * probably unreachable IF with reachable blocks by goto. + * if both go_else and go_else are false: + * never goes in any branch ? + * both branch visible -> dummy condition *) + mk_new_stmt s (If (Cil.one ~loc, bthen, belse, loc)) + | true, _, true, true + | false, _, false, true -> + (* can go in both or no branch (see above) : empty else *) + mk_new_block keep_stmts s bthen loc + | true, true, true, _ + | false, true, false, _ -> + (* can go in both or no branch (see above) : empty then *) + mk_new_block keep_stmts s belse loc let visible_lval vars_visible lval = let visitor = object @@ -222,6 +327,23 @@ val fun_vars = Hashtbl.create 7 val local_visible = Varinfo.Hashtbl.create 7 val formals_table = Varinfo.Hashtbl.create 7 + val my_kf = Varinfo.Hashtbl.create 7 + + val lab_num = ref 0; + val lab_prefix = "break_cont" + method private fresh_label loc = + incr lab_num; + let lname = Printf.sprintf "%s_%d" lab_prefix !lab_num in + Label (lname, loc, false) + method private is_our_label label = match label with + | Label (lname, _, false) -> + let ok = + try + let prefix = String.sub lname 0 (String.length lab_prefix) in + prefix = lab_prefix + with Invalid_argument _ -> false + in ok + | _ -> false method private get_finfo () = Extlib.the fi @@ -229,8 +351,8 @@ keep_stmts <- Stmt.Set.add stmt keep_stmts (** Applied on each variable use : - * must replace references to formal/local variables - * and source function calls *) + * must replace references to formal/local variables + * and source function calls *) method vvrbl (v: varinfo) = if v.vglob then @@ -270,8 +392,7 @@ | [] -> [] | var :: locals -> let visible = Info.loc_var_visible (self#get_finfo ()) var in - Kernel.debug ~level:2 - "[filter:local] %s -> %s@." var.vname + debug2 "[local] %s -> %s@." var.vname (if visible then "keep" else "remove"); if visible then begin @@ -294,23 +415,21 @@ let stmt = Cil.get_original_stmt self#behavior (Cilutil.valOf self#current_stmt) in - let before = self#is_annot_before in - Kernel.debug "[filter:annotation] %s stmt %d : %a @." - (if before then "before" else "after") + debug1 "[annotation] stmt %d : %a @." stmt.sid !Ast_printer.d_code_annotation v; - if Db.Value.is_accessible (Cil_types.Kstmt stmt) && - Info.annotation_visible (self#get_finfo ()) stmt before v + if Db.Value.is_reachable_stmt stmt && + Info.annotation_visible (self#get_finfo ()) stmt v then begin self#add_stmt_keep stmt; ChangeDoChildrenPost (v,Logic_const.refresh_code_annotation) end else begin - Kernel.debug "\t-> ignoring annotation: %a@." + debug1 "\t-> ignoring annotation: %a@." !Ast_printer.d_code_annotation v; ChangeTo (Logic_const.new_code_annotation (AAssert ([], - { name = []; loc = Lexing.dummy_pos,Lexing.dummy_pos; - content = Ptrue}))) + { name = []; loc = Lexing.dummy_pos,Lexing.dummy_pos; + content = Ptrue}))) end method private process_call call_stmt call = @@ -327,7 +446,7 @@ let need_lval = Info.res_call_visible finfo call_stmt in let new_lval = if need_lval then lval else None in let new_call = Call (new_lval, new_funcexp, new_args, loc) in - Kernel.debug "[filter:process_call] call %s@." var_slice.vname; + debug1 "[process_call] call %s@." var_slice.vname; Instr (new_call) method vblock (b: block) = @@ -341,9 +460,9 @@ b'.bstmts <- List.filter (fun st -> - not (Cil.is_skip st.skind) - || st.labels <> [] - || Annotations.get_all st <> [] + not (Cil.is_skip st.skind) + || st.labels <> [] + || Annotations.get_all st <> [] (*|| ((*Format.eprintf "Skipping %d@.@." st.sid;*) false)*) ) b'.bstmts) @@ -366,11 +485,11 @@ Cil.set_stmt self#behavior orig s; Cil.set_orig_stmt self#behavior s orig; if keep then self#add_stmt_keep s; - Kernel.debug ~level:2 - "@[finalize %d->%d = %a@]@\n@." old s.sid !Ast_printer.d_stmt s; + debug2 "@[finalize sid:%d->sid:%d@]@\n@." old s.sid method private process_invisible_stmt s = - Kernel.debug ~level:2 "[filter:process_invisible_stmt] sid:%d@." s.sid; + let finfo = self#get_finfo () in + debug2 "[process_invisible_stmt] does sid:%d@." s.sid; (* invisible statement : but still have to visit the children if any *) let oldskind = s.skind in let do_after s = @@ -380,41 +499,45 @@ | If (_,bthen,belse,loc) -> let bthen = Cil.visitCilBlock (self:>Cil.cilVisitor) bthen in let belse = Cil.visitCilBlock (self:>Cil.cilVisitor) belse in - optim_if keep_stmts s None bthen belse loc + let s_orig = Cil.get_original_stmt self#behavior s in + optim_if keep_stmts s_orig s None bthen belse loc | Switch (_exp, body, _, loc) -> (* the switch is invisible : it can be translated into a block. *) + rm_break_cont ~cont:false (self#fresh_label) finfo body; let block = Cil.visitCilBlock (self:>Cil.cilVisitor) body in (mk_new_block keep_stmts s block loc) - | Loop (_, body, loc, _yst1, _st2) -> - (* the loop test is invisible : - * the body it can be translated into a simple block. *) + | Loop (_, body, loc, _lcont, _lbreak) -> + rm_break_cont (self#fresh_label) finfo body; let bloop = Cil.visitCilBlock (self:>Cil.cilVisitor) body in - (mk_new_block keep_stmts s bloop loc) + mk_new_block keep_stmts s bloop loc | Block _ | UnspecifiedSequence _ -> assert false (* a block is always visible *) | TryFinally _ | TryExcept _ -> assert false (*TODO*) | Return (_,l) -> mk_new_stmt s (Return (None,l)) | _ -> mk_new_stmt s (mk_stmt_skip s)); + debug2 "@[<hov 10>[process_invisible_stmt] gives sid:%d@ @[%a@]@]@." + s.sid !Ast_printer.d_stmt s; s in s.skind <- mk_stmt_skip s; ChangeDoChildrenPost(s, do_after) method private process_visible_stmt s = - Kernel.debug ~level:2 "[filter:process_visible_stmt] sid:%d@." s.sid; + debug2 "[process_visible_stmt] does sid:%d@." s.sid; (match s.skind with - | Instr (Call (lval, funcexp, args, loc)) -> - let call = (lval, funcexp, args, loc) in - let new_call = self#process_call s call in - mk_new_stmt s new_call - | _ -> () (* copy the statement before modifying it *) - (* mk_new_stmt s [] s.skind *) + | Instr (Call (lval, funcexp, args, loc)) -> + let call = (lval, funcexp, args, loc) in + let new_call = self#process_call s call in + mk_new_stmt s new_call + | _ -> () (* copy the statement before modifying it *) + (* mk_new_stmt s [] s.skind *) ); let do_after s' = self#change_sid s'; (match s'.skind with | If (cond,bthen,belse,loc) -> - optim_if keep_stmts s' (Some cond) bthen belse loc + let s_orig = Cil.get_original_stmt self#behavior s' in + optim_if keep_stmts s_orig s' (Some cond) bthen belse loc | Switch (e,b,c,l) -> let c' = List.filter (not $ (can_skip keep_stmts)) c in s'.skind <- Switch(e,b,c',l) @@ -458,21 +581,31 @@ | _ -> ()) self#get_filling_actions | _ -> ()); + debug2 "@[<hov 10>[process_visible_stmt] gives sid:%d@ @[%a@]@]@." + s'.sid !Ast_printer.d_stmt s'; s' in Cil.ChangeDoChildrenPost (s, do_after) method vstmt_aux s = let finfo = self#get_finfo () in - let labels = filter_labels finfo s s.labels in + let rec filter_labels labels = match labels with + | [] -> [] + | l :: labs -> + let keep = Info.label_visible finfo s l || self#is_our_label l in + debug2 "[filter_labels] %svisible %a@." + (if keep then "" else "in") Cil.d_label l; + if keep then l::(filter_labels labs) else filter_labels labs + in + let labels = filter_labels s.labels in s.labels <- labels; match s.skind with - | Block _ | UnspecifiedSequence _ -> self#process_visible_stmt s - | _ when Info.inst_visible finfo s -> self#process_visible_stmt s - | _ -> self#process_invisible_stmt s + | Block _ | UnspecifiedSequence _ -> self#process_visible_stmt s + | _ when Info.inst_visible finfo s -> self#process_visible_stmt s + | _ -> self#process_invisible_stmt s method vfunc f = - Kernel.debug "@[[filter:vfunc] -> %s@\n@]@." f.svar.vname; + debug1 "@[[vfunc] -> %s@\n@]@." f.svar.vname; fi <- Some (Varinfo.Hashtbl.find fi_table f.svar); (* parameters *) let new_formals = @@ -529,8 +662,8 @@ let ensure_visible (_,p) = Info.fun_postcond_visible finfo p.ip_content in b.b_post_cond <- - filter_list ensure_visible (fun (k,p) -> k,self#visit_pred p) - b.b_post_cond; + filter_list ensure_visible (fun (k,p) -> k,self#visit_pred p) + b.b_post_cond; let from_visible a = Info.fun_assign_visible finfo a in let from_visit a = visitCilFrom (self:>Cil.cilVisitor) a in @@ -545,23 +678,23 @@ SkipChildren (* see the warning on [SkipChildren] in [vspec] ! *) method vspec spec = - Kernel.debug "@[[filter:vspec] for %a @\n@]@." - Kernel_function.pretty_name (Extlib.the self#current_kf); + debug1 "@[[vspec] for %a @\n@]@." + Kernel_function.pretty (Extlib.the self#current_kf); let finfo = self#get_finfo () in let b = Cil.visitCilBehaviors (self:>Cil.cilVisitor) spec.spec_behavior in let b = List.filter (not $ Cil.is_empty_behavior) b in spec.spec_behavior <- b; let new_variant = match spec.spec_variant with - | None -> None - | Some (t,n) -> if Info.fun_variant_visible finfo t + | None -> None + | Some (t,n) -> if Info.fun_variant_visible finfo t then Some (visitCilTerm (self:>Cil.cilVisitor) t, n) else None in spec.spec_variant <- new_variant ; let new_term = match spec.spec_terminates with - | None -> None - | Some p -> if Info.fun_precond_visible finfo p.ip_content + | None -> None + | Some p -> if Info.fun_precond_visible finfo p.ip_content then Some (self#visit_pred p) else None in @@ -579,11 +712,12 @@ let kf = Extlib.the self#current_kf in fi <- Some finfo; let new_var = ff_var fun_vars kf finfo in + let new_kf = make_new_kf my_kf kf new_var in Varinfo.Hashtbl.add fi_table new_var finfo; - Kernel.debug "@[[filter:build_cil_proto] -> %s@\n@]@." new_var.vname; + debug1 "@[[build_cil_proto] -> %s@\n@]@." new_var.vname; let action = - let (rt,args,va,attrs) = Cil.splitFunctionType new_var.vtype in - let () = + let (rt,args,va,attrs) = Cil.splitFunctionType new_var.vtype in + let () = match args with None -> () | Some args -> @@ -610,17 +744,19 @@ Queue.add (fun () -> Cil.unsafeSetFormalsDecl new_var new_formals) self#get_filling_actions - in - let res = Cil.visitCilFunspec (self:>Cil.cilVisitor) kf.spec in - let action () = + in + let res = Cil.visitCilFunspec (self:>Cil.cilVisitor) kf.spec in + let action () = (* Replace the funspec copied by the default visitor, as varinfo of formals would not be taken into account correctly - otherwise (everything would be mapped to the last set of + otherwise: everything would be mapped to the last set of formals... *) - Queue.add (fun () -> let kf = Globals.Functions.get new_var in - kf.spec <- res) self#get_filling_actions - in action + Queue.add + (fun () -> + !Globals.Functions.set_spec new_kf (fun _ -> res)) + self#get_filling_actions + in action (*end else fun () -> ()*) in let orig_var = Ast_info.Function.get_vi kf.fundec in @@ -628,18 +764,22 @@ by ff_var but directly by the visitor *) if (Cil.get_varinfo self#behavior orig_var) == orig_var then - Cil.set_varinfo self#behavior orig_var new_var; + Cil.set_varinfo self#behavior orig_var new_var; (* Set the new_var as an already known one, coming from the vi associated to the current kf. *) Cil.set_varinfo self#behavior new_var new_var; Cil.set_orig_varinfo self#behavior new_var orig_var; + Cil.set_kernel_function self#behavior kf new_kf; + Cil.set_orig_kernel_function self#behavior new_kf kf; + Queue.add + (fun () -> Globals.Functions.register new_kf) self#get_filling_actions; GVarDecl (Cil.empty_funspec(), new_var, loc), action method private compute_fct_prototypes (_fct_var,loc) = let finfo_list = Info.fct_info pinfo (Extlib.the self#current_kf) in - Kernel.debug "@[[filter:compute_fct_prototypes] for %a (x%d)@\n@]@." - Kernel_function.pretty_name (Extlib.the self#current_kf) + debug1 "@[[compute_fct_prototypes] for %a (x%d)@\n@]@." + Kernel_function.pretty (Extlib.the self#current_kf) (List.length finfo_list); let build_cil_proto finfo = self#build_proto finfo loc in List.map build_cil_proto finfo_list @@ -647,44 +787,52 @@ method private compute_fct_definitions f loc = let fvar = f.Cil_types.svar in let finfo_list = Info.fct_info pinfo (Extlib.the self#current_kf) in - Kernel.debug "@[[filter:compute_fct_definitions] for %a (x%d)@\n@]@." - Kernel_function.pretty_name - (Extlib.the self#current_kf) (List.length finfo_list); + debug1 "@[[compute_fct_definitions] for %a (x%d)@\n@]@." + Kernel_function.pretty + (Extlib.the self#current_kf) (List.length finfo_list); let do_f finfo = - if not (Info.body_visible finfo) then + if not (Info.body_visible finfo) then self#build_proto finfo loc - else begin - let new_fct_var = ff_var fun_vars (Extlib.the self#current_kf) finfo in + else begin + let kf = Extlib.the self#current_kf in + let new_fct_var = ff_var fun_vars kf finfo + in + let new_kf = make_new_kf my_kf kf new_fct_var in (* Set the new_var as an already known one, * coming from the vi associated to the current kf. *) Cil.set_varinfo self#behavior new_fct_var new_fct_var; Cil.set_orig_varinfo self#behavior new_fct_var fvar; + Cil.set_kernel_function self#behavior kf new_kf; + Cil.set_orig_kernel_function self#behavior new_kf kf; + Queue.add + (fun () -> Globals.Functions.register new_kf) + self#get_filling_actions; Varinfo.Hashtbl.add fi_table new_fct_var finfo; - Kernel.debug "@[[filter:build_cil_fct] -> %s@\n@]@." + debug1 "@[[build_cil_fct] -> %s@\n@]@." (Info.fct_name - (Kernel_function.get_vi (Extlib.the self#current_kf)) finfo); + (Kernel_function.get_vi (Extlib.the self#current_kf)) finfo); let action () = Queue.add (fun () -> - let kf = Globals.Functions.get new_fct_var in - kf.spec <- Varinfo.Hashtbl.find spec_table new_fct_var) + !Globals.Functions.set_spec new_kf + (fun _ -> Varinfo.Hashtbl.find spec_table new_fct_var)) self#get_filling_actions in let f = {f with svar = new_fct_var} in - (* [JS 2009/03/23] do not call self#vfunc in the assertion; - otherwise does not work whenever frama-c is compiled with - -no-assert *) - let res = self#vfunc f in - assert (res = SkipChildren); + (* [JS 2009/03/23] do not call self#vfunc in the assertion; + otherwise does not work whenever frama-c is compiled with + -no-assert *) + let res = self#vfunc f in + assert (res = SkipChildren); (* if this ever changes, we must do some work. *) GFun (f,loc), action - end + end in List.map do_f finfo_list method vglob_aux g = let post action g = List.iter (fun x -> x()) action; fi <- None; - Kernel.debug "[filter:post action] done.@."; + debug1 "[post action] done.@."; g in match g with @@ -697,24 +845,24 @@ begin match Cil.unrollType v.vtype with | TFun _ -> - Kernel.debug "[filter:vglob_aux] GVarDecl %s (TFun)@." v.vname; + debug1 "[vglob_aux] GVarDecl %s (TFun)@." v.vname; let var_decl = (v, loc) in let (new_decls,actions) = List.split (self#compute_fct_prototypes var_decl) in Cil.ChangeToPost (new_decls, post actions) | _ -> - Kernel.debug "[filter:vglob_aux] GVarDecl %s (other)@." v.vname; + debug1 "[vglob_aux] GVarDecl %s (other)@." v.vname; Cil.DoChildren end | _ -> Cil.DoChildren end let build_cil_file new_proj_name pinfo = - Kernel.debug "[filter:build_cil_file] in %s@." new_proj_name; + debug1 "[build_cil_file] in %s@." new_proj_name; let visitor = new filter_visitor pinfo in let prj = FC_file.create_project_from_visitor new_proj_name visitor in - Kernel.debug "[filter:build_cil_file] done.@."; + debug1 "[build_cil_file] done.@."; prj end diff -Nru frama-c-20110201+carbon+dfsg/src/misc/filter.mli frama-c-20111001+nitrogen+dfsg/src/misc/filter.mli --- frama-c-20110201+carbon+dfsg/src/misc/filter.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/filter.mli 2011-10-10 08:38:28.000000000 +0000 @@ -31,7 +31,7 @@ * have to be visible or not *) module type T_RemoveInfo = sig - (** exception that fun_assign_visible should raise to indicate that + (** exception that fun_assign_visible should raise to indicate that the corresponding assigns clause should be erased entirely *) exception EraseAssigns @@ -45,7 +45,7 @@ (** This function will be called for each function of the source program. * A new function will be created for each element of the returned list. *) - val fct_info : t_proj -> Db_types.kernel_function -> t_fct list + val fct_info : t_proj -> kernel_function -> t_fct list (** useful when we want to have several functions in the result for one * source function. If if is not the case, you can return [varinfo.vname]. @@ -70,17 +70,15 @@ (** tells if the label is visible. *) val label_visible : t_fct -> stmt -> label -> bool - (** tells if the annotation, attached to the given statement - (before when the flag is true, after otherwise) is visible. *) - val annotation_visible: t_fct -> stmt -> before:bool -> - code_annotation -> bool + (** tells if the annotation, attached to the given statement is visible. *) + val annotation_visible: t_fct -> stmt -> code_annotation -> bool val fun_precond_visible : t_fct -> predicate -> bool val fun_postcond_visible : t_fct -> predicate -> bool val fun_variant_visible : t_fct -> term -> bool val fun_assign_visible : t_fct -> identified_term from -> bool - (** true if the assigned value (first component of the from) is visible + (** true if the assigned value (first component of the from) is visible @raise EraseAssigns to indicate that the corresponding assigns clause should be erased entirely (i.e. assigns everything. If it were to just return false to all elements, this would result in assigns \nothing @@ -95,7 +93,7 @@ * The input [t_fct] parameter is the one of the caller function. * *) val called_info : t_proj * t_fct -> stmt -> - (Db_types.kernel_function * t_fct) option + (kernel_function * t_fct) option (** tells if the lvalue of the call has to be visible *) val res_call_visible : t_fct -> stmt -> bool @@ -110,7 +108,7 @@ * - [res_call_visible] must return [false] * if [result_visible] returns false on the called function. *) - val result_visible : Db_types.kernel_function -> t_fct -> bool + val result_visible : kernel_function -> t_fct -> bool end diff -Nru frama-c-20110201+carbon+dfsg/src/misc/service_graph.ml frama-c-20111001+nitrogen+dfsg/src/misc/service_graph.ml --- frama-c-20110201+carbon+dfsg/src/misc/service_graph.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/service_graph.ml 2011-10-10 08:38:28.000000000 +0000 @@ -28,7 +28,7 @@ val id: t -> int val name: t -> string val attributes: t -> Graph.Graphviz.DotAttributes.vertex list - val entry_point: unit -> t + val entry_point: unit -> t option end val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit @@ -61,21 +61,21 @@ include M module Datatype = Datatype.Make - (struct - (* [JS 2010/09/27] TODO: do better? *) - include Datatype.Serializable_undefined - type t = M.t - let name = G.datatype_name ^ " Service_graph.CallG.t" - let reprs = [ M.create () ] - let mem_project = Datatype.never_any_project - end) + (struct + (* [JS 2010/09/27] TODO: do better? *) + include Datatype.Serializable_undefined + type t = M.t + let name = G.datatype_name ^ " Service_graph.CallG.t" + let reprs = [ M.create () ] + let mem_project = Datatype.never_any_project + end) let () = Type.set_ml_name Datatype.ty None let add_labeled_edge g src l dst = if mem_edge g src dst then begin - remove_edge g src dst; - add_edge_e g (E.create src Both dst) + remove_edge g src dst; + add_edge_e g (E.create src Both dst) end else - add_edge_e g (E.create src l dst) + add_edge_e g (E.create src l dst) end type root = Is_root | In_service of vertex @@ -98,25 +98,25 @@ let edge_invariant src dst = function | Inter_functions -> assert - (if Vertex.equal src.root dst.root || dst.is_root then - true - else begin + (if Vertex.equal src.root dst.root || dst.is_root then + true + else begin Format.printf - "Src:%s in %s (is_root:%b) Dst:%s in %s (is_root:%b)@." + "Src:%s in %s (is_root:%b) Dst:%s in %s (is_root:%b)@." (G.V.name src.node) (G.V.name src.root.node) src.is_root (G.V.name dst.node) (G.V.name dst.root.node) dst.is_root; - false - end) + false + end) | Inter_services | Both -> assert (src.is_root && dst.is_root) let check_invariant callg = CallG.iter_edges_e (fun e -> - edge_invariant (CallG.E.src e) (CallG.E.dst e) (CallG.E.label e)) + edge_invariant (CallG.E.src e) (CallG.E.dst e) (CallG.E.label e)) callg let mem initial_roots node = @@ -126,34 +126,36 @@ exception Cannot_merge let merge_service s1 s2 = match s1, s2 with | Fresh_if_unchanged, (Maybe_fresh v2 | In_service v2) -> - To_be_confirmed v2 + To_be_confirmed v2 | (To_be_confirmed v1 | Final v1), In_service v2 when Vertex.equal v1 v2 -> - s1 + s1 | (To_be_confirmed v1 | Final v1), Maybe_fresh v2 - when Vertex.equal v1 v2 -> - To_be_confirmed v2 + when Vertex.equal v1 v2 -> + To_be_confirmed v2 | (To_be_confirmed v1 | Final v1), (Maybe_fresh v2 | In_service v2) -> - assert (not (Vertex.equal v1 v2)); - raise Cannot_merge + assert (not (Vertex.equal v1 v2)); + raise Cannot_merge let entry_point_ref = ref None let make_vertex g callg initial_roots node = let mk incomming_s = let v = match incomming_s with - | Fresh_if_unchanged -> - let rec v = { node = node; is_root = true; root = v } in v - | To_be_confirmed root | Final root -> - { node = node; is_root = false; root = root } + | Fresh_if_unchanged -> + let rec v = { node = node; is_root = true; root = v } in v + | To_be_confirmed root | Final root -> + { node = node; is_root = false; root = root } in - if G.V.equal node (G.V.entry_point ()) then entry_point_ref := Some v; + (match G.V.entry_point () with + | Some e when G.V.equal node e -> entry_point_ref := Some v + | None | Some _ -> ()); let s = match incomming_s with - | Fresh_if_unchanged | Final _ -> In_service v.root - | To_be_confirmed root -> Maybe_fresh root + | Fresh_if_unchanged | Final _ -> In_service v.root + | To_be_confirmed root -> Maybe_fresh root in - (* Format.printf "%s; root %s; final: %b@." - (G.V.name node) (G.V.name v.root.node) - (match s with In_service _ -> true | Maybe_fresh _ -> false);*) + (* Format.printf "%s; root %s; final: %b@." + (G.V.name node) (G.V.name v.root.node) + (match s with In_service _ -> true | Maybe_fresh _ -> false);*) Vertices.add node (v, s); CallG.add_vertex callg v in @@ -161,23 +163,23 @@ mk Fresh_if_unchanged else try - let service = - G.fold_pred - (fun node' acc -> - try - let _, s' = Vertices.find node' in - merge_service acc s' - with Not_found -> - acc) - g - node - Fresh_if_unchanged - in - (* if Fresh_if_unchanged at this point, - either node without predecessor or dominator cycle detected *) - mk service + let service = + G.fold_pred + (fun node' acc -> + try + let _, s' = Vertices.find node' in + merge_service acc s' + with Not_found -> + acc) + g + node + Fresh_if_unchanged + in + (* if Fresh_if_unchanged at this point, + either node without predecessor or dominator cycle detected *) + mk service with Cannot_merge -> - mk Fresh_if_unchanged + mk Fresh_if_unchanged let update_vertex g node = try @@ -185,22 +187,22 @@ match s with | In_service root -> assert (Vertex.equal v.root root) | Maybe_fresh root -> - assert (Vertex.equal v.root root); - try - G.iter_pred - (fun node' -> - try - let v', _ = Vertices.find node' in - if not (Vertex.equal root v'.root) then raise Exit - with Not_found -> - assert false) - g - node - (* old status is confirmed: nothing to do *) - with Exit -> - (* update *) - v.is_root <- true; - v.root <- v + assert (Vertex.equal v.root root); + try + G.iter_pred + (fun node' -> + try + let v', _ = Vertices.find node' in + if not (Vertex.equal root v'.root) then raise Exit + with Not_found -> + assert false) + g + node + (* old status is confirmed: nothing to do *) + with Exit -> + (* update *) + v.is_root <- true; + v.root <- v with Not_found -> assert false @@ -210,24 +212,24 @@ in G.iter_vertex (fun node -> - let v = find node in - G.iter_succ - (fun node' -> - let succ = find node' in - CallG.add_labeled_edge callg v Inter_functions succ; - let src_root = v.root in - let dst_root = succ.root in - if not (Vertex.equal src_root dst_root) then begin - CallG.add_labeled_edge callg src_root Inter_services dst_root - (* JS: no need of a `service_to_function' edge since - it is not possible to have an edge starting from a - not-a-root vertex and going to another service. - - no need of a `function_to_service' edge since the only - possible edges between two services go to a root. *) - end) - g - node) + let v = find node in + G.iter_succ + (fun node' -> + let succ = find node' in + CallG.add_labeled_edge callg v Inter_functions succ; + let src_root = v.root in + let dst_root = succ.root in + if not (Vertex.equal src_root dst_root) then begin + CallG.add_labeled_edge callg src_root Inter_services dst_root + (* JS: no need of a `service_to_function' edge since + it is not possible to have an edge starting from a + not-a-root vertex and going to another service. + + no need of a `function_to_service' edge since the only + possible edges between two services go to a root. *) + end) + g + node) g let compute g initial_roots = @@ -241,11 +243,7 @@ Vertices.clear (); callg - let entry_point () = match !entry_point_ref with - | None -> - Kernel.fatal "should call `Service_graph.compute' before calling \ -`Service_graph.entry_point'" - | Some s -> s + let entry_point () = !entry_point_ref (* *********************************************************************** *) (* Pretty-print *) @@ -263,11 +261,11 @@ let vertex_attributes s = let attr = - `Label + `Label (Pretty_utils.sfprintf "@[%a@]" !Ast_printer.d_ident - (G.V.name s.node)) - :: (`Color (Extlib.number_to_color (G.V.id s.root.node))) - :: G.V.attributes s.node + (G.V.name s.node)) + :: (`Color (Extlib.number_to_color (G.V.id s.root.node))) + :: G.V.attributes s.node in if s.is_root then `Shape `Diamond :: attr else attr @@ -285,9 +283,9 @@ Some { Graph.Graphviz.DotAttributes.sg_name = cs; sg_attributes = - [ `Label ("S " ^ cs); - `Color (Extlib.number_to_color id); - `Style `Bold ] } + [ `Label ("S " ^ cs); + `Color (Extlib.number_to_color id); + `Style `Bold ] } end @@ -299,9 +297,9 @@ module SS = Set.Make(struct - type t = G.V.t - let compare x y = Pervasives.compare (G.V.id x) (G.V.id y) - end) + type t = G.V.t + let compare x y = Pervasives.compare (G.V.id x) (G.V.id y) + end) type service_vertex = { service: int; mutable root: G.V.t; mutable nodes: SS.t } @@ -309,24 +307,24 @@ module SG = struct module M = Graph.Imperative.Digraph.ConcreteLabeled (struct - type t = service_vertex - let equal x y = x.service = y.service - let compare x y = Pervasives.compare x.service y.service - let hash x = x.service + type t = service_vertex + let equal x y = x.service = y.service + let compare x y = Pervasives.compare x.service y.service + let hash x = x.service end) (struct - type t = bool ref (* [true] for inter-service edge *) - let default = ref false - let compare = Pervasives.compare + type t = bool ref (* [true] for inter-service edge *) + let default = ref false + let compare = Pervasives.compare end) include M type tt = t module Datatype = Project.Datatype.Imperative - (struct - include M - let name = Project.Datatype.extend_name "Service_graph.SG " G.name - end) + (struct + include M + let name = Project.Datatype.extend_name "Service_graph.SG " G.name + end) end let get_service_id v = match v.mark with @@ -340,36 +338,36 @@ let id = get_service_id v in let node = v.node in try - let vertex = Hashtbl.find vertices id in - (* the service already exists *) - vertex.nodes <- SS.add node vertex.nodes; - if v.is_service then vertex.root <- node; - vertex + let vertex = Hashtbl.find vertices id in + (* the service already exists *) + vertex.nodes <- SS.add node vertex.nodes; + if v.is_service then vertex.root <- node; + vertex with Not_found -> - (* the service does not exist yet *) - let vertex = { service = id; root = node; nodes= SS.singleton node } in - SG.add_vertex sg vertex; - Hashtbl.add vertices id vertex; - vertex + (* the service does not exist yet *) + let vertex = { service = id; root = node; nodes= SS.singleton node } in + SG.add_vertex sg vertex; + Hashtbl.add vertices id vertex; + vertex in CallG.iter_edges (fun v1 v2 -> - let s1 = get_service v1 in - let s2 = get_service v2 in - match v1.is_service, v2.is_service with - | true, true -> - (try - let b = SG.E.label (SG.find_edge sg s1 s2) in - b := true - with Not_found -> - SG.add_edge sg s1 s2) - | true, false -> - assert false - | false, true -> - () - | false, false -> - if not (SG.mem_edge sg s1 s2 || SG.V.equal s1 s2) then - SG.add_edge sg s1 s2) + let s1 = get_service v1 in + let s2 = get_service v2 in + match v1.is_service, v2.is_service with + | true, true -> + (try + let b = SG.E.label (SG.find_edge sg s1 s2) in + b := true + with Not_found -> + SG.add_edge sg s1 s2) + | true, false -> + assert false + | false, true -> + () + | false, false -> + if not (SG.mem_edge sg s1 s2 || SG.V.equal s1 s2) then + SG.add_edge sg s1 s2) cg; sg diff -Nru frama-c-20110201+carbon+dfsg/src/misc/service_graph.mli frama-c-20111001+nitrogen+dfsg/src/misc/service_graph.mli --- frama-c-20110201+carbon+dfsg/src/misc/service_graph.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/service_graph.mli 2011-10-10 08:38:28.000000000 +0000 @@ -20,16 +20,21 @@ (* *) (**************************************************************************) +(** Compute services from a callgraph. *) + +(** Generic functor implementing the services algorithm according to a graph + implementation. *) module Make (G: sig type t module V: sig include Graph.Sig.HASHABLE val id: t -> int - (** assume is >= 0 and unique for each vertices of the graph *) + (** assume is >= 0 and unique for each vertices of the graph *) val name: t -> string val attributes: t -> Graph.Graphviz.DotAttributes.vertex list - val entry_point: unit -> t + val entry_point: unit -> t option + (** @modify Nitrogen-20111001 return an option*) end val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit @@ -53,9 +58,10 @@ val compute: G.t -> Datatype.String.Set.t -> CallG.t val output_graph: out_channel -> CallG.t -> unit - val entry_point: unit -> CallG.V.t + val entry_point: unit -> CallG.V.t option (** [compute] must be called before - @since Carbon-20101201 *) + @since Carbon-20101201 + @modify Nitrogen-20111001 return an option type *) module TP: Graph.Graphviz.GraphWithDotAttrs with type t = CallG.t diff -Nru frama-c-20110201+carbon+dfsg/src/misc/subst.ml frama-c-20111001+nitrogen+dfsg/src/misc/subst.ml --- frama-c-20110201+carbon+dfsg/src/misc/subst.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/subst.ml 2011-10-10 08:38:28.000000000 +0000 @@ -40,15 +40,15 @@ inherit nopCilVisitor method vexpr e = match e.enode with | Lval((Var x, NoOffset)) -> - (try - let e = M.find x subst in - modified := true; - let e = if trans then expr e else e in - ChangeTo e - with Not_found -> - SkipChildren) + (try + let e = M.find x subst in + modified := true; + let e = if trans then expr e else e in + ChangeTo e + with Not_found -> + SkipChildren) | _ -> - DoChildren + DoChildren end in visitCilExpr visitor e diff -Nru frama-c-20110201+carbon+dfsg/src/misc/subst.mli frama-c-20111001+nitrogen+dfsg/src/misc/subst.mli --- frama-c-20110201+carbon+dfsg/src/misc/subst.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/misc/subst.mli 2011-10-10 08:38:28.000000000 +0000 @@ -40,7 +40,7 @@ val expr: ?trans:bool -> exp -> t -> exp * bool (** Apply the substitution to an expression. If [trans], the substitution is transitively applied. Default is [true]. - For example, with subst = \{ x -> &y; y -> b \} and exp = x, the result + For example, with subst = \{ x -> &y; y -> b \} and exp = x, the result is &b by default and &y if trans is false. The returned boolean flag is true is a substitution occured. *) diff -Nru frama-c-20110201+carbon+dfsg/src/occurrence/options.ml frama-c-20111001+nitrogen+dfsg/src/occurrence/options.ml --- frama-c-20110201+carbon+dfsg/src/occurrence/options.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/occurrence/options.ml 2011-10-10 08:38:27.000000000 +0000 @@ -32,7 +32,7 @@ (struct let option_name = "-occurrence" let help = "print results of occurrence analysis" - let kind = `Tuning + let kind = Parameter.Other end) (* diff -Nru frama-c-20110201+carbon+dfsg/src/occurrence/options.mli frama-c-20111001+nitrogen+dfsg/src/occurrence/options.mli --- frama-c-20110201+carbon+dfsg/src/occurrence/options.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/occurrence/options.mli 2011-10-10 08:38:27.000000000 +0000 @@ -22,7 +22,7 @@ include Plugin.S -module Print: Plugin.BOOL +module Print: Plugin.Bool (** @plugin development guide *) (* diff -Nru frama-c-20110201+carbon+dfsg/src/occurrence/register_gui.ml frama-c-20111001+nitrogen+dfsg/src/occurrence/register_gui.ml --- frama-c-20110201+carbon+dfsg/src/occurrence/register_gui.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/occurrence/register_gui.ml 2011-10-10 08:38:27.000000000 +0000 @@ -26,15 +26,21 @@ open Cil_types open Cil_datatype -module Enabled= - State_builder.Ref + +(* Show or hide the 'Occurrence' column of the gui filetree. *) +let show_column = ref (fun () -> ()) + +(* Are results shown? *) +module Enabled = struct + include State_builder.Ref (Datatype.Bool) (struct - let name = "Occurrence_gui.Enabled" - let dependencies = [] - let kind = `Internal - let default () = true + let name = "Occrrence_gui.State" + let dependencies = [!Db.Occurrence.self] + let kind = `Internal + let default () = false end) +end let _ = Dynamic.register @@ -55,6 +61,7 @@ let find_occurrence (main_ui:Design.main_window_extension_points) vi () = ignore (!Db.Occurrence.get vi); Enabled.set true; + !show_column (); main_ui#rehighlight () (* Only these localizable interest this plugin *) @@ -73,23 +80,23 @@ () | Some (result, vi) -> let highlight () = - let tag = make_tag buffer "occurrence" [`BACKGROUND "yellow" ] in + let tag = make_tag buffer "occurrence" [`BACKGROUND "yellow" ] in apply_tag buffer tag start stop in match loc with | PLval (_, ki, lval) -> - let same_lval (k, l) = Kinstr.equal k ki && Lval.equal l lval in - if List.exists same_lval result then highlight () + let same_lval (k, l) = Kinstr.equal k ki && Lval.equal l lval in + if List.exists same_lval result then highlight () | PTermLval (_,ki,term_lval) -> - let same_tlval (k, l) = + let same_tlval (k, l) = Logic_utils.is_same_tlval - (Logic_utils.lval_to_term_lval ~cast:true l) - term_lval - && Kinstr.equal k ki - in - if List.exists same_tlval result then highlight () + (Logic_utils.lval_to_term_lval ~cast:true l) + term_lval + && Kinstr.equal k ki + in + if List.exists same_tlval result then highlight () | PVDecl(_, vi') when Varinfo.equal vi vi' -> - highlight () + highlight () | PVDecl _ | PStmt _ | PGlobal _ | PIP _ -> () module FollowFocus = @@ -125,7 +132,7 @@ localizable in ignore (set_selected#connect#pressed - (fun () -> Design.apply_on_selected do_select)); + (fun () -> History.apply_on_selected do_select)); (* check_button enabled *) let enabled = Enabled.get () in let enabled_button = GButton.check_button @@ -139,6 +146,7 @@ ~callback: (fun () -> Enabled.set enabled_button#active; + !show_column (); main_ui#rehighlight ())); (* check_button followFocus *) let followFocus = GButton.check_button @@ -154,18 +162,21 @@ let old_vi = ref (-2) in fun () -> (let sensitive_set_selected_button = ref false in - Design.apply_on_selected + History.apply_on_selected (apply_on_vi (fun _ -> sensitive_set_selected_button:=true)); set_selected#misc#set_sensitive !sensitive_set_selected_button; - enabled_button#set_active (Enabled.get()); + if Enabled.get () <> enabled_button#active then ( + enabled_button#set_active (Enabled.get ()); + !show_column (); + ); let new_result = !Db.Occurrence.get_last_result () in (match new_result with - | None when !old_vi<> -1 -> + | None when !old_vi<> -1 -> old_vi := -1; e#set_label "<i>None</i>" - | Some (_,vi) when vi.vid<> !old_vi-> + | Some (_,vi) when vi.vid<> !old_vi-> old_vi := vi.vid; e#set_label vi.vname - | _ -> ())) + | _ -> ())) in "Occurrence",w#coerce,Some refresh @@ -177,38 +188,42 @@ let callback = find_occurrence main_ui vi in ignore (popup_factory#add_item "_Occurrence" ~callback); if FollowFocus.get () then - ignore (Glib.Idle.add (fun () -> callback (); false)) + ignore (Glib.Idle.add (fun () -> callback (); false)) end) localizable let file_tree_decorate (file_tree:Filetree.t) = - file_tree#append_pixbuf_column - "Occurrence" - (fun globs -> - match !Db.Occurrence.get_last_result () with - | None -> (* occurrence not computed *) - [`STOCK_ID ""] - | Some (result, _) -> - let in_globals (ki,_) = - match ki with - | Kglobal -> false - | Kstmt stmt -> - let kf = Kernel_function.find_englobing_kf stmt in - let {vid=v0} = Kernel_function.get_vi kf in - List.exists - (fun glob -> match glob with - | GFun ({svar ={vid=v1}},_ ) -> v1=v0 - | _ -> false) - globs - in - if List.exists in_globals result then [`STOCK_ID "gtk-apply"] - else [`STOCK_ID ""]) + show_column := + file_tree#append_pixbuf_column + ~title:"Occurrence" + (fun globs -> + match !Db.Occurrence.get_last_result () with + | None -> (* occurrence not computed *) + [`STOCK_ID ""] + | Some (result, _) -> + let in_globals (ki,_) = + match ki with + | Kglobal -> false + | Kstmt stmt -> + let kf = Kernel_function.find_englobing_kf stmt in + let {vid=v0} = Kernel_function.get_vi kf in + List.exists + (fun glob -> match glob with + | GFun ({svar ={vid=v1}},_ ) -> v1=v0 + | _ -> false) + globs + in + if List.exists in_globals result then [`STOCK_ID "gtk-apply"] + else [`STOCK_ID ""]) + (fun () -> Enabled.get ()); + !show_column () let main main_ui = main_ui#register_source_selector occurrence_selector; main_ui#register_source_highlighter occurrence_highlighter; main_ui#register_panel occurrence_panel; - file_tree_decorate main_ui#file_tree + file_tree_decorate main_ui#file_tree; +;; let () = Design.register_extension main diff -Nru frama-c-20110201+carbon+dfsg/src/occurrence/register.ml frama-c-20111001+nitrogen+dfsg/src/occurrence/register.ml --- frama-c-20110201+carbon+dfsg/src/occurrence/register.ml 2011-02-07 13:53:54.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/occurrence/register.ml 2011-10-10 08:38:27.000000000 +0000 @@ -37,9 +37,9 @@ Cil_state_builder.Varinfo_hashtbl (Datatype.Pair(Kinstr)(Lval)) (struct - let size = 17 - let name = "Occurrences.State" - let dependencies = [ Db.Value.self ] + let size = 17 + let name = "Occurrences.State" + let dependencies = [ Db.Value.self ] let kind = `Internal end) @@ -47,8 +47,8 @@ State_builder.Option_ref (Varinfo) (struct - let name = "Occurrences.LastResult" - let dependencies = [ Ast.self; IState.self ] + let name = "Occurrences.LastResult" + let dependencies = [ Ast.self; IState.self ] let kind = `Internal end) @@ -74,16 +74,16 @@ let iter f = let old, l = IState.fold - (fun v elt (old, l) -> match v, old with - | v, None -> - assert (l = []); - Some v, [ elt ] - | v, (Some old as some) when Varinfo.equal v old -> - some, elt :: l - | v, Some old -> - f old l; - Some v, [ elt ]) - (None, []) + (fun v elt (old, l) -> match v, old with + | v, None -> + assert (l = []); + Some v, [ elt ] + | v, (Some old as some) when Varinfo.equal v old -> + some, elt :: l + | v, Some old -> + f old l; + Some v, [ elt ]) + (None, []) in Extlib.may (fun v -> f v l) old @@ -105,8 +105,8 @@ let ki = self#current_ki in if Db.Value.is_accessible ki then begin let z = - !Db.Value.lval_to_zone - ki ~with_alarms:CilE.warn_none_mode (Var vi, NoOffset) + !Db.Value.lval_to_zone + ki ~with_alarms:CilE.warn_none_mode (Var vi, NoOffset) in decls <- (vi, z) :: decls end; @@ -119,7 +119,7 @@ if not (Locations.Zone.equal Locations.Zone.bottom z) then List.iter (fun (vi, zvi) -> - if Locations.Zone.intersects z zvi then Occurrences.add vi ki lv) + if Locations.Zone.intersects z zvi then Occurrences.add vi ki lv) decls end; DoChildren @@ -129,7 +129,7 @@ let lv = !Db.Properties.Interp.term_lval_to_lval ~result:None tlv in ignore (self#vlval lv) with Invalid_argument msg -> - error "%s@." msg); + error ~current:true "%s@." msg); DoChildren method vstmt_aux s = @@ -157,7 +157,17 @@ | Kstmt s -> Format.fprintf fmt "%d" s.sid let print_one fmt v l = - Format.fprintf fmt "variable %s (%d):@\n" v.vname v.vid; + Format.fprintf fmt "variable %s (%s):@\n" + v.vname + (if v.vglob then "global" + else + let kf_name = match l with + | [] | (Kglobal, _) :: _ -> assert false + | (Kstmt s, _) :: _ -> + Kernel_function.get_name (Kernel_function.find_englobing_kf s) + in + if v.vformal then "parameter of " ^ kf_name + else "local of " ^ kf_name); List.iter (fun (ki, lv) -> Format.fprintf fmt " sid %a: %a@\n" d_ki ki d_lval lv) l @@ -173,8 +183,13 @@ Db.register (Db.Journalize ("Occurrence.get", - Datatype.func - Varinfo.ty (Datatype.list (Datatype.pair Kinstr.ty Lval.ty)))) + Datatype.func + Varinfo.ty + (* [JS 2011/04/01] Datatype.list buggy in presence of journalisation. + See comment in datatype.ml *) + (*(Datatype.list (Datatype.pair Kinstr.ty Lval.ty))*) + (let module L = Datatype.List(Datatype.Pair(Kinstr)(Lval)) in + L.ty))) Db.Occurrence.get get; Db.register diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/annot.ml frama-c-20111001+nitrogen+dfsg/src/pdg/annot.ml --- frama-c-20110201+carbon+dfsg/src/pdg/annot.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/annot.ml 2011-10-10 08:38:30.000000000 +0000 @@ -25,18 +25,15 @@ open Cil_types open Cil_datatype -module M = Macros -module G = PdgTypes.G -module Dpd = PdgTypes.Dpd -module FI = PdgIndex.FctIndex -module Key = PdgIndex.Key +open PdgTypes +open PdgIndex -type data_info = ((PdgTypes.Node.t * Locations.Zone.t option) list +type data_info = ((Node.t * Locations.Zone.t option) list * Locations.Zone.t option) option -type ctrl_info = PdgTypes.Node.t list +type ctrl_info = Node.t list -type decl_info = PdgTypes.Node.t list +type decl_info = Node.t list let zone_info_nodes pdg data_info = let add_info_nodes pdg (nodes_acc, undef_acc) info = @@ -47,7 +44,7 @@ Locations.Zone.pretty zone (if before then "before" else "after") stmt.sid; let nodes, undef_loc = - Sets.find_location_nodes_at_stmt pdg stmt before zone + Sets.find_location_nodes_at_stmt pdg stmt ~before zone in let undef_acc = match undef_acc, undef_loc with | None, _ -> undef_loc @@ -71,13 +68,13 @@ Varinfo.Set.fold add_decl_nodes decl_info [] let find_nodes_for_function_contract pdg f_interpret = - let kf = M.get_pdg_kf pdg in + let kf = Pdg.get_kf pdg in let (data_info, decl_info) = f_interpret kf in let data_dpds = zone_info_nodes pdg data_info in let decl_nodes = get_decl_nodes pdg decl_info in decl_nodes, data_dpds -let find_fun_precond_nodes (pdg:PdgTypes.Pdg.t) p = +let find_fun_precond_nodes (pdg:Pdg.t) p = let named_p = { name = []; loc = Location.unknown; content = p } in let f_interpret kf = let f_ctx = !Db.Properties.Interp.To_zone.mk_ctx_func_contrat @@ -92,13 +89,13 @@ ~state_opt:(Some false) kf in !Db.Properties.Interp.To_zone.from_pred named_p f_ctx in let nodes,deps = find_nodes_for_function_contract pdg f_interpret - in let nodes = - (* find is \result is used in p, and if it is the case, - * add the node [Sets.find_output_node pdg] + in let nodes = + (* find is \result is used in p, and if it is the case, + * add the node [Sets.find_output_node pdg] * to the returned list of nodes. *) if !Db.Properties.Interp.to_result_from_pred named_p then - (Sets.find_output_node pdg)::nodes + (Sets.find_output_node pdg)::nodes else nodes in nodes,deps @@ -109,17 +106,16 @@ !Db.Properties.Interp.To_zone.from_term t f_ctx in find_nodes_for_function_contract pdg f_interpret -let find_code_annot_nodes pdg ~before stmt annot = - Pdg_parameters.debug "[pdg:annotation] CodeAnnot-%d %s stmt %d : %a @." - annot.annot_id - (if before then "before" else "after") stmt.sid +let find_code_annot_nodes pdg stmt annot = + Pdg_parameters.debug "[pdg:annotation] CodeAnnot-%d stmt %d : %a @." + annot.annot_id stmt.sid !Ast_printer.d_code_annotation annot; - if Db.Value.is_accessible (Cil_types.Kstmt stmt) then + if Db.Value.is_reachable_stmt stmt then try begin - let kf = M.get_pdg_kf pdg in + let kf = Pdg.get_kf pdg in let (data_info, decl_info), pragmas = - !Db.Properties.Interp.To_zone.from_stmt_annot annot ~before (stmt, kf) + !Db.Properties.Interp.To_zone.from_stmt_annot annot (stmt, kf) in let data_dpds = zone_info_nodes pdg data_info in let decl_nodes = get_decl_nodes pdg decl_info in @@ -138,15 +134,15 @@ let ctrl_dpds = Stmt.Set.fold add_stmt_nodes stmt_pragmas ctrl_dpds in if Pdg_parameters.debug_atleast 2 then begin let p fmt (n,z) = match z with - | None -> PdgTypes.Node.pretty fmt n + | None -> Node.pretty fmt n | Some z -> Format.fprintf fmt "%a(%a)" - PdgTypes.Node.pretty n Locations.Zone.pretty z + Node.pretty n Locations.Zone.pretty z in let pl fmt l = List.iter (fun n -> Format.fprintf fmt " %a" p n) l in Pdg_parameters.debug " ctrl nodes = %a" - PdgTypes.Node.pretty_list ctrl_dpds; + Node.pretty_list ctrl_dpds; Pdg_parameters.debug " decl nodes = %a" - PdgTypes.Node.pretty_list decl_nodes; + Node.pretty_list decl_nodes; match data_dpds with | None -> Pdg_parameters.debug " data nodes = None (failed to compute)" @@ -169,7 +165,7 @@ Pdg_parameters.debug ~level:2 "[pdg:annotation] CodeAnnot-%d : unreachable stmt ! @." annot.annot_id; - raise PdgIndex.NotFound (* unreachable statement *) + raise Not_found (* unreachable statement *) end (* diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/annot.mli frama-c-20111001+nitrogen+dfsg/src/pdg/annot.mli --- frama-c-20110201+carbon+dfsg/src/pdg/annot.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/annot.mli 2011-10-10 08:38:30.000000000 +0000 @@ -45,8 +45,7 @@ (** @raise Not_found when the statement is unreachable. *) val find_code_annot_nodes : - PdgTypes.Pdg.t -> - before:bool -> Cil_types.stmt -> Cil_types.code_annotation -> + PdgTypes.Pdg.t -> Cil_types.stmt -> Cil_types.code_annotation -> ctrl_info * decl_info * data_info val find_fun_precond_nodes : PdgTypes.Pdg.t -> Cil_types.predicate -> diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/build.ml frama-c-20111001+nitrogen+dfsg/src/pdg/build.ml --- frama-c-20110201+carbon+dfsg/src/pdg/build.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/build.ml 2011-10-10 08:38:30.000000000 +0000 @@ -33,12 +33,14 @@ {!module: Build.Computer} below). *) +let dkey = "build" +let debug fmt = Pdg_parameters.debug ~dkey fmt +let debug2 fmt = Pdg_parameters.debug ~dkey fmt ~level:2 + open Cil_types module IH = Inthash open Cil_datatype -module M = Macros -module P = Pdg_parameters module G = PdgTypes.G module Dpd = PdgTypes.Dpd module FI = PdgIndex.FctIndex @@ -48,24 +50,30 @@ exception Err_Bot of string (** set of nodes of the graph *) -module SimpleNodeSet = Set.Make(PdgTypes.Node) +module BoolNodeSet = Set.Make(Datatype.Pair(Datatype.Bool)(PdgTypes.Node)) (* for mk_list_zones see Locations.Zone.fold_enum_by_base *) +let pretty_node ?(key=false) fmt n = + PdgTypes.Node.pretty fmt n; + if key then + Format.fprintf fmt ": %a" PdgIndex.Key.pretty (PdgTypes.Node.elem_key n) + let is_variadic kf = let varf = Kernel_function.get_vi kf in match varf.vtype with - TFun (_, _, is_variadic, _) -> is_variadic - | _ -> (Macros.bug - "The variable of a kernel_function has to be a function !") - + | TFun (_, _, is_variadic, _) -> is_variadic + | _ -> Pdg_parameters.fatal + "The variable of a kernel_function has to be a function !" (** add a dependency with the given label between the two nodes. Pre : the nodes have to be already in pdg. *) let add_dpd_in_g graph v1 dpd_kind part_opt v2 = (* let part_opt = match part_opt with Some _ | None -> None in *) - P.debug "add_dpd : %a -> %a@." Macros.pretty_node v1 Macros.pretty_node v2; + debug "add_dpd : %a -%a-> %a@." + PdgTypes.Node.pretty v1 Dpd.pretty_td dpd_kind + PdgTypes.Node.pretty v2; G.add_dpd graph v1 dpd_kind part_opt v2 (** Module to build the PDG. *) @@ -74,9 +82,9 @@ type t (** create an empty pdg for the function*) - val create : Db_types.kernel_function -> t + val create : kernel_function -> t - val get_kf : t -> Db_types.kernel_function + val get_kf : t -> kernel_function val pretty : Format.formatter -> t -> unit @@ -89,6 +97,8 @@ val print_state : Format.formatter -> t_state -> unit + val empty_state : t_state + (** type to describe the data locations (to store information in [t_state]) *) type t_loc = Locations.Zone.t @@ -114,7 +124,14 @@ (** for skip statement : we want to add a node in the PDG in ordrer to be able * to store information (like marks) about this statement later on *) - val process_skip : t -> Cil_types.stmt -> unit + val process_skip : t -> t_state -> Cil_types.stmt -> t_state option + + (** similar to [process_skip] but returns an empty state (bottom)*) + val process_unreachable : t -> t_state -> Cil_types.stmt -> t_state option + + (** similar to [process_unreachable] but for call stmt *) + val process_unreachable_call : + t -> t_state -> Cil_types.stmt -> t_state option (** Add a node for the stmt which is a jump. Add control dependencies from this node @@ -123,7 +140,8 @@ Don't use for jumps with data dependencies : use [process_jump_with_exp] instead ! *) - val process_jump : t -> Cil_types.stmt -> Cil_types.stmt list -> unit + val process_jump : t -> Cil_types.stmt -> + bool * Cil_datatype.Stmt.Hptset.t -> unit val process_block : t -> Cil_types.stmt -> Cil_types.block -> unit @@ -134,11 +152,11 @@ For conditional jumps and returns. *) val process_jump_with_exp : - t -> Cil_types.stmt -> Cil_types.stmt list -> + t -> Cil_types.stmt -> (bool * Cil_datatype.Stmt.Hptset.t) -> t_state -> t_loc -> Varinfo.Set.t -> unit - (** Kind of 'join' of hte two states + (** Kind of 'join' of the two states * but test before if the new state is included in ~old. * @return (true, old U new) if the result is a new state, * (false, old) if new is included in old. @@ -151,9 +169,9 @@ val process_call_args : t -> t_state -> Cil_types.stmt -> (t_loc * Varinfo.Set.t) list -> - (int * t_arg_nodes) + (t_arg_nodes) val process_call_params : t -> t_state -> Cil_types.stmt -> - Db_types.kernel_function -> t_arg_nodes -> + kernel_function -> t_arg_nodes -> t_state val process_call_ouput : t -> t_state -> t_state -> Cil_types.stmt -> @@ -190,15 +208,15 @@ (** The PDG used during its computation. *) - type t = { fct : Db_types.kernel_function; + type t = { fct : kernel_function; mutable topinput : PdgTypes.Node.t option; mutable other_inputs : (PdgTypes.Node.t * Dpd.td * Locations.Zone.t) list; graph : G.t; states : Pdg_state.t_states; - index : PdgTypes.Pdg.t_index; + index : PdgTypes.Pdg.t_fi; - ctrl_dpds : SimpleNodeSet.t Kinstr.Hashtbl.t ; + ctrl_dpds : BoolNodeSet.t Stmt.Hashtbl.t ; (** The nodes to which each stmt control-depend on. * The links will be added in the graph at the end. *) decl_nodes : t_node Varinfo.Hashtbl.t ; @@ -206,20 +224,19 @@ to build the dependencies. *) } + let empty_state = Pdg_state.empty + let create kf = let nb_stmts = - try - let fundec = Kernel_function.get_definition kf in - List.length fundec.sallstmts - with Kernel_function.No_Definition -> - 42 + if !Db.Value.use_spec_instead_of_definition kf then 17 + else List.length (Kernel_function.get_definition kf).sallstmts in let index = FI.create nb_stmts in let states = IH.create nb_stmts in let graph = G.create () in { fct = kf; graph = graph; states = states; index = index; topinput = None; other_inputs = []; - ctrl_dpds = Kinstr.Hashtbl.create nb_stmts ; + ctrl_dpds = Stmt.Hashtbl.create nb_stmts ; decl_nodes = Varinfo.Hashtbl.create 10 ; } @@ -240,7 +257,7 @@ let add_elem pdg key = let add_new_node key = let new_node = G.add_elem (graph pdg) key in - P.debug "add_new_node %a @." PdgTypes.Node.pretty new_node; + debug "add_new_node %a@." (pretty_node ~key:true) new_node; new_node in let index = nodes_index pdg in @@ -249,7 +266,7 @@ | Key.CallStmt _ -> assert false (*FI.find_info_call index (Key.call_from_id call_id)*) | _ -> FI.find_info index key - with PdgIndex.NotFound -> + with Not_found -> let new_node = add_new_node key in let _ = match key with | Key.CallStmt _call_id -> assert false @@ -263,15 +280,13 @@ let topinput pdg = match pdg.topinput with | None -> - let key = Key.top_input in - let topinput = add_elem pdg key in + let topinput = add_elem pdg Key.top_input in pdg.topinput <- Some topinput; topinput | Some top -> top let decl_var pdg var = - let key = Key.decl_var_key var in - let new_node = add_elem pdg key in + let new_node = add_elem pdg (Key.decl_var_key var) in Varinfo.Hashtbl.add pdg.decl_nodes var new_node; new_node @@ -302,7 +317,7 @@ let var_decl_node = Varinfo.Hashtbl.find pdg.decl_nodes var in add_decl_dpd pdg node dpd_kind var_decl_node with Not_found -> - () + () in Varinfo.Set.iter add_dpd varset @@ -325,38 +340,63 @@ match undef_zone with None -> () | Some undef_zone -> add_to_inputs pdg n dpd_kind undef_zone + (** Process and clear [pdg.ctrl_dpds] which contains a mapping between the * statements and the control dependencies that have to be added to the - * statement nodes. *) + * statement nodes. + * Because some jump nodes can vanish due to optimisations using the value + * analysis, we can not rely on the transitivity of the dependencies. + * So let's compute a transitive closure of the control dependencies. + * The table gives : stmt -> ctrl dependency nodes of the statement. + * So for each stmt, we have to find if some of its ctrl nodes + * also have dependencies that have to be added to the stmt. + * *) let add_ctrl_dpds pdg = - let add_node_ctrl_dpd n ctrl_node = add_ctrl_dpd pdg n ctrl_node in - let add_node_ctrl_dpds n ctrl_node_set = - SimpleNodeSet.iter (add_node_ctrl_dpd n) ctrl_node_set in - let add_stmt_ctrl_dpd ki ctrl_node_set = + let add_indirect ctrl_node_set = + (* Also add the ctrl_node dependencies to the set. + * TODOopt: probably a better way to do that if it happens to work ! *) + let rec add_node (real, n) (acc, seen) = + if BoolNodeSet.mem (real, n) seen then (acc, seen) + else + let seen = BoolNodeSet.add (real, n) seen in + let acc = if real then BoolNodeSet.add (true, n) acc else acc in + add_rec n (acc, seen) + and add_rec ctrl_node acc = + match PdgTypes.Node.elem_key ctrl_node with + | Key.Stmt ctrl_stmt -> + (try + let stmt_dpds = Stmt.Hashtbl.find pdg.ctrl_dpds ctrl_stmt in + BoolNodeSet.fold add_node stmt_dpds acc + with Not_found -> acc) + | _ -> (* strange control dependency ! Ignore. *) acc + in + let acc = BoolNodeSet.empty, BoolNodeSet.empty in + let acc, _ = BoolNodeSet.fold add_node ctrl_node_set acc in + acc + in + let add_stmt_ctrl_dpd stmt ctrl_node_set = let index = nodes_index pdg in - let label_nodes stmt labels label = - try labels @ FI.find_all index (Key.label_key stmt label) - with PdgIndex.NotFound -> labels + let stmt_nodes = + try FI.find_all index (Key.stmt_key stmt) + with Not_found -> [] + (* some stmts have no node if they are dead code for instance*) + in + let label_nodes acc label = + try acc @ FI.find_all index (Key.label_key stmt label) + with Not_found -> acc in - match ki with - | Kstmt stmt -> - let lab_nodes = - List.fold_left (label_nodes stmt) [] stmt.labels - in - let stmt_nodes = - try FI.find_all index (Key.stmt_key stmt) - with PdgIndex.NotFound -> [] - (* some stmts have no node if they are dead code for - * instance*) - in - let nodes = lab_nodes @ stmt_nodes in - List.iter (fun n -> add_node_ctrl_dpds n ctrl_node_set) nodes - | _ -> assert false + let stmt_nodes = List.fold_left label_nodes stmt_nodes stmt.labels in + let ctrl_node_set = add_indirect ctrl_node_set in + let add_node_ctrl_dpds stmt_node = + BoolNodeSet.iter + (fun (_, n) -> add_ctrl_dpd pdg stmt_node n) ctrl_node_set + in List.iter add_node_ctrl_dpds stmt_nodes in - Kinstr.Hashtbl.iter add_stmt_ctrl_dpd pdg.ctrl_dpds; - Kinstr.Hashtbl.clear pdg.ctrl_dpds + Stmt.Hashtbl.iter add_stmt_ctrl_dpd pdg.ctrl_dpds; + Stmt.Hashtbl.clear pdg.ctrl_dpds let test_and_merge_states = Pdg_state.test_and_merge + let print_state = Pdg_state.pretty let process_declarations pdg ~formals ~locals = @@ -374,8 +414,7 @@ *) let do_param (n, state) v = let decl_node = decl_var pdg v in - let key = Key.param_key n v in - let new_node = add_elem pdg key in + let new_node = add_elem pdg (Key.param_key n) in add_decl_dpd pdg new_node Dpd.Addr decl_node ; add_decl_dpd pdg decl_node Dpd.Addr new_node ; let new_state = @@ -385,31 +424,24 @@ in let _next_in_num, new_state = List.fold_left do_param (1, empty_state) formals in - (* set_max_in pdg (next_in_num - 1); *) - - (* local variables *) List.iter (fun v -> ignore (decl_var pdg v)) locals; - new_state let process_call_node pdg call_stmt = - let key = Key.call_ctrl_key call_stmt in - let _new_node = add_elem pdg key in () + ignore (add_elem pdg (Key.call_ctrl_key call_stmt)) let ctrl_call_node pdg call_stmt = try FI.find_info (nodes_index pdg) (Key.call_ctrl_key call_stmt) - with PdgIndex.NotFound -> assert false + with Not_found -> assert false let process_call_args pdg d_state stmt args_dpds = let num = ref 1 in let process_arg (dpds, decl_dpds) = - let key = Key.call_input_key stmt !num in - let new_node = add_elem pdg key in + let new_node = add_elem pdg (Key.call_input_key stmt !num) in let _ = add_dpds pdg new_node Dpd.Data d_state dpds in let _ = add_decl_dpds pdg new_node Dpd.Data decl_dpds in - num := !num+1; new_node - in let arg_nodes = List.map process_arg args_dpds in - !num, arg_nodes + incr num; new_node + in List.map process_arg args_dpds (** Add a PDG node for each formal argument, * and add its dependencies to the corresponding argument node. @@ -432,7 +464,8 @@ | [], _ -> (* call to a variadic function *) (* warning already sent during 'from' computation. *) state - | _, [] -> Macros.bug "call to a function with to few arguments" + | _, [] -> Pdg_parameters.fatal + "call to a function with to few arguments" in do_param_arg d_state param_list arg_nodes let create_call_output_node pdg state stmt out_key out_from fct_dpds = @@ -452,8 +485,7 @@ (new_node, new_state) let add_from pdg state_before state lval (default, deps) = - let key = Key.out_from_key lval in - let new_node = add_elem pdg key in + let new_node = add_elem pdg (Key.out_from_key lval) in let exact = (not default) in let state = Pdg_state.add_loc_node state exact lval new_node in let _ = add_dpds pdg new_node Dpd.Data state_before deps in @@ -465,7 +497,7 @@ (* TODO : Check this with Pascal ! * (Locations.Zone.cardinal_zero_or_one out) && *) (not default) in - P.debug "call-%d Out%d : %a From %a (%sexact)@." + debug "call-%d Out%d : %a From %a (%sexact)@." stmt.sid numout Locations.Zone.pretty out Locations.Zone.pretty from_out (if exact then "" else "not "); @@ -485,10 +517,10 @@ in let _ = add_dpds pdg new_node Dpd.Addr state_before_call l_dpds in let _ = add_decl_dpds pdg new_node Dpd.Addr l_decl in - let new_state = Pdg_state.add_loc_node state_before_call exact l_loc new_node in + let new_state = + Pdg_state.add_loc_node state_before_call exact l_loc new_node in new_state - let process_asgn pdg d_state stmt ~l_loc ~exact ~l_dpds ~l_decl ~r_dpds ~r_decl = let key = Key.stmt_key stmt in @@ -498,15 +530,22 @@ let _ = add_decl_dpds pdg new_node Dpd.Data r_decl in new_state - let process_skip pdg stmt = - let key = Key.stmt_key stmt in - let _new_node = add_elem pdg key in - () - + let process_skip pdg _state stmt = + let _new_node = add_elem pdg (Key.stmt_key stmt) in + None (* keep previous state *) + + let process_unreachable _pdg _state _stmt = + (* let key = Key.stmt_key stmt in + let _new_node = add_elem pdg key in *) + Some Pdg_state.empty + + let process_unreachable_call _pdg _state _call_stmt = + (* let key = Key.call_ctrl_key call_stmt in + let _new_node = add_elem pdg key in *) + Some Pdg_state.empty let add_label pdg label label_stmt jump_node = - let key = Key.label_key label_stmt label in - let label_node = add_elem pdg key in + let label_node = add_elem pdg (Key.label_key label_stmt label) in add_ctrl_dpd pdg jump_node label_node let add_dpd_goto_label pdg goto_node dest_goto = @@ -515,9 +554,15 @@ | Label _ as lab :: _ -> Some lab | _ :: rest -> pickLabel rest in - match pickLabel dest_goto.labels with - | Some label -> add_label pdg label dest_goto goto_node - | None -> assert false (* goto sans label ??? *) + let label = match pickLabel dest_goto.labels with + | Some label -> label + | None -> + (* break and continue might not jump to a stmt with label : create one*) + let lname = Printf.sprintf "fc_stmt_%d" dest_goto.sid in + let label = Label (lname, Cil_datatype.Stmt.loc dest_goto, false) in + dest_goto.labels <- label::dest_goto.labels; + label + in add_label pdg label dest_goto goto_node let add_dpd_switch_cases pdg switch_node case_stmts = let add_case stmt = @@ -532,29 +577,33 @@ | None -> assert false (* switch sans case ou default ??? *) in List.iter add_case case_stmts - (* The control dependencies are stored : they will be added at the end + (** The control dependencies are stored : they will be added at the end by [finalize_pdg] *) - let store_ctrl_dpds pdg node controled_stmt = + let store_ctrl_dpds pdg node iterator (real_dpd, controled_stmt) = + debug2 "store_ctrl_dpds on %a (real = %b)@." + (pretty_node ~key:true) node real_dpd ; let add_ctrl_dpd stmt = - let kinstr = (Kstmt stmt) in let new_dpds = try - let old_dpds = Kinstr.Hashtbl.find pdg.ctrl_dpds kinstr in - SimpleNodeSet.add node old_dpds - with Not_found -> SimpleNodeSet.singleton node + let old_dpds = Stmt.Hashtbl.find pdg.ctrl_dpds stmt in + BoolNodeSet.add (real_dpd, node) old_dpds + with Not_found -> BoolNodeSet.singleton (real_dpd, node) in - Kinstr.Hashtbl.replace pdg.ctrl_dpds kinstr new_dpds - in List.iter add_ctrl_dpd controled_stmt + Stmt.Hashtbl.replace pdg.ctrl_dpds stmt new_dpds + in iterator add_ctrl_dpd controled_stmt let mk_jump_node pdg stmt controled_stmts = - let key = Key.stmt_key stmt in - let new_node = add_elem pdg key in + let new_node = add_elem pdg (Key.stmt_key stmt) in let _ = match stmt.skind with - | If _ | Continue _ | Break _ | Loop _ | Return _ -> () - | Switch (_,_,stmts,_) -> add_dpd_switch_cases pdg new_node stmts + | If _ | Loop _ | Return _ -> () + | Break _ | Continue _ -> + (* can use : add_dpd_goto_label pdg new_node s + * if we want later to change break and continue to goto... + *) () | Goto (sref,_) -> add_dpd_goto_label pdg new_node !sref + | Switch (_,_,stmts,_) -> add_dpd_switch_cases pdg new_node stmts | _ -> assert false - in store_ctrl_dpds pdg new_node controled_stmts; + in store_ctrl_dpds pdg new_node Stmt.Hptset.iter controled_stmts; new_node let process_jump pdg stmt controled_stmts = @@ -567,19 +616,16 @@ let add_blk_ctrl_dpds pdg key bstmts = let new_node = add_elem pdg key in - store_ctrl_dpds pdg new_node bstmts + store_ctrl_dpds pdg new_node List.iter (true, bstmts) let process_block pdg stmt blk = - let key = Key.stmt_key stmt in - add_blk_ctrl_dpds pdg key blk.bstmts + add_blk_ctrl_dpds pdg (Key.stmt_key stmt) blk.bstmts let process_entry_point pdg bstmts = - let key = Key.entry_point in - add_blk_ctrl_dpds pdg key bstmts + add_blk_ctrl_dpds pdg Key.entry_point bstmts let create_fun_output_node pdg state dpds = - let key = Key.output_key in - let new_node = add_elem pdg key in + let new_node = add_elem pdg Key.output_key in match state with | Some state -> add_dpds pdg new_node Dpd.Data state dpds | None -> (* return is unreachable *) () @@ -588,7 +634,10 @@ let key_return = Key.stmt_key ret_stmt in let return_node = add_elem pdg key_return in let retres_loc = Db.Value.find_return_loc (get_kf pdg) in - let retres = Locations.valid_enumerate_bits retres_loc in + let retres = + Locations.valid_enumerate_bits ~for_writing:false + retres_loc + in let _ = add_dpds pdg return_node Dpd.Data state retres_loc_dpds in let _ = add_decl_dpds pdg return_node Dpd.Data retres_decls in let new_state = Pdg_state.add_loc_node state true retres return_node in @@ -607,14 +656,14 @@ * (notice that now, they can overlap, for example we can have G and G.a) * And also deals with warning for uninitialized local variables. *) let process_other_inputs pdg = - P.debug ~level:2 "process_other_inputs@."; + debug2 "process_other_inputs@."; let rec add n dpd_kind (state, zones) z_or_top = (* be careful because [z] can intersect several elements in [zones] *) match zones with | [] -> let key = Key.implicit_in_key z_or_top in let nz = add_elem pdg key in - P.debug "add_implicit_input : %a@." + debug "add_implicit_input : %a@." Locations.Zone.pretty z_or_top ; let state = Pdg_state.add_init_state_input state z_or_top nz in let _ = add_z_dpd pdg n dpd_kind None nz in @@ -644,12 +693,10 @@ let do_z z acc = add n dpd_kind acc z in Locations.Zone.fold_enum_by_base do_z z acc in acc - else - begin - Cil.log "[pdg warning] might use uninitialized : %a" - Locations.Zone.pretty z ; - acc - end + else begin + debug2 "might use uninitialized : %a" Locations.Zone.pretty z; + acc + end in let (state, _) = List.fold_left add_zone (Pdg_state.empty, []) pdg.other_inputs @@ -657,94 +704,87 @@ (** @param from_opt for undefined functions (declarations) *) let finalize_pdg pdg from_opt = - P.debug ~level:2 "try to finalize_pdg"; + debug2 "try to finalize_pdg"; let last_state = try Some (Pdg_state.get_last_state (get_states pdg)) with Not_found -> - CilE.warn_once "no final state. Probably unreachable..."; None - in - let _ = match from_opt with - | None -> () (* defined function : retres already processed. *) - | Some froms -> (* undefined function : add output 0 *) - (* TODO : also add the nodes for the other from ! *) - let in_state = - match last_state with Some s -> s | None -> assert false in - let state = in_state in - let process_out out (default, from_out) state = - add_from pdg in_state state out (default, from_out) - in - let from_table = froms.Function_Froms.deps_table in - let new_state = - try Lmap_bitwise.From_Model.fold process_out from_table state - with Lmap_bitwise.From_Model.Cannot_fold -> (* TOP in from_table *) - process_out Locations.Zone.top (false, Locations.Zone.top) state - in - let new_state = - if (not (Kernel_function.returns_void pdg.fct)) then - let from0 = froms.Function_Froms.deps_return in - let _ = create_fun_output_node pdg (Some new_state) - (Lmap_bitwise.From_Model.LOffset.collapse from0) - in new_state - else new_state - in - store_last_state pdg new_state + let ret = + try Kernel_function.find_return (get_kf pdg) + with Kernel_function.No_Statement -> + Pdg_parameters.abort "No return in a declaration" + in + Pdg_parameters.warning ~once:true ~source:(fst (Stmt.loc ret)) + "no final state. Probably unreachable..."; + None in + (match from_opt with + | None -> () (* defined function : retres already processed. *) + | Some froms -> (* undefined function : add output 0 *) + (* TODO : also add the nodes for the other from ! *) + let state = match last_state with Some s -> s | None -> assert false in + let process_out out (default, from_out) s = + add_from pdg state s out (default, from_out) + in + let from_table = froms.Function_Froms.deps_table in + let new_state = + try Lmap_bitwise.From_Model.fold process_out from_table state + with Lmap_bitwise.From_Model.Cannot_fold -> (* TOP in from_table *) + process_out Locations.Zone.top (false, Locations.Zone.top) state + in + if not (Kernel_function.returns_void pdg.fct) then begin + let from0 = froms.Function_Froms.deps_return in + ignore + (create_fun_output_node + pdg + (Some new_state) + (Lmap_bitwise.From_Model.LOffset.collapse from0)) + end; + store_last_state pdg new_state); let init_state = process_other_inputs pdg in - store_init_state pdg init_state; + store_init_state pdg init_state; add_ctrl_dpds pdg ; - P.debug ~level:2 "finalize_pdg ok"; + debug2 "finalize_pdg ok"; let states = get_states pdg in - let pdg = PdgTypes.Pdg.make pdg.fct pdg.graph states pdg.index - in - pdg + PdgTypes.Pdg.make pdg.fct pdg.graph states pdg.index end (*-----------------------------------------------------------------------*) - (** gives needed informations about [lval] : - = location + exact + dependencies + declarations - *) + = location + exact + dependencies + declarations *) let get_lval_infos lval stmt = let decl = Cil.extract_varinfos_from_lval lval in - let dpds, loc = !Db.Value.lval_to_loc_with_deps - ~with_alarms:CilE.warn_none_mode - (Kstmt stmt) - ~deps:Locations.Zone.bottom lval + let dpds, loc = + !Db.Value.lval_to_loc_with_deps + ~with_alarms:CilE.warn_none_mode + (Kstmt stmt) + ~deps:Locations.Zone.bottom lval in - let l_loc = Locations.valid_enumerate_bits loc in - let exact = Locations.valid_cardinal_zero_or_one loc in - (l_loc, exact, dpds, decl) + let l_loc = Locations.valid_enumerate_bits ~for_writing:true loc in + let exact = Locations.valid_cardinal_zero_or_one ~for_writing:true loc in + (l_loc, exact, dpds, decl) (** process assignment {v lval = exp; v} Use the state at ki (before assign) - and returns the new state (after assign). - *) + and returns the new state (after assign). *) let process_asgn pdg state stmt lval exp = - let r_dpds = !Db.From.find_deps_no_transitivity (Kstmt stmt) exp in + let r_dpds = !Db.From.find_deps_no_transitivity stmt exp in let r_decl = Cil.extract_varinfos_from_exp exp in let (l_loc, exact, l_dpds, l_decl) = get_lval_infos lval stmt in - BuildPdg.process_asgn pdg state stmt ~l_loc ~exact ~l_dpds ~l_decl - ~r_dpds ~r_decl - -let process_code_annot pdg stmt _annot = - (* TODO : we could add dependencies to some data if we know how to extract - * then from the annotation... *) - BuildPdg.process_skip pdg stmt - -let process_skip pdg stmt = BuildPdg.process_skip pdg stmt + let state = BuildPdg.process_asgn pdg state stmt + ~l_loc ~exact ~l_dpds ~l_decl ~r_dpds ~r_decl + in Some state (** Add a PDG node and its dependencies for each explicit call argument. *) let process_args pdg st stmt argl = let process_one_arg arg = - let dpds = !Db.From.find_deps_no_transitivity (Kstmt stmt) arg in + let dpds = !Db.From.find_deps_no_transitivity stmt arg in let decl_dpds = Cil.extract_varinfos_from_exp arg in (dpds, decl_dpds) in let arg_dpds = List.map process_one_arg argl in BuildPdg.process_call_args pdg st stmt arg_dpds - (** Add nodes for the call outputs, and add the dependencies according to from_table. To avoid mixing inputs and outputs, [in_state] is the input state @@ -763,30 +803,34 @@ Format.fprintf fmt "\t and \\result %a@." Lmap_bitwise.From_Model.LOffset.pretty froms_deps_return in - Pdg_parameters.debug "%t" print_outputs; - let new_state = - match lvaloption with - | None -> state_before_call - | Some lval -> - let r_dpds = - Lmap_bitwise.From_Model.LOffset.collapse froms_deps_return - in - let (l_loc, exact, l_dpds, l_decl) = get_lval_infos lval stmt in - BuildPdg.process_call_return pdg state_before_call - state_with_inputs stmt - ~l_loc ~exact ~l_dpds ~l_decl - ~r_dpds fct_dpds - in + debug "%t" print_outputs; let process_out out (default, from_out) (state, numout) = let new_state = BuildPdg.process_call_ouput pdg state_with_inputs state stmt numout out default from_out fct_dpds in (new_state, numout+1) in - let (new_state, _num) = - try Lmap_bitwise.From_Model.fold process_out from_table (new_state, 1) + let (state_with_outputs, _num) = + try + Lmap_bitwise.From_Model.fold process_out from_table (state_before_call, 1) with Lmap_bitwise.From_Model.Cannot_fold -> (* TOP in from_table *) - process_out Locations.Zone.top (false, Locations.Zone.top) (new_state, 1) + process_out Locations.Zone.top (false, Locations.Zone.top) + (state_before_call, 1) + in + let new_state = + match lvaloption with + | None -> state_with_outputs + | Some lval -> + let r_dpds = + Lmap_bitwise.From_Model.LOffset.collapse froms_deps_return + in + let (l_loc, exact, l_dpds, l_decl) = get_lval_infos lval stmt in + BuildPdg.process_call_return + pdg + state_with_outputs + state_with_inputs stmt + ~l_loc ~exact ~l_dpds ~l_decl + ~r_dpds fct_dpds in new_state (** process call : {v lvaloption = funcexp (argl); v} @@ -796,7 +840,7 @@ let process_call pdg state stmt lvaloption funcexp argl = let state_before_call = state in let _ = BuildPdg.process_call_node pdg stmt in - let _nb_arg, arg_nodes = process_args pdg state_before_call stmt argl in + let arg_nodes = process_args pdg state_before_call stmt argl in let state_with_args = state in let funcexp_dpds, called_functions = !Db.Value.expr_to_kernel_function @@ -830,7 +874,7 @@ | [] -> let stmt_str = Pretty_utils.sfprintf "%a" !Ast_printer.d_stmt stmt in Extlib.not_yet_implemented - ("pdg with an unknown function call : " ^ stmt_str) + ("pdg with an unknown function call : " ^ stmt_str) | st :: [] -> st | st :: other_states -> let merge s1 s2 = @@ -843,87 +887,79 @@ call_ouputs pdg state_before_call new_state stmt lvaloption froms funcexp_dpds in - new_state - - + Some new_state (** Add a node in the PDG for the conditional statement, * and register the statements that are control-dependent on it. *) let process_condition ctrl_dpds_infos pdg state stmt condition = - (* TODO : test if we met this stmt already to avoid recomputing - the control dependencies. *) + let loc_cond = !Db.From.find_deps_no_transitivity stmt condition in + let decls_cond = Cil.extract_varinfos_from_exp condition in - (* let's find the locations used in the condition *) - let loc_cond = !Db.From.find_deps_no_transitivity (Kstmt stmt) condition in - let decls_cond = Cil.extract_varinfos_from_exp condition in - - (*let cond_val = !Db.Value.access_expr (Kstmt stmt) condition in*) - let controled_stmts = - CtrlDpds.get_if_controled_stmts ctrl_dpds_infos stmt - in - (* - let real_dpd = - let always_false = Locations.Location_Bytes.is_zero cond_val in - if always_false then false - else - let always_true = - not (Locations.Location_Bytes.intersects - cond_val Locations.Location_Bytes.singleton_zero) in - if always_true then false - else true - in - * We cannot ignore de dependencies, even if [real_dpd = false] - * because we lose indirect dependencies... (see BTS#181) - *) + let controled_stmts = CtrlDpds.get_if_controled_stmts ctrl_dpds_infos stmt in + let go_then, go_else = Db.Value.condition_truth_value stmt in + let real = go_then && go_else (* real dpd if we can go in both branches *) in + if not real then + debug + "[process_condition] stmt %d is not a real cond (never goes in '%s')@." + stmt.sid (if go_then then "else" else "then"); (* build a node for the condition and store de control dependencies *) - BuildPdg.process_jump_with_exp pdg stmt controled_stmts + BuildPdg.process_jump_with_exp pdg stmt (real, controled_stmts) state loc_cond decls_cond (** let's add a node for e jump statement (goto, break, continue) and find the statements which are depending on it. - - Loop are processed like gotos because CIL transformations - make them {v while(true) body; v} which is equivalent to - {v L : body ; goto L; v} - Returns are not handled here, but in {!Build.process_return}. *) -let process_jump_or_loop_stmt pdg ctrl_dpds_infos jump = - let controled_stmt_list = +let process_jump_stmt pdg ctrl_dpds_infos jump = + let controled_stmts = CtrlDpds.get_jump_controled_stmts ctrl_dpds_infos jump in - BuildPdg.process_jump pdg jump controled_stmt_list + let real = Db.Value.is_reachable_stmt jump in + if not real then + debug "[process_jump_stmt] stmt %d is not a real jump@." jump.sid; + BuildPdg.process_jump pdg jump (real, controled_stmts) + +(** Loop are processed like gotos because CIL transforms them into +* {v while(true) body; v} which is equivalent to {v L : body ; goto L; v} +* There is a small difference because we have to detect the case where +* the [goto L;] would be unreachable (no real loop). +* This is important because it might lead to infinite loop (see bst#787) +*) +let process_loop_stmt pdg ctrl_dpds_infos loop = + let _entry, back_edges = Stmts_graph.loop_preds loop in + debug2 "[process_loop_stmt] for loop %d : back edges = {%a}@." + loop.sid (Pretty_utils.pp_list Stmt.pretty_sid) back_edges; + let controled_stmts = + CtrlDpds.get_loop_controled_stmts ctrl_dpds_infos loop + in + let real_loop = List.exists (Db.Value.is_reachable_stmt) back_edges in + if not real_loop then + debug "[process_loop_stmt] stmt %d is not a real loop@." loop.sid; + BuildPdg.process_jump pdg loop (real_loop, controled_stmts) (** [return ret_exp;] is equivalent to [out0 = ret_exp; goto END;] * while a simple [return;] is only a [goto END;]. * Here, we assume that the {{:../html/Oneret.html}Oneret} analysis * was used, ie. that it is the only return of the function - * and that it is the last statement. So, the [goto] is not usefull, + * and that it is the last statement. So, the [goto] is not useful, * and the final state is stored to be used later on to compute the outputs. *) let process_return _current_function pdg state stmt ret_exp = let last_state = match ret_exp with | Some exp -> - let loc_exp = !Db.From.find_deps_no_transitivity (Kstmt stmt) exp in + let loc_exp = !Db.From.find_deps_no_transitivity stmt exp in let decls_exp = Cil.extract_varinfos_from_exp exp in BuildPdg.add_retres pdg state stmt loc_exp decls_exp | None -> - let controled_stmt = [] in - BuildPdg.process_jump pdg stmt controled_stmt; + let controled_stmt = Cil_datatype.Stmt.Hptset.empty in + let real = Db.Value.is_reachable_stmt stmt in + BuildPdg.process_jump pdg stmt (real, controled_stmt); state in - BuildPdg.store_last_state pdg last_state - -(* -let rec process_labels pdg labels = - match stmt.labels with - | [] -> () - | label :: tail -> Pdg.process_label pdg label; - process_labels pdg labels -*) - + if Db.Value.is_reachable_stmt stmt then + BuildPdg.store_last_state pdg last_state (** Computer is a ForwardsTransfer to use ForwardsDataFlow *) module Computer (Param:sig @@ -931,6 +967,7 @@ val ctrl_dpds_infos : CtrlDpds.t end) = struct let name = "slicingflow" + let pdg_debug fmt = debug fmt let debug = ref false type t = BuildPdg.t_state @@ -940,8 +977,10 @@ let ctrl_dpds_infos = Param.ctrl_dpds_infos + (** place to store information at each point of the program during analysis *) module StmtStartData = struct type data = BuildPdg.t_state + type key = int let states = BuildPdg.get_states current_pdg let clear () = IH.clear states let mem = IH.mem states @@ -952,12 +991,6 @@ let length () = IH.length states end -(* - (** place to store information at each point of the program during analysis *) - let stmtStartData: IH.t = BuildPdg.get_states current_pdg -*) - let stmt_can_reach = Stmts_graph.stmt_can_reach current_function - let copy (d: t) = d let pretty fmt (v: t) = @@ -977,40 +1010,36 @@ let new_state = computeFirstPredecessor stmt new_ in let is_new, new_state = BuildPdg.test_and_merge_states old new_state in if is_new then Some new_state - else - begin - (if !debug - then P.debug "fix point reached for stmt %d" stmt.sid); - None - end + else (pdg_debug "fix point reached for sid:%d" stmt.sid; None) (** Compute the new state after 'instr' starting from state before 'state'. *) let doInstr stmt instr state = !Db.progress (); - P.debug "doInstr : %a" !Ast_printer.d_instr instr; - match instr with - | Set (lv, exp, _) -> - let new_state = process_asgn current_pdg state stmt lv exp in - Dataflow.Done new_state - | Call (lvaloption,funcexp,argl,_) -> - !Db.progress (); - let new_state = process_call current_pdg state stmt - lvaloption funcexp argl in - Dataflow.Done new_state - | Code_annot (annot, _) -> - process_code_annot current_pdg stmt annot; Dataflow.Default - | Skip _ -> process_skip current_pdg stmt ; Dataflow.Default - | Asm _ -> P.fatal ~current:true "inline assembly instruction" + pdg_debug "doInstr sid:%d : %a" stmt.sid !Ast_printer.d_instr instr; + let state = match instr with + | Call _ when not (Db.Value.is_reachable_stmt stmt) -> + pdg_debug "call sid:%d is unreachable : skip.@." stmt.sid ; + BuildPdg.process_unreachable_call current_pdg state stmt + | _ when not (Db.Value.is_reachable_stmt stmt) -> + pdg_debug "stmt sid:%d is unreachable : skip.@." stmt.sid ; + BuildPdg.process_unreachable current_pdg state stmt + | Set (lv, exp, _) -> process_asgn current_pdg state stmt lv exp + | Call (lvaloption,funcexp,argl,_) -> + !Db.progress (); + process_call current_pdg state stmt lvaloption funcexp argl + | Code_annot _ + | Skip _ -> BuildPdg.process_skip current_pdg state stmt + | Asm _ -> Extlib.not_yet_implemented "inline assembly instruction" + in match state with None -> Dataflow.Default + | Some state -> Dataflow.Done state (** Called before processing the successors of the statements. *) let doStmt (stmt: Cil_types.stmt) (state: t) = - P.debug "doStmt %d @." stmt.sid ; + pdg_debug "doStmt %d @." stmt.sid ; - (* labels are processed while processing the jumps. - process_labels current_pdg labels ; - *) + (* Notice that the stmt labels are processed while processing the jumps. *) match stmt.skind with | Instr _ @@ -1035,9 +1064,12 @@ | Continue _ | Break _ - | Goto _ + | Goto _ -> + process_jump_stmt current_pdg ctrl_dpds_infos stmt; + Dataflow.SDefault + | Loop _ -> - process_jump_or_loop_stmt current_pdg ctrl_dpds_infos stmt; + process_loop_stmt current_pdg ctrl_dpds_infos stmt; Dataflow.SDefault | TryExcept (_, _, _, _) @@ -1045,7 +1077,12 @@ -> Dataflow.SDefault (** Whether to put this statement in the worklist. *) - let filterStmt stmt = Db.Value.is_accessible (Kstmt stmt) + let filterStmt _stmt = true + (* don't use Db.Value.is_reachable_stmt here since we want to build node. + * Use it later in [doInstr] but be carreful about ctrl dpds ! *) + + (** used to optimize the order of the dataflow analysis. *) + let stmt_can_reach = Stmts_graph.stmt_can_reach current_function let doGuard _ _ _ = Dataflow.GDefault, Dataflow.GDefault @@ -1053,15 +1090,34 @@ end +(** Find the statements that are not reachable in CFG (no predecessors) +* to add them as starting point of the dataflow analysis because we need to +* process unreachable control statetemetns in order to have correct +* control dependancies. *) +let ctrl_no_preds stmts = + let rec add acc stmts = match stmts with [] -> acc + | s::tl -> add (add_stmt acc s) tl + and add_stmt acc s = + let acc = if s.preds = [] then s::acc else acc in + match s.skind with + | Instr _ | Return _ | Continue _ | Break _ | Goto _ -> acc + | Block b | Switch (_, b, _, _) | Loop (_, b, _, _, _) -> + add acc b.bstmts + | UnspecifiedSequence seq -> + let b = Cil.block_from_unspecified_sequence seq in + add acc b.bstmts + | If (_, b1, b2, _) -> add (add acc b1.bstmts) b2.bstmts + | TryExcept (_, _, _, _) | TryFinally (_, _, _) -> acc + in add [] stmts + (** Compute and return the PDG for the given function *) let compute_pdg_for_f kf = let pdg = BuildPdg.create kf in let f_locals, f_stmts = - try - let f = Kernel_function.get_definition kf in - f.slocals, f.sbody.bstmts - with Kernel_function.No_Definition -> [], [] + if !Db.Value.use_spec_instead_of_definition kf then [], [] + else let f = Kernel_function.get_definition kf in + f.slocals, f.sbody.bstmts in let init_state = let _ = BuildPdg.process_entry_point pdg f_stmts in @@ -1074,7 +1130,7 @@ BuildPdg.store_last_state pdg state ; let froms = !Db.From.get kf in Some (froms) - | start :: _ -> + | start :: stmts -> let ctrl_dpds_infos = CtrlDpds.compute kf in let module Computer = Computer (struct let current_pdg = pdg @@ -1082,63 +1138,73 @@ end) in let module Compute = Dataflow.ForwardsDataFlow(Computer) in - if Computer.filterStmt start then + if Db.Value.is_reachable_stmt start then begin let init_state = Computer.computeFirstPredecessor start init_state in Computer.StmtStartData.add start.sid init_state ; - Compute.compute [start] ; + let rec add acc l = match l with [] -> acc + | s::tl -> + Computer.StmtStartData.add s.sid BuildPdg.empty_state; + add (s::acc) tl + in + let starts = add [start] (ctrl_no_preds stmts) in + Compute.compute starts ; None end else raise - (Err_Bot - (Printf.sprintf "unreachable entry point (sid %d, function %s)" - start.sid (Kernel_function.get_name kf))) + (Err_Bot + (Printf.sprintf "unreachable entry point (sid:%d, function %s)" + start.sid (Kernel_function.get_name kf))) in let pdg = BuildPdg.finalize_pdg pdg froms in pdg let degenerated top kf = - P.feedback "%s for function %a" - (if top then "Top" else "Bottom") - Kernel_function.pretty_name kf; + Pdg_parameters.feedback "%s for function %a" (if top then "Top" else "Bottom") + Kernel_function.pretty kf; if top then PdgTypes.Pdg.top kf else PdgTypes.Pdg.bottom kf let compute_pdg kf = if not (Db.Value.is_computed ()) then !Db.Value.compute (); - P.feedback "computing for function %a" - Kernel_function.pretty_name kf; + Pdg_parameters.feedback "computing for function %a" Kernel_function.pretty kf; try if is_variadic kf then - Extlib.not_yet_implemented "PDG for a variadic function"; + Extlib.not_yet_implemented "variadic function"; let pdg = compute_pdg_for_f kf in - P.feedback "done for function %a" - Kernel_function.pretty_name kf; + Pdg_parameters.feedback "done for function %a" Kernel_function.pretty kf; - (* Datascope.compute kf; *) pdg with | Err_Bot what -> - P.warning "%s" what ; - degenerated false kf + Pdg_parameters.warning "%s" what ; + degenerated false kf - | PdgTypes.Pdg_Internal_Error what -> - P.failure "%s" what ; - degenerated true kf + | Log.AbortFatal what -> + Pdg_parameters.warning "internal error: %s" what ; + degenerated true kf + + | Log.AbortError what -> + Pdg_parameters.warning "user error: %s" what ; + degenerated true kf | Pdg_state.Cannot_fold -> - P.failure "too imprecise value analysis : abort" ; - degenerated true kf + Pdg_parameters.warning "too imprecise value analysis : abort" ; + degenerated true kf - | Extlib.NotYetImplemented why_nyi -> - P.failure "%s not implemented yet" why_nyi ; - degenerated true kf + | Extlib.NotYetImplemented what -> + Pdg_parameters.warning "not implemented by PDG yet: %s" what ; + degenerated true kf + + | Log.FeatureRequest (who, what) -> + Pdg_parameters.warning "not implemented by [%s] yet: %s" who what ; + degenerated true kf (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/build.mli frama-c-20111001+nitrogen+dfsg/src/pdg/build.mli --- frama-c-20110201+carbon+dfsg/src/pdg/build.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/build.mli 2011-10-10 08:38:30.000000000 +0000 @@ -22,7 +22,7 @@ (* *) (**************************************************************************) -val compute_pdg : Db_types.kernel_function -> PdgTypes.Pdg.t +val compute_pdg : Cil_types.kernel_function -> PdgTypes.Pdg.t (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/ctrlDpds.ml frama-c-20111001+nitrogen+dfsg/src/pdg/ctrlDpds.ml --- frama-c-20110201+carbon+dfsg/src/pdg/ctrlDpds.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/ctrlDpds.ml 2011-10-10 08:38:30.000000000 +0000 @@ -22,184 +22,302 @@ (* *) (**************************************************************************) +let dkey = "ctrl-dpds" + open Cil_types -module IH = Inthash open Cil_datatype -module S = struct - type t = Stmt.Set.t - let empty = Stmt.Set.empty - let singleton = Stmt.Set.singleton - - let add = Stmt.Set.add - let remove = Stmt.Set.remove - - let equal = Stmt.Set.equal - - let inter = Stmt.Set.inter - let diff = Stmt.Set.diff - let union = Stmt.Set.union +(*============================================================================*) +(** Lexical successors *) +(*============================================================================*) +(** Compute a graph which provide the lexical successor of each statement s, + ie. the statement which is the next one if 's' is replaced by Nop. + Notice that if 's' is an If, Loop, ... + the considered statement is the whole block. + + Example : (1) x = 3; + (2) if (c) (3) y = 3; (4) goto L; else (5) z = 8; + (6) while (c--) (7) x++; + (8) L : return x; + + (1) -> (2) -> (6) -> (8) + (3) -> (4) -> (6) + (5) -> (6) + (7) -> (6) - let elements = Stmt.Set.elements - let pretty = Stmt.Set.pretty -end + *) +module Lexical_successors : sig -type t_info = - | ToReturn of S.t - | ToInfinity of S.t - | Init - -module State = struct - type t = t_info - - let inter a b = match a,b with - | Init, Init -> Init - | ToReturn v, Init | Init, ToReturn v -> ToReturn v - | ToInfinity v, Init | Init, ToInfinity v -> ToInfinity v - | ToReturn v, ToReturn v' -> ToReturn ( S.inter v v') - | ToInfinity v, ToInfinity v' -> ToInfinity ( S.inter v v') - | ToReturn v, ToInfinity _ | ToInfinity _, ToReturn v -> ToReturn v - - let equal a b = match a,b with - | Init, Init -> true - | ToReturn v, ToReturn v' -> S.equal v v' - | ToInfinity v, ToInfinity v' -> S.equal v v' - | _ -> false - - let add stmt set = match set with - | Init -> Init - | ToReturn set -> ToReturn (S.add stmt set) - | ToInfinity set -> ToInfinity (S.add stmt set) - - let pretty fmt d = - match d with - | Init -> - Format.fprintf fmt "Top" - | ToReturn d -> Format.fprintf fmt "{%a}_ret" S.pretty d - | ToInfinity d -> Format.fprintf fmt "{%a}_oo" S.pretty d -end + type t + val compute : Cil_types.kernel_function -> t -module States = struct - type t = State.t IH.t - let create = IH.create - let add = IH.add - let find = IH.find - let pretty fmt infos = - IH.iter - (fun k v -> Format.fprintf fmt "Stmt:%d\n%a\n======" k State.pretty v) - infos -end + (** @return the lexical successor of stmt in graph. + @raise Not_found if 'stmt' has no successor in 'graph' + *) + val find : t -> Cil_types.stmt -> Cil_types.stmt +end = struct -type t = Lexical_successors.t * States.t + let dkey = "lex-succs" -module Computer (Param:sig - val states : States.t - val end_point : int - end) = struct - - let name = "ctrlDpds" - let debug = ref false - - type t = State.t - let pretty = State.pretty - - module StmtStartData = struct - type data = t - let clear () = IH.clear Param.states - let mem = IH.mem Param.states - let find = IH.find Param.states - let replace = IH.replace Param.states - let add = IH.add Param.states - let iter f = IH.iter f Param.states - let length () = IH.length Param.states - end + (** Type of the graph *) + type t = Cil_types.stmt Stmt.Hashtbl.t + let pp_stmt fmt s = Format.fprintf fmt "@[sid:%d(%a)@]" s.sid Stmt.pretty s - let combineStmtStartData _stmt ~old new_ = - let result = (* inter old *) new_ in - if State.equal result old then None else Some result - - let combineSuccessors = State.inter + (** Add links from each [prev] in [prev_list] to [next]. *) + let add_links graph prev_list next = match prev_list with + | [] -> () + | _ -> + let link prev = + try ignore (Stmt.Hashtbl.find graph prev) + with Not_found -> + Pdg_parameters.debug ~dkey "add @[%a@,-> %a@]" + pp_stmt prev pp_stmt next; + Stmt.Hashtbl.add graph prev next + in List.iter link prev_list + + (** Add links from [prev_list] to [stmt]. + * (ie. [stmt] is the lexical successor of every statements in [prev_list]) + * and build the links inside [stmt] (when it contains blocks) + * @return a list of the last statements in [stmt] to continue processing + * with the statement that follows. + *) + let rec process_stmt graph ~prev_list ~stmt = + Pdg_parameters.debug ~dkey "computing for statement %a@." + pp_stmt stmt; + match stmt.skind with + | If (_,bthen,belse,_) -> + let _ = add_links graph prev_list stmt in + let last_then = process_block graph bthen in + let last_else = process_block graph belse in + let prev_list = match last_then, last_else with + | [], [] -> [ stmt ] + | last, [] | [], last -> stmt::last + | last_then, last_else -> last_then @ last_else + in prev_list + + | Switch (_,blk,_,_) + | Block blk -> + let _ = add_links graph prev_list stmt in + process_block graph blk + | UnspecifiedSequence seq -> + let _ = add_links graph prev_list stmt in + process_block graph (Cil.block_from_unspecified_sequence seq) + + | Loop (_,body,_,_,_) -> + let prev_list = match body.bstmts with + | [] -> + let _ = add_links graph prev_list stmt in [ stmt ] + | head::_ -> + let _ = add_links graph prev_list head in + let last_list = process_block graph body in + let _ = add_links graph last_list stmt in + stmt::[] + in prev_list + + | Instr _ + | Return _ | Goto _ | Break _ | Continue _ + | TryFinally _ | TryExcept _ + -> let _ = add_links graph prev_list stmt in [stmt] + + (** Process each statement in blk with no previous statement to begin with. + * Then process each statement in the statement list + * knowing that the first element of 'tail' + * is the successor of every statement in prev_list. + * @return a list of the last statements in tail or prev_list if tail=[]. + *) + and process_block graph blk = + let rec process_stmts prev_list stmts = match stmts with + | [] -> prev_list + | s :: tail -> + let s_last_stmts = process_stmt graph prev_list s in + process_stmts s_last_stmts tail + in process_stmts [] blk.bstmts + + (** Compute the lexical successor graph for function kf *) + let compute kf = + Pdg_parameters.debug ~dkey "computing for function %s@." + (Kernel_function.get_name kf); + if !Db.Value.use_spec_instead_of_definition kf then Stmt.Hashtbl.create 0 + else let graph = Stmt.Hashtbl.create 17 in + let f = Kernel_function.get_definition kf in + let _ = process_block graph f.sbody in graph - let doStmt stmt = - if stmt.sid = Param.end_point then - Dataflow.Done (ToInfinity (S.singleton stmt)) - else - Dataflow.Post (fun data -> State.add stmt data) + (** @return the lexical successor of stmt in graph. + @raise Not_found if 'stmt' has no successor in 'graph' ie when it is [return]. + *) + let find graph stmt = + try Stmt.Hashtbl.find graph stmt + with Not_found -> + Pdg_parameters.debug ~dkey ~level:2 "not found for stmt:%d@." stmt.sid; + raise Not_found +end - let doInstr _ _ _ = Dataflow.Default +(*============================================================================*) +(** Postdominators (with infine path extension) *) +(*============================================================================*) +module PdgPostdom : sig + + type t + + val compute : kernel_function -> t + + (** @param with_s tells if the statement has to be added to its postdom. + * The returned boolean tells if there is a path to [return] *) + val get : t -> with_s:bool -> stmt -> bool * Stmt.Hptset.t + +end = struct + + module State = struct + type t = + | ToReturn of Stmt.Hptset.t + | ToInfinity of Stmt.Hptset.t + | Init + + let inter a b = match a,b with + | Init, Init -> Init + | ToReturn v, Init | Init, ToReturn v -> ToReturn v + | ToInfinity v, Init | Init, ToInfinity v -> ToInfinity v + | ToReturn v, ToReturn v' -> ToReturn ( Stmt.Hptset.inter v v') + | ToInfinity v, ToInfinity v' -> ToInfinity ( Stmt.Hptset.inter v v') + | ToReturn v, ToInfinity _ | ToInfinity _, ToReturn v -> ToReturn v + + let equal a b = match a,b with + | Init, Init -> true + | ToReturn v, ToReturn v' -> Stmt.Hptset.equal v v' + | ToInfinity v, ToInfinity v' -> Stmt.Hptset.equal v v' + | _ -> false + + let add stmt set = match set with + | Init -> Init + | ToReturn set -> ToReturn (Stmt.Hptset.add stmt set) + | ToInfinity set -> ToInfinity (Stmt.Hptset.add stmt set) + + let pretty fmt d = + match d with + | Init -> Format.fprintf fmt "Top" + | ToReturn d -> Format.fprintf fmt "{%a}_ret" Stmt.Hptset.pretty d + | ToInfinity d -> Format.fprintf fmt "{%a}_oo" Stmt.Hptset.pretty d + end - let filterStmt _stmt _next = true - (* assert (Db.ToReturn.is_accessible (Kstmt next)); - Db.ToReturn.is_accessible (Kstmt stmt) *) + type t = State.t Stmt.Hashtbl.t - let funcExitData = ToReturn S.empty + let pretty fmt infos = + Stmt.Hashtbl.iter + (fun k v -> Format.fprintf fmt "Stmt:%d\n%a\n======" k.sid State.pretty v) + infos -end + let is_in_stmts iter s stmts = + try iter (fun s' -> if s.sid = s'.sid then raise Exit) stmts; false + with Exit -> true + + (** change [succs] so move the edges [entry -> loop] to [entry -> head] *) + let succs stmt = + let modif acc s = match s.skind with + | Loop _ -> + let head = match s.succs with | [head] -> head | _ -> assert false in + let entry, _back_edges = Stmts_graph.loop_preds s in + if is_in_stmts List.iter stmt entry then head::acc else s::acc + | _ -> s::acc + in List.fold_left modif [] stmt.succs + + (** change [preds] so remove the edges [entry <- loop] + * and to add the edges [entry <- head] *) + let preds stmt = match stmt.skind with + | Loop _ -> (* remove edges from entry to loop *) + let _entry, back_edges = Stmts_graph.loop_preds stmt in back_edges + | _ -> + let modif acc s = match s.skind with + | Loop _ -> + let entry, _back_edges = Stmts_graph.loop_preds s in + s::entry@acc + | _ -> s::acc + in List.fold_left modif [] stmt.preds + + let add_postdom infos start init = + let get s = try Stmt.Hashtbl.find infos s with Not_found -> State.Init in + let do_stmt stmt = match succs stmt with + | [] when stmt.sid = start.sid -> + Some (State.ToReturn (Stmt.Hptset.empty)) + | [] -> assert false + | s::tl -> + let add_get s = State.add s (get s) in + let combineSuccessors st s = State.inter st (add_get s) in + let st = List.fold_left combineSuccessors (add_get s) tl in + let old = get stmt in + let new_st = (* don't need to State.inter old *) st in + if State.equal old new_st then None + else Some new_st + in + let todo = Queue.create () in + let add_todo p = + if is_in_stmts Queue.iter p todo then () else Queue.add p todo + in + let rec do_todo () = + try + let s = Queue.take todo in + let _ = match do_stmt s with + | None -> (* finished with that one *) () + | Some st -> (* store state and add preds *) + Stmt.Hashtbl.add infos s st; List.iter add_todo (preds s) + in do_todo () + with Queue.Empty -> () + in + let _ = Stmt.Hashtbl.add infos start init in + let _ = List.iter (fun p -> Queue.add p todo) (preds start) in + do_todo () + + let compute kf = + let infos = Stmt.Hashtbl.create 50 in + let return = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> + Pdg_parameters.fatal "No return statement for a function with body %a" + Kernel_function.pretty kf + in + let _ = add_postdom infos return (State.ToReturn (Stmt.Hptset.empty)) in + let stmts = + if !Db.Value.use_spec_instead_of_definition kf then + invalid_arg "[traces] cannot compute for a leaf function" + else + let f = Kernel_function.get_definition kf in f.sallstmts + in + let remove_top s = + try ignore (Stmt.Hashtbl.find infos s) with Not_found -> + Pdg_parameters.debug ~dkey "compute infinite path to sid:%d" s.sid; + add_postdom infos s (State.ToInfinity (Stmt.Hptset.empty)) + in + let _ = List.iter remove_top stmts in + infos -let go infos end_point = - let module Computer = Computer (struct - let end_point = end_point.sid - let states = infos - end) - in let module Compute = Dataflow.BackwardsDataFlow(Computer) in - Compute.compute [end_point] + let get infos ~with_s stmt = + try + let stmt_to_ret, postdoms = match Stmt.Hashtbl.find infos stmt with + | State.ToInfinity postdoms -> false, postdoms + | State.ToReturn postdoms -> true, postdoms + | State.Init -> assert false + in let postdoms = + if with_s then Stmt.Hptset.add stmt postdoms else postdoms + in + Pdg_parameters.debug ~dkey ~level:2 + "get_postdoms for sid:%d (%s) = %a (%spath to ret)@." + stmt.sid (if with_s then "with" else "without") + Stmt.Hptset.pretty postdoms (if stmt_to_ret then "" else "no "); + stmt_to_ret, postdoms + with Not_found -> assert false -let compute_on_infinite_traces infos tops = - let rec remove_top stmts = match stmts with - | [] -> () - | s :: stmts -> - if States.find infos s.sid = Init then go infos s else (); - remove_top stmts - in remove_top tops +end +(*============================================================================*) +(** Compute information needed for control dependencies *) +(*============================================================================*) -let compute_infos kf = - let stmts = - try - let f = Kernel_function.get_definition kf in f.sallstmts - with Kernel_function.No_Definition -> invalid_arg - "[traces] cannot compute for a leaf function" - in - let infos = States.create 50 in - (*List.iter (fun s -> States.add s.sid (ToReturn (S.empty))) stmts;*) - (*List.iter (fun s -> States.add s.sid (ToReturn (S.singleton s))) stmts;*) - (* let return = find_return kf in go return; *) - let init tops s = - let tops, postdom = - try tops, ToReturn (!Db.Postdominators.stmt_postdominators kf s) - with Db.Postdominators.Top -> s::tops, Init - in - States.add infos s.sid postdom ; - tops - in - let tops = List.fold_left init [] stmts in - let _ = match tops with - | [] -> () - | _ -> - begin - Cil.log "[traces] computing for function %a" - Kernel_function.pretty_name kf; - Cil.log "[traces] WARNING : experimental feature..."; - Cil.log " -> infinite loop processing" ; - compute_on_infinite_traces infos tops - end - in infos +type t = Lexical_successors.t * PdgPostdom.t let compute kf = let lex_succ_graph = Lexical_successors.compute kf in - let ctrl_dpds_infos = compute_infos kf in + let ctrl_dpds_infos = PdgPostdom.compute kf in (lex_succ_graph, ctrl_dpds_infos) -let get_postdoms infos ~without stmt = - try - let stmt_to_ret, postdoms = match States.find infos stmt.sid with - | ToInfinity postdoms -> false, postdoms - | ToReturn postdoms -> true, postdoms - | Init -> assert false - in let postdoms = if without then S.remove stmt postdoms else postdoms in - stmt_to_ret, postdoms - with Not_found -> assert false - (** Compute the PDB(A,B) set used in the control dependencies algorithm. * Roughly speaking, it gives {v (\{B\} U postdom(B))-postdom(A) v}. * It means that if S is in the result, it postdominates B but not A. @@ -209,23 +327,29 @@ (see the document to know more about the applied algorithm) *) let pd_b_but_not_a infos stmt_a stmt_b = - if stmt_a.sid = stmt_b.sid then S.empty + if stmt_a.sid = stmt_b.sid then Stmt.Hptset.empty else begin - let a_to_ret, postdom_a = get_postdoms infos ~without:true stmt_a in - let b_to_ret, postdom_b = get_postdoms infos ~without:false stmt_b in + let a_to_ret, postdom_a = PdgPostdom.get infos ~with_s:false stmt_a in + let b_to_ret, postdom_b = PdgPostdom.get infos ~with_s:true stmt_b in let res = match a_to_ret, b_to_ret with - | true, true | false, false -> S.diff postdom_b postdom_a + | true, true | false, false -> Stmt.Hptset.diff postdom_b postdom_a | true, false -> postdom_b | false, true -> (* no path [a, ret] but path [b, ret] * possible when a there is a jump, because then we have * either (A=G, B=S) or (A=S, B=L) *) - S.empty (* because we don't want b postdoms to depend on the jump *) + Stmt.Hptset.empty (* because we don't want b postdoms + to depend on the jump *) in - Pdg_parameters.debug ~level:2 "pd_b_but_not_a for a=%d b=%d = %a" - stmt_a.sid stmt_b.sid S.pretty res; - res + Pdg_parameters.debug ~dkey ~level:2 + "pd_b_but_not_a for a=sid:%d b=sid:%d = %a" + stmt_a.sid stmt_b.sid Stmt.Hptset.pretty res; + res end +(*============================================================================*) +(** Control dependencies *) +(*============================================================================*) + (** @return the statements which are depending on the condition. * * {v = U (PDB (if, succs(if)) v} @@ -233,49 +357,66 @@ *) let get_if_controled_stmts ctrl_dpds_infos stmt = let _, infos = ctrl_dpds_infos in - let add_pdb_s set succ = S.union set (pd_b_but_not_a infos stmt succ) in - let controled_stmts = List.fold_left add_pdb_s S.empty stmt.succs in - Pdg_parameters.debug "controled_stmt for cond %d = %a" - stmt.sid S.pretty controled_stmts; - S.elements controled_stmts + let add_pdb_s set succ = + Stmt.Hptset.union set (pd_b_but_not_a infos stmt succ) + in + let controled_stmts = List.fold_left add_pdb_s Stmt.Hptset.empty stmt.succs in + Pdg_parameters.debug ~dkey "controled_stmt for cond sid:%d = %a" + stmt.sid Stmt.Hptset.pretty controled_stmts; + controled_stmts + +let jump_controled_stmts infos jump label lex_suc = + Pdg_parameters.debug ~dkey ~level:2 + "lex_succ sid:%d = sid:%d" jump.sid lex_suc.sid; + Pdg_parameters.debug ~dkey ~level:2 + "jump succ sid:%d = sid:%d" jump.sid label.sid; + let controled_stmts = + if lex_suc.sid = label.sid then begin + (* the label is the jump lexical successor: no dpds *) + Pdg_parameters.debug ~dkey "useless jump sid:%d (label = lex_succ = %d)" + jump.sid lex_suc.sid; + Stmt.Hptset.empty + end else + let pdb_jump_lex_suc = pd_b_but_not_a infos jump lex_suc in + let pdb_lex_suc_label = pd_b_but_not_a infos lex_suc label in + let pdb_lex_suc_label = + Stmt.Hptset.remove lex_suc pdb_lex_suc_label + in Stmt.Hptset.union pdb_jump_lex_suc pdb_lex_suc_label + in + controled_stmts (** let's find the statements which are depending on -* the jump statement (goto, break, continue, loop) = +* the jump statement (goto, break, continue) = {v PDB(jump,lex_suc) U (PDB(lex_suc,label) - lex_suc) v} (see the document to know more about the applied algorithm). *) let get_jump_controled_stmts ctrl_dpds_infos jump = let lex_succ_graph, infos = ctrl_dpds_infos in - let controled_stmts = - try - let lex_suc = Lexical_successors.find lex_succ_graph jump in - Pdg_parameters.debug ~level:2 "lex_succ %d = %d" jump.sid lex_suc.sid; - match jump.succs with - | [label] -> - Pdg_parameters.debug ~level:2 "jump succ %d = %d" jump.sid label.sid; - if lex_suc.sid = label.sid then begin - (* the label is the jump lexical successor: no dpds *) - Pdg_parameters.debug "useless jump %d" jump.sid; - S.empty - end else - let pdb_jump_lex_suc = pd_b_but_not_a infos jump lex_suc in - let pdb_lex_suc_label = pd_b_but_not_a infos lex_suc label in - let pdb_lex_suc_label = S.remove lex_suc pdb_lex_suc_label in - S.union pdb_jump_lex_suc pdb_lex_suc_label - | _ -> assert false - with Not_found -> - Pdg_parameters.debug "lex_succ %d = (none)" jump.sid; - (* no lexical successor : every postdom (jump) depend on jump. *) - let _, pd_jump = (get_postdoms infos ~without:false jump) in - S.remove jump pd_jump + let lex_suc = + try Lexical_successors.find lex_succ_graph jump + with Not_found -> assert false in - Pdg_parameters.debug "controled_stmt for jump %d = %a" - jump.sid S.pretty controled_stmts; - let controled_stmt_list = S.elements controled_stmts in - controled_stmt_list + let label = match jump.succs with | [label] -> label | _ -> assert false in + let controled_stmts = jump_controled_stmts infos jump label lex_suc in + Pdg_parameters.debug ~dkey "controled_stmt for jump sid:%d = %a" + jump.sid Stmt.Hptset.pretty controled_stmts; + controled_stmts -let display = States.pretty +(** Try to process [while(1) S; LS: ] as [L: S; goto L; LS: ] *) +let get_loop_controled_stmts ctrl_dpds_infos loop = + let lex_succ_graph, infos = ctrl_dpds_infos in + let lex_suc = + try Lexical_successors.find lex_succ_graph loop + with Not_found -> (* must have at least a return *) assert false + in + let jump = loop in + let label = match loop.succs with [head] -> head | _ -> assert false in + let controled_stmts = jump_controled_stmts infos jump label lex_suc in + Pdg_parameters.debug ~dkey "controled_stmt for loop sid:%d = %a" + loop.sid Stmt.Hptset.pretty controled_stmts; + controled_stmts +(*============================================================================*) (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/ctrlDpds.mli frama-c-20111001+nitrogen+dfsg/src/pdg/ctrlDpds.mli --- frama-c-20110201+carbon+dfsg/src/pdg/ctrlDpds.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/ctrlDpds.mli 2011-10-10 08:38:30.000000000 +0000 @@ -22,6 +22,7 @@ (* *) (**************************************************************************) +(** Internal information about control dependencies *) type t (** Compute some information on the function in order to be able to compute @@ -30,7 +31,7 @@ (** Compute the list of the statements that should have a control dependency * on the given IF statement. *) -val get_if_controled_stmts : t -> Cil_types.stmt -> Cil_types.stmt list +val get_if_controled_stmts : t -> Cil_types.stmt -> Cil_datatype.Stmt.Hptset.t (** Compute the list of the statements that should have a control dependency * on the given jump statement. This statement can be a [goto] of course, @@ -38,7 +39,8 @@ make them of the form {v while(true) body; v} which is equivalent to {v L : body ; goto L; v} * *) -val get_jump_controled_stmts : t -> Cil_types.stmt -> Cil_types.stmt list +val get_jump_controled_stmts : t -> Cil_types.stmt -> Cil_datatype.Stmt.Hptset.t +val get_loop_controled_stmts : t -> Cil_types.stmt -> Cil_datatype.Stmt.Hptset.t (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/lexical_successors.ml frama-c-20111001+nitrogen+dfsg/src/pdg/lexical_successors.ml --- frama-c-20110201+carbon+dfsg/src/pdg/lexical_successors.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/lexical_successors.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version v2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Compute a graph which provide the lexical successor of each statement s, - ie. the statement which is the next one if 's' is replaced by Nop. - Notice that if 's' is an If, Loop, ... - the considered statement is the whole block. - - Example : (1) x = 3; - (2) if (c) (3) y = 3; (4) goto L; else (5) z = 8; - (6) while (c--) (7) x++; - (8) L : return x; - - (1) -> (2) -> (6) -> (8) - (3) -> (4) -> (6) - (5) -> (6) - (7) -> (6) - *) - -open Cil_types - -(** Add a link prev -> next in the graph. - Do nothing if prev or next is Kglobal. - *) -let add_link graph ~prev ~next = - match (prev, next) with - | (Kglobal, _) -> () - | (_, Kglobal) -> () - | (Kstmt s_prev, Kstmt s_next) -> - let prev_id = s_prev.sid in - try - ignore (Inthash.find graph prev_id) - with Not_found -> - Pdg_parameters.debug "[lexical successor] add %d -> %d" - prev_id s_next.sid; - Inthash.add graph prev_id s_next - -(** Add links from each prev in prev_list to next. *) -let add_links graph prev_list next = - let link prev = add_link graph prev next in - List.iter link prev_list - -(** Add links from prev_list to stmt, - (ie. 'stmt' is the lexical succesor of every statements in prev_list) - and build the links inside stmt (when it contains blocks) - @return a list of the last statements in stmt to continue processing - with the statement that follows. - *) -let rec process_stmt graph ~prev_list ~stmt = - let ki_stmt = Kstmt stmt in - - add_links graph prev_list ki_stmt; - - match stmt.skind with - | If (_,bthen,belse,_) -> - let last_then = process_block graph bthen in - let last_else = process_block graph belse in - last_then @ last_else - - | Switch (_,blk,_,_) - | Block blk -> process_block graph blk - | UnspecifiedSequence seq -> - process_block graph (Cil.block_from_unspecified_sequence seq) - | Loop (_,body,_,_,_) -> - let last_list = process_block graph body in - add_links graph last_list ki_stmt; [ki_stmt] - - | Instr _ - | Return _ | Goto _ | Break _ | Continue _ - | TryFinally _ | TryExcept _ - -> [ki_stmt] - -(** Process each statement in tail (statement list) - knowing that the first element of 'tail' - is the successor of every statement in prev_list. - @return a list of the last statements in tail or prev_list if tail=[]. - *) -and process_tail graph prev_list tail = - match tail with - | [] -> prev_list - | s :: tail -> let s_last_stmt = process_stmt graph prev_list s in - let tail_last_stmt = process_tail graph s_last_stmt tail - in tail_last_stmt - -(** Process each statement in blk with no previous statement to begin with *) -and process_block graph blk = process_tail graph [Kglobal] blk.bstmts - -(** Type of the graph *) -type t = Cil_types.stmt Inthash.t - -(** Compute the lexical successor graph for function kf *) -let compute kf = - Pdg_parameters.debug "[lexical successor] computing for function %s@." - (Kernel_function.get_name kf); - let graph = Inthash.create 50 in - match kf.Db_types.fundec with - | Db_types.Declaration _ -> graph - | Db_types.Definition (f, _) -> - let _ = process_block graph f.sbody in graph - -(** @return the lexical successor of stmt in graph. - @raise Not_found if 'stmt' has no successor in 'graph'. - *) -let find graph stmt = - try Inthash.find graph stmt.sid - with Not_found -> - assert (match stmt.skind with Return _ -> true | _ -> false); - raise Not_found diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/macros.ml frama-c-20111001+nitrogen+dfsg/src/pdg/macros.ml --- frama-c-20110201+carbon+dfsg/src/pdg/macros.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/macros.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version v2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -let bug msg = raise (PdgTypes.Pdg_Internal_Error msg) - -let cbug cond msg = if not cond then bug msg - -let pretty_node fmt n = PdgTypes.Node.pretty fmt n - -let get_pdg_kf pdg = PdgTypes.Pdg.get_kf pdg - -let pdg_name pdg = Kernel_function.get_name (get_pdg_kf pdg) - - -(* -Local Variables: -compile-command: "LC_ALL=C make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/marks.ml frama-c-20111001+nitrogen+dfsg/src/pdg/marks.ml --- frama-c-20110201+carbon+dfsg/src/pdg/marks.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/marks.ml 2011-10-10 08:38:30.000000000 +0000 @@ -102,9 +102,9 @@ let translate_out_mark _pdg m2m other_rqs (call, l) = let add_list l_out_m called_kf rqs = + let called_pdg = !Db.Pdg.get called_kf in + let m2m = m2m (Some call) called_pdg in try - let called_pdg = !Db.Pdg.get called_kf in - let m2m = m2m (Some call) called_pdg in let node_marks = call_out_marks_to_called called_pdg m2m ~rqs:[] l_out_m in (called_pdg, PdgMarks.SelList node_marks)::rqs @@ -147,14 +147,14 @@ * version for a source function). *) module F_Proj (C : PdgMarks.T_Config) : PdgMarks.T_Proj with type t_mark = C.M.t - and type t_fct = (C.M.t, C.M.t_call_info) PdgIndex.FctIndex.t - = -struct + and type t_call_info = C.M.t_call_info += struct module F = Db.Pdg.F_FctMarks (C.M) type t_mark = C.M.t - type t_fct = (C.M.t, C.M.t_call_info) PdgIndex.FctIndex.t + type t_call_info = C.M.t_call_info + type t_fct = F.t_fi type t_fct_info = F.t type t = t_fct_info Varinfo.Hashtbl.t diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/marks.mli frama-c-20111001+nitrogen+dfsg/src/pdg/marks.mli --- frama-c-20110201+carbon+dfsg/src/pdg/marks.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/marks.mli 2011-10-10 08:38:30.000000000 +0000 @@ -70,7 +70,7 @@ module F_Proj (C : PdgMarks.T_Config) : PdgMarks.T_Proj with type t_mark = C.M.t - and type t_fct = (C.M.t, C.M.t_call_info) PdgIndex.FctIndex.t + and type t_call_info = C.M.t_call_info (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/Pdg.mli frama-c-20111001+nitrogen+dfsg/src/pdg/Pdg.mli --- frama-c-20110201+carbon+dfsg/src/pdg/Pdg.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/Pdg.mli 2011-10-10 08:38:30.000000000 +0000 @@ -30,29 +30,29 @@ module Register : sig (** [stmt] is a call in the [pdg] function. * Interprocedural information is provided to know which marks have to be - * propagatedfrom the called funciton. + * propagatedfrom the called funciton. * [in_marks_to_caller] translate this [t_info_caller_inputs] * into a (node, mark) list where the marks are filtered by a m2m function. * Ths result is added to the [rqs] list which is empty by default. *) - val in_marks_to_caller : + val in_marks_to_caller : PdgTypes.Pdg.t -> Cil_types.stmt -> ('t_mark PdgMarks.t_m2m) -> - ?rqs:('t_mark PdgMarks.t_select) -> + ?rqs:('t_mark PdgMarks.t_select) -> 't_mark PdgMarks.t_info_caller_inputs -> 't_mark PdgMarks.t_select - (** similar to [in_marks_to_caller] except that it is done + (** similar to [in_marks_to_caller] except that it is done * for every callers of the function. *) val translate_in_marks : - PdgTypes.Pdg.t -> 't_mark PdgMarks.t_info_caller_inputs + PdgTypes.Pdg.t -> 't_mark PdgMarks.t_info_caller_inputs -> ?m2m:'t_mark PdgMarks.t_call_m2m -> 't_mark PdgMarks.t_pdg_select -> 't_mark PdgMarks.t_pdg_select (** similar to [in_marks_to_caller] except that it is for the outputs - * of a function propagated into its calls *) + * of a function propagated into its calls *) val call_out_marks_to_called : PdgTypes.Pdg.t -> 't_mark PdgMarks.t_m2m -> - ?rqs:('t_mark PdgMarks.t_select) -> + ?rqs:('t_mark PdgMarks.t_select) -> (PdgIndex.Signature.t_out_key * 't_mark) list -> 't_mark PdgMarks.t_select @@ -64,10 +64,10 @@ -> 't_mark PdgMarks.t_pdg_select -> 't_mark PdgMarks.t_pdg_select - (** Full backward interprocedural propagation. + (** Full backward interprocedural propagation. * Can be configured using the funtor parameter. * Used for instance in [Sparecode]. *) - module F_Proj (C : PdgMarks.T_Config) : PdgMarks.T_Proj - with type t_mark = C.M.t - and type t_fct = (C.M.t, C.M.t_call_info) PdgIndex.FctIndex.t + module F_Proj (C : PdgMarks.T_Config) : PdgMarks.T_Proj + with type t_mark = C.M.t + and type t_call_info = C.M.t_call_info end diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/pdg_parameters.ml frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_parameters.ml --- frama-c-20110201+carbon+dfsg/src/pdg/pdg_parameters.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_parameters.ml 2011-10-10 08:38:30.000000000 +0000 @@ -29,13 +29,16 @@ let help = "Program Dependence Graph" end) +let output = add_group "Output" + module BuildAll = - False + WithOutput (struct let option_name = "-pdg" let help = - "build the dependence graph of each function for the slicing tool" + "build the dependence graph of each function" let kind = `Tuning + let output_by_default = false end) module BuildFct = @@ -47,6 +50,8 @@ let kind = `Tuning end) + +let () = Plugin.set_group output module PrintBw = False(struct let option_name = "-codpds" @@ -54,6 +59,7 @@ let kind = `Tuning end) +let () = Plugin.set_group output module DotBasename = EmptyString (struct @@ -62,13 +68,3 @@ let help = "put the PDG of function <f> in basename.f.dot" let kind = `Tuning end) - -module DotPostdomBasename = - EmptyString - (struct - let option_name = "-dot-postdom" - let arg_name = "f" - let help = "put the postdominators of function <f> in basename.f.dot" - let kind = `Tuning - end) - diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/pdg_parameters.mli frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_parameters.mli --- frama-c-20110201+carbon+dfsg/src/pdg/pdg_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_parameters.mli 2011-10-10 08:38:30.000000000 +0000 @@ -24,13 +24,10 @@ include Plugin.S -module BuildAll: Plugin.BOOL +module BuildAll: Plugin.WithOutput -module BuildFct: Plugin.STRING_SET +module BuildFct: Plugin.String_set -module PrintBw: Plugin.BOOL - -module DotBasename: Plugin.STRING - -module DotPostdomBasename: Plugin.STRING +module PrintBw: Plugin.Bool +module DotBasename: Plugin.String diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/pdg_state.ml frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_state.ml --- frama-c-20110201+carbon+dfsg/src/pdg/pdg_state.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_state.ml 2011-10-10 08:38:30.000000000 +0000 @@ -28,8 +28,9 @@ was last defined. *) +let dkey = "state" + module P = Pdg_parameters -module M = Macros open PdgTypes exception Cannot_fold @@ -51,7 +52,7 @@ Locations.Zone.pretty state.under_outputs let add_loc_node state ~exact loc node = - P.debug ~level:2 "[pdg state] add_loc_node (%s) : node %a -> %a@." + P.debug ~dkey ~level:2 "add_loc_node (%s) : node %a -> %a@." (if exact then "exact" else "merge") PdgTypes.Node.pretty node Locations.Zone.pretty loc ; @@ -61,7 +62,7 @@ if exact then Locations.Zone.link state.under_outputs loc else state.under_outputs in - P.debug ~level:2 "add_loc_node -> %a" pretty state; + P.debug ~dkey ~level:2 "add_loc_node -> %a" pretty state; make new_loc_info new_outputs (** this one is very similar to [add_loc_node] except that @@ -81,7 +82,9 @@ make new_loc_info new_outputs let test_and_merge ~old new_ = - if LocInfo.is_included new_.loc_info old.loc_info then (false, old) + if LocInfo.is_included new_.loc_info old.loc_info + && Locations.Zone.is_included old.under_outputs new_.under_outputs + then (false, old) else let new_loc_info = LocInfo.join old.loc_info new_.loc_info in let new_outputs = @@ -111,15 +114,15 @@ let z = if Locations.Zone.equal loc z then Some loc - (* Be carreful not ot put None here, because if we have n_1 : (s1 = - s2) and then n_2 : (s1.b = 3) the state looks like : - s1.a -> n_1; s1.b -> n_2 ; s1.c -> n_1. And if we - look for s1.a in that state, we get n_1 but this node - represent more that s1.a even if it is so in the - state... *) + (* Be carreful not ot put None here, because if we have n_1 : (s1 = + s2) and then n_2 : (s1.b = 3) the state looks like : + s1.a -> n_1; s1.b -> n_2 ; s1.c -> n_1. And if we + look for s1.a in that state, we get n_1 but this node + represent more that s1.a even if it is so in the + state... *) else Some (Locations.Zone.narrow z loc) in let add n acc = - P.debug ~level:2 "[pdg state] get_loc_nodes -> %a@." + P.debug ~dkey ~level:2 "get_loc_nodes -> %a@." PdgTypes.Node.pretty_with_part (n,z); (n,z)::acc in @@ -132,14 +135,14 @@ (** @raise Cannot_fold (see [get_loc_nodes_and_part]) *) let get_loc_nodes state loc = - P.debug ~level:2 "[pdg state] get_loc_nodes %a@. in %a@." + P.debug ~dkey ~level:2 "get_loc_nodes %a@. in %a@." Locations.Zone.pretty loc pretty state ; if Locations.Zone.equal loc Locations.Zone.bottom then [], None (* nothing to do *) else let nodes = get_loc_nodes_and_part state loc in let undef_zone = Locations.Zone.diff loc state.under_outputs in - P.debug ~level:2 "[pdg state] get_loc_nodes -> undef = %a@." + P.debug ~dkey ~level:2 "get_loc_nodes -> undef = %a@." Locations.Zone.pretty undef_zone; let undef_zone = if (Locations.Zone.equal undef_zone Locations.Zone.bottom) then None diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/pdg_state.mli frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_state.mli --- frama-c-20110201+carbon+dfsg/src/pdg/pdg_state.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/pdg_state.mli 2011-10-10 08:38:30.000000000 +0000 @@ -54,4 +54,3 @@ val get_init_state : t_states -> t val get_stmt_state : t_states -> Cil_types.stmt -> t val get_last_state : t_states -> t - diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/print.ml frama-c-20111001+nitrogen+dfsg/src/pdg/print.ml --- frama-c-20110201+carbon+dfsg/src/pdg/print.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/print.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version v2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Cil_types - -module K = PdgIndex.Key -module S = PdgIndex.Signature - -module N = PdgTypes.Node -module G = PdgTypes.G -module Dpd = PdgTypes.Dpd - -let pretty_key = K.pretty - - - - (* - let build_fct_pdg_dot_file proj kf = - let pdg = get_pdg proj kf in - let dot_filename = Pdg.build_dot_file pdg in - Format.printf "[pdg] dot file generated in %s@." dot_filename; - dot_filename - - let show_fct_pdg_dot_file proj kf = - let filename = build_fct_pdg_dot_file proj kf in - let cmd = "zgrviewer -Pdot" in - ignore (Sys.command (cmd^" $PWD/" ^ filename)) -*) - -(*-----------------------------------------------------------------------*) diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/register.ml frama-c-20111001+nitrogen+dfsg/src/pdg/register.ml --- frama-c-20110201+carbon+dfsg/src/pdg/register.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/register.ml 2011-10-10 08:38:30.000000000 +0000 @@ -31,7 +31,7 @@ let pretty_node short = if short then PdgTypes.Node.pretty - else PdgTypes.Pdg.pretty_node + else PdgTypes.Node.pretty_node let print_dot pdg filename = PdgTypes.Pdg.build_dot filename pdg; @@ -51,8 +51,8 @@ Cmdline.run_after_extended_stage (fun () -> State_dependency_graph.Static.add_codependencies - ~onto:Tbl.self - [ !Db.From.self ]) + ~onto:Tbl.self + [ !Db.From.self ]) (** Register external functions into Db. *) let () = @@ -128,31 +128,39 @@ Ocamlviz.init () *) -let main () = - let force_pdg = - Pdg_parameters.BuildAll.get () - || not (Datatype.String.Set.is_empty (Pdg_parameters.BuildFct.get ())) - in - if force_pdg then begin - Pdg_parameters.feedback "in progress..."; +let output () = + Pdg_parameters.set_debug_keys ["?"]; let do_kf_pdg kf = let fname = Kernel_function.get_name kf in if Pdg_parameters.BuildAll.get () || - Datatype.String.Set.mem fname (Pdg_parameters.BuildFct.get ()) + Datatype.String.Set.mem fname (Pdg_parameters.BuildFct.get ()) then - let pdg = !Db.Pdg.get kf in - let dot_postdom = Pdg_parameters.DotPostdomBasename.get () in - if dot_postdom <> "" then !Db.Postdominators.print_dot dot_postdom kf; + let pdg = !Db.Pdg.get kf in let bw = Pdg_parameters.PrintBw.get () in - Pdg_parameters.result "@[%a@]" (!Db.Pdg.pretty ~bw) pdg; - let dot_basename = Pdg_parameters.DotBasename.get () in - if dot_basename <> "" then + Pdg_parameters.result "@[%a@]" (!Db.Pdg.pretty ~bw) pdg; + let dot_basename = Pdg_parameters.DotBasename.get () in + if dot_basename <> "" then !Db.Pdg.extract pdg (dot_basename ^ "." ^ fname ^ ".dot") in !Db.Semantic_Callgraph.topologically_iter_on_functions do_kf_pdg; + let ks = Pdg_parameters.get_debug_keyset () in + let pp_keys = + Pretty_utils.pp_flowlist ~left:"" ~sep:", " ~right:"." + Format.pp_print_string + in Pdg_parameters.debug ~level:1 "Logging keys : %a" pp_keys ks ; if Pdg_parameters.BuildAll.get () then - Pdg_parameters.feedback "====== PDG GRAPH COMPUTED ======"; - end + Pdg_parameters.feedback "====== PDG GRAPH COMPUTED ======" + +let () = Pdg_parameters.BuildAll.set_output_dependencies + [!Db.Pdg.self; Pdg_parameters.BuildAll.self; Pdg_parameters.BuildFct.self] + +let main () = + let force_pdg = + Pdg_parameters.BuildAll.get () + || not (Datatype.String.Set.is_empty (Pdg_parameters.BuildFct.get ())) + in + if force_pdg then Pdg_parameters.BuildAll.output output + let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/sets.ml frama-c-20111001+nitrogen+dfsg/src/pdg/sets.ml --- frama-c-20110201+carbon+dfsg/src/pdg/sets.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/sets.ml 2011-10-10 08:38:30.000000000 +0000 @@ -26,39 +26,41 @@ open Cil_types -module M = Macros -module P = PdgTypes.Pdg -module D = PdgTypes.Dpd -module N = PdgTypes.Node -module G = PdgTypes.G -module FI = PdgIndex.FctIndex -module K = PdgIndex.Key - -type t_node = PdgTypes.Node.t -type t_loc = Locations.Zone.t -type t_pdg = PdgTypes.Pdg.t -type t_dpds_kind = PdgTypes.Dpd.td -type t_nodes_and_undef = (t_node * t_loc option) list * t_loc option +open PdgTypes +open PdgIndex + +type t_nodes_and_undef = + (Node.t * Locations.Zone.t option) list * Locations.Zone.t option let get_init_state pdg = - try Pdg_state.get_init_state (PdgTypes.Pdg.get_states pdg) + try Pdg_state.get_init_state (Pdg.get_states pdg) with Not_found -> assert false + +(** @raise Not_found when no last state (strange !) *) let get_last_state pdg = - try Pdg_state.get_last_state (PdgTypes.Pdg.get_states pdg) - with Not_found -> raise Db.Pdg.NotFound (* no last state: strange ! *) + Pdg_state.get_last_state (Pdg.get_states pdg) + +(** @raise Not_found for unreachable stmt *) let get_stmt_state pdg stmt = - try Pdg_state.get_stmt_state (PdgTypes.Pdg.get_states pdg) stmt - with Not_found -> raise Db.Pdg.NotFound (* probably an unreachable stmt *) + Pdg_state.get_stmt_state (Pdg.get_states pdg) stmt -let find_node pdg key = FI.find_info (PdgTypes.Pdg.get_index pdg) key +let find_node pdg key = FctIndex.find_info (Pdg.get_index pdg) key (** notice that there can be several nodes if the statement is a call. * For If, Switch, ... the node represent only the condition * (see find_stmt_nodes below). *) let find_simple_stmt_nodes pdg stmt = - let key = K.stmt_key stmt in - FI.find_all (PdgTypes.Pdg.get_index pdg) key + let idx = Pdg.get_index pdg in + let key = Key.stmt_key stmt in + let nodes = FctIndex.find_all idx key in + match stmt.skind with + | Return _ -> (* also add OutRet *) + (try + let ret = FctIndex.find_all idx Key.output_key in + ret @ nodes + with Not_found -> nodes) + | _ -> nodes let rec add_stmt_nodes pdg nodes s = let s_nodes = find_simple_stmt_nodes pdg s in @@ -69,11 +71,11 @@ match s.skind with | Switch (_,blk,_,_) | Loop (_, blk, _, _, _) | Block blk -> Pdg_parameters.debug ~level:2 - " select_stmt_computation on composed stmt %d@." s.sid; + " select_stmt_computation on composed stmt %d@." s.sid; add_block_stmts_nodes nodes blk | UnspecifiedSequence seq -> Pdg_parameters.debug ~level:2 - " select_stmt_computation on composed stmt %d@." s.sid; + " select_stmt_computation on composed stmt %d@." s.sid; add_block_stmts_nodes nodes (Cil.block_from_unspecified_sequence seq) | If (_,bthen,belse,_) -> let nodes = add_block_stmts_nodes nodes bthen in @@ -87,19 +89,13 @@ let find_stmt_and_blocks_nodes pdg stmt = add_stmt_nodes pdg [] stmt -let find_stmt_node pdg stmt = - let key = K.stmt_key stmt in find_node pdg key +let find_stmt_node pdg stmt = find_node pdg (Key.stmt_key stmt) let find_entry_point_node pdg = - try - let key = K.entry_point in - find_node pdg key - with PdgIndex.NotFound -> - assert false - -let find_top_input_node pdg = - let key = K.top_input in find_node pdg key + try find_node pdg Key.entry_point + with Not_found -> assert false +let find_top_input_node pdg = find_node pdg Key.top_input let find_loc_nodes pdg state loc = let nodes, undef = Pdg_state.get_loc_nodes state loc in @@ -111,7 +107,7 @@ | Locations.Zone.Top(_,_) -> begin try (find_top_input_node pdg, None)::init_nodes - with PdgIndex.NotFound -> init_nodes + with Not_found -> init_nodes end | _ -> init_nodes in @@ -141,7 +137,7 @@ else match stmt.skind, stmt.succs with | Return _, [] -> get_nodes (get_last_state pdg) | _, [] -> (* no successors but not a return => unreachable *) - raise PdgIndex.NotFound + raise Not_found | _, succs -> get_stmts_nodes succs in nodes, undef_zone @@ -153,10 +149,10 @@ * init_state only contains implicit inputs * while begin contains only formal arguments *) let find_location_nodes_at_begin pdg loc = - let kf = M.get_pdg_kf pdg in + let kf = Pdg.get_kf pdg in let stmts = - try let f = Kernel_function.get_definition kf in f.sbody.bstmts - with Kernel_function.No_Definition -> [] + if !Db.Value.use_spec_instead_of_definition kf then [] + else let f = Kernel_function.get_definition kf in f.sbody.bstmts in let state = match stmts with | [] -> get_last_state pdg @@ -165,23 +161,18 @@ find_loc_nodes pdg state loc let find_label_node pdg label_stmt label = - let key = K.label_key label_stmt label in - find_node pdg key + find_node pdg (Key.label_key label_stmt label) -let find_decl_var_node pdg v = - let key = K.decl_var_key v in - find_node pdg key +let find_decl_var_node pdg v = find_node pdg (Key.decl_var_key v) -let find_output_node pdg = - let key = K.output_key in - find_node pdg key +let find_output_node pdg = find_node pdg Key.output_key let find_input_node pdg numin = - let sgn = FI.sgn (PdgTypes.Pdg.get_index pdg) in + let sgn = FctIndex.sgn (Pdg.get_index pdg) in PdgIndex.Signature.find_input sgn numin let find_all_input_nodes pdg = - let sgn = FI.sgn (PdgTypes.Pdg.get_index pdg) in + let sgn = FctIndex.sgn (Pdg.get_index pdg) in let add acc (_in_key, info) = info::acc in PdgIndex.Signature.fold_all_inputs add [] sgn @@ -189,24 +180,24 @@ match in_key with | PdgIndex.Signature.InCtrl | PdgIndex.Signature.InNum _ -> - let idx = PdgTypes.Pdg.get_index pdg_caller in - let _, call_sgn = FI.find_call idx call_stmt in + let idx = Pdg.get_index pdg_caller in + let _, call_sgn = FctIndex.find_call idx call_stmt in let node = PdgIndex.Signature.find_in_info call_sgn in_key in [ node, None ], None | PdgIndex.Signature.InImpl zone -> find_location_nodes_at_stmt pdg_caller call_stmt ~before:true zone let find_call_ctrl_node pdg stmt = - let key = K.call_ctrl_key stmt in + let key = Key.call_ctrl_key stmt in find_node pdg key let find_call_num_input_node pdg call num_in = if num_in = 0 then Pdg_parameters.fatal "0 is not an input number" ; - let key = K.call_input_key call num_in in + let key = Key.call_input_key call num_in in find_node pdg key let find_call_output_node pdg call = - let key = K.call_outret_key call in + let key = Key.call_outret_key call in find_node pdg key let find_output_nodes called_pdg out_key = @@ -241,7 +232,7 @@ (** add the node in the list if it is not already in. *) let add_node_in_list node node_list = let is_node_in node node_list = - let is_node n = (N.compare node n) = 0 in + let is_node n = (Node.compare node n) = 0 in try let _ = List.find is_node node_list in true with Not_found -> false in @@ -256,9 +247,9 @@ let node_list, added = add_node_in_list node node_list in if added then - let is_block = match N.elem_key node with - | K.SigKey (PdgIndex.Signature.In PdgIndex.Signature.InCtrl) -> true - | K.Stmt stmt -> + let is_block = match Node.elem_key node with + | Key.SigKey (PdgIndex.Signature.In PdgIndex.Signature.InCtrl) -> true + | Key.Stmt stmt -> (match stmt.skind with Block _ | UnspecifiedSequence _ -> true | _ -> false) @@ -268,7 +259,7 @@ then node_list (* blocks are not relevant to propagate information *) else List.fold_left - (add_node_and_custom_dpds get_dpds) node_list (get_dpds node) + (add_node_and_custom_dpds get_dpds) node_list (get_dpds node) else node_list let add_nodes_and_custom_dpds get_dpds node_list nodes = @@ -281,22 +272,22 @@ let filter_nodes l = List.map (fun (n,_) -> n) l let get_both_dpds pdg n = - filter_nodes (P.get_all_direct_codpds pdg n @ P.get_all_direct_dpds pdg n) + filter_nodes (Pdg.get_all_direct_codpds pdg n @ Pdg.get_all_direct_dpds pdg n) (** {3 Backward} build sets of the dependencies of given nodes *) (** gives the list of nodes that the given node depends on, without looking at the kind of dependency. *) -let direct_dpds pdg node = filter_nodes (P.get_all_direct_dpds pdg node) +let direct_dpds pdg node = filter_nodes (Pdg.get_all_direct_dpds pdg node) (** gives the list of nodes that the given node depends on, with a given kind of dependency. *) let direct_x_dpds dpd_type pdg node = - filter_nodes (P.get_x_direct_dpds dpd_type pdg node) + filter_nodes (Pdg.get_x_direct_dpds dpd_type pdg node) -let direct_data_dpds = direct_x_dpds D.Data -let direct_ctrl_dpds = direct_x_dpds D.Ctrl -let direct_addr_dpds = direct_x_dpds D.Addr +let direct_data_dpds = direct_x_dpds Dpd.Data +let direct_ctrl_dpds = direct_x_dpds Dpd.Ctrl +let direct_addr_dpds = direct_x_dpds Dpd.Addr (** accumulates in [node_list] the results of [add_node_and_dpds_or_codpds] for all the [nodes] *) @@ -323,34 +314,37 @@ in List.fold_left merge_dpds [] nodes -let find_nodes_all_data_dpds = find_nodes_all_x_dpds D.Data -let find_nodes_all_ctrl_dpds = find_nodes_all_x_dpds D.Ctrl -let find_nodes_all_addr_dpds = find_nodes_all_x_dpds D.Addr +let find_nodes_all_data_dpds = find_nodes_all_x_dpds Dpd.Data +let find_nodes_all_ctrl_dpds = find_nodes_all_x_dpds Dpd.Ctrl +let find_nodes_all_addr_dpds = find_nodes_all_x_dpds Dpd.Addr (** {3 Forward} build sets of the nodes that depend on given nodes *) (** @return the list of nodes that directly depend on the given node *) -let direct_uses pdg node = filter_nodes (P.get_all_direct_codpds pdg node) +let direct_uses pdg node = filter_nodes (Pdg.get_all_direct_codpds pdg node) let direct_x_uses dpd_type pdg node = - filter_nodes (P.get_x_direct_codpds dpd_type pdg node) + filter_nodes (Pdg.get_x_direct_codpds dpd_type pdg node) -let direct_data_uses = direct_x_uses D.Data -let direct_ctrl_uses = direct_x_uses D.Ctrl -let direct_addr_uses = direct_x_uses D.Addr +let direct_data_uses = direct_x_uses Dpd.Data +let direct_ctrl_uses = direct_x_uses Dpd.Ctrl +let direct_addr_uses = direct_x_uses Dpd.Addr (** @return a list containing all the nodes that depend on the given nodes. *) let all_uses pdg nodes = let add_codpds node_list node = - let codpds = P.get_all_direct_codpds pdg node in + let codpds = Pdg.get_all_direct_codpds pdg node in let codpds = filter_nodes codpds in - let get n = filter_nodes (P.get_all_direct_codpds pdg n) in + let get n = filter_nodes (Pdg.get_all_direct_codpds pdg n) in add_nodes_and_custom_dpds get node_list codpds in List.fold_left add_codpds [] nodes (** {3 Others} *) +let node_set_of_list l = + List.fold_left (fun acc n -> NodeSet.add n acc) NodeSet.empty l + (** build a list of all the nodes that are related 'somehow' to the given nodes. It is a kind of transitive closure of [all_uses] U [all_dpds]. *) let all_related_nodes pdg nodes = @@ -366,22 +360,21 @@ "[pdg:find_call_out_nodes_to_select] for call sid:%d@." call_stmt.sid; let _, call_sgn = - FI.find_call (PdgTypes.Pdg.get_index pdg_caller) call_stmt + FctIndex.find_call (Pdg.get_index pdg_caller) call_stmt in - let called_selected_nodes_set = - PdgTypes.NodeSet.add_list called_selected_nodes in + let called_selected_nodes_set = node_set_of_list called_selected_nodes in let test_out acc (out_key, call_out_node) = let called_out_nodes, _undef = find_output_nodes pdg_called out_key in (* undef can be ignored in this case because it is taken into account in * the call part. *) let intersect = List.exists - (fun (n,_z) -> PdgTypes.NodeSet.mem n called_selected_nodes_set) + (fun (n,_z) -> NodeSet.mem n called_selected_nodes_set) called_out_nodes in if intersect then begin Pdg_parameters.debug ~level:2 - "\t+ n_%a@." Macros.pretty_node call_out_node; + "\t+ %a@." Node.pretty call_out_node; call_out_node::acc end else acc @@ -393,9 +386,8 @@ Pdg_parameters.debug ~level:2 "[pdg:find_in_nodes_to_select_for_this_call] for call sid:%d@." call_stmt.sid; - let sgn = FI.sgn (PdgTypes.Pdg.get_index pdg_called) in - let caller_selected_nodes_set = - PdgTypes.NodeSet.add_list caller_selected_nodes in + let sgn = FctIndex.sgn (Pdg.get_index pdg_called) in + let caller_selected_nodes_set = node_set_of_list caller_selected_nodes in let test_in acc (in_key, in_node) = let caller_nodes, _undef = find_call_input_nodes pdg_caller call_stmt in_key in @@ -403,11 +395,12 @@ * the call part. *) let intersect = List.exists - (fun (n,_z) -> PdgTypes.NodeSet.mem n caller_selected_nodes_set) + (fun (n,_z) -> NodeSet.mem n caller_selected_nodes_set) caller_nodes in if intersect then begin - Pdg_parameters.debug ~level:2 "\t+ n_%a@." Macros.pretty_node in_node; + Pdg_parameters.debug ~level:2 "\t+ %a@." + Node.pretty in_node; in_node::acc end else acc diff -Nru frama-c-20110201+carbon+dfsg/src/pdg/sets.mli frama-c-20111001+nitrogen+dfsg/src/pdg/sets.mli --- frama-c-20110201+carbon+dfsg/src/pdg/sets.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg/sets.mli 2011-10-10 08:38:30.000000000 +0000 @@ -24,75 +24,72 @@ (** PDG (program dependence graph) access functions. *) -type t_node = PdgTypes.Node.t -type t_loc = Locations.Zone.t -type t_pdg = PdgTypes.Pdg.t -type t_dpds_kind = PdgTypes.Dpd.td +open PdgTypes -type t_nodes_and_undef = (t_node * t_loc option) list * t_loc option +type t_nodes_and_undef = + (Node.t * Locations.Zone.t option) list * Locations.Zone.t option (** {2 PDG nodes for some elements} *) -val find_stmt_node : t_pdg -> Cil_types.stmt -> t_node -val find_simple_stmt_nodes : t_pdg -> Cil_types.stmt -> t_node list -val find_stmt_and_blocks_nodes : t_pdg -> Cil_types.stmt -> t_node list -(*val find_nodes_for_stmt_id : t_pdg -> int -> t_node list*) -val find_location_nodes_at_stmt : - t_pdg -> Cil_types.stmt -> before:bool -> t_loc -> t_nodes_and_undef -val find_location_nodes_at_end : t_pdg -> t_loc -> t_nodes_and_undef -val find_location_nodes_at_begin : t_pdg -> t_loc -> t_nodes_and_undef -val find_label_node : t_pdg -> Cil_types.stmt -> Cil_types.label -> t_node -val find_decl_var_node : t_pdg -> Cil_types.varinfo -> t_node -val find_input_node : t_pdg -> int -> t_node -val find_output_node : t_pdg -> t_node -val find_all_input_nodes : t_pdg -> t_node list -val find_entry_point_node : t_pdg -> t_node -val find_top_input_node : t_pdg -> t_node +val find_stmt_node : Pdg.t -> Cil_types.stmt -> Node.t +val find_simple_stmt_nodes : Pdg.t -> Cil_types.stmt -> Node.t list +val find_stmt_and_blocks_nodes : Pdg.t -> Cil_types.stmt -> Node.t list +(*val find_nodes_for_stmt_id : Pdg.t -> int -> Node.t list*) +val find_location_nodes_at_stmt : Pdg.t -> Cil_types.stmt -> before:bool -> + Locations.Zone.t -> t_nodes_and_undef +val find_location_nodes_at_end : + Pdg.t -> Locations.Zone.t -> t_nodes_and_undef +val find_location_nodes_at_begin : + Pdg.t -> Locations.Zone.t -> t_nodes_and_undef +val find_label_node : Pdg.t -> Cil_types.stmt -> Cil_types.label -> Node.t +val find_decl_var_node : Pdg.t -> Cil_types.varinfo -> Node.t +val find_input_node : Pdg.t -> int -> Node.t +val find_output_node : Pdg.t -> Node.t +val find_all_input_nodes : Pdg.t -> Node.t list +val find_entry_point_node : Pdg.t -> Node.t +val find_top_input_node : Pdg.t -> Node.t val find_output_nodes : - t_pdg -> PdgIndex.Signature.t_out_key -> t_nodes_and_undef + Pdg.t -> PdgIndex.Signature.t_out_key -> t_nodes_and_undef -val find_call_ctrl_node : t_pdg -> Cil_types.stmt -> t_node -val find_call_num_input_node : t_pdg -> Cil_types.stmt -> int -> t_node +val find_call_ctrl_node : Pdg.t -> Cil_types.stmt -> Node.t +val find_call_num_input_node : Pdg.t -> Cil_types.stmt -> int -> Node.t val find_call_input_nodes : - t_pdg -> Cil_types.stmt -> PdgIndex.Signature.t_in_key -> t_nodes_and_undef -val find_call_output_node : t_pdg -> Cil_types.stmt -> t_node + Pdg.t -> Cil_types.stmt -> PdgIndex.Signature.t_in_key -> t_nodes_and_undef +val find_call_output_node : Pdg.t -> Cil_types.stmt -> Node.t val find_call_stmts: - Db_types.kernel_function -> caller:Db_types.kernel_function -> + Cil_types.kernel_function -> caller:Cil_types.kernel_function -> Cil_types.stmt list val find_call_out_nodes_to_select : - t_pdg -> t_node list -> t_pdg -> Cil_types.stmt -> t_node list + Pdg.t -> Node.t list -> Pdg.t -> Cil_types.stmt -> Node.t list val find_in_nodes_to_select_for_this_call : - t_pdg -> t_node list -> Cil_types.stmt -> t_pdg -> t_node list + Pdg.t -> Node.t list -> Cil_types.stmt -> Pdg.t -> Node.t list (* direct dependencies only : * This means the nodes that have an edge to the given node. *) -val direct_dpds : t_pdg -> t_node -> t_node list -val direct_x_dpds : t_dpds_kind -> t_pdg -> t_node -> t_node list -val direct_data_dpds : t_pdg -> t_node -> t_node list -val direct_ctrl_dpds : t_pdg -> t_node -> t_node list -val direct_addr_dpds : t_pdg -> t_node -> t_node list +val direct_dpds : Pdg.t -> Node.t -> Node.t list +val direct_data_dpds : Pdg.t -> Node.t -> Node.t list +val direct_ctrl_dpds : Pdg.t -> Node.t -> Node.t list +val direct_addr_dpds : Pdg.t -> Node.t -> Node.t list (* transitive closure *) -val find_nodes_all_dpds : t_pdg -> t_node list -> t_node list -val find_nodes_all_x_dpds : t_dpds_kind -> t_pdg -> t_node list -> t_node list -val find_nodes_all_data_dpds : t_pdg -> t_node list -> t_node list -val find_nodes_all_ctrl_dpds : t_pdg -> t_node list -> t_node list -val find_nodes_all_addr_dpds : t_pdg -> t_node list -> t_node list +val find_nodes_all_dpds : Pdg.t -> Node.t list -> Node.t list +val find_nodes_all_data_dpds : Pdg.t -> Node.t list -> Node.t list +val find_nodes_all_ctrl_dpds : Pdg.t -> Node.t list -> Node.t list +val find_nodes_all_addr_dpds : Pdg.t -> Node.t list -> Node.t list (* forward *) -val direct_uses : t_pdg -> t_node -> t_node list -val direct_x_uses : t_dpds_kind -> t_pdg -> t_node -> t_node list -val direct_data_uses : t_pdg -> t_node -> t_node list -val direct_ctrl_uses : t_pdg -> t_node -> t_node list -val direct_addr_uses : t_pdg -> t_node -> t_node list +val direct_uses : Pdg.t -> Node.t -> Node.t list +val direct_data_uses : Pdg.t -> Node.t -> Node.t list +val direct_ctrl_uses : Pdg.t -> Node.t -> Node.t list +val direct_addr_uses : Pdg.t -> Node.t -> Node.t list -val all_uses : t_pdg -> t_node list -> t_node list +val all_uses : Pdg.t -> Node.t list -> Node.t list (* others *) -val custom_related_nodes : (t_node -> t_node list) -> t_node list -> t_node list +val custom_related_nodes : (Node.t -> Node.t list) -> Node.t list -> Node.t list diff -Nru frama-c-20110201+carbon+dfsg/src/pdg_types/pdgIndex.ml frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgIndex.ml --- frama-c-20110201+carbon+dfsg/src/pdg_types/pdgIndex.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgIndex.ml 2011-10-10 08:38:28.000000000 +0000 @@ -31,7 +31,6 @@ exception AddError exception CallStatement exception Not_equal -exception NotFound let is_call_stmt stmt = match stmt.skind with Instr (Call _) -> true | _ -> false @@ -44,9 +43,9 @@ type 'info t = { in_ctrl : 'info option ; in_params : (int * 'info) list ; - (** implicit inputs : - Maybe we should use [Lmap_bitwise.Make_bitwise] ? - but that would make things a lot more complicated... :-? *) + (** implicit inputs : + Maybe we should use [Lmap_bitwise.Make_bitwise] ? + but that would make things a lot more complicated... :-? *) in_implicits : (Locations.Zone.t * 'info) list ; out_ret : 'info option ; outputs : (Locations.Zone.t * 'info) list } @@ -57,6 +56,16 @@ Structure (Sum [| [| p_int |]; [| Locations.Zone.packed_descr |] |]) let out_key = Structure (Sum [| [| Locations.Zone.packed_descr |] |]) let key = Structure (Sum [| [| pack in_key |]; [| pack out_key |] |]) + + let t d_info = t_record + [| pack (t_option d_info); + pack (t_list (t_tuple [| p_int; pack d_info |])); + pack (t_list (t_tuple [| Locations.Zone.packed_descr; + pack d_info |])); + pack (t_option d_info); + pack (t_list (t_tuple [| Locations.Zone.packed_descr; + pack d_info |])); + |] end let empty = { in_ctrl = None ; @@ -176,11 +185,11 @@ assert (n <> 0); (* no input 0 : use find_in_ctrl *) List.assoc n sgn.in_params with Not_found -> - raise NotFound + raise Not_found let find_output sgn out_key = let rec find l = match l with - | [] -> raise NotFound + | [] -> raise Not_found | (loc, e)::tl -> if Locations.Zone.equal out_key loc then e else find tl @@ -189,17 +198,17 @@ let find_out_ret sgn = match sgn.out_ret with | Some i -> i - | None -> raise NotFound + | None -> raise Not_found let find_in_ctrl sgn = match sgn.in_ctrl with | Some i -> i - | None -> raise NotFound + | None -> raise Not_found (** try to find an exact match with loc. * we shouldn't try to find a zone that we don't have... *) let find_implicit_input sgn loc = let rec find l = match l with - | [] -> raise NotFound + | [] -> raise Not_found | (in_loc, e)::tl -> if Locations.Zone.equal in_loc loc then e else find tl @@ -282,7 +291,7 @@ | (InNum n) -> Format.fprintf fmt "In%d" n | InCtrl -> Format.fprintf fmt "InCtrl" | InImpl loc -> - Format.fprintf fmt "@[<h 1>In(%a)@]" Locations.Zone.pretty loc + Format.fprintf fmt "@[<h 1>In(%a)@]" Locations.Zone.pretty loc let pretty_out_key fmt key = match key with | OutRet -> Format.fprintf fmt "OutRet" @@ -300,8 +309,7 @@ module Key = struct type t_call_id = Cil_types.stmt - - (* type annot_key = Cil_types.code_annotation *) + let t_call_id_packed_descr = Cil_datatype.Stmt.packed_descr type key = | SigKey of Signature.t_key @@ -317,12 +325,10 @@ | SigCallKey of t_call_id * Signature.t_key (** Key for an element of a call (input or output). * The call is identified by the statement. *) - (* | Annot of annot_key - * annotation identified by its kind and id *) let entry_point = SigKey (Signature.in_ctrl_key) let top_input = SigKey (Signature.in_top_key) - let param_key num_in _param = SigKey (Signature.in_key num_in) + let param_key num_in = SigKey (Signature.in_key num_in) let implicit_in_key loc = SigKey (Signature.in_impl_key loc) let output_key = SigKey (Signature.out_ret_key) @@ -343,11 +349,6 @@ let call_from_id call_id = call_id - (* let code_annot_key annot = Annot (annot) *) - - (* let cmp_annots (a1: annot_key) (a2: annot_key) = - compare a1.annot_id a2.annot_id *) - let stmt key = match key with | SigCallKey (call, _) -> Some call @@ -376,124 +377,111 @@ | CallStmt call -> let call = call_from_id call in Format.fprintf fmt "Call%d : %a" call.sid print_stmt call - | Stmt s -> - print_stmt fmt s - | Label (_,l) -> - Format.fprintf fmt "%a" !Ast_printer.d_label l - | VarDecl v -> - Format.fprintf fmt "VarDecl : %a" !Ast_printer.d_ident v.vname - | SigKey k -> - Format.fprintf fmt "%a" Signature.pretty_key k + | Stmt s -> print_stmt fmt s + | Label (_,l) -> Format.fprintf fmt "%a" !Ast_printer.d_label l + | VarDecl v -> Format.fprintf fmt "VarDecl : %a" !Ast_printer.d_var v + | SigKey k -> Format.fprintf fmt "%a" Signature.pretty_key k | SigCallKey (call, sgn) -> let call = call_from_id call in Format.fprintf fmt "Call%d-%a : %a" call.sid Signature.pretty_key sgn print_stmt call - (* | Annot annot -> - Format.fprintf fmt "CodeAnnot-%d : %a@\n" - annot.annot_id - !Ast_printer.d_code_annotation annot *) include Datatype.Make - (struct - include Datatype.Serializable_undefined - type t = key - let name = "PdgIndex.Key" - open Cil_datatype - let reprs = - List.fold_left - (fun acc v -> - List.fold_left - (fun acc s -> Stmt s :: acc) - (VarDecl v :: acc) - (Type.reprs Stmt.ty)) - [] - (Type.reprs Varinfo.ty) - open Structural_descr - let structural_descr = - let p_key = pack Signature.Str_descr.key in - Structure - (Sum - [| - [| p_key |]; - [| Varinfo.packed_descr |]; - [| Stmt.packed_descr |]; - [| Stmt.packed_descr |]; - [| p_int; Label.packed_descr |]; - [| Stmt.packed_descr; p_key |]; - |]) - let rehash = Datatype.identity - let pretty = pretty_node - let mem_project = Datatype.never_any_project - end) + (struct + include Datatype.Serializable_undefined + type t = key + let name = "PdgIndex.Key" + open Cil_datatype + let reprs = + List.fold_left + (fun acc v -> + List.fold_left + (fun acc s -> Stmt s :: acc) + (VarDecl v :: acc) + Stmt.reprs) + [] + Varinfo.reprs + open Structural_descr + let structural_descr = + let p_key = pack Signature.Str_descr.key in + Structure + (Sum + [| + [| p_key |]; + [| Varinfo.packed_descr |]; + [| Stmt.packed_descr |]; + [| t_call_id_packed_descr |]; + [| p_int; Label.packed_descr |]; + [| t_call_id_packed_descr; p_key |]; + |]) + let rehash = Datatype.identity + let pretty = pretty_node + let mem_project = Datatype.never_any_project + end) end +module Hkey = struct + type tt = Hdecl of Cil_types.varinfo + | Hstmt of int | Hlabel of int * Cil_types.label + let hkey k = + match k with + | Key.Stmt stmt -> Hstmt stmt.sid + | Key.VarDecl var -> Hdecl var + | Key.Label (sid,l) -> Hlabel (sid,l) + | _ -> assert false + + let key hk = match hk with + | Hdecl v -> Key.VarDecl v + | Hstmt sid -> Key.Stmt (fst (Kernel_function.find_from_sid sid)) + | Hlabel (sid,l) -> Key.Label (sid,l) -module FctIndex : sig - type ('a, 'b) t - - val create : int -> ('a, 'b) t - val length : ('a, 'b) t -> int - - val copy : ('a, 'b) t -> ('a, 'b) t - val merge : ('a, 'b) t -> ('a, 'b) t -> - ('a -> 'a -> 'a) -> ('b -> 'b -> 'b) -> - ('a, 'b) t - - val sgn : ('a, 'b) t -> 'a Signature.t - val find_info : ('a, 'b) t -> Key.t-> 'a - val find_all : ('a, 'b) t -> Key.t-> 'a list - - val find_call : ('a, 'b) t -> Cil_types.stmt -> 'b option * 'a Signature.t - val find_call_key : ('a, 'b) t -> Key.t -> 'b option * 'a Signature.t - - val find_info_call : ('a, 'b) t -> Cil_types.stmt -> 'b - val find_info_call_key : ('a, 'b) t -> Key.t -> 'b - - val fold_calls : (Key.t_call_id-> 'b option * 'a Signature.t -> 'c -> 'c) -> - ('a, 'b) t -> 'c -> 'c - - val add : ('a, 'b) t -> Key.t-> 'a -> unit - val add_or_replace : ('a, 'b) t -> Key.t-> 'a -> unit - val add_info_call : ('a, 'b) t -> Key.t_call_id -> 'b -> replace:bool -> unit - val add_info_call_key : ('a, 'b) t -> Key.t -> 'b -> replace:bool -> unit - -end = struct - - module Hkey = struct - type t = Hdecl of Cil_types.varinfo - | Hstmt of int | Hlabel of int * Cil_types.label + include Datatype.Make(struct + include Datatype.Serializable_undefined let hash k = let code n c = assert (c < 4) ; n*4 + c in match k with - | Hdecl v -> code v.vid 1 - | Hstmt n -> code n 2 - | Hlabel (n,_) -> code n 3 + | Hdecl v -> code v.vid 1 + | Hstmt n -> code n 2 + | Hlabel (n,_) -> code n 3 let equal k1 k2 = (hash k1) = (hash k2) + (* TODO: write better function, or check that the computation of the hash + does not overflow *) + type t = tt + let reprs = [Hstmt (-1)] + let name = "PdgIndex.Hkey.t" + end) +end - let hkey k = - match k with - | Key.Stmt stmt -> Hstmt stmt.sid - | Key.VarDecl var -> Hdecl var - | Key.Label (sid,l) -> Hlabel (sid,l) - | _ -> assert false - end - - module H = Hashtbl.Make(Hkey) +module H = Hashtbl.Make(Hkey) - type ('a,'b) t = { +module FctIndex = struct + + type ('node_info, 'call_info) t = { (** inputs and ouputs of the function *) - mutable sgn : 'a Signature.t ; + mutable sgn : 'node_info Signature.t ; (** calls signatures *) - mutable calls : (Key.t_call_id * ('b option * 'a Signature.t)) list ; + mutable calls : + (Key.t_call_id * ('call_info option * 'node_info Signature.t)) list ; (** everything else *) - other : 'a H.t + other : 'node_info H.t } - let hkey = Hkey.hkey + open Structural_descr + let t_descr ~ni:d_ninfo ~ci:d_cinfo = + t_record + [| pack (Signature.Str_descr.t d_ninfo); + pack (t_list (t_tuple [| Key.t_call_id_packed_descr; + pack (t_tuple [| + pack (t_option d_cinfo); + pack (Signature.Str_descr.t d_ninfo); + |]) + |])); + pack (t_hashtbl_unchanged_hashs (Descr.str Hkey.descr) d_ninfo); + |] let sgn idx = idx.sgn @@ -524,19 +512,6 @@ else c2 :: (merge l1 tl2) in merge calls1 calls2 - (* let merge_annots l1 l2 merge_info = - let rec merge l1 l2 = match l1, l2 with - | [], _ -> l2 - | _, [] -> l1 - | (k1, i1)::tl1, (k2, i2)::tl2 -> - let cmp = Key.cmp_annots k1 k2 in - if cmp = 0 then - let info = merge_info i1 i2 in - (k1, info) :: (merge tl1 tl2) - else if cmp < 0 then (k1, i1) :: (merge tl1 l2) - else (k2,i2) :: (merge l1 tl2) - in merge l1 l2 *) - let merge idx1 idx2 merge_a merge_b = let sgn = Signature.merge idx1.sgn idx2.sgn merge_a in let table = H.copy idx1.other in @@ -547,7 +522,6 @@ in H.replace table k a in H.iter add idx2.other; let calls = merge_info_calls idx1.calls idx2.calls merge_a merge_b in - (* let annots = merge_annots idx1.annots idx2.annots merge_a in *) {sgn = sgn; calls = calls; other = table} let add_info_call idx call e ~replace = @@ -582,31 +556,14 @@ else (c1 :: (add tl)) in add calls - (* let rec add_info_annot annots k e replace = match annots with - | [] -> (k, e)::[] - | (ka, ea)::tl -> - let cmp = Key.cmp_annots k ka in - if cmp = 0 then - (if replace then (k, e)::tl else raise AddError) - else if cmp < 0 then - (k,e)::annots - else (ka, ea)::(add_info_annot tl k e replace) - - let rec find_info_annot annots k = match annots with - | [] -> raise NotFound - | (ka, ea)::tl -> - if (Key.cmp_annots k ka) = 0 then ea - else find_info_annot tl k - *) - let find_call idx call = let rec find l = match l with - | [] -> raise NotFound + | [] -> raise Not_found | (call1, e1) :: tl -> let sid = call.sid in let sid1 = call1.sid in if sid = sid1 then e1 - else if sid < sid1 then raise NotFound + else if sid < sid1 then raise Not_found else find tl in find idx.calls @@ -621,7 +578,7 @@ let find_info_call idx call = let (e1, _sgn1) = find_call idx call in - match e1 with Some e -> e | None -> raise NotFound + match e1 with Some e -> e | None -> raise Not_found let find_info_call_key idx key = match key with @@ -645,31 +602,22 @@ | Key.SigCallKey (call, k) -> idx.calls <- add_info_sig_call idx.calls call k e replace | Key.VarDecl _ | Key.Stmt _ | Key.Label _ -> - hfct idx.other (hkey key) e - (* | Key.Annot k -> - idx.annots <- add_info_annot idx.annots k e replace *) + hfct idx.other (Hkey.hkey key) e let add idx key e = add_replace idx key e false let add_or_replace idx key e = add_replace idx key e true - (* let remove idx key = match key with - | Key.Annot ak -> - idx.annots <- - List.filter (fun (k,_) -> Key.cmp_annots k ak <> 0) idx.annots - | _ -> (* TODO is needed... *) assert false *) - let length idx = H.length idx.other - let find_info idx key = match key with | Key.SigKey k -> Signature.find_info idx.sgn k | Key.CallStmt _ -> raise CallStatement (* see find_info_call *) | Key.SigCallKey (call, k) -> find_info_sig_call idx call k | Key.VarDecl _ | Key.Stmt _ | Key.Label _ -> - (try H.find idx.other (hkey key) with Not_found -> raise NotFound) - (* | Key.Annot k -> find_info_annot idx.annots k *) + (try H.find idx.other (Hkey.hkey key) + with Not_found -> raise Not_found) let find_all idx key = match key with @@ -679,19 +627,32 @@ (** Similar to [find_info] for a label *) let find_label idx lab = let collect k info res = match k with - | Hkey.Hlabel (_,k_lab) -> if k_lab = lab then info :: res else res + | Hkey.Hlabel (_,k_lab) -> + if Cil_datatype.Label.equal k_lab lab then info :: res else res | _ -> res in let infos = H.fold collect idx.other [] in match infos with - info :: [] -> info | [] -> raise NotFound | _ -> assert false + info :: [] -> info | [] -> raise Not_found | _ -> assert false let fold_calls f idx acc = - let process acc (call, (i, sgn)) = f call (i, sgn) acc in + let process acc (call, (_i, _sgn as i_sgn)) = f call i_sgn acc in List.fold_left process acc idx.calls -(* let fold_implicit_inputs f acc idx = - Signature.fold_impl_inputs f acc idx.sgn *) + let fold f idx acc = + let acc = Signature.fold + (fun acc (k, info) -> f (Key.SigKey k) info acc) + acc idx.sgn in + let acc = H.fold + (fun k info acc -> f (Hkey.key k) info acc) idx.other acc in + List.fold_left + (fun acc (call, (_, sgn)) -> + Signature.fold (fun acc (k, info) -> + f (Key.SigCallKey (call, k)) info acc) + acc sgn) + acc idx.calls + + end (* diff -Nru frama-c-20110201+carbon+dfsg/src/pdg_types/pdgIndex.mli frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgIndex.mli --- frama-c-20110201+carbon+dfsg/src/pdg_types/pdgIndex.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgIndex.mli 2011-10-10 08:38:28.000000000 +0000 @@ -43,9 +43,6 @@ * information has a different type. *) exception CallStatement -(** When we try to find an element that is not in the index *) -exception NotFound - (** When we compare two things with different locations (no order) *) exception Not_equal @@ -114,7 +111,7 @@ module Key : sig (** type to identify a call statement *) - type t_call_id + type t_call_id = Cil_types.stmt type key = private @@ -129,9 +126,7 @@ include Datatype.S with type t = key - (* [VP 2011-02-02] What is exactly the purpose of this unused parameter 'a? - *) - val param_key : int -> 'a -> t + val param_key : int -> t val implicit_in_key : Locations.Zone.t -> t val entry_point : t val top_input : t @@ -155,6 +150,7 @@ end + (** Mapping between the function elements we are interested in and some * information. Used for instance to associate the nodes with the statements, * or the marks in a slice. @@ -163,58 +159,66 @@ (** this type is used to build indexes between program objects and some information such as the PDG nodes or the slicing marks. - - ['a] if the type of the information to store for each element, - - ['b] if the type of the information that can be attached to call - statements (calls are themselves composed of several elements, so ['a] - information stored for each of them (['a Signature.t])) *) - type ('a, 'b) t + - ['ni] if the type of the information to store for each element, + - ['ci] if the type of the information that can be attached to call + statements (calls are themselves composed of several elements, so ['ni] + information stored for each of them (['ni Signature.t])) *) + type ('ni, 'ci) t - val create: int -> ('a, 'b) t - val length: ('a, 'b) t -> int + val create : int -> ('ni, 'ci) t + val length : ('ni, 'ci) t -> int (** just copy the mapping *) - val copy: ('a, 'b) t -> ('a, 'b) t + val copy : ('ni, 'ci) t -> ('ni, 'ci) t (** merge the two indexes using given functions [merge_a] and [merge_b]. These function are _not_ called when an element is in one index, but not the other. It is assumed that [merge_x x bot = x]. *) - val merge: ('a, 'b) t -> ('a, 'b) t -> - ('a -> 'a -> 'a) -> ('b -> 'b -> 'b) -> - ('a, 'b) t + val merge : ('ni, 'ci) t -> ('ni, 'ci) t -> + ('ni -> 'ni -> 'ni) -> + ('ci -> 'ci -> 'ci) -> + ('ni, 'ci) t (** get the information stored for the function signature *) - val sgn: ('a, 'b) t -> 'a Signature.t + val sgn : ('ni, 'ci) t -> 'ni Signature.t (** find the information stored for the key. Cannot be used for [Key.CallStmt] keys because the type of the stored information is not the same. See [find_call] instead. *) - val find_info: ('a, 'b) t -> Key.t -> 'a + val find_info : ('ni, 'ci) t -> Key.t-> 'ni (** same than [find_info] except for call statements for which it gives the list of all the information in the signature of the call. *) - val find_all: ('a, 'b) t -> Key.t -> 'a list + val find_all : ('ni, 'ci) t -> Key.t-> 'ni list (** find the information stored for the call and its signature *) - val find_call: ('a, 'b) t -> Cil_types.stmt -> 'b option * 'a Signature.t - val find_call_key: ('a, 'b) t -> Key.t -> 'b option * 'a Signature.t + val find_call : + ('ni, 'ci) t -> Cil_types.stmt -> 'ci option * 'ni Signature.t + val find_call_key : ('ni, 'ci) t -> Key.t -> 'ci option * 'ni Signature.t (** find the information stored for the call *) - val find_info_call: ('a, 'b) t -> Cil_types.stmt -> 'b - val find_info_call_key: ('a, 'b) t -> Key.t -> 'b + val find_info_call : ('ni, 'ci) t -> Cil_types.stmt -> 'ci + val find_info_call_key : ('ni, 'ci) t -> Key.t -> 'ci + + val fold_calls : + (Key.t_call_id-> 'ci option * 'ni Signature.t -> 'c -> 'c) -> + ('ni, 'ci) t -> 'c -> 'c - val fold_calls: - (Cil_types.stmt -> 'b option * 'a Signature.t -> 'c -> 'c) -> - ('a, 'b) t -> 'c -> 'c + val fold : (Key.key -> 'ni -> 'a -> 'a) -> ('ni, 'ci) t -> 'a -> 'a (** store the information for the key. @raise AddError if there is already something stored. *) - val add: ('a, 'b) t -> Key.t -> 'a -> unit - + val add : ('ni, 'ci) t -> Key.t-> 'ni -> unit (** store the information for the key. Replace the previously stored information if any. *) - val add_or_replace: ('a, 'b) t -> Key.t -> 'a -> unit + val add_or_replace : ('ni, 'ci) t -> Key.t-> 'ni -> unit + val add_info_call : + ('ni, 'ci) t -> Key.t_call_id -> 'ci -> replace:bool -> unit + val add_info_call_key : ('ni, 'ci) t -> Key.t -> 'ci -> replace:bool -> unit + - val add_info_call: ('a, 'b) t -> Cil_types.stmt -> 'b -> replace:bool -> unit - val add_info_call_key: ('a, 'b) t -> Key.t -> 'b -> replace:bool -> unit + (** Structural destructor for unmarshaling *) + val t_descr: + ni:Structural_descr.t -> ci:Structural_descr.t -> Structural_descr.t end diff -Nru frama-c-20110201+carbon+dfsg/src/pdg_types/pdgMarks.ml frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgMarks.ml --- frama-c-20110201+carbon+dfsg/src/pdg_types/pdgMarks.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgMarks.ml 2011-10-10 08:38:28.000000000 +0000 @@ -83,12 +83,11 @@ type t_mark type t_call_info - type t_idx = (t_mark, t_call_info) PdgIndex.FctIndex.t - - type t = PdgTypes.Pdg.t * t_idx + type t_fi = (t_mark, t_call_info) PdgIndex.FctIndex.t + type t = PdgTypes.Pdg.t * t_fi val create : PdgTypes.Pdg.t -> t - val get_idx : t -> t_idx + val get_idx : t -> t_fi type t_mark_info_inter = t_mark t_info_inter @@ -113,21 +112,20 @@ module F_Fct (M : T_Mark) : T_Fct with type t_mark = M.t and type t_call_info = M.t_call_info - and type t_idx = (M.t, M.t_call_info) FctIndex.t = struct type t_mark = M.t type t_call_info = M.t_call_info - type t_idx = (t_mark, t_call_info) FctIndex.t - type t = Pdg.t * t_idx + type t_fi = (t_mark, t_call_info) PdgIndex.FctIndex.t + type t = Pdg.t * t_fi type t_mark_info_inter = t_mark t_info_inter let empty_to_prop = ([], []) let create pdg = - let idx = (FctIndex.create 100) (* TODO Pdg.get_index_size pdg *) + let idx = (PdgIndex.FctIndex.create 17) (* TODO Pdg.get_index_size pdg *) in (pdg, idx) let get_idx (_pdg, idx) = idx @@ -146,11 +144,11 @@ begin (* simple node *) let new_mark, mark_to_prop = try - let old_mark = FctIndex.find_info fm node_key in + let old_mark = PdgIndex.FctIndex.find_info fm node_key in let new_m, m_prop = M.combine old_mark mark in (new_m, m_prop) - with PdgIndex.NotFound -> (mark, mark) - in FctIndex.add_or_replace fm node_key new_mark; + with Not_found -> (mark, mark) + in PdgIndex.FctIndex.add_or_replace fm node_key new_mark; mark_to_prop end with PdgIndex.CallStatement -> (* call statement *) assert false @@ -204,16 +202,16 @@ then (c, add_out_key l out_key)::tl else (c, l)::(add_out tl call out_key) in - match key with - | Key.SigCallKey (call, Signature.Out out_key) -> - let in_marks, out_marks = to_prop in - let call = Key.call_from_id call in - let new_out_marks = add_out out_marks call out_key in - (in_marks, new_out_marks) - | Key.SigKey (Signature.In in_key) -> - let to_prop = add_in_to_to_prop to_prop in_key mark in - to_prop - | _ -> (* nothing to do *) to_prop + match key with + | Key.SigCallKey (call, Signature.Out out_key) -> + let in_marks, out_marks = to_prop in + let call = Key.call_from_id call in + let new_out_marks = add_out out_marks call out_key in + (in_marks, new_out_marks) + | Key.SigKey (Signature.In in_key) -> + let to_prop = add_in_to_to_prop to_prop in_key mark in + to_prop + | _ -> (* nothing to do *) to_prop (** mark the nodes and their dependencies with the given mark. @@ -223,9 +221,11 @@ * *) let rec add_node_mark_rec pdg fm node_marks to_prop = let mark_node_and_dpds to_prop (node, z_opt, mark) = + Kernel.debug ~level:2 + "[pdgMark] add mark to node %a" PdgTypes.Node.pretty node; let node_key = PdgTypes.Node.elem_key node in let node_key = match z_opt with - | None -> node_key + | None -> node_key | Some z -> match node_key with | Key.SigCallKey (call, Signature.Out (Signature.OutLoc out_z)) -> @@ -240,7 +240,7 @@ to_prop end else begin Kernel.debug ~level:2 - "[pdgMark] mark_and_propagate = to propagate %a@\n" + "[pdgMark] mark_and_propagate = to propagate %a@\n" M.pretty mark_to_prop; let to_prop = add_to_to_prop to_prop node_key mark_to_prop in let dpds_info = PdgTypes.Pdg.get_all_direct_dpds pdg node in @@ -256,13 +256,13 @@ let process to_prop (sel, mark) = match sel with | SelNode (n, z_opt) -> Kernel.debug ~level:2 - "[pdgMark] mark_and_propagate start with %a@\n" + "[pdgMark] mark_and_propagate start with %a@\n" PdgTypes.Node.pretty_with_part (n, z_opt); add_node_mark_rec pdg idx [(n, z_opt, mark)] to_prop | SelIn loc -> let in_key = Key.implicit_in_key loc in Kernel.debug ~level:2 - "[pdgMark] mark_and_propagate start with %a@\n" + "[pdgMark] mark_and_propagate start with %a@\n" Key.pretty in_key; let mark_to_prop = add_mark pdg idx in_key mark in if M.is_bottom mark_to_prop then to_prop @@ -274,8 +274,11 @@ module type T_Proj = sig type t - type t_fct + type t_mark + type t_call_info + type t_fct = (t_mark, t_call_info) PdgIndex.FctIndex.t + val empty : t val find_marks : t -> Cil_types.varinfo -> t_fct option val mark_and_propagate : diff -Nru frama-c-20110201+carbon+dfsg/src/pdg_types/pdgMarks.mli frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgMarks.mli --- frama-c-20110201+carbon+dfsg/src/pdg_types/pdgMarks.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgMarks.mli 2011-10-10 08:38:28.000000000 +0000 @@ -107,12 +107,11 @@ type t_mark type t_call_info - type t_idx = (t_mark, t_call_info) PdgIndex.FctIndex.t - - type t = PdgTypes.Pdg.t * t_idx + type t_fi = (t_mark, t_call_info) PdgIndex.FctIndex.t + type t = PdgTypes.Pdg.t * t_fi val create : PdgTypes.Pdg.t -> t - val get_idx : t -> t_idx + val get_idx : t -> t_fi type t_mark_info_inter = t_mark t_info_inter @@ -135,8 +134,10 @@ It is defined in PDG pluggin *) module type T_Proj = sig type t - type t_fct + type t_mark + type t_call_info + type t_fct = (t_mark, t_call_info) PdgIndex.FctIndex.t val empty: t val find_marks: t -> Cil_types.varinfo -> t_fct option diff -Nru frama-c-20110201+carbon+dfsg/src/pdg_types/pdgTypes.ml frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgTypes.ml --- frama-c-20110201+carbon+dfsg/src/pdg_types/pdgTypes.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgTypes.ml 2011-10-10 08:38:28.000000000 +0000 @@ -26,50 +26,95 @@ open Cil_types -(** this one shouldn't occur, but... *) -exception Pdg_Internal_Error of string -module Elem = struct +(** Node.t is the type of the PDG vertex. + [compare] and [pretty] are needed by [Abstract_interp.Make_Lattice_Set]. *) +module Node = struct type key = PdgIndex.Key.t type tt = { id : int; key : key } - let make counter key = - {id = (incr counter; - if !counter = -1 then - failwith "Internal limit reached in PDG counter"; - !counter); + module Counter = + State_builder.Counter(struct let name = "PdgTypes.Node.Counter" end) + + let make key = + {id = Counter.next (); key = key} let key e = e.key let print_id fmt e = Format.fprintf fmt "%d" e.id - include Datatype.Make - (struct - type t = tt - let name = "PdgTypes.Elem" - let structural_descr = - Structural_descr.t_record - [| Structural_descr.p_int; PdgIndex.Key.packed_descr |] - let reprs = [ { id = -1; key = PdgIndex.Key.top_input } ] - let compare e1 e2 = Datatype.Int.compare e1.id e2.id - let hash e = e.id - let equal e1 e2 = e1.id = e2.id - let pretty = print_id - let rehash = Datatype.identity - let copy = Datatype.undefined - let internal_pretty_code = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - end) + let elem_id n = n.id + let elem_key n = key n + let stmt n = PdgIndex.Key.stmt n.key + + (* BY: not sure it is a good idea to use (=) on keys, which contain + Cil structures. Disabled for now + (** tells if the node represent the same thing that the given key. *) + let equivalent n key = (elem_key n) = key + *) + + let print_id fmt n = + Format.fprintf fmt "n:%a" print_id n + + include Datatype.Make_with_collections + (struct + type t = tt + let name = "PdgTypes.Elem" + let reprs = [ { id = -1; key = PdgIndex.Key.top_input } ] + let structural_descr = Structural_descr.t_record + [| Structural_descr.p_int; PdgIndex.Key.packed_descr |] + let compare e1 e2 = Datatype.Int.compare e1.id e2.id + let hash e = e.id + let equal e1 e2 = e1.id = e2.id + let pretty = print_id + let rehash = Datatype.identity + let copy = Datatype.undefined + let internal_pretty_code = Datatype.undefined + let varname = Datatype.undefined + let mem_project = Datatype.never_any_project + end) + + let pretty_list fmt l = + List.iter (fun n -> Format.fprintf fmt " %a" pretty n) l + + let pretty_with_part fmt (n, z_part) = + Format.fprintf fmt "%a" pretty n; + match z_part with None -> () + | Some z -> Format.fprintf fmt "(restrict to @[<h 1>%a@])" + Locations.Zone.pretty z + + let pretty_node fmt n = + Format.fprintf fmt "[Elem] %d : %a" (elem_id n) + PdgIndex.Key.pretty (elem_key n) + + let pretty_nodes fmt nodes = + let pretty_node n = Format.fprintf fmt "%a@." pretty_node n in + List.iter pretty_node nodes end +module NodeSet = Hptset.Make(struct include Node let id = elem_id end) + (struct let v = [ [ ] ] end) + (struct let l = [ Ast.self ] end) + +(** set of nodes of the graph *) +module NodeSetLattice = struct + include Abstract_interp.Make_Lattice_Set(Node) + type t_elt = O.elt + let tag = hash + let default _v _a _b : t = empty + let defaultall _v : t = empty +end + +module LocInfo = Lmap_bitwise.Make_bitwise (NodeSetLattice) + + (** Edges label for the Program Dependence Graph. *) module Dpd : sig - type t + include Datatype.S (** used to speak about the different kinds of dependencies *) type td = Ctrl | Addr | Data @@ -89,9 +134,6 @@ val is_dpd : td -> t -> bool val is_bottom : t -> bool - (** total order. Used only to sort...*) - val compare : t -> t -> int - val equal : t -> t -> bool val is_included : t -> t -> bool val combine : t -> t -> t @@ -102,91 +144,63 @@ (** remove the flags that are in m2 for m1 *) val minus : t -> t -> t + val pretty_td : Format.formatter -> td -> unit val pretty : Format.formatter -> t -> unit end = struct - type t = {addr : bool; data: bool; ctrl:bool } type td = Ctrl | Addr | Data + let pretty_td fmt td = + Format.fprintf fmt "%s" + (match td with Ctrl -> "c" | Addr -> "a" | Data -> "d") + + include Datatype.Int (* Encoding: %b addr; %b data; %b control *) + let maddr = 0x100 + let mdata = 0x010 + let mctrl = 0x001 - (* internal constructor *) - let create ?(a=false) ?(d=false) ?(c=false) _ = - { addr = a; data = d; ctrl = c } - - (* all possible value for [t] *) - let bottom = create () - let top = create ~a:true ~d:true ~c:true () - let a_dpd = create ~a:true () - let d_dpd = create ~d:true () - let c_dpd = create ~c:true () - let ad_dpd = create ~a:true ~d:true () - let ac_dpd = create ~a:true ~c:true () - let dc_dpd = create ~d:true ~c:true () - - (* external constructor sharing identical [t] values *) let make ?(a=false) ?(d=false) ?(c=false) _ = match a,d,c with - | false, false, false -> bottom - | true, false, false -> a_dpd - | false, true, false -> d_dpd - | false, false, true -> c_dpd - | true, true, false -> ad_dpd - | true, false, true -> ac_dpd - | false, true, true -> dc_dpd - | true, true, true -> top - - (* the use the external constructor ensures [==] can be used instead of [=] *) - let equal d1 d2 = d1 == d2 - - let make_simple kind = match kind with - | Ctrl -> c_dpd - | Addr -> a_dpd - | Data -> d_dpd + | false, false, false -> 0x000 + | true, false, false -> 0x100 + | false, true, false -> 0x010 + | false, false, true -> 0x001 + | true, true, false -> 0x110 + | true, false, true -> 0x101 + | false, true, true -> 0x011 + | true, true, true -> 0x111 + let bottom = 0x000 + let top = 0x111 let default = bottom - let is_addr d = d.addr - let is_ctrl d = d.ctrl - let is_data d = d.data + let is_addr d = (d land maddr) != 0 + let is_ctrl d = (d land mctrl) != 0 + let is_data d = (d land mdata) != 0 let is_dpd tdpd d = match tdpd with - | Addr -> d.addr - | Ctrl -> d.ctrl - | Data -> d.data + | Addr -> is_addr d + | Ctrl -> is_ctrl d + | Data -> is_data d - let is_bottom d = equal d bottom + let is_bottom = (=) bottom let adc_value d = (is_addr d, is_data d, is_ctrl d) - let compare : t -> t -> int = Extlib.compare_basic + let combine d1 d2 = d1 lor d2 + let inter d1 d2 = d1 land d2 + let intersect d1 d2 = inter d1 d2 != 0 + let is_included d1 d2 = combine d1 d2 = d2 - let combine d1 d2 = - if (d1 == d2) then d1 - else make - ~a:(d1.addr || d2.addr) - ~c:(d1.ctrl || d2.ctrl) - ~d:(d1.data || d2.data) () - - let inter d1 d2 = - if (d1 == d2) then d1 - else make - ~a:(d1.addr && d2.addr) - ~c:(d1.ctrl && d2.ctrl) - ~d:(d1.data && d2.data) () - - let is_included d1 d2 = let d = combine d1 d2 in equal d d2 - let intersect d1 d2 = let d = inter d1 d2 in not (is_bottom d) + let make_simple kind = match kind with + | Ctrl -> mctrl + | Addr -> maddr + | Data -> mdata let add d kind = combine d (make_simple kind) - let minus adc1 adc2 = - let a1, d1, c1 = adc_value adc1 in - let a2, d2, c2 = adc_value adc2 in - let a = if a2 then false else a1 in - let d = if d2 then false else d1 in - let c = if c2 then false else c1 in - make ~a ~d ~c () + let minus adc1 adc2 = adc1 land (lnot adc2) let pretty fmt d = Format.fprintf fmt "[%c%c%c]" (if is_addr d then 'a' else '-') @@ -196,23 +210,22 @@ end module DpdZone : sig - type t + include Datatype.S + val is_dpd : Dpd.td -> t -> bool val make : Dpd.td -> Locations.Zone.t option -> t val add : t -> Dpd.td -> Locations.Zone.t option -> t val kind_and_zone : t -> Dpd.t * Locations.Zone.t option val dpd_zone : t -> Locations.Zone.t option - (** total order. Used only to sort...*) - val compare : t -> t -> int - val equal : t -> t -> bool - val default : t val pretty : Format.formatter -> t -> unit + val tag: t -> int end = struct - type t = Dpd.t * Locations.Zone.t option (* None == Locations.Zone.Top *) + include Datatype.Pair(Dpd)(Datatype.Option(Locations.Zone)) + (* None == Locations.Zone.Top *) let dpd_kind dpd = fst dpd let dpd_zone dpd = snd dpd @@ -223,39 +236,13 @@ let is_dpd k dpd = Dpd.is_dpd k (dpd_kind dpd) - let equal dpd1 dpd2 = - let cmp = Dpd.equal (dpd_kind dpd1) (dpd_kind dpd2) in - if cmp then - match (dpd_zone dpd1), (dpd_zone dpd2) with - | None, None -> true - | Some z1, Some z2 -> Locations.Zone.equal z1 z2 - | _, _ -> false - else false - - - let compare dpd1 dpd2 = - if equal dpd1 dpd2 then 0 - else assert false (* is this useful ? TODO ? *) - (* - let cmp = Dpd.compare (dpd_kind dpd1) (dpd_kind dpd2) in - if cmp = 0 then - match (dpd_zone dpd1), (dpd_zone dpd2) with - | None, None -> 0 - | _, None -> -1 - | None, _ -> 1 - | Some z1, Some z2 -> - if Locations.Zone.equal z1 z2 then 0 - else assert false (* is this useful ? TODO ? *) - else cmp - *) - let add ((d1,z1) as dpd) k z = let d = Dpd.add d1 k in let z = match z1, z with | None, _ -> z1 | _, None -> z | Some zz1, Some zz2 -> - (* we are loosing some precision here because for instance : + (* we are losing some precision here because for instance : * (zz1, addr) + (zz2, data) = (zz1 U zz2, data+addr) *) let zz = Locations.Zone.join zz1 zz2 in match zz with @@ -271,46 +258,134 @@ match (dpd_zone dpd) with None -> () | Some z -> Format.fprintf fmt "@[<h 1>(%a)@]" Locations.Zone.pretty z + + let tag = hash end -(** The graph itself. -* It uses ocamlgraph -* {{:http://ocamlgraph.lri.fr/doc/Imperative.S.concreteLabeled.html}Graph.Imperative.Digraph}. -* @see <http://ocamlgraph.lri.fr/> ocamlgraph web site -*) +(** The graph itself. *) module G = struct - module IGraph = Graph.Imperative.Digraph.AbstractLabeled(Elem)(DpdZone) - module E = IGraph.E - module V = IGraph.V - - (* Could be declared private out of G if the sig was explicit. *) - type t = { counter : int ref; graph : IGraph.t } - - let create = - fun () -> - let counter = ref (-1) in (*BUG: Should be ok but slicing fails if - it is not shared among all graphs?????? *) - { counter = counter; - graph = IGraph.create ()} + (* Hashtbl to maps of nodes to dpdzone. Used to encode one-directional graphs + whoses nodes are Node.t, and labels on edges are DpdZone. *) + module V = struct include Node let id = elem_id end + module E = struct + type t = Node.t * DpdZone.t * Node.t + type label = DpdZone.t + let src (n, _, _) = n + let dst (_, _, n) = n + let label (_, l, _) = l + end + + module To = Hptmap.Make(V)(DpdZone)(Hptmap.Comp_unused) + (struct let v = [[]] end)(struct let l = [Ast.self] end) + + module OneDir = Node.Hashtbl.Make(To) + + let add_node_one_dir g v = + if not (Node.Hashtbl.mem g v) then + Node.Hashtbl.add g v To.empty + + let add_edge_one_dir g vsrc vdst lbl = + let cur = try Node.Hashtbl.find g vsrc with Not_found -> To.empty in + let cur = To.add vdst lbl cur in + Node.Hashtbl.replace g vsrc cur + + let remove_edge_one_dir g vsrc vdst = + try + let cur = Node.Hashtbl.find g vsrc in + let cur = To.remove vdst cur in + Node.Hashtbl.replace g vsrc cur + with Not_found -> () + + let aux_iter_one_dir ?(rev=false) f v = + To.iter (fun v' lbl -> f (if rev then (v', lbl, v) else (v, lbl, v' : E.t))) + let iter_e_one_dir ?(rev=false) f g v = + let to_ = Node.Hashtbl.find g v in + aux_iter_one_dir ~rev f v to_ + + let fold_e_one_dir ?(rev=false) f g v = + let to_ = Node.Hashtbl.find g v in + To.fold (fun v' lbl acc -> + f (if rev then (v', lbl, v) else (v, lbl, v' : E.t)) acc) to_ + + let fold_one_dir f g v = + let to_ = Node.Hashtbl.find g v in + To.fold (fun v' _ acc -> f v' acc) to_ + + (* Bi-directional graphs *) + + type g = { + d_graph: OneDir.t; + co_graph: OneDir.t; + } + + include Datatype.Make + (struct + include Datatype.Undefined + type t = g + let name = "PdgTypes.G" + let reprs = [ let h = Node.Hashtbl.create 0 in + { d_graph = h; co_graph = h} ] + let mem_project = Datatype.never_any_project + let rehash = Datatype.identity + open Structural_descr + let structural_descr = + t_record [| OneDir.packed_descr; OneDir.packed_descr;|] + end) + + let add_node g v = + add_node_one_dir g.d_graph v; + add_node_one_dir g.co_graph v; + ;; + let add_vertex = add_node + + let add_edge g vsrc lbl vdst = + add_edge_one_dir g.d_graph vsrc vdst lbl; + add_edge_one_dir g.co_graph vdst vsrc lbl; + ;; + + let remove_edge g vsrc vdst = + remove_edge_one_dir g.d_graph vsrc vdst; + remove_edge_one_dir g.co_graph vdst vsrc; + ;; + + let find_edge g v1 v2 = + let dsts = Node.Hashtbl.find g.d_graph v1 in + To.find v2 dsts + ;; + + let iter_vertex f g = Node.Hashtbl.iter (fun v _ -> f v) g.d_graph + let iter_edges_e f g = + Node.Hashtbl.iter (fun v _to -> aux_iter_one_dir f v _to) g.d_graph + + let iter_succ_e f g = iter_e_one_dir f g.d_graph + let fold_succ f g = fold_one_dir f g.d_graph + let fold_pred f g = fold_one_dir f g.co_graph + let fold_succ_e f g = fold_e_one_dir f g.d_graph + let fold_pred_e f g = fold_e_one_dir ~rev:true f g.co_graph + let iter_pred_e f g = iter_e_one_dir ~rev:true f g.co_graph + + let succ g v = fold_succ (fun n l -> n :: l) g v [] + let pred g v = fold_pred (fun n l -> n :: l) g v [] + + let create () = + { d_graph = Node.Hashtbl.create 17; + co_graph = Node.Hashtbl.create 17; } let find_dpd g v1 v2 = - let edge = IGraph.find_edge g.graph v1 v2 in - (edge, IGraph.E.label edge) + let lbl = find_edge g v1 v2 in + ((v1, lbl, v2), lbl) let add_elem g key = - let elem = Elem.make g.counter key in - let new_vertex = V.create elem in - IGraph.add_vertex g.graph new_vertex; - new_vertex + let elem = Node.make key in + add_vertex g elem; + elem let simple_add_dpd g v1 dpd v2 = - IGraph.add_edge_e g.graph (IGraph.E.create v1 dpd v2) + add_edge g v1 dpd v2 - let replace_dpd g edge new_dpd = - let v1 = IGraph.E.src edge in - let v2 = IGraph.E.dst edge in - IGraph.remove_edge_e g.graph edge; + let replace_dpd g (v1, _, v2) new_dpd = + remove_edge g v1 v2; simple_add_dpd g v1 new_dpd v2 let add_dpd graph v1 dpd_kind opt_zone v2 = @@ -323,93 +398,11 @@ let new_dpd = DpdZone.make dpd_kind opt_zone in simple_add_dpd graph v1 new_dpd v2 - let iter_vertex x g = IGraph.iter_vertex x g.graph - let iter_edges_e x g = IGraph.iter_edges_e x g.graph - let iter_succ_e x g y = IGraph.iter_succ_e x g.graph y - let fold_succ_e x g y z = IGraph.fold_succ_e x g.graph y z - let fold_succ x g y z = IGraph.fold_succ x g.graph y z - let iter_pred_e x g y = IGraph.iter_pred_e x g.graph y - let fold_pred x g y z = IGraph.fold_pred x g.graph y z - let fold_pred_e x g y z = IGraph.fold_pred_e x g.graph y z - let pred g x = IGraph.pred g.graph x - let succ g x = IGraph.succ g.graph x - - let edge_dpd e = DpdZone.kind_and_zone (IGraph.E.label e) + let edge_dpd (_, lbl, _) = DpdZone.kind_and_zone lbl let pretty_edge_label = DpdZone.pretty end -(** Node.t is the type of the PDG vertex. - [compare] and [pretty] are needed by [Abstract_interp.Make_Lattice_Set]. *) -module Node = struct - - let elem n = G.V.label n - let elem_id n = (elem n).Elem.id - let elem_key n = Elem.key (elem n) - let stmt n = PdgIndex.Key.stmt (elem_key n) - - (** tells if the node represent the same thing that the given key. *) - let equivalent n key = (elem_key n) = key - - let print_id fmt n = Elem.print_id fmt (elem n) - - include Datatype.Make_with_collections - (struct - include G.V - let name = "PdgTypes.Node" - let structural_descr = - (* ocamlgraph abstract vertex descriptor; - see ocamlgraph/src/imperative.ml *) - Structural_descr.t_record - [| Structural_descr.p_int; - Elem.packed_descr; - Structural_descr.p_int |] - let reprs = List.map G.V.create Elem.reprs - let rehash = Datatype.identity - let copy = Datatype.undefined - let varname = Datatype.undefined - let mem_project = Datatype.never_any_project - let pretty = print_id - let internal_pretty_code = Datatype.undefined - end) - -(* - let add_simple_node g key = - let elem = Elem.make g key in - let new_vertex = G.V.create elem in - new_vertex -*) - - let pretty_list fmt l = - List.iter (fun n -> Format.fprintf fmt " %a" pretty n) l - - let pretty_with_part fmt (n, z_part) = - Format.fprintf fmt "n%a" pretty n; - match z_part with None -> () - | Some z -> Format.fprintf fmt "(restrict to @[<h 1>%a@])" - Locations.Zone.pretty z - -end - -module NodeSet = struct - include Set.Make(Node) - let add_list ?(set=empty) l = - List.fold_left (fun acc n -> add n acc) set l -end - -(** set of nodes of the graph *) -module NodeSetLattice = struct - include Abstract_interp.Make_Lattice_Set(Node) - type t_elt = O.elt - let tag = hash - let default _v _a _b : t = empty - (* raise (NoNodeForZone (Locations.Zone.default v a b)) *) - let defaultall _v : t = empty - (* raise (NoNodeForZone (Locations.Zone.defaultall v)) *) -end - -module LocInfo = Lmap_bitwise.Make_bitwise (NodeSetLattice) - (** DataState is associated with a program point and provide the dependancies for the data, ie. it stores for each location the nodes of the pdg where its value @@ -426,133 +419,39 @@ type t = t_data_state let name = "PdgTypes.Data_state" let reprs = - List.fold_left - (fun acc l -> - List.fold_left - (fun acc z -> { loc_info = l; under_outputs = z } :: acc) - acc - Locations.Zone.reprs) - [] - LocInfo.reprs + List.fold_left + (fun acc l -> + List.fold_left + (fun acc z -> { loc_info = l; under_outputs = z } :: acc) + acc + Locations.Zone.reprs) + [] + LocInfo.reprs + let rehash = Datatype.identity let structural_descr = - Structural_descr.t_record - [| LocInfo.packed_descr; Locations.Zone.packed_descr |] + Structural_descr.t_record + [| LocInfo.packed_descr; Locations.Zone.packed_descr |] let mem_project = Datatype.never_any_project end) -(** Dynamic dependencies *) -module DynDpds : sig - type t - type t_node = Node.t - type t_dpds_list = t_node list - type t_dpds_lists - - val empty : t - val add_x_dpds : t -> t_node -> - data:t_dpds_list -> addr:t_dpds_list -> ctrl:t_dpds_list -> - unit - val clear : t -> unit - - val find_dpds : t -> t_node -> t_dpds_lists - val find_co_dpds : t -> t_node -> t_dpds_lists - val get_x_dpds : t_dpds_lists -> Dpd.td option -> t_dpds_list - - val iter_dpds : (G.E.t -> unit) -> t -> unit - -end = struct - type t_node = Node.t - type t_dpds_list = t_node list - - (** [DAC] order ie. data + addr + ctrl *) - type t_dpds_lists = t_dpds_list * t_dpds_list * t_dpds_list - (** the node and its dependencies and codependencies lists *) - type t = (t_node * t_dpds_lists * t_dpds_lists) Inthash.t - - let empty = Inthash.create 100 - - let is_empty dd = (Inthash.length dd) = 0 - - let clear dd = Inthash.clear dd - - let find_lists dd node = - let _n, dpds, codpds = Inthash.find dd (Node.elem_id node) in dpds, codpds - - let find_dpds dd node = let (dpds, _) = find_lists dd node in dpds - - let find_co_dpds dd node = let (_, codpds) = find_lists dd node in codpds - - let iter_dpds f dd = - let rec iter n tdpd ldpds = match ldpds with [] -> () - | d :: ldpds -> f (G.E.create n tdpd d); iter n tdpd ldpds - in - let do_f _n_id (n, (ldata, laddr, lctrl), _codpds) = - iter n (DpdZone.make Dpd.Data None) ldata; - iter n (DpdZone.make Dpd.Addr None) laddr; - iter n (DpdZone.make Dpd.Ctrl None) lctrl - in Inthash.iter do_f dd - - let get_x_dpds (ldata, laddr, lctrl) td = - match td with - | None -> ldata @ laddr @ lctrl - | Some Dpd.Data -> ldata | Some Dpd.Addr -> laddr | Some Dpd.Ctrl -> lctrl - - (** keeps the list ordered from the smallest to the largest elem_id *) - (* TODO : add_node_to_list for several nodes at a time *) - let add_node_to_list node_list node = - let n_id = Node.elem_id node in - let rec add node_list = - match node_list with - | [] -> [node] - | n :: tail -> - if (Node.elem_id n) < n_id then n :: (add tail) - else if n_id < (Node.elem_id n) then node :: node_list - else (* already in *) node_list - in add node_list - - let add_node_to_lists td lists node = - let (ldata, laddr, lctrl) = lists in - let lists = match td with - | Dpd.Data -> add_node_to_list ldata node, laddr, lctrl - | Dpd.Addr -> ldata, add_node_to_list laddr node, lctrl - | Dpd.Ctrl -> ldata, laddr, add_node_to_list lctrl node - in lists - - (** add the nodes in [data] [addr] [ctrl] to the [node] dependancies. - * If [x] is a new dependency of [node], we also have to add [node] in [x] - * codependencies *) - let add_x_dpds dd node ~data ~addr ~ctrl = - let add_codpd t x = (* add [node] in [x] codpds *) - let x_dpds, x_codpds = - try find_lists dd x with Not_found -> ([], [], []), ([], [], []) in - let x_codpds = add_node_to_lists t x_codpds node in - Inthash.replace dd (Node.elem_id x) (x, x_dpds, x_codpds) - in - let add t old_node_dpds new_dpd = - add_codpd t new_dpd; - add_node_to_lists t old_node_dpds new_dpd - in - let node_dpds, node_codpds = - try find_lists dd node with Not_found -> ([], [], []), ([], [], []) in - let node_dpds = List.fold_left (add Dpd.Data) node_dpds data in - let node_dpds = List.fold_left (add Dpd.Addr) node_dpds addr in - let node_dpds = List.fold_left (add Dpd.Ctrl) node_dpds ctrl in - Inthash.replace dd (Node.elem_id node) (node, node_dpds, node_codpds) -end - (** PDG for a function *) module Pdg = struct exception Top exception Bottom - type t_index = (Node.t, unit) PdgIndex.FctIndex.t - (** The nodes which are associated the each element. - * There is only one node for simple statements, - * but there are several for a call for instance. *) + type t_fi = (Node.t, unit) PdgIndex.FctIndex.t + (** The nodes which are associated the each element. + There is only one node for simple statements, + but there are several for a call for instance. *) + let t_fi_descr = + PdgIndex.FctIndex.t_descr ~ni:(Descr.str Node.descr) ~ci:Structural_descr.t_unit + + type t_def = { graph : G.t ; states : t_data_state Inthash.t ; - index : t_index ; + index : t_fi ; } type t_body = PdgDef of t_def | PdgTop | PdgBottom @@ -560,27 +459,25 @@ module Body_datatype = Datatype.Make (struct - include Datatype.Undefined(*Serializable_undefined*) - type t = t_body - let reprs = [ PdgTop; PdgBottom ] -(* - (* [JS 2010/09/27] this descr is incorrect since its internal zones are - not rehashconsed (do not use Structural_descr.Abstract in all - positions containing hashconsed values) *) - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| - Structural_descr.pack - (Structural_descr.t_record [| - Structural_descr.pack Structural_descr.Abstract (* TODO *); - (let module H = Cil_datatype.Int_hashtbl.Make(Data_state) in - H.packed_descr); - Structural_descr.pack Structural_descr.Abstract (* TODO *); - |]) - |] |]) - *) - let name = "t_body" - let mem_project = Datatype.never_any_project + include Datatype.Undefined(*Serializable_undefined*) + type t = t_body + let reprs = [ PdgTop; PdgBottom ] + let rehash = Datatype.identity + open Structural_descr + let structural_descr = + Structure + (Sum [| [| + pack + (t_record [| + G.packed_descr; + (let module H = Cil_datatype.Int_hashtbl.Make(Data_state) in + H.packed_descr); + pack t_fi_descr; + |]) + |] |]) + + let name = "t_body" + let mem_project = Datatype.never_any_project end) let () = Type.set_ml_name Body_datatype.ty None @@ -613,12 +510,7 @@ let do_it acc (_k, n) = f acc n in PdgIndex.Signature.fold do_it acc call_pdg - - (* let remove_node pdg node = - G.remove_elem (get_graph pdg) node; - PdgIndex.FctIndex.remove (get_index pdg) (Node.elem_key node) *) - - type dpd_info = (Node.t * Locations.Zone.t option) + type dpd_info = (Node.t * Locations.Zone.t option) (** gives the list of nodes that depend to the given node with a given kind of dependency. @@ -665,19 +557,14 @@ in List.map get_info edges - let pretty_node fmt n = - let id = Node.elem_id n in - Format.fprintf fmt "[Elem] %d : " id; - let key = Node.elem_key n in - PdgIndex.Key.pretty fmt key - - let pretty_nodes fmt nodes = - let pretty_node n = Format.fprintf fmt "%a@." pretty_node n in - List.iter pretty_node nodes - let pretty_graph ?(bw=false) fmt graph = + let all = (* Sorted print is nicer for the user *) + let r = ref [] in + G.iter_vertex (fun n -> r := n :: !r) graph; + List.sort Node.compare !r + in let iter = if bw then G.iter_pred_e else G.iter_succ_e in - let print_node n = Format.fprintf fmt "%a@." pretty_node n in + let print_node n = Format.fprintf fmt "%a@." Node.pretty_node n in let print_dpd d = let dpd_kind = G.E.label d in if bw then Format.fprintf fmt " <-%a- %d@." G.pretty_edge_label dpd_kind @@ -689,7 +576,7 @@ print_node n; iter print_dpd graph n in - G.iter_vertex print_node_and_dpds graph + List.iter print_node_and_dpds all let pretty_bw ?(bw=false) fmt pdg = try @@ -715,14 +602,14 @@ let iter_vertex f pdg = try - let graph = get_graph pdg in + let graph = get_graph pdg in G.iter_vertex f graph with Top | Bottom -> () let iter_edges_e f pdg = try - let graph = get_graph pdg in - let f_static e = f (e, false) in + let graph = get_graph pdg in + let f_static e = f (e, false) in G.iter_edges_e f_static graph; with Top | Bottom -> () @@ -772,9 +659,6 @@ sh_box, txt | _ -> sh_box, "???" in sh, color_stmt, txt - (* | PdgIndex.Key.Annot _ -> - let txt = Pretty_utils.sfprintf "%a" PdgIndex.Key.pretty key in - (`Shape `Doublecircle), color_annot, txt *) | PdgIndex.Key.CallStmt call -> let call_stmt = PdgIndex.Key.call_from_id call in let txt = Pretty_utils.sfprintf "%a" @@ -783,8 +667,8 @@ in sh_box, color_call, txt | PdgIndex.Key.SigCallKey (_call, sgn) -> let txt = - Pretty_utils.sfprintf "%a" PdgIndex.Signature.pretty_key sgn - in + Pretty_utils.sfprintf "%a" PdgIndex.Signature.pretty_key sgn + in sh_box, color_elem_call, txt | PdgIndex.Key.Label _ -> let txt = Pretty_utils.sfprintf "%a" PdgIndex.Key.pretty key in @@ -797,28 +681,28 @@ let d, z = G.edge_dpd e in let attrib = [] in let attrib = match z with - | None -> attrib - | Some z -> + | None -> attrib + | Some z -> let txt = Pretty_utils.sfprintf "@[<h 1>%a@]" Locations.Zone.pretty z in (`Label txt) :: attrib in let attrib = - let color = + let color = if Dpd.is_data d then (if dynamic then 0xFF00FF else 0x0000FF) else (if dynamic then 0xFF0000 else 0x000000) - in (`Color color) :: attrib + in (`Color color) :: attrib in let attrib = - if Dpd.is_ctrl d then (`Arrowhead `Odot)::attrib else attrib + if Dpd.is_ctrl d then (`Arrowhead `Odot)::attrib else attrib in let attrib = - if Dpd.is_addr d then (`Style `Dotted)::attrib else attrib + if Dpd.is_addr d then (`Style `Dotted)::attrib else attrib in attrib let get_subgraph v = let mk_subgraph name attrib = - let attrib = (`Style `Filled) :: attrib in + let attrib = (`Style `Filled) :: attrib in Some { Graph.Graphviz.DotAttributes.sg_name= name; Graph.Graphviz.DotAttributes.sg_attributes = attrib } in diff -Nru frama-c-20110201+carbon+dfsg/src/pdg_types/pdgTypes.mli frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgTypes.mli --- frama-c-20110201+carbon+dfsg/src/pdg_types/pdgTypes.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/pdg_types/pdgTypes.mli 2011-10-10 08:38:28.000000000 +0000 @@ -26,8 +26,6 @@ function. @plugin development guide *) -exception Pdg_Internal_Error of string - (** [Dpd] stands for 'dependence'. This object is used as a label on the edges * of the PDG. There are three kinds of dependencies : * - control dependency, @@ -62,6 +60,7 @@ val inter : t -> t -> t val minus : t -> t -> t + val pretty_td : Format.formatter -> td -> unit val pretty : Format.formatter -> t -> unit end @@ -72,56 +71,54 @@ val elem_id : t -> int val elem_key : t -> PdgIndex.Key.t val stmt : t -> Cil_types.stmt option - val equivalent : t -> PdgIndex.Key.t -> bool + (*val equivalent : t -> PdgIndex.Key.t -> bool*) val pretty_list : Format.formatter -> t list -> unit val pretty_with_part : Format.formatter -> (t * Locations.Zone.t option) -> unit + val pretty_node: Format.formatter -> t -> unit end -module NodeSet : sig - include Set.S with type elt = Node.t - val add_list : ?set:t -> Node.t list -> t -end +module NodeSet : Hptset.S with type elt = Node.t (** Program dependence graph main part : the nodes of the graph represent * computations, and the edges represent the dependencies between these * computations. *) -module G : - sig +module G : sig +(* include Datatype.S*) + type t + module V : sig type t = Node.t end + module E : sig type t - module V : sig type t = Node.t end - module E : - sig - type t - type label - val src : t -> Node.t - val dst : t -> Node.t - val label : t -> label - end - - val create : unit -> t - - val add_elem : t -> PdgIndex.Key.t -> Node.t - val add_dpd : t -> Node.t -> - Dpd.td -> Locations.Zone.t option -> Node.t -> unit - (* val replace_dpd : t -> E.t -> Dpd.t -> unit *) - (* val find_dpd : t -> Node.t -> Node.t -> E.t * Dpd.t *) - - val succ : t -> Node.t -> Node.t list - val pred : t -> Node.t -> Node.t list - - val iter_vertex : (Node.t -> unit) -> t -> unit - val iter_edges_e : (E.t -> unit) -> t -> unit - val iter_succ_e : (E.t -> unit) -> t -> Node.t -> unit - val fold_succ_e : (E.t -> 'a -> 'a) -> t -> Node.t -> 'a -> 'a - val fold_succ : (Node.t -> 'a -> 'a) -> t -> Node.t -> 'a -> 'a - val iter_pred_e : (E.t -> unit) -> t -> Node.t -> unit - val fold_pred : (Node.t -> 'a -> 'a) -> t -> Node.t -> 'a -> 'a - - val edge_dpd : E.t -> Dpd.t * Locations.Zone.t option - val pretty_edge_label : Format.formatter -> E.label -> unit + type label + val src : t -> Node.t + val dst : t -> Node.t + val label : t -> label end + val create : unit -> t + + val add_elem : t -> PdgIndex.Key.t -> Node.t + val add_dpd : + t -> Node.t -> Dpd.td -> Locations.Zone.t option -> Node.t -> unit + + (* val replace_dpd : t -> E.t -> Dpd.t -> unit *) + (* val find_dpd : t -> Node.t -> Node.t -> E.t * Dpd.t *) + + val succ : t -> Node.t -> Node.t list + val pred : t -> Node.t -> Node.t list + + val iter_vertex : (Node.t -> unit) -> t -> unit + val iter_edges_e : (E.t -> unit) -> t -> unit + val iter_succ_e : (E.t -> unit) -> t -> Node.t -> unit + val fold_succ_e : (E.t -> 'a -> 'a) -> t -> Node.t -> 'a -> 'a + val fold_succ : (Node.t -> 'a -> 'a) -> t -> Node.t -> 'a -> 'a + val iter_pred_e : (E.t -> unit) -> t -> Node.t -> unit + val fold_pred : (Node.t -> 'a -> 'a) -> t -> Node.t -> 'a -> 'a + + val edge_dpd : E.t -> Dpd.t * Locations.Zone.t option + val pretty_edge_label : Format.formatter -> E.label -> unit +end + module NodeSetLattice : sig include Abstract_interp.Lattice_Set with type O.elt=Node.t val default : Base.t -> Abstract_interp.Int.t -> Abstract_interp.Int.t -> t @@ -163,6 +160,8 @@ val fold_call_nodes : ('a -> Node.t -> 'a) -> 'a -> t -> Cil_types.stmt -> 'a + (** a dependency to another node. The dependency can be restricted to a zone. + * (None means no restriction ie. total dependency) *) type dpd_info = (Node.t * Locations.Zone.t option) val get_all_direct_dpds : t -> Node.t -> dpd_info list @@ -171,20 +170,36 @@ val get_all_direct_codpds : t -> Node.t -> dpd_info list val get_x_direct_codpds : Dpd.td -> t -> Node.t -> dpd_info list - (* val get_all_direct_edges : t -> Node.t -> - (Dpd.t * Locations.Zone.t option * Node.t) list U*) val pretty_bw : ?bw:bool -> Format.formatter -> t -> unit val pretty_graph : ?bw:bool -> Format.formatter -> G.t -> unit - val pretty_node: Format.formatter -> Node.t -> unit - type t_index = (Node.t, unit) PdgIndex.FctIndex.t - val get_index : t -> t_index + type t_fi = (Node.t, unit) PdgIndex.FctIndex.t + + val get_index : t -> t_fi (** [make fundec graph states index] *) val make : - Kernel_function.t -> G.t -> t_data_state Inthash.t -> t_index -> t + Kernel_function.t -> G.t -> t_data_state Inthash.t -> t_fi -> t val get_states : t -> t_data_state Inthash.t val build_dot: string -> t -> unit + module Printer : sig + val iter_vertex : (G.V.t -> unit) -> t -> unit + val iter_edges_e : (G.E.t * bool -> unit) -> t -> unit + val graph_attributes : t -> Graph.Graphviz.DotAttributes.graph list + val default_vertex_attributes : t -> Graph.Graphviz.DotAttributes.vertex list + val vertex_name : G.V.t -> string + val vertex_attributes : G.V.t -> Graph.Graphviz.DotAttributes.vertex list + val get_subgraph : G.V.t -> Graph.Graphviz.DotAttributes.subgraph option + val default_edge_attributes : 'a -> Graph.Graphviz.DotAttributes.edge list + val edge_attributes : G.E.t * bool -> Graph.Graphviz.DotAttributes.edge list + end + end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/postdominators/compute.ml frama-c-20111001+nitrogen+dfsg/src/postdominators/compute.ml --- frama-c-20110201+carbon+dfsg/src/postdominators/compute.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/postdominators/compute.ml 2011-10-10 08:38:09.000000000 +0000 @@ -22,11 +22,10 @@ open Cil_types open Cil -open Db_types open Db open Cil_datatype -module Parameters = +module DomKernel = Plugin.Register (struct let name = "dominators" @@ -36,20 +35,20 @@ module DomSet = struct - type domset = Value of Stmt.Set.t | Top + type domset = Value of Stmt.Hptset.t | Top let inter a b = match a,b with | Top,Top -> Top | Value v, Top | Top, Value v -> Value v - | Value v, Value v' -> Value (Stmt.Set.inter v v') + | Value v, Value v' -> Value (Stmt.Hptset.inter v v') let add v d = match d with | Top -> Top - | Value d -> Value (Stmt.Set.add v d) + | Value d -> Value (Stmt.Hptset.add v d) let mem v = function | Top -> true - | Value d -> Stmt.Set.mem v d + | Value d -> Stmt.Hptset.mem v d let map f = function | Top -> Top @@ -57,25 +56,26 @@ include Datatype.Make (struct - include Datatype.Serializable_undefined - type t = domset - let name = "postdominator" - let reprs = Top :: List.map (fun s -> Value s) Stmt.Set.reprs - let structural_descr = - Structural_descr.Structure - (Structural_descr.Sum [| [| Stmt.Set.packed_descr |] |]) - let pretty fmt = function - | Top -> Format.fprintf fmt "Top" - | Value d -> - Pretty_utils.pp_list ~pre:"@[{" ~sep:",@," ~suf:"}@]" - (fun fmt s -> Format.fprintf fmt "%d" s.sid) - fmt (Stmt.Set.elements d) - let equal a b = match a,b with - | Top,Top -> true - | Value _v, Top | Top, Value _v -> false - | Value v, Value v' -> Stmt.Set.equal v v' - let copy = map Cil_datatype.Stmt.Set.copy - let mem_project = Datatype.never_any_project + include Datatype.Serializable_undefined + type t = domset + let name = "dominator_set" + let reprs = Top :: List.map (fun s -> Value s) Stmt.Hptset.reprs + let structural_descr = + Structural_descr.Structure + (Structural_descr.Sum [| [| Stmt.Hptset.packed_descr |] |]) + let pretty fmt = function + | Top -> Format.fprintf fmt "Top" + | Value d -> + Pretty_utils.pp_iter ~pre:"@[{" ~sep:",@," ~suf:"}@]" + Stmt.Hptset.iter + (fun fmt s -> Format.fprintf fmt "%d" s.sid) + fmt d + let equal a b = match a,b with + | Top,Top -> true + | Value _v, Top | Top, Value _v -> false + | Value v, Value v' -> Stmt.Hptset.equal v v' + let copy = map Cil_datatype.Stmt.Hptset.copy + let mem_project = Datatype.never_any_project end) end @@ -124,21 +124,23 @@ let start = Kernel_function.find_first_stmt kf in try let _ = Dom.find start.sid in - Parameters.feedback "computed for function %a" - Kernel_function.pretty_name kf; + DomKernel.feedback ~level:2 "computed for function %a" + Kernel_function.pretty kf; with Not_found -> - Parameters.feedback "computing for function %a" - Kernel_function.pretty_name kf; + DomKernel.feedback ~level:2 "computing for function %a" + Kernel_function.pretty kf; let f = kf.fundec in let stmts = match f with | Definition (f,_) -> f.sallstmts - | Declaration _ -> Parameters.fatal "cannot compute for a leaf function" + | Declaration _ -> + DomKernel.fatal "cannot compute for a leaf function %a" + Kernel_function.pretty kf in List.iter (fun s -> Dom.add s.sid DomSet.Top) stmts; - Dom.replace start.sid (DomSet.Value (Stmt.Set.singleton start)); + Dom.replace start.sid (DomSet.Value (Stmt.Hptset.singleton start)); DomCompute.compute [start]; - Parameters.feedback "done for function %a" - Kernel_function.pretty_name kf + DomKernel.feedback ~level:2 "done for function %a" + Kernel_function.pretty kf let get_stmt_dominators f stmt = let do_it () = Dom.find stmt.sid in @@ -156,115 +158,206 @@ let display_dom () = Dom.iter - (fun k v -> Parameters.result "Stmt:%d@\n%a@\n======" k DomSet.pretty v) + (fun k v -> DomKernel.result "Stmt:%d@\n%a@\n======" k DomSet.pretty v) (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) -module PostDom = - Cil_state_builder.Inthash - (DomSet) - (struct - let name = "postdominator" - let dependencies = [ Ast.self ] - let size = 503 - let kind = `Internal - end) +module type MakePostDomArg = sig + val is_accessible: stmt -> bool + (* Evaluation of an expression which is supposed to be the condition of an + 'if'. The first boolean (resp. second) represents the possibility that + the expression can be non-zero (resp. zero), ie. true (resp. false). *) + val eval_cond: stmt -> exp -> bool * bool -module PostComputer = struct + val dependencies: State.t list + val name: string +end - let name = "postdominator" - let debug = ref false +module MakePostDom(X: MakePostDomArg) = +struct - type t = DomSet.t - module StmtStartData = PostDom + module PostDom = + Cil_state_builder.Stmt_hashtbl + (DomSet) + (struct + let name = "postdominator." ^ X.name + let dependencies = Ast.self :: X.dependencies + let size = 503 + let kind = `Internal + end) - let pretty = DomSet.pretty + module PostComputer = struct - let combineStmtStartData _stmt ~old new_ = - let result = (* inter old *) new_ in - if DomSet.equal result old then None else Some result + let name = "postdominator" + let debug = ref false - let combineSuccessors = DomSet.inter + type t = DomSet.t + module StmtStartData = PostDom - let doStmt stmt = - !Db.progress (); - Parameters.debug "doStmt : %d" stmt.sid; - match stmt.skind with - | Return _ -> Dataflow.Done (DomSet.Value (Stmt.Set.singleton stmt)) - | _ -> Dataflow.Post (fun data -> DomSet.add stmt data) + let pretty = DomSet.pretty - let doInstr _ _ _ = Dataflow.Default + let combineStmtStartData _stmt ~old new_ = + (* No need to compute the intersection: the results can only decrease + (except on Top, but Top \inter Set = Set *) + let result = (* DomSet.inter old *) new_ in + if DomSet.equal result old then None else Some result - let filterStmt _stmt _next = true + let combineSuccessors = DomSet.inter - let funcExitData = DomSet.Value Stmt.Set.empty + let doStmt stmt = + !Db.progress (); + Postdominators_parameters.debug ~level:2 "doStmt: %d" stmt.sid; + match stmt.skind with + | Return _ -> Dataflow.Done (DomSet.Value (Stmt.Hptset.singleton stmt)) + | _ -> Dataflow.Post (fun data -> DomSet.add stmt data) -end -module PostCompute = Dataflow.BackwardsDataFlow(PostComputer) -let compute_postdom kf = - let return = Kernel_function.find_return kf in - try - let _ = PostDom.find return.sid in - Parameters.result "(post) computed for function %a" - Kernel_function.pretty_name kf - with Not_found -> - Parameters.feedback "computing (post) for function %a" - Kernel_function.pretty_name kf; - let f = kf.fundec in - let stmts = match f with - | Definition (f,_) -> f.sallstmts - | Declaration _ -> - Parameters.fatal "cannot compute postdominators for a leaf function" + let doInstr _ _ _ = Dataflow.Default + + (* We make special tests for 'if' statements without a 'then' or + 'else' branch. It can lead to better precision if we can evaluate + the condition of the 'if' with always the same truth value *) + let filterIf ifstmt next = match ifstmt.skind with + | If (e, { bstmts = sthen :: _ }, { bstmts = [] }, _) + when not (Stmt.equal sthen next) -> + (* [next] is the syntactic successor of the 'if', ie the + 'else' branch. If the condition is never false, then + [sthen] postdominates [next]. We must not follow the edge + from [ifstmt] to [next] *) + snd (X.eval_cond ifstmt e) + + | If (e, { bstmts = [] }, { bstmts = selse :: _ }, _) + when not (Stmt.equal selse next) -> + (* dual case *) + fst (X.eval_cond ifstmt e) + + | _ -> true + + let filterStmt pred next = + X.is_accessible pred && filterIf pred next + + + let funcExitData = DomSet.Value Stmt.Hptset.empty + + end + module PostCompute = Dataflow.Backwards(PostComputer) + + let compute_postdom kf = + let return = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> + Postdominators_parameters.abort + "No return statement for a function with body %a" + Kernel_function.pretty kf in - List.iter (fun s -> PostDom.add s.sid DomSet.Top) stmts; - PostCompute.compute [return]; - Parameters.feedback "done for function %a" - Kernel_function.pretty_name kf + try + let _ = PostDom.find return in + Postdominators_parameters.feedback ~level:2 "computed for function %a" + Kernel_function.pretty kf + with Not_found -> + Postdominators_parameters.feedback ~level:2 "computing for function %a" + Kernel_function.pretty kf; + let f = kf.fundec in + let stmts = match f with + | Definition (f,_) -> f.sallstmts + | Declaration _ -> + Postdominators_parameters.fatal + "cannot compute postdominators for leaf function %a" + Kernel_function.pretty kf + in + List.iter (fun s -> PostDom.add s DomSet.Top) stmts; + PostCompute.compute [return]; + Postdominators_parameters.feedback ~level:2 "done for function %a" + Kernel_function.pretty kf + + let get_stmt_postdominators f stmt = + let do_it () = PostDom.find stmt in + try do_it () + with Not_found -> compute_postdom f; do_it () + + (** @raise Db.PostdominatorsTypes.Top when the statement postdominators + * have not been computed ie neither the return statement is reachable, + * nor the statement is in a natural loop. *) + let stmt_postdominators f stmt = + match get_stmt_postdominators f stmt with + | DomSet.Value s -> + Postdominators_parameters.debug ~level:1 "Postdom for %d are %a" + stmt.sid Stmt.Hptset.pretty s; + s + | DomSet.Top -> raise Db.PostdominatorsTypes.Top + + let is_postdominator f ~opening ~closing = + let open_postdominators = get_stmt_postdominators f opening in + DomSet.mem closing open_postdominators + + let display_postdom () = + let disp_all fmt = + PostDom.iter + (fun k v -> Format.fprintf fmt "Stmt:%d -> @[%a@]\n" + k.sid PostComputer.pretty v) + in Postdominators_parameters.result "%t" disp_all + + let print_dot_postdom basename kf = + let filename = basename ^ "." ^ Kernel_function.get_name kf ^ ".dot" in + Print.build_dot filename kf; + Postdominators_parameters.result "dot file generated in %s" filename -let get_stmt_postdominators f stmt = - let do_it () = PostDom.find stmt.sid in - try do_it () - with Not_found -> compute_postdom f; do_it () +end + +module PostDomDb(X: MakePostDomArg)(DbPostDom: Db.PostdominatorsTypes.Sig) = +struct + include MakePostDom(X) + + let () = DbPostDom.compute := compute_postdom + let () = DbPostDom.is_postdominator := is_postdominator + let () = DbPostDom.stmt_postdominators := stmt_postdominators + let () = DbPostDom.display := display_postdom + let () = DbPostDom.print_dot := print_dot_postdom + +end + +module PostDomBasic = + PostDomDb( + struct + let is_accessible _ = true + let dependencies = [] + let name = "basic" + let eval_cond _ _ = true, true + end) + (Db.Postdominators) -(** @raise Db.Top_postdominators when the statement postdominators -* have not been computed ie neither the return statement is reachable, -* nor the statement is in a natural loop. *) -let stmt_postdominators f stmt = - match get_stmt_postdominators f stmt with - | DomSet.Value s -> s - | DomSet.Top -> raise Db.Postdominators.Top -let is_postdominator f ~opening ~closing = - let open_postdominators = get_stmt_postdominators f opening in - DomSet.mem closing open_postdominators - -let display_postdom () = - let disp_all fmt = - PostDom.iter - (fun k v -> Format.fprintf fmt "Stmt:%d\n%a\n======" k PostComputer.pretty v) - in Parameters.result "%t" disp_all - -let print_dot_postdom basename kf = - let filename = basename ^ "." ^ Kernel_function.get_name kf ^ ".dot" in - Print.build_dot filename kf; - Parameters.result "(post) dot file generated in %s" filename +let output () = + let dot_postdom = Postdominators_parameters.DotPostdomBasename.get () in + if dot_postdom <> "" then ( + Ast.compute (); + Globals.Functions.iter (!Db.Postdominators.print_dot dot_postdom) + ) + +let output, _ = State_builder.apply_once "Postdominators.Compute.output" + [PostDomBasic.PostDom.self] output + +let () = Db.Main.extend output + + +module PostDomVal = + PostDomDb( + struct + let is_accessible = Db.Value.is_reachable_stmt + let dependencies = [ Db.Value.self ] + let name = "value" + let eval_cond stmt _e = + Db.Value.condition_truth_value stmt -let main _fmt = () + end) + (Db.PostdominatorsValue) -let () = Db.Main.extend main let () = Db.Dominators.compute := compute_dom let () = Db.Dominators.is_dominator := is_dominator let () = Db.Dominators.stmt_dominators := stmt_dominators let () = Db.Dominators.display := display_dom -let () = Db.Postdominators.compute := compute_postdom -let () = Db.Postdominators.is_postdominator := is_postdominator -let () = Db.Postdominators.stmt_postdominators := stmt_postdominators -let () = Db.Postdominators.display := display_postdom -let () = Db.Postdominators.print_dot := print_dot_postdom - (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/postdominators/postdominators_parameters.ml frama-c-20111001+nitrogen+dfsg/src/postdominators/postdominators_parameters.ml --- frama-c-20110201+carbon+dfsg/src/postdominators/postdominators_parameters.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/postdominators/postdominators_parameters.ml 2011-10-10 08:38:09.000000000 +0000 @@ -27,6 +27,14 @@ let help = "computing postdominators of statements" end) +module DotPostdomBasename = + EmptyString + (struct + let option_name = "-dot-postdom" + let arg_name = "f" + let help = "put the postdominators of function <f> in basename.f.dot" + end) + (* Local Variables: compile-command: "LC_ALL=C make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/postdominators/postdominators_parameters.mli frama-c-20111001+nitrogen+dfsg/src/postdominators/postdominators_parameters.mli --- frama-c-20110201+carbon+dfsg/src/postdominators/postdominators_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/postdominators/postdominators_parameters.mli 2011-10-10 08:38:09.000000000 +0000 @@ -22,6 +22,9 @@ include Plugin.General_services +module DotPostdomBasename: Plugin.String + + (* Local Variables: compile-command: "LC_ALL=C make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/postdominators/print.ml frama-c-20111001+nitrogen+dfsg/src/postdominators/print.ml --- frama-c-20110201+carbon+dfsg/src/postdominators/print.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/postdominators/print.ml 2011-10-10 08:38:09.000000000 +0000 @@ -28,7 +28,7 @@ module Printer = struct - type t = string * (Stmt.Set.t option Kinstr.Hashtbl.t) + type t = string * (Stmt.Hptset.t option Kinstr.Hashtbl.t) module V = struct type t = Cil_types.stmt * bool let pretty fmt v = pretty_stmt fmt v @@ -54,7 +54,7 @@ match postdom with None -> () | Some postdom -> let do_edge p = f ((s, true), (p, true)) in - Stmt.Set.iter do_edge postdom + Stmt.Hptset.iter do_edge postdom in Kinstr.Hashtbl.iter do_s graph @@ -85,18 +85,18 @@ let get_postdom kf graph s = try match Kinstr.Hashtbl.find graph (Kstmt s) with - | None -> Stmt.Set.empty + | None -> Stmt.Hptset.empty | Some l -> l with Not_found -> try let postdom = !Db.Postdominators.stmt_postdominators kf s in - let postdom = Stmt.Set.remove s postdom in + let postdom = Stmt.Hptset.remove s postdom in Postdominators_parameters.debug "postdom for %d:%a = %a\n" - s.sid pretty_stmt s Stmt.Set.pretty postdom; + s.sid pretty_stmt s Stmt.Hptset.pretty postdom; Kinstr.Hashtbl.add graph (Kstmt s) (Some postdom); postdom - with Db.Postdominators.Top -> + with Db.PostdominatorsTypes.Top -> Kinstr.Hashtbl.add graph (Kstmt s) None; - raise Db.Postdominators.Top + raise Db.PostdominatorsTypes.Top (** [s_postdom] are [s] postdominators, including [s]. * We don't have to represent the relation between s and s. @@ -105,33 +105,34 @@ *) let reduce kf graph s = let remove p s_postdom = - if Stmt.Set.mem p s_postdom + if Stmt.Hptset.mem p s_postdom then try let p_postdom = get_postdom kf graph p in - let s_postdom = Stmt.Set.diff s_postdom p_postdom + let s_postdom = Stmt.Hptset.diff s_postdom p_postdom in s_postdom - with Db.Postdominators.Top -> assert false + with Db.PostdominatorsTypes.Top -> assert false (* p postdom s -> cannot be top *) else s_postdom (* p has already been removed from s_postdom *) in try let postdom = get_postdom kf graph s in - let postdom = Stmt.Set.fold remove postdom postdom in + let postdom = Stmt.Hptset.fold remove postdom postdom in Postdominators_parameters.debug "new postdom for %d:%a = %a\n" - s.sid pretty_stmt s Stmt.Set.pretty postdom; + s.sid pretty_stmt s Stmt.Hptset.pretty postdom; Kinstr.Hashtbl.replace graph (Kstmt s) (Some postdom) - with Db.Postdominators.Top -> + with Db.PostdominatorsTypes.Top -> () let rec build_reduced_graph kf graph stmts = List.iter (reduce kf graph) stmts let build_dot filename kf = - let stmts = match kf.Db_types.fundec with - | Db_types.Definition (fct, _) -> fct.sallstmts - | Db_types.Declaration _ -> - Kernel.abort "cannot compute for a function without body" + let stmts = match kf.fundec with + | Definition (fct, _) -> fct.sallstmts + | Declaration _ -> + Kernel.abort "cannot compute for a function without body %a" + Kernel_function.pretty kf in let graph = Kinstr.Hashtbl.create (List.length stmts) in let _ = build_reduced_graph kf graph stmts in diff -Nru frama-c-20110201+carbon+dfsg/src/project/dashtbl.ml frama-c-20111001+nitrogen+dfsg/src/project/dashtbl.ml --- frama-c-20110201+carbon+dfsg/src/project/dashtbl.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/dashtbl.ml 2011-10-10 08:38:25.000000000 +0000 @@ -121,22 +121,22 @@ type t = (D.t * State.t) list State_tbl.t - let create = State_tbl.create + let create x = State_tbl.create x let clear = State_tbl.clear let add tbl s v = try - let l = State_tbl.find tbl s in - State_tbl.replace tbl s (v :: l) + let l = State_tbl.find tbl s in + State_tbl.replace tbl s (v :: l) with Not_found -> - State_tbl.add tbl s [ v ] + State_tbl.add tbl s [ v ] let replace ~on_clear tbl s v = begin try - let old = State_tbl.find tbl s in - List.iter (fun (_, s') -> on_clear s') old + let old = State_tbl.find tbl s in + List.iter (fun (_, s') -> on_clear s') old with Not_found -> - () + () end; State_tbl.replace tbl s [ v ] @@ -144,15 +144,15 @@ let remove_single tbl key s = try - match State_tbl.find tbl key with - | [] -> - assert false - | _ :: _ as l -> - match List.filter (fun (_, s') -> not (State.equal s s')) l with - | [] -> State_tbl.remove tbl key; - | _ :: _ as l -> State_tbl.replace tbl key l + match State_tbl.find tbl key with + | [] -> + assert false + | _ :: _ as l -> + match List.filter (fun (_, s') -> not (State.equal s s')) l with + | [] -> State_tbl.remove tbl key; + | _ :: _ as l -> State_tbl.replace tbl key l with Not_found -> - () + () let find tbl s = match State_tbl.find tbl s with @@ -165,23 +165,23 @@ let fold f tbl acc = State_tbl.fold - (fun s l acc -> List.fold_left (fun acc v -> f s v acc) acc l) - tbl - acc + (fun s l acc -> List.fold_left (fun acc v -> f s v acc) acc l) + tbl + acc let is_empty tbl = try - State_tbl.iter (fun _ _ -> raise Exit) tbl; - true; + State_tbl.iter (fun _ _ -> raise Exit) tbl; + true; with Exit -> - false + false let is_singleton tbl = try - State_tbl.fold - (fun _ _ second -> if second then raise Exit else true) tbl false; + State_tbl.fold + (fun _ _ second -> if second then raise Exit else true) tbl false; with Exit -> - false + false end @@ -189,16 +189,16 @@ type data = D.t type tbl = { h: Internal_tbl.t K.Hashtbl.t; - inverse: (key * State.t) list State_tbl.t } + inverse: (key * State.t) list State_tbl.t } include Datatype.Make - (struct - include Datatype.Undefined - type t = tbl - let name = Info.name - let reprs = - [ { h = K.Hashtbl.create 0; inverse = State_tbl.create 0 } ] - end) + (struct + include Datatype.Undefined + type t = tbl + let name = Info.name + let reprs = + [ { h = K.Hashtbl.create 0; inverse = State_tbl.create 0 } ] + end) (* Global invariant: only one binding by key. So never required to call [K.Hashtbl.find_all] *) @@ -223,9 +223,9 @@ let () = Project.register_todo_before_clear (fun _ -> todo_list := []) let () = Project.register_todo_after_clear - (fun p -> - let del () = List.iter (fun f -> f ()) !todo_list in - Project.on p del ()) + (fun p -> + let del () = List.iter (fun f -> f ()) !todo_list in + Project.on p del ()) let add f = todo_list := f :: !todo_list @@ -239,12 +239,12 @@ let keys = State_tbl.find inverse s in State_tbl.remove inverse s; let clear key s' = - try - let internal = K.Hashtbl.find h key in - Internal_tbl.remove_single internal s' s; - if Internal_tbl.is_empty internal then K.Hashtbl.remove h key - with Not_found -> - assert false + try + let internal = K.Hashtbl.find h key in + Internal_tbl.remove_single internal s' s; + if Internal_tbl.is_empty internal then K.Hashtbl.remove h key + with Not_found -> + assert false in List.iter (fun (key, s') -> clear key s') keys with Not_found -> @@ -263,11 +263,11 @@ let h = t.h in let tbl = K.Hashtbl.find h key in (try - let bindings = Internal_tbl.find_all tbl s in - let del = single_remove ~reset t in - List.iter (fun (_, c) -> del c) bindings + let bindings = Internal_tbl.find_all tbl s in + let del = single_remove ~reset t in + List.iter (fun (_, c) -> del c) bindings with Not_found -> - ()); + ()); if Internal_tbl.is_singleton tbl then K.Hashtbl.remove h key else Internal_tbl.remove tbl s with Not_found -> @@ -286,7 +286,7 @@ let clear ~reset t = if reset then Project.clear - ~selection:(State_selection.Dynamic.with_dependencies !G.self) (); + ~selection:(State_selection.Dynamic.with_dependencies !G.self) (); K.Hashtbl.clear t.h; State_tbl.clear t.inverse @@ -306,7 +306,7 @@ (State.get_unique_name local) (State.get_name !G.self) (fun fmt -> - List.iter (fun s -> Format.fprintf fmt "%S, " (State.get_name s)) deps);*) + List.iter (fun s -> Format.fprintf fmt "%S, " (State.get_name s)) deps);*) let value = v, local in let full_deps = match deps with [] -> [ State.dummy ] | _ :: _ -> deps in let inverse_binders = @@ -336,9 +336,9 @@ try let l = Internal_tbl.find_all (K.Hashtbl.find t.h key) s in List.iter - (fun (_, local) -> - State_dependency_graph.Dynamic.add_codependencies ~onto:local who) - l; + (fun (_, local) -> + State_dependency_graph.Dynamic.add_codependencies ~onto:local who) + l; l with Not_found -> [] @@ -359,44 +359,44 @@ (* do not get the same value twice *) let module S = Set.Make - (struct - type t = D.t * State.t - let equal = (==) - (* cannot compare the first component but the second one is a - valid key *) - let compare (_, x) (_, y) = State.compare x y - end) + (struct + type t = D.t * State.t + let equal = (==) + (* cannot compare the first component but the second one is a + valid key *) + let compare (_, x) (_, y) = State.compare x y + end) in fun ?(who=[]) t key -> let values = tbl_fold (fun _ -> S.add) t key S.empty in S.fold - (fun (_, local as res) acc -> - State_dependency_graph.Dynamic.add_codependencies ~onto:local who; - res :: acc) - values - [] + (fun (_, local as res) acc -> + State_dependency_graph.Dynamic.add_codependencies ~onto:local who; + res :: acc) + values + [] (* optimized *) let find_all_data = (* do not get the same value twice *) let module S = Set.Make - (struct - type t = D.t * State.t - let equal = (==) - (* cannot compare the first component but the second one is a - valid key *) - let compare (_, x) (_, y) = State.compare x y - end) + (struct + type t = D.t * State.t + let equal = (==) + (* cannot compare the first component but the second one is a + valid key *) + let compare (_, x) (_, y) = State.compare x y + end) in fun ?(who=[]) t key -> let values = tbl_fold (fun _ -> S.add) t key S.empty in S.fold - (fun (v, local) acc -> - State_dependency_graph.Dynamic.add_codependencies ~onto:local who; - v :: acc) - values - [] + (fun (v, local) acc -> + State_dependency_graph.Dynamic.add_codependencies ~onto:local who; + v :: acc) + values + [] (* optimized *) let find_all_states = @@ -405,11 +405,11 @@ fun ?(who=[]) t key -> let selfs = tbl_fold (fun _ (_, s) -> S.add s) t key S.empty in S.fold - (fun local acc -> - State_dependency_graph.Dynamic.add_codependencies ~onto:local who; - local :: acc) - selfs - [] + (fun local acc -> + State_dependency_graph.Dynamic.add_codependencies ~onto:local who; + local :: acc) + selfs + [] let mem t key = K.Hashtbl.mem t.h key let is_local t s = State_tbl.mem t.inverse s @@ -425,27 +425,27 @@ let iter f t = K.Hashtbl.iter (fun k -> - Internal_tbl.iter - (fun s v -> - let s = if State.is_dummy s then None else Some s in - f k s v)) + Internal_tbl.iter + (fun s v -> + let s = if State.is_dummy s then None else Some s in + f k s v)) t.h let fold f t acc = K.Hashtbl.fold (fun k -> - Internal_tbl.fold - (fun s v -> - let s = if State.is_dummy s then None else Some s in - f k s v)) + Internal_tbl.fold + (fun s v -> + let s = if State.is_dummy s then None else Some s in + f k s v)) t.h acc let memo ~reset f t name key deps = let olds = List.fold_left - (fun acc s -> try find_data t key s :: acc with Not_found -> acc) - [] - deps + (fun acc s -> try find_data t key s :: acc with Not_found -> acc) + [] + deps in let data = f olds in replace ~reset t name key deps data; @@ -455,50 +455,50 @@ let module S = Set.Make(State) in fun ~reset f t key -> try - let h = t.h in - let tbl = K.Hashtbl.find h key in - let keep, to_be_delete = - Internal_tbl.fold - (fun s (v, state as x) (keep, delete) -> - let s = if State.is_dummy s then None else Some s in - if f key s v then (s, x) :: keep, delete - else begin -(* Format.printf "FILTERING %S (key is %S)@." - (State.get_name state) - (State.get_name s);*) - keep, S.add state delete - end) - tbl - ([], S.empty) - in - S.iter (single_remove ~reset t) to_be_delete; - match keep with - | [] -> K.Hashtbl.remove h key - | _ :: _ -> - Internal_tbl.clear tbl; - List.iter - (fun (s, v) -> - let s = match s with None -> State.dummy | Some s -> s in - Internal_tbl.add tbl s v) - keep; + let h = t.h in + let tbl = K.Hashtbl.find h key in + let keep, to_be_delete = + Internal_tbl.fold + (fun s (v, state as x) (keep, delete) -> + let s = if State.is_dummy s then None else Some s in + if f key s v then (s, x) :: keep, delete + else begin +(* Format.printf "FILTERING %S (key is %S)@." + (State.get_name state) + (State.get_name s);*) + keep, S.add state delete + end) + tbl + ([], S.empty) + in + S.iter (single_remove ~reset t) to_be_delete; + match keep with + | [] -> K.Hashtbl.remove h key + | _ :: _ -> + Internal_tbl.clear tbl; + List.iter + (fun (s, v) -> + let s = match s with None -> State.dummy | Some s -> s in + Internal_tbl.add tbl s v) + keep; with Not_found -> - () + () module H = Hashtbl.Make (struct - type t = K.marshaled - let equal = K.equal_marshaled - let hash = K.hash_marshaled + type t = K.marshaled + let equal = K.equal_marshaled + let hash = K.hash_marshaled end) type marshaled_value = { data: D.marshaled; - key_name: string; - key_cluster: string option; - data_uname: string; - data_name: string; - data_cluster: string option } + key_name: string; + key_cluster: string option; + data_uname: string; + data_name: string; + data_cluster: string option } type marshaled = (string, marshaled_value) Hashtbl.t H.t @@ -510,20 +510,20 @@ let h : marshaled = H.create 97 in K.Hashtbl.iter (fun key tbl -> - let tbl' = Hashtbl.create 7 in - Internal_tbl.iter - (fun s (d, s') -> - Hashtbl.add - tbl' - (State.get_unique_name s) - { data = data_marshal d; - key_name = State.get_name s; - key_cluster = State.Cluster.name s; - data_uname = State.get_unique_name s'; - data_name = State.get_name s'; - data_cluster = State.Cluster.name s' }) - tbl; - H.add h (key_marshal key) tbl') + let tbl' = Hashtbl.create 7 in + Internal_tbl.iter + (fun s (d, s') -> + Hashtbl.add + tbl' + (State.get_unique_name s) + { data = data_marshal d; + key_name = State.get_name s; + key_cluster = State.Cluster.name s; + data_uname = State.get_unique_name s'; + data_name = State.get_name s'; + data_cluster = State.Cluster.name s' }) + tbl; + H.add h (key_marshal key) tbl') dash.h; h @@ -533,51 +533,51 @@ let inverse = dash.inverse in H.iter (fun key tbl -> - let tbl' = Internal_tbl.create 7 in - let k = key_unmarshal key in - let update s k = - (* Format.printf "updating %S@." (State.get_unique_name s);*) - State.update_unusable s k (clear_state_on dash s); - G.add_state s; - in - Hashtbl.iter - (fun - unique_name - { data = d; - key_name = name; - key_cluster = c; - data_uname = unique_name'; - data_name = name'; - data_cluster = c' } - -> - let s = - if unique_name = State.dummy_unique_name then State.dummy - else - try State.get unique_name - with State.Unknown -> State.unusable ~name unique_name - in - State.Cluster.unmarshal c s; - let s' = - assert (unique_name' <> State.dummy_unique_name); - try - let s' = State.get unique_name' in - if not (State.is_usable s') then update s' G.internal_kind; - s' - with State.Unknown -> - let s' = State.unusable ~name:name' unique_name' in - update s' G.internal_kind; - s' - in - State.Cluster.unmarshal c' s'; - let d = data_unmarshal d in - Internal_tbl.add tbl' s (d, s'); - try - let l = State_tbl.find inverse s' in - State_tbl.replace inverse s' ((k, s) :: l) - with Not_found -> - State_tbl.add inverse s' [ k, s ]) - tbl; - K.Hashtbl.add dash_h k tbl') + let tbl' = Internal_tbl.create 7 in + let k = key_unmarshal key in + let update s k = + (* Format.printf "updating %S@." (State.get_unique_name s);*) + State.update_unusable s k (clear_state_on dash s); + G.add_state s; + in + Hashtbl.iter + (fun + unique_name + { data = d; + key_name = name; + key_cluster = c; + data_uname = unique_name'; + data_name = name'; + data_cluster = c' } + -> + let s = + if unique_name = State.dummy_unique_name then State.dummy + else + try State.get unique_name + with State.Unknown -> State.unusable ~name unique_name + in + State.Cluster.unmarshal c s; + let s' = + assert (unique_name' <> State.dummy_unique_name); + try + let s' = State.get unique_name' in + if not (State.is_usable s') then update s' G.internal_kind; + s' + with State.Unknown -> + let s' = State.unusable ~name:name' unique_name' in + update s' G.internal_kind; + s' + in + State.Cluster.unmarshal c' s'; + let d = data_unmarshal d in + Internal_tbl.add tbl' s (d, s'); + try + let l = State_tbl.find inverse s' in + State_tbl.replace inverse s' ((k, s) :: l) + with Not_found -> + State_tbl.add inverse s' [ k, s ]) + tbl; + K.Hashtbl.add dash_h k tbl') h; dash diff -Nru frama-c-20110201+carbon+dfsg/src/project/dashtbl.mli frama-c-20111001+nitrogen+dfsg/src/project/dashtbl.mli --- frama-c-20110201+carbon+dfsg/src/project/dashtbl.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/dashtbl.mli 2011-10-10 08:38:25.000000000 +0000 @@ -34,11 +34,11 @@ type key (** Type of keys of the table. - @since Boron-20100401 *) + @since Boron-20100401 *) type data (** Type of values of the table. - @since Boron-20100401 *) + @since Boron-20100401 *) (** {3 Modifying a table} *) @@ -48,34 +48,34 @@ val add: t -> string -> key -> State.t list -> data -> unit (** Add a new binding [key, data] in the table. - The dependencies are the states required for computing the binding. - More precisely, a binding is a triple [key --> state --> data] and [add - k l d] adds as many bindings as the length of the list, but all these - bindings correspond to the very same state. - - Be aware that [add k [ s1; s2 ] v] is NOT equivalent to [add k [ s1 - ] v; add k [ s2 ] v]. - - In the former, it looks like having only one binding [k, v] in the - table which requires both [s1] and [s2] to be computed. If you clear - the dependencies of [s1], this binding is removed from the table. - - In the latter, it looks like having have two disting bindings [k, v] - in the table. The first one is computed by using [s1] while the second - one (containing the same value) is computed by using [s2]. If you clear - the dependencies of [s1], only the first binding is removed from the - table, but the second one is still present. + The dependencies are the states required for computing the binding. + More precisely, a binding is a triple [key --> state --> data] and [add + k l d] adds as many bindings as the length of the list, but all these + bindings correspond to the very same state. + + Be aware that [add k [ s1; s2 ] v] is NOT equivalent to [add k [ s1 + ] v; add k [ s2 ] v]. + - In the former, it looks like having only one binding [k, v] in the + table which requires both [s1] and [s2] to be computed. If you clear + the dependencies of [s1], this binding is removed from the table. + - In the latter, it looks like having have two disting bindings [k, v] + in the table. The first one is computed by using [s1] while the second + one (containing the same value) is computed by using [s2]. If you clear + the dependencies of [s1], only the first binding is removed from the + table, but the second one is still present. - @modify Carbon-20101201 adding the string argument - @since Boron-20100401 *) + @modify Carbon-20101201 adding the string argument + @since Boron-20100401 *) val replace: reset:bool -> t -> string -> key -> State.t list -> data -> unit (** Similar to [add] but replace the existing bindings if any (same - difference that [Hashtbl.replace] wrt [Hashtbl.add]. - If [reset] to [true], all the dependencies of old bindings are cleared. - It is always safe to put [reset] to [true], but it may be unsafe to - put it to [false]. - [reset] era - @modify Carbon-20101201 adding the string argument - @since Boron-20100401 *) + difference that [Hashtbl.replace] wrt [Hashtbl.add]. + If [reset] to [true], all the dependencies of old bindings are cleared. + It is always safe to put [reset] to [true], but it may be unsafe to + put it to [false]. + [reset] era + @modify Carbon-20101201 adding the string argument + @since Boron-20100401 *) val memo: reset:bool -> (data list -> data) -> t -> string -> key -> State.t list -> @@ -99,38 +99,38 @@ val remove: reset:bool -> t -> key -> State.t -> unit (** Remove all the bindings associated to the given key and state. Do - nothing if there is no such binding. - If [reset] is [true], clear all athe dependencies of the removed - binding. - It is always safe to put [reset] to [true], but it may be unsafe to - put it to [false]. - @since Boron-20100401 *) + nothing if there is no such binding. + If [reset] is [true], clear all athe dependencies of the removed + binding. + It is always safe to put [reset] to [true], but it may be unsafe to + put it to [false]. + @since Boron-20100401 *) val remove_all: reset:bool -> t -> key -> unit (** Remove all the bindings added and associated to the given key. - Do nothing if there is no such binding. - If [reset] is [true], clear all the dependencies of each removed - binding. - It is always safe to put [reset] to [true], but it may be unsafe to - put it to [false]. - @since Boron-20100401 *) + Do nothing if there is no such binding. + If [reset] is [true], clear all the dependencies of each removed + binding. + It is always safe to put [reset] to [true], but it may be unsafe to + put it to [false]. + @since Boron-20100401 *) val filter: reset:bool -> (key -> State.t option -> data -> bool) -> t -> key -> unit (** Remove all the bindings added and associated to the given key and - which does not satisfy the given condition. - Do nothing if there is no such binding. - If [reset] is [true], clear all the dependencies of each removed - binding. - It is always safe to put [reset] to [true], but it may be unsafe to - put it to [false]. - @since Boron-20100401 *) + which does not satisfy the given condition. + Do nothing if there is no such binding. + If [reset] is [true], clear all the dependencies of each removed + binding. + It is always safe to put [reset] to [true], but it may be unsafe to + put it to [false]. + @since Boron-20100401 *) (** {3 Finders} *) val mem: t -> key -> bool (** @return [true] if there is a binding with the given key. - @since Boron-20100401 *) + @since Boron-20100401 *) val is_local: t -> State.t -> bool (** @return [true] if the state corresponds to a binding of the dashtbl. @@ -138,10 +138,10 @@ val find: ?who:State.t list -> t -> key -> State.t -> data * State.t (** Get the binding associated to the given key and state. - if [who] is set, automatically adds dependency from the found state - to each of states of [who]. - @raise Not_found if there is no such binding - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from the found state + to each of states of [who]. + @raise Not_found if there is no such binding + @since Boron-20100401 *) val find_key: t -> State.t -> (key * State.t) list (** Return the keys with their corresponding states which map to the given @@ -150,73 +150,73 @@ val find_data: ?who:State.t list -> t -> key -> State.t -> data (** Get the data associated to the given key and state. - if [who] is set, automatically adds dependency from the state - corresponding to the given data to each of states of [who]. - @raise Not_found if there is no such binding - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from the state + corresponding to the given data to each of states of [who]. + @raise Not_found if there is no such binding + @since Boron-20100401 *) val find_state: ?who:State.t list -> t -> key -> State.t -> State.t (** Get the state associated to the given key and state. - if [who] is set, automatically adds dependency from the found state - to each of states of [who]. - @raise Not_found if there is no such binding - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from the found state + to each of states of [who]. + @raise Not_found if there is no such binding + @since Boron-20100401 *) val find_all_local: ?who:State.t list -> t -> key -> State.t -> (data * State.t) list (** Get all the bindings associated to the given key and state. - if [who] is set, automatically adds dependency from each found state - to each of states of [who]. - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from each found state + to each of states of [who]. + @since Boron-20100401 *) val find_all_local_data: ?who:State.t list -> t -> key -> State.t -> data list (** Get all the data associated to the given key and state. - if [who] is set, automatically adds dependency from the state - corresponding to each data to each of states of [who]. - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from the state + corresponding to each data to each of states of [who]. + @since Boron-20100401 *) val find_all_local_states: ?who:State.t list -> t -> key -> State.t -> State.t list (** Get all the states associated to the given key and state. - if [who] is set, automatically adds dependency from each found state - to each of states of [who]. - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from each found state + to each of states of [who]. + @since Boron-20100401 *) val find_all: ?who:State.t list -> t -> key -> (data * State.t) list (** Get all bindings associated to the given key. - if [who] is set, automatically adds dependency from each found state - to each of states of [who]. - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from each found state + to each of states of [who]. + @since Boron-20100401 *) val find_all_data: ?who:State.t list -> t -> key -> data list (** Get all data associated to the given key. - if [who] is set, automatically adds dependency from the state - correspondin to of each found data to each of states of [who]. - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from the state + correspondin to of each found data to each of states of [who]. + @since Boron-20100401 *) val find_all_states: ?who:State.t list -> t -> key -> State.t list (** Get all states associated to the given key. - if [who] is set, automatically adds dependency from each found state - to each of states of [who]. - @since Boron-20100401 *) + if [who] is set, automatically adds dependency from each found state + to each of states of [who]. + @since Boron-20100401 *) (** {3 Iterators} *) val iter: (key -> State.t option -> data * State.t -> unit) -> t -> unit (** Iterator on each binding of the table. - @since Boron-20100401 + @since Boron-20100401 @modify Carbon-20101201 *) val iter_key: (State.t option -> data * State.t -> unit) -> t -> key -> unit (** Iterator on each binding of the table associated to the given key. - @since Boron-20100401 + @since Boron-20100401 @modify Carbon-20101201 *) val fold: (key -> State.t option -> data * State.t -> 'a -> 'a) -> t -> 'a -> 'a (** Folder on each binding of the table. - @since Boron-20100401 + @since Boron-20100401 @modify Carbon-20101201 *) val fold_key: @@ -229,7 +229,7 @@ val length: t -> int (** Number of bindings in the table. - @since Boron-20100401 *) + @since Boron-20100401 *) type marshaled val marshaler: (t -> marshaled) * (marshaled -> t) diff -Nru frama-c-20110201+carbon+dfsg/src/project/project.ml frama-c-20111001+nitrogen+dfsg/src/project/project.ml --- frama-c-20110201+carbon+dfsg/src/project/project.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/project.ml 2011-10-10 08:38:25.000000000 +0000 @@ -41,10 +41,10 @@ type t = project let name = "Project" let structural_descr = - Structural_descr.t_record - [| Structural_descr.p_int; - Structural_descr.p_string; - Structural_descr.p_string |] + Structural_descr.t_record + [| Structural_descr.p_int; + Structural_descr.p_string; + Structural_descr.p_string |] let reprs = [ dummy ] let equal = (==) let compare p1 p2 = Datatype.Int.compare p1.pid p2.pid @@ -52,11 +52,11 @@ let rehash x = !rehash_ref x let copy = Datatype.undefined let internal_pretty_code p_caller fmt p = - let pp f = - Format.fprintf - f "@[<hv 2>Project.from_unique_name@;%S@]" p.unique_name - in - Type.par p_caller Type.Call fmt pp + let pp f = + Format.fprintf + f "@[<hv 2>Project.from_unique_name@;%S@]" p.unique_name + in + Type.par p_caller Type.Call fmt pp let pretty fmt p = Format.fprintf fmt "project %S" p.unique_name let varname p = "p_" ^ p.name let mem_project f x = f x @@ -69,6 +69,9 @@ (** {2 States operations} *) (* ************************************************************************** *) +let current_selection = ref State_selection.empty +let get_current_selection () = !current_selection + module States_operations = struct module H = Hashtbl @@ -76,19 +79,17 @@ module Hashtbl = H let iter f x = + current_selection := State_selection.full; State_dependency_graph.Static.G.iter_vertex (fun s -> f s x) State_dependency_graph.Static.graph - let fold f x = - State_dependency_graph.Static.G.fold_vertex - (fun s -> f s x) - State_dependency_graph.Static.graph - let iter_on_selection ?(selection=State_selection.full) f x = + current_selection := selection; State_selection.Static.iter (fun s -> f s x) selection let fold_on_selection ?(selection=State_selection.full) f x = + current_selection := selection; State_selection.Static.fold (fun s -> f s x) selection let create = iter (fun s -> (private_ops s).create) @@ -105,33 +106,35 @@ let clear s = (private_ops s).clear in if State_selection.is_full selection then iter clear p (* clearing the static states also clears the dynamic ones *) - else + else begin + current_selection := selection; State_selection.Dynamic.iter (fun s -> clear s p) selection + end let clear_some_projects ?selection f p = let states_to_clear = fold_on_selection - ?selection - (fun s p acc -> - let is_cleared = (private_ops s).clear_some_projects f p in - if is_cleared then - State_selection.Dynamic.union - (State_selection.Dynamic.with_dependencies s) - acc - else - acc) - p - State_selection.empty + ?selection + (fun s p acc -> + let is_cleared = (private_ops s).clear_some_projects f p in + if is_cleared then + State_selection.Dynamic.union + (State_selection.Dynamic.with_dependencies s) + acc + else + acc) + p + State_selection.empty in if not (State_selection.is_empty states_to_clear) then begin warning "clearing dangling project pointers in project %S" p.unique_name; debug ~once:true ~append:(fun fmt -> Format.fprintf fmt "@]") - "@[the involved states are:%t" - (fun fmt -> - iter_on_selection - ~selection:states_to_clear - (fun s () -> Format.fprintf fmt "@ %S" (get_name s)) - ()) + "@[the involved states are:%t" + (fun fmt -> + iter_on_selection + ~selection:states_to_clear + (fun s () -> Format.fprintf fmt "@ %S" (get_name s)) + ()) end let copy ?selection src = @@ -147,11 +150,11 @@ let unserialize ?selection dst loaded_states = let pp_err fmt n = if n > 0 then begin - warning ~once:true - fmt - n - (if n = 1 then "" else "s") (if n = 1 then "is" else "are") - (if n = 1 then "It does not exist in" else "They do not exist in") + warning ~once:true + fmt + n + (if n = 1 then "" else "s") (if n = 1 then "is" else "are") + (if n = 1 then "It does not exist in" else "They do not exist in") end in let tbl = Hashtbl.create 97 in @@ -159,20 +162,20 @@ iter_on_selection ?selection (fun s () -> - try - let n = get_unique_name s in - let d = Hashtbl.find tbl n in - (try (private_ops s).unserialize dst d - with Not_found -> assert false); - Hashtbl.remove tbl n; - with Not_found -> - (* [s] is in RAM but not on disk: silently ignore it! - As [dst] is a new project, [s] is already equal to its default - value. Furthermore, all the dependencies of [s] are consistent - with this default value. So no need to clear them. Whenever - the value of [s] in [dst] changes, the dependencies will be - cleared (if required by the user of Project.clear). *) - ()) + try + let n = get_unique_name s in + let d = Hashtbl.find tbl n in + (try (private_ops s).unserialize dst d + with Not_found -> assert false); + Hashtbl.remove tbl n; + with Not_found -> + (* [s] is in RAM but not on disk: silently ignore it! + As [dst] is a new project, [s] is already equal to its default + value. Furthermore, all the dependencies of [s] are consistent + with this default value. So no need to clear them. Whenever + the value of [s] in [dst] changes, the dependencies will be + cleared (if required by the user of Project.clear). *) + ()) (); (* warns for the saved states that cannot be loaded. *) let nb_ignored = @@ -195,17 +198,17 @@ else let n = get_size selection in if n = 0 then - Log.nullprintf fmt_msg + Log.nullprintf fmt_msg else - let states fmt = - if n > 1 then Format.fprintf fmt " (for %d states)" n - else Format.fprintf fmt " (for 1 state)"; - if debug_atleast 1 then begin - Format.pp_print_newline fmt (); - pp_selection fmt selection - end - in - feedback ~level ~append:states fmt_msg + let states fmt = + if n > 1 then Format.fprintf fmt " (for %d states)" n + else Format.fprintf fmt " (for 1 state)"; + if debug_atleast 1 then begin + Format.pp_print_newline fmt (); + pp_selection fmt selection + end + in + feedback ~level ~append:states fmt_msg else Log.nullprintf fmt_msg @@ -319,7 +322,7 @@ Journal.register "Project.set_current" (lbl "on" (fun () -> false) Datatype.bool (lbl "selection" dft_sel State_selection.ty - (Datatype.func ty Datatype.unit))) + (Datatype.func ty Datatype.unit))) unjournalized_set_current let set_current ?(on=false) ?(selection=State_selection.full) p = @@ -389,7 +392,7 @@ (lbl "src" current ty (Datatype.func ty Datatype.unit))) (fun selection src dst -> guarded_feedback selection 2 "copying project from %S to %S" - src.unique_name dst.unique_name; + src.unique_name dst.unique_name; States_operations.commit ~selection src; States_operations.copy ~selection src dst) @@ -413,7 +416,7 @@ (lbl "project" current ty (Datatype.func Datatype.unit Datatype.unit))) (fun selection project () -> full_guarded_feedback selection 2 "clearing project %S" - project.unique_name; + project.unique_name; Before_Clear_Hook.apply project; States_operations.clear ~selection project; After_Clear_Hook.apply project; @@ -458,11 +461,11 @@ output_value cout !Graph.Blocks.cpt_vertex; let states : (t * (string * State.state_on_disk) list) list = Q.fold - (fun acc p -> - (* project + serialized version of all its states *) - (p, States_operations.serialize ~selection p) :: acc) - [] - projects + (fun acc p -> + (* project + serialized version of all its states *) + (p, States_operations.serialize ~selection p) :: acc) + [] + projects in (* projects are stored on disk from the current one to the last project *) output_value cout (List.rev states); @@ -512,19 +515,19 @@ module Rehash = Hashtbl.Make (struct - type t = project - let hash p = Hashtbl.hash p.pid - let equal x y = - match !project_under_copy_ref with - | Some p when p.pid <> x.pid && p.pid <> y.pid -> - (* Merge projects on disk with pre-existing projects, except the - project under copy; so don't use (==) in this context. *) - x.pid = y.pid - | None | Some _ -> - (* In all other cases, don't merge. - (==) ensures that there is no sharing between a pre-existing - project and a project on disk. Great! *) - x == y + type t = project + let hash p = Hashtbl.hash p.pid + let equal x y = + match !project_under_copy_ref with + | Some p when p.pid <> x.pid && p.pid <> y.pid -> + (* Merge projects on disk with pre-existing projects, except the + project under copy; so don't use (==) in this context. *) + x.pid = y.pid + | None | Some _ -> + (* In all other cases, don't merge. + (==) ensures that there is no sharing between a pre-existing + project and a project on disk. Great! *) + x == y end) let rehash_cache : project Rehash.t = Rehash.create 7 @@ -542,7 +545,7 @@ let init project_under_copy = assert (Rehash.length rehash_cache = 0 - && Project_tbl.length existing_projects = 0); + && Project_tbl.length existing_projects = 0); project_under_copy_ref := project_under_copy; Q.fold (fun acc p -> Project_tbl.add existing_projects p (); p :: acc) @@ -553,12 +556,12 @@ (match !project_under_copy_ref with | None -> List.iter - (fun ( (p, _)) -> - States_operations.clear_some_projects - ~selection - (fun p -> not (Project_tbl.mem existing_projects p)) - p) - loaded_states + (fun ( (p, _)) -> + States_operations.clear_some_projects + ~selection + (fun p -> not (Project_tbl.mem existing_projects p)) + p) + loaded_states | Some _ -> ()); Rehash.clear rehash_cache; @@ -568,41 +571,41 @@ let state_on_disk s = (* Format.printf "State %S@." s;*) let descr = - try State.get_descr (State.get s) - with State.Unknown -> Structural_descr.p_unit (* dummy value *) + try State.get_descr (State.get s) + with State.Unknown -> Structural_descr.p_unit (* dummy value *) in Descr.t_record - [| descr; - Structural_descr.p_bool; - Structural_descr.p_bool; - Structural_descr.p_string |] - State.dummy_state_on_disk + [| descr; + Structural_descr.p_bool; + Structural_descr.p_bool; + Structural_descr.p_string |] + State.dummy_state_on_disk in let tbl_on_disk = Descr.dependent_pair Descr.t_string state_on_disk in let one_state = let unmarshal_states p = - Descr.dynamic - (fun () -> - (* Local states must be up-to-date according [p] when unmarshalling - states of [p] *) - unjournalized_set_current true selection p; - Before_load.apply (); - Descr.t_list tbl_on_disk) + Descr.dynamic + (fun () -> + (* Local states must be up-to-date according [p] when unmarshalling + states of [p] *) + unjournalized_set_current true selection p; + Before_load.apply (); + Descr.t_list tbl_on_disk) in Descr.dependent_pair descr unmarshal_states in let final_one_state = Descr.transform - one_state - (fun (p, s as c) -> - (match name with None -> () | Some s -> set_name p s); - Project_tbl.add existing_projects p (); - (* At this point, the local states are always up-to-date according - to the current project, since we load first the old current - project *) - States_operations.unserialize ~selection p s; - After_load.apply (); - c) + one_state + (fun (p, s as c) -> + (match name with None -> () | Some s -> set_name p s); + Project_tbl.add existing_projects p (); + (* At this point, the local states are always up-to-date according + to the current project, since we load first the old current + project *) + States_operations.unserialize ~selection p s; + After_load.apply (); + c) in Descr.t_list final_one_state @@ -620,14 +623,14 @@ let check_magic cin to_string current = let old = read cin in if old <> current then begin - close_in cin; - let s = - Format.sprintf - "project saved with an incompatible version (old: %S,current: %S)" - (to_string old) - (to_string current) - in - raise (IOError s) + close_in cin; + let s = + Format.sprintf + "project saved with an incompatible version (old: %S,current: %S)" + (to_string old) + (to_string current) + in + raise (IOError s) end in check_magic cin (fun x -> x) Config.version; @@ -636,31 +639,31 @@ let pre_existing_projects = Descr.init project_under_copy in let loaded_states = gen_read - (fun c -> Descr.input_val c (Descr.global_state name selection)) - cin + (fun c -> Descr.input_val c (Descr.global_state name selection)) + cin in close_in cin; Descr.finalize loaded_states selection; Graph.Blocks.after_unserialization ocamlgraph_counter; - After_global_load.apply (); (* [set_current] done when unmarshalling and hooks may reorder projects: rebuild it in the good order *) let last = current () in Q.clear projects; let loaded_projects = List.fold_right - (fun (p, _) acc -> Q.add p projects; p :: acc) loaded_states [] + (fun (p, _) acc -> Q.add p projects; p :: acc) loaded_states [] in List.iter (fun p -> Q.add p projects) pre_existing_projects; (* We have to restore all the local states if the last loaded project is not the good current one. The trick is to call [set_current] on [current - ()], but we ensure that this operations **do** something (that is not + ()], but we ensure that this operation **does** something (that is not the case by default) by putting [last] as current project temporarily. *) let true_current = current () in Q.add last projects; unjournalized_set_current true selection true_current; Q.remove last projects; + After_global_load.apply (); loaded_projects end else abort "loading a file is not supported in the 'no obj' mode" @@ -677,7 +680,7 @@ Journal.register "Project.load" (lbl "selection" dft_sel State_selection.ty (lbl "name" (fun () -> None) - (Datatype.option Datatype.string) (Datatype.func Datatype.string ty))) + (Datatype.option Datatype.string) (Datatype.func Datatype.string ty))) (unjournalized_load ~project_under_copy:None) let load ?(selection=State_selection.full) ?name filename = @@ -709,12 +712,15 @@ let unjournalized_create_by_copy selection src name = guarded_feedback selection 2 "creating project %S by copying project %S" name (src.unique_name); - let filename = Filename.temp_file "frama_c_create_by_copy" ".sav" in + let filename = + try Filename.temp_file "frama_c_create_by_copy" ".sav" + with Sys_error s -> abort "cannot create temporary file: %s" s + in save ~selection ~project:src filename; try let prj = unjournalized_load - ~project_under_copy:(Some src) selection (Some name) filename + ~project_under_copy:(Some src) selection (Some name) filename in Extlib.safe_remove filename; Create_by_copy_hook.apply (src, prj); @@ -747,18 +753,20 @@ let restore () = if Cmdline.use_obj then begin try - Journal.prevent load_all !filename; - Journal.restore (); - clear_breakpoint () + Journal.prevent load_all !filename; + Journal.restore (); + clear_breakpoint () with IOError s -> - feedback "cannot restore the last breakpoint: %S" s; - clear_breakpoint () + feedback "cannot restore the last breakpoint: %S" s; + clear_breakpoint () end let breakpoint () = if Cmdline.use_obj then begin clear_breakpoint (); - filename := Filename.temp_file short_filename ".sav"; + filename := + (try Filename.temp_file short_filename ".sav" + with Sys_error s -> abort "cannot create temporary file: %s" s); Journal.prevent save_all !filename; Journal.save () end diff -Nru frama-c-20110201+carbon+dfsg/src/project/project.mli frama-c-20111001+nitrogen+dfsg/src/project/project.mli --- frama-c-20110201+carbon+dfsg/src/project/project.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/project.mli 2011-10-10 08:38:25.000000000 +0000 @@ -40,10 +40,10 @@ type project = Project_skeleton.t = private { pid : int; - mutable name : string; - mutable unique_name : string } + mutable name : string; + mutable unique_name : string } (** Type of a project. - @plugin development guide *) + @plugin development guide *) (* ************************************************************************* *) (** {2 Operations on all projects} *) @@ -258,10 +258,20 @@ val register_after_global_load_hook: (unit -> unit) -> unit (** [register_after_load_hook f] adds a hook called just after loading - **all projects**. + **all projects**. [f] must not set the current project. @since Boron-20100401 *) (* ************************************************************************* *) +(** {3 Handling the selection} *) +(* ************************************************************************* *) + +val get_current_selection: unit -> State_selection.t +(** If an operation on a project is ongoing, then [get_current_selection ()] + returns the selection which is applied on. + The behaviour is unspecified if this function is called when no operation + depending on a selection is ongoing. *) + +(* ************************************************************************* *) (** {2 Projects are comparable values} *) (* ************************************************************************* *) diff -Nru frama-c-20110201+carbon+dfsg/src/project/project_skeleton.mli frama-c-20111001+nitrogen+dfsg/src/project/project_skeleton.mli --- frama-c-20110201+carbon+dfsg/src/project/project_skeleton.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/project_skeleton.mli 2011-10-10 08:38:25.000000000 +0000 @@ -51,6 +51,10 @@ (** @since Carbon-20101201 *) module Make_setter(X: sig val mem: string -> bool end) : sig + val make_unique_name: string -> string + (** @return a fresh name from the given string according to [X.mem]. + @since Nitrogen-20111001 *) + val make: string -> t (** @since Carbon-20101201 *) diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_builder.ml frama-c-20111001+nitrogen+dfsg/src/project/state_builder.ml --- frama-c-20110201+carbon+dfsg/src/project/state_builder.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_builder.ml 2011-10-10 08:38:25.000000000 +0000 @@ -44,6 +44,7 @@ val mark_as_computed: ?project:Project.t -> unit -> unit val is_computed: ?project:Project.t -> unit -> bool module Datatype: Datatype.S + val add_hook_on_update: (Datatype.t -> unit) -> unit val howto_marshal: (Datatype.t -> 'a) -> ('a -> Datatype.t) -> unit end @@ -80,25 +81,26 @@ let create name kind correctness states = let s = State.create - ~descr:Structural_descr.p_abstract - ~create:do_nothing - ~remove:do_nothing - ~clear:do_nothing - ~clean:do_nothing - ~clear_some_projects:(fun _ _ -> false) - ~copy:do_nothing_2 - ~commit:do_nothing - ~update:do_nothing - ~serialize: - (fun _ -> - { on_disk_value = Obj.repr (); - on_disk_computed = false; - on_disk_saved = false; - on_disk_digest = Type.digest Datatype.unit }) - ~unserialize:do_nothing_2 - ~unique_name:name - ~name - (`Proxy correctness) + ~descr:Structural_descr.p_abstract + ~create:do_nothing + ~remove:do_nothing + ~clear:do_nothing + ~clean:do_nothing + ~clear_some_projects:(fun _ _ -> false) + ~copy:do_nothing_2 + ~commit:do_nothing + ~update:do_nothing + ~on_update:do_nothing + ~serialize: + (fun _ -> + { on_disk_value = Obj.repr (); + on_disk_computed = false; + on_disk_saved = false; + on_disk_digest = Type.digest Datatype.unit }) + ~unserialize:do_nothing_2 + ~unique_name:(State.unique_name_from_name name) + ~name + (`Proxy correctness) in State_dependency_graph.add_state_like_the_others states s; extend_state states kind s; @@ -141,18 +143,22 @@ let commit p = if Project.is_current p then try - let v = find p in - v.state <- Local_state.get () + let v = find p in + v.state <- Local_state.get () with Not_found -> - fatal - "state %S not associated with project %S; program will fail" - name - (Project.get_unique_name p) + fatal + "state %S not associated with project %S; program will fail" + name + (Project.get_unique_name p) + + module Update_hook = Hook.Build(Datatype) + let add_hook_on_update = Update_hook.extend let update_with ~force p s = if Project.is_current p || force then begin debug ~level:4 "update state %S of project %S" - !internal_name (Project.get_unique_name p); + !internal_name (Project.get_unique_name p); + Update_hook.apply s; Local_state.set s end @@ -174,17 +180,17 @@ fun p -> assert (not (mem p)); (* For efficiency purpose, do not create the initial project twice: - directly get it *) + directly get it *) let mk () = - if !first then begin - first := false; - Local_state.get () - end else begin + if !first then begin + first := false; + Local_state.get () + end else begin debug ~level:4 "creating state %S for project %S" - !internal_name (Project.get_unique_name p); - let s = Local_state.create () in - update_with ~force:false p s; - s + !internal_name (Project.get_unique_name p); + let s = Local_state.create () in + update_with ~force:false p s; + s end in let s = mk () in @@ -239,23 +245,23 @@ assert Cmdline.use_obj; if Type.digest Datatype.ty = new_s.State.on_disk_digest then begin debug ~level:4 "unserializing state %S for project %S" - !internal_name (Project.get_unique_name p); + !internal_name (Project.get_unique_name p); (* Format.printf "UNSERIALIZING %s / %s: %b@." !internal_name Datatype.name !must_save;*) let s, computed = - if !must_save && new_s.State.on_disk_saved then - !unmarshal new_s.State.on_disk_value, new_s.State.on_disk_computed - else - (* invariant: the found state is equal to the default one since it - has been just created. - Do not call Local_state.create to don't break sharing *) - (find p).state, false + if !must_save && new_s.State.on_disk_saved then + !unmarshal new_s.State.on_disk_value, new_s.State.on_disk_computed + else + (* invariant: the found state is equal to the default one since it + has been just created. + Do not call Local_state.create to don't break sharing *) + (find p).state, false in change ~force:true p { state = s; computed = computed }; end else raise - (Project.IOError - ("project saved with incompatibles datatypes for state " - ^ !internal_name)) + (Project.IOError + ("project saved with incompatibles datatypes for state " + ^ !internal_name)) (* ********************************************************************* *) let mark_as_computed ?(project=(Project.current ())) () = @@ -271,7 +277,8 @@ State.create (* we will marshal the value [()] if the state is unmarshable *) ~descr ~create ~remove ~clear ~clear_some_projects ~copy - ~commit ~update ~serialize ~unserialize ~clean + ~commit ~update ~on_update:(fun f -> Update_hook.extend (fun _ -> f ())) + ~serialize ~unserialize ~clean ~unique_name ~name:Info.name Info.kind let name = State.get_name self @@ -345,7 +352,7 @@ let new_kind ~name unique_name clear = let clear p = debug ~level:4 "clearing dynamic state %S for project %S" - name (Project.get_unique_name p); + name (Project.get_unique_name p); clear p in let s = State.unusable ~name unique_name in @@ -359,9 +366,9 @@ (G.Datatype) (G) (struct - include Info - let unique_name = name - let descr _ = Descr.unmarshable + include Info + let unique_name = name + let descr _ = Descr.unmarshable end) let () = Proxy.extend [ Graph_state.self ] states_graph_proxy @@ -388,8 +395,8 @@ let kind = State.kind self let () = let deps = - !self_ref - :: List.filter (fun s -> not (State.is_dummy s)) Info.dependencies + !self_ref + :: List.filter (fun s -> not (State.is_dummy s)) Info.dependencies in G.add_state self deps end @@ -478,7 +485,7 @@ try let old = get () in Extlib.may_map - ~dft:old (fun f -> let v = f old in set v; v) change + ~dft:old (fun f -> let v = f old in set v; v) change with Not_found -> let data = f () in set data; @@ -492,6 +499,7 @@ module type List_ref = sig type data_in_list include Ref + val add: data_in_list -> unit val iter: (data_in_list -> unit) -> unit val fold_left: ('a -> data_in_list -> 'a) -> 'a -> 'a end @@ -499,6 +507,7 @@ module List_ref(Data:Datatype.S)(Info:Info) = struct type data_in_list = Data.t include Ref(Datatype.List(Data))(struct include Info let default () = [] end) + let add d = set (d::get()) let iter f = List.iter f (get ()) let fold_left f acc = List.fold_left f acc (get ()) end @@ -523,7 +532,7 @@ (* ************************************************************************* *) module type Set_ref = sig - include S + include Ref type elt val add: elt -> unit val is_empty: unit -> bool @@ -593,21 +602,21 @@ (* Format.printf "%S: %S %S@." Info.name H.Key.name Data.name;*) let x = if D.mem_project == Datatype.never_any_project then - false + false else - (* [TODO] BUG: if [Data.mem_project f v] returns [true] and there are - several bindings for the key [k] of [v] (and [v] is not the last - added binding) *) - let found = - H.fold - (fun k v l -> - if H.Key.mem_project f k || Data.mem_project f v then k :: l - else l) - h - [] - in - List.iter (H.remove h) found; - found <> [] + (* [TODO] BUG: if [Data.mem_project f v] returns [true] and there are + several bindings for the key [k] of [v] (and [v] is not the last + added binding) *) + let found = + H.fold + (fun k v l -> + if H.Key.mem_project f k || Data.mem_project f v then k :: l + else l) + h + [] + in + List.iter (H.remove h) found; + found <> [] in (* Format.printf "DONE@.";*) x @@ -629,7 +638,7 @@ try let old = find key in Extlib.may_map - ~dft:old (fun f -> let v = f old in replace key v; v) change + ~dft:old (fun f -> let v = f old in replace key v; v) change with Not_found -> let data = f key in replace key data; @@ -678,14 +687,14 @@ let set x = state := x let clear_some_projects f h = if Data.mem_project == Datatype.never_any_project then - false + false else - let found = - W.fold - (fun k l -> if Data.mem_project f k then k :: l else l) h [] - in - List.iter (W.remove h) found; - found <> [] + let found = + W.fold + (fun k l -> if Data.mem_project f k then k :: l else l) h [] + in + List.iter (W.remove h) found; + found <> [] end) (struct include Info let unique_name = name end) @@ -721,20 +730,20 @@ include Weak.Make (struct - include Data - let equal = Data.equal_internal - let hash = Data.hash_internal + include Data + let equal = Data.equal_internal + let hash = Data.hash_internal end) let add_initial_values h = (* Format.printf "adding initial values for %s@." Info.name;*) List.iter - (fun vi -> - let _r = merge h vi in - (* (* Check that we do not add the value twice, which is probably a - bug in the calling interface *) - assert (r == vi) *) ()) - Data.initial_values + (fun vi -> + let _r = merge h vi in + (* (* Check that we do not add the value twice, which is probably a + bug in the calling interface *) + assert (r == vi) *) ()) + Data.initial_values let create size = let h = create size in @@ -749,16 +758,16 @@ let merge = let c = ref 0 in fun h x -> - incr c; - if (!c land 4095 = 0) - then begin - Gc.full_major (); - let length, n, sum, small, med, large = stats h in - Format.printf "%s length %d, n %d, sum %d, small %d, med %d, large %d@." - Info.name - length n sum small med large - end; - merge h x + incr c; + if (!c land 4095 = 0) + then begin + Gc.full_major (); + let length, n, sum, small, med, large = stats h in + Format.printf "%s length %d, n %d, sum %d, small %d, med %d, large %d@." + Info.name + length n sum small med large + end; + merge h x *) end @@ -806,43 +815,85 @@ module Graph: Dashtbl.Graph end + (* Create a fresh, shared reference among projects. The projectification is only required for correct marshalling. *) -module Counter(Info : sig val name : string end) = -struct +module SharedCounter(Info : sig val name : string end) = struct + let cpt = ref 0 module Cpt = Register (struct - include Datatype.Int - let default () = 0 - let descr = - Descr.transform - Descr.t_int - (fun n -> - cpt := Extlib.max_cpt n !cpt; - !cpt) + include Datatype.Int + let default () = 0 + let descr = + Descr.transform + Descr.t_int + (fun n -> + cpt := Extlib.max_cpt n !cpt; + !cpt) end) (struct - type t = int - let create () = !cpt - let clear _ = () - let get () = !cpt - let set _ = () - let clear_some_projects _ _ = false + type t = int + let create () = !cpt + let clear _ = () + let get () = !cpt + let set _ = () + let clear_some_projects _ _ = false end) (struct - let name = Info.name - let unique_name = Info.name - let dependencies = [] - let kind = `Internal + let name = Info.name + let unique_name = Info.name + let dependencies = [] + let kind = `Internal end) let next () = incr cpt ; !cpt + let self = Cpt.self + +end + +module Cpt = SharedCounter(struct let name = "State_builder.Cpt" end) + + +module Counter(Info : sig val name : string end) = struct + + let create () = ref 0 + let cpt = ref (create ()) + + module Cpt = + Register + (struct + include Datatype.Ref(Datatype.Int) + let default () = 0 + let descr = + Descr.transform + (Descr.t_ref Descr.t_int) + (fun n -> + let r = !cpt in + r := Extlib.max_cpt !n !r; + r) + end) + (struct + type t = int ref + let create = create + let clear x = x := 0 + let get () = !cpt + let set x = cpt := x + let clear_some_projects _ _ = false + end) + (struct + let name = Info.name + let unique_name = Info.name + let dependencies = [] + let kind = `Internal + end) + + let next () = incr !cpt ; !(!cpt) + let self = Cpt.self end -module Cpt = Counter(struct let name = "State_builder.Cpt" end) module Dashtbl (Key: Dashtbl.Key) @@ -855,24 +906,24 @@ module D = Dynamic - (struct - let name = Info.name ^ " Dependency Graph" - let dependencies = [] - let kind = `Internal - let internal_kind = Info.internal_kind - end) + (struct + let name = Info.name ^ " Dependency Graph" + let dependencies = [] + let kind = `Internal + let internal_kind = Info.internal_kind + end) let create_and_add_state ~clear ~name ~deps = let module S = - D.Register - (struct let clear = clear end) - (struct - let name = name - let unique_name = - let n = Cpt.next () in - Info.name ^ "; binding " ^ string_of_int n - let dependencies = deps - end) + D.Register + (struct let clear = clear end) + (struct + let name = name + let unique_name = + let n = Cpt.next () in + Info.name ^ "; binding " ^ string_of_int n + let dependencies = deps + end) in S.self @@ -902,7 +953,7 @@ let clear_some_projects _ _ = (* TODO: not able to handle project in dashtbl yet *) assert (Data.mem_project == Datatype.never_any_project - || Data.mem_project == Datatype.undefined); + || Data.mem_project == Datatype.undefined); false end) (struct include Info let unique_name = name end) @@ -919,16 +970,16 @@ let () = Project.register_after_load_hook (fun () -> - Dash.iter - (fun _ s (_, s') -> - assert (not (State.is_dummy s')); - let from = - match s with - | None -> [ self ] - | Some s -> [ s; self ] - in - State_dependency_graph.Dynamic.add_codependencies ~onto:s' from) - !state) + Dash.iter + (fun _ s (_, s') -> + assert (not (State.is_dummy s')); + let from = + match s with + | None -> [ self ] + | Some s -> [ s; self ] + in + State_dependency_graph.Dynamic.add_codependencies ~onto:s' from) + !state) type key = Dash.key type data = Dash.data @@ -987,15 +1038,15 @@ let set x = state := x let clear_some_projects f q = if Data.mem_project == Datatype.never_any_project then - false + false else - (* cannot remove a single element from a queue *) - try - Queue.iter (fun x -> if Data.mem_project f x then raise Exit) q; - false - with Exit -> - clear q; - true + (* cannot remove a single element from a queue *) + try + Queue.iter (fun x -> if Data.mem_project f x then raise Exit) q; + false + with Exit -> + clear q; + true end) (struct include Info let unique_name = name end) @@ -1013,8 +1064,8 @@ let module First = True_ref (struct - let dependencies = dep - let name = name + let dependencies = dep + let name = name let kind = `Internal end) in @@ -1022,11 +1073,11 @@ if First.get () then begin First.set false; try - f (); - assert (First.get () = false) + f (); + assert (First.get () = false) with exn -> - First.set true; - raise exn + First.set true; + raise exn end), First.self diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_builder.mli frama-c-20111001+nitrogen+dfsg/src/project/state_builder.mli --- frama-c-20110201+carbon+dfsg/src/project/state_builder.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_builder.mli 2011-10-10 08:38:25.000000000 +0000 @@ -50,7 +50,7 @@ val self: State.t (** The kind of the registered state. - @plugin development guide *) + @plugin development guide *) val name: string val kind: State.kind @@ -67,13 +67,18 @@ module Datatype: Datatype.S + val add_hook_on_update: (Datatype.t -> unit) -> unit + (** Add an hook which is applied each time (just before) the project library + changes the local value of the state. + @since Nitrogen-20111001 *) + val howto_marshal: (Datatype.t -> 'a) -> ('a -> Datatype.t) -> unit - (** [howto_marshal marshal unmarshal] registers a custom couple of - countions [(marshal, unmarshal)] to be used for serialization. - Default functions are identities. In particular, calling this - function must be used if [Datatype.t] is not marshallable and - [do_not_save] is not called. - @since Boron-20100401 *) +(** [howto_marshal marshal unmarshal] registers a custom couple of + countions [(marshal, unmarshal)] to be used for serialization. + Default functions are identities. In particular, calling this + function must be used if [Datatype.t] is not marshallable and + [do_not_save] is not called. + @since Boron-20100401 *) end @@ -125,8 +130,8 @@ include Ref val memo: ?change:(data -> data) -> (unit -> data) -> data (** Memoization. Compute on need the stored value. - If the data is already computed (i.e. is not [None]), - it is possible to change with [change]. *) + If the data is already computed (i.e. is not [None]), + it is possible to change with [change]. *) val map: (data -> data) -> data option val may: (data -> unit) -> unit val get_option : unit -> data option @@ -142,6 +147,7 @@ module type List_ref = sig type data_in_list include Ref + val add: data_in_list -> unit (** @since Nitrogen-20111001 *) val iter: (data_in_list -> unit) -> unit val fold_left: ('a -> data_in_list -> 'a) -> 'a -> 'a end @@ -184,12 +190,12 @@ module type Dashtbl = sig include S (** A dashtable is a standard computation. - BUT: - - that is INCORRECT to add the [self] value of a dashtbl into a - selection without also adding all the {!selection}. - - that is INCORRECT to use dashtable if keys or values have a custom - [rehash] function (see {!Project.DATATYPE_OUTPUT.rehash}) - @since Boron-20100401 *) + BUT: + - that is INCORRECT to add the [self] value of a dashtbl into a + selection without also adding all the {!selection}. + - that is INCORRECT to use dashtable if keys or values have a custom + [rehash] function (see {!Project.DATATYPE_OUTPUT.rehash}) + @since Boron-20100401 *) type key type data @@ -244,30 +250,30 @@ include S (** Hashtbl are a standard computation. - BUT it is INCORRECT to use projectified hashtables if keys have a - custom [rehash] function (see {!Project.DATATYPE_OUTPUT.rehash}) *) + BUT it is INCORRECT to use projectified hashtables if keys have a + custom [rehash] function (see {!Project.DATATYPE_OUTPUT.rehash}) *) type data (** @since Boron-20100401 *) val merge: data -> data (** [merge x] returns an instance of [x] found in the table if any, or else - adds [x] and return [x]. - @since Boron-20100401 *) + adds [x] and return [x]. + @since Boron-20100401 *) val add: data -> unit (** [add x] adds [x] to the table. If there is already an instance of [x], - it is unspecified which one will be returned by subsequent calls to - [find] and [merge]. - @since Boron-20100401 *) + it is unspecified which one will be returned by subsequent calls to + [find] and [merge]. + @since Boron-20100401 *) val clear: unit -> unit (** Clear the table. - @since Boron-20100401 *) + @since Boron-20100401 *) val count: unit -> int (** Length of the table. - @since Boron-20100401 *) + @since Boron-20100401 *) val iter: (data -> unit) -> unit (** @since Boron-20100401 *) @@ -277,22 +283,22 @@ val find: data -> data (** [find x] returns an instance of [x] found in table. - @Raise Not_found if there is no such element. - @since Boron-20100401 *) + @Raise Not_found if there is no such element. + @since Boron-20100401 *) val find_all: data -> data list (** [find_all x] returns a list of all the instances of [x] found in t. - @since Boron-20100401 *) + @since Boron-20100401 *) val mem: data -> bool (** [mem x] returns [true] if there is at least one instance of [x] in the - table, [false] otherwise. - @since Boron-20100401 *) + table, [false] otherwise. + @since Boron-20100401 *) val remove: data -> unit (** [remove x] removes from the table one instance of [x]. Does nothing if - there is no instance of [x]. - @since Boron-20100401 *) + there is no instance of [x]. + @since Boron-20100401 *) end @@ -322,7 +328,7 @@ (** Hash function for datatype internally used by the built table. *) val initial_values: t list (** Pre-existing values stored in the built table and shared by all - existing projects. *) + existing projects. *) end) (Info: Info_with_size) : Weak_hashtbl with type data = Data.t @@ -338,8 +344,8 @@ module type Hashtbl = sig include S (** Hashtbl are a standard computation. - BUT that is INCORRECT to use projectified hashtables if keys have a - custom [rehash] function (see {!Project.DATATYPE_OUTPUT.rehash}) *) + BUT that is INCORRECT to use projectified hashtables if keys have a + custom [rehash] function (see {!Project.DATATYPE_OUTPUT.rehash}) *) type key type data @@ -355,12 +361,12 @@ val fold: (key -> data -> 'a -> 'a) -> 'a -> 'a val memo: ?change:(data -> data) -> (key -> data) -> key -> data (** Memoization. Compute on need the data associated to a given key using - the given function. - If the data is already computed, it is possible to change with - [change]. *) + the given function. + If the data is already computed, it is possible to change with + [change]. *) val find: key -> data (** Return the current binding of the given key. - @raise Not_found if the key is not in the table. *) + @raise Not_found if the key is not in the table. *) val find_all: key -> data list (** Return the list of all data associated with the given key. *) val mem: key -> bool @@ -368,10 +374,11 @@ end module Hashtbl - (H: Datatype.Hashtbl) - (Data: Datatype.S) + (H: Datatype.Hashtbl (** hashtable implementation *)) + (Data: Datatype.S (** datatype for values stored in the table *)) (Info: Info_with_size) : Hashtbl with type key = H.key and type data = Data.t + and module Datatype = H.Make(Data) (* ************************************************************************* *) (** {3 References on a set} *) @@ -379,7 +386,7 @@ (** Output signature of builders of references on a set. *) module type Set_ref = sig - include S + include Ref type elt val add: elt -> unit val is_empty: unit -> bool @@ -420,7 +427,7 @@ | Backward (** All states in the proxy depend on it. *) | Forward (** The proxy depends on all states inside. *) | Both (** States in the proxy and the proxy itself are mutually - dependent. *) + dependent. *) val create: string -> kind -> State.standard_kind -> State.t list -> t (** [create s k sk l] creates a new proxy with the given name, kinds and @@ -441,19 +448,27 @@ val apply_once: string -> State.t list -> (unit -> unit) -> (unit -> unit) * State.t (** [apply_once name dep f] returns a closure applying [f] only once and the - state internally used. [name] and [dep] are respectively the name and - the dependencies of the local state created by this function. Should - be used partially applied. If [f] raises an exception, then it is - considered as not applied. *) + state internally used. [name] and [dep] are respectively the name and + the dependencies of the local state created by this function. Should + be used partially applied. If [f] raises an exception, then it is + considered as not applied. *) -(** Creates a projectified counter which is marshalling compliant. +(** Creates a shared counter which is marshalling compliant. @since Carbon-20101201 *) -module Counter(Info : sig val name : string end) : -sig - val next : unit -> int +module SharedCounter(Info : sig val name : string end) : sig + val next : unit -> int (** Increments the counter and returns a fresh value *) end +(** Creates a shared counter which is marshalling compliant. + @since Nitrogen-20111001 *) +module Counter(Info : sig val name : string end) : sig + val next : unit -> int + (** Increments the counter and returns a fresh value *) + + val self: State.t +end + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_dependency_graph.ml frama-c-20111001+nitrogen+dfsg/src/project/state_dependency_graph.ml --- frama-c-20110201+carbon+dfsg/src/project/state_dependency_graph.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_dependency_graph.ml 2011-10-10 08:38:25.000000000 +0000 @@ -23,7 +23,7 @@ module type G = sig module V: Graph.Sig.VERTEX with type t = State.t and type label = State.t module E: Graph.Sig.EDGE with type vertex = State.t - and type t = State.t * State.t + and type t = State.t * State.t type t val iter_vertex: (V.t -> unit) -> t -> unit val fold_vertex: (V.t -> 'a -> 'a) -> t -> 'a -> 'a @@ -67,7 +67,7 @@ type graphs = { internal_graph: Dependency_graph.t; - mutable external_graph: Dependency_graph.t } + mutable external_graph: Dependency_graph.t } (* invariant: for each edge in external_graph, @@ -230,21 +230,21 @@ let iter_succ f _g v = on_vertex (fun g v -> - Single_graph.iter_succ f g v; - try Single_graph.external_iter_succ f g v - with Invalid_argument _ -> ()) + Single_graph.iter_succ f g v; + try Single_graph.external_iter_succ f g v + with Invalid_argument _ -> ()) v let fold_succ f _g v acc = on_vertex (fun g v acc -> - let acc = Single_graph.fold_succ f g v acc in - try - Single_graph.external_fold_succ - (fun v acc -> try f v acc with Invalid_argument _ -> assert false) - g v acc - with Invalid_argument _ -> - acc) + let acc = Single_graph.fold_succ f g v acc in + try + Single_graph.external_fold_succ + (fun v acc -> try f v acc with Invalid_argument _ -> assert false) + g v acc + with Invalid_argument _ -> + acc) v acc @@ -252,8 +252,8 @@ let g = !g in List.fold_left (fun acc g -> - try Single_graph.external_fold_pred f g v acc - with Invalid_argument _ -> acc) + try Single_graph.external_fold_pred f g v acc + with Invalid_argument _ -> acc) (on_vertex (Single_graph.fold_pred f) v acc) g @@ -261,17 +261,17 @@ let g = !g in List.fold_left (fun n g -> - try Single_graph.external_in_degree g v + n - with Invalid_argument _ -> n) + try Single_graph.external_in_degree g v + n + with Invalid_argument _ -> n) (on_vertex Single_graph.in_degree v) g let out_degree _g v = on_vertex (fun g v -> - let n = Single_graph.out_degree g v in - try Single_graph.external_out_degree g v + n - with Invalid_argument _ -> n) + let n = Single_graph.out_degree g v in + try Single_graph.external_out_degree g v + n + with Invalid_argument _ -> n) v let nb_vertex g = fold_vertex (fun _ -> succ) g 0 @@ -312,9 +312,9 @@ let get_graph s = try (Vertices.find s).Single_graph.id with Not_found -> -(* Format.printf "state %S (%S) not found@." - (State.get_unique_name s) (State.get_name s);*) - assert false +(* Format.printf "state %S (%S) not found@." + (State.get_unique_name s) (State.get_name s);*) + assert false let color n = `Color (Extlib.number_to_color n) let vertex_name s = "\"" ^ State.get_unique_name s ^ "\"" @@ -332,8 +332,8 @@ let get_subgraph s = let n = get_graph s in Some - { DotAttributes.sg_name = string_of_int n; - sg_attributes = [ color n ] } + { DotAttributes.sg_name = string_of_int n; + sg_attributes = [ color n ] } end @@ -386,25 +386,20 @@ type local_search = Begin | Static | Dynamic of Single_graph.t let add_state_like_the_others states s = - if states = [] then - Project_skeleton.Output.fatal - "State_dependency_graph.add_state_like_others: \ -non empty list of states required"; let rec search go = function | [] -> go | s' :: l -> let g' = Vertices.find s' in let go = match go with - | Begin | Static -> - if Single_graph.equal g' Static.graph then Static else Dynamic g' - | Dynamic _ -> go + | Begin | Static -> + if Single_graph.equal g' Static.graph then Static else Dynamic g' + | Dynamic _ -> go in search go l in match search Begin states with - | Begin -> assert false - | Static -> Static.add_state s [] + | Begin | Static -> Static.add_state s [] | Dynamic g -> Single_graph.add_vertex g s; Vertices.add s g false @@ -448,10 +443,10 @@ module Datatype = Datatype.Make (struct - include Datatype.Undefined - type t = Local.t - let name = "State_dependency_graph.Make_dynamic(" ^ T.name ^ ").t" - let reprs = [ graph.graphs ] + include Datatype.Undefined + type t = Local.t + let name = "State_dependency_graph.Make_dynamic(" ^ T.name ^ ").t" + let reprs = [ graph.graphs ] end) let () = Type.set_ml_name Datatype.ty None @@ -483,7 +478,7 @@ | `Tuning | `Correctness | `Proxy (`Internal | `Correctness) -> - G.iter_pred (fun s' -> H.replace h s' ()) g s + G.iter_pred (fun s' -> H.replace h s' ()) g s in D.iter ~post g; H.fold (fun v () g -> G.remove_vertex g v) to_be_removed g diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_dependency_graph.mli frama-c-20111001+nitrogen+dfsg/src/project/state_dependency_graph.mli --- frama-c-20110201+carbon+dfsg/src/project/state_dependency_graph.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_dependency_graph.mli 2011-10-10 08:38:25.000000000 +0000 @@ -33,7 +33,7 @@ (** @since Carbon-20101201 *) module E: Graph.Sig.EDGE with type vertex = State.t - and type t = State.t * State.t + and type t = State.t * State.t type t (** @since Carbon-20101201 *) @@ -154,8 +154,8 @@ val add_state_like_the_others: State.t list -> State.t -> unit (** [add_state_like_others l s] adds [s] to the same graph that each state of - [l]. If states of [l] belong to different graphs, then adds [s] to the best - graph as possible. + [l]. If states of [l] belong to different graphs or if [l] is empty, then + adds [s] to the best graph as possible. @since Carbon-20101201 *) module Vertices: State.Local diff -Nru frama-c-20110201+carbon+dfsg/src/project/state.ml frama-c-20111001+nitrogen+dfsg/src/project/state.ml --- frama-c-20110201+carbon+dfsg/src/project/state.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state.ml 2011-10-10 08:38:25.000000000 +0000 @@ -60,6 +60,7 @@ copy: t -> t -> unit; commit: t -> unit; update: t -> unit; + on_update: (unit -> unit) -> unit; clean: unit -> unit; serialize: t -> state_on_disk; unserialize: t -> state_on_disk -> unit } @@ -96,6 +97,7 @@ copy = never_called; commit = never_called; update = never_called; + on_update = never_called; serialize = never_called; unserialize = never_called; clean = never_called } @@ -124,16 +126,16 @@ let structural_descr = Structural_descr.Unknown let reprs = [ dummy ] let compare x y = - if x == y then 0 else String.compare x.unique_name y.unique_name + if x == y then 0 else String.compare x.unique_name y.unique_name let equal = (==) let hash x = Hashtbl.hash x.unique_name let copy = Datatype.undefined let rehash = Datatype.undefined let internal_pretty_code p_caller fmt s = - let pp fmt = - Format.fprintf fmt "@[<hv 2>State.get@;%S@]" s.unique_name - in - Type.par p_caller Type.Call fmt pp + let pp fmt = + Format.fprintf fmt "@[<hv 2>State.get@;%S@]" s.unique_name + in + Type.par p_caller Type.Call fmt pp let pretty fmt s = Format.fprintf fmt "state %S" s.unique_name let varname = Datatype.undefined let mem_project = Datatype.never_any_project @@ -152,6 +154,7 @@ let get_descr s = s.private_ops.descr let set_name s n = s.name <- n +let add_hook_on_update s f = s.private_ops.on_update f (* ************************************************************************** *) (** {2 States are comparable values} *) @@ -214,6 +217,13 @@ Caml_hashtbl.add !states uname s; if is_static then Caml_hashtbl.add statics uname s +let unique_name_from_name = + let module M = + Project_skeleton.Make_setter + (struct let mem s = Caml_hashtbl.mem !states s end) + in + M.make_unique_name + (* ************************************************************************** *) (** {3 Cluster} *) (* ************************************************************************** *) @@ -223,7 +233,7 @@ let edit_cluster c states = let set_cluster s = if s.cluster <> None then - Output.fatal "state %S already in a cluster." s.unique_name; + Output.fatal "state %S already in a cluster." s.unique_name; s.cluster <- Some c in List.iter set_cluster states @@ -231,9 +241,9 @@ let create_and_return name states = if States.exists - (fun s -> match s.cluster with - | None -> false - | Some c -> c.c_name = name) + (fun s -> match s.cluster with + | None -> false + | Some c -> c.c_name = name) then Output.fatal "cluster %S already exists." name; let c = { c_name = name; states = states } in @@ -252,9 +262,9 @@ let extend name states = try States.iter - (fun _ s -> match s.cluster with - | None -> () - | Some c -> raise (Found c)); + (fun _ s -> match s.cluster with + | None -> () + | Some c -> raise (Found c)); Output.fatal "no existing cluster %S." name; with Found c -> unsafe_extend c states @@ -278,11 +288,11 @@ | Some n -> let l = [ state ] in try - let c = Datatype.String.Hashtbl.find h n in - unsafe_extend c l + let c = Datatype.String.Hashtbl.find h n in + unsafe_extend c l with Not_found -> - let c = create_and_return n l in - Datatype.String.Hashtbl.add h n c), + let c = create_and_return n l in + Datatype.String.Hashtbl.add h n c), (fun () -> Datatype.String.Hashtbl.clear h) end @@ -311,7 +321,7 @@ let create ~descr ~create ~remove ~clear ~clear_some_projects ~copy - ~commit ~update ~clean ~serialize ~unserialize + ~commit ~update ~on_update ~clean ~serialize ~unserialize ~unique_name ~name kind = let ops = { descr = descr; @@ -322,6 +332,7 @@ copy = copy; commit = commit; update = update; + on_update = on_update; clean = clean; serialize = serialize; unserialize = unserialize } diff -Nru frama-c-20110201+carbon+dfsg/src/project/state.mli frama-c-20111001+nitrogen+dfsg/src/project/state.mli --- frama-c-20110201+carbon+dfsg/src/project/state.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state.mli 2011-10-10 08:38:25.000000000 +0000 @@ -20,7 +20,7 @@ (* *) (**************************************************************************) -(** A state is a meta-representation of a project-compliant mutable value. +(** A state is a project-compliant mutable value. @since Carbon-20101201 *) open Project_skeleton @@ -33,7 +33,7 @@ [ | `Correctness (** The state has an impact on the correctness of a result. *) | `Internal (** The state is for internal purpose only: - it is hidden to the external user. *) + it is hidden to the external user. *) ] (** Type of state kinds. @@ -42,11 +42,11 @@ [ | standard_kind | `Tuning (** The state has an impact on a result, - but it does not change its correctness. - For instance, it just improves the preciseness. *) + but it does not change its correctness. + For instance, it just improves the preciseness. *) | `Irrelevant (** The state has no impact on any result. - If any analyser is run, then its result is not modified by - setting this state. *) + If any analyser is run, then its result is not modified by + setting this state. *) ] type kind = @@ -68,22 +68,22 @@ val create: unit -> t (** How to create a new fresh state which must be equal to the initial - state: that is, if you never change the state, [create ()] and [get - ()] must be equal (see invariant 1 below). *) + state: that is, if you never change the state, [create ()] and [get + ()] must be equal (see invariant 1 below). *) val clear: t -> unit (** How to clear a state. After clearing, the state should be - observationaly the same that after its creation (see invariant 2 - below). - @plugin development guide *) + observationaly the same that after its creation (see invariant 2 + below). + @plugin development guide *) val get: unit -> t (** How to access to the current state. Be aware of invariants 3 and 4 - below. *) + below. *) val set: t -> unit (** How to change the current state. Be aware of invariants 3 and 4 - below. *) + below. *) (** The four following invariants must hold. {ol @@ -119,6 +119,10 @@ (** Unique name of a state. @since Carbon-20101201 *) +val unique_name_from_name: string -> string +(** @return a fresh unique state name from the given name. + @since Nitrogen-20111001 *) + val kind: t -> kind (** Kind of a state. @since Carbon-20101201 *) @@ -142,6 +146,11 @@ val get_descr: t -> Structural_descr.pack (** @since Carbon-20101201 *) +val add_hook_on_update: t -> (unit -> unit) -> unit +(** Add an hook which is applied each time the project library changes the local + value of the state. + @since Nitrogen-20111001 *) + (* ************************************************************************** *) (** {2 Clusters} *) (* ************************************************************************** *) @@ -168,19 +177,19 @@ val name: t -> string option (** [cluster_name s] returns the name of cluster of [s], if any. - @since Carbon-20101201 *) - + @since Carbon-20101201 *) + (** {2 Internal Stuff} *) val unmarshal: string option -> t -> unit (** How to unmarshal a cluster stored in a state, previously marshaled with - its name. - @since Carbon-20101201 *) + its name. + @since Carbon-20101201 *) val after_load: unit -> unit (** Must be called after each project loading. - Exported for breaking mutual dependencies with [Project]. - @since Carbon-20101201 *) + Exported for breaking mutual dependencies with [Project]. + @since Carbon-20101201 *) end @@ -207,6 +216,7 @@ copy: project -> project -> unit; commit: project -> unit; update: project -> unit; + on_update: (unit -> unit) -> unit; clean: unit -> unit; serialize: project -> state_on_disk; unserialize: project -> state_on_disk -> unit } @@ -251,6 +261,7 @@ copy:(project -> project -> unit) -> commit:(project -> unit) -> update:(project -> unit) -> + on_update:((unit -> unit) -> unit) -> clean:(unit -> unit) -> serialize:(project -> state_on_disk) -> unserialize:(project -> state_on_disk -> unit) -> @@ -258,7 +269,8 @@ name:string -> kind -> t -(** @since Carbon-20101201 *) +(** @since Carbon-20101201 + @modify Nitrogen-20111001 add the [on_update] argument *) (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_selection.ml frama-c-20111001+nitrogen+dfsg/src/project/state_selection.ml --- frama-c-20110201+carbon+dfsg/src/project/state_selection.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_selection.ml 2011-10-10 08:38:25.000000000 +0000 @@ -33,6 +33,9 @@ let is_empty s = s = Subset Selection.empty let is_full s = s = Full +let mem sel s = match sel with + | Full -> true + | Subset sel -> Selection.mem_vertex sel s include Datatype.Make (struct @@ -46,20 +49,20 @@ match Selection.fold_vertex (fun s acc -> s :: acc) sel [] with | [] -> Format.fprintf fmt "@[State_selection.empty@]" | [ s ] -> - let pp fmt = - Format.fprintf fmt "@[<hv 2>State_selection.singleton@;%a@]" - (State.internal_pretty_code Type.Call) - s - in - Type.par p_caller Type.Call fmt pp + let pp fmt = + Format.fprintf fmt "@[<hv 2>State_selection.singleton@;%a@]" + (State.internal_pretty_code Type.Call) + s + in + Type.par p_caller Type.Call fmt pp | l -> - let module D = Datatype.List(State) in - let pp fmt = - Format.fprintf fmt "@[<hv 2>State_selection.of_list@;%a@]" - (D.internal_pretty_code Type.Call) - l - in - Type.par p_caller Type.Call fmt pp + let module D = Datatype.List(State) in + let pp fmt = + Format.fprintf fmt "@[<hv 2>State_selection.of_list@;%a@]" + (D.internal_pretty_code Type.Call) + l + in + Type.par p_caller Type.Call fmt pp end) module type S = sig @@ -85,11 +88,11 @@ let transitive_closure next_vertices s = let rec visit acc v = next_vertices - (fun v' acc -> - let e = v, v' in - if Selection.mem_edge_e acc e then acc - else visit (Selection.add_edge_e acc e) v') - G.graph v acc + (fun v' acc -> + let e = v, v' in + if Selection.mem_edge_e acc e then acc + else visit (Selection.add_edge_e acc e) v') + G.graph v acc in (* add [s] in the selection even if it has no ingoing/outgoing edges *) visit (Selection.add_vertex Selection.empty s) s @@ -115,19 +118,19 @@ (fun v acc -> if Selection.mem_vertex sel2 v then acc else Selection.add_vertex acc v) - G.graph + G.graph Selection.empty in - G.G.fold_edges - (fun v1 v2 acc -> - if Selection.mem_vertex sel2 v1 || Selection.mem_vertex sel2 v2 - then acc - else Selection.add_edge acc v1 v2) - G.graph - selection + G.G.fold_edges + (fun v1 v2 acc -> + if Selection.mem_vertex sel2 v1 || Selection.mem_vertex sel2 v2 + then acc + else Selection.add_edge acc v1 v2) + G.graph + selection | Subset sel1, Subset sel2 -> - Selection.fold_vertex - (fun v acc -> Selection.remove_vertex acc v) sel2 sel1) + Selection.fold_vertex + (fun v acc -> Selection.remove_vertex acc v) sel2 sel1) let union = let module O = Graph.Oper.P(Selection) in @@ -170,14 +173,14 @@ Format.fprintf fmt "contents of the selection:@\n"; let mem s = State_dependency_graph.Static.G.mem_vertex - State_dependency_graph.Static.graph - s + State_dependency_graph.Static.graph + s in iter_in_order (fun s -> - Format.fprintf fmt "\t state %S%s@\n" - (State.get_unique_name s) - (if mem s then "" else "(\"" ^ State.get_name s ^ "\")")) + Format.fprintf fmt "\t state %S%s@\n" + (State.get_unique_name s) + (if mem s then "" else "(\"" ^ State.get_name s ^ "\")")) sel; Format.pp_print_flush fmt () @@ -185,7 +188,7 @@ | Full -> assert false | Subset sel -> let module R = - State_dependency_graph.Remove_useless_states(Selection)(State) + State_dependency_graph.Remove_useless_states(Selection)(State) in Subset (R.get sel) @@ -204,9 +207,9 @@ match s with | Full -> DG.dump filename | Subset s -> - let cout = open_out filename in - DS.output_graph cout s; - close_out cout + let cout = open_out filename in + DS.output_graph cout s; + close_out cout end include Dot(State_dependency_graph.Dynamic.Attributes) diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_selection.mli frama-c-20111001+nitrogen+dfsg/src/project/state_selection.mli --- frama-c-20110201+carbon+dfsg/src/project/state_selection.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_selection.mli 2011-10-10 08:38:25.000000000 +0000 @@ -68,6 +68,8 @@ (** @return [true] iff the selection contains all the states. @since Carbon-20101201 *) +val mem: t -> State.t -> bool + (* ************************************************************************** *) (** {2 Specific selections} *) (* ************************************************************************** *) diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_topological.ml frama-c-20111001+nitrogen+dfsg/src/project/state_topological.ml --- frama-c-20110201+carbon+dfsg/src/project/state_topological.ml 2011-02-07 13:53:52.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_topological.ml 2011-10-10 08:38:25.000000000 +0000 @@ -46,38 +46,38 @@ let rec walk acc = if Queue.is_empty todo then (* let's find any node of minimal degree *) - let min = - H.fold - (fun v d acc -> - match acc with - | None -> Some (v, d) - | Some(_, min) -> if d < min then Some (v, d) else acc) - degree - None - in - match min with - | None -> acc - | Some(v, _) -> push v; walk acc + let min = + H.fold + (fun v d acc -> + match acc with + | None -> Some (v, d) + | Some(_, min) -> if d < min then Some (v, d) else acc) + degree + None + in + match min with + | None -> acc + | Some(v, _) -> push v; walk acc else - let v = Queue.pop todo in - let acc = f v acc in - G.iter_succ - (fun x-> + let v = Queue.pop todo in + let acc = f v acc in + G.iter_succ + (fun x-> try let d = H.find degree x in - if d = 1 then push x else H.replace degree x (d-1) + if d = 1 then push x else H.replace degree x (d-1) with Not_found -> - (* [x] already visited *) - ()) - g v; - do_cluster v; - walk acc + (* [x] already visited *) + ()) + g v; + do_cluster v; + walk acc in G.iter_vertex (fun v -> - let d = G.in_degree g v in - if d = 0 then Queue.push v todo - else H.add degree v d) + let d = G.in_degree g v in + if d = 0 then Queue.push v todo + else H.add degree v d) g; let acc = walk acc in H.fold (fun v () acc -> f v acc) in_cluster acc diff -Nru frama-c-20110201+carbon+dfsg/src/project/state_topological.mli frama-c-20111001+nitrogen+dfsg/src/project/state_topological.mli --- frama-c-20110201+carbon+dfsg/src/project/state_topological.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/project/state_topological.mli 2011-10-10 08:38:25.000000000 +0000 @@ -20,7 +20,7 @@ (* *) (**************************************************************************) -(** Topological order. +(** Topological ordering over states. This functor provides functions which allow iterating over a <b>state</b> graph in topological order. diff -Nru frama-c-20110201+carbon+dfsg/src/report/configure frama-c-20111001+nitrogen+dfsg/src/report/configure --- frama-c-20110201+carbon+dfsg/src/report/configure 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/configure 2011-10-10 08:56:39.000000000 +0000 @@ -0,0 +1,3271 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.65. +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="Makefile.in" +ac_subst_vars='LTLIBOBJS +LIBOBJS +DYNAMIC_REPORT +ENABLE_REPORT +ENABLE_GUI +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_report +with_report_static +' + ac_precious_vars='build_alias +host_alias +target_alias' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-report support for report plug-in (default: yes) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-report-static link report statically (default: no) + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.65 + +Copyright (C) 2009 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.65. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + KNOWN_PLUGINS=$(frama-c -help | \ + sed -e '0,/^\*\*\*\*\*/ d' \ + -e 's/\([^ ][^ ]*\( [^ ][^ ]*\)*\) .*/\1/' \ + -e '/^ /d' -e '/^$/d' | \ + tr "a-z- " "A-Z__") + for plugin in ${KNOWN_PLUGINS}; do + export $(echo ENABLE_$plugin)=yes + done + # Extract the first word of "frama-c-gui", so it can be a program name with args. +set dummy frama-c-gui; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ENABLE_GUI+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ENABLE_GUI"; then + ac_cv_prog_ENABLE_GUI="$ENABLE_GUI" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ENABLE_GUI="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ENABLE_GUI" && ac_cv_prog_ENABLE_GUI="no" +fi +fi +ENABLE_GUI=$ac_cv_prog_ENABLE_GUI +if test -n "$ENABLE_GUI"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_GUI" >&5 +$as_echo "$ENABLE_GUI" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +upper() { + echo "$1" | tr "a-z-" "A-Z_" +} + +lower() { + echo "$1" | tr "A-Z" "a-z" +} + + + +new_section() { + banner=`echo "* $1 *" | sed -e 's/./*/g'` + title=`echo "* $1 *" | tr "a-z" "A-Z"` + { $as_echo "$as_me:${as_lineno-$LINENO}: $banner" >&5 +$as_echo "$as_me: $banner" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: $title" >&5 +$as_echo "$as_me: $title" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: $banner" >&5 +$as_echo "$as_me: $banner" >&6;} +} + + + +# sadly, there's no way to define a new diversion beside the internal ones. +# hoping for the best here... + + + + +# to distinguish internal plugins, known by the main configure, from +# purely external plugins living in src/ and compiled together with the main +# frama-c + + + + # end of check_plugin + +# 1st param: uppercase name of the library +# 2nd param: file which must exist. This parameter can be a list of files. +# In this case, they will be tried in turn until one of them exists. The +# name of the file found will be put in the variable SELECTED_$1 +# 3d param: warning to display if problem +# 4th param: yes iff checking the library must always to be done +# (even if there is no plug-in using it) + + +# 1st param: uppercase name of the program +# 2nd param: program which must exist. See comment on configure_library() +# on how to deal with multiple choices for a given program. +# 3d param: warning to display if problem +# 4th param: yes iff checking the tool must always to be done +# (even if there is no plug-in using it) + + +EXTERNAL_PLUGINS= + + + + + + + + +# Implementation of an ordering $1 < $2: "" < yes < partial < no +lt_mark () { + first=`echo "$1" | sed -e 's/ .*//' ` + second=`echo "$2" | sed -e 's/ .*//' ` + case $first in + "") echo "true";; + "yes"*) + case $second in + "yes") echo "";; + "partial" | "no") echo "true";; + esac;; + "partial"*) + case $second in + "yes" | "partial") echo "";; + "no") echo "true";; + esac;; + "no"*) echo "";; + esac +} + +# Check and propagate marks to requires and users. +# $1: parent plugin +# $2: mark to propagate to requires +# $3: mark to propagate to users +check_and_propagate () { + # for each requiers + r=REQUIRE_$1 + eval require="\$$r" + for p in $require; do + up=`upper "$p"` + m=MARK_"$up" + eval mark="\$$m" + if test -z "$mark"; then + m=ENABLE_"$up" + eval mark="\$$m" + fi + if test `lt_mark "$mark" "$2" `; then + # update marks + eval MARK_$up=\"$2\"; + TODOLIST=$TODOLIST" "$p + # display a warning or an error if required + short_mark=`echo $2 | sed -e 's/ .*//'` + lp=`lower $p` + reason=`echo $2 | sed -e 's/no (\(.*\))/\1/' ` + if test "$short_mark" = "no"; then + fp=FORCE_"$up" + if eval test "\$$fp" = "yes"; then + as_fn_error "$lp requested but $reason." "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $lp disabled because $reason." >&2;} + fi + else + if test "$short_mark" = "partial"; then + reason=`echo $2 | sed -e 's/partial (\(.*\))/\1/' ` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp only partially enable because $reason." >&5 +$as_echo "$as_me: WARNING: $lp only partially enable because $reason." >&2;} + fi + fi + eval INFO_$up=\", $reason\" + fi + done + # for each users + u=USE_$1 + eval use="\$$u" + for p in $use; do + up=`upper "$p"` + m=MARK_$up + eval mark="\$$m" + if test -z "$mark"; then + m=ENABLE_"$up" + eval mark="\$$m" + fi + if test `lt_mark "$mark" "$3" `; then + # update marks + eval MARK_$up=\"$3\"; + TODOLIST=$TODOLIST" "$p + # display a warning if required + lp=`lower $p` + reason=`echo $3 | sed -e 's/partial (\(.*\))/\1/' ` + if test "$reason" != "$3"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp only partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $lp only partially enabled because $reason." >&2;} + fi + eval INFO_$up=\", $reason\" + fi + done +} + +# checks direct dependencies of a plugin. Useful for dynamic plugins which +# have a dependency toward already installed (or not) plug-ins, since the old +# plugins are not in the TODO list from the beginning (and need not their +# mutual dependencies be rechecked anyway +check_required_used () { + ep=ENABLE_$1 + eval enabled=\$$ep + + if test "$enabled" != "no"; then + + r=REQUIRED_$1 + u=USED_$1 + m=MARK_$1 + eval required=\$$r + eval used=\$$u + eval $m=yes + + reason= + + for p in $required; do + up=`upper $p` + ec=ENABLE_$up + eval enabled=\$$ec + case `echo "$enabled" | sed -e 's/ .*//'` in + "") reason="$p unknown";; + "yes" | "partial");; + "no") reason="$p not enabled";; + esac + done + if test -n "$reason"; then + eval $m=\"no\ \($reason\)\" + p_name=`lower $1` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p_name disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p_name disabled because $reason." >&2;} + eval INFO_$1=\", $reason\" + else + for p in $used; do + up=`upper $p` + ec=ENABLE_$up + eval enabled=\$$ec + case `echo "$enabled" | sed -e 's/ .*//'` in + "") reason="$p unknown";; + "yes" | "partial");; + "no") reason="$p not enabled";; + esac + done + if test -n "$reason"; then + eval $m=\"partial\ \($reason\)\" + p_name=`lower $1` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p_name partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p_name partially enabled because $reason." >&2;} + eval INFO_$1=\", $reason\" + fi + fi + + else # $enabled = "no" + eval $m=\"no\" + fi +} + +# Recursively check the plug-in dependencies using the plug-in dependency graph +compute_dependency () { + plugin=`echo $TODOLIST | sed -e 's/ .*//' ` + TODOLIST=`echo $TODOLIST | sed -e 's/[^ ]* *\(.*\)/\1/' ` + + lplugin=`lower "$plugin"` + uplugin=`upper "$plugin"` + # new mark to consider + m=MARK_$uplugin + eval mark="\$$m" + # old mark to consider + r=REMEMBER_$uplugin + eval remember="\$$r" + # the exact mark (final result), + # also the old mark if plugin already visited + e=ENABLE_$uplugin + eval enable="\$$e" + #first visit. Performs additional checks over requirements. + if test -z "$mark"; then + check_required_used "$uplugin"; + eval mark=\$$m + fi + +# echo "plug-in $lplugin (mark=$mark, remember=$remember, enable=$enable)" + if test `lt_mark "$remember" "$mark"`; then + # visit the current plugin: + # mark <- max(mark, enable) + case `echo "$mark" | sed -e 's/ .*//' ` in + "") echo "problem?"; exit 3;; + "yes") + if test -n "$enable"; then mark="$enable"; else mark="yes"; fi;; + "partial") if test "$enable" = "no"; then mark="no"; fi;; + "no") ;; + esac + # update plug-in attributes with the new mark +# echo "update attributes with $mark" + eval $m=\"$mark\" + eval $e=\"`echo "$mark" | sed -e 's/ .*//' `\" + enable="$mark" + eval $r=\"$mark\" + # compute and propagate a new mark to requires and users + case `echo "$enable" | sed -e 's/ .*//' ` in + "") echo "problem?"; exit 3;; + "yes") check_and_propagate $uplugin "yes" "yes";; + "partial") +# if a plug-in is partial, does not consider its dependencies as partial +# so the second argument is "yes" and not "partial" + check_and_propagate \ + "$uplugin" \ + "yes" \ + "yes";; + "no") + check_and_propagate \ + "$uplugin" \ + "no ($lplugin not enabled)" \ + "partial ($lplugin not enabled)";; + esac + fi + # recursively consider the next plugins + if test -n "$TODOLIST"; then + compute_dependency; + fi +} + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Makefile.in" >&5 +$as_echo_n "checking for Makefile.in... " >&6; } +if test "${ac_cv_file_Makefile_in+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "Makefile.in"; then + ac_cv_file_Makefile_in=yes +else + ac_cv_file_Makefile_in=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_Makefile_in" >&5 +$as_echo "$ac_cv_file_Makefile_in" >&6; } +if test "x$ac_cv_file_Makefile_in" = x""yes; then : + default=yes;plugin_present=yes +else + plugin_present=no;default=no +fi + + +FORCE=no + +# Check whether --enable-report was given. +if test "${enable_report+set}" = set; then : + enableval=$enable_report; ENABLE=$enableval;FORCE=$enableval +else + ENABLE=$default + +fi + + +if test "$ONLY_KERNEL" = "yes" -a "$FORCE" = "no"; then + ENABLE=no +fi + + + +# Test to change for static plugin, dynamic option +#default_dyn=no +#define([PLUGIN_HELP_DYN], +# AC_HELP_STRING([--enable-PLUGIN_NAME-dynamic], +# [PLUGIN_MSG (default: static)]) +#define([PLUGIN_NAME_DYN],[PLUGIN_NAME]-dynamic) +#AC_ARG_ENABLE( +# [PLUGIN_NAME_DYN], +# PLUGIN_HELP_DYN, +# ENABLE=$enableval; +# FORCE=$enableval +# ENABLE=$default_dyn +#) +#eval ENABLE_DYNAMIC_$up=\$ENABLE + +if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then + as_fn_error "report is not available" "$LINENO" 5 +fi + +FORCE_REPORT=$FORCE +PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_REPORT + +ENABLE_REPORT=$ENABLE +NAME_REPORT=report +if test "$default" = "no" -a "$FORCE" = "no"; then + INFO_REPORT=" (not available by default)" +fi + +# Dynamic plug-ins configuration + + +# Check whether --with-report-static was given. +if test "${with_report_static+set}" = set; then : + withval=$with_report_static; is_static=$withval +else + is_static=$IS_ALL_STATIC +fi + + + # is_static = "yes" iff the user forces the plug-in to be static + # is_static = "no" iff the user forces the plug-in to be dynamic + # is_static = "" in others cases (no special instruction) + STATIC_REPORT=$is_static + if test "$is_static" != "yes"; then + USE_NATIVE_DYNLINK="${USE_NATIVE_DYNLINK} report" + DYNAMIC_REPORT=yes + else + DYNAMIC_REPORT=no + fi + + + +echo "report... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) + + + + + + + + +####################### +# Generating Makefile # +####################### + + + + + ac_config_files="$ac_config_files ./Makefile" + + + + +# Compute INFO_* and exported ENABLE_* from previously computed ENABLE_* + for fp in ${PLUGINS_FORCE_LIST}; do + if test "$fp" != "FORCE_GTKSOURCEVIEW"; then + plugin=`echo $fp | sed -e "s/FORCE_\(.*\)/\1/" ` + ep=ENABLE_$plugin + eval v=\$$ep + eval ep_v=`echo $v | sed -e 's/ .*//' ` + eval ENABLE_$plugin=$ep_v + reason=`echo $v | sed -e 's/[a-z]*\( .*\)/\1/' ` + n=NAME_$plugin + eval name=\$$n + info= + if test "$reason" != "$ep_v"; then + info=$reason + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: $name: $ep_v$info" >&5 +$as_echo "$as_me: $name: $ep_v$info" >&6;} + fi + done + cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.65. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.65, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2009 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "./Makefile") CONFIG_FILES="$CONFIG_FILES ./Makefile" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + + + case $ac_file$ac_mode in + "./Makefile":F) chmod -w ./Makefile ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit $? +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + + diff -Nru frama-c-20110201+carbon+dfsg/src/report/configure.ac frama-c-20111001+nitrogen+dfsg/src/report/configure.ac --- frama-c-20110201+carbon+dfsg/src/report/configure.ac 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/configure.ac 2011-10-10 08:38:25.000000000 +0000 @@ -0,0 +1,45 @@ +########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2011 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +######################################## +# E-ACSL as a standard Frama-C plug-in # +######################################## + +m4_define([plugin_file],Makefile.in) + +m4_define([FRAMAC_SHARE_ENV], + [m4_normalize(m4_esyscmd([echo $FRAMAC_SHARE]))]) + +m4_define([FRAMAC_SHARE], + [m4_ifval(FRAMAC_SHARE_ENV,[FRAMAC_SHARE_ENV], + [m4_esyscmd(frama-c -print-path)])]) + +m4_ifndef([FRAMAC_M4_MACROS], [m4_include(FRAMAC_SHARE/configure.ac)]) + +check_plugin(report,PLUGIN_RELATIVE_PATH(plugin_file), + [support for report plug-in],yes,yes) + +####################### +# Generating Makefile # +####################### + +write_plugin_config(Makefile) diff -Nru frama-c-20110201+carbon+dfsg/src/report/dump.ml frama-c-20111001+nitrogen+dfsg/src/report/dump.ml --- frama-c-20110201+carbon+dfsg/src/report/dump.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/dump.ml 2011-10-10 08:38:25.000000000 +0000 @@ -0,0 +1,187 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Dump Report on Output --- *) +(* -------------------------------------------------------------------------- *) + +open Property_status +open Scan + +let bar = String.make 80 '-' +let dim = 9 (* Size for status [----] *) +let tab = String.make (dim+3) ' ' + +let pp_status fmt s = + let n = String.length s in + if n < dim then + let m = String.make dim ' ' in + let p = (dim - n) / 2 in + String.blit s 0 m p n ; + Format.fprintf fmt "[%s]" m + else Format.fprintf fmt "[%s]" s + +open Consolidation +module E = Emitter.Usable_emitter + +class dumper out = +object(self) + + val mutable st_unknown = 0 ; (* no status *) + val mutable st_partial = 0 ; (* locally valid but missing hyp *) + val mutable st_extern = 0 ; (* considered valid *) + val mutable st_complete = 0 ; (* valid and complete *) + val mutable st_bug = 0 ; (* invalid and complete *) + val mutable st_alarm = 0 ; (* invalid but missing hyp *) + val mutable st_dead = 0 ; (* under invalid hyp *) + val mutable st_inconsistent = 0 ; (* unsound *) + val mutable kf : Description.kf = `Always + + method started = () + + method global_section = + Format.fprintf out "%s@\n--- Global Properties@\n%s@\n@." bar bar + + method function_section thekf = + Format.fprintf out "@\n%s@\n--- Properties of Function '%s'@\n%s@\n@." + bar (Kernel_function.get_name thekf) bar ; + kf <- `Context thekf + + method category = function + | Never_tried | Unknown _ -> st_unknown <- succ st_unknown ; "-" + | Considered_valid -> st_extern <- succ st_extern ; "Extern" + | Valid _ -> st_complete <- succ st_complete ; "Valid" + | Invalid _ -> st_bug <- succ st_bug ; "Bug" + | Valid_under_hyp _ -> st_partial <- succ st_partial ; "Partial" + | Invalid_under_hyp _ -> st_alarm <- succ st_alarm ; "Alarm" + | Valid_but_dead _ | Invalid_but_dead _ | Unknown_but_dead _ -> + st_dead <- succ st_dead ; "Dead" + | Inconsistent _ -> st_inconsistent <- succ st_inconsistent ; "Unsound" + + method emitter e = Format.fprintf out "%s@[<hov 2>by %a.@]@\n" tab E.pretty e + + method emitters es = E.Set.iter self#emitter es + + method tried_emitters ps = + let es = E.Map.fold (fun e _ es -> e::es) ps [] in + match es with + | [] -> () + | e::es -> + Format.fprintf out "%s@[<hov 2>tried with %a" tab E.pretty e ; + List.iter (fun e -> Format.fprintf out ",@ %a" E.pretty e) es ; + Format.fprintf out ".@]@\n" + + method dead_reasons ps = + E.Map.iter + (fun e ps -> + Format.fprintf out "%s@[<hov 2>By %a because:@]@\n" tab E.pretty e ; + Property.Set.iter + (fun p -> Format.fprintf out "%s@[<hov 3> - %a@]@\n" tab + (Description.pp_localized ~kf ~ki:true) p) ps + ) (Scan.partial_pending ps) + + method partial_pending ps = + E.Map.iter + (fun e ps -> + Format.fprintf out "%s@[<hov 2>By %a, with pending:@]@\n" tab E.pretty e ; + Property.Set.iter + (fun p -> Format.fprintf out "%s@[<hov 3> - %a@]@\n" tab + (Description.pp_localized ~kf ~ki:true) p) ps + ) (Scan.partial_pending ps) + + method property ip st = + begin + Format.fprintf out "%a @[%a@]@\n" pp_status (self#category st) + (Description.pp_localized ~kf:`Never ~ki:true) ip ; + match st with + | Never_tried -> () + | Unknown emitters -> self#tried_emitters emitters + | Valid emitters -> self#emitters emitters + | Invalid emitters -> self#emitters emitters + | Invalid_but_dead pending -> + Format.fprintf out "%sLocally invalid, but unreachable.@\n" tab ; + self#dead_reasons pending + | Valid_but_dead pending -> + Format.fprintf out "%sLocally valid, but unreachable.@\n" tab ; + self#dead_reasons pending + | Unknown_but_dead pending -> + Format.fprintf out "%sLocally unknown, but unreachable.@\n"tab ; + self#dead_reasons pending + | Invalid_under_hyp pending | Valid_under_hyp pending -> + self#partial_pending pending + | Considered_valid -> + Format.fprintf out "%sUnverifiable but considered Valid.@\n" tab + | Inconsistent s -> + let p = ref 0 in + let n = String.length s in + while !p < n do + try + let k = String.index_from s !p '\n' in + Format.fprintf out "%s%s@\n" tab (String.sub s !p (k - !p)) ; + p := succ k ; + with Not_found -> + Format.fprintf out "%s%s@\n" tab (String.sub s !p (n - !p)) ; + p := n ; + done + + end + + method finished = + Format.fprintf out "@\n%s@\n--- Status Report Summary@\n%s@\n" bar bar ; + if st_complete > 0 then + Format.fprintf out " %4d Completely validated@\n" st_complete ; + if st_partial > 0 then + Format.fprintf out " %4d Locally validated@\n" st_partial ; + if st_extern > 0 then + Format.fprintf out " %4d Considered valid@\n" st_extern ; + if st_unknown > 0 then + Format.fprintf out " %4d To be validated@\n" st_unknown ; + if st_alarm > 0 then + Format.fprintf out " %4d Alarms emitted@\n" st_alarm ; + if st_bug > 0 then + Format.fprintf out " %4d Bugs found@\n" st_bug ; + if st_dead > 1 then + Format.fprintf out " %4d Dead properties@\n" st_dead ; + if st_dead = 1 then + Format.fprintf out " 1 Dead property@\n" ; + if st_inconsistent > 1 + then Format.fprintf out " %4d Inconsistencies@\n" st_inconsistent ; + if st_inconsistent = 1 + then Format.fprintf out " 1 Inconsistency@\n" ; + let total = + st_complete + st_partial + st_extern + st_unknown + st_alarm + st_bug + + st_dead + st_inconsistent + in + Format.fprintf out " %5d Total@\n%s@." total bar ; + + method empty = + Format.fprintf out "%s@\n--- No status to report@\n%s@." bar bar ; + +end + +let create out = (new dumper out :> Scan.inspector) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/report/dump.mli frama-c-20111001+nitrogen+dfsg/src/report/dump.mli --- frama-c-20110201+carbon+dfsg/src/report/dump.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/dump.mli 2011-10-10 08:38:25.000000000 +0000 @@ -0,0 +1,23 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val create : Format.formatter -> Scan.inspector diff -Nru frama-c-20110201+carbon+dfsg/src/report/Makefile.in frama-c-20111001+nitrogen+dfsg/src/report/Makefile.in --- frama-c-20110201+carbon+dfsg/src/report/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/Makefile.in 2011-10-10 08:38:25.000000000 +0000 @@ -0,0 +1,66 @@ +########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2011 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +# Do not use ?= to initialize both below variables +# (fixed efficiency issue, see GNU Make manual, Section 8.11) +ifndef FRAMAC_SHARE +FRAMAC_SHARE :=$(shell frama-c -journal-disable -print-path) +endif +ifndef FRAMAC_LIBDIR +FRAMAC_LIBDIR :=$(shell frama-c -journal-disable -print-libpath) +endif + +################### +# Plug-in Setting # +################### + +PLUGIN_DIR ?=. +PLUGIN_ENABLE:=@ENABLE_REPORT@ +PLUGIN_DYNAMIC:=@DYNAMIC_REPORT@ +PLUGIN_NAME:=Report +PLUGIN_CMO:= scan dump register +PLUGIN_HAS_MLI:=yes +PLUGIN_DISTRIBUTED:=$(PLUGIN_ENABLE) +PLUGIN_DISTRIB_EXTERNAL:= Makefile.in configure.ac configure +#PLUGIN_DISTRIB_BIN:=no +#PLUGIN_NO_DEFAULT_TEST:=no +PLUGIN_TESTS_DIRS:=report + +################ +# Generic part # +################ + +include $(FRAMAC_SHARE)/Makefile.dynamic + +##################################### +# Regenerating the Makefile on need # +##################################### + +ifeq ("$(FRAMAC_INTERNAL)","yes") +CONFIG_STATUS_DIR=$(FRAMAC_SRC) +else +CONFIG_STATUS_DIR=. +endif + +$(Report_DIR)/Makefile: $(Report_DIR)/Makefile.in \ + $(CONFIG_STATUS_DIR)/config.status + cd $(CONFIG_STATUS_DIR) && ./config.status diff -Nru frama-c-20110201+carbon+dfsg/src/report/register.ml frama-c-20111001+nitrogen+dfsg/src/report/register.ml --- frama-c-20110201+carbon+dfsg/src/report/register.ml 2011-02-07 13:53:57.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/register.ml 2011-10-10 08:38:25.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,72 +15,12 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) -(* -------------------------------------------------------------------------- *) -(* --- Computes a TODO-list for properties --- *) -(* -------------------------------------------------------------------------- *) - -open Cil_types -open Properties_status - -type proof = { - p_emitter : string ; - p_pending : Property.t list ; (* not yet complete *) -} - -(* -------------------------------------------------------------------------- *) -(* --- Utilities --- *) -(* -------------------------------------------------------------------------- *) - -let compare_proof p1 p2 = - let n1 = List.length p1.p_pending in - let n2 = List.length p2.p_pending in - let c = Datatype.Int.compare n1 n2 in - if c<>0 then c else String.compare p1.p_emitter p2.p_emitter - -(* -------------------------------------------------------------------------- *) -(* --- Consolidation calculus with Memoization --- *) -(* -------------------------------------------------------------------------- *) - -module Hip = Property.Hashtbl - -let rec get_proofs hmap ip : proof list = - try Hip.find hmap ip - with Not_found -> - Hip.add hmap ip [] ; - (* Force dependencies to be computed *) - ignore (Properties_status.strongest ip) ; - (* Now report *) - let ctree = Consolidation_tree.get ip in - let proofs = - List.fold_left - (fun ps s -> - match s.Consolidation_tree.value with - | Checked {valid=True;emitter=e} , _ -> - let hs = - List.filter - (fun s -> not (is_complete hmap s)) - s.Consolidation_tree.hypothesis - in - let hips = - List.sort - Property.compare - (List.map (fun h -> h.Consolidation_tree.property) hs) - in - { p_emitter=e ; p_pending=hips } :: ps - | _ -> ps - ) [] ctree.Consolidation_tree.status in - let ordered = List.sort compare_proof proofs in - Hip.replace hmap ip ordered ; ordered - -and is_complete hmap (s : Consolidation_tree.t) = - List.exists - (fun p -> p.p_pending=[]) - (get_proofs hmap s.Consolidation_tree.property) +open Property_status (* -------------------------------------------------------------------------- *) (* --- Plug-in Implementation --- *) @@ -97,145 +35,27 @@ module Enabled = Self.Action(struct - let option_name = "-report" - let help = "display a summary of properties status" - let kind = `Tuning - end) - -module Emitter = - Self.False(struct - let option_name = "-report-emitter" - let help = "display the list of emitters for available proofs" - let kind = `Tuning - end) - -module Pending = - Self.False(struct - let option_name = "-report-pending" - let help = "display the list of pending properties for partial proofs" - let kind = `Tuning - end) - -module OnlyValid = - Self.False(struct - let option_name = "-report-valid" - let help = "only report on validated properties" - let kind = `Tuning - end) - -let txt_unknown = " Unknown " -let txt_valid = " Valid " -let txt_partial = " Partial " -let bar = String.make 60 '-' + let option_name = "-report" + let help = "display a summary of properties status" + let kind = `Tuning + end) -let report ~partials ~completes ~untried hmap fmt title ips = - if ips <> [] then - begin - Format.fprintf fmt "%s@\n %s@\n%s@\n@\n" - bar title bar ; - let ips = List.sort Property.compare ips in - List.iter - (fun ip -> - let proofs = get_proofs hmap ip in - let status = - if proofs = [] then - ( incr untried ; txt_unknown ) - else - if List.exists (fun p -> p.p_pending=[]) proofs - then ( incr completes ; txt_valid ) - else ( incr partials ; txt_partial ) - in - let pkf = Property.get_kf ip in - (match pkf with - | None -> - Format.fprintf fmt "[%s] Global @[%a@]@\n" - status Property.pretty ip - | Some kf -> - Format.fprintf fmt "[%s] Function '%s' @[%a@]@\n" - status (Kernel_function.get_name kf) Property.pretty ip); - if Pending.get () || Emitter.get () then - List.iter - (fun p -> - begin - match Emitter.get () , Pending.get () , p.p_pending with - | _ , _ , [] -> - Format.fprintf fmt " Emitter %s [complete]@\n" - p.p_emitter - | true , false , hs -> - Format.fprintf fmt " Emitter %s [%d pending]@\n" - p.p_emitter (List.length hs) ; - | _ , true , _ -> - Format.fprintf fmt " Emitter %s:@\n" - p.p_emitter - | false , false , _ -> assert false (* englobing 'if' *) - end ; - if Pending.get () then - List.iter - (fun h -> - match Property.get_kf h , pkf with - | Some hkf, Some kf when Kernel_function.equal hkf kf -> - Format.fprintf fmt " - @[pending %a@]@\n" - Property.pretty h - | Some hkf , _ -> - Format.fprintf fmt " - @[pending %a@ from function '%s'@]@\n" - Property.pretty h (Kernel_function.get_name hkf) - | None , _ -> - Format.fprintf fmt " - @[pending global %a@]@\n" - Property.pretty h) - p.p_pending ; - Format.pp_print_flush fmt () - ) proofs - ) ips ; - Format.pp_print_newline fmt () ; - end +let bar = String.make 60 '-' -let print () = - begin - let hmap = Hip.create 131 in - let forest = Consolidation_tree.get_all () in - let globals = ref [] in - let reports = ref Kernel_function.Map.empty in - Self.feedback "Computing properties status..." ; - List.iter - (fun t -> - let ip = t.Consolidation_tree.property in - let proofs = get_proofs hmap ip in - if (if OnlyValid.get () then proofs <> [] else true) then - match Property.get_kf ip with - | None -> globals := ip :: !globals - | Some kf -> - let ipfs = - try Kernel_function.Map.find kf !reports with Not_found -> [] - in - reports := Kernel_function.Map.add kf (ip::ipfs) !reports) - forest; - Log.print_on_output "%t" - (fun fmt -> - if !globals = [] && Kernel_function.Map.is_empty !reports then - Format.fprintf fmt "No properties status@." ; - let partials = ref 0 in - let completes = ref 0 in - let untried = ref 0 in - report ~partials ~completes ~untried hmap fmt "Global Properties" !globals ; - Kernel_function.Map.iter - (fun kf ips -> - let title = - Printf.sprintf "Properties for Function '%s'" - (Kernel_function.get_name kf) - in report ~partials ~completes ~untried hmap fmt title ips - ) !reports ; - let s = !untried + !partials + !completes in - Format.fprintf fmt "%s@\n" bar ; - Format.fprintf fmt " No proofs : %4d@\n" !untried ; - Format.fprintf fmt " Partial proofs : %4d@\n" !partials ; - Format.fprintf fmt " Complete proofs : %4d@\n" !completes ; - Format.fprintf fmt " Total : %4d@\n" s ; - Format.fprintf fmt "%s@." bar ; - ) ; - end +let print () = + Self.feedback "Computing properties status..." ; + Log.print_on_output (fun fmt -> Scan.iter (Dump.create fmt)) + +let print = + Dynamic.register + ~plugin:"Report" + ~journalize:true + "print" + (Datatype.func Datatype.unit Datatype.unit) + print -let main () = - if Enabled.get () then +let main () = + if Enabled.get () then begin print () ; Enabled.clear () ; (* Hack for not printing the report after -then *) diff -Nru frama-c-20110201+carbon+dfsg/src/report/register.mli frama-c-20111001+nitrogen+dfsg/src/report/register.mli --- frama-c-20110201+carbon+dfsg/src/report/register.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/register.mli 2011-10-10 08:38:25.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,7 +15,7 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) @@ -27,8 +25,12 @@ (* -------------------------------------------------------------------------- *) module Self : Plugin.S -module Enabled : Plugin.BOOL -module Emitter : Plugin.BOOL -module Pending : Plugin.BOOL +module Enabled : Plugin.Bool val print : unit -> unit + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/report/Report.mli frama-c-20111001+nitrogen+dfsg/src/report/Report.mli --- frama-c-20110201+carbon+dfsg/src/report/Report.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/Report.mli 2011-10-10 08:38:25.000000000 +0000 @@ -3,10 +3,8 @@ (* This file is part of Frama-C. *) (* *) (* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* INRIA (Institut National de Recherche en Informatique et en *) -(* Automatique) *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) @@ -17,7 +15,7 @@ (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) -(* See the GNU Lesser General Public License version v2.1 *) +(* See the GNU Lesser General Public License version 2.1 *) (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) diff -Nru frama-c-20110201+carbon+dfsg/src/report/scan.ml frama-c-20111001+nitrogen+dfsg/src/report/scan.ml --- frama-c-20110201+carbon+dfsg/src/report/scan.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/scan.ml 2011-10-10 08:38:25.000000000 +0000 @@ -0,0 +1,134 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Iterator for Report --- *) +(* -------------------------------------------------------------------------- *) + +open Property_status +module E = Emitter.Usable_emitter + +class type inspector = +object + + method empty : unit + method started : unit + method global_section : unit + method function_section : Kernel_function.t -> unit + method property : Property.t -> Consolidation.t -> unit + method finished : unit + +end + +let dead_reasons (ps:Consolidation.pending) = + E.Map.fold + (fun _ -> E.Map.fold (fun _ -> Property.Set.union)) + ps Property.Set.empty + +let partial_pending (ps:Consolidation.pending) = + E.Map.map + (fun best -> E.Map.fold + (fun _ -> Property.Set.union) + best Property.Set.empty) + ps + +let rec add_property ips ip = + if not (Property.Set.mem ip !ips) then + begin + ips := Property.Set.add ip !ips ; + add_consolidation ips (Consolidation.get ip) + end + +and add_consolidation ips = function + | Consolidation.Never_tried + | Consolidation.Considered_valid + | Consolidation.Valid _ + | Consolidation.Invalid _ + | Consolidation.Inconsistent _ -> () + + | Consolidation.Valid_under_hyp ps + | Consolidation.Unknown ps + | Consolidation.Invalid_under_hyp ps + | Consolidation.Valid_but_dead ps + | Consolidation.Invalid_but_dead ps + | Consolidation.Unknown_but_dead ps -> + add_pending ips ps + +and add_pending ipref (ps:Consolidation.pending) = + E.Map.iter + (fun _ m -> + E.Map.iter + (fun _ ips -> + Property.Set.iter (add_property ipref) ips + ) m + ) ps + +let never_tried ip = + match Consolidation.get ip with + | Consolidation.Never_tried -> true + | _ -> false + +let iter (inspector:inspector) = + begin + (* Collect noticeable properties (tried + their pending) *) + let properties = ref Property.Set.empty in + Property_status.iter + (fun ip -> if not (never_tried ip) then add_property properties ip) ; + let globals = ref Property.Set.empty in + let functions = ref Kernel_function.Map.empty in + (* Dispatch properties into globals and per-function map *) + Property.Set.iter + (fun ip -> + match Property.get_kf ip with + | None -> globals := Property.Set.add ip !globals + | Some kf -> + if not (Ast_info.is_frama_c_builtin (Kernel_function.get_name kf)) + then try + let fips = Kernel_function.Map.find kf !functions in + fips := Property.Set.add ip !fips + with Not_found -> + let ips = Property.Set.singleton ip in + functions := Kernel_function.Map.add kf (ref ips) !functions) + !properties ; + (* Report a set of ip in a section *) + let report s f ips = if not (Property.Set.is_empty ips) then + ( s () ; Property.Set.iter (fun ip -> f ip (Consolidation.get ip)) ips ) + in + if Property.Set.is_empty !globals && Kernel_function.Map.is_empty !functions then + inspector#empty + else + begin + inspector#started ; + report (fun () -> inspector#global_section) inspector#property !globals ; + Kernel_function.Map.iter + (fun kf ips -> + report (fun () -> inspector#function_section kf) inspector#property !ips) + !functions ; + inspector#finished ; + end + end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/report/scan.mli frama-c-20111001+nitrogen+dfsg/src/report/scan.mli --- frama-c-20110201+carbon+dfsg/src/report/scan.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/report/scan.mli 2011-10-10 08:38:25.000000000 +0000 @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Iterator for Report --- *) +(* -------------------------------------------------------------------------- *) + +open Property_status + +class type inspector = +object + + method empty : unit + method started : unit + method global_section : unit + method function_section : Kernel_function.t -> unit + method property : Property.t -> Consolidation.t -> unit + method finished : unit + +end + +val dead_reasons : Consolidation.pending -> Property.Set.t +val partial_pending : Consolidation.pending -> Property.Set.t Emitter.Usable_emitter.Map.t +val iter : inspector -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/rte/register.ml frama-c-20111001+nitrogen+dfsg/src/rte/register.ml --- frama-c-20110201+carbon+dfsg/src/rte/register.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/rte/register.ml 2011-10-10 08:38:22.000000000 +0000 @@ -20,7 +20,6 @@ (* *) (**************************************************************************) -open Db_types open Rte_parameters let start_msg () = diff -Nru frama-c-20110201+carbon+dfsg/src/rte/rte.ml frama-c-20111001+nitrogen+dfsg/src/rte/rte.ml --- frama-c-20110201+carbon+dfsg/src/rte/rte.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/rte/rte.ml 2011-10-10 08:38:22.000000000 +0000 @@ -25,13 +25,12 @@ (* should we check for plugin option -no-overflow: disable signed overflow annotation generation ? *) -open Db_types open Cil open Cil_types open Rte_parameters - + let rte_prefix = "rte" (* prefix for generated predicates (not behaviors) *) -let precond_prefix = "pre" (* prefix for generate behaviors *) +let precond_prefix = "pre" (* prefix for generated behaviors *) module Int = Abstract_interp.Int (* for integer computation *) @@ -55,8 +54,8 @@ let rec get_state kf = match find_all kf with | [] -> - add (Kernel_function.get_name kf) kf [ ] () ; - get_state kf + add (Kernel_function.get_name kf) kf [ ] () ; + get_state kf | [ _, s ] -> s | _ -> assert false @@ -105,10 +104,10 @@ let rec get_state kf = let sglobal = RteGlobalTbl.get_state kf in match find_all kf with - | [] -> add (Kernel_function.get_name kf) kf [ sglobal ] () ; - get_state kf - | [ _, s ] -> s - | _ -> assert false + | [] -> add (Kernel_function.get_name kf) kf [ sglobal ] () ; + get_state kf + | [ _, s ] -> s + | _ -> assert false end @@ -240,14 +239,25 @@ end) (PrecondAnnot_Proxy) - -(* this module is used for annotation status registering in this plugin *) -module S = - Properties_status.Make_updater - (struct - let name = "RTE" - let emitter = self - end) +let emit_status = + let emitter = + Emitter.create "RTE" + ~correctness:[ DoUnsignedOverflow.parameter ; + DoAll.parameter ; + DoSignedOverflow.parameter ; + DoDownCast.parameter ; + DoDivMod.parameter ; + DoMemAccess.parameter ; + DoCalledPrecond.parameter ; + FunctionSelection.parameter + ] + ~tuning:[ Enabled.parameter ; + Print.parameter ; + ConstFold.parameter ; + Warn.parameter + ] + in + fun ppt s -> Extlib.may (Property_status.emit emitter ~hyps:[] ppt) s module Parameter_map = struct @@ -260,21 +270,21 @@ let is_one_true ~except:name_opt m = match name_opt with | None -> ( - try - Datatype.String.Map.iter - (fun _ bval -> if bval then failwith "") m - ; - false - with _ -> true - ) + try + Datatype.String.Map.iter + (fun _ bval -> if bval then failwith "") m + ; + false + with _ -> true + ) | Some name -> ( - try - Datatype.String.Map.iter - (fun n bval -> if bval && (n <> name) then failwith "") m - ; - false - with _ -> true - ) + try + Datatype.String.Map.iter + (fun n bval -> if bval && (n <> name) then failwith "") m + ; + false + with _ -> true + ) let is_true name m = try @@ -298,7 +308,7 @@ DoDownCast.name, DoDownCast.get, true, RTE_DownCast_Generated.set; (* DoCalledPrecond *) - DoCalledPrecond.name, DoCalledPrecond.get, true, + DoCalledPrecond.name, DoCalledPrecond.get, false (* NOT set on DoAll *), Called_Precond_Generated.set; (* DoUnsignedOverflow *) DoUnsignedOverflow.name, DoUnsignedOverflow.get, false (* NOT set on DoAll *), @@ -313,31 +323,31 @@ let empty_gen = List.fold_left (fun acc (opt_name,opt_fun, _, _) -> - Datatype.String.Map.add opt_name (opt_fun ()) acc) + Datatype.String.Map.add opt_name (opt_fun ()) acc) Datatype.String.Map.empty generating_opts let empty_other = List.fold_left (fun acc (opt_name,opt_fun) -> - Datatype.String.Map.add opt_name (opt_fun ()) acc ) + Datatype.String.Map.add opt_name (opt_fun ()) acc ) Datatype.String.Map.empty other_opts let gen_from_command_line_options () = let opt_state opt_fun bset_on_do_all = (* DoAll is set + bset_on_do_all = set all options to true ; - otherwise rely on option switch *) + otherwise rely on option switch *) if bset_on_do_all && (DoAll.get ()) then true else opt_fun () in List.fold_left - (fun acc (opt_name,opt_fun,bset_on_do_all,_) -> - Datatype.String.Map.add - opt_name - (opt_state opt_fun bset_on_do_all) - acc) - Datatype.String.Map.empty generating_opts + (fun acc (opt_name,opt_fun,bset_on_do_all,_) -> + Datatype.String.Map.add + opt_name + (opt_state opt_fun bset_on_do_all) + acc) + Datatype.String.Map.empty generating_opts let set_precond pmap = Datatype.String.Map.add DoCalledPrecond.name true pmap @@ -347,9 +357,9 @@ (fun acc name -> Datatype.String.Map.add name true acc) pmap [ DoSignedOverflow.name ; - DoMemAccess.name ; - DoDivMod.name ; - DoDownCast.name ] + DoMemAccess.name ; + DoDivMod.name ; + DoDownCast.name ] let set_unsignedOv pmap = Datatype.String.Map.add DoUnsignedOverflow.name true pmap @@ -357,7 +367,7 @@ let other_from_command_line_options () = List.fold_left (fun acc (opt_name,opt_fun) -> - Datatype.String.Map.add opt_name (opt_fun ()) acc) + Datatype.String.Map.add opt_name (opt_fun ()) acc) Datatype.String.Map.empty other_opts end @@ -372,10 +382,10 @@ Kernel_function.Make_Table (Datatype.Pair(Parameter_map)(Parameter_map)) (struct - let size = 97 - let name = "rte_options" - let dependencies = [ Ast.self ] - let kind = `Correctness + let size = 97 + let name = "rte_options" + let dependencies = [ Ast.self ] + let kind = `Correctness end) let find_current_gen_options kf = @@ -391,8 +401,8 @@ let rec get_state_kf kf = match RteGlobalTbl.find_all kf with | [] -> - RteGlobalTbl.add (Kernel_function.get_name kf) kf [ ] () ; - get_state_kf kf + RteGlobalTbl.add (Kernel_function.get_name kf) kf [ ] () ; + get_state_kf kf | [ _, s ] -> s | _ -> assert false @@ -400,9 +410,9 @@ let rec get_rte_state_kf kf = let sglobal = get_state_kf kf in match RteAnnotTbl.find_all kf with - | [] -> - RteAnnotTbl.add (Kernel_function.get_name kf) kf [ sglobal ] () ; - get_rte_state_kf kf + | [] -> + RteAnnotTbl.add (Kernel_function.get_name kf) kf [ sglobal ] () ; + get_rte_state_kf kf | [ _, s ] -> s | _ -> assert false @@ -410,24 +420,60 @@ let rec get_precond_state_kf kf = let sglobal = get_state_kf kf in match PrecondAnnotTbl.find_all kf with - | [] -> - PrecondAnnotTbl.add (Kernel_function.get_name kf) kf [ sglobal ] () ; - get_precond_state_kf kf - | [ _, s ] -> s - | _ -> assert false + | [] -> + PrecondAnnotTbl.add (Kernel_function.get_name kf) kf [ sglobal ] () ; + get_precond_state_kf kf + | [ _, s ] -> s + | _ -> assert false *) end (* warning *) +let fmt_warn_no_valid_fptr_deref = + format_of_string "no predicate available yet to check \ + validity of function pointer dereferencing %a" + +let fmt_warn_bitsize_over_64 = + format_of_string "bitsSize of %a > 64: not treated" + +let fmt_warn_bitsize_over_32 = + format_of_string "bitsSize of %a > 32: not treated" + +let fmt_warn_bad_bitsize = + format_of_string "problem with bitsSize of %a: not treated" + +let fmt_warn_shift_assert1 = + format_of_string "shift assert broken (signed overflow): %a" + +let fmt_warn_shift_assert2 = + format_of_string "shift assert broken (left operand should be nonnegative): %a" + +let fmt_warn_shift_assert3 = + format_of_string "shift assert broken (unsigned overflow): %a" + +let fmt_warn_shift_assert4 = + format_of_string "shift assert broken (bad right operand): %a" + +let fmt_warn_signed_downcast_assert = + format_of_string "signed downcast assert broken: %a" + +let fmt_unary_minus_assert = + format_of_string "unary minus assert broken: %a" + +let fmt_signed_overflow_assert = + format_of_string "signed overflow assert broken: %a" + +let fmt_unsigned_overflow_assert = + format_of_string "unsigned overflow assert broken: %a" + +let fmt_divisor_assert = + format_of_string "divisor assert broken: %a" + let rte_warn ?source fmt = Rte_parameters.warning ?source ~current:true ~once:true (*warn*) fmt -(* build a "checked as false" annotation status *) -let make_check_false () = Checked { emitter = "rte" ; valid = False } -(* and make_check_true () = Checked { emitter = "rte" ; valid = True } *) ;; - (* compute a term from a C expr, with the property that arithmetic operations are evaluated in Z (integers) *) @@ -455,25 +501,25 @@ let term = if cast then begin - (* expr_to_term_with_cast expr *) - (* not used since it adds casts everywhere (not pretty): - since sub-expressions are also checked for annotation, - might as well cast only top expression *) - match aterm.term_node with - | TCastE(_,_) -> (* no point in recasting *) aterm - | TConst _ -> (* constants are not cast, - though in some cases they should (big const) *) aterm - | TLval _ -> aterm - | _ -> - if (Cil.isIntegralType e_typ || Cil.isFloatingType e_typ) - then - Logic_const.term - (TCastE - (e_typ, - Logic_const.term - aterm.term_node - (Logic_utils.typ_to_logic_type e_typ))) (Ctype e_typ) - else aterm + (* expr_to_term_with_cast expr *) + (* not used since it adds casts everywhere (not pretty): + since sub-expressions are also checked for annotation, + might as well cast only top expression *) + match aterm.term_node with + | TCastE(_,_) -> (* no point in recasting *) aterm + | TConst _ -> (* constants are not cast, + though in some cases they should (big const) *) aterm + | TLval _ -> aterm + | _ -> + if (Cil.isIntegralType e_typ || Cil.isFloatingType e_typ) + then + Logic_const.term + (TCastE + (e_typ, + Logic_const.term + aterm.term_node + (Logic_utils.typ_to_logic_type e_typ))) (Ctype e_typ) + else aterm end else aterm in @@ -484,10 +530,10 @@ let t1,t2 = expr_to_term ~cast:false expr, expr_to_term ~cast:true expr in debug ~level:2 - "output integer term: %a (%a)\n" Cil.d_term t1 Cil.d_logic_type t1.term_type + "output integer term: %a (%a)\n" Cil.d_term t1 Cil.d_logic_type t1.term_type ; debug ~level:2 - "output (C cast) term: %a (%a)\n" Cil.d_term t2 Cil.d_logic_type t2.term_type + "output (C cast) term: %a (%a)\n" Cil.d_term t2 Cil.d_logic_type t2.term_type ; *) term @@ -498,12 +544,12 @@ let cexpr = constFold true expr in match cexpr.enode with | Const c -> - let rec get_constant_expr_val e = - match e with - | CChr c -> get_constant_expr_val (charConstToInt c) - | CInt64 (d64,_,_) -> Some d64 - | _ -> None - in get_constant_expr_val c + let rec get_constant_expr_val e = + match e with + | CChr c -> get_constant_expr_val (charConstToInt c) + | CInt64 (d64,_,_) -> Some d64 + | _ -> None + in get_constant_expr_val c | _ -> None type tOff = MyField of fieldinfo | MyIndex of exp @@ -516,11 +562,12 @@ let get_lval_assertion (lv : lval) = (* one has to build assertions for: - pointer dereferencing: only if lval host is of the form (Mem expr) - - array access: several may occur, one for each offset of the form (Index _,_) + - array access: several may occur, one for each offset of the form (Index + _,_) *) (* so we : A. compute all assertions for array accesses by - 1. transforming the offset recurvise structure + 1. transforming the offset recursive structure in an ad hoc list (offsets_as_list) 2. keeping offsets which are array accesses (all_array_offsets) 3. rebuilding Cil offsets from these (final_array_offsets) @@ -533,93 +580,68 @@ let (lhost, init_offset) = lv in let rec fetch_all_offsets acc off = match off with - | NoOffset -> acc - | Field (fi, next_off) -> fetch_all_offsets ((MyField fi) :: acc) next_off - | Index (e, next_off) -> fetch_all_offsets ((MyIndex e) :: acc) next_off - in let offsets_as_list = List.rev (fetch_all_offsets [] init_offset) - in let all_array_offsets = - fst ( - List.fold_left - (fun (acc_off,acc_prefix) moff -> - match moff with - | MyIndex _ -> - ((moff :: acc_prefix) :: acc_off, moff :: acc_prefix) - | _ -> (acc_off, moff :: acc_prefix) - ) ([],[]) offsets_as_list) - - in let rec build_offset_from_list off_list = + | NoOffset -> acc + | Field (fi, next_off) -> fetch_all_offsets ((MyField fi) :: acc) next_off + | Index (e, next_off) -> fetch_all_offsets ((MyIndex e) :: acc) next_off + in + let offsets_as_list = List.rev (fetch_all_offsets [] init_offset) in + let all_array_offsets, _ = + List.fold_left + (fun (acc_off,acc_prefix) moff -> + match moff with + | MyIndex _ -> + ((moff :: acc_prefix) :: acc_off, moff :: acc_prefix) + | _ -> (acc_off, moff :: acc_prefix)) + ([],[]) + offsets_as_list + in + let rec build_offset_from_list off_list = match off_list with | [] -> NoOffset | (MyField fi) :: tl -> Field (fi, build_offset_from_list tl) | (MyIndex e) :: tl -> Index (e, build_offset_from_list tl) - in let final_array_offsets = + in + let final_array_offsets = List.map (fun off_list -> - build_offset_from_list (List.rev off_list) + build_offset_from_list (List.rev off_list) ) all_array_offsets (* in let () = debug "Final list of offsets is\n" ; List.iter (fun off -> debug "%a\n" d_offset off) final_array_offsets *) - in let final_array_lvals = (List.map (fun off -> (lhost,off)) final_array_offsets) - in let final_array_terms = - List.fold_left - (fun acc lv -> - if isFunctionType (typeOfLval lv) then ( - rte_warn "no predicate available yet to check \ - validity of function pointer dereferencing %a" - Cil.d_lval lv - ; - acc) - else - (translate_C_expr_to_term ~cast:false - (mkAddrOf ~loc:(CurrentLoc.get())lv)) - :: acc) + in + let final_array_lvals = + List.map (fun off -> (lhost,off)) final_array_offsets in + let final_array_terms = + List.fold_left + (fun acc lv -> + if isFunctionType (typeOfLval lv) then begin + rte_warn fmt_warn_no_valid_fptr_deref + Cil.d_lval lv; + acc + end else + translate_C_expr_to_term ~cast:false + (mkAddrOf ~loc:(CurrentLoc.get())lv) + :: acc) [] final_array_lvals - in let final_terms = - match lv with - | Mem exp, _ -> - if isFunctionType (typeOfLval lv) then ( - rte_warn "no predicate available yet to check \ -validity of function pointer dereferencing %a" - Cil.d_lval lv - ; - final_array_terms - ) else - (translate_C_expr_to_term ~cast:false exp) :: final_array_terms - | Var _, _ -> final_array_terms - in List.map (fun t -> (Logic_const.pvalid t, None) ) final_terms - -(* compute min/max representable signed integer with bit-length sz (<= 64) *) -let get_signed_min sz = - assert(sz <= 64); - let min64 = Int64.min_int - and shift_value = 64 - sz in - if shift_value > 0 - then Int64.shift_right min64 shift_value - else min64 - -let get_signed_max sz = - assert(sz <= 64); - let max64 = Int64.max_int - and shift_value = 64 - sz in - if shift_value > 0 - then Int64.shift_right max64 shift_value - else max64 - -(* compute max representable unsigned integer - with bit-length sz (<= 32 for the time being) *) -let get_unsigned_max sz = - assert(sz <= 32); - let max32 = Int64.of_string "0xffffffff" - and shift_value = 32 - sz - in - if shift_value > 0 - then Int64.shift_right max32 shift_value - else max32 - + in + let final_terms = + match lv with + | Mem exp, _ -> + if isFunctionType (typeOfLval lv) then begin + rte_warn fmt_warn_no_valid_fptr_deref + Cil.d_lval lv; + final_array_terms + end else + translate_C_expr_to_term ~cast:false exp :: final_array_terms + | Var _, _ -> final_array_terms + in + List.map + (fun t -> (Logic_const.pvalid t, None)) + final_terms (* assertions for bounding a term *) let assertion_le term bound = Logic_const.prel (Rle, term, Cil.lconstant bound) @@ -632,29 +654,28 @@ let size = bitsSizeOf t in if (size > 64) then ( (* should never happen *) - rte_warn "bitsSize of %a > 64: not treated" d_exp expr ; + rte_warn fmt_warn_bitsize_over_64 d_exp expr ; [] ) else - let minType = get_signed_min size in + let minType = min_signed_number size in let assertion () = - let term = translate_C_expr_to_term expr - in Logic_const.prel (Rneq, term, Cil.lconstant minType) + let term = translate_C_expr_to_term expr + in Logic_const.prel (Rneq, term, Cil.lconstant minType) in - if simplify_constants then ( - match get_expr_val expr with - | Some a64 -> (* constant operand *) - if Int64.compare a64 minType = 0 then ( - let assertion = assertion () - in - if warning then - rte_warn "unary minus assert broken: %a" d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - ) - else [] - | None -> [ (assertion (), None) ] - ) else [ (assertion (), None) ] + if simplify_constants then ( + match get_expr_val expr with + | Some a64 -> (* constant operand *) + if My_bigint.equal a64 minType then begin + let assertion = assertion () in + if warning then + rte_warn fmt_unary_minus_assert + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ] + end else + [] + | None -> [ (assertion (), None) ] + ) else [ (assertion (), None) ] (* assertions for multiplication/addition/subtraction signed overflow *) let get_multsubadd_assertion @@ -668,93 +689,96 @@ let size = bitsSizeOf t in if (size > 64) then ( (* should never happen *) - rte_warn "bitsSize of %a > 64: not treated" d_exp full_expr ; - [] - ) + rte_warn fmt_warn_bitsize_over_64 d_exp full_expr ; + [] + ) else - let (minType,maxType) = (get_signed_min size, get_signed_max size) in + let (minType,maxType) = (min_signed_number size, max_signed_number size) + in let full_add_term () = - (* no cast to int since we check "true result" which is an integer *) - let term1 = translate_C_expr_to_term ~cast:false expr1 - and term2 = translate_C_expr_to_term ~cast:false expr2 - in Logic_const.term (TBinOp (op, term1,term2)) (Ctype t) + (* no cast to int since we check "true result" which is an integer *) + let term1 = translate_C_expr_to_term ~cast:false expr1 + and term2 = translate_C_expr_to_term ~cast:false expr2 + in Logic_const.term (TBinOp (op, term1,term2)) (Ctype t) in let assertion_le () = assertion_le (full_add_term ()) maxType and assertion_ge () = assertion_ge (full_add_term ()) minType in - let full_assertion () = Logic_const.pand (assertion_le (), assertion_ge ()) + let full_assertion () = + Logic_const.pand (assertion_le (), assertion_ge ()) in - if simplify_constants then ( - match get_expr_val expr1, get_expr_val expr2 with - | Some a64, Some b64 -> (* both operands are constant *) - let big_a64 = Int.of_int64 a64 - and big_b64 = Int.of_int64 b64 - in - if op = MinusA then - let big_diff = Int.sub big_a64 big_b64 - in if Int.compare big_diff (Int.of_int64 minType) < 0 then - let assertion = assertion_ge () - in - if warning then - rte_warn - "signed overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else [ ] - else if op = PlusA then - let big_add = Int.add big_a64 big_b64 - in if Int.compare big_add (Int.of_int64 maxType) > 0 then - let assertion = assertion_le () - in - if warning then - rte_warn - "signed overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else [ ] - else ( - assert(op = Mult) ; - let big_mult = Int.mul big_a64 big_b64 - in let b_ov = (Int.compare big_mult (Int.of_int64 maxType) > 0) - in if b_ov then - let assertion = assertion_le () - in - if warning then - rte_warn - "signed overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else let b_uv = (Int.compare big_mult (Int.of_int64 minType) < 0) - in if b_uv then - let assertion = assertion_ge () - in - if warning then - rte_warn - "signed overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else [ ] - ) - | Some a64, None - | None, Some a64 -> (* one operand is constant *) - if op = MinusA then [ (assertion_ge (), None) ] - else if op = PlusA then [ (assertion_le (), None) ] - else ( - assert(op = Mult); - (* multiplying by 1 or 0 if not dangerous *) - if (Int64.compare a64 Int64.zero = 0) || - (Int64.compare a64 Int64.one = 0) then [] - else - (* multiplying by -1 is dangerous (albeit seldom) *) - if (Int64.compare a64 (Int64.of_int (-1)) = 0) then - [ (assertion_le (), None) ] - else [ (full_assertion (), None) ] - ) - | None,None -> [ (full_assertion (), None) ] (* no operand is a constant *) - ) else [ (full_assertion (), None) ] + if simplify_constants then begin + match get_expr_val expr1, get_expr_val expr2 with + | Some a64, Some b64 -> (* both operands are constant *) + let big_a64 = a64 + and big_b64 = b64 + in + if op = MinusA then + let big_diff = Int.sub big_a64 big_b64 + in if Int.lt big_diff minType then + let assertion = assertion_ge () in + if warning then + rte_warn + fmt_signed_overflow_assert + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ] + else + [ ] + else if op = PlusA then + let big_add = Int.add big_a64 big_b64 in + if Int.gt big_add maxType then + let assertion = assertion_le () in + if warning then + rte_warn + fmt_signed_overflow_assert + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ] + else + [ ] + else ( + assert(op = Mult) ; + let big_mult = Int.mul big_a64 big_b64 in + let b_ov = Int.gt big_mult maxType in + if b_ov then + let assertion = assertion_le () in + if warning then + rte_warn + fmt_signed_overflow_assert + d_predicate_named assertion ; + [ assertion, Some Property_status.False_if_reachable ] + else + let b_uv = Int.lt big_mult minType in + if b_uv then + let assertion = assertion_ge () in + if warning then + rte_warn + fmt_signed_overflow_assert + d_predicate_named assertion ; + [ assertion, Some Property_status.False_if_reachable ] + else [ ]) + | Some a64, None + | None, Some a64 -> (* one operand is constant *) + if op = MinusA then + [ assertion_ge (), None ] + else if op = PlusA then + [ assertion_le (), None ] + else begin + assert(op = Mult); + (* multiplying by 1 or 0 if not dangerous *) + if (My_bigint.equal a64 My_bigint.zero) || + (My_bigint.equal a64 My_bigint.one) + then [] + else + (* multiplying by -1 is dangerous (albeit seldom) *) + if My_bigint.equal a64 My_bigint.minus_one then + [ assertion_le (), None ] + else + [ full_assertion (), None ] + end + | None,None -> + (* no operand is a constant *) + [ full_assertion (), None ] + end else + [ full_assertion (), None ] (* assertions for multiplication/addition/subtraction unsigned overflow *) (* this is allowed by C and NOT a runtime-error *) @@ -769,80 +793,76 @@ let size = bitsSizeOf t in if (size > 32) then ( (* could happen: but then it's not possible yet to represent the maximum - possible value of the domain (2^64 - 1) as a Cil constant - (see TODO in cil_types.mli) + possible value of the domain (2^64 - 1) as a Cil constant + (see TODO in cil_types.mli) *) - rte_warn "bitsSize of %a > 32: not treated" d_exp full_expr ; - [] - ) + rte_warn fmt_warn_bitsize_over_32 d_exp full_expr ; + [] + ) else - let (minType,maxType) = (Int64.zero, get_unsigned_max size) in + let (minType,maxType) = My_bigint.zero, max_unsigned_number size in let full_add_term () = - (* no cast to int since we check "true result" which is an integer *) - let term1 = translate_C_expr_to_term ~cast:false expr1 - and term2 = translate_C_expr_to_term ~cast:false expr2 - in Logic_const.term (TBinOp (op, term1,term2)) (Ctype t) + (* no cast to int since we check "true result" which is an integer *) + let term1 = translate_C_expr_to_term ~cast:false expr1 + and term2 = translate_C_expr_to_term ~cast:false expr2 + in Logic_const.term (TBinOp (op, term1,term2)) (Ctype t) in let assertion () = - if op = MinusA then - assertion_ge (full_add_term ()) minType - else - assertion_le (full_add_term ()) maxType - in - if simplify_constants then ( - match get_expr_val expr1, get_expr_val expr2 with - | Some a64, Some b64 -> (* both operands are constant *) - let big_a64 = Int.of_int64 a64 - and big_b64 = Int.of_int64 b64 - in - if op = MinusA then - let big_diff = Int.sub big_a64 big_b64 - in if Int.compare big_diff (Int.of_int64 minType) < 0 then - let assertion = assertion () in - if warning then - rte_warn - "unsigned overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else [ ] - else if op = PlusA then - let big_add = Int.add big_a64 big_b64 - in if Int.compare big_add (Int.of_int64 maxType) > 0 then - let assertion = assertion () in - if warning then - rte_warn - "unsigned overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else [ ] - else ( - assert(op = Mult) ; - let big_mult = Int.mul big_a64 big_b64 - in let () = assert(Int.compare big_mult Int.zero >= 0) - in let b_ov = (Int.compare big_mult (Int.of_int64 maxType) > 0) - in - if b_ov then - let assertion = assertion () in - if warning then - rte_warn - "unsigned overflow assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else [ ] - ) - | Some a64, None - | None, Some a64 -> (* one operand is constant *) - if op = Mult then ( - (* multiplying by 1 or 0 if not dangerous *) - if (Int64.compare a64 Int64.zero = 0) || - (Int64.compare a64 Int64.one = 0) - then [] - else [ (assertion (), None) ] - ) else [ (assertion (), None) ] - | None,None -> [ (assertion (), None) ] (* no operand is a constant *) - ) else [ (assertion (), None) ] + if op = MinusA then + assertion_ge (full_add_term ()) minType + else + assertion_le (full_add_term ()) maxType + in + if simplify_constants then begin + match get_expr_val expr1, get_expr_val expr2 with + | Some big_a64, Some big_b64 -> (* both operands are constant *) + if op = MinusA then + let big_diff = Int.sub big_a64 big_b64 + in + if Int.lt big_diff minType then + let assertion = assertion () in + if warning then + rte_warn + fmt_unsigned_overflow_assert + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ] + else [ ] + else if op = PlusA then + let big_add = Int.add big_a64 big_b64 in + if Int.gt big_add maxType then + let assertion = assertion () in + if warning then + rte_warn + fmt_unsigned_overflow_assert + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ] + else [ ] + else ( + assert(op = Mult) ; + let big_mult = Int.mul big_a64 big_b64 in + let () = assert(Int.compare big_mult Int.zero >= 0) in + let b_ov = Int.gt big_mult maxType in + if b_ov then + let assertion = assertion () in + if warning then + rte_warn + fmt_unsigned_overflow_assert + d_predicate_named assertion ; + [ assertion, Some Property_status.False_if_reachable ] + else [ ]) + | Some a64, None + | None, Some a64 -> (* one operand is constant *) + if op = Mult then begin + (* multiplying by 1 or 0 if not dangerous *) + if My_bigint.equal a64 My_bigint.zero + || My_bigint.equal a64 My_bigint.one + then [] + else [ assertion (), None ] + end else [ assertion (), None ] + | None, None -> + (* no operand is a constant *) + [ assertion (), None ] + end else + [ assertion (), None ] (* assertions for division and modulo (divisor is 0) *) let get_divmod_assertion @@ -850,28 +870,29 @@ ~warning:warning divisor_expr = (* division or modulo: overflow occurs when divisor is equal to zero *) - let badValDivisor = Int64.zero - in let assertion () = - let term = translate_C_expr_to_term divisor_expr - in Logic_const.prel (Rneq, term, Cil.lconstant badValDivisor) - in if simplify_constants then ( - match get_expr_val divisor_expr with - | None -> (* divisor is not a constant (or it's value has not been computed) *) - [ (assertion (), None) ] - | Some v64 -> - if Int64.compare v64 badValDivisor = 0 then - (* divide by 0 *) - let assertion = assertion () - in - if warning then - rte_warn "divisor assert broken: %a" d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - else - (* divide by constant which is not 0 *) - (* nothing to assert *) - [] - ) else [ (assertion (), None) ] + let badValDivisor = My_bigint.zero in + let assertion () = + let term = translate_C_expr_to_term divisor_expr in + Logic_const.prel (Rneq, term, Cil.lconstant badValDivisor) + in + if simplify_constants then begin + match get_expr_val divisor_expr with + | None -> (* divisor is not a constant (or it's value has not + been computed) *) + [ assertion (), None ] + | Some v64 -> + if My_bigint.equal v64 badValDivisor then + (* divide by 0 *) + let assertion = assertion () in + if warning then + rte_warn fmt_divisor_assert d_predicate_named assertion ; + [ assertion, Some Property_status.False_if_reachable ] + else + (* divide by constant which is not 0 *) + (* nothing to assert *) + [] + end else + [ assertion (), None ] (* assertion for signed division overflow *) let get_signed_div_assertion @@ -884,91 +905,86 @@ represented in two's completement. Nothing done for modulo (the result of TYPE_MIN % -1 is 0, which does not overflow) Still it may be dangerous on a number of compilers / architectures - (modulo may be performed in parallel with divison) + (modulo may be performed in parallel with division) *) let t = Cil.typeOf divisor_expr in let size = bitsSizeOf t in - (* check dividend_expr / divisor_expr : if constants ... *) - if (size > 64) then ( - (* should never happen *) - rte_warn "bitsSize of %a > 64: not treated" d_exp divisor_expr ; - [] - ) - else - let badValDividend = - (* compute smallest representable "size bits" (signed) integer *) - get_signed_min size -(* - let min64 = Int64.min_int - and shiftright_value = 64 - size - in if shiftright_value > 0 then Int64.shift_right min64 shiftright_value else min64 -*) - and badValDivisor = Int64.minus_one - in let assert_for_divisor () = - Logic_const.prel - (Req, translate_C_expr_to_term divisor_expr, Cil.lconstant badValDivisor) - and assert_for_dividend () = - Logic_const.prel - (Req, - translate_C_expr_to_term dividend_expr, Cil.lconstant badValDividend) - in let assert_not_both () = - Logic_const.pnot - (Logic_const.pand (assert_for_divisor (), assert_for_dividend ())) - in - if simplify_constants then ( - let problem_with_divisor () = - match get_expr_val divisor_expr with - | None -> (false,false) - | Some c64 -> - if Int64.compare c64 badValDivisor = 0 - then (true,true) - else (true,false) - and problem_with_dividend () = - match get_expr_val dividend_expr with - | None -> (false,false) - | Some c64 -> - if Int64.compare c64 badValDividend = 0 - then (true,true) - else (true,false) - in - match problem_with_divisor (), problem_with_dividend () with - | (false,_), (false,_) -> (* neither divisor nor dividend is constant *) - (* Printf.eprintf "neither divisor nor dividend is constant\n"; - flush stderr; *) - [ (assert_not_both (), None) ] - | (true,true), (true,true) -> - (* divisor and dividend are constant and have both bad values *) - (* Printf.eprintf - "divisor and dividend are constant and have both bad values\n"; - flush stderr ; *) - let assertion = assert_not_both () - in - if warning then - rte_warn - "signed overflow assert broken: %a" d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - | (true,false), _ - | _ , (true,false) -> - (* one of divisor or dividend is constant and has a good value *) - (* Printf.eprintf - "one of divisor or dividend is constant and has a good value\n"; - flush stderr; *) - [] - | (true,true), (false,_) -> - (* divisor is constant and has bad value, dividend is not constant *) - (* Printf.eprintf - "divisor is constant and has bad value, dividend is not constant\n"; - flush stderr; *) - [ (Logic_const.pnot (assert_for_dividend ()), None) ] - | (false,_), (true,true) -> - (* divisor is not constant, dividend is constant and has bad value *) - (* Printf.eprintf - "divisor is not constant, dividend is constant and has bad value\n"; - flush stderr; *) - [ (Logic_const.pnot (assert_for_divisor ()), None) ] - ) else [ (assert_not_both (), None) ] + (* check dividend_expr / divisor_expr : if constants ... *) + if (size > 64) then ( + (* should never happen *) + rte_warn fmt_warn_bitsize_over_64 d_exp divisor_expr ; + [] + ) + else + let badValDividend = + (* compute smallest representable "size bits" (signed) integer *) + min_signed_number size + (* + let min64 = Int64.min_int + and shiftright_value = 64 - size + in if shiftright_value > 0 then Int64.shift_right min64 shiftright_value else min64 + *) + and badValDivisor = My_bigint.minus_one + in let assert_for_divisor () = + Logic_const.prel + (Req, translate_C_expr_to_term divisor_expr, Cil.lconstant badValDivisor) + and assert_for_dividend () = + Logic_const.prel + (Req, + translate_C_expr_to_term dividend_expr, Cil.lconstant badValDividend) + in let assert_not_both () = + Logic_const.pnot + (Logic_const.pand (assert_for_divisor (), assert_for_dividend ())) + in + if simplify_constants then ( + let problem_with_divisor () = + match get_expr_val divisor_expr with + | None -> (false,false) + | Some c64 -> + if My_bigint.equal c64 badValDivisor then (true,true) + else (true,false) + and problem_with_dividend () = + match get_expr_val dividend_expr with + | None -> (false,false) + | Some c64 -> + if My_bigint.equal c64 badValDividend then (true,true) + else (true,false) + in + match problem_with_divisor (), problem_with_dividend () with + | (false,_), (false,_) -> + (* neither divisor nor dividend is constant *) + (* Printf.eprintf "neither divisor nor dividend is constant\n"; + flush stderr; *) + [ assert_not_both (), None ] + | (true,true), (true,true) -> + (* divisor and dividend are constant and have both bad values *) + (* Printf.eprintf + "divisor and dividend are constant and have both bad values\n"; + flush stderr ; *) + let assertion = assert_not_both () + in + if warning then + rte_warn + fmt_signed_overflow_assert + d_predicate_named assertion ; + [ assertion, Some Property_status.False_if_reachable ] + | (true,false), _ + | _ , (true,false) -> + (* one of divisor or dividend is constant and has a good value *) + [] + | (true,true), (false,_) -> + (* divisor is constant and has bad value, dividend is not + constant *) + [ Logic_const.pnot (assert_for_dividend ()), + None ] + | (false,_), (true,true) -> + (* divisor is not constant, dividend is constant and has bad + value *) + [ Logic_const.pnot (assert_for_divisor ()), + None ]) + else + [ assert_not_both (), None ] (* assertions for bitwise left shift unsigned overflow *) (* this is allowed by C and NOT a runtime-error *) @@ -979,49 +995,41 @@ (* result should be representable in result type *) let t = Cil.typeOf exp in let size = bitsSizeOf t in - let () = - if not (size <= 32) - (* 64 bits size "requires" representing a constant - which does not hold in a Cil constant - (as long as it remains an int64 and not a big integer) *) - then rte_warn "problem with bitsSize of %a: not treated" d_exp exp ; - in let maxValResult = (* compute greatest reprensentable "size bits" unsigned integer *) - get_unsigned_max size + let maxValResult = + (* compute greatest reprensentable "size bits" unsigned integer *) + max_unsigned_number size in let ov_assertion () = - let term = translate_C_expr_to_term ~cast:false exp - in (* unsigned result is representable in result type if loperand times 2^roperand - (where loperand and roperand are nonnegative), - which should be equal to term (obtained with a shift), - is less than the maximal value for the result type *) - (* no cast to int since we check "true result" which is an integer*) - Logic_const.prel (Rle, term, Cil.lconstant maxValResult) - in let problem_with_ov_assertion () = - if simplify_constants then ( - match get_expr_val loperand, get_expr_val roperand with - | None,_ - | _, None -> (false,false) - | Some lval64, Some rval64 -> - (* both operands are constant: - check result is representable in result type *) - let result_true_val = - Int.shift_left (Int.of_int64 lval64) (Int.of_int64 rval64) - in - if Int.compare result_true_val (Int.of_int64 maxValResult) > 0 - then (true,false) (* constant operators and assertion does not hold *) - else (true,true) (* constant operators and assertion holds *) - ) else (false,false) - in - match problem_with_ov_assertion () with - | (true,false) -> + let term = translate_C_expr_to_term ~cast:false exp + in (* unsigned result is representable in result type if loperand times 2^roperand + (where loperand and roperand are nonnegative), + which should be equal to term (obtained with a shift), + is less than the maximal value for the result type *) + (* no cast to int since we check "true result" which is an integer*) + Logic_const.prel (Rle, term, Cil.lconstant maxValResult) + in let problem_with_ov_assertion () = + if simplify_constants then ( + match get_expr_val loperand, get_expr_val roperand with + | None,_ + | _, None -> (false,false) + | Some lval64, Some rval64 -> + (* both operands are constant: + check result is representable in result type *) + let result_true_val = Int.shift_left lval64 rval64 in + if Int.gt result_true_val maxValResult then + (true,false)(* constant operators and assertion does not hold *) + else (true,true)(* constant operators and assertion holds *) + ) else (false,false) + in + match problem_with_ov_assertion () with + | (true,false) -> let assertion = ov_assertion () in - if warning then ( - rte_warn - "shift assert broken (unsigned overflow): %a" d_predicate_named assertion - ) - ; - [ (assertion, Some (make_check_false())) ] - | (true,true) -> [ ] - | (false,_) -> [ (ov_assertion (), None) ] + if warning then + rte_warn + fmt_warn_shift_assert3 + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ] + | (true,true) -> [ ] + | (false,_) -> [ ov_assertion (), None ] (* generic assertion for bitwise left/right shift on right operand *) @@ -1031,36 +1039,37 @@ ~warning:warning exp roperand = let t = Cil.typeOf exp in - let size = bitsSizeOf t - in let size64 = Int64.of_int size - in let right_operand_assertion () = - let term = translate_C_expr_to_term roperand - in - Logic_const.pand - (Logic_const.prel (Rge, term, Cil.lzero ()), - Logic_const.prel (Rlt, term, Cil.lconstant size64)) - in let problem_with_operand_assertion () = - if simplify_constants then ( - match get_expr_val roperand with - | None -> (false,false) - | Some c64 -> - (* right operand is constant: - check it is nonnegative and stricly less than size *) - if (Int64.compare c64 size64 < 0) && (Int64.compare c64 Int64.zero >= 0) - then (true,true) (* constant operator and assertion holds *) - else (true,false) (* constant operator and assertion does not hold *) - ) else (false,false) - in match problem_with_operand_assertion () with - | (true,false) -> - let assertion = right_operand_assertion () in - if warning then ( - rte_warn - "shift assert broken (bad right operand): %a" d_predicate_named assertion - ) - ; - ([ (assertion, Some (make_check_false ())) ], false) - | (true,true) -> ([ ], true) - | (false,_) -> ([ (right_operand_assertion (), None) ], true) + let size = bitsSizeOf t in + let size64 = My_bigint.of_int size in + let right_operand_assertion () = + let term = translate_C_expr_to_term roperand in + Logic_const.pand + (Logic_const.prel (Rge, term, Cil.lzero ()), + Logic_const.prel (Rlt, term, Cil.lconstant size64)) + in + let problem_with_operand_assertion () = + if simplify_constants then ( + match get_expr_val roperand with + | None -> (false,false) + | Some c64 -> + (* right operand is constant: + check it is nonnegative and stricly less than size *) + if (My_bigint.lt c64 size64) && (My_bigint.ge c64 My_bigint.zero) + then (true,true) (* constant operator and assertion holds *) + else (true,false) (* constant operator and assertion does not hold *) + ) else (false,false) + in + match problem_with_operand_assertion () with + | (true,false) -> + let assertion = right_operand_assertion () in + if warning then + rte_warn + fmt_warn_shift_assert4 + d_predicate_named assertion; + [ assertion, Some Property_status.False_if_reachable ], false + | (true,true) -> [ ], true + | (false,_) -> + [ right_operand_assertion (), None ], true (* assertions for bitwise left/right shift signed overflow *) @@ -1079,88 +1088,87 @@ let size = bitsSizeOf t in let () = if not(size = bitsSizeOf (Cil.typeOf loperand) && size <= 64) - (* size of result type should be size of left (promoted) operand *) + (* size of result type should be size of left (promoted) operand *) then ( - rte_warn "problem with bitsSize of %a: not treated" d_exp exp ; + rte_warn fmt_warn_bad_bitsize d_exp exp ; ) in - let maxValResult = (* compute greatest representable "size bits" (signed) integer *) - get_signed_max size -(* + let maxValResult = + (* compute greatest representable "size bits" (signed) integer *) + max_signed_number size + (* let max64 = Int64.max_int and shiftright_value = 64 - size - in if shiftright_value > 0 then Int64.shift_right max64 shiftright_value else max64 -*) - in let assertion_2 () = - let term = translate_C_expr_to_term loperand - in Logic_const.prel (Rge, term, Cil.lzero ()) - and assertion_3 () = - let term = translate_C_expr_to_term ~cast:false exp - in (* signed result is representable in result type if loperand times 2^roperand - (where loperand and roperand are nonnegative), - which should be equal to term (obtained with a shift), - is less than the maximal value for the result type *) - (* no cast to int since we check "true result" which is an integer*) - Logic_const.prel (Rle, term, Cil.lconstant maxValResult) - in let problem_with_assertion_2 () = - if simplify_constants then ( - match get_expr_val loperand with - | None -> (false,false) - | Some c64 -> - (* left operand is constant: check it is nonnegative *) - if (Int64.compare c64 Int64.zero >= 0) - then (true, true) (* constant operator and assertion holds *) - else (true,false) (* constant operator and assertion does not hold *) - ) else (false,false) - and problem_with_assertion_3 () = - if simplify_constants then ( - match get_expr_val loperand, get_expr_val roperand with - | None,_ - | _, None -> (false,false) - | Some lval64, Some rval64 -> - (* both operands are constant: - check result is representable in result type *) - if (Int64.compare lval64 Int64.zero <= 0) || - (Int64.compare rval64 (Int64.of_int 64) >= 0) then - (true,false) (* constant operators and assertion does not hold *) - else - let result_true_val = - Int.shift_left (Int.of_int64 lval64) (Int.of_int64 rval64) - in - if Int.compare result_true_val (Int.of_int64 maxValResult) > 0 - then (true,false) (* constant operators and assertion does not hold *) - else (true,true) (* constant operators and assertion holds *) - ) else (false,false) - in let proceed_with_assertion_3 lassert = - if (shiftop = Shiftlt) then ( - match problem_with_assertion_3 () with - | (true,false) -> - let assertion = assertion_3 () in - if warning then ( - rte_warn - "shift assert broken (signed overflow): %a" - d_predicate_named assertion - ) - ; - ((assertion, Some (make_check_false ())))::lassert - | (true,true) -> lassert - | (false,_) -> (assertion_3 (), None)::lassert - ) else lassert + in if shiftright_value > 0 then Int64.shift_right max64 shiftright_value else max64 *) in - match problem_with_assertion_2 () with + let assertion_2 () = + let term = translate_C_expr_to_term loperand in Logic_const.prel (Rge, term, Cil.lzero ()) + and assertion_3 () = + let term = translate_C_expr_to_term ~cast:false exp in + (* signed result is representable in result type if loperand + times 2^roperand (where loperand and roperand are nonnegative), + which should be equal to term (obtained with a shift), + is less than the maximal value for the result type *) + (* no cast to int since we check "true result" which is an integer*) + Logic_const.prel (Rle, term, Cil.lconstant maxValResult) + in + let problem_with_assertion_2 () = + if simplify_constants then ( + match get_expr_val loperand with + | None -> (false,false) + | Some c64 -> + (* left operand is constant: check it is nonnegative *) + if My_bigint.ge c64 My_bigint.zero + then (true, true) (* constant operator and assertion holds *) + else (true,false) (* constant operator and assertion does not hold *) + ) else (false,false) + and problem_with_assertion_3 () = + if simplify_constants then ( + match get_expr_val loperand, get_expr_val roperand with + | None,_ + | _, None -> (false,false) + | Some lval64, Some rval64 -> + (* both operands are constant: + check result is representable in result type *) + if (My_bigint.le lval64 My_bigint.zero) + || (My_bigint.ge rval64 (My_bigint.of_int 64)) then + (true,false)(* constant operators and assertion does not hold *) + else + let result_true_val = Int.shift_left lval64 rval64 in + if Int.gt result_true_val maxValResult + then (true,false) + (* constant operators and assertion does not hold *) + else (true,true) (* constant operators and assertion holds *)) + else (false,false) + in + let proceed_with_assertion_3 lassert = + if (shiftop = Shiftlt) then begin + match problem_with_assertion_3 () with | (true,false) -> - let assertion = assertion_2 () in - if warning then ( - rte_warn - "shift assert broken (left operand should be nonnegative): %a" - d_predicate_named assertion - ) - ; - (* do not proceed with assertion 3: left operand is negative, - hence result is implementation defined anyway for left shift *) - [ (assertion, Some (make_check_false ())) ] - | (true,true) -> proceed_with_assertion_3 [ ] - | (false,_) -> proceed_with_assertion_3 [ (assertion_2 (), None) ] + let assertion = assertion_3 () in + if warning then + rte_warn + fmt_warn_shift_assert1 + d_predicate_named assertion; + (assertion, Some Property_status.False_if_reachable)::lassert + | (true,true) -> lassert + | (false,_) -> (assertion_3 (), None)::lassert + end else + lassert + in + match problem_with_assertion_2 () with + | true, false -> + let assertion = assertion_2 () in + if warning then + rte_warn + fmt_warn_shift_assert2 + d_predicate_named assertion; + (* do not proceed with assertion 3: left operand is negative, + hence result is implementation defined anyway for left shift *) + [ assertion, Some Property_status.False_if_reachable ] + | true, true -> proceed_with_assertion_3 [ ] + | false, _ -> + proceed_with_assertion_3 [ assertion_2 (), None ] (* assertion for downcasting to a signed integer type *) @@ -1172,56 +1180,54 @@ cast_typ expr = let e_typ = Cil.typeOf expr in - match e_typ with - | TInt (_,_) -> - let szTo = bitsSizeOf cast_typ - and szFrom = bitsSizeOf e_typ - in - if (szTo < szFrom) then - (* downcast: the expression result should fit on szTo bits *) - let (minType,maxType) = (get_signed_min szTo, get_signed_max szTo) - in let term = translate_C_expr_to_term ~cast:false expr in - let assertion_le () = assertion_le term maxType - and assertion_ge () = assertion_ge term minType - in - let ceval = - if simplify_constants then ( - match get_expr_val expr with - | Some a64 -> (* constant expr *) - Some (Int64.compare a64 minType >= 0, - Int64.compare a64 maxType <= 0) - | None -> None - ) else None - in match ceval with - | None -> - let full_assertion () = - Logic_const.pand (assertion_le (), assertion_ge ()) - in [ (full_assertion (), None) ] - | Some (emin,emax) -> ( - match (emin,emax) with - | (true,true) -> [] - | (true,false) -> - let assertion = assertion_le () in - if warning then - rte_warn - "signed downcast assert broken: %a" - d_predicate_named assertion - ; - [ (assertion, Some (make_check_false ())) ] - | (false,true) -> - let assertion = assertion_ge () in - if warning then - rte_warn - "signed downcast assert broken: %a" - d_predicate_named assertion - ; - [ (assertion_le (), Some (make_check_false ())) ] - - | (false,false) -> assert false (* should not happen *) - - ) - else [] - | _ -> [] + match e_typ with + | TInt (_,_) -> + let szTo = bitsSizeOf cast_typ + and szFrom = bitsSizeOf e_typ + in + if (szTo < szFrom) then + (* downcast: the expression result should fit on szTo bits *) + let (minType,maxType) = + (min_signed_number szTo, max_signed_number szTo) + in + let term = translate_C_expr_to_term ~cast:false expr in + let assertion_le () = assertion_le term maxType in + let assertion_ge () = assertion_ge term minType in + let ceval = + if simplify_constants then ( + match get_expr_val expr with + | Some a64 -> (* constant expr *) + Some (My_bigint.ge a64 minType, + My_bigint.le a64 maxType) + | None -> None) + else None + in match ceval with + | None -> + let full_assertion () = + Logic_const.pand (assertion_le (), assertion_ge ()) + in + [ full_assertion (), None ] + | Some (emin,emax) -> ( + match (emin,emax) with + | (true,true) -> [] + | (true,false) -> + let assertion = assertion_le () in + if warning then + rte_warn + fmt_warn_signed_downcast_assert + d_predicate_named assertion ; + [ assertion, Some Property_status.False_if_reachable ] + | (false,true) -> + let assertion = assertion_ge () in + if warning then + rte_warn + fmt_warn_signed_downcast_assert + d_predicate_named assertion ; + [ assertion_le (), Some Property_status.False_if_reachable ] + + | (false,false) -> assert false (* should not happen *)) + else [] + | _ -> [] (* assertion for preconditions *) type orig_lval = (* StartOfOrig | *) AddrOfOrig | LvalOrig @@ -1232,8 +1238,8 @@ match fa_terms with | [] -> None | (formal,term) :: tl -> - if vinfo.vid = formal.vid then Some term - else find_term_to_replace vinfo tl + if vinfo.vid = formal.vid then Some term + else find_term_to_replace vinfo tl exception AddrOfFormal exception NoResult @@ -1254,10 +1260,11 @@ | TConst _ | TSizeOf _ | TSizeOfStr _ | TAlignOf _ | Tnull | Ttype _ | Tempty_set -> SkipChildren - | TLval _tlv -> + | Tat _ -> self#add_tlval t ; SkipChildren - self#add_tlval t ; - DoChildren + | Tunion _ + | Tinter _ + | TLval _ -> self#add_tlval t ; DoChildren | _ -> DoChildren @@ -1266,7 +1273,6 @@ end - (* for each lval, replace each logic_variable which stems from a C variable by the term corresponding to the variable at this point iff it is a formal *) @@ -1274,98 +1280,97 @@ let treat_tlval fa_terms ret_opt origin tlval = let prefix_origin ntlval = match origin with - | LvalOrig -> TLval ntlval - | AddrOfOrig -> TAddrOf ntlval + | LvalOrig -> TLval ntlval + | AddrOfOrig -> TAddrOf ntlval in let (t_lhost, t_offset) = tlval in - match t_lhost with + match t_lhost with - | TMem _st -> DoChildren + | TMem _st -> DoChildren - | TResult _ty -> ( (* for post-conditions and assigns containing a \result *) - match ret_opt with - | None -> raise NoResult (* BTS 692 *) - | Some trm -> + | TResult _ty -> ( (* for post-conditions and assigns containing a \result *) + match ret_opt with + | None -> raise NoResult (* BTS 692 *) + | Some trm -> (* [VP] What happens if t_offset <> TNoOffset? *) - ChangeTo (prefix_origin trm) - ) + ChangeTo (prefix_origin trm) + ) - | TVar { lv_origin = Some vinfo } when vinfo.vformal -> - (match find_term_to_replace vinfo fa_terms with - | None -> DoChildren - (* ? can this happen ? is it correct ? *) - | Some nt -> - let make_li tmp_lvar = { - l_var_info = tmp_lvar; l_body = LBterm nt; - l_type = None; l_tparams = []; - l_labels = []; l_profile = []; - } - in - let make_tlet () = - let tmp_lvar = make_temp_logic_var nt.term_type in - Tlet - (make_li tmp_lvar, - mk_term - (prefix_origin (TVar tmp_lvar, t_offset)) - nt.term_type) - in - let tlet_or_ident () = - if t_offset = TNoOffset then + | TVar { lv_origin = Some vinfo } when vinfo.vformal -> + (match find_term_to_replace vinfo fa_terms with + | None -> DoChildren + (* ? can this happen ? is it correct ? *) + | Some nt -> + let make_li tmp_lvar = { + l_var_info = tmp_lvar; l_body = LBterm nt; + l_type = None; l_tparams = []; + l_labels = []; l_profile = []; + } + in + let make_tlet () = + let tmp_lvar = make_temp_logic_var nt.term_type in + Tlet + (make_li tmp_lvar, + mk_term + (prefix_origin (TVar tmp_lvar, t_offset)) + nt.term_type) + in + let tlet_or_ident () = + if t_offset = TNoOffset then (* Nothing to substitute afterwards. *) - ChangeTo nt.term_node - else + ChangeTo nt.term_node + else (* May need substitution in t_offset. *) - ChangeDoChildrenPost (make_tlet (), fun x -> x) - in - let add_offset lval = addTermOffsetLval t_offset lval in - match nt.term_node with - | TLval lv -> - ChangeDoChildrenPost - (prefix_origin (add_offset lv), fun x -> x) - | TStartOf lv -> - let lv = add_offset lv in - let t = - match origin with - LvalOrig -> TStartOf lv - | AddrOfOrig -> TAddrOf lv - in - ChangeDoChildrenPost(t,fun x->x) - (* [VP]: TAddrOf must be treated as the other - non-lval arguments. *) - (*| TAddrOf (lhost,off) -> - let prefix_origin2 lv = - match nt.term_node with - | TLval _ -> TLval lv - | TStartOf _ -> TStartOf lv - | _ -> TAddrOf lv - in - ChangeDoChildrenPost - ((let ntlval = addTermOffsetLval t_offset (lhost,off) - in prefix_origin2 ntlval), fun x -> x) - *) - | TCastE(ty,{ term_node = TLval lv | TStartOf lv }) -> - (match origin with - LvalOrig -> tlet_or_ident() - | AddrOfOrig when t_offset = TNoOffset -> - let t = - Logic_const.taddrof lv (typeOfTermLval lv) - in - ChangeTo (TCastE(TPtr(ty,[]), t)) - | AddrOfOrig -> - let lh = TMem nt in - ChangeDoChildrenPost - (TAddrOf (lh,t_offset),fun x -> x)) - | _ when origin = AddrOfOrig -> - let source = Cil.source nt.term_loc in - rte_warn ~source - "Cannot substitute a non-lval \ + ChangeDoChildrenPost (make_tlet (), fun x -> x) + in + let add_offset lval = addTermOffsetLval t_offset lval in + match nt.term_node with + | TLval lv -> + ChangeDoChildrenPost + (prefix_origin (add_offset lv), fun x -> x) + | TStartOf lv -> + let lv = add_offset lv in + let t = + match origin with + LvalOrig -> TStartOf lv + | AddrOfOrig -> TAddrOf lv + in + ChangeDoChildrenPost(t,fun x->x) + (* [VP]: TAddrOf must be treated as the other + non-lval arguments. *) + (*| TAddrOf (lhost,off) -> + let prefix_origin2 lv = + match nt.term_node with + | TLval _ -> TLval lv + | TStartOf _ -> TStartOf lv + | _ -> TAddrOf lv + in + ChangeDoChildrenPost + ((let ntlval = addTermOffsetLval t_offset (lhost,off) + in prefix_origin2 ntlval), fun x -> x) + *) + | TCastE(ty,{ term_node = TLval lv | TStartOf lv }) -> + (match origin with + LvalOrig -> tlet_or_ident() + | AddrOfOrig when t_offset = TNoOffset -> + let t = + Logic_const.taddrof lv (typeOfTermLval lv) + in + ChangeTo (TCastE(TPtr(ty,[]), t)) + | AddrOfOrig -> + let lh = TMem nt in + ChangeDoChildrenPost + (TAddrOf (lh,t_offset),fun x -> x)) + | _ when origin = AddrOfOrig -> + rte_warn ~source:(fst nt.term_loc) + "Cannot substitute a non-lval \ parameter under an addrof operation"; - raise AddrOfFormal - | _ -> tlet_or_ident ()) - | _ -> DoChildren + raise AddrOfFormal + | _ -> tlet_or_ident ()) + | _ -> DoChildren -let replacement_visitor fa_terms ret_opt = object +let replacement_visitor replace_pre fa_terms ret_opt = object (* for each term, replace each logic_variable which stems from a C variable by the term corresponding to the variable at this point iff it is a formal *) @@ -1385,14 +1390,22 @@ *) | _ -> DoChildren + method vlogic_label l = + match l with + | StmtLabel _ -> DoChildren + | LogicLabel _ + when Cil_datatype.Logic_label.equal l Logic_const.pre_label -> + ChangeDoChildrenPost(replace_pre, fun x->x) + | LogicLabel _ -> DoChildren + end -let treat_pred pred fa_terms (ret_opt : term_lval option) = - let visitor = replacement_visitor fa_terms ret_opt in +let treat_pred replace_pre pred fa_terms (ret_opt : term_lval option) = + let visitor = replacement_visitor replace_pre fa_terms ret_opt in visitCilPredicate (visitor :> cilVisitor) pred -let treat_term trm fa_terms ret_opt = - let visitor = replacement_visitor fa_terms ret_opt in +let treat_term replace_pre trm fa_terms ret_opt = + let visitor = replacement_visitor replace_pre fa_terms ret_opt in visitCilTerm (visitor :> cilVisitor) trm (* AST inplace visitor for runtime annotation generation *) @@ -1437,10 +1450,13 @@ module H = Hashtbl module HStmt = Cil_datatype.Stmt.Hashtbl +exception NontreatedAssign +exception DontKeep + class rte_annot_visitor kf = object(self) inherit Visitor.frama_c_inplace (* inplace since no Ast transformation: - only annotations are added *) + only annotations are added *) val mutable skip_set = SkipIdSet.empty val mutable index_behavior = 0 @@ -1481,86 +1497,73 @@ method private is_ConstFold () = Parameter_map.is_true ConstFold.name other_optionTbl - method private queue_stmt_spec _kf spec = + method private queue_stmt_spec spec = let stmt = Extlib.the (self#current_stmt) in + let kf = Extlib.the self#current_kf in Queue.add (fun () -> let annot = - Logic_const.new_code_annotation (AStmtSpec (*stmt_*)spec) + Logic_const.new_code_annotation (AStmtSpec ([],spec)) in - Annotations.add - stmt - [ precond_dep_state ] - (Db_types.Before (Db_types.User annot)) - ) self#get_filling_actions + Annotations.add kf stmt [ precond_dep_state ] (User annot)) + self#get_filling_actions - method private queue_assertion ?(pos = Before) assertion_list = - (* add an assertion (with an optionally given status) in front of current statement *) + method private queue_assertion assertion_list = + (* add an assertion (with an optionally given status) in front of current + statement *) match assertion_list with - | [] -> () - | _ -> - let stmt = Extlib.the (self#current_stmt) in - let kf = Extlib.the (self#current_kf) in - let already_posted_assertions = - try - HStmt.find assertion_table stmt - with Not_found -> [] - in let pruned_assertion_list = - (* do not keep an assertion if an equivalent assertion (content) - is already scheduled *) - List.rev ( - List.fold_left - (fun acc (assertion, status_opt) -> - if not (List.exists - (fun p -> - Logic_utils.is_same_predicate - p assertion.content) - already_posted_assertions) - then (assertion, status_opt) :: acc - else acc - ) [] assertion_list - ) - in let loc_add_assertion assertion assertion_status_opt = - let rte_named_assertion = - (* give a name to assertion in order to indicate - it has been generated by RTE plugin *) - { content = assertion.content ; - loc = assertion.loc ; name = [ rte_prefix ] } - in let annot = - Logic_const.new_code_annotation - (AAssert ([], rte_named_assertion)) - in - Annotations.add - stmt - [ rte_dep_state ] - (match pos with - | Before -> Db_types.Before (Db_types.User annot) - | After -> - Db_types.After (Db_types.User annot) (* not used *)); - let astatus = match assertion_status_opt with - | None -> Unknown - | Some checked_status -> checked_status - in - let ip = Property.ip_of_code_annot kf stmt annot in - List.iter (fun x -> S.set x [] astatus) ip - in - (* update scheduled assertions *) - let () = HStmt.replace assertion_table stmt - (List.rev_append - (List.rev_map (fun (a,_) -> a.content) pruned_assertion_list) - already_posted_assertions) - in - Queue.add - (fun () -> - List.iter - (fun (assertion, assertion_status_opt) -> - loc_add_assertion assertion assertion_status_opt - ) pruned_assertion_list - ) self#get_filling_actions - - method private get_current_kf () = - Kernel_function.find_englobing_kf (Extlib.the (self#current_stmt)) + | [] -> () + | _ -> + let stmt = Extlib.the self#current_stmt in + let kf = Extlib.the self#current_kf in + let already_posted_assertions = + try + HStmt.find assertion_table stmt + with Not_found -> [] + in + let pruned_assertion_list = + (* do not keep an assertion if an equivalent assertion (content) + is already scheduled *) + List.rev + (List.fold_left + (fun acc (assertion, status_opt) -> + if not (List.exists + (fun p -> + Logic_utils.is_same_predicate + p assertion.content) + already_posted_assertions) + then (assertion, status_opt) :: acc + else acc) + [] + assertion_list) + in + let loc_add_assertion assertion assertion_status_opt = + let rte_named_assertion = + (* give a name to assertion in order to indicate + it has been generated by RTE plugin *) + { content = assertion.content ; + loc = assertion.loc ; name = [ rte_prefix ] } + in + let annot = + Logic_const.new_code_annotation (AAssert ([], rte_named_assertion)) + in + Annotations.add kf stmt [ rte_dep_state ] (User annot); + let ip = Property.ip_of_code_annot kf stmt annot in + List.iter(fun x -> emit_status x assertion_status_opt) ip + in + (* update scheduled assertions *) + HStmt.replace assertion_table stmt + (List.rev_append + (List.rev_map (fun (a,_) -> a.content) pruned_assertion_list) + already_posted_assertions); + Queue.add + (fun () -> + List.iter + (fun (assertion, assertion_status_opt) -> + loc_add_assertion assertion assertion_status_opt) + pruned_assertion_list) + self#get_filling_actions method private mk_new_behavior_name kf_callee = let error () = @@ -1568,206 +1571,253 @@ error "Generated too many behavior names." ; assert false in - let kf = self#get_current_kf () (* get englobing kf *) + let kf = Extlib.the self#current_kf (* get englobing kf *) in let known_behaviors = Kernel_function.all_function_behaviors kf - in let rec aux_new_name i = - let name = - precond_prefix ^ "_" ^ - (Kernel_function.get_name kf_callee) ^ "_" ^ (string_of_int i) - in if List.mem name known_behaviors then ( - let nindex = i + 1 - in if nindex = 0 then error () + in let rec aux_new_name i = + (* [JS 20110607] seem to be equivalent to + Kernel_function.fresh_behavior_name *) + let name = + precond_prefix ^ "_" ^ + (Kernel_function.get_name kf_callee) ^ "_" ^ (string_of_int i) + in if List.mem name known_behaviors then ( + let nindex = i + 1 + in if nindex = 0 then error () (* if index becomes 0 (again): serious problem, but unlikely to happen *) - else aux_new_name nindex - ) else (name, i) - in - let (name, new_index) = - try - let i = H.find bhv_index_table kf - in - let nindex = i+1 - in if nindex = 0 then error () - else aux_new_name nindex - with Not_found -> - aux_new_name 0 - in - H.replace bhv_index_table kf new_index ; - name + else aux_new_name nindex + ) else (name, i) + in + let (name, new_index) = + try + let i = H.find bhv_index_table kf + in + let nindex = i+1 + in if nindex = 0 then error () + else aux_new_name nindex + with Not_found -> + aux_new_name 0 + in + H.replace bhv_index_table kf new_index ; + name method private make_stmt_contract kf formals_actuals_terms ret_opt = - let tret_opt = - match ret_opt with - | None -> None - | Some lv -> Some (Logic_utils.lval_to_term_lval ~cast:true lv) + let tret_opt = match ret_opt with + | None -> None + | Some lv -> Some (Logic_utils.lval_to_term_lval ~cast:true lv) in - let fun_transform_pred p = + let fun_transform_pred replace_pre p = let p' = Logic_const.pred_of_id_pred p in try let p_unnamed = Logic_const.unamed (treat_pred + replace_pre p'.content formals_actuals_terms tret_opt) in Logic_const.new_predicate { content = p_unnamed.content ; loc = p_unnamed.loc ; - name = p'.name - } + name = p'.name } with - | AddrOfFormal - | NoResult -> - (* A warning has been emitted, we simply ignore the predicate here. *) - Logic_const.new_predicate Logic_const.ptrue + | AddrOfFormal + | NoResult -> + (* A warning has been emitted, we simply ignore the predicate here. *) + Logic_const.new_predicate Logic_const.ptrue and fun_transform_assigns assigns = (* substitute terms, then for each from extract lvals and - keep those and only those as froms *) + keep those and only those as froms *) let treat_from it = + let rec keep_it t = + match t.term_node with + | TLval _ -> true + | Tat (loc,_) -> keep_it loc + | TCastE (_,te) -> keep_it te + | Tinter locs + | Tunion locs -> ( + try + List.iter + (fun loc -> + if not(keep_it loc) then + raise DontKeep + ) locs ; + true + with DontKeep -> false ) + | _ -> false + in + (* also, discard casts in froms *) + let rec transform_term t = + match t.term_node with + | TCastE (_,te) -> transform_term te + | _ -> t + in let nterm = - treat_term it.it_content formals_actuals_terms tret_opt + treat_term Logic_const.old_label + it.it_content formals_actuals_terms tret_opt in - let visitor = tlval_fetcher_visitor () in - let _ = visitCilTerm (visitor :> cilVisitor) nterm in + if keep_it nterm then + [ Logic_const.new_identified_term (transform_term nterm) ] + else [] + (* Do not generate froms from child left values any more *) + (* + let visitor = tlval_fetcher_visitor () in + let _ = visitCilTerm (visitor :> cilVisitor) nterm in let list_tlvals = visitor#fetch_lvals () in - List.map - (fun lv -> Logic_const.new_identified_term lv) list_tlvals + List.rev_map + (fun lv -> + Logic_const.new_identified_term lv) + (List.filter keep_it list_tlvals) + *) in let treat_identified_term_zone_froms z = match z with - | FromAny -> FromAny - | From l -> From (List.flatten (List.map treat_from l)) + | FromAny -> FromAny + | From l -> + From (List.flatten (List.rev_map treat_from l)) in let treat_assign (z,lz) = - let nt = - treat_term - z.it_content formals_actuals_terms tret_opt (* should be an lval *) - in - match nt.term_node with - | TLval _ -> (* if substituted term is not an lval, - do not generate an assign *) - Some (Logic_const.new_identified_term nt, - treat_identified_term_zone_froms lz) - | _ -> None - in - let treat_assigns_list acc a = try - match treat_assign a with - | None -> acc - | Some e -> e :: acc - with - | AddrOfFormal - | NoResult -> acc - (* Ignore the location based on the address of a formal parameter. *) - + let nt = + treat_term Logic_const.old_label + z.it_content formals_actuals_terms tret_opt + (* should be an lval *) + in + (* also treat union, inter and at terms *) + match nt.term_node with + | Tat _ + | TLval _ + | Tunion _ + | Tinter _ -> + (Logic_const.new_identified_term nt, + treat_identified_term_zone_froms lz) + | _ -> raise NontreatedAssign + with + | AddrOfFormal + | NoResult -> raise NontreatedAssign in let treat_assigns_clause l = (* compute list of assigns as (terms, list of terms) ; if empty list of terms => it's a Nothing, else Location ... *) (* then process to transform assign on \result *) match l with - WritesAny -> WritesAny - | Writes l -> Writes (List.fold_left treat_assigns_list [] l) + | WritesAny -> WritesAny + | Writes l -> + try + Writes (List.rev (List.rev_map treat_assign l)) + with NontreatedAssign -> WritesAny in let final_assigns_list = match ret_opt with - | None -> - (* no return value: there should be no assign of \result *) - treat_assigns_clause assigns - | Some ret -> - let ret_type = typeOfLval ret in - let nlist_assigns = - (* if there is a assigns \at(\result,Post) \from x - replace by \assigns \result \from x *) - match assigns with - | WritesAny -> WritesAny - | Writes assigns -> - let rec change_at_result acc assgn = - match assgn with - [] -> Writes (List.rev acc) - | (a,from)::tl -> - let new_a = - match a.it_content.term_node with - | Tat ({term_node=(TLval(TResult _,_) as trm)}, - LogicLabel (_, "Post")) -> - let ttype = Ctype ret_type - (* cf. bug #559 *) - (* Logic_utils.typ_to_logic_type - ret_type *) - in - Logic_const.new_identified_term - (mk_term trm ttype) - | _ -> a - in - change_at_result ((new_a,from) :: acc) tl - in - change_at_result [] assigns - in - (* add assign on result iff no assigns(\result) already appears ; - treat_assign will then do the job *) - let add_assigns_result () = - (* add assigns \result with empty list of froms to do the job *) - let ttype = Ctype ret_type - (* bug #559 *) - (* Logic_utils.typ_to_logic_type ret_type *) - in - let nterm = mk_term (TLval (TResult ret_type, TNoOffset)) ttype in - (Logic_const.new_identified_term nterm, FromAny) - in - match nlist_assigns with - WritesAny -> WritesAny - | Writes l when - List.exists - (fun (a,_) -> Logic_utils.is_result a.it_content) l - -> - nlist_assigns - | Writes l -> Writes (add_assigns_result()::l) - in treat_assigns_clause final_assigns_list + | None -> + (* no return value: there should be no assign of \result *) + assigns + | Some ret -> + let ret_type = typeOfLval ret in + let nlist_assigns = + (* if there is a assigns \at(\result,Post) \from x + replace by assigns \result \from x *) + match assigns with + | WritesAny -> WritesAny + | Writes assigns -> + let rec change_at_result acc assgn = + match assgn with + [] -> Writes (List.rev acc) + | (a,from)::tl -> + let new_a = + match a.it_content.term_node with + | Tat ({term_node=(TLval(TResult _,_) as trm)}, + LogicLabel (_, "Post")) -> + let ttype = Ctype ret_type + (* cf. bug #559 *) + (* Logic_utils.typ_to_logic_type + ret_type *) + in + Logic_const.new_identified_term + (mk_term trm ttype) + | _ -> a + in + change_at_result ((new_a,from) :: acc) tl + in + change_at_result [] assigns + in + (* add assign on result iff no assigns(\result) already appears ; + treat_assign will then do the job *) + let add_assigns_result () = + (* add assigns \result with empty list of froms to do the job *) + let ttype = Ctype ret_type + (* bug #559 *) + (* Logic_utils.typ_to_logic_type ret_type *) + in + let nterm = mk_term (TLval (TResult ret_type, TNoOffset)) ttype in + (Logic_const.new_identified_term nterm, FromAny) + in + match nlist_assigns with + | WritesAny -> WritesAny + | Writes l when + List.exists + (fun (a,_) -> Logic_utils.is_result a.it_content) l + -> + nlist_assigns + | Writes l -> Writes (add_assigns_result()::l) + in + treat_assigns_clause final_assigns_list and behaviors = (* calling get_spec on a function with a contract but no code generates default assigns *) (Kernel_function.get_spec kf).spec_behavior in - try - let new_behaviors = - List.fold_left - (fun acc bhv -> - (mk_behavior - ~name:(self#mk_new_behavior_name kf) - ~post_cond:(List.map - (fun (k,p) -> (k,fun_transform_pred p)) bhv.b_post_cond) - ~assumes:(List.map fun_transform_pred bhv.b_assumes) - ~requires:(List.map fun_transform_pred bhv.b_requires) - ~assigns:(fun_transform_assigns bhv.b_assigns) - ~extended:[] ())::acc - ) [] behaviors - in - if new_behaviors <> [] then - let spec = { spec_behavior = List.rev new_behaviors ; - spec_variant = None ; - spec_terminates = None ; - spec_complete_behaviors = [] ; - spec_disjoint_behaviors = [] - } - in Some spec - else None - with Exit -> None + try + let new_behaviors = + List.fold_left + (fun acc bhv -> + let b = + mk_behavior + ~name:(self#mk_new_behavior_name kf) + ~post_cond:(List.map + (fun (k,p) -> k, + fun_transform_pred Logic_const.old_label p) + bhv.b_post_cond) + ~assumes:(List.map + (fun_transform_pred Logic_const.here_label) + bhv.b_assumes) + ~requires:(List.map + (fun_transform_pred Logic_const.here_label) + bhv.b_requires) + ~assigns:(fun_transform_assigns bhv.b_assigns) + ~extended:[] + () + in + b :: acc) + [] + behaviors + in + (match new_behaviors with + | [] -> None + | _ :: _ -> + Some + { spec_behavior = List.rev new_behaviors ; + spec_variant = None ; + spec_terminates = None ; + spec_complete_behaviors = [] ; + spec_disjoint_behaviors = [] }) + with Exit -> None method vinst vi = (* assigned left values are checked for valid access *) match vi with - | Set (lval,_,_) -> - if self#is_DoMemAccess () then - self#queue_assertion (get_lval_assertion lval) - ; + | Set (lval,_,_) -> + if self#is_DoMemAccess () then + self#queue_assertion (get_lval_assertion lval) + ; + DoChildren + | Call (ret_opt,funcexp,argl,_) -> ( + if not(self#is_DoCalledPrecond ()) then DoChildren - | Call (ret_opt,funcexp,argl,_) -> ( - if not(self#is_DoCalledPrecond ()) then - DoChildren - else - match funcexp.enode with - | Lval (Var vinfo,NoOffset) -> - let kf = Globals.Functions.get vinfo in - let formals = Kernel_function.get_formals kf in + else + match funcexp.enode with + | Lval (Var vinfo,NoOffset) -> + let kf = Globals.Functions.get vinfo in + let do_no_implicit_cast () = + let formals = Kernel_function.get_formals kf in if (List.length formals <> List.length argl) then ( rte_warn "(%a) function call with # actuals <> # formals: not treated" @@ -1778,189 +1828,220 @@ let formals_actuals_terms = List.rev_map2 (fun formal arg_exp -> - (formal, - Logic_utils.expr_to_term ~cast:true arg_exp) + (formal, + Logic_utils.expr_to_term ~cast:true arg_exp) ) formals argl in - match self#make_stmt_contract kf formals_actuals_terms ret_opt with - | None -> DoChildren - | Some contract_stmt -> - self#queue_stmt_spec kf contract_stmt - ; - DoChildren + match self#make_stmt_contract kf formals_actuals_terms ret_opt with + | None -> DoChildren + | Some contract_stmt -> + self#queue_stmt_spec contract_stmt + ; + DoChildren ) - | Lval (Mem _,NoOffset) -> - rte_warn "(%a) function called through a pointer: not treated" - d_stmt (Extlib.the (self#current_stmt)) - ; - DoChildren - | _ -> assert false - ) - | _ -> DoChildren + in ( + match ret_opt with + | None -> do_no_implicit_cast () + | Some lv -> + let kf_ret_type = Kernel_function.get_return_type kf + and lv_type = Cil.typeOfLval lv in + if Cil.need_cast kf_ret_type lv_type then ( + rte_warn "(%a) function call with intermediate cast: not treated" + d_stmt (Extlib.the (self#current_stmt)) + ; + DoChildren + ) + else do_no_implicit_cast () + ) + | Lval (Mem _,NoOffset) -> + rte_warn "(%a) function called through a pointer: not treated" + d_stmt (Extlib.the (self#current_stmt)) + ; + DoChildren + | _ -> assert false + ) + | _ -> DoChildren method vexpr exp = debug "considering exp %a\n" Cil.d_exp exp ; match exp.enode with - | BinOp((Div|Mod) as op,dividend,divisor,TInt(kind,_)) -> - (* add assertion "divisor not zero" *) - if self#is_DoDivMod () then + | BinOp((Div|Mod) as op,dividend,divisor,TInt(kind,_)) -> + (* add assertion "divisor not zero" *) + if self#is_DoDivMod () then + self#queue_assertion + (get_divmod_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + divisor) + ; + if (self#is_DoSignedOverflow ()) && (op = Div) && (isSigned kind) then + begin + (* treat the special case of signed division overflow + (no signed modulo overflow) *) self#queue_assertion - (get_divmod_assertion + (get_signed_div_assertion ~simplify_constants:(self#is_ConstFold ()) ~warning:(self#is_Warning ()) - divisor) - ; - if (self#is_DoSignedOverflow ()) && (op = Div) && (isSigned kind) then - begin - (* treat the special case of signed division overflow - (no signed modulo overflow) *) - self#queue_assertion - (get_signed_div_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - dividend divisor) - - end - ; - DoChildren + dividend divisor) + end + ; + DoChildren - | BinOp((Shiftlt|Shiftrt) as shiftop,loperand,roperand,TInt(kind,_)) -> + | BinOp((Shiftlt|Shiftrt) as shiftop,loperand,roperand,TInt(kind,_)) -> - if self#is_DoSignedOverflow () || self#is_DoUnsignedOverflow () then ( - let (a, isOk) = - (* generate and check assertion on right operand of shift *) - get_bitwise_shift_right_operand_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - exp roperand - in - self#queue_assertion a ; - if isOk (* right operand is correct: - otherwise no need to proceed with other assertions *) - then - ( - (* assertions specific to signed shift *) - if (self#is_DoSignedOverflow ()) && (isSigned kind) then ( + if self#is_DoSignedOverflow () || self#is_DoUnsignedOverflow () then ( + let (a, isOk) = + (* generate and check assertion on right operand of shift *) + get_bitwise_shift_right_operand_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + exp roperand + in + self#queue_assertion a ; + if isOk (* right operand is correct: + otherwise no need to proceed with other assertions *) + then + ( + (* assertions specific to signed shift *) + if (self#is_DoSignedOverflow ()) && (isSigned kind) then ( + self#queue_assertion + (get_bitwise_shift_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + exp shiftop loperand roperand) + ) + ; + (* assertions specific to unsigned shift *) + if self#is_DoUnsignedOverflow () && + (shiftop = Shiftlt) && not(isSigned kind) then ( self#queue_assertion - (get_bitwise_shift_assertion + (get_bitwise_lshift_unsigned_assertion ~simplify_constants:(self#is_ConstFold ()) ~warning:(self#is_Warning ()) - exp shiftop loperand roperand) - ) - ; - - (* assertions specific to unsigned shift *) - if self#is_DoUnsignedOverflow () && - (shiftop = Shiftlt) && not(isSigned kind) then ( - self#queue_assertion - (get_bitwise_lshift_unsigned_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - exp loperand roperand) - ) - ) - ) - ; - DoChildren - - | BinOp((PlusA|MinusA|Mult) - as op,loperand,roperand,TInt(kind,_)) when (isSigned kind) -> - (* may be skipped if enclosing expression is a downcast to a signed type *) - if (self#is_DoSignedOverflow ()) && - not(self#is_in_skip_set exp.eid SkipBounding) then - self#queue_assertion - (get_multsubadd_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - exp op loperand roperand) - ; - DoChildren - - | BinOp((PlusA|MinusA|Mult) - as op,loperand,roperand,TInt(kind,_)) when not(isSigned kind) -> - if self#is_DoUnsignedOverflow () then - self#queue_assertion - (get_multsubadd_unsigned_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - exp op loperand roperand) - ; - DoChildren + exp loperand roperand) + ) + ) + ) + ; + DoChildren - | UnOp(Neg,operand,TInt(kind,_)) when (isSigned kind) -> - if self#is_DoSignedOverflow () then - self#queue_assertion - (get_uminus_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - operand) - ; - DoChildren + | BinOp((PlusA|MinusA|Mult) + as op,loperand,roperand,TInt(kind,_)) when (isSigned kind) -> + (* may be skipped if enclosing expression is a downcast to a signed type *) + if (self#is_DoSignedOverflow ()) && + not(self#is_in_skip_set exp.eid SkipBounding) then + self#queue_assertion + (get_multsubadd_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + exp op loperand roperand) + ; + DoChildren + | BinOp((PlusA|MinusA|Mult) + as op,loperand,roperand,TInt(kind,_)) when not(isSigned kind) -> + if self#is_DoUnsignedOverflow () then + self#queue_assertion + (get_multsubadd_unsigned_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + exp op loperand roperand) + ; + DoChildren - (* Note: if unary minus on unsigned integer is to be understood as - "subtracting the promoted value from the largest value - of the promoted type and adding one" - the result is always representable so no overflow - *) - - | Lval lval -> - (* left values are checked for valid access *) - if self#is_DoMemAccess () then ( - debug "exp %a is an lval: validity of potential mem access checked\n" - Cil.d_exp exp ; - self#queue_assertion (get_lval_assertion lval) - ) - ; - DoChildren + | UnOp(Neg,operand,TInt(kind,_)) when (isSigned kind) -> + if self#is_DoSignedOverflow () then + self#queue_assertion + (get_uminus_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + operand) + ; + DoChildren - | CastE (TInt (kind,_) as typ, e) when (isSigned kind) -> - if self#is_DoDownCast () then ( - let downcast_asserts = - get_downcast_assertion - ~simplify_constants:(self#is_ConstFold ()) - ~warning:(self#is_Warning ()) - typ e - in match downcast_asserts with - | [] -> () - | _ -> - self#queue_assertion downcast_asserts - ; - self#add_to_skip_set e.eid SkipBounding - (* expression should be skipped w.r.t - signed mult/add/sub arithmetic overflow *) - ) - ; - DoChildren + (* Note: if unary minus on unsigned integer is to be understood as + "subtracting the promoted value from the largest value + of the promoted type and adding one" + the result is always representable so no overflow + *) + + | Lval lval -> + (* left values are checked for valid access *) + if self#is_DoMemAccess () then ( + debug "exp %a is an lval: validity of potential mem access checked\n" + Cil.d_exp exp ; + self#queue_assertion (get_lval_assertion lval) + ) + ; + DoChildren + | CastE (TInt (kind,_) as typ, e) when (isSigned kind) -> + if self#is_DoDownCast () then ( + let downcast_asserts = + get_downcast_assertion + ~simplify_constants:(self#is_ConstFold ()) + ~warning:(self#is_Warning ()) + typ e + in match downcast_asserts with + | [] -> () + | _ -> + self#queue_assertion downcast_asserts + ; + self#add_to_skip_set e.eid SkipBounding + (* expression should be skipped w.r.t + signed mult/add/sub arithmetic overflow *) + ) + ; + DoChildren + (* removed, see BTS#567: no point in asserting validity + of first cell of an array simply because its address + is taken as &tab[0] *) + (* | StartOf _lval -> - if self#is_DoMemAccess () then - self#queue_assertion - [ (Logic_const.pvalid (translate_C_expr_to_term ~cast:false exp), None) ] - ; - DoChildren - - | AddrOf _ - | Info _ - | UnOp _ - | Const _ - | CastE _ - | BinOp _ -> DoChildren - - - | SizeOf _ - | SizeOfE _ - | SizeOfStr _ - | AlignOf _ - | AlignOfE _ -> SkipChildren + if self#is_DoMemAccess () then + self#queue_assertion + [ (Logic_const.pvalid (translate_C_expr_to_term ~cast:false exp), None) ] + ; + DoChildren + *) + | StartOf _ + | AddrOf _ + | Info _ + | UnOp _ + | Const _ + | CastE _ + | BinOp _ -> DoChildren + + + | SizeOf _ + | SizeOfE _ + | SizeOfStr _ + | AlignOf _ + | AlignOfE _ -> SkipChildren end let remove_annotations_kf kf = + (* [JS 2011/08/04] fix bug #910: + new implementation now requires to remove by hand annotations. *) + let annotations = Kernel_function.code_annotations kf in + let must_keep _ state _ = match state with + | None -> true + | Some s -> + not (State.equal s (RteAnnotTbl.get_state kf) + || State.equal s (PrecondAnnotTbl.get_state kf)) + in + List.iter + (fun (stmt, _) -> + (* [false] because [Project.clear] is still applied *) + Annotations.filter ~reset:false must_keep kf stmt) + annotations; + (* JS: still keep [Project.clear] because I don't know if it clears something + else than annotations. If it is not the case, it can safely be removed *) (* remove annotations dependant on function (in fact all dependencies*) let s = RteGlobalTbl.get_state kf in - Project.clear ~selection:(State_selection.Dynamic.only_dependencies s) () + Project.clear ~selection:(State_selection.Dynamic.only_dependencies s) () let is_computed_kf kf = (* check whether annotations are computed for function kf @@ -1968,20 +2049,20 @@ match kf.fundec with | Declaration _ -> true | Definition _ -> - (* check whether options have changed for function kf *) - let old_gen_opts = StateManager.find_current_gen_options kf - and new_gen_opts = Parameter_map.gen_from_command_line_options () - and old_other_opts = StateManager.find_current_other_options kf - and new_other_opts = Parameter_map.other_from_command_line_options () - in - (* case 1: generating options have changed *) - Parameter_map.compare old_gen_opts new_gen_opts <> 0 - || - (* case 2: no generating option has changed, but the user wants to - generate the same annotations with const folding, warning - enabled ... *) - (Parameter_map.is_one_true ~except:None new_gen_opts && - Parameter_map.compare old_other_opts new_other_opts <> 0) + (* check whether options have changed for function kf *) + let old_gen_opts = StateManager.find_current_gen_options kf + and new_gen_opts = Parameter_map.gen_from_command_line_options () + and old_other_opts = StateManager.find_current_other_options kf + and new_other_opts = Parameter_map.other_from_command_line_options () + in + (* case 1: generating options have changed *) + Parameter_map.compare old_gen_opts new_gen_opts <> 0 + || + (* case 2: no generating option has changed, but the user wants to + generate the same annotations with const folding, warning + enabled ... *) + (Parameter_map.is_one_true ~except:None new_gen_opts && + Parameter_map.compare old_other_opts new_other_opts <> 0) let annotate_kf_with kf new_gen_opts new_other_opts = (* generates annotation for function kf @@ -1993,11 +2074,11 @@ match kf.fundec with | Declaration _ -> () | Definition (f,_) -> - remove_annotations_kf kf ; - let vis = new rte_annot_visitor kf - (* (StateManager.find_current_gen_options kf) *) - in let _nkf = Visitor.visitFramacFunction vis f in - assert(_nkf == f) + remove_annotations_kf kf ; + let vis = new rte_annot_visitor kf + (* (StateManager.find_current_gen_options kf) *) + in let _nkf = Visitor.visitFramacFunction vis f in + assert(_nkf == f) in let old_gen_opts = StateManager.find_current_gen_options kf and old_other_opts = StateManager.find_current_other_options kf @@ -2006,36 +2087,36 @@ (* case 1: generating options have changed *) Parameter_map.compare old_gen_opts new_gen_opts <> 0 || - (* case 2: no generating option has changed, - but the user wants to generate the same annotations with const - folding, warning enabled ... *) - (Parameter_map.is_one_true ~except:None new_gen_opts && - Parameter_map.compare old_other_opts new_other_opts <> 0) + (* case 2: no generating option has changed, + but the user wants to generate the same annotations with const + folding, warning enabled ... *) + (Parameter_map.is_one_true ~except:None new_gen_opts && + Parameter_map.compare old_other_opts new_other_opts <> 0) then begin (* options have changed for function kf: there is some work to do *) debug "Options have changed: something to do for function %s" - (Kernel_function.get_name kf) ; + (Kernel_function.get_name kf) ; (* update analysis options for function kf *) StateManager.FuncOptionTbl.replace kf (new_gen_opts, new_other_opts) ; if Parameter_map.is_one_true ~except:None new_gen_opts then begin - (* there may be new annotations to add and remove *) - feedback "annotating function %s" (Kernel_function.get_name kf) ; - do_annotate_kf kf ; - (* set status of rte/precond generation (see properties_status.mli) *) - List.iter - (fun (opt_name, _opt_get, _, property_set) -> - property_set kf (Parameter_map.is_true opt_name new_gen_opts)) - Parameter_map.generating_opts + (* there may be new annotations to add and remove *) + feedback "annotating function %s" (Kernel_function.get_name kf) ; + do_annotate_kf kf ; + (* set status of rte/precond generation (see properties_status.mli) *) + List.iter + (fun (opt_name, _opt_get, _, property_set) -> + property_set kf (Parameter_map.is_true opt_name new_gen_opts)) + Parameter_map.generating_opts end else begin - (* all annotations should be removed *) - (* and RTE_Generated / Called_Precond_Generated are reset *) - feedback "unannotating function %s" (Kernel_function.get_name kf) ; - (* reset status of rte/precond generation *) - List.iter - (fun (_opt_name, _opt_get, _, property_set) -> - property_set kf false) - Parameter_map.generating_opts; - remove_annotations_kf kf + (* all annotations should be removed *) + (* and RTE_Generated / Called_Precond_Generated are reset *) + feedback "unannotating function %s" (Kernel_function.get_name kf) ; + (* reset status of rte/precond generation *) + List.iter + (fun (_opt_name, _opt_get, _, property_set) -> + property_set kf false) + Parameter_map.generating_opts; + remove_annotations_kf kf end end @@ -2062,8 +2143,8 @@ | Definition _ -> (* check whether options have changed for function kf *) annotate_kf_with kf - (Parameter_map.gen_from_command_line_options ()) - (Parameter_map.other_from_command_line_options ()) + (Parameter_map.gen_from_command_line_options ()) + (Parameter_map.other_from_command_line_options ()) let is_computed () = (* check whether annotations are computed for the @@ -2075,20 +2156,20 @@ let fsel = FunctionSelection.get () in Datatype.String.Set.is_empty fsel || let name = Kernel_function.get_name kf in - Datatype.String.Set.mem name fsel + Datatype.String.Set.mem name fsel in try - Globals.Functions.iter - (fun kf -> - if include_function kf then - begin - match kf.fundec with - | Declaration _ -> () - | Definition _ -> if not(is_computed_kf kf) then raise Exit - end - ) - ; - true + Globals.Functions.iter + (fun kf -> + if include_function kf then + begin + match kf.fundec with + | Declaration _ -> () + | Definition _ -> if not(is_computed_kf kf) then raise Exit + end + ) + ; + true with Exit -> false let compute () = @@ -2103,9 +2184,9 @@ Globals.Functions.iter (fun kf -> if include_function kf then begin - match kf.fundec with - | Declaration _ -> () - | Definition _ -> !Db.RteGen.annotate_kf kf + match kf.fundec with + | Declaration _ -> () + | Definition _ -> !Db.RteGen.annotate_kf kf end) let () = @@ -2159,7 +2240,7 @@ (* let do_precond = Dynamic.register - ~plugin:"rte" + ~plugin:"RteGen" "do_precond" (Datatype.func Kernel_function.ty @@ -2205,22 +2286,22 @@ module M6 = RTE_UnsignedOverflow_Generated let get_all_status () = - [ (M1.self, M1.get_state, M1.get); - (M2.self, M2.get_state, M2.get); - (M3.self, M3.get_state, M3.get); - (M4.self, M4.get_state, M4.get); - (M5.self, M5.get_state, M5.get); - (M6.self, M6.get_state, M6.get); + [ (M1.self, M1.get_state, M1.get, M1.set); + (M2.self, M2.get_state, M2.get, M2.set); + (M3.self, M3.get_state, M3.get, M3.set); + (M4.self, M4.get_state, M4.get, M4.set); + (M5.self, M5.get_state, M5.get, M5.set); + (M6.self, M6.get_state, M6.get, M6.set); ] let () = Db.register - Db.Journalization_not_required + Db.Journalization_not_required Db.RteGen.get_all_status get_all_status let get_precond_status () = - (M5.self, M5.get_state, M5.get) + (M5.self, M5.get_state, M5.get, M5.set) let () = Db.register @@ -2229,16 +2310,16 @@ get_precond_status let get_signedOv_status () = - (M1.self, M1.get_state, M1.get) + (M1.self, M1.get_state, M1.get, M1.set) let () = Db.register - Db.Journalization_not_required + Db.Journalization_not_required Db.RteGen.get_signedOv_status get_signedOv_status let get_divMod_status () = - (M3.self, M3.get_state, M3.get) + (M3.self, M3.get_state, M3.get, M3.set) let () = Db.register @@ -2247,25 +2328,25 @@ get_divMod_status let get_downCast_status () = - (M4.self, M4.get_state, M4.get) + (M4.self, M4.get_state, M4.get, M4.set) let () = Db.register - Db.Journalization_not_required + Db.Journalization_not_required Db.RteGen.get_downCast_status get_downCast_status let get_memAccess_status () = - (M2.self, M2.get_state, M2.get) + (M2.self, M2.get_state, M2.get, M2.set) let () = Db.register - Db.Journalization_not_required + Db.Journalization_not_required Db.RteGen.get_memAccess_status get_memAccess_status let get_unsignedOv_status () = - (M6.self, M6.get_state, M6.get) + (M6.self, M6.get_state, M6.get, M6.set) let () = Db.register @@ -2279,7 +2360,7 @@ (* all rte + precond *) let get_global_state = Dynamic.register - ~plugin:"rte" + ~plugin:"RteGen" "get_global_state" (Datatype.func Kernel_function.ty @@ -2290,7 +2371,7 @@ (* only rte (no precond) *) let get_rte_state = Dynamic.register - ~plugin:"rte" + ~plugin:"RteGen" "get_rte_state" (Datatype.func Kernel_function.ty @@ -2301,7 +2382,7 @@ (* only precond (no rte) *) let get_precond_state = Dynamic.register - ~plugin:"rte" + ~plugin:"RteGen" "get_precond_state" (Datatype.func Kernel_function.ty diff -Nru frama-c-20110201+carbon+dfsg/src/rte/rte_parameters.ml frama-c-20111001+nitrogen+dfsg/src/rte/rte_parameters.ml --- frama-c-20110201+carbon+dfsg/src/rte/rte_parameters.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/rte/rte_parameters.ml 2011-10-10 08:38:22.000000000 +0000 @@ -53,6 +53,7 @@ end) (* if DoAll is true: all other options become true, except for DoUnsignedOverflow + and "PreConds" <=> all "true" runtime error assertions are generated *) module DoAll = True @@ -107,9 +108,9 @@ (struct let option_name = "-rte-const" let help = "when on (by default), simplify assertions involving constants" - (* if on, evaluates constants in order to check if assertions - are trivially true / false *) - let kind = `Correctness + (* if on, evaluates constants in order to check if assertions + are trivially true / false *) + let kind = `Tuning end) module DoCalledPrecond = @@ -136,3 +137,9 @@ let help = "select <fun> for analysis (default all functions)" let kind = `Correctness end) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/rte/rte_parameters.mli frama-c-20111001+nitrogen+dfsg/src/rte/rte_parameters.mli --- frama-c-20110201+carbon+dfsg/src/rte/rte_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/rte/rte_parameters.mli 2011-10-10 08:38:22.000000000 +0000 @@ -22,26 +22,32 @@ include Plugin.S -module Enabled: Plugin.BOOL +module Enabled: Plugin.Bool -module DoUnsignedOverflow : Plugin.BOOL +module DoUnsignedOverflow : Plugin.Bool -module DoAll: Plugin.BOOL +module DoAll: Plugin.Bool -module Print: Plugin.BOOL +module Print: Plugin.Bool -module DoSignedOverflow : Plugin.BOOL +module DoSignedOverflow : Plugin.Bool -module DoDownCast : Plugin.BOOL +module DoDownCast : Plugin.Bool -module DoDivMod : Plugin.BOOL +module DoDivMod : Plugin.Bool -module DoMemAccess : Plugin.BOOL +module DoMemAccess : Plugin.Bool -module ConstFold : Plugin.BOOL +module ConstFold : Plugin.Bool -module Warn : Plugin.BOOL +module Warn : Plugin.Bool -module DoCalledPrecond : Plugin.BOOL +module DoCalledPrecond : Plugin.Bool -module FunctionSelection : Plugin.STRING_SET +module FunctionSelection : Plugin.String_set + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/scope/datascope.ml frama-c-20111001+nitrogen+dfsg/src/scope/datascope.ml --- frama-c-20110201+carbon+dfsg/src/scope/datascope.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/scope/datascope.ml 2011-10-10 08:38:30.000000000 +0000 @@ -26,11 +26,9 @@ * has the same value then a given starting program point L. *) open Cil_types -open Db_types -module IH = Inthash open Cil_datatype -module R : Plugin.S = +module R = Plugin.Register (struct let name = "scope" @@ -44,33 +42,34 @@ **) (** Statement identifier *) -module Sid = struct - include Datatype.Int - let default = -1 +module StmtDefault = struct + include Stmt + let default = Cil.dummyStmt end (** set of values to store for each data *) -module SidSet = struct +module StmtSetLattice = struct - include Abstract_interp.Make_Lattice_Set(Sid) + include Abstract_interp.Make_Lattice_Set(StmtDefault) - let default _v _a _b : t = inject_singleton Sid.default - let defaultall _v : t = inject_singleton Sid.default + let default _v _a _b : t = inject_singleton StmtDefault.default + let defaultall _v : t = inject_singleton StmtDefault.default let empty = bottom let cardinal set = fold (fun _ n -> n+1) set 0 - let single sid = inject_singleton sid + let single s = inject_singleton s let to_list ~keep_default set = - fold (fun n l -> if (n = Sid.default) && not keep_default then l else n::l) + fold + (fun n l -> if (n = StmtDefault.default) && not keep_default then l else n::l) set [] - let add sid set = join set (single sid) + let add s set = join set (single s) end (** A place to map each data to the state of statements that modify it. *) module InitSid = struct - module LM = Lmap_bitwise.Make_bitwise (SidSet) + module LM = Lmap_bitwise.Make_bitwise (StmtSetLattice) type t = LM.t @@ -78,7 +77,7 @@ let find = LM.find let add_zone ~exact lmap zone sid = - let new_val = SidSet.single sid in + let new_val = StmtSetLattice.single sid in let lmap = LM.add_binding exact lmap zone new_val in lmap @@ -91,14 +90,14 @@ Format.fprintf fmt "Lmap = %a@\n" LM.pretty lmap end -let get_lval_zones stmt lval = +let get_lval_zones ~for_writing stmt lval = let dpds, loc = !Db.Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode (Kstmt stmt) ~deps:Locations.Zone.bottom lval in - let zone = Locations.valid_enumerate_bits loc in - let exact = Locations.valid_cardinal_zero_or_one loc in + let zone = Locations.valid_enumerate_bits ~for_writing loc in + let exact = Locations.valid_cardinal_zero_or_one ~for_writing loc in dpds, exact, zone (** Add to [stmt] to [lmap] for all the locations modified by the statement. @@ -107,7 +106,7 @@ let register_modified_zones lmap stmt inst = let register lmap zone = (* [exact] should always be false because we want to store all the stmts *) - InitSid.add_zone ~exact:false lmap zone stmt.sid + InitSid.add_zone ~exact:false lmap zone stmt in let process_froms lmap froms = let from_table = froms.Function_Froms.deps_table in @@ -120,13 +119,16 @@ in match inst with | Set (lval, _, _) -> - let _dpds, _exact, zone = get_lval_zones stmt lval in - register lmap zone + let _dpds, _, zone = + get_lval_zones ~for_writing:true stmt lval + in + register lmap zone | Call (lvaloption,funcexp,_args,_) -> begin let lmap = match lvaloption with None -> lmap | Some lval -> - let _dpds, _exact, zone = get_lval_zones stmt lval in + let _dpds, _, zone = + get_lval_zones ~for_writing:true stmt lval in register lmap zone in try @@ -141,7 +143,7 @@ Kernel_function.Hptset.fold (fun kf lmap -> process_froms lmap (!Db.From.get kf)) called_functions - lmap + lmap end | _ -> lmap @@ -150,10 +152,10 @@ * @raise Kernel_function.No_Definition if [kf] has no definition *) let compute kf = - R.debug ~level:1 "computing for function %a" Kernel_function.pretty_name kf; + R.debug ~level:1 "computing for function %a" Kernel_function.pretty kf; let f = Kernel_function.get_definition kf in let do_stmt lmap s = - if Db.Value.is_accessible (Kstmt s) then + if Db.Value.is_reachable_stmt s then match s.skind with | Instr i -> register_modified_zones lmap s i | _ -> lmap @@ -198,25 +200,26 @@ val pretty : Format.formatter -> t -> unit end) = struct + type key = stmt type data = S.t - type t = data IH.t + type t = data Stmt.Hashtbl.t - let states:t = IH.create 50 - let clear () = IH.clear states + let states:t = Stmt.Hashtbl.create 50 + let clear () = Stmt.Hashtbl.clear states - let add = IH.add states - let find = IH.find states - let mem = IH.mem states - let find = IH.find states - let replace = IH.replace states - let add = IH.add states - let iter f = IH.iter f states - let fold f = IH.fold f states - let length () = IH.length states + let add = Stmt.Hashtbl.add states + let find = Stmt.Hashtbl.find states + let mem = Stmt.Hashtbl.mem states + let find = Stmt.Hashtbl.find states + let replace = Stmt.Hashtbl.replace states + let add = Stmt.Hashtbl.add states + let iter f = Stmt.Hashtbl.iter f states + let fold f = Stmt.Hashtbl.fold f states + let length () = Stmt.Hashtbl.length states let pretty fmt infos = - IH.iter - (fun k v -> Format.fprintf fmt "Stmt:%d\n%a\n======" k S.pretty v) + Stmt.Hashtbl.iter + (fun k v -> Format.fprintf fmt "Stmt:%d\n%a\n======" k.sid S.pretty v) infos end @@ -247,12 +250,12 @@ let backward_data_scope allstmts modif_stmts s = States.clear (); - List.iter (fun s -> States.add s.sid State.NotSeen) allstmts; - let modified s = SidSet.mem s.sid modif_stmts in - States.replace s.sid State.Start; + List.iter (fun s -> States.add s State.NotSeen) allstmts; + let modified s = StmtSetLattice.mem s modif_stmts in + States.replace s State.Start; let stmts = s.preds in let module Computer = BackwardScope (struct let modified = modified end) in - let module Compute = Dataflow.BackwardsDataFlow(Computer) in + let module Compute = Dataflow.Backwards(Computer) in Compute.compute stmts module ForwardScope (X : sig val modified : stmt -> bool end ) = struct @@ -269,8 +272,9 @@ if state = State.Start then State.SameVal else state let combinePredecessors _stmt ~old new_ = - assert (R.verify (new_ <> State.Start) - "forward traversal shouldn't go through Start !"); + if new_ = State.Start then + R.error "forward traversal shouldn't go through Start, stmt %d, prev %a !" + _stmt.sid State.pretty old; State.test_and_merge ~old new_ let doStmt _stmt _state = Dataflow.SDefault @@ -288,20 +292,20 @@ let forward_data_scope modif_stmts s = States.clear (); - let modified s = SidSet.mem s.sid modif_stmts in + let modified s = StmtSetLattice.mem s modif_stmts in let module Computer = ForwardScope (struct let modified = modified end) in - let module Compute = Dataflow.ForwardsDataFlow(Computer) in - States.replace s.sid State.Start; + let module Compute = Dataflow.Forwards(Computer) in + States.replace s State.Start; Compute.compute [s] -let add_s sid acc = - let s, _ = Kernel_function.find_from_sid sid in - (* we add only 'simple' statements *) - match s.skind with - | Instr _ | Return _ | Continue _ | Break _ | Goto _ +(* XXX *) +let add_s s acc = + (* we add only 'simple' statements *) + match s.skind with + | Instr _ | Return _ | Continue _ | Break _ | Goto _ -> Stmt.Set.add s acc - | Block _ | Switch _ | If _ | UnspecifiedSequence _ | Loop _ - | TryExcept _ | TryFinally _ + | Block _ | Switch _ | If _ | UnspecifiedSequence _ | Loop _ + | TryExcept _ | TryFinally _ -> acc (** Do backward and then forward propagations and compute the 3 statement sets : @@ -310,17 +314,17 @@ * - backward only. *) let find_scope allstmts modif_stmts s = - let add fw sid x acc = + let add fw s' x acc = match x with | State.Start -> - if fw then add_s sid acc + if fw then add_s s' acc else let x = - List.fold_left (fun x s -> State.merge x (States.find s.sid)) + List.fold_left (fun x s -> State.merge x (States.find s)) State.NotSeen s.succs - in let x = State.transfer (SidSet.mem sid modif_stmts) x in - if x = State.SameVal then add_s sid acc else acc - | State.SameVal -> add_s sid acc + in let x = State.transfer (StmtSetLattice.mem s' modif_stmts) x in + if x = State.SameVal then add_s s' acc else acc + | State.SameVal -> add_s s' acc | _ -> acc in let _ = backward_data_scope allstmts modif_stmts s in @@ -339,7 +343,7 @@ * @raise Kernel_function.No_Definition if [kf] has no definition *) let get_data_scope_at_stmt kf stmt lval = - let dpds, _exact, zone = get_lval_zones stmt lval in + let dpds, _, zone = get_lval_zones ~for_writing:false stmt lval in (* TODO : is there something to do with 'exact' ? *) let zone = Locations.Zone.join dpds zone in let allstmts, info = compute kf in @@ -354,8 +358,8 @@ (* stmt at *) Locations.Zone.pretty zone stmt.sid (* modified by *) - (Cilutil.print_list Cilutil.space Sid.pretty) - (SidSet.to_list ~keep_default:false modif_stmts) + (Cilutil.pretty_list (Cilutil.space_sep " ") Stmt.pretty_sid) + (StmtSetLattice.to_list ~keep_default:false modif_stmts) (* scope *) Stmt.Set.pretty f_scope Stmt.Set.pretty fb_scope @@ -378,9 +382,9 @@ raise ToDo in let (info, _), _ = - !Db.Properties.Interp.To_zone.from_stmt_annot annot - ~before:true (stmt, kf) - in match info with + !Db.Properties.Interp.To_zone.from_stmt_annot annot (stmt, kf) + in + match info with | None -> raise ToDo | Some info -> let zone = List.fold_left add_zone Locations.Zone.bottom info in @@ -406,7 +410,7 @@ let check_stmt_annots pred s acc = let check acc annot = match annot with - | Before (AI (_, ({annot_content= AAssert (_, p) } as annot))) -> + | (AI (_, ({annot_content= AAssert (_, p) } as annot))) -> if Logic_utils.is_same_named_predicate p pred then begin let acc, added = add_annot annot acc in @@ -418,7 +422,7 @@ else acc | _ -> acc in - List.fold_left check acc (Annotations.get_filter Logic_utils.is_assert s) + List.fold_left check acc (Annotations.get_all_annotations s) (** Return the set of stmts (scope) where [annot] has the same value * than in [stmt] @@ -427,7 +431,7 @@ * *) let get_prop_scope_at_stmt kf stmt ?(to_be_removed=[]) annot = R.debug "[get_prop_scope_at_stmt] at stmt %d in %a : %a" - stmt.sid Kernel_function.pretty_name kf + stmt.sid Kernel_function.pretty kf !Ast_printer.d_code_annotation annot; let sets = (Stmt.Set.empty, to_be_removed) in @@ -441,18 +445,17 @@ | AAssert (_, p) -> p | _ -> R.abort "only 'assert' are handeled here" in - let add sid x ((acc_scope, acc_to_be_rm) as acc) = + let add s x ((acc_scope, acc_to_be_rm) as acc) = match x with - | State.Start -> (add_s sid acc_scope, acc_to_be_rm) + | State.Start -> (add_s s acc_scope, acc_to_be_rm) | State.SameVal -> - let s, _ = Kernel_function.find_from_sid sid in - if !Db.Dominators.is_dominator kf ~opening:stmt ~closing:s - then begin - let acc_scope = add_s sid acc_scope in - let acc_to_be_rm = check_stmt_annots pred s acc_to_be_rm in - (acc_scope, acc_to_be_rm) - end - else acc + if !Db.Dominators.is_dominator kf ~opening:stmt ~closing:s + then begin + let acc_scope = add_s s acc_scope in + let acc_to_be_rm = check_stmt_annots pred s acc_to_be_rm in + (acc_scope, acc_to_be_rm) + end + else acc | _ -> acc in let sets = States.fold add sets in @@ -483,7 +486,7 @@ | AAssert (_, _) -> if before then begin R.debug ~level:2 "[check] annot %d at stmt %d in %a : %a@." - annot.annot_id stmt.sid Kernel_function.pretty_name kf + annot.annot_id stmt.sid Kernel_function.pretty kf !Ast_printer.d_code_annotation annot; let _, added = add_annot annot to_be_removed in (* just check if [annot] is in [to_be_removed] : @@ -563,7 +566,7 @@ (Db.Journalize ("Scope.get_data_scope_at_stmt", Datatype.func3 - Kernel_function.ty + Kernel_function.ty Stmt.ty Lval.ty (Datatype.pair Stmt.Set.ty (Datatype.pair Stmt.Set.ty Stmt.Set.ty)))) @@ -591,3 +594,9 @@ ("Scope.rm_asserts", Datatype.func Datatype.unit Datatype.unit)) Db.Scope.rm_asserts rm_asserts; + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/scope/defs.ml frama-c-20111001+nitrogen+dfsg/src/scope/defs.ml --- frama-c-20110201+carbon+dfsg/src/scope/defs.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/scope/defs.ml 2011-10-10 08:38:30.000000000 +0000 @@ -0,0 +1,154 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* INRIA (Institut National de Recherche en Informatique et en *) +(* Automatique) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version v2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Find the statements that defines a given data at a program point, +* ie. in each backward path starting from this point, find the statement +* the the data has been assigned for the last time. *) + +open Cil_datatype +open Cil_types + +let debug1 fmt = Datascope.R.debug ~level:1 fmt +let debug2 fmt = Datascope.R.debug ~level:2 fmt + +module Interproc = + Datascope.R.True(struct + let option_name = "-scope-defs-interproc" + let help = "interprocedural defs computation" + let kind = `Tuning + end) + + +let rec add_callee_nodes acc nodes = + let new_nodes, acc = List.fold_left (fun acc2 (node,_) -> + match !Db.Pdg.node_key node with + | PdgIndex.Key.SigCallKey (cid,(PdgIndex.Signature.Out out_key)) -> + let callees = + Db.Value.call_to_kernel_function (PdgIndex.Key.call_from_id cid) + in + Kernel_function.Hptset.fold (fun kf (new_nodes, acc) -> + let callee_pdg = !Db.Pdg.get kf in + let outputs = fst (!Db.Pdg.find_output_nodes callee_pdg out_key) in + outputs @ new_nodes, outputs @ acc) + callees + acc2 + | _ -> acc2) + ([], acc) + nodes + in match new_nodes with [] -> acc + | _ -> add_callee_nodes acc new_nodes + +let rec add_caller_nodes kf acc (undef,nodes) = + let callers = !Db.Value.callers kf in + List.fold_left + (fun acc (kf,stmts) -> + let pdg = !Db.Pdg.get kf in + let acc_undef,caller_nodes = + List.fold_left (fun (acc_undef,acc) stmt -> + let nodes_for_undef, undef' = + !Db.Pdg.find_location_nodes_at_stmt pdg stmt ~before:true + undef + in + let acc_undef = match undef' with + | None -> acc_undef + | Some z -> Locations.Zone.join acc_undef z + in + List.fold_left (fun (acc_undef,acc) (node,_) -> + match !Db.Pdg.node_key node with + | PdgIndex.Key.SigKey (PdgIndex.Signature.In in_key) -> + begin match in_key with + | PdgIndex.Signature.InCtrl ->(* We only look for the values *) + acc_undef,acc + | PdgIndex.Signature.InNum n_param -> + acc_undef, + (!Db.Pdg.find_call_input_node pdg stmt n_param,None)::acc + | PdgIndex.Signature.InImpl z -> + let nodes,undef'= + !Db.Pdg.find_location_nodes_at_stmt pdg stmt ~before:true z + in + let acc_undef = match undef' with + | None -> acc_undef + | Some z -> Locations.Zone.join acc_undef z + in + + acc_undef, nodes@acc + end + | _ -> acc_undef,acc) + (acc_undef,nodes_for_undef@acc) + nodes) + (Locations.Zone.bottom,[]) + stmts + in + add_caller_nodes kf (caller_nodes@acc) (acc_undef,caller_nodes)) + acc + callers + +let compute kf stmt lval = + debug1 "[Defs.compute] for %a at sid:%d in '%a'@." + !Ast_printer.d_lval lval stmt.sid Kernel_function.pretty kf; + try + let pdg = !Db.Pdg.get kf in + let zone = !Db.Value.lval_to_zone (Kstmt stmt) + ~with_alarms:CilE.warn_none_mode lval + in + let nodes, undef = + !Db.Pdg.find_location_nodes_at_stmt pdg stmt ~before:true zone + in + let nodes = + if Interproc.get () then + begin + let caller_nodes = + add_caller_nodes kf nodes + ((match undef with None -> Locations.Zone.bottom | Some z -> z), + nodes) + in add_callee_nodes caller_nodes caller_nodes + end + else nodes + in + let add_node defs (node,_z) = + match PdgIndex.Key.stmt (!Db.Pdg.node_key node) with + | None -> defs + | Some s -> Stmt.Set.add s defs + in + (* select corresponding stmts *) + let defs = List.fold_left add_node Stmt.Set.empty nodes in + Some (defs, undef) + with Db.Pdg.Bottom | Db.Pdg.Top | Not_found -> + None + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + +let () = + Db.register (* kernel_function -> stmt -> lval -> + (Cilutil.StmtSet.t * Locations.Zone.t option) option *) + (Db.Journalize + ("Scope.get_defs", + Datatype.func3 + Kernel_function.ty + Stmt.ty + Lval.ty + (Datatype.option + (Datatype.pair Stmt.Set.ty (Datatype.option Locations.Zone.ty))))) + Db.Scope.get_defs compute + diff -Nru frama-c-20110201+carbon+dfsg/src/scope/defs.mli frama-c-20111001+nitrogen+dfsg/src/scope/defs.mli --- frama-c-20110201+carbon+dfsg/src/scope/defs.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/scope/defs.mli 2011-10-10 08:38:30.000000000 +0000 @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* INRIA (Institut National de Recherche en Informatique et en *) +(* Automatique) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version v2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* + This file is empty on purpose. Plugins register callbacks in src/kernel/db.ml. +*) diff -Nru frama-c-20110201+carbon+dfsg/src/scope/dpds_gui.ml frama-c-20111001+nitrogen+dfsg/src/scope/dpds_gui.ml --- frama-c-20110201+carbon+dfsg/src/scope/dpds_gui.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/scope/dpds_gui.ml 2011-10-10 08:38:30.000000000 +0000 @@ -22,16 +22,15 @@ (* *) (**************************************************************************) -open Properties_status open Pretty_source open Cil_types open Cil_datatype -open Db_types + +let update_visibility = ref (fun () -> ()) let add_tag buffer (name, tag_prop) start stop = - (* TODO : maybe we should use lazy to build the each tag only once ?... *) let tag = Gtk_helper.make_tag buffer ~name tag_prop in - Gtk_helper.apply_tag buffer tag start stop + Gtk_helper.apply_tag buffer tag start stop let scope_start_tag = ("startscope", [`UNDERLINE `DOUBLE]) let zones_used_tag = ("zones", [`BACKGROUND "#FFeeCC"]) @@ -56,8 +55,8 @@ try let term_lval = !Db.Properties.Interp.lval kf stmt txt in let lval = - !Db.Properties.Interp.term_lval_to_lval ~result:None term_lval - in + !Db.Properties.Interp.term_lval_to_lval ~result:None term_lval + in Some (txt, lval) with e -> main_ui#error "[ask for lval] '%s' invalid expression: %s@." @@ -84,14 +83,26 @@ Some (lv_txt, lv) | _ -> ( match kf_stmt_opt with - None -> None + None -> None | Some (kf, stmt) -> match (ask_for_lval main_ui kf stmt) with - None -> None + None -> None | Some (lv_txt, lv) -> Some (lv_txt, lv)) +module Kf_containing_highlighted_stmt = + Kernel_function.Make_Table + (Datatype.Unit) + (struct + let name = "Dpds_gui.Kf_containing_highlighted_stmt" + let size = 7 + let dependencies = + [ (*Dependencies are managed manually by Make_StmtSetState*) ] + let kind = `Internal + end) + + module Make_StmtSetState (Info:sig val name: string end) = - State_builder.Ref + struct include State_builder.Ref (Stmt.Set) (struct let name = Info.name @@ -99,7 +110,18 @@ let kind = `Internal let default () = Stmt.Set.empty end) + + let set s = + set s; + Kf_containing_highlighted_stmt.clear (); + Stmt.Set.iter + (fun stmt -> + Kf_containing_highlighted_stmt.replace + (Kernel_function.find_englobing_kf stmt) ()) + s; + !update_visibility () + end module type DpdCmdSig = sig type t_in val help : string @@ -164,9 +186,9 @@ State_builder.List_ref (Code_annotation) (struct - let name = "Dpds_gui.Highlighter.Pscope_warn" - let dependencies = [ Db.Value.self ] - let kind = `Internal + let name = "Dpds_gui.Highlighter.Pscope_warn" + let dependencies = [ Db.Value.self ] + let kind = `Internal end) let clear () = Pscope.clear(); Pscope_warn.clear() @@ -216,7 +238,7 @@ let get_info _kf_stmt_opt = if Stmt.Set.is_empty (ShowDefState.get()) then "" else "[show_def] selected" - + let compute kf stmt lv = match !Db.Scope.get_defs kf stmt lv with | None -> clear (); "[show_def] nothing found..." @@ -241,16 +263,25 @@ type t_in = lval module ZonesState = - State_builder.Option_ref + struct include State_builder.Option_ref (Datatype.Pair - (Int_hashtbl.Make(Locations.Zone)) + (Stmt.Hashtbl.Make(Locations.Zone)) (Stmt.Set)) (struct let name = "Dpds_gui.Highlighter.ZonesState" let dependencies = [ Db.Value.self ] let kind = `Internal end) - + let set s = + set s; + Kf_containing_highlighted_stmt.clear (); + Stmt.Set.iter + (fun stmt -> + Kf_containing_highlighted_stmt.replace + (Kernel_function.find_englobing_kf stmt) ()) + (snd s); + !update_visibility () + end let clear () = ZonesState.clear () let help = @@ -318,7 +349,10 @@ ShowDef.clear (); Zones.clear (); DataScope.clear (); - Pscope.clear () + Pscope.clear (); + Kf_containing_highlighted_stmt.clear (); + !update_visibility () + let print_info main_ui kf_stmt_opt = try @@ -353,7 +387,7 @@ let set_txt x = let txt = Pretty_utils.sfprintf "[dependencies] for %s before stmt %d in %a" - x stmt.sid Kernel_function.pretty_name kf + x stmt.sid Kernel_function.pretty kf in DpdsState.set (kf, stmt, txt); add_msg main_ui txt @@ -401,6 +435,22 @@ | PVDecl _ | PTermLval _ | PLval _ | PGlobal _ | PIP _ -> () with Not_found -> () +let check_value (main_ui:Design.main_window_extension_points) = + if Db.Value.is_computed () then true + else + let answer = GToolbox.question_box + ~title:("Need Value Analysis") + ~buttons:[ "Run"; "Cancel" ] + ("Value analysis has to be run first.\nThis can take some time.\n" + ^"Do you want to run the value analysis now ?") + in + if answer = 1 then + match main_ui#full_protect ~cancelable:true !Db.Value.compute with + | Some _ -> true + | None -> false + else false + + (** To add a sensitive/unsensitive menu item to a [factory]. * The menu item is insensitive when [arg_opt = None], * else, when the item is selected, the callback is called with the argument. @@ -408,19 +458,17 @@ *) let add_item (main_ui:Design.main_window_extension_points) ~use_values (factory:GMenu.menu GMenu.factory) name arg_opt callback = - if use_values && not (Db.Value.is_computed ()) then - (* add the menu item asking for running value analysis *) - let callback () = - let msg = "You need to Execute Values analysis first." in - add_msg main_ui ("[" ^ name ^ "] " ^ msg) - in ignore (factory#add_item name ~callback) - else match arg_opt with | None -> (* add the menu item, but it isn't sensitive *) let item = factory#add_item name ~callback: (fun () -> ()) in item#misc#set_sensitive false | Some arg -> (* add the menu item with its callback *) - ignore (factory#add_item name ~callback: (fun () -> callback arg)) + let cb arg = + if use_values then + if check_value main_ui then callback arg else () + else callback arg + in + ignore (factory#add_item name ~callback: (fun () -> cb arg)) let selector (popup_factory:GMenu.menu GMenu.factory) (main_ui:Design.main_window_extension_points) @@ -458,8 +506,28 @@ else if button = 1 then print_info main_ui (get_kf_stmt_opt localizable) +let filetree_decorate main_ui = + main_ui#file_tree#append_pixbuf_column + ~title:"Scope" + (fun globs -> + let is_hilighted = function + | GFun ({svar = v }, _) -> + Kf_containing_highlighted_stmt.mem (Globals.Functions.get v) + | _ -> false + in + let id = + (* lazyness of && is used for efficiency *) + if (Kf_containing_highlighted_stmt.length () <> 0) + && List.exists is_hilighted globs + then "gtk-apply" + else "" + in + [ `STOCK_ID id ]) + (fun _ -> Kf_containing_highlighted_stmt.length () <>0) + let main main_ui = main_ui#register_source_selector selector; - main_ui#register_source_highlighter highlighter - + main_ui#register_source_highlighter highlighter; + update_visibility := (filetree_decorate main_ui) + let () = Design.register_extension main diff -Nru frama-c-20110201+carbon+dfsg/src/scope/zones.ml frama-c-20111001+nitrogen+dfsg/src/scope/zones.ml --- frama-c-20110201+carbon+dfsg/src/scope/zones.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/scope/zones.ml 2011-10-10 08:38:30.000000000 +0000 @@ -23,7 +23,8 @@ (**************************************************************************) module R = Datascope.R -module IH = Inthash +let debug1 fmt = R.debug ~level:1 fmt +let debug2 fmt = R.debug ~level:2 fmt open Cil_datatype open Cil_types @@ -37,21 +38,21 @@ let diff = Locations.Zone.diff (* over-approx *) let pretty fmt z = Format.fprintf fmt "@[<h 1>%a@]" Locations.Zone.pretty z - let exp_zone stmt exp = !Db.From.find_deps_no_transitivity (Kstmt stmt) exp + let exp_zone stmt exp = !Db.From.find_deps_no_transitivity stmt exp end module Ctx = struct - type t = Data.t IH.t - let create = IH.create - let find = IH.find + type t = Data.t Stmt.Hashtbl.t + let create = Stmt.Hashtbl.create + let find = Stmt.Hashtbl.find let add ctx k d = let d = try let old_d = find ctx k in Data.merge old_d d with Not_found -> d - in IH.replace ctx k d - (* let mem = IH.mem : useless because Ctx has to be initialized to bot *) + in Stmt.Hashtbl.replace ctx k d + (* let mem = Stmt.Hashtbl.mem : useless because Ctx has to be initialized to bot *) let pretty fmt infos = - IH.iter - (fun k d -> Format.fprintf fmt "Stmt:%d -> %a@\n" k Data.pretty d) + Stmt.Hashtbl.iter + (fun k d -> Format.fprintf fmt "Stmt:%d -> %a@\n" k.sid Data.pretty d) infos end @@ -70,7 +71,8 @@ | Some lval -> let ret_dpds = froms.Function_Froms.deps_return in let r_dpds = Lmap_bitwise.From_Model.LOffset.collapse ret_dpds in - let l_dpds, exact, l_zone = Datascope.get_lval_zones stmt lval in + let l_dpds, exact, l_zone = + Datascope.get_lval_zones ~for_writing:true stmt lval in compute_new_data data l_zone l_dpds exact r_dpds in data @@ -151,18 +153,18 @@ (process_one_call data_after stmt lvaloption (!Db.From.get kf))::acc in let l = Kernel_function.Hptset.fold do_call called_functions [] in - (* in l, we have one result for each possible function called *) + (* in l, we have one result for each possible function called *) List.fold_left (fun (acc_u,acc_d) (u,d) -> (acc_u || u), Data.merge acc_d d) (false, Data.bottom) - l + l in if used then let data = (* no problem of order because parameters are disjoint for sure *) Kernel_function.Hptset.fold - (fun kf data -> process_call_args data kf stmt args) - called_functions + (fun kf data -> process_call_args data kf stmt args) + called_functions data in let data = Data.merge funcexp_dpds data in @@ -188,13 +190,14 @@ module StmtStartData = struct type data = t - let clear () = IH.clear Param.states - let mem = IH.mem Param.states - let find = IH.find Param.states - let replace = IH.replace Param.states - let add = IH.add Param.states - let iter f = IH.iter f Param.states - let length () = IH.length Param.states + type key = stmt + let clear () = Stmt.Hashtbl.clear Param.states + let mem = Stmt.Hashtbl.mem Param.states + let find = Stmt.Hashtbl.find Param.states + let replace = Stmt.Hashtbl.replace Param.states + let add = Stmt.Hashtbl.add Param.states + let iter f = Stmt.Hashtbl.iter f Param.states + let length () = Stmt.Hashtbl.length Param.states end let combineStmtStartData _stmt ~old new_ = @@ -208,7 +211,8 @@ let doInstr stmt instr data = match instr with | Set (lval, exp, _) -> - let l_dpds, exact, l_zone = Datascope.get_lval_zones stmt lval in + let l_dpds, exact, l_zone = + Datascope.get_lval_zones ~for_writing:true stmt lval in let r_dpds = Data.exp_zone stmt exp in let used, data = compute_new_data data l_zone l_dpds exact r_dpds in let _ = if used then add_used_stmt stmt in @@ -220,8 +224,6 @@ | _ -> Dataflow.Default let filterStmt _stmt _next = true - (* assert (Db.ToReturn.is_accessible (Kstmt next)); - Db.ToReturn.is_accessible (Kstmt stmt) *) let funcExitData = Data.bottom @@ -229,34 +231,34 @@ let compute_ctrl_info pdg ctrl_part used_stmts = let module CtrlComputer = Computer (struct let states = ctrl_part end) in - let module CtrlCompute = Dataflow.BackwardsDataFlow(CtrlComputer) in - let seen = IH.create 50 in + let module CtrlCompute = Dataflow.Backwards(CtrlComputer) in + let seen = Stmt.Hashtbl.create 50 in let rec add_node_ctrl_nodes new_stmts node = let ctrl_nodes = !Db.Pdg.direct_ctrl_dpds pdg node in List.fold_left add_ctrl_node new_stmts ctrl_nodes and add_ctrl_node new_stmts ctrl_node = - R.debug ~level:2 "[zones] add ctrl node %a@." PdgTypes.Node.pretty ctrl_node; + debug2 "[zones] add ctrl node %a@." PdgTypes.Node.pretty ctrl_node; match PdgTypes.Node.stmt ctrl_node with | None -> (* node without stmt : add its ctrl_dpds *) add_node_ctrl_nodes new_stmts ctrl_node | Some stmt -> - R.debug ~level:2 "[zones] node %a is stmt %d@." + debug2 "[zones] node %a is stmt %d@." PdgTypes.Node.pretty ctrl_node stmt.sid; - if IH.mem seen stmt.sid then new_stmts + if Stmt.Hashtbl.mem seen stmt then new_stmts else let ctrl_zone = match stmt.skind with | Switch (exp,_,_,_) | If (exp,_,_,_) -> Data.exp_zone stmt exp | _ -> Data.bottom - in Ctx.add ctrl_part stmt.sid ctrl_zone; - IH.add seen stmt.sid (); - R.debug ~level:2 "[zones] add ctrl zone %a at stmt %d@." + in Ctx.add ctrl_part stmt ctrl_zone; + Stmt.Hashtbl.add seen stmt (); + debug2 "[zones] add ctrl zone %a at stmt %d@." Data.pretty ctrl_zone stmt.sid; stmt::new_stmts and add_stmt_ctrl new_stmts stmt = - R.debug ~level:1 "[zones] add ctrl of stmt %d@." stmt.sid; - if IH.mem seen stmt.sid then new_stmts + debug1 "[zones] add ctrl of stmt %d@." stmt.sid; + if Stmt.Hashtbl.mem seen stmt then new_stmts else begin - IH.add seen stmt.sid (); + Stmt.Hashtbl.add seen stmt (); match !Db.Pdg.find_simple_stmt_nodes pdg stmt with | [] -> [] | n::_ -> add_node_ctrl_nodes new_stmts n @@ -275,15 +277,16 @@ let compute kf stmt lval = let f = Kernel_function.get_definition kf in - let dpds, _exact, zone = Datascope.get_lval_zones stmt lval in + let dpds, _exact, zone = + Datascope.get_lval_zones ~for_writing:false stmt lval in let zone = Data.merge dpds zone in - R.debug ~level:1 "[zones] build for %a before %d in %a@\n" - Data.pretty zone stmt.sid Kernel_function.pretty_name kf; + debug1 "[zones] build for %a before %d in %a@\n" + Data.pretty zone stmt.sid Kernel_function.pretty kf; let data_part = Ctx.create 50 in - List.iter (fun s -> Ctx.add data_part s.sid Data.bottom) f.sallstmts; - let _ = Ctx.add data_part stmt.sid zone in + List.iter (fun s -> Ctx.add data_part s Data.bottom) f.sallstmts; + let _ = Ctx.add data_part stmt zone in let module DataComputer = Computer (struct let states = data_part end) in - let module DataCompute = Dataflow.BackwardsDataFlow(DataComputer) in + let module DataCompute = Dataflow.Backwards(DataComputer) in let _ = DataCompute.compute stmt.preds in let ctrl_part = data_part (* Ctx.create 50 *) in (* it is confusing to have 2 part in the provided information, @@ -301,34 +304,11 @@ all_used_stmts, data_part let get stmt_zones stmt = - try Ctx.find stmt_zones stmt.sid with Not_found -> Data.bottom + try Ctx.find stmt_zones stmt with Not_found -> Data.bottom let pretty fmt stmt_zones = - let pp s d = Format.fprintf fmt "Stmt:%d -> %a@." s Data.pretty d - in IH.iter pp stmt_zones - - (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) - -let compute_defs kf stmt lval = - (* TODO : move this function somewhere else ? *) - try - let pdg = !Db.Pdg.get kf in - let zone = !Db.Value.lval_to_zone (Kstmt stmt) - ~with_alarms:CilE.warn_none_mode lval - in - let nodes, undef = - !Db.Pdg.find_location_nodes_at_stmt pdg stmt ~before:true zone - in - let add_node defs (node,_z) = - match PdgIndex.Key.stmt (!Db.Pdg.node_key node) with - | None -> defs - | Some s -> Stmt.Set.add s defs - in - (* select corresponding stmts *) - let defs = List.fold_left add_node Stmt.Set.empty nodes in - Some (defs, undef) - with Db.Pdg.Bottom | Db.Pdg.Top | Db.Pdg.NotFound -> - None + let pp s d = Format.fprintf fmt "Stmt:%d -> %a@." s.sid Data.pretty d + in Stmt.Hashtbl.iter pp stmt_zones (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) @@ -355,16 +335,3 @@ (*(Db.Journalize("Scope.pretty_zones", Datatype.func Datatype.formatter (Datatype.func zones_ty Datatype.unit)))*) Db.Scope.pretty_zones pretty; - - Db.register (* kernel_function -> stmt -> lval -> - (Cilutil.StmtSet.t * Locations.Zone.t option) option *) - (Db.Journalize - ("Scope.get_defs", - Datatype.func3 - Kernel_function.ty - Stmt.ty - Lval.ty - (Datatype.option - (Datatype.pair Stmt.Set.ty (Datatype.option Locations.Zone.ty))))) - Db.Scope.get_defs compute_defs - diff -Nru frama-c-20110201+carbon+dfsg/src/scope/zones.mli frama-c-20111001+nitrogen+dfsg/src/scope/zones.mli --- frama-c-20110201+carbon+dfsg/src/scope/zones.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/scope/zones.mli 2011-10-10 08:38:30.000000000 +0000 @@ -22,6 +22,6 @@ (* *) (**************************************************************************) -(* +(* This file is empty on purpose. Plugins register callbacks in src/kernel/db.ml. *) diff -Nru frama-c-20110201+carbon+dfsg/src/security_slicing/components.ml frama-c-20111001+nitrogen+dfsg/src/security_slicing/components.ml --- frama-c-20110201+carbon+dfsg/src/security_slicing/components.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/security_slicing/components.ml 2011-10-10 08:38:07.000000000 +0000 @@ -23,7 +23,6 @@ open Cil_types open Cil open Cil_datatype -open Db_types open Db open Extlib @@ -43,15 +42,15 @@ | Pand(p1, p2) -> is_security_predicate p1 || is_security_predicate p2 | (* [state(lval) op term] *) Prel(_, - { term_node = Tapp(f1, _ , ([ _ ])) }, - { term_node = TLval(TVar _,_) }) - when f1.l_var_info.lv_name = Model.state_name -> + { term_node = Tapp(f1, _ , ([ _ ])) }, + { term_node = TLval(TVar _,_) }) + when f1.l_var_info.lv_name = Model.state_name -> true | (* [state(lval) op term] *) Prel(_, - { term_node = Tapp(f1, _, [ _ ]) }, - { term_node = _ }) - when f1.l_var_info.lv_name = Model.state_name -> + { term_node = Tapp(f1, _, [ _ ]) }, + { term_node = _ }) + when f1.l_var_info.lv_name = Model.state_name -> assert false | _ -> false @@ -68,35 +67,35 @@ (* TODO: chercher dans les GlobalAnnotations *) let is_security_annotation = function | User a -> - (match a.annot_content with - | AAssert (_behav,p,_) -> is_security_predicate p - | AStmtSpec { spec_requires = l } -> - List.exists - (is_security_predicate $ Logic_const.pred_of_id_pred) l - | APragma _ + (match a.annot_content with + | AAssert (_behav,p,_) -> is_security_predicate p + | AStmtSpec { spec_requires = l } -> + List.exists + (is_security_predicate $ Logic_const.pred_of_id_pred) l + | APragma _ | AInvariant _ (* | ALoopBehavior _ *) - (* [JS 2008/02/26] may contain a security predicate *) + (* [JS 2008/02/26] may contain a security predicate *) | AVariant _ | AAssigns _ -> false) | AI _ -> - false + false in Annotations.iter (fun s annotations -> - if - Value.is_reachable_stmt s - && List.exists - (function Before a | After a -> is_security_annotation a) - !annotations - then - Security_Annotations.add s); + if + Value.is_reachable_stmt s + && List.exists + (function Before a | After a -> is_security_annotation a) + !annotations + then + Security_Annotations.add s); Globals.Functions.iter (fun kf -> - if has_security_requirement kf then - List.iter - (fun (_, callsites) -> - List.iter Security_Annotations.add callsites) - (!Value.callers kf)); + if has_security_requirement kf then + List.iter + (fun (_, callsites) -> + List.iter Security_Annotations.add callsites) + (!Value.callers kf)); end *) (* ************************************************************************* *) @@ -135,8 +134,8 @@ module Callstack = struct type t = - { mutable stack: (stmt * kernel_function) list; - mutable current_kf: kernel_function } + { mutable stack: (stmt * kernel_function) list; + mutable current_kf: kernel_function } let init kf callstack = callstack.stack <- []; callstack.current_kf <- kf @@ -151,14 +150,14 @@ let equal s1 s2 = Kernel_function.equal s1.current_kf s2.current_kf && try - List.iter2 - (fun (s1, kf1) (s2, kf2) -> - if not (s1.sid = s2.sid && Kernel_function.equal kf1 kf2) then - raise Exit) - s1.stack s2.stack; - true + List.iter2 + (fun (s1, kf1) (s2, kf2) -> + if not (s1.sid = s2.sid && Kernel_function.equal kf1 kf2) then + raise Exit) + s1.stack s2.stack; + true with Exit -> - false + false let hash = Hashtbl.hash @@ -180,29 +179,41 @@ include Hashtbl let memo tbl k callstack = try - let callstacks = find tbl k in - Callstacks.memo callstacks callstack + let callstacks = find tbl k in + Callstacks.memo callstacks callstack with Not_found -> - let callstacks = Callstacks.create 7 in - let t = Nodekfs.create 7 in - Callstacks.replace callstacks callstack t; - replace tbl k callstacks; - t + let callstacks = Callstacks.create 7 in + let t = Nodekfs.create 7 in + Callstacks.replace callstacks callstack t; + replace tbl k callstacks; + t end type local_tbl = (Pdg.t_node * kernel_function) list Nodekfs.t type state = { mutable kind: kind; - mutable callstack: Callstack.t; - mutable local_tbl: local_tbl; - memo_tbl: (kind, local_tbl Callstacks.t) Memo.t; } + mutable callstack: Callstack.t; + mutable local_tbl: local_tbl; + memo_tbl: (kind, local_tbl Callstacks.t) Memo.t; } (* *********************************************************************** *) let state = + let spec = Cil.empty_funspec () in { kind = Backward Direct; callstack = - { Callstack.stack = []; current_kf = Kernel_function.dummy () }; + { Callstack.stack = []; + current_kf = + { fundec = + (* do not use Cil.emptyFunction here since it changes the + numerotation of variables *) + Declaration + (spec, + Cil_datatype.Varinfo.dummy, + None, + Cil_datatype.Location.unknown); + return_stmt = None; + spec = Cil.empty_funspec () } }; local_tbl = Nodekfs.create 0; memo_tbl = Hashtbl.create 5 } @@ -237,10 +248,10 @@ module Todolist : sig type todo = private { node: Pdg.t_node; - kf: kernel_function; - pdg: Pdg.t; - callstack_length: int; - from_deep: bool } + kf: kernel_function; + pdg: Pdg.t; + callstack_length: int; + from_deep: bool } type t = todo list val mk_init: kernel_function -> Pdg.t -> Pdg.t_node list -> todo list val add: Pdg.t_node -> kernel_function -> Pdg.t -> int -> bool -> t -> t @@ -248,30 +259,30 @@ type todo = { node: Pdg.t_node; - kf: kernel_function; - pdg: Pdg.t; - callstack_length: int; - from_deep: bool } + kf: kernel_function; + pdg: Pdg.t; + callstack_length: int; + from_deep: bool } type t = todo list let add n kf pdg len fd list = match !Pdg.node_key n with | Key.SigKey (Signature.In Signature.InCtrl) -> - (* do not consider node [InCtrl] *) - list - | Key.VarDecl vi when not (Parameters.LibEntry.get () && vi.vglob) -> - (* do not consider variable declaration, - except if libEntry is set and they are globals - (i.e. we could have no further info about them) *) - list + (* do not consider node [InCtrl] *) + list + | Key.VarDecl vi when not (Kernel.LibEntry.get () && vi.vglob) -> + (* do not consider variable declaration, + except if libEntry is set and they are globals + (i.e. we could have no further info about them) *) + list | _ -> - Security_slicing_parameters.debug ~level:2 "adding node %a (in %s)" - (!Pdg.pretty_node false) n - (Kernel_function.get_name kf); - { node = n; kf = kf; pdg = pdg; - callstack_length = len; from_deep = fd } - :: list + Security_slicing_parameters.debug ~level:2 "adding node %a (in %s)" + (!Pdg.pretty_node false) n + (Kernel_function.get_name kf); + { node = n; kf = kf; pdg = pdg; + callstack_length = len; from_deep = fd } + :: list let mk_init kf pdg = List.fold_left (fun acc n -> add n kf pdg 0 false acc) [] @@ -293,10 +304,10 @@ type value = { pdg: Pdg.t; - mutable callstack_length: int; - mutable direct: bool; - mutable indirect_backward: bool; - mutable forward: bool } + mutable callstack_length: int; + mutable direct: bool; + mutable indirect_backward: bool; + mutable forward: bool } type t = value M.t @@ -310,15 +321,15 @@ value. *) let check_and_add first elt kind pdg len already = try - (* Format.printf "[security] check node %a (in %s, kind %a)@." - (!Pdg.pretty_node true) (fst elt) - (Kernel_function.get_name (snd elt)) - pretty_kind kind;*) + (* Format.printf "[security] check node %a (in %s, kind %a)@." + (!Pdg.pretty_node true) (fst elt) + (Kernel_function.get_name (snd elt)) + pretty_kind kind;*) let v = M.find elt already in let found, dir, up, down = match kind with - | Direct -> true, true, false, false - | Indirect_Backward -> v.indirect_backward, v.direct, true, false - | Forward _ -> v.forward, v.direct, v.indirect_backward, true + | Direct -> true, true, false, false + | Indirect_Backward -> v.indirect_backward, v.direct, true, false + | Forward _ -> v.forward, v.direct, v.indirect_backward, true in v.callstack_length <- min v.callstack_length len; v.direct <- dir; @@ -327,21 +338,21 @@ found, already with Not_found -> let dir, up, down = match kind with - | Direct -> true, false, false - | Indirect_Backward -> false, true, false - | Forward _ -> false, false, true + | Direct -> true, false, false + | Indirect_Backward -> false, true, false + | Forward _ -> false, false, true in let v = - { pdg = pdg; callstack_length = len; - direct = dir; indirect_backward = up; forward = down } + { pdg = pdg; callstack_length = len; + direct = dir; indirect_backward = up; forward = down } in false, if first && kind = Forward Impact then - (* do not add the initial selected stmt for an impact analysis. - fixed FS#411 *) - already + (* do not add the initial selected stmt for an impact analysis. + fixed FS#411 *) + already else - M.add elt v already + M.add elt v already let one_step_related_nodes kind pdg node = (* do not consider address dependencies now (except for impact analysis): @@ -352,18 +363,20 @@ | Direct -> direct node | Indirect_Backward -> direct node @ !Pdg.direct_ctrl_dpds pdg node | Forward Security -> - !Pdg.direct_data_uses pdg node @ !Pdg.direct_ctrl_uses pdg node + !Pdg.direct_data_uses pdg node @ !Pdg.direct_ctrl_uses pdg node | Forward Impact -> - !Pdg.direct_data_uses pdg node @ !Pdg.direct_ctrl_uses pdg node - @ !Pdg.direct_addr_uses pdg node + !Pdg.direct_data_uses pdg node @ !Pdg.direct_ctrl_uses pdg node + @ !Pdg.direct_addr_uses pdg node let search_input kind kf lazy_l = try match kind with | Forward _ -> Lazy.force lazy_l | Direct | Indirect_Backward -> - if Kernel_function.is_definition kf then [] else Lazy.force lazy_l - with Pdg.NotFound -> + if !Db.Value.use_spec_instead_of_definition kf + then Lazy.force lazy_l + else [] + with Not_found -> [] let add_from_deep caller todo n = @@ -373,19 +386,19 @@ let pdg = !Pdg.get kf in List.fold_left (fun todolist (caller, callsites) -> - (* foreach caller *) - List.fold_left - (fun todolist callsite -> - let nodes = - !Pdg.find_call_out_nodes_to_select - pdg [ node ] (!Pdg.get caller) callsite - in - List.fold_left - (add_from_deep caller) - todolist - nodes) - todolist - callsites) + (* foreach caller *) + List.fold_left + (fun todolist callsite -> + let nodes = + !Pdg.find_call_out_nodes_to_select + pdg [ node ] (!Pdg.get caller) callsite + in + List.fold_left + (add_from_deep caller) + todolist + nodes) + todolist + callsites) todolist (!Value.callers kf) @@ -396,200 +409,217 @@ let rec aux first result = function | [] -> result | { Todolist.node = node; kf = kf; pdg = pdg; - callstack_length = callstack_length; from_deep = from_deep } - :: todolist - -> - let elt = node, kf in - let found, result = - check_and_add first elt kind pdg callstack_length result - in - let todolist = - if found then begin - todolist - end else begin - Security_slicing_parameters.debug - ~level:2 "considering node %a (in %s)" - (!Pdg.pretty_node false) node - (Kernel_function.get_name kf); - (* intraprocedural related_nodes *) - let related_nodes = one_step_related_nodes kind pdg node in - Security_slicing_parameters.debug ~level:3 - "intraprocedural part done"; - let todolist = - List.fold_left - (fun todo n -> - Todolist.add n kf pdg callstack_length false todo) - todolist - related_nodes - in - (* interprocedural part *) - let backward_from_deep compute_nodes = - (* [TODO optimisation:] - en fait, regarder from_deep: - si vrai, faire pour chaque caller - sinon, faire uniquement pour le caller d'où on vient *) - match kind, callstack_length with - | (Direct | Indirect_Backward), 0 -> - (* input of a deep security annotation: foreach call - to [kf], compute its related nodes *) - let do_caller todolist (caller, callsites) = - (* Format.printf "[security of %s] search callers in %s - for zone %a@." (Kernel_function.get_name kf) - (Kernel_function.get_name caller) - Locations.Zone.pretty zone;*) - let pdg_caller = !Pdg.get caller in - let do_call todolist callsite = - match kind with - | Direct | Indirect_Backward -> - let nodes = compute_nodes pdg_caller callsite in - List.fold_left - (add_from_deep caller) todolist nodes - | Forward _ -> - todolist (* not considered here, see at end *) - in - List.fold_left do_call todolist callsites - in - List.fold_left do_caller todolist (!Value.callers kf) - | _ -> - todolist - in - let todolist = - match !Pdg.node_key node with - | Key.SigKey (Signature.In Signature.InCtrl) -> - assert false - | Key.SigKey (Signature.In (Signature.InImpl zone)) -> - let compute_nodes pdg_caller callsite = + callstack_length = callstack_length; from_deep = from_deep } + :: todolist + -> + let elt = node, kf in + let found, result = + check_and_add first elt kind pdg callstack_length result + in + let todolist = + if found then begin + todolist + end else begin + Security_slicing_parameters.debug + ~level:2 "considering node %a (in %s)" + (!Pdg.pretty_node false) node + (Kernel_function.get_name kf); + (* intraprocedural related_nodes *) + let related_nodes = one_step_related_nodes kind pdg node in + Security_slicing_parameters.debug ~level:3 + "intraprocedural part done"; + let todolist = + List.fold_left + (fun todo n -> + Todolist.add n kf pdg callstack_length false todo) + todolist + related_nodes + in + (* interprocedural part *) + let backward_from_deep compute_nodes = + (* [TODO optimisation:] + en fait, regarder from_deep: + si vrai, faire pour chaque caller + sinon, faire uniquement pour le caller d'où on vient *) + match kind, callstack_length with + | (Direct | Indirect_Backward), 0 -> + (* input of a deep security annotation: foreach call + to [kf], compute its related nodes *) + let do_caller todolist (caller, callsites) = + (* Format.printf "[security of %s] search callers in %s + for zone %a@." (Kernel_function.get_name kf) + (Kernel_function.get_name caller) + Locations.Zone.pretty zone;*) + let pdg_caller = !Pdg.get caller in + let do_call todolist callsite = + match kind with + | Direct | Indirect_Backward -> + let nodes = compute_nodes pdg_caller callsite in + List.fold_left + (add_from_deep caller) todolist nodes + | Forward _ -> + todolist (* not considered here, see at end *) + in + List.fold_left do_call todolist callsites + in + List.fold_left do_caller todolist (!Value.callers kf) + | _ -> + todolist + in + let todolist = + match !Pdg.node_key node with + | Key.SigKey (Signature.In Signature.InCtrl) -> + assert false + | Key.SigKey (Signature.In (Signature.InImpl zone)) -> + let compute_nodes pdg_caller callsite = let nodes, _undef_zone = - !Pdg.find_location_nodes_at_stmt - pdg_caller callsite ~before:true zone + !Pdg.find_location_nodes_at_stmt + pdg_caller callsite ~before:true zone (* TODO : use undef_zone (see FS#201)? *) in let nodes = List.map (fun (n, _z_part) -> n) nodes in (* TODO : use _z_part ? *) - nodes - in - backward_from_deep compute_nodes - | Key.SigKey key -> - let compute_nodes pdg_caller callsite = - [ match key with - | Signature.In (Signature.InNum n) -> - !Pdg.find_call_input_node pdg_caller callsite n - | Signature.Out Signature.OutRet -> - !Pdg.find_call_output_node pdg_caller callsite - | Signature.In - (Signature.InCtrl | Signature.InImpl _) - | Signature.Out _ -> - assert false ] - in - backward_from_deep compute_nodes - | Key.SigCallKey(id, key) -> - (* the node is a call: search the related nodes inside the - called function (see FS#155) *) - if from_deep then - (* already come from a deeper annotation: - do not go again inside it *) - todolist - else - let stmt = Key.call_from_id id in - let called_kfs = - Kernel_function.Hptset.elements - (try Value.call_to_kernel_function stmt - with Value.Not_a_call -> assert false) - in - let todolist = - List.fold_left - (fun todolist called_kf -> - (* foreach called kf *) - (*Format.printf - "[security] search inside %s (from %s)@." - (Kernel_function.get_name called_kf) - (Kernel_function.get_name kf);*) - let called_pdg = !Pdg.get called_kf in - let nodes = match kind, key with - | (Direct | Indirect_Backward), - Signature.Out out_key -> - let nodes, _undef_zone = - !Pdg.find_output_nodes called_pdg out_key - (* TODO: use undef_zone (see FS#201) *) - in - let nodes = - List.map (fun (n, _z_part) -> n) nodes in + nodes + in + backward_from_deep compute_nodes + | Key.SigKey key -> + let compute_nodes pdg_caller callsite = + [ match key with + | Signature.In (Signature.InNum n) -> + !Pdg.find_call_input_node pdg_caller callsite n + | Signature.Out Signature.OutRet -> + !Pdg.find_call_output_node pdg_caller callsite + | Signature.In + (Signature.InCtrl | Signature.InImpl _) + | Signature.Out _ -> + assert false ] + in + backward_from_deep compute_nodes + | Key.SigCallKey(id, key) -> + (* the node is a call: search the related nodes inside the + called function (see FS#155) *) + if from_deep then + (* already come from a deeper annotation: + do not go again inside it *) + todolist + else + let stmt = Key.call_from_id id in + let called_kfs = + Kernel_function.Hptset.elements + (try Value.call_to_kernel_function stmt + with Value.Not_a_call -> assert false) + in + let todolist = + List.fold_left + (fun todolist called_kf -> + (* foreach called kf *) + (*Format.printf + "[security] search inside %s (from %s)@." + (Kernel_function.get_name called_kf) + (Kernel_function.get_name kf);*) + let called_pdg = !Pdg.get called_kf in + let nodes = + try + match kind, key with + | (Direct | Indirect_Backward), + Signature.Out out_key -> + let nodes, _undef_zone = + !Pdg.find_output_nodes called_pdg out_key + (* TODO: use undef_zone (see FS#201) *) + in + let nodes = + List.map (fun (n, _z_part) -> n) nodes in (* TODO : use _z_part ? *) - nodes - | _, Signature.In (Signature.InNum n) -> - search_input kind called_kf - (lazy [!Pdg.find_input_node called_pdg n]) - | _, Signature.In Signature.InCtrl -> - search_input kind called_kf - (lazy - [!Pdg.find_entry_point_node called_pdg]) - | _, Signature.In (Signature.InImpl _) -> - assert false - | Forward _, Signature.Out _ -> - [] - in - List.fold_left - (fun todo n -> - (*Format.printf "node %a inside %s@." - (!Pdg.pretty_node false) n - (Kernel_function.get_name called_kf);*) - Todolist.add - n called_kf called_pdg - (callstack_length + 1) false todo) - todolist - nodes) - todolist - called_kfs - in - (match kind with - | Direct | Indirect_Backward -> - todolist - | Forward _ -> - List.fold_left - (fun todolist called_kf -> - let compute_from_stmt fold = - fold - (fun (n, kfn) _ acc -> - if kfn == kf then n :: acc else acc) - in - let from_stmt = - compute_from_stmt M.fold result [] in - let from_stmt = - (* initial nodes may be not in results *) - compute_from_stmt - (fun f e acc -> - List.fold_left - (fun acc e -> f e [] acc) acc e) - initial_nodes - from_stmt - in - let called_pdg = !Pdg.get called_kf in - let nodes = - !Pdg.find_in_nodes_to_select_for_this_call - pdg from_stmt stmt called_pdg - in - List.fold_left - (fun todo n -> - Todolist.add - n called_kf called_pdg - (callstack_length + 1) false todo) - todolist - nodes) - todolist - called_kfs) - | Key.CallStmt _ | Key.VarDecl _ -> - assert false - | Key.Stmt _ | Key.Label _ -> - todolist - in - (* [TODO optimisation:] voir commentaire plus haut *) - match kind with - | (Direct | Indirect_Backward) -> todolist - | Forward _ -> forward_caller kf node todolist - end - in - (* recursive call *) - aux false result todolist + nodes + | _, Signature.In (Signature.InNum n) -> + search_input kind called_kf + (lazy [!Pdg.find_input_node called_pdg n]) + | _, Signature.In Signature.InCtrl -> + search_input kind called_kf + (lazy + [!Pdg.find_entry_point_node called_pdg]) + | _, Signature.In (Signature.InImpl _) -> + assert false + | Forward _, Signature.Out _ -> + [] + with + | Pdg.Top -> + Security_slicing_parameters.warning + "no precise pdg for function %s. \n\ +Ignoring this function in the analysis (potentially incorrect results)." + (Kernel_function.get_name called_kf); + [] + | Pdg.Bottom | Not_found -> assert false + in + List.fold_left + (fun todo n -> + (*Format.printf "node %a inside %s@." + (!Pdg.pretty_node false) n + (Kernel_function.get_name called_kf);*) + Todolist.add + n called_kf called_pdg + (callstack_length + 1) false todo) + todolist + nodes) + todolist + called_kfs + in + (match kind with + | Direct | Indirect_Backward -> + todolist + | Forward _ -> + List.fold_left + (fun todolist called_kf -> + let compute_from_stmt fold = + fold + (fun (n, kfn) _ acc -> + if Kernel_function.equal kfn kf then n :: acc + else acc) + in + let from_stmt = + compute_from_stmt M.fold result [] in + let from_stmt = + (* initial nodes may be not in results *) + compute_from_stmt + (fun f e acc -> + List.fold_left + (fun acc e -> f e [] acc) acc e) + initial_nodes + from_stmt + in + let called_pdg = !Pdg.get called_kf in + let nodes = + try + !Pdg.find_in_nodes_to_select_for_this_call + pdg from_stmt stmt called_pdg + with + | Pdg.Top -> + (* warning already emited in the previous fold *) + [] + | Pdg.Bottom | Not_found -> assert false + in + List.fold_left + (fun todo n -> + Todolist.add + n called_kf called_pdg + (callstack_length + 1) false todo) + todolist + nodes) + todolist + called_kfs) + | Key.CallStmt _ | Key.VarDecl _ -> + assert false + | Key.Stmt _ | Key.Label _ -> + todolist + in + (* [TODO optimisation:] voir commentaire plus haut *) + match kind with + | (Direct | Indirect_Backward) -> todolist + | Forward _ -> forward_caller kf node todolist + end + in + (* recursive call *) + aux false result todolist in aux true result nodes @@ -599,12 +629,12 @@ let pdg = !Pdg.get kf in let nodes = if Db.Value.is_reachable_stmt stmt then - try !Pdg.find_simple_stmt_nodes pdg stmt - with Pdg.NotFound -> assert false + try !Pdg.find_simple_stmt_nodes pdg stmt + with Not_found -> assert false else begin - Security_slicing_parameters.debug - ~level:3 "stmt %d is dead. skipping." stmt.sid; - [] + Security_slicing_parameters.debug + ~level:3 "stmt %d is dead. skipping." stmt.sid; + [] end in Todolist.mk_init kf pdg nodes @@ -613,18 +643,18 @@ try let nodes = initial_nodes kf stmt in Security_slicing_parameters.debug - "computing direct component %d" stmt.sid; + "computing direct component %d" stmt.sid; let res = related_nodes_of_nodes Direct M.empty nodes in (* add the initial node, fix FS#180 *) let mk p = - { pdg = p; callstack_length = 0; - direct = true; indirect_backward = false; forward = false } + { pdg = p; callstack_length = 0; + direct = true; indirect_backward = false; forward = false } in let res = - List.fold_left - (fun acc { Todolist.node=n; kf=f; pdg=p } -> M.add (n,f) (mk p) acc) - res - nodes + List.fold_left + (fun acc { Todolist.node=n; kf=f; pdg=p } -> M.add (n,f) (mk p) acc) + res + nodes in res with Pdg.Top | Pdg.Bottom -> @@ -636,7 +666,7 @@ let nodes = initial_nodes kf stmt in let res = direct kf stmt in Security_slicing_parameters.debug - "computing backward indirect component for %d" stmt.sid; + "computing backward indirect component for %d" stmt.sid; related_nodes_of_nodes Indirect_Backward res nodes with Pdg.Top | Pdg.Bottom -> Security_slicing_parameters.warning "PDG is not manageable. skipping."; @@ -646,10 +676,10 @@ let res = backward kf stmt in let from = M.fold - (fun (n,kf) v acc -> - Todolist.add n kf v.pdg v.callstack_length false(*?*) acc) - res - [] + (fun (n,kf) v acc -> + Todolist.add n kf v.pdg v.callstack_length false(*?*) acc) + res + [] in Security_slicing_parameters.debug "computing forward component for stmt %d" stmt.sid; @@ -663,18 +693,18 @@ let res = related_nodes_of_nodes (Forward fwd_kind) M.empty nodes in let set = M.fold - (fun (n,_) _ acc -> - Extlib.may_map - ~dft:acc - (fun s -> Stmt.Set.add s acc) - (get_node_stmt n)) - res - Stmt.Set.empty + (fun (n,_) _ acc -> + Extlib.may_map + ~dft:acc + (fun s -> Stmt.Set.add s acc) + (get_node_stmt n)) + res + Stmt.Set.empty in Stmt.Set.elements set let get_component kind stmt = - let _, kf = Kernel_function.find_from_sid stmt.sid in + let kf = Kernel_function.find_englobing_kf stmt in let action, check = match kind with | Direct -> direct, is_direct | Indirect_Backward -> backward, is_indirect_backward @@ -682,16 +712,16 @@ in let set = M.fold - (fun (n,_) v acc -> - if check v then - Extlib.may_map - ~dft:acc - (fun s -> Stmt.Set.add s acc) - (get_node_stmt n) - else - acc) - (action kf stmt) - Stmt.Set.empty + (fun (n,_) v acc -> + if check v then + Extlib.may_map + ~dft:acc + (fun s -> Stmt.Set.add s acc) + (get_node_stmt n) + else + acc) + (action kf stmt) + Stmt.Set.empty in Stmt.Set.elements set @@ -749,18 +779,18 @@ (Stmt.Hashtbl) (Datatype.Ref(Datatype.List(Stmt))) (struct - let name = "Components" - let size = 7 - let dependencies = [ Ast.self; Db.Value.self ] + let name = "Components" + let size = 7 + let dependencies = [ Ast.self; Db.Value.self ] let kind = `Internal end) let () = Cmdline.run_after_extended_stage (fun () -> - State_dependency_graph.Static.add_codependencies - ~onto:S.self - [ !Db.Pdg.self ]) + State_dependency_graph.Static.add_codependencies + ~onto:S.self + [ !Db.Pdg.self ]) let add c = let l = S.memo (fun _ -> ref []) c in @@ -793,17 +823,17 @@ (fun () -> search_security_requirements (); let add_component stmt = - Security_slicing_parameters.debug - "computing security component %d" stmt.sid; - let add_one = Components.add stmt in - let kf = snd (Kernel_function.find_from_sid stmt.sid) in - Component.iter - !use_ctrl_dependencies - (fun (n, _ as elt) -> - Nodes.add elt; - Extlib.may add_one (get_node_stmt n)) - kf - stmt + Security_slicing_parameters.debug + "computing security component %d" stmt.sid; + let add_one = Components.add stmt in + let kf = Kernel_function.find_englobing_kf stmt in + Component.iter + !use_ctrl_dependencies + (fun (n, _ as elt) -> + Nodes.add elt; + Extlib.may add_one (get_node_stmt n)) + kf + stmt in Security_Annotations.iter add_component) diff -Nru frama-c-20110201+carbon+dfsg/src/security_slicing/configure frama-c-20111001+nitrogen+dfsg/src/security_slicing/configure --- frama-c-20110201+carbon+dfsg/src/security_slicing/configure 2011-02-07 15:05:33.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/security_slicing/configure 2011-10-10 08:56:40.000000000 +0000 @@ -1,11 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.65. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # # # This configure script is free software; the Free Software Foundation @@ -315,7 +315,7 @@ test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -355,19 +355,19 @@ fi # as_fn_arith -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -529,7 +529,7 @@ exec 6>&1 # Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -668,9 +668,8 @@ fi case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -715,7 +714,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -741,7 +740,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -945,7 +944,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -961,7 +960,7 @@ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -991,8 +990,8 @@ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." ;; *=*) @@ -1000,7 +999,7 @@ # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1018,13 +1017,13 @@ if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" + as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1047,7 +1046,7 @@ [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1061,8 +1060,8 @@ if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1077,9 +1076,9 @@ ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" + as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" + as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1118,11 +1117,11 @@ fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1162,7 +1161,7 @@ --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages + -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1288,9 +1287,9 @@ if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.65 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1305,7 +1304,7 @@ running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -1415,9 +1414,11 @@ { echo - $as_echo "## ---------------- ## + cat <<\_ASBOX +## ---------------- ## ## Cache variables. ## -## ---------------- ##" +## ---------------- ## +_ASBOX echo # The following way of writing the cache mishandles newlines in values, ( @@ -1451,9 +1452,11 @@ ) echo - $as_echo "## ----------------- ## + cat <<\_ASBOX +## ----------------- ## ## Output variables. ## -## ----------------- ##" +## ----------------- ## +_ASBOX echo for ac_var in $ac_subst_vars do @@ -1466,9 +1469,11 @@ echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + cat <<\_ASBOX +## ------------------- ## ## File substitutions. ## -## ------------------- ##" +## ------------------- ## +_ASBOX echo for ac_var in $ac_subst_files do @@ -1482,9 +1487,11 @@ fi if test -s confdefs.h; then - $as_echo "## ----------- ## + cat <<\_ASBOX +## ----------- ## ## confdefs.h. ## -## ----------- ##" +## ----------- ## +_ASBOX echo cat confdefs.h echo @@ -1539,12 +1546,7 @@ ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -1559,11 +1561,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } + . "$ac_site_file" fi done @@ -1639,7 +1637,7 @@ $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -1811,7 +1809,7 @@ if test "$short_mark" = "no"; then fp=FORCE_"$up" if eval test "\$$fp" = "yes"; then - as_fn_error $? "$lp requested but $reason." "$LINENO" 5 + as_fn_error "$lp requested but $reason." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp disabled because $reason." >&5 $as_echo "$as_me: WARNING: $lp disabled because $reason." >&2;} @@ -2001,7 +1999,7 @@ $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "Makefile.in"; then ac_cv_file_Makefile_in=yes else @@ -2050,7 +2048,7 @@ #eval ENABLE_DYNAMIC_$up=\$ENABLE if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then - as_fn_error $? "security_slicing is not available" "$LINENO" 5 + as_fn_error "security_slicing is not available" "$LINENO" 5 fi FORCE_SECURITY_SLICING=$FORCE @@ -2087,7 +2085,9 @@ echo "security_slicing... $ENABLE" - +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) @@ -2160,7 +2160,7 @@ - ac_config_files="$ac_config_files ./Makefile" + ac_config_files="$ac_config_files ./Makefile" @@ -2184,7 +2184,7 @@ $as_echo "$as_me: $name: $ep_v$info" >&6;} fi done - cat >confcache <<\_ACEOF + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. @@ -2303,7 +2303,6 @@ ac_libobjs= ac_ltlibobjs= -U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -2465,19 +2464,19 @@ (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -2673,7 +2672,7 @@ test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -2727,7 +2726,7 @@ # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -2780,10 +2779,10 @@ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -2798,16 +2797,11 @@ while test $# != 0 do case $1 in - --*=?*) + --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; *) ac_option=$1 ac_optarg=$2 @@ -2829,7 +2823,6 @@ $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -2840,7 +2833,7 @@ ac_cs_silent=: ;; # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' + -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -2891,7 +2884,7 @@ case $ac_config_target in "./Makefile") CONFIG_FILES="$CONFIG_FILES ./Makefile" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -2927,7 +2920,7 @@ { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -2944,7 +2937,7 @@ fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' + ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi @@ -2958,18 +2951,18 @@ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -3058,28 +3051,20 @@ else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 + || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// s/^[^=]*=[ ]*$// }' fi @@ -3097,7 +3082,7 @@ esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -3125,7 +3110,7 @@ [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -3152,7 +3137,7 @@ case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -3278,22 +3263,22 @@ $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 +which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} +which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; @@ -3313,7 +3298,7 @@ ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -3334,7 +3319,7 @@ exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 + $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 diff -Nru frama-c-20110201+carbon+dfsg/src/security_slicing/register_gui.ml frama-c-20111001+nitrogen+dfsg/src/security_slicing/register_gui.ml --- frama-c-20110201+carbon+dfsg/src/security_slicing/register_gui.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/security_slicing/register_gui.ml 2011-10-10 08:38:07.000000000 +0000 @@ -70,12 +70,12 @@ ~callback: (fun () -> ForwardHighlighterState.set - (Components.get_forward_component ki); + (Components.get_forward_component ki); IndirectBackwardHighlighterState.set - (Components.get_indirect_backward_component ki); - DirectHighlighterState.set - (Components.get_direct_component ki); - main_ui#rehighlight ())) + (Components.get_indirect_backward_component ki); + DirectHighlighterState.set + (Components.get_direct_component ki); + main_ui#rehighlight ())) | _ -> () let main main_ui = diff -Nru frama-c-20110201+carbon+dfsg/src/security_slicing/security_slicing_parameters.ml frama-c-20111001+nitrogen+dfsg/src/security_slicing/security_slicing_parameters.ml --- frama-c-20110201+carbon+dfsg/src/security_slicing/security_slicing_parameters.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/security_slicing/security_slicing_parameters.ml 2011-10-10 08:38:07.000000000 +0000 @@ -38,6 +38,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/security_slicing/security_slicing_parameters.mli frama-c-20111001+nitrogen+dfsg/src/security_slicing/security_slicing_parameters.mli --- frama-c-20110201+carbon+dfsg/src/security_slicing/security_slicing_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/security_slicing/security_slicing_parameters.mli 2011-10-10 08:38:07.000000000 +0000 @@ -28,11 +28,11 @@ include S -module Slicing: BOOL +module Slicing: Bool (** Perform the security slicing pre-analysis. *) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/semantic_callgraph/options.mli frama-c-20111001+nitrogen+dfsg/src/semantic_callgraph/options.mli --- frama-c-20110201+carbon+dfsg/src/semantic_callgraph/options.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/semantic_callgraph/options.mli 2011-10-10 08:38:07.000000000 +0000 @@ -23,8 +23,8 @@ include Plugin.S val name: string -module Filename: Plugin.STRING -module InitFunc: Plugin.STRING_SET +module Filename: Plugin.String +module InitFunc: Plugin.String_set (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/semantic_callgraph/register.ml frama-c-20111001+nitrogen+dfsg/src/semantic_callgraph/register.ml --- frama-c-20110201+carbon+dfsg/src/semantic_callgraph/register.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/semantic_callgraph/register.ml 2011-10-10 08:38:07.000000000 +0000 @@ -20,9 +20,6 @@ (* *) (**************************************************************************) -module H = Hashtbl - -open Db_types open Db open Options open Cil_types @@ -37,7 +34,7 @@ how the numbering of varinfo is done internally *) let equal = Kernel_function.equal - let hash kf = H.hash (Kernel_function.get_name kf) + let hash kf = Hashtbl.hash (Kernel_function.get_name kf) let compare kf1 kf2 = if kf1 == kf2 then 0 else @@ -58,13 +55,13 @@ State_builder.Option_ref (Datatype.Make (struct - (* [JS 2010/09/27] do better? *) - include Datatype.Serializable_undefined - type t = SGraph.t - let name = "SGraph" - let reprs = [ SGraph.create () ] - let mem_project = Datatype.never_any_project - end)) + (* [JS 2010/09/27] do better? *) + include Datatype.Serializable_undefined + type t = SGraph.t + let name = "SGraph" + let reprs = [ SGraph.create () ] + let mem_project = Datatype.never_any_project + end)) (struct let name = "SGState" let dependencies = [ Value.self ] @@ -89,11 +86,11 @@ (fun kf -> if !Value.is_called kf then SGraph.add_vertex g kf; List.iter - (fun (caller,call_sites) -> - List.iter - (fun call_site -> SGraph.add_edge_e g (kf,call_site,caller)) - call_sites) - (!Value.callers kf)); + (fun (caller,call_sites) -> + List.iter + (fun call_site -> SGraph.add_edge_e g (kf,call_site,caller)) + call_sites) + (!Value.callers kf)); g) module Service = @@ -109,12 +106,11 @@ [ `Style (if Kernel_function.is_definition v then `Bold else `Dotted) ] - let equal = Kernel_function.equal - let hash = Kernel_function.hash - let entry_point () = - fst - (try Globals.entry_point () - with Globals.No_such_entry_point _ -> assert false) + let equal = Kernel_function.equal + let hash = Kernel_function.hash + let entry_point () = + try Some (fst (Globals.entry_point ())) + with Globals.No_such_entry_point _ -> None end let iter_vertex = SGraph.iter_vertex let iter_succ = SGraph.iter_succ @@ -129,25 +125,30 @@ (struct let name = "SemanticsServicestate" let dependencies = - [ SGState.self; Parameters.MainFunction.self; InitFunc.self ] + [ SGState.self; Kernel.MainFunction.self; InitFunc.self ] let kind = `Internal end) let get_init_funcs () = - let entry_point_name = Parameters.MainFunction.get () in - let init_funcs = - (* entry point is always a root *) - Datatype.String.Set.add entry_point_name (InitFunc.get ()) - in - (* Add the callees of entry point as roots *) - let callees = - let kf = fst (Globals.entry_point ()) in - !Db.Users.get kf - in - Kernel_function.Hptset.fold - (fun kf acc -> Datatype.String.Set.add (Kernel_function.get_name kf) acc) - callees - init_funcs + let init_funcs = InitFunc.get () in + try + let callees = + let kf, _ = Globals.entry_point () in + !Db.Users.get kf + in + (** add the entry point as root *) + let init_funcs = + Datatype.String.Set.add (Kernel.MainFunction.get ()) init_funcs + in + (* add the callees of entry point as roots *) + Kernel_function.Hptset.fold + (fun kf acc -> Datatype.String.Set.add (Kernel_function.get_name kf) acc) + callees + init_funcs + with Globals.No_such_entry_point _ -> + (* always an entry point for the semantic callgraph since value analysis has + been computed. *) + assert false let compute () = feedback "beginning analysis"; @@ -201,18 +202,18 @@ let rec aux kf = if SGraph.mem_vertex cg kf then SGraph.iter_succ - (fun caller -> - if not (V.mem visited caller) then begin - f caller; - V.add visited caller (); - aux caller - end) - cg - kf + (fun caller -> + if not (V.mem visited caller) then begin + f caller; + V.add visited caller (); + aux caller + end) + cg + kf else Options.warning ~once:true - "Function %s not registered in semantic callgraph. Skipped." - (Kernel_function.get_name kf) + "Function %s not registered in semantic callgraph. Skipped." + (Kernel_function.get_name kf) in aux kf diff -Nru frama-c-20110201+carbon+dfsg/src/semantic_callgraph/Semantic_callgraph.mli frama-c-20111001+nitrogen+dfsg/src/semantic_callgraph/Semantic_callgraph.mli --- frama-c-20110201+carbon+dfsg/src/semantic_callgraph/Semantic_callgraph.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/semantic_callgraph/Semantic_callgraph.mli 2011-10-10 08:38:07.000000000 +0000 @@ -24,5 +24,5 @@ (** Semantic callgraph. *) -(** No function is directly exported: they are registered in +(** No function is directly exported: they are registered in {!Db.Semantic_Callgraph}. *) diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/fct_slice.ml frama-c-20111001+nitrogen+dfsg/src/slicing/fct_slice.ml --- frama-c-20110201+carbon+dfsg/src/slicing/fct_slice.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/fct_slice.ml 2011-10-10 08:38:22.000000000 +0000 @@ -102,7 +102,7 @@ | None, sgn -> None, sgn | Some (None), sgn -> None, sgn | Some (Some f), sgn -> Some f, sgn - with PdgIndex.NotFound -> empty + with Not_found -> empty in (call_id, f, sgn) let get_call_f_called call_id = get_f_called (get_info_call call_id) @@ -308,7 +308,6 @@ val debug_marked_ff : Format.formatter -> T.t_fct_slice -> unit end = struct - module FI = PdgIndex.FctIndex module Marks4Pdg = struct type t = Marks.t_mark @@ -339,7 +338,7 @@ let pdg = M.get_fi_pdg fi in if (PdgTypes.Pdg.is_top pdg) then raise SlicingTypes.NoPdg; let marks = match marks with None -> empty pdg - | Some (pdg, marks) -> (pdg, FI.copy marks) + | Some (pdg, marks) -> (pdg, PdgIndex.FctIndex.copy marks) in let ff = { T.ff_fct = fi ; T.ff_id = ff_num ; T.ff_marks = marks ; T.ff_called_by = [] } in @@ -375,12 +374,12 @@ assert (Db.Pdg.from_same_fun pdg1 pdg2) ; let merge_marks m1 m2 = Marks.merge_marks [m1; m2] in let merge_call_info _c1 _c2 = None in - let fm = FI.merge fm1 fm2 merge_marks merge_call_info in + let fm = PdgIndex.FctIndex.merge fm1 fm2 merge_marks merge_call_info in (pdg1, fm) let get_mark fm node_key = - try FI.find_info (get_marks fm) node_key - with PdgIndex.NotFound -> Marks.bottom_mark + try PdgIndex.FctIndex.find_info (get_marks fm) node_key + with Not_found -> Marks.bottom_mark let get_node_mark ff node_key = let fm = ff.T.ff_marks in get_mark fm node_key @@ -391,13 +390,13 @@ let get_node_marks ff node_key = let fm = ff.T.ff_marks in - FI.find_all (get_marks fm) node_key + PdgIndex.FctIndex.find_all (get_marks fm) node_key - let get_sgn ff = let fm = ff.T.ff_marks in Some (FI.sgn (get_marks fm)) + let get_sgn ff = let fm = ff.T.ff_marks in Some (PdgIndex.FctIndex.sgn (get_marks fm)) let get_all_input_marks fm = let fm = get_marks fm in - let in_marks = Marks.get_all_input_marks (FI.sgn fm) in + let in_marks = Marks.get_all_input_marks (PdgIndex.FctIndex.sgn fm) in let out_marks = [] in (in_marks, out_marks) @@ -589,12 +588,12 @@ let m = Marks.inter_marks dpds_marks in let marks = check_in_params (n+1) params in if not (Marks.is_bottom_mark m) then begin - SlicingParameters.debug ~level:2 - "[Fct_Slice.FctMarks.mark_visible_inputs] %a -> %a" + SlicingKernel.debug ~level:2 + "[Fct_Slice.FctMarks.mark_visible_inputs] %a -> %a" (!Db.Pdg.pretty_node true) node Marks.pretty_mark m; PdgMarks.add_node_to_select marks (node, None) m end else - marks + marks in let new_marks = check_in_params 1 param_list in mark_and_propagate ff_marks ~to_prop new_marks @@ -611,13 +610,13 @@ let m = Marks.inter_marks dpds_marks in if not (Marks.is_bottom_mark m) then begin SlicingParameters.debug ~level:2 - "[Fct_Slice.FctMarks.mark_visible_outputs] %a -> %a" + "[Fct_Slice.FctMarks.mark_visible_outputs] %a -> %a" (!Db.Pdg.pretty_node true) out_node Marks.pretty_mark m; let select = PdgMarks.add_node_to_select [] (out_node, None) m in let to_prop = mark_and_propagate ff_marks select in assert (to_prop = PropMark.empty_to_prop); () end - with PdgIndex.NotFound -> () + with Not_found -> () let debug_ff_marks fmt fm = let pdg, fm = fm in @@ -625,9 +624,9 @@ let node_key = PdgTypes.Node.elem_key node in let m = try - try FI.find_info fm node_key + try PdgIndex.FctIndex.find_info fm node_key with PdgIndex.CallStatement -> assert false - with PdgIndex.NotFound -> Marks.bottom_mark + with Not_found -> Marks.bottom_mark in Format.fprintf fmt "%a : %a@." (!Db.Pdg.pretty_node true) node Marks.pretty_mark m @@ -996,11 +995,11 @@ * have to add some marks, but no new inputs. *) let add_spare_call_inputs called_kf call_info = let (ff_caller, _call) = CallInfo.get_call_id call_info in - SlicingParameters.debug ~level:2 "[slicing] add_spare_call_inputs in %s@." (M.ff_name ff_caller); + SlicingKernel.debug ~level:2 "[slicing] add_spare_call_inputs in %s@." (M.ff_name ff_caller); let sig_call = CallInfo.get_call_sig call_info in let out0, marked_out_zone = Marks.get_marked_out_zone sig_call in let called_in_zone = get_called_needed_input called_kf out0 marked_out_zone in - SlicingParameters.debug ~level:2 "\tneed %a inputs : %a@." Kernel_function.pretty_name called_kf + SlicingKernel.debug ~level:2 "\tneed %a inputs : %a@." Kernel_function.pretty called_kf Locations.Zone.pretty called_in_zone; let needed_nodes, undef = get_call_in_nodes called_kf call_info called_in_zone in @@ -1054,7 +1053,7 @@ if more_inputs then (* [ff] needs too many inputs *) begin - SlicingParameters.debug ~level:2 "[Fct_Slice.choose_precise_slice] %s ? too many inputs" + SlicingKernel.debug ~level:2 "[Fct_Slice.choose_precise_slice] %s ? too many inputs" (M.ff_name ff); find slices end @@ -1080,7 +1079,7 @@ | [] -> make_new_ff fi_to_call true | ff :: [] -> ff, [] | _ -> (* TODO : choose a slice *) - Extlib.not_yet_implemented "choose_min_slice with several slices" + Extlib.not_yet_implemented "choose_min_slice with several slices" in let choose_full_slice fi_to_call = SlicingParameters.debug ~level:2 "PropagateMarksOnly -> choose_full_slice"; @@ -1120,7 +1119,8 @@ choose_precise_slice fi_to_call call_info in (T.CallSlice ff_to_call), new_filters with SlicingTypes.NoPdg -> - Cil.log "[slicing]unable to compute %s PDG : call source function" + SlicingParameters.feedback + "unable to compute %s PDG : call source function" (M.fi_name fi_to_call); T.CallSrc None, [] in to_call, new_filters @@ -1346,7 +1346,7 @@ let get_node_key_mark ff k = try FctMarks.get_node_mark ff k - with PdgIndex.NotFound -> Marks.bottom_mark + with Not_found -> Marks.bottom_mark let get_node_mark ff node = get_node_key_mark ff (PdgTypes.Node.elem_key node) @@ -1358,7 +1358,7 @@ try match FctMarks.get_sgn ff with None -> Marks.bottom_mark | Some sgn -> Marks.get_input_mark sgn n - with PdgIndex.NotFound -> Marks.bottom_mark + with Not_found -> Marks.bottom_mark let get_label_mark ff label_stmt label = let key = PdgIndex.Key.label_key label_stmt label in @@ -1374,7 +1374,7 @@ | _ -> assert false in Marks.merge_marks marks - with PdgIndex.NotFound -> + with Not_found -> match stmt.Cil_types.skind with | Cil_types.Block _ | Cil_types.UnspecifiedSequence _ -> (* block are always visible for syntactic reasons *) @@ -1385,7 +1385,7 @@ try let key = PdgIndex.Key.top_input in FctMarks.get_fi_node_mark fi key - with PdgIndex.NotFound -> Marks.bottom_mark + with Not_found -> Marks.bottom_mark let merge_inputs_m1_mark ff = let ff_sig = @@ -1413,7 +1413,7 @@ let merge m = acc := merge m !acc ; if is_top !acc then - raise StopMerging (* acceleration when top is reached *) + raise StopMerging (* acceleration when top is reached *) in let rec merge_fun_callers kf = let merge_fun_caller (kf,_) = merge_fun_callers kf in @@ -1423,13 +1423,13 @@ List.iter (fun x -> merge (get_value x)) (get_list proj kf) ; List.iter merge_fun_caller (!Db.Value.callers kf) end - (* else no way to add something, the [kf] contribution is already - accumulated. *) + (* else no way to add something, the [kf] contribution is already + accumulated. *) in - merge_fun_callers kf; + merge_fun_callers kf; !acc with StopMerging -> - !acc + !acc end (** The mark [m] related to all statements of a source function [kf]. @@ -1455,3 +1455,9 @@ | None -> Format.fprintf fmt "<not computed>@." | Some s -> Format.fprintf fmt "%a@." Marks.pretty_sig s (*-----------------------------------------------------------------------*) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/fct_slice.mli frama-c-20111001+nitrogen+dfsg/src/slicing/fct_slice.mli --- frama-c-20110201+carbon+dfsg/src/slicing/fct_slice.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/fct_slice.mli 2011-10-10 08:38:22.000000000 +0000 @@ -32,10 +32,10 @@ * because there cannot be any slice for it. * @raise SlicingTypes.NoPdg when there is no PDG for the function. *) -val make_new_ff : SlicingInternals.t_fct_info -> bool -> +val make_new_ff : SlicingInternals.t_fct_info -> bool -> t_fct_slice * t_crit list -val merge_slices : t_fct_slice -> t_fct_slice -> +val merge_slices : t_fct_slice -> t_fct_slice -> t_fct_slice * t_crit list val copy_slice : t_fct_slice -> t_fct_slice @@ -44,19 +44,19 @@ SlicingInternals.t_fct_base_criterion -> SlicingInternals.t_fct_base_criterion -val apply_add_marks : +val apply_add_marks : t_fct_slice -> SlicingInternals.t_fct_base_criterion -> t_crit list -val add_marks_to_fi : - SlicingInternals.t_project -> - SlicingInternals.t_fct_info -> +val add_marks_to_fi : + SlicingInternals.t_project -> + SlicingInternals.t_fct_info -> SlicingInternals.t_fct_base_criterion -> bool -> t_crit list -> bool * t_crit list -val add_top_mark_to_fi : - SlicingInternals.t_fct_info -> +val add_top_mark_to_fi : + SlicingInternals.t_fct_info -> SlicingInternals.t_pdg_mark -> bool -> t_crit list -> t_crit list @@ -67,10 +67,10 @@ val apply_change_call : SlicingInternals.t_project -> t_fct_slice -> SlicingInternals.t_call_id -> - SlicingInternals.t_called_fct -> + SlicingInternals.t_called_fct -> t_crit list -val apply_choose_call : SlicingInternals.t_project -> +val apply_choose_call : SlicingInternals.t_project -> t_fct_slice -> SlicingInternals.t_call_id -> t_crit list @@ -78,7 +78,7 @@ t_fct_slice -> SlicingInternals.t_call_id -> (SlicingInternals.t_fct_base_criterion * bool) -> t_crit list - + val apply_missing_outputs : SlicingInternals.t_project -> t_fct_slice -> SlicingInternals.t_call_id -> SlicingInternals.t_fct_base_criterion -> bool -> @@ -88,7 +88,7 @@ t_mark PdgMarks.t_info_called_outputs -> t_crit list -val get_called_slice : +val get_called_slice : t_fct_slice -> SlicingInternals.t_call_id -> (t_fct_slice option * bool) val get_node_mark : t_fct_slice -> PdgTypes.Node.t -> t_mark @@ -100,7 +100,7 @@ val get_param_mark : t_fct_slice -> int -> t_mark val get_local_var_mark : t_fct_slice -> Cil_types.varinfo -> t_mark val get_input_loc_under_mark : t_fct_slice -> Locations.Zone.t -> t_mark - + val get_mark_from_src_fun : SlicingInternals.t_project -> Kernel_function.t -> t_mark val merge_inputs_m1_mark : t_fct_slice -> t_mark diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/printSlice.ml frama-c-20111001+nitrogen+dfsg/src/slicing/printSlice.ml --- frama-c-20110201+carbon+dfsg/src/slicing/printSlice.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/printSlice.ml 2011-10-10 08:38:22.000000000 +0000 @@ -55,7 +55,7 @@ in Format.fprintf fmt "/* sig call : %a */@\n%t" SlicingMarks.pretty_sig sgn print_called - with Db.Pdg.NotFound -> Format.fprintf fmt "/* invisible call */@." + with Not_found -> Format.fprintf fmt "/* invisible call */@." class printerClass optional_ff = object(self) inherit Printer.print () as super @@ -72,7 +72,7 @@ try let m = Fct_slice.get_local_var_mark ff var in SlicingMarks.mark_to_string m - with Db.Pdg.NotFound -> "[---]" + with Not_found -> "[---]" in Format.fprintf fmt "/* %s */ %a" str_m @@ -85,7 +85,7 @@ let str_m = try let m = Fct_slice.get_stmt_mark ff stmt in SlicingMarks.mark_to_string m - with Db.Pdg.NotFound -> "[---]" + with Not_found -> "[---]" in if (M.is_call_stmt stmt) then Format.fprintf fmt "%t/* %s */" (str_call_sig ff stmt) str_m diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/register_gui.ml frama-c-20111001+nitrogen+dfsg/src/slicing/register_gui.ml --- frama-c-20110201+carbon+dfsg/src/slicing/register_gui.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/register_gui.ml 2011-10-10 08:38:22.000000000 +0000 @@ -25,16 +25,20 @@ open Cil_types open Cil_datatype -module Enable = - State_builder.Ref +(* Show or hide the 'Slicing' column of the gui filetree. *) +let show_column = ref (fun () -> ()) + +(* Are results shown? *) +module Enabled = struct + include State_builder.Ref (Datatype.Bool) (struct let name = "Slicing_gui.State" - let dependencies = [] + let dependencies = [!Db.Slicing.self] let kind = `Internal let default () = false end) - +end (* for slicing callback *) let mk_selection fselect = fselect Db.Slicing.Select.empty_selects @@ -56,10 +60,10 @@ !Db.Slicing.Request.apply_all_internal project; if SlicingParameters.Mode.Callers.get () then !Db.Slicing.Slice.remove_uncalled project; - let sliced_project_name = + let sliced_project_name = let postfix = SlicingParameters.ExportedProjectPostfix.get () in if postfix = "" then project_name else (project_name ^ " " ^ postfix) - in + in let new_project = !Db.Slicing.Project.extract sliced_project_name project in @@ -117,7 +121,7 @@ if not (Db.Value.is_computed ()) then begin let tag_style_oblique = Gtk_helper.make_tag main_ui#annot_window#buffer - ~name:"slicing:style oblique" [`STYLE `OBLIQUE ; ] + ~name:"slicing:style oblique" [`STYLE `OBLIQUE ; ] in main_ui#annot_window#buffer#insert "[Slicing] activation requires an execution of a "; @@ -160,16 +164,18 @@ let slicing_selector (popup_factory:GMenu.menu GMenu.factory) (main_ui:Design.main_window_extension_points) ~button localizable = - if (not (Db.Value.is_computed ())) || not (Enable.get ()) + if (not (Db.Value.is_computed ())) || not (Enabled.get ()) then ignore - (popup_factory#add_item "_Slicing ..." - ~callback: - (fun () -> - if (not (Db.Value.is_computed ())) - then gui_compute_values main_ui ; - if Db.Value.is_computed () - then Enable.set true)) + (popup_factory#add_item "Enable _slicing" + ~callback: + (fun () -> + if (not (Db.Value.is_computed ())) + then gui_compute_values main_ui ; + if Db.Value.is_computed () + then (Enabled.set true; + !show_column ()) + )) else let slicing_project = !Db.Slicing.Project.get_project () in if button = 1 then @@ -222,71 +228,71 @@ let add_slicing_item name = add_item slicing_factory name in let mk_slice = gui_mk_slice main_ui in let add_slice_menu kf_opt kf_ki_opt = - (let callback kf = - mk_slice + (let callback kf = + mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing effects of function %a" - Kernel_function.pretty_name kf) + Pretty_utils.sfprintf + "Request for slicing effects of function %a" + Kernel_function.pretty kf) (mk_selection_all !Db.Slicing.Select.select_func_calls_to kf) - in + in add_slicing_item "Slice calls to" kf_opt ~callback); - (let callback kf = + (let callback kf = mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing entrance into function %a" - Kernel_function.pretty_name kf) + Pretty_utils.sfprintf + "Request for slicing entrance into function %a" + Kernel_function.pretty kf) (mk_selection_all !Db.Slicing.Select.select_func_calls_into kf) - in + in add_slicing_item "Slice calls into" kf_opt ~callback); (let callback kf = mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for returned value of function %a" - Kernel_function.pretty_name kf) + Pretty_utils.sfprintf + "Request for returned value of function %a" + Kernel_function.pretty kf) (mk_selection_all !Db.Slicing.Select.select_func_return kf) - in - add_slicing_item "Slice result" + in + add_slicing_item "Slice result" (Extlib.opt_filter - (fun kf -> - let is_not_void_kf x = + (fun kf -> + let is_not_void_kf x = match x.Cil_types.vtype with | Cil_types.TFun (Cil_types.TVoid (_),_,_,_) -> false | _ -> true - in is_not_void_kf (Kernel_function.get_vi kf)) + in is_not_void_kf (Kernel_function.get_vi kf)) kf_opt) ~callback); - (let callback (kf, ki) = + (let callback (kf, ki) = mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing effects of statement %d" + Pretty_utils.sfprintf + "Request for slicing effects of statement %d" ki.sid) (mk_selection_all !Db.Slicing.Select.select_stmt ki kf) - in + in add_slicing_item "Slice stmt" kf_ki_opt ~callback); - (let callback (kf, ki) = + (let callback (kf, ki) = let do_with_txt txt = try let lval_str = - Datatype.String.Set.add txt Datatype.String.Set.empty - in + Datatype.String.Set.add txt Datatype.String.Set.empty + in mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing Lvalue %s before statement %d" + Pretty_utils.sfprintf + "Request for slicing Lvalue %s before statement %d" txt ki.sid) (mk_selection_cad !Db.Slicing.Select.select_stmt_lval lval_str ~before:true ki ~scope:ki ~eval:ki kf) with e -> - main_ui#error "Invalid expression: %s" (Printexc.to_string e) + main_ui#error "Invalid expression: %s" (Printexc.to_string e) in let txt = GToolbox.input_string @@ -294,91 +300,91 @@ statement" "" in - Extlib.may do_with_txt txt - in + Extlib.may do_with_txt txt + in add_slicing_item "Slice lval" kf_ki_opt ~callback); - (let callback (kf, ki) = + (let callback (kf, ki) = let do_with_txt txt = try let lval_str = - Datatype.String.Set.add txt Datatype.String.Set.empty - in + Datatype.String.Set.add txt Datatype.String.Set.empty + in mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing read accesses to Lvalue %s" + Pretty_utils.sfprintf + "Request for slicing read accesses to Lvalue %s" txt) (mk_selection_cad - !Db.Slicing.Select.select_func_lval_rw + !Db.Slicing.Select.select_func_lval_rw ~rd:lval_str - ~wr:Datatype.String.Set.empty - ~scope:ki - ~eval:ki kf) + ~wr:Datatype.String.Set.empty + ~scope:ki + ~eval:ki kf) with e -> - main_ui#error "Invalid expression: %s" (Printexc.to_string e) + main_ui#error "Invalid expression: %s" (Printexc.to_string e) in let txt = GToolbox.input_string ~title:"Input a pure Lvalue expression to slice read accesses" "" in - Extlib.may do_with_txt txt - in + Extlib.may do_with_txt txt + in add_slicing_item "Slice rd" kf_ki_opt ~callback); - (let callback (kf, ki) = + (let callback (kf, ki) = let do_with_txt txt = try let lval_str = - Datatype.String.Set.add txt Datatype.String.Set.empty - in + Datatype.String.Set.add txt Datatype.String.Set.empty + in mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing writen accesses to Lvalue %s" + Pretty_utils.sfprintf + "Request for slicing writen accesses to Lvalue %s" txt) (mk_selection_cad - !Db.Slicing.Select.select_func_lval_rw + !Db.Slicing.Select.select_func_lval_rw ~rd:Datatype.String.Set.empty - ~wr:lval_str - ~scope:ki - ~eval:ki kf) + ~wr:lval_str + ~scope:ki + ~eval:ki kf) with e -> - main_ui#error "Invalid expression: %s" (Printexc.to_string e) + main_ui#error "Invalid expression: %s" (Printexc.to_string e) in let txt = GToolbox.input_string ~title:"Input a pure Lvalue expression to slice read accesses" "" in - Extlib.may do_with_txt txt - in + Extlib.may do_with_txt txt + in add_slicing_item "Slice wr" kf_ki_opt ~callback); - let callback (kf, ki) = + let callback (kf, ki) = mk_slice ~info:(fun () -> - Pretty_utils.sfprintf - "Request for slicing accessibility to statement %d" + Pretty_utils.sfprintf + "Request for slicing accessibility to statement %d" ki.sid) (mk_selection_all !Db.Slicing.Select.select_stmt_ctrl ki kf) - in + in add_slicing_item "Slice ctrl" kf_ki_opt ~callback in let some_kf_from_vi vi = - try let kf = Globals.Functions.get vi in - if Enable.get () && !Db.Value.is_called kf then Some kf else None + try let kf = Globals.Functions.get vi in + if Enabled.get () && !Db.Value.is_called kf then Some kf else None with Not_found -> None in let some_kf_from_lv lv = match lv with | Var vi,_ -> some_kf_from_vi vi | _ -> None in - let some_kf_ki kf ki = - if Enable.get () + let some_kf_ki kf stmt = + if Enabled.get () && !Db.Value.is_called kf - && Db.Value.is_accessible (Cil_types.Kstmt ki) - then Some (kf, ki) else None in + && Db.Value.is_reachable_stmt stmt + then Some (kf, stmt) else None in begin (* add menu for slicing and scope plug-in *) match localizable with | Pretty_source.PLval (Some kf,(Kstmt stmt),lv) -> @@ -395,7 +401,7 @@ ignore (slicing_factory#add_separator ()); add_slicing_item "_Disable" (Some ()) - ~callback:(fun () -> Enable.set false); + ~callback:(fun () -> Enabled.set false); add_slicing_item "_Clear" (if slicing_project = None then None else Some ()) ~callback:(fun () -> gui_set_project main_ui None) ; @@ -414,33 +420,33 @@ let slicing_highlighter (buffer:GSourceView2.source_buffer) localizable ~start ~stop = - if Enable.get () then begin + if Enabled.get () then begin (* Definition for highlight 'Slicing' *) let highlight project = let ki = Pretty_source.ki_of_localizable localizable in if Db.Value.is_accessible ki then let unused_code_area = - Gtk_helper.make_tag buffer + Gtk_helper.make_tag buffer ~name:"slicing_unused" [`STRIKETHROUGH true ] in let spare_code_area = - Gtk_helper.make_tag buffer ~name:"slicing_spare" [`UNDERLINE `LOW] in + Gtk_helper.make_tag buffer ~name:"slicing_spare" [`UNDERLINE `LOW] in let necessary_code_area = - Gtk_helper.make_tag buffer + Gtk_helper.make_tag buffer ~name:"slicing_necessary" [`BACKGROUND "green"] in let apply_on_one_project_and_merge_slices kf pb pe mark_of_slice = let apply_mark mark = - if SlicingParameters.debug_atleast 1 then - SlicingParameters.debug "Got mark: %a" + if SlicingParameters.debug_atleast 1 then + SlicingParameters.debug "Got mark: %a" !Db.Slicing.Mark.pretty mark; if !Db.Slicing.Mark.is_bottom mark then Gtk_helper.apply_tag buffer unused_code_area pb pe; if !Db.Slicing.Mark.is_spare mark then Gtk_helper.apply_tag buffer spare_code_area pb pe; if (!Db.Slicing.Mark.is_ctrl mark - || !Db.Slicing.Mark.is_data mark - || !Db.Slicing.Mark.is_addr mark) + || !Db.Slicing.Mark.is_data mark + || !Db.Slicing.Mark.is_addr mark) then Gtk_helper.apply_tag buffer necessary_code_area pb pe in @@ -475,20 +481,20 @@ end in let tag_stmt kf stmt pb pe = - assert (Db.Value.is_accessible (Kstmt stmt)) ; + assert (Db.Value.is_reachable_stmt stmt) ; apply_on_one_project_and_merge_slices - kf - pb - pe - (fun _ slice -> !Db.Slicing.Slice.get_mark_from_stmt slice stmt) + kf + pb + pe + (fun _ slice -> !Db.Slicing.Slice.get_mark_from_stmt slice stmt) in let tag_vdecl kf vi pb pe = if not vi.vglob then - apply_on_one_project_and_merge_slices - kf - pb - pe - (fun _ slice -> !Db.Slicing.Slice.get_mark_from_local_var slice vi) + apply_on_one_project_and_merge_slices + kf + pb + pe + (fun _ slice -> !Db.Slicing.Slice.get_mark_from_local_var slice vi) in match localizable with | Pretty_source.PStmt (kf,stmt) -> tag_stmt kf stmt start stop @@ -496,7 +502,7 @@ | Pretty_source.PVDecl (None,_) | Pretty_source.PLval _ | Pretty_source.PTermLval _ - | Pretty_source.PGlobal _ + | Pretty_source.PGlobal _ | Pretty_source.PIP _ -> () in let slicing_project = !Db.Slicing.Project.get_project () in @@ -590,26 +596,27 @@ let hbox2 = GPack.hbox ~packing:(table#attach ~left:1 ~top:0) () in (* [enabled_button] to give slicing menu available *) - let enable_refresh () = - gui_compute_values main_ui ; - main_ui#rehighlight () + let do_refresh to_enable = + if to_enable then gui_compute_values main_ui; + !show_column (); + main_ui#rehighlight (); in let enabled_button = let b = GButton.check_button ~label:"Enable" - ~active:(Enable.get ()) + ~active:(Enabled.get ()) ~packing:(table#attach ~left:0 ~top:0) () in main_ui#help_message b "%s" msg_help_enable_gui ; ignore (b#connect#toggled ~callback:(fun () -> - Enable.set b#active; - enable_refresh ())); + Enabled.set b#active; + do_refresh b#active)); b in let verbose_refresh = Gtk_helper.on_int ~lower:0 ~upper:3 hbox2 "Verbosity" - ~sensitive:Enable.get + ~sensitive:Enabled.get SlicingParameters.Verbose.get (gui_set_slicing_debug main_ui) in @@ -618,7 +625,7 @@ let slice_undef_button = let b = GButton.check_button ~label:"Libraries" - ~active:(Enable.get ()) + ~active:(Enabled.get ()) ~packing:(table#attach ~left:0 ~top:1) () in main_ui#help_message b "%s" msg_help_libraries ; ignore (b#connect#toggled @@ -629,7 +636,7 @@ let level_refresh = Gtk_helper.on_int ~lower:0 ~upper:3 hbox3 "Level" - ~sensitive:Enable.get + ~sensitive:Enabled.get SlicingParameters.Mode.Calls.get (gui_set_slicing_level main_ui) in @@ -640,50 +647,49 @@ let refresh () = let value_is_computed = Db.Value.is_computed () in let slicing_project = !Db.Slicing.Project.get_project () in - let enabled = Enable.get () in + let enabled = Enabled.get () in activate_button#misc#set_sensitive (not value_is_computed) ; enabled_button#misc#set_sensitive value_is_computed ; slice_undef_button#misc#set_sensitive enabled ; - verbose_refresh (); level_refresh (); - - if enabled_button#active <> enabled then - begin - enabled_button#set_active enabled ; - enable_refresh (); - end; - + if Enabled.get () <> enabled_button#active then ( + enabled_button#set_active (Enabled.get ()); + !show_column (); + ); slice_undef_button#set_active (SlicingParameters.Mode.SliceUndef.get()); - - ignore (refresh_combo_box combo_box_text slicing_project (enabled && value_is_computed)) + refresh_combo_box combo_box_text slicing_project + (enabled && value_is_computed) in refresh () ; "Slicing",w#coerce,Some refresh let file_tree_decorate (file_tree:Filetree.t) = - file_tree#append_pixbuf_column - "Slicing" - (fun globs -> - Extlib.may_map - (fun project -> + show_column := + file_tree#append_pixbuf_column + ~title:"Slicing" + (fun globs -> + Extlib.may_map + (fun project -> if (List.exists (fun glob -> match glob with - | GFun ({svar = vi},_ ) -> - begin - try - let kf = Globals.Functions.get vi - in (!Db.Slicing.Project.is_called project kf) - || ( [] != (!Db.Slicing.Slice.get_all project kf)) - with Not_found -> false - end - | _ -> false) + | GFun ({svar = vi},_ ) -> + begin + try + let kf = Globals.Functions.get vi + in (!Db.Slicing.Project.is_called project kf) + || ( [] != (!Db.Slicing.Slice.get_all project kf)) + with Not_found -> false + end + | _ -> false) globs) then [`STOCK_ID "gtk-apply"] else [`STOCK_ID ""]) - ~dft:[`STOCK_ID ""] - (!Db.Slicing.Project.get_project ())) + ~dft:[`STOCK_ID ""] + (!Db.Slicing.Project.get_project ())) + (fun () -> Enabled.get ()); + !show_column () let main (main_ui:Design.main_window_extension_points) = main_ui#register_source_selector slicing_selector; diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/register_gui.mli frama-c-20111001+nitrogen+dfsg/src/slicing/register_gui.mli --- frama-c-20110201+carbon+dfsg/src/slicing/register_gui.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/register_gui.mli 2011-10-10 08:38:22.000000000 +0000 @@ -32,4 +32,3 @@ compile-command: "LC_ALL=C make -C ../.. -j" End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/register.ml frama-c-20111001+nitrogen+dfsg/src/slicing/register.ml --- frama-c-20110201+carbon+dfsg/src/slicing/register.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/register.ml 2011-10-10 08:38:22.000000000 +0000 @@ -50,16 +50,16 @@ let print_select fmt db_select = let db_fvar, select = db_select in Format.fprintf fmt "In %a : %a@." - Ast_info.pretty_vname db_fvar Act.print_f_crit select + Varinfo.pretty_vname db_fvar Act.print_f_crit select let get_select_kf (fvar, _select) = Globals.Functions.get fvar let check_db_select fvar db_select = let db_fvar, select = db_select in - if db_fvar.vid <> fvar.vid then + if not (Cil_datatype.Varinfo.equal db_fvar fvar) then begin SlicingParameters.debug - "slice name = %s <> select = %a@." + "slice name = %s <> select = %a@." (fvar.vname) print_select db_select ; raise (Invalid_argument "This selection doesn't belong to the given function"); @@ -73,7 +73,8 @@ let check_ff_db_select ff = check_db_select (M.ff_svar ff) let bottom_msg kf = - Cil.log "[slicing] bottom PDG for function '%s': ignore selection" + SlicingParameters.feedback + "bottom PDG for function '%s': ignore selection" (Kernel_function.get_name kf) let basic_add_select kf select nodes ?(undef) nd_marks = @@ -125,9 +126,9 @@ let sel = mk_select pdg sel nodes undef mark in (fvar, sel) with - | Db.Pdg.NotFound -> (* stmt probably unreachable *) - SlicingParameters.debug - "@[Nothing to select for @[%a@]@ %s stmt %d@]" + | Not_found -> (* stmt probably unreachable *) + SlicingParameters.debug + "@[Nothing to select for @[%a@]@ %s stmt %d@]" Locations.Zone.pretty loc (if before then "before" else "after") stmt.sid ; select @@ -141,7 +142,7 @@ SlicingParameters.debug "[Register.select_in_out_zone] select zone %a (m=%a) at %s of %a" Locations.Zone.pretty loc SlicingMarks.pretty_mark mark - (if at_end then "end" else "begin") Kernel_function.pretty_name kf; + (if at_end then "end" else "begin") Kernel_function.pretty kf; let fvar, sel = check_kf_db_select kf select in match sel with | T.CuTop _ -> select @@ -156,7 +157,7 @@ let sel = mk_select pdg sel nodes undef mark in (fvar, sel) with - | Db.Pdg.NotFound -> assert false + | Not_found -> assert false | Db.Pdg.Top -> top_db_select kf mark | Db.Pdg.Bottom -> bottom_msg kf; select @@ -171,7 +172,7 @@ let stmt_nodes_to_select pdg stmt = let stmt_nodes = - try !Db.Pdg.find_stmt_and_blocks_nodes pdg stmt with Db.Pdg.NotFound -> [] + try !Db.Pdg.find_stmt_and_blocks_nodes pdg stmt with Not_found -> [] in (* TODO : add this when visibility of anotations are ok let stmt_nodes = @@ -235,7 +236,7 @@ let select_entry_point kf ?(select=empty_db_select kf) mark = SlicingParameters.debug ~level:1 "[Register.select_entry_point] of %a" - Kernel_function.pretty_name kf; + Kernel_function.pretty kf; try let pdg = !Db.Pdg.get kf in let node = !Db.Pdg.find_entry_point_node pdg in @@ -246,20 +247,20 @@ let select_return kf ?(select=empty_db_select kf) mark = SlicingParameters.debug ~level:1 "[Register.select_return] of %a" - Kernel_function.pretty_name kf; + Kernel_function.pretty kf; try let pdg = !Db.Pdg.get kf in let node = !Db.Pdg.find_ret_output_node pdg in let nd_marks = Act.build_simple_node_selection mark in basic_add_select kf select [node] nd_marks with - | Db.Pdg.NotFound -> (* unreachable ? *) select + | Not_found -> (* unreachable ? *) select | Db.Pdg.Top -> top_db_select kf mark | Db.Pdg.Bottom -> bottom_msg kf; empty_db_select kf let select_decl_var kf ?(select=empty_db_select kf) vi mark = SlicingParameters.debug ~level:1 "[Register.select_decl_var] of %s in %a@." - vi.Cil_types.vname Kernel_function.pretty_name kf; + vi.Cil_types.vname Kernel_function.pretty kf; if vi.Cil_types.vglob (* no slicing request on globals *) then select else try @@ -268,7 +269,7 @@ let nd_marks = Act.build_simple_node_selection mark in basic_add_select kf select [node] nd_marks with - | Db.Pdg.NotFound -> (* unreachable ? *) select + | Not_found -> (* unreachable ? *) select | Db.Pdg.Top -> top_db_select kf mark | Db.Pdg.Bottom -> bottom_msg kf; empty_db_select kf @@ -295,13 +296,13 @@ let add_to_selects db_select set = let vf, select = db_select in let select = - try merge_select (SlicingTypes.Sl_selects.find vf set) select + try merge_select (Cil_datatype.Varinfo.Map.find vf set) select with Not_found -> select in - SlicingTypes.Sl_selects.add vf select set + Cil_datatype.Varinfo.Map.add vf select set let iter_selects_internal f set = - SlicingTypes.Sl_selects.iter (fun v sel -> f (v, sel)) set + Cil_datatype.Varinfo.Map.iter (fun v sel -> f (v, sel)) set end @@ -404,7 +405,7 @@ let param_list = Kernel_function.get_formals kf in let rec find n var_list = match var_list with | [] -> raise Not_found - | v :: var_list -> if v.vid = var.vid then n + | v :: var_list -> if Cil_datatype.Varinfo.equal v var then n else find (n+1) var_list in let n = find 1 param_list in Fct_slice.get_param_mark ff n @@ -418,7 +419,7 @@ | Instr (Call (_,expr_f,_,_)) -> if snd (Fct_slice.get_called_slice ff stmt) then Kernel_function.Hptset.elements - (snd (!Db.Value.expr_to_kernel_function + (snd (!Db.Value.expr_to_kernel_function (Kstmt stmt) ~with_alarms:CilE.warn_none_mode ~deps:None @@ -530,9 +531,9 @@ "!Db.Slicing.Project.extract" (Datatype.func3 ~label1:("f_slice_names", - Some (fun () -> !Db.Slicing.Project.default_slice_names)) + Some (fun () -> !Db.Slicing.Project.default_slice_names)) (Datatype.func3 - Kernel_function.ty Datatype.bool Datatype.int Datatype.string) + Kernel_function.ty Datatype.bool Datatype.int Datatype.string) Datatype.string Db.Slicing.Project.dyn_t Project.ty) @@ -590,7 +591,7 @@ ~label3:("rd", None) Datatype.String.Set.ty ~label4:("wr", None) Datatype.String.Set.ty (Datatype.func4 - Stmt.ty + Stmt.ty ~label2:("scope", None) Stmt.ty ~label3:("eval", None) Stmt.ty Kernel_function.ty @@ -610,7 +611,7 @@ Datatype.String.Set.ty ~label4:("before", None) Datatype.bool (Datatype.func4 - Stmt.ty + Stmt.ty ~label2:("scope", None) Stmt.ty ~label3:("eval", None) Stmt.ty Kernel_function.ty @@ -630,12 +631,12 @@ ~label3:("spare", None) Datatype.bool ~label4:("ai", None) Datatype.bool (Datatype.func4 - ~label1:("user_assert", None) Datatype.bool + ~label1:("user_assert", None) Datatype.bool ~label2:("slicing_pragma", None) Datatype.bool ~label3:("loop_inv", None) Datatype.bool ~label4:("loop_var", None) Datatype.bool (Datatype.func2 - Stmt.ty + Stmt.ty Kernel_function.ty Db.Slicing.Select.dyn_t_set))) higher_select_stmt_annots @@ -653,7 +654,7 @@ ~label3:("rd", None) Datatype.String.Set.ty ~label4:("wr", None) Datatype.String.Set.ty (Datatype.func3 - ~label1:("scope", None) Stmt.ty + ~label1:("scope", None) Stmt.ty ~label2:("eval", None) Stmt.ty Kernel_function.ty Db.Slicing.Select.dyn_t_set)) @@ -713,7 +714,7 @@ ~label3:("spare", None) Datatype.bool ~label4:("ai", None) Datatype.bool (Datatype.func4 - ~label1:("user_assert", None) Datatype.bool + ~label1:("user_assert", None) Datatype.bool ~label2:("slicing_pragma", None) Datatype.bool ~label3:("loop_inv", None) Datatype.bool ~label4:("loop_var", None) Datatype.bool @@ -812,7 +813,7 @@ ~label3:("sliceUndef", None) Datatype.bool ~label4:("keepAnnotation", None) Datatype.bool (Datatype.func2 - ~label1:("print", None) Datatype.bool + ~label1:("print", None) Datatype.bool Datatype.unit Datatype.unit)) set_modes @@ -830,7 +831,7 @@ Cmdline.run_after_extended_stage (fun () -> State_dependency_graph.Static.add_codependencies - ~onto:P.self + ~onto:P.self [ !Db.Pdg.self; !Db.Inputs.self_external; !Db.Outputs.self_external ]) (** {3 Register external functions into Db.Slicing} *) @@ -846,7 +847,7 @@ Db.register (Db.Journalize ("Slicing.Project.mk_project", - Datatype.func Datatype.string Db.Slicing.Project.dyn_t)) + Datatype.func Datatype.string Db.Slicing.Project.dyn_t)) Db.Slicing.Project.mk_project mk_project; Db.register @@ -859,10 +860,10 @@ (Db.Journalize ("Slicing.Project.change_slicing_level", Datatype.func3 - Db.Slicing.Project.dyn_t - Kernel_function.ty + Db.Slicing.Project.dyn_t + Kernel_function.ty Datatype.int - Datatype.unit)) + Datatype.unit)) Db.Slicing.Project.change_slicing_level M.change_slicing_level ; @@ -960,7 +961,7 @@ (Db.Journalize ("Slicing.Select.select_func_lval", Datatype.func4 - Db.Slicing.Select.dyn_t_set + Db.Slicing.Select.dyn_t_set Db.Slicing.Mark.dyn_t Datatype.String.Set.ty Kernel_function.ty @@ -991,9 +992,9 @@ Db.register (Db.Journalize ("Slicing.Slice.create", Datatype.func2 - Db.Slicing.Project.dyn_t + Db.Slicing.Project.dyn_t Kernel_function.ty - Db.Slicing.Slice.dyn_t)) + Db.Slicing.Slice.dyn_t)) Db.Slicing.Slice.create create_slice ; Db.register @@ -1061,14 +1062,14 @@ (Db.Journalize ("Slicing.Request.add_selection", Datatype.func2 - Db.Slicing.Project.dyn_t Db.Slicing.Select.dyn_t_set Datatype.unit)) + Db.Slicing.Project.dyn_t Db.Slicing.Select.dyn_t_set Datatype.unit)) Db.Slicing.Request.add_selection C.add_selection ; Db.register (Db.Journalize ("Slicing.Request.add_persistent_selection", Datatype.func2 - Db.Slicing.Project.dyn_t Db.Slicing.Select.dyn_t_set Datatype.unit)) + Db.Slicing.Project.dyn_t Db.Slicing.Select.dyn_t_set Datatype.unit)) Db.Slicing.Request.add_persistent_selection C.add_persistent_selection ; Db.register @@ -1085,16 +1086,16 @@ (Db.Journalize ("Slicing.Request.copy_slice", Datatype.func2 - Db.Slicing.Project.dyn_t - Db.Slicing.Slice.dyn_t - Db.Slicing.Slice.dyn_t)) + Db.Slicing.Project.dyn_t + Db.Slicing.Slice.dyn_t + Db.Slicing.Slice.dyn_t)) Db.Slicing.Request.copy_slice copy_slice ; Db.register (Db.Journalize ("Slicing.Request.split_slice", Datatype.func2 - Db.Slicing.Project.dyn_t + Db.Slicing.Project.dyn_t Db.Slicing.Slice.dyn_t (Datatype.list Db.Slicing.Slice.dyn_t))) Db.Slicing.Request.split_slice @@ -1151,7 +1152,7 @@ * because some functions use its results, * and the value analysis is not launched automatically. *) !Db.Value.compute (); - + let project_name = SlicingParameters.ProjectName.get () in let project = !Db.Slicing.Project.mk_project project_name in !Db.Slicing.Project.set_project (Some project); @@ -1161,24 +1162,24 @@ if SlicingParameters.Mode.Callers.get () then !Db.Slicing.Slice.remove_uncalled project; - let sliced_project_name = + let sliced_project_name = let postfix = SlicingParameters.ExportedProjectPostfix.get () in if postfix = "" then project_name else (project_name ^ " " ^ postfix) in + SlicingParameters.set_off (); let sliced_project = !Db.Slicing.Project.extract sliced_project_name project in + Project.on sliced_project SlicingParameters.clear (); if SlicingParameters.Print.get () then begin FC_file.pretty_ast ~prj:sliced_project (); SlicingParameters.result ~level:2 "Results :@. %a@." - !Db.Slicing.Project.pretty project + !Db.Slicing.Project.pretty project end; SlicingParameters.feedback ~level:2 "done (slicing requests in progress)."; - SlicingParameters.set_off () end (** Register the function [main] as a main entry point. *) let () = Db.Main.extend main - diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/register.mli frama-c-20111001+nitrogen+dfsg/src/slicing/register.mli --- frama-c-20110201+carbon+dfsg/src/slicing/register.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/register.mli 2011-10-10 08:38:22.000000000 +0000 @@ -22,7 +22,7 @@ (* *) (**************************************************************************) -(** +(** * This file should be empty because every API functions of the slicing module * should be registered in {!Db.Slicing}. @@ -31,6 +31,5 @@ *) -val print_fct_stmts : - Format.formatter -> (SlicingTypes.sl_project * Db_types.kernel_function) -> unit - +val print_fct_stmts : + Format.formatter -> (SlicingTypes.sl_project * Cil_types.kernel_function) -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingActions.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingActions.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingActions.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingActions.ml 2011-10-10 08:38:22.000000000 +0000 @@ -22,7 +22,7 @@ (* *) (**************************************************************************) -(** This module deals with the action management. +(** This module deals with the action management. * It consiste of the definitions of the different kind of actions, * and the management of the action list. *) @@ -52,51 +52,51 @@ (** {3 How the elements will be selected} *) (** Build a description to tell that the associated nodes have to be marked -* with the given mark, and than the same one will be propagated through +* with the given mark, and than the same one will be propagated through * their dependencies. (see also {!build_node_and_dpds_selection}) *) -let build_simple_node_selection ?(nd_marks=[]) mark = +let build_simple_node_selection ?(nd_marks=[]) mark = (T.CwNode, mark)::nd_marks (** Only the control dependencies of the nodes will be marked *) -let build_addr_dpds_selection ?(nd_marks=[]) mark = +let build_addr_dpds_selection ?(nd_marks=[]) mark = (T.CwAddrDpds, mark)::nd_marks (** Only the control dependencies of the nodes will be marked *) -let build_data_dpds_selection ?(nd_marks=[]) mark = +let build_data_dpds_selection ?(nd_marks=[]) mark = (T.CwDataDpds, mark)::nd_marks (** Only the control dependencies of the nodes will be marked *) -let build_ctrl_dpds_selection ?(nd_marks=[]) mark = +let build_ctrl_dpds_selection ?(nd_marks=[]) mark = (T.CwCtrlDpds, mark)::nd_marks (** Build a description to tell how the selected PDG nodes and their -* dependencies will have to be marked -* (see {!type:SlicingTypes.Internals.t_node_or_dpds}). +* dependencies will have to be marked +* (see {!type:SlicingTypes.Internals.t_node_or_dpds}). * This description depend on the mark that has been asked for. * First of all, whatever the mark is, the node is selected as [spare], -* so that it will be visible, and so will its dependencies. Then, +* so that it will be visible, and so will its dependencies. Then, * if [is_ctrl mark] propagate a m1 control mark through the control dependencies * and do a similar thing for [addr] and [data] *) let build_node_and_dpds_selection ?(nd_marks=[]) mark = let m_spare = Marks.mk_user_spare in let nd_marks = build_simple_node_selection ~nd_marks:nd_marks m_spare in - let nd_marks = + let nd_marks = if Marks.is_ctrl_mark mark - then + then let m_ctrl = Marks.mk_user_mark ~ctrl:true ~data:false ~addr:false in build_ctrl_dpds_selection ~nd_marks:nd_marks m_ctrl else nd_marks in - let nd_marks = + let nd_marks = if Marks.is_addr_mark mark - then + then let m_addr = Marks.mk_user_mark ~ctrl:false ~data:false ~addr:true in build_addr_dpds_selection ~nd_marks:nd_marks m_addr else nd_marks in - let nd_marks = + let nd_marks = if Marks.is_data_mark mark - then + then let m_data = Marks.mk_user_mark ~ctrl:false ~data:true ~addr:false in build_data_dpds_selection ~nd_marks:nd_marks m_data else nd_marks @@ -108,9 +108,9 @@ let translate_crit_to_select pdg ?(to_select=[]) list_crit = let translate acc (nodes, nd_mark) = let add_pdg_mark acc (nd, mark) = - let add_nodes m acc nodes = - let add m acc nodepart = - PdgMarks.add_node_to_select acc nodepart m + let add_nodes m acc nodes = + let add m acc nodepart = + PdgMarks.add_node_to_select acc nodepart m in List.fold_left (add m) acc nodes in @@ -136,7 +136,7 @@ (** build an action to apply the criteria to the persistent selection of the * function. It means that it will be applied to all slices. *) -let mk_fct_crit fi crit = +let mk_fct_crit fi crit = T.CrFct { T.cf_fct = T.FctSrc fi ; T.cf_info = crit } let mk_fct_user_crit fi crit = mk_fct_crit fi (T.CcUserMark crit) @@ -144,11 +144,11 @@ let mk_crit_fct_top fi m = mk_fct_user_crit fi (T.CuTop m) let mk_crit_fct_user_select fi select = mk_fct_user_crit fi (T.CuSelect select) -let mk_crit_prop_persit_marks fi node_marks = +let mk_crit_prop_persit_marks fi node_marks = mk_fct_crit fi (T.CcPropagate node_marks) (** build an action to apply the criteria to the given slice. *) -let mk_ff_crit ff crit = +let mk_ff_crit ff crit = T.CrFct { T.cf_fct = T.FctSliced ff ; T.cf_info = crit } let mk_ff_user_select ff crit = mk_ff_crit ff (T.CcUserMark (T.CuSelect crit)) @@ -172,23 +172,23 @@ let caller = M.get_fi_kf fi_caller in let pdg_caller = !Db.Pdg.get caller in let call_stmts = !Db.Pdg.find_call_stmts ~caller to_call in - let stmt_mark stmt = + let stmt_mark stmt = let stmt_ctrl_node = !Db.Pdg.find_call_ctrl_node pdg_caller stmt in (PdgMarks.mk_select_node stmt_ctrl_node, mark) in let select = List.map stmt_mark call_stmts in T.CuSelect select with PdgTypes.Pdg.Top -> T.CuTop mark - in + in mk_fct_user_crit fi_caller select let mk_crit_add_output_marks ff select = (* let pdg = M.get_ff_pdg ff in - let add acc (out, m) = + let add acc (out, m) = let nd_m = build_simple_node_selection m in let node = out in - mk_mark_nodes pdg ~marks:acc [node] nd_m + mk_mark_nodes pdg ~marks:acc [node] nd_m in let select = List.fold_left add [] output_marks in *) mk_ff_user_select ff select @@ -216,49 +216,49 @@ let rec print_nd_and_mark_list fmt ndm_list = match ndm_list with | [] -> () - | x :: ndm_list -> + | x :: ndm_list -> print_nd_and_mark fmt x; print_nd_and_mark_list fmt ndm_list let print_nodes fmt nodes = - let print n = Format.fprintf fmt "n%a " (!Db.Pdg.pretty_node true) n in + let print n = Format.fprintf fmt "%a " (!Db.Pdg.pretty_node true) n in List.iter print nodes let print_node_mark fmt n z m = - Format.fprintf fmt "(%a ,%a)" + Format.fprintf fmt "(%a ,%a)" (PdgTypes.Node.pretty_with_part) (n, z) Marks.pretty_mark m let print_sel_marks_list fmt to_select = - let print_sel (s, m) = match s with + let print_sel (s, m) = match s with | PdgMarks.SelNode (n, z) -> print_node_mark fmt n z m - | PdgMarks.SelIn l -> - Format.fprintf fmt "(UndefIn %a:%a)" + | PdgMarks.SelIn l -> + Format.fprintf fmt "(UndefIn %a:%a)" Locations.Zone.pretty l Marks.pretty_mark m in match to_select with [] -> Format.fprintf fmt "<empty>" | _ -> List.iter print_sel to_select let print_ndm fmt (nodes, ndm_list) = - Format.fprintf fmt "(%a,%a)" print_nodes nodes + Format.fprintf fmt "(%a,%a)" print_nodes nodes print_nd_and_mark_list ndm_list let print_f_crit fmt f_crit = - match f_crit with + match f_crit with | T.CuTop m -> Format.fprintf fmt "top(%a)" Marks.pretty_mark m | T.CuSelect to_select -> print_sel_marks_list fmt to_select let print_crit fmt crit = - match crit with - | T.CrFct fct_crit -> + match crit with + | T.CrFct fct_crit -> let fct = fct_crit.T.cf_fct in let name = SlicingMacros.f_name fct in Format.fprintf fmt "[%s = " name; let _ = match fct_crit.T.cf_info with - | T.CcUserMark info -> print_f_crit fmt info + | T.CcUserMark info -> print_f_crit fmt info | T.CcMissingInputs (call, _input_marks, more_inputs) - -> Format.fprintf fmt "missing_inputs for call %d (%s)" - call.Cil_types.sid + -> Format.fprintf fmt "missing_inputs for call %d (%s)" + call.Cil_types.sid (if more_inputs then "more_inputs" else "marks only") | T.CcMissingOutputs (call, _output_marks, more_outputs) - -> Format.fprintf fmt "missing_outputs for call %d (%s)" + -> Format.fprintf fmt "missing_outputs for call %d (%s)" call.Cil_types.sid (if more_outputs then "more_outputs" else "marks only") | T.CcChooseCall call @@ -268,14 +268,14 @@ | T.CallSlice ff -> SlicingMacros.ff_name ff | T.CallSrc (Some fi) -> ("(src:"^( SlicingMacros.fi_name fi)^")") | T.CallSrc None -> "(src)" - in Format.fprintf fmt "change_call for call %d -> %s" + in Format.fprintf fmt "change_call for call %d -> %s" call.Cil_types.sid fname - | T.CcPropagate nl -> - Format.fprintf fmt "propagate %a" + | T.CcPropagate nl -> + Format.fprintf fmt "propagate %a" print_sel_marks_list nl | T.CcExamineCalls _ -> Format.fprintf fmt "examine_calls" in Format.fprintf fmt "]" - | T.CrAppli (T.CaCall fi) -> + | T.CrAppli (T.CaCall fi) -> let name = SlicingMacros.fi_name fi in Format.fprintf fmt "[Appli : calls to %s]" name | _ -> diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingActions.mli frama-c-20111001+nitrogen+dfsg/src/slicing/slicingActions.mli --- frama-c-20110201+carbon+dfsg/src/slicing/slicingActions.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingActions.mli 2011-10-10 08:38:22.000000000 +0000 @@ -26,7 +26,7 @@ type t_select = t_mark PdgMarks.t_select (* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) -(** selection mode (ie which mark to associate to the node +(** selection mode (ie which mark to associate to the node * and how to propagate in the different kinds of dependencies) *) type t_n_or_d_marks @@ -42,7 +42,7 @@ ?nd_marks:t_n_or_d_marks -> t_mark -> t_n_or_d_marks (* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) val translate_crit_to_select : - Db.Pdg.t -> ?to_select:t_select -> + Db.Pdg.t -> ?to_select:t_select -> ((Db.Pdg.t_node * Locations.Zone.t option) list * t_n_or_d_marks) list -> t_select (* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) @@ -68,7 +68,7 @@ t_fct_slice -> t_mark PdgMarks.t_info_called_outputs -> t_criterion val mk_appli_select_calls : t_fct_info -> t_criterion val mk_crit_mark_calls : - t_fct_info -> Db_types.kernel_function -> t_mark -> t_criterion + t_fct_info -> Cil_types.kernel_function -> t_mark -> t_criterion val mk_crit_add_output_marks : t_fct_slice -> t_select -> t_criterion (* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingCmds.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingCmds.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingCmds.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingCmds.ml 2011-10-10 08:38:22.000000000 +0000 @@ -32,7 +32,6 @@ open Cilutil open Cil_types open Db -open Db_types (** Utilities for [kinstr]. *) module Kinstr: sig @@ -100,7 +99,7 @@ match ki.skind with | Instr (Call (_,expr_f,_,_)) -> Kernel_function.Hptset.elements - (snd (!Value.expr_to_kernel_function + (snd (!Value.expr_to_kernel_function (Kstmt ki) ~with_alarms:CilE.warn_none_mode ~deps:None @@ -114,9 +113,9 @@ (** Get directly read/writen [Zone.t] by the statement. * i.e. directly means when [ki] is a call, it doesn't don't look at the assigns clause of the called function. *) - let get_rw_zone ki = (* returns [Zone.t read],[Zone.t writen] *) + let get_rw_zone stmt = (* returns [Zone.t read],[Zone.t writen] *) assert (Db.Value.is_computed ()); - let lval_process read_zone kstmt lv = + let lval_process read_zone stmt lv = (* returns [read_zone] joined to [Zone.t read] by [lv], [Zone.t writen] by [lv] *) let deps, looking_for = (* The modified locationss are [looking_for], those address are @@ -124,30 +123,28 @@ !Db.Value.lval_to_loc_with_deps ~with_alarms:CilE.warn_none_mode ~deps:read_zone - kstmt + (Kstmt stmt) lv - in deps, Locations.valid_enumerate_bits looking_for - in match ki.skind with + in deps, Locations.valid_enumerate_bits ~for_writing:true looking_for + in match stmt.skind with | Switch (exp,_,_,_) | If (exp,_,_,_) -> (* returns [Zone.t read] by condition [exp], [Zone.bottom] *) - !Db.From.find_deps_no_transitivity (Kstmt ki) exp, Locations.Zone.bottom + !Db.From.find_deps_no_transitivity stmt exp, Locations.Zone.bottom | Instr (Set (lv,exp,_)) -> (* returns [Zone.t read] by [exp, lv], [Zone.t writen] by [lv] *) - let kstmt = Kstmt ki in - let read_zone = !Db.From.find_deps_no_transitivity kstmt exp in - lval_process read_zone kstmt lv + let read_zone = !Db.From.find_deps_no_transitivity stmt exp in + lval_process read_zone stmt lv | Instr (Call (lvaloption,funcexp,argl,_)) -> (* returns [Zone.t read] by [lvaloption, funcexp, argl], [Zone.t writen] by [lvaloption] *) - let kstmt = Kstmt ki in - let read_zone = !Db.From.find_deps_no_transitivity kstmt funcexp in + let read_zone = !Db.From.find_deps_no_transitivity stmt funcexp in let add_args arg inputs = - Locations.Zone.join inputs (!Db.From.find_deps_no_transitivity kstmt arg) in + Locations.Zone.join inputs (!Db.From.find_deps_no_transitivity stmt arg) in let read_zone = List.fold_right add_args argl read_zone in let read_zone,write_zone = match lvaloption with | None ->read_zone , Locations.Zone.bottom - | Some lv -> lval_process read_zone kstmt lv + | Some lv -> lval_process read_zone stmt lv in read_zone,write_zone | _ -> Locations.Zone.bottom, Locations.Zone.bottom @@ -155,8 +152,8 @@ directly read/writen [Zone.t] by the statement. * i.e. directly means when [ki] is a call, it doesn't don't look at the assigns clause of the called function. *) - let is_rw_zone (rd_zone_opt, wr_zone_opt) ki = - let rd_zone, wr_zone = get_rw_zone ki in + let is_rw_zone (rd_zone_opt, wr_zone_opt) stmt = + let rd_zone, wr_zone = get_rw_zone stmt in let inter_zone zone_opt zone = match zone_opt with | None -> zone_opt @@ -206,7 +203,7 @@ (fun kf -> SlicingParameters.debug ~level:3 "doing topologic propagation for function: %a" - Kernel_function.pretty_name kf; + Kernel_function.pretty kf; !Slicing.Request.apply_all_internal project) let add_to_selection set selection = @@ -220,10 +217,10 @@ (** Registered as a slicing selection function: Add a selection of the statement. *) -let select_stmt set ~spare ki kf = +let select_stmt set ~spare stmt kf = let stmt_mark = !Db.Slicing.Mark.make ~data:(not spare) ~addr:(not spare) ~ctrl:(not spare) in - let selection = !Db.Slicing.Select.select_stmt_internal kf ki stmt_mark + let selection = !Db.Slicing.Select.select_stmt_internal kf stmt stmt_mark in add_to_selection set selection (** Add a selection to the entrance of the function [kf] @@ -233,7 +230,7 @@ let select_entry_point_and_some_inputs_outputs set ~mark kf ~return ~outputs ~inputs = SlicingParameters.debug ~level:3 "select_entry_point_and_some_inputs_outputs %a" - Kernel_function.pretty_name kf ; + Kernel_function.pretty kf ; let set = let selection = !Db.Slicing.Select.select_entry_point_internal kf mark in add_to_selection set selection in @@ -320,13 +317,18 @@ try let ki = Kernel_function.find_return kf in select_stmt set ~spare ki kf - with Kernel_function.No_Definition -> - let mark = !Db.Slicing.Mark.make - ~data:(not spare) ~addr:(not spare) ~ctrl:(not spare) + with Kernel_function.No_Statement -> + let mark = + !Db.Slicing.Mark.make + ~data:(not spare) ~addr:(not spare) ~ctrl:(not spare) in - select_entry_point_and_some_inputs_outputs set ~mark kf - ~return:true ~outputs:Locations.Zone.bottom - ~inputs:Locations.Zone.bottom + select_entry_point_and_some_inputs_outputs + set + ~mark + kf + ~return:true + ~outputs:Locations.Zone.bottom + ~inputs:Locations.Zone.bottom (** Registered as a slicing selection function: Add a selection of the statement reachability. @@ -365,18 +367,18 @@ (fun lval_str acc -> let lval_term = !Db.Properties.Interp.lval kf scope lval_str in let lval = - !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term - in + !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term + in let loc = - !Db.Value.lval_to_loc - ~with_alarms:CilE.warn_none_mode - (Kstmt eval) - lval - in - let zone = Locations.valid_enumerate_bits loc in - Locations.Zone.join zone acc) + !Db.Value.lval_to_loc + ~with_alarms:CilE.warn_none_mode + (Kstmt eval) + lval + in + let zone = Locations.valid_enumerate_bits ~for_writing:false loc in + Locations.Zone.join zone acc) lval_str - Locations.Zone.bottom + Locations.Zone.bottom in select_stmt_zone set mark zone ~before ki kf @@ -393,7 +395,7 @@ of a call. *) let select_lval_rw set mark ~rd ~wr ~scope ~eval kf ki_opt= assert (Db.Value.is_computed ()); - let zone_option lval_str = + let zone_option ~for_writing lval_str = if Datatype.String.Set.is_empty lval_str then None else @@ -403,18 +405,18 @@ let lval_term = !Db.Properties.Interp.lval kf scope lval_str in let lval = !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term in let loc = !Db.Value.lval_to_loc ~with_alarms:CilE.warn_none_mode (Kstmt eval) lval in - let zone = Locations.valid_enumerate_bits loc + let zone = Locations.valid_enumerate_bits ~for_writing loc in Locations.Zone.join zone acc) lval_str Locations.Zone.bottom in SlicingParameters.debug ~level:3 "select_lval_rw %a zone=%a" - Kernel_function.pretty_name kf + Kernel_function.pretty kf Locations.Zone.pretty zone; Some zone in - let zone_rd_opt = zone_option rd in - let zone_wr_opt = zone_option wr - in match zone_rd_opt, zone_wr_opt with + let zone_rd_opt = zone_option ~for_writing:false rd in + let zone_wr_opt = zone_option ~for_writing:true wr in + match zone_rd_opt, zone_wr_opt with | None, None -> set | (_, _) as zone_option_rw -> let ac = ref set in @@ -434,12 +436,12 @@ in (match ki_opt with | Some ki -> select_rw_from_stmt kf ki | None -> - Globals.Functions.iter - (fun kf -> + Globals.Functions.iter + (fun kf -> if !Db.Value.is_called kf then - if Kernel_function.is_definition kf - then (* Called function with source code: just looks at its stmt *) - Kinstr.iter_from_func (select_rw_from_stmt kf) kf + if not (!Db.Value.use_spec_instead_of_definition kf) + then (* Called function with source code: just looks at its stmt *) + Kinstr.iter_from_func (select_rw_from_stmt kf) kf else begin (* Called function without source code: looks at its effect *) let select_inter_zone fsel zone_opt zone = match zone_opt with @@ -510,10 +512,10 @@ (fun z acc -> (* selection related to the parsing/compilation of the annotation *) select_stmt_zone acc mark - z.Properties.Interp.To_zone.zone + z.Properties.Interp.To_zone.zone ~before:z.Properties.Interp.To_zone.before - z.Properties.Interp.To_zone.ki - kf) + z.Properties.Interp.To_zone.ki + kf) zones set let get_or_raise (info_data_opt, info_decl) = match info_data_opt with @@ -526,25 +528,25 @@ (** Registered as a slicing selection function: Add selection of the annotations related to a statement. Note: add also a transparent selection on the whole statement. *) -let select_stmt_pred set mark pred ~before ki kf = +let select_stmt_pred set mark pred ki kf = let zones_decl_vars = !Properties.Interp.To_zone.from_pred pred - (!Properties.Interp.To_zone.mk_ctx_stmt_annot kf ki ~before) + (!Properties.Interp.To_zone.mk_ctx_stmt_annot kf ki) in select_ZoneAnnot_zones_decl_vars set mark (get_or_raise zones_decl_vars) kf (** Registered as a slicing selection function: Add selection of the annotations related to a statement. Note: add also a transparent selection on the whole statement. *) -let select_stmt_term set mark term ~before ki kf = - let zones_decl_vars = !Properties.Interp.To_zone.from_term term (!Properties.Interp.To_zone.mk_ctx_stmt_annot kf ki ~before) +let select_stmt_term set mark term ki kf = + let zones_decl_vars = !Properties.Interp.To_zone.from_term term (!Properties.Interp.To_zone.mk_ctx_stmt_annot kf ki) in select_ZoneAnnot_zones_decl_vars set mark (get_or_raise zones_decl_vars) kf (** Registered as a slicing selection function: Add selection of the annotations related to a statement. Note: add also a transparent selection on the whole statement. *) -let select_stmt_annot set mark ~spare annot ~before ki kf = +let select_stmt_annot set mark ~spare annot ki kf = let zones_decl_vars,pragmas = - !Properties.Interp.To_zone.from_stmt_annot annot ~before (ki, kf) + !Properties.Interp.To_zone.from_stmt_annot annot (ki, kf) in let set = select_ZoneAnnot_pragmas set ~spare pragmas kf in select_ZoneAnnot_zones_decl_vars set mark (get_or_raise zones_decl_vars) kf @@ -661,49 +663,49 @@ Globals.Functions.iter (fun kf -> let add_selection opt select = - if Datatype.String.Set.mem (Kernel_function.get_name kf) (opt ()) - then selection := select !selection ~spare:false kf + if Datatype.String.Set.mem (Kernel_function.get_name kf) (opt ()) + then selection := select !selection ~spare:false kf in add_selection - SlicingParameters.Select.Return.get + SlicingParameters.Select.Return.get !Db.Slicing.Select.select_func_return; add_selection - SlicingParameters.Select.Calls.get - !Db.Slicing.Select.select_func_calls_to; + SlicingParameters.Select.Calls.get + !Db.Slicing.Select.select_func_calls_to; add_selection - SlicingParameters.Select.Pragma.get - (fun s -> !Db.Slicing.Select.select_func_annots s top_mark - ~ai:false ~user_assert:false ~slicing_pragma:true - ~loop_inv:false ~loop_var:false); + SlicingParameters.Select.Pragma.get + (fun s -> !Db.Slicing.Select.select_func_annots s top_mark + ~ai:false ~user_assert:false ~slicing_pragma:true + ~loop_inv:false ~loop_var:false); add_selection - SlicingParameters.Select.Threat.get + SlicingParameters.Select.Threat.get (fun s -> !Db.Slicing.Select.select_func_annots s top_mark - ~ai:true ~user_assert:false ~slicing_pragma:false - ~loop_inv:false ~loop_var:false); + ~ai:true ~user_assert:false ~slicing_pragma:false + ~loop_inv:false ~loop_var:false); add_selection - SlicingParameters.Select.Assert.get + SlicingParameters.Select.Assert.get (fun s -> !Db.Slicing.Select.select_func_annots s top_mark - ~ai:false ~user_assert:true ~slicing_pragma:false - ~loop_inv:false ~loop_var:false); + ~ai:false ~user_assert:true ~slicing_pragma:false + ~loop_inv:false ~loop_var:false); add_selection - SlicingParameters.Select.LoopInv.get + SlicingParameters.Select.LoopInv.get (fun s -> !Db.Slicing.Select.select_func_annots s top_mark - ~ai:false ~user_assert:false ~slicing_pragma:false - ~loop_inv:true ~loop_var:false); + ~ai:false ~user_assert:false ~slicing_pragma:false + ~loop_inv:true ~loop_var:false); add_selection - SlicingParameters.Select.LoopVar.get + SlicingParameters.Select.LoopVar.get (fun s -> !Db.Slicing.Select.select_func_annots s top_mark - ~ai:false ~user_assert:false ~slicing_pragma:false - ~loop_inv:false ~loop_var:true); + ~ai:false ~user_assert:false ~slicing_pragma:false + ~loop_inv:false ~loop_var:true); ); if not (Datatype.String.Set.is_empty - (SlicingParameters.Select.Value.get ())) + (SlicingParameters.Select.Value.get ())) || not (Datatype.String.Set.is_empty - (SlicingParameters.Select.RdAccess.get ())) + (SlicingParameters.Select.RdAccess.get ())) || not (Datatype.String.Set.is_empty - (SlicingParameters.Select.WrAccess.get ())) + (SlicingParameters.Select.WrAccess.get ())) then begin (* fprintf fmt "@\n[-slice-value] Select %s at end of the entry point %a@." lval_str Db.pretty_name kf; *) diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingMacros.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingMacros.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingMacros.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingMacros.ml 2011-10-10 08:38:22.000000000 +0000 @@ -86,8 +86,11 @@ try Cil_datatype.Varinfo.Hashtbl.find proj.T.functions fct_var with Not_found -> let fi_def, is_def = - try let def = Kernel_function.get_definition kf in Some def, true - with Kernel_function.No_Definition -> None, false + match kf.fundec with + | Declaration _ -> None, false + | Definition _ when !Db.Value.use_spec_instead_of_definition kf -> + None, false + | Definition (def, _) -> Some def, true in let new_fi = { T.fi_kf = kf; @@ -178,7 +181,7 @@ let equal_fi fi1 fi2 = let v1 = fi_svar fi1 in let v2 = fi_svar fi2 in - v1.vid = v2.vid + Cil_datatype.Varinfo.equal v1 v2 let equal_ff ff1 ff2 = (equal_fi ff1.T.ff_fct ff2.T.ff_fct) && ((get_ff_id ff1) = (get_ff_id ff2)) @@ -205,9 +208,9 @@ let _funcexp_dpds, called_functions = !Db.Value.expr_to_kernel_function ~with_alarms:CilE.warn_none_mode - ~deps:(Some Locations.Zone.bottom) + ~deps:(Some Locations.Zone.bottom) (Kstmt call_stmt) - funcexp + funcexp in (match Kernel_function.Hptset.contains_single_elt called_functions with | Some kf -> kf diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingMarks.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingMarks.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingMarks.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingMarks.ml 2011-10-10 08:38:22.000000000 +0000 @@ -49,11 +49,11 @@ val is_top : t -> bool val is_included : t -> t -> bool - (** Total order over the marks. Used only for sorting... + (** Total order over the marks. Used only for sorting... * Use rather [is_included] to make a clever comparison. *) val compare : t -> t -> int - (** this operation has to be commutative. + (** this operation has to be commutative. It is used to merge two slices into one. *) val merge : t -> t -> t @@ -61,13 +61,13 @@ val inter : t -> t -> t (** this operation add a new information to the old value. - * @return (new_mark, is_new) + * @return (new_mark, is_new) where is_new=true if the new_mark is not included in the old one. *) val combine : old:t -> t -> bool * t (** [minus m1 m2] provides the mark [m] that you have to merge with [m2] to - * get at least [m1]. So : [m1 <= m U m2] + * get at least [m1]. So : [m1 <= m U m2] * If [m1 <= m2] then [m = bot]. * *) val minus : t -> t -> t @@ -79,21 +79,21 @@ type t = T.t_mark - + let spare = T.Spare (* Internal constructor *) let create_adc a d c = T.Cav (D.make ~a ~d ~c ()) - + let bottom = T.Cav D.bottom let top = T.Cav D.top - - let addr = create_adc true false false + + let addr = create_adc true false false let data = create_adc false true false let ctrl = create_adc false false true - - let m_ad = create_adc true true false - let m_ac = create_adc true false true + + let m_ad = create_adc true true false + let m_ac = create_adc true false true let m_dc = create_adc false true true let create adc = @@ -106,11 +106,11 @@ | true, false, true -> m_ac | false, true, true -> m_dc | true, true, true -> top - + (* External constructor sharing same values *) let mk_adc a d c = create (a, d, c) let mk_mark dpd = create (D.adc_value dpd) - + let is_bottom m = (m = bottom) let is_top m = (m = top) @@ -124,7 +124,7 @@ | T.Cav _, T.Spare -> if is_bottom m1 then true else false | T.Cav d1, T.Cav d2 -> D.is_included d1 d2 - let merge m1 m2 = + let merge m1 m2 = match m1,m2 with | T.Spare, T.Spare -> m1 | T.Spare, T.Cav _ -> if is_bottom m2 then m1 else m2 @@ -138,19 +138,19 @@ match m1,m2 with | T.Spare, _ -> m1 | _, T.Spare -> m2 - | T.Cav d1, T.Cav d2 -> + | T.Cav d1, T.Cav d2 -> let m = mk_mark (D.inter d1 d2) in if is_bottom m then spare else m - let combine ~old m = + let combine ~old m = match old, m with | T.Spare, T.Spare -> (false, old) - | T.Cav old_d, T.Spare -> + | T.Cav old_d, T.Spare -> if D.is_bottom old_d then (true, m) else (false, old) - | T.Spare, T.Cav new_d -> + | T.Spare, T.Cav new_d -> if D.is_bottom new_d then (false, old) else (true, m) | T.Cav old_d, T.Cav new_d -> - let new_d = D.combine old_d new_d in + let new_d = D.combine old_d new_d in if old_d = new_d then (false, old) else (true, mk_mark new_d) let minus m1 m2 = @@ -161,16 +161,16 @@ | T.Cav d1, T.Cav d2 -> mk_mark (D.minus d1 d2) let pretty fmt m = - match m with + match m with | T.Cav d -> D.pretty fmt d | T.Spare -> Format.fprintf fmt "[ S ]" let to_string m = Pretty_utils.sfprintf "%a" pretty m end - -(** a [MarkPair] is associated with each element of the PDG in a slice. - * The first component gives the mark propagated from a user request, while + +(** a [MarkPair] is associated with each element of the PDG in a slice. + * The first component gives the mark propagated from a user request, while * the second one is used to propagate informations to the called functions. *) module MarkPair = struct @@ -178,7 +178,7 @@ (* To do hash-consing *) let create = SlicingInternals.create_sl_mark - + let mk_m1 m1 = create ~m1 ~m2:Mark.bottom let mk_m2 m2 = create ~m1:Mark.bottom ~m2 let mk_m m1 m2 = create ~m1 ~m2 @@ -202,12 +202,12 @@ let is_addr m = (Mark.is_included Mark.addr (user_mark m)) let is_data m = (Mark.is_included Mark.data (user_mark m)) - let is_spare m = + let is_spare m = not (is_bottom m) && not (is_ctrl m || is_addr m || is_data m) let compare = T.compare_pdg_mark - let is_included ma mb = + let is_included ma mb = (Mark.is_included ma.T.m1 mb.T.m1) && (Mark.is_included ma.T.m2 mb.T.m2) let pretty fmt m = @@ -215,19 +215,19 @@ in Format.fprintf fmt "<%a,%a>" pm m.T.m1 pm m.T.m2 let to_string m = - Pretty_utils.sfprintf "%a" pretty m + Pretty_utils.sfprintf "%a" pretty m - let minus ma mb = + let minus ma mb = mk_m (Mark.minus ma.T.m1 mb.T.m1) (Mark.minus ma.T.m2 mb.T.m2) (** see {! Mark.merge} *) - let merge ma mb = + let merge ma mb = let m1 = Mark.merge ma.T.m1 mb.T.m1 in let m2 = Mark.merge ma.T.m2 mb.T.m2 in mk_m m1 m2 (** merge only ma_1 et mb_1, m_2 is always bottom *) - let merge_user_marks ma mb = + let merge_user_marks ma mb = let m1 = Mark.merge ma.T.m1 mb.T.m1 in mk_m m1 Mark.bottom @@ -237,7 +237,7 @@ | m :: [] -> m (* to avoid merging with bottom every time ! *) | m :: tl -> merge m (merge_all tl) - let inter ma mb = + let inter ma mb = let m1 = Mark.inter ma.T.m1 mb.T.m1 in let m2 = Mark.inter ma.T.m2 mb.T.m2 in mk_m m1 m2 @@ -251,7 +251,7 @@ (** [combine ma mb] is used to add the [mb] to the [ma]. * @return two marks : the first one is the new mark (= merge), * and the second is the one to propagate. - * Notice that if the mark to propagate is bottom, + * Notice that if the mark to propagate is bottom, * it means that [mb] was included in [ma]. *) let combine ma mb = @@ -264,12 +264,12 @@ let new_m2, prop2 = combine_m ma.T.m2 mb.T.m2 in (mk_m new_m1 new_m2), (mk_m prop1 prop2) - (** we want to know if the called function [g] with output marks - * [m_out_called] compute enough things to be used in [f] call + (** we want to know if the called function [g] with output marks + * [m_out_called] compute enough things to be used in [f] call * with output marks [m_out_call]. * Remember the [mf1] marks propagates as [mg2] and the marks to add * can only be [m2] marks. - * TODO : write this down in the specification + * TODO : write this down in the specification * and check with Patrick if it is ok. * *) let missing_output ~call:m_out_call ~called:m_out_called = @@ -284,13 +284,13 @@ Mark.merge mf1 mf2 in let min_mg2 = (* let remove from needed_mg2 what we have in mg1 *) Mark.minus needed_mg2 mg1 in - if Mark.is_included min_mg2 mg2 then None + if Mark.is_included min_mg2 mg2 then None else let m2 = mk_m2 min_mg2 in - if debug then + if debug then Format.printf "check_out missing output -> %a\n" pretty m2; (Some m2) - (** tells if the caller ([f]) computes enough inputs for the callee ([g]). + (** tells if the caller ([f]) computes enough inputs for the callee ([g]). * Remember that [mg1] has to be propagated as [mf1], * but [mg2] has to be propagated as [mf2=spare] *) let missing_input ~call:m_in_call ~called:m_in_called = @@ -299,7 +299,7 @@ let mg1 = m_in_called.T.m1 in let mg2 = m_in_called.T.m2 in let new_mf1 = if Mark.is_included mg1 mf1 then Mark.bottom else mg1 in - let new_mf2 = + let new_mf2 = if (not (Mark.is_bottom mg2)) && (Mark.is_bottom mf2) then Mark.spare else Mark.bottom @@ -353,8 +353,8 @@ Signature.fold_all_inputs (fun acc (k, m) -> (k, m)::acc) [] sgn exception Visible - let raise_if_visible () (_, m) = - if M.is_bottom m then () else raise Visible + let raise_if_visible () (_, m) = + if M.is_bottom m then () else raise Visible let some_visible_out cm = try Signature.fold_all_outputs raise_if_visible () cm ; false @@ -362,24 +362,24 @@ let is_topin_visible cm = try - let m = get_in_top_mark cm in + let m = get_in_top_mark cm in if M.is_bottom m then false else true - with PdgIndex.NotFound -> false + with Not_found -> false let ctrl_visible cm = try - let ctrl_m = get_in_ctrl_mark cm in + let ctrl_m = get_in_ctrl_mark cm in if M.is_bottom ctrl_m then false else true - with PdgIndex.NotFound -> false + with Not_found -> false let some_visible_in cm = try Signature.fold_num_inputs raise_if_visible () cm ; ctrl_visible cm with Visible -> true let merge_inputs_m1_mark cm = - Signature.fold_all_inputs (fun acc (_, m) -> M.merge_user_marks acc m) + Signature.fold_all_inputs (fun acc (_, m) -> M.merge_user_marks acc m) M.bottom cm - + (** @return an under-approxamation of the mark for the given location. * If the location is not included in the union of the implicit inputs, * it returns bottom. @@ -392,19 +392,19 @@ assert (not (Locations.Zone.equal Locations.Zone.bottom loc)); let do_in (marked_inputs, marks) (in_loc, m) = if M.is_bottom m then (marked_inputs, []) - else if Locations.Zone.intersects in_loc loc - then + else if Locations.Zone.intersects in_loc loc + then let marked_inputs = Locations.Zone.link marked_inputs in_loc in let marks = m::marks in (marked_inputs, marks) else (marked_inputs, marks) - in + in let marked_inputs = Locations.Zone.bottom in - let marked_inputs, marks = + let marked_inputs, marks = Signature.fold_impl_inputs do_in (marked_inputs, []) cm in - let m = - if Locations.Zone.is_included loc marked_inputs + let m = + if Locations.Zone.is_included loc marked_inputs then M.inter_all marks else M.bottom in @@ -413,7 +413,7 @@ M.pretty m; m - let something_visible cm = + let something_visible cm = some_visible_out cm || some_visible_in cm || ctrl_visible cm (** @return the mark that has to be associated to the call statement. @@ -421,7 +421,7 @@ *) let rec combined_marks cm = let add_m m (_, m2) = M.merge m m2 in - Signature.fold add_m M.bottom cm + Signature.fold add_m M.bottom cm let add_spare out_marks max_out = let rec add_out lst n = @@ -434,21 +434,21 @@ (* let same_output_visibility sig1 sig2 = let check sig_b () (num_out, m_a) = - let m_b = + let m_b = try Signature.find_output sig_b num_out - with Not_found -> M.bottom + with Not_found -> M.bottom in if (M.is_bottom m_a) <> (M.is_bottom m_b) then raise SlicingMacros.Break in let same = try - Signature.fold_outputs (check sig2) () sig1; + Signature.fold_outputs (check sig2) () sig1; Signature.fold_outputs (check sig1) () sig2; true with SlicingMacros.Break -> false in same *) - + (** check if the output marks in [called_marks] are enough for the * [call_marks]. * @return a list of (output number, mark) that are missing, @@ -456,15 +456,15 @@ * would make more visible outputs. * *) (* - let check_output called_marks (new_marks, more_outputs) (num_out, m_call) = - let m_called = - try Signature.find_output called_marks num_out + let check_output called_marks (new_marks, more_outputs) (num_out, m_call) = + let m_called = + try Signature.find_output called_marks num_out with Not_found -> M.bottom in let missing_m = M.missing_output ~call:m_call ~called:m_called in - let new_marks, more_outputs = match missing_m with + let new_marks, more_outputs = match missing_m with | None -> new_marks, more_outputs - | Some missing_m -> + | Some missing_m -> let new_output = M.is_bottom m_called in (num_out, missing_m) :: new_marks, more_outputs || new_output in new_marks, more_outputs @@ -474,8 +474,8 @@ let called_marks = match called_marks_opt with | Some called_marks -> called_marks | None -> empty - in - if debug then + in + if debug then Format.printf "with called = %a\n" pretty called_marks; called_marks @@ -485,42 +485,42 @@ List.fold_left (check_output called_marks) ([], false) new_call_marks let check_called_output_marks call_marks called_marks_opt = - if debug then - Format.printf "check_called_output_marks : call = %a\n" + if debug then + Format.printf "check_called_output_marks : call = %a\n" pretty call_marks; let called_marks = get_called_marks called_marks_opt in Signature.fold_outputs (check_output called_marks) ([], false) call_marks *) - let check_input sgn result (in_key, mark) = + let check_input sgn result (in_key, mark) = let add_if_needed m_sgn (in_key, m_input) (marks, more) = if debug then Format.printf "check_input : sgn=%a ; needed=%a\n" M.pretty m_sgn M.pretty m_input; let missing_m = M.missing_input ~call:m_sgn ~called:m_input in - match missing_m with + match missing_m with | None -> marks, more - | Some missing_m -> + | Some missing_m -> let new_input = M.is_bottom m_sgn in (in_key, missing_m) :: marks, more || new_input in - let m_sgn = + let m_sgn = try Signature.find_in_info sgn in_key - with PdgIndex.NotFound -> M.bottom + with Not_found -> M.bottom in add_if_needed m_sgn (in_key, mark) result let check_input_marks sgn input_marks = List.fold_left (check_input sgn) ([], false) input_marks (** check if the input marks in [call_marks] are enough to call a slice with - * [called_marks]. + * [called_marks]. * @return a list of (input number, mark) that are missing, - * and a boolean that says if the propagation in the call + * and a boolean that says if the propagation in the call * would make more visible inputs in the call signature. * *) let check_called_input_marks call_marks called_marks_opt = match called_marks_opt with - | Some called_marks -> + | Some called_marks -> let result = Signature.fold_all_inputs (check_input call_marks) ([], false) called_marks in result (*missing_marks, more_inputs*) @@ -538,7 +538,7 @@ end -(** The mark associated with a call stmt is composed of +(** The mark associated with a call stmt is composed of * marks for the call inputs (numbered form 1 to [max_in]) * and marks for the call outputs (numbered from 0 to [max_out] *) module SigMarks = F_SigMarks (MarkPair) @@ -551,8 +551,8 @@ let bottom_mark = MarkPair.bottom let mk_gen_spare = MarkPair.mk_gen_spare let mk_user_spare = MarkPair.mk_m1_spare -let mk_user_mark ~data ~addr ~ctrl = - if addr || data || ctrl then +let mk_user_mark ~data ~addr ~ctrl = + if addr || data || ctrl then MarkPair.mk_m1 (Mark.mk_adc addr data ctrl) else mk_user_spare @@ -596,5 +596,3 @@ let check_called_input_marks = SigMarks.check_called_input_marks let get_marked_out_zone = SigMarks.get_marked_out_zone let pretty_sig = SigMarks.pretty - - diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingMarks.mli frama-c-20111001+nitrogen+dfsg/src/slicing/slicingMarks.mli --- frama-c-20110201+carbon+dfsg/src/slicing/slicingMarks.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingMarks.mli 2011-10-10 08:38:22.000000000 +0000 @@ -42,7 +42,7 @@ val inter_marks : t_mark list -> t_mark (** [combine_marks] add a new information to the old value. -* @return (new_mark, is_new) +* @return (new_mark, is_new) where [is_new=true] if the new mark is not included in the old one. *) val combine_marks : t_mark -> t_mark -> (t_mark * t_mark) @@ -59,7 +59,7 @@ val empty_sig : t_sig_marks val get_input_mark : t_sig_marks -> int -> t_mark -val get_all_input_marks : t_sig_marks -> +val get_all_input_marks : t_sig_marks -> (PdgIndex.Signature.t_in_key * t_mark) list val merge_inputs_m1_mark : t_sig_marks -> t_mark val get_input_loc_under_mark : t_sig_marks -> Locations.Zone.t -> t_mark @@ -69,16 +69,15 @@ val some_visible_out : t_sig_marks -> bool val is_topin_visible : t_sig_marks -> bool (* -val check_output_marks : (int * t_mark) list -> t_sig_marks option -> +val check_output_marks : (int * t_mark) list -> t_sig_marks option -> (int * t_mark) list * bool val check_called_output_marks : t_sig_marks -> t_sig_marks option -> (int * t_mark) list * bool -val check_input_marks : t_sig_marks -> - (PdgIndex.Signature.t_in_key * t_mark) list -> +val check_input_marks : t_sig_marks -> + (PdgIndex.Signature.t_in_key * t_mark) list -> (PdgIndex.Signature.t_in_key * t_mark) list * bool -val check_called_input_marks : t_sig_marks -> t_sig_marks option -> +val check_called_input_marks : t_sig_marks -> t_sig_marks option -> (PdgIndex.Signature.t_in_key * t_mark) list * bool *) val get_marked_out_zone : t_sig_marks -> bool * Locations.Zone.t val pretty_sig : Format.formatter -> t_sig_marks -> unit - diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingParameters.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingParameters.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingParameters.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingParameters.ml 2011-10-10 08:38:22.000000000 +0000 @@ -38,184 +38,201 @@ module Calls = StringSet (struct - let option_name = "-slice-calls" - let arg_name = "f1, ..., fn" - let help = - "select every calls to functions f1,...,fn, and all their effect" + let option_name = "-slice-calls" + let arg_name = "f1, ..., fn" + let help = + "select every calls to functions f1,...,fn, and all their effect" let kind = `Correctness end) module Return = StringSet (struct - let option_name = "-slice-return" - let arg_name = "f1, ..., fn" - let help = - "select the result (returned value) of functions f1,...,fn" + let option_name = "-slice-return" + let arg_name = "f1, ..., fn" + let help = + "select the result (returned value) of functions f1,...,fn" let kind = `Correctness end) module Threat = StringSet (struct - let option_name = "-slice-threat" - let arg_name = "f1, ..., fn" - let help = "select the threats of functions f1,...,fn" + let option_name = "-slice-threat" + let arg_name = "f1, ..., fn" + let help = "select the threats of functions f1,...,fn" let kind = `Correctness end) module Assert = StringSet (struct - let option_name = "-slice-assert" - let arg_name = "f1, ..., fn" - let help = "select the assertions of functions f1,...,fn" + let option_name = "-slice-assert" + let arg_name = "f1, ..., fn" + let help = "select the assertions of functions f1,...,fn" let kind = `Correctness end) module LoopInv = StringSet (struct - let option_name = "-slice-loop-inv" - let arg_name = "f1, ..., fn" - let help = "select the loop invariants of functions f1,...,fn" + let option_name = "-slice-loop-inv" + let arg_name = "f1, ..., fn" + let help = "select the loop invariants of functions f1,...,fn" let kind = `Correctness end) module LoopVar = StringSet (struct - let option_name = "-slice-loop-var" - let arg_name = "f1, ..., fn" - let help = "select the loop variants of functions f1,...,fn" + let option_name = "-slice-loop-var" + let arg_name = "f1, ..., fn" + let help = "select the loop variants of functions f1,...,fn" let kind = `Correctness end) module Pragma = StringSet (struct - let option_name = "-slice-pragma" - let arg_name = "f1, ..., fn" + let option_name = "-slice-pragma" + let arg_name = "f1, ..., fn" let kind = `Correctness - let help = - "use the slicing pragmas in the code of functions f1,...,fn as \ + let help = + "use the slicing pragmas in the code of functions f1,...,fn as \ slicing criteria" - let () = Plugin.set_optional_help + let () = Plugin.set_optional_help "@;<0 0>@[<hov>@[<hov 4>//@@slice pragma ctrl; @ to@ reach@ this@ \ control-flow@ point@]@\n\ @[<hov 4>//@@slice pragma expr <expr_desc;> @ to@ preserve@ the@ value@ of@ \ an@ expression@ at@ this@ control-flow@ point@]@\n\ @[<hov 4>//@@slice pragma stmt; @ to@ preserve@ the@ effect@ of@ the@ next@ \ statement@]@]" - end) + end) module RdAccess = StringSet - (struct + (struct let kind = `Correctness - let module_name = "Slicing.Select.RdAccess" - let option_name = "-slice-rd" - let arg_name = "v1, ..., vn" - let help = - "select the read accesses to left-values v1,...,vn \ - (addresses are evaluated at the beginning of the function given as \ + let module_name = "Slicing.Select.RdAccess" + let option_name = "-slice-rd" + let arg_name = "v1, ..., vn" + let help = + "select the read accesses to left-values v1,...,vn \ + (addresses are evaluated at the beginning of the function given as \ entry point)" - end) + end) module WrAccess = StringSet - (struct + (struct let kind = `Correctness - let module_name = "Slicing.Select.WrAccess" - let option_name = "-slice-wr" - let arg_name = "v1, ..., vn" - let help = - "select the write accesses to left-values v1,...,vn \ - (addresses are evaluated at the beginning of the function given as\ + let module_name = "Slicing.Select.WrAccess" + let option_name = "-slice-wr" + let arg_name = "v1, ..., vn" + let help = + "select the write accesses to left-values v1,...,vn \ + (addresses are evaluated at the beginning of the function given as\ entry point)" - end) + end) module Value = StringSet - (struct + (struct let kind = `Correctness - let module_name = "Slicing.Select.Value" - let option_name = "-slice-value" - let arg_name = "v1, ..., vn" - let help = - "select the result of left-values v1,...,vn at the end of the \ + let module_name = "Slicing.Select.Value" + let option_name = "-slice-value" + let arg_name = "v1, ..., vn" + let help = + "select the result of left-values v1,...,vn at the end of the \ function given as entry point (addresses are evaluated at the beginning of \ the function given as entry point)" - end) + end) end module Mode = struct module Callers = True(struct - let option_name = "-slice-callers" - let help = "propagate the slicing to the function callers" + let option_name = "-slice-callers" + let help = "propagate the slicing to the function callers" let kind = `Tuning - end) + end) module Calls = Int (struct - let option_name = "-slicing-level" - let default = 2 - let arg_name = "" - let help = "set the default level of slicing used to propagate to \ + let option_name = "-slicing-level" + let default = 2 + let arg_name = "" + let help = "set the default level of slicing used to propagate to \ the calls\n\ - 0 : don't slice the called functions\n\ - 1 : don't slice the called functions but propagate the marks anyway\n\ - 2 : try to use existing slices, create at most one\n\ - 3 : most precise slices\n\ + 0 : don't slice the called functions\n\ + 1 : don't slice the called functions but propagate the marks anyway\n\ + 2 : try to use existing slices, create at most one\n\ + 3 : most precise slices\n\ note: this value (defaults to 2) is not used for calls to undefined \ functions\n\ - except when '-slice-undef-functions' option is set" + except when '-slice-undef-functions' option is set" let kind = `Tuning - end) + end) let () = Calls.set_range ~min:0 ~max:3 module SliceUndef = False(struct - let option_name = "-slice-undef-functions" - let help = "allow the use of the -slicing-level option for calls \ + let option_name = "-slice-undef-functions" + let help = "allow the use of the -slicing-level option for calls \ to undefined functions" let kind = `Tuning - end) + end) module KeepAnnotations = False(struct - let option_name = "-slicing-keep-annotations" - let help = "keep annotations as long as the used variables are \ + let option_name = "-slicing-keep-annotations" + let help = "keep annotations as long as the used variables are \ declared and the accessibility of the program point is preserved (even if the \ value of the data is not preserved)" let kind = `Correctness - end) + end) end module ProjectName = String(struct - let option_name = "-slicing-project-name" - let arg_name = "" - let help = "name of the slicing project (defaults to \"Slicing\")" - let default = "Slicing" + let option_name = "-slicing-project-name" + let arg_name = "" + let help = "name of the slicing project (defaults to \"Slicing\")" + let default = "Slicing" let kind = `Tuning - end) + end) module ExportedProjectPostfix = String(struct - let option_name = "-slicing-exported-project-postfix" - let arg_name = "" - let help = "postfix added to the slicing project name for building the name of the exported project (defaults to \"export\")" - let default = "export" + let option_name = "-slicing-exported-project-postfix" + let arg_name = "" + let help = "postfix added to the slicing project name for building \ +the name of the exported project (defaults to \"export\")" + let default = "export" let kind = `Tuning - end) - -module Print = - False(struct - let option_name = "-slice-print" - let help = "pretty print the sliced code" - let kind = `Tuning - end) + end) + +module Print = struct + let new_command = "<normal slicing command> -then-on 'Slicing export' -print" + include False(struct + let option_name = "-slice-print" + let help = "deprecated. Use instead " ^ new_command + let kind = `Tuning + end) + (* Just a small hack to inform the end-user that he is using a deprecated + option without changing the old behavior (incompatible with -ocode for + instance). *) + let get () = + let b = get () in + if b then deprecated "-slice-print" ~now:new_command (fun () -> ()) (); + b +end + +module Force = + True(struct + let option_name = "-slice-force" + let help = "force slicing" + let kind = `Tuning + end) module OptionModified = State_builder.Ref @@ -227,13 +244,6 @@ let default () = true end) -module Force = - True(struct - let option_name = "-slice-force" - let help = "don't slice" - let kind = `Tuning - end) - let () = State_dependency_graph.Static.add_codependencies ~onto:OptionModified.self @@ -270,12 +280,25 @@ let set_off () = Force.off () ; - OptionModified.set false ; + OptionModified.set false +let clear () = + Force.clear () ; + Select.Calls.clear () ; + Select.Return.clear () ; + Select.Threat.clear () ; + Select.Assert.clear () ; + Select.LoopInv.clear () ; + Select.LoopVar.clear () ; + Select.Pragma.clear () ; + Select.RdAccess.clear () ; + Select.WrAccess.clear () ; + Select.Value.clear () ; + OptionModified.clear () (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingParameters.mli frama-c-20111001+nitrogen+dfsg/src/slicing/slicingParameters.mli --- frama-c-20110201+carbon+dfsg/src/slicing/slicingParameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingParameters.mli 2011-10-10 08:38:22.000000000 +0000 @@ -28,32 +28,33 @@ (* modules related to the command line options *) module Select : sig - module Calls: Plugin.STRING_SET - module Return: Plugin.STRING_SET - module Threat: Plugin.STRING_SET - module Assert: Plugin.STRING_SET - module Pragma: Plugin.STRING_SET - module LoopInv: Plugin.STRING_SET - module LoopVar: Plugin.STRING_SET - module RdAccess: Plugin.STRING_SET - module WrAccess: Plugin.STRING_SET - module Value: Plugin.STRING_SET + module Calls: Plugin.String_set + module Return: Plugin.String_set + module Threat: Plugin.String_set + module Assert: Plugin.String_set + module Pragma: Plugin.String_set + module LoopInv: Plugin.String_set + module LoopVar: Plugin.String_set + module RdAccess: Plugin.String_set + module WrAccess: Plugin.String_set + module Value: Plugin.String_set end - + module Mode : sig - module Callers: Plugin.BOOL - module Calls: Plugin.INT - module SliceUndef: Plugin.BOOL - module KeepAnnotations: Plugin.BOOL + module Callers: Plugin.Bool + module Calls: Plugin.Int + module SliceUndef: Plugin.Bool + module KeepAnnotations: Plugin.Bool end -(** @since Carbon-20101202+dev *) -module ProjectName: Plugin.STRING - -(** @since Carbon-20101202+dev *) -module ExportedProjectPostfix: Plugin.STRING +(** @since Carbon-20110201 *) +module ProjectName: Plugin.String + +(** @since Carbon-20110201 *) +module ExportedProjectPostfix: Plugin.String + +module Print: Plugin.Bool -module Print: Plugin.BOOL - val is_on: unit -> bool val set_off: unit -> unit +val clear: unit -> unit diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingProject.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingProject.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingProject.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingProject.ml 2011-10-10 08:38:22.000000000 +0000 @@ -358,8 +358,8 @@ add_persistante_marks proj fi node_marks false propagate [] | T.CcExamineCalls _ | _ -> - Extlib.not_yet_implemented - "This slicing criterion on source function" + Extlib.not_yet_implemented + "This slicing criterion on source function" (** apply [filter] and return a list of generated filters *) let apply_action proj filter = @@ -403,17 +403,24 @@ apply new_filters; apply actions in - SlicingParameters.feedback ~level:1 "applying %d actions..." nb_actions; - let rec apply_user n = - try let a = get_next_filter proj in - SlicingParameters.feedback ~level:1 "applying actions: %d/%d..." n nb_actions; - let new_filters = apply_action proj a in - apply new_filters; - apply_user (n+1) - with Not_found -> - if nb_actions > 0 then - SlicingParameters.feedback ~level:2 "done (applying %d actions." nb_actions - in - apply_user 1 - + SlicingParameters.feedback ~level:1 "applying %d actions..." nb_actions; + let rec apply_user n = + try + let a = get_next_filter proj in + SlicingParameters.feedback ~level:1 "applying actions: %d/%d..." + n nb_actions; + let new_filters = apply_action proj a in + apply new_filters; + apply_user (n+1) + with Not_found -> + if nb_actions > 0 then + SlicingParameters.feedback + ~level:2 "done (applying %d actions." nb_actions + in + apply_user 1 +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingTransform.ml frama-c-20111001+nitrogen+dfsg/src/slicing/slicingTransform.ml --- frama-c-20110201+carbon+dfsg/src/slicing/slicingTransform.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingTransform.ml 2011-10-10 08:38:22.000000000 +0000 @@ -50,8 +50,8 @@ else begin table := Cil_datatype.Varinfo.Set.add vf !table ; List.exists - (fun (kf,_) -> exists_fun_callers kf) - (!Db.Value.callers kf) + (fun (kf,_) -> exists_fun_callers kf) + (!Db.Value.callers kf) end in exists_fun_callers kf @@ -67,7 +67,7 @@ in exists_fun_callers fpred kf module Visibility (SliceName : sig - val get : Db_types.kernel_function -> bool -> int -> string + val get : kernel_function -> bool -> int -> string end) = struct exception EraseAssigns @@ -85,7 +85,7 @@ let slices = M.fi_slices fi in let src_visible = is_src_fun_visible project kf in SlicingParameters.debug ~level:1 "[SlicingTransform.Visibility.fct_info] processing %a (%d slices/src %svisible)" - Kernel_function.pretty_name kf (List.length slices) + Kernel_function.pretty kf (List.length slices) (if src_visible then "" else "not "); let need_addr = (Kernel_function.get_vi kf).vaddrof in let src_name_used = src_visible || need_addr in @@ -128,7 +128,11 @@ | Iproto -> false | Iff (ff,_) -> let m = !Db.Slicing.Slice.get_mark_from_label ff inst label in - visible_mark m + let v = visible_mark m in + SlicingParameters.debug ~level:2 + "[SlicingTransform.Visibility.label_visible] label %a is %svisible" + !Ast_printer.d_label label (if v then "" else "in"); + v let data_in_visible ff data_in = match data_in with | None -> true @@ -137,14 +141,11 @@ * compute [data_in] or not, but let's see if, by chance, * some data have been selected manually... *) let m = Fct_slice.get_input_loc_under_mark ff data_in in - if !Db.Slicing.Mark.is_bottom m then - begin - SlicingParameters.debug ~level:2 - "[SlicingTransform.Visibility.data_in_visible] data %a invisible" - Locations.Zone.pretty data_in; - false - end - else true + let v = visible_mark m in + SlicingParameters.debug ~level:2 + "[SlicingTransform.Visibility.data_in_visible] data %a is %svisible" + Locations.Zone.pretty data_in (if v then "" else "in"); + v let all_nodes_visible ff nodes = let is_visible visi n = @@ -201,7 +202,7 @@ in case we end up with NotImplemented somewhere, we keep the annotation iff all C variables occuring in there are visible. *) - let all_logic_var_visible, all_logic_var_visible_term, + let all_logic_var_visible, all_logic_var_visible_term, all_logic_var_visible_assigns, all_logic_var_visible_deps = let module Exn = struct exception Invisible end in let vis ff = object @@ -242,7 +243,7 @@ ignore (Visitor.visitFramacTerm (vis ff) d.it_content); true with Exn.Invisible -> false) - let annotation_visible ff_opt stmt ~before annot = + let annotation_visible ff_opt stmt annot = SlicingParameters.debug ~level:2 "[SlicingTransform.Visibility.annotation_visible] ?"; match ff_opt with @@ -253,7 +254,7 @@ let pdg = !Db.Pdg.get kf in try let ctrl_nodes, decl_nodes, data_info = - !Db.Pdg.find_code_annot_nodes pdg before stmt annot + !Db.Pdg.find_code_annot_nodes pdg stmt annot in let data_visible = data_nodes_visible ff (decl_nodes, data_info) in let visible = ((all_nodes_visible ff ctrl_nodes) && data_visible) in @@ -327,7 +328,7 @@ let fun_assign_visible ff_opt v = let keep_annots = SlicingParameters.Mode.KeepAnnotations.get () in - SlicingParameters.debug ~level:2 + SlicingParameters.debug ~level:2 "[SlicingTransform.Visibility.fun_assign_visible \ (with keep_annots = %B)] ?" keep_annots; @@ -343,7 +344,7 @@ let fun_deps_visible ff_opt v = let keep_annots = SlicingParameters.Mode.KeepAnnotations.get () in - SlicingParameters.debug ~level:2 + SlicingParameters.debug ~level:2 "[SlicingTransform.Visibility.fun_deps_visible \ (with keep_annots = %B)] ?" keep_annots; @@ -352,8 +353,8 @@ | Isrc -> true | Iproto -> true | Iff (ff,_) -> all_logic_var_visible_deps ff v - in - SlicingParameters.debug ~level:2 + in + SlicingParameters.debug ~level:2 "[SlicingTransform.Visibility.fun_deps_visible] -> %s" (if visible then "yes" else "no"); visible @@ -374,7 +375,7 @@ try let m = PdgIndex.FctIndex.find_info ff_marks key in visible_mark m - with PdgIndex.NotFound -> false + with Not_found -> false let result_visible _kf ff = match ff with | Isrc | Iproto -> true @@ -384,7 +385,7 @@ try let m = PdgIndex.FctIndex.find_info ff_marks key in visible_mark m - with PdgIndex.NotFound -> false + with Not_found -> false let called_info (project, ff) call_stmt = let info = match ff with @@ -404,7 +405,7 @@ let kf_ff = M.get_ff_kf ff in let src_visible = is_src_fun_visible project kf_ff in (Some (kf_ff, Iff (ff, src_visible))) - with PdgIndex.NotFound -> + with Not_found -> (* the functor should call [called_info] only for visible calls *) assert false in @@ -426,10 +427,14 @@ let module S = struct let get = f_slice_names end in let module Visi = Visibility (S) in let module Transform = Filter.F (Visi) in - let tmp_prj = Transform.build_cil_file (new_proj_name ^ " tmp") slicing_project in - let new_prj = !Db.Sparecode.rm_unused_globals ~new_proj_name:new_proj_name ~project:tmp_prj () in + let tmp_prj = + Transform.build_cil_file (new_proj_name ^ " tmp") slicing_project + in + let new_prj = + !Db.Sparecode.rm_unused_globals ~new_proj_name ~project:tmp_prj () + in Project.remove ~project:tmp_prj (); - let ctx = Parameters.get_selection_context () in + let ctx = Plugin.get_selection_context () in Project.copy ~selection:ctx new_prj; SlicingParameters.feedback ~level:2 "done (exporting project to '%s')." new_proj_name; diff -Nru frama-c-20110201+carbon+dfsg/src/slicing/slicingTransform.mli frama-c-20111001+nitrogen+dfsg/src/slicing/slicingTransform.mli --- frama-c-20110201+carbon+dfsg/src/slicing/slicingTransform.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing/slicingTransform.mli 2011-10-10 08:38:22.000000000 +0000 @@ -24,23 +24,23 @@ (** Export a CIL application from a slicing project *) -val default_slice_names:(Db_types.kernel_function -> bool -> int -> string) - -(** Apply the actions still waiting in the project -* and transform the program (CIL AST) using slicing results +val default_slice_names:(Cil_types.kernel_function -> bool -> int -> string) + +(** Apply the actions still waiting in the project +* and transform the program (CIL AST) using slicing results * Can optionally specify how to name the sliced functions using [f_slice_names]. * (see db.mli) *) val extract : - f_slice_names:(Db_types.kernel_function -> bool -> int -> string) + f_slice_names:(Cil_types.kernel_function -> bool -> int -> string) -> string -> Db.Slicing.Project.t -> Project.t - -(** Return [true] if the source function is called + +(** Return [true] if the source function is called * (even indirectly via transitivity) from a [Slice.t]. *) -val is_src_fun_called : - Db.Slicing.Project.t -> Db_types.kernel_function -> bool - -(** Return [true] if the source function is visible +val is_src_fun_called : + Db.Slicing.Project.t -> Cil_types.kernel_function -> bool + +(** Return [true] if the source function is visible * (even indirectly via transitivity) from a [Slice.t]. *) -val is_src_fun_visible : - Db.Slicing.Project.t -> Db_types.kernel_function -> bool +val is_src_fun_visible : + Db.Slicing.Project.t -> Cil_types.kernel_function -> bool diff -Nru frama-c-20110201+carbon+dfsg/src/slicing_types/slicingInternals.ml frama-c-20111001+nitrogen+dfsg/src/slicing_types/slicingInternals.ml --- frama-c-20110201+carbon+dfsg/src/slicing_types/slicingInternals.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing_types/slicingInternals.ml 2011-10-10 08:38:30.000000000 +0000 @@ -73,6 +73,9 @@ (** Each PDG element has 2 marks to deal with interprocedural propagation *) type t_pdg_mark = {m1 : t_mark ; m2 : t_mark } +let t_pdg_mark_packed_descr = Structural_descr.p_abstract + (* Ok: Dpd.t is in fact int *) + let compare_pdg_mark p1 p2 = if p1 == p2 then 0 else @@ -85,7 +88,7 @@ (** Type for all the informations related to any function, * even if we don't have its definition. *) and t_fct_info = { - fi_kf : Db_types.kernel_function; + fi_kf : Cil_types.kernel_function; fi_def : Cil_types.fundec option; fi_project : t_project; mutable fi_top : t_pdg_mark option; diff -Nru frama-c-20110201+carbon+dfsg/src/slicing_types/slicingTypes.ml frama-c-20111001+nitrogen+dfsg/src/slicing_types/slicingTypes.ml --- frama-c-20110201+carbon+dfsg/src/slicing_types/slicingTypes.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/slicing_types/slicingTypes.ml 2011-10-10 08:38:30.000000000 +0000 @@ -67,11 +67,9 @@ let reprs = [ SlicingInternals.dummy_t_fct_user_crit ] let name = "SlicingTypes.Fct_user_crit" let mem_project = Datatype.never_any_project + let varname _ = "user_criteria" end) -(** A set of selections, grouped by function *) -module Sl_selects = Cil_datatype.Varinfo.Map - (** Function slice *) type sl_fct_slice = SlicingInternals.t_fct_slice @@ -105,10 +103,11 @@ include Datatype.Undefined (* TODO: unmarshal *) type t = sl_select let reprs = - List.map - (fun v -> v, SlicingInternals.dummy_t_fct_user_crit) - Cil_datatype.Varinfo.reprs + List.map + (fun v -> v, SlicingInternals.dummy_t_fct_user_crit) + Cil_datatype.Varinfo.reprs let name = "SlicingTypes.Sl_select" + let varname _s = "sl_select" let mem_project = Datatype.never_any_project end) @@ -144,27 +143,27 @@ | _, SlicingInternals.Spare -> None | SlicingInternals.Cav mark1, SlicingInternals.Cav mark2 -> if (PdgTypes.Dpd.is_bottom mark2) then - (* use [!Db.Slicing.Mark.make] contructor *) + (* use [!Db.Slicing.Mark.make] contructor *) Some (fun fmt -> Format.fprintf fmt "@[<hv 2>!Db.Slicing.Mark.make@;~addr:%b@;~data:%b@;~ctrl:%b@]" (PdgTypes.Dpd.is_addr mark1) - (PdgTypes.Dpd.is_data mark1) - (PdgTypes.Dpd.is_ctrl mark1)) + (PdgTypes.Dpd.is_data mark1) + (PdgTypes.Dpd.is_ctrl mark1)) else - None + None in let pp = match pp with | Some pp -> pp | None -> - let pp fmt sub_m = match sub_m with - (* use internals constructors *) + let pp fmt sub_m = match sub_m with + (* use internals constructors *) | SlicingInternals.Spare -> Format.fprintf fmt "SlicingInternals.Spare" | SlicingInternals.Cav pdg_m -> Format.fprintf fmt "@[<hv 2>(SlicingInternals.Cav@;@[<hv 2>(PdgTypes.Dpd.make@;~a:%b@;~d:%b@;~c:%b@;())@])@]" - (PdgTypes.Dpd.is_addr pdg_m) - (PdgTypes.Dpd.is_data pdg_m) - (PdgTypes.Dpd.is_ctrl pdg_m) - in + (PdgTypes.Dpd.is_addr pdg_m) + (PdgTypes.Dpd.is_data pdg_m) + (PdgTypes.Dpd.is_ctrl pdg_m) + in fun fmt -> Format.fprintf fmt "@[<hv 2>SlicingInternals.create_sl_mark@;~m1:%a@;~m2:%a@]" pp m.SlicingInternals.m1 pp m.SlicingInternals.m2 diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/globs.ml frama-c-20111001+nitrogen+dfsg/src/sparecode/globs.ml --- frama-c-20110201+carbon+dfsg/src/sparecode/globs.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/globs.ml 2011-10-10 08:38:24.000000000 +0000 @@ -26,7 +26,10 @@ open Cilutil open Cil -let debug format = Sparecode_params.debug ~level:2 format +let dkey = "globs" + +let debug format = Sparecode_params.debug ~dkey ~level:2 format +let debug' format = Sparecode_params.debug ~dkey ~level:3 format let used_variables = Hashtbl.create 257 let var_init = Hashtbl.create 257 @@ -53,7 +56,7 @@ * name... *) if Hashtbl.mem used_typeinfo ti.tname then SkipChildren else begin - debug "[sparecode:globs] add used typedef %s@." ti.tname; + debug "add used typedef %s@." ti.tname; Hashtbl.add used_typeinfo ti.tname (); ignore (visitCilType (self:>Cil.cilVisitor) ti.ttype); DoChildren @@ -61,13 +64,13 @@ | TEnum(ei,_) -> if Hashtbl.mem used_enuminfo ei.ename then SkipChildren else begin - debug "[sparecode:globs] add used enum %s@." ei.ename; + debug "add used enum %s@." ei.ename; Hashtbl.add used_enuminfo ei.ename (); DoChildren end | TComp(ci,_,_) -> if Hashtbl.mem used_compinfo ci.cname then SkipChildren else begin - debug "[sparecode:globs] add used comp %s@." ci.cname; + debug "add used comp %s@." ci.cname; Hashtbl.add used_compinfo ci.cname (); List.iter (fun f -> ignore (visitCilType (self:>Cil.cilVisitor) f.ftype)) @@ -78,7 +81,7 @@ method vvrbl v = if v.vglob && not (Hashtbl.mem used_variables v) then begin - debug "[sparecode:globs] add used var %s@." v.vname; + debug "add used var %s@." v.vname; Hashtbl.add used_variables v (); ignore (visitCilType (self:>Cil.cilVisitor) v.vtype); try @@ -90,14 +93,20 @@ method vglob_aux g = match g with | GFun (f, _) -> - debug "[sparecode:globs] add function %s@." f.svar.vname; + debug "add function %s@." f.svar.vname; Hashtbl.add used_variables f.svar (); Cil.DoChildren | GAnnot _ -> Cil.DoChildren | GVar (v, init, _) -> - (match init.init with None -> () - | Some i -> Hashtbl.add var_init v i); - Cil.SkipChildren + let _ = match init.init with | None -> () + | Some init -> + begin + Hashtbl.add var_init v init; + if Hashtbl.mem used_variables v then + (* already used before its initialization (see bug #758) *) + ignore (visitCilInit (self:>Cil.cilVisitor) v NoOffset init) + end + in Cil.SkipChildren | GVarDecl(_,v,_) when isFunctionType v.vtype -> DoChildren | _ -> Cil.SkipChildren @@ -115,27 +124,27 @@ | GVarDecl (_, v, _loc) -> (* variable/function declaration *) if Hashtbl.mem used_variables v then DoChildren else begin - debug "[sparecode:globs] remove var %s@." v.vname; + debug "remove var %s@." v.vname; ChangeTo [] end | GType (ti, _loc) (* typedef *) -> if Hashtbl.mem used_typeinfo ti.tname then DoChildren else begin - debug "[sparecode:globs] remove typedef %s@." ti.tname; + debug "remove typedef %s@." ti.tname; ChangeTo [] end | GCompTag (ci, _loc) (* struct/union definition *) | GCompTagDecl (ci, _loc) (* struct/union declaration *) -> if Hashtbl.mem used_compinfo ci.cname then DoChildren else begin - debug "[sparecode:globs] remove comp %s@." ci.cname; + debug "remove comp %s@." ci.cname; ChangeTo [] end | GEnumTag (ei, _loc) (* enum definition *) | GEnumTagDecl (ei, _loc) (* enum declaration *) -> if Hashtbl.mem used_enuminfo ei.ename then DoChildren else begin - debug "[sparecode:globs] remove enum %s@." ei.ename; + debug "remove enum %s@." ei.ename; DoChildren (* ChangeTo [] *) end | _ -> Cil.DoChildren @@ -156,7 +165,7 @@ Cmdline.run_after_extended_stage (fun () -> State_dependency_graph.Static.add_codependencies - ~onto:Result.self + ~onto:Result.self [ !Db.Pdg.self; !Db.Outputs.self_external ]) let rm_unused_decl = @@ -165,12 +174,12 @@ clear_tables (); let visitor = new collect_visitor in ignore - (Visitor.visitFramacFile - (visitor:>Visitor.frama_c_visitor) (Ast.get ())); - debug "[sparecode:globs] filtering done@."; + (Visitor.visitFramacFile + (visitor:>Visitor.frama_c_visitor) (Ast.get ())); + debug "filtering done@."; let visitor = new filter_visitor in let new_prj = File.create_project_from_visitor new_proj_name visitor in - let ctx = Parameters.get_selection_context () in + let ctx = Plugin.get_selection_context () in Project.copy ~selection:ctx new_prj; new_prj) diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/marks.ml frama-c-20111001+nitrogen+dfsg/src/sparecode/marks.ml --- frama-c-20110201+carbon+dfsg/src/sparecode/marks.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/marks.ml 2011-10-10 08:38:24.000000000 +0000 @@ -23,8 +23,13 @@ (**************************************************************************) let debug n format = Sparecode_params.debug ~level:n format +let fatal fmt = Sparecode_params.fatal fmt -let fatal text = Sparecode_params.fatal text +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** The project is composed of [FctIndex] marked with [BoolMark] +* to be used by [Pdg.Register.F_Proj], and another table to store if a function +* is visible (usefull for Top PDG). *) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) module BoolMark = struct type prop_mode = Glob | Loc @@ -34,6 +39,8 @@ let bottom = false,Loc let top = true,Glob + let visible (b,_) = b + let mk glob = if glob then (true,Glob) else (true, Loc) let merge (b1,p1) (b2,p2) = @@ -58,6 +65,26 @@ (match p with Glob -> "Glob" | Loc -> "Loc") end +module KfTopVisi = struct + include Cil_datatype.Kf.Hashtbl + + let add proj kf b = add (snd proj) kf b + + let find proj kf = find (snd proj) kf + + (** as soon as a TOP function is called, all its callees are called. *) + let rec set proj kf = + try find proj kf + with Not_found -> + add proj kf (); + debug 1 "select '%a' as fully visible (top or called by top)" + Kernel_function.pretty kf; + let callees = !Db.Users.get kf in + Kernel_function.Hptset.iter (set proj) callees + + let get proj kf = try find proj kf; true with Not_found -> false +end + (** when we first compute marks to select outputs, * we don't immediately propagate input marks to the calls, * because some calls may be useless and we don't want to compute @@ -66,23 +93,30 @@ * lead to them : so, we propagate... * *) let call_in_to_check = ref [] +let called_top = ref [] module Config = struct - module M = struct - include BoolMark - end + module M = BoolMark let mark_to_prop_to_caller_input call_opt pdg_caller sel_elem m = match m with | true, M.Glob -> Some m | true, M.Loc -> - call_in_to_check := + call_in_to_check := (pdg_caller, call_opt, sel_elem, m) :: !call_in_to_check; None | _ -> fatal "cannot propagate invisible mark@." - let mark_to_prop_to_called_output _call _pdg _node m = - match m with + let mark_to_prop_to_called_output _call called_pdg = + if PdgTypes.Pdg.is_top called_pdg then + begin + let kf = PdgTypes.Pdg.get_kf called_pdg in + called_top := kf :: !called_top; + debug 1 "memo call to TOP '%a'" Kernel_function.pretty kf; + (fun _ _ -> None) + end + else + fun _n m -> match m with | true, M.Glob -> Some (true, M.Loc) | true, M.Loc -> Some m | _ -> fatal "cannot propagate invisible mark@." @@ -91,13 +125,28 @@ module ProjBoolMarks = Pdg.Register.F_Proj (Config) -type t_proj = ProjBoolMarks.t +type t_proj = ProjBoolMarks.t * unit KfTopVisi.t type t_fct = ProjBoolMarks.t_fct -let get_marks proj kf = - ProjBoolMarks.find_marks proj (Kernel_function.get_vi kf) +let new_project () = (ProjBoolMarks.empty, KfTopVisi.create 10) -let mark_visible _fm (b,_) = b +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** Get stored information *) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + +let proj_marks proj = fst proj + +(** @raise Not_found when the function is not marked. It might be the case +* that it is nonetheless visible, but has no marks because of a Top PDG. *) +let get_marks proj kf = + try KfTopVisi.find proj kf ; None + with Not_found -> + ProjBoolMarks.find_marks (proj_marks proj) (Kernel_function.get_vi kf) + +(** Useful only if there has been some Pdg.Top *) +let kf_visible proj kf = + try KfTopVisi.find proj kf ; true + with Not_found -> get_marks proj kf <> None let rec key_visible fm key = try @@ -106,37 +155,75 @@ let call = PdgIndex.Key.call_from_id call_id in call_visible fm call | _ -> let m = PdgIndex.FctIndex.find_info fm key in - mark_visible fm m - with PdgIndex.NotFound -> false + BoolMark.visible m + with Not_found -> false and -(** the call is visible if its control node is visible *) - call_visible fm call = - let key = PdgIndex.Key.call_ctrl_key call in - key_visible fm key - (* - try - let _, call_sgn = PdgIndex.FctIndex.find_call fm call in - let test old_v (_, m) = old_v || (mark_visible fm m) in - let visible = - let visible = PdgIndex.Signature.fold_all_outputs test false call_sgn in - visible - with PdgIndex.NotFound -> false - *) - - -let rec all_keys_visible fm keys = match keys with - | [] -> true - | k :: keys -> (key_visible fm k) && (all_keys_visible fm keys) - -let select_pdg_elements proj pdg to_select = - ProjBoolMarks.mark_and_propagate proj pdg to_select + (** the call is visible if its control node is visible *) + call_visible fm call = + let key = PdgIndex.Key.call_ctrl_key call in + key_visible fm key + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** Build selections and propagate. *) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** Doesn't mark yet, but add what has to be marked in the selection, +* and keep things sorted. *) let rec add_pdg_selection to_select pdg sel_mark = match to_select with - | [] -> [(pdg, [sel_mark])] + | [] -> + let l = match sel_mark with None -> [] | Some m -> [m] in [(pdg, l)] | (p, ln) :: tl -> - if Db.Pdg.from_same_fun p pdg then (p, sel_mark::ln):: tl + if Db.Pdg.from_same_fun p pdg + then + let ln = match sel_mark with None -> ln + | Some sel_mark -> sel_mark::ln + in (p, ln)::tl else (p, ln)::(add_pdg_selection tl pdg sel_mark) +let add_node_to_select glob to_select z_opt node = + PdgMarks.add_node_to_select to_select (node, z_opt) (BoolMark.mk glob) + +let add_nodes_and_undef_to_select + glob (ctrl_nodes, decl_nodes, data_info) to_select = + match data_info with + | None -> to_select (* don't select anything (computation failed) *) + | Some (data_nodes, undef) -> + let to_select = + List.fold_left (fun s n -> add_node_to_select glob s None n) + to_select ctrl_nodes + in + let to_select = + List.fold_left (fun s n -> add_node_to_select glob s None n) + to_select decl_nodes + in + let to_select = + List.fold_left (fun s (n,z_opt) -> add_node_to_select glob s z_opt n) + to_select data_nodes + in + let m = (BoolMark.mk glob) in + let to_select = PdgMarks.add_undef_in_to_select to_select undef m in + to_select + +(** Mark the function as visible +* and add the marks according to the selection. + Notice that if the function has been marked as called by a visible top, + we can skip the selection since the function has to be fully visible anyway. +**) +let select_pdg_elements proj pdg to_select = + let kf = PdgTypes.Pdg.get_kf pdg in + try KfTopVisi.find proj kf; + debug 1 "function '%a' selected for top: skip selection" + Kernel_function.pretty kf + with Not_found -> + debug 1 "add selection in function '%a'@." Kernel_function.pretty kf; + ProjBoolMarks.mark_and_propagate (proj_marks proj) pdg to_select; + List.iter (KfTopVisi.set proj) !called_top; + called_top := [] + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** First step is finished: propagate in the calls. *) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** [proj] contains some function marks and [!call_in_to_check] * is a list of call input marks to propagate when the call is visible. * These marks come from the called function selection, @@ -152,20 +239,20 @@ | [] -> (to_select, unused) | (pdg_caller, call, sel, m) as e :: calls -> let kf_caller = PdgTypes.Pdg.get_kf pdg_caller in - let fm_caller = get_marks proj kf_caller in - let visible = match call with + let visible, select = match call with | Some call -> - let fm = match fm_caller with + let fm = match get_marks proj kf_caller with | None -> fatal "the caller should have marks@." - | Some fm -> fm + | Some fm -> fm in - call_visible fm call + let visible = call_visible fm call in + visible, Some (sel, m) | None -> (* let see if the function is visible or not *) assert (PdgTypes.Pdg.is_top pdg_caller); - match fm_caller with None -> false | Some _fm -> true + KfTopVisi.get proj kf_caller, None in let res = if visible then - let to_select = add_pdg_selection to_select pdg_caller (sel, m) + let to_select = add_pdg_selection to_select pdg_caller select in (to_select, unused) else (to_select, e::unused) in process res calls @@ -180,30 +267,28 @@ to_select; process_call_inputs proj +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** Main selection: select starting points and propagate. *) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) -let add_node_to_select glob to_select z_opt node = - PdgMarks.add_node_to_select to_select (node, z_opt) (BoolMark.mk glob) +let select_entry_point proj _kf pdg = + let ctrl = !Db.Pdg.find_entry_point_node pdg in + let to_select = add_node_to_select true [] None ctrl in + select_pdg_elements proj pdg to_select -let add_nodes_and_undef_to_select - glob (ctrl_nodes, decl_nodes, data_info) to_select = - match data_info with - | None -> to_select (* don't select anything (computation failed) *) - | Some (data_nodes, undef) -> - let to_select = - List.fold_left (fun s n -> add_node_to_select glob s None n) - to_select ctrl_nodes - in - let to_select = - List.fold_left (fun s n -> add_node_to_select glob s None n) - to_select decl_nodes - in - let to_select = - List.fold_left (fun s (n,z_opt) -> add_node_to_select glob s z_opt n) - to_select data_nodes - in - let m = (BoolMark.mk glob) in - let to_select = PdgMarks.add_undef_in_to_select to_select undef m in - to_select +let select_all_outputs proj kf pdg = + let outputs = !Db.Outputs.get_external kf in + debug 1 "selecting output zones %a@." Locations.Zone.pretty outputs; + try + let nodes, undef = !Db.Pdg.find_location_nodes_at_end pdg outputs in + let nodes = + try ((!Db.Pdg.find_ret_output_node pdg),None) :: nodes + with Not_found -> nodes + in + let nodes_and_co = ([], [], Some (nodes, undef)) in + let to_select = add_nodes_and_undef_to_select false nodes_and_co [] in + select_pdg_elements proj pdg to_select + with Not_found -> (* end is unreachable *) () (** used to visit all the annotations of a given function * and to find the PDG nodes to select so that the reachable annotations @@ -221,71 +306,65 @@ if filter annot then try let stmt = Cilutil.valOf self#current_stmt in - let before = self#is_annot_before in - debug 1 "selecting annotation : %a @." - !Ast_printer.d_code_annotation annot; - let info = !Db.Pdg.find_code_annot_nodes pdg before stmt annot in + debug 1 "selecting annotation : %a @." + !Ast_printer.d_code_annotation annot; + let info = !Db.Pdg.find_code_annot_nodes pdg stmt annot in to_select <- add_nodes_and_undef_to_select true info to_select - with PdgIndex.NotFound -> () (* unreachable *) + with Not_found -> () (* unreachable *) in Cil.SkipChildren end -let select_all_outputs proj kf = - let pdg = !Db.Pdg.get kf in - let outputs = !Db.Outputs.get_external kf in - debug 1 "selecting output zones %a@." - Locations.Zone.pretty outputs; - try - let nodes, undef = !Db.Pdg.find_location_nodes_at_end pdg outputs in - let nodes = - try ((!Db.Pdg.find_ret_output_node pdg),None) :: nodes - with Db.Pdg.NotFound -> nodes - in - let nodes_and_co = ([], [], Some (nodes, undef)) in - let to_select = add_nodes_and_undef_to_select false nodes_and_co [] in - select_pdg_elements proj pdg to_select - with PdgIndex.NotFound -> (* end is unreachable *) - () - let select_annotations ~select_annot ~select_slice_pragma proj = let visit_fun kf = - try - debug 1 "look for annotations in function %s@." - (Kernel_function.get_name kf); - let filter annot = match annot.Cil_types.annot_content with - | Cil_types.APragma (Cil_types.Slice_pragma _) -> select_slice_pragma - | _ -> select_annot in - let f = Kernel_function.get_definition kf in - let pdg = !Db.Pdg.get kf in - let visit = new annot_visitor ~filter pdg in - ignore (Visitor.visitFramacFunction (visit:>Visitor.frama_c_visitor) f); - let to_select = visit#get_select in - select_pdg_elements proj pdg to_select - with Kernel_function.No_Definition -> - () (* nothing to do *) + debug 1 "look for annotations in function %a@." Kernel_function.pretty kf; + let pdg = !Db.Pdg.get kf in + if PdgTypes.Pdg.is_top pdg then debug 1 "pdg top: skip annotations" + else if PdgTypes.Pdg.is_bottom pdg + then debug 1 "pdg bottom: skip annotations" + else begin + let filter annot = match annot.Cil_types.annot_content with + | Cil_types.APragma (Cil_types.Slice_pragma _) -> select_slice_pragma + | _ -> select_annot + in + try + let f = Kernel_function.get_definition kf in + let visit = new annot_visitor ~filter pdg in + let fc_visit = (visit:>Visitor.frama_c_visitor) in + let _ = Visitor.visitFramacFunction fc_visit f in + let to_select = visit#get_select in + if to_select <> [] then select_pdg_elements proj pdg to_select + with Kernel_function.No_Definition -> () (* nothing to do *) + end in Globals.Functions.iter visit_fun -let select_entry_point proj kf = - let pdg = !Db.Pdg.get kf in - let ctrl = !Db.Pdg.find_entry_point_node pdg in - let to_select = add_node_to_select true [] None ctrl in - select_pdg_elements proj pdg to_select - let finalize proj = - debug 1 "finalize (process call inputs) @."; + debug 1 "finalize call input propagation@."; process_call_inputs proj; assert (!call_in_to_check = []) - -let select_usefull_things ~select_annot ~select_slice_pragma kf_entry = - let proj = ProjBoolMarks.empty in +let select_useful_things ~select_annot ~select_slice_pragma kf_entry = + let proj = new_project () in assert (!call_in_to_check = []); - debug 1 "selecting function %s outputs and entry point@." - (Kernel_function.get_name kf_entry); - select_entry_point proj kf_entry; - select_all_outputs proj kf_entry; - if (select_annot or select_slice_pragma) then - select_annotations ~select_annot ~select_slice_pragma proj; - finalize proj; + debug 1 "selecting function %a outputs and entry point@." + Kernel_function.pretty kf_entry; + let pdg = !Db.Pdg.get kf_entry in + if PdgTypes.Pdg.is_top pdg + then KfTopVisi.set proj kf_entry + else if PdgTypes.Pdg.is_bottom pdg + then debug 1 "unreachable entry point ?" + else begin + select_entry_point proj kf_entry pdg; + select_all_outputs proj kf_entry pdg; + if (select_annot || select_slice_pragma) then + select_annotations ~select_annot ~select_slice_pragma proj; + finalize proj + end; proj + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/marks.mli frama-c-20111001+nitrogen+dfsg/src/sparecode/marks.mli --- frama-c-20110201+carbon+dfsg/src/sparecode/marks.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/marks.mli 2011-10-10 08:38:24.000000000 +0000 @@ -26,10 +26,19 @@ type t_fct -val select_usefull_things : - select_annot:bool -> select_slice_pragma:bool -> Db_types.kernel_function -> t_proj +val select_useful_things : + select_annot:bool -> select_slice_pragma:bool -> Cil_types.kernel_function + -> t_proj -val get_marks : t_proj -> Db_types.kernel_function -> t_fct option +val get_marks : t_proj -> Cil_types.kernel_function -> t_fct option val key_visible : t_fct -> PdgIndex.Key.t -> bool +(** Useful mainly if there has been some Pdg.Top *) +val kf_visible : t_proj -> Cil_types.kernel_function -> bool + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/register.ml frama-c-20111001+nitrogen+dfsg/src/sparecode/register.ml --- frama-c-20110201+carbon+dfsg/src/sparecode/register.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/register.ml 2011-10-10 08:38:24.000000000 +0000 @@ -46,7 +46,7 @@ Cmdline.run_after_extended_stage (fun () -> State_dependency_graph.Static.add_codependencies - ~onto:Result.self + ~onto:Result.self [ !Db.Pdg.self; !Db.Outputs.self_external ]) module P = Sparecode_params @@ -66,10 +66,14 @@ ~label1:("new_proj_name", None) Datatype.string ~label2:("project", Some Project.current) Project.ty Project.ty) - unjournalized_rm_unused_globals + unjournalized_rm_unused_globals let rm_unused_globals ?new_proj_name ?(project=Project.current ()) () = - let new_proj_name = match new_proj_name with Some name -> name | None -> (Project.get_name project)^ " (without unused globals)" in + let new_proj_name = + match new_proj_name with + | Some name -> name + | None -> (Project.get_name project)^ " (without unused globals)" + in journalized_rm_unused_globals new_proj_name project let run select_annot select_slice_pragma = @@ -77,20 +81,22 @@ (*let initial_file = Ast.get () in*) let kf_entry, _library = Globals.entry_point () in - let proj = Marks.select_usefull_things - ~select_annot ~select_slice_pragma kf_entry in + let proj = + Marks.select_useful_things ~select_annot ~select_slice_pragma kf_entry + in let old_proj_name = Project.get_name (Project.current ()) in let new_proj_name = (old_proj_name^" without sparecode") in - P.feedback "remove unused global declarations..."; + P.feedback "remove unused global declarations..."; let tmp_prj = Transform.Info.build_cil_file "tmp_prj" proj in let new_prj = Project.on tmp_prj Globs.rm_unused_decl new_proj_name in - P.result "result in new project '%s'." (Project.get_name new_prj); - Project.remove ~project:tmp_prj (); - let ctx = Parameters.get_selection_context () in - Project.copy ~selection:ctx new_prj; - new_prj + + P.result "result in new project '%s'." (Project.get_name new_prj); + Project.remove ~project:tmp_prj (); + let ctx = Plugin.get_selection_context () in + Project.copy ~selection:ctx new_prj; + new_prj let journalized_get = Journal.register @@ -100,9 +106,9 @@ ~label2:("select_slice_pragma", None) Datatype.bool Project.ty) (fun select_annot select_slice_pragma -> - Result.memo - (fun _ -> run select_annot select_slice_pragma) - (select_annot, select_slice_pragma)) + Result.memo + (fun _ -> run select_annot select_slice_pragma) + (select_annot, select_slice_pragma)) (* add labels *) let get ~select_annot ~select_slice_pragma = @@ -131,7 +137,7 @@ let () = Db.Main.extend main (* -Local Variables: -compile-command: "make -C ../.." -End: + Local Variables: + compile-command: "make -C ../.." + End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/sparecode_params.ml frama-c-20111001+nitrogen+dfsg/src/sparecode/sparecode_params.ml --- frama-c-20110201+carbon+dfsg/src/sparecode/sparecode_params.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/sparecode_params.ml 2011-10-10 08:38:24.000000000 +0000 @@ -31,10 +31,11 @@ module Analysis = False(struct - let option_name = "-sparecode-analysis" + let option_name = "-sparecode" let help = "perform a spare code analysis" let kind = `Tuning end) +let () = Analysis.add_aliases ["-sparecode-analysis"] module Annot = True(struct @@ -50,3 +51,10 @@ "(automatically done by -sparecode-analysis)") let kind = `Correctness end) + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/sparecode_params.mli frama-c-20111001+nitrogen+dfsg/src/sparecode/sparecode_params.mli --- frama-c-20110201+carbon+dfsg/src/sparecode/sparecode_params.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/sparecode_params.mli 2011-10-10 08:38:24.000000000 +0000 @@ -24,12 +24,17 @@ include Plugin.S -module Analysis: Plugin.BOOL +module Analysis: Plugin.Bool (** Whether to perform spare code detection or not. *) -module Annot : Plugin.BOOL +module Annot : Plugin.Bool (** keep more things to keep all reachable annotations. *) -module GlobDecl : Plugin.BOOL +module GlobDecl : Plugin.Bool (** remove unused global types and variables *) +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/sparecode/transform.ml frama-c-20111001+nitrogen+dfsg/src/sparecode/transform.ml --- frama-c-20110201+carbon+dfsg/src/sparecode/transform.ml 2011-02-07 13:53:56.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/sparecode/transform.ml 2011-10-10 08:38:24.000000000 +0000 @@ -27,70 +27,60 @@ module BoolInfo = struct type t_proj = Marks.t_proj - type t_fct = Marks.t_fct * Kernel_function.t + type t_fct = Marks.t_fct option * Kernel_function.t exception EraseAssigns let fct_info project kf = match Marks.get_marks project kf with - | None -> [] - | Some fm -> [fm,kf] + | None -> + if Marks.kf_visible project kf then [None, kf] else [] + | Some fm -> [Some fm, kf] let key_visible txt fm key = - let visible = Marks.key_visible fm key in - Sparecode_params.debug ~level:3 "%s : %a -> %s@\n" - txt !Db.Pdg.pretty_key key (if visible then "true" else "false"); - visible + let visible = match fm with None -> true + | Some fm -> Marks.key_visible fm key + in + Sparecode_params.debug ~level:3 "%s : %a -> %b" + txt !Db.Pdg.pretty_key key visible; + visible + + let param_visible (fm,_) n = + let key = PdgIndex.Key.param_key n in + key_visible "param_visible" fm key + + let loc_var_visible (fm,_) var = + let key = PdgIndex.Key.decl_var_key var in + key_visible "loc_var_visible" fm key let term_visible (fm,kf) t = let module M = struct exception Invisible end in - let visitor = - object - inherit Visitor.frama_c_inplace - method vlogic_var_use v = - match v.lv_origin with - None -> DoChildren - | Some v when v.vformal -> - (try - if not - (key_visible "logic_var_visible" fm - (PdgIndex.Key.param_key - (Kernel_function.get_formal_position v kf + 1) - v)) - then raise M.Invisible - else DoChildren - with Not_found -> - Sparecode_params.fatal - "%a is a formal parameter but not of the current \ - kernel function %a. Aborting because of inconsistent state." - !Ast_printer.d_var v !Ast_printer.d_var - (Kernel_function.get_vi kf) - ) - | Some v when not v.vglob -> - if - not - (key_visible "logic_var_visible" fm - (PdgIndex.Key.decl_var_key v)) + let visitor = object inherit Visitor.frama_c_inplace + method vlogic_var_use v = + match v.lv_origin with + | None -> DoChildren + | Some v when v.vformal -> + let n_param = Kernel_function.get_formal_position v kf + 1 in + if not (param_visible (fm,kf) n_param) + then raise M.Invisible + else DoChildren + | Some v when not v.vglob -> + if not (loc_var_visible (fm, kf) v) then raise M.Invisible else DoChildren - | Some _ -> DoChildren - end + | Some _ -> DoChildren + end in - try - ignore (Visitor.visitFramacTerm visitor t); true - with M.Invisible -> false + try ignore (Visitor.visitFramacTerm visitor t); true + with M.Invisible -> false let body_visible _fm = true - let param_visible (fm,_) n = - let key = PdgIndex.Key.param_key n () in - key_visible "param_visible" fm key - let label_visible (fm,_) stmt label = let lab_key = PdgIndex.Key.label_key stmt label in key_visible "label_visible" fm lab_key - let annotation_visible _ _stmt ~before:_ _annot = + let annotation_visible _ _stmt _annot = (* all the annotation should have been selected by the analysis *) true @@ -121,36 +111,45 @@ key_visible "res_call_visible" fm key - let called_info (project, _fm) call_stmt = match call_stmt.skind with - | Instr (Call (_, _fexp, _, _)) -> - let called_functions = Db.Value.call_to_kernel_function call_stmt in - (match Kernel_function.Hptset.contains_single_elt called_functions with - | None -> None - | Some funct -> - (match Marks.get_marks project funct with - | None -> None - | Some fm -> Some (funct, (fm,funct)))) - | _ -> - Sparecode_params.fatal "this call is not a call" + let called_info (project, _fm) call_stmt = + match call_stmt.skind with + | Instr (Call (_, _fexp, _, _)) -> + let called_functions = Db.Value.call_to_kernel_function call_stmt in + let call_info = + match + Kernel_function.Hptset.contains_single_elt called_functions + with + | None -> None + | Some kf -> + match Marks.get_marks project kf with + | None -> + if Marks.kf_visible project kf + then Some (kf, (None,kf)) + else None + | Some fm -> Some (kf, (Some fm,kf)) + in call_info + | _ -> Sparecode_params.fatal "this call is not a call" let inst_visible (fm,_) stmt = match stmt.Cil_types.skind with - | Cil_types.Block _ -> - (* block are always visible for syntactic reasons *) - true - | _ -> - let stmt_key = PdgIndex.Key.stmt_key stmt in - key_visible "inst_visible" fm stmt_key - - let loc_var_visible (fm,_) var = - let key = PdgIndex.Key.decl_var_key var in - key_visible "loc_var_visible" fm key + | Cil_types.Block _ -> (* block are always visible for syntactic reasons *) + true + | _ -> + let stmt_key = PdgIndex.Key.stmt_key stmt in + key_visible "inst_visible" fm stmt_key let fct_name v _fm = v.Cil_types.vname let result_visible kf fm_kf = try inst_visible fm_kf (Kernel_function.find_return kf) - with Kernel_function.No_Definition -> true + with Kernel_function.No_Statement -> true end module Info = Filter.F (BoolInfo) + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/cg_viewer.ml frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/cg_viewer.ml --- frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/cg_viewer.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/cg_viewer.ml 2011-10-10 08:38:30.000000000 +0000 @@ -55,16 +55,16 @@ (* itering on nodes of the current service *) List.iter (fun n -> - n#compute (); - if not (self#is_root n) then n#show (); - view#iter_succ_e - (fun e -> match self#edge_kind e with - | Service.Inter_functions | Service.Both -> - e#compute (); - e#show () - | Service.Inter_services -> - e#hide ()) - n) + n#compute (); + if not (self#is_root n) then n#show (); + view#iter_succ_e + (fun e -> match self#edge_kind e with + | Service.Inter_functions | Service.Both -> + e#compute (); + e#show () + | Service.Inter_services -> + e#hide ()) + n) !nodes method undeploy node = @@ -76,12 +76,12 @@ (* itering on nodes of the current service *) List.iter (fun n -> - if not (self#is_root n) then n#hide (); - view#iter_succ_e - (fun e -> match self#edge_kind e with - | Service.Inter_services | Service.Both -> e#show () - | Service.Inter_functions -> e#hide ()) - n) + if not (self#is_root n) then n#hide (); + view#iter_succ_e + (fun e -> match self#edge_kind e with + | Service.Inter_services | Service.Both -> e#show () + | Service.Inter_functions -> e#hide ()) + n) !nodes method service n = n#item.Service.root.Service.node.Callgraph.cnid @@ -97,11 +97,11 @@ let connect_trigger_to_node n = let callback = function | `BUTTON_PRESS _ -> - if self#is_deployed (self#service n) then self#undeploy n - else self#deploy n; - false + if self#is_deployed (self#service n) then self#undeploy n + else self#deploy n; + false | _ -> - false + false in n#connect_event ~callback in @@ -139,27 +139,27 @@ let width = int_of_float (float parent#default_width *. 3. /. 4.) in let window = GWindow.window - ~position:`CENTER - ~height ~width ~title:"Syntactic Callgraph" - ~allow_shrink:true ~allow_grow:true () + ~position:`CENTER + ~height ~width ~title:"Syntactic Callgraph" + ~allow_shrink:true ~allow_grow:true () in let _, view = View.from_graph_with_commands - ~packing:window#add - ~root:(Service.entry_point ()) - ~mk_global_view:services_view - graph + ~packing:window#add + ?root:(Service.entry_point ()) + ~mk_global_view:services_view + graph in window#show (); view#adapt_zoom () - with DGraphModel.DotError cmd -> - main_window#error "%s failed\n" cmd + with DGraphModel.DotError cmd -> main_window#error "%s\n" cmd let main (window: Design.main_window_extension_points) = ignore ((window#menu_manager ())#add_plugin - [ Menu_manager.Menubar(None, "Show callgraph"), - (fun () -> graph_window window) ]) + [ Menu_manager.menubar "Show callgraph" + (Menu_manager.Unit_callback (fun () -> graph_window window)); + ]) let () = Design.register_extension main diff -Nru frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/options.ml frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/options.ml --- frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/options.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/options.ml 2011-10-10 08:38:30.000000000 +0000 @@ -37,7 +37,7 @@ let arg_name = "filename" let help = "dump the syntactic stratified callgraph to the file \ <filename> in dot format" - let kind = `Tuning + let kind = Parameter.Other end) module InitFunc = @@ -46,7 +46,7 @@ let option_name = "-cg-init-func" let arg_name = "" let help = "use the given functions as a root service for the callgraph (you can add as many comma-separated functions as you want; if no function is declared, then root services are initialized with functions with no callers)" - let kind = `Correctness + let kind = Parameter.Correctness end) module ServicesOnly = @@ -54,7 +54,7 @@ (struct let option_name = "-cg-services-only" let help = "only computes the graph of services" - let kind = `Tuning + let kind = Parameter.Other end) (* diff -Nru frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/options.mli frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/options.mli --- frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/options.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/options.mli 2011-10-10 08:38:30.000000000 +0000 @@ -23,10 +23,10 @@ include Plugin.S val name: string -module Filename: Plugin.STRING -module InitFunc: Plugin.STRING_SET +module Filename: Plugin.String +module InitFunc: Plugin.String_set -module ServicesOnly: Plugin.BOOL +module ServicesOnly: Plugin.Bool (** @since Beryllium-20090901 *) (* diff -Nru frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/register.ml frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/register.ml --- frama-c-20110201+carbon+dfsg/src/syntactic_callgraph/register.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/syntactic_callgraph/register.ml 2011-10-10 08:38:30.000000000 +0000 @@ -25,7 +25,6 @@ open Callgraph open Options - let entry_point_ref = ref None module Service = @@ -41,11 +40,9 @@ [ match v.cnInfo with | NIVar (_,b) when not !b -> `Style `Dotted | _ -> `Style `Bold ] - let equal v1 v2 = id v1 = id v2 - let hash = id - let entry_point () = match !entry_point_ref with - | None -> assert false - | Some v -> v + let equal v1 v2 = id v1 = id v2 + let hash = id + let entry_point () = !entry_point_ref end let iter_vertex f = Hashtbl.iter (fun _ -> f) let iter_succ f _g v = Inthash.iter (fun _ -> f) v.cnCallees @@ -63,37 +60,42 @@ let kind = `Correctness end) -let get_init_funcs cg = - (* already checked that this entry point is ok *) - let entry_point_name = Parameters.MainFunction.get () in - let init_funcs = (* entry point is always a root *) - Datatype.String.Set.add entry_point_name (InitFunc.get ()) - in - (* Add the callees of entry point as roots *) - Datatype.String.Set.union - (try - let callees = (Hashtbl.find cg entry_point_name).Callgraph.cnCallees in - Inthash.fold - (fun _ v acc -> match v.Callgraph.cnInfo with - | Callgraph.NIVar ({vname=n},_) -> Datatype.String.Set.add n acc - | _ -> acc) - callees - Datatype.String.Set.empty - with Not_found -> - Datatype.String.Set.empty) - init_funcs +let get_init_funcs main_name cg = + match main_name with + | None -> InitFunc.get () + | Some s -> + (* the entry point is always a root *) + let init_funcs = Datatype.String.Set.add s (InitFunc.get ()) in + (* Add the callees of entry point as roots *) + Datatype.String.Set.union + (try + let callees = (Hashtbl.find cg s).Callgraph.cnCallees in + Inthash.fold + (fun _ v acc -> match v.Callgraph.cnInfo with + | Callgraph.NIVar ({vname=n},_) -> Datatype.String.Set.add n acc + | _ -> acc) + callees + Datatype.String.Set.empty + with Not_found -> + Datatype.String.Set.empty) + init_funcs let compute () = feedback "beginning analysis"; let p = Ast.get () in - (* fixes bts#587: check that Parameters.MainFunction.get is valid. *) - ignore (Globals.entry_point ()); let cg = computeGraph p in - entry_point_ref := - Some - (try Hashtbl.find cg (Parameters.MainFunction.get ()) - with Not_found -> assert false); - let init_funcs = get_init_funcs cg in + let main = Kernel.MainFunction.get () in + let main_name = + try + entry_point_ref := Some (Hashtbl.find cg main); + Some main + with Not_found -> + warning "no entry point available: services could be less precise. \ +Use option `-main' to improve them."; + entry_point_ref := None; + None + in + let init_funcs = get_init_funcs main_name cg in let cg = Service.compute cg init_funcs in CG.mark_as_computed (); feedback "analysis done"; @@ -145,6 +147,6 @@ (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/toplevel/toplevel_topdirs.ml frama-c-20111001+nitrogen+dfsg/src/toplevel/toplevel_topdirs.ml --- frama-c-20110201+carbon+dfsg/src/toplevel/toplevel_topdirs.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/toplevel/toplevel_topdirs.ml 2011-10-10 08:38:28.000000000 +0000 @@ -20,7 +20,7 @@ (* *) (**************************************************************************) -let top = +let top = let dir_bin = Filename.dirname Sys.executable_name in Filename.concat dir_bin ".." @@ -28,15 +28,14 @@ let abs_dir = Filename.concat top dir in Topdirs.dir_directory abs_dir -let src_dir = +let src_dir = [ "ai"; "buckx"; "constant_propagation"; "cxx_types"; "from"; "gui"; "impact"; "inout"; "jessie"; "journal"; "kernel"; "lib"; "logic"; "memory_state"; "misc"; "modular_dependencies"; "occurrence"; - "pdg"; "pdg_types"; "phantom"; "postdominators"; "project"; "scope"; - "security"; "semantic_callgraph"; "slicing"; "slicing_types"; "sparecode"; + "pdg"; "pdg_types"; "phantom"; "postdominators"; "project"; "scope"; + "security"; "semantic_callgraph"; "slicing"; "slicing_types"; "sparecode"; "toplevel"; "users"; "value"; "wp" ] -let () = +let () = List.iter (fun s -> add_top (Filename.concat "src" s)) src_dir; add_top "external" - diff -Nru frama-c-20110201+carbon+dfsg/src/type/datatype.ml frama-c-20111001+nitrogen+dfsg/src/type/datatype.ml --- frama-c-20110201+carbon+dfsg/src/type/datatype.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/datatype.ml 2011-10-10 08:38:09.000000000 +0000 @@ -70,22 +70,26 @@ module Infos = Type.Ty_tbl(struct type 'a t = 'a info end) let info_tbl = Infos.create 97 -let info ty = + +let internal_info s ty = try Infos.find info_tbl ty with Not_found -> - Format.eprintf "Internal Datatype.info error: no info for %S@." - (Type.name ty); + Format.eprintf "Internal Datatype.info error: no %s for %S@." + s (Type.name ty); assert false -let equal ty = (info ty).equal -let compare ty = (info ty).compare -let hash ty = (info ty).hash -let copy ty = (info ty).copy -let internal_pretty_code ty = (info ty).internal_pretty_code -let pretty_code ty = (info ty).pretty_code -let pretty ty = (info ty).pretty -let varname ty = (info ty).varname -let mem_project ty = (info ty).mem_project +let equal ty = (internal_info "equal" ty).equal +let compare ty = (internal_info "compare" ty).compare +let hash ty = (internal_info "hash" ty).hash +let copy ty = (internal_info "copy" ty).copy +let internal_pretty_code ty = + (internal_info "internal_pretty_code" ty).internal_pretty_code +let pretty_code ty = (internal_info "pretty_code" ty).pretty_code +let pretty ty = (internal_info "pretty" ty).pretty +let varname ty = (internal_info "varname" ty).varname +let mem_project ty = (internal_info "mem_project" ty).mem_project + +let info ty = internal_info "info" ty (* ********************************************************************** *) (** {2 Easy builders} *) @@ -145,18 +149,19 @@ let check f fname tname fstr = assert - (if f == undefined then begin + (if f == undefined && Type.may_use_obj () then begin Format.printf "@[Preliminary datatype check failed.@\n\ Value `%s' of type %s is required for building %s.@]@." - fname tname fstr; + fname tname fstr; false end else - true) + true) module Build (T: sig type t val ty: t Type.t + val reprs: t list val equal: t -> t -> bool val compare: t -> t -> int val hash: t -> int @@ -221,25 +226,27 @@ let mk_full_descr d = let descr = if rehash == undefined then - if Descr.is_unmarshable d then Descr.unmarshable - else begin - check rehash "rehash" name "descriptor"; - assert false - end + if Descr.is_unmarshable d then Descr.unmarshable + else begin + check rehash "rehash" name "descriptor"; + assert false + end else - if rehash == identity then d - else begin - if Descr.is_unmarshable d then begin - check undefined "structural_descr" name "descriptor"; - assert false - end; - Descr.transform d rehash - end + if rehash == identity then d + else + if Type.may_use_obj () then begin + if Descr.is_unmarshable d then begin + check undefined "structural_descr" name "descriptor"; + assert false + end; + Descr.transform d rehash + end else + Descr.unmarshable in descr, Descr.pack descr let descr, packed_descr = mk_full_descr (Descr.of_type T.ty) - let reprs = Type.reprs T.ty + let reprs = T.reprs (* [Type.reprs] is not usable in the "no-obj" mode *) end @@ -294,13 +301,14 @@ end module type Map = sig - include Map.S + include Map_common_interface.S module Key: S with type t = key module Make(Data: S) : S with type t = Data.t t end module type Hashtbl = sig include Hashtbl.S + val memo: 'a t -> key -> (key -> 'a) -> 'a module Key: S with type t = key module Make(Data: S) : S with type t = Data.t t end @@ -369,47 +377,53 @@ include T include Build (struct - include T - let build mk f1 f2 = - if mk == undefined || f1 == undefined || f2 == undefined then - undefined - else - mk f1 f2 - let compare = build P.mk_compare T1.compare T2.compare - let equal = build P.mk_equal T1.equal T2.equal - let hash = build P.mk_hash T1.hash T2.hash - let rehash = identity - let copy = - let mk f1 f2 = - if P.map == undefined then undefined - else if f1 == identity && f2 == identity then identity - else P.map f1 f2 - in - build mk T1.copy T2.copy - let internal_pretty_code = + include T + let reprs = + if Type.may_use_obj () then Type.reprs ty + else P.reprs (List.hd T1.reprs) (List.hd T2.reprs) + let build mk f1 f2 = + if mk == undefined || f1 == undefined || f2 == undefined then + undefined + else + mk f1 f2 + let compare = build P.mk_compare T1.compare T2.compare + let equal = build P.mk_equal T1.equal T2.equal + let hash = build P.mk_hash T1.hash T2.hash + let rehash = identity + let copy = + let mk f1 f2 = + if P.map == undefined then undefined + else + (* [JS 2011/05/31] No optimisation for the special case of identity, + since we really want to perform a DEEP copy. *) + (*if f1 == identity && f2 == identity then identity + else*) P.map f1 f2 + in + build mk T1.copy T2.copy + let internal_pretty_code = let mk f1 f2 = if f1 == pp_fail || f2 == pp_fail then pp_fail else fun p fmt x -> P.mk_internal_pretty_code f1 f2 p fmt x in - build mk T1.internal_pretty_code T2.internal_pretty_code - let pretty = build P.mk_pretty T1.pretty T2.pretty - let varname = build P.mk_varname T1.varname T2.varname - let mem_project = - let mk f1 f2 = - if P.mk_mem_project == undefined then undefined - else if f1 == never_any_project && f2 == never_any_project then - never_any_project - else - P.mk_mem_project f1 f2 - in - build mk T1.mem_project T2.mem_project + build mk T1.internal_pretty_code T2.internal_pretty_code + let pretty = build P.mk_pretty T1.pretty T2.pretty + let varname = build P.mk_varname T1.varname T2.varname + let mem_project = + let mk f1 f2 = + if P.mk_mem_project == undefined then undefined + else if f1 == never_any_project && f2 == never_any_project then + never_any_project + else + P.mk_mem_project f1 f2 + in + build mk T1.mem_project T2.mem_project end) let descr, packed_descr = mk_full_descr - (Descr.of_structural - ty - (P.structural_descr (Descr.str T1.descr) (Descr.str T2.descr))) + (Descr.of_structural + ty + (P.structural_descr (Descr.str T1.descr) (Descr.str T2.descr))) end @@ -434,7 +448,7 @@ let mk_internal_pretty_code f1 f2 p fmt (x1, x2) = let pp fmt = Format.fprintf - fmt "@[<hv 2>%a,@;%a@]" (f1 Type.Tuple) x1 (f2 Type.Tuple) x2 + fmt "@[<hv 2>%a,@;%a@]" (f1 Type.Tuple) x1 (f2 Type.Tuple) x2 in Type.par p Type.Tuple fmt pp let mk_pretty f1 f2 fmt p = @@ -449,9 +463,9 @@ let name ty1 ty2 = let arg ty = Type.par_ty_name - (fun ty -> - Type.Function.is_instance_of ty || Poly_pair.is_instance_of ty) - ty + (fun ty -> + Type.Function.is_instance_of ty || Poly_pair.is_instance_of ty) + ty in arg ty1 ^ " * " ^ arg ty2 end @@ -510,6 +524,8 @@ let pretty = undefined let varname _ = "f" let mem_project = never_any_project + let reprs = + if Type.may_use_obj () then Type.reprs ty else [ fun _ -> assert false ] end include T include Build(T) @@ -566,39 +582,46 @@ include Build (struct - include T - let build mk f = - if mk == undefined || f == undefined then undefined else mk f - let compare = build P.mk_compare X.compare - let equal = build P.mk_equal X.equal - let hash = build P.mk_hash X.hash - let copy = - let mk f = - if P.map == undefined then undefined - else if f == identity then identity else fun x -> P.map f x - in - build mk X.copy - let rehash = identity - let internal_pretty_code = + include T + let build mk f = + if mk == undefined || f == undefined then undefined else mk f + let compare = build P.mk_compare X.compare + let equal = build P.mk_equal X.equal + let hash = build P.mk_hash X.hash + let copy = + let mk f = + if P.map == undefined then undefined + else + (* [JS 2011/05/31] No optimisation for the special case of + identity, since we really want to perform a DEEP copy. *) + (*if f == identity then identity else*) + fun x -> P.map f x + in + build mk X.copy + let rehash = identity + let internal_pretty_code = let mk f = if f == pp_fail then pp_fail else fun p fmt x -> P.mk_internal_pretty_code f p fmt x in - build mk X.internal_pretty_code - let pretty = build P.mk_pretty X.pretty - let varname = build P.mk_varname X.varname - let mem_project = - let mk f = - if P.mk_mem_project == undefined then undefined - else if f == never_any_project then never_any_project - else fun p x -> P.mk_mem_project f p x - in - build mk X.mem_project + build mk X.internal_pretty_code + let pretty = build P.mk_pretty X.pretty + let varname = build P.mk_varname X.varname + let mem_project = + let mk f = + if P.mk_mem_project == undefined then undefined + else if f == never_any_project then never_any_project + else fun p x -> P.mk_mem_project f p x + in + build mk X.mem_project + let reprs = + if Type.may_use_obj () then Type.reprs ty + else P.reprs (List.hd X.reprs) end) let descr, packed_descr = mk_full_descr - (Descr.of_structural ty (P.structural_descr (Descr.str X.descr))) + (Descr.of_structural ty (P.structural_descr (Descr.str X.descr))) end @@ -621,10 +644,10 @@ let mk_hash f x = f !x let map f x = ref (f !x) let mk_internal_pretty_code f p fmt x = - let pp fmt = Format.fprintf fmt "@[<hv 2>ref@;%a@]" (f Type.Call) !x in - Type.par p Type.Call fmt pp + let pp fmt = Format.fprintf fmt "@[<hv 2>ref@;%a@]" (f Type.Call) !x in + Type.par p Type.Call fmt pp let mk_pretty f fmt x = - mk_internal_pretty_code (fun _ -> f) Type.Basic fmt x + mk_internal_pretty_code (fun _ -> f) Type.Basic fmt x let mk_varname = undefined let mk_mem_project mem f x = mem f !x end) @@ -645,27 +668,27 @@ let reprs ty = [ Some ty ] let structural_descr = Structural_descr.t_option let mk_equal f x y = match x, y with - | None, None -> true - | None, Some _ | Some _, None -> false - | Some x, Some y -> f x y + | None, None -> true + | None, Some _ | Some _, None -> false + | Some x, Some y -> f x y let mk_compare f x y = - if x == y then 0 - else match x, y with - | None, None -> 0 - | None, Some _ -> 1 - | Some _, None -> -1 - | Some x, Some y -> f x y + if x == y then 0 + else match x, y with + | None, None -> 0 + | None, Some _ -> 1 + | Some _, None -> -1 + | Some x, Some y -> f x y let mk_hash f = function None -> 0 | Some x -> f x let map f = function None -> None | Some x -> Some (f x) let mk_internal_pretty_code f p fmt = function - | None -> Format.fprintf fmt "None" - | Some x -> - let pp fmt = - Format.fprintf fmt "@[<hv 2>Some@;%a@]" (f Type.Call) x - in - Type.par p Type.Call fmt pp + | None -> Format.fprintf fmt "None" + | Some x -> + let pp fmt = + Format.fprintf fmt "@[<hv 2>Some@;%a@]" (f Type.Call) x + in + Type.par p Type.Call fmt pp let mk_pretty f fmt x = - mk_internal_pretty_code (fun _ -> f) Type.Basic fmt x + mk_internal_pretty_code (fun _ -> f) Type.Basic fmt x let mk_varname = undefined let mk_mem_project mem f = function None -> false | Some x -> mem f x end) @@ -686,32 +709,32 @@ let reprs ty = [ [ ty ] ] let structural_descr = Structural_descr.t_list let mk_equal f l1 l2 = - try List.for_all2 f l1 l2 with Invalid_argument _ -> false + try List.for_all2 f l1 l2 with Invalid_argument _ -> false let rec mk_compare f l1 l2 = - if l1 == l2 then 0 - else match l1, l2 with - | [], [] -> assert false - | [], _ :: _ -> -1 - | _ :: _, [] -> 1 - | x1 :: q1, x2 :: q2 -> - let n = f x1 x2 in - if n = 0 then mk_compare f q1 q2 else n + if l1 == l2 then 0 + else match l1, l2 with + | [], [] -> assert false + | [], _ :: _ -> -1 + | _ :: _, [] -> 1 + | x1 :: q1, x2 :: q2 -> + let n = f x1 x2 in + if n = 0 then mk_compare f q1 q2 else n let mk_hash f = List.fold_left (fun acc d -> 257 * acc + f d) 1 let map = List.map let mk_internal_pretty_code f p fmt l = - let pp fmt = - Format.fprintf fmt "@[<hv 2>[ %t ]@]" - (fun fmt -> - let rec print fmt = function - | [] -> () - | [ x ] -> Format.fprintf fmt "%a" (f Type.List) x - | x :: l -> Format.fprintf fmt "%a;@;%a" (f Type.List) x print l - in - print fmt l) - in - Type.par p Type.Basic fmt pp (* Never enclose lists in parentheses *) + let pp fmt = + Format.fprintf fmt "@[<hv 2>[ %t ]@]" + (fun fmt -> + let rec print fmt = function + | [] -> () + | [ x ] -> Format.fprintf fmt "%a" (f Type.List) x + | x :: l -> Format.fprintf fmt "%a;@;%a" (f Type.List) x print l + in + print fmt l) + in + Type.par p Type.Basic fmt pp (* Never enclose lists in parentheses *) let mk_pretty f fmt x = - mk_internal_pretty_code (fun _ -> f) Type.Basic fmt x + mk_internal_pretty_code (fun _ -> f) Type.Basic fmt x let mk_varname = undefined let mk_mem_project mem f = List.exists (mem f) end) @@ -760,9 +783,9 @@ let name ty = Type.par_ty_name is_function_or_pair ty ^ " Queue.t" let module_name = "Datatype.Queue" let reprs x = - let q = Queue.create () in - Queue.add x q; - [ q ] + let q = Queue.create () in + Queue.add x q; + [ q ] let structural_descr = Structural_descr.t_queue let mk_equal = undefined let mk_compare = undefined @@ -772,8 +795,8 @@ let mk_pretty = undefined let mk_varname = undefined let mk_mem_project mem f q = - try Queue.iter (fun x -> if mem f x then raise Exit) q; false - with Exit -> true + try Queue.iter (fun x -> if mem f x then raise Exit) q; false + with Exit -> true end) module Queue = Poly_queue.Make @@ -798,44 +821,45 @@ type t = S.t let name = Info.module_name ^ "(" ^ E.name ^ ")" let structural_descr = - Structural_descr.t_set_unchanged_compares (Descr.str E.descr) + Structural_descr.t_set_unchanged_compares (Descr.str E.descr) open S - let reprs = - empty :: Caml_list.map (fun r -> singleton r) (Type.reprs E.ty) + let reprs = empty :: Caml_list.map (fun r -> singleton r) E.reprs let compare = S.compare let equal = S.equal let hash = Hashtbl.hash (* Don't know how to do better *) let rehash = identity let copy = - if E.copy == identity then identity - else fun s -> S.fold (fun x -> S.add (E.copy x)) s S.empty + (* [JS 2011/05/31] No optimisation for the special case of + identity, since we really want to perform a DEEP copy. *) +(* if E.copy == identity then identity + else*) fun s -> S.fold (fun x -> S.add (E.copy x)) s S.empty let internal_pretty_code p_caller fmt s = - if is_empty s then - Format.fprintf fmt "%s.empty" Info.module_name - else - let pp fmt = - if S.cardinal s = 1 then - Format.fprintf fmt "@[<hv 2>%s.singleton@;%a@]" - Info.module_name - (E.internal_pretty_code Type.Call) - (Caml_list.hd (S.elements s)) - else - Format.fprintf fmt - "@[<hv 2>List.fold_left@;\ + if is_empty s then + Format.fprintf fmt "%s.empty" Info.module_name + else + let pp fmt = + if S.cardinal s = 1 then + Format.fprintf fmt "@[<hv 2>%s.singleton@;%a@]" + Info.module_name + (E.internal_pretty_code Type.Call) + (Caml_list.hd (S.elements s)) + else + Format.fprintf fmt + "@[<hv 2>List.fold_left@;\ (fun acc s -> %s.add s acc)@;%s.empty@;%a@]" - Info.module_name - Info.module_name - (let module L = List(E) in L.internal_pretty_code Type.Call) - (S.elements s) - in - Type.par p_caller Type.Call fmt pp + Info.module_name + Info.module_name + (let module L = List(E) in L.internal_pretty_code Type.Call) + (S.elements s) + in + Type.par p_caller Type.Call fmt pp let pretty = from_pretty_code let varname = undefined let mem_project p s = - try S.iter (fun x -> if E.mem_project p x then raise Exit) s; false - with Exit -> true + try S.iter (fun x -> if E.mem_project p x then raise Exit) s; false + with Exit -> true end) include S @@ -860,9 +884,8 @@ (** {3 Map} *) (* ****************************************************************************) -module Initial_caml_map = Map - -module Map(M: Map.S)(Key: S with type t = M.key)(Info: Functor_info) = struct +module Map(M: Map_common_interface.S) + (Key: S with type t = M.key)(Info: Functor_info) = struct let () = check Key.equal "equal" Key.name Info.module_name let () = check Key.compare "compare" Key.name Info.module_name @@ -871,44 +894,67 @@ (struct type 'a t = 'a M.t let name ty = - Info.module_name ^ "(" ^ Key.name ^ ", " ^ Type.name ty ^ ")" + Info.module_name ^ "(" ^ Key.name ^ ", " ^ Type.name ty ^ ")" let structural_descr d = - Structural_descr.t_map_unchanged_compares (Descr.str Key.descr) d + Structural_descr.t_map_unchanged_compares (Descr.str Key.descr) d let module_name = Info.module_name open M let reprs r = - [ Caml_list.fold_left (fun m k -> add k r m) empty Key.reprs ] + [ Caml_list.fold_left (fun m k -> add k r m) empty Key.reprs ] let mk_compare = M.compare let mk_equal = M.equal let mk_hash = undefined let map = M.map let mk_internal_pretty_code = undefined + (*f_value p_caller fmt map = + (* [JS 2011/04/01] untested code! *) + let pp_empty fmt = Format.fprintf fmt "%s.empty" Info.module_name in + if M.is_empty map then + Type.par p_caller Type.Basic fmt pp_empty + else + let pp fmt = + Format.fprintf + fmt "@[<hv 2>@[<hv 2>let map =@;%t@;<1 -2>in@]" pp_empty; + M.iter + (fun k v -> + Format.fprintf + fmt + "@[<hv 2>let map =@;%s.add@;@[<hv 2>map@;%a@;%a@]@;<1 -2>in@]" + Info.module_name + (Key.internal_pretty_code Type.Call) k + (f_value Type.Call) v) + map; + Format.fprintf fmt "@[map@]@]" + in + Type.par p_caller Type.Call fmt pp*) let mk_pretty f_value fmt map = - Format.fprintf fmt "@[{{ "; - M.iter - (fun k v -> + Format.fprintf fmt "@[{{ "; + M.iter + (fun k v -> Format.fprintf fmt "@[@[%a@] -> @[%a@]@];@ " - Key.pretty k - f_value v) - map; - Format.fprintf fmt " }}@]" - let mk_varname = undefined + Key.pretty k + f_value v) + map; + Format.fprintf fmt " }}@]" + let mk_varname _ = + if Key.varname == undefined then undefined + else fun _ -> Format.sprintf "%s_map" Key.name let mk_mem_project = - if Key.mem_project == undefined then undefined - else - fun mem -> - if mem == never_any_project && Key.mem_project == never_any_project - then never_any_project - else - fun p m -> - try - M.iter - (fun k v -> - if Key.mem_project p k || mem p v then raise Exit) - m; - false - with Exit -> - true + if Key.mem_project == undefined then undefined + else + fun mem -> + if mem == never_any_project && Key.mem_project == never_any_project + then never_any_project + else + fun p m -> + try + M.iter + (fun k v -> + if Key.mem_project p k || mem p v then raise Exit) + m; + false + with Exit -> + true end) include M @@ -934,14 +980,14 @@ (struct type 'a t = 'a H.t let name ty = - Info.module_name ^ "(" ^ Key.name ^ ", " ^ Type.name ty ^ ")" + Info.module_name ^ "(" ^ Key.name ^ ", " ^ Type.name ty ^ ")" let module_name = Info.module_name let structural_descr d = - Structural_descr.t_hashtbl_unchanged_hashs (Descr.str Key.descr) d + Structural_descr.t_hashtbl_unchanged_hashs (Descr.str Key.descr) d open Hashtbl let reprs x = - [ let h = H.create 7 in - Caml_list.iter (fun k -> H.add h k x) Key.reprs; h ] + [ let h = H.create 7 in + Caml_list.iter (fun k -> H.add h k x) Key.reprs; h ] let mk_compare = undefined let mk_equal = from_compare let mk_hash = undefined @@ -958,24 +1004,32 @@ let mk_pretty = from_pretty_code let mk_varname = undefined let mk_mem_project = - if Key.mem_project == undefined then undefined - else - fun mem -> - if mem == never_any_project && Key.mem_project == never_any_project - then never_any_project - else - fun p m -> - try - H.iter - (fun k v -> - if Key.mem_project p k || mem p v then raise Exit) - m; - false - with Exit -> - true + if Key.mem_project == undefined then undefined + else + fun mem -> + if mem == never_any_project && Key.mem_project == never_any_project + then never_any_project + else + fun p m -> + try + H.iter + (fun k v -> + if Key.mem_project p k || mem p v then raise Exit) + m; + false + with Exit -> + true end) include H + + let memo tbl k f = + try find tbl k + with Not_found -> + let v = f k in + add tbl k v; + v + module Key = Key module Make = P.Make @@ -1030,7 +1084,7 @@ module Map = Map - (Initial_caml_map.Make(D)) + (Map_common_interface.Make(D)) (D) (struct let module_name = Info.module_name ^ ".Map" end) @@ -1248,14 +1302,13 @@ module Big_int = Make_with_collections (struct - open Big_int - type t = big_int + type t = My_bigint.t let name = "Datatype.Big_int" - let reprs = [ zero_big_int ] + let reprs = [ My_bigint.zero ] let structural_descr = Structural_descr.Abstract - let equal = eq_big_int - let compare = compare_big_int - let hash = Initial_caml_hashtbl.hash + let equal = My_bigint.equal + let compare = My_bigint.compare + let hash = My_bigint.hash let rehash = identity let copy = identity let internal_pretty_code par fmt n = @@ -1263,10 +1316,10 @@ Format.fprintf fmt "Big_int.big_int_of_string %S" - (Big_int.string_of_big_int n) + (My_bigint.to_string n) in Type.par par Type.Call fmt pp - let pretty fmt n = Format.fprintf fmt "%s" (Big_int.string_of_big_int n) + let pretty = My_bigint.pretty ~hexa:false let varname _ = "big_n" let mem_project = never_any_project end) @@ -1278,81 +1331,81 @@ type t = T1.t * T2.t * T3.t let name = "(" ^ T1.name ^ ", " ^ T2.name ^ ", " ^ T3.name ^ ")" let reprs = - Caml_list.fold_left - (fun acc x1 -> - Caml_list.fold_left - (fun acc x2 -> - Caml_list.fold_left - (fun acc x3 -> (x1, x2, x3) :: acc) - acc - T3.reprs) - acc - T2.reprs) - [] - T1.reprs + Caml_list.fold_left + (fun acc x1 -> + Caml_list.fold_left + (fun acc x2 -> + Caml_list.fold_left + (fun acc x3 -> (x1, x2, x3) :: acc) + acc + T3.reprs) + acc + T2.reprs) + [] + T1.reprs let structural_descr = - Structural_descr.t_tuple - [| T1.packed_descr; T2.packed_descr; T3.packed_descr |] + Structural_descr.t_tuple + [| T1.packed_descr; T2.packed_descr; T3.packed_descr |] let equal = - if T1.equal == undefined - || T2.equal == undefined - || T3.equal == undefined - then undefined - else - fun (x1, x2, x3) (y1, y2, y3) -> - T1.equal x1 y1 && T2.equal x2 y2 && T3.equal x3 y3 + if T1.equal == undefined + || T2.equal == undefined + || T3.equal == undefined + then undefined + else + fun (x1, x2, x3) (y1, y2, y3) -> + T1.equal x1 y1 && T2.equal x2 y2 && T3.equal x3 y3 let compare = - if T1.compare == undefined - || T2.compare == undefined - || T3.compare == undefined - then undefined - else - fun (x1, x2, x3 as x) (y1, y2, y3 as y) -> - if x == y then 0 - else - let n = T1.compare x1 y1 in - if n = 0 then - let n = T2.compare x2 y2 in - if n = 0 then T3.compare x3 y3 else n - else n + if T1.compare == undefined + || T2.compare == undefined + || T3.compare == undefined + then undefined + else + fun (x1, x2, x3 as x) (y1, y2, y3 as y) -> + if x == y then 0 + else + let n = T1.compare x1 y1 in + if n = 0 then + let n = T2.compare x2 y2 in + if n = 0 then T3.compare x3 y3 else n + else n let hash = - if T1.hash == undefined || T2.hash == undefined || T3.hash == undefined - then undefined - else - fun (x1, x2, x3) -> - Initial_caml_hashtbl.hash (T1.hash x1, T2.hash x2, T3.hash x3) + if T1.hash == undefined || T2.hash == undefined || T3.hash == undefined + then undefined + else + fun (x1, x2, x3) -> + Initial_caml_hashtbl.hash (T1.hash x1, T2.hash x2, T3.hash x3) let copy = - if T1.copy == undefined || T2.copy == undefined || T3.copy == undefined - then undefined - else fun (x1, x2, x3) -> T1.copy x1, T2.copy x2, T3.copy x3 + if T1.copy == undefined || T2.copy == undefined || T3.copy == undefined + then undefined + else fun (x1, x2, x3) -> T1.copy x1, T2.copy x2, T3.copy x3 let rehash = identity let varname = undefined let mem_project = - if T1.mem_project == undefined - || T2.mem_project == undefined - || T3.mem_project == undefined - then undefined - else - if T1.mem_project == never_any_project - && T2.mem_project == never_any_project - && T3.mem_project == never_any_project - then never_any_project - else - fun f (x1, x2, x3) -> - T1.mem_project f x1 && T2.mem_project f x2 && T3.mem_project f x3 - let pretty = undefined + if T1.mem_project == undefined + || T2.mem_project == undefined + || T3.mem_project == undefined + then undefined + else + if T1.mem_project == never_any_project + && T2.mem_project == never_any_project + && T3.mem_project == never_any_project + then never_any_project + else + fun f (x1, x2, x3) -> + T1.mem_project f x1 && T2.mem_project f x2 && T3.mem_project f x3 + let pretty = from_pretty_code let internal_pretty_code = - if T1.internal_pretty_code == undefined - || T2.internal_pretty_code == undefined - || T3.internal_pretty_code == undefined - then undefined - else - if T1.internal_pretty_code == pp_fail - || T2.internal_pretty_code == pp_fail - || T3.internal_pretty_code == pp_fail - then pp_fail - else - fun par fmt (x1, x2, x3) -> + if T1.internal_pretty_code == undefined + || T2.internal_pretty_code == undefined + || T3.internal_pretty_code == undefined + then undefined + else + if T1.internal_pretty_code == pp_fail + || T2.internal_pretty_code == pp_fail + || T3.internal_pretty_code == pp_fail + then pp_fail + else + fun par fmt (x1, x2, x3) -> let pp fmt = Format.fprintf fmt @@ -1364,8 +1417,127 @@ Type.par par Type.Tuple fmt pp end) -module Triple_with_collections(T1: S)(T2: S)(T3: S)(Info:Functor_info) = - Generic_make_with_collections(Triple(T1)(T2)(T3))(Info) +module Quadruple(T1: S)(T2: S)(T3: S)(T4:S) = + Make + (struct + type t = T1.t * T2.t * T3.t * T4.t + let name = + Printf.sprintf "(%s, %s, %s, %s)" + T1.name T2.name T3.name T4.name + let reprs = + Caml_list.fold_left + (fun acc x1 -> + Caml_list.fold_left + (fun acc x2 -> + Caml_list.fold_left + (fun acc x3 -> + Caml_list.fold_left + (fun acc x4 -> + (x1, x2, x3, x4) :: acc) + acc + T4.reprs) + acc + T3.reprs) + acc + T2.reprs) + [] + T1.reprs + let structural_descr = + Structural_descr.t_tuple + [| T1.packed_descr; T2.packed_descr; T3.packed_descr; + T4.packed_descr |] + let equal = + if T1.equal == undefined + || T2.equal == undefined + || T3.equal == undefined + || T4.equal == undefined + then undefined + else + fun (x1, x2, x3, x4) (y1, y2, y3, y4) -> + T1.equal x1 y1 && T2.equal x2 y2 && T3.equal x3 y3 && T4.equal x4 y4 + let compare = + if T1.compare == undefined + || T2.compare == undefined + || T3.compare == undefined + || T4.compare == undefined + then undefined + else + fun (x1, x2, x3, x4 as x) (y1, y2, y3, y4 as y) -> + if x == y then 0 + else + let n = T1.compare x1 y1 in + if n = 0 then + let n = T2.compare x2 y2 in + if n = 0 then + let n = T3.compare x3 y3 in + if n = 0 then T4.compare x4 y4 + else n + else n + else n + let hash = + if T1.hash == undefined + || T2.hash == undefined + || T3.hash == undefined + || T4.hash == undefined + then undefined + else + fun (x1, x2, x3, x4) -> + Initial_caml_hashtbl.hash + (T1.hash x1, T2.hash x2, T3.hash x3, T4.hash x4) + let copy = + if T1.copy == undefined + || T2.copy == undefined + || T3.copy == undefined + || T4.copy == undefined + then undefined + else fun (x1, x2, x3,x4) -> + T1.copy x1, T2.copy x2, T3.copy x3, T4.copy x4 + let rehash = identity + let varname = undefined + let mem_project = + if T1.mem_project == undefined + || T2.mem_project == undefined + || T3.mem_project == undefined + || T4.mem_project == undefined + then undefined + else + if T1.mem_project == never_any_project + && T2.mem_project == never_any_project + && T3.mem_project == never_any_project + && T4.mem_project == never_any_project + then never_any_project + else + fun f (x1, x2, x3, x4) -> + T1.mem_project f x1 + && T2.mem_project f x2 + && T3.mem_project f x3 + && T4.mem_project f x4 + let pretty = from_pretty_code + let internal_pretty_code = + if T1.internal_pretty_code == undefined + || T2.internal_pretty_code == undefined + || T3.internal_pretty_code == undefined + || T4.internal_pretty_code == undefined + then undefined + else + if T1.internal_pretty_code == pp_fail + || T2.internal_pretty_code == pp_fail + || T3.internal_pretty_code == pp_fail + || T4.internal_pretty_code == pp_fail + then pp_fail + else + fun par fmt (x1, x2, x3, x4) -> + let pp fmt = + Format.fprintf + fmt + "%a, %a, %a, %a" + (T1.internal_pretty_code Type.Tuple) x1 + (T2.internal_pretty_code Type.Tuple) x2 + (T3.internal_pretty_code Type.Tuple) x3 + (T4.internal_pretty_code Type.Tuple) x4 + in + Type.par par Type.Tuple fmt pp + end) module Pair_with_collections(T1: S)(T2: S)(Info:Functor_info) = Generic_make_with_collections @@ -1375,6 +1547,15 @@ end) (Info) +module Triple_with_collections(T1: S)(T2: S)(T3: S)(Info:Functor_info) = + Generic_make_with_collections(Triple(T1)(T2)(T3))(Info) + +module Quadruple_with_collections(T1:S)(T2:S)(T3:S)(T4:S)(Info:Functor_info) = + Generic_make_with_collections(Quadruple(T1)(T2)(T3)(T4))(Info) + +module Option_with_collections(T:S)(Info:Functor_info) = + Generic_make_with_collections (Option(T))(Info) + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/type/datatype.mli frama-c-20111001+nitrogen+dfsg/src/type/datatype.mli --- frama-c-20110201+carbon+dfsg/src/type/datatype.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/datatype.mli 2011-10-10 08:38:09.000000000 +0000 @@ -189,8 +189,8 @@ val rehash: t -> t (** How to rehashconsed values. Must be {!identity} if you does not use - hashconsing. Only useful for unmarshaling (use {!undefined for - unmarshable type}). *) + hashconsing. Only useful for unmarshaling (use {!undefined} for + unmarshable type). *) (** All the above operations have the same semantics than the corresponding value specified in module type {!S}. *) @@ -238,7 +238,7 @@ (** A standard OCaml map signature extended with datatype operations. *) module type Map = sig - include Map.S + include Map_common_interface.S module Key: S with type t = key (** Datatype for the keys of the map. *) @@ -254,6 +254,12 @@ include Hashtbl.S + val memo: 'a t -> key -> (key -> 'a) -> 'a + (** [memo tbl k f] returns the binding of [k] in [tbl]. If there is + no binding, add the binding [f k] associated to [k] in [tbl] and return + it. + @since Nitrogen-20111001 *) + module Key: S with type t = key (** Datatype for the keys of the hashtbl. *) @@ -311,7 +317,7 @@ module Formatter: S with type t = Format.formatter val formatter: Format.formatter Type.t -module Big_int: S_with_collections with type t = Big_int.big_int +module Big_int: S_with_collections with type t = My_bigint.t val big_int: Big_int.t Type.t (* ****************************************************************************) @@ -393,6 +399,11 @@ module Poly_option: Polymorphic with type 'a poly = 'a option module Option(T: S) : S with type t = T.t option + +(** @since Nitrogen-20111001 *) +module Option_with_collections(T:S)(Info: Functor_info): + S_with_collections with type t = T.t option + val option: 'a Type.t -> 'a option Type.t module Poly_list: Polymorphic with type 'a poly = 'a list @@ -407,6 +418,14 @@ module Triple_with_collections(T1: S)(T2: S)(T3: S)(Info: Functor_info): S_with_collections with type t = T1.t * T2.t * T3.t +(** @since Nitrogen-20111001 *) +module Quadruple(T1: S)(T2: S)(T3: S)(T4:S): + S with type t = T1.t * T2.t * T3.t * T4.t +(** @since Nitrogen-20111001 *) +module Quadruple_with_collections + (T1: S)(T2: S)(T3: S)(T4:S)(Info: Functor_info): + S_with_collections with type t = T1.t * T2.t * T3.t * T4.t + module Function (T1: sig include S val label: (string * (unit -> t) option) option end) (T2: S) @@ -446,7 +465,7 @@ module Set(S: Set.S)(E: S with type t = S.elt)(Info : Functor_info): Set with type t = S.t and type elt = E.t -module Map(M: Map.S)(Key: S with type t = M.key)(Info: Functor_info) : +module Map(M: Map_common_interface.S)(Key: S with type t = M.key)(Info: Functor_info) : Map with type 'a t = 'a M.t and type key = M.key and module Key = Key module Hashtbl(H: Hashtbl.S)(Key: S with type t = H.key)(Info : Functor_info): diff -Nru frama-c-20110201+carbon+dfsg/src/type/descr.ml frama-c-20111001+nitrogen+dfsg/src/type/descr.ml --- frama-c-20110201+carbon+dfsg/src/type/descr.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/descr.ml 2011-10-10 08:38:09.000000000 +0000 @@ -30,6 +30,8 @@ let coerce d = (d : single_pack :> Unmarshal.t) +let uncheck_pack d = try unsafe_pack d with Cannot_pack -> assert false + (* ********************************************************************** *) (** {2 Predefined type descriptors} *) (* ********************************************************************** *) @@ -37,14 +39,14 @@ let unmarshable = pack Unknown let is_unmarshable x = x = unmarshable -let t_unit = unsafe_pack Unmarshal.t_unit -let t_int = unsafe_pack Unmarshal.t_int -let t_string = unsafe_pack Unmarshal.t_string -let t_float = unsafe_pack Unmarshal.t_float -let t_bool = unsafe_pack Unmarshal.t_bool -let t_int32 = unsafe_pack Unmarshal.t_int32 -let t_int64 = unsafe_pack Unmarshal.t_int64 -let t_nativeint = unsafe_pack Unmarshal.t_nativeint +let t_unit = uncheck_pack Unmarshal.t_unit +let t_int = uncheck_pack Unmarshal.t_int +let t_string = uncheck_pack Unmarshal.t_string +let t_float = uncheck_pack Unmarshal.t_float +let t_bool = uncheck_pack Unmarshal.t_bool +let t_int32 = uncheck_pack Unmarshal.t_int32 +let t_int64 = uncheck_pack Unmarshal.t_int64 +let t_nativeint = uncheck_pack Unmarshal.t_nativeint (* ********************************************************************** *) (** {2 Type descriptor builders} *) @@ -58,10 +60,10 @@ try let x = Array.map - (fun x -> match x with - | Nopack | Recursive _ -> raise Invalid_descriptor - | Pack x -> coerce x) - x + (fun x -> match x with + | Nopack | Recursive _ -> raise Invalid_descriptor + | Pack x -> coerce x) + x in unsafe_pack (Unmarshal.t_record x) with Cannot_pack -> @@ -70,12 +72,12 @@ let t_tuple = t_record let t_pair x y = match x, y with | (Nopack | Recursive _), _ | _, (Nopack | Recursive _) -> unmarshable - | Pack x, Pack y -> unsafe_pack (Unmarshal.t_tuple [| coerce x; coerce y |]) + | Pack x, Pack y -> uncheck_pack (Unmarshal.t_tuple [| coerce x; coerce y |]) let t_poly f = function | Nopack -> unmarshable | Recursive _ -> raise Invalid_descriptor - | Pack x -> unsafe_pack (f (coerce x)) + | Pack x -> uncheck_pack (f (coerce x)) let t_list = t_poly Unmarshal.t_list let t_ref = t_poly Unmarshal.t_ref @@ -86,7 +88,9 @@ let of_type ty = pack (Type.structural_descr ty) let of_structural ty d = - if Structural_descr.are_consistent (Type.structural_descr ty) d then + if not (Type.may_use_obj ()) || + Structural_descr.are_consistent (Type.structural_descr ty) d + then pack d else invalid_arg "Descr.of_structural: inconsistent descriptor" @@ -101,20 +105,20 @@ | Nopack | Recursive _ -> raise Invalid_descriptor | Pack b -> coerce b in - unsafe_pack (Unmarshal.Structure (Unmarshal.Dependent_pair (coerce a, f))) + uncheck_pack (Unmarshal.Structure (Unmarshal.Dependent_pair (coerce a, f))) let return d f = match d with | Nopack -> unmarshable | Recursive _ -> raise Invalid_descriptor | Pack d -> - unsafe_pack (Unmarshal.Return(coerce d, (fun x -> Obj.repr (f x)))) + uncheck_pack (Unmarshal.Return(coerce d, (fun x -> Obj.repr (f x)))) let dynamic f = let f () = match f () with | Nopack | Recursive _ -> raise Invalid_descriptor | Pack y -> coerce y in - unsafe_pack (Unmarshal.Dynamic f) + uncheck_pack (Unmarshal.Dynamic f) module Unmarshal_tbl = Hashtbl.Make @@ -131,10 +135,10 @@ let l = ref [] in Array.iter (fun a -> - Array.iteri - (fun i y -> - if x == y then l := (a, i) :: !l else transform_unmarshal term x y) - a) + Array.iteri + (fun i y -> + if x == y then l := (a, i) :: !l else transform_unmarshal term x y) + a) arr; List.iter (fun (a, i) -> a.(i) <- term) !l | Unmarshal.Dependent_pair(d, _) | Unmarshal.Array d -> @@ -162,7 +166,7 @@ let term = Unmarshal.Transform(d, fun x -> Obj.repr (f (Obj.obj x))) in transform_unmarshal term d d; Unmarshal_tbl.clear visited; - unsafe_pack term + uncheck_pack term (* ********************************************************************** *) (** {2 Coercions} *) diff -Nru frama-c-20110201+carbon+dfsg/src/type/structural_descr.ml frama-c-20111001+nitrogen+dfsg/src/type/structural_descr.ml --- frama-c-20110201+carbon+dfsg/src/type/structural_descr.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/structural_descr.ml 2011-10-10 08:38:09.000000000 +0000 @@ -35,14 +35,6 @@ (** {2 Injection into Unmarshal} *) (* ********************************************************************** *) -module Unmarshal_tbl = - Hashtbl.Make - (struct - type t = Unmarshal.t - let equal = (==) - let hash = Hashtbl.hash - end) - module Recursive = struct let create () = ref Unknown @@ -53,9 +45,9 @@ module Tbl = Hashtbl.Make (struct - type t = recursive - let equal = (==) - let hash = Hashtbl.hash + type t = recursive + let equal = (==) + let hash = Hashtbl.hash end) let positions = Tbl.create 7 @@ -115,6 +107,8 @@ | Unmarshal.Transform _ | Unmarshal.Return _ | Unmarshal.Dynamic _ -> assert false (* not structural *) +let recursive_pack r = Recursive r + (* ********************************************************************** *) (** {2 Predefined values} *) (* ********************************************************************** *) @@ -173,6 +167,14 @@ (* {3 cleanup} *) (* ********************************************************************** *) +module Unmarshal_tbl = + Hashtbl.Make + (struct + type t = Unmarshal.t + let equal = (==) + let hash = Hashtbl.hash + end) + let unmarshal_visited = Unmarshal_tbl.create 7 module Tbl = @@ -246,11 +248,11 @@ | Unmarshal.Sum arr1, Unmarshal.Sum arr2 -> (try for i = 0 to Array.length arr1 - 1 do - let arr1_i = arr1.(i) in - for j = 0 to Array.length arr1_i - 1 do - if not (are_consistent_unmarshal arr1_i.(j) arr2.(i).(j)) then - raise Exit - done + let arr1_i = arr1.(i) in + for j = 0 to Array.length arr1_i - 1 do + if not (are_consistent_unmarshal arr1_i.(j) arr2.(i).(j)) then + raise Exit + done done; true with Invalid_argument _ | Exit -> @@ -294,10 +296,10 @@ | Sum arr1, Sum arr2 -> (try for i = 0 to Array.length arr1 - 1 do - let arr1_i = arr1.(i) in - for j = 0 to Array.length arr1_i - 1 do - if not (are_consistent_pack arr1_i.(j) arr2.(i).(j)) then raise Exit - done + let arr1_i = arr1.(i) in + for j = 0 to Array.length arr1_i - 1 do + if not (are_consistent_pack arr1_i.(j) arr2.(i).(j)) then raise Exit + done done; true with Invalid_argument _ | Exit -> @@ -319,7 +321,7 @@ let are_consistent d1 d2 = assert (Unmarshal_tbl.length unmarshal_consistent_visited = 0 - && Tbl.length consistent_visited = 0); + && Tbl.length consistent_visited = 0); let b = are_consistent_aux d1 d2 in Unmarshal_tbl.clear unmarshal_consistent_visited; Tbl.clear consistent_visited; diff -Nru frama-c-20110201+carbon+dfsg/src/type/structural_descr.mli frama-c-20111001+nitrogen+dfsg/src/type/structural_descr.mli --- frama-c-20110201+carbon+dfsg/src/type/structural_descr.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/structural_descr.mli 2011-10-10 08:38:09.000000000 +0000 @@ -38,12 +38,14 @@ It MUST NOT be used directly in any case. *) -(** Structural descriptor used inside structural descriptor. *) -type pack = - | Nopack (** Internal use only *) - | Pack of single_pack (** Internal use only *) - | Recursive of recursive (** Use for handling recursive structural - descriptor. See module {!Recursive}. *) +(** Structural descriptor used inside structures. + @modify Nitrogen-20111001 this type is now private. Use smart + constructors instead. *) +type pack = private + | Nopack (** Was impossible to build a pack. *) + | Pack of single_pack (** A standard pack. *) + | Recursive of recursive (** Pack for a recursive descriptor. + See module {!Recursive}. *) (** Type of internal representations of OCaml type. @@ -51,7 +53,7 @@ is [Structure (Sum [| [| p_int; p_bool |]; [| p_string |] |])]. Ok, in this case, just [Abstract] is valid too. *) type t = - | Unknown + | Unknown (** Use it either for unmarshable types or if you don't know its internal representation. In any case, values of types with such a descriptor will be never write on disk. *) @@ -63,7 +65,8 @@ | Structure of structure (** Provide a description of the representation of data. *) - | T_pack of single_pack (** Internal use only *) + | T_pack of single_pack (** Internal use only. + Do not use it outside the library *) (** Description with details. *) and structure = @@ -75,14 +78,18 @@ corresponding constructor. *) | Array of pack (** The data is an array of values of the same type, each - value being described by the pack. *) + value being described by the pack. *) (* ********************************************************************** *) -(** {2 Useful functions} *) +(** {2 Pack builders} *) (* ********************************************************************** *) val pack: t -> pack -(** Pack a structural descriptor for embedding inside another one. *) +(** Pack a structural descriptor in order to embed it inside another one. *) + +val recursive_pack: recursive -> pack +(** Pack a recursive descriptor. + @since Nitrogen-20111001 *) (** Use this module for handling a (possibly recursive) structural descriptor [d]. Call [Recursive.create ()] (returning [r]) before building [d]. Build diff -Nru frama-c-20110201+carbon+dfsg/src/type/type.ml frama-c-20111001+nitrogen+dfsg/src/type/type.ml --- frama-c-20110201+carbon+dfsg/src/type/type.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/type.ml 2011-10-10 08:38:09.000000000 +0000 @@ -33,6 +33,7 @@ let use_obj = ref true let no_obj () = use_obj := false +let may_use_obj () = !use_obj (* ****************************************************************************) (* ****************************************************************************) @@ -64,7 +65,6 @@ { name: string; digest: Digest.t; structural_descr: Structural_descr.t; - mutable is_dynamic_abstract:bool; mutable pp_ml_name: precedence -> Format.formatter -> unit } (* phantom type *) @@ -74,15 +74,12 @@ (* non-phantom type: the type variable is used here *) type 'a full_t = { ty: 'a t; reprs: 'a list } -type abstract - let types : (string (* name *), Obj.t full_t) Hashtbl.t = Hashtbl.create 97 let dummy = { name = ""; digest = ""; structural_descr = Structural_descr.Unknown; - is_dynamic_abstract = false; pp_ml_name = fun _ _ -> assert false } let mk_dyn_pp name = function @@ -92,17 +89,15 @@ | Some s -> let prec = try - ignore (Str.search_forward (Str.regexp " ") name 0); - Call + ignore (Str.search_forward (Str.regexp " ") name 0); + Call with Not_found -> - Basic + Basic in fun p fmt -> par p prec fmt (fun fmt -> Format.fprintf fmt "%s" s) exception AlreadyExists of string -let register - ?(closure=false) ?(dynamic_abstract=false) - ~name ~ml_name structural_descr reprs = +let register ?(closure=false) ~name ~ml_name structural_descr reprs = let error () = invalid_arg ("Type.register: invalid reprs for type " ^ name) in @@ -118,24 +113,28 @@ let pp_ml_name = mk_dyn_pp name ml_name in let digest = match structural_descr with | Structural_descr.Unknown -> - (* unserializable type: weakest digest *) - Digest.string name + (* unserializable type: weakest digest *) + Digest.string name | _ -> - let key = name, Structural_descr.cleanup structural_descr, reprs in - Digest.string (Marshal.to_string key []) + let key = name, Structural_descr.cleanup structural_descr, reprs in + Digest.string (Marshal.to_string key []) in let ty = - { name = name; digest = digest; structural_descr = structural_descr; - is_dynamic_abstract = dynamic_abstract; pp_ml_name = pp_ml_name } + { name = name; + digest = digest; + structural_descr = structural_descr; + pp_ml_name = pp_ml_name } in let full_ty = { ty = ty; reprs = List.map Obj.repr reprs } in if !use_obj then Hashtbl.add types name full_ty; ty -exception Not_dynamic of string -let get x = - if !use_obj then (Hashtbl.find types x).ty - else failwith "Cannot call `Type.get' in `no obj' mode" +module Abstract(T: sig val name: string end) = struct + type t + let ty = + if !use_obj then (Hashtbl.find types T.name).ty + else failwith "Cannot call `Type.get' in `no obj' mode" +end let name ty = ty.name let structural_descr ty = ty.structural_descr @@ -148,15 +147,14 @@ let unsafe_reprs ty = (Hashtbl.find types ty.name).reprs let reprs ty = - let l = try unsafe_reprs ty with Not_found -> assert false in + let l = try unsafe_reprs ty with Not_found -> Format.printf "Type %s@." + ty.name ;assert false in List.map Obj.obj l let set_ml_name ty ml_name = let pp = mk_dyn_pp ty.name ml_name in ty.pp_ml_name <- pp -let is_dynamic_abstract ty = ty.is_dynamic_abstract <- true - (* ****************************************************************************) (** {2 Type values are comparable} *) (* ****************************************************************************) @@ -216,18 +214,18 @@ let instantiate (ty:'a t) = if !use_obj then try - Tbl.find ty, false + Tbl.find ty, false with Not_found -> - let repr = - register - ~name:(T.name ty) - ~ml_name:(Some (ml_name ty)) - (T.structural_descr ty.structural_descr) - (List.fold_left - (fun acc ty -> T.reprs ty @ acc) [] (unsafe_reprs ty)) - in - Tbl.add ty repr; - repr, true + let repr = + register + ~name:(T.name ty) + ~ml_name:(Some (ml_name ty)) + (T.structural_descr ty.structural_descr) + (List.fold_left + (fun acc ty -> T.reprs ty @ acc) [] (unsafe_reprs ty)) + in + Tbl.add ty repr; + repr, true else dummy, false @@ -276,37 +274,37 @@ let ml_name from_ty1 from_ty2 = let b = Buffer.create 31 in Format.bprintf b "%s.instantiate %t %t" - T.module_name - (from_ty1.pp_ml_name Call) - (from_ty2.pp_ml_name Call); + T.module_name + (from_ty1.pp_ml_name Call) + (from_ty2.pp_ml_name Call); Buffer.contents b let instantiate a b = if !use_obj then let key = a, b in try - Concrete_pair.find memo_tbl key, false + Concrete_pair.find memo_tbl key, false with Not_found -> - let reprs = - List.fold_left - (fun acc r1 -> - List.fold_left - (fun acc r2 -> T.reprs r1 r2 @ acc) - acc - (unsafe_reprs b)) - [] - (unsafe_reprs a) - in - let ty = - register - ~name:(T.name a b) - ~ml_name:(Some (ml_name a b)) - (T.structural_descr a.structural_descr b.structural_descr) - reprs - in - Concrete_pair.add memo_tbl key ty; - Tbl.add instances ty key; - ty, true + let reprs = + List.fold_left + (fun acc r1 -> + List.fold_left + (fun acc r2 -> T.reprs r1 r2 @ acc) + acc + (unsafe_reprs b)) + [] + (unsafe_reprs a) + in + let ty = + register + ~name:(T.name a b) + ~ml_name:(Some (ml_name a b)) + (T.structural_descr a.structural_descr b.structural_descr) + reprs + in + Concrete_pair.add memo_tbl key ty; + Tbl.add instances ty key; + ty, true else dummy, false @@ -339,11 +337,11 @@ module Memo = Hashtbl.Make (struct - type t = instance - let hash x = - Hashtbl.hash (hash x.arg, hash x.ret, Hashtbl.hash x.label) - let equal x y = - equal x.arg y.arg && equal x.ret y.ret && x.label = y.label + type t = instance + let hash x = + Hashtbl.hash (hash x.arg, hash x.ret, x.label) + let equal x y = + equal x.arg y.arg && equal x.ret y.ret && x.label = y.label end) let memo_tbl : concrete_repr Memo.t = Memo.create 17 let instances @@ -366,12 +364,12 @@ let get_optional_argument (ty:('a, 'b) poly t) = if !use_obj then try - match Tbl.find instances ty with - | _, None -> None - | _, Some o -> Some (Obj.obj o : unit -> 'b) + match Tbl.find instances ty with + | _, None -> None + | _, Some o -> Some (Obj.obj o : unit -> 'b) with Not_found -> - (* static typing ensures than [ty] has already been instantiated. *) - assert false + (* static typing ensures than [ty] has already been instantiated. *) + assert false else invalid_arg "cannot call `Type.get_optional_argument in the 'no obj' mode" @@ -391,29 +389,29 @@ let instantiate ?label (a:'a) (b:'b t) = if !use_obj then let l, o = match label with - | None -> None, None - | Some (l, None) -> Some l, None - | Some (l, Some o) -> Some l , Some (Obj.repr o) + | None -> None, None + | Some (l, None) -> Some l, None + | Some (l, Some o) -> Some l , Some (Obj.repr o) in let key = { arg = a; ret = b; label = l } in try - Memo.find memo_tbl key, false + Memo.find memo_tbl key, false with Not_found -> - let ty = - (* Do not inline [Types.repr b] in the closure below because - caml is not able to marshal the closure. - Sadly don't know exactly why. Seem to have some value tagged as - abstract in the closure environment. *) - register - ~closure:true - ~name:(name l a b) - ~ml_name:(Some (ml_name l a b)) - Structural_descr.Unknown - (List.map (fun r _ -> r) (unsafe_reprs b)) - in - Memo.add memo_tbl key ty; - Tbl.add instances ty (key, o); - ty, true + let ty = + (* Do not inline [Types.repr b] in the closure below because + caml is not able to marshal the closure. + Sadly don't know exactly why. Seem to have some value tagged as + abstract in the closure environment. *) + register + ~closure:true + ~name:(name l a b) + ~ml_name:(Some (ml_name l a b)) + Structural_descr.Unknown + (List.map (fun r _ -> r) (unsafe_reprs b)) + in + Memo.add memo_tbl key ty; + Tbl.add instances ty (key, o); + ty, true else dummy, false @@ -438,7 +436,7 @@ module Ty_tbl(Info: sig type 'a t end) = struct type t = Obj.t Tbl.t - let create = Tbl.create + let create x = Tbl.create x let add tbl (ty:'a ty) (x:'a Info.t) = Tbl.add tbl ty (Obj.repr x) let find tbl (ty:'a ty) = (Obj.obj (Tbl.find tbl ty) : 'a Info.t) end @@ -457,19 +455,19 @@ type t = Obj.t let equal = (==) let hash x = - if !use_obj then - (* 0 is correct; trying to do a bit better... *) - let tag = Obj.tag x in - if tag = 0 then - 0 - else if tag = Obj.closure_tag then - (* assumes that the first word of a closure does not change in - anyway (even by Gc.compact invokation). *) - Obj.magic (Obj.field x 0) - else - Hashtbl.hash x - else - 0 + if !use_obj then + (* 0 is correct; trying to do a bit better... *) + let tag = Obj.tag x in + if tag = 0 then + 0 + else if tag = Obj.closure_tag then + (* assumes that the first word of a closure does not change in + any way (even by Gc.compact invokation). *) + Obj.magic (Obj.field x 0) + else + Hashtbl.hash x + else + 0 end) type 'a t = 'a O.t Tbl.t @@ -479,11 +477,11 @@ let add tbl ty k v = if !use_obj then let tytbl = - try Tbl.find tbl ty - with Not_found -> - let tytbl = O.create 7 in - Tbl.add tbl ty tytbl; - tytbl + try Tbl.find tbl ty + with Not_found -> + let tytbl = O.create 7 in + Tbl.add tbl ty tytbl; + tytbl in O.replace tytbl (Obj.repr k) v @@ -513,7 +511,7 @@ module O = Weak.Make(struct (* we use the weak hash tbl as a weak list since we cannot use [(==)] in - weak hash tables. See documentation of module Weak. *) + weak hash tables. See documentation of module Weak. *) type t = Obj.t let equal _ _ = false let hash _ = 0 @@ -526,11 +524,11 @@ let add tbl ty k = if !use_obj then let tytbl = - try Tbl.find tbl ty - with Not_found -> - let tytbl = O.create 7 in - Tbl.add tbl ty tytbl; - tytbl + try Tbl.find tbl ty + with Not_found -> + let tytbl = O.create 7 in + Tbl.add tbl ty tytbl; + tytbl in O.add tytbl (Obj.repr k) @@ -540,10 +538,10 @@ let objs = Tbl.find tbl ty in assert !use_obj; try - O.iter (fun x -> if x == Obj.repr k then raise Exit) objs; - false + O.iter (fun x -> if x == Obj.repr k then raise Exit) objs; + false with Exit -> - true + true with Not_found -> false @@ -554,7 +552,7 @@ type 'a info type t val create: int -> t - val add: t -> key -> 'a ty -> 'a info -> 'a info + val add: t -> key -> 'a ty -> 'a info -> unit exception Unbound_value of string exception Incompatible_type of string val find: t -> key -> 'a ty -> 'a info @@ -573,61 +571,31 @@ exception Incompatible_type of string - let create = H.create - let values_of_abstracts = Obj_weak.create () - - let rec objectify name n ty x : Obj.t = - assert !use_obj; - if ty.is_dynamic_abstract then Obj_weak.add values_of_abstracts ty x; - if Function.is_instance_of ty then - let a, b, _ = Function.get_instance ty in - (* ok: [x] is a function here *) - let f : 'a -> 'b = Obj.magic x in - Obj.repr - (fun (y:'a) -> - (* for dynamic types, dynamically check that the argument was - built with a constructor of this type. *) - if a.is_dynamic_abstract && not (Obj_weak.mem values_of_abstracts a y) - then begin - let msg = - Format.sprintf - "argument %d of %s not built with a constructor of type %s" - n name a.name - in - raise (Incompatible_type msg) - end; - (* recursive call *) - (Obj.obj (objectify name (succ n) b (f y)) : 'b)) - else - Obj.repr x + let create x = H.create x let add tbl s ty x = if !use_obj then begin let name = Key.to_string s in if H.mem tbl s then raise (AlreadyExists name); - let o = objectify name 1 ty x in - H.add tbl s { ty = ty; o = o }; - Obj.obj o - end else - x + H.add tbl s { ty = ty; o = Obj.repr x } + end exception Unbound_value of string let type_error s ty_name ty_name' = raise (Incompatible_type - (Format.sprintf "%s has type %s but is used with type %s." - s ty_name' ty_name)) + (Format.sprintf "%s has type %s but is used with type %s." + s ty_name' ty_name)) let find tbl s ty = if !use_obj then let name = Key.to_string s in - try - let data = H.find tbl s in - if ty.digest <> data.ty.digest then - type_error name ty.name data.ty.name; - Obj.obj data.o - with Not_found -> - raise (Unbound_value name) + let data = + try H.find tbl s with Not_found -> raise (Unbound_value name) + in + if ty.digest <> data.ty.digest then + type_error name ty.name data.ty.name; + Obj.obj data.o else invalid_arg "cannot call function 'find' in the 'no obj' mode" @@ -637,7 +605,7 @@ Make_tbl (struct type t = string - let hash = Hashtbl.hash + let hash x = Hashtbl.hash x let equal : string -> string -> bool = (=) let to_string x = x end) diff -Nru frama-c-20110201+carbon+dfsg/src/type/type.mli frama-c-20111001+nitrogen+dfsg/src/type/type.mli --- frama-c-20110201+carbon+dfsg/src/type/type.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/type/type.mli 2011-10-10 08:38:09.000000000 +0000 @@ -30,6 +30,11 @@ (** Deactivate all the black magic. Roughly, in this mode, nothing is done by this module. *) +(**/**) +val may_use_obj: unit -> bool +(** Internal use only. Please, do not use it yourself. *) +(**/**) + (* ****************************************************************************) (** {2 Type declaration} *) (* ****************************************************************************) @@ -83,13 +88,12 @@ val register: ?closure:bool -> - ?dynamic_abstract:bool -> name:string -> ml_name:string option -> Structural_descr.t -> 'a list -> 'a t -(** [register ?closure ?dynamic_abstract ~name ~ml_name descr reprs] registers +(** [register ?closure ~name ~ml_name descr reprs] registers a new type value. Should not be used directly. Use one of functors of module {!Datatype} instead. @raise AlreadyExists if the given name is already used by another type. @@ -99,23 +103,24 @@ @modify Carbon-20101201 [value_name] is now [ml_name]. Must provide a structural descriptor. Argument [pp] does not exist anymore. *) -type abstract -val get: string -> abstract t -(** @return the type value from its name. *) +(** Apply this functor to access to the abstract type of the given name. + @since Nitrogen-20111001 *) +module Abstract(T: sig val name: string end): sig + type t + val ty: t ty +end val name: 'a t -> string val structural_descr: 'a t -> Structural_descr.t val reprs: 'a t -> 'a list +(** Not usable in the "no-obj" mode *) + val digest: 'a t -> Digest.t val ml_name: 'a t -> string val pp_ml_name: 'a t -> precedence -> Format.formatter -> unit val set_ml_name: 'a t -> string option -> unit -val is_dynamic_abstract: 'a t -> unit -(** Call this function to indicate that this type is an abstract type - dynamically registered. *) - (* ****************************************************************************) (** {2 Type values are comparable} *) (* ****************************************************************************) @@ -146,7 +151,7 @@ type 'a t (** Static polymorphic type corresponding to its dynamic counterpart to - register. *) + register. *) val reprs: 'a -> 'a t list (** How to make the representant of each monomorphic instance of the @@ -164,18 +169,18 @@ val instantiate: 'a t -> 'a poly t * bool (** @return the monomorphic instantiation of the polymorph type with the - given type value. For instance, if ['a poly = 'a list], then - [instantiate int] returns the type value [int list]. *) + given type value. For instance, if ['a poly = 'a list], then + [instantiate int] returns the type value [int list]. *) val is_instance_of: 'a t -> bool (** @return [true] iff the given type value has been created from - function [instantiate] above. - For instance, [is_instance_of (instantiate int)] always returns [true] - but [is_instance_of int] always returns [false]. *) + function [instantiate] above. + For instance, [is_instance_of (instantiate int)] always returns [true] + but [is_instance_of int] always returns [false]. *) val get_instance: 'a poly t -> 'a t (** [get_instance ty] returns the type value used to create the given - monomorphic instantiation. *) + monomorphic instantiation. *) end @@ -214,7 +219,7 @@ val instantiate: ?label:string * (unit -> 'a) option -> 'a t -> 'b t -> ('a -> 'b) t * bool (** Possibility to add a label for the parameter. - - [~label:(p,None)] for a mandatory labelized parameter [p]; + - [~label:(p,None)] for a mandatory labelized parameter [p]; - [~label:(p,Some f)] for an optional labelized parameter [p], with default value [f ()]. *) val is_instance_of: 'a t -> bool @@ -237,19 +242,18 @@ type 'a info type t (** Type of heterogeneous (hash)tables indexed by values of type Key.t. - Type values ensure type safety. *) + Type values ensure type safety. *) val create: int -> t (** [create n] creates a new table of initial size [n]. *) - val add: t -> key -> 'a ty -> 'a info -> 'a info + val add: t -> key -> 'a ty -> 'a info -> unit (** [add tbl s ty v] binds [s] to the value [v] in the table [tbl]. - If the returned value is a closure whose the type of one of its - argument was dynamically registered, then it may raise - [Incompatible_Type]. - @return the exact value stored in the table which is observationally - equal to [v] but it deals better with dynamic types. - @raise AlreadyExists if [s] is already bound in [tbl]. *) + If the returned value is a closure whose the type of one of its + argument was dynamically registered, then it may raise + [Incompatible_Type]. + @raise AlreadyExists if [s] is already bound in [tbl]. + @modify Nitrogen-20111001 returns [unit] now. *) exception Unbound_value of string exception Incompatible_type of string @@ -257,9 +261,9 @@ val find: t -> key -> 'a ty -> 'a info (** [find tbl s ty] returns the binding of [s] in the table [tbl]. - @raise Unbound_value if [s] is not bound in [tbl]. - @raise Incompatible_Type if [ty] was not the type value used to add - the binding of [s] in [tbl]. *) + @raise Unbound_value if [s] is not bound in [tbl]. + @raise Incompatible_Type if [ty] was not the type value used to add + the binding of [s] in [tbl]. *) end diff -Nru frama-c-20110201+carbon+dfsg/src/users/users_register.ml frama-c-20111001+nitrogen+dfsg/src/users/users_register.ml --- frama-c-20110201+carbon+dfsg/src/users/users_register.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/users/users_register.ml 2011-10-10 08:38:23.000000000 +0000 @@ -57,11 +57,11 @@ | [] -> assert false | (current_function, _call_site) :: tail -> let treat_element (user, _call_site) = - ignore - (Users.memo - ~change:(Kernel_function.Hptset.add current_function) - (fun _ -> Kernel_function.Hptset.singleton current_function) - user) + ignore + (Users.memo + ~change:(Kernel_function.Hptset.add current_function) + (fun _ -> Kernel_function.Hptset.singleton current_function) + user) in List.iter treat_element tail @@ -71,41 +71,52 @@ let () = Cmdline.run_after_configuring_stage init let get kf = + let find kf = + try Users.find kf + with Not_found -> Kernel_function.Hptset.empty + in if Users.is_computed () then - Users.find kf + find kf else begin if Db.Value.is_computed () then begin feedback "requiring again the computation of the value analysis"; Project.clear - ~selection:(State_selection.Dynamic.with_dependencies Db.Value.self) - () + ~selection:(State_selection.Dynamic.with_dependencies Db.Value.self) + () end else feedback ~level:2 "requiring the computation of the value analysis"; add_value_hook (); !Db.Value.compute (); - Users.find kf + find kf end -let () = Db.Users.get := get +let () = + Db.register + (Db.Journalize("Users.get", + Datatype.func Kernel_function.ty Kernel_function.Hptset.ty)) + Db.Users.get + get -let main () = +let print () = if ForceUsers.get () then - begin - result "====== DISPLAYING USERS ======@\n%t\ - ====== END OF USERS ==========" - (fun fmt -> - !Db.Semantic_Callgraph.topologically_iter_on_functions - (fun kf -> - try - Format.fprintf fmt "@[%a: @[%a@]@]@\n" - Kernel_function.pretty_name kf - Kernel_function.Hptset.pretty (!Db.Users.get kf) - with Not_found -> - () (* [kf] is not called during analysis *)) - ) ; - end + result "@[<v>====== DISPLAYING USERS ======@ %t\ + ====== END OF USERS ==========" + (fun fmt -> + !Db.Semantic_Callgraph.topologically_iter_on_functions + (fun kf -> + let callees = !Db.Users.get kf in + if not (Kernel_function.Hptset.is_empty callees) then + Format.fprintf fmt "@[<hov 4>%a: %a@]@ " + Kernel_function.pretty kf + (Pretty_utils.pp_iter + ~pre:"" ~sep:"@ " ~suf:"" Kernel_function.Hptset.iter + Kernel_function.pretty) + callees)) -let () = Db.Main.extend main +let print_once, _self_print = + State_builder.apply_once "Users_register.print" [ Users.self ] print + +let () = Db.Main.extend print_once (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/value/builtins.ml frama-c-20111001+nitrogen+dfsg/src/value/builtins.ml --- frama-c-20110201+carbon+dfsg/src/value/builtins.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/builtins.ml 2011-10-10 08:38:26.000000000 +0000 @@ -20,13 +20,14 @@ (* *) (**************************************************************************) -open Cvalue_type +open Cvalue open Abstract_interp open Cil open Locations open Value_util +open Cil_types -let table = Hashtbl.create 7 +let table = Hashtbl.create 17 let register_builtin name f = Hashtbl.add table name f @@ -39,6 +40,9 @@ let mem_builtin name = Hashtbl.mem table name let () = Db.Value.mem_builtin := mem_builtin +let overridden_by_builtin s = + try ignore (Value_parameters.BuiltinsOverrides.find s); true + with Not_found -> false let offsetmap_of_value ~typ v = V_Offsetmap.update_ival @@ -56,58 +60,136 @@ exception Found_misaligned_base -let frama_C_cos state actuals = +let double_double_fun name caml_fun state actuals = match actuals with [_, arg, _] -> begin - let r = - try - let i = Cvalue_type.V.project_ival arg in - let f = Ival.project_float i in - Cvalue_type.V.inject_ival - (Ival.inject_float (Ival.Float_abstract.cos_float f)) - with Cvalue_type.V.Not_based_on_null -> - Value_parameters.result ~once:true ~current:true - "Builtin Frama_C_cos applied to address"; - Cvalue_type.V.topify_arith_origin arg - in - (wrap_double r), state, Location_Bits.Top_Param.bottom + let r = + try + let i = Cvalue.V.project_ival arg in + let f = Ival.project_float i in + Cvalue.V.inject_ival + (Ival.inject_float (caml_fun f)) + with Cvalue.V.Not_based_on_null -> + Value_parameters.result ~once:true ~current:true "%s" + ("Builtin " ^ name ^ " applied to address"); + Cvalue.V.topify_arith_origin arg + in + (wrap_double r), state, Location_Bits.Top_Param.bottom end | _ -> - Value_parameters.error "Invalid argument for Frama_C_cos function"; + Value_parameters.error "%s" + ("Invalid argument for " ^ name ^ " function"); do_degenerate None; raise Db.Value.Aborted + +let frama_C_cos = double_double_fun "Frama_C_cos" Ival.Float_abstract.cos_float +let frama_C_cos_precise = + double_double_fun "Frama_C_cos_precise" Ival.Float_abstract.cos_float_precise + let () = register_builtin "Frama_C_cos" frama_C_cos +let () = register_builtin "Frama_C_cos_precise" frama_C_cos_precise + +let frama_C_sin = double_double_fun "Frama_C_sin" Ival.Float_abstract.sin_float +let () = register_builtin "Frama_C_sin" frama_C_sin + +let frama_C_sin_precise = + double_double_fun "Frama_C_sin_precise" Ival.Float_abstract.sin_float_precise +let () = register_builtin "Frama_C_sin_precise" frama_C_sin_precise + +let frama_C_exp = double_double_fun "Frama_C_exp" Ival.Float_abstract.exp_float +let () = register_builtin "Frama_C_exp" frama_C_exp + +(* +external cos_rd : float -> float = "caml_cos_rd" +external cos_ru : float -> float = "caml_cos_ru" +external crlibm_init : unit -> unit = "caml_crlibm_init" +*) + +let frama_C_compare_cos state actuals = + match actuals with + [_, arg, _; _, res, _; _, eps, _] -> begin + try + let iarg = Cvalue.V.project_ival arg in + let farg = Ival.project_float iarg in + let larg,uarg = Ival.Float_abstract.min_and_max_float farg in + let larg = Ival.F.to_float larg in + let uarg = Ival.F.to_float uarg in + let ires = Cvalue.V.project_ival res in + let fres = Ival.project_float ires in + let lres,ures = Ival.Float_abstract.min_and_max_float fres in + let lres = Ival.F.to_float lres in + let ures = Ival.F.to_float ures in + let ieps = Cvalue.V.project_ival eps in + let feps = Ival.project_float ieps in + let _,ueps = Ival.Float_abstract.min_and_max_float feps in + let ueps = Ival.F.to_float ueps in +(* crlibm_init(); + let lref = cos_rd uarg in (* cos is decreasing *) + let uref = cos_ru larg in (* cos is decreasing *) *) + Ival.set_round_nearest_even(); + (* system cos probably isn't designed for non-default rounding *) + let lref = cos uarg in + let uref = cos larg in + Ival.set_round_upward(); + let lallow = uref -. ueps in + Ival.set_round_downward(); + let uallow = lref +. ueps in + if lallow <= lres && ures <= uallow + then + Value_parameters.result "CC %1.16f %1.16f %1.16f %1.16f %1.16f %1.16f OK" + larg uarg + lres ures + lref uref + else + Value_parameters.result "CC %1.16f %1.16f %1.16f %1.16f %1.16f %1.16f KO" + larg uarg + lres ures + lref uref; + None, state, Location_Bits.Top_Param.bottom + with _ -> Value_parameters.error + "Invalid argument for Frama_C_compare_cos function"; + do_degenerate None; + raise Db.Value.Aborted + end + | _ -> Value_parameters.error + "Invalid argument for Frama_C_compare_cos function"; + do_degenerate None; + raise Db.Value.Aborted + +let () = register_builtin "Frama_C_compare_cos" frama_C_compare_cos + let frama_C_sqrt state actuals = match actuals with [_, arg, _] -> begin - let r = - try - let i = Cvalue_type.V.project_ival arg in - let f = Ival.project_float i in - let result_alarm, f = - Ival.Float_abstract.sqrt_float (get_rounding_mode()) f - in - if result_alarm - then -(* CilE.warn_result_nan_infinite - (warn_all_quiet_mode ()) ; *) - Value_parameters.result ~once:true ~current:true - "float sqrt: assert (Ook)"; - Cvalue_type.V.inject_ival (Ival.inject_float f) - - with - Cvalue_type.V.Not_based_on_null -> - Value_parameters.result ~once:true ~current:true - "float sqrt applied to address"; - Cvalue_type.V.topify_arith_origin arg - | Ival.Float_abstract.Bottom -> - ignore (CilE.warn_once "sqrt: TODO -- a proper alarm"); - V.bottom - in - (wrap_double r), state, Location_Bits.Top_Param.bottom + let r = + try + let i = Cvalue.V.project_ival arg in + let f = Ival.project_float i in + let result_alarm, f = + Ival.Float_abstract.sqrt_float (get_rounding_mode()) f + in + if result_alarm + then +(* CilE.warn_result_nan_infinite + (warn_all_quiet_mode ()) ; *) + Value_parameters.result ~once:true ~current:true + "float sqrt: assert (Ook)"; + Cvalue.V.inject_ival (Ival.inject_float f) + + with + Cvalue.V.Not_based_on_null -> + Value_parameters.result ~once:true ~current:true + "float sqrt applied to address"; + Cvalue.V.topify_arith_origin arg + | Ival.Float_abstract.Bottom -> + Value_parameters.warning ~once:true ~current:true + "sqrt: TODO -- a proper alarm"; + V.bottom + in + (wrap_double r), state, Location_Bits.Top_Param.bottom end | _ -> Value_parameters.error "Invalid argument for Frama_C_sqrt function"; @@ -116,74 +198,7 @@ let () = register_builtin "Frama_C_sqrt" frama_C_sqrt -exception Base_aligned_error - -let frama_C_is_base_aligned state actuals = - try begin - match actuals with - [_,x,_; _,y,_] -> - let i = Cvalue_type.V.project_ival y in - begin match i with - Ival.Set si -> - Location_Bytes.fold_i - (fun b _o () -> - Ival.O.iter - (fun int -> - if not (Base.is_aligned_by b int) - then raise Found_misaligned_base) - si) - x - (); - (wrap_int Cvalue_type.V.singleton_one), - state, - Location_Bits.Top_Param.bottom - | _ -> raise Found_misaligned_base - end - | _ -> raise Base_aligned_error - end - with Base_aligned_error -> - Cilmsg.error "Invalid arguments for Frama_C_is_base_aligned function" ; - do_degenerate None; - raise Db.Value.Aborted - | Found_misaligned_base - | Not_found (* from project_ival *) -> - (wrap_int Cvalue_type.V.zero_or_one), - state, - Location_Bits.Top_Param.bottom - -let () = register_builtin "Frama_C_is_base_aligned" frama_C_is_base_aligned - -exception Offset_error - -let frama_c_offset state actuals = - try begin - match actuals with - [_,x,_] -> - begin - let value = - try - let offsets = - Location_Bytes.fold_i - (fun _b o a -> Ival.join a o) - x - Ival.bottom - in - Cvalue_type.V.inject_ival offsets - with Location_Bytes.Error_Top -> - error - "Builtin Frama_C_offset is applied to a value not guaranteed to be an address"; - Cvalue_type.V.top_int - in - (wrap_int value), state, Location_Bits.Top_Param.bottom - end - | _ -> raise Offset_error - end - with Offset_error -> - Cilmsg.error "Invalid arguments for builtin Frama_C_offset" ; - do_degenerate None; - raise Db.Value.Aborted -let () = register_builtin "Frama_C_offset" frama_c_offset exception Invalid_CEA_alloc_infinite exception Not_found_lonely_key @@ -207,45 +222,48 @@ in let file_base,_file_offset = try - Cvalue_type.V.find_lonely_key file + Cvalue.V.find_lonely_key file with Not_found -> raise Not_found_lonely_key in let file = match file_base with - | Base.String (_,s) -> s + | Base.String (_,e) -> + ( match Base.get_string e with + Base.CSString s -> s + | Base.CSWstring _ -> assert false ) | Base.Var (s,_) | Base.Initialized_Var (s,_) -> s.Cil_types.vname - | Base.Null | Base.Cell_class _ -> raise Invalid_CEA_alloc_infinite + | Base.Null -> raise Invalid_CEA_alloc_infinite in let loc = Dynamic_Alloc_Table.memo - (fun file -> - let new_name = + (fun file -> + let new_name = if Extlib.string_prefix ~strict:true "Frama_C_alloc_" file - then file - else Format.sprintf "Frama_C_alloc_%s" file - in - let new_name = Cabs2cil.fresh_global new_name in - let unbounded_type = + then file + else Format.sprintf "Frama_C_alloc_%s" file + in + let new_name = Cabs2cil.fresh_global new_name in + let unbounded_type = Cil_types.TArray (intType, Some (new_exp ~loc:Cil_datatype.Location.unknown (Cil_types.Const (Cil_types.CStr "NOSIZE"))), empty_size_cache (),[]) - in - let new_varinfo = - makeGlobalVar ~logic:true new_name unbounded_type - in - let new_offsetmap = - Cvalue_type.V_Offsetmap.sized_zero (Bit_utils.memory_size ()) - in - let new_base = - Cvalue_type.Default_offsetmap.create_initialized_var - new_varinfo - Base.All - new_offsetmap - in - Location_Bytes.inject new_base Ival.zero) - file + in + let new_varinfo = + makeGlobalVar ~logic:true new_name unbounded_type + in + let new_offsetmap = + Cvalue.V_Offsetmap.sized_zero (Bit_utils.memory_size ()) + in + let new_base = + Cvalue.Default_offsetmap.create_initialized_var + new_varinfo + Base.All + new_offsetmap + in + Location_Bytes.inject new_base Ival.zero) + file in wrap_ptr loc, state, Location_Bits.Top_Param.bottom with @@ -259,94 +277,116 @@ let () = register_builtin "Frama_C_alloc_infinite" frama_c_alloc_infinite +let frama_c_dump_assert state _actuals = + Value_parameters.result ~current:true "Frama_C_dump_assert_each called:@\n(%a)@\nEnd of Frama_C_dump_assert_each output" + Cvalue.Model.pretty_c_assert state; + None, state, Location_Bits.Top_Param.bottom + +let () = register_builtin "Frama_C_dump_assert_each" frama_c_dump_assert + -let frama_c_memcpy state actuals = +(* -------------------------------------------------------------------------- *) +(* --- Builtins not registered in the table --- *) +(* -------------------------------------------------------------------------- *) + +exception Invalid_CEA_alloc + +let alloc_with_validity initial_state actuals = try - match actuals with - | [exp_dst,dst,_; exp_src,src,_ ; exp_size,size,_] -> - let size = Cvalue_type.V.project_ival size in - let min,max = Ival.min_and_max size in - let min = match min with - | None -> Int.zero - | Some m -> Int.max m Int.zero - and max = match max with - | None -> assert false (* TODO *) - | Some m -> m - in - let size_min = Int.mul Int.eight min in - let right = loc_bytes_to_loc_bits src in - let left = loc_bytes_to_loc_bits dst in - let right_loc = make_loc right (Int_Base.inject size_min) in - let term_size = Logic_utils.expr_to_term ~cast:true exp_size in - let array_src = Logic_utils.array_with_range exp_src term_size - and array_dst = Logic_utils.array_with_range exp_dst term_size - in - CilE.set_syntactic_context (CilE.SyMemLogic array_src); - begin - match Relations_type.Model.copy_offsetmap - ~with_alarms:(warn_all_quiet_mode ()) - right_loc - state - with - | None -> - None, - Relations_type.Model.bottom, - Location_Bits.Top_Param.bottom - - | Some offsetmap -> - CilE.set_syntactic_context (CilE.SyMemLogic array_dst); - let new_state = - Relations_type.Model.paste_offsetmap - offsetmap left Int.zero size_min state - in - let fuzz = Int.sub max min in - if Int.is_zero fuzz - then None, new_state, Location_Bits.get_bases right - else - let fuzz = Int.mul Int.eight fuzz in - let fuzz = Int_Base.inject fuzz in - let ival_min = Ival.inject_singleton size_min in - let left = Location_Bits.location_shift ival_min left in - let right = Location_Bits.location_shift ival_min right in - CilE.set_syntactic_context (CilE.SyMemLogic array_src); - let garb = - Relations_type.Model.find - ~conflate_bottom:false - ~with_alarms:(warn_all_quiet_mode ()) - state - (make_loc right fuzz) - in - CilE.set_syntactic_context (CilE.SyMemLogic array_dst); - let new_state = - Relations_type.Model.add_binding - ~exact:false - ~with_alarms:(warn_all_quiet_mode ()) - new_state - (make_loc left fuzz) - garb - in - None, new_state, Location_Bits.get_bases right - end - | _ -> - raise Db.Value.Aborted - with - V.Not_based_on_null | Lmap.Cannot_copy | Db.Value.Aborted -> - Value_parameters.error - "Invalid call to Frama_C_memcpy%a" - pretty_actuals - actuals; - do_degenerate None; - raise Db.Value.Aborted + let size = match actuals with + | [_,size,_] -> size + | _ -> raise Invalid_CEA_alloc + in + let size = + try + let size = Cvalue.V.project_ival size in + Ival.project_int size + with Ival.Not_Singleton_Int | V.Not_based_on_null -> + raise Invalid_CEA_alloc + in + if Int.le size Int.zero then raise Invalid_CEA_alloc; + let new_name = Format.sprintf "Frama_C_alloc" in + let new_name = Cabs2cil.fresh_global new_name in + let bounded_type = + TArray( + charType, + Some (new_exp ~loc:Cil_datatype.Location.unknown + (Const (CInt64 (size,IInt ,None)))), + empty_size_cache (), + []) + in + let new_varinfo = makeGlobalVar ~logic:true new_name bounded_type in + let size_in_bits = Int.mul (Bit_utils.sizeofchar()) size in + let new_offsetmap = Cvalue.V_Offsetmap.sized_zero ~size_in_bits in + let new_base = + Cvalue.Default_offsetmap.create_initialized_var + new_varinfo + (Base.Known (Int.zero, Int.pred size_in_bits)) + new_offsetmap + in + let loc_without_size = Location_Bytes.inject new_base Ival.zero in + (wrap_ptr loc_without_size), + initial_state, + Location_Bits.Top_Param.bottom + with Ival.Error_Top | Invalid_CEA_alloc -> + Value_parameters.error + "Invalid argument for Frama_C_alloc_size function"; + do_degenerate None; + raise Db.Value.Aborted -let () = register_builtin "Frama_C_memcpy" frama_c_memcpy +let dump_state initial_state = + let l = fst (CurrentLoc.get ()) in + Value_parameters.result + "DUMPING STATE of file %s line %d@\n%a=END OF DUMP==" + l.Lexing.pos_fname l.Lexing.pos_lnum + Cvalue.Model.pretty initial_state; + None, initial_state, Location_Bits.Top_Param.bottom + +module DumpFileCounters = + State_builder.Hashtbl (Datatype.String.Hashtbl)(Datatype.Int) + (struct let size = 3 + let kind = `Correctness + let dependencies = [Db.Value.self] + let name = "Builtins.DumpFileCounters" + end) +let dump_state_file name initial_state args = + (try + let size = String.length name in + let name = + if size > 23 (* Frama_C_dump_each_file_ + 'something' *) then + String.sub name 23 (size - 23) + else failwith "no filename specified" + in + let n = try DumpFileCounters.find name with Not_found -> 0 in + DumpFileCounters.add name (n+1); + let file = Format.sprintf "%s_%d" name n in + let ch = open_out file in + let fmt = Format.formatter_of_out_channel ch in + let l = fst (CurrentLoc.get ()) in + Value_parameters.feedback ~current:true "Dumping state in file '%s'%t" + file Value_util.pp_callstack; + Format.fprintf fmt "DUMPING STATE at file %s line %d@." + l.Lexing.pos_fname l.Lexing.pos_lnum; + if args <> [] then Format.fprintf fmt "Args: %a@." pretty_actuals args; + Cvalue.Model.pretty fmt initial_state; + close_out ch + with e -> + Value_parameters.warning ~current:true ~once:true + "Error during, or invalid call to Frama_C_dump_each_file (%s). Ignoring" + (Printexc.to_string e) + ); + None, initial_state, Location_Bits.Top_Param.bottom + +let dump_args name initial_state actuals = + Value_parameters.result "Called %s%a%t" + name + pretty_actuals actuals + Value_util.pp_callstack; + None, initial_state, Location_Bits.Top_Param.bottom -(* -let name_cea_offset = -let is_cea_offset name = name = name_cea_offset -*) (* Local Variables: -compile-command: "LC_ALL=C make -C ../.." +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/value/current_table.ml frama-c-20111001+nitrogen+dfsg/src/value/current_table.ml --- frama-c-20110201+carbon+dfsg/src/value/current_table.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/current_table.ml 2011-10-10 08:38:26.000000000 +0000 @@ -25,43 +25,40 @@ open Cilutil open Cil_datatype -module Ki = Cil_datatype.Kinstr (* do not mask kinstr in src/value *) - type record = { - mutable superposition : State_imp.t ; - mutable widening : int ; - mutable widening_state : Relations_type.Model.t ; + mutable superposition : State_imp.t ; + mutable widening : int ; + mutable widening_state : Cvalue.Model.t ; } - + let empty_record () = { superposition = State_imp.empty () ; widening = Value_parameters.WideningLevel.get () ; - widening_state = Relations_type.Model.bottom } + widening_state = Cvalue.Model.bottom } - type t = record Ki.Hashtbl.t + type t = record Stmt.Hashtbl.t - let create () = - Ki.Hashtbl.create 257 + let create () = + Stmt.Hashtbl.create 257 - let clear t = Ki.Hashtbl.clear t + let clear t = Stmt.Hashtbl.clear t let find_current current_table kinstr = try - Ki.Hashtbl.find current_table kinstr + Stmt.Hashtbl.find current_table kinstr with Not_found -> let record = empty_record () in - Ki.Hashtbl.add current_table kinstr record; + Stmt.Hashtbl.add current_table kinstr record; record let find_widening_info current_table kinstr = let r = find_current current_table kinstr in r.widening, r.widening_state - let update_current_exn current_table kinstr v = - assert (kinstr <> Kglobal); - let record = find_current current_table kinstr in - State_imp.merge_set_into v record.superposition + let update_current_exn current_table stmt v = + let record = find_current current_table stmt in + State_imp.merge_set_into v record.superposition let update_current current_table kinstr v = @@ -72,20 +69,26 @@ let update_and_tell_if_changed current_table kinstr d = let record = find_current current_table kinstr in - State_imp.merge_set_return_new d record.superposition + if Cvalue.Model.is_reachable record.widening_state + then + let j = State_set.join d in + if Cvalue.Model.is_included j record.widening_state + then State_set.empty + else State_set.singleton j + else + State_imp.merge_set_return_new d record.superposition let update_widening_info current_table kinstr wcounter wstate = let record = find_current current_table kinstr in record.widening <- wcounter; - record.widening_state <- wstate; - record.superposition <- State_imp.singleton wstate + record.widening_state <- wstate let merge_db_table hash_states = - let treat_instr k sum = - let current_state = Db.Value.noassert_get_state k in + let treat_stmt k sum = + let current_state = Db.Value.noassert_get_stmt_state k in let is_top_already = - Relations_type.Model.is_top current_state + Cvalue.Model.is_top current_state in if not is_top_already then Db.Value.update_table k sum @@ -93,33 +96,39 @@ if Mark_noresults.should_memorize_function (Kernel_function.get_definition (Value_util.current_kf())) then - Ki.Hashtbl.iter treat_instr (Lazy.force hash_states) + Stmt.Hashtbl.iter treat_stmt (Lazy.force hash_states) let superpositions current_table = - let r = Ki.Hashtbl.create (Ki.Hashtbl.length current_table) + let r = Stmt.Hashtbl.create (Stmt.Hashtbl.length current_table) in - Ki.Hashtbl.iter + Stmt.Hashtbl.iter (fun k record -> - let sup2 = - State_imp.fold - State_set.add - record.superposition - State_set.empty - in - Ki.Hashtbl.add r k sup2) + let sup2 = + State_imp.fold + State_set.add + record.superposition + State_set.empty + in + Stmt.Hashtbl.add r k sup2) current_table; r let states current_table = - let r = Ki.Hashtbl.create (Ki.Hashtbl.length current_table) + let r = Stmt.Hashtbl.create (Stmt.Hashtbl.length current_table) in - Ki.Hashtbl.iter + Stmt.Hashtbl.iter (fun k record -> - Ki.Hashtbl.add r k - (State_imp.join_dropping_relations record.superposition)) + Stmt.Hashtbl.add r k + (Cvalue.Model.join + (State_imp.join_dropping_relations record.superposition) + record.widening_state)) current_table; r let find_superposition current_table s = - (find_current current_table s).superposition + let record = find_current current_table s in + let s = State_imp.to_set record.superposition in + if Cvalue.Model.is_reachable record.widening_state + then State_set.add record.widening_state s + else s diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval_exprs.ml frama-c-20111001+nitrogen+dfsg/src/value/eval_exprs.ml --- frama-c-20110201+carbon+dfsg/src/value/eval_exprs.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval_exprs.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,1694 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil +open Ast_printer +open Abstract_interp +open Locations +open Cvalue +open Bit_utils +open Value_util + + +exception Distinguishable_strings + +exception Leaf (* raised when nothing is known for a function : + no source nor specification *) + +exception Not_an_exact_loc + +exception Reduce_to_bottom + +exception Offset_not_based_on_Null of + Locations.Zone.t option * Location_Bytes.t + +exception Cannot_find_lv + +exception Too_linear + + +type cond = + { exp: exp; (* The condition of the branch*) + positive: bool; (* true: normal false: negated *)} + +(* Returns boolean telling to display a warning, + and optionally reduce the values of [ev1] and [ev2], + knowing that they are involved in a comparison *) +(* TODO: this function currently never reduces ev1 and ev2 *) +let check_comparable op ev1 ev2 = + try + if not (Location_Bytes.is_included ev1 Location_Bytes.top_int) + || not (Location_Bytes.is_included ev2 Location_Bytes.top_int) + then begin + let null_1, rest_1 = Location_Bytes.split Base.null ev1 in + let null_2, rest_2 = Location_Bytes.split Base.null ev2 in + let is_bottom1 = Location_Bytes.is_bottom rest_1 in + let is_bottom2 = Location_Bytes.is_bottom rest_2 in + + (* First check if a non-zero integer is compared to an address *) + if ((not (Ival.is_included null_1 Ival.zero)) && (not is_bottom2)) + || ((not (Ival.is_included null_2 Ival.zero)) && (not is_bottom1)) + then raise Not_found; + + if not (is_bottom1 && is_bottom2) + then begin + let loc_bits1 = loc_bytes_to_loc_bits rest_1 in + let loc_bits2 = loc_bytes_to_loc_bits rest_2 in + let single_base_ok = + begin try + (* If they are both in the same base and both almost valid, + it's also fine, but beware of empty rest for comparisons + to NULL, or of function pointers *) + let extract_base is_bot loc = + if is_bot then Base.null + else begin + let base, offs = Location_Bits.find_lonely_key loc in + if Base.is_function base then + (if not (Ival.equal Ival.zero offs) + then raise Base.Not_valid_offset) + else + Base.is_valid_offset ~for_writing:false + Int.zero base offs; + base + end + in + let base_1 = extract_base is_bottom1 loc_bits1 + and base_2 = extract_base is_bottom2 loc_bits2 + in + is_bottom1 || is_bottom2 || (Base.equal base_1 base_2) + with + Not_found -> false + end + in + if not single_base_ok + then begin + if op = Eq || op = Ne + then begin + (* If both addresses are valid, they can be compared + for equality. *) + let loc1 = make_loc loc_bits1 Int_Base.one in + let loc2 = make_loc loc_bits2 Int_Base.one in + if (not (Locations.is_valid_or_function loc1)) || + (not (Locations.is_valid_or_function loc2)) + then raise Not_found; + (* But wait! literal strings can only be compared + if their contents are recognizably different! + (or the strings are physically the same) *) + Locations.Location_Bytes.iter_on_strings + ~skip:None + (fun base1 s1 offs1 len1 -> + Locations.Location_Bytes.iter_on_strings + ~skip:(Some base1) + (fun _ s2 offs2 len2 -> + let delta = offs1-offs2 in + begin + try + let start = if delta <= 0 then (-delta) else 0 + in + for i = start to min len2 (len1 - delta) + do +(* Format.printf "%S %S %d %d@." + s1 s2 i delta; *) + if s2.[i] <> s1.[i + delta] + then raise Distinguishable_strings; + done; + raise Not_found + with Distinguishable_strings -> (); + end) + rest_1) + rest_2 + end + else raise Not_found + end + end + end; + false, ev1, ev2 + with Not_found | Base.Not_valid_offset -> + true, ev1, ev2 + +let do_cast ~with_alarms t expr = + let treat inttype = + match inttype with + | TInt(kind,_) -> + let size = Int.of_int (bitsSizeOf inttype) in + let signed = isSigned kind in + V.cast ~with_alarms ~signed ~size expr + | TFloat (FFloat,_) -> + let addresses, overflow, res = V.cast_float expr in + if addresses + then warning_once_current + "addresses in float"; + if overflow then warning_once_current + "overflow in float: %a -> %a. assert(Ook)" + V.pretty expr V.pretty res; + res + | TFloat (FDouble,_) + | TFloat (FLongDouble,_) -> + expr + | _ -> assert false + in + match unrollType t with + | TInt _ | TFloat _ as t' -> + treat t' + | TPtr _ -> + treat theMachine.upointType + | TEnum ({ekind=k},_) -> treat (TInt(k,[])) + | TComp _ -> expr (* see test [struct_call.c] *) + | TBuiltin_va_list _ -> + (match with_alarms.CilE.imprecision_tracing with + | CilE.Aignore -> () + | CilE.Acall f -> f () + | CilE.Alog _ -> + warning_once_current + "cast to __builtin_va_list is not precisely implemented yet"); + V.topify_arith_origin expr + | TFun _ -> expr + | TNamed _ -> assert false + | TVoid _ -> assert false + | TArray _ -> assert false + +let do_promotion ~with_alarms ~src_typ ~dest_type v e_src = + match dest_type, src_typ with + | TFloat _, TInt _ -> + Cvalue.V.cast_int_to_float ~with_alarms (get_rounding_mode()) v + | TInt (kind,_), TFloat _ -> + let size = bitsSizeOf dest_type in + let signed = isSigned kind in + let alarm_use_as_float, alarm_overflow, r = + Cvalue.V.cast_float_to_int ~signed ~size v + in + if alarm_use_as_float + then begin + warning_once_current + "converting %a to float: assert(Ook)" + !d_exp e_src; + end; + if alarm_overflow + then + warning_once_current + "Overflow in cast of %a (%a) from floating-point to integer: assert(Ook)" + !d_exp e_src + Cvalue.V.pretty v; + r + | _, _ -> v + +let handle_signed_overflow ~with_alarms typ interpreted_e = + match unrollType typ with + TInt(kind, _) + when isSigned kind -> + let size = bitsSizeOf typ in + let mn, mx = + let b = Int.power_two (size-1) in + Int.neg b, Int.pred b + in + let mn64 = Int.to_int64 mn in + let mx64 = Int.to_int64 mx in + let warn_under, warn_over = + try + let i = V.project_ival interpreted_e in + let imn, imx = Ival.min_and_max i in + let u = + match imn with + Some bound when Int.ge bound mn -> None + | _ -> Some mn64 + in + let o = + match imx with + Some bound when Int.le bound mx -> None + | _ -> Some mx64 + in + u, o + with V.Not_based_on_null -> + Some mn64, Some mx64 + in + ( match warn_under, warn_over with + None, None -> + interpreted_e + | _ -> + if Value_parameters.SignedOverflow.get() + then + let all_values = + Cvalue.V.inject_ival + (Ival.inject_range (Some mn) (Some mx)) + in + CilE.warn_signed_overflow + with_alarms + warn_under + warn_over; + V.narrow all_values interpreted_e + else + ( warning_once_current + "2's complement assumed for overflow"; + interpreted_e ) ) + | _ -> interpreted_e + +let warn_lval_read lv loc contents = + let pretty_param fmt param = + match param with + | Location_Bits.Top_Param.Top -> Format.fprintf fmt "is imprecise" + | Location_Bits.Top_Param.Set _s -> + Format.fprintf fmt "is a garbled mix of %a" + Location_Bits.Top_Param.pretty param + in + let pretty_param_b fmt param = + match param with + | Location_Bytes.Top_Param.Top -> + Format.fprintf fmt "The contents@ are imprecise" + | Location_Bytes.Top_Param.Set _s -> + Format.fprintf fmt "It contains@ a garbled@ mix@ of@ %a" + Location_Bytes.Top_Param.pretty param + in + let something_to_warn = + match loc.loc with Location_Bits.Top _ -> true + | Location_Bits.Map _ -> + match contents with + | Location_Bytes.Top _ -> true + | Location_Bytes.Map _ -> false + in + if something_to_warn then + Value_parameters.result ~current:true ~once:true + "@[<v>@[Reading left-value %a.@]@ %t%t%t@]" + !Ast_printer.d_lval lv + (fun fmt -> + match lv with + | Mem _, _ -> + (match loc.loc with + | Location_Bits.Top (param,o) when Origin.equal o Origin.top -> + Format.fprintf fmt "@[The location %a.@]@ " + pretty_param param + | Location_Bits.Top (param,orig) -> + Format.fprintf fmt "@[The location @[%a@]@ because of@ %a.@]@ " + pretty_param param + Origin.pretty orig + | Location_Bits.Map _ -> + Format.fprintf fmt "@[The location is @[%a@].@]@ " + Location_Bits.pretty loc.loc) + | Var _, _ -> ()) + (fun fmt -> + match contents with + | Location_Bytes.Top (param,o) when Origin.equal o Origin.top -> + Format.fprintf fmt "@[%a.@]" + pretty_param_b param + | Location_Bytes.Top (param,orig) -> + Format.fprintf fmt "@[%a@ because of@ %a.@]" + pretty_param_b param + Origin.pretty orig + | Location_Bytes.Map _ -> ()) + pp_callstack + +let eval_binop_float ~with_alarms ev1 op ev2 = + try + let conv v = + try Ival.project_float (V.project_ival v) + with + | V.Not_based_on_null + | Ival.Float_abstract.Nan_or_infinite -> + warning_once_current "converting value to float: assert(Ook)"; + Ival.Float_abstract.top + in + let f1 = conv ev1 + and f2 = conv ev2 + in + let binary_float_floats (_name: string) f = + try + let alarm, f = f (get_rounding_mode ()) f1 f2 in + if alarm then CilE.warn_result_nan_infinite with_alarms; + V.inject_ival (Ival.inject_float f) + with + | Ival.Float_abstract.Nan_or_infinite -> + CilE.warn_result_nan_infinite with_alarms ; + V.top_float + | Ival.Float_abstract.Bottom -> + CilE.warn_result_nan_infinite with_alarms ; + V.bottom + in + begin match op with + | PlusA -> binary_float_floats "+." Ival.Float_abstract.add_float + | MinusA -> binary_float_floats "-." Ival.Float_abstract.sub_float + | Mult -> binary_float_floats "*." Ival.Float_abstract.mult_float + | Div -> binary_float_floats "/." Ival.Float_abstract.div_float + | Eq -> + let contains_zero, contains_non_zero = + Ival.Float_abstract.equal_float_ieee f1 f2 + in + V.interp_boolean ~contains_zero ~contains_non_zero + | Ne -> + let contains_non_zero, contains_zero = + Ival.Float_abstract.equal_float_ieee f1 f2 + in + V.interp_boolean ~contains_zero ~contains_non_zero + | Lt -> + V.interp_boolean + ~contains_zero:(Ival.Float_abstract.maybe_le_ieee_float f2 f1) + ~contains_non_zero:(Ival.Float_abstract.maybe_lt_ieee_float f1 f2) + | Le -> + V.interp_boolean + ~contains_zero:(Ival.Float_abstract.maybe_lt_ieee_float f2 f1) + ~contains_non_zero:(Ival.Float_abstract.maybe_le_ieee_float f1 f2) + | Gt -> + V.interp_boolean + ~contains_zero:(Ival.Float_abstract.maybe_le_ieee_float f1 f2) + ~contains_non_zero:(Ival.Float_abstract.maybe_lt_ieee_float f2 f1) + | Ge -> + V.interp_boolean + ~contains_zero:(Ival.Float_abstract.maybe_lt_ieee_float f1 f2) + ~contains_non_zero:(Ival.Float_abstract.maybe_le_ieee_float f2 f1) + | _ -> raise V.Not_based_on_null + end + with V.Not_based_on_null | Ival.F.Nan_or_infinite -> + warning_once_current + "float operation on address."; + V.join + (V.topify_arith_origin ev1) + (V.topify_arith_origin ev2) + +(* eval some operations on location_bytes. This function is more low-level + than eval_binop, that evaluates the expressions in the given state. Here, + we suppose someone else has done the evaluation, and combine the results. + The expressions are passed in order to have the types of the expressions + at hand; hopefully they are correct. [typ] is optional. If it is not + passed, the function must behave as if it was acting on unbounded integers *) +let eval_binop_int ~with_alarms ?typ ~te1 ev1 op ev2 = + match op with + | PlusPI | IndexPI -> V.add_untyped (osizeof_pointed te1) ev1 ev2 + | MinusPI -> V.add_untyped (Int_Base.neg (osizeof_pointed te1)) ev1 ev2 + | PlusA -> V.add_untyped (Int_Base.one) ev1 ev2 + | MinusA -> V.add_untyped Int_Base.minus_one ev1 ev2 + | MinusPP -> + let minus_val = V.add_untyped Int_Base.minus_one ev1 ev2 in + begin + try + let size = Int_Base.project (sizeof_pointed te1) in + let size = Int.div size Int.eight in + if Int.is_one size then + minus_val + else + let minus_val = Cvalue.V.project_ival minus_val in + Cvalue.V.inject_ival (Ival.scale_div ~pos:true size minus_val) + with + | Int_Base.Error_Top + | Cvalue.V.Not_based_on_null + | Not_found -> + V.join (V.topify_arith_origin ev1) (V.topify_arith_origin ev2) + end + | Mod -> V.c_rem ~with_alarms ev1 ev2 + | Div -> V.div ~with_alarms ev1 ev2 + | Mult -> V.arithmetic_function ~with_alarms "*" Ival.mul ev1 ev2 + | LOr -> + assert false + (* This code makes a strict evaluation: V.interp_boolean + ~contains_zero: (V.contains_zero ev1 && + V.contains_zero ev2) ~contains_non_zero: + (V.contains_non_zero ev1 || V.contains_non_zero + ev2)*) + | LAnd -> + assert false + (* This code makes a strict evaluation: + V.interp_boolean ~contains_zero: (V.contains_zero + ev1 || V.contains_zero ev2) ~contains_non_zero: + (V.contains_non_zero ev1 && V.contains_non_zero + ev2)*) + | BXor -> + V.oper_on_values ~with_alarms "^" Int.logxor ev1 ev2 + | BOr -> + V.bitwise_or ~size:(bitsSizeOf te1) ev1 ev2 + | BAnd -> + (try + let size = bitsSizeOf te1 in + let signed = is_signed_int_enum_pointer te1 in + V.bitwise_and ~size ~signed ev1 ev2 + with SizeOfError _ -> + V.join (V.topify_arith_origin ev1) (V.topify_arith_origin ev2)) + + | Eq | Ne | Ge | Le | Gt | Lt -> + let warn, ev1, ev2 = check_comparable op ev1 ev2 in + if warn then CilE.warn_pointer_comparison with_alarms; + if warn && Value_parameters.UndefinedPointerComparisonPropagateAll.get () + then V.zero_or_one + else + let signed = is_signed_int_enum_pointer (unrollType te1) in + let f = match op with + | Eq -> V.check_equal true + | Ne -> V.check_equal false + | Ge -> V.comparisons ">=" ~signed V.do_ge + | Le -> V.comparisons "<=" ~signed V.do_le + | Gt -> V.comparisons ">" ~signed V.do_gt + | Lt -> V.comparisons "<" ~signed V.do_lt + | _ -> assert false + in + f ev1 ev2 + | Shiftrt | Shiftlt -> + begin + let f = + if op = Shiftlt then V.shift_left else V.shift_right + in + try + let size = Extlib.opt_map bitsSizeOf typ in + f ~with_alarms ?size ev1 ev2 + with SizeOfError _ -> assert false + end + +(* TODO: A version that does not create bigints would be better *) +let bitfield_size_lv lv = sizeof (typeOfLval lv) +let bitfield_size_bf lv = Bit_utils.sizeof_lval lv +let is_bitfield lv ?(sizelv=bitfield_size_lv lv) ?(sizebf=(bitfield_size_bf lv)) () = + not (Int_Base.equal sizelv sizebf) + +let rec lval_to_loc ~with_alarms state lv = + let _,_,r = + lval_to_loc_deps_option + ~with_alarms + ~deps:None + ~reduce_valid_index:(Kernel.SafeArrays.get ()) + state + lv + in + r + +and exp_lval_to_loc state exp = + let lv = + match exp.enode with + | Lval lv -> lv + | _ -> raise Cannot_find_lv + in + (* TODO: utiliser find_lv_plus pour traiter plus d'expressions *) + lv, lval_to_loc ~with_alarms:CilE.warn_none_mode state lv + +and lval_to_loc_deps_option + ~with_alarms ~deps state ~reduce_valid_index (base,offset as lv) + = + if not (Cvalue.Model.is_reachable state) then + state, deps, loc_bottom + else + let typ = match base with + | Var host -> host.vtype + | Mem x -> typeOf x + in + try + let state, deps, offs = + eval_offset + ~reduce_valid_index + ~with_alarms deps typ state offset + in + base_to_loc ~with_alarms ?deps state lv base offs + with Offset_not_based_on_Null(deps,offset) -> + let state, deps, loc_if_there_wasnt_offset = + base_to_loc ~with_alarms ?deps state lv base Ival.zero + in + state, deps, + loc_bits_to_loc lv + (Location_Bits.join + (loc_bytes_to_loc_bits offset) + loc_if_there_wasnt_offset.loc) + +(* pc says: only called in addrOf *) +and lval_to_loc_with_offset_deps_only ~deps state v = + lval_to_loc_with_offset_deps_only_option ~deps:(Some deps) state v + +and lval_to_loc_with_deps ~deps state lv ~with_alarms = + lval_to_loc_deps_option ~with_alarms ~deps:(Some deps) state lv + +(* pc says: only called in addrOf *) +and lval_to_loc_with_offset_deps_only_option + ~with_alarms ~deps (state:Cvalue.Model.t) (_base, _offset as v) + = + lval_to_loc_deps_option + ~with_alarms ~deps (state:Cvalue.Model.t) (v) + ~reduce_valid_index:false + + +(** Detects if an expression can be considered as a lvalue even though + it is hidden by a cast that does not change the lvalue. + Raises [exn] if it is not an lvalue. + + TODO: When the goal is to recognize the form (cast)l-value == expr, + it would be better and more powerful to have chains of inverse functions *) + +and pass_cast ~with_alarms state exn typ e = + (* type might be the same but their attributes. + But volatile attribute cannot be skipped *) + if not (Cilutil.equals + (typeSigWithAttrs (filterAttributes "volatile") typ) + (typeSigWithAttrs (filterAttributes "volatile") (typeOf e))) + then + (try + let typeofe = typeOf e in + (* Any volatile attribute may have an effect on the expression value *) + if hasAttribute "volatile" (typeAttrs typeofe) + || hasAttribute "volatile" (typeAttrs typ) + then raise exn; + let sztyp = sizeof typ in + let szexpr = sizeof typeofe in + let typ_ge_typeofe = + match sztyp,szexpr with + Int_Base.Value styp, Int_Base.Value sexpr -> Int.ge styp sexpr + | _ -> false + in + if not typ_ge_typeofe then raise exn; + let sityp = is_signed_int_enum_pointer typ in + let sisexpr = is_signed_int_enum_pointer (typeOf e) in + if sityp = sisexpr then () + (* destination type is larger and has the same sign as + the original type *) + else begin (* try to ignore the cast if it acts as identity + on the value [e] even if signed/unsigned + conflict. *) + match unrollType typ with + | TInt _ | TEnum _ -> + let size = Int.of_int (bitsSizeOf typ) in + let signed = sityp in + (try + let old_ival = V.project_ival + (eval_expr ~with_alarms state e) + in + if (Ival.equal + old_ival + (Ival.cast ~size ~signed ~value:old_ival)) + then () (* [e] is not sensitive to cast *) + else raise exn + with + | Not_found + | V.Not_based_on_null -> + raise exn) + (* this is not always injective, thus cannot be + easily reverted. *) + | _ -> raise exn + end + with Neither_Int_Nor_Enum_Nor_Pointer + -> raise exn) + +and find_lv ~with_alarms (state:Cvalue.Model.t) ee = + (* [BM] Do not recognize an lval whenever a volatile is involved to + prevent copy/paste optimization. IS THIS THE RIGHTPLACE PC ?*) + if hasAttribute "volatile" (typeAttrs (typeOf ee)) then + raise Cannot_find_lv; + match ee.enode with + | Lval lv -> lv + | CastE (typ,e) -> + ( match unrollType typ, unrollType (typeOf e) with + TFloat (FDouble,_), TFloat _ -> find_lv ~with_alarms state e + (* see remark at pass_cast about inverse functions *) + | _ -> + pass_cast ~with_alarms state Cannot_find_lv typ e; + find_lv ~with_alarms state e) + | _ -> raise Cannot_find_lv + +and find_lv_plus ~with_alarms state e = + let acc = ref [] in + let rec find_lv_plus_rec e current_offs = + try + let lv = find_lv ~with_alarms state e in + if not (hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lv))) + then acc := (lv,current_offs) :: !acc + with Cannot_find_lv -> + match e.enode with + BinOp(op, e1, e2, typ) -> + begin + match unrollType typ with + TFloat _ -> () + | _ -> begin + match op with + PlusA -> + let ev1 = eval_expr ~with_alarms state e1 in + let ev2 = eval_expr ~with_alarms state e2 in + ( try + let ival1 = V.project_ival ev1 in + find_lv_plus_rec e2 (Ival.add current_offs ival1) + with V.Not_based_on_null -> ()); + ( try + let ival2 = V.project_ival ev2 in + find_lv_plus_rec e1 (Ival.add current_offs ival2) + with V.Not_based_on_null -> ()); + | (MinusA|MinusPI|PlusPI|IndexPI as b) -> + let ev2 = eval_expr ~with_alarms state e2 in + ( try + let ival2 = V.project_ival ev2 in + let ival2 = + if b = MinusA + then ival2 + else + let ival2 = + Ival.scale + (Int_Base.project (osizeof_pointed typ)) + ival2 + in + if b = MinusPI + then ival2 + else Ival.neg ival2 + in + find_lv_plus_rec e1 (Ival.sub current_offs ival2) + with V.Not_based_on_null | Int_Base.Error_Top-> ()); + | _ -> () + end + end + | CastE(typ,e) -> + ( try + pass_cast ~with_alarms state Cannot_find_lv typ e; + find_lv_plus_rec e current_offs + with Cannot_find_lv -> ()) + | _ -> () + in + find_lv_plus_rec e Ival.singleton_zero; + (*List.iter + (fun (lv,ival) -> + ignore (Pretty.printf "find_lv_plus %a : %s\n" + d_lval lv + (pretty_to_string Ival.pretty ival))) + !acc;*) + !acc + +and base_to_loc ~with_alarms ?deps state lv base offs = + if Ival.is_bottom offs + then begin + Cvalue.Model.bottom, + (Some Zone.bottom), + loc_bits_to_loc lv Location_Bits.bottom + end + else + let result = match base with + | Var host -> + let base = Base.find host in + state, deps, + loc_bits_to_loc lv (Location_Bits.inject base offs) + | Mem x -> + let state, deps, loc_lv = + eval_expr_with_deps_state ~with_alarms deps state x + in + let loc_bits = + Location_Bits.location_shift + offs + (loc_bytes_to_loc_bits loc_lv) + in + state, deps, loc_bits_to_loc lv loc_bits + in + CilE.set_syntactic_context (CilE.SyMem lv); + result + +and eval_expr ~with_alarms state e = + snd (eval_expr_with_deps ~with_alarms None state e) + +and get_influential_vars ~with_alarms state cond = + (* Format.printf "get_influential cond:%a@.state:%a@." + !d_exp cond + Cvalue.Model.pretty state; *) + let rec get_vars acc cond = + match cond.enode with + | Lval (Var v, off as lv) -> + let offset = + try + let _, _, offset = + eval_offset ~reduce_valid_index:true ~with_alarms None + v.vtype state off + in + offset + with Offset_not_based_on_Null _ -> + Ival.top + in + if Ival.cardinal_zero_or_one offset + then + (* no variable in offset can be influential *) + let varid = Base.create_varinfo v in + let loc = + Locations.make_loc + (Locations.Location_Bits.inject varid offset) + (sizeof_lval lv) + in + let contents = + Cvalue.Model.find ~conflate_bottom:true + state ~with_alarms loc + in + if Location_Bytes.cardinal_zero_or_one contents + then ( + (* Format.printf "cond:%a@.var contents:%a@.state:%a@." + !d_exp cond + Location_Bytes.pretty contents + Cvalue.Model.pretty state; *) + acc (* it's not influential *) + ) + else loc :: acc + else + (* a variable in offset can be influential *) + get_vars_offset acc off + | Lval (Mem e, off) -> + get_vars_offset (get_vars acc e) off + | BinOp(_,v1,v2,_) -> + get_vars (get_vars acc v1) v2 + | UnOp(_,v1,_) -> + get_vars acc v1 + | CastE (_typ,exp) -> + get_vars acc exp + | _ -> acc + and get_vars_offset acc offset = + match offset with + NoOffset -> acc + | Field (_,off) -> get_vars_offset acc off + | Index (ind,off) -> get_vars (get_vars_offset acc off) ind + in + get_vars [] cond + +and reduce_by_valid_expr ~positive ~for_writing exp state = + try + let lv, loc = exp_lval_to_loc state exp in + if not (Locations.valid_cardinal_zero_or_one ~for_writing:false loc) + then state + else reduce_by_valid_loc ~positive ~for_writing loc (typeOfLval lv) state + with Cannot_find_lv -> state + +and reduce_by_valid_loc ~positive ~for_writing loc typ state = + try + let value = Cvalue.Model.find ~with_alarms:CilE.warn_none_mode + ~conflate_bottom:true state loc + in + if Cvalue.V.is_imprecise value then + (* we won't reduce anything anyway, and we may lose information if loc + contains misaligned data *) + raise Cannot_find_lv; + let value_as_loc = + make_loc (loc_bytes_to_loc_bits value) (sizeof_pointed typ) + in + let reduced_value = + loc_to_loc_without_size + (if positive + then valid_part ~for_writing value_as_loc + else invalid_part value_as_loc ) + in + if Location_Bytes.equal value reduced_value + then state + else begin + if Location_Bytes.equal Location_Bytes.bottom reduced_value + then Cvalue.Model.bottom + else + Cvalue.Model.reduce_binding ~with_alarms:CilE.warn_none_mode + state loc reduced_value + end + with Cannot_find_lv -> state + +and reduce_by_initialized_loc ~with_alarms:_ ~positive (typ, loc) state = + try + let locbi = loc_bytes_to_loc_bits loc in + let size = match unrollType typ with + | TPtr (t, _) -> bitsSizeOf t + | _ -> assert false + in + let loc = make_loc locbi (Int_Base.inject (Int.of_int size)) in + if not (Locations.valid_cardinal_zero_or_one ~for_writing:false loc) + then state + else + let value = Cvalue.Model.find_unspecified + ~with_alarms:CilE.warn_none_mode state loc + in + (match value with + | Cvalue.V_Or_Uninitialized.C_uninit_esc (Location_Bytes.Top _) + | Cvalue.V_Or_Uninitialized.C_uninit_noesc (Location_Bytes.Top _) + | Cvalue.V_Or_Uninitialized.C_init_esc (Location_Bytes.Top _) + | Cvalue.V_Or_Uninitialized.C_init_noesc (Location_Bytes.Top _) -> + (* we won't reduce anything anyway, + and we may lose information if loc contains misaligned data *) + raise Cannot_find_lv + | _ -> () ); + let reduced_value = + Cvalue.V_Or_Uninitialized.change_initialized positive value + in + if Cvalue.V_Or_Uninitialized.equal value reduced_value + then state + else begin + if Cvalue.V_Or_Uninitialized.equal + Cvalue.V_Or_Uninitialized.bottom reduced_value + then Cvalue.Model.bottom + else + Cvalue.Model.add_binding_unspecified + state + loc + reduced_value + end + with Cannot_find_lv -> state + +and eval_BinOp ~with_alarms e deps state = + match e.enode with + | BinOp (op, e1, e2, typ) -> + let state, deps, ev1 = + eval_expr_with_deps_state ~with_alarms deps state e1 + in + if V.is_bottom ev1 + then Cvalue.Model.bottom, (Some Zone.bottom) ,V.bottom + else + let state, deps, ev2 = + eval_expr_with_deps_state ~with_alarms deps state e2 + in + if V.is_bottom ev2 + then Cvalue.Model.bottom, (Some Zone.bottom) ,V.bottom + else begin + begin match unrollType (typeOf e1) with + | TFloat _ -> + CilE.set_syntactic_context (CilE.SyUnOp e); + let r = eval_binop_float ~with_alarms ev1 op ev2 in + state, deps, r + | TInt _ | TPtr (_, _) | _ as te1 -> + CilE.set_syntactic_context (CilE.SyBinOp (op, e1, e2)); + let v = eval_binop_int + ~with_alarms ~typ ~te1 ev1 op ev2 in + (* Warn if overflow in a signed int binop *) + let v = match op with + | Shiftlt | Mult | MinusPP | MinusPI | IndexPI | PlusPI + | PlusA | Div | Mod | MinusA -> + handle_signed_overflow ~with_alarms typ v + | _ -> v + in + state, deps, v + end + end + | _ -> assert false + +and eval_expr_with_deps ~with_alarms deps (state : Cvalue.Model.t) e = + let _,deps,r = eval_expr_with_deps_state ~with_alarms deps state e in + deps, r + +and eval_expr_with_deps_state ~with_alarms deps state e = + let state, deps, r = + let orig_expr = Cil.stripInfo e in + match orig_expr.enode with + | Info _ -> assert false + | Const v -> + let r = + begin match v with + | CInt64 (i,_k,_s) -> + V.inject_int i + | CChr c -> + (match charConstToInt c with + | CInt64 (i,_,_) -> V.inject_int i + | _ -> assert false) + | CReal (f, _fsize, _) -> + Value_parameters.result ~once:true + "float support is experimental"; + let f = Ival.F.of_float f in + let overflow, af = + try + let o, af = Ival.Float_abstract.inject_r f f in + o, V.inject_ival (Ival.inject_float af) + with Ival.Float_abstract.Bottom -> + Value_parameters.result ~current:true + "Floating-point literal (or constant expression) is not finite. This path is assumed to be dead."; + true, V.bottom + in + if overflow + then Value_parameters.result "overflow in constant: assert(Ook);"; + af + | CWStr _ | CStr _ -> + V.inject (Base.create_string orig_expr) Ival.zero + | CEnum {eival = e} -> + eval_expr ~with_alarms state e + end + in + state, deps, r + | BinOp _ -> + eval_BinOp ~with_alarms orig_expr deps state + | Lval lv -> + eval_lval ~conflate_bottom:true ~with_alarms deps state lv + | AddrOf v | StartOf v -> + let state, deps, r = + lval_to_loc_with_offset_deps_only_option ~with_alarms ?deps state v + in + state, deps, loc_to_loc_without_size r + + | CastE (typ, e) -> + let deps, evaled_expr = + eval_expr_with_deps ~with_alarms deps state e + in + let src_typ = unrollType (typeOf e) in + let dest_type = unrollType typ in + let r = do_promotion ~with_alarms ~dest_type ~src_typ evaled_expr e in + state, deps, r + + | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ -> + let e = Cil.constFold true orig_expr in + let r = match e.enode with + | Const (CInt64 (v, _, _)) -> Cvalue.V.inject_int v + | _ -> + Value_parameters.error ~current:true + "cannot interpret sizeof or alignof (incomplete type)"; + V.top_int + in + state, deps, r + + | UnOp (op, e, _t_res) -> + let t = unrollType (typeOf e) in + let deps, expr = eval_expr_with_deps ~with_alarms deps state e in + let syntactic_context = match op with + | Neg -> CilE.SyUnOp orig_expr (* Can overflow *) + | BNot -> CilE.SyUnOp orig_expr (* does in fact never raise an alarm*) + | LNot -> CilE.SyBinOp (Eq, Cil.zero ~loc:e.eloc, e) + (* Can raise a pointer comparison. CilE needs a binop there *) + in + CilE.set_syntactic_context syntactic_context; + let result = eval_unop ~with_alarms expr t op in + state, deps, result + in + let r = + if hasAttribute "volatile" (typeAttrs (typeOf e)) + && not (Cvalue.V.is_bottom r) + then V.top_int + else + r + in + let typ = typeOf e in + let rr = do_cast ~with_alarms typ r in +(* ( match typ with + TInt _ when not (V.equal r rr || V.is_topint r) -> + warning_once_current + "downcast %a -> %a@." V.pretty r V.pretty rr + | _ -> ()); *) + state, deps, rr + +and eval_unop ~with_alarms expr t op = + match op with + | Neg -> + let t = unrollType t in + (match t with TFloat _ -> + (try + let v = V.project_ival expr in + let f = Ival.project_float v in + V.inject_ival + (Ival.inject_float (Ival.Float_abstract.neg_float f)) + with + V.Not_based_on_null -> + begin match with_alarms.CilE.others with + CilE.Aignore -> () + | CilE.Acall f -> f() + | CilE.Alog _ -> + warning_once_current + "converting address to float: assert(TODO)" + end; + V.topify_arith_origin expr + | Ival.Float_abstract.Nan_or_infinite -> + begin match with_alarms.CilE.others with + CilE.Aignore -> () + | CilE.Acall f -> f() + | CilE.Alog _ -> + warning_once_current + "converting value to float: assert (TODO)" + end; + V.top_float + ) + | _ -> + let result = + try + let v = V.project_ival expr in + V.inject_ival (Ival.neg v) + with V.Not_based_on_null -> V.topify_arith_origin expr + in + handle_signed_overflow ~with_alarms t result + ) + + | BNot -> + (try + let v = V.project_ival expr in + V.inject_ival + (Ival.apply_set_unary "~" Int.lognot v) + with V.Not_based_on_null -> V.topify_arith_origin expr) + + | LNot -> + (* TODO: on float, LNot is equivalent to == 0.0 *) + let warn, _, expr = check_comparable Eq V.singleton_zero expr in + if warn then CilE.warn_pointer_comparison with_alarms; + if (warn && + Value_parameters.UndefinedPointerComparisonPropagateAll.get ()) + || not (isIntegralType t || isPointerType t) + then + V.zero_or_one + else + V.interp_boolean + ~contains_zero:(V.contains_non_zero expr) + ~contains_non_zero:(V.is_included V.singleton_zero expr) + +and eval_expr_with_deps_state_subdiv ~with_alarms deps state e = + let (state_without_subdiv, deps_without_subdiv, result_without_subdiv as r) = + eval_expr_with_deps_state ~with_alarms deps state e + in + let subdivnb = Value_parameters.Subdivide_float_in_expr.get() in + if subdivnb=0 + then r + else if not (Locations.Location_Bytes.is_included result_without_subdiv Locations.Location_Bytes.top_int) + then begin + Value_parameters.debug ~level:2 + "subdivfloatvar: expression has an address result"; + r + end + else + let compare_min, compare_max = + if Locations.Location_Bytes.is_included result_without_subdiv Locations.Location_Bytes.top_float + then begin + Value_parameters.debug ~level:2 + "subdivfloatvar: optimizing floating-point expression %a=%a" + !d_exp e + Locations.Location_Bytes.pretty result_without_subdiv; + Cvalue.V.compare_min_float, Cvalue.V.compare_max_float + end + else begin + Value_parameters.debug ~level:2 + "subdivfloatvar: optimizing integer expression %a=%a" + !d_exp e + Locations.Location_Bytes.pretty result_without_subdiv; + Cvalue.V.compare_min_int, Cvalue.V.compare_max_int + end + in + let vars = + get_influential_vars ~with_alarms:CilE.warn_none_mode state e + in + Value_parameters.debug ~level:2 "subdivfloatvar: variable list=%a" + (Pretty_utils.pp_list Locations.pretty) + vars; + let rec try_sub vars = + match vars with + | [] | [ _ ] -> r + | v :: tail -> + try + if not (List.exists (fun x -> Locations.loc_equal v x) tail) + then raise Too_linear; + let v_value = + Cvalue.Model.find + ~conflate_bottom:true + ~with_alarms:CilE.warn_none_mode + state + v + in + (* Value_parameters.result ~current:true + "subdivfloatvar: considering optimizing variable %a (value %a)" + Locations.pretty v Cvalue.V.pretty v_value; *) + if not (Locations.Location_Bytes.is_included + v_value + Locations.Location_Bytes.top_float) + then raise Too_linear; + + let working_list = ref [ (v_value, result_without_subdiv) ] in + let had_bottom = ref false in + let subdiv_for_bound better_bound = + let rec insert_subvalue_in_list (_, exp_value as p) l = + match l with + [] -> [p] + | (_, exp_value1 as p1) :: tail -> + if better_bound exp_value1 exp_value >= 0 + then p :: l + else p1 :: (insert_subvalue_in_list p tail) + in + let exp_subvalue subvalue l = + let substate = + (* FIXME: should be relation-aware primitive *) + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + v + subvalue + in + let subexpr = eval_expr ~with_alarms substate e in +(* Value_parameters.result ~current:true + "subdivfloatvar: computed var=%a expr=%a" + V.pretty subvalue + V.pretty subexpr; *) + if Cvalue.V.is_bottom subexpr + then begin + had_bottom := true; + l + end + else + insert_subvalue_in_list (subvalue, subexpr) l + in + let size = + if Value_parameters.AllRoundingModes.get () + then 0 + else Int.to_int (Int_Base.project v.Locations.size) + in + let subdiv l = + match l with + [] -> + Value_parameters.debug + "subdivfloatvar: all reduced to bottom!!"; + raise Ival.Can_not_subdiv + | (value, _exp_value) :: tail -> + let (subvalue1, subvalue2) = + Cvalue.V.subdiv_float_interval ~size value + in + let s = exp_subvalue subvalue1 tail + in + exp_subvalue subvalue2 s + in + try + for i = 1 to subdivnb do + working_list := subdiv !working_list; + done + with Ival.Can_not_subdiv -> () + in + subdiv_for_bound compare_min ; + (* Now sort working_list in decreasing order + on the upper bounds of exp_value *) + let comp_exp_value (_value1,exp_value1) (_value2,exp_value2) = + compare_max exp_value1 exp_value2 + in + working_list := List.sort comp_exp_value !working_list ; + if Value_parameters.debug_atleast 2 then + List.iter + (function (x, e) -> + Value_parameters.debug + "subdivfloatvar: elements of list max %a %a" + V.pretty x V.pretty e) + !working_list; + subdiv_for_bound compare_max ; + let working_list = !working_list in + if Value_parameters.debug_atleast 2 then + List.iter + (function (x, e) -> + Value_parameters.debug + "subdivfloatvar: elements of final list %a %a" + V.pretty x V.pretty e) + working_list; + let reduced_state, optimized_exp_value = + if !had_bottom + then + let reduced_var, optimized_exp_value = + List.fold_left + (fun (accv,acce) (value, exp_value) -> + Cvalue.V.join value accv, + Cvalue.V.join exp_value acce) + (Cvalue.V.bottom, + Cvalue.V.bottom) + working_list + in + (* FIXME: should be relation-aware primitive *) + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + v + reduced_var, + optimized_exp_value + else + state_without_subdiv, + List.fold_left + (fun acc (_value, exp_value) -> + Cvalue.V.join exp_value acc) + Cvalue.V.bottom + working_list + in + reduced_state, deps_without_subdiv, optimized_exp_value + with Not_less_than | Too_linear -> + try_sub tail + in + try_sub vars + +(* TODO. Cf also [Eval_stmts.do_assign_abstract_value_to_loc]. Should we check + that the value is an int, and topify otherwise ? *) +and cast_lval_bitfield lv size v = + let signed = signof_typeof_lval lv in + Cvalue.V.cast ~with_alarms:CilE.warn_none_mode ~size ~signed v + +and cast_lval_when_bitfield lv ?(sizelv=bitfield_size_lv lv) ?(sizebf=(bitfield_size_bf lv)) v = + match sizebf with + | Int_Base.Value size when is_bitfield lv ~sizelv ~sizebf () -> + cast_lval_bitfield lv size v + | _ -> v + +and eval_lval_using_main_memory ~conflate_bottom ~with_alarms deps state lv = + let state,deps,loc = + lval_to_loc_deps_option ~with_alarms ?deps state lv + ~reduce_valid_index:(Kernel.SafeArrays.get ()) + in + CilE.set_syntactic_context (CilE.SyMem lv); + let result = + Cvalue.Model.find ~conflate_bottom ~with_alarms state loc + in +(* Format.printf "lval %a before %a@." + !d_lval lv + Cvalue.V.pretty result; *) + let result = cast_lval_when_bitfield lv ~sizebf:loc.Locations.size result in +(* Format.printf "lval %a after %a@." + !d_lval lv + Cvalue.V.pretty result; *) + (* TODO: move into Model.find *) + let valid_loc = Locations.valid_part ~for_writing:false loc in + let state = + if Location_Bits.equal loc.Locations.loc valid_loc.Locations.loc + then state + else begin + match lv with + Mem (exp_mem),NoOffset -> + let lv_mem_plus_list = + find_lv_plus ~with_alarms:CilE.warn_none_mode state exp_mem + in + let treat_lv_mem_plus (lv_mem, plus) state = + let loc_mem = + lval_to_loc ~with_alarms:CilE.warn_none_mode state lv_mem + in + if Location_Bits.is_relationable loc_mem.Locations.loc + then + let new_val = + Location_Bytes.location_shift + (Ival.neg plus) + (loc_bits_to_loc_bytes valid_loc.loc) + in + Cvalue.Model.reduce_binding + ~with_alarms:CilE.warn_none_mode + state loc_mem new_val + else state + in + List.fold_right treat_lv_mem_plus lv_mem_plus_list state + | _ -> state + end + in + (match with_alarms.CilE.imprecision_tracing with + | CilE.Aignore -> () + | CilE.Acall f -> f () + | CilE.Alog _ -> warn_lval_read lv loc result); + let new_deps = + match deps with + | None -> None + | Some deps -> + Some (Zone.join deps (valid_enumerate_bits ~for_writing:false loc)) + in + state, new_deps, result + +and eval_lval ~conflate_bottom ~with_alarms deps state lv = + let state, deps, result = + eval_lval_using_main_memory ~conflate_bottom ~with_alarms deps state lv + in + let result_conv = + (* match unrollType (Cil.typeOfLval lv) with + TFloat (FDouble|FFloat as kind, _) -> + let f, r = Cvalue.V.force_float kind result in + if f then Format.printf "TODO: assert@."; + r + | _ -> *) result + in + state, deps, result_conv + +and eval_offset ~reduce_valid_index ~with_alarms deps typ state offset = + match offset with + | NoOffset -> + state, deps, Ival.singleton_zero + | Index (exp,remaining) -> + let typ_pointed,array_size = match (unrollType typ) with + | TArray (t,size,_,_) -> t, size + | TPtr(t,_) -> + (match unrollType t with + | TArray (t,size,_,_) -> t,size (* pointer to start of an array *) + | _ -> + Value_parameters.error ~current:true + "Got type '%a'" !Ast_printer.d_type t; + assert false) + | t -> + Value_parameters.error ~current:true + "Got type '%a'" !Ast_printer.d_type t; + assert false + in + let state, deps, current = + eval_expr_with_deps_state ~with_alarms deps state exp + in + if V.is_bottom current + then Cvalue.Model.bottom, (Some Zone.bottom), Ival.bottom + else + let state, offset = + try + let v = V.project_ival current in + let state, v = + if reduce_valid_index then + try + let array_siz = lenOfArray64 array_size in + let new_v = + Ival.narrow + (Ival.inject_range + (Some Int.zero) + (Some (My_bigint.pred array_siz))) + v + in + let new_state = + if Ival.equal new_v v + then state + else begin + begin + match with_alarms.CilE.others with + | CilE.Aignore -> () + | CilE.Acall f -> f () + | CilE.Alog _ -> + CilE.set_syntactic_context + (CilE.SyBinOp + (IndexPI, + exp, + Cilutil.out_some array_size)); + CilE.warn_index with_alarms "accessing" + (Pretty_utils.sfprintf "%a" V.pretty current); + end; + state (* TODO : if the index is a variable, reduce *) + end + in + new_state, new_v + with LenOfArray -> state, v + else state, v + in + state, v + with V.Not_based_on_null -> + let deps, offset = + topify_offset + ~with_alarms + deps + state + (Cvalue.V.topify_arith_origin current) + remaining + in + raise (Offset_not_based_on_Null (deps,offset)) + in + let state, deps, r = + eval_offset ~reduce_valid_index ~with_alarms + deps typ_pointed state remaining + in + let offset = Ival.scale_int64base (sizeof typ_pointed) offset in + state, deps, Ival.add offset r + | Field (fi,remaining) -> + let current,_ = bitsOffset typ (Field(fi,NoOffset)) in + let state, deps, r = + eval_offset ~reduce_valid_index ~with_alarms + deps + fi.ftype + state + remaining + in + state, deps, Ival.add (Ival.of_int current) r +and topify_offset ~with_alarms deps state acc offset = + match offset with + | NoOffset -> deps,acc + | Field (_fi,remaining) -> topify_offset ~with_alarms deps state acc remaining + | Index (exp,remaining) -> + let deps, loc_index = eval_expr_with_deps ~with_alarms deps state exp in + let acc = Location_Bytes.join + (Cvalue.V.topify_arith_origin loc_index) + acc + in + topify_offset ~with_alarms deps state acc remaining + + +let eval_as_exact_loc ~with_alarms state e = + try + let lv = find_lv ~with_alarms state e in + let loc = lval_to_loc ~with_alarms state lv in + if not (valid_cardinal_zero_or_one ~for_writing:false loc) + then raise Not_an_exact_loc; + let typ = typeOfLval lv in + let value_for_loc = + Cvalue.Model.find ~conflate_bottom:true ~with_alarms state loc in + (* Using (typeOf e) caused imprecisions with the condition + char c; ... if (c>0) being transformed in if (((int)c)>0) by Cil. *) + let value_for_loc2 = do_cast ~with_alarms typ value_for_loc in + let value_for_loc2 = + cast_lval_when_bitfield lv ~sizebf:loc.size value_for_loc2 + in + if Cvalue.V.has_sign_problems value_for_loc && + not (Cvalue.V.equal value_for_loc value_for_loc2) + then raise Not_an_exact_loc; + loc, value_for_loc2, typ + with Cannot_find_lv -> + raise Not_an_exact_loc + +let eval_symetric_int positive binop cond_expr value = + match positive,binop with + | false, Eq | true, Ne -> V.diff_if_one value cond_expr + | true, Eq | false, Ne -> V.narrow value cond_expr + | _,_ -> value + +let eval_symetric_float = eval_symetric_int + +let eval_antisymetric_int ~typ_loc:_ positive binop cond_expr value = + try match positive,binop with + | true, Le | false, Gt -> V.filter_le value ~cond_expr + | true, Ge | false, Lt -> V.filter_ge value ~cond_expr + | false, Le | true, Gt -> V.filter_gt value ~cond_expr + | false, Ge | true, Lt -> V.filter_lt value ~cond_expr + | _,_ -> value + with V.Error_Bottom -> V.bottom + +let eval_antisymetric_float round ~typ_loc positive binop cond_expr value = + try let r = match positive,binop with + | true, Le | false, Gt -> V.filter_le_float round ~typ_loc value ~cond_expr + | true, Ge | false, Lt -> V.filter_ge_float round ~typ_loc value ~cond_expr + | false, Le | true, Gt -> V.filter_gt_float round ~typ_loc value ~cond_expr + | false, Ge | true, Lt -> V.filter_lt_float round ~typ_loc value ~cond_expr + | _,_ -> value + in + r + with V.Error_Bottom -> V.bottom + + +type eval_int_float = { + eval_symetric: bool -> binop -> V.t -> V.t -> V.t; + eval_antisymetric: typ_loc:typ -> bool -> binop -> V.t -> V.t -> V.t; +} + +let eval_int = { + eval_symetric = eval_symetric_int; + eval_antisymetric = eval_antisymetric_int; +} + +let eval_float round = { + eval_symetric = eval_symetric_float; + eval_antisymetric = eval_antisymetric_float round; +} + +let eval_from_type t round = + if isIntegralType t || isPointerType t + then eval_int + else eval_float round + +(** Reduce the state for comparisons of the form 'v Rel k', where v + evaluates to a location, and k to some value *) +let reduce_by_left_comparison ~with_alarms eval pos expl binop expr state = + try + let loc,value_for_loc,typ_loc = eval_as_exact_loc ~with_alarms state expl in +(* Format.printf "red_by_left1 %a %a %a@." + Locations.pretty loc + Cvalue.V.pretty value_for_loc + !d_type typ_loc; *) + let cond_v = eval_expr ~with_alarms state expr in + let v_sym = eval.eval_symetric pos binop cond_v value_for_loc in + let v_asym = eval.eval_antisymetric ~typ_loc pos binop cond_v v_sym in +(* Format.printf "red_by_left %a@." Cvalue.V.pretty v_asym; *) + if V.equal v_asym V.bottom then raise Reduce_to_bottom; + if V.equal v_asym value_for_loc + then state, Some loc + else + ( Cvalue.Model.reduce_binding + ~with_alarms:CilE.warn_none_mode + state loc v_asym, + Some loc ) + with Not_an_exact_loc -> state, None + +(** Reduce the state for comparisons of the form + 'v Rel k', 'k Rel v' or 'v = w' *) +let reduce_by_comparison ~with_alarms eval pos exp1 binop exp2 state = +(* Format.printf "red_by %a@." Cvalue.Model.pretty state; *) + let state, _loc1 = reduce_by_left_comparison ~with_alarms eval + pos exp1 binop exp2 state + in + let inv_binop = match binop with + | Gt -> Lt | Lt -> Gt | Le -> Ge | Ge -> Le + | _ -> binop + in + let state, _loc2 = reduce_by_left_comparison ~with_alarms eval + pos exp2 inv_binop exp1 state + in +(* Format.printf "red_by1 %a@." Cvalue.Model.pretty state; *) + (* Without relations, this is now the identity + begin match (pos, binop), loc1, loc2 with + | ((true, Eq) | (false, Ne)), Some left_loc , Some right_loc -> + Cvalue.Model.reduce_equality state left_loc right_loc + | _ -> state + end + *) + state + +(** raises [Reduce_to_bottom] and never returns [Cvalue.Model.bottom]*) +let reduce_by_cond ~with_alarms state cond = + (* Do not reduce anything if the cond is volatile. + (This test is dumb because the cond may contain volatile l-values + without the "volatile" attribute appearing at toplevel. pc 2007/11) *) +(* Format.printf "eval_cond %B %a@." cond.positive (!d_exp) cond.exp; *) + if hasAttribute "volatile" (typeAttr (typeOf cond.exp)) then state + else + let rec aux cond state = + match cond.positive,cond.exp.enode with + | _positive, BinOp ((Le|Ne|Eq|Gt|Lt|Ge as binop), exp1, exp2, _typ) -> + let eval = eval_from_type (unrollType (typeOf exp1)) + (Value_parameters.AllRoundingModes.get ()) + in + reduce_by_comparison ~with_alarms eval + cond.positive exp1 binop exp2 state + + | true, BinOp (LAnd, exp1, exp2, _) + | false, BinOp (LOr, exp1, exp2, _) -> + let new_state = aux {cond with exp = exp1} state in + let result = aux {cond with exp = exp2} new_state in + result + | false, BinOp (LAnd, exp1, exp2, _) + | true, BinOp (LOr, exp1, exp2, _) -> + let new_v1 = try aux {cond with exp = exp1} state + with Reduce_to_bottom -> Cvalue.Model.bottom + in let new_v2 = try aux {cond with exp = exp2} state + with Reduce_to_bottom -> Cvalue.Model.bottom + in let r = Cvalue.Model.join new_v1 new_v2 in + if Db.Value.is_reachable r then r else raise Reduce_to_bottom + + | _, UnOp(LNot,exp,_) -> + aux { positive = not cond.positive; exp = exp; } state + | _, Lval _ when (let t = typeOf cond.exp in + isIntegralType t || isPointerType t) + -> (* "if (c)" is equivalent to "if(!(c==0))" *) + (try + let loc,value_for_loc,_ = + eval_as_exact_loc ~with_alarms state cond.exp in + let new_value = eval_symetric_int + (not cond.positive) Eq V.singleton_zero value_for_loc + in + if V.equal new_value V.bottom then raise Reduce_to_bottom + else + Cvalue.Model.reduce_binding + ~with_alarms:CilE.warn_none_mode state loc new_value + with Not_an_exact_loc -> state) + | _ -> state + in + let result = aux cond state in + let contains_zero = + if Value_parameters.UndefinedPointerComparisonPropagateAll.get() + then V.contains_zero + else (fun x -> V.is_included V.singleton_zero x) + in + let condition_may_still_be_true_in_state state = + let cond_interp = eval_expr ~with_alarms state cond.exp in + (not cond.positive || V.contains_non_zero cond_interp) && + (cond.positive || contains_zero cond_interp) + in + if (not (Cvalue.Model.equal result state)) && + (not (condition_may_still_be_true_in_state result)) + then raise Reduce_to_bottom; + let is_enumerable v = + let v_interp = + Cvalue.Model.find ~conflate_bottom:true ~with_alarms result v + in + ignore (Location_Bytes.cardinal_less_than v_interp 7); + v_interp + in + let rec enumerate_one_var l = + match l with + | [] -> raise Not_found + | v::t -> + try + let v_interp = is_enumerable v in + v,v_interp,t + with Abstract_interp.Not_less_than -> + enumerate_one_var t + in + let invert_cond vl = + try + let v1,v_interp1, _tail = enumerate_one_var vl in +(* Format.printf "enumerate %a %a@." + Locations.pretty v1 + Cvalue.V.pretty v_interp1; *) + let f one_val acc = + (* interpret cond in an environment where v -> one_val + *) + let env = + Cvalue.Model.reduce_binding + ~with_alarms:CilE.warn_none_mode + result v1 one_val + in + let stays = condition_may_still_be_true_in_state env in +(* Format.printf "enumerate %a stays:%B@." + Cvalue.V.pretty one_val + stays; *) + if stays + then begin + Location_Bytes.join one_val acc + end + else begin + acc + end + in + let new_v_interp = + Location_Bytes.fold_enum + ~split_non_enumerable:2 + f v_interp1 Location_Bytes.bottom + in + let state_value = + if V.equal new_v_interp V.bottom + then raise Reduce_to_bottom + else + Cvalue.Model.reduce_binding + ~with_alarms:CilE.warn_none_mode + result v1 new_v_interp + in + state_value + with Not_found -> result + in + let result = + invert_cond (get_influential_vars ~with_alarms result cond.exp) + in + if not (Cvalue.Model.is_reachable result) + then raise Reduce_to_bottom + else result + + +let resolv_func_vinfo ~with_alarms deps state funcexp = + match funcexp.enode with + | Lval (Var vinfo,NoOffset) -> + Kernel_function.Hptset.singleton (Globals.Functions.get vinfo), deps + | Lval (Mem v,NoOffset) -> + let deps, loc = eval_expr_with_deps ~with_alarms deps state v in + let fundecs = List.fold_left + (fun acc varid -> + match varid with + | Base.String (_,_) -> + warning_once_current + "Function pointer call at string position in memory: \ + ignoring this particular value: assert(TODO)"; + acc + | Base.Null -> + warning_once_current + "Function pointer call at absolute position in memory: \ + ignoring this particular value: assert(TODO)"; + acc + | Base.Var (v,_) | Base.Initialized_Var (v,_) -> + Kernel_function.Hptset.add (Globals.Functions.get v) acc + ) + Kernel_function.Hptset.empty + (try Location_Bytes.get_keys_exclusive Ival.zero loc + with Location_Bytes.Not_all_keys -> + warning_once_current + "Function pointer call is completely unknown: \ + assuming no effects: assert(TODO)"; + raise Leaf) + in + fundecs, deps + | _ -> + assert false + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval_exprs.mli frama-c-20111001+nitrogen+dfsg/src/value/eval_exprs.mli --- frama-c-20110201+carbon+dfsg/src/value/eval_exprs.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval_exprs.mli 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,197 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Locations + +exception Reduce_to_bottom +exception Cannot_find_lv +exception Too_linear +exception Leaf + +type cond = { exp : exp; positive : bool; } + +val check_comparable : + binop -> + Location_Bytes.t -> + Location_Bytes.t -> + bool * Location_Bytes.t * Location_Bytes.t + +val do_cast : + with_alarms:CilE.warn_mode -> typ -> Cvalue.V.t -> Cvalue.V.t + + +val eval_binop_float : + with_alarms:CilE.warn_mode -> + Cvalue.V.t -> binop -> Cvalue.V.t -> Cvalue.V.t +val eval_binop_int : + with_alarms:CilE.warn_mode -> + ?typ:typ -> + te1:typ -> + Cvalue.V.t -> binop -> Cvalue.V.t -> Cvalue.V.t + +val eval_unop: + with_alarms:CilE.warn_mode -> + Cvalue.V.t -> + typ (** Type of the expression under the unop *) -> + Cil_types.unop -> Cvalue.V.t + + +val is_bitfield : + lval -> ?sizelv:Int_Base.t -> ?sizebf:Int_Base.t -> unit -> bool + +val lval_to_loc : + with_alarms:CilE.warn_mode -> + Cvalue.Model.t -> lval -> location +val exp_lval_to_loc : + Cvalue.Model.t -> exp -> lval * location +val lval_to_loc_deps_option : + with_alarms:CilE.warn_mode -> + deps:Zone.t option -> + Cvalue.Model.t -> + reduce_valid_index:Kernel.SafeArrays.t -> + lval -> + Cvalue.Model.t * Zone.t option * location +val lval_to_loc_with_offset_deps_only : + deps:Zone.t -> + Cvalue.Model.t -> + lval -> + with_alarms:CilE.warn_mode -> + Cvalue.Model.t * Zone.t option * location +val lval_to_loc_with_deps : + deps:Zone.t -> + Cvalue.Model.t -> + lval -> + with_alarms:CilE.warn_mode -> + reduce_valid_index:Kernel.SafeArrays.t -> + Cvalue.Model.t * Zone.t option * location +val lval_to_loc_with_offset_deps_only_option : + with_alarms:CilE.warn_mode -> + deps:Zone.t option -> + Cvalue.Model.t -> + lval -> + Cvalue.Model.t * Zone.t option * location +val pass_cast : + with_alarms:CilE.warn_mode -> + Cvalue.Model.t -> exn -> typ -> exp -> unit +val find_lv : + with_alarms:CilE.warn_mode -> + Cvalue.Model.t -> exp -> lval +val find_lv_plus : + with_alarms:CilE.warn_mode -> + Cvalue.Model.t -> exp -> (lval * Ival.t) list +val base_to_loc : + with_alarms:CilE.warn_mode -> + ?deps:Zone.t -> + Cvalue.Model.t -> + lval -> + lhost -> + Ival.t -> Cvalue.Model.t * Zone.t option * location +val eval_expr : + with_alarms:CilE.warn_mode -> Cvalue.Model.t -> exp -> Cvalue.V.t +val get_influential_vars : + with_alarms:CilE.warn_mode -> + Cvalue.Model.t -> exp -> location list +val reduce_by_valid_expr : + positive:bool -> + for_writing:bool -> exp -> Cvalue.Model.t -> Cvalue.Model.t +val reduce_by_valid_loc : + positive:bool -> + for_writing:bool -> location -> typ -> Cvalue.Model.t -> Cvalue.Model.t +val reduce_by_initialized_loc : + with_alarms:'a -> + positive:bool -> + typ * Location_Bytes.t -> + Cvalue.Model.t -> Cvalue.Model.t +val eval_BinOp : + with_alarms:CilE.warn_mode -> + exp -> + Zone.t option -> + Cvalue.Model.t -> Cvalue.Model.t * Zone.t option * Cvalue.V.t +val eval_expr_with_deps : + with_alarms:CilE.warn_mode -> + Zone.t option -> + Cvalue.Model.t -> exp -> Zone.t option * Cvalue.V.t +val eval_expr_with_deps_state : + with_alarms:CilE.warn_mode -> + Zone.t option -> + Cvalue.Model.t -> + exp -> + Cvalue.Model.t * Zone.t option * Location_Bytes.t +val eval_expr_with_deps_state_subdiv : + with_alarms:CilE.warn_mode -> + Zone.t option -> + Cvalue.Model.t -> + exp -> + Cvalue.Model.t * Zone.t option * Location_Bytes.t +val cast_lval_bitfield : + lval -> Abstract_interp.Int.t -> Cvalue.V.t -> Cvalue.V.t +val cast_lval_when_bitfield : + lval -> + ?sizelv:Int_Base.t -> ?sizebf:Int_Base.t -> Cvalue.V.t -> Cvalue.V.t +val eval_lval_using_main_memory : + conflate_bottom:bool -> + with_alarms:CilE.warn_mode -> + Zone.t option -> + Cvalue.Model.t -> + lval -> Cvalue.Model.t * Zone.t option * Cvalue.V.t +val eval_lval : + conflate_bottom:bool -> + with_alarms:CilE.warn_mode -> + Zone.t option -> + Cvalue.Model.t -> + lval -> Cvalue.Model.t * Zone.t option * Cvalue.V.t +val eval_offset : + reduce_valid_index:bool -> + with_alarms:CilE.warn_mode -> + Zone.t option -> + typ -> + Cvalue.Model.t -> + offset -> Cvalue.Model.t * Zone.t option * Ival.t +val eval_as_exact_loc : + with_alarms:CilE.warn_mode -> + Cvalue.Model.t -> + exp -> location * Cvalue.V.t * typ +type eval_int_float = { + eval_symetric : + bool -> binop -> Cvalue.V.t -> Cvalue.V.t -> Cvalue.V.t; + eval_antisymetric : + typ_loc:typ -> + bool -> binop -> Cvalue.V.t -> Cvalue.V.t -> Cvalue.V.t; +} +val eval_int : eval_int_float +val eval_float : bool -> eval_int_float +val eval_from_type : typ -> bool -> eval_int_float +val reduce_by_comparison : + with_alarms:CilE.warn_mode -> + eval_int_float -> + bool -> + exp -> + binop -> exp -> Cvalue.Model.t -> Cvalue.Model.t +val reduce_by_cond : + with_alarms:CilE.warn_mode -> Cvalue.Model.t -> cond -> Cvalue.Model.t +val resolv_func_vinfo : + with_alarms:CilE.warn_mode -> + Zone.t option -> + Cvalue.Model.t -> + exp -> Kernel_function.Hptset.t * Zone.t option + diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval_funs.ml frama-c-20111001+nitrogen+dfsg/src/value/eval_funs.ml --- frama-c-20110201+carbon+dfsg/src/value/eval_funs.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval_funs.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,583 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Value analysis of statements *) + +open Cil_types +open Cil +open Cil_datatype +open Locations +open Abstract_interp +open Bit_utils +open Cvalue +open Value_util +open Eval_exprs +open Locals_scoping + +module StmtCanReachCache = + Kernel_function.Make_Table + (Datatype.Function + (struct include Cil_datatype.Stmt let label = None end) + (Datatype.Function + (struct include Cil_datatype.Stmt let label = None end) + (Datatype.Bool))) + (struct + let name = "Eval_funs.StmtCanReachCache" + let kind = `Internal + let size = 17 + let dependencies = [ Ast.self ] + end) + +let stmt_can_reach_memo = StmtCanReachCache.memo Stmts_graph.stmt_can_reach + +let compute_using_cfg kf ~call_kinstr initial_state = + match kf.fundec with + | Declaration _ -> assert false + | Definition (f,_loc) -> + begin + let f_varinfo = f.svar in + let module Computer = + Eval_stmts.Computer + (struct + let current_kf = kf + let stmt_can_reach = + if Value_parameters.MemoryFootprint.get () >= 3 + then stmt_can_reach_memo kf + else Stmts_graph.stmt_can_reach kf + let is_natural_loop = Loop.is_natural kf + let non_linear_assignments = Non_linear.find f + let slevel = get_slevel kf + let initial_state = initial_state (* for future reference *) + let active_behaviors = + Eval_logic.ActiveBehaviors.create initial_state kf + end) + in + let module Compute = Dataflow.Forwards(Computer) in + List.iter + (function {called_kf = g} -> + if kf == g + then begin + if Value_parameters.IgnoreRecursiveCalls.get() + then begin + warning_once_current + "ignoring recursive call during value analysis of %a (%a)" + Varinfo.pretty f_varinfo + pretty_call_stack (call_stack ()); + Db.Value.recursive_call_occurred kf; + raise Leaf + end + else begin + warning_once_current + "@[recursive call@ during@ value@ analysis@ (%a <- %a)@.Use %s@ to@ ignore@ (beware@ this@ will@ make@ the analysis@ unsound)@]" + Varinfo.pretty f_varinfo + pretty_call_stack (call_stack ()) + Value_parameters.IgnoreRecursiveCalls.option_name; + raise (Extlib.NotYetImplemented "recursive calls in value analysis") + end + end) + (call_stack ()); + push_call_stack {called_kf = kf; + call_site = call_kinstr; + called_merge_current = Computer.merge_current}; + match f.sbody.bstmts with + [] -> assert false + | start :: _ -> + let ret_id = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> assert false + in + (* We start with only the start block *) + Computer.StmtStartData.add + start + (Computer.computeFirstPredecessor + start + { + Computer.counter_unroll = 0; + value = initial_state}); + begin try + Compute.compute [start] + with Db.Value.Aborted as e -> + (* State_builder.was aborted: pop the call stack and inform + the caller *) + pop_call_stack (); + raise e + end; + let last_ret,_,last_clob as last_state = + try + let _,state,_ as result = + try + Computer.externalize ret_id kf + with Not_found -> assert false + in + if Cvalue.Model.is_reachable state + then begin + try + if hasAttribute "noreturn" f_varinfo.vattr + then + warning_once_current + "function %a may terminate but has the noreturn attribute" + Kernel_function.pretty kf; + with Not_found -> assert false + end + else raise Not_found; + result + with Not_found -> begin + None, + Cvalue.Model.bottom, + Location_Bits.Top_Param.bottom + end + in + Value_parameters.debug + "@[RESULT FOR %a <-%a:@\n\\result -> %a@\nClobered set:%a@]" + Kernel_function.pretty kf + pretty_call_stack (call_stack ()) + (fun fmt v -> + match v with + | None -> () + | Some v -> V_Offsetmap.pretty fmt v) + last_ret + Location_Bits.Top_Param.pretty + last_clob; + pop_call_stack (); + last_state + end + +let compute_using_prototype kf ~active_behaviors ~state_with_formals = +(* Format.printf "compute_using_prototype %s %a@." + (Kernel_function.get_name kf) + Cvalue.Model.pretty state_with_formals; *) + let vi = Kernel_function.get_vi kf in + if Cil.hasAttribute "noreturn" vi.vattr then + None, Cvalue.Model.bottom, Location_Bits.Top_Param.bottom + else + let return_type,_formals_type,_inline,_attr = + splitFunctionType (Kernel_function.get_type kf) + in + let behaviors = + Eval_logic.ActiveBehaviors.active_behaviors active_behaviors in + let assigns = Ast_info.merge_assigns behaviors in + let returned_value, state_with_formals = + Library_functions.returned_value kf return_type state_with_formals + in + let returned_value = ref returned_value in + let clobbered_set = ref Location_Bits.Top_Param.bottom in + let state = + match assigns with + | WritesAny -> + warning_once_current "Cannot handle empty assigns clause. Assuming assigns \\nothing: be aware this is probably incorrect."; + state_with_formals + | Writes [] -> state_with_formals + | Writes l -> + let treat_assign acc (out, ins) = + let input_contents = + try + match ins with + | FromAny -> Cvalue.V.top_int + | From l -> + List.fold_left + (fun acc term -> + let input_loc = + !Db.Properties.Interp.loc_to_loc + ~result:None + state_with_formals + term.it_content + in + let r = + Cvalue.V.topify_arith_origin( + Cvalue.Model.find + ~conflate_bottom:true + ~with_alarms:CilE.warn_none_mode + state_with_formals + input_loc + ) in + Cvalue.V.join acc r) + Cvalue.V.top_int + l + with Invalid_argument "not an lvalue" -> + warning_once_current + "cannot interpret@ assigns@ in function %a" + Kernel_function.pretty kf; + Cvalue.V.top + in + let treat_output_loc loc acc = + remember_bases_with_locals + clobbered_set + loc + input_contents; + let state = + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:false acc loc input_contents + in + (* ugly; Fix ? Yes. *) + if Cvalue.Model.is_reachable state + then state + else acc + in + try + let loc = !Db.Properties.Interp.loc_to_loc + ~result:None acc out.it_content + in + let st = treat_output_loc loc acc in + if Cvalue.Model.equal Cvalue.Model.top st then ( + Value_parameters.error ~once:true ~current:true + "Cannot@ handle@ assigns@ for %a,@ location@ is@ too@ \ + imprecise@ (%a).@ Assuming@ it@ is@ not@ assigned,@ but@ \ + be@ aware@ this@ is@ incorrect." + d_term out.it_content Locations.pretty loc; + acc) + else st + with + | Invalid_argument "not an lvalue" -> + if Logic_utils.is_result out.it_content then begin + returned_value := + Cvalue.V.join input_contents !returned_value; + acc + end else begin + warning_once_current + "Cannot interpret assigns in function %a; \ + effects will be ignored" + Kernel_function.pretty kf; acc + end + in + (List.fold_left treat_assign state_with_formals l) + in +(* Value_parameters.debug "compute_using_prototype suite %s %a@." + (Kernel_function.get_name kf) + Cvalue.Model.pretty state; *) + let retres_vi, state = + if isVoidType return_type + then None, state + else + let offsetmap = + V_Offsetmap.update_ival + ~with_alarms:CilE.warn_none_mode + ~validity:Base.All + ~offsets:Ival.zero + ~exact:true + ~size:(Int.of_int (bitsSizeOf return_type)) + V_Offsetmap.empty + (Cvalue.V_Or_Uninitialized.initialized !returned_value) + in + let rvi, state = Library_functions.add_retres_to_state + ~with_alarms:CilE.warn_none_mode kf offsetmap state + in + Some rvi, state + in + retres_vi, state, !clobbered_set + +let initial_state_formals kf (state:Cvalue.Model.t) = + match kf.fundec with + | Declaration (_, _, None, _) -> state + | Declaration (_, _, Some l, _) + | Definition ({ sformals = l }, _) -> + List.fold_right + Initial_state.initialize_var_using_type + l + state + +let rec fold_left2_best_effort f acc l1 l2 = + match l1,l2 with + | _,[] -> acc + | [],_ -> + raise Eval_stmts.Wrong_function_type + | (x1::r1),(x2::r2) -> fold_left2_best_effort f (f acc x1 x2) r1 r2 + +let actualize_formals kf state actuals check = + let formals = Kernel_function.get_formals kf in + let treat_one_formal acc (expr,_actual_val,actual_o) formal = + check expr formal; + let loc_without_size = + Location_Bits.inject + (Base.create_varinfo formal) + (Ival.zero) + in + Cvalue.Model.paste_offsetmap CilE.warn_none_mode + actual_o + loc_without_size + Int.zero + (Int_Base.project (sizeof_vid formal)) + true + acc + in + fold_left2_best_effort + treat_one_formal + state + actuals + formals + +let () = + Db.Value.add_formals_to_state := + (fun state kf exps -> + try + let compute_actual = Eval_stmts.compute_actual + ~with_alarms:CilE.warn_none_mode (false, false) in + let actuals = List.map (compute_actual state) exps in + actualize_formals kf state actuals + (fun _ _ -> ()) + with Eval_stmts.Got_bottom -> Cvalue.Model.bottom) + +let compute_using_declaration kf with_formals = + Kf_state.mark_as_called kf; + let stateset = Eval_logic.check_fct_preconditions kf with_formals in + (* TODO: This is a hack. Use a function that checks preconditions without + multiplying the states instead -- or compute_using_prototype several times *) + let active_behaviors = Eval_logic.ActiveBehaviors.create stateset kf in + let state_with_formals = State_set.join stateset in + let retres_vi, result_state, thing = + compute_using_prototype kf ~active_behaviors ~state_with_formals in + let result_state = + Eval_logic.check_fct_postconditions ~result:retres_vi kf ~active_behaviors + ~init_state:(State_set.singleton state_with_formals) + ~post_state:(State_set.singleton result_state) + Normal + in + let result_state = State_set.join result_state in + let result, result_state = match retres_vi with + | None -> None, result_state + | Some vi -> + if not (Cvalue.Model.is_reachable result_state) then + (* This test prevents the call to Model.find_base that would + raise Not_found in this case. *) + None, result_state + else + let value_state = result_state in + let retres_base = Base.create_varinfo vi in + (Some (Cvalue.Model.find_base retres_base value_state)) , + Cvalue.Model.remove_base retres_base result_state + in + let formals = Kernel_function.get_formals kf in + let result_state = + List.fold_left + (fun acc vi -> + Cvalue.Model.remove_base + (Base.create_varinfo vi) + acc) + result_state + formals + in + result, result_state, thing + +(* In the state [initial_state] globals and formals are present + but locals of [kf] are not.*) +let compute_with_initial_state ~call_kinstr kf with_formals = + match kf.fundec with + | Declaration _ -> compute_using_declaration kf with_formals + | Definition (f,_) -> + let with_locals = + List.fold_left + (fun acc local -> + Cvalue.Model.add_binding_not_initialized + acc + (Locations.loc_of_varinfo local)) + with_formals + f.slocals + in + (* Remark: the pre-condition cannot talk about the locals. BUT + check_fct_preconditions split the state into a stateset, hence + it is simpler to apply it to the (unique) state with locals *) + let initial_states= Eval_logic.check_fct_preconditions kf with_locals in + compute_using_cfg ~call_kinstr kf initial_states + +let compute_entry_point kf ~library = + clear_call_stack (); + Kf_state.mark_as_called kf; + Value_parameters.feedback "Analyzing a%scomplete application starting at %a" + (if library then "n in" else " ") + Kernel_function.pretty kf; + + Separate.prologue(); + + let initial_state_globals = + if Db.Value.globals_use_supplied_state () then ( + let r = Db.Value.globals_state () in + Value_parameters.feedback "Initial state supplied by user"; + Value_parameters.debug "@[<hov 0>Values of globals@\n%a@]" + Db.Value.pretty_state_without_null r; + r) + else ( + Value_parameters.feedback "Computing initial state"; + let r = Db.Value.globals_state () in + Value_parameters.feedback "Initial state computed"; + Value_parameters.result + "@[<hov 0>Values of globals at initialization@\n%a@]" + Db.Value.pretty_state_without_null r; + r + ) in + if not (Db.Value.is_reachable initial_state_globals) then begin + Value_parameters.result "Value analysis not started because globals \ + initialization is not computable."; + None, initial_state_globals, Locations.Location_Bits.Top_Param.empty + end else begin + Mark_noresults.run(); + + let with_formals = match Db.Value.fun_get_args () with + | None -> initial_state_formals kf initial_state_globals + | Some actuals -> + let formals = Kernel_function.get_formals kf in + if (List.length formals) <> List.length actuals then + raise Db.Value.Incorrect_number_of_arguments; + let treat_one_formal f a = + (), a, Builtins.offsetmap_of_value ~typ:f.vtype a + in + actualize_formals + kf + initial_state_globals + (List.map2 treat_one_formal formals actuals) + (fun _ _ -> ()) + in + Db.Value.Call_Value_Callbacks.apply (with_formals, [ kf, Kglobal ]); + let result = + compute_with_initial_state kf ~call_kinstr:Kglobal with_formals + in + Value_parameters.feedback "done for function %a" + Kernel_function.pretty kf; + Separate.epilogue(); + result + end + +let compute_call_to_cil_function kf _initial_state with_formals call_kinstr = + let print_progress = Value_parameters.ValShowProgress.get() in + if print_progress then + Value_parameters.feedback + "@[computing for function %a <- %a.@\nCalled from %a.@]" + Kernel_function.pretty kf + pretty_call_stack (call_stack ()) + pretty_loc_simply (CilE.current_stmt()); + let result = match kf.fundec with + | Declaration (_,_,_,_) -> + compute_using_declaration kf with_formals + | Definition (def, _) -> + Kf_state.mark_as_called kf; + if Datatype.String.Set.mem + def.svar.vname (Value_parameters.UsePrototype.get ()) + then + compute_using_declaration kf with_formals + else + compute_with_initial_state kf ~call_kinstr with_formals + in + if print_progress then + Value_parameters.feedback "Done for function %a" + Kernel_function.pretty kf; + result + +(* Compute a call to a possible builtin. Returns [Some result], or [None] + if the call must be computed using the Cil function *) +let compute_call_to_builtin kf initial_state actuals = + let name = Kernel_function.get_name kf in + try + let name, override = + (* Advanced builtins which override a Cil function with a Caml one, but + use the Cil one as backup if the Caml one fails. (None by default) *) + try + let name = Value_parameters.BuiltinsOverrides.find name in + Kf_state.mark_as_called kf; + name, true + with Not_found -> name, false + in + (* Standard builtins with constant names, e.g. Frama_C_cos *) + let abstract_function = Builtins.find_builtin name in + (try + Some (abstract_function initial_state actuals) + with Db.Value.Outside_builtin_possibilities -> + if override then None + else ( + do_degenerate None; + raise Db.Value.Aborted + ) + ) + with Not_found -> + (* Special builtins, such as Frama_C_show_each_foo *) + if Ast_info.can_be_cea_function name then + (* A few special functions that are not registered in the builtin table *) + if Ast_info.is_cea_dump_function name then + Some (Builtins.dump_state initial_state) + else if Ast_info.is_cea_alloc_with_validity name then + Some (Builtins.alloc_with_validity initial_state actuals) + else if Ast_info.is_cea_function name then + Some (Builtins.dump_args name initial_state actuals) + else if Ast_info.is_cea_dump_file_function name then + Some (Builtins.dump_state_file name initial_state actuals) + else + None + else None + +let compute_call kf ~call_kinstr initial_state actuals = + let with_formals = + actualize_formals kf initial_state actuals + (fun expr formal -> + if bitsSizeOf (typeOf expr) <> bitsSizeOf (formal.vtype) + then raise Eval_stmts.Wrong_function_type) + in + Db.Value.merge_initial_state kf with_formals; + let stack_without_call = for_callbacks_stack () in + Db.Value.Call_Value_Callbacks.apply + (with_formals, ((kf, call_kinstr) :: stack_without_call)); + match compute_call_to_builtin kf initial_state actuals with + | Some r -> r + | None -> + compute_call_to_cil_function kf initial_state with_formals call_kinstr + +let () = Eval_stmts.compute_call_ref := compute_call + +let floats_ok () = + let u = min_float /. 2. in + let u = u /. 2. in + 0. < u && u < min_float + +let cleanup () = + StmtCanReachCache.clear () + +let force_compute () = + assert (floats_ok ()); + try + let kf, library = Globals.entry_point () in + ignore (compute_entry_point kf ~library); + Db.Value.mark_as_computed (); + cleanup (); + (* Remove redundant alarms *) + if Value_parameters.RmAssert.get() then !Db.Scope.rm_asserts () + with + | Db.Value.Aborted -> + cleanup (); + (* This case is reached only if [do_degenerate] did not raise another + exception to handle abortion properly. See the behavior of the GUI + in case of degeneration to understand the machinery. *) + Db.Value.mark_as_computed (); + Value_parameters.abort + "Degeneration occured:@\nresults are not correct for lines of code \ +that can be reached from the degeneration point." + | Globals.No_such_entry_point _ as exn -> raise exn + | exn -> Db.Value.mark_as_computed (); raise exn + +let _self = + Db.register_compute "Value.compute" + [ Db.Value.self ] + Db.Value.compute + (fun () -> if not (Db.Value.is_computed ()) then force_compute ()) + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval_funs.mli frama-c-20111001+nitrogen+dfsg/src/value/eval_funs.mli --- frama-c-20110201+carbon+dfsg/src/value/eval_funs.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval_funs.mli 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval_logic.ml frama-c-20111001+nitrogen+dfsg/src/value/eval_logic.ml --- frama-c-20110201+carbon+dfsg/src/value/eval_logic.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval_logic.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,1061 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil +open Cil_datatype +open Eval_exprs +open Locations +open Abstract_interp +open Cvalue +open Bit_utils +open Value_util + + +(** Truth values for a predicate analyzed by the value analysis *) + +type predicate_value = True | False | Unknown + +let string_of_predicate_value = function + | Unknown -> "unknown" + | True -> "valid" + | False -> "invalid" + +let pretty_predicate_value fmt v = + Format.fprintf fmt "%s" (string_of_predicate_value v) + +let join_predicate x y = match x, y with + | True, True -> True + | False, False -> False + | True, False | False, True + | Unknown, _ | _, Unknown -> Unknown + +exception Stop + +let fold_join_predicate fold f s = + try + match + fold + (fun acc e -> + match f e with + | Unknown -> raise Stop + | v -> match acc with + | None -> Some v + | Some acc -> Some (join_predicate acc v) + ) + None + s + with + | None -> True + | Some v -> v + with Stop -> Unknown + +(* Exception raised to end the computation for a predicate *) +exception Predicate_alarm +let predicate_alarm () = raise Predicate_alarm + +let warn_raise_mode = + { CilE.imprecision_tracing = CilE.Aignore ; + others = CilE.Acall predicate_alarm ; + unspecified = CilE.Acall predicate_alarm } + + +(** Evaluation environments. Used to evaluate predicate on \at nodes *) + +(* Labels: + pre: pre-state of the function. Equivalent to \old in the postcondition + (and displayed as such) + here: current location, always the intuitive meaning. Assertions are + evaluated before the statement. + post: forbidden in preconditions; + In postconditions: + in function contracts, state of in the post-state + in statement contracts, state after the evaluation of the statement + old: forbidden in assertions. + In statement contracts post, means the state before the statement + In functions contracts post, means the pre-state +*) + +type label = Pre | Here | Old | Post + +type eval_env = { + e_cur: label; + e_pre: Cvalue.Model.t; + e_here: Cvalue.Model.t; + e_old: Cvalue.Model.t option; + e_post: Cvalue.Model.t option; +} + +let join_env e1 e2 = + let join_opt v1 v2 = match v1, v2 with + | None, None -> None + | Some v, None | None, Some v -> Some v + | Some v1, Some v2 -> Some (Cvalue.Model.join v1 v2) + in { + e_cur = (assert (e1.e_cur = e2.e_cur); e1.e_cur); + e_pre = Cvalue.Model.join e1.e_pre e2.e_pre; + e_here = Cvalue.Model.join e1.e_here e2.e_here; + e_old = join_opt e1.e_old e2.e_old; + e_post = join_opt e1.e_post e2.e_post; + } + +let extract_opt_env = function + | Some v -> v + | None -> predicate_alarm () + +let convert_label = function + | StmtLabel _ -> predicate_alarm () + | LogicLabel (_, "Pre") -> Pre + | LogicLabel (_, "Here") -> Here + | LogicLabel (_, "Old") -> Old + | LogicLabel (_, "Post") -> Post + | LogicLabel _ -> predicate_alarm () + +let env_state env = function + | Pre -> env.e_pre + | Here -> env.e_here + | Old -> extract_opt_env env.e_old + | Post -> extract_opt_env env.e_post + +let env_current_state e = env_state e e.e_cur + +let overwrite_state env state = function + | Pre -> { env with e_pre = state } + | Here -> { env with e_here = state } + | Old -> { env with e_old = Some state } + | Post -> { env with e_post = Some state } + +let overwrite_current_state env state = overwrite_state env state env.e_cur + +let env_pre_f ~init = { + e_cur = Here; + e_pre = init; e_here = init; + e_post = None; e_old = None; +} + +let env_post_f ~pre ~post = { + e_cur = Here; + e_pre = pre; e_old = Some pre; + e_post = Some post; e_here = post; +} + +let env_annot ~pre ~here = { + e_cur = Here; + e_pre = pre; e_here = here; + e_post = None; e_old = None; +} + + +let (!!) = Lazy.force + +let lop_to_cop op = + match op with + | Req -> Eq + | Rneq -> Ne + | Rle -> Le + | Rge -> Ge + | Rlt -> Lt + | Rgt -> Gt + +let rec eval_term env result t = + let with_alarms = warn_raise_mode in + match t.term_node with + | Tat (t, lab) -> begin + let lab = convert_label lab in + eval_term { env with e_cur = lab } result t + end + + | TConst (CInt64 (v, _, _)) -> [intType, Cvalue.V.inject_int v] + | TConst (CEnum e) -> + (match (constFold true e.eival).enode with + | Const (CInt64 (v, _, _)) -> [intType, Cvalue.V.inject_int v] + | _ -> raise Predicate_alarm) + | TConst (CChr c) -> [intType, Cvalue.V.inject_int + (Int.of_int (int_of_char c))] + | TConst (CReal (f, _, _)) -> + (* TODO: there might be a problem with float constant present in the + code that have been rounded *) + Value_parameters.result ~once:true "float support is experimental"; + let f = Ival.F.of_float f in + let _, f = Ival.Float_abstract.inject_r f f in + [floatType, Cvalue.V.inject_ival (Ival.Float f)] +(* | TConst ((CStr | CWstr) Missing cases *) + + | TAddrOf _ + | TStartOf _ -> + let conv (typ, loc) = (typ, loc_bits_to_loc_bytes loc) in + List.map conv (eval_tlval env result t) + + | TLval _ -> + let lvals = eval_tlval env result t in + let eval_lval (typ, loc) = + let v = Cvalue.Model.find ~conflate_bottom:false + ~with_alarms (env_current_state env) + (make_loc loc (Bit_utils.sizeof typ)) + in + let v = do_cast ~with_alarms typ v in + (typ, v) + in + List.map eval_lval lvals + + | TBinOp (op,t1,t2) -> begin + let l1 = eval_term env result t1 in + let l2 = eval_term env result t2 in + let aux (te1, v1) (_te2, v2) = + (* Format.printf "T1 %a %a:%a, T2 %a %a:%a@." + d_term t1 Cvalue.V.pretty v1 d_type te1 + d_term t2 Cvalue.V.pretty v2 d_type _te2; *) + let te1 = unrollType te1 in + (* We use the type of t1 to determine whether we are performing + an int or float operation. Hopefully this is correct *) + let v = match te1 with + | TInt _ | TPtr _ | TEnum _ -> + (* Do not pass ~typ here. We want the operations to be + performed on unbounded integers mode *) + eval_binop_int ~with_alarms ~te1 v1 op v2 + | TFloat _ -> + eval_binop_float ~with_alarms v1 op v2 + | _ -> raise Predicate_alarm + in + (te1, v) + in + match op, l1, l2 with + | (PlusA | PlusPI | IndexPI | MinusA | MinusPI), _, _ + | (Eq | Ne), _ , _ -> (* TODO: use set semantics *) + List.fold_left (fun acc e1 -> + List.fold_left (fun acc e2 -> aux e1 e2 :: acc) acc l2) [] l1 + | _, [e1], [e2] -> [aux e1 e2] + | _ -> (*Format.printf "Bla %a %a@." d_term t1 d_term t2;*) + raise Predicate_alarm + end + + | TUnOp (op, t) -> + let l = eval_term env result t in + let typ' t = match op with + | Neg -> t + | BNot -> t (* can only be used on an integer type *) + | LNot -> intType + in + let eval typ v = eval_unop ~with_alarms v typ op in + List.map (fun (typ, v) -> typ' typ, eval typ v) l + + | Trange (otlow, othigh) -> + let eval proj join = function + | None -> None + | Some t -> + let lbound = eval_term env result t in + let aux (typ, v) = + if not (isIntegralType typ) then raise Predicate_alarm; + try proj (Cvalue.V.project_ival v) + with Cvalue.V.Not_based_on_null -> None + in + match List.map aux lbound with + | [] -> raise Predicate_alarm + | h :: q -> + let join v1 v2 = match v1, v2 with + | None, _ | _, None -> None + | Some v1, Some v2 -> Some (join v1 v2) + in + List.fold_left join h q + in + let min = eval Ival.min_int Int.min otlow + and max = eval Ival.max_int Int.max othigh in + [intType, Cvalue.V.inject_ival (Ival.inject_range min max)] + + | TCastE (typ, t) -> + let l = eval_term env result t in + List.map (fun (_, v) -> typ, do_cast ~with_alarms typ v) l + + | Tif (tcond, ttrue, tfalse) -> + let l = eval_term env result tcond in + let vtrue = List.exists (fun (_, v) -> Cvalue.V.contains_non_zero v) l + and vfalse = List.exists (fun (_, v) -> Cvalue.V.contains_zero v) l in + (if vtrue then eval_term env result ttrue else []) + @ (if vfalse then eval_term env result tfalse else []) + + | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ | TAlignOf _ | TAlignOfE _ -> + let e = Cil.constFoldTerm true t in + let r = match e.term_node with + | TConst (CInt64 (v, _, _)) -> Cvalue.V.inject_int v + | _ -> V.top_int + in + [intType, r] + + | _ -> raise Predicate_alarm + +and eval_tlhost env result lv = + match lv with + | TVar { lv_origin = Some v } -> + let loc = Location_Bits.inject (Base.find v) Ival.zero in + [v.vtype, loc] + | TResult typ -> + (match result with + | Some v -> + let loc = Location_Bits.inject (Base.find v) Ival.zero in + [typ, loc] + | None -> raise Predicate_alarm) + | TVar { lv_origin = None } -> (* TODO: add an env for logic vars *) + raise Predicate_alarm + | TMem t -> + let l = eval_term env result t in + List.map (fun (t, loc) -> + match t with + | TPtr (t, _) -> t, loc_bytes_to_loc_bits loc + | _ -> raise Predicate_alarm + ) l + +and eval_toffset env result typ toffset = + match toffset with + | TNoOffset -> + [typ, Ival.singleton_zero] + | TIndex (trm, remaining) -> + let typ_pointed = match (unrollType typ) with + | TArray (t, _, _, _) -> t + | TPtr(t,_) -> + (match unrollType t with + | TArray (t, _,_,_) -> t + | _ -> raise Predicate_alarm) + | _ -> raise Predicate_alarm + in + let lloctrm = eval_term env result trm in + let aux (_typ, current) = + let offset = + try Cvalue.V.project_ival current + with Cvalue.V.Not_based_on_null -> raise Predicate_alarm + in + let loffsrem = eval_toffset env result typ_pointed remaining in + let aux (typ, r) = + let offset = Ival.scale_int64base (sizeof typ_pointed) offset in + typ, Ival.add offset r + in + List.map aux loffsrem + in + List.fold_left (fun acc trm -> aux trm @ acc) [] lloctrm + + | TField (fi,remaining) -> + let current,_ = bitsOffset typ (Field(fi,NoOffset)) in + let loffs = eval_toffset env result fi.ftype remaining in + List.map (fun (typ, r) -> typ, Ival.add (Ival.of_int current) r) loffs + +and eval_tlval env result t = + let process ftyp tlval toffs = + let lvals = eval_tlhost env result tlval in + let aux acc (typ, loc) = + let loffset = eval_toffset env result typ toffs in + let aux acc (typ_offs, offs) = + let loc = Location_Bits.location_shift offs loc in + (ftyp typ_offs, loc) :: acc + in + List.fold_left aux acc loffset + in + List.fold_left aux [] lvals + in + match t.term_node with + | TAddrOf (tlval, toffs) + | TStartOf (tlval, toffs) -> + process (fun typ -> TPtr (typ, [])) tlval toffs + | TLval (tlval, toffs) -> + process (fun typ -> typ) tlval toffs + | Tunion l -> List.concat (List.map (eval_tlval env result) l) + | Tempty_set -> [] + (* TODO: add support for TcastE, by adapting what is done for pass_cast + in eval_exprs.ml *) + | _ -> raise Predicate_alarm + +let eval_tlval_as_location env result t = + let l = eval_tlval env result t in + let aux acc (typ, loc) = + let s = Bit_utils.sizeof typ in + assert (loc_equal acc loc_bottom || Int_Base.equal s acc.size); + make_loc (Location_Bits.join loc acc.loc) s + in + List.fold_left aux loc_bottom l + +exception Not_an_exact_loc + +let eval_term_as_exact_loc env result t = + match t.term_node with + | TLval _ -> + (match eval_tlval env result t with + | [] | _ :: _ :: _ -> raise Not_an_exact_loc + | [typ, loc] -> + let loc = Locations.make_loc loc (Bit_utils.sizeof typ) in + if not (valid_cardinal_zero_or_one ~for_writing:false loc) + then raise Not_an_exact_loc; + typ, loc + ) + | _ -> raise Not_an_exact_loc + +let rec reduce_by_predicate ~result env positive p = + let result = + match positive,p.content with + | true,Ptrue | false,Pfalse -> env + + | true,Pfalse | false,Ptrue -> + overwrite_current_state env Cvalue.Model.bottom + + | true,Pand (p1,p2 ) | false,Por(p1,p2)-> + let r1 = reduce_by_predicate ~result env positive p1 in + reduce_by_predicate ~result r1 positive p2 + + | true,Por (p1,p2 ) | false,Pand (p1, p2) -> + join_env + (reduce_by_predicate ~result env positive p1) + (reduce_by_predicate ~result env positive p2) + + | true,Pimplies (p1,p2) -> + join_env + (reduce_by_predicate ~result env false p1) + (reduce_by_predicate ~result env true p2) + + | false,Pimplies (p1,p2) -> + reduce_by_predicate ~result + (reduce_by_predicate ~result env true p1) + false + p2 + + | _,Pnot p -> reduce_by_predicate ~result env (not positive) p + + | true,Piff (p1, p2) -> + let red1 = + reduce_by_predicate ~result env true (Logic_const.pand (p1, p2)) in + let red2 = + reduce_by_predicate ~result env false (Logic_const.por (p1, p2)) in + join_env red1 red2 + + | false,Piff (p1, p2) -> + reduce_by_predicate ~result env true + (Logic_const.por + (Logic_const.pand (p1, Logic_const.pnot p2), + Logic_const.pand (Logic_const.pnot p1, p2))) + + | _,Pxor(p1,p2) -> + reduce_by_predicate ~result env + (not positive) (Logic_const.piff(p1, p2)) + + | _,Prel (op,t1,t2) -> + begin + try + let eval = match t1.term_type with + | t when isLogicRealOrFloatType t -> + eval_float (Value_parameters.AllRoundingModes.get ()) + | t when isLogicIntegralType t -> eval_int + | Ctype (TPtr _) -> eval_int + | _ -> raise Predicate_alarm + in + reduce_by_relation eval ~result env positive t1 op t2 + with + | Predicate_alarm -> env + | Reduce_to_bottom -> + overwrite_current_state env Cvalue.Model.bottom + (* if the exception was obtained without an alarm emitted, + it is correct to return the bottom state *) + end + + | _,Pvalid ({ term_node = TLval _} as t) -> + begin + try + let l = eval_tlval env result t in + let aux env (typ, lval) = + let loc = make_loc lval (Bit_utils.sizeof typ) in + if valid_cardinal_zero_or_one ~for_writing:false loc then + let state = + reduce_by_valid_loc ~positive ~for_writing:false + loc typ (env_current_state env) + in + overwrite_current_state env state + else env + in + List.fold_left aux env l + with Predicate_alarm -> env + end + | _, Pvalid _ -> env (* no way to reduce for now. *) + + | _,Pinitialized tsets -> + begin try + let locb = eval_term env result tsets in + List.fold_left + (fun env (e, loc) -> + let state = reduce_by_initialized_loc ~with_alarms:warn_raise_mode + ~positive (e, loc) (env_current_state env) + in + overwrite_current_state env state + ) env locb + with + | Predicate_alarm -> env + end + | _,Pat _ -> env + | _,Papp _ + | _,Pexists (_, _) | _,Pforall (_, _) + | _,Pvalid_range (_, _, _)| _,Pvalid_index (_, _) + | _,Plet (_, _) | _,Pif (_, _, _) + | _,Pfresh _ | _,Psubtype _ + | _, Pseparated _ + -> env + in + result + +and reduce_by_relation eval ~result env positive t1 rel t2 = + let env = reduce_by_left_relation eval ~result env positive t1 rel t2 in + let inv_binop = match rel with + | Rgt -> Rlt | Rlt -> Rgt | Rle -> Rge | Rge -> Rle + | _ -> rel + in + reduce_by_left_relation eval ~result env positive t2 inv_binop t1 + +and reduce_by_left_relation eval ~result env positive tl rel tr = + let with_alarms = warn_raise_mode in + try + let state = env_current_state env in + let typ_loc, loc = eval_term_as_exact_loc env result tl in + let value_for_loc = + Cvalue.Model.find ~conflate_bottom:true ~with_alarms state loc in + let value_for_loc = do_cast ~with_alarms typ_loc value_for_loc in + let cond_v = + List.fold_left (fun v (_, v') -> Location_Bytes.join v v') + Location_Bytes.bottom (eval_term env result tr) + in + let op = lop_to_cop rel in + let v_sym = eval.eval_symetric positive op cond_v value_for_loc in + let v_asym = eval.eval_antisymetric ~typ_loc positive op cond_v v_sym in + if V.equal v_asym V.bottom then raise Reduce_to_bottom; + if V.equal v_asym value_for_loc + then env + else + let state' = Cvalue.Model.reduce_binding ~with_alarms state loc v_asym in + overwrite_current_state env state' + with Predicate_alarm | Not_an_exact_loc -> env + + +let rec eval_predicate ~result env pred = + let rec do_eval env p = + match p.content with + | Ptrue -> True + | Pfalse -> False + | Pand (p1,p2 ) -> + begin match do_eval env p1 with + | True -> do_eval env p2 + | False -> False + | Unknown -> + let reduced = reduce_by_predicate ~result env true p1 in + match do_eval reduced p2 with + | False -> False + | _ -> Unknown + end + | Por (p1,p2 ) -> + let val_p1 = do_eval env p1 in + (*Format.printf "Disjunction: state %a p1:%a@." + Cvalue.Model.pretty (env_current_state env) + Cil.d_predicate_named p1; *) + begin match val_p1 with + | True -> True + | False -> do_eval env p2 + | Unknown -> begin + let reduced_state = reduce_by_predicate ~result env false p1 in + (* Format.printf "Disjunction: reduced to %a to eval %a@." + Cvalue.Model.pretty (env_current_state reduced_state) + Cil.d_predicate_named p2; *) + match do_eval reduced_state p2 with + | True -> True + | _ -> Unknown + end + end + | Pxor (p1,p2) -> + begin match do_eval env p1, do_eval env p2 with + | True, True -> False + | False, False -> False + | True, False | False, True -> True + | Unknown, _ | _, Unknown -> Unknown + end + | Piff (p1,p2 ) -> + begin match do_eval env p1,do_eval env p2 with + | True, True | False, False -> True + | Unknown, _ | _, Unknown -> Unknown + | _ -> False + end + | Pat (p, lbl) -> begin + let _env = { env with e_cur = convert_label lbl } in + do_eval env p + end + | Papp _ -> Unknown + | Pvalid tsets -> begin + try + List.iter + (fun (typ, loc) -> + if not (isPointerType typ) + then raise Predicate_alarm (* TODO: global arrays *); + let size = sizeof_pointed typ in + let loc = loc_bytes_to_loc_bits loc in + let loc = Locations.make_loc loc size in + if not (Locations.is_valid ~for_writing:false loc) then ( + (* Maybe the location is guaranteed to be invalid? *) + (if Locations.cardinal_zero_or_one loc then + let valid = valid_part ~for_writing:false loc in + if Location_Bits.equal Location_Bits.bottom valid.loc + then raise Stop; + ); + raise Predicate_alarm + )) + (eval_term env result tsets); + True + with + | Predicate_alarm -> Unknown + | Stop -> False + end + | Pinitialized tsets -> begin + try + let locb = eval_term env result tsets in + fold_join_predicate List.fold_left + (fun (typ, loc) -> + let locbi = loc_bytes_to_loc_bits loc in + let size = match unrollType typ with + | TPtr (t, _) -> bitsSizeOf t + | _ -> assert false + in + let loc = make_loc locbi (Int_Base.inject (Int.of_int size)) in + let value = Cvalue.Model.find_unspecified + ~with_alarms:CilE.warn_none_mode (env_current_state env) loc + in + match value with + | Cvalue.V_Or_Uninitialized.C_uninit_esc v + | Cvalue.V_Or_Uninitialized.C_uninit_noesc v -> + if Location_Bytes.is_bottom v then False else Unknown + | Cvalue.V_Or_Uninitialized.C_init_esc _ + | Cvalue.V_Or_Uninitialized.C_init_noesc _ -> True + ) locb + with + | Cannot_find_lv + | Predicate_alarm -> Unknown + end + | Prel (op,t1,t2) -> begin + try + let t = t1.term_type in (* TODO: t1.term_type and t2.term_type are + sometimes different (Z vs. int, double vs. R, attribute const added, + etc). I think it is always correct to use any of the two types, + but I am not 100% sure *) + let trm = Logic_const.term (TBinOp (lop_to_cop op, t1, t2)) t in + let l = List.map snd (eval_term env result trm) in + if List.for_all + (Location_Bytes.equal Location_Bytes.singleton_zero) l + then False + else if List.for_all + (Location_Bytes.equal Location_Bytes.singleton_one) l + then True + else Unknown + with + | Predicate_alarm -> Unknown + end + | Pexists (varl, p1) | Pforall (varl, p1) -> + let result = + begin try + let env = List.fold_left + (fun acc var -> + match var.lv_origin with + | None -> raise Exit + | Some vi -> + let loc = loc_of_varinfo vi in + let state = + Cvalue.Model.add_binding + ~with_alarms:warn_raise_mode ~exact:true + (env_current_state acc) loc Location_Bytes.top + in + overwrite_current_state env state + ) env varl + in + do_eval env p1 + with + Exit -> Unknown + | Predicate_alarm -> Unknown + end + in + begin match p.content with + | Pexists _ -> if result = False then False else Unknown + | Pforall _ -> if result = True then True else Unknown + | _ -> assert false + end + + | Pnot p -> begin match do_eval env p with + | True -> False + | False -> True + | Unknown -> Unknown + end + | Pimplies (p1,p2) -> + do_eval env (Logic_const.por ((Logic_const.pnot p1), p2)) + | Pseparated (_tset_l) -> Unknown + | Pfresh _ + | Pvalid_range (_, _, _)| Pvalid_index (_, _) + | Plet (_, _) | Pif (_, _, _) + | Psubtype _ + -> Unknown + in + do_eval env pred + +exception Does_not_improve + +let rec fold_on_disjunction f p acc = + match p.content with + | Por (p1,p2 ) -> fold_on_disjunction f p2 (fold_on_disjunction f p1 acc) + | _ -> f p acc + +let count_disjunction p = fold_on_disjunction (fun _pred -> succ) p 0 + +let reduce_by_disjunction ~result ~env states n p = + if State_set.is_empty states + then states + else if (State_set.length states) * (count_disjunction p) <= n + then begin + let treat_state acc state = + let env = overwrite_current_state env state in + let treat_pred pred acc = + let result = reduce_by_predicate ~result env true pred in + if Cvalue.Model.equal (env_current_state result) state + then raise Does_not_improve + else State_set.add (env_current_state result) acc + in + try + fold_on_disjunction treat_pred p acc + with + Does_not_improve -> State_set.add state acc + in + State_set.fold treat_state State_set.empty states + end + else + State_set.fold + (fun acc state -> + let env = overwrite_current_state env state in + let reduced = reduce_by_predicate ~result env true p in + State_set.add (env_current_state reduced) acc) + State_set.empty + states + +module ActiveBehaviors = struct + + let header b = + if Cil.is_default_behavior b then "" + else ", behavior " ^ b.b_name + + let is_active_aux init_states b = + let assumes = + (Logic_const.pands + (List.map Logic_const.pred_of_id_pred b.b_assumes)) + in + fold_join_predicate State_set.fold + (fun init -> eval_predicate ~result:None (env_pre_f init) assumes) + init_states + + type t = { + init_states: State_set.t; + funspec: funspec; + is_active: funbehavior -> predicate_value + } + + module HashBehaviors = Hashtbl.Make( + struct + type t = funbehavior + let equal b1 b2 = b1.b_name = b2.b_name + let hash b = Hashtbl.hash b.b_name + end) + + let create init_states kf = + let funspec = Kernel_function.get_spec kf in + let h = HashBehaviors.create 3 in + { is_active = + (fun b -> + try HashBehaviors.find h b + with Not_found -> + let active = is_active_aux init_states b in + HashBehaviors.add h b active; + active + ); + init_states = init_states; + funspec = funspec; + } + + let active ba = ba.is_active + + let is_active ba b = active ba b != False + + exception No_such_behavior + + let behavior_from_name ab b = + try List.find (fun b' -> b'.b_name = b) ab.funspec.spec_behavior + with Not_found -> raise No_such_behavior + + let active_behaviors ab = + List.filter (is_active ab) ab.funspec.spec_behavior + + (* Is the behavior b the only one currently active. Check if it is in a + group of complete behaviors, and the only one active in its group. + TODO: we should also check that we can prove the 'complete' clause *) + let only_active ab b = + assert (is_active ab b); + let none_other_active group = + let other_not_active b'_name = + b'_name = b.b_name || + (let b' = behavior_from_name ab b'_name in not (is_active ab b')) + in + List.for_all other_not_active group + in + try + let complete = + List.find (List.mem b.b_name) ab.funspec.spec_complete_behaviors + in + none_other_active complete + with + Not_found | No_such_behavior -> false + +end + + +let check_postconditions kf kinstr ~result ~slevel header ~init_state ~active_behaviors ~post_state kind behaviors = + let fused_init = State_set.join init_state in + (* TODO BY: not optimal in reduce_by_disjunction below *) + let e_post = + lazy (env_post_f ~post:(State_set.join post_state) ~pre:fused_init) + in + let incorporate_behavior state b = + if b.b_post_cond = [] then state + else + let header = header ^ ActiveBehaviors.header b in + let posts = List.filter (fun (x,_) -> x = kind) b.b_post_cond in + let update_status st post = + let ip = Property.ip_of_ensures kf kinstr b post in + emit_status ip st + in + match ActiveBehaviors.active active_behaviors b with + | True -> + List.fold_left + (fun acc (_,{ip_content=pred;ip_loc=loc} as post) -> + let source = fst loc in + if State_set.is_empty acc then + (Value_parameters.result ~once:true ~source + "%s: no state left to evaluate postcondition, status not computed.%t" + header pp_callstack; + acc) + else + let pred = Ast_info.predicate loc pred in + let res = fold_join_predicate State_set.fold + (fun state -> + let env = env_post_f ~post:state ~pre:fused_init in + eval_predicate ~result env pred) acc + in + Value_parameters.result ~once:true ~source + "%s: postcondition got status %a.%t" + header pretty_predicate_value res pp_callstack; + match res with + | False -> + update_status Property_status.False_if_reachable post; + State_set.empty + | True -> + update_status Property_status.True post; + (* The reduction is needed in the True case, + because the function is "reduce_by_disjunction". + Example: //@ assert x<0 || x>=0; *) + reduce_by_disjunction ~result ~env:!!e_post acc slevel pred + | Unknown -> + update_status Property_status.Dont_know post; + reduce_by_disjunction ~result ~env:!!e_post acc slevel pred + ) state posts + | Unknown -> + List.fold_left + (fun acc (_,{ip_content=pred;ip_loc=loc} as post) -> + let source = fst loc in + if State_set.is_empty acc then + (Value_parameters.result ~once:true ~source + "%s: no state left to evaluate postcondition, status not computed.%t" + header pp_callstack; + acc) + else + let pred = Ast_info.predicate loc pred in + let res = fold_join_predicate State_set.fold + (fun state -> + let env = env_post_f ~post:state ~pre:fused_init in + eval_predicate ~result env pred) + acc + in + Value_parameters.result ~once:true ~source + "%s: postcondition got status %a.%t" + header pretty_predicate_value res pp_callstack; + match res with + | Unknown | False -> + update_status Property_status.Dont_know post; + Value_parameters.result ~once:true ~source + "%s: postcondition got status %a, \ +but it is unknown if the behavior is active.%t" + header pretty_predicate_value res pp_callstack; + state + | True -> + update_status Property_status.True post; + Value_parameters.result ~once:true ~source + "%s: postcondition got status %a, \ +but it is unknown if the behavior is active.%t" + header pretty_predicate_value res pp_callstack; + state + ) state posts + | False -> + (* if assumes is false, post-condition status is not updated *) + (match posts with + | [] -> () + | (_,{ip_loc=(source,_)})::_ -> + Value_parameters.result ~once:true ~source + "%s: assumes got status invalid; post-condition not evaluated.%t" + header pp_callstack); + state + in + List.fold_left incorporate_behavior post_state behaviors + +let check_fct_postconditions ~result kf ~init_state ~active_behaviors + ~post_state kind = + try + let spec = (Kernel_function.get_spec kf).spec_behavior in + let slevel = get_slevel kf in + check_postconditions kf Kglobal ~result ~slevel + (Pretty_utils.sfprintf "Function %a@?" Kernel_function.pretty kf) + ~init_state ~active_behaviors ~post_state kind spec + with Not_found -> post_state + +let check_preconditions kf kinstr ~slevel header active_behaviors + init_state spec = + let env = env_pre_f (State_set.join init_state) in + let incorporate_behavior states b = + if b.b_requires = [] then states + else + let header = header ^ ActiveBehaviors.header b in + let update_status st vc = + let ip = Property.ip_of_requires kf kinstr b vc in + emit_status ip st + in + match ActiveBehaviors.active active_behaviors b with + | True -> + List.fold_left (fun state ({ip_content=pr;ip_loc=loc} as pre) -> + let source = fst loc in + if State_set.is_empty state then + (Value_parameters.result ~once:true ~source + "%s: no state in which to evaluate precondition, status not computed.%t" + header pp_callstack; + state) + else + let pr = Ast_info.predicate loc pr in + let res = fold_join_predicate State_set.fold + (fun state -> + eval_predicate ~result:None (env_pre_f state) pr) + state + in + Value_parameters.result ~once:true ~source + "%s: precondition got status %a.%t" + header pretty_predicate_value res pp_callstack; + match res with + | False -> + update_status Property_status.False_if_reachable pre; + State_set.empty + | True -> + update_status Property_status.True pre; + (* The reduction is needed in the True case, + because the function is "reduce_by_disjunction". + Example: //@ assert x<0 || x>=0; *) + reduce_by_disjunction ~result:None ~env state slevel pr + | Unknown -> + update_status Property_status.Dont_know pre; + reduce_by_disjunction ~result:None ~env state slevel pr + ) states b.b_requires + | Unknown -> + List.fold_left + (fun state ({ip_content=pr;ip_loc=loc} as pre) -> + let source = fst loc in + if State_set.is_empty state then + (Value_parameters.result ~once:true ~source + "%s: no state in which to evaluate precondition, status not computed.%t" + header pp_callstack; + state) + else + let pr = Ast_info.predicate loc pr in + let res = fold_join_predicate State_set.fold + (fun state -> + eval_predicate ~result:None (env_pre_f state) pr) + state + in + Value_parameters.result ~once:true ~source:(fst loc) + "%s: precondition got status %a.%t" + header pretty_predicate_value res pp_callstack; + match res with + | Unknown | False -> + update_status Property_status.Dont_know pre; + Value_parameters.result ~once:true ~source + "%s: precondition got status %a, \ +but it is unknown if the behavior is active.%t" + header pretty_predicate_value res pp_callstack; + state + | True -> + update_status Property_status.True pre; + Value_parameters.result ~once:true ~source + "%s: precondition got status %a.%t" + header pretty_predicate_value res pp_callstack; + state + ) states b.b_requires + | False -> + (* if assumes is false, post-condition status is not updated *) + (match b.b_requires with + | [] -> () + | {ip_loc=(source,_)}::_ -> + Value_parameters.result ~once:true ~source + "%s: assumption got status invalid; precondition not evaluated.%t" + header pp_callstack); + states + in + List.fold_left + incorporate_behavior + init_state spec.spec_behavior + +(** Check the precondition of [kf]. This may result in splitting [init_state] + into multiple states if the precondition contains disjunctions. The active + behaviors are computed wrt [init_state], but further computations on [kf] + will use active behaviors computed wrt the result of this function. *) +let check_fct_preconditions kf init_state = + let init_states = State_set.singleton init_state in + try + let spec = Kernel_function.get_spec kf in + let slevel = get_slevel kf in + let active_behaviors = ActiveBehaviors.create init_states kf in + check_preconditions kf Kglobal ~slevel + (Pretty_utils.sfprintf "Function %a@?" Kernel_function.pretty kf) + active_behaviors init_states spec + with Not_found -> init_states + + +let () = + Db.Value.valid_behaviors := + (fun kf state -> + let ab = ActiveBehaviors.create (State_set.singleton state) kf in + ActiveBehaviors.active_behaviors ab + ); + Db.Properties.Interp.loc_to_loc := + (fun ~result state t -> + try eval_tlval_as_location (env_pre_f state) result t + with Predicate_alarm -> raise (Invalid_argument "not an lvalue") + ) + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval.ml frama-c-20111001+nitrogen+dfsg/src/value/eval.ml --- frama-c-20110201+carbon+dfsg/src/value/eval.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,5434 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** Analysis for values and pointers *) - -open Cil_types -open Cil -open Cilutil -open Cil_datatype -module Ki = Cil_datatype.Kinstr (* do not mask kinstr in src/value *) -open Db_types -open Locations -open Abstract_interp -open Abstract_value -open Bit_utils -open Cvalue_type -open Extlib -open Ast_printer -open Value_util - -let make_status st = Checked {emitter = "value analysis"; valid = st} -let status_true = make_status Cil_types.True -let status_false = make_status Cil_types.False -let status_maybe = make_status Cil_types.Maybe - -module Status: sig - val join: Property.t -> annotation_status -> unit -end = -struct - - module S = - Properties_status.Make_updater - (struct - let name = "Value" - let emitter = Db.Value.self - end) - -(* let () = - List.iter (fun self -> - Project.State_builder.add_dependency - Db.Value.self - self - ) - [] - (* used to be dependent on a state such as - Properties_status.RTE_Status_Proxy, but not - a good idea after all - *) -*) - let merge old_s new_s = match old_s, new_s with - | Cil_types.Unknown, status | status, Cil_types.Unknown -> - status - | Checked { valid = Maybe },Checked _ - | Checked _ ,Checked { valid = Maybe } - -> status_maybe - | Checked {valid = s1 }, Checked {valid = s2 } when s1 = s2 -> - (* Do not share with argument to be on the safe side *) - make_status s1 - | _ -> status_maybe - - let join ip status = - ignore (S.update ip [] (fun old -> merge old status)) - -end - -type cond = - { exp: exp; (* The condition of the branch*) - positive: bool; (* true: normal false: negated *)} - -let get_slevel kf = - let name = Kernel_function.get_name kf in - Value_parameters.SlevelFunction.find name - -(* Returns boolean telling to display a warning, - and optionally reduce the values of [ev1] and [ev2], - knowing that they are involved in a comparison *) -let check_comparable ev1 ev2 = - try - if not (Location_Bytes.is_included ev1 Location_Bytes.top_int) - || not (Location_Bytes.is_included ev2 Location_Bytes.top_int) - then begin - (* First check if a non-zero integer is compared to an address *) - let null_1, rest_1 = Location_Bytes.split Base.null ev1 in - let null_2, rest_2 = Location_Bytes.split Base.null ev2 in - if (not (Ival.is_included null_1 Ival.zero)) && - (not (Location_Bytes.equal rest_2 Location_Bytes.bottom )) - then raise Not_found; - if (not (Ival.is_included null_2 Ival.zero)) && - (not (Location_Bytes.equal rest_1 Location_Bytes.bottom )) - then raise Not_found; - - (* If both addresses are valid, they can be compared. - If one/both is not valid, the only way they can be - compared is if they are offsets in a same array t. - In this case, if t+n is the address of the last valid - location in t, t+n+1 is allowed in the comparison. - FIXME: Take string literals into account. *) - let loc1 = make_loc (loc_bytes_to_loc_bits rest_1) Int_Base.one in - if (not (Locations.is_valid_or_function loc1)) || - let loc2 = make_loc (loc_bytes_to_loc_bits rest_2) Int_Base.one in - (not (Locations.is_valid_or_function loc2)) - then begin - let base_1, _offs_1 = Location_Bytes.find_lonely_key rest_1 in - let base_2, _offs_2 = Location_Bytes.find_lonely_key rest_2 in - if Base.compare base_1 base_2 <> 0 then raise Not_found; - (* TODO *) - end - end; - false, ev1, ev2 - with Not_found -> - true, ev1, ev2 - - -module type Domain = sig - type state - val eval_expr : - with_alarms:CilE.warn_mode -> state -> exp -> state*Cvalue_type.V.t - val do_assign : with_alarms:CilE.warn_mode -> state -> lval -> exp -> state - val eval_cond : with_alarms:CilE.warn_mode -> state -> cond -> state - val widen : state -> state -> state - val join : state -> state -> state - val call : kernel_function -> state -> state - val return : kernel_function -> state -> state - -end - -module PtrRelational = struct - type state = Relations_type.Model.t - let eval_expr ~with_alarms state expr = match expr.enode with - | BinOp ((MinusA | MinusPP | Eq | Ne | Ge | Le | Gt | Lt as op),e1,e2,_) -> - let state, ev1 = !Db.Value.eval_expr_with_state ~with_alarms state e1 in - let state, ev2 = !Db.Value.eval_expr_with_state ~with_alarms state e2 in - CilE.set_syntactic_context (CilE.SyBinOp (op,e1,e2)); - begin - match unrollType (typeOf e1) with - | TFloat _ -> - state,Cvalue_type.V.top - | TInt _ | TPtr (_, _) | _ (* Enum ? *) -> - let compute_diff acc = - let lv1 = !Db.Value.find_lv_plus ~with_alarms state e1 in - let lv2 = !Db.Value.find_lv_plus ~with_alarms state e2 in - List.fold_left - (fun acc (lv1, offs1) -> - let loc1 = !Db.Value.lval_to_loc_state state lv1 in - List.fold_left - (fun acc (lv2, offs2) -> - let loc2 = !Db.Value.lval_to_loc_state state lv2 in - try - let new_v = - V.location_shift - (Ival.sub offs1 offs2) - (Relations_type.Model.compute_diff - state loc1 loc2) - in - assert (V.is_included new_v acc); - new_v - with Relations_type.Use_Main_Memory -> acc) - acc - lv2) - acc - lv1 - in - match op with - | MinusA -> state,compute_diff Cvalue_type.V.top - | MinusPP -> - let minus_val = compute_diff Cvalue_type.V.top in - let r = - try - let size = Int_Base.project - (sizeof_pointed(Cil.typeOf e1)) - in - let size = Int.div size Int.eight in - if Int.is_one size then - minus_val - else - let minus_val = - Cvalue_type.V.project_ival minus_val - in - Cvalue_type.V.inject_ival - (Ival.scale_div ~pos:true size minus_val) - with - Int_Base.Error_Top - | Cvalue_type.V.Not_based_on_null - | Not_found -> - V.join - (V.topify_arith_origin ev1) - (V.topify_arith_origin ev2) - in - state, r - | Eq | Ne | Ge | Le | Gt | Lt -> - let r = - let warn, ev1, ev2 = check_comparable ev1 ev2 in - if warn - then begin - CilE.warn_pointer_comparison with_alarms; - end; - if warn && Value_parameters.UndefinedPointerComparisonPropagateAll.get () - then V.zero_or_one - else - let f = match op with - | Eq -> V.check_equal true - | Ne -> V.check_equal false - | Ge -> V.comparisons ">=" V.do_ge - | Le -> V.comparisons "<=" V.do_le - | Gt -> V.comparisons ">" V.do_gt - | Lt -> V.comparisons "<" V.do_lt - | _ -> assert false - in - let diff = compute_diff V.top in - let result = f diff V.singleton_zero in - if V.cardinal_zero_or_one result - then result - else f ev1 ev2 - in - state, r - - | _ -> state,Cvalue_type.V.top - - end - | _ -> state,Cvalue_type.V.top -end - - -(* set the value to false for debugging value analysis without relations *) -module UseRelations = - State_builder.Ref - (Datatype.Bool) - (struct let name = "UseRelations" - let dependencies = [] - let kind = `Internal - let default () = true - end) - -let () = - State_dependency_graph.Static.add_dependencies - ~from:UseRelations.self [ Db.Value.self ] - -let compute_call_ref = ref (fun _ -> assert false) - -let remember_bases_with_locals bases_containing_locals left_loc evaled_exp = - if Cvalue_type.V.contains_addresses_of_any_locals evaled_exp then - let clobbered_set = Location_Bits.get_bases left_loc.loc in - bases_containing_locals := - Location_Bits.Top_Param.join clobbered_set !bases_containing_locals - -let timer = ref 0 - -let set_loc kinstr = - match kinstr with - | Kglobal -> CurrentLoc.clear () - | Kstmt s -> CurrentLoc.set (Stmt.loc s) - -exception Leaf (* raised when nothing is known for a function : - no source nor specification *) - -exception Not_an_exact_loc - -exception Reduce_to_bottom - - -module Got_Imprecise_Value = - State_builder.Ref - (Datatype.Bool) - (struct - let name = "Eval.Got_Imprecise_Value" - let dependencies = [ Db.Value.self ] - let kind = `Internal - let default () = false - end) - -module Location_list = Datatype.List (Locations.Location) - -module Non_linear_assignments = - Cil_state_builder.Varinfo_hashtbl - (Ki.Hashtbl.Make(Location_list)) - (struct - let name = "Non linear assignments" - let size = 37 - let dependencies = [ Ast.self ] - let kind = `Internal - end) - - -let pretty_current_cfunction_name fmt = - Kernel_function.pretty_name fmt (current_kf()) - -exception Offset_not_based_on_Null of - Locations.Zone.t option * Location_Bytes.t - -let warn_locals_escape is_block fundec k = - (*TODO: find a better alarm for variables escaping block scope *) - Value_parameters.warning ~current:true ~once:true - "local escaping the scope of %t%a through %a" - (swap (Pretty_utils.pp_cond is_block) "a block of ") - !d_var fundec.svar - Base.pretty k - -let warn_locals_escape_result fundec = - Value_parameters.warning ~current:true ~once:true - "local escaping the scope of %a through \\result" - !d_var fundec.svar - -let do_cast ~with_alarms t expr = - let treat inttype = - match inttype with - | TInt(kind,_) -> - let size = Int.of_int (bitsSizeOf inttype) in - let signed = isSigned kind in - V.cast ~with_alarms ~signed ~size expr - | TFloat (FFloat,_) -> - let addresses, overflow, res = V.cast_float expr in - if addresses - then Value_parameters.warning ~current:true ~once:true - "addresses in float"; - if overflow then Value_parameters.warning ~current:true ~once:true - "overflow in float: %a -> %a. assert(Ook)" - V.pretty expr V.pretty res; - res - | TFloat (FDouble,_) -> - expr - | TFloat (FLongDouble,_) -> - expr - | _ -> assert false - in - match unrollType t with - | TInt _ | TFloat _ as t' -> - treat t' - | TPtr _ -> - treat theMachine.upointType - | TEnum _ -> - if theMachine.enum_are_signed then - treat (TInt(IInt,[])) - else treat (TInt(IUInt,[])) - | TComp _ -> expr (* see test [struct_call.c] *) - | TBuiltin_va_list _ -> - (match with_alarms.CilE.imprecision_tracing with - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> - Value_parameters.warning ~once:true ~current:true - "cast to __builtin_va_list is not precisely implemented yet"); - V.topify_arith_origin expr - | TFun _ -> expr - | TNamed _ -> assert false - | TVoid _ -> assert false - | TArray _ -> assert false - -let do_promotion ~with_alarms ~src_typ ~dest_type v e_src = - match dest_type, src_typ with - | TFloat _, TInt _ -> - Cvalue_type.V.cast_int_to_float ~with_alarms (get_rounding_mode()) v - | TInt (kind,_), TFloat _ -> - let size = bitsSizeOf dest_type in - let signed = isSigned kind in - let alarm_use_as_float, alarm_overflow, r = - Cvalue_type.V.cast_float_to_int ~signed ~size v - in - if alarm_use_as_float - then begin - Value_parameters.warning ~current:true ~once:true - "converting %a to float: assert(Ook)" - !d_exp e_src; - end; - if alarm_overflow - then - Value_parameters.warning ~current:true ~once:true - "Overflow in cast of %a (%a) from floating-point to integer: assert(Ook)" - !d_exp e_src - Cvalue_type.V.pretty v; - r - | _, _ -> v - -let handle_signed_overflow ~with_alarms syntactic_context typ e interpreted_e = - match unrollType typ with - TInt(kind, _) - when Value_parameters.SignedOverflow.get() - && isSigned kind -> - let size = bitsSizeOf typ in - let mn, mx = - let b = Int.power_two (size-1) in - Int.neg b, Int.pred b - in - let mn64 = Int.to_int64 mn in - let mx64 = Int.to_int64 mx in - let warn_under, warn_over = - try - let i = V.project_ival interpreted_e in - let imn, imx = Ival.min_and_max i in - let u = - match imn with - Some bound when Int.ge bound mn -> None - | _ -> Some mn64 - in - let o = - match imx with - Some bound when Int.le bound mx -> None - | _ -> Some mx64 - in - u, o - with V.Not_based_on_null -> - Some mn64, Some mx64 - in - let all_values = - Cvalue_type.V.inject_ival (Ival.inject_range (Some mn) (Some mx)) - in - if V.is_included interpreted_e all_values - then interpreted_e - else begin - CilE.set_syntactic_context syntactic_context; - CilE.warn_signed_overflow with_alarms e - warn_under warn_over; - let r = V.narrow all_values interpreted_e in - Value_parameters.debug - "signed overflow: %a reduced to %a@." - V.pretty interpreted_e - V.pretty r; - r - end - | _ -> interpreted_e - -exception Cannot_find_lv - -exception Too_linear - -let warn_lval_read lv loc contents = - let pretty_param fmt param = - match param with - | Location_Bits.Top_Param.Top -> Format.fprintf fmt "is imprecise" - | Location_Bits.Top_Param.Set _s -> - Format.fprintf fmt "is a garbled mix of %a" - Location_Bits.Top_Param.pretty param - in - let pretty_param_b fmt param = - match param with - | Location_Bytes.Top_Param.Top -> - Format.fprintf fmt "The contents is imprecise" - | Location_Bytes.Top_Param.Set _s -> - Format.fprintf fmt "It contains a garbled mix of %a" - Location_Bytes.Top_Param.pretty param - in - let something_to_warn = - match loc.loc with Location_Bits.Top _ -> true - | Location_Bits.Map _ -> - match contents with - | Location_Bytes.Top _ -> true - | Location_Bytes.Map _ -> false - in - if something_to_warn then - Value_parameters.result ~current:true ~once:true - "reading left-value @[%a@].@ @[%t%t@]" - !Ast_printer.d_lval lv - (fun fmt -> - match lv with - | Mem _, _ -> - (match loc.loc with - | Location_Bits.Top (param,o) when Origin.equal o Origin.top -> - Format.fprintf fmt "The location %a. " - pretty_param param - | Location_Bits.Top (param,orig) -> - Format.fprintf fmt "The location @[%a@]@ because of@ @[%a@],@ " - pretty_param param - Origin.pretty orig - | Location_Bits.Map _ -> - Format.fprintf fmt "The location is @[%a@].@ " - Location_Bits.pretty loc.loc) - | Var _, _ -> ()) - (fun fmt -> - match contents with - | Location_Bytes.Top (param,o) when Origin.equal o Origin.top -> - Format.fprintf fmt "@[%a.@]" - pretty_param_b param - | Location_Bytes.Top (param,orig) -> - Format.fprintf fmt "@[%a@]@ because of@ @[%a.@]" - pretty_param_b param - Origin.pretty orig - | Location_Bytes.Map _ -> ()) - -let rec lval_to_loc ~with_alarms state lv = - let _,_,r = - lval_to_loc_deps_option - ~with_alarms - ~deps:None - ~reduce_valid_index:(Parameters.SafeArrays.get ()) - state - lv - in - r - -and lval_to_loc_deps_option - ~with_alarms ~deps (state:Relations_type.Model.t) ~reduce_valid_index - (base,offset as lv) = - if not (Relations_type.Model.is_reachable state) then - state, deps, loc_bottom - else - let typ = match base with - | Var host -> host.vtype - | Mem x -> typeOf x - in - try - let state, deps, offs = - eval_offset - ~reduce_valid_index - ~with_alarms deps typ state offset - in - base_to_loc ~with_alarms ?deps state lv base offs - with Offset_not_based_on_Null(deps,offset) -> - let state, deps, loc_if_there_wasnt_offset = - base_to_loc ~with_alarms ?deps state lv base Ival.zero - in - state, deps, - loc_bits_to_loc lv - (Location_Bits.join - (loc_bytes_to_loc_bits offset) - loc_if_there_wasnt_offset.loc) - -(* pc says: only called in addrOf *) -and lval_to_loc_with_offset_deps_only - ~deps (state:Relations_type.Model.t) v - = - lval_to_loc_with_offset_deps_only_option ~deps:(Some deps) state v - -and lval_to_loc_with_deps ~deps state lv ~with_alarms = - lval_to_loc_deps_option ~with_alarms ~deps:(Some deps) state lv - -(* pc says: only called in addrOf *) -and lval_to_loc_with_offset_deps_only_option - ~with_alarms ~deps (state:Relations_type.Model.t) (_base, _offset as v) - = - lval_to_loc_deps_option - ~with_alarms ~deps (state:Relations_type.Model.t) (v) - ~reduce_valid_index:false - - -(** Detects if an expression can be considered as a lvalue even though - it is hidden by a cast that does not change the lvalue. - Raises [exn] if it is not an lvalue. - - TODO: When the goal is to recognize the form (cast)l-value == expr, - it would be better and more powerful to have chains of inverse functions *) - -and pass_cast ~with_alarms state exn typ e = - (* type might be the same but their attributes. - But volatile attribute cannot be skipped *) - if not (Cilutil.equals - (typeSigWithAttrs (filterAttributes "volatile") typ) - (typeSigWithAttrs (filterAttributes "volatile") (typeOf e))) - then - (try - let typeofe = typeOf e in - (* Any volatile attribute may have an effect on the expression value *) - if hasAttribute "volatile" (typeAttrs typeofe) - || hasAttribute "volatile" (typeAttrs typ) - then raise exn; - let sztyp = sizeof typ in - let szexpr = sizeof typeofe in - let typ_ge_typeofe = - match sztyp,szexpr with - Int_Base.Value styp, Int_Base.Value sexpr -> Int.ge styp sexpr - | _ -> false - in - if not typ_ge_typeofe then raise exn; - let sityp = is_signed_int_enum_pointer typ in - let sisexpr = is_signed_int_enum_pointer (typeOf e) in - if sityp = sisexpr then () - (* destination type is larger and has the same sign as - the original type *) - else begin (* try to ignore the cast if it acts as identity - on the value [e] even if signed/unsigned - conflict. *) - match unrollType typ with - | TInt _ | TEnum _ -> - let size = Int.of_int (bitsSizeOf typ) in - let signed = sityp in - (try - let old_ival = V.project_ival - (eval_expr ~with_alarms state e) - in - if (Ival.equal - old_ival - (Ival.cast ~size ~signed ~value:old_ival)) - then () (* [e] is not sensitive to cast *) - else raise exn - with - | Not_found - | V.Not_based_on_null -> - raise exn) - (* this is not always injective, thus cannot be - easily reverted. *) - | _ -> raise exn - end - with Neither_Int_Nor_Enum_Nor_Pointer - -> raise exn) - -and find_lv ~with_alarms (state:Relations_type.Model.t) ee = - (* [BM] Do not recognize an lval whenever a volatile is involved to - prevent copy/paste optimization. IS THIS THE RIGHTPLACE PC ?*) - if hasAttribute "volatile" (typeAttrs (typeOf ee)) then - raise Cannot_find_lv; - match ee.enode with - | Lval lv -> lv - | CastE (typ,e) -> - ( match unrollType typ, unrollType (typeOf e) with - TFloat (FDouble,_), TFloat _ -> find_lv ~with_alarms state e - (* see remark at pass_cast about inverse functions *) - | _ -> - pass_cast ~with_alarms state Cannot_find_lv typ e; - find_lv ~with_alarms state e) - | _ -> raise Cannot_find_lv - -and find_lv_plus ~with_alarms state e = - let acc = ref [] in - let rec find_lv_plus_rec e current_offs = - try - let lv = find_lv ~with_alarms state e in - if not (hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lv))) - then acc := (lv,current_offs) :: !acc - with Cannot_find_lv -> - match e.enode with - BinOp(op, e1, e2, typ) -> - begin - match unrollType typ with - TFloat _ -> () - | _ -> begin - match op with - PlusA -> - let ev1 = eval_expr ~with_alarms state e1 in - let ev2 = eval_expr ~with_alarms state e2 in - ( try - let ival1 = V.project_ival ev1 in - find_lv_plus_rec e2 (Ival.add current_offs ival1) - with V.Not_based_on_null -> ()); - ( try - let ival2 = V.project_ival ev2 in - find_lv_plus_rec e1 (Ival.add current_offs ival2) - with V.Not_based_on_null -> ()); - | (MinusA|MinusPI|PlusPI|IndexPI as b) -> - let ev2 = eval_expr ~with_alarms state e2 in - ( try - let ival2 = V.project_ival ev2 in - let ival2 = - if b = MinusA - then ival2 - else - let ival2 = - Ival.scale - (Int_Base.project (osizeof_pointed typ)) - ival2 - in - if b = MinusPI - then ival2 - else Ival.neg ival2 - in - find_lv_plus_rec e1 (Ival.sub current_offs ival2) - with V.Not_based_on_null | Int_Base.Error_Top-> ()); - | _ -> () - end - end - | CastE(typ,e) -> - ( try - pass_cast ~with_alarms state Cannot_find_lv typ e; - find_lv_plus_rec e current_offs - with Cannot_find_lv -> ()) - | _ -> () - in - find_lv_plus_rec e Ival.singleton_zero; - (*List.iter - (fun (lv,ival) -> - ignore (Pretty.printf "find_lv_plus %a : %s\n" - d_lval lv - (pretty_to_string Ival.pretty ival))) - !acc;*) - !acc - -and base_to_loc ~with_alarms ?deps state lv base offs = - if Ival.equal Ival.bottom offs - then begin - Relations_type.Model.bottom, - (Some Zone.bottom), - loc_bits_to_loc lv Location_Bits.bottom - end - else - let result = match base with - | Var host -> - let base = Base.find host in - state, deps, - loc_bits_to_loc lv (Location_Bits.inject base offs) - | Mem x -> - let state, deps, loc_lv = - eval_expr_with_deps_state ~with_alarms deps state x - in - let loc_bits = - Location_Bits.location_shift - offs - (loc_bytes_to_loc_bits loc_lv) - in - state, deps, loc_bits_to_loc lv loc_bits - in - CilE.set_syntactic_context (CilE.SyMem lv); - result - -and eval_expr ~with_alarms state e = - snd (eval_expr_with_deps ~with_alarms None state e) - -and get_influential_vars ~with_alarms state cond = - (* Format.printf "get_influential cond:%a@.state:%a@." - !d_exp cond - Relations_type.Model.pretty state; *) - let rec get_vars acc cond = - match cond.enode with - | Lval (Var v, off as lv) -> - let offset = - try - let _, _, offset = - eval_offset ~reduce_valid_index:true ~with_alarms None - v.vtype state off - in - offset - with Offset_not_based_on_Null _ -> - Ival.top - in - if Ival.cardinal_zero_or_one offset - then - (* no variable in offset can be influential *) - let varid = Base.create_varinfo v in - let loc = - Locations.make_loc - (Locations.Location_Bits.inject varid offset) - (sizeof_lval lv) - in - let contents = - Relations_type.Model.find ~conflate_bottom:true - state ~with_alarms loc - in - if Location_Bytes.cardinal_zero_or_one contents - then ( - (* Format.printf "cond:%a@.var contents:%a@.state:%a@." - !d_exp cond - Location_Bytes.pretty contents - Relations_type.Model.pretty state; *) - acc (* it's not influential *) - ) - else loc :: acc - else - (* a variable in offset can be influential *) - get_vars_offset acc off - | Lval (Mem e, off) -> - get_vars_offset (get_vars acc e) off - | BinOp(_,v1,v2,_) -> - get_vars (get_vars acc v1) v2 - | UnOp(_,v1,_) -> - get_vars acc v1 - | CastE (_typ,exp) -> - get_vars acc exp - | _ -> acc - and get_vars_offset acc offset = - match offset with - NoOffset -> acc - | Field (_,off) -> get_vars_offset acc off - | Index (ind,off) -> get_vars (get_vars_offset acc off) ind - in - get_vars [] cond - -and reduce_by_valid_expr ~with_alarms ~positive exp state = - try - ignore (with_alarms); - let lv = - match exp.enode with - Lval lv -> lv - | _ -> raise Cannot_find_lv - in - (* TODO: utiliser find_lv_plus pour traiter plus d'expressions *) - let loc = lval_to_loc ~with_alarms:CilE.warn_none_mode state lv in - if not (Locations.valid_cardinal_zero_or_one loc) - then state - else - let value = - Relations_type.Model.find - ~conflate_bottom:true - ~with_alarms:CilE.warn_none_mode - state - loc - in - ( match value with - Location_Bytes.Top _ -> - (* we won't reduce anything anyway, - and we may lose information if loc contains misaligned data *) - raise Cannot_find_lv - | _ -> () ); - let value_as_loc = - make_loc - (loc_bytes_to_loc_bits value) - (sizeof_pointed (Cil.typeOfLval lv)) - in - let reduced_value = - loc_to_loc_without_size - (if positive - then valid_part value_as_loc - else invalid_part value_as_loc ) - in - if Location_Bytes.equal value reduced_value - then state - else begin - if Location_Bytes.equal Location_Bytes.bottom reduced_value - then Relations_type.Model.bottom - else - Relations_type.Model.reduce_binding - state - loc - reduced_value - end - with Cannot_find_lv -> state - -and eval_expr_with_deps ~with_alarms deps (state : Relations_type.Model.t) e = - let _,deps,r = eval_expr_with_deps_state ~with_alarms deps state e in - deps, r - -and eval_BinOp ~with_alarms e deps state = - match e.enode with - BinOp (op, e1, e2, typ) -> - let state, deps, ev1 = - eval_expr_with_deps_state ~with_alarms deps state e1 - in - if V.is_bottom ev1 - then Relations_type.Model.bottom, (Some Zone.bottom) ,V.bottom - else - let state, deps, ev2 = - eval_expr_with_deps_state ~with_alarms deps state e2 - in - if V.is_bottom ev2 - then Relations_type.Model.bottom, (Some Zone.bottom) ,V.bottom - else begin - let syntactic_context = CilE.SyBinOp (op,e1,e2) in - CilE.set_syntactic_context syntactic_context; - begin match unrollType (typeOf e1) with - | TFloat _ -> - let interpreted_expr = - (* refactor: shouldn't this be somewhere else? *) - try - let f1 = - try - let v1 = V.project_ival ev1 in - Ival.project_float v1 - with V.Not_based_on_null - | Ival.Float_abstract.Nan_or_infinite -> - Value_parameters.warning ~current:true ~once:true - "converting value to float: assert(Ook)"; - Ival.Float_abstract.top - in - let f2 = - try - let v2 = V.project_ival ev2 in - Ival.project_float v2 - with V.Not_based_on_null - | Ival.Float_abstract.Nan_or_infinite -> - Value_parameters.warning ~current:true ~once:true - "converting value to float: assert(Ook)"; - Ival.Float_abstract.top - in - let binary_float_floats _name f = - CilE.set_syntactic_context (CilE.SyUnOp e); - try - let alarm, f = f (get_rounding_mode ()) f1 f2 in - if alarm then begin - CilE.warn_result_nan_infinite with_alarms ; - end; - V.inject_ival (Ival.inject_float f) - with - Ival.Float_abstract.Nan_or_infinite -> - CilE.warn_result_nan_infinite with_alarms ; - V.top_float - | Ival.Float_abstract.Bottom -> - CilE.warn_result_nan_infinite with_alarms ; - V.bottom - in - begin match op with - | PlusA -> - binary_float_floats "+." - Ival.Float_abstract.add_float - | MinusA -> - binary_float_floats "-." - Ival.Float_abstract.sub_float - | Mult -> - binary_float_floats "*." - Ival.Float_abstract.mult_float - | Div -> - binary_float_floats "/." - Ival.Float_abstract.div_float - | Eq -> - let contains_zero, contains_non_zero = - Ival.Float_abstract.equal_float_ieee f1 f2 - in - V.interp_boolean ~contains_zero ~contains_non_zero - | Ne -> - let contains_non_zero, contains_zero = - Ival.Float_abstract.equal_float_ieee f1 f2 - in - V.interp_boolean ~contains_zero ~contains_non_zero - | Lt -> - V.interp_boolean - ~contains_zero:(Ival.Float_abstract.maybe_le_ieee_float f2 f1) - ~contains_non_zero:(Ival.Float_abstract.maybe_lt_ieee_float f1 f2) - | Le -> - V.interp_boolean - ~contains_zero:(Ival.Float_abstract.maybe_lt_ieee_float f2 f1) - ~contains_non_zero:(Ival.Float_abstract.maybe_le_ieee_float f1 f2) - | Gt -> - V.interp_boolean - ~contains_zero:(Ival.Float_abstract.maybe_le_ieee_float f1 f2) - ~contains_non_zero:(Ival.Float_abstract.maybe_lt_ieee_float f2 f1) - | Ge -> - V.interp_boolean - ~contains_zero:(Ival.Float_abstract.maybe_lt_ieee_float f1 f2) - ~contains_non_zero:(Ival.Float_abstract.maybe_le_ieee_float f2 f1) - | _ -> raise V.Not_based_on_null - end - with V.Not_based_on_null | Ival.F.Nan_or_infinite -> - Value_parameters.warning ~once:true ~current:true - "float operation on address."; - V.join - (V.topify_arith_origin ev1) - (V.topify_arith_origin ev2) - in - state, deps, interpreted_expr - | TInt _ | TPtr (_, _) | _ -> - let interpreted_expr = begin match op with - | PlusPI | IndexPI -> - V.add_untyped (osizeof_pointed typ) ev1 ev2 - | MinusPI -> - V.add_untyped (Int_Base.neg (osizeof_pointed typ)) ev1 ev2 - | PlusA -> - V.add_untyped (Int_Base.inject Int.one) ev1 ev2 - | MinusA | MinusPP -> - let minus_val = V.add_untyped Int_Base.minus_one ev1 ev2 in - if op = MinusA - then minus_val - else (* MinusPP *) - ( try - let size = - Int_Base.project (sizeof_pointed(Cil.typeOf e1)) - in - let size = Int.div size Int.eight in - if Int.is_one size then - minus_val - else - let minus_val = Cvalue_type.V.project_ival minus_val - in - Cvalue_type.V.inject_ival - (Ival.scale_div ~pos:true size minus_val) - with - Int_Base.Error_Top - | Cvalue_type.V.Not_based_on_null - | Not_found -> - V.join - (V.topify_arith_origin ev1) - (V.topify_arith_origin ev2)) - | Mod -> V.c_rem ~with_alarms ev1 ev2 - | Div -> V.div ~with_alarms ev1 ev2 - | Mult -> - V.arithmetic_function ~with_alarms "*" Ival.mul ev1 ev2 - | LOr -> - assert false - (* This code makes a strict evaluation: V.interp_boolean - ~contains_zero: (V.contains_zero ev1 && - V.contains_zero ev2) ~contains_non_zero: - (V.contains_non_zero ev1 || V.contains_non_zero - ev2)*) - | LAnd -> - assert false - (* This code makes a strict evaluation: - V.interp_boolean ~contains_zero: (V.contains_zero - ev1 || V.contains_zero ev2) ~contains_non_zero: - (V.contains_non_zero ev1 && V.contains_non_zero - ev2)*) - | BXor -> V.oper_on_values ~with_alarms "^" Int.logxor ev1 ev2 - | BOr -> - V.bitwise_or ~size:(bitsSizeOf (typeOf e1)) ev1 ev2 - | BAnd -> - ( try - let t = typeOf e1 in - let size = bitsSizeOf t in - let signed = is_signed_int_enum_pointer t in - V.bitwise_and ~size ~signed ev1 ev2 - with SizeOfError _ -> - V.join - (V.topify_arith_origin ev1) - (V.topify_arith_origin ev2)) - - | Eq | Ne | Ge | Le | Gt | Lt -> - let warn, ev1, ev2 = check_comparable ev1 ev2 in - if warn - then begin - CilE.warn_pointer_comparison with_alarms; - end; - if warn && Value_parameters.UndefinedPointerComparisonPropagateAll.get () - then V.zero_or_one - else - let f = match op with - | Eq -> V.check_equal true - | Ne -> V.check_equal false - | Ge -> V.comparisons ">=" V.do_ge - | Le -> V.comparisons "<=" V.do_le - | Gt -> V.comparisons ">" V.do_gt - | Lt -> V.comparisons "<" V.do_lt - | _ -> assert false - in - f ev1 ev2 - | Shiftrt -> - begin try - let signed = is_signed_int_enum_pointer typ in - V.shift_right - ~with_alarms ~size:(bitsSizeOf typ) ~signed - ev1 - ev2 - with SizeOfError _ -> - ( match with_alarms.CilE.imprecision_tracing with - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> - Value_parameters.result - "shifting value of unknown size"); - V.top (* TODO: topify ... *) - end - | Shiftlt -> - begin try - V.shift_left ~with_alarms ~size:(bitsSizeOf typ) ev1 ev2 - with SizeOfError _ -> - ( match with_alarms.CilE.imprecision_tracing with - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> - Value_parameters.result - "shifting value of unknown size"); - V.top (* TODO: topify ... *) - end - end - in - (* Warn if overflow in a signed int binop *) - let interpreted_expr = - match op with - Shiftlt|Mult|MinusPP|MinusPI|IndexPI| - PlusPI|PlusA|Div|Mod|MinusA -> - handle_signed_overflow - ~with_alarms - syntactic_context - typ - e - interpreted_expr - | _ -> interpreted_expr - in - state, deps, interpreted_expr - end - end - | _ -> assert false - -and eval_expr_with_deps_state - ~with_alarms deps (state : Relations_type.Model.t) e = - let state, deps, expr = - let orig_expr = Cil.stripInfo e in - match orig_expr.enode with - | Info _ -> assert false - | Const v -> - let r = - begin match v with - | CInt64 (i,k,_s) -> - V.inject_int ( - if isSigned k - then Int.of_int64 i - else (* For 64 bits type we need to reinterpret the sign *) - let s = Printf.sprintf "%Lu" i in - Int.of_string s) - | CChr c -> - (match charConstToInt c with - | CInt64 (i,_,_) -> V.inject_int (Int.of_int64 i) - | _ -> assert false) - | CReal (f, _fsize, _) -> - Value_parameters.result ~once:true - "float support is experimental"; - let f = Ival.F.of_float f in - let overflow, af = - try - let o, af = Ival.Float_abstract.inject_r f f in - o, V.inject_ival (Ival.inject_float af) - with Ival.Float_abstract.Bottom -> - Value_parameters.result ~current:true - "Floating-point literal (or constant expression) is not finite. This path is assumed to be dead."; - true, V.bottom - in - if overflow - then Value_parameters.result "overflow in constant: assert(Ook);"; - af - | CWStr _ -> - Value_parameters.result "approximation because of a wide string"; - (* TODO *) V.top_int - | CStr s -> - V.inject (Base.create_string s) Ival.zero - | CEnum {eival = e} -> - let _,_, r = - eval_expr_with_deps_state ~with_alarms deps state e - in - r - end - in - state, deps, r - | BinOp _ -> - eval_BinOp ~with_alarms orig_expr deps state - | Lval lv -> - eval_lval ~conflate_bottom:true ~with_alarms deps state lv - | AddrOf v | StartOf v -> - let state, deps, r = - lval_to_loc_with_offset_deps_only_option ~with_alarms ?deps state v - in - state, deps, loc_to_loc_without_size r - - | CastE (typ, e) -> - let deps, evaled_expr = - eval_expr_with_deps ~with_alarms deps state e - in - let src_typ = unrollType (typeOf e) in - let dest_type = unrollType typ in - let r = do_promotion ~with_alarms ~dest_type ~src_typ evaled_expr e in - state, deps, r - - - | SizeOf typ -> - let r = - try V.inject_ival - (Ival.inject_singleton ((Int.of_int ((bitsSizeOf typ) / 8)))) - with SizeOfError _ -> - error "cannot interpret sizeof(incomplete type)"; - V.top_int - in - state, deps, r - | SizeOfE e -> - let typ = typeOf e in - let r = - try V.inject_ival - (Ival.inject_singleton ((Int.of_int ((bitsSizeOf typ) / 8)))) - with SizeOfError _ -> - error "cannot interpret sizeof(incomplete type)"; - V.top_int - in - state, deps, r - - | UnOp (LNot, e, _) -> - (* TODO: on float, LNot is equivalent to == 0.0 *) - let deps, expr = eval_expr_with_deps ~with_alarms deps state e in - CilE.set_syntactic_context (CilE.SyBinOp (Eq, Cil.zero ~loc:e.eloc, e)); - let warn, _, expr = - check_comparable V.singleton_zero expr - in - if warn - then begin - CilE.warn_pointer_comparison with_alarms; - end; - let r = - if warn && - Value_parameters.UndefinedPointerComparisonPropagateAll.get () - then V.zero_or_one - else - if - let t1 = typeOf e in isIntegralType t1 || isPointerType t1 - then - V.interp_boolean - ~contains_zero:(V.contains_non_zero expr) - ~contains_non_zero:(V.contains_zero expr) - else V.zero_or_one - in - state, deps,r - | UnOp (Neg, e, t) -> - let t = unrollType t in - let deps, expr = eval_expr_with_deps ~with_alarms deps state e in - let syntactic_context = CilE.SyUnOp orig_expr in - CilE.set_syntactic_context syntactic_context; - ( match t with TFloat _ -> - let result = - try - let v = V.project_ival expr in - let f = - Ival.project_float v - in - V.inject_ival - (Ival.inject_float (Ival.Float_abstract.neg_float f)) - with - V.Not_based_on_null -> - begin match with_alarms.CilE.others with - CilE.Aignore -> () - | CilE.Acall f -> f() - | CilE.Alog -> - Value_parameters.warning ~once:true ~current:true - "converting address to float: assert(TODO)" - end; - V.topify_arith_origin expr - | Ival.Float_abstract.Nan_or_infinite -> - begin match with_alarms.CilE.others with - CilE.Aignore -> () - | CilE.Acall f -> f() - | CilE.Alog -> - Value_parameters.warning ~once:true ~current:true - "converting value to float: assert (TODO)" - end; - V.top_float - in - state, deps, result - | _ -> - let result = - try - let v = V.project_ival expr in - V.inject_ival (Ival.neg v) - with V.Not_based_on_null -> V.topify_arith_origin expr - in - let result = - handle_signed_overflow ~with_alarms - syntactic_context t orig_expr result - in - state, deps, result) - - | UnOp (BNot, e, _) -> - let deps, expr = eval_expr_with_deps ~with_alarms deps state e in - CilE.set_syntactic_context (CilE.SyUnOp e); - let result = - try - let v = V.project_ival expr in - V.inject_ival - (Ival.apply_set_unary "~" Int.lognot v) - with V.Not_based_on_null -> V.topify_arith_origin expr - in - state, deps, result - | AlignOfE _|AlignOf _|SizeOfStr _ - -> - Value_parameters.result - "C construct alignof or sizeof string not precisely handled"; - state, deps, V.top_int - in - let r = - if hasAttribute "volatile" (typeAttrs (typeOf e)) - && not (Cvalue_type.V.equal Cvalue_type.V.bottom expr) - then V.top_int - else - expr - in - let state,r_ptr = PtrRelational.eval_expr ~with_alarms state e in - let r = Cvalue_type.V.narrow r_ptr r in - let typ = typeOf e in - (* let r = - handle_signed_overflow ~with_alarms (CilE.SyUnOp e) typ e r - in TODO *) - let r = do_cast ~with_alarms typ r in - state, deps, r - -and eval_expr_with_deps_state_subdiv ~with_alarms deps - (state : Relations_type.Model.t) e = - let ((state_without_subdiv, deps_without_subdiv, result_without_subdiv) as result) = - eval_expr_with_deps_state ~with_alarms deps - (state : Relations_type.Model.t) e - in - let subdivnb = Value_parameters.Subdivide_float_in_expr.get() in - if subdivnb=0 - then result - else if not (Locations.Location_Bytes.is_included result_without_subdiv Locations.Location_Bytes.top_int) - then begin - Value_parameters.debug ~level:2 - "subdivfloatvar: expression has an address result"; - result - end - else - let compare_min, compare_max = - if Locations.Location_Bytes.is_included result_without_subdiv Locations.Location_Bytes.top_float - then begin - Value_parameters.debug ~level:2 - "subdivfloatvar: optimizing floating-point expression %a=%a" - !d_exp e - Locations.Location_Bytes.pretty result_without_subdiv; - Cvalue_type.V.compare_min_float, Cvalue_type.V.compare_max_float - end - else begin - Value_parameters.debug ~level:2 - "subdivfloatvar: optimizing integer expression %a=%a" - !d_exp e - Locations.Location_Bytes.pretty result_without_subdiv; - Cvalue_type.V.compare_min_int, Cvalue_type.V.compare_max_int - end - in - let vars = - get_influential_vars ~with_alarms:CilE.warn_none_mode state e - in - Value_parameters.debug ~level:2 "subdivfloatvar: variable list=%a" - (Pretty_utils.pp_list Locations.pretty) - vars; - let rec try_sub vars = - match vars with - [] | [ _ ] -> - result - | v :: tail -> - try - if not (List.exists (fun x -> Locations.loc_equal v x) tail) - then raise Too_linear; - let v_value = - Relations_type.Model.find - ~conflate_bottom:true - ~with_alarms:CilE.warn_none_mode - state - v - in - Value_parameters.debug ~level:2 - "subdivfloatvar: considering optimizing variable %a (value %a)" - Locations.pretty v Cvalue_type.V.pretty v_value; - if not (Locations.Location_Bytes.is_included - v_value - Locations.Location_Bytes.top_float) - then raise Too_linear; - - let working_list = ref [ (v_value, result_without_subdiv) ] in - let had_bottom = ref false in - let subdiv_for_bound better_bound = - let rec insert_subvalue_in_list (_, exp_value as p) l = - match l with - [] -> [p] - | (_, exp_value1 as p1) :: tail -> - if better_bound exp_value1 exp_value >= 0 - then p :: l - else p1 :: (insert_subvalue_in_list p tail) - in - let exp_subvalue subvalue l = - let substate = - (* FIXME: should be relation-aware primitive *) - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - v - subvalue - in - let subexpr = eval_expr ~with_alarms substate e in - Value_parameters.debug ~level:2 - "subdivfloatvar: computed var=%a expr=%a" - V.pretty subvalue - V.pretty subexpr; - if Cvalue_type.V.is_bottom subexpr - then begin - had_bottom := true; - l - end - else - insert_subvalue_in_list (subvalue, subexpr) l - in - let subdiv l = - match l with - [] -> - Value_parameters.debug - "subdivfloatvar: all reduced to bottom!!"; - raise Ival.Can_not_subdiv - | (value, _exp_value) :: tail -> - let (subvalue1, subvalue2) = - Cvalue_type.V.subdiv_float_interval value - in - let s = exp_subvalue subvalue1 tail - in - exp_subvalue subvalue2 s - in - try - for i = 1 to subdivnb do - working_list := subdiv !working_list; - done - with Ival.Can_not_subdiv -> () - in - subdiv_for_bound compare_min ; - (* sort working_list in decreasing order - on the upper bounds of exp_value *) - let comp_exp_value (_value1,exp_value1) (_value2,exp_value2) = - compare_max exp_value1 exp_value2 - in - working_list := List.sort comp_exp_value !working_list ; - if Value_parameters.debug_atleast 2 then - List.iter - (function (x, e) -> - Value_parameters.debug - "subdivfloatvar: elements of list max %a %a" - V.pretty x V.pretty e) - !working_list; - subdiv_for_bound compare_max ; - let working_list = !working_list in - if Value_parameters.debug_atleast 2 then - List.iter - (function (x, e) -> - Value_parameters.debug - "subdivfloatvar: elements of final list %a %a" - V.pretty x V.pretty e) - working_list; - let reduced_state, optimized_exp_value = - if !had_bottom - then - let reduced_var, optimized_exp_value = - List.fold_left - (fun (accv,acce) (value, exp_value) -> - Cvalue_type.V.join value accv, - Cvalue_type.V.join exp_value acce) - (Cvalue_type.V.bottom, - Cvalue_type.V.bottom) - working_list - in - (* FIXME: should be relation-aware primitive *) - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - v - reduced_var, - optimized_exp_value - else - state_without_subdiv, - List.fold_left - (fun acc (_value, exp_value) -> - Cvalue_type.V.join exp_value acc) - Cvalue_type.V.bottom - working_list - in - reduced_state, deps_without_subdiv, optimized_exp_value - with Not_less_than | Too_linear -> - try_sub tail - in - try_sub vars - -and eval_lval_using_main_memory ~conflate_bottom ~with_alarms - deps (state:Relations_type.Model.t) lv - = - let state,deps,loc = - lval_to_loc_deps_option ~with_alarms ?deps state lv - ~reduce_valid_index:(Parameters.SafeArrays.get ()) - in - CilE.set_syntactic_context (CilE.SyMem lv); - let result = - Relations_type.Model.find - ~conflate_bottom - ~with_alarms state loc in - (* TODO: move into Model.find *) - let valid_loc = Locations.valid_part loc in - let state = - if Location_Bits.equal loc.Locations.loc valid_loc.Locations.loc - then state - else begin - match lv with - Mem (exp_mem),NoOffset -> - let lv_mem_plus_list = - find_lv_plus ~with_alarms:CilE.warn_none_mode state exp_mem - in - let treat_lv_mem_plus (lv_mem, plus) state = - let loc_mem = - lval_to_loc ~with_alarms:CilE.warn_none_mode state lv_mem - in - if Location_Bits.is_relationable loc_mem.Locations.loc - then - let new_val = - Location_Bytes.location_shift - (Ival.neg plus) - (loc_bits_to_loc_bytes valid_loc.loc) - in - Relations_type.Model.reduce_binding - state loc_mem new_val - else state - in - List.fold_right treat_lv_mem_plus lv_mem_plus_list state - | _ -> state - end - in - (match with_alarms.CilE.imprecision_tracing with - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> warn_lval_read lv loc result); - let new_deps = - match deps with - | None -> None - | Some deps -> Some (Zone.join deps (valid_enumerate_bits loc)) - in - state, new_deps, result - -and eval_lval ~conflate_bottom ~with_alarms deps state (base,offset as lv) = - let state, deps, result_from_main_memory = - eval_lval_using_main_memory ~conflate_bottom ~with_alarms deps state lv - in - let find_loc_mem sub_lv offs = - try - let loc = lval_to_loc ~with_alarms state sub_lv in - let size = sizeof_lval lv in - CilE.set_syntactic_context (CilE.SyMem lv); - Relations_type.Model.find_mem loc size offs state - with Relations_type.Use_Main_Memory -> - result_from_main_memory - in - let result = match base with - | Mem({enode = Lval sub_lv} as e) when UseRelations.get () -> - let typ = typeOf e in - begin try - let _, _, offs = - eval_offset ~reduce_valid_index:(Parameters.SafeArrays.get ()) - ~with_alarms None typ state offset - in - find_loc_mem sub_lv offs - with - Offset_not_based_on_Null _ -> - result_from_main_memory - end - | Mem({enode = BinOp((PlusPI|IndexPI|MinusPI as op), - {enode = Lval sub_lv} , - e2,_)} - as e) - when UseRelations.get () -> - begin - let e2 = eval_expr ~with_alarms state e2 in - let typ = typeOf e in - try - let ival = Cvalue_type.V.project_ival e2 in - let ival = if op=MinusPI then Ival.neg ival else ival in - let _, _, offs = - eval_offset ~reduce_valid_index:(Parameters.SafeArrays.get ()) - ~with_alarms None typ state offset in - let offs = (* convert to bits *) - Ival.add - (Ival.scale - (Int_Base.project (sizeof_pointed typ)) - ival) - offs - in - let result = find_loc_mem sub_lv offs in - result - with - | Offset_not_based_on_Null _ - | Int_Base.Error_Top - | Cvalue_type.V.Not_based_on_null -> result_from_main_memory - end - | _e -> - result_from_main_memory - in - let result_inter = Cvalue_type.V.narrow result_from_main_memory result in - state, deps, result_inter - -and eval_offset ~reduce_valid_index ~with_alarms deps typ state offset = - match offset with - | NoOffset -> - state, deps, Ival.singleton_zero - | Index (exp,remaining) -> - let typ_pointed,array_size = match (unrollType typ) with - | TArray (t,size,_,_) -> t, size - | TPtr(t,_) -> - (match unrollType t with - | TArray (t,size,_,_) -> t,size (* pointer to start of an array *) - | _ -> - error "Got type '%a'" !Ast_printer.d_type t; - assert false) - | t -> - error "Got type '%a'" !Ast_printer.d_type t; - assert false - in - let state, deps, current = - eval_expr_with_deps_state ~with_alarms deps state exp - in - if V.is_bottom current - then Relations_type.Model.bottom, (Some Zone.bottom), Ival.bottom - else - let state, offset = - try - let v = V.project_ival current in - let state, v = - if reduce_valid_index then - try - let array_siz = lenOfArray64 array_size in - let new_v = - Ival.narrow - (Ival.inject_range - (Some Int.zero) - (Some (Int.of_int64 (Int64.pred array_siz)))) - v - in - let new_state = - if Ival.equal new_v v - then state - else begin - begin - match with_alarms.CilE.others with - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> - CilE.set_syntactic_context - (CilE.SyBinOp - (IndexPI, - exp, - Cilutil.out_some array_size)); - CilE.warn_index with_alarms "accessing" - end; - state (* TODO : if the index is a variable, reduce *) - end - in - new_state, new_v - with LenOfArray -> state, v - else state, v - in - state, v - with V.Not_based_on_null -> - let deps, offset = - topify_offset - ~with_alarms - deps - state - (Cvalue_type.V.topify_arith_origin current) - remaining - in - raise (Offset_not_based_on_Null (deps,offset)) - in - let state, deps, r = - eval_offset ~reduce_valid_index ~with_alarms - deps typ_pointed state remaining - in - let offset = Ival.scale_int64base (sizeof typ_pointed) offset in - state, deps, Ival.add offset r - | Field (fi,remaining) -> - let current,_ = bitsOffset typ (Field(fi,NoOffset)) in - let state, deps, r = - eval_offset ~reduce_valid_index ~with_alarms - deps - fi.ftype - state - remaining - in - state, deps, Ival.add (Ival.of_int current) r -and topify_offset ~with_alarms deps state acc offset = - match offset with - | NoOffset -> deps,acc - | Field (_fi,remaining) -> topify_offset ~with_alarms deps state acc remaining - | Index (exp,remaining) -> - let deps, loc_index = eval_expr_with_deps ~with_alarms deps state exp in - let acc = Location_Bytes.join - (Cvalue_type.V.topify_arith_origin loc_index) - acc - in - topify_offset ~with_alarms deps state acc remaining - -(** raises [Reduce_to_bottom] and never returns [Relations_type.Model.bottom]*) -let rec eval_cond ~with_alarms state cond = - (* Do not reduce anything if the cond is volatile. - (This test is dumb because the cond may contain volatile l-values - without the "volatile" attribute appearing at toplevel. pc 2007/11) *) - if hasAttribute "volatile" (typeAttr (typeOf cond.exp)) then state - else - let eval_symetric_int positive binop cond_expr value = - match positive,binop with - | false, Eq | true, Ne -> V.diff_if_one value cond_expr - | true, Eq | false, Ne -> V.narrow value cond_expr - | _,_ -> value - in - let eval_symetric_float = eval_symetric_int in - let eval_antisymetric_int ~typ_loc:_ positive binop cond_expr value = - try match positive,binop with - | true, Le | false, Gt -> - V.filter_le value ~cond_expr - | true, Ge | false, Lt -> - V.filter_ge value ~cond_expr - | false, Le | true, Gt -> - V.filter_gt value ~cond_expr - | false, Ge | true, Lt -> - V.filter_lt value ~cond_expr - | _,_ -> value - with V.Error_Bottom -> V.bottom - in - let eval_antisymetric_float ~typ_loc positive binop cond_expr value = - try match positive,binop with - | true, Le | false, Gt -> - V.filter_le_float value ~cond_expr - | true, Ge | false, Lt -> - V.filter_ge_float value ~cond_expr - | false, Le | true, Gt -> - V.filter_gt_float (Value_parameters.AllRoundingModes.get ()) - ~typ_loc value ~cond_expr - | false, Ge | true, Lt -> - V.filter_lt_float (Value_parameters.AllRoundingModes.get ()) - ~typ_loc value ~cond_expr - | _,_ -> value - with V.Error_Bottom -> V.bottom - in - let eval_as_exact_loc state e = - try - let lv = find_lv ~with_alarms state e in - let loc = lval_to_loc ~with_alarms state lv in - if not (valid_cardinal_zero_or_one loc) - then raise Not_an_exact_loc; - let typ = typeOfLval lv in - let value_for_loc = - Relations_type.Model.find ~conflate_bottom:true - ~with_alarms state loc - in - let value_for_loc2 = - do_cast - ~with_alarms - (* Using (typeOf e) caused imprecisions with - the condition char c; ... if (c>0) - being transformed in if (((int)c)>0) by Cil. *) - typ - value_for_loc - in - if Cvalue_type.V.has_sign_problems value_for_loc && - not (Cvalue_type.V.equal value_for_loc value_for_loc2) - then begin -(* Value_parameters.warning ~current:true "oh: %a %a %a@." - Locations.pretty loc - V.pretty value_for_loc - V.pretty value_for_loc2; *) - raise Not_an_exact_loc; - end; - loc, value_for_loc2, typ - with Cannot_find_lv -> - raise Not_an_exact_loc - in - let rec aux cond state = - match cond.positive,cond.exp.enode with - | _positive, BinOp ((Le|Ne|Eq|Gt|Lt|Ge as binop), exp1, exp2, _typ) -> - let eval_eq_ineq eval_symetric eval_antisymetric = - let loc1 = ref None in - let loc2 = ref None in - let result1 = - try - let left_loc,value_for_loc,typ_loc = - eval_as_exact_loc state exp1 - in - loc1 := Some left_loc; - let cond_expr = eval_expr ~with_alarms state exp2 in - let v_sym = - eval_symetric cond.positive binop cond_expr value_for_loc - in - let v_asym = - eval_antisymetric ~typ_loc - cond.positive binop cond_expr v_sym - in - if V.equal v_asym V.bottom then raise Reduce_to_bottom; - if V.equal v_asym value_for_loc - then state - else - Relations_type.Model.reduce_binding state left_loc v_asym - with Not_an_exact_loc -> state - in - let result2 = try - let right_loc,value_for_loc,typ_loc = - eval_as_exact_loc result1 exp2 - in - loc2 := Some right_loc; - let cond_expr = eval_expr ~with_alarms result1 exp1 - in - let v_sym = eval_symetric - cond.positive binop cond_expr value_for_loc - in - let v_asym = eval_antisymetric - ~typ_loc - cond.positive - (match binop with Gt -> Lt | Lt -> Gt | Le -> Ge | Ge -> Le - | _ -> binop) - cond_expr - v_sym - in - if V.equal v_asym V.bottom then raise Reduce_to_bottom; - if V.equal v_asym value_for_loc - then result1 - else - Relations_type.Model.reduce_binding result1 right_loc v_asym - with Not_an_exact_loc -> result1 - in - let result3 = - begin match (cond.positive, binop), !loc1, !loc2 with - ((true,Eq)|(false, Ne)), Some(left_loc), Some(right_loc) -> - Relations_type.Model.reduce_equality - result2 left_loc right_loc - | _ -> result2 - end - in - result3 - in - let t1 = unrollType (typeOf exp1) in - if isIntegralType t1 || isPointerType t1 - then - eval_eq_ineq eval_symetric_int eval_antisymetric_int - else - eval_eq_ineq eval_symetric_float eval_antisymetric_float - | true, BinOp (LAnd, exp1, exp2, _) - | false, BinOp (LOr, exp1, exp2, _) -> - let new_state = aux {cond with exp = exp1} state in - let result = aux {cond with exp = exp2} new_state in - result - | false, BinOp (LAnd, exp1, exp2, _) - | true, BinOp (LOr, exp1, exp2, _) -> - let new_v1 = try aux {cond with exp = exp1} state - with Reduce_to_bottom -> Relations_type.Model.bottom - in let new_v2 = try aux {cond with exp = exp2} state - with Reduce_to_bottom -> Relations_type.Model.bottom - in - Relations_type.Model.join new_v1 new_v2 - - | _, UnOp(LNot,exp,_) -> - aux - { positive = not cond.positive; - exp = exp; } - state - | _, Lval _ - when let t = typeOf cond.exp in - isIntegralType t || isPointerType t - -> - (* "if (c)" is equivalent to "if(!(c==0))" *) - (try - let loc,value_for_loc,_ = eval_as_exact_loc state cond.exp in - let new_value = - eval_symetric_int (not cond.positive) - Eq - (V.inject_ival Ival.singleton_zero) - value_for_loc - in - if V.equal new_value V.bottom then - raise Reduce_to_bottom - else - Relations_type.Model.reduce_binding - state loc new_value - with Not_an_exact_loc -> state) - | _ -> state - in - let result = - aux cond state - in - let condition_may_still_be_true_in_state env = - let cond_interp = eval_expr ~with_alarms env cond.exp in - (not cond.positive || V.contains_non_zero cond_interp) && - (cond.positive || V.contains_zero cond_interp) - in - if (not (Relations_type.Model.equal result state)) && - (not (condition_may_still_be_true_in_state result)) - then raise Reduce_to_bottom; - let is_enumerable v = - let v_interp = - Relations_type.Model.find ~conflate_bottom:true ~with_alarms result v - in - ignore (Location_Bytes.cardinal_less_than v_interp 7); - v_interp - in - let rec enumerate_one_var l = - match l with - | [] -> raise Not_found - | v::t -> - try - let v_interp = is_enumerable v in - v,v_interp,t - with Abstract_interp.Not_less_than -> - enumerate_one_var t - in - let invert_cond vl = - try - let v1,v_interp1, _tail = enumerate_one_var vl in - let f one_val acc = - (* interpret cond in an environment where v -> one_val - *) - let env = - Relations_type.Model.reduce_binding - result v1 one_val - in - if condition_may_still_be_true_in_state env - then begin - (* stays *) - Location_Bytes.join one_val acc - end - else begin - (* goes *) - acc - end - in - let new_v_interp = - Location_Bytes.fold_enum - ~split_non_enumerable:2 - f v_interp1 Location_Bytes.bottom - in - let state_value = - if V.equal new_v_interp V.bottom - then raise Reduce_to_bottom - else Relations_type.Model.reduce_binding result v1 new_v_interp - in - state_value - with Not_found -> result - in - let result1 = - invert_cond (get_influential_vars ~with_alarms result cond.exp) - in - if not (Relations_type.Model.is_reachable result1) - then raise Reduce_to_bottom - else result1 - -exception Ignore - (* raised to completely ignore an instruction or statement *) - -(* See bug report fs#182 *) -let resolv_func_vinfo ~with_alarms deps state funcexp = - match funcexp.enode with - | Lval (Var vinfo,NoOffset) -> - deps, Kernel_function.Hptset.singleton (Globals.Functions.get vinfo) - | Lval (Mem v,NoOffset) -> - let deps, loc = eval_expr_with_deps ~with_alarms deps state v in - let fundecs = List.fold_left - (fun acc varid -> - match varid with - | Base.String (_,_) -> - Value_parameters.warning ~once:true ~current:true - "Function pointer call at string position in memory: ignoring this particular value: assert(TODO)"; - acc - | Base.Null -> - Value_parameters.warning ~once:true ~current:true - "Function pointer call at absolute position in memory: ignoring this particular value: assert(TODO)"; - acc - | Base.Cell_class _ -> - Value_parameters.warning ~once:true ~current:true - "Function pointer call at memory cell class: ignoring this particular value: assert(TODO)"; - acc - | Base.Var (v,_) | Base.Initialized_Var (v,_) -> - Kernel_function.Hptset.add (Globals.Functions.get v) acc - ) - Kernel_function.Hptset.empty - (try - Location_Bytes.get_keys_exclusive Ival.zero loc - with Location_Bytes.Not_all_keys -> - Value_parameters.warning ~once:true ~current:true - "Function pointer call is completely unknown: assuming no effects: assert(TODO)"; - raise Leaf) - in - (* (ignore (Errormsg.log - "Function pointer resolved to %d functions.\n" - (List.length fundecs)); true);*) - deps, fundecs - | _ -> - assert false - -let make_well hidden_base state loc = - let size = Bit_utils.max_bit_size () in - let well = Cvalue_type.V.inject_top_origin - Origin.Well - (Cvalue_type.V.Top_Param.O.singleton hidden_base) - in - let well_loc = - Locations.make_loc - (Location_Bits.inject hidden_base Ival.zero) - (Int_Base.inject size) - in - let state_with_well = - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - well_loc - well - in - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state_with_well - loc - well - -let create_hidden_base - validity_from_type ~hidden_var_name ~name_desc pointed_typ = - let hidden_var = - makeGlobalVar ~generated:false ~logic:true hidden_var_name pointed_typ - in - Globals.Vars.add_decl hidden_var; - hidden_var.vdescr <- Some name_desc; - let validity = - if validity_from_type - then begin - match Base.validity_from_type hidden_var with - | Base.Known (a,b) - when not (Value_parameters.AllocatedContextValid.get ()) -> - Base.Unknown (a,b) - | (Base.All | Base.Unknown _ | Base.Known _) as s -> s - | Base.Periodic _ -> assert false - end - else Base.Unknown (Int.zero,Bit_utils.max_bit_address ()) - in - let hidden_base = Base.create_logic hidden_var validity - in - hidden_base - -(** [initialize_var_using_type varinfo state] uses the type of [varinfo] - to create an initial value in [state]. *) -let initialize_var_using_type varinfo state = - CurrentLoc.set varinfo.vdecl; - let initializing_formal = not varinfo.vglob in - let rec add_offsetmap depth v name_desc name typ offset_orig typ_orig state = - let typ = Cil.unrollType typ in - let loc = loc_of_typoffset v typ_orig offset_orig in - let must_initialize = - initializing_formal || - (not (hasAttribute "const" (typeAttrs typ))) || - (Cvalue_type.V.equal - (Relations_type.Model.find - ~conflate_bottom:true ~with_alarms:CilE.warn_none_mode - state loc) - Cvalue_type.V.bottom) - in - if not must_initialize - (* if we do not have an initializer for this const, we generate - a formal constant *) - then state else - match typ with - | TInt _ | TEnum (_, _)-> - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - Cvalue_type.V.top_int - | TFloat _ -> - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - Cvalue_type.V.top_float - | TFun _ -> - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - (Cvalue_type.V.top_leaf_origin ()) - | TPtr (typ, _) as full_typ - when depth <= Value_parameters.AutomaticContextMaxDepth.get () -> - let attr = typeAttr full_typ in - let context_max_width = - Value_parameters.AutomaticContextMaxWidth.get () - in - if not (isVoidType typ) && not (isFunctionType typ) then - let i = - match findAttribute "arraylen" attr with - | [AInt i] -> i - | _ -> context_max_width - in - let pointed_typ = - TArray(typ, - Some (integer ~loc:varinfo.vdecl i), - empty_size_cache (), - []) - in - let hidden_var_name = - Cabs2cil.fresh_global ("S_" ^ name) - in - let name_desc = "*"^name_desc in - let hidden_base = - create_hidden_base - true - ~hidden_var_name - ~name_desc - pointed_typ - in - let state = - add_offsetmap - (depth + 1) - hidden_base - name_desc - hidden_var_name - pointed_typ - NoOffset - pointed_typ - state - in - let value = Cvalue_type.V.inject hidden_base (Ival.zero) - in - let value = - if Value_parameters.AllocatedContextValid.get () - then value - else Cvalue_type.V.join Cvalue_type.V.singleton_zero value - in - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - value - else - let hidden_var_name = - Cabs2cil.fresh_global ("S_" ^ name) - in - let name_desc = "*"^name_desc in - let hidden_base = - create_hidden_base - false - ~hidden_var_name - ~name_desc - typ - in - make_well hidden_base state loc - - | TArray (typ, len, _, _) -> - begin try - let size = lenOfArray len in - let state = ref state in - let typ = Cil.unrollType typ in - let treat_index (i : int) = - let offset = - addOffset - (Index (integer ~loc:varinfo.vdecl i, NoOffset)) - offset_orig - in - let name = (string_of_int i) ^"_"^ name in - let name_desc = name_desc ^ "[" ^ (string_of_int i) ^ "]" in - let s = - add_offsetmap depth v - name_desc name typ - offset typ_orig !state - in - state := s; - let loc = loc_of_typoffset v typ_orig offset in - let r_offsetmap = - Relations_type.Model.copy_offsetmap - ~with_alarms:CilE.warn_none_mode - loc s - in - match r_offsetmap with - Some r_offsetmap -> r_offsetmap - | None -> assert false - in - let max_precise_size = - Value_parameters.AutomaticContextMaxWidth.get () - in - if size <= max_precise_size - then - for i = 0 to pred size do - ignore (treat_index i) - done - else begin -(* Format.printf "ST %a: size=%d max_precise_size=%d offset=%a@." - Base.pretty v - size - max_precise_size - (!d_offset) offset_orig ; *) - let vv = ref None in - for i = 0 to pred max_precise_size do -(* Format.printf "IT %d@.%a@." - i - Relations_type.Model.pretty !state; *) - let r = treat_index i in - vv := - Some - ( match !vv with - None -> r - | Some vv -> snd (Cvalue_type.V_Offsetmap.join r vv)) - done; - ( match !vv with - None -> assert false - | Some vv -> -(* Format.printf "EN %a@." - Cvalue_type.V_Offsetmap.pretty vv; *) - for i = max_precise_size to pred size do - let offset = - addOffset - (Index (integer ~loc:varinfo.vdecl i, NoOffset)) - offset_orig - in - let loc = loc_of_typoffset v typ_orig offset in - let size = - try - Int_Base.project loc.size - with - | Int_Base.Error_Top - | Int_Base.Error_Bottom -> - assert false - in - state := - Relations_type.Model.paste_offsetmap - vv loc.loc Int.zero size !state - done); - end; - !state - with LenOfArray -> - Value_parameters.result ~once:true ~current:true - "could not find a size for array"; - state - end - | TComp ({cstruct=true;} as compinfo, _, _) -> (* Struct *) - let treat_field (next_offset,state) field = - let new_offset = Field (field, NoOffset) in - let offset = - addOffset - new_offset - offset_orig - in - let field_offset,field_width = bitsOffset typ_orig offset in - let state = - if field_offset>next_offset then (* padding bits needs filling*) - let loc = make_loc - (Location_Bits.inject v (Ival.of_int next_offset)) - (Int_Base.inject (Int.of_int (field_offset-next_offset))) - in - Relations_type.Model.add_binding_unspecified - state - loc - else state - in - field_offset+field_width, - add_offsetmap - depth - v - (name_desc ^ "." ^ field.fname) - (field.fname^"_"^name) - field.ftype - offset - typ_orig - state - in - begin try - let boff,bwidth = bitsOffset typ_orig offset_orig in - let last_offset,state= List.fold_left - treat_field - (boff,state) - compinfo.cfields - in - if last_offset<(boff+bwidth) then (* padding at end of struct*) - let loc = make_loc - (Location_Bits.inject v (Ival.of_int last_offset)) - (Int_Base.inject (Int.of_int (boff+bwidth-last_offset))) - in - Relations_type.Model.add_binding_unspecified - state - loc - else state - with Cil.SizeOfError _ -> state - end - | TComp ({cstruct=false}, _, _) when - is_fully_arithmetic typ - -> (* Union of arithmetic types *) - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - Cvalue_type.V.top_int - - | TPtr _ when Value_parameters.AllocatedContextValid.get () -> - (* deep pointers map to NULL in this case *) - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - state - loc - Cvalue_type.V.singleton_zero - - | TBuiltin_va_list _ | TComp _ | TVoid _ | TPtr _ -> - (* variable arguments or union with non-arithmetic type - or deep pointers *) - - (* first create a new varid and offsetmap for the - "hidden location" *) - let hidden_var_name = - Cabs2cil.fresh_global ("WELL_"^name) - in - let hidden_var = - makeGlobalVar ~logic:true hidden_var_name charType - in - hidden_var.vdescr <- Some (name_desc^"_WELL"); - let hidden_base = - Base.create_logic - hidden_var - (Base.Known (Int.zero,Bit_utils.max_bit_address ())) - in - make_well hidden_base state loc - | TNamed (_, _) -> assert false - in - add_offsetmap - 0 - (Base.create_varinfo varinfo) - varinfo.vname varinfo.vname varinfo.vtype NoOffset varinfo.vtype state - -let initial_state_only_globals = - let module S = - State_builder.Option_ref - (Relations_type.Model) - (struct - let name = "only_globals" - let dependencies = - [ Ast.self; Parameters.LibEntry.self; Parameters.MainFunction.self ] - let kind = `Internal - end) - in - function () -> - let compute () = - Value_parameters.debug ~level:2 "Computing globals values"; - let state = ref Relations_type.Model.empty_map in - let complete_init last_bitsoffset typ _l lval = - (* Now process the non initialized bits defaulting to 0 *) - begin try - let size_to_add, offset = - bitsSizeOf typ - last_bitsoffset, - Ival.inject_singleton (Int.of_int last_bitsoffset) - in - assert (size_to_add >= 0); - if size_to_add <> 0 then - let loc = - match lval with - | Var vinfo, _ -> - let base = Base.create_varinfo vinfo in - let size_to_add = (Int.of_int size_to_add) in - let offset, size = - match Base.validity base with - Base.Periodic (mn, _mx, p) when Int.ge size_to_add p -> - Ival.inject_singleton mn, p - | _ -> offset, size_to_add - in - let loc = - Location_Bits.inject base offset - in - let loc = make_loc loc (Int_Base.inject size) in -(* Format.printf "loc for final zeroes %a@." - Locations.pretty loc; *) - loc - | _ -> error "Whacky initializer ? Please report."; - assert false - in - let v = - if hasAttribute "volatile" (typeAttrs typ) - then V.top_int - else V.singleton_zero - in - state := - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - !state - loc - v - with Cil.SizeOfError _ -> - Value_parameters.result ~once:true ~current:true - "cannot provide a default initializer: size is unknown" - end - in - let rec eval_init lval init = - match init with - | SingleInit exp -> - let loc = - lval_to_loc ~with_alarms:CilE.warn_none_mode - Relations_type.Model.top lval - in -(* Format.printf "loc:%a state before:%a@." - Locations.pretty loc - Relations_type.Model.pretty !state; *) - let exact = cardinal_zero_or_one loc in - assert - (if not exact - then - (Cil.warning "In global initialisation, the location can not be represented. Aborting@."; - exit 1); - true); - let value = - eval_expr ~with_alarms:(warn_all_quiet_mode ()) - Relations_type.Model.top - exp - in - let v = - if hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lval)) - then V.top_int - else value - in - state := - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode ~exact - !state loc v; -(* Format.printf "state after:%a@." - Relations_type.Model.pretty !state; *) - - | CompoundInit (base_typ, l) -> - if not (hasAttribute "volatile" (typeAttrs base_typ)) - then - let last_bitsoffset = - foldLeftCompound - ~implicit:false - ~doinit: - (fun off init typ (acc:int) -> - let o,w = bitsOffset base_typ off in - if acc<o - then begin (* uninitialize the padding bits *) - let vi, (base_off,_) = - (match lval with - | Var vinfo, abs_offset -> - vinfo, - (bitsOffset vinfo.vtype abs_offset) - | _ -> - Value_parameters.fatal "Whacky initializer?") - in - let loc_bits = - Location_Bits.inject - (Base.create_varinfo vi) - (Ival.inject_singleton (Int.of_int (base_off+acc))) - in - let loc_size = Int_Base.inject (Int.of_int (o-acc)) in - let loc = make_loc loc_bits loc_size in -(* Format.printf "loc:%a@." Locations.pretty loc; *) - state := - Relations_type.Model.add_binding_unspecified - !state - loc - end - else assert (acc=o); - if hasAttribute "volatile" (typeAttrs typ) then - Value_parameters.warning ~current:true ~once:true - "global initialization of volatile value ignored" - else - eval_init (addOffsetLval off lval) init; - o+w) - ~ct:base_typ - ~initl:l - ~acc:0 in - complete_init last_bitsoffset base_typ l lval - else () - in - Globals.Vars.iter - (fun varinfo init -> - if not varinfo.vlogic then begin - CurrentLoc.set varinfo.vdecl; - match init.init with - | None -> (* Default to zero init *) - if varinfo.vstorage = Extern - then - (* Must not assume zero when the storage is extern. *) - state := initialize_var_using_type varinfo !state - else - complete_init 0 varinfo.vtype [] (Var varinfo,NoOffset) - | Some i -> - eval_init (Var varinfo,NoOffset) i - end); - - (** Bind the declared range for NULL to uninitialized *) - if Int.le - (Base.min_valid_absolute_address ()) - (Base.max_valid_absolute_address ()) - then begin - let loc_bits = Location_Bits.inject_ival - (Ival.inject_singleton (Base.min_valid_absolute_address ())) - in - let loc_size = - Int_Base.inject - (Int.length - (Base.min_valid_absolute_address ()) - (Base.max_valid_absolute_address ())) - in - if true (* TODO: command line option *) - then - state := - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - !state - (make_loc loc_bits loc_size) - Cvalue_type.V.top_int - else - state := - Relations_type.Model.add_binding_unspecified - (* ~with_alarms:warn_none_mode - ~exact:true *) - !state - (make_loc loc_bits loc_size) - (* Cvalue_type.V.bottom *) - end; - let result = !state in - result - in - S.memo compute - - - -type predicate_value = True | False | Unknown -exception Stop -let lop_to_cop op = - match op with - | Req -> Eq - | Rneq -> Ne - | Rle -> Le - | Rge -> Ge - | Rlt -> Lt - | Rgt -> Gt - -let rec fold_on_disjunction f p acc = - match p.content with - | Por (p1,p2 ) -> fold_on_disjunction f p2 (fold_on_disjunction f p1 acc) - | _ -> f p acc - -let count_disjunction p = fold_on_disjunction (fun _pred -> succ) p 0 - -exception Predicate_alarm - -let raise_predicate_alarm () = raise Predicate_alarm - -let warn_raise_mode = - { CilE.imprecision_tracing = CilE.Aignore ; - others = CilE.Acall raise_predicate_alarm ; - unspecified = CilE.Acall raise_predicate_alarm } - -let rec reduce_by_predicate ~result ~old state positive p = - let result = - match positive,p.content with - | true,Ptrue | false,Pfalse -> state - | true,Pfalse | false,Ptrue -> Relations_type.Model.bottom - | true,Pand (p1,p2 ) | false,Por(p1,p2)-> - reduce_by_predicate ~result ~old - (reduce_by_predicate ~result ~old state positive p1) - positive - p2 - | true,Por (p1,p2 ) | false,Pand (p1, p2) -> - Relations_type.Model.join - (reduce_by_predicate ~result ~old state positive p1) - (reduce_by_predicate ~result ~old state positive p2) - - | true,Pimplies (p1,p2) -> - Relations_type.Model.join - (reduce_by_predicate ~result ~old state false p1) - (reduce_by_predicate ~result ~old state true p2) - - | false,Pimplies (p1,p2) -> - reduce_by_predicate ~result ~old - (reduce_by_predicate ~result ~old state true p1) - false - p2 - - | _,Pnot p -> reduce_by_predicate ~result ~old state (not positive) p - | true,Piff (p1, p2) -> - let red1 = - reduce_by_predicate ~result ~old - state true (Logic_const.pand (p1, p2)) - in - let red2 = - reduce_by_predicate ~result ~old state false - (Logic_const.por (p1, p2)) - in - Relations_type.Model.join red1 red2 - | false,Piff (p1, p2) -> - reduce_by_predicate ~result ~old state true - (Logic_const.por - (Logic_const.pand (p1, Logic_const.pnot p2), - Logic_const.pand (Logic_const.pnot p1, p2))) - | _,Pxor(p1,p2) -> - reduce_by_predicate ~result ~old - state (not positive) (Logic_const.piff(p1, p2)) - | _,Prel (op,t1,t2) -> - begin try - let c1 = !Db.Properties.Interp.term_to_exp ~result t1 in - let c2 = !Db.Properties.Interp.term_to_exp ~result t2 in - let t = dummy_exp (BinOp(lop_to_cop op, c1, c2, intType)) in - let state = - eval_cond ~with_alarms:warn_raise_mode - state { positive = positive ; exp = t } - in - state - with - Invalid_argument "not an lvalue" -> state - | Reduce_to_bottom -> - Relations_type.Model.bottom - (* if the exception was obtained without an alarm emitted, - it is correct to return the bottom state *) - | Predicate_alarm -> state - end - - | _,Pvalid tsets -> - begin try - let exps = !Db.Properties.Interp.loc_to_exp ~result tsets in - List.fold_left - (fun state exp -> - reduce_by_valid_expr ~with_alarms:warn_raise_mode ~positive - exp state) state exps - with Invalid_argument "not an lvalue" -> state - | Predicate_alarm -> state - end - - | _,Papp _ | _,Pold _ | _,Pat _ -> state - | _,Pexists (_varl, _p1) | _,Pforall (_varl, _p1) -> state - | _,Pfresh _ - | _,Pvalid_range (_, _, _)| _,Pvalid_index (_, _) - | _,Plet (_, _) | _,Pif (_, _, _) - | _,Psubtype _ - -> state - | _, Pseparated _ -> state - - in - result - -exception Does_not_improve - -let reduce_by_disjunction ~result ~old states n p = - if State_set.is_empty states - then states - else if (State_set.length states) * (count_disjunction p) <= n - then begin - let treat_state state acc = - let treat_pred pred acc = - let result = reduce_by_predicate ~result ~old state true pred in - if Relations_type.Model.equal result state - then raise Does_not_improve - else State_set.add result acc - in - try - fold_on_disjunction treat_pred p acc - with - Does_not_improve -> State_set.add state acc - in - State_set.fold treat_state states State_set.empty - end - else - State_set.fold - (fun state acc -> - State_set.add (reduce_by_predicate ~result ~old state true p) acc) - states - State_set.empty - -let eval_predicate ~result ~old state pred = - let rec do_eval state p = - match p.content with - | Ptrue -> True - | Pfalse -> False - | Pand (p1,p2 ) -> - begin match do_eval state p1 with - | True -> do_eval state p2 - | False -> False - | Unknown -> - ( match do_eval (reduce_by_predicate ~result ~old state true p1) p2 with - False -> False - | _ -> Unknown ) - end - | Por (p1,p2 ) -> - let val_p1 = do_eval state p1 in -(* Format.printf "Conjunction: state %a p1:%a@." - Relations_type.Model.pretty state - Cil.d_predicate_named p1;*) - begin match val_p1 with - | True -> -(* Format.printf "Conjunction: true@."; *) - True - | False -> -(* Format.printf "Conjunction: false@."; *) - do_eval state p2 - | Unknown -> begin - let reduced_state = reduce_by_predicate ~result ~old state false p1 in -(* Format.printf "Conjunction: reduced to %a to eval %a@." - Relations_type.Model.pretty reduced_state - Cil.d_predicate_named p2; *) - match do_eval reduced_state p2 with - True -> True - | _ -> Unknown - end - end - | Pxor (p1,p2) -> - begin match do_eval state p1, do_eval state p2 with - | True, True -> False - | False, False -> False - | True, False | False, True -> True - | Unknown, _ | _, Unknown -> Unknown - end - | Piff (p1,p2 ) -> - begin match do_eval state p1,do_eval state p2 with - | True, True | False, False -> True - | Unknown, _ | _, Unknown -> Unknown - | _ -> False - end - | Papp _ | Pold _ | Pat _ -> Unknown - | Pvalid tsets -> begin - try - let cexps = !Db.Properties.Interp.loc_to_exp ~result tsets in - List.iter - ( fun cexp -> - let typ = typeOf cexp in - if not (isPointerType typ) - then raise Predicate_alarm; (* TODO: global arrays *) - - let evaled = - loc_bytes_to_loc_bits - (eval_expr ~with_alarms:warn_raise_mode state cexp) - in - let size = sizeof_pointed typ in - let loc = Locations.make_loc evaled size in - if not (Locations.is_valid loc) - then raise Predicate_alarm) - cexps; - True - with - Invalid_argument "not an lvalue" -> Unknown - | Predicate_alarm -> Unknown - end - | Prel (op,t1,t2) -> - begin - try - let cexp1 = !Db.Properties.Interp.term_to_exp ~result t1 in - let cexp2 = !Db.Properties.Interp.term_to_exp ~result t2 in - let cops = - dummy_exp (BinOp(lop_to_cop op, - cexp1, - cexp2, - intType)) - in - let evaled = eval_expr ~with_alarms:warn_raise_mode state cops in - if Location_Bytes.equal - evaled - Location_Bytes.singleton_zero - then - False - else if Location_Bytes.equal - evaled - Location_Bytes.singleton_one - then - True - else Unknown - with - Invalid_argument "not an lvalue" -> Unknown - | Predicate_alarm -> Unknown - end - | Pexists (varl, p1) | Pforall (varl, p1) -> - let result = - begin try - let state = List.fold_left - (fun acc var -> - match var.lv_origin with - None -> raise Exit - | Some vi -> - let loc = loc_of_varinfo vi in - Relations_type.Model.add_binding - ~with_alarms:warn_raise_mode ~exact:true - acc loc Location_Bytes.top) - state - varl - in - do_eval state p1 - with - Exit -> Unknown - | Predicate_alarm -> Unknown - end - in - begin match p.content with - | Pexists _ -> if result = False then False else Unknown - | Pforall _ -> if result = True then True else Unknown - | _ -> assert false - end - - | Pnot p -> begin match do_eval state p with - | True -> False - | False -> True - | Unknown -> Unknown - end - | Pimplies (p1,p2) -> - do_eval state (Logic_const.por ((Logic_const.pnot p1), p2)) - | Pseparated (_tset_l) -> Unknown - | Pfresh _ - | Pvalid_range (_, _, _)| Pvalid_index (_, _) - | Plet (_, _) | Pif (_, _, _) - | Psubtype _ - -> Unknown - - in - try - match State_set.fold - (fun s acc -> - match do_eval s pred with - | Unknown -> raise Stop - |( True | False ) as arg -> - (match acc with - | None -> Some arg - | Some old when old = arg -> Some arg - | _ -> raise Stop)) - state - None - with - | None -> True - | Some v -> v - with Stop -> Unknown - -let string_of_status result = - (match result with - | Unknown -> "unknown" - | True -> "valid" - | False -> "invalid") - -let check_postconditions kf kinstr ~result ~slevel header init_state state kind behaviors = - let incorporate_behavior state b = - if b.b_post_cond = [] then state - else - (* TODO: have an individual status for each post. *) - let header = - if Cil.is_default_behavior b then header - - else header ^ ", behavior " ^ b.b_name - in - let vc = Ast_info.behavior_postcondition b kind in - let assumes = - (Logic_const.pands - (List.map Logic_const.pred_of_id_pred b.b_assumes)) - in - let activated = eval_predicate ~result ~old:None init_state assumes in - let update_status st = - let ip = Property.ip_ensures_of_behavior kf kinstr b in - List.iter (swap Status.join st) ip - in - let old = init_state in - match activated with - | True -> - (let res = eval_predicate ~result ~old state vc in - Value_parameters.result ~once:true ~current:true - "%s: postcondition got status %s" header (string_of_status res); - match res with - | False -> update_status status_false; State_set.empty - | True -> - update_status status_true; - (* The reduction is needed in the True case, - because the function is "reduce_by_disjunction". - Example: //@ assert x<0 || x>=0; *) - reduce_by_disjunction ~result ~old state slevel vc - | Unknown -> - update_status status_maybe; - reduce_by_disjunction ~result ~old state slevel vc) - | Unknown -> - (let res = eval_predicate ~result ~old state vc in - Value_parameters.result ~once:true ~current:true - "%s: postcondition got status %s" header (string_of_status res); - match res with - Unknown | False -> - update_status status_maybe; - Value_parameters.result ~once:true ~current:true - "%s: postcondition got status %s, \ - but it is unknown if the behavior is active" - header (string_of_status res); - state - | True -> - update_status status_true; - Value_parameters.result ~once:true ~current:true - "%s: postcondition got status valid" header; - state) - | False -> - (* if assumes is false, post-condition status is not updated *) - Value_parameters.result ~once:true ~current:true - "%s: assumption got status invalid; post-condition not evaluated" - header; - state - in - List.fold_left incorporate_behavior state behaviors - -let check_fct_postconditions ~result kf init_state state kind = - try - let spec = (Kernel_function.get_spec kf).spec_behavior in - let slevel = get_slevel kf in - check_postconditions kf Kglobal ~result ~slevel - (Pretty_utils.sfprintf "Function %a@?" Kernel_function.pretty_name kf) - init_state state kind spec - with Not_found -> state - -let check_preconditions kf kinstr ~slevel header state spec = - let incorporate_behavior state b = - let header = - if Cil.is_default_behavior b then header - else header ^ ", behavior " ^ b.b_name - in - if b.b_requires = [] then state - else - let assumes = - (Logic_const.pands - (List.map Logic_const.pred_of_id_pred b.b_assumes)) - in - (* TODO: have an individual status for each requires. *) - let vc = - (Logic_const.pands - (List.map Logic_const.pred_of_id_pred b.b_requires)) - in - let activated = eval_predicate ~result:None ~old:None state assumes in - let update_status st = - let ip = Property.ip_requires_of_behavior kf kinstr b in - List.iter (swap Status.join st) ip - in - match activated with - | True -> - (let res = eval_predicate ~result:None ~old:None state vc in - Value_parameters.result ~once:true ~current:true - "%s: precondition got status %s" - header - (string_of_status res); - match res with - | False -> update_status status_false; State_set.empty - | True -> - update_status status_true; - (* The reduction is needed in the True case, - because the function is "reduce_by_disjunction". - Example: //@ assert x<0 || x>=0; *) - reduce_by_disjunction ~result:None ~old:None state slevel vc - | Unknown -> - update_status status_maybe; - reduce_by_disjunction ~result:None ~old:None state slevel vc) - | Unknown -> - (let res = eval_predicate ~result:None ~old:None state vc in - Value_parameters.result ~once:true ~current:true - "%s: precondition got status %s" - header - (string_of_status res); - match res with - Unknown | False -> - update_status status_maybe; - Value_parameters.result ~once:true ~current:true - "%s: precondition got status %s, but it is unknown if the behavior is active" - header (string_of_status res); - state - | True -> - update_status status_true; - Value_parameters.result ~once:true ~current:true - "%s: precondition got status valid" header; - state) - | False -> - (* if assumes is false, post-condition status is not updated *) - Value_parameters.result ~once:true ~current:true - "%s: assumption got status invalid; precondition not evaluated" - header; - state - in - List.fold_left - incorporate_behavior - state spec.spec_behavior - -let check_fct_preconditions kf state = - try - let spec = Kernel_function.get_spec kf in - let slevel = get_slevel kf in - check_preconditions kf Kglobal ~slevel - (Pretty_utils.sfprintf "Function %a@?" Kernel_function.pretty_name kf) - (State_set.singleton state) spec - with Not_found -> (State_set.singleton state) - -let extract_valid_behaviors state behavior = - List.filter - (fun b -> - let assumes = Logic_const.pands - (List.map Logic_const.pred_of_id_pred b.b_assumes) in - match eval_predicate ~result:None ~old:None state assumes with - | True | Unknown -> true - | False -> false) - behavior.spec_behavior - -(* state before entering the given function *) -let valid_behaviors kf state = - extract_valid_behaviors - (State_set.singleton state) - (Kernel_function.get_spec kf) - -let () = Db.Value.valid_behaviors := valid_behaviors - - -(* SEE eval_lval and do_assign to be consistent. - Same match cases must exist in order to be precise. - May raise [Lmap.Cannot_copy]. -*) -let copy_offsetmap_from_virtual ~with_alarms - loc1 lv2 loc2 (state:Relations_type.Model.t) = - if (not (Int_Base.equal loc1.size loc2.size)) - || (try - ignore - (Location_Bits.cardinal_less_than loc2.loc - (Value_parameters.ArrayPrecisionLevel.get ())); - false - with Not_less_than -> true) - then begin - raise Lmap.Cannot_copy - end; - let target_offset = snd lv2 in -(* let target_size = sizeof_lval lv2 in - let target_size = Int_Base.project target_size in*) - let target_size = - try Int_Base.project loc2.size - with Int_Base.Error_Top -> raise Lmap.Cannot_copy - in - let result_relations = - match fst lv2 with - | Mem({enode = Lval slv} as e) when UseRelations.get () -> - let sub_left_loc = lval_to_loc ~with_alarms state slv in - begin try - let _, _, target_offset = - try - eval_offset ~reduce_valid_index:(Parameters.SafeArrays.get ()) - ~with_alarms None (typeOf e) state target_offset - with Offset_not_based_on_Null _ -> raise Lmap.Cannot_copy - in - let offsetmap = - Relations_type.Model.copy_from_virtual - sub_left_loc target_offset target_size state - in - offsetmap - with Relations_type.Use_Main_Memory -> - Cvalue_type.V_Offsetmap.empty - end - | Mem({enode = BinOp((PlusPI|IndexPI|MinusPI as op), - {enode = Lval slv},e2,_)} as e) - when UseRelations.get () -> - let typ = typeOf e in - let e2 = eval_expr ~with_alarms state e2 in - begin try - - let ival = (Cvalue_type.V.project_ival e2) in - let ival = if op=MinusPI then Ival.neg ival else ival in - let ival = Ival.scale - (Int_Base.project (sizeof_pointed typ)) - ival - in - let sub_left_loc = lval_to_loc ~with_alarms state slv in - (*TODO: with_alarms:false should be used ? *) - let _, _, target_offset = eval_offset - ~reduce_valid_index:(Parameters.SafeArrays.get ()) - ~with_alarms None typ state target_offset in - let target_offset = Ival.add target_offset ival in - let offsetmap = - Relations_type.Model.copy_from_virtual - sub_left_loc target_offset target_size state - in - offsetmap - with Relations_type.Use_Main_Memory | Cvalue_type.V.Not_based_on_null -> - Cvalue_type.V_Offsetmap.empty - end - - | _ -> - Cvalue_type.V_Offsetmap.empty - in - result_relations - -let need_cast t1 t2 = - match (unrollType t1, unrollType t2) with - | (TInt _| TEnum _| TPtr _),(TInt _| TEnum _| TPtr _) - | (TFloat _,TFloat _) - | (TComp _, TComp _) -> - (try bitsSizeOf t1 <> bitsSizeOf t2 - with SizeOfError _ -> true) - | _ -> true - - -module Computer - (AnalysisParam:sig - val stmt_can_reach : stmt -> stmt -> bool - val is_natural_loop : stmt -> bool - val slevel: int - val initial_state : State_set.t - end) = - -struct - let debug = ref false - let name = "Values analysis" - - let stmt_can_reach = AnalysisParam.stmt_can_reach - let slevel = AnalysisParam.slevel - let debug = ref false - - let current_table = Current_table.create () - - let states_after = Cil_datatype.Stmt.Hashtbl.create 17 - - - (* During the dataflow analysis, if required by a callback, we store the - state after a statement, but only if the following conditions are met - ([succ] being a successor of [s]) - - if [s] is an instr (which almost always change the state, unlike - the other kind of statements) - - if there is a control-flow join on [succ] - - if [s] is the last instruction of a block that contains - local variables - For statements for which the function below returns false, we deduce - the state after by the state before [succ] or another successor of [s]. - This avoid potentially useless computations - *) - let store_state_after_during_dataflow s succ = - ((match s.skind with Instr _ -> true | _ -> false) && - (match succ.preds with [_] -> false | _ -> true)) - || (let b1 = Kernel_function.find_enclosing_block s - and b2 = Kernel_function.find_enclosing_block succ in - not (Cil_datatype.Block.equal b1 b2) && b1.blocals <> []) - - - let merge_current ~degenerate = - let superposed = lazy (Current_table.states current_table) in - Current_table.merge_db_table superposed; - if not degenerate && - ((not (Db.Value.Record_Value_Callbacks.is_empty ())) || - (not (Db.Value.Record_Value_Superposition_Callbacks.is_empty ())) || - (not (Db.Value.Record_Value_After_Callbacks.is_empty ()))) - then begin - let stack_for_callbacks = for_callbacks_stack () in - - if not (Db.Value.Record_Value_Superposition_Callbacks.is_empty ()) - then begin - let current_superpositions = - Current_table.superpositions current_table - in - Value_parameters.feedback - "now calling Record_Value_Superposition callbacks"; - Db.Value.Record_Value_Superposition_Callbacks.apply - (stack_for_callbacks, current_superpositions); - end ; - - if not (Db.Value.Record_Value_Callbacks.is_empty ()) - then begin - Value_parameters.feedback "now calling Record_Value callbacks"; - Db.Value.Record_Value_Callbacks.apply - (stack_for_callbacks, Lazy.force superposed) - end; - - if not (Db.Value.Record_Value_After_Callbacks.is_empty ()) - then begin - Value_parameters.feedback "now calling Record_After_Value callbacks"; - let superposed = Lazy.force superposed in - Cil_datatype.Kinstr.Hashtbl.iter - (fun ki state -> - match ki with - | Kglobal -> () - | Kstmt stmt -> - List.iter - (fun pred -> - if not (store_state_after_during_dataflow pred stmt) - then - try - let cur = Cil_datatype.Stmt.Hashtbl.find - states_after pred in - Cil_datatype.Stmt.Hashtbl.replace - states_after pred - (Relations_type.Model.join state cur) - with Not_found -> - Cil_datatype.Stmt.Hashtbl.add - states_after pred state - ) - stmt.preds; - ) - superposed; - (* Since the return instruction has no successor, it is not visited - by the iter above. We fill it manually *) - let ret = Kernel_function.find_return (current_kf ()) in - (try - let s = Cil_datatype.Kinstr.Hashtbl.find superposed (Kstmt ret) in - Cil_datatype.Stmt.Hashtbl.add states_after ret s - with Not_found -> () - ); - - - Db.Value.Record_Value_After_Callbacks.apply - (stack_for_callbacks, states_after); - end; - - end; - Current_table.clear current_table - - type u = - { counter_unroll : int; (* how many times this state has been crossed *) - mutable value : State_set.t ; } - - module StmtStartData = - Dataflow.StmtStartData(struct type t = u let size = 107 end) - - type t = u - - let copy (d: t) = d - - let display_one fmt v = - State_set.iter (fun value -> - if not (Relations_type.Model.is_reachable value) then begin - Format.fprintf fmt "Statement (x%d): UNREACHABLE@\n" - v.counter_unroll ; - end - else - (Format.fprintf fmt "Statement (x%d)@\n%a" - v.counter_unroll - Relations_type.Model.pretty - value)) - (v.value) - - let pretty fmt (d: t) = display_one fmt d - - let computeFirstPredecessor (_s: stmt) state = - { - counter_unroll = 0; - value = state.value;} - - let getWidenHints (s: stmt) = - Widen.getWidenHints (current_kf()) s - - let counter_unroll_target = ref 100 - - let combinePredecessors (_s: stmt) ~old new_ = - if State_set.is_empty (new_.value) - then None - else begin - if old.counter_unroll >= slevel - then - let sum = - Relations_type.Model.join - (State_set.join (new_.value)) - (State_set.join (old.value)) - in - Some {counter_unroll = old.counter_unroll ; - value = (State_set.singleton sum);} - else begin try - let merged = State_set.merge_into (new_.value) (old.value) in - let length_new = State_set.length (new_.value) in - let new_counter_unroll = old.counter_unroll + length_new in - if new_counter_unroll >= !counter_unroll_target - then begin - Value_parameters.result ~once:true - "Semantic level unrolling superposing up to %d states" - !counter_unroll_target; - counter_unroll_target := !counter_unroll_target + 100; - end; - let result = - Some - { value = merged ; - counter_unroll = new_counter_unroll } - in - result - with State_set.Unchanged -> None - end - end - - - - -(** Precondition: the type of [exp] and the type [loc_lv] may be different - only if the cast from [typeOf exp] and [typeOf loc_lv] is a truncation - or an extension. - This function will not perform any conversion (float->int, int->float, ...) - [exp] should not be bottom for optimization purposes in the caller. - *) - let do_assign_abstract_value_to_loc ~with_alarms state lv loc_lv exp = - assert (not (Cvalue_type.V.is_bottom exp)); - (* Or one may propagate bottoms uselessly for too long. *) - let exp = (* truncate the value if the [lv] is too small: this may - happen when the [lv] is a bitfield. Otherwise, the - cast is explicit thanks to Cil and no truncation is - necessary. *) - try - (* if it is a bitfield, the size is statically known. *) - let size = Int_Base.project loc_lv.size in - try - let old_ival = V.project_ival exp in - let exp = - V.inject_ival (* Inject on null as [project_ival] did not raise - [Not_based_on_null] *) - (Ival.cast - ~size - ~signed:(signof_typeof_lval lv) - (* the sign can be computed on integral types. *) - ~value:old_ival) - in - exp - with - | V.Not_based_on_null (* from [project_ival] *) -> - (* The exp is a pointer: check there are enough bits in - the bitfield to contain it. *) - if Int.compare size (Int.of_int (sizeofpointer ())) >= 0 - || V.is_imprecise exp - then exp - else begin - Value_parameters.result "casting address to a bitfield of %s bits: this is smaller than sizeof(void*)" (Int.to_string size); - V.topify_arith_origin exp - end - | Neither_Int_Nor_Enum_Nor_Pointer - (* from [signof_typeof_lval] *) -> exp - with - | Int_Base.Error_Top | Int_Base.Error_Bottom -> - (* from [project]: size is not known *) - exp - in - let pretty_org fmt org = if not (Origin.is_top org) then - Format.fprintf fmt " because of %a" Origin.pretty org - in - (match loc_lv.loc with - | Location_Bits.Top (Location_Bits.Top_Param.Top, orig) -> - Value_parameters.result - "State before degeneration:@\n======%a@\n=======" - Relations_type.Model.pretty state; - Value_parameters.warning ~once:true - "writing at a completely unknown address@[%a@].@\nAborting." - pretty_org orig; - do_degenerate (Some lv) - - | Location_Bits.Top((Location_Bits.Top_Param.Set _) as param,orig) -> - Value_parameters.result ~current:true ~once:true - "writing somewhere in @[%a@]@[%a@]." - Location_Bits.Top_Param.pretty param - pretty_org orig - | Location_Bits.Map _ -> (* everything is normal *) ()); - let exact = valid_cardinal_zero_or_one loc_lv in - let value = - Relations_type.Model.add_binding ~with_alarms ~exact - state loc_lv exp - in - value - - (** Clobber list for bases containing addresses of local variables. *) - let bases_containing_locals = ref Location_Bits.Top_Param.bottom - let remember_bases_with_locals = - remember_bases_with_locals bases_containing_locals - - (** Precondition: the type of [exp] and the type [loc_lv] may be different - only if the cast from [typeOf exp] - and [typeOfPointed lv] is a truncation or an extension. - This function will not perform any conversion (float->int, int->float,..) - *) - let do_assign_abstract_value ~with_alarms - ~former_state - (state:Relations_type.Model.t) - lv - exp = - let state_for_lv = - if true (*!Cabs2cil.forceRLArgEval*) then state - else former_state - in - let loc_lv = lval_to_loc ~with_alarms state_for_lv lv in - remember_bases_with_locals loc_lv exp; - CilE.set_syntactic_context (CilE.SyMem lv); - do_assign_abstract_value_to_loc ~with_alarms state lv loc_lv exp - - - let offsetmap_top_addresses_of_locals is_local = - let is_local_bytes = Location_Bytes.contains_addresses_of_locals is_local in - fun offsetmap -> - if Cvalue_type.V_Offsetmap.is_empty offsetmap - then offsetmap, true - else - let found_locals = ref false in - let loc_contains_addresses_of_locals t = - let l = - is_local_bytes (Cvalue_type.V_Or_Uninitialized.get_v t) - in - found_locals := !found_locals - || (l - && (match Cvalue_type.V_Or_Uninitialized.get_v t with - | Location_Bytes.Top (Location_Bytes.Top_Param.Top,_) -> false - (* Do not be too verbose if the value is top. *) - | _ -> true)); - l - in - let result = - Cvalue_type.V_Offsetmap.top_stuff - loc_contains_addresses_of_locals - (fun v -> - Cvalue_type.V_Or_Uninitialized.unspecify_escaping_locals - is_local v) - offsetmap - in - result, !found_locals - - let state_top_addresses_of_locals ~is_block - offsetmap_top_addresses_of_locals fundec - = - let f k offsm = - let r,found_locals = offsetmap_top_addresses_of_locals offsm in - if found_locals then - warn_locals_escape is_block fundec k; - r - in - (fun (state:Relations_type.Model.t) -> - (* let's forget relations *) - let simple_state = Relations_type.Model.value_state state in - let f base acc = - try - let offset_to_clean = Cvalue_type.Model.find_base base simple_state - in - let cleaned_offsetmap = f base offset_to_clean in - Cvalue_type.Model.add_offsetmap base cleaned_offsetmap acc - with Not_found -> acc - in - try - Relations_type.Model.inject - (Location_Bits.Top_Param.fold - f - !bases_containing_locals - (f Base.null simple_state)) - with Location_Bits.Top_Param.Error_Top -> - begin - let f k offsm acc = - let r,found_locals = offsetmap_top_addresses_of_locals offsm in - if found_locals then - warn_locals_escape is_block fundec k; - Cvalue_type.Model.add_offsetmap k r acc - in - let result = - try - Relations_type.Model.inject - (Cvalue_type.Model.fold_base_offsetmap - f - (Relations_type.Model.value_state state) - Cvalue_type.Model.empty_map) - with Cvalue_type.Model.Error_Bottom -> Relations_type.Model.bottom - in - result - - end) - - let top_addresses_of_locals fundec = - let entry_point = Globals.entry_point () in - if snd entry_point (* lib *) || - current_kf() != fst entry_point (* not entry point *) - then - let offsetmap_top_addresses_of_locals = - offsetmap_top_addresses_of_locals (swap Base.is_formal_or_local fundec) - in - let state_top_addresses_of_locals = - state_top_addresses_of_locals ~is_block:false - offsetmap_top_addresses_of_locals fundec - in - offsetmap_top_addresses_of_locals, state_top_addresses_of_locals - else (fun x -> x,false),(fun x -> x) - - let block_top_addresses_of_locals blocks = - if List.for_all (fun b -> List.for_all (fun v -> v.vgenerated) b.blocals) - blocks - then - fun x -> x (* no need to change the state if there is no local - variable or if all the variable have been generated - by Cil (in which case we know that they are correctly - initialized and used, don't we) - *) - else - let offsetmap_top_addresses_of_locals = - offsetmap_top_addresses_of_locals - (fun v -> List.exists (Base.is_block_local v) blocks) - in - let state_top_addresses_of_locals = - state_top_addresses_of_locals ~is_block:true - offsetmap_top_addresses_of_locals - (Kernel_function.get_definition (current_kf())) - in - state_top_addresses_of_locals - - (* Assigns [exp] to [lv] in [state] *) - let do_assign ~with_alarms old_state lv exp = - assert (Relations_type.Model.is_reachable old_state); - let fresh_flags () = - let flag = ref false in - (fun () -> flag := true), - fun () -> !flag - in - let set_alarm, get_alarm = fresh_flags () in - let logger v = - if v <> CilE.Aignore - then CilE.Acall set_alarm - else CilE.Aignore - in - let warn_remember_mode = - { CilE.imprecision_tracing = logger with_alarms.CilE.imprecision_tracing; - others = with_alarms.CilE.others; - unspecified = logger with_alarms.CilE.unspecified} - in - let reduced_state, _, evaled_exp = - eval_expr_with_deps_state_subdiv ~with_alarms:warn_remember_mode None - old_state - exp - in - Value_parameters.debug ~level:2 "do_assign %a = (%a)(%a)" - !d_lval lv - !d_exp exp - V.pretty evaled_exp; - let left_loc = lval_to_loc ~with_alarms old_state lv in - remember_bases_with_locals left_loc evaled_exp; - let warn_right_exp_imprecision () = - (match with_alarms.CilE.imprecision_tracing with - | CilE.Aignore -> () - | CilE.Acall f -> f () - | CilE.Alog -> - match evaled_exp with - | Cvalue_type.V.Top(_topparam,origin) -> - Value_parameters.result ~once:true ~current:true - "assigning imprecise value to @[%a@]@[%t@]@[%a@]" - !Ast_printer.d_lval lv - (fun fmt -> match lv with - | (Mem _, _) -> - Format.fprintf fmt " (i.e. %a)" Locations.pretty left_loc - | (Var _, _) -> ()) - (fun fmt org -> - if not (Origin.is_top origin) then - Format.fprintf fmt ".@ The imprecision originates from %a" - Origin.pretty org) - origin - | Cvalue_type.V.Map _ -> - if not (Got_Imprecise_Value.get ()) && - not (Cvalue_type.V.cardinal_zero_or_one evaled_exp) - then begin - Got_Imprecise_Value.set true; - Value_parameters.result ~current:true - "assigning non deterministic value for the first time"; - end) - in - let reduced_state = - match lv with - Mem mem_e,NoOffset -> - let new_reduced_state = - reduce_by_valid_expr ~with_alarms ~positive:true mem_e reduced_state - in - if not (Relations_type.Model.is_reachable new_reduced_state) - then begin - CilE.set_syntactic_context (CilE.SyMem lv); - CilE.warn_mem_write with_alarms ; - Value_parameters.result ~current:true - "all target addresses were invalid. This path is assumed to be dead."; - end; - new_reduced_state - (* | Var _ , Index _ -> assert false - TODO: do something for "TAB[i] = expr" - *) - | _ -> reduced_state - in - let default () = - warn_right_exp_imprecision (); - if get_alarm() then - (* log alarms that have not been logged the first time *) - ignore - (eval_expr - ~with_alarms: - {CilE.imprecision_tracing=with_alarms.CilE.imprecision_tracing; - others=CilE.Aignore; - unspecified=with_alarms.CilE.unspecified} - old_state - exp); - - if Cvalue_type.V.is_bottom evaled_exp || - Location_Bits.equal left_loc.loc Location_Bits.bottom || - not (Relations_type.Model.is_reachable reduced_state) - then Relations_type.Model.bottom - else begin - CilE.set_syntactic_context (CilE.SyMem lv); - do_assign_abstract_value_to_loc ~with_alarms - reduced_state - lv - left_loc - evaled_exp - end - in - let default_lval exp_lv = - (* directly copy the old value without trying to recompose it. - Useful for structs assignment. *) - let right_loc = lval_to_loc ~with_alarms old_state exp_lv in - - CilE.set_syntactic_context (CilE.SyMem exp_lv); - let full_val = - Relations_type.Model.find_unspecified - ~with_alarms:CilE.warn_none_mode - old_state - right_loc - in - if Location_Bits.equal left_loc.loc Location_Bits.bottom || - not (Relations_type.Model.is_reachable reduced_state) || - V_Or_Uninitialized.equal full_val V_Or_Uninitialized.bottom - then Relations_type.Model.bottom - else begin - match right_loc.size, left_loc.size with - | Int_Base.Value size, Int_Base.Value other_size - when Int.equal other_size size -> - let offsetmap_relations = - try - copy_offsetmap_from_virtual - ~with_alarms - right_loc exp_lv left_loc old_state - with Lmap.Cannot_copy -> - Cvalue_type.V_Offsetmap.empty - in - CilE.set_syntactic_context (CilE.SyMem exp_lv); - let offsetmap_memory = - match Relations_type.Model.copy_offsetmap ~with_alarms right_loc old_state with - | Some v -> v - | None -> raise Lmap.Cannot_copy (* invalid copy paste *) - in - let offsetmap = - Cvalue_type.V_Offsetmap.over_intersection - offsetmap_relations - offsetmap_memory - in - if not (Cvalue_type.V_Offsetmap.is_empty offsetmap) - then begin - CilE.set_syntactic_context (CilE.SyMem lv); - let copy_paste_succeeded = - Relations_type.Model.paste_offsetmap - offsetmap left_loc.loc Int.zero size reduced_state - in - (* Shall we warn about imprecise contents just copied? *) - let module L = struct exception Got_imprecise end in - (try - Cvalue_type.V_Offsetmap.iter_contents - (fun v -> - match Cvalue_type.V_Or_Uninitialized.get_v v with - | Location_Bytes.Map _ -> () - | _ -> raise L.Got_imprecise) - offsetmap - size - with L.Got_imprecise -> - warn_right_exp_imprecision ()); - copy_paste_succeeded - end - else raise Lmap.Cannot_copy - | _ -> raise Lmap.Cannot_copy - end - in - let new_main_memory_state = - try - (* An lval assignement might be hidden by a dummy cast *) - let lv = find_lv ~with_alarms old_state exp in - default_lval lv - with | Cannot_find_lv | Lmap.Cannot_copy - (* from Relations_type.Model.paste_offsetmap or directly default_lval *) -> - default () - in (* The main memory state is now computed. *) - (* Let's try to improve it with relations *) - if UseRelations.get () - && Relations_type.Model.is_reachable new_main_memory_state - then begin - if (* hasAttribute "volatile" (typeAttrs (typeOf exp)) - || hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lv)) doesn't work *) - false - then begin - Relations_type.Model.propagate_change_from_real_to_virt - [] - left_loc - new_main_memory_state - evaled_exp - end - else - let list_lv = find_lv_plus ~with_alarms old_state exp in - try - let (_lv_right,offs_right) = - List.find - (fun (lv_right,_offs_right) -> - Location_Bits.equal left_loc.loc - (lval_to_loc ~with_alarms:CilE.warn_none_mode old_state lv_right).loc) - list_lv (* Check for a self assignement *) - in - Relations_type.Model.shift_location - new_main_memory_state - left_loc - offs_right - evaled_exp - with Not_found -> (* not a self assignement *) - let protected_clusters,optimized_state_value = - match lv with - | Mem({enode = Lval slv} as e),offs -> - let sub_left_loc = - lval_to_loc ~with_alarms old_state slv - in - if Location_Bits.is_relationable sub_left_loc.loc then - Relations_type.Model.add_mem - sub_left_loc - (sizeof_lval lv) - (try - let _,_,offset = - eval_offset - ~reduce_valid_index:(Parameters.SafeArrays.get ()) - ~with_alarms - None (typeOf e) old_state offs - in - offset - with Offset_not_based_on_Null _ -> Ival.top) - new_main_memory_state - evaled_exp - else [],new_main_memory_state - - | Mem({enode = BinOp((PlusPI|IndexPI|MinusPI as op), - { enode = Lval slv},e2,_)} as e), - offs -> - let typ = typeOf e in - let e2 = eval_expr ~with_alarms old_state e2 in - begin try - let ival = Cvalue_type.V.project_ival e2 in - let ival = if op = MinusPI then Ival.neg ival else ival - in - let _, _, offs = - eval_offset - ~reduce_valid_index:(Parameters.SafeArrays.get ()) - ~with_alarms - None typ old_state offs - in - let offs = (* convert to bits *) - Ival.add - (Ival.scale - (Int_Base.project (sizeof_pointed typ)) - ival) - offs - in - let sub_left_loc = - lval_to_loc ~with_alarms old_state slv - in - if Location_Bits.is_relationable sub_left_loc.loc - then - Relations_type.Model.add_mem - sub_left_loc - (sizeof_lval lv) - offs - new_main_memory_state - evaled_exp - else [],new_main_memory_state - with - | Offset_not_based_on_Null _ - | Int_Base.Error_Top - | Cvalue_type.V.Not_based_on_null -> [],new_main_memory_state - end - | _ -> [],new_main_memory_state - in - (* Let's clean the obsoleted relations. *) - let optimized_state_value = - Relations_type.Model.propagate_change_from_real_to_virt - protected_clusters - left_loc - optimized_state_value - evaled_exp - in - let rec optimize_list_lv l = - match l with - [] -> optimized_state_value - | (lvr,offset) :: tail -> - if Ival.is_singleton_int offset - then begin - let locr = lval_to_loc ~with_alarms old_state lvr in - if Location_Bits.is_relationable locr.loc - then - Relations_type.Model.add_equality - ?offset:(Some (Ival.neg offset)) - optimized_state_value left_loc locr - else optimize_list_lv tail - end - else optimize_list_lv tail - in - optimize_list_lv list_lv - end - else new_main_memory_state - - - - let do_assign ~with_alarms old_state lv exp = - if true then do_assign ~with_alarms old_state lv exp - else - let vars = - get_influential_vars ~with_alarms:CilE.warn_none_mode old_state exp - in - let rec try_sub vars = - match vars with - [] | [ _ ] -> - do_assign ~with_alarms old_state lv exp - | v :: tail -> - try - if not (List.exists (fun x -> Locations.loc_equal v x) tail) - then raise Too_linear; - let value = - Relations_type.Model.find - ~conflate_bottom:true - ~with_alarms:CilE.warn_none_mode - old_state - v - in - - if Locations.Location_Bytes.is_included value Locations.Location_Bytes.top_float - then raise Too_linear; - - ignore (Cvalue_type.V.splitting_cardinal_less_than - ~split_non_enumerable:42 value 142); - Value_parameters.debug - "subdiv assignment: candidate %a value %a@." - Locations.pretty v - Cvalue_type.V.pretty value; - let treat_subdiv subvalue acc = - let sub_oldstate = - (* FIXME: should be relation-aware primitive *) - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:true - old_state - v - subvalue - in - let sub_newstate = - do_assign ~with_alarms sub_oldstate lv exp - in - Relations_type.Model.join acc sub_newstate - in - Location_Bytes.fold_enum - ~split_non_enumerable:42 - treat_subdiv - value - Relations_type.Model.bottom - with - Not_less_than | Too_linear -> - try_sub tail - | Location_Bytes.Error_Top -> - assert false; - in - try_sub vars - - exception Got_bottom - - let empty_interpretation_result = - None, Relations_type.Model.bottom, Location_Bits.Top_Param.bottom - - let offsetmap_of_lv ~with_alarms state lv = - CilE.set_syntactic_context (CilE.SyMem lv); - let loc_to_read = - lval_to_loc ~with_alarms state lv - in - Relations_type.Model.copy_offsetmap - ~with_alarms:CilE.warn_none_mode - loc_to_read - state - - let interp_call stmt lval_to_assign funcexp argl d_value = - let call_site_loc = CurrentLoc.get () in - let with_alarms = warn_all_quiet_mode () in - let treat_one_state state acc = - let new_state_after_call = - try - let _, functions = - resolv_func_vinfo ~with_alarms - None state funcexp - in - let is_library_function kf = - not (Kernel_function.is_definition kf) - in - let calling_at_least_one_library_function = - Kernel_function.Hptset.exists - is_library_function - functions - in - let calling_all_library_functions = - calling_at_least_one_library_function && - (Kernel_function.Hptset.for_all - is_library_function - functions) - in - let actuals = - List.map - (fun e -> - let interpreted_expr, o = - match e with - { enode = Lval l } -> - let _, _, interpreted_expr = - eval_lval ~conflate_bottom:false ~with_alarms - None state l - in - if calling_at_least_one_library_function - then begin - let _, _, conf_expr = - eval_lval ~conflate_bottom:true ~with_alarms - None state l - in - ignore (conf_expr); - end; - if calling_all_library_functions && - V.is_bottom interpreted_expr - then begin - Value_parameters.result ~current:true - "Non-termination in evaluation of library function call l-value argument"; - raise Got_bottom; - end; - let r = do_cast ~with_alarms (typeOf e) interpreted_expr - in - let o = - offsetmap_of_lv ~with_alarms:(warn_all_quiet_mode ()) - state - l - in - r, out_some o - | _ -> - let interpreted_expr = - eval_expr ~with_alarms state e - in - if V.equal interpreted_expr V.bottom - then begin - Value_parameters.result ~current:true - "Non-termination in evaluation of function call expression argument"; - raise Got_bottom - end; - interpreted_expr, - Builtins.offsetmap_of_value ~typ:(Cil.typeOf e) - interpreted_expr - in - e,interpreted_expr,o) - argl - in - let treat_one_call f (acc_rt,acc_res,acc_clobbered_set) = - let caller = current_kf (), stmt in - Kf_state.add_caller f ~caller; - let return, result, clobbered_set = - !compute_call_ref - f - ~call_kinstr:(Kstmt stmt) - state - actuals - in - CurrentLoc.set call_site_loc; - (match acc_rt,return with - | None,_ -> return - | Some _, None -> acc_rt - | Some acc_rt, Some return -> - Some (snd (V_Offsetmap.join - acc_rt - return))), - Relations_type.Model.join acc_res result, - Location_Bits.Top_Param.join acc_clobbered_set clobbered_set - in - let return,new_state,clobbered_set = - Kernel_function.Hptset.fold - treat_one_call - functions - empty_interpretation_result - in - - bases_containing_locals := - Location_Bits.Top_Param.join - !bases_containing_locals - clobbered_set; - - match lval_to_assign with - | None -> new_state - | Some lv -> - begin match return with - | Some return -> - let loc = - lval_to_loc - ~with_alarms new_state lv - in - let rtype = - getReturnType (typeOf funcexp) - in - let lvtyp = typeOfLval lv in - let default () = - let value_with_init - = - V_Offsetmap.find_ival - ~conflate_bottom:false - ~validity:Base.All - ~with_alarms:CilE.warn_none_mode - Ival.zero - return - (Int.of_int (bitsSizeOf rtype)) - in - let flags = V_Or_Uninitialized.get_flags value_with_init - in - let init = V_Or_Uninitialized.is_initialized flags in - let no_esc = V_Or_Uninitialized.is_noesc flags in - let value = V_Or_Uninitialized.get_v value_with_init in - if not init - then CilE.warn_uninitialized with_alarms; - if not no_esc - then CilE.warn_escapingaddr with_alarms; - if Cvalue_type.V.is_bottom value - && not (init && no_esc) - then - Value_parameters.result ~current:true - "Function call returned an unspecified value. This path is assumed to be dead."; - - let exact = valid_cardinal_zero_or_one loc in - let evaled_exp = - do_cast - ~with_alarms:CilE.warn_none_mode - lvtyp - value - in - remember_bases_with_locals loc evaled_exp; - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact - new_state - loc - evaled_exp - in - if need_cast lvtyp rtype - then - default () - else - (try - let result = - Relations_type.Model.paste_offsetmap - return - loc.loc - Int.zero - (Int_Base.project loc.size) - new_state - in - let evaled_exp= - Cvalue_type.V_Or_Uninitialized.get_v - (V_Offsetmap.find_ival - ~conflate_bottom:false - ~validity:Base.All - ~with_alarms:CilE.warn_none_mode - Ival.zero - return - (Int.of_int (bitsSizeOf rtype)) - ) - in - remember_bases_with_locals loc evaled_exp; - result - with Lmap.Cannot_copy -> default ()) - | None -> - (if Relations_type.Model.is_reachable new_state - then - Value_parameters.warning ~current:true - "In function %t: called function returns void but returned value is assigned; ignoring assignment" - pretty_current_cfunction_name; - new_state) - end - with - | Ignore -> - CurrentLoc.set call_site_loc; - state - | Got_bottom -> - CurrentLoc.set call_site_loc; - Relations_type.Model.bottom - | Leaf -> - CurrentLoc.set call_site_loc; - (match lval_to_assign with - | None -> state - | Some lv -> - let evaled_exp = V.top_leaf_origin () in - do_assign_abstract_value - ~with_alarms - ~former_state:state - state - lv - evaled_exp) - in - State_set.add new_state_after_call acc - in - State_set.fold - treat_one_state - d_value - State_set.empty - - let doInstr stmt (i: instr) (d: t) = - !Db.progress (); - CilE.start_stmt (Kstmt stmt); - let d_states = (d.value) in - let unreachable = State_set.is_empty d_states in - let result = - if unreachable then - Dataflow.Done d - else begin - let apply_each_state f = - let modified_states = - State_set.fold - (fun state_value acc -> State_set.add (f state_value) acc) - d_states - State_set.empty - in - Dataflow.Done { counter_unroll = 0; value = modified_states } - in - (* update current statement *) - match i with - | Set (lv,exp,_loc) -> - apply_each_state - (fun state_value -> - do_assign - ~with_alarms:(warn_all_quiet_mode ()) - state_value - lv - exp) - | Call (None, - {enode = Lval (Var {vname=("__builtin_va_start"|"__builtin_va_arg"|"__builtin_va_end" as _builtin_name) },NoOffset)}, - [{enode = Lval lv}],_loc) -> -(* Format.printf "builtin: %s@." _builtin_name; *) - apply_each_state - (fun state_value -> - do_assign_abstract_value - ~with_alarms:(warn_all_quiet_mode ()) - ~former_state:state_value - state_value - lv - Cvalue_type.V.top_int) - | Call (lval_to_assign,funcexp,argl,_loc) -> - Dataflow.Done - { - counter_unroll = 0; - value = - (interp_call stmt lval_to_assign funcexp argl d_states) - } - | Asm _ -> - Value_parameters.warning ~once:true ~current:true - "assuming assembly code has no effects in function %t" - pretty_current_cfunction_name; - Dataflow.Default - | Skip _ -> - Dataflow.Default - | Code_annot (_,_) -> (* processed in dostmt from Db *) - Dataflow.Default - end - in - CilE.end_stmt (); - result - - let interp_annot state stmt ca = - match ca.annot_content with - | AAssert (behav,p) -> - let in_behavior = - match behav with - [] -> True - | [ behav ] -> - let initial_state_single = - State_set.join AnalysisParam.initial_state in - let _valid_behaviors = - valid_behaviors - (current_kf()) - initial_state_single - in - if List.exists (fun b -> b.b_name = behav) _valid_behaviors - then Unknown - else False - | _ -> Unknown - in - if in_behavior = False - then state - else - let result = eval_predicate ~result:None ~old:None state p in - let ip = Property.ip_of_code_annot (current_kf()) stmt ca in - let change_status st = List.iter (swap Status.join st) ip in - let message, result = - (match result, in_behavior with - | Unknown, _ | False, Unknown -> - change_status status_maybe; - "unknown", state - | True, _ -> - change_status status_true; - "valid", state - | False, True -> - change_status status_false; - "invalid (stopping propagation).", State_set.empty - | _, False -> assert false) - in - let result = - if in_behavior = True - then - reduce_by_disjunction ~result:None ~old:None - result - AnalysisParam.slevel - p - else result - in - Value_parameters.result ~once:true ~current:true - "Assertion got status %s." message; - result - | APragma _ - | AInvariant _ (*TODO*) - | AVariant _ | AAssigns _ - | AStmtSpec _ (*TODO*) -> state - - let check_non_overlapping state lvs1 lvs2 = - List.iter - (fun lv1 -> - List.iter - (fun lv2 -> - let zone1 = - Locations.valid_enumerate_bits - (lval_to_loc ~with_alarms:CilE.warn_none_mode state lv1) - in - let zone2 = - Locations.valid_enumerate_bits - (lval_to_loc ~with_alarms:CilE.warn_none_mode state lv2) - in - if Locations.Zone.intersects zone1 zone2 - then begin - CilE.set_syntactic_context - (CilE.SySep - (Cil.mkAddrOf ~loc:(CurrentLoc.get ()) lv1, - Cil.mkAddrOf ~loc:(CurrentLoc.get ()) lv2)); - CilE.warn_separated CilE.warn_all_mode - end) - lvs2) - lvs1 - -(* TODO: Take advantage of calls information. *) - let check_unspecified_sequence state seq = - let rec check_one_stmt ((stmt1,_,writes1,_,_) as my_stmt) = function - [] -> () - | (stmt2,_,_,_,_)::seq when stmt1 == stmt2 -> check_one_stmt my_stmt seq - | (stmt2,modified2,writes2,reads2,_) :: seq -> - let unauthorized_reads = - (* TODO: try to have a more semantical interpretation of modified *) - List.filter - (fun x -> List.for_all (fun y -> not (Lval.equal x y)) modified2) - writes1 - in - check_non_overlapping state unauthorized_reads reads2; - if stmt1.sid < stmt2.sid then - check_non_overlapping state writes1 writes2; - check_one_stmt my_stmt seq - in - if Parameters.UnspecifiedAccess.get () then - List.iter (fun x -> check_one_stmt x seq) seq - - let doStmt (s: stmt) (d: t) = - let states = (d.value) in - d.value <- State_set.empty; - let kinstr = Kstmt s in - - - let not_already_states = - Current_table.update_and_tell_if_changed - current_table - kinstr - states - in - - if State_set.is_empty not_already_states then - Dataflow.SDefault - else begin - - let annots_before, contract = - Annotations.single_fold_stmt - (fun a (before, spec as acc) -> match a with - | Before - (User { annot_content = AStmtSpec spec' } - | AI (_,{annot_content = AStmtSpec spec' }) ) - -> - let spec = match spec with - | None -> spec' - | Some s -> Logic_utils.merge_funspec s spec'; s - in - (before, Some spec) - | Before (AI (_, b) | User b) -> b :: before, spec - | After _ -> acc) - s - ([], None) - in - - CilE.start_stmt kinstr; - let states = - List.fold_left - (fun states annot -> interp_annot states s annot) - states - annots_before - in - let states = - match contract with - Some spec -> - check_preconditions (current_kf()) kinstr - ~slevel "statement" states spec - | None -> states - in - CilE.end_stmt (); - - let curr_wcounter, curr_wstate = - Current_table.find_widening_info current_table kinstr in - let d = - if d.counter_unroll >= AnalysisParam.slevel - then begin - let state = State_set.join states in - let joined = - Relations_type.Model.join - curr_wstate - state - in - let r = - if (AnalysisParam.is_natural_loop s) && - (curr_wcounter = 0) - then - let wh_key_set, wh_hints = getWidenHints s in - let widen_hints = - true, wh_key_set(* no longer used thanks to 0/1 widening*), - wh_hints - in - let _,result = Relations_type.Model.widen - widen_hints - curr_wstate - joined - in - result - else - joined - in - let new_widening = - if curr_wcounter = 0 - then 1 - else pred curr_wcounter - in - Current_table.update_widening_info - current_table - kinstr - new_widening - r; - { - counter_unroll = d.counter_unroll; - value = (State_set.singleton r); - } - - end - else { d with value = states } - in - - match s.skind with - | Return _ -> - Dataflow.SUse d - | Loop _ -> - if d.counter_unroll >= AnalysisParam.slevel - then - Value_parameters.result ~once:true ~current:true - "entering loop for the first time"; - Dataflow.SUse d - | UnspecifiedSequence seq -> - CilE.start_stmt kinstr; - State_set.iter - (fun state -> check_unspecified_sequence state seq) states; - CilE.end_stmt (); - Dataflow.SUse d - | _ -> Dataflow.SUse d - end - - let doEdge s succ d = - let kinstr = Kstmt s in - let states = (d.value) in - (* Check if there are some after-annotations to verify *) - let annots_after, _specs = - Annotations.single_fold_stmt - (fun annot (annot_after,spec as acc) -> - match annot with - | Before - (User { annot_content = AStmtSpec spec' } - | AI (_,{annot_content = AStmtSpec spec' }) ) - -> - let spec = match spec with - | None -> spec' - | Some s -> Logic_utils.merge_funspec s spec'; s - in - (annot_after, Some spec) - | After - (User { annot_content = AStmtSpec _spec' } - | AI (_,{annot_content = AStmtSpec _spec' }) ) -> - CilE.warn_once - "Ignoring statement contract rooted after statement"; - acc - | After (AI (_, a) | User a) -> a :: annot_after, spec - | Before _ -> acc) - s - ([], None) - in - CilE.start_stmt kinstr; - let states = - List.fold_left - (fun acc annot -> interp_annot acc s annot) - states - annots_after - in - - (* We store the state after the execution of [s] for the callback - {Value.Record_Value_After_Callbacks}. This is done here - because we want to see the values of the variables local to the block *) - if (not (Db.Value.Record_Value_After_Callbacks.is_empty ())) && - (store_state_after_during_dataflow s succ) - then ( - let old = - try Cil_datatype.Stmt.Hashtbl.find states_after s - with Not_found -> Relations_type.Model.bottom - in - let updated = State_set.fold Relations_type.Model.join states old in - Cil_datatype.Stmt.Hashtbl.replace states_after s updated - ); - - let states = - match Kernel_function.blocks_closed_by_edge s succ with - | [] -> states - | closed_blocks -> - let block_top_addresses_of_locals = - block_top_addresses_of_locals closed_blocks - in - State_set.fold - (fun state set -> - let state = - Relations_type.Model.uninitialize_locals closed_blocks state - in - State_set.add (block_top_addresses_of_locals state) set) - states - State_set.empty; - in - CilE.end_stmt (); - { d with value = states } - - let filterStmt _stmt = true - - (* Remove all local variables and formals from table *) - let externalize return kf = - match kf.fundec with - | Declaration _ -> assert false - | Definition (fundec,_loc) -> - assert - (StmtStartData.iter - (fun k v -> - if State_set.is_empty (v.value) - then () - else (Value_parameters.fatal "sid:%d@\n%a@\n" - k - State_set.pretty (v.value))); - true); - let superpos = - Current_table.find_superposition current_table return - in - let init_state = - Current_table.find_superposition - current_table - (Kstmt (Kernel_function.find_first_stmt kf)) - in - let superpos = - let result = - match return with - | Kstmt {skind = Return (Some ({enode = Lval (Var v,_)}),_)} -> - Some v - | _ -> None - in - check_fct_postconditions ~result - kf - (State_imp.to_set init_state) - (State_imp.to_set superpos) - Normal - in - let state = State_set.join_dropping_relations superpos in - Value_parameters.feedback "Recording results for %a" - Kernel_function.pretty_name kf; - merge_current ~degenerate:false; - let ret_val = - (match return with - | Kstmt {skind = Return (Some ({enode = Lval lv}),_)} -> - offsetmap_of_lv ~with_alarms:(warn_all_quiet_mode ()) state lv - | Kstmt {skind = Return (None,_)} -> None - | _ -> assert false) - in - let state = - Relations_type.Model.clear_state_from_locals fundec state - in - let offsetmap_top_addresses_of_locals, state_top_addresses_of_locals = - top_addresses_of_locals fundec - in - let result = - (match ret_val with - | None -> ret_val - | Some ret_val -> - let r,warn = offsetmap_top_addresses_of_locals ret_val - in - if warn then warn_locals_escape_result fundec; - Some r), - state_top_addresses_of_locals state, - !bases_containing_locals - in - result - - - let doGuardOneCond stmt exp t = - if State_set.is_empty (t.value) - then Dataflow.GUnreachable - else begin - CilE.start_stmt (Kstmt stmt); - let with_alarms = warn_all_quiet_mode () in - let new_values = - State_set.fold - (fun state acc -> - let test = - eval_expr - ~with_alarms - state exp - in - CilE.set_syntactic_context - (CilE.SyBinOp (Ne, Cil.zero ~loc:exp.eloc, exp)); - let warn, _, test = - check_comparable V.singleton_zero test - in - - let do_it = - (warn && Value_parameters.UndefinedPointerComparisonPropagateAll.get ()) || - let t1 = unrollType (typeOf exp) in - if isIntegralType t1 || isPointerType t1 - then V.contains_non_zero test - else true (* TODO: a float condition is true iff != 0.0 *) - in - if do_it then - try - State_set.add - (eval_cond ~with_alarms:CilE.warn_none_mode - state {positive = true; exp = exp}) - acc - with Reduce_to_bottom -> acc - else acc) - (t.value) - State_set.empty - in - let result = - if State_set.is_empty new_values then Dataflow.GUnreachable - else Dataflow.GUse {t with value = new_values} - in - CilE.end_stmt (); - result - - end - - let doGuard stmt exp t = - let not_exp = new_exp ~loc:exp.eloc (UnOp(LNot, exp, intType)) in - let thel = - doGuardOneCond stmt exp t, doGuardOneCond stmt not_exp t - in - Separate.filter_if stmt thel -end - -let dummy_non_linear_assignment = Ki.Hashtbl.create 1 - -module Loc_hashtbl = Hashtbl.Make (Location_Bits) - -class do_non_linear_assignments = object(self) - inherit - Visitor.generic_frama_c_visitor (Project.current ()) (Cil.inplace_visit ()) - as super - val mutable current_locs = None - val mutable assigns_table = - (Ki.Hashtbl.create 17 : Location_list.t Ki.Hashtbl.t) - - method result = assigns_table - - method vstmt s = - current_locs <- None; - match s.skind with - | UnspecifiedSequence seq -> - List.iter - (fun (stmt,_,_,_,_) -> - ignore (visitCilStmt (self:>cilVisitor) stmt)) - seq; - SkipChildren (* do not visit the additional lvals *) - | _ -> super#vstmt s - - method vlval lv = - match current_locs with - None -> SkipChildren - | Some current_locs -> - begin match lv with - Mem _e, _ -> DoChildren - | Var v, NoOffset -> - let loc = Locations.loc_of_varinfo v in - ignore (Loc_hashtbl.find current_locs loc.loc); - SkipChildren - | Var _v, (Index _ | Field _) -> DoChildren - end - -(* - - try - - let deps,loc = - !Value.lval_to_loc_with_deps - ~with_alarms:CilE.warn_none_mode - ~deps:Zone.bottom - current_stmt lv - in - let bits_loc = valid_enumerate_bits loc in - self#join deps; - self#join bits_loc; - SkipChildren -*) - - method vcode_annot _ = SkipChildren - - method visit_addr lv = - begin match lv with - Var v, offset -> - let offset' = visitCilOffset (self :> cilVisitor) offset in - let v' = Cil.get_varinfo self#behavior v in - if offset' == offset && v == v' - then SkipChildren - else ChangeTo (Var v', offset') - | Mem e, offset -> - let e' = visitCilExpr (self :> cilVisitor) e in - let offset' = visitCilOffset (self :> cilVisitor) offset in - if offset' == offset && e == e' - then SkipChildren - else ChangeTo (Mem e', offset') - end; - - method vinst i = - match i with - | Set (lv,exp,_) -> - current_locs <- Some (Loc_hashtbl.create 7); - begin match lv with - Var _, offset -> - ignore (self#voffs offset); - | Mem e, offset -> - ignore (self#vexpr e); - ignore (self#voffs offset); - end; - ignore (self#vexpr exp); - (* TODO: do some stuff with self#current_stmt *) - SkipChildren - | _ -> SkipChildren - - method vexpr exp = - match exp.enode with - | AddrOf _lv | StartOf _lv -> - SkipChildren (* TODO: do better stuff *) - | _ -> DoChildren - -end - -let no_pretty _ _ = () - -let compute_non_linear_assignments f = - let vis = new do_non_linear_assignments in - ignore (Visitor.visitFramacFunction (vis:>Visitor.frama_c_visitor) f); - vis#result - -let compute_using_cfg kf ~call_kinstr initial_state = - match kf.fundec with - | Declaration _ -> assert false - | Definition (f,_loc) -> - (*if let (_,_,variadic,_) = splitFunctionTypeVI f.svar in variadic - then raise Leaf (* Do not visit variadic bodies *) - else *) -(* PH: Removed - Properties_status.RTE_Signed_Generated.set kf true; - Properties_status.RTE_DivMod_Generated.set kf true; - Properties_status.RTE_MemAccess_Generated.set kf true; -*) - begin - let f_varinfo = f.svar in - let module Computer = - Computer - (struct - let stmt_can_reach = Stmts_graph.stmt_can_reach kf - let is_natural_loop = Loop.is_natural kf - let non_linear_assignments = - try - Non_linear_assignments.find f_varinfo - with - Not_found -> - let n = compute_non_linear_assignments f in - Non_linear_assignments.add f_varinfo n; - n - let slevel = get_slevel kf - let initial_state = initial_state (* for future reference *) - end) - in - let module Compute = Dataflow.ForwardsDataFlow(Computer) in - List.iter - (function {called_kf = g} -> - if kf == g - then begin - if Value_parameters.IgnoreRecursiveCalls.get() - then begin - Value_parameters.warning ~current:true ~once:true - "ignoring recursive call during value analysis of %a (%a)" - Ast_info.pretty_vname f_varinfo - pretty_call_stack (call_stack ()); - raise Leaf - end - else - raise (Extlib.NotYetImplemented "recursive calls in value analysis") - end) - (call_stack ()); - push_call_stack {called_kf = kf; - call_site = call_kinstr; - called_merge_current = Computer.merge_current}; - match f.sbody.bstmts with - [] -> assert false - | start :: _ -> - let ret_id = Kernel_function.find_return kf in - (* We start with only the start block *) - Computer.StmtStartData.add - start.sid - (Computer.computeFirstPredecessor - start - { - Computer.counter_unroll = 0; - value = initial_state}); - begin try - Compute.compute [start] - with Db.Value.Aborted as e -> - (* State_builder.was aborted: pop the call stack and inform - the caller *) - pop_call_stack (); - raise e - end; - let last_ret,last_s,last_clob as last_state = - try - let _,state,_ as result = - try - Computer.externalize (Kstmt ret_id) kf - with Not_found -> assert false - in - if Relations_type.Model.is_reachable state - then begin - try - if hasAttribute "noreturn" f_varinfo.vattr - then - Value_parameters.warning ~current:true ~once:true - "function %a may terminate but has the noreturn attribute" - Kernel_function.pretty_name kf; - with Not_found -> assert false - end - else raise Not_found; - result - with Not_found -> begin - None, - Relations_type.Model.bottom, - Location_Bits.Top_Param.bottom - end - in - Value_parameters.debug - "@[RESULT FOR %a <-%a:@\n\\result -> %a@\n%a@\nClobered set:%a@]" - Kernel_function.pretty_name kf - pretty_call_stack (call_stack ()) - (fun fmt v -> - match v with - | None -> () - | Some v -> V_Offsetmap.pretty fmt v) - last_ret - no_pretty last_s - Location_Bits.Top_Param.pretty - last_clob; - pop_call_stack (); - last_state - end - -(** Associates [kernel_function] to a fresh base for the address returned by - the [kernel_function]. *) -module Leaf_Table = - Kernel_function.Make_Table - (Base) - (struct - let dependencies = [Db.Value.self] - let size = 7 - let name = "Leaf_Table" - let kind = `Internal - end) - -let return_value return_type kf state = - (* Process return of function *) - let return_type = unrollType return_type in - match return_type with - | TComp _ when is_fully_arithmetic return_type -> - Cvalue_type.V.top_int, state - | TPtr(typ,_) | (TComp _ as typ) -> begin - let new_base = - Leaf_Table.memo - (fun kf -> - let new_varinfo = - makeGlobalVar - ~logic:true - (Cabs2cil.fresh_global - ("alloced_return_" ^ Kernel_function.get_name kf)) - typ - in - let new_offsetmap = - Cvalue_type.V_Offsetmap.sized_zero (memory_size ()) - in - Cvalue_type.Default_offsetmap.create_initialized_var - new_varinfo - (Base.Known (Int.zero, max_bit_address ())) - new_offsetmap) - kf - in - let initial_value = - if isIntegralType typ - then Cvalue_type.V.top_int - else if isFloatingType typ - then Cvalue_type.V.top_float - else - Cvalue_type.V.inject_top_origin - (Origin.Leaf (LocationSetLattice.currentloc_singleton())) - (Cvalue_type.V.Top_Param.O.singleton new_base) - (*top_leaf_origin ()*) - in - let modu = try - if isVoidType typ then Int.one else Int_Base.project (osizeof typ) - with Int_Base.Error_Top -> - assert (Cvalue_type.V.is_isotropic initial_value); - Int.one - in - let returned_loc = - try - Location_Bytes.inject - new_base - (Ival.filter_ge_int (Some Int.zero) - (Ival.create_all_values - ~signed:true - ~modu - ~size:(sizeofpointer ()))) - with Int_Base.Error_Top -> - Location_Bytes.inject - new_base - Ival.top - in - let state = - Relations_type.Model.create_initial - ~base:new_base - ~v:initial_value ~modu:(Int.mul Int.eight modu) ~state - in - returned_loc, state - end - | TInt _ | TEnum _ -> Cvalue_type.V.top_int, state - | TFloat _ -> Cvalue_type.V.top_float, state - | TBuiltin_va_list _ -> - Cvalue_type.V.top_leaf_origin() - (* Only some builtins may return this type *), - state - | TVoid _ -> Cvalue_type.V.top (* this value will never be used *), state - | TFun _ | TNamed _ | TArray _ -> assert false - -exception Deref_lvals of Cil_types.lval list - -let compute_using_prototype kf ~state_with_formals = - match kf.fundec with - | Definition (_,_) -> assert false - | Declaration (_,vi,_,_) when Cil.hasAttribute "noreturn" vi.vattr -> - None, Relations_type.Model.bottom, Location_Bits.Top_Param.bottom - | Declaration (_spec,varinfo,_,_) -> - let return_type,_formals_type,_inline,_attr = - splitFunctionType (Kernel_function.get_type kf) - in - let behaviors = valid_behaviors kf state_with_formals in - let assigns = Ast_info.merge_assigns behaviors in - let returned_value, state_with_formals = - return_value return_type kf state_with_formals - in - let returned_value = ref returned_value in - let clobbered_set = ref Location_Bits.Top_Param.bottom in - let state = - match assigns with - | WritesAny -> Value_parameters.warning "Cannot handle empty assigns clause. Assuming assigns \\nothing: be aware this is probably incorrect."; - state_with_formals - | Writes [] -> state_with_formals - | Writes l -> - let treat_assign acc (out, ins) = - let input_contents = - try - match ins with - FromAny -> - (* [VP] \from \nothing has the - same meaning as unspecified \from... *) - Cvalue_type.V.top_int - | From l -> - List.fold_left - (fun acc term -> - let input_loc = - !Db.Properties.Interp.identified_term_zone_to_loc - ~result:None - state_with_formals - term - in - let r = - Relations_type.Model.find - ~conflate_bottom:true - ~with_alarms:CilE.warn_none_mode - state_with_formals - input_loc - in - (* Format.printf "loc %a r %a@." - Locations.pretty input_loc - Cvalue_type.V.pretty r; *) - Cvalue_type.V.join acc r) - Cvalue_type.V.top_int - l - with Invalid_argument "not an lvalue" -> - Value_parameters.result - ~once:true ~current:true - "cannot interpret assigns in function %a" - Kernel_function.pretty_name kf; - Cvalue_type.V.top - in - let treat_output_loc loc acc = - remember_bases_with_locals - clobbered_set - loc - input_contents; - let bound = - Relations_type.Model.add_binding - ~with_alarms:CilE.warn_none_mode - ~exact:false acc loc input_contents - in - bound - in - try - let lvals_out = - try - !Db.Properties.Interp.loc_to_lval - ~result:None - out.it_content - with - Invalid_argument "not an lvalue" as e -> - begin - match out with - {it_content= - {term_node= - TLval - (TMem - {term_node=TBinOp((IndexPI|PlusPI) , - t1,_o1)}, _o2)}} - -> - let deref_lvals = - !Db.Properties.Interp.loc_to_lval - ~result:None t1 - in - (* Format.printf "input: %a@." - Cvalue_type.V.pretty input_contents ; *) - raise (Deref_lvals deref_lvals) - | _ -> raise e - end - in - let result = - List.fold_left - (fun acc lval -> - let loc = - lval_to_loc ~with_alarms:CilE.warn_none_mode - state_with_formals lval - in - (* Format.printf "lval:%a loc:%a@." - !d_lval lval - Locations.pretty loc; *) - treat_output_loc loc acc - ) - acc - lvals_out - in - result - with - Invalid_argument "not an lvalue" -> - if Logic_utils.is_result out.it_content then begin - returned_value := - Cvalue_type.V.join - (Cvalue_type.V.topify_arith_origin - input_contents) - !returned_value; - acc - end else begin - Value_parameters.warning ~once:true ~current:true - "Can not interpret assigns in function %a; \ - effects will be ignored" - Kernel_function.pretty_name kf; acc - end - | Deref_lvals deref_lvals -> - let deref_loc = - List.fold_left - (fun acc lv -> - Location_Bits.join - (lval_to_loc ~with_alarms:CilE.warn_none_mode - state_with_formals lv).loc - acc) - Location_Bits.bottom - deref_lvals - in - let deref_loc = Location_Bits.topify_arith_origin deref_loc - in - let loc_bytes = - Relations_type.Model.find - ~conflate_bottom:true - ~with_alarms:CilE.warn_none_mode - state_with_formals - (make_loc deref_loc Int_Base.top) - in - let loc = - make_loc (loc_bytes_to_loc_bits loc_bytes) Int_Base.top - in - treat_output_loc loc acc - in - (List.fold_left treat_assign state_with_formals l) - in - let retres_vi, state = - if isVoidType return_type - then None, state - else - let offsetmap = - V_Offsetmap.update_ival - ~with_alarms:CilE.warn_none_mode - ~validity:Base.All - ~offsets:Ival.zero - ~exact:true - ~size:(Int.of_int (bitsSizeOf return_type)) - V_Offsetmap.empty - (Cvalue_type.V_Or_Uninitialized.initialized !returned_value) - in - Library_functions.add_retres_to_state - varinfo - offsetmap - state - in - retres_vi, state, !clobbered_set - - -(* Replace in [initial_state] all keys in [mem_outs] by their value in - [mem_final_state]. *) -let compute_using_mem - _kf - (initial_state:Relations_type.Model.t) - (new_return_v,mem_final_state) - mem_outs - instanciation = - let (a,clobbered_bases) = - Relations_type.Model.compute_actual_final_from_generic - initial_state - mem_final_state - mem_outs - instanciation - in - (*TODO: new_return_v MUST be substituted! *) - new_return_v,a,clobbered_bases - - -(** Compute only once the initial values for globals and NULL *) -let initial_state_contextfree_only_globals = - let module S = - State_builder.Option_ref - (Relations_type.Model) - (struct - let name = "contextfree_only_globals" - let dependencies = - [ Ast.self; Parameters.LibEntry.self; Parameters.MainFunction.self ] - let kind = `Internal - end) - in - function () -> - let add_varinfo state varinfo = - CurrentLoc.set varinfo.vdecl; - initialize_var_using_type varinfo state - in - let treat_global state = function - | GVar(vi,_,_) -> add_varinfo state vi - | GVarDecl(_,vi,_) when not (Cil.isFunctionType vi.vtype) -> - add_varinfo state vi - | GType _ | GCompTag _ | GCompTagDecl _ | GEnumTag _ | GEnumTagDecl _ - | GVarDecl _ | GFun _ | GAsm _ | GPragma _ | GText _ | GAnnot _ -> state - in - let compute () = - List.fold_left treat_global (initial_state_only_globals()) - (Ast.get ()).globals - in - S.memo compute - -let initial_state_formals kf (state:Relations_type.Model.t) = - match kf.fundec with - | Declaration _ -> assert false - | Definition (f,_) -> - List.fold_right - initialize_var_using_type - f.sformals - state - -let rec fold_left2_best_effort f acc l1 l2 = - match l1,l2 with - | _,[] -> acc - | [],_ -> - Value_parameters.result ~once:true ~current:true - "not enough arguments in function call."; - acc - | (x1::r1),(x2::r2) -> fold_left2_best_effort f (f acc x1 x2) r1 r2 - -let actualize_formals kf state actuals = - let formals = Kernel_function.get_formals kf in - let treat_one_formal acc (_,_actual_val,actual_o) formal = - let loc_without_size = - Location_Bits.inject - (Base.create_varinfo formal) - (Ival.zero) - in - Relations_type.Model.paste_offsetmap - actual_o - loc_without_size - Int.zero - (Int_Base.project (sizeof_vid formal)) - acc - in - fold_left2_best_effort - treat_one_formal - state - actuals - formals - -(* In the state [initial_state] globals and formals are present - but locals of [kf] are not.*) -let compute_with_initial_state kf initial_state = - match kf.fundec with - | Declaration _ -> assert false - | Definition (f,_) -> - let initial_state = - List.fold_left - (fun acc local -> - Relations_type.Model.add_binding_unspecified - acc - (Locations.loc_of_varinfo local)) - initial_state - f.slocals - in - let initial_state = check_fct_preconditions kf initial_state in - compute_using_cfg kf initial_state - -let compute_entry_point kf ~library = - clear_call_stack (); - Kf_state.mark_as_called kf; - Value_parameters.feedback "Analyzing a%scomplete application starting at %a" - (if library then "n in" else " ") - Kernel_function.pretty_name kf; - - Separate.prologue(); - - let initial_state_globals = - if Db.Value.globals_use_supplied_state () then ( - let r = Db.Value.globals_state () in - Value_parameters.feedback "Initial state supplied by user"; - Value_parameters.debug "@[<hov 0>Values of globals@\n%a@]" - Db.Value.pretty_state_without_null r; - r) - else ( - Value_parameters.feedback "Computing initial state"; - let r = Db.Value.globals_state () in - Value_parameters.feedback "Initial state computed"; - Value_parameters.result - "@[<hov 0>Values of globals at initialization@\n%a@]" - Db.Value.pretty_state_without_null r; - r - ) in - Db.Value.update_table Kglobal initial_state_globals; - - Mark_noresults.run(); - - let with_formals = match Db.Value.fun_get_args () with - | None -> initial_state_formals kf initial_state_globals - | Some actuals -> - let formals = Kernel_function.get_formals kf in - if (List.length formals) <> List.length actuals then - raise Db.Value.Incorrect_number_of_arguments; - let treat_one_formal f a = - (), a, Builtins.offsetmap_of_value ~typ:f.vtype a - in - actualize_formals - kf - initial_state_globals - (List.map2 treat_one_formal formals actuals) - in - Db.Value.Call_Value_Callbacks.apply (with_formals, [ kf, Kglobal ]); - let result = - compute_with_initial_state kf ~call_kinstr:Kglobal with_formals - in - Value_parameters.feedback "done for function %a" - Kernel_function.pretty_name kf; - Separate.epilogue(); - result - -exception Not_modular -exception Invalid_CEA_alloc -exception Invalid_CEA_memcpy - -module Mem_Exec = - Kernel_function.Make_Table - (Datatype.Make - (struct - include Datatype.Undefined - type t = - Relations_type.Model.t - * (V_Offsetmap.t option * Relations_type.Model.t) - * Locations.Zone.t (* in *) - * Locations.Zone.t (* out *) - let name = "Mem_Exec" - let reprs = - List.fold_left - (fun acc m -> - List.fold_left - (fun acc o -> - List.fold_left - (fun acc z -> (m, (Some o, m), z, z) :: acc) - acc - Locations.Zone.reprs) - acc - V_Offsetmap.reprs) - [] - Relations_type.Model.reprs - end)) - (struct - let name = "Mem_Exec" - let size = 7 - let dependencies = [ Db.Value.self ] - let kind = `Internal - end) - - -let compute_call kf ~call_kinstr - (initial_state:Relations_type.Model.t) actuals = - let initial_state = Relations_type.Model.drop_relations initial_state in - let with_formals = actualize_formals kf initial_state actuals in - Db.Value.merge_initial_state kf with_formals; - let stack_without_call = for_callbacks_stack () in - Db.Value.Call_Value_Callbacks.apply - (with_formals, ((kf, call_kinstr) :: stack_without_call)); - let name = Kernel_function.get_name kf in - (* function whose name starts with 'CEA_' - print their arguments on stdout during computations.*) - let result = - if Ast_info.is_cea_dump_function name then begin - let l = fst (CurrentLoc.get ()) in - Value_parameters.result - "DUMPING STATE of file %s line %d@\n%a=END OF DUMP==" - l.Lexing.pos_fname l.Lexing.pos_lnum - Relations_type.Model.pretty initial_state; - None, initial_state, Location_Bits.Top_Param.bottom - end - else - try - let abstract_function = Builtins.find_builtin name in - abstract_function initial_state actuals - with Not_found -> - if Ast_info.is_cea_alloc_with_validity name then begin - try - let size = match actuals with - | [_,size,_] -> size - | _ -> raise Invalid_CEA_alloc - in - let size = - try - let size = Cvalue_type.V.project_ival size in - Ival.project_int size - with Ival.Not_Singleton_Int | V.Not_based_on_null -> - raise Invalid_CEA_alloc - in - if Int.le size Int.zero then raise Invalid_CEA_alloc; - let new_name = - Format.sprintf "Frama_C_alloc" - in - let new_name = Cabs2cil.fresh_global new_name in - let bounded_type = - TArray( - charType, - Some (new_exp ~loc:Cil_datatype.Location.unknown - (Const (CInt64 (Int.to_int64 size,IInt ,None)))), - empty_size_cache (), - []) - in - let new_varinfo = - makeGlobalVar ~logic:true new_name bounded_type - in - let size_in_bits = Int.mul (sizeofchar()) size in - let new_offsetmap = - Cvalue_type.V_Offsetmap.sized_zero ~size_in_bits - in - let new_base = - Cvalue_type.Default_offsetmap.create_initialized_var - new_varinfo - (Base.Known (Int.zero, Int.pred size_in_bits)) - new_offsetmap - in - let loc_without_size = Location_Bytes.inject new_base Ival.zero in - (* Hashtbl.add dynamic_alloc_table file loc_without_size; *) - (Builtins.wrap_ptr loc_without_size),initial_state, Location_Bits.Top_Param.bottom - with Ival.Error_Top | Invalid_CEA_alloc - | Not_found (* from [find_lonely_key]*) - -> - Value_parameters.error - "Invalid argument for Frama_C_alloc_size function"; - do_degenerate None; - raise Db.Value.Aborted - end else if Ast_info.is_cea_function name then begin - Value_parameters.result "Called %s%a" - name - pretty_actuals - actuals; - None,initial_state, Location_Bits.Top_Param.bottom - end - else begin - let function_name = Kernel_function.get_name kf in - Value_parameters.feedback - "computing for function %a <-%a.@\nCalled from %a." - !Ast_printer.d_ident function_name - pretty_call_stack (call_stack ()) - pretty_loc_simply - (CilE.current_stmt()); - Kf_state.mark_as_called kf; - let modular = - Value_parameters.MemExecAll.get () - || Datatype.String.Set.mem name (Value_parameters.MemFunctions.get ()) - in - let result = - match kf.fundec with - | Definition _ -> - begin try - if not modular then raise Not_modular; - let mem_initial_state, mem_final_state, mem_in, mem_outs = - !Db.Value.memoize kf; - try Mem_Exec.find kf with Not_found -> raise Not_modular - in - try - let instanciation = - Relations_type.Model.is_included_actual_generic - (Zone.join mem_in mem_outs) - with_formals - mem_initial_state - in - Value_parameters.result ~current:true "Instanciation succeeded: %a" - (let module M = Base.Map.Make(Location_Bytes) in - M.pretty) - instanciation; - compute_using_mem kf - initial_state - mem_final_state - mem_outs - instanciation - with Is_not_included -> - Value_parameters.result ~current:true ~once:true - "Failed to see context as an instance of the generic context: inlining call to %a." - Kernel_function.pretty_name kf; - raise Not_modular - with Not_modular -> - compute_with_initial_state kf ~call_kinstr with_formals - end - | Declaration (_,_varinfo,_,_) -> - let stateset = check_fct_preconditions kf with_formals in - (* TODO: This is a hack. Use a function that checks preconditions - without multiplying the states instead -- or - compute_using_prototype several times *) - let state_with_formals = State_set.join stateset in - let retres_vi, result_state, thing = - compute_using_prototype kf ~state_with_formals in - let result_state = - check_fct_postconditions ~result:retres_vi kf - (State_set.singleton state_with_formals) - (State_set.singleton result_state) - Normal - in - let result_state = State_set.join result_state in - let result, retres = - match retres_vi with - None -> None, None - | Some vi -> - let value_state = - Relations_type.Model.value_state result_state - in - let retres_base = Base.create_varinfo vi in - Some - (Cvalue_type.Model.find_base - retres_base - value_state), - (Some retres_base) - in - let formals = Kernel_function.get_formals kf in - let result_state = - List.fold_left - (fun acc vi -> - Relations_type.Model.remove_base - (Base.create_varinfo vi) - acc) - result_state - formals - in - let result_state = - match retres with - Some retres -> - Relations_type.Model.remove_base retres result_state - | None -> result_state - in - result, result_state, thing - in - Value_parameters.feedback "Done for function %a" - Kernel_function.pretty_name kf; - result - end - in - result - -let memoize kf = - try - ignore - (Mem_Exec.memo - (fun kf -> - Kf_state.mark_as_called kf; - let with_globals = initial_state_contextfree_only_globals () in - let with_formals = initial_state_formals kf with_globals in - let (a,b,_) = - compute_with_initial_state kf ~call_kinstr:Kglobal with_formals - in - let result = a,b in - let ins = - (!Db.InOutContext.get_internal kf).Inout_type.over_inputs - in - let outs = !Db.Outputs.get_external kf in - with_formals,result,ins,outs) - kf) - with Db.Value.Aborted -> - (* the function will not be memoized. TODO: inform the user - that the analyzer will behave as if the option was not set *) - () - -let force_compute () = - (* check floats *) - let u = min_float /. 2. in - let u = u /. 2. in - assert (0. < u && u < min_float); - try - let kf, library = Globals.entry_point () in - ignore (compute_entry_point kf ~library); - (* Move all alarms to Db *) - Db.Properties.synchronize_alarms [ Db.Value.self ]; - Db.Value.mark_as_computed (); - (* Cleanup trivially redundant alarms *) - !Db.Scope.rm_asserts () - with - | Db.Value.Aborted -> - (* This case is reached only if [do_degenerate] did not raise another - exception to handle abortion properly. See the behavior of the GUI - in case of degeneration to understand the machinery. *) - Db.Value.mark_as_computed (); - Value_parameters.abort - "Degeneration occured:@\nresults are not correct for lines of code \ -that can be reached from the degeneration point." - | Globals.No_such_entry_point _ as exn -> raise exn - | exn -> Db.Value.mark_as_computed (); raise exn - -let () = compute_call_ref := compute_call - -let _self = - Db.register_compute "Value.compute" - [ Db.Value.self ] - Db.Value.compute - (fun () -> if not (Db.Value.is_computed ()) then force_compute ()) - -let () = Db.Value.memoize := memoize -let () = Db.Value.initial_state_only_globals := - (fun () -> if snd(Globals.entry_point ()) then - initial_state_contextfree_only_globals () - else - initial_state_only_globals () - ) -let () = Db.Value.find_lv_plus := find_lv_plus -let () = Db.Value.eval_expr_with_state := - (fun ~with_alarms state expr -> - let (s,_,v) = eval_expr_with_deps_state ~with_alarms None state expr in - s,v) - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval.mli frama-c-20111001+nitrogen+dfsg/src/value/eval.mli --- frama-c-20110201+carbon+dfsg/src/value/eval.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -val eval_lval : - conflate_bottom:bool -> - with_alarms:CilE.warn_mode -> - Locations.Zone.t option -> - Db.Value.state -> - Cil_types.lval -> - Db.Value.state * Locations.Zone.t option * Cvalue_type.V.t - -val eval_expr : - with_alarms:CilE.warn_mode -> - Db.Value.state -> Cil_types.exp -> Cvalue_type.V.t - -val lval_to_loc_with_deps : - deps:Locations.Zone.t -> - Db.Value.state -> - Cil_types.lval -> - with_alarms:CilE.warn_mode -> - reduce_valid_index:bool -> - Db.Value.state * Locations.Zone.t option * Locations.location - -val lval_to_loc : - with_alarms:CilE.warn_mode -> - Db.Value.state -> Cil_types.lval -> Locations.location - -val resolv_func_vinfo : - with_alarms:CilE.warn_mode -> - Locations.Zone.t option -> - Db.Value.state -> - Cil_types.exp -> Locations.Zone.t option * Kernel_function.Hptset.t - -exception Leaf - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/eval_stmts.ml frama-c-20111001+nitrogen+dfsg/src/value/eval_stmts.ml --- frama-c-20110201+carbon+dfsg/src/value/eval_stmts.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/eval_stmts.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,1406 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Value analysis of statements and functions bodies *) + +open Cil_types +open Cil +open Cil_datatype +open Locations +open Abstract_interp +open Bit_utils +open Cvalue +open Ast_printer +open Value_util +open Eval_exprs +open Eval_logic +open Locals_scoping + +exception Wrong_function_type (* in function call *) + +let need_cast t1 t2 = + match unrollType t1, unrollType t2 with + | (TInt _| TEnum _| TPtr _), (TInt _| TEnum _| TPtr _) + | TFloat _, TFloat _ + | TComp _, TComp _ -> + (try bitsSizeOf t1 <> bitsSizeOf t2 + with SizeOfError _ -> true) + | _ -> true + +let offsetmap_of_lv ~with_alarms state lv = + CilE.set_syntactic_context (CilE.SyMem lv); + let loc_to_read = + lval_to_loc ~with_alarms state lv + in + Cvalue.Model.copy_offsetmap + ~with_alarms:CilE.warn_none_mode + loc_to_read + state + +exception Got_bottom + +let compute_actual ~with_alarms (one_library_fun, all_library_funs) state e = + let interpreted_expr, o = match e with + | { enode = Lval l } + when (* make sure not a bit-field *) not (is_bitfield l ()) -> + let _, _, interpreted_expr = + eval_lval ~conflate_bottom:false ~with_alarms None state l + in + if one_library_fun then + ignore (eval_lval ~conflate_bottom:true ~with_alarms None state l); + if V.is_bottom interpreted_expr + then begin + if not one_library_fun then (* alarm *) + ignore (eval_lval ~conflate_bottom:true ~with_alarms None state l); + if all_library_funs + then begin + Value_parameters.result ~current:true + "Non-termination@ in@ evaluation@ of@ library function@ call@ lvalue@ argument@ @[%a@]" (!d_lval) l; + end; + raise Got_bottom; + end; + let r = do_cast ~with_alarms (typeOf e) interpreted_expr in + let o = offsetmap_of_lv ~with_alarms state l in + (match o with + | Some o -> r, o + | None -> + Format.printf "failure in evaluation of function arguments@\n\ + lval %a -> %a@." !d_lval l V.pretty interpreted_expr; + assert false) + | _ -> + let interpreted_expr = eval_expr ~with_alarms state e in + if V.is_bottom interpreted_expr + then begin + Value_parameters.result ~current:true + "Non-termination@ in@ evaluation@ of@ function@ call@ expression@ argument@ @[%a@]" + (!d_exp) e; + raise Got_bottom + end; + let typ = Cil.typeOf e in + interpreted_expr, + Builtins.offsetmap_of_value ~typ interpreted_expr + in + e, interpreted_expr, o + + +(* Forward reference to {Eval_calls.compute_call} *) +let compute_call_ref = ref (fun _ -> assert false) + +module Computer + (AnalysisParam:sig + val stmt_can_reach : stmt -> stmt -> bool + val is_natural_loop : stmt -> bool + val slevel: int + val initial_state : State_set.t + val active_behaviors: Eval_logic.ActiveBehaviors.t + end) = + +struct + let debug = ref false + let name = "Values analysis" + + let stmt_can_reach = AnalysisParam.stmt_can_reach + + let obviously_terminates = + Value_parameters.ObviouslyTerminatesAll.get() (* TODO: by function *) + + let slevel = + if obviously_terminates + then max_int + else + AnalysisParam.slevel + + let debug = ref false + + let fused_initial_state = lazy (State_set.join AnalysisParam.initial_state) + + let current_table = Current_table.create () + + let states_after = Cil_datatype.Stmt.Hashtbl.create 5 + + (* During the dataflow analysis, if required by a callback, we store the + state after a statement, but only if the following conditions are met + ([succ] being a successor of [s]) + - if [s] is an instr (which almost always change the state, unlike + the other kind of statements) + - if there is a control-flow join on [succ] + - if [s] is the last instruction of a block that contains + local variables + For statements for which the function below returns false, we deduce + the state after by the state before [succ] or another successor of [s]. + This avoids potentially useless computations + *) + let store_state_after_during_dataflow s succ = + ((match s.skind with Instr _ -> true | _ -> false) && + (match succ.preds with [_] -> false | _ -> true)) + || (let b1 = Kernel_function.find_enclosing_block s + and b2 = Kernel_function.find_enclosing_block succ in + not (Cil_datatype.Block.equal b1 b2) && b1.blocals <> []) + + (* Computation of the per-function 'after statement' states *) + let local_after_states superposed = + lazy ( + let superposed = Lazy.force superposed in + Stmt.Hashtbl.iter + (fun stmt state -> + List.iter + (fun pred -> + if not (store_state_after_during_dataflow pred stmt) then + try + let cur = Stmt.Hashtbl.find states_after pred in + Stmt.Hashtbl.replace states_after pred + (Cvalue.Model.join state cur) + with Not_found -> Stmt.Hashtbl.add states_after pred state + ) stmt.preds; + ) superposed; + (* Since the return instruction has no successor, it is not visited + by the iter above. We fill it manually *) + (try + let ret = Kernel_function.find_return (current_kf ()) in + let s = Stmt.Hashtbl.find superposed ret in + Stmt.Hashtbl.add states_after ret s + with Kernel_function.No_Statement | Not_found -> () + ); + states_after + ) + + (* Merging of 'after statement' states in the global table *) + let merge_after after_full = + Cil_datatype.Stmt.Hashtbl.iter + (fun stmt st -> + try + let prev = Db.Value.AfterTable.find stmt in + Db.Value.AfterTable.replace stmt (Cvalue.Model.join prev st) + with Not_found -> + Db.Value.AfterTable.add stmt st + ) (Lazy.force after_full) + + (* Table storing whether conditions on 'if' have been evaluated + to true or false *) + let conditions_table = Cil_datatype.Stmt.Hashtbl.create 5 + + let merge_current ~degenerate = + let superposed = lazy (Current_table.states current_table) in + let after_full = local_after_states superposed in + Current_table.merge_db_table superposed; + Db.Value.merge_conditions conditions_table; + if Value_parameters.ResultsAfter.get () then merge_after after_full; + if not degenerate then begin + let stack_for_callbacks = for_callbacks_stack () in + + if not (Db.Value.Record_Value_Superposition_Callbacks.is_empty ()) + then begin + let current_superpositions = + lazy (Current_table.superpositions current_table) + in + if Value_parameters.ValShowProgress.get() then + Value_parameters.feedback + "now calling Record_Value_Superposition callbacks"; + Db.Value.Record_Value_Superposition_Callbacks.apply + (stack_for_callbacks, current_superpositions); + end ; + + if not (Db.Value.Record_Value_Callbacks.is_empty ()) + then begin + if Value_parameters.ValShowProgress.get() then + Value_parameters.feedback "now calling Record_Value callbacks"; + Db.Value.Record_Value_Callbacks.apply + (stack_for_callbacks, superposed) + end; + + if not (Db.Value.Record_Value_After_Callbacks.is_empty ()) + then begin + if Value_parameters.ValShowProgress.get() then + Value_parameters.feedback "now calling Record_After_Value callbacks"; + Db.Value.Record_Value_After_Callbacks.apply + (stack_for_callbacks, after_full); + end; + + end; + Current_table.clear current_table + + type u = + { counter_unroll : int; (* how many times this state has been crossed *) + mutable value : State_set.t ; } + + module StmtStartData = + Dataflow.StartData(struct type t = u let size = 107 end) + + type t = u + + let copy (d: t) = d + + let display_one fmt v = + State_set.iter (fun value -> + if not (Cvalue.Model.is_reachable value) then + Format.fprintf fmt "Statement (x%d): UNREACHABLE@\n" v.counter_unroll + else + Format.fprintf fmt "Statement (x%d)@\n%a" + v.counter_unroll + Cvalue.Model.pretty + value) + v.value + + let pretty fmt (d: t) = display_one fmt d + + let computeFirstPredecessor (_s: stmt) state = + { counter_unroll = 0; value = state.value;} + + let getWidenHints (s: stmt) = + Widen.getWidenHints (current_kf()) s + + let counter_unroll_target = ref 100 + + let combinePredecessors (_s: stmt) ~old new_ = + if State_set.is_empty (new_.value) + then None + else begin + if old.counter_unroll >= slevel + then + let sum = + Cvalue.Model.join + (State_set.join new_.value) + (State_set.join old.value) + in + Some {counter_unroll = old.counter_unroll ; + value = State_set.singleton sum;} + else begin try + let merged = State_set.merge_into new_.value old.value in + let length_new = State_set.length new_.value in + let new_counter_unroll = old.counter_unroll + length_new in + if new_counter_unroll >= !counter_unroll_target + then begin + Value_parameters.result ~once:true + "Semantic level unrolling superposing up to %d states" + !counter_unroll_target; + counter_unroll_target := !counter_unroll_target + 100; + end; + let result = + Some + { value = merged ; + counter_unroll = new_counter_unroll } + in + result + with State_set.Unchanged -> None + end + end + + (** Clobber list for bases containing addresses of local variables. *) + let bases_containing_locals = ref Location_Bits.Top_Param.bottom + let remember_bases_with_locals = + remember_bases_with_locals bases_containing_locals + +(** Precondition: the type of [exp] and the type [loc_lv] may be different + only if the cast from [typeOf exp] and [typeOf loc_lv] is a truncation + or an extension. + This function will not perform any conversion (float->int, int->float, ...) + [exp] should not be bottom for optimization purposes in the caller. + *) + let do_assign_abstract_value_to_loc ~with_alarms state lv loc_lv exp = + assert (not (Cvalue.V.is_bottom exp)); + (* Or one may propagate bottoms uselessly for too long. *) + let exp = (* truncate the value if the [lv] is too small: this may + happen when the [lv] is a bit-field. Otherwise, the + cast is explicit thanks to Cil and no truncation is + necessary. *) + try + (* if it is a bit-field, the size is statically known. *) + let size = Int_Base.project loc_lv.size in + try + ignore (V.project_ival exp); + cast_lval_bitfield lv size exp + with + | V.Not_based_on_null (* from [project_ival] *) -> + (* The exp is a pointer: check there are enough bits in + the bit-field to contain it. *) + if Int.compare size (Int.of_int (sizeofpointer ())) >= 0 + || V.is_imprecise exp + then exp + else begin + Value_parameters.result + "casting address to a bit-field of %s bits: this is smaller than sizeof(void*)" + (Int.to_string size); + V.topify_arith_origin exp + end + | Neither_Int_Nor_Enum_Nor_Pointer + (* from [signof_typeof_lval] *) -> exp + with + | Int_Base.Error_Top | Int_Base.Error_Bottom -> + (* from [project]: size is not known *) + exp + in + let pretty_org fmt org = if not (Origin.is_top org) then + Format.fprintf fmt " because of %a" Origin.pretty org + in + (match loc_lv.loc with + | Location_Bits.Top (Location_Bits.Top_Param.Top, orig) -> + Value_parameters.result + "State before degeneration:@\n======%a@\n=======" + Cvalue.Model.pretty state; + warning_once_current + "writing at a completely unknown address@[%a@].@\nAborting." + pretty_org orig; + do_degenerate (Some lv) + + | Location_Bits.Top((Location_Bits.Top_Param.Set _) as param,orig) -> + Value_parameters.result ~current:true ~once:true + "writing somewhere in @[%a@]@[%a@]." + Location_Bits.Top_Param.pretty param + pretty_org orig + | Location_Bits.Map _ -> (* everything is normal *) ()); + let exact = valid_cardinal_zero_or_one ~for_writing:true loc_lv in + let value = + Cvalue.Model.add_binding ~with_alarms ~exact + state loc_lv exp + in + value + + (** Precondition: the type of [exp] and the type [loc_lv] may be different + only if the cast from [typeOf exp] + and [typeOfPointed lv] is a truncation or an extension. + This function will not perform any conversion (float->int, int->float,..) + *) + let do_assign_abstract_value ~with_alarms state lv exp = + let loc_lv = lval_to_loc ~with_alarms state lv in + remember_bases_with_locals loc_lv exp; + CilE.set_syntactic_context (CilE.SyMem lv); + do_assign_abstract_value_to_loc ~with_alarms state lv loc_lv exp + + + let offsetmap_top_addresses_of_locals is_local = + let is_local_bytes = Location_Bytes.contains_addresses_of_locals is_local in + fun offsetmap -> + if Cvalue.V_Offsetmap.is_empty offsetmap + then Location_Bytes.Top_Param.top, offsetmap + else + let loc_contains_addresses_of_locals t = + let v = Cvalue.V_Or_Uninitialized.get_v t in + is_local_bytes v + in + let locals, result = + Cvalue.V_Offsetmap.top_stuff + loc_contains_addresses_of_locals + (fun v -> + Cvalue.V_Or_Uninitialized.unspecify_escaping_locals + is_local v) + Location_Bytes.Top_Param.join + Location_Bytes.Top_Param.bottom + offsetmap + in + locals, result + + let state_top_addresses_of_locals ~is_block offsetmap_top_addresses_of_locals fundec = + let f k offsm = + let locals, r = offsetmap_top_addresses_of_locals offsm in + let found_locals = not (Cvalue.V_Offsetmap.equal r offsm) in + if found_locals then + warn_locals_escape is_block fundec k locals; + r + in + (fun (state:Cvalue.Model.t) -> + (* let's forget relations *) + let simple_state = state in + let f base acc = + try + let offset_to_clean = Cvalue.Model.find_base base simple_state + in + let cleaned_offsetmap = f base offset_to_clean in + Cvalue.Model.add_offsetmap base cleaned_offsetmap acc + with Not_found -> acc + in + try + (Location_Bits.Top_Param.fold + f + !bases_containing_locals + (f Base.null simple_state)) + with Location_Bits.Top_Param.Error_Top -> + begin + let f k offsm acc = + let locals, r = offsetmap_top_addresses_of_locals offsm in + let found_locals = not (Cvalue.V_Offsetmap.equal r offsm) in + if found_locals then + warn_locals_escape is_block fundec k locals; + Cvalue.Model.add_offsetmap k r acc + in + let result = + try + (Cvalue.Model.fold_base_offsetmap + f + state + Cvalue.Model.empty_map) + with Cvalue.Model.Error_Bottom -> Cvalue.Model.bottom + in + result + end) + + let top_addresses_of_locals fundec = + let entry_point = Globals.entry_point () in + if snd entry_point (* lib *) || + current_kf() != fst entry_point (* not entry point *) + then + let offsetmap_top_addresses_of_locals = + offsetmap_top_addresses_of_locals + (Cilutil.swap Base.is_formal_or_local fundec) + in + let state_top_addresses_of_locals = + state_top_addresses_of_locals ~is_block:false + offsetmap_top_addresses_of_locals fundec + in + offsetmap_top_addresses_of_locals, state_top_addresses_of_locals + else (fun x -> Location_Bytes.Top_Param.bottom, x),(fun x -> x) + + let block_top_addresses_of_locals blocks = + if List.for_all (fun b -> List.for_all (fun v -> v.vgenerated) b.blocals) + blocks + then + fun x -> x (* no need to change the state if there is no local + variable or if all the variable have been generated + by Cil (in which case we know that they are correctly + initialized and used, don't we) + *) + else + let offsetmap_top_addresses_of_locals = + offsetmap_top_addresses_of_locals + (fun v -> List.exists (Base.is_block_local v) blocks) + in + let state_top_addresses_of_locals = + state_top_addresses_of_locals ~is_block:true + offsetmap_top_addresses_of_locals + (Kernel_function.get_definition (current_kf())) + in + state_top_addresses_of_locals + + (* Assigns [exp] to [lv] in [state] *) + let do_assign ~with_alarms old_state lv exp = + assert (Cvalue.Model.is_reachable old_state); + let fresh_flags () = + let flag = ref false in + (fun () -> flag := true), + fun () -> !flag + in + let set_alarm, get_alarm = fresh_flags () in + let logger v = + if v <> CilE.Aignore + then CilE.Acall set_alarm + else CilE.Aignore + in + let warn_remember_mode = + { CilE.imprecision_tracing = logger with_alarms.CilE.imprecision_tracing; + others = with_alarms.CilE.others; + unspecified = logger with_alarms.CilE.unspecified} + in + let reduced_state, _, evaled_exp = + eval_expr_with_deps_state_subdiv ~with_alarms:warn_remember_mode None + old_state + exp + in +(* Value_parameters.debug ~level:2 "do_assign %a = (%a)(%a)" + !d_lval lv + !d_exp exp + V.pretty evaled_exp; *) + let left_loc = lval_to_loc ~with_alarms old_state lv in + let is_bitfield = is_bitfield lv ~sizebf:left_loc.size () in + remember_bases_with_locals left_loc evaled_exp; + let warn_right_exp_imprecision () = + (match with_alarms.CilE.imprecision_tracing with + | CilE.Aignore -> () + | CilE.Acall f -> f () + | CilE.Alog _ -> + match evaled_exp with + | Cvalue.V.Top(_topparam,origin) -> + Value_parameters.result ~once:true ~current:true + "@[<v>@[Assigning imprecise value to %a%t.@]%a%t@]" + !Ast_printer.d_lval lv + (fun fmt -> match lv with + | (Mem _, _) -> + Format.fprintf fmt "@ (i.e. %a)" + Locations.pretty left_loc + | (Var _, _) -> ()) + (fun fmt org -> + if not (Origin.is_top origin) then + Format.fprintf fmt + "@ @[The imprecision@ originates@ from@ %a@]" + Origin.pretty org) + origin + pp_callstack + | Cvalue.V.Map _ -> + if not (Got_Imprecise_Value.get ()) && + not (Cvalue.V.cardinal_zero_or_one evaled_exp) + then begin + Got_Imprecise_Value.set true; + if (Value_parameters.ValShowProgress.get()) + then + Value_parameters.result ~current:true + "assigning non deterministic value for the first time"; + end) + in + let reduced_state = + match lv with + | Mem mem_e,NoOffset -> + let new_reduced_state = + reduce_by_valid_expr + ~positive:true ~for_writing:true + mem_e + reduced_state + in + if not (Cvalue.Model.is_reachable new_reduced_state) + then begin + CilE.set_syntactic_context (CilE.SyMem lv); + CilE.warn_mem_write with_alarms ; + Value_parameters.result ~current:true + "all target addresses were invalid. This path is assumed to be dead."; + end; + new_reduced_state + (* | Var _ , Index _ -> assert false + TODO: do something for "TAB[i] = expr" + *) + | _ -> reduced_state + in + let default () = + warn_right_exp_imprecision (); + if get_alarm() then + (* log alarms that have not been logged the first time *) + ignore + (eval_expr + ~with_alarms: + {CilE.imprecision_tracing=with_alarms.CilE.imprecision_tracing; + others=CilE.Aignore; + unspecified=with_alarms.CilE.unspecified} + old_state + exp); + + if Cvalue.V.is_bottom evaled_exp || + Location_Bits.equal left_loc.loc Location_Bits.bottom || + not (Cvalue.Model.is_reachable reduced_state) + then Cvalue.Model.bottom + else begin + CilE.set_syntactic_context (CilE.SyMem lv); + do_assign_abstract_value_to_loc ~with_alarms + reduced_state + lv + left_loc + evaled_exp + end + in + let default_lval exp_lv = + (* directly copy the old value without trying to recompose it. + Useful for structs assignment. *) + let right_loc = lval_to_loc ~with_alarms old_state exp_lv in + ( match right_loc.size, left_loc.size with + Int_Base.Value rsize, Int_Base.Value lsize when + Int.equal rsize lsize && + Int.to_int(rsize) > bitsSizeOf (TInt (IInt, [])) -> + if + Location_Bits.partially_overlaps + rsize + right_loc.loc + left_loc.loc + then begin + warning_once_current "Partially overlapping lvalue assignment \"%a=%a;\". Left address in bits: %a. Right address in bits: %a. assert(separated or same)" + !d_lval lv + !d_lval exp_lv + Location_Bits.pretty left_loc.loc + Location_Bits.pretty right_loc.loc; + CilE.stop_if_stop_at_first_alarm_mode () + end + | _ -> () ); + + + CilE.set_syntactic_context (CilE.SyMem exp_lv); + let full_val = + Cvalue.Model.find_unspecified + ~with_alarms:CilE.warn_none_mode + old_state + right_loc + in + if Location_Bits.equal left_loc.loc Location_Bits.bottom || + not (Cvalue.Model.is_reachable reduced_state) || + V_Or_Uninitialized.equal full_val V_Or_Uninitialized.bottom + then Cvalue.Model.bottom + else begin + match right_loc.size, left_loc.size with + | Int_Base.Value size, Int_Base.Value other_size + when Int.equal other_size size -> + let offsetmap_relations = + Cvalue.V_Offsetmap.empty (* TODO: cleanup *) + in + CilE.set_syntactic_context (CilE.SyMem exp_lv); + let offsetmap_memory = + match Cvalue.Model.copy_offsetmap ~with_alarms right_loc old_state with + | Some v -> v + | None -> raise Lmap.Cannot_copy (* invalid copy paste *) + in + let offsetmap = + Cvalue.V_Offsetmap.over_intersection + offsetmap_relations + offsetmap_memory + in + if not (Cvalue.V_Offsetmap.is_empty offsetmap) + then begin + CilE.set_syntactic_context (CilE.SyMem lv); + let copy_paste_succeeded = + Cvalue.Model.paste_offsetmap with_alarms + offsetmap left_loc.loc Int.zero size true reduced_state + in + (* Shall we warn about imprecise contents just copied? *) + let module L = struct exception Got_imprecise end in + (try + Cvalue.V_Offsetmap.iter_contents + (fun v -> + match Cvalue.V_Or_Uninitialized.get_v v with + | Location_Bytes.Map _ -> () + | _ -> raise L.Got_imprecise) + offsetmap + size + with L.Got_imprecise -> + warn_right_exp_imprecision ()); + copy_paste_succeeded + end + else raise Lmap.Cannot_copy + | _ -> raise Lmap.Cannot_copy + end + in + let new_main_memory_state = + try + if is_bitfield then default() + else + (* An lval assignement might be hidden by a dummy cast *) + let lv = find_lv ~with_alarms old_state exp in + default_lval lv + with Cannot_find_lv | Lmap.Cannot_copy + (* from Cvalue.Model.paste_offsetmap + or directly default_lval *) -> + default () + in + new_main_memory_state + + + let do_assign ~with_alarms old_state lv exp = + if true then do_assign ~with_alarms old_state lv exp + else + let vars = + get_influential_vars ~with_alarms:CilE.warn_none_mode old_state exp + in + let rec try_sub vars = + match vars with + | [] | [ _ ] -> do_assign ~with_alarms old_state lv exp + | v :: tail -> + try + if not (List.exists (fun x -> Locations.loc_equal v x) tail) + then raise Too_linear; + let value = + Cvalue.Model.find + ~conflate_bottom:true + ~with_alarms:CilE.warn_none_mode + old_state + v + in + + if Location_Bytes.is_included value Location_Bytes.top_float + then raise Too_linear; + + ignore (Cvalue.V.splitting_cardinal_less_than + ~split_non_enumerable:42 value 142); +(* Value_parameters.debug + "subdiv assignment: candidate %a value %a@." + Locations.pretty v + Cvalue.V.pretty value; *) + let treat_subdiv subvalue acc = + let sub_oldstate = + (* FIXME: should be relation-aware primitive *) + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + old_state + v + subvalue + in + let sub_newstate = + do_assign ~with_alarms sub_oldstate lv exp + in + Cvalue.Model.join acc sub_newstate + in + Location_Bytes.fold_enum + ~split_non_enumerable:42 + treat_subdiv + value + Cvalue.Model.bottom + with + | Not_less_than | Too_linear -> try_sub tail + | Location_Bytes.Error_Top -> assert false; + in + try_sub vars + + let empty_interpretation_result = + None, Cvalue.Model.bottom, Location_Bits.Top_Param.bottom + + let assign_return_to_lv ~with_alarms funcexp lv return new_state = + let loc = lval_to_loc ~with_alarms new_state lv in + let rtype = getReturnType (typeOf funcexp) in + let lvtyp = typeOfLval lv in + let is_bitfield = is_bitfield lv ~sizebf:loc.size ~sizelv:(sizeof lvtyp) () in + let default () = + let value_with_init = + V_Offsetmap.find_ival + ~conflate_bottom:false + ~validity:Base.All + ~with_alarms:CilE.warn_none_mode + Ival.zero + return + (Int.of_int (bitsSizeOf rtype)) + in + let flags = V_Or_Uninitialized.get_flags value_with_init in + let init = V_Or_Uninitialized.is_initialized flags in + let no_esc = V_Or_Uninitialized.is_noesc flags in + let value = V_Or_Uninitialized.get_v value_with_init in + if not init then CilE.warn_uninitialized with_alarms; + if not no_esc then CilE.warn_escapingaddr with_alarms; + if Cvalue.V.is_bottom value && not (init && no_esc) + then + Value_parameters.result ~current:true + "Function call returned an unspecified value. \ + This path is assumed to be dead."; + let exact = valid_cardinal_zero_or_one ~for_writing:true loc in + let evaled_exp = + (* fix http://bts.frama-c.com/view.php?id=798 *) + do_cast ~with_alarms:CilE.warn_none_mode rtype value in + let evaled_exp = + if is_bitfield + then cast_lval_bitfield lv (Int_Base.project loc.size) evaled_exp + else do_cast ~with_alarms:CilE.warn_none_mode lvtyp evaled_exp + in + remember_bases_with_locals loc evaled_exp; + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact + new_state + loc + evaled_exp + in + if is_bitfield || (need_cast lvtyp rtype) + then default () + else + (try + let result = + Cvalue.Model.paste_offsetmap with_alarms + return + loc.loc + Int.zero + (Int_Base.project loc.size) + true + new_state + in + let evaled_exp= + Cvalue.V_Or_Uninitialized.get_v + (V_Offsetmap.find_ival + ~conflate_bottom:false + ~validity:Base.All + ~with_alarms:CilE.warn_none_mode + Ival.zero + return + (Int.of_int (bitsSizeOf rtype)) + ) + in + remember_bases_with_locals loc evaled_exp; + result + with Lmap.Cannot_copy -> default ()) + + let interp_call stmt lval_to_assign funcexp argl d_value = + let call_site_loc = CurrentLoc.get () in + let with_alarms = warn_all_quiet_mode () in + let return_type_funcexp = + match unrollType (typeOf funcexp) with + TFun (t, _, _, _) -> t + | _ -> assert false + in + let bitssizeofreturntypefuncexp = + bitsSizeOf return_type_funcexp + in + let state_after_call state = + try + let functions, _ = resolv_func_vinfo ~with_alarms None state funcexp in + let is_library_function kf = not (Kernel_function.is_definition kf) in + let calling_at_least_one_library_function = + Kernel_function.Hptset.exists is_library_function functions + in + let calling_only_library_functions = + calling_at_least_one_library_function && + (Kernel_function.Hptset.for_all is_library_function functions) + in + let compute_actual = compute_actual ~with_alarms + (calling_at_least_one_library_function, + calling_only_library_functions) + in + let actuals = List.map (compute_actual state) argl in + let treat_one_call f (acc_rt,acc_res,acc_clobbered_set as acc) = + try + let return_type = Kernel_function.get_return_type f in + if bitsSizeOf return_type <> bitssizeofreturntypefuncexp + then raise Wrong_function_type; + + let return, result, clobbered_set = + !compute_call_ref f ~call_kinstr:(Kstmt stmt) state actuals + in + let caller = current_kf (), stmt in + Kf_state.add_caller f ~caller; + CurrentLoc.set call_site_loc; + (match acc_rt,return with + | None,_ -> return + | Some _, None -> acc_rt + | Some acc_rt, Some return -> + Some (snd (V_Offsetmap.join acc_rt return))), + Cvalue.Model.join acc_res result, + Location_Bits.Top_Param.join acc_clobbered_set clobbered_set + with Wrong_function_type -> + warning_once_current + "Pointed function type must match function pointer type when dereferenced: assert(Ook)"; + CilE.stop_if_stop_at_first_alarm_mode (); + acc + in + let return,new_state,clobbered_set = + Kernel_function.Hptset.fold treat_one_call + functions + empty_interpretation_result + in + bases_containing_locals := + Location_Bits.Top_Param.join !bases_containing_locals clobbered_set; + match lval_to_assign with + | None -> new_state + | Some lv -> + match return with + | Some return -> + assign_return_to_lv ~with_alarms funcexp lv return new_state + | None -> + if Cvalue.Model.is_reachable new_state + then + warning_once_current + "In function %t: called function returns void but \ + returned value is assigned; ignoring assignment" + pretty_current_cfunction_name; + new_state + with + | Got_bottom -> + CurrentLoc.set call_site_loc; + Cvalue.Model.bottom + | Leaf -> + CurrentLoc.set call_site_loc; + (match lval_to_assign with + | None -> state + | Some lv -> + let evaled_exp = V.top_leaf_origin () in + do_assign_abstract_value ~with_alarms state lv evaled_exp) + in + State_set.fold + (fun acc state -> State_set.add (state_after_call state) acc) + State_set.empty + d_value + + let doInstr stmt (i: instr) (d: t) = + !Db.progress (); + CilE.start_stmt (Kstmt stmt); + let d_states = d.value in + let unreachable = State_set.is_empty d_states in + let result = + if unreachable then + Dataflow.Done d + else begin + let apply_each_state f = + let modified_states = + State_set.fold + (fun acc state_value -> State_set.add (f state_value) acc) + State_set.empty + d_states + in + Dataflow.Done { counter_unroll = 0; value = modified_states } + in + (* update current statement *) + match i with + | Set (lv,exp,_loc) -> + apply_each_state + (fun state_value -> + do_assign + ~with_alarms:(warn_all_quiet_mode ()) + state_value + lv + exp) + | Call (lval_to_assign, + {enode = Lval (Var {vname=("__builtin_va_start"|"__builtin_va_arg"|"__builtin_va_end" as _builtin_name) },NoOffset)}, + [{enode = Lval lv}],_loc) -> +(* Format.printf "builtin: %s@." _builtin_name; *) + apply_each_state + (fun state -> + let state = + do_assign_abstract_value + ~with_alarms:(warn_all_quiet_mode ()) + state + lv + Cvalue.V.top_int + in + ( match lval_to_assign with + None -> state + | Some lval_assign -> + do_assign_abstract_value + ~with_alarms:(warn_all_quiet_mode ()) + state + lval_assign + Cvalue.V.top_int)) + | Call (lval_to_assign,funcexp,argl,_loc) -> + Dataflow.Done + { counter_unroll = 0; + value = interp_call stmt lval_to_assign funcexp argl d_states} + | Asm _ -> + warning_once_current + "assuming assembly code has no effects in function %t" + pretty_current_cfunction_name; + Dataflow.Default + | Skip _ -> + Dataflow.Default + | Code_annot (_,_) -> (* processed in dostmt from Db *) + Dataflow.Default + end + in + CilE.end_stmt (); + result + + (* Reduce the given states according to the given code annotations. + If [record] is true, update the proof state of the code annotation. + DO NOT PASS record=false unless you known what your are doing *) + let interp_annot state stmt ca record = + let aux text behav p = + let in_behavior = + match behav with + | [] -> True + | behavs -> + let ab = AnalysisParam.active_behaviors in + let all_active = Extlib.filter_map' + (ActiveBehaviors.behavior_from_name ab) + (ActiveBehaviors.is_active ab) + behavs + in + if all_active = [] then False + else + if List.exists (ActiveBehaviors.only_active ab) all_active + then True + else Unknown + in + if in_behavior = False + then state + else + let result = fold_join_predicate State_set.fold + (fun here -> + let env = env_annot ~pre:!!fused_initial_state ~here in + eval_predicate ~result:None env p) + state + in + let ip = Property.ip_of_code_annot (current_kf()) stmt ca in + let change_status st = + if record then List.iter (fun p -> emit_status p st) ip + in + let message, result = + (match result, in_behavior with + | Unknown, _ | False, Unknown -> + if State_set.is_empty state then begin + change_status Property_status.False_if_reachable; + "invalid (stopping propagation)", State_set.empty + end else begin + change_status Property_status.Dont_know; + "unknown", state + end + | True, _ -> + change_status Property_status.True; + "valid", state + | False, True -> + change_status Property_status.False_if_reachable; + "invalid (stopping propagation)", State_set.empty + | _, False -> assert false) + in + if record then + Value_parameters.result ~once:true ~current:true + "%s got status %s.%t" text message pp_callstack; + if in_behavior = True then + let env = env_annot ~pre:!!fused_initial_state + ~here:(State_set.join result) in + reduce_by_disjunction ~result:None ~env + result + slevel + p + else + result + in + match ca.annot_content with + | AAssert (behav,p) -> aux "Assertion" behav p + | AInvariant (behav, true, p) -> aux "Loop invariant" behav p + | APragma _ + | AInvariant (_, false, _) + | AVariant _ | AAssigns _ + | AStmtSpec _ (*TODO*) -> state + + let check_non_overlapping state lvs1 lvs2 = + List.iter + (fun lv1 -> + List.iter + (fun lv2 -> + let zone1 = + Locations.valid_enumerate_bits ~for_writing:false + (lval_to_loc ~with_alarms:CilE.warn_none_mode state lv1) + in + let zone2 = + Locations.valid_enumerate_bits ~for_writing:false + (lval_to_loc ~with_alarms:CilE.warn_none_mode state lv2) + in + if Locations.Zone.intersects zone1 zone2 + then begin + CilE.set_syntactic_context + (CilE.SySep + (Cil.mkAddrOf ~loc:(CurrentLoc.get ()) lv1, + Cil.mkAddrOf ~loc:(CurrentLoc.get ()) lv2)); + CilE.warn_separated warn_all_mode + end) + lvs2) + lvs1 + +(* TODO: Take advantage of calls information. *) + let check_unspecified_sequence state seq = + let rec check_one_stmt ((stmt1,_,writes1,_,_) as my_stmt) = function + [] -> () + | (stmt2,_,_,_,_)::seq when stmt1 == stmt2 -> check_one_stmt my_stmt seq + | (stmt2,modified2,writes2,reads2,_) :: seq -> + let unauthorized_reads = + (* TODO: try to have a more semantical interpretation of modified *) + List.filter + (fun x -> List.for_all + (fun y -> not (Cil.compareLval x y)) modified2) + writes1 + in + check_non_overlapping state unauthorized_reads reads2; + if stmt1.sid < stmt2.sid then + check_non_overlapping state writes1 writes2; + check_one_stmt my_stmt seq + in + List.iter (fun x -> check_one_stmt x seq) seq + + let doStmt (s: stmt) (d: t) = + let states = d.value in + d.value <- State_set.empty; + let kinstr = Kstmt s in + + if State_set.is_empty states + then + Dataflow.SDefault + else + let annots_before = + Annotations.single_fold_stmt + (fun a acc -> + match a with + | User { annot_content = AStmtSpec _ } + | AI (_,{annot_content = AStmtSpec _ }) -> acc + | AI (_, b) | User b -> b :: acc) + s + [] + in + CilE.start_stmt kinstr; + let states = + List.fold_left + (fun states annot -> interp_annot states s annot true) + states + annots_before + in + CilE.end_stmt (); + let not_already_states = + if obviously_terminates + then states + else Current_table.update_and_tell_if_changed current_table s states + in + if State_set.is_empty not_already_states + then Dataflow.SDefault + else + let is_return = match s.skind with Return _ -> true | _ -> false in + let new_states = + if d.counter_unroll >= slevel || (is_return && obviously_terminates) + then + let curr_wcounter, curr_wstate = + Current_table.find_widening_info current_table s + in + let state = State_set.join states in + let joined = Cvalue.Model.join curr_wstate state in + if obviously_terminates + then begin + Current_table.update_widening_info current_table s 0 joined; + states + end + else + let r = + if AnalysisParam.is_natural_loop s && curr_wcounter = 0 then + let wh_key_set, wh_hints = getWidenHints s in + let widen_hints = + true, wh_key_set(* no longer used thanks to 0/1 widening*), + wh_hints + in + snd (Cvalue.Model.widen widen_hints curr_wstate joined) + else + joined + in + let new_widening = + if curr_wcounter = 0 + then 1 + else pred curr_wcounter + in + let new_state = State_set.singleton r in + if Cvalue.Model.equal r joined then ( + Current_table.update_widening_info current_table s new_widening r; + new_state) + else begin + (* Try to correct over-widenings *) + CilE.start_stmt kinstr; + let new_states = + (* Do *not* record the status after interpreting the annotation + here. Possible unproven assertions have already been + recorded when the assertion has been interpreted the first + time higher in this function. *) + List.fold_left + (fun states annot -> interp_annot states s annot false) + new_state + annots_before + in + CilE.end_stmt (); + let new_joined = State_set.join new_states in + Current_table.update_widening_info + current_table s new_widening new_joined; + State_set.singleton new_joined + end + else states + in + let d = { d with value = new_states } + in + ( match s.skind with + | Loop _ -> + if d.counter_unroll >= slevel && + (Value_parameters.ValShowProgress.get()) + then + Value_parameters.result ~level:1 ~once:true ~current:true + "entering loop for the first time" + | UnspecifiedSequence seq -> + if Kernel.UnspecifiedAccess.get () + then begin + CilE.start_stmt kinstr; + State_set.iter + (fun state -> check_unspecified_sequence state seq) states; + CilE.end_stmt () + end + | _ -> ()); + Dataflow.SUse d + + let doEdge s succ d = + let kinstr = Kstmt s in + let states = d.value in + CilE.start_stmt kinstr; + (* We store the state after the execution of [s] for the callback + {Value.Record_Value_After_Callbacks}. This is done here + because we want to see the values of the variables local to the block *) + if (Value_parameters.ResultsAfter.get () || + not (Db.Value.Record_Value_After_Callbacks.is_empty ())) + && (store_state_after_during_dataflow s succ) + then ( + let old = + try Cil_datatype.Stmt.Hashtbl.find states_after s + with Not_found -> Cvalue.Model.bottom + in + let updated = State_set.fold Cvalue.Model.join old states in + Cil_datatype.Stmt.Hashtbl.replace states_after s updated + ); + + let states = + match Kernel_function.blocks_closed_by_edge s succ with + | [] -> states + | closed_blocks -> + let block_top_addresses_of_locals = + block_top_addresses_of_locals closed_blocks + in + State_set.fold + (fun set state -> + let state = + Cvalue.Model.uninitialize_locals closed_blocks state + in + State_set.add (block_top_addresses_of_locals state) set) + State_set.empty + states; + in + CilE.end_stmt (); + { d with value = states } + + let filterStmt _stmt = true + + (* Remove all local variables and formals from table *) + let externalize return kf = + match kf.fundec with + | Declaration _ -> assert false + | Definition (fundec,_loc) -> + assert + (StmtStartData.iter + (fun k v -> + if State_set.is_empty (v.value) + then () + else (Value_parameters.fatal "sid:%d@\n%a@\n" + k.sid + State_set.pretty (v.value))); + true); + let superpos = + Current_table.find_superposition current_table return + in + let init_state = + Current_table.find_superposition + current_table + (Kernel_function.find_first_stmt kf) + in + let superpos = + let result = + match return with + | {skind = Return (Some ({enode = Lval (Var v,_)}),_)} -> + Some v + | _ -> None + in + check_fct_postconditions ~result + kf + ~init_state + ~active_behaviors:AnalysisParam.active_behaviors + ~post_state:superpos + Normal + in + let state = State_set.join_dropping_relations superpos in + + if Value_parameters.ValShowProgress.get() then + Value_parameters.feedback "Recording results for %a" + Kernel_function.pretty kf; + + merge_current ~degenerate:false; + let ret_val = + (match return with + | {skind = Return (Some ({enode = Lval lv}),_)} -> + offsetmap_of_lv ~with_alarms:(warn_all_quiet_mode ()) state lv + | {skind = Return (None,_)} -> None + | _ -> assert false) + in + let state = + Cvalue.Model.clear_state_from_locals fundec state + in + let offsetmap_top_addresses_of_locals, state_top_addresses_of_locals = + top_addresses_of_locals fundec + in + let result = + (match ret_val with + | None -> ret_val + | Some ret_val -> + let locals, r = offsetmap_top_addresses_of_locals ret_val in + let warn = not (Cvalue.V_Offsetmap.equal r ret_val) + in + if warn then warn_locals_escape_result fundec locals; + Some r), + state_top_addresses_of_locals state, + !bases_containing_locals + in + result + + let doGuardOneCond stmt exp t = + if State_set.is_empty (t.value) + then Dataflow.GUnreachable + else begin + CilE.start_stmt (Kstmt stmt); + let with_alarms = warn_all_quiet_mode () in + let new_values = + State_set.fold + (fun acc state -> + let test = + eval_expr + ~with_alarms + state exp + in + CilE.set_syntactic_context + (CilE.SyBinOp (Ne, Cil.zero ~loc:exp.eloc, exp)); + let warn, _, test = + check_comparable Eq V.singleton_zero test + in + + let do_it = + (warn && Value_parameters.UndefinedPointerComparisonPropagateAll.get ()) || + let t1 = unrollType (typeOf exp) in + if isIntegralType t1 || isPointerType t1 + then V.contains_non_zero test + else true (* TODO: a float condition is true iff != 0.0 *) + in + if do_it then + try + State_set.add + (reduce_by_cond ~with_alarms:CilE.warn_none_mode + state {positive = true; exp = exp}) + acc + with Reduce_to_bottom -> acc + else acc) + State_set.empty + t.value + in + let result = + if State_set.is_empty new_values then Dataflow.GUnreachable + else Dataflow.GUse {t with value = new_values} + in + CilE.end_stmt (); + result + + end + + let mask_then = Db.Value.mask_then + let mask_else = Db.Value.mask_else + + let doGuard stmt exp t = + let not_exp = new_exp ~loc:exp.eloc (UnOp(LNot, exp, intType)) in + let th, el as thel = + doGuardOneCond stmt exp t, doGuardOneCond stmt not_exp t + in + let current_condition_status = + try + Cil_datatype.Stmt.Hashtbl.find conditions_table stmt + with Not_found -> 0 + in + let new_status = + ( if (current_condition_status land mask_then) <> 0 + then mask_then + else + match th with + Dataflow.GUse _ | Dataflow.GDefault -> mask_then + | Dataflow.GUnreachable -> 0) lor + ( if (current_condition_status land mask_else) <> 0 + then mask_else + else + match el with + Dataflow.GUse _ | Dataflow.GDefault -> mask_else + | Dataflow.GUnreachable -> 0) + in + if new_status <> 0 + then Cil_datatype.Stmt.Hashtbl.replace conditions_table stmt new_status; + Separate.filter_if stmt thel +end + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/initial_state.ml frama-c-20111001+nitrogen+dfsg/src/value/initial_state.ml --- frama-c-20110201+carbon+dfsg/src/value/initial_state.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/initial_state.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,662 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Creation of the initial state for Value *) + +open Cil_types +open Cil +open Abstract_interp +open Cvalue +open Locations +open Bit_utils +open Value_util + +exception Initialization_failed + +let make_well hidden_base state loc = + let size = Bit_utils.max_bit_size () in + let well = Cvalue.V.inject_top_origin + Origin.Well + (Cvalue.V.Top_Param.O.singleton hidden_base) + in + let well_loc = + Locations.make_loc + (Location_Bits.inject hidden_base Ival.zero) + (Int_Base.inject size) + in + let state_with_well = + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + well_loc + well + in + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state_with_well + loc + well + +let create_hidden_base + validity_from_type ~hidden_var_name ~name_desc pointed_typ = + let hidden_var = + makeGlobalVar ~generated:false ~logic:true hidden_var_name pointed_typ + in + Globals.Vars.add_decl hidden_var; + hidden_var.vdescr <- Some name_desc; + let validity = + if validity_from_type + then begin + match Base.validity_from_type hidden_var with + | Base.Known (a,b) + when not (Value_parameters.AllocatedContextValid.get ()) -> + Base.Unknown (a,b) + | (Base.All | Base.Unknown _ | Base.Known _) as s -> s + | Base.Periodic _ -> assert false + end + else Base.Unknown (Int.zero,Bit_utils.max_bit_address ()) + in + let hidden_base = Base.create_logic hidden_var validity + in + hidden_base + +(** [initialize_var_using_type varinfo state] uses the type of [varinfo] + to create an initial value in [state]. *) +let initialize_var_using_type varinfo state = + CurrentLoc.set varinfo.vdecl; + let initializing_formal = not varinfo.vglob in + let force_initialize = + initializing_formal || + (Cvalue.Model.has_been_initialized + (Base.create_varinfo varinfo) + state) + in + let rec add_offsetmap depth v name_desc name typ offset_orig typ_orig state = + let typ = Cil.unrollType typ in + let loc = loc_of_typoffset v typ_orig offset_orig in + let rec treat_as_const typ = + (hasAttribute "const" (typeAttrs typ)) || + ( match typ with + TArray (typ, _,_,_) -> treat_as_const (Cil.unrollType typ) + | _ -> false) + in + let must_initialize = + force_initialize || (not (treat_as_const typ)) + in + if not must_initialize + (* if we do not have an initializer for this const, we generate + a formal constant *) + then state else + match typ with + | TInt _ | TEnum (_, _)-> + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + Cvalue.V.top_int + | TFloat ((FDouble | FLongDouble as fkind), _) -> + if fkind = FLongDouble + then + Value_parameters.warning + ~once:true + "Warning: unsupported long double treated as double"; + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + Cvalue.V.top_float + | TFloat (FFloat, _) -> + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + Cvalue.V.top_single_precision_float + | TFun _ -> + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + (Cvalue.V.top_leaf_origin ()) + | TPtr (typ, _) as full_typ + when depth <= Value_parameters.AutomaticContextMaxDepth.get () -> + let attr = typeAttr full_typ in + let context_max_width = + Value_parameters.AutomaticContextMaxWidth.get () + in + if not (isVoidType typ) && not (isFunctionType typ) then + let i = + match findAttribute "arraylen" attr with + | [AInt i] -> i + | _ -> context_max_width + in + let pointed_typ = + TArray(typ, + Some (integer ~loc:varinfo.vdecl i), + empty_size_cache (), + []) + in + let hidden_var_name = + Cabs2cil.fresh_global ("S_" ^ name) + in + let name_desc = "*"^name_desc in + let hidden_base = + create_hidden_base + true + ~hidden_var_name + ~name_desc + pointed_typ + in + let state = + add_offsetmap + (depth + 1) + hidden_base + name_desc + hidden_var_name + pointed_typ + NoOffset + pointed_typ + state + in + let value = Cvalue.V.inject hidden_base (Ival.zero) + in + let value = + if Value_parameters.AllocatedContextValid.get () + then value + else Cvalue.V.join Cvalue.V.singleton_zero value + in + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + value + else + let hidden_var_name = + Cabs2cil.fresh_global ("S_" ^ name) + in + let name_desc = "*"^name_desc in + let hidden_base = + create_hidden_base + false + ~hidden_var_name + ~name_desc + typ + in + make_well hidden_base state loc + + | TArray (typ, len, _, _) -> + begin try + let size = lenOfArray len in + let state = ref state in + let typ = Cil.unrollType typ in + let treat_index (i : int) = + let offset = + addOffset + (Index (integer ~loc:varinfo.vdecl i, NoOffset)) + offset_orig + in + let name = (string_of_int i) ^"_"^ name in + let name_desc = name_desc ^ "[" ^ (string_of_int i) ^ "]" in + let s = + add_offsetmap depth v + name_desc name typ + offset typ_orig !state + in + state := s; + let loc = loc_of_typoffset v typ_orig offset in + let r_offsetmap = + Cvalue.Model.copy_offsetmap + ~with_alarms:CilE.warn_none_mode + loc s + in + match r_offsetmap with + Some r_offsetmap -> r_offsetmap + | None -> assert false + in + let max_precise_size = + Value_parameters.AutomaticContextMaxWidth.get () + in + if size <= max_precise_size + then + for i = 0 to pred size do + ignore (treat_index i) + done + else begin +(* Format.printf "ST %a: size=%d max_precise_size=%d offset=%a@." + Base.pretty v + size + max_precise_size + (!d_offset) offset_orig ; *) + let vv = ref None in + for i = 0 to pred max_precise_size do +(* Format.printf "IT %d@.%a@." + i + Cvalue.Model.pretty !state; *) + let r = treat_index i in + vv := + Some + ( match !vv with + None -> r + | Some vv -> snd (Cvalue.V_Offsetmap.join r vv)) + done; + ( match !vv with + None -> assert false + | Some vv -> +(* Format.printf "EN %a@." + Cvalue.V_Offsetmap.pretty vv; *) + for i = max_precise_size to pred size do + let offset = + addOffset + (Index (integer ~loc:varinfo.vdecl i, NoOffset)) + offset_orig + in + let loc = loc_of_typoffset v typ_orig offset in + let size = + try + Int_Base.project loc.size + with + | Int_Base.Error_Top + | Int_Base.Error_Bottom -> + assert false + in + state := + Cvalue.Model.paste_offsetmap CilE.warn_none_mode + vv loc.loc Int.zero size true !state + done); + end; + !state + with LenOfArray -> + Value_parameters.result ~once:true ~current:true + "could not find a size for array"; + state + end + | TComp ({cstruct=true;} as compinfo, _, _) -> (* Struct *) + let treat_field (next_offset,state) field = + let new_offset = Field (field, NoOffset) in + let offset = + addOffset + new_offset + offset_orig + in + let field_offset,field_width = bitsOffset typ_orig offset in + let state = + if field_offset>next_offset then (* padding bits needs filling*) + let loc = make_loc + (Location_Bits.inject v (Ival.of_int next_offset)) + (Int_Base.inject (Int.of_int (field_offset-next_offset))) + in + Cvalue.Model.add_binding_not_initialized state loc + else state + in + field_offset+field_width, + add_offsetmap + depth + v + (name_desc ^ "." ^ field.fname) + (field.fname^"_"^name) + field.ftype + offset + typ_orig + state + in + begin try + let boff,bwidth = bitsOffset typ_orig offset_orig in + let last_offset,state= List.fold_left + treat_field + (boff,state) + compinfo.cfields + in + if last_offset<(boff+bwidth) then (* padding at end of struct*) + let loc = make_loc + (Location_Bits.inject v (Ival.of_int last_offset)) + (Int_Base.inject (Int.of_int (boff+bwidth-last_offset))) + in + Cvalue.Model.add_binding_not_initialized state loc + else state + with Cil.SizeOfError _ -> state + end + | TComp ({cstruct=false}, _, _) when + is_fully_arithmetic typ + -> (* Union of arithmetic types *) + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + Cvalue.V.top_int + + | TPtr _ when Value_parameters.AllocatedContextValid.get () -> + (* deep pointers map to NULL in this case *) + Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + state + loc + Cvalue.V.singleton_zero + + | TBuiltin_va_list _ | TComp _ | TVoid _ | TPtr _ -> + (* variable arguments or union with non-arithmetic type + or deep pointers *) + + (* first create a new varid and offsetmap for the + "hidden location" *) + let hidden_var_name = + Cabs2cil.fresh_global ("WELL_"^name) + in + let hidden_var = + makeGlobalVar ~logic:true hidden_var_name charType + in + hidden_var.vdescr <- Some (name_desc^"_WELL"); + let hidden_base = + Base.create_logic + hidden_var + (Base.Known (Int.zero,Bit_utils.max_bit_address ())) + in + make_well hidden_base state loc + | TNamed (_, _) -> assert false + in + add_offsetmap + 0 + (Base.create_varinfo varinfo) + varinfo.vname varinfo.vname varinfo.vtype NoOffset varinfo.vtype state + +let initial_state_only_globals = + let module S = + State_builder.Option_ref + (Cvalue.Model) + (struct + let name = "only_globals" + let dependencies = + [ Ast.self; Kernel.LibEntry.self; Kernel.MainFunction.self ] + let kind = `Internal + end) + in + function () -> + let compute () = + Value_parameters.debug ~level:2 "Computing globals values"; + let state = ref Cvalue.Model.empty_map in + let update_state st' = + if not (Db.Value.is_reachable st') + then raise Initialization_failed + else state := st' + in + let complete_init ~last_bitsoffset ~abs_offset typ _l lval = + (* process the non initialized bits defaulting to 0 *) + begin try + let size_to_add, offset = + bitsSizeOf typ - last_bitsoffset, + Ival.inject_singleton (Int.of_int abs_offset) + in + assert (size_to_add >= 0); + if size_to_add <> 0 then + let loc = + match lval with + | Var vinfo, _ -> + let base = Base.create_varinfo vinfo in + let size_to_add = (Int.of_int size_to_add) in + let offset, size = + match Base.validity base with + Base.Periodic (mn, _mx, p) when Int.ge size_to_add p -> + Ival.inject_singleton mn, p + | _ -> offset, size_to_add + in + let loc = + Location_Bits.inject base offset + in + let loc = make_loc loc (Int_Base.inject size) in +(* Format.printf "loc for final zeroes %a@." + Locations.pretty loc; *) + loc + | _ -> + Value_parameters.error ~current:true + "Whacky initializer ? Please report."; + assert false + in + let v = + if hasAttribute "volatile" (typeAttrs typ) + then V.top_int + else V.singleton_zero + in + update_state + (Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + !state + loc + v) + with Cil.SizeOfError _ -> + Value_parameters.result ~once:true ~current:true + "cannot provide a default initializer: size is unknown" + end + in + let rec eval_init lval init = + match init with + | SingleInit exp -> + let loc = + Eval_exprs.lval_to_loc ~with_alarms:CilE.warn_none_mode + Cvalue.Model.top lval + in +(* Format.printf "loc:%a state before:%a@." + Locations.pretty loc + Cvalue.Model.pretty !state; *) + let exact = cardinal_zero_or_one loc in + assert + (if exact then true + else begin + Value_parameters.warning ~current:true + "In global initialisation, the location can not be \ +represented. Aborting."; + false + end); + let value = + Eval_exprs.eval_expr ~with_alarms:(warn_all_quiet_mode ()) + !state + exp + in + let v = + if hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lval)) + then V.top_int + else if not (Int_Base.equal + loc.Locations.size + (Int_Base.inject + (Int.of_int ((bitsSizeOf (typeOf exp)))))) + then (* bit-field *) + (* same sequence used for assignment to bit-fields in the code; + refactor *) + Cvalue.V.cast ~with_alarms:CilE.warn_none_mode + ~size:(Int_Base.project loc.Locations.size) + ~signed:(signof_typeof_lval lval) + value + else value + in + update_state + (Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode ~exact + !state loc v); +(* Format.printf "state after:%a@." + Cvalue.Model.pretty !state; *) + + | CompoundInit (base_typ, l) -> + if not (hasAttribute "volatile" (typeAttrs base_typ)) + then + let last_bitsoffset = + foldLeftCompound + ~implicit:false + ~doinit: + (fun off init typ (acc:int) -> + let o,w = bitsOffset base_typ off in + (* Format.printf "acc:%d o:%d w:%d@." acc o w; *) + if acc<o + then begin (* uninitialize the padding bits *) + let vi, (base_off,_) = + (match lval with + | Var vinfo, abs_offset -> + vinfo, + (bitsOffset vinfo.vtype abs_offset) + | _ -> + Value_parameters.fatal "Whacky initializer?") + in + let loc_bits = + Location_Bits.inject + (Base.create_varinfo vi) + (Ival.inject_singleton (Int.of_int (base_off+acc))) + in + let loc_size = Int_Base.inject (Int.of_int (o-acc)) in + let loc = make_loc loc_bits loc_size in +(* Format.printf "loc:%a@." Locations.pretty loc; *) + update_state + (Cvalue.Model.add_binding_not_initialized + !state + loc) + end + else assert (acc=o); + if hasAttribute "volatile" (typeAttrs typ) then + warning_once_current + "global initialization of volatile value ignored" + else + eval_init (addOffsetLval off lval) init; + o+w) + ~ct:base_typ + ~initl:l + ~acc:0 + in + let base_off,_ = + (match lval with + | Var vinfo, abs_offset -> + bitsOffset vinfo.vtype abs_offset + | _ -> + Value_parameters.fatal "Whacky initializer?") + in + (* Format.printf "last_bitsoffset:%d base_off:%d@\nstate after:%a@." + last_bitsoffset + base_off + Cvalue.Model.pretty !state; *) + complete_init ~last_bitsoffset + ~abs_offset:(base_off+last_bitsoffset) + base_typ + l + lval + else () + in + Globals.Vars.iter_in_file_order + (fun varinfo init -> + if not varinfo.vlogic then begin + CurrentLoc.set varinfo.vdecl; + match init.init with + | None -> (* Default to zero init *) + if varinfo.vstorage = Extern + then + (* Must not assume zero when the storage is extern. *) + update_state (initialize_var_using_type varinfo !state) + else + complete_init ~last_bitsoffset:0 ~abs_offset:0 + varinfo.vtype [] (Var varinfo,NoOffset) + | Some i -> + eval_init (Var varinfo,NoOffset) i + end); + + (** Bind the declared range for NULL to uninitialized *) + let min_valid = Base.min_valid_absolute_address () in + let max_valid = Base.max_valid_absolute_address () in + if Int.le min_valid max_valid + then begin + let loc_bits = + Location_Bits.inject_ival + (Ival.inject_singleton min_valid) + in + let loc_size = + Int_Base.inject + (Int.length min_valid max_valid) + in + if true (* TODO: command line option *) + then + update_state + (Cvalue.Model.add_binding + ~with_alarms:CilE.warn_none_mode + ~exact:true + !state + (make_loc loc_bits loc_size) + Cvalue.V.top_int) + else + update_state + (Cvalue.Model.add_binding_not_initialized + !state + (make_loc loc_bits loc_size)) + end; + let result = !state in + result + in + S.memo + (fun () -> + try compute () + with Initialization_failed -> Cvalue.Model.bottom) + +(** Compute only once the initial values for globals and NULL *) +let initial_state_contextfree_only_globals = + let module S = + State_builder.Option_ref + (Cvalue.Model) + (struct + let name = "contextfree_only_globals" + let dependencies = + [ Ast.self; Kernel.LibEntry.self; Kernel.MainFunction.self ] + let kind = `Internal + end) + in + function () -> + let add_varinfo state varinfo = + CurrentLoc.set varinfo.vdecl; + initialize_var_using_type varinfo state + in + let treat_global state = function + | GVar(vi,_,_) -> add_varinfo state vi + | GVarDecl(_,vi,_) when not (Cil.isFunctionType vi.vtype) -> + add_varinfo state vi + | GType _ | GCompTag _ | GCompTagDecl _ | GEnumTag _ | GEnumTagDecl _ + | GVarDecl _ | GFun _ | GAsm _ | GPragma _ | GText _ | GAnnot _ -> state + in + let compute () = + List.fold_left treat_global (initial_state_only_globals()) + (Ast.get ()).globals + in + S.memo compute + +let () = + Db.Value.initial_state_only_globals := + (fun () -> + if snd(Globals.entry_point ()) then + initial_state_contextfree_only_globals () + else + initial_state_only_globals () + ); + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/initial_state.mli frama-c-20111001+nitrogen+dfsg/src/value/initial_state.mli --- frama-c-20110201+carbon+dfsg/src/value/initial_state.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/initial_state.mli 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,32 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val initial_state_only_globals: unit -> Cvalue.Model.t +val initial_state_contextfree_only_globals: unit -> Cvalue.Model.t +val initialize_var_using_type: + Cil_types.varinfo -> Cvalue.Model.t -> Cvalue.Model.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/kf_state.ml frama-c-20111001+nitrogen+dfsg/src/value/kf_state.ml --- frama-c-20110201+carbon+dfsg/src/value/kf_state.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/kf_state.ml 2011-10-10 08:38:26.000000000 +0000 @@ -41,7 +41,7 @@ let is_called = Is_Called.memo (fun kf -> - try Value.is_accessible (Kstmt (Kernel_function.find_first_stmt kf)) + try Value.is_reachable_stmt (Kernel_function.find_first_stmt kf) with Kernel_function.No_Statement -> false) let mark_as_called kf = diff -Nru frama-c-20110201+carbon+dfsg/src/value/kf_state.mli frama-c-20111001+nitrogen+dfsg/src/value/kf_state.mli --- frama-c-20110201+carbon+dfsg/src/value/kf_state.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/kf_state.mli 2011-10-10 08:38:26.000000000 +0000 @@ -22,10 +22,10 @@ (** Keep information attached to kernel functions. *) -open Db_types +open Cil_types val mark_as_called: kernel_function -> unit -val add_caller: caller:kernel_function*Cil_types.stmt -> kernel_function -> unit +val add_caller: caller:kernel_function*stmt -> kernel_function -> unit (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/value/kinstr.ml frama-c-20111001+nitrogen+dfsg/src/value/kinstr.ml --- frama-c-20110201+carbon+dfsg/src/value/kinstr.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/kinstr.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,192 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -open Cil_types -open Eval -open Db_types -open Locations -open CilE - -(* [TODO Julien 2007/07/04]: - - is it signature really useful? - - should the comments be somewhere in [Db.Value]? *) -module type Kinstr_S = sig - (* Transform an lval into a location. - The boolean argument forces the analysis to be on bit level. - The result boolean is true iff the transformation is exact. *) - - (* Highlevel function : uses the alias analysis - If [deps] is present, accumulates in deps the locations - encountered while analyzing the [lval] *) - val lval_to_loc_with_deps : - skip_base_deps:bool - -> kinstr - -> deps:Locations.Zone.t - -> lval - -> Locations.Zone.t * Locations.location - - val lval_to_loc : kinstr -> lval -> Locations.location - - val expr_to_kernel_function : - kinstr - -> deps:Locations.Zone.t option - -> exp - -> Locations.Zone.t * kernel_function list -end - -let lval_to_loc_with_deps_state ~with_alarms state ~deps lv = - let state, deps, r = - Eval.lval_to_loc_with_deps - ~with_alarms - ~deps - ~reduce_valid_index:(Parameters.SafeArrays.get ()) - state - lv - in - state, Zone.out_some_or_bottom deps, r - -let lval_to_loc_with_deps ~with_alarms kinstr ~deps lv = - CilE.start_stmt kinstr; - let state = Db.Value.noassert_get_state kinstr in - let result = - lval_to_loc_with_deps_state ~with_alarms state ~deps lv in - CilE.end_stmt (); - result - -let lval_to_loc_with_deps_state state ~deps lv = - lval_to_loc_with_deps_state ~with_alarms:warn_none_mode state ~deps lv - -let lval_to_loc_kinstr kinstr ~with_alarms lv = - CilE.start_stmt kinstr; - let state = Db.Value.noassert_get_state kinstr in - (* Format.printf "@\ngot state when lval_to_loc:%a@." - Relations_type.Model.pretty state; *) - let r = lval_to_loc ~with_alarms state lv in - CilE.end_stmt (); - r - -let lval_to_zone kinstr ~with_alarms lv = - Locations.valid_enumerate_bits (lval_to_loc_kinstr ~with_alarms kinstr lv) - -let lval_to_zone_state state lv = - Locations.valid_enumerate_bits (lval_to_loc ~with_alarms:warn_none_mode state lv) - -let expr_to_kernel_function_state ~with_alarms state ~deps exp = - try - let deps, r = resolv_func_vinfo ~with_alarms deps state exp in - Zone.out_some_or_bottom deps, r - with Leaf -> Zone.out_some_or_bottom deps, Kernel_function.Hptset.empty - -let expr_to_kernel_function kinstr ~with_alarms ~deps exp = - CilE.start_stmt kinstr; - let state = Db.Value.noassert_get_state kinstr in - (* Format.printf "STATE IS %a@\n" Relations_type.Model.pretty state;*) - let r = - expr_to_kernel_function_state ~with_alarms state ~deps exp - in - CilE.end_stmt (); - r - -let expr_to_kernel_function_state = - expr_to_kernel_function_state ~with_alarms:warn_none_mode - -exception Top_input - -let assigns_to_zone_inputs_state state assigns = - try - let treat_one_zone acc (_,ins) = - match ins with - FromAny -> raise Top_input - | From l -> - List.fold_left - (fun acc term -> - let loc_ins = - !Db.Properties.Interp.identified_term_zone_to_loc ~result:None - state - term - in - Zone.join - acc - (Locations.valid_enumerate_bits loc_ins)) - acc - l - in - match assigns with - WritesAny -> Zone.bottom (*VP This corresponds to the old code - (cvs rev 1.9) - Not sure this is what we really want, though. - *) - | Writes [] -> Zone.bottom - | Writes l -> List.fold_left treat_one_zone Zone.bottom l - with - Top_input -> Zone.top - | Invalid_argument "not an lvalue" -> - CilE.warn_once "Failed to interpret assigns clause in inputs"; - Zone.top - -let lval_to_offsetmap kinstr lv ~with_alarms = - CilE.start_stmt kinstr; - let state = Db.Value.noassert_get_state kinstr in - let loc = Locations.valid_part - (lval_to_loc ~with_alarms state lv) - in - let offsetmap = - Relations_type.Model.copy_offsetmap ~with_alarms loc state - in - CilE.end_stmt (); - offsetmap - -let lval_to_offsetmap_state state lv = - let with_alarms = CilE.warn_none_mode in - let loc = Locations.valid_part (lval_to_loc ~with_alarms state lv) in - Relations_type.Model.copy_offsetmap ~with_alarms loc state - - -let () = - Db.Value.lval_to_loc_with_deps := - (fun s ~with_alarms ~deps lval -> - let _, deps, r = lval_to_loc_with_deps ~with_alarms s ~deps lval in - deps, r); - Db.Value.lval_to_loc_with_deps_state := - (fun s ~deps lval -> - let _, deps, r = lval_to_loc_with_deps_state s ~deps lval in - deps, r); - Db.Value.expr_to_kernel_function := expr_to_kernel_function; - Db.Value.expr_to_kernel_function_state := expr_to_kernel_function_state; - Db.Value.lval_to_loc := lval_to_loc_kinstr; - Db.Value.lval_to_loc_state := lval_to_loc ~with_alarms:warn_none_mode ; - Db.Value.lval_to_zone_state := lval_to_zone_state; - Db.Value.lval_to_zone := lval_to_zone; - Db.Value.lval_to_offsetmap := lval_to_offsetmap; - Db.Value.lval_to_offsetmap_state := lval_to_offsetmap_state; - Db.Value.assigns_to_zone_inputs_state := assigns_to_zone_inputs_state; - Db.Value.eval_expr := eval_expr; - Db.Value.eval_lval := - (fun ~with_alarms deps state lval -> - let _, deps, r = eval_lval ~conflate_bottom:true ~with_alarms deps state lval in - deps, r) - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/kinstr.mli frama-c-20111001+nitrogen+dfsg/src/value/kinstr.mli --- frama-c-20110201+carbon+dfsg/src/value/kinstr.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/kinstr.mli 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2011 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) -(* alternatives) *) -(* *) -(* you can redistribute it and/or modify it under the terms of the GNU *) -(* Lesser General Public License as published by the Free Software *) -(* Foundation, version 2.1. *) -(* *) -(* It 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 Lesser General Public License for more details. *) -(* *) -(* See the GNU Lesser General Public License version 2.1 *) -(* for more details (enclosed in the file licenses/LGPLv2.1). *) -(* *) -(**************************************************************************) - -(** No function is directly exported. *) - -(* -Local Variables: -compile-command: "make -C ../.." -End: -*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/library_functions.ml frama-c-20111001+nitrogen+dfsg/src/value/library_functions.ml --- frama-c-20110201+carbon+dfsg/src/value/library_functions.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/library_functions.ml 2011-10-10 08:38:26.000000000 +0000 @@ -24,40 +24,136 @@ open Cil open Locations open Abstract_interp +open Bit_utils module Retres = - Cil_state_builder.Varinfo_hashtbl + Kernel_function.Make_Table (Cil_datatype.Varinfo) - (struct - let name = "retres_variable" - let size = 9 - let dependencies = [Ast.self] - let kind = `Internal - end) + (struct + let name = "retres_variable" + let size = 9 + let dependencies = [Ast.self] + let kind = `Internal + end) let () = State_dependency_graph.Static.add_dependencies ~from:Retres.self [ Db.Value.self ] -let get f_vi = - try - Retres.find f_vi - with Not_found -> - let typ = Cil.getReturnType f_vi.vtype in - let rv = makeVarinfo false false "__retres" typ in - Retres.add f_vi rv; - rv +let get = Retres.memo + (fun kf -> + let vi = Kernel_function.get_vi kf in + let typ = Cil.getReturnType vi.vtype in + makeVarinfo false false "__retres" typ) -let add_retres_to_state f_vi offsetmap state = - let retres_vi = get f_vi in +let add_retres_to_state ~with_alarms kf offsetmap state = + let retres_vi = get kf in let retres_base = Base.create_varinfo retres_vi in let loc = Location_Bits.inject retres_base Ival.zero in let size = - try - Int.of_int (bitsSizeOf retres_vi.vtype) + try Int.of_int (bitsSizeOf retres_vi.vtype) with SizeOfError _ -> - Value_parameters.abort "library function return type size unknown. Please report" + Value_parameters.abort "library function return type size unknown. \ + Please report" in - Some retres_vi, - Relations_type.Model.paste_offsetmap offsetmap loc Int.zero size state + let state = Cvalue.Model.paste_offsetmap + with_alarms offsetmap loc Int.zero size true state + in + retres_vi, state + + +(** Associates [kernel_function] to a fresh base for the address returned by + the [kernel_function]. *) +module Returned_Val = + Kernel_function.Make_Table + (Base) + (struct + let dependencies = [Ast.self] + let size = 7 + let name = "Leaf_Table" + let kind = `Internal + end) + + +let returned_value kf return_type state = + (* Process return of function *) + let return_type = unrollType return_type in + match return_type with + | TComp _ when is_fully_arithmetic return_type -> + Cvalue.V.top_int, state + | TPtr(typ,_) | (TComp _ as typ) -> begin + let new_base = + Returned_Val.memo + (fun kf -> + (* Value_parameters.warning + "Undefined function returning a pointer: %a" + Kernel_function.pretty kf; *) + let new_varinfo = + makeGlobalVar + ~logic:true + (Cabs2cil.fresh_global + ("alloced_return_" ^ Kernel_function.get_name kf)) + typ + in + let new_offsetmap = + Cvalue.V_Offsetmap.sized_zero (memory_size ()) + in + Cvalue.Default_offsetmap.create_initialized_var + new_varinfo + (Base.Known (Int.zero, max_bit_address ())) + new_offsetmap) + kf + in + let initial_value = + if isIntegralType typ + then Cvalue.V.top_int + else if isFloatingType typ + then Cvalue.V.top_float + else + Cvalue.V.inject_top_origin + (Origin.Leaf (LocationSetLattice.currentloc_singleton())) + (Cvalue.V.Top_Param.O.singleton new_base) + (*top_leaf_origin ()*) + in + let modu = try + if isVoidType typ then Int.one else Int_Base.project (osizeof typ) + with Int_Base.Error_Top -> + assert (Cvalue.V.is_isotropic initial_value); + Int.one + in + let returned_loc = + try + Location_Bytes.inject + new_base + (Ival.filter_ge_int (Some Int.zero) + (Ival.create_all_values + ~signed:true + ~modu + ~size:(sizeofpointer ()))) + with Int_Base.Error_Top -> + Location_Bytes.inject + new_base + Ival.top + in + let state = + Cvalue.Model.create_initial + ~base:new_base + ~v:initial_value ~modu:(Int.mul Int.eight modu) ~state + in + returned_loc, state + end + | TInt _ | TEnum _ -> Cvalue.V.top_int, state + | TFloat _ -> Cvalue.V.top_float, state + | TBuiltin_va_list _ -> + Cvalue.V.top_leaf_origin() + (* Only some builtins may return this type *), + state + | TVoid _ -> Cvalue.V.top (* this value will never be used *), state + | TFun _ | TNamed _ | TArray _ -> assert false + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/library_functions.mli frama-c-20111001+nitrogen+dfsg/src/value/library_functions.mli --- frama-c-20110201+carbon+dfsg/src/value/library_functions.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/library_functions.mli 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +val add_retres_to_state: + with_alarms:CilE.warn_mode -> + kernel_function -> + Cvalue.V_Offsetmap.t -> + Cvalue.Model.t -> + varinfo * Cvalue.Model.t + +val returned_value: + kernel_function -> + Cil_types.typ -> + Cvalue.Model.t -> + Cvalue.V.t * Cvalue.Model.t + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/locals_scoping.ml frama-c-20111001+nitrogen+dfsg/src/value/locals_scoping.ml --- frama-c-20110201+carbon+dfsg/src/value/locals_scoping.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/locals_scoping.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,74 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Value analysis of statements and functions bodies *) + +open Cil_types +open Cil +open Cil_datatype +open Locations +open Abstract_interp +open Bit_utils +open Cvalue +open Ast_printer +open Value_util +open Eval_exprs +open Eval_logic + +let remember_bases_with_locals bases_containing_locals left_loc evaled_exp = + if Cvalue.V.contains_addresses_of_any_locals evaled_exp then + let clobbered_set = Location_Bits.get_bases left_loc.loc in + bases_containing_locals := + Location_Bits.Top_Param.join clobbered_set !bases_containing_locals + +let warn_locals_escape is_block fundec k locals = + let pretty_base = Base.pretty in + let pretty_block fmt = Pretty_utils.pp_cond is_block fmt "a block of " in + let sv = fundec.svar in + match locals with + Location_Bytes.Top_Param.Top -> + warning_once_current + "locals escaping the scope of %t%a through %a" + pretty_block + !d_var sv + pretty_base k + | Location_Bytes.Top_Param.Set _ -> + warning_once_current + "locals %a escaping the scope of %t%a through %a" + Location_Bytes.Top_Param.pretty locals + pretty_block + !d_var sv + pretty_base k + +let warn_locals_escape_result fundec locals = + let d_var = !d_var in + let sv = fundec.svar in + match locals with + Location_Bytes.Top_Param.Top -> + warning_once_current + "locals escaping the scope of %a through \\result" + d_var sv + | Location_Bytes.Top_Param.Set _ -> + warning_once_current + "locals %a escaping the scope of %a through \\result" + Location_Bytes.Top_Param.pretty locals + d_var sv diff -Nru frama-c-20110201+carbon+dfsg/src/value/mark_noresults.ml frama-c-20111001+nitrogen+dfsg/src/value/mark_noresults.ml --- frama-c-20110201+carbon+dfsg/src/value/mark_noresults.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/mark_noresults.ml 2011-10-10 08:38:26.000000000 +0000 @@ -26,26 +26,29 @@ inherit Cil.nopCilVisitor as super method vstmt s = - Db.Value.update_table (Kstmt s) Relations_type.Model.top; + Db.Value.update_table s Cvalue.Model.top; Cil.DoChildren end let should_memorize_function name = - not (Value_parameters.NoResultsAll.get() - || (Datatype.String.Set.mem - name.svar.vname (Value_parameters.NoResultsFunctions.get ()))) - + not (Value_parameters.NoResultsAll.get() || + (Value_parameters.ObviouslyTerminatesAll.get()) || + let name = name.svar.vname in + let mem = Datatype.String.Set.mem in + mem name (Value_parameters.NoResultsFunctions.get ()) + || mem name (Value_parameters.ObviouslyTerminatesFunctions.get ())) let run () = - let names = Value_parameters.NoResultsFunctions.get () in - if Value_parameters.NoResultsAll.get() || - not (Datatype.String.Set.is_empty names) - then - let visitor = new mark_visitor in - Globals.Functions.iter_on_fundecs + let visitor = new mark_visitor in + Globals.Functions.iter_on_fundecs (fun afundec -> if not (should_memorize_function afundec) - then - ignore (Cil.visitCilFunction (visitor:>Cil.cilVisitor) afundec);) + then + ignore (Cil.visitCilFunction (visitor:>Cil.cilVisitor) afundec)) +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/non_linear.ml frama-c-20111001+nitrogen+dfsg/src/value/non_linear.ml --- frama-c-20110201+carbon+dfsg/src/value/non_linear.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/non_linear.ml 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,152 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil +open Locations +module Ki = Cil_datatype.Kinstr + + +module Location_list = Datatype.List (Locations.Location) + +module Non_linear_assignments = + Cil_state_builder.Varinfo_hashtbl + (Cil_datatype.Kinstr.Hashtbl.Make(Location_list)) + (struct + let name = "Non linear assignments" + let size = 37 + let dependencies = [ Ast.self ] + let kind = `Internal + end) + +module Loc_hashtbl = Hashtbl.Make (Location_Bits) + +class do_non_linear_assignments = object(self) + inherit + Visitor.generic_frama_c_visitor (Project.current ()) (Cil.inplace_visit ()) + as super + val mutable current_locs = None + val mutable assigns_table = + (Ki.Hashtbl.create 17 : Location_list.t Ki.Hashtbl.t) + + method result = assigns_table + + method vstmt s = + current_locs <- None; + match s.skind with + | UnspecifiedSequence seq -> + List.iter + (fun (stmt,_,_,_,_) -> + ignore (visitCilStmt (self:>cilVisitor) stmt)) + seq; + SkipChildren (* do not visit the additional lvals *) + | _ -> super#vstmt s + + method vlval lv = + match current_locs with + None -> SkipChildren + | Some current_locs -> + begin match lv with + Mem _e, _ -> DoChildren + | Var v, NoOffset -> + let loc = Locations.loc_of_varinfo v in + ignore (Loc_hashtbl.find current_locs loc.loc); + SkipChildren + | Var _v, (Index _ | Field _) -> DoChildren + end + +(* + + try + + let deps,loc = + !Value.lval_to_loc_with_deps + ~with_alarms:CilE.warn_none_mode + ~deps:Zone.bottom + current_stmt lv + in + let bits_loc = valid_enumerate_bits loc in + self#join deps; + self#join bits_loc; + SkipChildren +*) + + method vcode_annot _ = SkipChildren + + method visit_addr lv = + begin match lv with + Var v, offset -> + let offset' = visitCilOffset (self :> cilVisitor) offset in + let v' = Cil.get_varinfo self#behavior v in + if offset' == offset && v == v' + then SkipChildren + else ChangeTo (Var v', offset') + | Mem e, offset -> + let e' = visitCilExpr (self :> cilVisitor) e in + let offset' = visitCilOffset (self :> cilVisitor) offset in + if offset' == offset && e == e' + then SkipChildren + else ChangeTo (Mem e', offset') + end; + + method vinst i = + match i with + | Set (lv,exp,_) -> + current_locs <- Some (Loc_hashtbl.create 7); + begin match lv with + Var _, offset -> + ignore (self#voffs offset); + | Mem e, offset -> + ignore (self#vexpr e); + ignore (self#voffs offset); + end; + ignore (self#vexpr exp); + (* TODO: do some stuff with self#current_stmt *) + SkipChildren + | _ -> SkipChildren + + method vexpr exp = + match exp.enode with + | AddrOf _lv | StartOf _lv -> + SkipChildren (* TODO: do better stuff *) + | _ -> DoChildren + +end + +let compute_non_linear_assignments f = + let vis = new do_non_linear_assignments in + ignore (Visitor.visitFramacFunction (vis:>Visitor.frama_c_visitor) f); + vis#result + +let find fundec = + let var = fundec.svar in + try Non_linear_assignments.find var + with Not_found -> + let nl = compute_non_linear_assignments fundec in + Non_linear_assignments.replace var nl; + nl + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/non_linear.mli frama-c-20111001+nitrogen+dfsg/src/value/non_linear.mli --- frama-c-20110201+carbon+dfsg/src/value/non_linear.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/non_linear.mli 2011-10-10 08:38:26.000000000 +0000 @@ -0,0 +1,30 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val find: + Cil_types.fundec -> Locations.location list Cil_datatype.Kinstr.Hashtbl.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/value/register_gui.ml frama-c-20111001+nitrogen+dfsg/src/value/register_gui.ml --- frama-c-20110201+carbon+dfsg/src/value/register_gui.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/register_gui.ml 2011-10-10 08:38:26.000000000 +0000 @@ -25,7 +25,6 @@ open CilE open Format open Db -open Db_types open Pretty_source open Gtk_helper @@ -34,15 +33,73 @@ let vi = Kernel_function.get_vi kf in tree_view#select_global vi -let pretty_offsetmap lv fmt offsetmap = + +type lval_or_absolute = LVal of lval | AbsoluteMem + +let pretty_lval_or_absolute fmt = function + | LVal lv -> !Ast_printer.d_lval fmt lv + | AbsoluteMem -> Format.pp_print_string fmt "[MEMORY]" + +let pretty_offsetmap lva fmt offsetmap = begin match offsetmap with | None -> Format.fprintf fmt "<BOTTOM>" | Some off -> + let typ = match lva with + | LVal lv -> Some (typeOfLval lv) + | AbsoluteMem -> None + in Format.fprintf fmt "%a%a" - !Ast_printer.d_lval lv - (Cvalue_type.V_Offsetmap.pretty_typ - (Some (typeOfLval lv))) - off + pretty_lval_or_absolute lva + (Cvalue.V_Offsetmap.pretty_typ typ) off + end + +let lval_or_absolute_to_offsetmap state lva = + match lva with + | LVal lv -> !Db.Value.lval_to_offsetmap_state state lv + | AbsoluteMem -> + try Some (Cvalue.Model.find_base Base.null state) + with Not_found -> None + +let pretty_lval_or_absolute (annot : GText.buffer) ki lva = + begin (* State before ki *) + annot#insert "Before statement:\n"; + let state = Value.get_state ki in + try + let offsetmap = lval_or_absolute_to_offsetmap state lva in + annot#insert (Pretty_utils.sfprintf "%a@\n" + (pretty_offsetmap lva) offsetmap); + with Lmap.Cannot_copy -> + match lva with + | LVal lv -> + let value = !Db.Value.access ki lv in + let inset_utf8 = Unicode.inset_string () in + annot#insert (Pretty_utils.sfprintf "%a %s %a@\n" + !Ast_printer.d_lval lv + inset_utf8 + Db.Value.pretty value) + | AbsoluteMem -> annot#insert "<>" + end; + begin (* State after ki *) + if Value_parameters.ResultsAfter.get () then + match ki with + | Kstmt ({ skind = Instr _} as stmt) -> + let state = + try Value.AfterTable.find stmt + with Not_found -> Cvalue.Model.bottom + in + let offsetmap_after = lval_or_absolute_to_offsetmap state lva in + annot#insert (Pretty_utils.sfprintf "After statement:\n%a\n" + (pretty_offsetmap lva) offsetmap_after); + | Kglobal | Kstmt _ -> () + else + try + (match lva with + | LVal lv -> + let offsetmap_after = !Db.Value.lval_to_offsetmap_after ki lv in + annot#insert (Pretty_utils.sfprintf "At next statement:@\n%a@\n" + (pretty_offsetmap lva) offsetmap_after) + | AbsoluteMem -> ()) + with Not_found -> () end let gui_annot_action (main_ui:Design.main_window_extension_points) txt = @@ -54,254 +111,201 @@ if not (Db.Value.is_computed ()) then main_ui#launcher () - -module After_States = - State_builder.Hashtbl(Cil_datatype.Stmt.Hashtbl)(Relations_type.Model) - (struct - let name = "Register_gui.After_states" - let dependencies = [Db.Value.self] - let kind = `Correctness - let size = 257 - end) - -(* We unconditionnally monitor the states after a statement to - correctly display the "After statement" information of the gui *) -let () = - Db.Value.Record_Value_After_Callbacks.extend - (fun (_stack, h) -> - Cil_datatype.Stmt.Hashtbl.iter - (fun stmt state -> - try - let prev = After_States.find stmt in - After_States.replace stmt (Relations_type.Model.join prev state) - with Not_found -> - After_States.add stmt state - ) h - ) - - +let cleant_outputs kf s = + let outs = Db.Outputs.kinstr (Kstmt s) in + let filter = Locations.Zone.filter_base + (Db.accept_base ~with_formals:true ~with_locals:true kf) in + Extlib.opt_map filter outs let rec to_do_on_select (popup_factory:GMenu.menu GMenu.factory) (main_ui:Design.main_window_extension_points) button_nb selected = - let inset_utf8 = Unicode.inset_string () in - let annot = main_ui#annot_window#buffer in if button_nb = 1 then begin if Db.Value.is_computed () then begin - match selected with - | PStmt (_kf,ki) -> begin - (* Find kinstr and kf *) - (* Is it an accessible statement ? *) - if Db.Value.is_accessible (Kstmt ki) then begin - (* Out for this statement *) - let outs = Db.Outputs.kinstr (Kstmt ki) in - let n = ( match outs with - | Some outs -> - Pretty_utils.sfprintf - "Modifies @[<hov>%a@]@\n" Db.Outputs.pretty outs - | _ -> "\n"); - in annot#insert n - end else annot#insert "This code is dead\n"; - end - | PLval (_kf, ki,lv) -> - if not (isFunctionType (typeOfLval lv)) - then begin - (try - let offsetmap = - !Db.Value.lval_to_offsetmap ~with_alarms:CilE.warn_none_mode ki lv - in - annot#insert (Pretty_utils.sfprintf - "Before statement:@\n%a@\n" - (pretty_offsetmap lv ) offsetmap); - with Lmap.Cannot_copy -> - let value = !Db.Value.access ki lv in - annot#insert (Pretty_utils.sfprintf "Before statement:@\n%a %s %a@\n" - !Ast_printer.d_lval lv inset_utf8 Db.Value.pretty value)); - ((* Ugly hack: we use this condition to determine - if the after states have been computed *) - if After_States.length () > 0 then - match ki with - | Kstmt ({ skind = Instr _} as stmt) -> - let state = - try After_States.find stmt - with Not_found -> Relations_type.Model.bottom - in - let offsetmap_after = - !Db.Value.lval_to_offsetmap_state state lv in - annot#insert (Pretty_utils.sfprintf - "After statement:\n%a\n" - (pretty_offsetmap lv) - offsetmap_after); - | Kglobal | Kstmt _ -> () - else - try - let offsetmap_after = - !Db.Value.lval_to_offsetmap_after ki lv in - annot#insert "At next statement:\n"; - annot#insert (Pretty_utils.sfprintf "%a\n" - (pretty_offsetmap lv) offsetmap_after); - with Not_found -> () - ); - end - | PTermLval _ -> () (* JS: TODO (?) *) - | PVDecl (_kf,_vi) -> () - | PGlobal _ | PIP _ -> () - end + match selected with + | PStmt (kf,stmt) -> begin + (* Is it an accessible statement ? *) + if Db.Value.is_reachable_stmt stmt then + (* Out for this statement *) + let outs = cleant_outputs kf stmt in + let n = ( match outs with + | Some outs -> + Pretty_utils.sfprintf + "Modifies @[<hov>%a@]@\n" Db.Outputs.pretty outs + | _ -> "\n"); + in annot#insert n + else annot#insert "This code is dead\n"; + end + | PLval (_kf, ki,lv) -> + if not (isFunctionType (typeOfLval lv)) then + pretty_lval_or_absolute annot ki (LVal lv) + | PTermLval _ -> () (* JS: TODO (?) *) + | PVDecl (_kf,_vi) -> () + | PGlobal _ | PIP _ -> () + end end else if button_nb = 3 then begin match selected with | PVDecl (_,vi) -> - begin - try - let kfun = Globals.Functions.get vi in - if Db.Value.is_computed () - then - let callers = !Value.callers kfun in - (* popup a menu to jump to the definitions of the callers *) - let do_menu l = - try - List.iter - (fun (v,call_sites) -> - let v = Kernel_function.get_vi v in - let nb_sites = List.length call_sites in - let label = "Go to caller " ^ - (Pretty_utils.escape_underscores - (Pretty_utils.sfprintf "%a" - Ast_info.pretty_vname v)) - in - let label = - if nb_sites > 1 - then - label ^ " (" ^ (string_of_int nb_sites) ^" call sites)" - else label - in - ignore - (popup_factory#add_item - label - ~callback: - (fun () -> main_ui#file_tree#select_global v))) - l; - with Not_found -> () - in - do_menu callers - else - ignore - (popup_factory#add_item - "Callers ..." - ~callback: - (fun () -> (gui_compute_values main_ui))) + begin + try + let kfun = Globals.Functions.get vi in + if Db.Value.is_computed () + then + let callers = !Value.callers kfun in + (* popup a menu to jump to the definitions of the callers *) + let do_menu l = + try + List.iter + (fun (kf,call_sites) -> + let nb_sites = List.length call_sites in + let label = "Go to caller " ^ + (Pretty_utils.escape_underscores + (Pretty_utils.sfprintf "%a" + Kernel_function.pretty kf)) + in + let label = + if nb_sites > 1 then + label ^ " (" ^ (string_of_int nb_sites) + ^ " call sites)" + else label + in + ignore + (popup_factory#add_item + label + ~callback: + (fun () -> main_ui#select_or_display_global + (Kernel_function.get_global kf)))) + l; + with Not_found -> () + in + do_menu callers + else + ignore + (popup_factory#add_item + "Callers ..." + ~callback: + (fun () -> (gui_compute_values main_ui))) - with Not_found -> - () + with Not_found -> + () end - | PStmt (kf,ki) -> - if Db.Value.is_computed () - then begin + | PStmt (kf,stmt) -> + if Db.Value.is_computed () + then begin let eval_expr () = - let txt = - GToolbox.input_string + let txt = + GToolbox.input_string ~title:"Evaluate" " Enter an ACSL expression to evaluate " - (* the spaces at beginning and end should not be necessary - but are the quickest fix for an aesthetic GTK problem *) - in - match txt with - | None -> () - | Some txt -> try - let exp = - !Db.Properties.Interp.term_to_exp ~result:None - (!Db.Properties.Interp.expr kf ki txt) - in + (* the spaces at beginning and end should not be necessary + but are the quickest fix for an aesthetic GTK problem *) + in + match txt with + | None -> () + | Some txt -> + try + if txt = "[MEM]" then + pretty_lval_or_absolute annot (Kstmt stmt) AbsoluteMem + else + let exp = + !Db.Properties.Interp.term_to_exp ~result:None + (!Db.Properties.Interp.expr kf stmt txt) + in begin match exp.enode with | Lval lv | StartOf lv -> - to_do_on_select popup_factory main_ui 1 (PLval((Some kf),Kstmt ki,lv)) + pretty_lval_or_absolute annot (Kstmt stmt) (LVal lv) | _ -> - let loc = - !Db.Value.access_expr - (Kstmt ki) - exp - in - let txt = - Format.sprintf + let loc = !Db.Value.access_expr (Kstmt stmt) exp in + let txt = + Format.sprintf "Before the selected statement, all the values taken by the expression %s are contained in %s@\n" - (Pretty_utils.sfprintf "%a" !Ast_printer.d_exp exp) - (Pretty_utils.sfprintf "%a" Cvalue_type.V.pretty loc) - in - annot#insert txt + (Pretty_utils.sfprintf "%a" !Ast_printer.d_exp exp) + (Pretty_utils.sfprintf "%a" Cvalue.V.pretty loc) + in + annot#insert txt end - with e -> - main_ui#error "Invalid expression: %s" (Cmdline.protect e) + with + | Logic_interp.Error (_, mess) -> + main_ui#error "Invalid expression: %s" mess + | Parsing.Parse_error -> + main_ui#error "Invalid expression: %s" "Parse error" + | e -> + main_ui#error "Invalid expression: %s" (Cmdline.protect e) in begin - try - ignore - (popup_factory#add_item "_Evaluate expression" - ~callback:eval_expr) - with Not_found -> () + try + ignore + (popup_factory#add_item "_Evaluate expression" + ~callback:eval_expr) + with Not_found -> () end - end - else - ignore - (popup_factory#add_item - "_Evaluate expression ..." - ~callback: - (fun () -> (gui_compute_values main_ui))) + end + else + ignore + (popup_factory#add_item + "_Evaluate expression ..." + ~callback: + (fun () -> (gui_compute_values main_ui))) | PLval (_kf, ki, lv) -> + if Db.Value.is_computed () then let ty = typeOfLval lv in (* Do special actions for functions *) begin - (* popup a menu to jump the definitions of the given varinfos *) - let do_menu l = - match l with - | [] -> () - | _ -> - try - List.iter - (fun v -> - ignore - (popup_factory#add_item - ("Go to definition of " ^ - (Pretty_utils.escape_underscores - (Pretty_utils.sfprintf "%a" - Ast_info.pretty_vname v)) - ^ " (indirect)") - ~callback: - (fun () -> - main_ui#file_tree#select_global v))) - l ; - with Not_found -> () - in - (match lv with - | Var _,NoOffset when isFunctionType ty -> + (* popup a menu to jump the definitions of the given varinfos *) + let do_menu l = + match l with + | [] -> () + | _ -> + List.iter + (fun v -> + try + let kf = Globals.Functions.get v in + let g = Kernel_function.get_global kf in + ignore + (popup_factory#add_item + ("Go to definition of " ^ + (Pretty_utils.escape_underscores + (Pretty_utils.sfprintf "%a" + Cil_datatype.Varinfo.pretty_vname v)) + ^ " (indirect)") + ~callback: + (fun () -> + main_ui#select_or_display_global g)) + with Not_found -> ()) + l; + in + (match lv with + | Var _,NoOffset when isFunctionType ty -> (* simple literal calls are done by [Design]. *) () - | Mem ({ enode = Lval lv}), NoOffset -> + | Mem ({ enode = Lval lv}), NoOffset -> if isFunctionType ty then (* Function pointers *) - begin try - (* get the list of exact bases in the values *) - let value,_exact = - Cvalue_type.V.find_exact_base_without_offset + begin try + (* get the list of exact bases in the values *) + let value,_exact = + Cvalue.V.find_exact_base_without_offset (!Db.Value.access ki lv) - in - let functions = - List.fold_left + in + let functions = + List.fold_left (fun acc -> - (function - | Base.Var (vi,_) -> vi::acc - | _ -> acc)) + (function + | Base.Var (vi,_) -> vi::acc + | _ -> acc)) [] value - in - do_menu functions + in + do_menu functions - with Not_found -> () + with Not_found -> () end | _ -> () ) @@ -322,53 +326,78 @@ let kind = `Internal end) -let used_var var = - try - UsedVarState.find var - with Not_found -> - let return v = UsedVarState.add var v; v in - try - let f = fst (Globals.entry_point ()) in - let inputs = !Db.Inputs.get_external f - and outputs = !Db.Outputs.get_external f in - let b = Base.create_varinfo var in - return (Locations.Zone.mem_base b inputs || - Locations.Zone.mem_base b outputs) - with e -> - Gui_parameters.error ~once:true - "Exception during usability analysis of var %s: %s" - var.vname (Printexc.to_string e); - return true (* No really sane value, so in doubt... *) - - -let reset (main_ui:Design.main_window_extension_points) = - Globals.Functions.iter - (fun kf -> +let no_memoization_enabled () = + Value_parameters.NoResultsAll.get() || + Value_parameters.ObviouslyTerminatesAll.get() || + not (Value_parameters.NoResultsFunctions.is_empty ()) || + not (Value_parameters.ObviouslyTerminatesFunctions.is_empty ()) + + +let used_var = UsedVarState.memo + (fun var -> + no_memoization_enabled () || + try + let f = fst (Globals.entry_point ()) in + let inputs = !Db.Inputs.get_external f in + let outputs = !Db.Outputs.get_external f in + let b = Base.create_varinfo var in + Locations.Zone.mem_base b inputs || Locations.Zone.mem_base b outputs + with e -> + Gui_parameters.error ~once:true + "Exception during usability analysis of var %s: %s" + var.vname (Printexc.to_string e); + true (* No really sane value, so in doubt... *) + ) + + +(* Set when the callback is installed *) +let hide_unused = ref (fun () -> false) + +let sync_filetree (filetree:Filetree.t) = + if not (!hide_unused ()) then + (Globals.Functions.iter + (fun kf -> try let vi = Kernel_function.get_vi kf in - main_ui#file_tree#set_global_attribute + filetree#set_global_attribute ~strikethrough:(Value.is_computed () && not (!Value.is_called kf)) vi with Not_found -> ()); - Globals.Vars.iter - (fun vi _ -> - if vi.vlogic = false then - main_ui#file_tree#set_global_attribute - ~strikethrough:(Value.is_computed () && not (used_var vi)) - vi - ); - List.iter - (fun file -> - (* the display name removes the path *) - let name, _globals = Globals.FileIndex.find file in - let globals_state = main_ui#file_tree#get_file_globals name in - main_ui#file_tree#set_file_attribute - ~strikethrough:(Value.is_computed () && - List.for_all snd globals_state) - name + Globals.Vars.iter + (fun vi _ -> + if vi.vlogic = false then + filetree#set_global_attribute + ~strikethrough:(Value.is_computed () && not (used_var vi)) + vi + ); + if not (filetree#flat_mode) then + List.iter + (fun file -> + (* the display name removes the path *) + let name, _globals = Globals.FileIndex.find file in + let globals_state = filetree#get_file_globals name in + filetree#set_file_attribute + ~strikethrough:(Value.is_computed () && + List.for_all snd globals_state) + name + ) + (Globals.FileIndex.get_files ()) ) - (Globals.FileIndex.get_files ()) + else + (* Some lines may have disappeared. We should reset the entire filetree, + but the method reset of design.ml already does this. *) + () + + +let hide_unused_function_or_var vi = + !hide_unused () && Value.is_computed () && + (try + let kf = Globals.Functions.get vi in + not (!Value.is_called kf) + with Not_found -> + not (used_var vi) + ) module DegeneratedHighlighted = State_builder.Option_ref @@ -380,9 +409,19 @@ end) let main (main_ui:Design.main_window_extension_points) = - - (* reset attributes for the list of source files *) - reset main_ui; + (* Hide unused functions and variables. Must be registered only once *) + hide_unused := + main_ui#file_tree#add_global_filter + ~text:"Hide unused according to\nvalue analysis" + ~key:"value_hide_unused" hide_unused_function_or_var; + + main_ui#file_tree#register_reset_extension sync_filetree; + + (* Very first display, we need to do a few things by hand *) + if !hide_unused () then + main_ui#file_tree#reset () + else + sync_filetree main_ui#file_tree; let value_selector menu (main_ui:Design.main_window_extension_points) ~button localizable = @@ -423,7 +462,8 @@ in main_ui#register_source_highlighter highlighter -let degeneration_occurred ki lv = +let degeneration_occurred _ki _lv = +(* Db.Value.mark_as_computed (); ignore (GtkMain.Main.init ()); let app = new Design.main_window () in @@ -432,13 +472,13 @@ (Glib.Idle.add ~prio:1000 (fun () -> let localizable = - (match ki,lv with + (match ki,lv with | Kstmt st, Some lv -> - let kf = snd (Kernel_function.find_from_sid st.sid) in + let kf = Kernel_function.find_englobing_kf st in select_kf app#file_tree kf; PLval(Some kf,ki,lv) | Kstmt st, None -> - let kf = snd (Kernel_function.find_from_sid st.sid) in + let kf = Kernel_function.find_englobing_kf st in select_kf app#file_tree kf; PStmt(kf,st) | Kglobal, Some lv -> @@ -449,23 +489,25 @@ (new GMenu.factory (GMenu.menu ())) app 1 - localizable; + localizable; DegeneratedHighlighted.set localizable; app#rehighlight (); app#scroll localizable (*match ki with - | Kstmt st -> + | Kstmt st -> let l = (Cil_datatype.Stmt.loc st.skind) in select_locs ~file:l.file ~line:l.line app#source_viewer - | _ -> ()*); + | _ -> ()*); false(*do it once only*))); GMain.Main.main (); +*) ignore (raise Db.Value.Aborted) let () = Design.register_extension main; - Design.register_reset_extension reset; - Db.Value.degeneration_occurred := degeneration_occurred + Db.Value.degeneration_occurred := degeneration_occurred; +;; + (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/value/register_gui.mli frama-c-20111001+nitrogen+dfsg/src/value/register_gui.mli --- frama-c-20110201+carbon+dfsg/src/value/register_gui.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/register_gui.mli 2011-10-10 08:38:26.000000000 +0000 @@ -28,4 +28,3 @@ compile-command: "make -C ../.." End: *) - diff -Nru frama-c-20110201+carbon+dfsg/src/value/register.ml frama-c-20111001+nitrogen+dfsg/src/value/register.ml --- frama-c-20110201+carbon+dfsg/src/value/register.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/register.ml 2011-10-10 08:38:26.000000000 +0000 @@ -20,68 +20,184 @@ (* *) (**************************************************************************) -(* $id: cvalue.ml,v 1.36 2006/03/17 13:54:56 uid527 Exp $ *) -open Abstract_interp +open Cil_types +open Locations +open Eval_exprs -(* -(** Initialize the default bound for absolute address to max addressable bit *) -let () = Parameters.max_valid_absolute_address := Utils.memory_size () -*) - -let main () = +(** Main function of the value plugin for the kernel *) - (* Memoization of context free functions *) - let mem_functions = Value_parameters.MemFunctions.get () in - if Value_parameters.MemExecAll.get () - || not (Datatype.String.Set.is_empty mem_functions) - then begin - Value_parameters.feedback "====== MEMOIZING FUNCTIONS ======"; - Ast.compute (); - Globals.Functions.iter +let display_results () = + if Db.Value.is_computed () && Value_parameters.verbose_atleast 1 then begin + Value_parameters.result "====== VALUES COMPUTED ======"; + (* Val display and Inout compute/display *) + !Db.Semantic_Callgraph.topologically_iter_on_functions (fun kf -> - let name = Kernel_function.get_name kf in - if Kernel_function.is_definition kf && - (Value_parameters.MemExecAll.get () - || Datatype.String.Set.mem name mem_functions) - then begin - Value_parameters.feedback "== function %a" - Kernel_function.pretty_name kf; - try - !Db.Value.memoize kf - with Db.Value.Aborted -> - Value_parameters.fatal "Cannot memoize %a: Analysis degenerated@." - Kernel_function.pretty_name kf - end) - end; + if Kernel_function.is_definition kf then + begin + Value_parameters.result "%a" Db.Value.display kf ; + end) + end + +let () = Value_parameters.ForceValues.set_output_dependencies [Db.Value.self] +let main () = (* Value computations *) if Value_parameters.ForceValues.get () then begin !Db.Value.compute (); - Value_parameters.result "====== VALUES COMPUTED ======"; - end; + Value_parameters.ForceValues.output display_results; + end + +let () = Db.Main.extend main + - (* Val display and Inout compute/display *) +(** Functions to register in Db.Value *) - let display_val = - Value_parameters.verbose_atleast 1 && Value_parameters.ForceValues.get () +let lval_to_loc_with_deps_state ~with_alarms state ~deps lv = + let _state, deps, r = + lval_to_loc_with_deps + ~with_alarms + ~deps + ~reduce_valid_index:(Kernel.SafeArrays.get ()) + state + lv in + Zone.out_some_or_bottom deps, r - (* Iteration *) +let lval_to_loc_with_deps kinstr ~with_alarms ~deps lv = + CilE.start_stmt kinstr; + let state = Db.Value.noassert_get_state kinstr in + let result = + lval_to_loc_with_deps_state ~with_alarms state ~deps lv in + CilE.end_stmt (); + result + +let lval_to_loc_kinstr kinstr ~with_alarms lv = + CilE.start_stmt kinstr; + let state = Db.Value.noassert_get_state kinstr in + (* Format.printf "@\ngot state when lval_to_loc:%a@." + Cvalue.Model.pretty state; *) + let r = lval_to_loc ~with_alarms state lv in + CilE.end_stmt (); + r + +let lval_to_zone kinstr ~with_alarms lv = + Locations.valid_enumerate_bits + ~for_writing:false + (lval_to_loc_kinstr ~with_alarms kinstr lv) + +let lval_to_zone_state state lv = + Locations.valid_enumerate_bits + ~for_writing:false + (lval_to_loc ~with_alarms:CilE.warn_none_mode state lv) + +let expr_to_kernel_function_state ~with_alarms state ~deps exp = + try + let r, deps = resolv_func_vinfo ~with_alarms deps state exp in + Zone.out_some_or_bottom deps, r + with Leaf -> Zone.out_some_or_bottom deps, Kernel_function.Hptset.empty + +let expr_to_kernel_function kinstr ~with_alarms ~deps exp = + CilE.start_stmt kinstr; + let state = Db.Value.noassert_get_state kinstr in + (* Format.printf "STATE IS %a@\n" Cvalue.Model.pretty state;*) + let r = + expr_to_kernel_function_state ~with_alarms state ~deps exp + in + CilE.end_stmt (); + r - if display_val then - begin - !Db.Semantic_Callgraph.topologically_iter_on_functions - (fun kf -> - if Kernel_function.is_definition kf then - begin - Value_parameters.result "%a" Db.Value.display kf ; - end) - end +let expr_to_kernel_function_state = + expr_to_kernel_function_state ~with_alarms:CilE.warn_none_mode + +exception Top_input + +let assigns_to_zone_inputs_state state assigns = + try + let treat_one_zone acc (_,ins) = + match ins with + FromAny -> raise Top_input + | From l -> + List.fold_left + (fun acc { it_content = term } -> + let loc_ins = + !Db.Properties.Interp.loc_to_loc ~result:None state term + in + Zone.join + acc + (Locations.valid_enumerate_bits ~for_writing:false loc_ins)) + acc + l + in + match assigns with + | WritesAny -> Zone.top + | Writes [] -> Zone.bottom + | Writes l -> List.fold_left treat_one_zone Zone.bottom l + with + | Top_input -> Zone.top + | Invalid_argument "not an lvalue" -> + Value_parameters.warning ~current:true ~once:true + "Failed to interpret assigns clause in inputs"; + Zone.top + +let lval_to_offsetmap kinstr lv ~with_alarms = + CilE.start_stmt kinstr; + let state = Db.Value.noassert_get_state kinstr in + let loc = Locations.valid_part ~for_writing:false + (lval_to_loc ~with_alarms state lv) + in + let offsetmap = + Cvalue.Model.copy_offsetmap ~with_alarms loc state + in + CilE.end_stmt (); + offsetmap + +let lval_to_offsetmap_state state lv = + let with_alarms = CilE.warn_none_mode in + let loc = + Locations.valid_part ~for_writing:false + (lval_to_loc ~with_alarms state lv) + in + Cvalue.Model.copy_offsetmap ~with_alarms loc state + + +(* If the function is a builtin, or if the user has requested it, use + \assigns and \from clauses, that give an approximation of the result *) +let use_spec_instead_of_definition kf = + not (Kernel_function.is_definition kf) || + (let name = Kernel_function.get_name kf in + Builtins.overridden_by_builtin name || + Datatype.String.Set.mem name (Value_parameters.UsePrototype.get ()) + ) + +let () = + Db.Value.use_spec_instead_of_definition := use_spec_instead_of_definition; + Db.Value.lval_to_loc_with_deps := lval_to_loc_with_deps; + Db.Value.lval_to_loc_with_deps_state := + lval_to_loc_with_deps_state ~with_alarms:CilE.warn_none_mode; + Db.Value.expr_to_kernel_function := expr_to_kernel_function; + Db.Value.expr_to_kernel_function_state := expr_to_kernel_function_state; + Db.Value.lval_to_loc := lval_to_loc_kinstr; + Db.Value.lval_to_loc_state := lval_to_loc ~with_alarms:CilE.warn_none_mode ; + Db.Value.lval_to_zone_state := lval_to_zone_state; + Db.Value.lval_to_zone := lval_to_zone; + Db.Value.lval_to_offsetmap := lval_to_offsetmap; + Db.Value.lval_to_offsetmap_state := lval_to_offsetmap_state; + Db.Value.assigns_to_zone_inputs_state := assigns_to_zone_inputs_state; + Db.Value.eval_expr := eval_expr; + Db.Value.eval_expr_with_state := + (fun ~with_alarms state expr -> + let (s,_,v) = eval_expr_with_deps_state ~with_alarms None state expr in + s,v); + Db.Value.eval_lval := + (fun ~with_alarms deps state lval -> + let _, deps, r = eval_lval ~conflate_bottom:true ~with_alarms deps state lval in + deps, r); + Db.Value.find_lv_plus := find_lv_plus; +;; -let () = Db.Main.extend main (* Local Variables: -compile-command: "LC_ALL=C make -C ../.. -j" +compile-command: "make -C ../.." End: *) diff -Nru frama-c-20110201+carbon+dfsg/src/value/separate.ml frama-c-20111001+nitrogen+dfsg/src/value/separate.ml --- frama-c-20110201+carbon+dfsg/src/value/separate.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/separate.ml 2011-10-10 08:38:26.000000000 +0000 @@ -28,8 +28,8 @@ then begin let sep_case = Value_parameters.SeparateStmtWord.get() in Value_parameters.feedback "Part of a case analysis: %d of 0..%d" - sep_case - sep_of; + sep_case + sep_of; assert (sep_of >= 1); assert (sep_of <= 1073741823); (* should be enough for anyone *) assert (sep_of land (succ sep_of) = 0); (* pred of power of two *) @@ -47,48 +47,46 @@ then thel else let sep = !mask in - if sep <> 0 && + if sep <> 0 && ( Value_parameters.SeparateStmtStart.is_empty() || - (Value_parameters.SeparateStmtStart.exists - (fun s -> stmt.Cil_types.sid = int_of_string s)) ) + (Value_parameters.SeparateStmtStart.exists + (fun s -> stmt.Cil_types.sid = int_of_string s)) ) then begin - mask := sep lsr 1; - let c = - (Value_parameters.SeparateStmtWord.get()) land sep <> 0 - in - Value_parameters.warning ~current:true - "Statement %d: only propagating for condition %B" - stmt.Cil_types.sid - c; - if c - then - th, Dataflow.GUnreachable - else - Dataflow.GUnreachable, el + mask := sep lsr 1; + let c = + (Value_parameters.SeparateStmtWord.get()) land sep <> 0 + in + Value_parameters.warning ~current:true + "Statement %d: only propagating for condition %B" + stmt.Cil_types.sid + c; + if c + then + th, Dataflow.GUnreachable + else + Dataflow.GUnreachable, el end else thel let epilogue () = let sep = !mask in let word1 = Value_parameters.SeparateStmtWord.get() in - let next = + let next = if sep <> 0 then begin - let unimportant = sep lor pred sep in - let important = lnot unimportant in - let c = word1 in - let mn = c land important in - let mx = c lor unimportant in - let next = succ mx in - Value_parameters.feedback "This analysis covers cases %d to %d" mn mx; - next + let unimportant = sep lor pred sep in + let important = lnot unimportant in + let c = word1 in + let mn = c land important in + let mx = c lor unimportant in + let next = succ mx in + Value_parameters.feedback "This analysis covers cases %d to %d" mn mx; + next end else succ word1 in if next <= Value_parameters.SeparateStmtOf.get() then - Value_parameters.feedback "Next case to cover in sequential order: %d" + Value_parameters.feedback "Next case to cover in sequential order: %d" next; - - diff -Nru frama-c-20110201+carbon+dfsg/src/value/value_parameters.ml frama-c-20111001+nitrogen+dfsg/src/value/value_parameters.ml --- frama-c-20110201+carbon+dfsg/src/value/value_parameters.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/value_parameters.ml 2011-10-10 08:38:26.000000000 +0000 @@ -20,6 +20,38 @@ (* *) (**************************************************************************) +(* Dependencies to kernel options *) +let kernel_parameters_correctness = [ + Kernel.MainFunction.parameter; + Kernel.LibEntry.parameter; + Kernel.AbsoluteValidRange.parameter; + Kernel.Overflow.parameter; + Kernel.SafeArrays.parameter; + Kernel.UnspecifiedAccess.parameter; +] + +let kernel_parameters_precision = [ + Kernel.PreciseUnions.parameter; + Kernel.ArrayPrecisionLevel.parameter; +] + +let parameters_correctness = ref [] +let parameters_tuning = ref [] +let add_dep p = + State_dependency_graph.Static.add_codependencies + ~onto:Db.Value.self [State.get p.Parameter.name] +let add_correctness_dep p = + add_dep p; + parameters_correctness := p :: !parameters_correctness +let add_precision_dep p = + add_dep p; + parameters_tuning := p :: !parameters_tuning +let () = + List.iter add_correctness_dep kernel_parameters_correctness; + List.iter add_precision_dep kernel_parameters_precision; +;; + + include Plugin.Register (struct let name = "value analysis" @@ -30,88 +62,71 @@ end) module ForceValues = - Action + WithOutput (struct let option_name = "-val" let help = "compute values" - let kind = `Tuning + let output_by_default = true end) -module MemFunctions = - StringSet - (struct - let option_name = "-mem-exec" - let arg_name = "f" - let help = "do not unroll calls to function f (experimental)" - let kind = `Tuning - end) +let precision_tuning = add_group "Precision vs. time" +let initial_context = add_group "Initial Context" +let performance = add_group "Results memoization vs. time" -module MemExecAll = - False - (struct - let option_name = "-mem-exec-all" - let help = "(experimental)" - let kind = `Tuning - end) -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ MemFunctions.self; - MemExecAll.self; - ] +(* -------------------------------------------------------------------------- *) +(* --- Performance options --- *) +(* -------------------------------------------------------------------------- *) +let () = Plugin.set_group performance module NoResultsFunctions = StringSet (struct let option_name = "-no-results-function" let arg_name = "f" let help = "do not record the values obtained for the statements of function f" - let kind = `Tuning end) +let () = add_dep NoResultsFunctions.parameter +let () = Plugin.set_group performance module NoResultsAll = False (struct let option_name = "-no-results" let help = "do not record values for any of the statements of the program" - let kind = `Tuning end) +let () = add_dep NoResultsAll.parameter -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - NoResultsFunctions.self; - NoResultsAll.self; - ] - +let () = Plugin.set_group performance +module ObviouslyTerminatesFunctions = + StringSet + (struct + let option_name = "-obviously-terminates-function" + let arg_name = "f" + let help = "do not record the values obtained for the statements of function f" + end) +let () = add_dep ObviouslyTerminatesFunctions.parameter -module SignedOverflow = +let () = Plugin.set_group performance +module ObviouslyTerminatesAll = False (struct - let option_name = "-val-signed-overflow-alarms" - let help = - "Emit alarms for overflows in signed arithmetic. Experimental" - let kind = `Correctness + let option_name = "-obviously-terminates" + let help = "undocumented. Among effects of this options are the same effects as -no-results" end) +let () = add_dep ObviouslyTerminatesAll.parameter -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - SignedOverflow.self; - ] - -module IgnoreRecursiveCalls = - False +let () = Plugin.set_group performance +module ResultsAfter = + Bool (struct - let option_name = "-val-ignore-recursive-calls" - let help = - "Pretend function calls that would be recursive do not happen. Causes unsoundness" - let kind = `Correctness + let option_name = "-val-after-results" + let help = "record precisely the values obtained after the evaluation of each statement" + let default = !Config.is_gui end) +let () = add_dep ResultsAfter.parameter +let () = Plugin.set_group performance module MemoryFootprint = Int (struct @@ -119,10 +134,7 @@ let default = 2 let arg_name = "" let help = "tell the analyser to compromise towards speed or towards low memory use. 1 : small memory; 2 : medium (suitable for recent notebooks); 3 : big (suitable for workstations with 3Gb physical memory or more). Defaults to 2" - let kind = `Tuning end) - - let () = MemoryFootprint.add_set_hook (fun _ x -> @@ -132,7 +144,58 @@ ~from:MemoryFootprint.self [ Binary_cache.MemoryFootprint.self; Buckx.MemoryFootprint.self ] -let initial_context = add_group "Initial Context" + +(* ------------------------------------------------------------------------- *) +(* --- Misc --- *) +(* ------------------------------------------------------------------------- *) + +module PropagateTop = + False + (struct + let option_name = "-propagate-top" + let help = "do not stop value analysis even if it is degenerating" + end) +let () = add_correctness_dep PropagateTop.parameter + +module AllRoundingModes = + False + (struct + let option_name = "-all-rounding-modes" + let help = "Take more target FPU and compiler behaviors into account" + let kind = `Correctness + end) +let () = add_correctness_dep AllRoundingModes.parameter + +module UndefinedPointerComparisonPropagateAll = + False + (struct + let option_name = "-undefined-pointer-comparison-propagate-all" + let help = "if the target program appears to contain undefined pointer comparisons, propagate both outcomes {0; 1} in addition to the emission of an alarm" + end) +let () = add_correctness_dep UndefinedPointerComparisonPropagateAll.parameter + +module SignedOverflow = + False + (struct + let option_name = "-val-signed-overflow-alarms" + let help = + "Emit alarms for overflows in signed arithmetic. Experimental" + end) +let () = add_correctness_dep SignedOverflow.parameter + +module IgnoreRecursiveCalls = + False + (struct + let option_name = "-val-ignore-recursive-calls" + let help = + "Pretend function calls that would be recursive do not happen. Causes unsoundness" + end) +let () = add_correctness_dep IgnoreRecursiveCalls.parameter + + +(* ------------------------------------------------------------------------- *) +(* --- Initial context --- *) +(* ------------------------------------------------------------------------- *) let () = Plugin.set_group initial_context module AutomaticContextMaxDepth = @@ -142,8 +205,8 @@ let default = 2 let arg_name = "n" let help = "use <n> as the depth of the default context for value analysis. (defaults to 2)" - let kind = `Correctness end) +let () = add_correctness_dep AutomaticContextMaxDepth.parameter let () = Plugin.set_group initial_context module AutomaticContextMaxWidth = @@ -153,17 +216,9 @@ let default = 2 let arg_name = "n" let help = "use <n> as the width of the default context for value analysis. (defaults to 2)" - let kind = `Correctness end) let () = AutomaticContextMaxWidth.set_range ~min:1 ~max:max_int - -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - AutomaticContextMaxWidth.self; - AutomaticContextMaxDepth.self; - ] +let () = add_correctness_dep AutomaticContextMaxWidth.parameter let () = Plugin.set_group initial_context module SeparateStmtStart = @@ -172,8 +227,8 @@ let option_name = "-separate-stmts" let arg_name = "n1,..,nk" let help = "Undocumented" - let kind = `Correctness end) +let () = add_correctness_dep SeparateStmtStart.parameter let () = Plugin.set_group initial_context module SeparateStmtWord = @@ -183,9 +238,9 @@ let default = 0 let arg_name = "n" let help = "Undocumented" - let kind = `Correctness end) let () = SeparateStmtWord.set_range ~min:0 ~max:1073741823 +let () = add_correctness_dep SeparateStmtWord.parameter let () = Plugin.set_group initial_context module SeparateStmtOf = @@ -195,36 +250,9 @@ let default = 0 let arg_name = "n" let help = "Undocumented" - let kind = `Correctness end) let () = SeparateStmtOf.set_range ~min:0 ~max:1073741823 - - -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - SeparateStmtStart.self; - SeparateStmtWord.self; - SeparateStmtOf.self; - ] - - -let () = Plugin.set_group initial_context -module AllRoundingModes = - False - (struct - let option_name = "-all-rounding-modes" - let help = "Take more target FPU and compiler behaviors into account" - let kind = `Correctness - end) - -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - AllRoundingModes.self; - ] +let () = add_correctness_dep SeparateStmtOf.parameter let () = Plugin.set_group initial_context module AllocatedContextValid = @@ -232,40 +260,13 @@ (struct let option_name = "-context-valid-pointers" let help = "only allocate valid pointers until context-depth, and then use NULL (defaults to false)" - let kind = `Correctness end) -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - AllocatedContextValid.self; - ] +let () = add_correctness_dep AllocatedContextValid.parameter -let () = Plugin.set_group initial_context -module UndefinedPointerComparisonPropagateAll = - False - (struct - let option_name = "-undefined-pointer-comparison-propagate-all" - let help = "if the target program appears to contain undefined pointer comparisons, propagate both outcomes {0; 1;} in addition to the emission of an alarm" - let kind = `Correctness - end) -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - UndefinedPointerComparisonPropagateAll.self; - ] -let precision_tuning = add_group "Precision tuning" - -let () = Plugin.set_group precision_tuning -module PropagateTop = - False - (struct - let option_name = "-propagate-top" - let help = "do not stop value analysis even if it is degenerating" - let kind = `Tuning - end) +(* ------------------------------------------------------------------------- *) +(* --- Tuning --- *) +(* ------------------------------------------------------------------------- *) let () = Plugin.set_group precision_tuning module WideningLevel = @@ -275,20 +276,9 @@ let option_name = "-wlevel" let arg_name = "n" let help = - "do <n> loop iterations before widening (defaults to 3)" - let kind = `Tuning - end) - -let () = Plugin.set_group precision_tuning -module ArrayPrecisionLevel = - Int - (struct - let default = 200 - let option_name = "-plevel" - let arg_name = "n" - let help = "use <n> as the precision level for arrays accesses. Array accesses are precise as long as the interval for the index contains less than n values. (defaults to 200)" - let kind = `Tuning + "do <n> loop iterations before widening (defaults to 3)" end) +let () = add_precision_dep WideningLevel.parameter let () = Plugin.set_group precision_tuning module SemanticUnrollingLevel = @@ -297,9 +287,18 @@ let option_name = "-slevel" let arg_name = "n" let help = - "use <n> as number of path to explore in parallel (defaults to 0)" - let kind = `Tuning + "use <n> as number of path to explore in parallel (defaults to 0)" end) +let () = add_precision_dep SemanticUnrollingLevel.parameter + +let split_option = + let rx = Str.regexp_string ":" in + fun s -> + try + match Str.split rx s with + | [ f ; n ] -> (f, n) + | _ -> failwith "" + with _ -> failwith "split_option" let () = Plugin.set_group precision_tuning module SlevelFunction = @@ -308,22 +307,37 @@ let option_name = "-slevel-function" let arg_name = "f:n" let help = "override slevel with <n> when analyzing <f>" - let kind = `Tuning end) (struct include Datatype.Int - let rx = Str.regexp_string ":" + let parse s = - try - match Str.split rx s with - [ f ; n ] -> - let n = int_of_string n in - f, n - | _ -> failwith "" - with + try + let f, n = split_option s in + let n = int_of_string n in + f, n + with | Failure _ -> abort "Could not parse option \"-slevel-function %s\"" s let no_binding _ = SemanticUnrollingLevel.get () end) +let () = add_precision_dep SlevelFunction.parameter + +let () = Plugin.set_group precision_tuning +module BuiltinsOverrides = + StringHashtbl + (struct + let option_name = "-val-builtin" + let arg_name = "f:ffc" + let help = "when analyzing function <f>, try to use Frama-C builtin <ffc> instead. Fall back to <f> if <ffc> cannot handle its arguments (experimental)." + end) + (struct + include Datatype.String + let parse s = + try split_option s + with Failure _ -> abort "Could not parse option \"-val-builtin %s\"" s + let no_binding _ = raise Not_found + end) +let () = add_precision_dep BuiltinsOverrides.parameter let () = Plugin.set_group precision_tuning module Subdivide_float_in_expr = @@ -332,21 +346,54 @@ let option_name = "-subdivide-float-var" let arg_name = "n" let help = - "use <n> as number of subdivisions allowed for float variables in expressions (experimental, defaults to 0)" - let kind = `Tuning + "use <n> as number of subdivisions allowed for float variables in expressions (experimental, defaults to 0)" end) +let () = add_precision_dep Subdivide_float_in_expr.parameter + +let () = Plugin.set_group precision_tuning +module UsePrototype = + StringSet + (struct + let option_name = "-val-use-spec" + let arg_name = "f1,..,fn" + let help = "undocumented" + end) +let () = add_precision_dep UsePrototype.parameter + +let () = Plugin.set_group precision_tuning +module RmAssert = + False + (struct + let option_name = "-remove-redundant-alarms" + let help = "after the analysis, try to remove redundant alarms, so that the user needs inspect fewer of them" + end) +let () = add_precision_dep RmAssert.parameter + + +(* ------------------------------------------------------------------------- *) +(* --- Messages --- *) +(* ------------------------------------------------------------------------- *) + +let () = Plugin.set_group messages +module ValShowProgress = + True + (struct + let option_name = "-val-show-progress" + let help = "Show progression messages during value analysis" + end) + +let () = Plugin.set_group messages +module PrintCallstacks = + False + (struct + let option_name = "-val-print-callstacks" + let help = "When printing a message, also show the current analysis context." + end) + + +let parameters_correctness = !parameters_correctness +let parameters_tuning = !parameters_tuning -let () = - State_dependency_graph.Static.add_codependencies - ~onto:Db.Value.self - [ - PropagateTop.self; - WideningLevel.self; - ArrayPrecisionLevel.self; - SemanticUnrollingLevel.self; - SlevelFunction.self; - Subdivide_float_in_expr.self; - ] (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/value/value_parameters.mli frama-c-20111001+nitrogen+dfsg/src/value/value_parameters.mli --- frama-c-20110201+carbon+dfsg/src/value/value_parameters.mli 2011-02-07 13:59:39.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/value_parameters.mli 2011-10-10 08:38:26.000000000 +0000 @@ -22,43 +22,54 @@ include Plugin.S -module ForceValues: Plugin.BOOL +module ForceValues: Plugin.WithOutput -module PropagateTop: Plugin.BOOL +module PropagateTop: Plugin.Bool -module AutomaticContextMaxDepth: Plugin.INT -module AutomaticContextMaxWidth: Plugin.INT +module AutomaticContextMaxDepth: Plugin.Int +module AutomaticContextMaxWidth: Plugin.Int -module SeparateStmtStart: Plugin.STRING_SET -module SeparateStmtWord: Plugin.INT -module SeparateStmtOf: Plugin.INT +module SeparateStmtStart: Plugin.String_set +module SeparateStmtWord: Plugin.Int +module SeparateStmtOf: Plugin.Int -module AllRoundingModes: Plugin.BOOL +module AllRoundingModes: Plugin.Bool -module MemFunctions: Plugin.STRING_SET -module MemExecAll: Plugin.BOOL +module NoResultsFunctions: Plugin.String_set +module NoResultsAll: Plugin.Bool -module NoResultsFunctions: Plugin.STRING_SET -module NoResultsAll: Plugin.BOOL +module ObviouslyTerminatesAll: Plugin.Bool +module ObviouslyTerminatesFunctions: Plugin.String_set -module SignedOverflow: Plugin.BOOL +module ResultsAfter: Plugin.Bool -module IgnoreRecursiveCalls: Plugin.BOOL +module SignedOverflow: Plugin.Bool -module MemoryFootprint: Plugin.INT +module IgnoreRecursiveCalls: Plugin.Bool +module ValShowProgress: Plugin.Bool -module SemanticUnrollingLevel: Plugin.INT +module MemoryFootprint: Plugin.Int -module AllocatedContextValid: Plugin.BOOL +module SemanticUnrollingLevel: Plugin.Int -module UndefinedPointerComparisonPropagateAll: Plugin.BOOL +module AllocatedContextValid: Plugin.Bool -module ArrayPrecisionLevel: Plugin.INT +module UndefinedPointerComparisonPropagateAll: Plugin.Bool -module WideningLevel: Plugin.INT -module SlevelFunction: Plugin.STRING_HASHTBL with type value = int +module WideningLevel: Plugin.Int +module SlevelFunction: Plugin.String_hashtbl with type value = int -module Subdivide_float_in_expr: Plugin.INT +module UsePrototype: Plugin.String_set + +module RmAssert: Plugin.Bool + +module Subdivide_float_in_expr: Plugin.Int +module BuiltinsOverrides: Plugin.String_hashtbl with type value = string + +module PrintCallstacks: Plugin.Bool + +val parameters_correctness: Parameter.t list +val parameters_tuning: Parameter.t list (* Local Variables: diff -Nru frama-c-20110201+carbon+dfsg/src/value/value_util.ml frama-c-20111001+nitrogen+dfsg/src/value/value_util.ml --- frama-c-20110201+carbon+dfsg/src/value/value_util.ml 2011-02-07 13:53:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/value/value_util.ml 2011-10-10 08:38:26.000000000 +0000 @@ -20,13 +20,9 @@ (* *) (**************************************************************************) -open Db_types open Cil_types -let get_rounding_mode () = - if Value_parameters.AllRoundingModes.get () - then Ival.Float_abstract.Any - else Ival.Float_abstract.Nearest_Even +(** Callstacks related types and functions *) type called_function = { called_kf : kernel_function; @@ -34,34 +30,8 @@ called_merge_current : degenerate:bool -> unit} let call_stack : called_function list ref = ref [] - let call_stack_for_callbacks : (kernel_function * kinstr) list ref = ref [] - -let do_degenerate lv = - List.iter - (fun {called_merge_current = merge_current } -> - merge_current ~degenerate:true) - !call_stack; - !Db.Value.degeneration_occurred (CilE.current_stmt ()) lv - -let warn_all_quiet_mode () = - if Value_parameters.verbose_atleast 1 then - CilE.warn_all_mode - else - { CilE.warn_all_mode with CilE.imprecision_tracing = CilE.Aignore } - - -let pretty_actuals fmt actuals = - Pretty_utils.pp_flowlist (fun fmt (_,x,_) -> Cvalue_type.V.pretty fmt x) - fmt actuals - -let pretty_call_stack fmt callstack = - Pretty_utils.pp_flowlist ~left:"" ~sep:" <-" ~right:"" - (fun fmt {called_kf = kf} -> Kernel_function.pretty_name fmt kf) - fmt - callstack - let clear_call_stack () = call_stack := []; call_stack_for_callbacks := [] @@ -80,6 +50,94 @@ let call_stack () = !call_stack let for_callbacks_stack () = !call_stack_for_callbacks +let pretty_call_stack fmt callstack = + Pretty_utils.pp_flowlist ~left:"" ~sep:" <- " ~right:"" + (fun fmt {called_kf = kf} -> Kernel_function.pretty fmt kf) + fmt + callstack + +let pretty_callbacks_call_stack fmt callstack = + Format.fprintf fmt "@[<hv>"; + List.iter (fun (kf, ki) -> + Kernel_function.pretty fmt kf; + match ki with + | Kglobal -> () + | Kstmt stmt -> Format.fprintf fmt " :: %a <-@ " + Cil_datatype.Location.pretty (Cil_datatype.Stmt.loc stmt) + ) callstack; + Format.fprintf fmt "@]" + +let pp_callstack fmt = + if Value_parameters.PrintCallstacks.get () then + Format.fprintf fmt "@ stack: %a" + pretty_callbacks_call_stack !call_stack_for_callbacks +;; + +(** Misc *) + +let get_rounding_mode () = + if Value_parameters.AllRoundingModes.get () + then Ival.Float_abstract.Any + else Ival.Float_abstract.Nearest_Even + +let do_degenerate lv = + List.iter + (fun {called_merge_current = merge_current } -> + merge_current ~degenerate:true) + (call_stack ()); + !Db.Value.degeneration_occurred (CilE.current_stmt ()) lv + +(** Assertions emitted during the analysis *) + +let emitter_value = + Emitter.create + "value analysis" + ~correctness:Value_parameters.parameters_correctness + ~tuning:Value_parameters.parameters_tuning + +let emit_status ppt s = + Property_status.emit ~distinct:true emitter_value ~hyps:[] ppt s + +let warn_all_mode = + CilE.warn_all_mode { CilE.warn_emitter = emitter_value; + warn_deps = [Db.Value.self] } + +let warn_all_quiet_mode () = + if Value_parameters.verbose_atleast 1 then + warn_all_mode + else + { warn_all_mode with CilE.imprecision_tracing = CilE.Aignore } + +let get_slevel kf = + let name = Kernel_function.get_name kf in + Value_parameters.SlevelFunction.find name + +let set_loc kinstr = + match kinstr with + | Kglobal -> Cil.CurrentLoc.clear () + | Kstmt s -> Cil.CurrentLoc.set (Cil_datatype.Stmt.loc s) + +module Got_Imprecise_Value = + State_builder.Ref + (Datatype.Bool) + (struct + let name = "Eval.Got_Imprecise_Value" + let dependencies = [ Db.Value.self ] + let kind = `Internal + let default () = false + end) + +let pretty_actuals fmt actuals = + Pretty_utils.pp_flowlist (fun fmt (_,x,_) -> Cvalue.V.pretty fmt x) + fmt actuals + +let pretty_current_cfunction_name fmt = + Kernel_function.pretty fmt (current_kf()) + +let warning_once_current fmt = + Value_parameters.warning ~current:true ~once:true fmt + + (* Local Variables: compile-command: "make -C ../.." diff -Nru frama-c-20110201+carbon+dfsg/src/wp/ACSL.ml frama-c-20111001+nitrogen+dfsg/src/wp/ACSL.ml --- frama-c-20110201+carbon+dfsg/src/wp/ACSL.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/ACSL.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,481 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Custom Registries --- *) +(* -------------------------------------------------------------------------- *) + +module type Compiler = +sig + type key + type data + val name : string + val reprs : data list + val compile : key -> data +end + +module Register(K : Datatype.Hashtbl)(C : Compiler with type key = K.key) = +struct + + type value = Data of C.data | Error of exn | Locked + + module D : Datatype.S with type t = value = + Datatype.Make + (struct + include Datatype.Undefined + type t = value + let name = "Wp.Data." ^ C.name + let reprs = Locked :: Error Exit :: List.map (fun x -> Data x) C.reprs + end) + + module H = State_builder.Hashtbl(K)(D) + (struct + let name = "Wp.ACSL." ^ C.name + let dependencies = [Ast.self] + let kind = `Tuning + let size = 231 + end) + + let get_value x = + try H.find x + with Not_found -> + H.replace x Locked ; + let value = try Data(C.compile x) with exn -> Error exn in + H.replace x value ; value + + let obtain x = + match get_value x with + | Locked -> Wp_parameters.fatal "Cyclic compilation (%a)" K.Key.pretty x + | Error exn -> raise exn + | Data y -> y + +end + +(* -------------------------------------------------------------------------- *) +(* --- ACSL Definitions --- *) +(* -------------------------------------------------------------------------- *) + +open Ctypes +open Cil_types +open Cil_datatype + +open LogicId +open LogicTau +open LogicLang +open LogicDef + +let dtau_ctype : (typ -> tau) ref = ref (fun _ -> assert false) +let dhas_ctype : (typ -> term -> pred) ref = ref (fun _ _ -> assert false) +let deq_ctype : (typ -> term -> term -> pred) ref = ref (fun _ _ _ -> assert false) + +(* -------------------------------------------------------------------------- *) +(* --- Array with Dimension --- *) +(* -------------------------------------------------------------------------- *) + +module Tarray = + Datatype.Make_with_collections + (struct + include Datatype.Undefined + type t = typ * int option list + let name = "Wp.ACSL.Tarray" + let reprs = [TVoid[],[]] + let pp_hash_dim h = function + | None -> h * 731 + | Some d -> h * 731 + d * 27 + let hash (te,dims) = + List.fold_left pp_hash_dim (Typ.hash te) dims + let equal (t1,d1) (t2,d2) = + Pervasives.(=) d1 d2 && Typ.equal t1 t2 + let compare _ _ = 0 (* incorrect but never used *) + let pp_dim fmt = function + | None -> Format.pp_print_string fmt "[]" + | Some d -> Format.fprintf fmt "[%d]" d + let pretty fmt (te,dims) = + Typ.pretty fmt te ; List.iter (pp_dim fmt) dims + end) + +(* Find the head-dimension of an array *) +let tarray_dim = function + | None -> None + | Some aflat -> + try Some(Int64.to_int aflat.arr_size) + with _ -> None + +(* t-array extraction *) +let rec tarray_of_typ t ds = + match object_of t with + | C_array info -> tarray_of_arrayinfo info ds + | _ -> t,ds + +and tarray_of_arrayinfo info ds = + let d = tarray_dim info.arr_flat in + tarray_of_typ info.arr_element (d::ds) + +let rec tau_of_tarray tau = function + | [] -> tau + | _::ds -> tau_of_tarray (Array(Integer,tau)) ds + +let tarray_elt fmt te = + match object_of te with + | C_int i -> pp_int fmt i + | C_float f -> pp_float fmt f + | C_comp c -> Format.pp_print_string fmt c.cname + | C_array _ -> Wp_parameters.fatal "incomplete array-dimension" + | C_pointer _ -> Wp_parameters.fatal "pointer array constraint" + +let tarray_name te ds = + Pretty_utils.sfprintf "%a%t" tarray_elt te + (fun fmt -> + List.iter + (function + | None -> Format.fprintf fmt "_arr" + | Some n -> Format.fprintf fmt "_a%d" n + ) ds) + +let in_range i d p = + match d with + | None -> p + | Some n -> + let k = e_var i in + p_goal [ p_icmp Cleq e_zero k ; p_icmp Clt k (e_int n) ] p + +module Darray = + Datatype.Make_with_collections + (struct + include Datatype.Undefined + type t = typ * int + let name = "Wp.ACSL.Darray" + let reprs = [TVoid[],0] + let hash (te,dims) = 31*(Typ.hash te) + dims + let equal (t1,d1) (t2,d2) = + Pervasives.(=) d1 d2 && Typ.equal t1 t2 + let compare _ _ = 0 (* incorrect but never used *) + let pretty fmt (te,dims) = + Typ.pretty fmt te ; + for i=1 to dims do Format.pp_print_string fmt "[]" done + end) + +let rec tau_of_darray te n = + if n > 0 then Array(Integer, tau_of_darray te (pred n)) else te + +let darray_name te n = Pretty_utils.sfprintf "%a_d%d" tarray_elt te n + +let rec darray_of_arrayinfo info n = + let te = info.arr_element in + match object_of te with + | C_int _ | C_float _ | C_pointer _ | C_comp _ -> te , n + | C_array arr -> darray_of_arrayinfo arr (succ n) + +(* -------------------------------------------------------------------------- *) +(* --- C-Comp --- *) +(* -------------------------------------------------------------------------- *) + +module Fmap = Fieldinfo.Map +module Record = Register(Compinfo.Hashtbl) + (struct + + type key = compinfo + type data = id * field Fmap.t + + let name = "Record" + let reprs = [LogicId.dummy,Fmap.empty] + + let compile comp = + let prefix = if comp.cstruct then "S_" else "U_" in + let record_id = LogicId.create (prefix ^ comp.cname) in + let record_fields = ref [] in + let compile_fields = ref Fmap.empty in + List.iter + (fun f -> + let field = { + LogicTau.f_name = LogicId.create ("F_" ^ f.fname) ; + LogicTau.f_type = !dtau_ctype f.ftype ; + LogicTau.f_record = record_id ; + } in + record_fields := field :: !record_fields ; + compile_fields := Fmap.add f field !compile_fields ; + ) comp.cfields ; + let descr = { + t_source = fst (List.hd comp.cfields).floc ; + t_short = (if comp.cstruct then "struct " else "union ") ^ comp.corig_name ; + t_descr = "" ; + } in + LogicDef.declare { + d_name = record_id ; + d_item = RECORD (List.rev !record_fields) ; + d_descr = descr ; + } ; + (record_id , !compile_fields) + + end) + +let record_of comp = fst (Record.obtain comp) +let field_of finfo = Fmap.find finfo (snd (Record.obtain finfo.fcomp)) + +(* -------------------------------------------------------------------------- *) +(* --- ADT-Types --- *) +(* -------------------------------------------------------------------------- *) + +module ADT = Register(Logic_type_info.Hashtbl) + (struct + type key = logic_type_info + type data = id + let name = "ADT" + let reprs = [LogicId.dummy] + let compile lt = + let tid = LogicId.create ("T_" ^ lt.lt_name) in + LogicDef.declare { + d_name = tid ; + d_item = TYPE (List.length lt.lt_params) ; + d_descr = { + t_source = Lexing.dummy_pos ; + t_short = Printf.sprintf "logic type %s" lt.lt_name ; + t_descr = "" ; + } ; + } ; tid + end) + +(* -------------------------------------------------------------------------- *) +(* --- Types --- *) +(* -------------------------------------------------------------------------- *) + +open Ctypes + +let rec tau_of_ctype t = + tau_of_object (Ctypes.object_of t) + +and tau_of_object = function + | C_int _ -> Integer + | C_float _ -> Real + | C_pointer _ -> Pointer + | C_comp c -> Record (record_of c) + | C_array a -> Array(Integer,tau_of_ctype a.arr_element) + +and tau_of_logic_type = function + | Ctype c -> tau_of_ctype c + | Linteger -> Integer + | Lreal -> Real + | Ltype( d , [] ) when d.lt_name = Utf8_logic.boolean -> Boolean + | Ltype( {lt_name="set"} , [t] ) -> Set (tau_of_logic_type t) + | Ltype( lt , ts) -> ADT( ADT.obtain lt , List.map tau_of_logic_type ts ) + | Lvar _ -> Wp_parameters.not_yet_implemented "logic type variables" + | Larrow _ -> Wp_parameters.not_yet_implemented "type of logic function" + +let () = dtau_ctype := tau_of_ctype + +(* -------------------------------------------------------------------------- *) +(* --- Is Int --- *) +(* -------------------------------------------------------------------------- *) + +let lib_is_int = List.map + (fun i -> i , LogicId.library (Pretty_utils.sfprintf "is_%a" pp_int i)) + Ctypes.c_int_all + +let lib_to_int = List.map + (fun i -> i , LogicId.library (Pretty_utils.sfprintf "to_%a" pp_int i)) + Ctypes.c_int_all + +let is_int i = List.assoc i lib_is_int +let to_int i = List.assoc i lib_to_int + +(* -------------------------------------------------------------------------- *) +(* --- Is Comp --- *) +(* -------------------------------------------------------------------------- *) + +module IsComp = Register(Compinfo.Hashtbl) + (struct + type key = compinfo + type data = id + let name = "IsComp" + let reprs = [LogicId.dummy] + let compile compinfo = + let record = record_of compinfo in + let pid = LogicId.create ("Is_" ^ compinfo.cname) in + let pool = LogicLang.pool () in + let r_var = LogicLang.fresh pool "r" (Record record) in + let r_val = e_var r_var in + let has_ftype f = + !dhas_ctype f.Cil_types.ftype (e_getfield r_val (field_of f)) + in + let condition = p_conj (List.map has_ftype compinfo.cfields) in + LogicDef.declare { + d_name = pid ; + d_item = PREDICATE([r_var],Some condition) ; + d_descr = { + t_source = Lexing.dummy_pos ; + t_short = "subtype " ^ compinfo.corig_name ; + t_descr = "" ; + } ; + } ; pid + end) + +(* -------------------------------------------------------------------------- *) +(* --- Is Array --- *) +(* -------------------------------------------------------------------------- *) + +let rec is_darray pool te dims a = + if dims > 0 then + let i = LogicLang.fresh pool "i" Integer in + let a_i = e_access a (e_var i) in + p_forall i (is_darray pool te (pred dims) a_i) + else + !dhas_ctype te a + +module IsArray = Register(Darray.Hashtbl) + (struct + type key = Darray.t + type data = id + let name = "IsArray" + let reprs = [LogicId.dummy] + let compile (te,dims) = + let tau = tau_of_ctype te in + let tau_dim = tau_of_darray tau dims in + let aid = LogicId.create ("Is_" ^ darray_name te dims) in + let pool = LogicLang.pool () in + let a = LogicLang.fresh pool "a" tau_dim in + let condition = is_darray pool te dims (e_var a) in + LogicDef.declare { + d_name = aid ; + d_item = PREDICATE([a],Some condition) ; + d_descr = { + t_source = Lexing.dummy_pos ; + t_short = "subtype of array" ; + t_descr = "" ; + } ; + } ; aid + end) + +(* -------------------------------------------------------------------------- *) +(* --- ACSL-Types --- *) +(* -------------------------------------------------------------------------- *) + +let rec has_ctype typ term = has_object (object_of typ) term +and has_object obj term = + match obj with + | C_float _ | C_pointer _ -> p_true + | C_int i -> p_call (is_int i) [term] + | C_comp c -> p_call (IsComp.obtain c) [term] + | C_array info -> + let ta = darray_of_arrayinfo info 1 in + match object_of (fst ta) with + | C_float _ | C_pointer _ -> p_true + | C_array _ -> Wp_parameters.fatal "non canonical array-dimension" + | C_int _ | C_comp _ -> + p_call (IsArray.obtain ta) [term] + +let () = dhas_ctype := has_ctype + +(* -------------------------------------------------------------------------- *) +(* --- Eq-Comp --- *) +(* -------------------------------------------------------------------------- *) + +module EqComp = Register(Compinfo.Hashtbl) + (struct + type key = compinfo + type data = id + let reprs = [LogicId.dummy] + let name = "EqComp" + let compile compinfo = + let record = record_of compinfo in + let cid = LogicId.create ("Eq_" ^ compinfo.cname) in + let pool = LogicLang.pool () in + let a = LogicLang.fresh pool "a" (Record record) in + let b = LogicLang.fresh pool "b" (Record record) in + let a_val = e_var a in + let b_val = e_var b in + let eq_field f = + let fd = field_of f in + !deq_ctype f.Cil_types.ftype (e_getfield a_val fd) (e_getfield b_val fd) + in + let condition = p_conj (List.map eq_field compinfo.cfields) in + LogicDef.declare { + d_name = cid ; + d_item = PREDICATE([a;b],Some condition) ; + d_descr = { + t_source = Lexing.dummy_pos ; + t_short = "equality for " ^ compinfo.corig_name ; + t_descr = "" ; + } ; + } ; cid + end) + +(* -------------------------------------------------------------------------- *) +(* --- Eq-Array --- *) +(* -------------------------------------------------------------------------- *) + +let rec eq_tarray pool te dims ta tb = + match dims with + | [] -> !deq_ctype te ta tb + | d::ds -> + let i = LogicLang.fresh pool "i" Integer in + let ta_i = e_access ta (e_var i) in + let tb_i = e_access tb (e_var i) in + p_forall i + (in_range i d (eq_tarray pool te ds ta_i tb_i)) + +module EqArray = Register(Tarray.Hashtbl) + (struct + type key = Tarray.t + type data = id + let reprs = [LogicId.dummy] + let name = "EqArray" + let compile (te,dims) = + let tau = tau_of_ctype te in + let tau_dim = tau_of_tarray tau dims in + let aid = LogicId.create ("Eq_" ^ tarray_name te dims) in + let pool = LogicLang.pool () in + let a = LogicLang.fresh pool "a" tau_dim in + let b = LogicLang.fresh pool "b" tau_dim in + let condition = eq_tarray pool te dims (e_var a) (e_var b) in + LogicDef.declare { + d_name = aid ; + d_item = PREDICATE([a],Some condition) ; + d_descr = { + t_source = Lexing.dummy_pos ; + t_short = "equality for array" ; + t_descr = "" ; + } ; + } ; aid + end) + +(* -------------------------------------------------------------------------- *) +(* --- ACSL-Equality --- *) +(* -------------------------------------------------------------------------- *) + +let rec eq_ctype typ t1 t2 = eq_object (object_of typ) t1 t2 + +and eq_object obj t1 t2 = + match obj with + | C_int _ -> p_icmp Ceq t1 t2 + | C_float _ -> p_rcmp Ceq t1 t2 + | C_comp c -> p_call (EqComp.obtain c) [t1;t2] + | C_array a -> p_call (EqArray.obtain (tarray_of_arrayinfo a [])) [t1;t2] + | C_pointer _ -> p_equal t1 t2 + +and eq_logic_type lt t1 t2 = + match lt with + | Ctype typ -> eq_ctype typ t1 t2 + | _ -> p_equal t1 t2 (* Stronger for Set, etc. *) + +let () = deq_ctype := eq_ctype + +(* -------------------------------------------------------------------------- *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/ACSL.mli frama-c-20111001+nitrogen+dfsg/src/wp/ACSL.mli --- frama-c-20110201+carbon+dfsg/src/wp/ACSL.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/ACSL.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,81 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Logic Declarations for ACSL *) + +open Ctypes +open Cil_types +open LogicId +open LogicTau +open LogicLang + +(* -------------------------------------------------------------------------- *) +(** {2 Types} *) +(* -------------------------------------------------------------------------- *) + +val record_of : compinfo -> id +val field_of : fieldinfo -> field + +val tau_of_ctype : typ -> tau +val tau_of_object : c_object -> tau +val tau_of_logic_type : logic_type -> tau + +(* -------------------------------------------------------------------------- *) +(** {2 Sub-Types} *) +(* -------------------------------------------------------------------------- *) + +val is_int : c_int -> id +val to_int : c_int -> id + +val has_ctype : typ -> term -> pred +val has_object : c_object -> term -> pred + +(* -------------------------------------------------------------------------- *) +(** {2 Equality} *) +(* -------------------------------------------------------------------------- *) + +val eq_ctype : typ -> term -> term -> pred +val eq_object : c_object -> term -> term -> pred +val eq_logic_type : logic_type -> term -> term -> pred + +(* -------------------------------------------------------------------------- *) +(** {2 Declarator Helper} *) +(* -------------------------------------------------------------------------- *) + +module type Compiler = +sig + type key + type data + val name : string + val reprs : data list (* Project+Datatype requirement *) + val compile : key -> data +end + +module Register(H : Datatype.Hashtbl)(C : Compiler with type key = H.key) : +sig + + val obtain : C.key -> C.data + (** Projectified and memoized [C.compile]. The compiler can not + be recursive. An exception during the compilation is + re-raised each time its value is requested. *) + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/calculus.ml frama-c-20111001+nitrogen+dfsg/src/wp/calculus.ml --- frama-c-20110201+carbon+dfsg/src/wp/calculus.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/calculus.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,720 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Wp computation using the CFG *) + +open Cil_types +open Cil_datatype + +module Cfg (W : Mcfg.S) = struct + + let dkey = "calculus" (* Debugging key *) + let debug fmt = Wp_parameters.debug ~dkey fmt + + (** Before storing something at a program point, we have to process the label + * at that point. *) + let do_labels wenv e obj = + let do_lab o l = + debug "[do_label] process %a@." Clabels.pretty l; + W.label wenv l o + in + let obj = do_lab obj Clabels.Here in + let labels = Cil2cfg.get_edge_labels e in + let obj = List.fold_left do_lab obj labels in + obj + + let add_hyp wenv obj h = + debug "add hyp %a@." WpPropId.pp_pred_info h; + W.add_hyp wenv h obj + + let add_call_hyp wenv obj h = + debug "add hyp %a@." WpPropId.pp_pred_info h; + W.add_hyp wenv h obj + + let add_goal wenv obj g = + debug "add goal %a@." WpPropId.pp_pred_info g; + W.add_goal wenv g obj + + let add_assigns_goal wenv obj g_assigns = match g_assigns with + | WpPropId.AssignsAny _ | WpPropId.NoAssignsInfo -> obj + | WpPropId.AssignsLocations a -> + debug "add assign goal (@[%s@])@." + (WpPropId.prop_id_name (WpPropId.assigns_info_id a)); + W.add_assigns wenv a obj + + let add_assigns_hyp wenv obj h_assigns = match h_assigns with + | WpPropId.AssignsLocations (h_id, a) -> + let obj = W.use_assigns wenv (Some h_id) a obj in + Some (Clabels.c_label a.WpPropId.a_label), obj + | WpPropId.AssignsAny a -> + let obj = W.use_assigns wenv None a obj in + Some (Clabels.c_label a.WpPropId.a_label), obj + | WpPropId.NoAssignsInfo -> None, obj + + (** detect if the computation of the result at [edge] is possible, + * or if it will loop. If [strategy] are provide, + * cut are done on edges with cut properties, + * and if not, cut are done on loop node back edge if any. + * TODO: maybe this should be done while building the strategy ? + * *) + exception Stop of Cil2cfg.edge + let test_edge_loop_ok cfg strategy edge = + debug "[test_edge_loop_ok] (%s strategy) for %a" + (match strategy with None -> "without" | Some _ -> "with") + Cil2cfg.pp_edge edge; + let rec collect_edge_preds set e = + let cut = + match strategy with None -> Cil2cfg.is_back_edge e + | Some strategy -> + let e_annots = WpStrategy.get_annots strategy e in + (WpStrategy.get_cut e_annots <> []) + in + if cut then () (* normal loop cut *) + else if Cil2cfg.Eset.mem e set + then (* e is already in set : loop without cut ! *) + raise (Stop e) + else (* add e to set and continue with its preds *) + let set = Cil2cfg.Eset.add e set in + let preds = Cil2cfg.pred_e cfg (Cil2cfg.edge_src e) in + List.iter (collect_edge_preds set) preds + in + try + let _ = collect_edge_preds Cil2cfg.Eset.empty edge in + debug "[test_edge_loop_ok] ok."; + true + with Stop e -> + begin + debug "[test_edge_loop_ok] loop without cut detected at %a" + Cil2cfg.pp_edge e; + false + end + + (** to store the results of computations : + * we store a result for each edge, and also a list of proof obligations. + * + * Be careful that there are two modes of computation : + * the first one ([Pass1]) is used to prove the establishment of properties + * while the second (after [change_mode_if_needed]) prove the preservation. + * See {!R.set} for more details. + * *) + module R : sig + type t + val empty : keep:bool -> Cil2cfg.t -> t + val is_pass1 : t -> bool + val change_mode_if_needed : t -> unit + val find : t -> Cil2cfg.edge -> W.t_prop + val set : WpStrategy.strategy -> W.t_env -> + t -> Cil2cfg.edge -> W.t_prop -> W.t_prop + val add_oblig : t -> Clabels.c_label -> W.t_prop -> unit + val add_memo : t -> Cil2cfg.edge -> W.t_prop -> unit + end = + struct + type t_mode = Pass1 | Pass2 + + module HE = Cil2cfg.HE (struct type t = W.t_prop option end) + + module LabObligs : sig + type t + val empty : t + val is_empty : t -> bool + val get_of_label : t -> Clabels.c_label -> W.t_prop list + val get_of_edge : t -> Cil2cfg.edge -> W.t_prop list + val add_to_label : t -> Clabels.c_label -> W.t_prop -> t + val add_to_edge : t -> Cil2cfg.edge -> W.t_prop -> t + end = struct + + type key = Olab of Clabels.c_label | Oedge of Cil2cfg.edge + + let cmp_key k1 k2 = match k1, k2 with + | Olab l1, Olab l2 when l1 = l2 -> true + | Oedge e1, Oedge e2 when Cil2cfg.same_edge e1 e2 -> true + | _ -> false + + (* TODOopt: could have a sorted list... *) + type t = (key * W.t_prop list) list + + let empty = [] + + let is_empty obligs = (obligs = []) + + let add obligs k obj = + let rec aux l_obligs = match l_obligs with + | [] -> (k, [obj])::[] + | (k', obligs)::tl when cmp_key k k' -> + (k, obj::obligs)::tl + | o::tl -> o::(aux tl) + in aux obligs + + let add_to_label obligs label obj = add obligs (Olab label) obj + + let add_to_edge obligs e obj = add obligs (Oedge e) obj + + let get obligs k = + let rec aux l_obligs = match l_obligs with + | [] -> [] + | (k', obligs)::_ when cmp_key k k' -> obligs + | _::tl -> aux tl + in aux obligs + + let get_of_label obligs label = get obligs (Olab label) + + let get_of_edge obligs e = get obligs (Oedge e) + + end + + type t = { + mutable mode : t_mode ; + keep_res : bool ; (* whether to keep intermediate results or not *) + cfg: Cil2cfg.t; + tbl : HE.t ; + mutable memo : LabObligs.t; + mutable obligs : LabObligs.t; + } + + let empty ~keep cfg = + debug "start computing (pass 1)@."; + { mode = Pass1; keep_res = keep; cfg = cfg; tbl = HE.create 97 ; + obligs = LabObligs.empty ; memo = LabObligs.empty ;} + + let is_pass1 res = (res.mode = Pass1) + + let add_oblig res label obj = + debug "add proof obligation at label %a =@. @[<hov2> %a@]@." + Clabels.pretty label W.pretty obj; + res.obligs <- LabObligs.add_to_label (res.obligs) label obj + + let add_memo res e obj = + debug "Memo goal for Pass2 at %a=@. @[<hov2> %a@]@." + Cil2cfg.pp_edge e W.pretty obj; + res.memo <- LabObligs.add_to_edge (res.memo) e obj + + let find res e = + let obj = HE.find res.tbl e in + match obj with None -> + Wp_parameters.warning "find edge annot twice (%a) ?" + Cil2cfg.pp_edge e; + raise Not_found + | Some obj -> + if (not res.keep_res) + && (res.mode = Pass2) + && (List.length + (Cil2cfg.pred_e res.cfg (Cil2cfg.edge_src e)) < 2) then + begin + (* it should be used once only : can free it *) + HE.replace res.tbl e None; + debug "clear edge %a@." Cil2cfg.pp_edge e + end; + obj + + (** If needed, clear wp table to compute Pass2. + * If nothing has been stored in res.memo, there is nothing to do. *) + let change_mode_if_needed res = + if LabObligs.is_empty res.memo then () + else + begin + debug "change to Pass2 (clear wp table)@."; + begin try + let e_start = Cil2cfg.start_edge res.cfg in + let start_goal = find res e_start in + add_memo res e_start start_goal + with Not_found -> () + end; + HE.clear res.tbl; + (* move memo obligs of Pass1 to obligs for Pass2 *) + res.obligs <- res.memo; + res.memo <- LabObligs.empty; + res.mode <- Pass2 + end + + let collect_oblig _wenv res e obj = + let labels = Cil2cfg.get_edge_labels e in + let add obj obligs = + List.fold_left (fun obj o -> W.merge (*wenv*) o obj) obj obligs + in + let obj = + try + debug "get proof obligation at edge %a@." Cil2cfg.pp_edge e; + let obligs = LabObligs.get_of_edge res.obligs e in + add obj obligs + with Not_found -> obj + in + let add_lab_oblig obj label = + try + debug "get proof obligation at label %a@." Clabels.pretty label; + let obligs = LabObligs.get_of_label res.obligs label in + add obj obligs + with Not_found -> obj + in + let obj = List.fold_left add_lab_oblig obj labels in + obj + + + (** We have found some assigns hypothesis in the stategy : + * it means that we skip the corresponding bloc, ie. we directly compute + * the result before the block : (forall assigns. P), + * and continue with empty. *) + let use_assigns wenv res obj h_assigns = + let lab, obj = add_assigns_hyp wenv obj h_assigns in + match lab with None -> obj + | Some label -> add_oblig res label obj; W.empty + + (** store the result p for the computation of the edge e. + * + * - In Compute mode : + if we have some hyps H about this edge, store H => p + if we have some goal G about this edge, store G /\ p + if we have annotation B to be used as both H and G, store B /\ B=>P + We also have to add H and G from HI (invariants computed in Pass1 mode) + So finaly, we build : [ H => [ BG /\ (BH => (G /\ P)) ] ] + *) + let set strategy wenv res e obj = + try + match (HE.find res.tbl e) with + | None -> raise Not_found + | Some obj -> obj + (* cannot warn here because it can happen with CUT properties. + * We could check that obj is the same thing than the founded result *) + (* Wp_parameters.fatal "strange loop at %a ?" Cil2cfg.pp_edge e *) + with Not_found -> + begin + let e_annot = WpStrategy.get_annots strategy e in + let h_prop = WpStrategy.get_hyp_only e_annot in + let g_prop = WpStrategy.get_goal_only e_annot in + let bh_prop, bg_prop = WpStrategy.get_both_hyp_goals e_annot in + let h_assigns = WpStrategy.get_asgn_hyp e_annot in + let g_assigns = WpStrategy.get_asgn_goal e_annot in + (* get_cut is ignored : see get_wp_edge *) + let obj = collect_oblig wenv res e obj in + let is_loop_head = + match Cil2cfg.node_type (Cil2cfg.edge_src e) with + | Cil2cfg.Vloop (Some _, _) -> true + | _ -> false + in + let compute ~goal obj = + let local_add_goal obj g = + if goal then add_goal wenv obj g else obj + in + let obj = List.fold_left (local_add_goal) obj g_prop in + let obj = List.fold_left (add_hyp wenv) obj bh_prop in + let obj = + if goal then add_assigns_goal wenv obj g_assigns else obj + in + let obj = List.fold_left (local_add_goal) obj bg_prop in + let obj = List.fold_left (add_hyp wenv) obj h_prop in + obj + in + let obj = match res.mode with + | Pass1 -> compute ~goal:true obj + | Pass2 -> compute ~goal:false obj + in + let obj = do_labels wenv e obj in + let obj = + if is_loop_head then obj (* assigns used in [wp_loop] *) + else use_assigns wenv res obj h_assigns + in + debug "[set_wp_edge] %a@." Cil2cfg.pp_edge e; + debug " = @[<hov2> %a@]@." W.pretty obj; + Format.print_flush (); + HE.replace res.tbl e (Some obj); + find res e (* this should give back obj, but also do more things *) + end + + end (* module R *) + + + let use_loop_assigns strategy wenv e obj = + let e_annot = WpStrategy.get_annots strategy e in + let h_assigns = WpStrategy.get_asgn_hyp e_annot in + let label, obj = add_assigns_hyp wenv obj h_assigns in + match label with Some _ -> obj + | None -> assert false (* we should have assigns hyp for loops !*) + + let loop_with_cut cfg annots vloop = + let to_loop_edges = Cil2cfg.pred_e cfg vloop in + (* + let back_edges = + List.filter (Cil2cfg.is_back_edge) (Cil2cfg.pred_e cfg vloop) + in *) + List.for_all (test_edge_loop_ok cfg (Some annots)) to_loop_edges + + (** Compute the result for edge [e] which goes to the loop node [nloop]. + * So [e] can be either a back_edge or a loop entry edge. + * Be very careful not to make an infinite loop by calling [get_loop_head]... + * *) + let wp_loop ((_, cfg, strategy, _, wenv)) res nloop e get_loop_head = + let loop_with_cut_pass1 () = + (* simply propagate both for [entry_edge] and [back_edge] *) + debug "[wp_loop] propagate"; + let obj = get_loop_head nloop (* loop should be broken by a cut *) in + let obj = + if Cil2cfg.is_back_edge e then obj + else W.tag "BeforeLoop" obj + in obj + in + let loop_with_quantif () = + if Cil2cfg.is_back_edge e then + (* Be careful not to use get_only_succ here (infinite loop) *) + (debug "[wp_loop] cut at back edge"; + W.empty) + else (* edge going into the loop from outside : quantify *) + begin + debug "[wp_loop] quantify"; + let obj = get_loop_head nloop in + let head = match Cil2cfg.succ_e cfg nloop with + | [h] -> h + | _ -> assert false (* already detected in [get_loop_head] *) + in use_loop_assigns strategy wenv head obj + end + in + if WpStrategy.new_loop_computation strategy + && R.is_pass1 res + && loop_with_cut cfg strategy nloop + then + loop_with_cut_pass1 () + else (* old mode or no inv or pass2 *) + match Cil2cfg.node_type nloop with + | Cil2cfg.Vloop (Some true, _) -> (* natural loop (has back edges) *) + loop_with_quantif () + | _ -> (* TODO : print info about the loop *) + Wp_error.unsupported + "non-natural loop without invariant property." + + let wp_call ((_, cfg, strategy, _, wenv)) v stmt res fct args p_post p_exit = + debug "[wp_call] %a@." !Ast_printer.d_exp fct; + let eb = match Cil2cfg.pred_e cfg v with e::_ -> e | _ -> assert false in + let en, ee = Cil2cfg.get_call_out_edges cfg v in + let eb_annot = WpStrategy.get_annots strategy eb in + let en_annot = WpStrategy.get_annots strategy en in + let ee_annot = WpStrategy.get_annots strategy ee in + let call_asgn = WpStrategy.get_call_asgn en_annot in + match WpStrategy.get_called_kf fct with + | None -> + let obj = W.merge p_post p_exit in + let lab, obj = add_assigns_hyp wenv obj call_asgn in + let obj = match lab with Some _ -> obj + | None -> assert false + (* we should always have some information, + * even if it is only assigns everything. *) + in obj + | Some kf -> + let assigns = match call_asgn with + | WpPropId.AssignsLocations (_, asgn_body) -> + asgn_body.WpPropId.a_assigns + | WpPropId.AssignsAny _ -> WritesAny + | WpPropId.NoAssignsInfo -> assert false (* see above *) + in + let pre_hyp, pre_goals = WpStrategy.get_call_pre eb_annot in + let obj = W.call wenv stmt res kf args + ~pre:(pre_hyp) + ~post:((WpStrategy.get_call_hyp en_annot)) + ~pexit:((WpStrategy.get_call_hyp ee_annot)) + ~assigns ~p_post ~p_exit + in W.call_goal_precond wenv stmt kf args ~pre:(pre_goals) obj + + let wp_stmt wenv s obj = match s.skind with + | Return (r, _) -> W.return wenv r obj + | Instr i -> + begin match i with + | (Set (lv, e, _)) -> W.assign wenv lv e obj + | (Call _) -> assert false + | (Asm _) -> + Wp_parameters.warning + "Unsupported inline assembler. Assuming no effects.@."; + obj + | Skip _ | Code_annot _ -> obj + end + | Break _ | Continue _ | Goto _ -> obj + | Loop _-> (* this is not a real loop (exit before looping) + just ignore it ! *) obj + | If _ -> assert false + | Switch _-> assert false + | Block _-> assert false + | UnspecifiedSequence _-> assert false + | TryExcept _ | TryFinally _ -> assert false + + let wp_scope wenv vars scope obj = + debug "[wp_scope] %s : %a@." + (match scope with + | Mcfg.SC_Global -> "global" + | Mcfg.SC_Block_in -> "block in" + | Mcfg.SC_Block_out -> "block out" + | Mcfg.SC_Function_in -> "function in" + | Mcfg.SC_Function_frame -> "function frame" + | Mcfg.SC_Function_out -> "function out" ) + (Pretty_utils.pp_list ~sep:", " !Ast_printer.d_var) vars; + W.scope wenv vars scope obj + + + (** @return the WP stored for edge [e]. Compute it if it is not already + * there and store it. Also handle the Acut annotations. *) + let rec get_wp_edge ((_kf, cfg, strategy, res, wenv) as env) e = + !Db.progress (); + let v = Cil2cfg.edge_dst e in + debug "[get_wp_edge] get wp before %a@." Cil2cfg.pp_node v; + try + let res = R.find res e in + debug "[get_wp_edge] %a already computed@." Cil2cfg.pp_node v; + res + with Not_found -> + (* Notice that other hyp and goal are handled in R.set as usual *) + let cutp = + if R.is_pass1 res + then WpStrategy.get_cut (WpStrategy.get_annots strategy e) + else [] + in + match cutp with + | [] -> + let wp = compute_wp_edge env e in + R.set strategy wenv res e wp + | cutp -> + debug "[get_wp_edge] cut at node %a@." Cil2cfg.pp_node v; + let add_cut_goal (g,p) acc = + if g then add_goal wenv acc p else acc + in + let edge_annot = List.fold_right add_cut_goal cutp W.empty in + (* put cut goal properties as goals in e if any, else true *) + let edge_annot = R.set strategy wenv res e edge_annot in + let wp = compute_wp_edge env e in + let add_cut_hyp (_,p) acc = add_hyp wenv acc p in + let oblig = List.fold_right add_cut_hyp cutp wp in + (* TODO : we could add hyp to the oblig if we have some in strategy *) + let oblig = W.tag "InLoop" oblig in + if test_edge_loop_ok cfg None e + then R.add_memo res e oblig + else R.add_oblig res Clabels.Pre (W.close wenv oblig); + edge_annot + + and get_only_succ env cfg v = match Cil2cfg.succ_e cfg v with + | [e'] -> get_wp_edge env e' + | ls -> Wp_parameters.fatal "CFG node %a has %d successors instead of 1@." + Cil2cfg.pp_node v (List.length ls) + + and compute_wp_edge ((kf, cfg, _annots, res, wenv) as env) e = + let v = Cil2cfg.edge_dst e in + debug "[compute_edge] before %a go...@." Cil2cfg.pp_node v; + let old_loc = Cil.CurrentLoc.get () in + let () = match Cil2cfg.node_stmt_opt v with + | Some s -> Cil.CurrentLoc.set (Stmt.loc s) + | None -> () + in + let formals = Kernel_function.get_formals kf in + let res = match Cil2cfg.node_type v with + | Cil2cfg.Vstart -> + Wp_parameters.fatal "No CFG edge can lead to Vstart" + | Cil2cfg.VfctIn -> + let obj = get_only_succ env cfg v in + let obj = wp_scope wenv formals Mcfg.SC_Function_in obj in + let obj = wp_scope wenv [] Mcfg.SC_Global obj in + obj + | Cil2cfg.VblkIn (Cil2cfg.Bfct, b) -> + let obj = get_only_succ env cfg v in + let obj = wp_scope wenv b.blocals Mcfg.SC_Block_in obj in + wp_scope wenv formals Mcfg.SC_Function_frame obj + | Cil2cfg.VblkIn (_, b) -> + let obj = get_only_succ env cfg v in + wp_scope wenv b.blocals Mcfg.SC_Block_in obj + | Cil2cfg.VblkOut (_, _b) -> + let obj = get_only_succ env cfg v in + obj (* cf. blocks_closed_by_edge below *) + | Cil2cfg.Vstmt s -> + let obj = get_only_succ env cfg v in + wp_stmt wenv s obj + | Cil2cfg.Vcall (stmt, res, fct, args) -> + let en, ee = Cil2cfg.get_call_out_edges cfg v in + let objn = get_wp_edge env en in + let obje = get_wp_edge env ee in + wp_call env v stmt res fct args objn obje + | Cil2cfg.Vtest (true, _, c) -> + let et, ef = Cil2cfg.get_test_edges cfg v in + let t_obj = get_wp_edge env et in + let f_obj = get_wp_edge env ef in + W.test wenv c t_obj f_obj + | Cil2cfg.Vtest (false, _, _) -> + get_only_succ env cfg v + | Cil2cfg.Vswitch (_, e) -> + let cases, def_edge = Cil2cfg.get_switch_edges cfg v in + let cases_obj = List.map (fun (c,e) -> c, get_wp_edge env e) cases in + let def_obj = get_wp_edge env def_edge in + W.switch wenv e cases_obj def_obj + | Cil2cfg.Vloop _ | Cil2cfg.Vloop2 _ -> + let get_loop_head = fun n -> get_only_succ env cfg n in + wp_loop env res v e get_loop_head + | Cil2cfg.VfctOut + | Cil2cfg.Vexit -> + let obj = get_only_succ env cfg v (* exitpost / postcondition *) in + wp_scope wenv formals Mcfg.SC_Function_out obj + | Cil2cfg.Vend -> + W.empty +(* LC : unused entry point... + let obj = W.empty in + wp_scope wenv formals Mcfg.SC_Function_after_POST obj +*) + in + let res = + let blks = Cil2cfg.blocks_closed_by_edge cfg e in + let free_locals res b = wp_scope wenv b.blocals Mcfg.SC_Block_out res in + List.fold_left free_locals res blks + in + debug "[compute_edge] before %a done@." Cil2cfg.pp_node v; + Cil.CurrentLoc.set old_loc; + res + + (* Hypothesis for initialization of one global variable *) + let rec init_global_variable wenv lv init obj = + match init with + + | SingleInit exp -> + W.init_value wenv lv (Cil.typeOfLval lv)(Some exp) obj + + | CompoundInit ( ct , initl ) -> + + let len = List.length initl in + let implicit_defaults = + match ct with + | TArray (ty,Some {enode = (Const CInt64 (size,_,_))},_,_) + when My_bigint.lt (My_bigint.of_int len) size -> + + W.init_range wenv lv ty + (Int64.of_int len) (My_bigint.to_int64 size) obj + + | TComp (cp,_,_) when len < (List.length cp.cfields) -> + + List.fold_left + (fun obj f -> + if List.exists + (function (Field(g,_),_) -> Fieldinfo.equal f g | _ -> false) + initl + then obj + else + W.init_value wenv + (Cil.addOffsetLval (Field(f, NoOffset)) lv) + f.ftype None obj) + obj (List.rev cp.cfields) + + | _ -> obj + in + List.fold_left + (fun obj (off,init) -> + let lv = Cil.addOffsetLval off lv in + init_global_variable wenv lv init obj) + implicit_defaults (List.rev initl) + + + (* WP of global initialisations. *) + let process_global_init wenv kf obj = + if WpStrategy.is_main_init kf then + List.fold_left + (fun obj global -> + match global with + | GVar (var, initinfo, loc) -> + if var.vstorage = Extern then obj + else + let old_loc = Cil.CurrentLoc.get () in + Cil.CurrentLoc.set loc ; + let obj = + match initinfo.init with + | None -> + W.init_value + wenv (Var var,NoOffset) var.vtype None obj + | Some init -> + let lv = Var var, NoOffset in + init_global_variable wenv lv init obj + in Cil.CurrentLoc.set old_loc ; obj + | _ -> obj + ) obj (Ast.get()).globals + else + obj + + let get_weakest_precondition cfg ((kf, _g, strategy, res, wenv) as env) = + debug "[wp-cfg] start Pass1"; + Cil2cfg.iter_edges (fun e -> ignore (get_wp_edge env e)) cfg ; + debug "[wp-cfg] end of Pass1"; + R.change_mode_if_needed res; + (* Notice that [get_wp_edge] will start Pass2 if needed, + * but if not, it will only fetch Pass1 result. *) + let e_start = Cil2cfg.start_edge cfg in + let obj = get_wp_edge env e_start in + let obj = process_global_init wenv kf obj in + let obj = match WpStrategy.strategy_kind strategy with + | WpStrategy.SKannots -> obj + | WpStrategy.SKfroms info -> + let pre = info.WpStrategy.get_pre () in + let pre = WpStrategy.get_hyp_only pre in + W.build_prop_of_from wenv pre obj + in + debug "before close: %a@." W.pretty obj; + W.close wenv obj + + let add_axiom (id, (name,labels,p)) = + W.add_axiom id name labels p + + let compute cfg strategy = + debug "[wp-cfg] start computing with the strategy for %a" + WpStrategy.pp_info_of_strategy strategy; + if WpStrategy.strategy_has_prop_goal strategy + || WpStrategy.strategy_has_asgn_goal strategy then + try + let kf = Cil2cfg.cfg_kf cfg in + + if WpStrategy.new_loop_computation strategy then + (match Cil2cfg.very_strange_loops cfg with [] -> () + | _ -> (* TODO : print info about the loops *) + Wp_error.unsupported "strange loop(s).") + else + (match Cil2cfg.strange_loops cfg with [] -> () + | _ -> (* TODO : print info about the loops *) + Wp_error.unsupported + "non natural loop(s): try [-wp-invariants] option"); + + let lvars = match WpStrategy.strategy_kind strategy with + | WpStrategy.SKfroms info -> info.WpStrategy.more_vars + | _ -> [] + in + let wenv = W.new_env ~lvars kf in + let keep = if Wp_parameters.Dot.get () then true else false in + let res = R.empty ~keep cfg in + let env = (kf, cfg, strategy, res, wenv) in + List.iter add_axiom (WpStrategy.global_axioms strategy) ; + let goal = get_weakest_precondition cfg env in + debug "[get_weakest_precondition] %a@." W.pretty goal; + let pp_cfg_edges_annot res fmt e = + try W.pretty fmt (R.find res e) + with Not_found -> Format.fprintf fmt "<released>" + in + let annot_cfg = pp_cfg_edges_annot res in + debug "[wp-cfg] computing done."; + [goal] , annot_cfg + with Wp_error.Error (_, msg) -> + Wp_parameters.warning "@[calculus failed on strategy@ @[for %a@]@ \ + because@ %s (abort)@]" + WpStrategy.pp_info_of_strategy strategy + msg; + let annot_cfg fmt _e = Format.fprintf fmt "" in + [], annot_cfg + else + begin + debug "[wp-cfg] no goal in this strategy : ignore."; + let annot_cfg fmt _e = Format.fprintf fmt "" in + [], annot_cfg + end + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/calculus.mli frama-c-20111001+nitrogen+dfsg/src/wp/calculus.mli --- frama-c-20110201+carbon+dfsg/src/wp/calculus.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/calculus.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,37 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* $Id: calculus.mli 15451 2011-10-04 11:34:51Z signoles $ *) + +open Cil_types + +(** Generic WP calculus *) + +module Cfg(W : Mcfg.S) : +sig + + val compute : + Cil2cfg.t -> + WpStrategy.strategy -> + W.t_prop list * (Format.formatter -> Cil2cfg.edge -> unit) + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cfgProof.ml frama-c-20111001+nitrogen+dfsg/src/wp/cfgProof.ml --- frama-c-20110201+carbon+dfsg/src/wp/cfgProof.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cfgProof.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,334 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cfgpropid + +let dkey = "cfgproof" (* debugging key *) + +class type computer = +object + + method add : WpStrategy.strategy list -> unit + method compute : Wpo.t list + +end + +module type Description = +sig + + val shared : string (** Shared resource basename for the model *) + val context : string (** Basename for environment files ; unique per updater *) + val updater : string (** Unique name for the internal updater *) + val name : string (** Public name for user feedback *) + +end + +module Create + (WpModel:Mwp.S) + (Why:Mcfg.Export with type pred = WpModel.F.pred and type decl = WpModel.F.decl) + (Coq:Mcfg.Export with type pred = WpModel.F.pred and type decl = WpModel.F.decl) + (Ergo:Mcfg.Export with type pred = WpModel.F.pred and type decl = WpModel.F.decl) + (Splitter:Mcfg.Splitter with type pred = WpModel.F.pred) + (Descr:Description) + = +struct + + module Me = State_builder.Ref + (Datatype.Unit) + (struct + let dependencies = [Ast.self] + let name = "WP-" ^ Descr.updater + let kind = `Correctness + let default () = () + end) + + module F = WpModel.F + module L = WpModel.L + module CV = + CfgWeakestPrecondition.Create + (struct + include WpModel + let model = Descr.updater + end) + module PO = Cfgpropid.Create(CV) + module WP = Calculus.Cfg(PO) + + (* ------------------------------------------------------------------------ *) + (* --- Proof Obligations : Export to WHY --- *) + (* ------------------------------------------------------------------------ *) + + type exportation = { + env : string ; + mutable goals : Wpo.t list ; + } + + let assigns_method = PO.assigns_method + + (* ------------------------------------------------------------------------ *) + (* --- Goal Registering --- *) + (* ------------------------------------------------------------------------ *) + + let active_lgg () = + match Wpo.language_of_prover_name (Wp_parameters.Prover.get ()) with + | None -> + (match Wpo.language_of_name (Wp_parameters.Check.get ()) with + | None -> None + | Some l -> Some l + ) + | Some l -> Some l + + let export_wpo export kf bhv wrn dep propid gpred = + let gname = WpPropId.prop_id_name propid in + let gid = Wpo.gid ~context:Descr.context ~kf ~bhv ~propid in + (* --- HEADER --- *) + Wp_parameters.debug ~dkey "Export PO %s " gname; + let fhead = Wpo.file_for_head ~gid in + Wp_parameters.debug ~dkey "DO HEADER in %s" fhead ; + Command.pp_to_file fhead + (fun fmt -> + Format.fprintf fmt "@[<v 0>Proof Obligation %s:@]@\n" gname ; + Format.fprintf fmt "Environment: %s@\n" export.env ; + List.iter (fun d -> Format.fprintf fmt "%a@\n" (Wpo.pp_dependency kf) d) dep ; + List.iter (fun w -> Format.fprintf fmt "%a@\n" Wpo.pp_warning w) wrn ; + ) ; + Wp_parameters.debug ~dkey "DONE HEADER in %s" fhead; + (* --- BODY --- *) + let fbody = Wpo.file_for_body ~gid in + Wp_parameters.debug ~dkey "DO BODY in %s" fbody ; + Command.pp_to_file fbody + (fun fmt -> + Format.fprintf fmt "@[<v 2>Goal %s:@ %a@]" gid F.pp_pred gpred ; + ) ; + Wp_parameters.debug ~dkey "DONE BODY in %s" fbody ; + (* --- WHY Others --- *) + let export_lgg l = + Wp_parameters.debug ~dkey "DO export goal in language %a" + Wpo.pp_language l; + Command.pp_to_file (Wpo.file_for_goal ~gid l ) + (fun fmt -> + match l with + | Wpo.L_why -> Why.export_goal fmt gid gpred + | Wpo.L_coq -> Coq.export_goal fmt gid gpred + | Wpo.L_altergo -> Ergo.export_goal fmt gid gpred + ) ; + Wp_parameters.debug ~dkey "DONE export goal in language %a" + Wpo.pp_language l; + in + + let export_all () = + export_lgg Wpo.L_why ; + export_lgg Wpo.L_coq ; + export_lgg Wpo.L_altergo; + in + ( + if !Config.is_gui || (Wp_parameters.debug_atleast 2) then + (Wp_parameters.debug ~dkey + "Into gui config, goal has to be produce in all languages"; + export_all () ) + else + (match active_lgg () with + | None -> () + | Some l ->export_lgg l + ) + ); + + (* --- Warnings --- *) + if wrn <> [] then + begin + let pp_warnings fmt ws = + let n = List.length ws in if n = 1 + then Format.pp_print_string fmt "1 warning" + else Format.fprintf fmt "%d warnings" n + in + let degenerated = List.exists (fun w -> w.Wpo.wrn_severe) wrn in + if not (Wp_parameters.Details.get ()) then + Wp_parameters.warning ~current:false ~once:true + "Use -wp-warnings for details about 'Stronger' and 'Degenerated' goals" ; + Wp_parameters.warning ~current:false + "%s goal %s (%a)" + (if degenerated then "Degenerated" else "Stronger") + gid pp_warnings wrn ; + if Wp_parameters.Details.get () then + List.iter + (fun w -> + Log.print_on_output + (fun fmt -> Wpo.pp_warning fmt w ; Format.pp_print_newline fmt ()) + ) wrn ; + end ; + + let emitter = + Emitter.create Me.name + ~correctness:[] ~tuning:[ Wp_parameters.Prover.parameter ] + in + + (* --- WPO --- *) + let wpo = { + Wpo.po_fun = kf ; + Wpo.po_bhv = bhv ; + Wpo.po_name = gname ; + Wpo.po_gid = gid ; + Wpo.po_model = Descr.shared ; + Wpo.po_env = export.env ; + Wpo.po_pid = propid ; + Wpo.po_dep = dep ; + Wpo.po_warn = wrn ; + Wpo.po_updater = emitter; + } + in + Wpo.add wpo ; + if F.is_true gpred then + Wpo.set_result wpo Wpo.WP Wpo.Valid ; + export.goals <- wpo :: export.goals + + (* ------------------------------------------------------------------------ *) + (* --- Goal Splitting --- *) + (* ------------------------------------------------------------------------ *) + + let build_wpos export kf bhv wrn dep propid gpred = + let gpred = Splitter.simplify gpred in + if Wp_parameters.Split.get () || Wp_parameters.Invariants.get () || + (WpPropId.is_assigns propid && PO.assigns_method() = Mcfg.EffectAssigns) + then + let goals = Splitter.split (PO.assigns_method ()) gpred in + if Bag.is_empty goals then + export_wpo export kf bhv wrn dep propid F.p_true + else + WpAnnot.split (export_wpo export kf bhv wrn dep) propid goals + else + export_wpo export kf bhv wrn dep propid gpred + + let add_goal export kf bhv po = + let gpred = CV.zip po.PO.g_prop in + let wrn = ref [] in + let dep = ref [] in + PO.iter_description + (fun w -> wrn := w :: !wrn) + (fun d -> dep := d :: !dep) + po.PO.g_descr ; + build_wpos export kf bhv (List.rev !wrn) (List.rev !dep) po.PO.g_id gpred + + (* ------------------------------------------------------------------------ *) + (* --- Proof Obilgation Generation --- *) + (* ------------------------------------------------------------------------ *) + + class computer = + object + + val mutable wptasks = [] + val mutable exported = None + + method add strategies = + wptasks <- strategies :: wptasks + + method compute = + begin + + exported <- None ; + Wp_error.set_model Descr.name ; + F.clear () ; + let env = Wpo.new_env ~context:Descr.context in + let export = { env=env ; goals=[] } in + + (* Generates Wpos and accumulate exported goals *) + List.iter + (fun (strategies) -> + List.iter + (fun strategy -> + let cfg = WpStrategy.cfg_of_strategy strategy in + let kf = Cil2cfg.cfg_kf cfg in + let names = WpAnnot.missing_rte kf in + if names <> [] then + Wp_parameters.warning ~current:false ~once:true + "Missing RTE guards" ; + !Db.progress (); + let bhv = WpStrategy.behavior_name_of_strategy strategy in + let goals,annotations = WP.compute cfg strategy in + if Wp_parameters.Dot.get () then + ignore (Cil2cfg.dot_wp_res cfg Descr.shared annotations) ; + List.iter + (List.iter + (add_goal export kf bhv)) + goals + ) strategies + ) wptasks ; + + if export.goals <> [] then + begin + + (* --- Env Description --- *) + let ctxt = Wpo.file_for_ctxt ~env in + Wp_parameters.debug ~dkey "DO ENV DESCP %s" ctxt ; + Command.pp_to_file ctxt + (fun fmt -> F.iter_all (F.pp_section fmt) (F.pp_decl fmt)) ; + Wp_parameters.debug ~dkey "DONE ENV DESCP %s" ctxt ; + + let export_env_lgg l = + Wp_parameters.debug ~dkey "DO export env for %a" Wpo.pp_language l ; + Command.pp_to_file (Wpo.file_for_env ~env l) + (fun fmt -> + match l with + | Wpo.L_coq -> Format.fprintf fmt + "Require Import Reals.@\n\ + Require Import wp.@\n\ + Require Import %s.@\n" + (Wpo.coq_for_model Descr.shared) ; + F.iter_all (Coq.export_section fmt) (Coq.export_decl fmt) + | Wpo.L_why -> + F.iter_all (Why.export_section fmt) (Why.export_decl fmt) + | Wpo.L_altergo -> + F.iter_all (Ergo.export_section fmt) (Ergo.export_decl fmt) + ) + in + if !Config.is_gui || Wp_parameters.debug_atleast 2 then + begin + export_env_lgg Wpo.L_why ; + export_env_lgg Wpo.L_coq ; + export_env_lgg Wpo.L_altergo ; + end + else + begin + match active_lgg () with + | None -> () + | Some l -> export_env_lgg l + end + + end + else + Wpo.release_env env ; + + (* --- Generated Goals --- *) + export.goals + + end (* method compute *) + + end (* class computer *) + + let create () = (new computer :> computer) + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cfgpropid.ml frama-c-20111001+nitrogen+dfsg/src/wp/cfgpropid.ml --- frama-c-20110201+carbon+dfsg/src/wp/cfgpropid.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cfgpropid.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,317 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +type dnode = { + dn_id : int; + dn_warn : Wpo.warning list; + dn_depends : Property.t list; + dn_source : dnode list; +} + +module Sint = Set.Make + (struct type t = int let compare = Datatype.Int.compare end) + +let iter_dnodes f d = + let rec iter marked f d = + if not (Sint.mem d.dn_id !marked) then + ( (f d:unit) ; marked := Sint.add d.dn_id !marked ; + List.iter (iter marked f) d.dn_source ) + in iter (ref Sint.empty) f d + +let pp_list pp fmt xs = + List.iter (fun x -> pp fmt x ; Format.pp_print_newline fmt ()) xs + +let pp_dnode fmt d = + iter_dnodes + (fun d -> + pp_list Wpo.pp_warning fmt d.dn_warn ; + pp_list Wpo.pp_depend fmt d.dn_depends ; + ) d + +module Create (W : Mcfg.S) = +struct + + type t_env = W.t_env + let new_env = W.new_env + + type description = dnode + + type t_goal = { + g_id : WpPropId.prop_id ; + g_prop : W.t_prop; + g_descr : dnode; + } + + type t_prop = t_goal list + + let pp_goal fmt name g = + begin + Format.fprintf fmt "@[<v 0>Proof Obligation %a:@]@\n" WpPropId.pp_id_name g.g_id ; + pp_dnode fmt g.g_descr ; + Format.fprintf fmt "@[<v 2>Goal %s:@ %a@]@." name W.pretty g.g_prop ; + end + + let pp_descr fmt g = + Format.fprintf fmt "Proof Obligation for %a:@\n" + WpPropId.pretty g.g_id ; + pp_dnode fmt g.g_descr + + let iter_description fwrn fdep d = + iter_dnodes + (fun d -> + List.iter fwrn d.dn_warn ; + List.iter fdep d.dn_depends ; + ) d + + let pp_goalx fmt g = pp_goal fmt "" g + + let pretty = pp_list pp_goalx + + let empty = [] + + let dnode_cpt = ref 0 + + let make_goal prop_id process dsource = + let collect = Datalib.Collector.push () in + let p = + try process () + with e -> + ignore (Datalib.Collector.pop collect) ; + (* TODO : catch the exception here to not break the wp calculus *) + raise e + in + let warns, depends = Datalib.Collector.pop collect in + let id = incr dnode_cpt; !dnode_cpt in + let dn = { + dn_id = id ; + dn_warn = warns ; + dn_depends = depends ; + dn_source = dsource ; + } in { + g_id = prop_id ; + g_prop = p ; + g_descr = dn ; + } + + let rec merge goals1 goals2 = + (* List.merge sort_obligs opl1 opl2 : no, because keeps duplicates *) + match goals1, goals2 with + | _, [] -> goals1 + | [], _ -> goals2 + | g1::tl1, g2::tl2 -> + let cmp = WpPropId.compare_prop_id g1.g_id g2.g_id in + if cmp < 0 then g1::(merge tl1 goals2) + else if cmp > 0 then g2::(merge goals1 tl2) + else + let g = make_goal g1.g_id + (fun () -> W.merge g1.g_prop g2.g_prop) + [g1.g_descr; g2.g_descr] + in g::(merge tl1 tl2) + + let add_hyp env h goals = + let f p () = W.add_hyp env h p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let build_prop_of_from env pre goals = + let f p () = W.build_prop_of_from env pre p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let add_goal env g goals = + let new_prop () = W.add_goal env g W.empty in + let g = make_goal (WpPropId.pred_info_id g) new_prop [] in + merge [g] goals + + let add_axiom id name labels axiom = + let collect = Datalib.Collector.push () in + W.add_axiom id name labels axiom; + let warns, depends = Datalib.Collector.pop collect in + begin + List.iter + (fun w -> + Wp_parameters.warning "Warning for Axiom %s:@\nFrom %s: %s@\nEffect: %s" + name w.Wpo.wrn_source w.Wpo.wrn_reason w.Wpo.wrn_effect) + warns ; + List.iter + (fun d -> + Wp_parameters.warning "Warning for Axiom %s:@\nDepends on %a" + name Description.pp_property d) + depends ; + end + + let add_assigns env assigns goals = + let f () = W.add_assigns env assigns W.empty in + let new_goal = make_goal (WpPropId.assigns_info_id assigns) f [] in + if new_goal.g_prop = W.empty then goals + else merge [new_goal] goals + + let assigns_method = W.assigns_method + + let init_value env lv ty e_opt goals = + let f p () = W.init_value env lv ty e_opt p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let init_range env lv ty ka kb goals = + let f p () = W.init_range env lv ty ka kb p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let assign env lv e goals = + let f p () = W.assign env lv e p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let return env e goals = + let f p () = W.return env e p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let test env c goals_t goals_f = + let test pt pf () = W.test env c pt pf in + let rec merge lt lf = match lt, lf with + | [], [] -> [] + | g::lt, [] -> + let dsource = [g.g_descr] in + let g = make_goal g.g_id (test g.g_prop W.empty) dsource in + g::(merge lt lf) + | [], g::lf -> + let dsource = [g.g_descr] in + let g = make_goal g.g_id (test W.empty g.g_prop) dsource in + g::(merge lt lf) + | gt::tlt, gf::tlf -> + let cmp = WpPropId.compare_prop_id gt.g_id gf.g_id in + if cmp < 0 then + let dsource = [gt.g_descr] in + let g = make_goal gt.g_id (test gt.g_prop W.empty) dsource in + g::(merge tlt lf) + else if cmp > 0 then + let dsource = [gf.g_descr] in + let g = make_goal gf.g_id (test W.empty gf.g_prop) dsource in + g::(merge lt tlf) + else + let dsource = [gt.g_descr; gf.g_descr] in + let g = make_goal gf.g_id (test gt.g_prop gf.g_prop) dsource in + g::(merge tlt tlf) + in merge goals_t goals_f + + (** merge the switch branches : + * @param e : switch expression, + * @param cases : a list of (case expression, wp for that case), + * @param p_def : wp for the default branch. + * Because each wp is a list, it is not so easy to merge. + * So we decide to chose a simple, but not optimized, algorithm : + * - we first collect a sorted list of all the ids in every branches, + * - we then process each id but getting the wp for this id in each branch, + * - and we then put back things together. + *) + let switch env e cases p_def = + let rec add_id ids new_id = match ids with [] -> [new_id] + | id::other_ids -> let cmp = WpPropId.compare_prop_id new_id id in + if cmp = 0 then ids (* new_id already in *) + else if cmp < 0 then new_id::ids + else id::(add_id other_ids new_id) + in + let collect_id ids g = add_id ids g.g_id in + let collect_ids ids (_, lp) = List.fold_left collect_id ids lp in + let ids = List.map (fun g -> g.g_id) p_def in + let ids = List.fold_left collect_ids ids cases in + (* we now have all the ids found in all the lists *) + let get_p_id id goals = + try + let g = + List.find (fun g -> WpPropId.compare_prop_id id g.g_id = 0) goals + in g.g_prop + with Not_found -> W.empty + in + let get_descr_id id = + let add_goal acc g = + if WpPropId.compare_prop_id id g.g_id = 0 then g.g_descr::acc + else acc + in + let add_goals = List.fold_left add_goal in + let acc = add_goals [] p_def in + List.fold_left (fun acc (_, gs) -> add_goals acc gs) acc cases + in + let process_id id = + let id_p_def = get_p_id id p_def in + let id_cases = + List.map (fun (cond, lp) -> (cond, get_p_id id lp)) cases + in + let f () = W.switch env e id_cases id_p_def in + let d = get_descr_id id in + make_goal id f d + in List.map process_id ids (* ids are sorted => goals are also sorted *) + + (* -------------------------------------------------------------------------- *) + (* --- Call Rules --- *) + (* -------------------------------------------------------------------------- *) + + let call_goal_precond wenv stmt kf args ~pre goals = + let new_prop p () = + W.call_goal_precond wenv stmt kf args ~pre:[p] W.empty + in + let preconds = + List.map + (fun p -> make_goal (WpPropId.pred_info_id p) (new_prop p) []) pre + in + merge preconds goals + + let call wenv stmt lv kf args ~pre ~post ~pexit ~assigns ~p_post ~p_exit = + let wp ~post ~pexit p_post p_exit () = + W.call wenv stmt lv kf args + ~pre ~post ~pexit ~assigns ~p_post ~p_exit + in + let g_post = + List.map + (fun g -> + make_goal g.g_id (wp ~post ~pexit:[] g.g_prop W.empty) + [g.g_descr]) + p_post + in + let g_exit = + List.map + (fun g -> + make_goal g.g_id (wp ~post:[] ~pexit W.empty g.g_prop) + [g.g_descr]) + p_exit + in + merge g_post g_exit + + let use_assigns env id assigns goals = + let f p () = W.use_assigns env id assigns p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let label env l goals = + let f p () = W.label env l p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let scope env vars sc goals = + let f p () = W.scope env vars sc p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let close env goals = + let f p () = W.close env p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + + let tag t goals = + let f p () = W.tag t p in + List.map (fun g -> make_goal g.g_id (f g.g_prop) [g.g_descr]) goals + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cfgpropid.mli frama-c-20111001+nitrogen+dfsg/src/wp/cfgpropid.mli --- frama-c-20110201+carbon+dfsg/src/wp/cfgpropid.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cfgpropid.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,45 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Indexed goals by [prop_id] *) + +module Create (W : Mcfg.S) : +sig + type description + type t_goal = { + g_id : WpPropId.prop_id ; + g_prop : W.t_prop; + g_descr : description; + } + + val pp_goal : Format.formatter -> string -> t_goal -> unit + + val pp_descr : Format.formatter -> t_goal -> unit + + val iter_description : + (Wpo.warning -> unit) -> + (Property.t -> unit) -> + description -> unit + + include Mcfg.S with type t_prop = t_goal list + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cfgWeakestPrecondition.ml frama-c-20111001+nitrogen+dfsg/src/wp/cfgWeakestPrecondition.ml --- frama-c-20110201+carbon+dfsg/src/wp/cfgWeakestPrecondition.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cfgWeakestPrecondition.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,880 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Generator of Preconditions --- *) +(* -------------------------------------------------------------------------- *) + +open Cil_types +open Wp_error + +module Create + (WpModel: + sig + include Mwp.S + val model : string + end) + = +struct + + module F = WpModel.F + module D = WpModel.L + module E = Translate_expr.Create(WpModel) + module L = Translate_prop.Create(WpModel) + + let predicate = Wp_error.protect_translation L.prop + let expr = Wp_error.protect_translation E.expr + let addr = Wp_error.protect_translation E.addr + let cond = Wp_error.protect_translation E.prop + let cast = Wp_error.protect_translation3 E.expr_cast + + type t_env = F.pool * L.env + + type t_prop = assigns_kind * property + + and property = { + bindings : D.bindings ; + property : F.pred ; + } + + and assigns_kind = + | NoAssigns + | EffectAssigns of effect_assigns + + and effect_assigns = { + a_pid : WpPropId.prop_id ; + a_label : Clabels.c_label ; + a_effect : F.var ; (* accumulated zones for effects *) + a_locals : F.var ; (* accumulated zones for local variables *) + } + + + let empty = NoAssigns , { + bindings = D.closed ; + property = F.p_true ; + } + + let zip (_,omega) = + D.close omega.bindings omega.property + + let merge_assigns s1 s2 = + match s1,s2 with + | NoAssigns,NoAssigns -> NoAssigns + | NoAssigns,a -> a + | a,NoAssigns -> a + | EffectAssigns a1 , EffectAssigns a2 when a1 == a2 -> s1 + | _ -> Wp_parameters.fatal "Merging different assigns goals" + + let merge_property f w1 w2 = + { + bindings=D.closed ; + property=f + (D.close w1.bindings w1.property) + (D.close w2.bindings w2.property) ; + } + + let is_empty (_,p) = F.is_true p.property + + let merge (s1,p1) (s2,p2) = + if F.is_true p2.property then (s1,p1) else + if F.is_true p1.property then (s2,p2) else + merge_assigns s1 s2 , merge_property F.p_and p1 p2 + + let pretty fmt wp = F.pp_pred fmt (zip wp) + + let new_env ?(lvars=[]) kf = + let pool = F.pool () in + pool, L.add_logic_vars (L.env kf ()) pool lvars + + type closing = + | Keep_opened + | Close_context + + type assigns = + | Keep_assigns + | Clear_assigns + | Label_assigns of Clabels.c_label + | Goal_assigns of assigns_kind ref + + (* --- Utilities --- *) + + let pp_vars fmt = function + | [] -> Format.pp_print_string fmt "-" + | x::xs -> + Format.fprintf fmt "@[<hov 2>%s" x.vname ; + List.iter + (fun x -> Format.fprintf fmt ",@,%s" x.vname) + xs ; + Format.fprintf fmt "@]" + + (* ------------------------------------------------------------------------ *) + (* --- Context Management --- *) + (* ------------------------------------------------------------------------ *) + + let close_property where context q = function + | Keep_opened -> + let bindings = D.pop where context in + { + bindings = bindings ; + property = q ; + } + | Close_context -> + { + bindings = D.closed ; + property = D.flush where context q ; + } + + exception Failed + + let on_context (pool,env) (where:string) + (akind,omega) closing assigns + (f : L.env -> assigns_kind -> F.pred -> F.pred) : t_prop + = + let context = D.push where pool omega.bindings in + try + let wp = ref F.p_false in + begin + try + let prop = + try f env akind omega.property + with Failed -> F.p_false + in + let huge = + let m = Wp_parameters.Huge.get () in + if m < 1 then 1 else if m > 29 then max_int else 1 lsl m + in + if F.huge_pred huge prop then + (raise(Wp_error.Error("WP","Huge property"))) ; + wp := prop ; + with err -> + let (source,reason) = Wp_error.protect err in + Datalib.Collector.add_warning ~source ~reason ~severe:true + "Abort goal generation" ; + end ; + (* f must be computed before, because of lazy bindings for assign goals *) + let asgns = + match assigns , akind with + | Goal_assigns gref , _ -> !gref + | Keep_assigns , a -> a + | Clear_assigns , _ | _ , NoAssigns -> NoAssigns + | Label_assigns l , EffectAssigns a when a.a_label = l -> + let ze = WpModel.dzone_empty () in + wp := D.subst a.a_effect ze (D.subst a.a_locals ze !wp) ; + NoAssigns + | Label_assigns _ , a -> a + in + asgns , close_property where context !wp closing + with err -> + D.kill where context ; + raise err + + let label env lab wp = + on_context env "label" wp Keep_opened (Label_assigns lab) + (fun env _assigns p -> + if lab = Clabels.Here then p else + match L.find_mem env lab with + | Some at -> + let here = L.mem_at env Clabels.Here in + let wp = WpModel.update ~at ~here p in + Clabels.label F.p_named lab wp + | None -> p) + + let tag t (akind,p) = (akind,{ p with property = F.p_named t p.property }) + + (* ------------------------------------------------------------------------ *) + (* --- Hypotheses and Goal Management --- *) + (* ------------------------------------------------------------------------ *) + + let merge_with f (a,p) (a',p') = + merge_assigns a a' , merge_property f p p' + + let add_hyp env h wp = + on_context env "add_hyp" wp Keep_opened Keep_assigns + (fun env _assigns p -> + if F.is_true p then p else + let hid, hp = h in + let pid = WpPropId.property_of_id hid in + match predicate env hp with + | Result h -> + Datalib.Collector.add_depend pid ; F.p_implies h p + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored hypothesis %a" Description.pp_property pid ; p) + + let add_goal env g wp = + on_context env "add_goal" wp Keep_opened Clear_assigns + (fun env _assigns p -> + if F.is_false p then p else + let pid, pn = g in + match predicate env pn with + | Result g -> + F.p_and g p + | Warning(source,reason) -> + Datalib.Collector.add_warning ~severe:true ~source ~reason + "Goal %a can not be translated" + Description.pp_property (WpPropId.property_of_id pid) ; + F.p_false) + + (* ------------------------------------------------------------------------ *) + (* --- Axiom Rule --- *) + (* ------------------------------------------------------------------------ *) + + let add_axiom _id name labels pn = + match + Wp_error.protect_translation3 L.add_axiom name labels pn + with + | Result () -> () + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored user-defined axiom '%s'" name + + (* ------------------------------------------------------------------------ *) + (* --- Initialisation Rule --- *) + (* ------------------------------------------------------------------------ *) + + exception SkipInit + + let compute_init_loc mem lv = + match addr mem lv with + | Warning(source,reason) -> + Datalib.Collector.add_warning + ~severe:false ~source ~reason + "No translation for init l-value '%a'" !Ast_printer.d_lval lv ; + raise SkipInit + | Result loc -> loc + + let compute_init_value mem vexp = + match expr mem vexp with + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored r-value of initializer" ; + raise SkipInit + | Result value -> value + + let init_value env lv typ e_opt wp = + on_context env "init_value" wp Keep_opened Keep_assigns + (fun env _assigns p -> + try + let mem = L.mem_at env Clabels.Here in + let obj = Ctypes.object_of typ in + let loc = compute_init_loc mem lv in + let loaded = WpModel.logic_of_value (WpModel.load mem obj loc) in + match e_opt with + | None -> + begin + match WpModel.symb_is_init obj with + | Some p_name -> F.p_implies (F.p_app1 p_name loaded) p + | None -> p + end + + | Some vexp -> + let value = + WpModel.logic_of_value (compute_init_value mem vexp) + in + F.p_implies (WpModel.equal obj loaded value) p + + with SkipInit -> p) + + let init_range env lv typ_elt ka kb wp = + on_context env "init_range" wp Keep_opened Keep_assigns + (fun env _assigns p -> + try + let mem = L.mem_at env Clabels.Here in + let obj = Ctypes.object_of typ_elt in + let loc = compute_init_loc mem lv in + let loaded = WpModel.logic_of_value (WpModel.load mem obj loc) in + match WpModel.symb_is_init_range obj with + | Some p_range -> + F.p_implies + (F.p_app3 p_range loaded (F.e_int64 ka) (F.e_int64 kb)) p + | None -> p + with SkipInit -> p) + + (* ------------------------------------------------------------------------ *) + (* --- Assignment Rule --- *) + (* ------------------------------------------------------------------------ *) + + let assign env lv e wp = + on_context env "assign" wp Keep_opened Keep_assigns + (fun env assigns p -> + let mem = L.mem_at env Clabels.Here in + match addr mem lv with + | Warning(source,reason) -> + Datalib.Collector.add_warning + ~severe:true ~source ~reason + "No translation for l-value '%a'" !Ast_printer.d_lval lv ; + F.p_false + | Result l -> + let te = Cil.typeOf e in + let obj = Ctypes.object_of te in + let wp = + match expr mem e with + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored r-value of assignment" ; + let modified = F.Aloc(obj,l) in + D.havoc_static (WpModel.subst_havoc mem modified) p + | Result v -> + let t = Ctypes.object_of (Cil.typeOf e) in + WpModel.subst_lval mem t l v p + in + begin + match assigns with + | NoAssigns -> wp + | EffectAssigns a -> + let zl = WpModel.dzone_assigned mem (F.Aloc(obj,l)) in + let zs = WpModel.dzone_union (F.var a.a_effect) zl in + D.subst a.a_effect zs wp + end ) + + (* ------------------------------------------------------------------------ *) + (* --- Return Rule --- *) + (* ------------------------------------------------------------------------ *) + + let return env e wp = + on_context env "return" wp Keep_opened Keep_assigns + (fun env _assigns p -> + match e with + | None -> p + | Some e -> + begin + let mem = L.mem_at env Clabels.Here in + match expr mem e with + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored returned value" ; + L.subst_result env None p + | Result v -> + let ty_to = L.result_type env in + let ty_from = Cil.typeOf e in + let r_cast = cast ty_to ty_from v in + begin + match r_cast with + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored returned value (because of a cast)" ; + L.subst_result env None p + | Result v -> L.subst_result env (Some v) p + end + end) + + (* ------------------------------------------------------------------------ *) + (* --- Conditional Rule --- *) + (* ------------------------------------------------------------------------ *) + + let test env e wpt wpf = + let pt = zip wpt in + let pf = zip wpf in + let wpe = merge_assigns (fst wpt) (fst wpf) , snd empty in + on_context env "test" wpe Keep_opened Keep_assigns + (fun env _assigns _true -> + match cond (L.mem_at env Clabels.Here) e with + | Result b -> + F.p_and + (F.p_named "Then" (F.p_implies b pt)) + (F.p_named "Else" (F.p_implies (F.p_not b) pf)) + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored condition of if-statement (%a)" !Ast_printer.d_exp e ; + F.p_and pt pf) + + (* ------------------------------------------------------------------------ *) + (* --- Switch Rule --- *) + (* ------------------------------------------------------------------------ *) + + let case_of_exp m_here e = + match Ctypes.get_int e with + | Some k -> F.e_int64 k + | None -> + match expr m_here e with + | Result( WpModel.V_int(_,term) ) -> term + | Result( _ ) -> + Datalib.Collector.add_warning + ~severe:true ~source:"wp" + ~reason:"non-integer expression" + "Can not translate switch statement@[@ (%a)@]" + !Ast_printer.d_exp e ; + raise Failed + | Warning(source,reason) -> + Datalib.Collector.add_warning + ~severe:true ~source ~reason + "Can not translate switch statement@[@ (%a)@]" + !Ast_printer.d_exp e ; + raise Failed + + let switch env e wp_cases wp_def = + let cases = List.map (fun (es,wp) -> es , zip wp) wp_cases in + let p_def = zip wp_def in + let assigns = + List.fold_left + (fun ak (_es,wp) -> merge_assigns ak (fst wp)) + (fst wp_def) wp_cases in + let wpe = assigns , { (snd empty) with property = p_def } in + on_context env "swith" wpe Keep_opened Keep_assigns + (fun env _assigns _true -> + + let m_here = L.mem_at env Clabels.Here in + let typ_e = Cil.typeOf e in + let int_e = case_of_exp m_here e in + let t = WpModel.tau_of_object (Ctypes.object_of typ_e) in + let var_e = D.fresh "k" (Formula.Acsl(t,Ctype typ_e)) in + let val_e = F.var var_e in + + let (default,cases) = + List.fold_left + (fun (default,cases) (es_case,p_case) -> + let ks = List.map (case_of_exp m_here) es_case in + let hs = F.p_disj (List.map (F.p_eq val_e) ks) in + let ds = F.p_conj (List.map (F.p_neq val_e) ks) in + F.p_and ds default , + F.p_and (F.p_implies hs p_case) cases + ) (F.p_true , F.p_true) cases + in + let wp_switch = F.p_and cases (F.p_implies default p_def) in + D.subst var_e int_e wp_switch) + + (* ------------------------------------------------------------------------ *) + (* --- Scope Rule --- *) + (* ------------------------------------------------------------------------ *) + + let scope env vars sc wp = + on_context env "scope" wp Keep_opened Keep_assigns + (fun env assigns p -> + let mem = L.mem_at env Clabels.Here in + let wp = WpModel.local_scope mem vars sc p in + begin + match assigns , sc with + | EffectAssigns a , (Mcfg.SC_Block_in | Mcfg.SC_Function_frame) -> + let zs = + List.fold_left + (fun zs x -> + let te = Ctypes.object_of x.vtype in + let ax = F.Aloc(te,WpModel.cvar mem x) in + let zx = WpModel.dzone_assigned mem ax in + WpModel.dzone_union zs zx) + (F.var a.a_locals) vars + in + D.subst a.a_locals zs wp + + | _ -> wp + end) + + (* ------------------------------------------------------------------------ *) + (* --- Build property to prove the FROMs --- *) + (* ------------------------------------------------------------------------ *) + + (* TODO: ask Loïc if the parameters for [on_context] are correct + * because I don't really understand what it means... [2011-07-06-Anne]. *) + let build_prop_of_from wenv (pre:WpPropId.pred_info list) wp = + on_context wenv "build_froms" wp Keep_opened Keep_assigns + (fun env _assigns p -> + let alpha, p' = F.p_more_alpha_cv F.empty_alpha p in + let p = F.p_implies p p' in + let add_pre (alpha, p) (id, pre) = + let pid = WpPropId.property_of_id id in + match predicate env pre with + | Result pre -> + let pre = + match L.find_mem env Clabels.Pre with + | Some at -> + let here = L.mem_at env Clabels.Here in + WpModel.update ~at ~here pre + | None -> pre + in + Datalib.Collector.add_depend pid ; + let p = F.p_implies pre p in + let alpha', pre' = F.p_more_alpha_cv alpha pre in + let p = F.p_implies pre' p in + alpha', p + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Ignored hypothesis %a" Description.pp_property pid ; + alpha, p + in + let alpha, p = List.fold_left add_pre (alpha, p) pre in + let vars = F.fold_alpha (fun _v v' acc -> v'::acc) alpha [] in + let p = F.p_forall vars p in + let p = F.p_forall (L.collect_logic_vars env) p in + p + ) + + (* ------------------------------------------------------------------------ *) + (* --- Closing Goal --- *) + (* ------------------------------------------------------------------------ *) + + let close env wp = + on_context env "close" wp Close_context Clear_assigns + (fun env _assigns p -> + let pfinal = WpModel.quantify (L.mem_at env Clabels.Here) p in + let xs = F.freevars pfinal in + if xs <> [] then + (Datalib.Collector.add_warning + ~severe:false ~source:"CFG" + ~reason:"Some labels may escape the control flow" + "Generalization of un-labeled values" ; + F.p_forall xs pfinal) + else pfinal) + + (* ------------------------------------------------------------------------ *) + (* --- Normal Assigns clauses --- *) + (* ------------------------------------------------------------------------ *) + + let rec translate_assigned_targets env assigned = + match assigned with + | [] -> Result [] + | lv::others -> + match translate_assigned_targets env others with + | Warning(p,m) -> Warning(p,m) + | Result acc -> + Wp_error.protect_translation + (fun e t -> L.assigned e t @ acc) + env lv + + let translate_assigned env assigned = + let lvset = List.fold_left + (fun lvset (loc,_from) -> + Cil_datatype.Term.Set.add loc.it_content lvset) + Cil_datatype.Term.Set.empty assigned + in + translate_assigned_targets env (Cil_datatype.Term.Set.elements lvset) + + type assigned = A_everything | A_region of WpModel.loc F.assigned list + + let assigned_of_assigns env assigned = + match assigned with + | WritesAny -> A_everything + | Writes assigned -> + match translate_assigned env assigned with + | Result region -> A_region region + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Can not translate assign hypothesis, assigns everything instead" ; + A_everything + + (* Region for proving assign close *) + let assigned_for_assigns_goal kind label_from env assigned = + let env_assigned = + match kind with + | WpPropId.StmtAssigns -> L.env_at env label_from + | WpPropId.LoopAssigns -> env + in + match translate_assigned env_assigned assigned with + | Warning(wsrc, msg) -> raise (Wp_error.Error(wsrc,msg)) + | Result region -> region + + (* Apply region during wp *) + let havoc_region hkind caller_mem region prop = + match region with + | A_everything -> + WpModel.quantify caller_mem prop + | A_region region -> + let hs = + List.concat + (List.map (WpModel.subst_havoc caller_mem) region) in + begin + match hkind with + | WpPropId.StmtAssigns -> D.havoc_static hs prop + | WpPropId.LoopAssigns -> D.havoc_inductive hs prop + end + + (* ------------------------------------------------------------------------ *) + (* --- Assigns Method --- *) + (* ------------------------------------------------------------------------ *) + + let assigns_method () = + let mth = Wp_parameters.get_assigns_method () in + match mth with + | Mcfg.NoAssigns -> mth + | Mcfg.EffectAssigns when WpModel.effect_supported -> mth + | _ -> + if WpModel.assigns_supported + then Mcfg.NormalAssigns + else Mcfg.NoAssigns + + (* ------------------------------------------------------------------------ *) + (* --- Generate Observational Assigns Goal --- *) + (* ------------------------------------------------------------------------ *) + + let add_normal_assigns env pid label kind assigned wp = + on_context env "add_assigns" wp Keep_opened Clear_assigns + (fun env _noassigns prop -> + try + let label_from = Clabels.c_label label in + let mem1 = L.mem_at env label_from in + let mem2 = L.mem_at env Clabels.Here in + let region = assigned_for_assigns_goal kind label_from env assigned in + let goal = WpModel.assigns_goal mem1 region mem2 in + F.p_and goal prop + with e -> (* [VP 2011-02-03] Argl! *) + let (source,reason) = Wp_error.protect e in + Datalib.Collector.add_warning + ~severe:true ~source ~reason + "Goal for %a can not be translated" + WpPropId.pretty pid ; + F.p_false) + + (* ------------------------------------------------------------------------ *) + (* --- Prove assigns clauses with WpModel.dzones --- *) + (* ------------------------------------------------------------------------ *) + + let add_effect_assigns env pid label kind assigned wp = + let from = Clabels.c_label label in + let goal = ref NoAssigns in + on_context env "add_assigns" wp Keep_opened (Goal_assigns goal) + (fun env _noassigns _prop -> + try + let asgns = assigned_for_assigns_goal kind from env assigned in + let ze = D.fresh "ze" (Formula.Model WpModel.tau_of_dzone) in + let zx = D.fresh "zx" (Formula.Model WpModel.tau_of_dzone) in + let mem = L.mem_at env from in + let zs = List.fold_left + (fun zs a -> + let zx = WpModel.dzone_assigned mem a in + WpModel.dzone_union zs zx) + (F.var zx) asgns + in + goal := EffectAssigns { + a_pid = pid ; + a_label = from ; + a_effect = ze ; + a_locals = zx ; + } ; + WpModel.dzone_subset (F.var ze) zs + with e -> (* [VP 2011-02-03] Argl! *) + let (source,reason) = Wp_error.protect e in + Datalib.Collector.add_warning + ~severe:true ~source ~reason + "Goal for %a can not be translated" + WpPropId.pretty pid ; + F.p_false) + + (* ------------------------------------------------------------------------ *) + (* --- Dispatch Assigns Goal against selected method --- *) + (* ------------------------------------------------------------------------ *) + + let add_assigns env assigns wp = + let pid, a_desc = assigns in + let label = a_desc.WpPropId.a_label in + let kind = a_desc.WpPropId.a_kind in + let assigned = a_desc.WpPropId.a_assigns in + match assigned with + WritesAny -> + on_context env "add_assigns" wp Keep_opened + (Goal_assigns (ref NoAssigns)) + (fun _ _ _ -> F.p_true) (* Nothing to prove *) + | Writes assigns -> + match assigns_method () with + | Mcfg.NoAssigns -> + Wp_parameters.abort "Unsupported assigns with the model" + | Mcfg.NormalAssigns -> + add_normal_assigns env pid label kind assigns wp + | Mcfg.EffectAssigns -> + add_effect_assigns env pid label kind assigns wp + + (* Assigns Hypothesis *) + + let check_assigns m goal region wp = + match goal , region with + | NoAssigns , _ -> wp + | (EffectAssigns _ ) , A_everything -> + Datalib.Collector.add_warning + ~severe:true + ~reason:"Assigns everything during calculus" + "Can not prove the assign goal" ; + F.p_false + | EffectAssigns a , A_region zones -> + let ze = List.fold_left + (fun zs a -> + let za = WpModel.dzone_assigned m a in + WpModel.dzone_union zs za) + (F.var a.a_effect) zones + in + D.subst a.a_effect ze wp + + let use_assigns env hid a_desc wp = + on_context env "use_assigns" wp Close_context Keep_assigns + (fun env assignsgoal p -> + let kind = a_desc.WpPropId.a_kind in + let assigned = a_desc.WpPropId.a_assigns in + (match hid with + | Some h -> Datalib.Collector.add_depend (WpPropId.property_of_id h) + | None -> ()) ; + let region = assigned_of_assigns env assigned in + let mem = L.mem_at env Clabels.Here in + let p0 = check_assigns mem assignsgoal region p in + havoc_region kind mem region p0) + + (* -------------------------------------------------------------------------- *) + (* --- CALL NEW API --- *) + (* -------------------------------------------------------------------------- *) + + type callenv = { + callsite : Clabels.c_label ; (* Clabels.CallAt stmt *) + m_pre : WpModel.mem ; + m_post : WpModel.mem ; + v_args : WpModel.value list ; + } + + (* Local elements used in call_xxx *) + let callenv env stmt args = + let pre_label = Clabels.CallAt stmt.sid in + let m_pre = L.mem_at env pre_label in + let m_post = L.mem_at env Clabels.Here in + let translate_arg e = + match expr m_pre e with + | Warning(source,reason) -> + Datalib.Collector.add_warning ~source ~reason + "Can not call function, no translation for parameter '%a'" + !Ast_printer.d_exp e ; + raise Failed + | Result v -> v + in { + callsite = pre_label ; + m_pre = m_pre ; + m_post = m_post ; + v_args = List.map translate_arg args ; + } + + (* Utility function to handle errors in call_xxx *) + let do_prop env item p = + match predicate env p with + | Warning(source,reason) -> + Datalib.Collector.add_warning + ~source ~reason + "Ignored %s for function call" item ; + F.p_true + | Result p -> p + + let do_properties env item idps = + F.p_conj (List.map (fun (_id,p) -> do_prop env item p) idps) + + let rec do_hypothesis env item idps wp = + match idps with + | [] -> wp + | (_id,h)::hs -> F.p_implies (do_prop env item h) (do_hypothesis env item hs wp) + + (* Apply a returned value from a function call *) + let do_return call kf lvopt p_after = + let t_result = Kernel_function.get_return_type kf in + if Ctypes.is_void t_result then + ( p_after , None ) + else + let x_result = D.fresh "result" + (Formula.Acsl ((WpModel.tau_of_object (Ctypes.object_of t_result)), + Ctype t_result)) in + match lvopt with + | None -> p_after , Some x_result + | Some lv -> + let lv_t = Ctypes.object_of t_result in + let casted_result = + cast t_result (Cil.typeOfLval lv) + (WpModel.value_of_logic lv_t (F.var x_result)) + in + let v_result = match casted_result with + | Warning(source,reason) -> + Datalib.Collector.add_warning + ~severe:true ~source ~reason + "Can not cast the returned value" ; + raise Failed + | Result res -> res + in + + let p_with_result = + begin + (* TODO : check memory for computing return loc *) + match addr call.m_post lv with + | Warning(source, reason) -> + Datalib.Collector.add_warning + ~severe:true ~source ~reason + "Can not assign the returned value, no translation for l-value" ; + raise Failed + | Result loc -> + WpModel.subst_lval call.m_post lv_t loc v_result p_after + end + in + p_with_result , Some x_result + + (* ------------------------------------------------------------------------ *) + (* --- CALL Rule --- *) + (* ------------------------------------------------------------------------ *) + + let call_goal_precond caller_env stmt kf args ~pre wp = + on_context caller_env "call_goal_precond" wp Keep_opened Keep_assigns + (fun env _assigns p -> + let call = callenv env stmt args in + let env_pre = L.call_pre env kf call.v_args call.m_pre in + let preconds = do_properties env_pre "pre-condition" pre in + F.p_and preconds p) + + let add_dependencies = List.iter Datalib.Collector.add_depend + + let call_normal_only caller_env stmt lv kf args ~pre ~post ~assigns ~p_post = + on_context caller_env "call_normal" p_post Keep_opened Keep_assigns + (fun env assigns_method p_post -> + add_dependencies (WpAnnot.get_called_assigns kf) ; + add_dependencies (WpAnnot.get_called_post_conditions kf) ; + add_dependencies (WpAnnot.get_called_preconditions_at kf stmt) ; + let call = callenv env stmt args in + let p_after , x_result = do_return call kf lv p_post in + let env_pre = L.call_pre env kf call.v_args call.m_pre in + let env_post = L.call_post env kf call.v_args call.m_pre call.m_post x_result in + let p_called = do_hypothesis env_post "post-condition" post p_after in + let p_called = match x_result with + | None -> p_called + | Some x -> D.forall [x] p_called + in + let asgnd = assigned_of_assigns env_pre assigns in + let p_havoc = havoc_region WpPropId.StmtAssigns call.m_post asgnd p_called in + let p_before = do_hypothesis env_pre "pre-condition" pre p_havoc in + check_assigns call.m_pre assigns_method asgnd p_before) + + let call_exit_only caller_env stmt kf args ~pre ~pexit ~assigns ~p_exit = + on_context caller_env "call_normal" p_exit Keep_opened Keep_assigns + (fun env assigns_method p_exit -> + add_dependencies (WpAnnot.get_called_assigns kf) ; + add_dependencies (WpAnnot.get_called_exit_conditions kf) ; + add_dependencies (WpAnnot.get_called_preconditions_at kf stmt) ; + let call = callenv env stmt args in + let x_status = L.exit_status env in + let env_pre = L.call_pre env kf call.v_args call.m_pre in + let env_exit = L.call_exit env kf call.v_args call.m_pre call.m_post x_status in + let p_called = do_hypothesis env_exit "exit-condition" pexit p_exit in + let p_called = D.forall [x_status] p_called in + let asgnd = assigned_of_assigns env_pre assigns in + let p_havoc = havoc_region WpPropId.StmtAssigns call.m_post asgnd p_called in + let p_before = do_hypothesis env_pre "pre-condition" pre p_havoc in + check_assigns call.m_pre assigns_method asgnd p_before) + + let call caller_env stmt lv kf args ~pre ~post ~pexit ~assigns ~p_post ~p_exit = + let wp_post = + if is_empty p_post then p_post + else call_normal_only caller_env stmt lv kf args ~pre ~post ~assigns ~p_post + in + let wp_exit = + if is_empty p_exit then p_exit + else call_exit_only caller_env stmt kf args ~pre ~pexit ~assigns ~p_exit + in + merge wp_post wp_exit + +(* --- End of Weakest Precondition Rules --- *) + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cfgWeakestPrecondition.mli frama-c-20111001+nitrogen+dfsg/src/wp/cfgWeakestPrecondition.mli --- frama-c-20110201+carbon+dfsg/src/wp/cfgWeakestPrecondition.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cfgWeakestPrecondition.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,33 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** {1 VC Generator} *) +(* -------------------------------------------------------------------------- *) + +module Create + (WpModel:sig include Mwp.S val model: string end) + : +sig + include Mcfg.S + val zip : t_prop -> WpModel.F.pred +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cil2cfg.ml frama-c-20111001+nitrogen+dfsg/src/wp/cil2cfg.ml --- frama-c-20110201+carbon+dfsg/src/wp/cil2cfg.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cil2cfg.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,1330 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Build a CFG of a function keeping some information of the initial structure. + **) + +open Cil_types + +let dkey = "cil2cfg" (* debugging key *) +let debug fmt = Wp_parameters.debug ~dkey fmt +let debug2 fmt = Wp_parameters.debug ~dkey ~level:2 fmt + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Nodes} *) + +(** Be careful that only Bstmt are real Block statements *) +type block_type = + Bstmt of stmt | Bthen of stmt | Belse of stmt | Bloop of stmt | Bfct + (* added to identify 2 blocks for tests, else there are mixed up because same + * sid *) + +type node_type = + | Vstart | Vend | Vexit + | VfctIn | VfctOut (* TODO : not useful anymore -> Bfct *) + | VblkIn of block_type * block + | VblkOut of block_type * block + | Vstmt of stmt + | Vcall of stmt * lval option * exp * exp list + | Vtest of bool * stmt * exp (** bool=true for In and false for Out *) + | Vswitch of stmt * exp + | Vloop of bool option * stmt + (** boolean is is_natural. None means the node has not been detected + * as a loop *) + | Vloop2 of bool * int + +type node_info = { kind : node_type ; mutable reachable : bool } + +type node = node_info ref + +let node_type n = !n.kind + +let bkind_stmt bk = match bk with + | Bfct -> None + | Bstmt s | Bthen s | Belse s | Bloop s -> Some s + +let bkind_sid bk = match bk with + | Bfct -> 0 + | Bstmt s | Bthen s | Belse s | Bloop s -> s.sid + +type node_id = int * int + +(** gives a identifier to each CFG node in order to hash them *) +let node_type_id t = match t with + | Vstart -> (0, 0) + | VfctIn -> (0, 1) + | VfctOut -> (0, 2) + | Vexit -> (0, 3) + | Vend -> (0, 4) + | Vstmt s | Vtest (true, s, _) | Vswitch (s,_) | Vcall (s, _, _, _) -> + (1, s.sid) + | Vloop (_, s) -> (2, s.sid) + | Vloop2 (_, n) -> (3, n) + | VblkIn (Bfct, _) -> (4, 0) + | VblkIn (Bstmt s,_) -> (5, s.sid) + | VblkIn (Bthen s,_) -> (6, s.sid) + | VblkIn (Belse s,_) -> (7, s.sid) + | VblkIn (Bloop s,_) -> (8, s.sid) + | VblkOut (Bfct, _) -> (9, 0) + | VblkOut (Bstmt s,_) -> (10, s.sid) + | VblkOut (Bthen s,_) -> (11, s.sid) + | VblkOut (Belse s,_) -> (12, s.sid) + | VblkOut (Bloop s,_) -> (13, s.sid) + | Vtest (false, s, _) -> (14, s.sid) + +let node_id n = node_type_id (node_type n) + +let pp_bkind fmt bk = match bk with + | Bfct -> Format.fprintf fmt "fct" + | Bstmt s -> Format.fprintf fmt "stmt:%d" s.sid + | Bthen s -> Format.fprintf fmt "then:%d" s.sid + | Belse s -> Format.fprintf fmt "else:%d" s.sid + | Bloop s -> Format.fprintf fmt "loop:%d" s.sid + +let pp_node_type fmt n = match n with + | Vstart -> Format.fprintf fmt "<start>" + | VfctIn -> Format.fprintf fmt "<fctIn>" + | VfctOut -> Format.fprintf fmt "<fctOut>" + | Vend -> Format.fprintf fmt "<end>" + | Vexit -> Format.fprintf fmt "<exit>" + | VblkIn (bk,_) -> Format.fprintf fmt "<blkIn-%a>" pp_bkind bk + | VblkOut (bk,_) -> Format.fprintf fmt "<blkOut-%a>" pp_bkind bk + | Vcall (s, _, _, _) -> Format.fprintf fmt "<callIn-%d>" s.sid + | Vstmt s -> Format.fprintf fmt "<stmt-%d>" s.sid + | Vtest (b, s, _) -> + Format.fprintf fmt "<test%s-%d>" (if b then "In" else "Out") s.sid + | Vswitch (s,_) -> Format.fprintf fmt "<switch-%d>" s.sid + | Vloop (_, s) -> Format.fprintf fmt "<loop-%d>" s.sid + | Vloop2 (_, n) -> Format.fprintf fmt "<loop-n%d>" n + +let same_node v v' = + (node_id v) = (node_id v') + +(** the CFG nodes *) +module VL = struct + type t = node + + let hash v = let k = node_type v in Hashtbl.hash (node_type_id k) + + let equal v v' = same_node v v' + + let compare v v' = + let k = node_type v in + let k' = node_type v' in + Extlib.compare_basic (node_type_id k) (node_type_id k') + + let pretty fmt v = pp_node_type fmt (node_type v) +end + +let pp_node fmt v = VL.pretty fmt v + +let start_stmt_of_node v = match node_type v with + | Vstart | Vtest (false, _, _) | VblkOut _ + | VfctIn | VfctOut | Vend | Vexit | Vloop2 _ -> None + | VblkIn (bk, _) -> bkind_stmt bk + | Vstmt s | Vtest (true, s, _) | Vloop (_, s) | Vswitch (s,_) + | Vcall (s, _, _, _) + -> Some s + +let node_stmt_opt v = match node_type v with + | Vstart | Vtest (false, _, _) + | VfctIn | VfctOut | Vend | Vexit | Vloop2 _ -> None + | VblkIn (bk, _) | VblkOut (bk, _) -> bkind_stmt bk + | Vstmt s | Vtest (true, s, _) | Vloop (_, s) | Vswitch (s,_) + | Vcall (s, _, _, _) + -> Some s + +let node_stmt_exn v = + match node_stmt_opt v with None -> raise Not_found | Some s -> s + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Edge labels} *) + +type edge_type = + | Enone (** normal edge *) + | Ethen (** then branch : edge source is a Vtest *) + | Eelse (** else branch : edge source is a Vtest *) + | Eback (** back edge to a loop : the edge destination is a Vloop *) + | EbackThen (** Eback + Ethen *) + | EbackElse (** Eback + Eelse *) + | Ecase of (exp list) (** switch branch : edge source is a Vswitch. + Ecase [] for default case *) + | Enext (** not really a edge : gives the next node of a complex stmt *) + +(** the CFG edges *) +module EL = struct + + let compare_edge_type e1 e2 = + if e1 == e2 then 0 + else match e1, e2 with + | Enone, Enone | Ethen, Ethen | Eelse, Eelse | Eback, Eback + | EbackThen, EbackThen | EbackElse, EbackElse | Enext, Enext -> 0 + + | Ecase l1, Ecase l2 -> Extlib.list_compare Cil_datatype.Exp.compare l1 l2 + + | Enone, (Ethen | Eelse | Eback | EbackThen | EbackElse | Ecase _ | Enext) + | Ethen, (Eelse | Eback | EbackThen | EbackElse | Ecase _ | Enext) + | Eelse, (Eback | EbackThen | EbackElse | Ecase _ | Enext) + | Eback, (EbackThen | EbackElse | Ecase _ | Enext) + | EbackThen, (EbackElse | Ecase _ | Enext) + | EbackElse, (Ecase _ | Enext) + | Ecase _, Enext + -> -1 + + | Enext, (Ecase _ | EbackElse | EbackThen | Eback | Eelse | Ethen | Enone) + | Ecase _, (EbackElse | EbackThen | Eback | Eelse | Ethen | Enone) + | EbackElse, (EbackThen | Eback | Eelse | Ethen | Enone) + | EbackThen, (Eback | Eelse | Ethen | Enone) + | Eback, (Eelse | Ethen | Enone) + | Eelse, (Ethen | Enone) + | Ethen, Enone -> 1 + + type t = edge_type ref + + let compare (e1 : t) (e2 : t) = compare_edge_type !e1 !e2 + let default = ref Enone + let pretty fmt e = + let txt = match e with + | Enone -> "----" | Ethen -> "then" | Eelse -> "else" + | Eback -> "back" | EbackThen -> "then-back" | EbackElse -> "else-back" + | Ecase [] -> "default" + | Ecase l -> Pretty_utils.sfprintf "case(%a)" + (Pretty_utils.pp_list ~sep:", " !Ast_printer.d_exp) l + | Enext -> "(next)" + in Format.fprintf fmt "%s" txt +end + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Graph} *) + +(** the CFG is an ocamlgraph, but be careful to use it through the cfg function + * because some edges doesn't have the same meaning the some others... *) +module CFG = Graph.Imperative.Digraph.ConcreteLabeled(VL)(EL) + +(** Set of edges. *) +module Eset = Set.Make (CFG.E) + +(** Set of nodes. *) +module Nset = Set.Make (CFG.V) + +(** The final CFG is composed of the graph, but also : + * the function that it represents, + * an hashtable to find a CFG node knowing its hashcode, + * and the hashcode of the start node *) +type t = { + kernel_function : kernel_function; + graph : CFG.t; + spec_only : bool; + stmt_node : ((int*int), CFG.V.t) Hashtbl.t; + start_id : int; + unreachables : node_type list; + loop_nodes : (node list) option; + mutable loop_cpt : int; +} + +let new_cfg_env spec_only kf = { + kernel_function = kf; + spec_only = spec_only ; + graph = CFG.create (); + stmt_node = Hashtbl.create 97; + start_id = Cil.Sid.next (); + unreachables = []; + loop_nodes = None; + loop_cpt = 0; +} + +let cfg_kf cfg = cfg.kernel_function +let cfg_graph cfg = cfg.graph +let cfg_spec_only cfg = cfg.spec_only + +let unreachable_nodes cfg = cfg.unreachables + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 CFG edges} *) + +type edge = CFG.E.t + +let edge_type e = !(CFG.E.label e) +let edge_src e = CFG.E.src e +let edge_dst e = CFG.E.dst e + +let pp_edge fmt e = + Format.fprintf fmt "%a -%a-> %a" + pp_node (CFG.E.src e) EL.pretty (edge_type e) pp_node (CFG.E.dst e) + +let pred_e cfg n = + try + let edges = CFG.pred_e cfg.graph n in + List.filter (fun e -> (edge_type e) <> Enext) edges + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.pred_e] pb with node %a" pp_node n; []) + +let succ_e cfg n = + try + let edges = CFG.succ_e cfg.graph n in + List.filter (fun e -> (edge_type e) <> Enext) edges + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.succ_e] pb with node %a" pp_node n; []) + + +let is_back_edge e = match (edge_type e) with + | Eback | EbackThen | EbackElse -> true + | Enone | Ethen | Eelse | Ecase _ | Enext -> false + +let edge_key e = (VL.hash (edge_src e)), (VL.hash (edge_dst e)) + +let same_edge e1 e2 = (edge_key e1 = edge_key e2) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Iterators} ignoring the [Enext] edges *) + +let iter_nodes f cfg = CFG.iter_vertex f (cfg.graph) +let fold_nodes f cfg acc = CFG.fold_vertex f (cfg.graph) acc + +let iter_edges f cfg = + let f e = match (edge_type e) with Enext -> () | _ -> f e in + CFG.iter_edges_e f (cfg.graph) + +let iter_succ f cfg n = + let f e = + match (edge_type e) with Enext -> () | _ -> f (CFG.E.dst e) + in try CFG.iter_succ_e f (cfg.graph) n + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.iter_succ] pb with node %a" pp_node n) + +let fold_succ f cfg n acc = + let f e acc = + match (edge_type e) with Enext -> acc | _ -> f (CFG.E.dst e) acc + in try CFG.fold_succ_e f (cfg.graph) n acc + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.fold_succ] pb with node %a" pp_node n; acc) + +let fold_pred f cfg n acc = + let f e acc = + match (edge_type e) with Enext -> acc | _ -> f (CFG.E.src e) acc + in try CFG.fold_pred_e f (cfg.graph) n acc + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.fold_pred] pb with node %a" pp_node n; acc) + +let iter_succ_e f cfg n = + let f e = + match (edge_type e) with Enext -> () | _ -> f e + in try CFG.iter_succ_e f (cfg.graph) n + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.iter_succ_e] pb with node %a" pp_node n) + +let iter_pred_e f cfg n = + let f e = + match (edge_type e) with Enext -> () | _ -> f e + in try CFG.iter_pred_e f (cfg.graph) n + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.iter_pred_e] pb with node %a" pp_node n) + +let fold_pred_e f cfg n acc = + let f e acc = + match (edge_type e) with Enext -> acc | _ -> f e acc + in try CFG.fold_pred_e f (cfg.graph) n acc + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.fold_pred_e] pb with node %a" pp_node n; acc) + +let fold_succ_e f cfg n acc = + let f e acc = + match (edge_type e) with Enext -> acc | _ -> f e acc + in try CFG.fold_succ_e f (cfg.graph) n acc + with Invalid_argument _ -> + (Wp_parameters.warning "[cfg.fold_succ_e] pb with node %a" pp_node n; acc) + + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Getting information} *) + +let cfg_start cfg = Hashtbl.find cfg.stmt_node (node_type_id Vstart) + +let start_edge cfg = match succ_e cfg (cfg_start cfg) with [e] -> e + | _ -> Wp_parameters.fatal "[cfg] should have exactly ONE starting edge !" + +exception Found of node +let find_stmt_node cfg stmt = + let find n = match node_stmt_opt n with None -> () + | Some s -> if s.sid = stmt.sid then raise (Found n) + in + try (iter_nodes find cfg; raise Not_found) + with Found n -> n + +(** Get the edges going out a test node with the then branch first *) +let get_test_edges cfg v = + match succ_e cfg v with + | [e1; e2] -> + begin match (edge_type e1), (edge_type e2) with + | (Ethen|EbackThen), (Eelse|EbackElse) -> e1, e2 + | (Eelse|EbackElse), (Ethen|EbackThen) -> e2, e1 + | _, (Eelse|EbackElse) -> + Wp_parameters.fatal "[cfg] test node with invalid edges %a" + pp_edge e1 + | _, _ -> + Wp_parameters.fatal "[cfg] test node with invalid edges %a" + pp_edge e2 + end + | _ -> raise (Invalid_argument "[cfg:get_test_edges] not a test") + +let get_switch_edges cfg v = + match node_type v with + | Vswitch _ -> + begin + let get_case (cl, dl) e = match (edge_type e) with + | Ecase [] -> cl, e::dl + | Ecase c -> (c, e)::cl, dl + | _ -> Wp_parameters.fatal ("[cfg] switch node with invalid edges") + in match List.fold_left get_case ([],[]) (succ_e cfg v) with + | cl, [d] -> cl, d + | _ -> + Wp_parameters.fatal ("[cfg] switch node with several 'default' ?") + end + | _ -> raise (Invalid_argument "[cfg:get_switch_edges] not a switch") + +let get_call_out_edges cfg v = + let e1, e2 = match succ_e cfg v with + | [e1;e2] -> e1, e2 + | _ -> assert false + in + let en, ee = match node_type (edge_dst e1) , + node_type (edge_dst e2) with + | _, Vexit -> e1, e2 + | Vexit, _ -> e2, e1 + | _, _ -> assert false + in en, ee + +let get_edge_labels e = + let v_after = edge_dst e in + let l = match node_type v_after with + | Vstart -> assert false + | VfctIn -> [] + | Vexit | VfctOut -> [Clabels.Post] + | VblkIn (Bstmt s, _) -> [Clabels.mk_stmt_label s] + | Vtest (false, _, _) | VblkIn _ | VblkOut _ | Vend -> [] + | Vcall (s,_,_,_) -> + [Clabels.CallAt s.sid; Clabels.mk_stmt_label s] + | Vstmt s | Vtest (true, s, _) | Vswitch (s,_) -> + [Clabels.mk_stmt_label s] + | Vloop2 _ -> [] + | Vloop (_,s) -> + if is_back_edge e then [] + else [Clabels.mk_stmt_label s] + in + let v_before = edge_src e in + match node_type v_before with + | VfctIn -> Clabels.Pre::l + | Vloop (_, s) -> (Clabels.mk_loop_label s)::l + | _ -> l + +let next_edge cfg n = + let edges = match node_type n with + | VblkIn _ | Vswitch _ | Vtest _ | Vloop _ -> + let edges = CFG.succ_e cfg.graph n in + List.filter (fun e -> (edge_type e) = Enext) edges + | Vcall _ -> + let en, _ee = get_call_out_edges cfg n in [en] + | Vstmt _ -> + let edges = match CFG.succ_e cfg.graph n with + | (([] | _::[]) as edges) -> edges + | edges -> (* this case may happen in case of a loop + which is not really a loop : it is then a Vstmt, + and the Enext is not the succ_e. *) + List.filter (fun e -> (edge_type e) = Enext) edges + in edges + | _ -> + debug "[next_edge] not found for %a@." pp_node n; + raise Not_found (* No Enext information on this node *) + in + match edges with + | [] -> (* can append when nodes have been removed *) raise Not_found + | [e] -> e + | _ -> Wp_parameters.fatal "several (%d) Enext edges to node %a" + (List.length edges) pp_node n + +(** Find the node that follows the input node statement. +* The statement postcondition can then be stored to the edges before that node. +* @raise Not_found when the node after has been removed (unreachable) *) +let node_after cfg n = edge_dst (next_edge cfg n) + +let get_pre_edges cfg n = pred_e cfg n + +let get_post_edges cfg v = + try let v' = node_after cfg v in pred_e cfg v' + with Not_found -> [] + +let get_exit_edges cfg src = + debug "[get_exit_edges] of %a@." pp_node src; + let do_node n acc = + let add_exit e acc = + let dst = edge_dst e in + match node_type dst with + | Vexit -> + debug + "[get_exit_edges] add %a@." pp_edge e; + (* (succ_e cfg dst) @ acc *) + e :: acc + | _ -> acc + in fold_succ_e add_exit cfg n acc + in + let rec do_node_and_preds n acc = + let acc = do_node n acc in + if CFG.V.compare src n = 0 then acc + else do_preds n acc + and do_preds n acc = + fold_pred do_node_and_preds cfg n acc + in + let edges = try do_preds (node_after cfg src) [] with Not_found -> [] in + if edges = [] then + debug "[get_exit_edges] -> empty"; + edges + +let add_edges_before cfg src set e_after = + let rec add_preds set e = + let e_src = edge_src e in + if CFG.V.compare src e_src = 0 then set + else + let add_edge_and_preds e set = + if Eset.mem e set then set + else add_preds (Eset.add e set) e + in fold_pred_e add_edge_and_preds cfg e_src set + in add_preds set e_after + +let get_internal_edges cfg n = + let edges = try pred_e cfg (node_after cfg n) with Not_found -> [] in + let set = Eset.empty in + let set = List.fold_left (add_edges_before cfg n) set edges in + edges, set + +let rec get_edge_next_stmt cfg e = + let v_after = edge_dst e in + let get_next v = match succ_e cfg v with + | [e] -> get_edge_next_stmt cfg e + | [] | _ :: _ -> None (* nodes without statement should have one succ, + except the last one *) + in + match node_type v_after with + | VblkOut _ | VblkIn ((Bthen _|Belse _|Bloop _|Bfct),_) -> get_next v_after + | _ -> + match node_stmt_opt v_after with + | Some s -> Some s + | None -> get_next v_after + +let get_post_logic_label cfg v = + match get_post_edges cfg v with [] -> None + | e::_ -> (* TODO: is this ok to consider only one edge ? *) + match get_edge_next_stmt cfg e with + | None -> None + | Some s -> Some (Clabels.mk_logic_label s) + +let blocks_closed_by_edge cfg e = + let v_before = edge_src e in + let blocks = match node_type v_before with + | Vstmt s | Vtest (true, s, _) | Vloop (_, s) | Vswitch (s,_) -> + Cfg.clearFileCFG ~clear_id:false (Ast.get ()); + Cfg.computeFileCFG (Ast.get ()); + + begin match s.succs with + | [s'] -> Kernel_function.blocks_closed_by_edge s s' + | [] | _ :: _ -> + let s' = get_edge_next_stmt cfg e in + match s' with + | None -> [] + | Some s' -> + debug + "[blocks_closed_by_edge] found sid:%d -> sid:%d@." + s.sid s'.sid; + Kernel_function.blocks_closed_by_edge s s' + end + | _ -> (* TODO ? *) [] + in + let v_after = edge_dst e in + let blocks = match node_type v_after with + | VblkOut (Bfct, b) -> b::blocks + | _ -> blocks + in blocks + +let has_exit cfg = + try + let node = Hashtbl.find cfg.stmt_node (node_type_id Vexit) in + match pred_e cfg node with + | [] -> false + | _ -> true + with Not_found | Invalid_argument _ -> false + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Generic table to store things on edges} *) + +module type HEsig = sig + type ti + type t + val create : int -> t + val find : t -> edge -> ti + val find_all : t -> edge -> ti list + val add : t -> edge -> ti -> unit + val replace : t -> edge -> ti -> unit + val remove : t -> edge -> unit + val clear : t -> unit +end + +module HE (I : sig type t end) = struct + type ti = I.t + type t = ((int*int), ti) Hashtbl.t + let create n = Hashtbl.create n + let edge_key e = (VL.hash (edge_src e)), (VL.hash (edge_dst e)) + let find info e = Hashtbl.find info (edge_key e) + let find_all info e = Hashtbl.find_all info (edge_key e) + let add info e i = Hashtbl.add info (edge_key e) i + let replace info e i = Hashtbl.replace info (edge_key e) i + let remove info e = Hashtbl.remove info (edge_key e) + let clear info = Hashtbl.clear info +end + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {2 Building the CFG} *) + +let add_node env t = + let id = node_type_id t in + let n = {kind = t ; reachable = false } in + debug "add node : %a@." VL.pretty (ref n); + let n = CFG.V.create (ref n) in + Hashtbl.add env.stmt_node id n; + n + +let add_edge env n1 edge_type n2 = + let e = CFG.E.create n1 (ref edge_type) n2 in + debug "add edge : %a@." pp_edge e; + CFG.add_edge_e env.graph e + +let remove_edge env e = + debug "remove edge : %a@." pp_edge e; + CFG.remove_edge_e env.graph e + +let insert_loop_node env loop_head loop_kind = + let n_loop = add_node env loop_kind in + let mv_pred_edge e = + add_edge env (edge_src e) (edge_type e) n_loop; + remove_edge env e + in iter_pred_e mv_pred_edge env loop_head; + add_edge env n_loop Enone loop_head; + n_loop + +let init_cfg spec_only kf = + let env = new_cfg_env spec_only kf in + let start = add_node env (Vstart) in + let fct_in = add_node env (VfctIn) in + let _ = add_edge env start Enone fct_in in + let fct_out = add_node env (VfctOut) in + let nexit = add_node env (Vexit) in + let nend = add_node env (Vend) in + let _ = add_edge env fct_out Enone nend in + let _ = add_edge env nexit Enone nend in + env, fct_in, fct_out + +let get_node env t = + let id = node_type_id t in + debug "get_node: %a --> id:%d,%d" + pp_node_type t (fst id) (snd id); + try Hashtbl.find env.stmt_node id + with Not_found -> add_node env t + +(** In some cases (goto for instance) we have to create a node before having +* processed if through [cfg_stmt]. It is important that the created node +* is the same than while the 'normal' processing ! That is why +* this pattern matching might seem redondant with the other one. *) +let get_stmt_node env s = match s.skind with + | Instr (Call (res, fct, args, _)) -> + get_node env (Vcall (s, res, fct, args)) + | Block b -> get_node env (VblkIn (Bstmt s,b)) + | UnspecifiedSequence seq -> + let b = Cil.block_from_unspecified_sequence seq in + get_node env (VblkIn (Bstmt s,b)) + | If (e, _, _, _) -> get_node env (Vtest (true, s, e)) + | Loop _ -> get_node env (Vloop (None, s)) + | Break _ | Continue _ | Goto _ + | Instr _ | Return _ -> get_node env (Vstmt s) + | Switch (e, _, _, _) -> get_node env (Vswitch (s, e)) + | TryExcept _ | TryFinally _ -> + Wp_parameters.not_yet_implemented "[cfg] exception handling" + + +(** build the nodes for the [stmts], connect the last one with [next], +* and return the node of the first stmt. *) +let rec cfg_stmts env stmts next = match stmts with +| [] -> next +| [s] -> cfg_stmt env s next +| s::tl -> + let next = cfg_stmts env tl next in + let ns = cfg_stmt env s next in + ns + +and cfg_block env bkind b next = + (* + match b.bstmts with + | [] -> next + | _ -> + *) + let in_blk = get_node env (VblkIn (bkind, b)) in + let _ = add_edge env in_blk Enext next in + let out_blk = get_node env (VblkOut (bkind, b)) in + let _ = add_edge env out_blk Enone next in + let first_in_blk = cfg_stmts env b.bstmts out_blk in + let _ = add_edge env in_blk Enone first_in_blk in + in_blk + +and cfg_switch env switch_stmt switch_exp blk case_stmts next = + let n_switch = get_node env (Vswitch (switch_stmt, switch_exp)) in + add_edge env n_switch Enext next; + let _first = cfg_stmts env blk.bstmts next in + let branch with_def s = + let n = get_stmt_node env s in + let rec find_case l = match l with + | [] -> false, [] + | Case (e, _)::tl -> + let r = match find_case tl with + | true, [] -> true, [] + | true, _ -> assert false + | false, l -> false, e::l + in r + | Default _ :: _ -> + (* we don't check if we have several Default because it is impossible: + * CIL gives an error *) + true, [] + | _::tl -> find_case tl + in + let def, case = find_case s.labels in + if case = [] && not def then + Wp_parameters.fatal "[cfg] switch branch without label"; + add_edge env n_switch (Ecase case) n; + if def then true else with_def + in + let with_def = List.fold_left branch false case_stmts in + let _ = if not with_def then add_edge env n_switch (Ecase []) next in + n_switch + +and cfg_stmt env s next = + !Db.progress (); + match s.skind with + | Instr (Call _) -> + let in_call = get_stmt_node env s in + add_edge env in_call Enone next; + let exit_node = get_node env (Vexit) in + add_edge env in_call Enone exit_node; + in_call + | Instr _ | Return _ -> + let n = get_stmt_node env s in + add_edge env n Enone next; + n + | Block b -> + cfg_block env (Bstmt s) b next + | UnspecifiedSequence seq -> + let b = Cil.block_from_unspecified_sequence seq in + cfg_block env (Bstmt s) b next + | If (e, b1, b2, _) -> + begin + let n_in = get_stmt_node env s (*get_node env (Vtest (true, s, e))*) in + let n_out = get_node env (Vtest (false, s, e)) in + (* this node is to ensure that there is only one edge before + * the [next] node of a if to put post properties about the IF. *) + add_edge env n_out Enone next; + let in_b1 = cfg_block env (Bthen s) b1 n_out in + let in_b2 = cfg_block env (Belse s) b2 n_out in + add_edge env n_in Ethen in_b1; + add_edge env n_in Eelse in_b2; + add_edge env n_in Enext next; + n_in + end + | Loop(_, b, _, _, _) -> + let loop = get_stmt_node env s in + add_edge env loop Enext next; + let in_b = cfg_block env (Bloop s) b loop in + add_edge env loop Enone in_b; + loop + | Break _ | Continue _ | Goto _ -> + let n = get_stmt_node env s in + let _ = match s.succs with + | [s'] -> add_edge env n Enone (get_stmt_node env s') + | _ -> Wp_parameters.fatal "[cfg] jump with more than one successor ?" + in n + | Switch (e, b, lstmts, _) -> + cfg_switch env s e b lstmts next + | TryExcept _ | TryFinally _ -> + Wp_parameters.not_yet_implemented "[cfg] exception handling" + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {3 Cleaning} remove node and edges that are unreachable *) + +let clean_graph cfg = + let graph = cfg_graph cfg in + let rec reach n = + if !n.reachable then () + else (!n.reachable <- true; iter_succ reach cfg n) + in reach (cfg_start cfg); + let clean n acc = + if !n.reachable then acc + else begin + debug "remove unreachable node %a@." VL.pretty n; + let v = node_type n in + CFG.remove_vertex graph n; + Hashtbl.remove cfg.stmt_node (node_type_id v); + v::acc + end + in + let unreach = fold_nodes clean cfg [] in + { cfg with unreachables = unreach } + + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {3 About loops} +* Let's first remind some definitions about loops : +* - {b back edge} : edge n->h such that h dominates n. +* - {b natural loop} : defined by a back edge n->h +* * h is called the {b loop header}, +* * the body of the loop is the set of nodes n that are "between" h and n, +* ie all n predecessors until h. +* Because h dominates n, every backward path from n go through h. +* Notice that each node in the loop body is dominated by h. +* +* A loop is not a natural loop if it has several entries (no loop header), +* or if it has some irreducible region (no back edge). +* +* Below, we use an algorithm from the paper : + * "A New Algorithm for Identifying Loops in Decompilation" + * of Tao Wei, Jian Mao, Wei Zou, and Yu Chen, + * to gather information about the loops in the builted CFG. + *) + +module type WeiMaoZouChenInput = sig + type graph + type node + type tenv + + (** build a new env from a graph, + * and also return the entry point of the graph which has to be unique. *) + val init : graph -> tenv * node + + (** apply the function on the node successors *) + val fold_succ : (tenv -> node -> tenv) -> tenv -> node -> tenv + + val eq_nodes : node -> node -> bool + + (** store the position for the node and also the fact that the node has + * been seen *) + val set_pos : tenv -> node -> int -> tenv + + (** reset the position (set the position to 0), but should keep the + * information that the node has been seen already. *) + val reset_pos : tenv -> node -> tenv + + (** get the previously stored position of the node or 0 if nothing has been + * stored *) + val get_pos : tenv -> node -> int + + (** get the previously stored position of the node if any, or None + * if [set_pos] hasn't been called already for this node. *) + val get_pos_if_traversed : tenv -> node -> int option + + (** [set_iloop_header env b h] store h as the innermost loop header for b. + * Beware that this function can be called several times for the same b + * with different values of h during the computation. Only the last one + * will give the correct information. + * *) + val set_iloop_header : tenv -> node -> node -> tenv + + (** get the node innermost loop header if any *) + val get_iloop_header : tenv -> node -> node option + + (** store the node as a loop header. *) + val add_loop_header : tenv -> node -> tenv + + (** store the node as an irreducible loop header. *) + val add_irreducible : tenv -> node -> tenv + + (** store the edge between the two nodes (n1, n2) as a reentry edge. + * n2 is the reentry point which means that it is in a loop, + * but it is not the loop header, and n1 is not in the loop. *) + val add_reentry_edge : tenv -> node -> node -> tenv + + val pretty_node : Format.formatter -> node -> unit + + (** the unstructuredness coefficient k can be computed = 1+(xi+yi)/E + * when E is the number of edge in the graph. + * See the paper for more details. + * Just do nothing in [incr_xi] and [incr_yi] if you don't need k. + * *) + val incr_xi : tenv -> tenv + val incr_yi : tenv -> tenv +end + +(** Implementation of + * "A New Algorithm for Identifying Loops in Decompilation" *) +module WeiMaoZouChen (G : WeiMaoZouChenInput) : sig + val identify_loops : G.graph -> G.tenv +end = struct + + let tag_lhead env b h = + match h with + | None -> env + | Some h -> + if G.eq_nodes h b then (* already done *) env + else + let rec do_cur env cur_b cur_h = + match G.get_iloop_header env cur_b with + | None -> G.set_iloop_header env cur_b cur_h + | Some hb when G.eq_nodes hb cur_h -> (* nothing to do *) env + | Some hb -> + if (G.get_pos env hb) < (G.get_pos env cur_h) then + let env = G.set_iloop_header env cur_b cur_h in + do_cur env cur_h hb + else do_cur env hb cur_h + in do_cur env b h + + (** @return innermost loop header of b0 (None if b0 is not in a loop) *) + let rec trav_loops_DFS env b0 pos = + let env = G.set_pos env b0 pos in + let do_b env b = + match G.get_pos_if_traversed env b with + | None -> (* case A : b is not traversed already *) + let env, nh = trav_loops_DFS env b (pos + 1) in + tag_lhead env b0 nh + | Some b_pos when (b_pos > 0) -> + begin (* case B : b already in path -> it is a loop *) + let env = G.add_loop_header env b in + tag_lhead env b0 (Some b) + end + | Some 0 -> + begin + match G.get_iloop_header env b with + | None -> (* case C : do nothing *) env + | Some h when (G.get_pos env h > 0) -> + (* case D : b not in path, but h is *) + tag_lhead env b0 (Some h) + | Some h -> (* h not in path *) + begin (* case E : reentry *) + assert (G.get_pos env h = 0); + let env = G.add_irreducible env h in + let env = G.add_reentry_edge env b0 b in + let rec f env h = match G.get_iloop_header env h with + | Some h when (G.get_pos env h > 0) -> + tag_lhead env b0 (Some h) + | Some h -> + let env = G.add_irreducible env h in + f env h + | None -> env + in f env h + end + end + | _ -> assert false (* b_pos cannot be < 0 *) + in + let env = G.fold_succ do_b env b0 in + let env = G.reset_pos env b0 in + let h0 = G.get_iloop_header env b0 in + env, h0 + + let identify_loops g = + let env, start = G.init g in + let env, _ = trav_loops_DFS env start 1 in + env + +end + +(** To use WeiMaoZouChen algorithm, + * we need to define how to interact with our CFG graph *) +module LoopInfo = struct + type node = CFG.V.t + type graph = t + type tenv = { graph : t ; + dfsp : (node, int) Hashtbl.t; + iloop_header : (node, node) Hashtbl.t; + loop_headers : node list ; + irreducible : node list ; + unstruct_coef : int } + + let init cfg = + let env = { graph = cfg ; + dfsp = Hashtbl.create 97; iloop_header = Hashtbl.create 7; + loop_headers = []; irreducible = []; unstruct_coef = 0 } in + env, cfg_start cfg + + let eq_nodes = CFG.V.equal + + let set_pos env n pos = Hashtbl.add env.dfsp n pos; env + let reset_pos env n = Hashtbl.replace env.dfsp n 0; env + let get_pos env n = try Hashtbl.find env.dfsp n with Not_found -> 0 + let get_pos_if_traversed env n = + try Some (Hashtbl.find env.dfsp n) with Not_found -> None + + let set_iloop_header env b h = Hashtbl.add env.iloop_header b h; env + let get_iloop_header env b = + try Some (Hashtbl.find env.iloop_header b) with Not_found -> None + + let add_loop_header env h = { env with loop_headers = h :: env.loop_headers} + let add_irreducible env h = { env with irreducible = h :: env.irreducible} + let add_reentry_edge env _ _ = (* TODO *) env + + let is_irreducible env h = List.exists (eq_nodes h) env.irreducible + + let fold_succ f env n = fold_succ (fun v env -> f env v) env.graph n env + + let incr env = {env with unstruct_coef = env.unstruct_coef + 1} + let incr_xi = incr + let incr_yi = incr + let unstructuredness env = + let k = float_of_int env.unstruct_coef in + let k = k /. (float_of_int (CFG.nb_edges (cfg_graph env.graph))) in + let k = 1. +. k in + k + + let pretty_node fmt n = Format.fprintf fmt "%d" (VL.hash n) +end + +module Mloop = WeiMaoZouChen (LoopInfo) + +module HEloop = HE (struct type t = Nset.t end) + +let set_back_edge e = + let info = CFG.E.label e in + match !info with + | Eback | EbackThen | EbackElse -> () + | Enone -> info := Eback + | Ethen -> info := EbackThen + | Eelse -> info := EbackElse + | Ecase _ | Enext -> assert false + +let mark_loops cfg = + let kf = cfg_kf cfg in + let env = Mloop.identify_loops cfg in + let mark_loop_back_edge h = match node_stmt_opt h with + | None -> (* Because we use !Db.Dominators that work on statements, + we don't know how to detect back edge here. + TODO: compute dominators on our cfg ? *) false + | Some h_stmt -> + let mark_back_edge e = + let n = edge_src e in + let is_back_edge = + try + let n_stmt = node_stmt_exn n in + !Db.Dominators.is_dominator kf ~opening:h_stmt ~closing:n_stmt + with Not_found -> false (* pred of h is not a stmt *) + in + if is_back_edge then set_back_edge e; + debug "to loop edge %a@." pp_edge e + in iter_pred_e mark_back_edge cfg h; true + in + let mark_loop loops h = + debug "loop head in %a@." VL.pretty h; + let is_natural = + if (LoopInfo.is_irreducible env h) then + (debug "irreducible loop detected in %a@." VL.pretty h; false) + else true + in let back_edges_ok = + if is_natural then mark_loop_back_edge h else true + in + let loop = match node_type h with + | Vloop (_, h_stmt) -> + assert (back_edges_ok); + h := { !h with kind = Vloop (Some is_natural, h_stmt)}; + h + | _ -> match node_stmt_opt h with + | Some h_stmt when back_edges_ok -> + insert_loop_node cfg h (Vloop (Some is_natural, h_stmt)) + | None when back_edges_ok -> + let n = cfg.loop_cpt in cfg.loop_cpt <- n + 1; + insert_loop_node cfg h (Vloop2 (is_natural, n)) + | _ -> (* consider it has non-natural. *) + let n = cfg.loop_cpt in cfg.loop_cpt <- n + 1; + insert_loop_node cfg h (Vloop2 (false, n)) + in loop::loops + in + let loops = List.fold_left mark_loop [] env.LoopInfo.loop_headers in + debug2 "unstructuredness coef = %f@." (LoopInfo.unstructuredness env); + { cfg with loop_nodes = Some loops } + +let loop_nodes cfg = match cfg.loop_nodes with Some l -> l + | None -> Wp_parameters.fatal + "Cannot use the loop nodes before having computed them" + +let strange_loops cfg = + let strange n = match node_type n with + | Vloop (Some is_natural, _) when is_natural -> false + | _ -> true + in let loops = loop_nodes cfg in + let strange_loops = List.filter strange loops in + debug "%d/%d strange loops" + (List.length strange_loops) (List.length loops); + strange_loops + +let very_strange_loops cfg = + let strange n = match node_type n with + | Vloop (Some _, _) | Vloop2 _ -> false + | _ -> true + in let loops = loop_nodes cfg in + let strange_loops = List.filter strange loops in + debug "%d/%d very strange loops" + (List.length strange_loops) (List.length loops); + strange_loops + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(** {3 Create CFG} *) + +let cfg_from_definition kf f = + let kf_name = Kernel_function.get_name kf in + let cfg, fct_in, fct_out = init_cfg false kf in + let in_b = cfg_block cfg Bfct f.sbody fct_out in + let _ = add_edge cfg fct_in Enone in_b in + let graph = cfg_graph cfg in + debug "for function '%s': %d vertex - %d edges@." + kf_name (CFG.nb_edges graph) (CFG.nb_vertex graph); + debug + "start removing unreachable in %s@." kf_name; + !Db.progress (); + let cfg = clean_graph cfg in + debug "for function '%s': %d vertex - %d edges@." + kf_name (CFG.nb_edges graph) (CFG.nb_vertex graph); + !Db.progress (); + debug + "start loop analysis for %s@." kf_name; + let cfg = mark_loops cfg in + cfg + +let cfg_from_proto kf = + let cfg, fct_in, fct_out = init_cfg true kf in + let _ = add_edge cfg fct_in Enone fct_out in + let cfg = { cfg with loop_nodes = Some [] } in + cfg + +(* ------------------------------------------------------------------------ *) +(** {2 Export dot graph} *) + +(** {3 Printer for ocamlgraph} *) + +module Printer (PE : sig val edge_txt : edge -> string end) = struct + type t = CFG.t * (edge -> string) + module V = CFG.V + module E = CFG.E + let iter_edges_e f (g, _f) = CFG.iter_edges_e f g + let iter_vertex f (g, _) = CFG.iter_vertex f g + + let graph_attributes _t = [] + + let pretty_raw_stmt s = + let s = Pretty_utils.sfprintf "%a" !Ast_printer.d_stmt s in + let s' = if String.length s >= 50 then (String.sub s 0 49) ^ "..." else s in + String.escaped s' + + let vertex_name v = + let n = V.label v in (string_of_int (VL.hash n)) + + let vertex_attributes v = + let n = V.label v in + let label = match node_type n with + | Vstart -> "Start" | Vend -> "End" | Vexit -> "Exit" + | VfctIn -> "FctIn" | VfctOut -> "FctOut" + | VblkIn (bk,_) -> Pretty_utils.sfprintf "BLOCKin <%a>" pp_bkind bk + | VblkOut (bk,_) -> Pretty_utils.sfprintf "BLOCKout <%a>" pp_bkind bk + | Vcall _ -> Format.sprintf "CALL" + | Vtest (true, s, e) -> + Pretty_utils.sfprintf "IF <%d>\n%a" s.sid !Ast_printer.d_exp e + | Vtest (false, s, _e) -> Pretty_utils.sfprintf "IFout <%d>" s.sid + | Vstmt s | Vloop (_, s) | Vswitch (s, _) -> + begin match s.skind with + | Instr _ -> Format.sprintf "INSTR <%d>\n%s" s.sid (pretty_raw_stmt s) + | If _ -> "invalid IF ?" + | Return _ -> Format.sprintf "RETURN <%d>" s.sid + | Goto _ -> Format.sprintf "%s <%d>" (pretty_raw_stmt s) s.sid + | Break _ -> Format.sprintf "BREAK <%d>" s.sid + | Continue _ -> Format.sprintf "CONTINUE <%d>" s.sid + | Switch _ -> Format.sprintf "SWITCH <%d>" s.sid + | Loop _ -> Format.sprintf "WHILE(1) <%d>" s.sid + | Block _ -> Format.sprintf "BLOCK??? <%d>" s.sid + | TryExcept _ -> Format.sprintf "TRY EXCEPT <%d>" s.sid + | TryFinally _ -> Format.sprintf "TRY FINALLY <%d>" s.sid + | UnspecifiedSequence _ -> Format.sprintf "UnspecifiedSeq <%d>" s.sid + end + | Vloop2 (_, n) -> Format.sprintf "Loop-%d" n + in + let attr = match node_type n with + | Vstart | Vend | Vexit -> [`Color 0x0000FF; `Shape `Doublecircle] + | VfctIn | VfctOut -> [`Color 0x0000FF; `Shape `Box] + | VblkIn _ | VblkOut _ -> [`Shape `Box] + | Vloop _ | Vloop2 _ -> [`Color 0xFF0000; `Style `Filled] + | Vtest _ | Vswitch _ -> [`Color 0x00FF00; `Style `Filled; `Shape `Diamond] + | Vcall _ | Vstmt _ -> [] + in (`Label (String.escaped label))::attr + + let default_vertex_attributes _v = [] + + let edge_attributes e = + let attr = [] in + let attr = (`Label (String.escaped (PE.edge_txt e)))::attr in + let attr = + if is_back_edge e then (`Constraint false)::(`Style `Bold)::attr + else attr + in + let attr = match (edge_type e) with + | Ethen | EbackThen -> (`Color 0x00FF00)::attr + | Eelse | EbackElse -> (`Color 0xFF0000)::attr + | Ecase [] -> (`Color 0x0000FF)::(`Style `Dashed)::attr + | Ecase _ -> (`Color 0x0000FF)::attr + | Enext -> (`Style `Dotted)::attr + | Eback -> attr (* see is_back_edge above *) + | Enone -> attr + in + attr + + let default_edge_attributes _ = [] + + let get_subgraph v = + let mk_subgraph name attrib = + let attrib = (`Style `Filled) :: attrib in + Some { Graph.Graphviz.DotAttributes.sg_name= name; + Graph.Graphviz.DotAttributes.sg_attributes = attrib } + in + match node_type (V.label v) with + | Vcall (s,_,_,_) -> + let name = Format.sprintf "Call_%d" s.sid in + let call_txt = pretty_raw_stmt s in + let label = Format.sprintf "Call <%d> : %s" s.sid call_txt in + let attrib = [(`Label label)] in + let attrib = (`Fillcolor 0xB38B4D) :: attrib in + mk_subgraph name attrib + | _ -> None + +end + +(* ---------------------------------- *) +(** {3 Export to dot file} *) + +type pp_edge_fun = Format.formatter -> edge -> unit + +let export ~file ?pp_edge_fun cfg = + Kernel.Unicode.without_unicode + (fun () -> + let edge_txt = match pp_edge_fun with + | None -> + (fun e -> match (edge_type e) with + | Ecase (_::_) -> Pretty_utils.sfprintf "%a" EL.pretty (edge_type e) + | _ -> "" + ) + | Some pp -> (fun e -> Pretty_utils.sfprintf "%a" pp e) + in + let module P = Printer (struct let edge_txt = edge_txt end) in + let module GPrint = Graph.Graphviz.Dot(P) in + (* [JS 2011/03/11] open_out and output_graph (and close_out?) may raise + exception. Should be caught. *) + let oc = open_out file in + GPrint.output_graph oc (cfg_graph cfg, edge_txt); + close_out oc + ) () + +let cfg_dot msg dotname ?pp_edge_fun cfg = + let dir = Wp_parameters.get_output () in + let file = Printf.sprintf "%s/wp_%s.dot" dir dotname in + Wp_parameters.result "export %s in %s@." msg file ; + export ~file ?pp_edge_fun cfg ; + file + +let dot_cfg cfg = + let kf = cfg_kf cfg in + let kf_name = Kernel_function.get_name kf in + let dotname = kf_name^".cfg" in + cfg_dot "cfg" dotname cfg + +let dot_annots cfg bhv_name pp_edge_fun = + let kf = cfg_kf cfg in + let kf_name = Kernel_function.get_name kf in + let name = match bhv_name with + | None -> + Printf.sprintf "%s.wp_annot_cfg" kf_name + | Some bhv -> + Printf.sprintf "%s_%s.wp_annot_cfg" kf_name bhv + in + cfg_dot "cfg" name cfg ~pp_edge_fun + +let dot_wp_res cfg model pp_edge_fun = + let kf = cfg_kf cfg in + let f = Kernel_function.get_name kf in + let msg = (model^" results") in + let dotname = (f^".wp_"^model) in + cfg_dot msg dotname cfg ~pp_edge_fun + +(* ------------------------------------------------------------------------ *) +(** {2 CFG management} *) + +let create kf = + let kf_name = Kernel_function.get_name kf in + debug "create cfg for function '%s'@." kf_name; + let cfg = + try + let f = Kernel_function.get_definition kf in + cfg_from_definition kf f + with Kernel_function.No_Definition -> + cfg_from_proto kf + in debug "done for %s@." kf_name; + if Wp_parameters.Dot.get () then ignore (dot_cfg cfg); + !Db.progress (); + cfg + +module KfCfg = + Kernel_function.Make_Table + (Datatype.Make + (struct + include Datatype.Undefined + type tt = t + type t = tt + let name = "WpCfg" + let mem_project = Datatype.never_any_project + let reprs = + List.map + (fun kf -> + { kernel_function = kf; + spec_only = true; + graph = CFG.create (); + stmt_node = Hashtbl.create 0; + start_id = -1; + unreachables = []; + loop_nodes = None; + loop_cpt = 0; + } + ) + Kernel_function.reprs + let equal t1 t2 = + Kernel_function.equal t1.kernel_function t2.kernel_function + let hash t = Kernel_function.hash t.kernel_function + let compare t1 t2 = + Kernel_function.compare t1.kernel_function t2.kernel_function + end)) + (struct let name = "KfCfg" + let dependencies = [Ast.self] + let kind = `Internal + let size = 17 + end) + +let get kf = KfCfg.memo create kf + +(* ------------------------------------------------------------------------ *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/cil2cfg.mli frama-c-20111001+nitrogen+dfsg/src/wp/cil2cfg.mli --- frama-c-20110201+carbon+dfsg/src/wp/cil2cfg.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/cil2cfg.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,178 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** abstract type of a cfg *) +type t + +(** @raise Log.FeatureRequest for non natural loops and 'exception' stmts. + * @return the graph and the list of unreachable nodes. + * *) +val get : Kernel_function.t -> t + +(** abstract type of the cfg nodes *) +type node +val pp_node : Format.formatter -> node -> unit +val same_node : node -> node -> bool + +(** abstract type of the cfg edges *) +type edge +val pp_edge : Format.formatter -> edge -> unit +val same_edge : edge -> edge -> bool + +(** get the starting edges *) +val start_edge : t -> edge + +(** set of edges *) +module Eset : Set.S with type elt = edge + +(** node and edges relations *) +val edge_src : edge -> node +val edge_dst : edge -> node +val pred_e : t -> node -> edge list +val succ_e : t -> node -> edge list + +(** iterators *) +val fold_nodes : (node -> 'a -> 'a) -> t -> 'a -> 'a +val iter_nodes : (node -> unit) -> t -> unit +val iter_edges : (edge -> unit) -> t -> unit + +(** Be careful that only Bstmt are real Block statements *) +type block_type = private + | Bstmt of stmt | Bthen of stmt | Belse of stmt | Bloop of stmt | Bfct + +type node_type = private + | Vstart | Vend | Vexit + | VfctIn | VfctOut + | VblkIn of block_type * block + | VblkOut of block_type * block + | Vstmt of stmt + | Vcall of stmt * lval option * exp * exp list + | Vtest of bool * stmt * exp + | Vswitch of stmt * exp + | Vloop of bool option * stmt + (** boolean is is_natural. None means the node has not been + * detected as a loop. *) + | Vloop2 of bool * int + +val node_type : node -> node_type +val pp_node_type : Format.formatter -> node_type -> unit + +val node_stmt_opt : node -> stmt option +val start_stmt_of_node : node -> stmt option + +(** @return the nodes that are unreachable from the 'start' node. +* These nodes have been removed from the cfg already. *) +val unreachable_nodes : t -> node_type list + +(** similar to [succ_e g v] +* but tests the branch to return (then-edge, else-edge) + * @raise Invalid_argument if the node is not a test. +* *) +val get_test_edges : t -> node -> edge * edge + +(** similar to [succ_e g v] +but give the switch cases and the default edge *) +val get_switch_edges : t -> node -> (exp list * edge) list * edge + +(** similar to [succ_e g v] +but gives the edge to VcallOut first and the edge to Vexit second. *) +val get_call_out_edges : t -> node -> edge * edge + +val blocks_closed_by_edge : t -> edge -> block list + +val is_back_edge : edge -> bool + +(** detect is there are non natural loops or natural loops where we didn't +* manage to compute back edges (see [mark_loops]). Must be empty in the mode +* [-wp-no-invariants]. (see also [very_strange_loops]) *) +val strange_loops : t -> node list + +(** detect is there are natural loops where we didn't manage to compute +* back edges (see [mark_loops]). At the moment, we are not able to handle those +* loops. *) +val very_strange_loops : t -> node list + +(** @return the (normalized) labels at the program point of the edge. *) +val get_edge_labels : edge -> Clabels.c_label list + +(** @return None when the edge leads to the end of the function. *) +val get_edge_next_stmt : t -> edge -> stmt option + +(** wether an exit edge exists or not *) +val has_exit : t -> bool + +(** Find the edges where the precondition of the node statement have to be +* checked. *) +val get_pre_edges : t -> node -> edge list + +(** Find the edges where the postconditions of the node statement have to be +* checked. *) +val get_post_edges : t -> node -> edge list + +(** Get the label to be used for the Post state of the node contract if any. *) +val get_post_logic_label : t -> node -> logic_label option + +(** Find the edges [e] that goes to the [Vexit] node inside the statement +* begining at node [n] *) +val get_exit_edges : t -> node -> edge list + +(** Find the edges [e] of the statement node [n] postcondition +* and the set of edges that are inside the statement ([e] excluded). +* For instance, for a single statement node, [e] is [succ_e n], +* and the set is empty. For a test node, [e] are the last edges of the 2 +* branches, and the set contains all the edges between [n] and the [e] edges. +* *) +val get_internal_edges : t -> node -> edge list * Eset.t + +val cfg_kf : t -> Kernel_function.t +val cfg_spec_only : t -> bool + (** returns [true] is this CFG is degenerated (no code available) *) + +(** signature of a mapping table from cfg edges to some information. *) +module type HEsig = +sig + type ti + type t + val create : int -> t + val find : t -> edge -> ti + val find_all : t -> edge -> ti list + val add : t -> edge -> ti -> unit + val replace : t -> edge -> ti -> unit + val remove : t -> edge -> unit + val clear : t -> unit +end + +module HE (I : sig type t end) : HEsig with type ti = I.t + +(** type of functions to print things related to edges *) +type pp_edge_fun = Format.formatter -> edge -> unit + +(** Output the graph in a dot file and return its name **) +val dot_cfg : t -> string + +(** [dot_annots cfg bhv_name pp_annots] *) +val dot_annots : t -> string option -> pp_edge_fun -> string + +(** [dot_wp_res cfg model pp_wp_res] *) +val dot_wp_res : t -> string -> pp_edge_fun -> string diff -Nru frama-c-20110201+carbon+dfsg/src/wp/clabels.ml frama-c-20111001+nitrogen+dfsg/src/wp/clabels.ml --- frama-c-20110201+carbon+dfsg/src/wp/clabels.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/clabels.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,116 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Normalized C-labels --- *) +(* -------------------------------------------------------------------------- *) + +open Cil_types + +type c_label = + | Here + | Pre + | Post + | Exit + | At of string list * int + | CallAt of int + | LabelParam of string + + +let has_prefix p s = + let rec scan k p s = + ( k >= String.length p ) || + ( k < String.length s && p.[k] = s.[k] && scan (succ k) p s ) + in scan 0 p s + +let rec names_at = function + | [] -> [] + | Default _ :: labels -> "default" :: names_at labels + | Label(l,_,_) :: labels -> + (*TODO [LC] see mk_logic_label and loop_head_label *) + if has_prefix "wp!" l || has_prefix "return_label" l + then names_at labels + else l :: names_at labels + | Case(e,_) :: labels -> + match Ctypes.get_int e with + | None -> "case" :: names_at labels + | Some n -> + if n < 0L + then ("caseneg" ^ Int64.to_string (Int64.neg n)) :: names_at labels + else ("case" ^ Int64.to_string n) :: names_at labels + +let c_label = function + | LogicLabel (None, "Here") -> Here + | LogicLabel (None, "Pre") -> Pre + | LogicLabel (None, "Post") -> Post + | LogicLabel (None, "Exit") -> Exit + | LogicLabel (None, l) -> LabelParam l + | LogicLabel (Some stmt, _) + | StmtLabel { contents=stmt } -> At(names_at stmt.labels,stmt.sid) + +(*TODO [LC] : Use extension of Clabels instead *) +let loop_head_label s = + LogicLabel (None, "wp!loop_"^(string_of_int s.sid)^"_head") + +(*TODO [LC] : Use extension of Clabels instead *) +let mk_logic_label s = + LogicLabel (Some s, "wp!stmt_"^(string_of_int s.sid)) + +let mk_stmt_label s = (* TODO: clean that !*) c_label (mk_logic_label s) +let mk_loop_label s = (* TODO: clean that !*) c_label (loop_head_label s) + +let pretty fmt = function + | Here -> Format.pp_print_string fmt "\\here" + | Pre -> Format.pp_print_string fmt "\\pre" + | Post -> Format.pp_print_string fmt "\\post" + | Exit -> Format.pp_print_string fmt "\\exit" + | LabelParam label -> Format.fprintf fmt "Label '%s'" label + | CallAt sid -> Format.fprintf fmt "Call sid:%d" sid + | At(label::_,_) -> Format.fprintf fmt "Stmt '%s'" label + | At([],sid) -> Format.fprintf fmt "Stmt sid:%d" sid + +let label f a x = + if Wp_parameters.Trace.get () then + match a with + | Here | Pre | Post | Exit -> x + | LabelParam label -> + (*TODO [LC] see mk_logic_label and loop_head_label *) + if has_prefix "wp!" label + then x + else f label x + | CallAt sid -> + if Wp_parameters.debug_atleast 1 + then f (Printf.sprintf "Call%d" sid) x else x + | At(labels,sid) -> + List.fold_left + (fun x label -> f label x) + (if Wp_parameters.debug_atleast 1 + then f (Printf.sprintf "Stmt%d" sid) x else x) + labels + else x + +let lookup labels param = + try + let is_param p = function (LogicLabel (None, a),_) -> a = p | _ -> false in + c_label (snd (List.find (is_param param) labels)) + with Not_found -> Wp_parameters.fatal + "Unbound label parameter '%s' in predicate or function call" param diff -Nru frama-c-20110201+carbon+dfsg/src/wp/clabels.mli frama-c-20111001+nitrogen+dfsg/src/wp/clabels.mli --- frama-c-20110201+carbon+dfsg/src/wp/clabels.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/clabels.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,67 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Normalized C-labels *) +(* -------------------------------------------------------------------------- *) + +(** + Structural representation of logic labels. + Compatible with pervasives comparison and structural equality. +*) + +type c_label = + | Here + | Pre + | Post + | Exit + | At of string list * int (** Label name, stmt-id. *) + | CallAt of int (** stmt-id *) + | LabelParam of string (** Logic label name in user-defined + function or predicate *) + +(** @return a label that represent the first point of a loop body. *) +val loop_head_label : Cil_types.stmt -> Cil_types.logic_label + +(** create a virtual label to a statement (it can have no label) *) +val mk_logic_label : Cil_types.stmt -> Cil_types.logic_label + +val mk_stmt_label : Cil_types.stmt -> c_label +val mk_loop_label : Cil_types.stmt -> c_label + +val c_label : Cil_types.logic_label -> c_label + (** + Assumes the logic label only comes from normalized labels. + + This is the case inside [Wp] module, where all ACSL formula comes + from [WpAnnot], which in turns always preprocess the labels + through [NormAtLabels]. + *) + +val pretty : Format.formatter -> c_label -> unit +val label : (string -> 'a -> 'a) -> c_label -> 'a -> 'a + +open Cil_types + +val lookup : (logic_label * logic_label) list -> string -> c_label + (** [lookup bindings lparam] retrieves the actual label + for the label in [bindings] for label parameter [lparam]. *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/configure frama-c-20111001+nitrogen+dfsg/src/wp/configure --- frama-c-20110201+carbon+dfsg/src/wp/configure 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/configure 2011-10-10 08:56:40.000000000 +0000 @@ -0,0 +1,3759 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.65. +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="Makefile.in" +ac_subst_vars='ALTERGO_VERSION +LTLIBOBJS +LIBOBJS +COQ +HAS_COQ +ALTERGO +HAS_ALTERGO +WHYDP +HAS_WHYDP +WHY +HAS_WHY +DYNAMIC_WP +ENABLE_WP +ENABLE_GUI +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_wp +with_wp_static +' + ac_precious_vars='build_alias +host_alias +target_alias' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-wp support for wp plug-in (default: yes) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-wp-static link wp statically (default: no) + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.65 + +Copyright (C) 2009 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.65. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + KNOWN_PLUGINS=$(frama-c -help | \ + sed -e '0,/^\*\*\*\*\*/ d' \ + -e 's/\([^ ][^ ]*\( [^ ][^ ]*\)*\) .*/\1/' \ + -e '/^ /d' -e '/^$/d' | \ + tr "a-z- " "A-Z__") + for plugin in ${KNOWN_PLUGINS}; do + export $(echo ENABLE_$plugin)=yes + done + # Extract the first word of "frama-c-gui", so it can be a program name with args. +set dummy frama-c-gui; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ENABLE_GUI+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ENABLE_GUI"; then + ac_cv_prog_ENABLE_GUI="$ENABLE_GUI" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ENABLE_GUI="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ENABLE_GUI" && ac_cv_prog_ENABLE_GUI="no" +fi +fi +ENABLE_GUI=$ac_cv_prog_ENABLE_GUI +if test -n "$ENABLE_GUI"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_GUI" >&5 +$as_echo "$ENABLE_GUI" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +upper() { + echo "$1" | tr "a-z-" "A-Z_" +} + +lower() { + echo "$1" | tr "A-Z" "a-z" +} + + + +new_section() { + banner=`echo "* $1 *" | sed -e 's/./*/g'` + title=`echo "* $1 *" | tr "a-z" "A-Z"` + { $as_echo "$as_me:${as_lineno-$LINENO}: $banner" >&5 +$as_echo "$as_me: $banner" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: $title" >&5 +$as_echo "$as_me: $title" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: $banner" >&5 +$as_echo "$as_me: $banner" >&6;} +} + + + +# sadly, there's no way to define a new diversion beside the internal ones. +# hoping for the best here... + + + + +# to distinguish internal plugins, known by the main configure, from +# purely external plugins living in src/ and compiled together with the main +# frama-c + + + + # end of check_plugin + +# 1st param: uppercase name of the library +# 2nd param: file which must exist. This parameter can be a list of files. +# In this case, they will be tried in turn until one of them exists. The +# name of the file found will be put in the variable SELECTED_$1 +# 3d param: warning to display if problem +# 4th param: yes iff checking the library must always to be done +# (even if there is no plug-in using it) + + +# 1st param: uppercase name of the program +# 2nd param: program which must exist. See comment on configure_library() +# on how to deal with multiple choices for a given program. +# 3d param: warning to display if problem +# 4th param: yes iff checking the tool must always to be done +# (even if there is no plug-in using it) + + +EXTERNAL_PLUGINS= + + + + + + + + +# Implementation of an ordering $1 < $2: "" < yes < partial < no +lt_mark () { + first=`echo "$1" | sed -e 's/ .*//' ` + second=`echo "$2" | sed -e 's/ .*//' ` + case $first in + "") echo "true";; + "yes"*) + case $second in + "yes") echo "";; + "partial" | "no") echo "true";; + esac;; + "partial"*) + case $second in + "yes" | "partial") echo "";; + "no") echo "true";; + esac;; + "no"*) echo "";; + esac +} + +# Check and propagate marks to requires and users. +# $1: parent plugin +# $2: mark to propagate to requires +# $3: mark to propagate to users +check_and_propagate () { + # for each requiers + r=REQUIRE_$1 + eval require="\$$r" + for p in $require; do + up=`upper "$p"` + m=MARK_"$up" + eval mark="\$$m" + if test -z "$mark"; then + m=ENABLE_"$up" + eval mark="\$$m" + fi + if test `lt_mark "$mark" "$2" `; then + # update marks + eval MARK_$up=\"$2\"; + TODOLIST=$TODOLIST" "$p + # display a warning or an error if required + short_mark=`echo $2 | sed -e 's/ .*//'` + lp=`lower $p` + reason=`echo $2 | sed -e 's/no (\(.*\))/\1/' ` + if test "$short_mark" = "no"; then + fp=FORCE_"$up" + if eval test "\$$fp" = "yes"; then + as_fn_error "$lp requested but $reason." "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $lp disabled because $reason." >&2;} + fi + else + if test "$short_mark" = "partial"; then + reason=`echo $2 | sed -e 's/partial (\(.*\))/\1/' ` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp only partially enable because $reason." >&5 +$as_echo "$as_me: WARNING: $lp only partially enable because $reason." >&2;} + fi + fi + eval INFO_$up=\", $reason\" + fi + done + # for each users + u=USE_$1 + eval use="\$$u" + for p in $use; do + up=`upper "$p"` + m=MARK_$up + eval mark="\$$m" + if test -z "$mark"; then + m=ENABLE_"$up" + eval mark="\$$m" + fi + if test `lt_mark "$mark" "$3" `; then + # update marks + eval MARK_$up=\"$3\"; + TODOLIST=$TODOLIST" "$p + # display a warning if required + lp=`lower $p` + reason=`echo $3 | sed -e 's/partial (\(.*\))/\1/' ` + if test "$reason" != "$3"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $lp only partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $lp only partially enabled because $reason." >&2;} + fi + eval INFO_$up=\", $reason\" + fi + done +} + +# checks direct dependencies of a plugin. Useful for dynamic plugins which +# have a dependency toward already installed (or not) plug-ins, since the old +# plugins are not in the TODO list from the beginning (and need not their +# mutual dependencies be rechecked anyway +check_required_used () { + ep=ENABLE_$1 + eval enabled=\$$ep + + if test "$enabled" != "no"; then + + r=REQUIRED_$1 + u=USED_$1 + m=MARK_$1 + eval required=\$$r + eval used=\$$u + eval $m=yes + + reason= + + for p in $required; do + up=`upper $p` + ec=ENABLE_$up + eval enabled=\$$ec + case `echo "$enabled" | sed -e 's/ .*//'` in + "") reason="$p unknown";; + "yes" | "partial");; + "no") reason="$p not enabled";; + esac + done + if test -n "$reason"; then + eval $m=\"no\ \($reason\)\" + p_name=`lower $1` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p_name disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p_name disabled because $reason." >&2;} + eval INFO_$1=\", $reason\" + else + for p in $used; do + up=`upper $p` + ec=ENABLE_$up + eval enabled=\$$ec + case `echo "$enabled" | sed -e 's/ .*//'` in + "") reason="$p unknown";; + "yes" | "partial");; + "no") reason="$p not enabled";; + esac + done + if test -n "$reason"; then + eval $m=\"partial\ \($reason\)\" + p_name=`lower $1` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p_name partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p_name partially enabled because $reason." >&2;} + eval INFO_$1=\", $reason\" + fi + fi + + else # $enabled = "no" + eval $m=\"no\" + fi +} + +# Recursively check the plug-in dependencies using the plug-in dependency graph +compute_dependency () { + plugin=`echo $TODOLIST | sed -e 's/ .*//' ` + TODOLIST=`echo $TODOLIST | sed -e 's/[^ ]* *\(.*\)/\1/' ` + + lplugin=`lower "$plugin"` + uplugin=`upper "$plugin"` + # new mark to consider + m=MARK_$uplugin + eval mark="\$$m" + # old mark to consider + r=REMEMBER_$uplugin + eval remember="\$$r" + # the exact mark (final result), + # also the old mark if plugin already visited + e=ENABLE_$uplugin + eval enable="\$$e" + #first visit. Performs additional checks over requirements. + if test -z "$mark"; then + check_required_used "$uplugin"; + eval mark=\$$m + fi + +# echo "plug-in $lplugin (mark=$mark, remember=$remember, enable=$enable)" + if test `lt_mark "$remember" "$mark"`; then + # visit the current plugin: + # mark <- max(mark, enable) + case `echo "$mark" | sed -e 's/ .*//' ` in + "") echo "problem?"; exit 3;; + "yes") + if test -n "$enable"; then mark="$enable"; else mark="yes"; fi;; + "partial") if test "$enable" = "no"; then mark="no"; fi;; + "no") ;; + esac + # update plug-in attributes with the new mark +# echo "update attributes with $mark" + eval $m=\"$mark\" + eval $e=\"`echo "$mark" | sed -e 's/ .*//' `\" + enable="$mark" + eval $r=\"$mark\" + # compute and propagate a new mark to requires and users + case `echo "$enable" | sed -e 's/ .*//' ` in + "") echo "problem?"; exit 3;; + "yes") check_and_propagate $uplugin "yes" "yes";; + "partial") +# if a plug-in is partial, does not consider its dependencies as partial +# so the second argument is "yes" and not "partial" + check_and_propagate \ + "$uplugin" \ + "yes" \ + "yes";; + "no") + check_and_propagate \ + "$uplugin" \ + "no ($lplugin not enabled)" \ + "partial ($lplugin not enabled)";; + esac + fi + # recursively consider the next plugins + if test -n "$TODOLIST"; then + compute_dependency; + fi +} + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Makefile.in" >&5 +$as_echo_n "checking for Makefile.in... " >&6; } +if test "${ac_cv_file_Makefile_in+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "Makefile.in"; then + ac_cv_file_Makefile_in=yes +else + ac_cv_file_Makefile_in=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file_Makefile_in" >&5 +$as_echo "$ac_cv_file_Makefile_in" >&6; } +if test "x$ac_cv_file_Makefile_in" = x""yes; then : + default=yes;plugin_present=yes +else + plugin_present=no;default=no +fi + + +FORCE=no + +# Check whether --enable-wp was given. +if test "${enable_wp+set}" = set; then : + enableval=$enable_wp; ENABLE=$enableval;FORCE=$enableval +else + ENABLE=$default + +fi + + +if test "$ONLY_KERNEL" = "yes" -a "$FORCE" = "no"; then + ENABLE=no +fi + + + +# Test to change for static plugin, dynamic option +#default_dyn=no +#define([PLUGIN_HELP_DYN], +# AC_HELP_STRING([--enable-PLUGIN_NAME-dynamic], +# [PLUGIN_MSG (default: static)]) +#define([PLUGIN_NAME_DYN],[PLUGIN_NAME]-dynamic) +#AC_ARG_ENABLE( +# [PLUGIN_NAME_DYN], +# PLUGIN_HELP_DYN, +# ENABLE=$enableval; +# FORCE=$enableval +# ENABLE=$default_dyn +#) +#eval ENABLE_DYNAMIC_$up=\$ENABLE + +if test "$plugin_present" = "no" -a "$FORCE" = "yes"; then + as_fn_error "wp is not available" "$LINENO" 5 +fi + +FORCE_WP=$FORCE +PLUGINS_FORCE_LIST=${PLUGINS_FORCE_LIST}" "FORCE_WP + +ENABLE_WP=$ENABLE +NAME_WP=wp +if test "$default" = "no" -a "$FORCE" = "no"; then + INFO_WP=" (not available by default)" +fi + +# Dynamic plug-ins configuration + + +# Check whether --with-wp-static was given. +if test "${with_wp_static+set}" = set; then : + withval=$with_wp_static; is_static=$withval +else + is_static=$IS_ALL_STATIC +fi + + + # is_static = "yes" iff the user forces the plug-in to be static + # is_static = "no" iff the user forces the plug-in to be dynamic + # is_static = "" in others cases (no special instruction) + STATIC_WP=$is_static + if test "$is_static" != "yes"; then + USE_NATIVE_DYNLINK="${USE_NATIVE_DYNLINK} wp" + DYNAMIC_WP=yes + else + DYNAMIC_WP=no + fi + + + +echo "wp... $ENABLE" +# kept defined for write_plugin_config. A bit ugly, but not more than +# usual autoconf stuff. +# m4_undefine([PLUGIN_NAME]) + + + + + + + + +if test "$ENABLE_WP" != "no"; then + + + + + USE_GUI=$USE_GUI" "wp + USED_WP=$USED_WP" "gui + + + + + + + + + + USE_RTE_ANNOTATION=$USE_RTE_ANNOTATION" "wp + USED_WP=$USED_WP" "rte_annotation + + + + + + + + USE_ALTERGO=$USE_ALTERGO" "wp + + + + + USE_COQ=$USE_COQ" "wp + + + + + USE_WHY=$USE_WHY" "wp + + + + + USE_DOT=$USE_DOT" "wp + + + + + USE_WHYDP=$USE_WHYDP" "wp + + + + # Why + + + + + + + + + + + for file in why; do + HAS_WHY= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_WHY+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_WHY"; then + ac_cv_prog_HAS_WHY="$HAS_WHY" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_WHY="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_WHY" && ac_cv_prog_HAS_WHY="no" +fi +fi +HAS_WHY=$ac_cv_prog_HAS_WHY +if test -n "$HAS_WHY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_WHY" >&5 +$as_echo "$HAS_WHY" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_WHY" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + # Why-dp + + + + + + + + + + + for file in why-dp; do + HAS_WHYDP= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_WHYDP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_WHYDP"; then + ac_cv_prog_HAS_WHYDP="$HAS_WHYDP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_WHYDP="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_WHYDP" && ac_cv_prog_HAS_WHYDP="no" +fi +fi +HAS_WHYDP=$ac_cv_prog_HAS_WHYDP +if test -n "$HAS_WHYDP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_WHYDP" >&5 +$as_echo "$HAS_WHYDP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_WHYDP" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + # alt-ergo + + + + + + + + + + + for file in alt-ergo; do + HAS_ALTERGO= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_ALTERGO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_ALTERGO"; then + ac_cv_prog_HAS_ALTERGO="$HAS_ALTERGO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_ALTERGO="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_ALTERGO" && ac_cv_prog_HAS_ALTERGO="no" +fi +fi +HAS_ALTERGO=$ac_cv_prog_HAS_ALTERGO +if test -n "$HAS_ALTERGO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_ALTERGO" >&5 +$as_echo "$HAS_ALTERGO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_ALTERGO" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + ALTERGO_VERSION=`alt-ergo -version | sed -e 's/Alt-Ergo \(.*\)/\1/' ` + { $as_echo "$as_me:${as_lineno-$LINENO}: alt-ergo version is $ALTERGO_VERSION." >&5 +$as_echo "$as_me: alt-ergo version is $ALTERGO_VERSION." >&6;} + case $ALTERGO_VERSION in + 0.92.2) { $as_echo "$as_me:${as_lineno-$LINENO}: good." >&5 +$as_echo "$as_me: good." >&6;};; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: alt-ergo's array theory unsupported." >&5 +$as_echo "$as_me: alt-ergo's array theory unsupported." >&6;};; + esac + + + # coq + + + + + + + + + + + for file in coqc; do + HAS_COQ= +# Extract the first word of "$file", so it can be a program name with args. +set dummy $file; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_HAS_COQ+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAS_COQ"; then + ac_cv_prog_HAS_COQ="$HAS_COQ" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAS_COQ="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_HAS_COQ" && ac_cv_prog_HAS_COQ="no" +fi +fi +HAS_COQ=$ac_cv_prog_HAS_COQ +if test -n "$HAS_COQ"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAS_COQ" >&5 +$as_echo "$HAS_COQ" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$HAS_COQ" = "yes"; then SELECTED_VAR=$file break; fi + done + + + + + + + + + + + + + + if test -n "$REQUIRE_WHY" -o -n "$USE_WHY" -o "$no" = "yes"; then + if test "$HAS_WHY" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: why not found" >&5 +$as_echo "$as_me: WARNING: why not found" >&2;} + reason="why missing" + for p in $REQUIRE_WHY; do + up=`upper "$p"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$p"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$p requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ why\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for p in $USE_WHY; do + up=`upper "$p"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ why\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + WHY=why + fi + fi + + if test -n "$REQUIRE_WHYDP" -o -n "$USE_WHYDP" -o "$no" = "yes"; then + if test "$HAS_WHYDP" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: why-dp not found" >&5 +$as_echo "$as_me: WARNING: why-dp not found" >&2;} + reason="why-dp missing" + for p in $REQUIRE_WHYDP; do + up=`upper "$p"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$p"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$p requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ why-dp\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for p in $USE_WHYDP; do + up=`upper "$p"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ why-dp\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + WHYDP=why-dp + fi + fi + + if test -n "$REQUIRE_ALTERGO" -o -n "$USE_ALTERGO" -o "$no" = "yes"; then + if test "$HAS_ALTERGO" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: alt-ergo not found" >&5 +$as_echo "$as_me: WARNING: alt-ergo not found" >&2;} + reason="alt-ergo missing" + for p in $REQUIRE_ALTERGO; do + up=`upper "$p"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$p"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$p requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ alt-ergo\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for p in $USE_ALTERGO; do + up=`upper "$p"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ alt-ergo\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + ALTERGO=alt-ergo + fi + fi + + if test -n "$REQUIRE_COQ" -o -n "$USE_COQ" -o "$no" = "yes"; then + if test "$HAS_COQ" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: coq not found" >&5 +$as_echo "$as_me: WARNING: coq not found" >&2;} + reason="coqc missing" + for p in $REQUIRE_COQ; do + up=`upper "$p"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$p"` + if eval test "\$$fp" = "yes"; then + as_fn_error "$p requested but $reason." "$LINENO" 5 + fi + eval $ep="no\ \(see\ warning\ about\ coqc\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p disabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p disabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + for p in $USE_COQ; do + up=`upper "$p"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ coqc\)" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $p partially enabled because $reason." >&5 +$as_echo "$as_me: WARNING: $p partially enabled because $reason." >&2;} + eval INFO_$up=\", $reason\" + fi + done + else + COQ=coqc + fi + fi + + +# First, initialize some variables +for fp in ${PLUGINS_FORCE_LIST}; do + if test "$fp" != "FORCE_GTKSOURCEVIEW"; then + plugin=`echo $fp | sed -e "s/FORCE_\(.*\)/\1/" ` + TODOLIST=$TODOLIST" "$plugin + eval MARK_$plugin= + eval REMEMBER_$plugin= + fi +done +# main call +compute_dependency + +fi + + + + + ac_config_files="$ac_config_files ./Makefile" + + + + +# Compute INFO_* and exported ENABLE_* from previously computed ENABLE_* + for fp in ${PLUGINS_FORCE_LIST}; do + if test "$fp" != "FORCE_GTKSOURCEVIEW"; then + plugin=`echo $fp | sed -e "s/FORCE_\(.*\)/\1/" ` + ep=ENABLE_$plugin + eval v=\$$ep + eval ep_v=`echo $v | sed -e 's/ .*//' ` + eval ENABLE_$plugin=$ep_v + reason=`echo $v | sed -e 's/[a-z]*\( .*\)/\1/' ` + n=NAME_$plugin + eval name=\$$n + info= + if test "$reason" != "$ep_v"; then + info=$reason + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: $name: $ep_v$info" >&5 +$as_echo "$as_me: $name: $ep_v$info" >&6;} + fi + done + cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.65. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.65, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2009 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "./Makefile") CONFIG_FILES="$CONFIG_FILES ./Makefile" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + + + case $ac_file$ac_mode in + "./Makefile":F) chmod -w ./Makefile ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit $? +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + + + + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/configure.ac frama-c-20111001+nitrogen+dfsg/src/wp/configure.ac --- frama-c-20110201+carbon+dfsg/src/wp/configure.ac 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/configure.ac 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,72 @@ +########################################################################## +# # +# This file is part of WP plug-in of Frama-C. # +# # +# Copyright (C) 2007-2011 # +# CEA (Commissariat a l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +m4_define([plugin_file],Makefile.in) + +m4_define([FRAMAC_SHARE_ENV], + [m4_normalize(m4_esyscmd([echo $FRAMAC_SHARE]))]) + +m4_define([FRAMAC_SHARE], + [m4_ifval(FRAMAC_SHARE_ENV,[FRAMAC_SHARE_ENV], + [m4_esyscmd(frama-c -print-path)])]) + +m4_ifndef([FRAMAC_M4_MACROS], + [m4_include(FRAMAC_SHARE/configure.ac)] + ) + +check_plugin(wp,PLUGIN_RELATIVE_PATH(plugin_file),[support for wp plug-in],yes,yes) + +if test "$ENABLE_WP" != "no"; then + plugin_use(wp,gui) + plugin_use(wp,rte_annotation) + plugin_use_external(wp,altergo) + plugin_use_external(wp,coq) + plugin_use_external(wp,why) + plugin_use_external(wp,dot) + plugin_use_external(wp,whydp) + + # Why + configure_tool([WHY],[why],[why not found],no) + + # Why-dp + configure_tool([WHYDP],[why-dp],[why-dp not found],no) + + # alt-ergo + configure_tool([ALTERGO],[alt-ergo],[alt-ergo not found],no) + + ALTERGO_VERSION=`alt-ergo -version | sed -e 's/Alt-Ergo \(.*\)/\1/' ` + AC_MSG_NOTICE([alt-ergo version is $ALTERGO_VERSION.]) + case $ALTERGO_VERSION in + 0.92.2) AC_MSG_NOTICE([good.]);; + *) AC_MSG_NOTICE([alt-ergo's array theory unsupported.]);; + esac + + + # coq + configure_tool([COQ],[coqc],[coq not found],no) + + check_plugin_dependencies +fi + +write_plugin_config(Makefile) + +AC_SUBST(ALTERGO_VERSION) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/ctypes.ml frama-c-20111001+nitrogen+dfsg/src/wp/ctypes.ml --- frama-c-20110201+carbon+dfsg/src/wp/ctypes.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/ctypes.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,472 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- C-Types --- *) +(* -------------------------------------------------------------------------- *) + +open Cil_types +open Cil_datatype + +module WpLog = Wp_parameters + +type c_int = + | UInt8 + | SInt8 + | UInt16 + | SInt16 + | UInt32 + | SInt32 + | UInt64 + | SInt64 + +let compare_c_int : c_int -> c_int -> _ = Extlib.compare_basic + +let signed = function + | UInt8 | UInt16 | UInt32 | UInt64 -> false + | SInt8 | SInt16 | SInt32 | SInt64 -> true + +let i_sizeof = function + | UInt8 | SInt8 -> 8 + | UInt16 | SInt16 -> 16 + | UInt32 | SInt32 -> 32 + | UInt64 | SInt64 -> 64 + +let make_c_int signed = function + | 1 -> if signed then SInt8 else UInt8 + | 2 -> if signed then SInt16 else UInt16 + | 4 -> if signed then SInt32 else UInt32 + | 8 -> if signed then SInt64 else UInt64 + | size -> WpLog.not_yet_implemented "%d-bits integers" size + +let c_int ikind = + let mach = Cil.theMachine.Cil.theMachine in + match ikind with + | IBool -> make_c_int false mach.sizeof_int + | IChar -> if mach.char_is_unsigned then UInt8 else SInt8 + | ISChar -> SInt8 + | IUChar -> UInt8 + | IInt -> make_c_int true mach.sizeof_int + | IUInt -> make_c_int false mach.sizeof_int + | IShort -> make_c_int true mach.sizeof_short + | IUShort -> make_c_int false mach.sizeof_short + | ILong -> make_c_int true mach.sizeof_long + | IULong -> make_c_int false mach.sizeof_long + | ILongLong -> make_c_int true mach.sizeof_longlong + | IULongLong -> make_c_int false mach.sizeof_longlong + +(* Bounds of an integer according to c_int ti : + An integer i : i \in [c_int_bounds ti] if + [c_int_bounds ti] = (min,max) then min <=i<max.*) +let c_int_bounds = function + | UInt8 -> (Big_int.zero_big_int,Big_int.big_int_of_string "256") + | SInt8 -> (Big_int.big_int_of_string "-128", + Big_int.big_int_of_string "128") + | UInt16 -> (Big_int.zero_big_int, + Big_int.big_int_of_string "65536") + | SInt16 -> (Big_int.big_int_of_string "-32768", + Big_int.big_int_of_string "32768") + | UInt32 -> (Big_int.zero_big_int, + Big_int.big_int_of_string "4294967296") + | SInt32 -> (Big_int.big_int_of_string "-2147483648" , + Big_int.big_int_of_string "2147483648" ) + | UInt64 -> (Big_int.zero_big_int , + Big_int.big_int_of_string "18446744073709551616" ) + | SInt64 -> (Big_int.big_int_of_string "-9223372036854775808" , + Big_int.big_int_of_string "9223372036854775808" ) + +let c_int_all = + [ UInt8 ; SInt8 ; UInt16 ; SInt16 ; UInt32 ; SInt32 ; UInt64 ; SInt64 ] + +let c_bool () = c_int IInt +let c_char () = c_int IChar +let c_ptr () = + make_c_int false Cil.theMachine.Cil.theMachine.sizeof_ptr + +let sub_c_int t1 t2 = + if (signed t1 = signed t2) then i_sizeof t1 <= i_sizeof t2 + else (not(signed t1) && (i_sizeof t1 < i_sizeof t2)) + + +type c_float = + | Float16 + | Float32 + | Float64 + | Float96 + | Float128 + +let compare_c_float : c_float -> c_float -> _ = Extlib.compare_basic + +let f_sizeof = function + | Float16 -> 16 + | Float32 -> 32 + | Float64 -> 64 + | Float96 -> 96 + | Float128 -> 128 + +let make_c_float = function + | 2 -> Float16 + | 4 -> Float32 + | 8 -> Float64 + | 12 -> Float96 + | 16 -> Float128 + | size -> WpLog.not_yet_implemented "%d-bits floats" size + +let c_float fkind = + let mach = Cil.theMachine.Cil.theMachine in + match fkind with + | FFloat -> make_c_float mach.sizeof_float + | FDouble -> make_c_float mach.sizeof_double + | FLongDouble -> make_c_float mach.sizeof_longdouble + +let sub_c_float f1 f2 = f_sizeof f1 <= f_sizeof f2 + +(* Array objects, with both the head view and the flatten view. *) + +type arrayflat = { + arr_size : int64; (* number of elements in the array *) + arr_dim : int ; (* number of dimensions in the array *) + arr_cell : typ ; (* type of elementary cells of the flatten array *) + arr_cell_nbr : int64 ; (* number of elementary cells in the flatten array *) +} + +type arrayinfo = { + arr_element : typ ; (* type of the elements of the array *) + arr_flat : arrayflat option; +} + +(* Type of variable, inits, field or assignable values. *) +type c_object = + | C_int of c_int + | C_float of c_float + | C_pointer of typ + | C_comp of compinfo + | C_array of arrayinfo + +(* -------------------------------------------------------------------------- *) +(* --- Memoization --- *) +(* -------------------------------------------------------------------------- *) + +let idx = function + | UInt8 -> 0 + | SInt8 -> 1 + | UInt16 -> 2 + | SInt16 -> 3 + | UInt32 -> 4 + | SInt32 -> 5 + | UInt64 -> 6 + | SInt64 -> 7 + +let imemo f = + let m = Array.create 8 None in + fun i -> + let k = idx i in + match m.(k) with + | Some r -> r + | None -> + let r = f i in m.(k) <- Some r ; r + +let fdx = function + | Float16 -> 0 + | Float32 -> 1 + | Float64 -> 2 + | Float96 -> 3 + | Float128 -> 4 + +let fmemo f = + let m = Array.create 8 None in + fun z -> + let k = fdx z in + match m.(k) with + | Some r -> r + | None -> + let r = f z in m.(k) <- Some r ; r + +(* -------------------------------------------------------------------------- *) +(* --- Pretty Printers --- *) +(* -------------------------------------------------------------------------- *) + +let pp_int fmt i = Format.fprintf fmt "%cint%d" + (if signed i then 's' else 'u') (i_sizeof i) + +let pp_float fmt f = Format.fprintf fmt "float%d" (f_sizeof f) + +let pp_object fmt = function + | C_int i -> pp_int fmt i + | C_float f -> pp_float fmt f + | C_pointer _ -> Format.pp_print_string fmt "obj-pointer" + | C_comp _ -> Format.pp_print_string fmt "obj-struct/union" + | C_array _ -> Format.pp_print_string fmt "obj-array" + +(* -------------------------------------------------------------------------- *) +(* --- Array Info --- *) +(* -------------------------------------------------------------------------- *) + +let char c = + match Cil.charConstToInt c with + | CInt64(k,_,_) -> My_bigint.to_int64 k + | _ -> WpLog.fatal "char-const-to-int" + +let constant e = + match (Cil.constFold true e).enode with + | Const(CInt64(k,_,_)) -> My_bigint.to_int64 k + | Const(CChr c) -> char c + | _ -> WpLog.fatal "Non-constant expression (%a)" !Ast_printer.d_exp e + +let get_int e = + match (Cil.constFold true e).enode with + | Const(CInt64(k,_,_)) -> Some (My_bigint.to_int64 k) + | Const(CChr c) -> Some (char c) + | _ -> None + +let dimension t = + let rec flat k d = function + | TNamed _ as t -> flat k d (Cil.unrollType t) + | TArray(ty,Some e,_,_) -> + flat (succ k) (Int64.mul d (constant e)) ty + | te -> k , d , te + in flat 1 Int64.one t + +(* -------------------------------------------------------------------------- *) +(* --- Value State_builder. --- *) +(* -------------------------------------------------------------------------- *) + +let is_void typ = + match Cil.unrollType typ with + | TVoid _ -> true + | _ -> false + +let object_of typ = + match Cil.unrollType typ with + | TInt(i,_) -> C_int (c_int i) + | TFloat(f,_) -> C_float (c_float f) + | TPtr(typ,_) -> + begin + match Cil.unrollType typ with + | TVoid _ -> C_pointer (TInt (IChar,[])) + | _ -> C_pointer typ + end + | TFun _ as t -> C_pointer t + | TEnum ({ekind=i},_) -> C_int (c_int i) + | TComp (comp,_,_) -> C_comp comp + | TArray (typ_elt,e_opt,_,_) -> + begin + match e_opt with + | None -> + C_array { + arr_element = typ_elt; + arr_flat = None; + } + + | Some e -> + let dim,ncells,ty_cell = dimension typ in + C_array { + arr_element = typ_elt ; + arr_flat = Some { + arr_size = constant e ; + arr_dim = dim ; + arr_cell = ty_cell ; + arr_cell_nbr = ncells ; + } + } + end + | TBuiltin_va_list _ -> + WpLog.not_yet_implemented "valiadyc type" + | TVoid _ -> + WpLog.fatal ~current:true "void object" + | TNamed _ -> + WpLog.fatal "non-unrolled named type (%a)" !Ast_printer.d_type typ + +let object_of_pointed = function + C_int _ | C_float _ | C_comp _ as o -> + Wp_parameters.fatal + "object_of_pointed called on non-pointer %a@." pp_object o + | C_array info -> object_of info.arr_element + | C_pointer typ -> object_of typ + + +let object_of_array_elem = function + | C_array arr -> object_of arr.arr_element + | o -> Wp_parameters.fatal + "object_of_array_elem called on non-array %a." pp_object o + +let no_infinite_array = function + | C_array {arr_flat = None} -> false + | _ -> true + +let array_dim arr = + match arr.arr_flat with + | Some f -> object_of f.arr_cell , f.arr_dim - 1 + | None -> + let rec collect_dim arr n = + match object_of arr.arr_element with + | C_array arr -> collect_dim arr (succ n) + | te -> te,n + in collect_dim arr 1 + +let int64_max a b = + if Int64.compare a b < 0 then b else a + +let rec sizeof_object = function + | C_int i -> Int64.of_int (i_sizeof i) + | C_float f -> Int64.of_int (f_sizeof f) + | C_pointer _ty -> Int64.of_int (i_sizeof (c_ptr())) + | C_comp cinfo -> + let merge = if cinfo.cstruct then Int64.add else int64_max in + List.fold_left + (fun sz f -> merge sz (sizeof_object (object_of f.ftype))) + Int64.zero cinfo.cfields + | C_array ainfo -> + begin + match ainfo.arr_flat with + | Some a -> Int64.mul + (sizeof_object(object_of a.arr_cell)) a.arr_cell_nbr + | None -> WpLog.not_yet_implemented "Sizeof unknown-size array" + end + +let field_offset f = + let rec acc ofs f = function + | [] -> Wp_parameters.fatal "[field_offset] not found field %s" f.fname ; + | fi::m -> + if Cil_datatype.Fieldinfo.equal f fi then ofs else + let sf = sizeof_object (object_of fi.ftype) in + acc (Int64.add ofs sf) f m + in acc Int64.zero f f.fcomp.cfields + +(* Conforms to @ C-ISO § 6.3.1.8 *) +(* If same sign => greater rank. *) +(* If different: *) +(* Case 1: *) +(* rank(unsigned) >= rank(signed) *) +(* then convert to unsigned *) +(* Case 2: *) +(* domain(unsigend) contains *) +(* domain(signed) *) +(* then convert to signed *) +(* Otherwise: *) +(* both are converted to unsiged *) +(* *) +(* Case 2 is actually the negative *) +(* of Case 1, and both simplifies *) +(* into converting to the operand *) +(* with greater rank, whatever *) +(* their sign. *) + +let i_convert t1 t2 = if i_sizeof t1 < i_sizeof t2 then t2 else t1 +let f_convert t1 t2 = if f_sizeof t1 < f_sizeof t2 then t2 else t1 + +let promote a1 a2 = + match a1 , a2 with + | C_int i1 , C_int i2 -> C_int (i_convert i1 i2) + | C_float f1 , C_float f2 -> C_float (f_convert f1 f2) + | C_int _ , C_float _ -> a2 + | C_float _ , C_int _ -> a1 + | _ -> WpLog.not_yet_implemented + "promotion between arithmetics and pointer types" + +(* ------------------------------------------------------------------------ *) +(* --- Comparable --- *) +(* ------------------------------------------------------------------------ *) + +module AinfoComparable = struct + type t = arrayinfo + let hash a = Typ.hash a.arr_element + let equal a b = + Typ.equal a.arr_element b.arr_element && + (match a.arr_flat , b.arr_flat with + | Some a , Some b -> Int64.compare a.arr_size b.arr_size = 0 + | None , None -> true + | _ -> false) + let compare a b = + let c = Typ.compare a.arr_element b.arr_element in + if c <> 0 then c + else match a.arr_flat , b.arr_flat with + | Some a , Some b -> Int64.compare a.arr_size b.arr_size + | None , Some _ -> (-1) + | Some _ , None -> 1 + | None , None -> 0 +end + +let hash = function + | C_int _ -> 3 + | C_float _ -> 5 + | C_pointer _ -> 7 + | C_comp c -> 11 * Compinfo.hash c + | C_array a -> 13 * AinfoComparable.hash a + +let equal a b = + match a,b with + | C_int i, C_int i' -> i=i' + | C_float f , C_float f' -> f=f' + | C_pointer te , C_pointer te' -> Typ.equal te te' + | C_comp c , C_comp c' -> Compinfo.equal c c' + | C_array a , C_array a' -> AinfoComparable.equal a a' + | _ -> false + +let basetype = function + | C_int _ -> 1 + | C_float _ -> 2 + | C_pointer _ -> 3 + | C_comp c -> if c.cstruct then 4 else 5 + | C_array _ -> Wp_parameters.fatal "[basetype] of an array" + +let compare a b = + match a,b with + | C_int i, C_int i' -> compare_c_int i i' + | C_float f , C_float f' -> compare_c_float f f' + | C_pointer te , C_pointer te' -> Typ.compare te te' + | C_comp c , C_comp c' -> Compinfo.compare c c' + | C_array a , C_array a' -> AinfoComparable.compare a a' + | _ -> + let k1 = basetype a in + let k2 = basetype b in + assert (k1<>k2) ; + k1 - k2 + +let rec basename = function + | C_int i -> Pretty_utils.sfprintf "%a" pp_int i + | C_float f -> Pretty_utils.sfprintf "%a" pp_float f + | C_pointer _ -> "pointer" + | C_comp c -> c.cname + | C_array a -> + let te = basename (object_of a.arr_element) in + match a.arr_flat with + | None -> te ^ "_array" + | Some f -> te ^ "_" ^ Int64.to_string f.arr_size + +let rec pretty fmt = function + | C_int i -> pp_int fmt i + | C_float f -> pp_float fmt f + | C_pointer _ -> Format.pp_print_string fmt "pointer" + | C_comp c -> Format.pp_print_string fmt c.cname + | C_array a -> + let te = object_of a.arr_element in + match a.arr_flat with + | None -> Format.fprintf fmt "%a[]" pretty te + | Some f -> Format.fprintf fmt "%a[%s]" pretty te + (Int64.to_string f.arr_size) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/ctypes.mli frama-c-20111001+nitrogen+dfsg/src/wp/ctypes.mli --- frama-c-20110201+carbon+dfsg/src/wp/ctypes.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/ctypes.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,140 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** C-Types *) +(* -------------------------------------------------------------------------- *) + +open Cil_types + +(** Runtime integers. *) +type c_int = + | UInt8 + | SInt8 + | UInt16 + | SInt16 + | UInt32 + | SInt32 + | UInt64 + | SInt64 + +val c_int_all : c_int list + +(** Runtime floats. *) +type c_float = + | Float16 + | Float32 + | Float64 + | Float96 + | Float128 + +(** Array objects, with both the head view and the flatten view. *) +type arrayflat = { + arr_size : int64 ; (** number of elements in the array *) + arr_dim : int ; (** number of dimensions in the array *) + arr_cell : typ ; (** type of elementary cells of the flatten array. Never an array. *) + arr_cell_nbr : int64 ; (** number of elementary cells in the flatten array *) +} + +type arrayinfo = { + arr_element : typ ; (** type of the elements of the array *) + arr_flat : arrayflat option; +} + +(** Type of variable, inits, field or assignable values. *) +type c_object = + | C_int of c_int + | C_float of c_float + | C_pointer of typ + | C_comp of compinfo + | C_array of arrayinfo + +(** c_objects of elements pointed to by pointer or array. fatal error + if called on other type. +*) +val object_of_pointed: c_object -> c_object + +val object_of_array_elem : c_object -> c_object +(** {2 Utilities} *) + +val imemo : (c_int -> 'a) -> c_int -> 'a +val fmemo : (c_float -> 'a) -> c_float -> 'a + +val c_char : unit -> c_int (** Returns the type of [char] *) +val c_bool : unit -> c_int (** Returns the type of [int] *) +val c_ptr : unit -> c_int (** Returns the type of pointers *) + +val c_int : ikind -> c_int (** Conforms to {Cil.theMachine} *) +val c_float : fkind -> c_float (** Conforms to {Cil.theMachine} *) +val object_of : typ -> c_object + +val is_void : typ -> bool + +val char : char -> int64 +val constant : exp -> int64 +val get_int : exp -> int64 option + +val signed : c_int -> bool (** true if ikind is signed *) +val c_int_bounds: c_int -> Big_int.big_int * Big_int.big_int + +(** All sizes are in bits *) +val i_sizeof : c_int -> int + +val f_sizeof : c_float -> int + +val sub_c_int: c_int -> c_int -> bool + +val sub_c_float : c_float -> c_float -> bool + +val sizeof_object: c_object -> int64 +val field_offset : fieldinfo -> int64 + +val no_infinite_array : c_object -> bool +val array_dim : arrayinfo -> c_object * int + +val i_convert : c_int -> c_int -> c_int +val f_convert : c_float -> c_float -> c_float +val promote : c_object -> c_object -> c_object + +val pp_int : Format.formatter -> c_int -> unit +val pp_float : Format.formatter -> c_float -> unit +val pp_object : Format.formatter -> c_object -> unit + +val basename : c_object -> string +val compare : c_object -> c_object -> int +val equal : c_object -> c_object -> bool +val hash : c_object -> int +val pretty : Format.formatter -> c_object -> unit + +module AinfoComparable : +sig + type t = arrayinfo + val compare : t -> t -> int + val equal : t -> t -> bool + val hash : t -> int +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/datalib.ml frama-c-20111001+nitrogen+dfsg/src/wp/datalib.ml --- frama-c-20110201+carbon+dfsg/src/wp/datalib.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/datalib.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,908 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module WpLog = Wp_parameters +open Format +open Ctypes +open Cil_types +open Formula + +(* ------------------------------------------------------------------------ *) +(* --- Goals information collection --- *) +(* ------------------------------------------------------------------------ *) + +module Collector = +struct + + type t = { + mutable c_warning : Wpo.warning list; + mutable c_depends : Property.t list; + } + + let stack = ref [] + + let push () = + let c = { c_warning = []; c_depends = [] } in + stack := c::(!stack) ; c + + let pop c = match !stack with + | top::tl when top == c -> + stack := tl; (List.rev c.c_warning, List.rev c.c_depends) + | _ -> Wp_parameters.fatal "Datalib.Collector: inconsistent stack" + + let add_warning ?(severe=false) ?source ~reason effect = + let f _ = + let msg = Format.flush_str_formatter () in + let wrn = { + Wpo.wrn_loc = Log.get_current_source () ; + Wpo.wrn_severe = severe ; + Wpo.wrn_source = (match source with None -> "wp" | Some r -> r) ; + Wpo.wrn_reason = reason ; + Wpo.wrn_effect = msg ; + } in + match !stack with + | top::_ -> top.c_warning <- wrn::top.c_warning + | _ -> Wp_parameters.fatal "Datalib.Collector: empty stack" + in Format.kfprintf f Format.str_formatter effect + + let add_depend pid = + match !stack with + | top::_ -> top.c_depends <- pid::top.c_depends + | _ -> Wp_parameters.fatal "Datalib.Collector: empty stack" + +end + +module Create (V:Mvalues.Values) : Formula.Logic with module F = V.F = +struct + + module F = V.F + + (* ------------------------------------------------------------------------ *) + (* --- Acsl Types Guards Generations --- *) + (* ------------------------------------------------------------------------ *) + + let has_type_rec = ref (fun (_:F.abstract) _ -> assert false) + let has_obj_rec = ref (fun (_:F.abstract) _ -> assert false) + + module IsComp = F.DRegister + (struct + include F.Compinfo + let prefix = "Is" + let section = S_Logic_Def + let clear () = () + let pp_title fmt x = Format.fprintf fmt "Type constraint for %a" + F.Compinfo.pp_title x + let declare compinfo _ = + let pool = F.pool () in + let x = F.p_fresh pool "x" (Model(Record compinfo)) in + let vx = F.var x in + let has_type_fd f = !has_type_rec (F.acc_field vx f) (Ctype f.ftype) in + let def = F.p_conj (List.map has_type_fd compinfo.cfields) in + PredicateDef([x],def) + end) + + let rec is_array_dim pool a te n = + if n > 0 then + let i = F.p_fresh pool "i" (Model Formula.Integer) in + let a_i = F.acc_index (F.unwrap a) (F.var i) in + F.p_forall [i] (is_array_dim pool a_i te (pred n)) + else !has_obj_rec a te + + module IsArray = F.DRegister + (struct + include F.ArrayDim + let prefix = "IsArray" + let section = S_Logic_Def + let clear () = () + let pp_title fmt x = Format.fprintf fmt "Type constraint for %a" + F.ArrayDim.pp_title x + let declare (te,n) _ = + let pool = F.pool () in + let a = F.p_fresh pool "a" (Model(V.tau_of_object_array te n)) in + PredicateDef([a],is_array_dim pool (F.var a) te n) + end) + + let has_type_int i e = F.guard i e + + let is_comp comp e = F.p_app1 (IsComp.get_definition comp).d_name e + let is_array arr e = + let adim = Ctypes.array_dim arr in + F.p_app1 (IsArray.get_definition adim).d_name e + + + let has_obj e = function + | C_int i -> has_type_int i (F.unwrap e) + | C_float _ -> F.p_true + | C_pointer _ -> F.p_true + | C_array arr -> is_array arr e + | C_comp comp -> is_comp comp e + + let has_type e = function + | Ctype ty -> has_obj e (object_of ty) + | (Ltype _ | Linteger | Lreal | Lvar _ | Larrow _ ) -> F.p_true + + let () = has_type_rec := has_type + let () = has_obj_rec := has_obj + + (* ------------------------------------------------------------------------ *) + (* --- Constrained Terms --- *) + (* ------------------------------------------------------------------------ *) + + type bindings = binding list and binding = + | Forall of F.var list + | Exists of F.var list + | Any of F.var * F.pred + | Let of F.var * F.abstract + + let pp_binding fmt = function + | Forall xs -> Format.fprintf fmt "Forall @[%a@]" (Pretty_utils.pp_list F.pp_var) xs + | Exists xs -> Format.fprintf fmt "Exists @[%a@]" (Pretty_utils.pp_list F.pp_var) xs + | Any(x,p) -> Format.fprintf fmt "Any %a s.t. @[%a@]" F.pp_var x F.pp_pred p + | Let(x,t) -> Format.fprintf fmt "Let %a = @[%a@]" F.pp_var x F.pp_term t + + type context = { + pool : F.pool ; + mutable bindings : bindings ; + } + + let closed : bindings = [] + let context = ref [] + + let occur_check y xs = + if List.exists (F.eq_var y) xs then + Wp_parameters.fatal + "Quantification of constrained variable" + + let pp_vkind fmt = function + | Formula.Model t -> F.pp_tau fmt t + | Formula.Acsl (_t,ty) -> !Ast_printer.d_logic_type fmt ty + + let guards_with f xs p = + let do_with f p x = + match F.kind_of_var x with + | Model _ -> p + | Acsl (_,ty) -> f (has_type (F.var x) ty) p + + in + List.fold_left (do_with f) xs p + + let sub y xs = List.filter (fun x -> not (F.eq_var x y)) xs + + let some_alpha pool x = Some(F.p_freshen pool x) + + let rec apply_bindings alpha bindings p = + match bindings with + | [] -> p + | b::bindings -> + let p = apply_bindings alpha bindings p in + match b with + | Forall xs -> F.p_forall xs p + | Exists xs -> F.p_exists xs p + | Any(x,q) -> F.p_forall [x] (F.p_implies q p) + | Let(x,t) -> F.p_subst alpha x t p + + let alpha x = + match !context with + | [] -> None + | c::_ -> Some(F.p_freshen c.pool x) + + let do_subst x v p = + if F.pred_has_var [x] p + then F.p_subst alpha x v p + else p + + let do_forall xs p = + if F.pred_has_var xs p + then + let ys = List.filter (fun y -> F.pred_has_var [y] p) xs in + if ys = [] then p + else + F.p_forall ys (guards_with F.p_implies p ys) + else p + + let do_exists xs p = + if F.pred_has_var xs p + then + let ys = List.filter (fun y -> F.pred_has_var [y] p) xs in + if ys = [] then p + else F.p_exists ys (guards_with F.p_and p ys) + else p + + let rec has_var xs bindings = + xs <> [] && + match bindings with + | [] -> false + | b::others -> + match b with + | Forall ys | Exists ys -> + let xs = List.fold_right sub ys xs in + has_var xs others + | Any(y,p) -> + F.pred_has_var xs p || has_var (sub y xs) others + | Let(y,t) -> + F.term_has_var xs t || has_var (sub y xs) others + + let forall xs p = + match !context with + | [] -> do_forall xs p + | c :: _ -> + if has_var xs c.bindings + then ( c.bindings <- Forall xs :: c.bindings ; p ) + else do_forall xs p + + let exists xs p = + match !context with + | [] -> do_exists xs p + | c :: _ -> + if has_var xs c.bindings + then ( c.bindings <- Exists xs :: c.bindings ; p ) + else do_exists xs p + + let fresh id vk = + match !context with + | [] -> + Wp_parameters.fatal "Bad context (for %S:%a)" id pp_vkind vk + | c::_ -> + F.p_fresh c.pool id + (match vk with + | Formula.Model t -> Model t + | Formula.Acsl (t,ty) -> Acsl (t,ty) + ) + + let pool () = + match !context with + | [] -> Wp_parameters.fatal "Bad context (no pool available)" + | c::_ -> c.pool + + let vkind_of_var x = + match F.kind_of_var x with + | Model t -> Formula.Model t + | Acsl(t,c) -> Formula.Acsl (t,c) + + let term_such_that tau phi = + match !context with + | [] -> Wp_parameters.fatal "No context opened for constraints" + | c::_ -> + let x = F.p_fresh c.pool "X" (Model tau) in + let t = F.var x in + c.bindings <- Any(x,phi t) :: c.bindings ; t + + let subst_in_bindings c x v p = + if has_var [x] c.bindings + then ( c.bindings <- Let(x,v) :: c.bindings ; p ) + else ( do_subst x v p ) + + let subst x v p = + match !context with + | [] -> do_subst x v p + | c::_ -> subst_in_bindings c x (F.wrap v) p + + let close bindings p = + apply_bindings (fun _ -> None) bindings p + + let has_context_vars xs p = + F.pred_has_var xs p || + ( match !context with + | [] -> false + | c::_ -> has_var xs c.bindings ) + + (* -------------------------------------------------------------------------- *) + (* --- Context Management --- *) + (* -------------------------------------------------------------------------- *) + + let push where pool bindings = + Wp_parameters.debug ~dkey:"context" "PUSH %d: %S@." (List.length !context) where ; + let c = { pool=pool ; bindings=bindings } in + context := c :: !context ; c + + let pop where c0 = + Wp_parameters.debug ~dkey:"context" "POPK %d: %S@." (pred (List.length !context)) where ; + match !context with + | [] -> Wp_parameters.fatal "No context for constrained term" + | c::stack -> + if not (c0 == c) + then Wp_parameters.fatal "Context mismatch for constrained term" ; + context := stack ; + c.bindings + + let flush where c0 p = + Wp_parameters.debug ~dkey:"context" "FLUSH %d %S@." (pred (List.length !context)) where ; + match !context with + | [] -> Wp_parameters.fatal "No context for constrained term" + | c::stack -> + if not (c0 == c) + then Wp_parameters.fatal "Context mismatch for constrained term" ; + context := stack ; + apply_bindings (some_alpha c.pool) c.bindings p + + let kill where c = ignore (pop where c) + + (* ------------------------------------------------------------------------ *) + (* --- Generalized Substitutions --- *) + (* ------------------------------------------------------------------------ *) + + + let pp_sigma fmt s = + begin + Format.fprintf fmt "[" ; + List.iter (fun (x,x') -> Format.fprintf fmt " %a:=%a" F.pp_var x F.pp_var x') s ; + Format.fprintf fmt " ]" ; + end + + let pp_bindings fmt xts = + List.iter (fun (x,t) -> Format.fprintf fmt "%a:= %a@\n" F.pp_var x F.pp_term t) xts + + + let freshen x = + match !context with + | [] -> Wp_parameters.fatal "no context opened for havoc" + | c::_ -> F.p_freshen c.pool x + + let apply = F.e_rename + + let rec domain xs d = function + | [] -> List.rev xs,List.rev d + | h::hs -> + match h with + | F.Fresh x -> domain (x::xs) d hs + | F.Update(x,_) -> + let d' = if List.exists (F.eq_var x) d then d else (x::d) in + domain xs d' hs + + let reverse = List.map (fun (x,y) -> (y,x)) + + let freshen_sigma y = + List.map (fun u -> if F.eq_var (fst u) y then y,freshen y else u) + + let rec compute_bindings bindings sigmaR sigma = function + | [] -> bindings , sigma + | F.Fresh _ :: havocs -> compute_bindings bindings sigmaR sigma havocs + | F.Update(x,phi) :: havocs -> + let sigma' = freshen_sigma x sigma in + let x' = snd (List.find (fun (y,_) -> F.eq_var x y) sigma') in + let t' = apply sigmaR (phi sigma) in + compute_bindings ((x',t')::bindings) sigmaR sigma' havocs + + + let rec apply_bindings xts p = + match xts with + | [] -> p + | (x,t)::xts -> apply_bindings xts (subst x t p) + + let rec rename s p = + match s with + | [] -> p + | (x,x')::s -> subst x (F.var x') (rename s p) + + let rec fixpoint sf sn p = + match sf,sn with + | (_,x')::sf , (_,y)::sn -> + F.p_implies + (F.p_eq (F.var x') (F.var y)) + (fixpoint sf sn p) + | [] , [] -> p + | _ -> Wp_parameters.fatal "inconsistent domains in fixpoint substitutions" + + let havoc_inductive hs p = + let xs,d = domain [] [] hs in + let sigma_0 = List.map (fun x -> x,freshen x) d in + let sigma_F = List.map (fun x -> x,freshen x) d in + let bindings,sigma_N = compute_bindings [] sigma_F sigma_0 hs in + forall ( xs @ List.map snd sigma_F ) + (rename (reverse sigma_0) + (apply_bindings bindings + (fixpoint sigma_F sigma_N + (rename sigma_F p)))) + + let havoc_static hs p = + let xs,d = domain [] [] hs in + let sigma_0 = List.map (fun x -> x,freshen x) d in + let bindings,sigma_N = compute_bindings [] sigma_0 sigma_0 hs in + forall xs + (rename (reverse sigma_0) + (apply_bindings bindings + (rename sigma_N p))) + +end + +(* -------------------------------------------------------------------------- *) +(* --- Interpret C-runtime values --- *) +(* -------------------------------------------------------------------------- *) + +module Cvalues(M : Mvalues.Model) = +struct + + module A = M.A + module R = M.R + module F = M.F + type loc = M.loc + type m_cell + type cell = F.abstract + + let loc_of_term = M.loc_of_term + let term_of_loc = M.term_of_loc + + let cast_int_to_loc = M.cast_int_to_loc + let cast_loc_to_int = M.cast_loc_to_int + + type value = + | V_int of Ctypes.c_int * F.integer + | V_float of Ctypes.c_float * F.real + | V_pointer of Ctypes.c_object * M.loc + | V_record of compinfo * F.record + | V_union of compinfo * F.urecord + | V_array of arrayinfo * F.array + + let rec logic_of_value = function + | V_int(_,t) -> F.wrap t + | V_float(_,t) -> F.wrap t + | V_pointer(_,loc) -> F.wrap (M.term_of_loc loc) + | V_record(_,t) -> F.wrap t + | V_union(_,t) -> F.wrap t + | V_array(_,t) -> F.wrap t + + + let rec value_of_logic c_obj t = + match c_obj with + | C_int i -> V_int(i,F.unwrap t) + | C_float f -> V_float(f,F.unwrap t) + | C_pointer typ -> + V_pointer + (object_of typ, + M.loc_of_term (object_of typ) (F.unwrap t)) + | C_comp cinfo -> + if cinfo.cstruct + then V_record(cinfo,F.unwrap t) + else V_union(cinfo,F.unwrap t) + | C_array ainfo -> V_array(ainfo,F.unwrap t) + + let pp_loc = M.pp_loc + let pp_value fmt = function + | V_pointer(_,loc) -> M.pp_loc fmt loc + | v -> F.pp_term fmt (logic_of_value v) + + (* ------------------------------------------------------------------------ *) + (* --- Logic type of Values --- *) + (* ------------------------------------------------------------------------ *) + + let tau_of_loc = M.tau_of_loc + let tau_of_object = function + | C_int _ -> Integer + | C_float _ -> Real + | C_pointer _ -> Pointer tau_of_loc + | C_comp c -> Record c + | C_array a -> Array a + + let tau_of_object_array obj n = + let rec apply_dim t n = + (*[LC] not perfect, but works *) + if n > 0 then ADT("farray",[apply_dim t (pred n)]) + else t + in apply_dim (tau_of_object obj) n + + let tau_of_ctype_logic t = tau_of_object (object_of t) + + let rec pp_tau fmt = function + | Formula.Integer -> pp_print_string fmt "int" + | Formula.Real -> pp_print_string fmt "real" + | Formula.Boolean -> pp_print_string fmt "bool" + | Formula.Pointer t -> Format.fprintf fmt "%a" pp_tau t + | Formula.Record c -> Format.fprintf fmt "%s" c.Cil_types.cname + | Formula.Array a -> + Format.fprintf fmt "%a farray" pp_tau + (tau_of_object (object_of a.arr_element)) + | Formula.Set te -> + if Wp_parameters.verbose_atleast 2 + then Format.fprintf fmt "%a set" pp_tau te + else pp_print_string fmt "set" + | Formula.ADT(s,[]) -> pp_print_string fmt s + | Formula.ADT(s,[t]) -> Format.fprintf fmt "%a %s" pp_tau t s + | Formula.ADT(s,t::ts) -> + Format.fprintf fmt "@[(%a" pp_tau t ; + List.iter (fun t -> Format.fprintf fmt ",@,%a" pp_tau t) ts ; + Format.fprintf fmt ") %s@]" s + + + let tau_of_ctype t = tau_of_object (Ctypes.object_of t) + + let rec tau_of_logic_type = function + | Ctype c -> tau_of_object (object_of c) + | Linteger -> Formula.Integer + | Lreal -> Formula.Real + | Ltype( d , [] ) when d.lt_name = Utf8_logic.boolean -> Formula.Boolean + | Ltype( {lt_name="set"} , [t] ) -> Formula.Set (tau_of_logic_type t) + | Ltype( lt , ts) -> + let d = F.adt_decl lt in + Formula.ADT (d,List.map tau_of_logic_type ts) + | Lvar _ -> Wp_parameters.not_yet_implemented "logic type variables" + | Larrow _ -> Wp_parameters.not_yet_implemented "type of logic function" + + + (* ------------------------------------------------------------------------ *) + (* --- Default Initialization of value --- *) + (* ------------------------------------------------------------------------ *) + + let init_value_term_rec = ref (fun _ _ _ -> assert false) + + module InitObj = F.DRegister + (struct + include F.Cobject + let declare obj _ = + Formula.Predicate [tau_of_object obj] + let prefix = "IsInit" + let section = S_Logic_Sig + let clear () = () + let pp_title fmt x = + Format.fprintf fmt + "Predicate is initial value of type %a" F.Cobject.pp_title x + end) + + + module InitObjRange = F.DRegister + (struct + include F.Cobject + let declare obj _ = + Formula.Predicate [tau_of_object_array obj 1;Integer;Integer] + let prefix = "IsInitRange" + let section = S_Logic_Sig + let clear () = () + let pp_title fmt x = + Format.fprintf fmt + "Initialisation of a range of type %a in a array" F.Cobject.pp_title x + end) + + module InitObjRangeDef = F.DRegister + (struct + include F.Cobject + let declare obj _ = + let pool = F.pool () in + let xt = F.p_fresh pool "t" + (Model (ADT("farray",[tau_of_object obj]))) + in + let t = F.var xt in + let xi = F.p_fresh pool "i" (Model Integer) in + let i = F.var xi in + let xlow = F.p_fresh pool "low" (Model Integer) in + let low = F.var xlow in + let xhigh = F.p_fresh pool "high" (Model Integer) in + let high = F.var xhigh in + let is_init = + F.p_app3 ((InitObjRange.get_definition obj).d_name) t low high + in + let i_low = F.p_icmp Cleq low i in + let i_high = F.p_icmp Clt i high in + let i_init = + !init_value_term_rec pool (F.acc_index (F.unwrap t) i) obj + in + let body = + F.p_forall [xi] + (F.p_implies i_low (F.p_implies i_high i_init)) + in + Formula.Axiom + (F.p_forall [xt;xlow;xhigh] (F.p_iff is_init body)) + + let prefix = "IsInitRangeDef" + let section = S_Logic_Prop + let clear () = () + let pp_title fmt x = + Format.fprintf fmt + "Initialisation of a range of type %a in a array" F.Cobject.pp_title x + end) + + let rec init_value_term pool x = function + | C_int _ -> F.p_eq x (F.wrap F.i_zero) + | C_float _ -> F.p_eq x (F.wrap F.r_zero) + | C_pointer te -> M.equal_loc (M.loc_of_term (object_of te) x) M.null + | C_array arr -> + let obj = object_of arr.arr_element in + begin + match arr.arr_flat with + | None -> F.p_true + | Some f -> + let bound = F.e_int64 f.arr_size in + InitObjRangeDef.define obj ; + F.p_app3 (InitObjRange.get_definition obj).d_name x + F.i_zero bound + end + + | C_comp cp -> + begin + let get_f f = F.acc_field (F.unwrap x) f in + let field_init f = + init_value_term pool (get_f f) (object_of f.ftype) + in + List.fold_left (fun p f -> F.p_and p (field_init f)) + F.p_true cp.cfields + end + + module InitObjDef = F.DRegister + (struct + include F.Cobject + let declare obj _ = + let p_is_init = (InitObj.get_definition obj).d_name in + let pool = F.pool () in + let vx = F.p_fresh pool "x" (Model (tau_of_object obj)) in + let x = F.var vx in + let is_init_x = F.p_app1 p_is_init x in + let body = init_value_term pool x obj in + Formula.Axiom (F.p_forall [vx ] (F.p_iff is_init_x body)) + + let prefix = "IsInitDef" + let section = S_Logic_Prop + let clear () = () + let pp_title fmt x = + Format.fprintf fmt + "Axiomatic definition of the predicate of is initial value of type %a" F.Cobject.pp_title x + let prefix = "IsInitRangeDef" + let clear () = () + let pp_title fmt x = + Format.fprintf fmt + "Initialisation of a range of type %a in a array" F.Cobject.pp_title x + end) + + let rec init_value_term pool x = function + | C_int _ -> F.p_eq x (F.wrap F.i_zero) + | C_float _ -> F.p_eq x (F.wrap F.r_zero) + | C_pointer te -> M.equal_loc (M.loc_of_term (object_of te) x) M.null + | C_array arr -> + let obj = object_of arr.arr_element in + begin + match arr.arr_flat with + | None -> F.p_true + | Some f -> + let bound = F.e_int64 f.arr_size in + InitObjRangeDef.define obj ; + F.p_app3 (InitObjRange.get_definition obj).d_name x + F.i_zero bound + end + + | C_comp cp -> + begin + let get_f f = F.acc_field (F.unwrap x) f in + let field_init f = + init_value_term pool (get_f f) (object_of f.ftype) + in + List.fold_left (fun p f -> F.p_and p (field_init f)) + F.p_true cp.cfields + end + + + let () = init_value_term_rec := init_value_term + + let symb_is_init obj = + if Ctypes.no_infinite_array obj then + (InitObjDef.define obj ; + Some (InitObj.get_definition obj).d_name) + else None + + let symb_is_init_range obj = + if Ctypes.no_infinite_array obj then + (InitObjRangeDef.define obj; + Some (InitObjRange.get_definition obj).d_name) + else None + + (* ------------------------------------------------------------------------ *) + (* --- Pointer Arithmetics --- *) + (* ------------------------------------------------------------------------ *) + + let lt_loc = M.lt_loc + let le_loc = M.le_loc + + let minus_loc = M.minus_loc + + let equal_loc_bool = M.equal_loc_bool + let lt_loc_bool = M.lt_loc_bool + let le_loc_bool = M.le_loc_bool + let equal_loc = M.equal_loc + let le_loc = M.le_loc + let lt_loc = M.lt_loc + + let null = M.null + let is_null = M.is_null + + (* ------------------------------------------------------------------------ *) + (* --- Comparison of Record and Arrays --- *) + (* ------------------------------------------------------------------------ *) + + module RecEqName = F.DRegister + (struct + include F.Compinfo + let declare tcomp _eqname = + Formula.Predicate[Record tcomp;Record tcomp] + let prefix = "Eqrec" + let section = S_Logic_Sig + let clear () = () + let pp_title fmt x = + Format.fprintf fmt "Equality for %a" + F.Compinfo.pp_title x + end) + + + let equal_rec = ref (fun _ _ _ -> assert false) + + (** 2 struct or union objects are equal when all the fields are equal. *) + let eq_record_definition tcomp eq_name = + let pool = F.pool() in + let xa = F.p_fresh pool "a" (Model (Record tcomp)) in + let xb = F.p_fresh pool "b" (Model (Record tcomp)) in + let ra = F.var xa in + let rb = F.var xb in + let p_comp = + List.fold_left + (fun p field -> + let tf = Ctypes.object_of field.ftype in + let va = F.acc_field ra field in + let vb = F.acc_field rb field in + let ef = !equal_rec tf va vb in + F.p_and p ef + ) F.p_true tcomp.cfields + in + F.p_forall [xa;xb] + (F.p_iff (F.p_app2 eq_name ra rb) p_comp) + + let eq_array_definition ta eq_name = + let pool = F.pool() in + let te = Ctypes.object_of ta.arr_element in + let vmodel = Model(Array ta) in + let xa = F.p_fresh pool "a" vmodel in + let xb = F.p_fresh pool "b" vmodel in + let ra = F.var xa in + let rb = F.var xb in + let xi = F.p_fresh pool "i" (Model Integer) in + let vi = F.var xi in + let i_pos = F.p_icmp Cleq (F.i_zero) vi in + let i_max = + match ta.arr_flat with + | None -> F.p_true + | Some f -> F.p_icmp Clt vi (F.e_icst (Int64.to_string f.arr_size)) + in + let i_range = F.p_and i_pos i_max in + let a_comp = + F.p_forall [xi] + (F.p_implies + i_range + (!equal_rec te (F.acc_index ra vi) (F.acc_index rb vi))) in + F.p_forall [xa;xb] + (F.p_iff (F.p_app2 eq_name ra rb) a_comp) + + + module RecEqSym = F.DRegister + (struct + include F.Compinfo + let declare tcomp _eqname = + let eq_name = F.p_app2 (RecEqName.get_definition tcomp).d_name in + let pool = F.pool() in + let xa = F.p_fresh pool "a" (Model (Record tcomp)) in + let ra = F.var xa in + let p = F.p_forall [xa] (eq_name ra ra) in + Formula.Axiom p + let prefix = "EqrecSym" + let section = S_Logic_Prop + let clear () = () + let pp_title fmt x = + Format.fprintf fmt "Symmetry of Equality for %a" + F.Compinfo.pp_title x + let pp_descr fmt _ = + Format.pp_print_string fmt "Axiomatic Definition" + end) + + + module RecEqTrans = F.DRegister + (struct + include F.Compinfo + let declare tcomp _eqname = + let eq_name = F.p_app2 (RecEqName.get_definition tcomp).d_name in + let pool = F.pool() in + let xa = F.p_fresh pool "a" (Model (Record tcomp)) in + let ra = F.var xa in + let xb = F.p_fresh pool "b" (Model (Record tcomp)) in + let rb = F.var xb in + let xc = F.p_fresh pool "c" (Model (Record tcomp)) in + let rc = F.var xc in + Formula.Axiom + (F.p_forall [xa;xb;xc] + (F.p_implies (eq_name ra rb) + (F.p_implies (eq_name rb rc) (eq_name ra rc)))) + let prefix = "EqrecTrans" + let section = S_Logic_Prop + let clear () = () + let pp_title fmt x = + Format.fprintf fmt "Symmetry of Equality for %a" + F.Compinfo.pp_title x + let pp_descr fmt _ = + Format.pp_print_string fmt "Axiomatic Definition" + end) + + module RecEqDef = F.DRegister + (struct + include F.Compinfo + let declare tcomp _axname = + let eq_name = RecEqName.get_definition tcomp in + RecEqSym.define tcomp ; + RecEqTrans.define tcomp ; + Formula.Axiom(eq_record_definition tcomp eq_name.d_name) + let prefix = "EqrecDef" + let section = S_Logic_Prop + let clear () = () + let pp_title fmt x = + Format.fprintf fmt "Equality for %a" + F.Compinfo.pp_title x + let pp_descr fmt _ = + Format.pp_print_string fmt "Axiomatic Definition" + end) + + module ArrEqName = F.DRegister + (struct + include F.Arrayinfo + let declare arr _eqname = + Formula.Predicate[Array arr;Array arr] + let prefix = "Eqarr" + let section = S_Logic_Sig + let clear () = () + let pp_title fmt x = + Format.fprintf fmt "Equality for %a" F.Arrayinfo.pp_title x + end) + + module ArrEqDef = F.DRegister + (struct + include F.Arrayinfo + let declare arr _axname = + let eq_name = ArrEqName.get_definition arr in + Formula.Axiom(eq_array_definition arr eq_name.d_name) + let prefix = "EqarrDef" + let section = S_Logic_Prop + let clear () = () + let pp_title fmt x = + Format.fprintf fmt "Equality for %a" + F.Arrayinfo.pp_title x + let pp_descr fmt _ = + Format.pp_print_string fmt "Axiomatic Definition" + end) + + let eq_record comp (ta:F.record) (tb:F.record) = + if comp.cfields <>[] then RecEqDef.define comp ; + let eq = RecEqName.get_definition comp in + F.p_app2 eq.d_name ta tb + + let eq_array arr (ta:F.array) (tb:F.array) = + ArrEqDef.define arr ; + let eq = ArrEqName.get_definition arr in + F.p_app2 eq.d_name ta tb + + let equal te a b = + match te with + | C_int _ | C_float _ -> F.p_eq a b + | C_pointer t -> + let obj = object_of t in + M.equal_loc (M.loc_of_term obj a) (M.loc_of_term obj b) + | C_comp comp -> eq_record comp (F.unwrap a) (F.unwrap b) + | C_array arr -> eq_array arr (F.unwrap a) (F.unwrap b) + + let () = equal_rec := equal + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/datalib.mli frama-c-20111001+nitrogen+dfsg/src/wp/datalib.mli --- frama-c-20110201+carbon+dfsg/src/wp/datalib.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/datalib.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,66 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Ctypes +open Formula + + +module Cvalues(M : Mvalues.Model) : Mvalues.Values + with type loc = M.loc + and module F = M.F + and module A = M.A + and module R = M.R + + +module Collector : sig + type t + + val push : unit -> t + val pop : t -> Wpo.warning list * Property.t list + + (** + * When adding a warning, one has to provide : + * - the source of the warning (for instance "model M"), + * - the effect of the warning (for instance "stop computation") + * - and a formated message about why this warning is emited. + *) + val add_warning : ?severe:bool -> ?source:string -> reason:string -> + ('a, Format.formatter, unit) format -> 'a + + val add_depend : Property.t -> unit + +end + + + + + +module Create (V:Mvalues.Values) : Formula.Logic with module F = V.F + + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/data_mem.ml frama-c-20111001+nitrogen+dfsg/src/wp/data_mem.ml --- frama-c-20110201+carbon+dfsg/src/wp/data_mem.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/data_mem.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,335 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Proof Environment to deal with Arrays and Record in Memory Models --- *) +(* -------------------------------------------------------------------------- *) + +open Formula +open Cil_types +open Ctypes + +module Create(M : Mvalues.Data) = +struct + module F = M.F + + (* Declaration of record format *) + + module Cformat = F.DRegister + (struct + include F.Compinfo + let prefix = "Cfmt" + let section = S_Cons + let clear () = () + let pp_title fmt c = + Format.fprintf fmt "Format for %s '%s'" + (if c.cstruct then "struct" else "union") c.cname + let declare comp _ = + Function ([],Formula.ADT("format",[Record comp])) + end) + + (* Declaration of array format *) + + module Aformat = F.DRegister + (struct + include F.Arrayinfo + let prefix = "Afmt" + let section = S_Cons + let clear () = () + let pp_title fmt arr = + Format.fprintf fmt "Format for array %a" + Ctypes.pretty (C_array arr) + let pp_descr fmt _ = + Format.fprintf fmt "Decode array from memory" + let declare arr _ = + Function ([],Formula.ADT("format",[Array arr])) + end) + + (* ------------------------------------------------------------------------ *) + (* --- Utilities --- *) + (* ------------------------------------------------------------------------ *) + + let in_range arr xi = + let i_pos = F.p_icmp Cleq F.i_zero xi in + let i_max = match arr.arr_flat with + | None -> F.p_true + | Some a -> F.p_icmp Clt xi (F.e_icst (Int64.to_string a.arr_size)) + in F.p_and i_pos i_max + + module Compound(R : sig val prefix : string end) : + sig + val add_axiom : string -> Lexing.position option + -> string -> string -> F.pred -> unit + val on_array : (arrayinfo -> unit) -> unit + val on_record : (compinfo -> unit) -> unit + val define : c_object -> unit + end + = + struct + + module Hcomp = F.Compinfo.H + module Harray = F.Arrayinfo.H + + let cindex = Hcomp.create 131 + let aindex = Harray.create 131 + let clear () = Hcomp.clear cindex ; Harray.clear aindex + let () = Fol_decl.register_prefix R.prefix + let () = F.on_clear clear + + let add_axiom obj src name path prop = + let dname = F.fresh_name R.prefix name in + F.add_declaration { + d_name = dname ; + d_section = S_Model_Prop ; + d_source = src ; + d_item = Formula.Axiom prop ; + d_title = (fun fmt -> Format.fprintf fmt "%s in loaded object %s" R.prefix obj) ; + d_descr = (fun fmt -> Format.fprintf fmt "Path %s" path) ; + } + + let define_array = ref (fun _ -> assert false) + let define_comp = ref (fun _ -> assert false) + + let on_array f = define_array := f + let on_record f = define_comp := f + + let define = function + | C_array arr -> + let key = F.Arrayinfo.index arr in + if not (Harray.mem aindex key) then + ( Harray.add aindex key () ; !define_array arr ) + + | C_comp comp -> + let key = F.Compinfo.index comp in + if not (Hcomp.mem cindex key) then + ( Hcomp.add cindex key () ; !define_comp comp ) + | _ -> () + + end + + (* ------------------------------------------------------------------------ *) + (* --- Axioms for accessing sub-terms in loaded compounds --- *) + (* ------------------------------------------------------------------------ *) + + module LoadedCompound = + struct + + include Compound(struct let prefix = "Loaded" end) + + let rec define_access obj pool name path xs mem loc tr = + match tr with + + | C_array arr -> + let te = Ctypes.object_of arr.arr_element in + let xi = F.p_fresh pool "i" (Model Formula.Integer) in + let loc' = M.index loc te (F.var xi) in + let r = M.logic_of_value (M.load_mem mem tr loc) in + let v = F.acc_index (F.unwrap r) (F.var xi) in + let v' = M.logic_of_value (M.load_mem mem te loc') in + let xs' = xs @ [xi] in + let prop = + F.p_forall xs' + (F.p_implies (in_range arr (F.var xi)) (M.equal te v v')) + in + let name' = Pretty_utils.sfprintf "%s_idx" name in + let path' = Pretty_utils.sfprintf "%s[%a]" path F.pp_term (F.var xi) in + add_axiom obj (F.Arrayinfo.location arr) name' path' prop ; + define_access obj pool name' path' xs' mem loc' te + + | C_comp comp -> + List.iter + (fun f -> + let te = Ctypes.object_of f.ftype in + let loc' = M.field loc f in + let r = M.logic_of_value (M.load_mem mem tr loc) in + let v = F.acc_field (F.unwrap r) f in + let v' = M.logic_of_value (M.load_mem mem te loc') in + let prop = F.p_forall xs (M.equal te v v') in + let name' = Format.sprintf "%s_%s" name f.fname in + let path' = Format.sprintf "%s.%s" name f.fname in + add_axiom obj (F.Compinfo.location comp) name' path' prop ; + define_access obj pool name' path' xs mem loc' te + ) comp.cfields + + | _ -> () + + let define_array arr = + let pool = F.pool () in + let name = F.Arrayinfo.basename arr in + let path = "array" in + let xm = F.p_fresh pool "m" (Model M.tau_of_mem) in + let xa,a = M.forall_loc pool in + define_access name pool name path (xm::xa) (F.var xm) a (C_array arr) + + let define_comp comp = + let pool = F.pool () in + let name = F.Compinfo.basename comp in + let path = comp.cname in + let xm = F.p_fresh pool "m" (Model M.tau_of_mem) in + let xa,a = M.forall_loc pool in + define_access name pool name path (xm::xa) (F.var xm) a (C_comp comp) + + let () = on_array define_array + let () = on_record define_comp + + end + + (* -------------------------------------------------------------------------- *) + (* --- Axioms for accessing sub-terms in stored compounds --- *) + (* -------------------------------------------------------------------------- *) + + module StoredCompound = + struct + + include Compound(struct let prefix = "Stored" end) + + let rec define_update obj pool name path xs mem loc tr r = + match tr with + + | C_array arr -> + let xi = F.p_fresh pool "i" (Model Formula.Integer) in + let te = Ctypes.object_of arr.arr_element in + let mem' = M.store_mem mem tr loc (M.value_of_logic tr r) in + let loc' = M.index loc te (F.var xi) in + let ve = F.acc_index (F.unwrap r) (F.var xi) in + let v' = M.logic_of_value (M.load_mem mem' te loc') in + let xs' = xs @ [xi] in + let prop = F.p_forall xs' + (F.p_implies (in_range arr (F.var xi)) (M.equal te ve v')) in + let name' = Pretty_utils.sfprintf "%s_idx" name in + let path' = Pretty_utils.sfprintf "%s[%a]" path F.pp_var xi in + add_axiom obj (F.Arrayinfo.location arr) name' path' prop ; + define_update obj pool name' path' xs' mem' loc' te ve + + | C_comp comp -> + List.iter + (fun f -> + let te = Ctypes.object_of f.ftype in + let mem' = M.store_mem mem tr loc (M.value_of_logic tr r) in + let loc' = M.field loc f in + let ve = F.acc_field (F.unwrap r) f in + let v' = M.logic_of_value (M.load_mem mem' te loc') in + let prop = F.p_forall xs (M.equal te ve v') in + let name' = Format.sprintf "%s_%s" name f.fname in + let path' = Format.sprintf "%s.%s" name f.fname in + add_axiom obj (F.Compinfo.location comp) name' path' prop ; + define_update obj pool name' path' xs mem loc' te ve + ) comp.cfields + + | _ -> () + + + let define_array arr = + let pool = F.pool () in + let name = F.Arrayinfo.basename arr in + let path = "array" in + let xm = F.p_fresh pool "m" (Model M.tau_of_mem) in + let xr = F.p_fresh pool "r" (Model (Array arr)) in + let xa,a = M.forall_loc pool in + define_update name pool name path + (xm::xr::xa) (F.var xm) a (C_array arr) (F.var xr) + + let define_comp comp = + let pool = F.pool () in + let name = F.Compinfo.basename comp in + let path = comp.cname in + let xm = F.p_fresh pool "m" (Model M.tau_of_mem) in + let xr = F.p_fresh pool "r" (Model (Record comp)) in + let xa,a = M.forall_loc pool in + define_update name pool name path + (xm::xr::xa) (F.var xm) a (C_comp comp) (F.var xr) + + let () = on_array define_array + let () = on_record define_comp + + end + + (* -------------------------------------------------------------------------- *) + (* --- Axioms for loading an object after a store inside --- *) + (* -------------------------------------------------------------------------- *) + + module UpdatedCompound = + struct + + include Compound(struct let prefix = "Updated" end) + + let define_array arr = + let tr = C_array arr in + let te = Ctypes.object_of arr.arr_element in + let pool = F.pool () in + let xm = F.p_fresh pool "m" (Model M.tau_of_mem) in + let xa,loc = M.forall_loc pool in + let xi = F.p_fresh pool "i" (Model Integer) in + let xv = F.p_fresh pool "e" (Model (M.tau_of_object te)) in + let mem = F.var xm in + let loc' = M.index loc te (F.var xi) in + let mem' = M.store_mem mem te loc' (M.value_of_logic te (F.var xv)) in + let r0 = M.logic_of_value (M.load_mem mem tr loc) in + let r1 = M.logic_of_value (M.load_mem mem' tr loc) in + let r2 = F.wrap (F.upd_index (F.unwrap r0) (F.var xi) (F.var xv)) in + let prop = F.p_forall (xm::xi::xv::xa) + (F.p_implies (in_range arr (F.var xi)) (M.equal tr r1 r2)) in + let name = F.Arrayinfo.basename arr in + let path = Pretty_utils.sfprintf "%s.[%a]" name F.pp_var xi in + add_axiom name (F.Arrayinfo.location arr) name path prop + + let define_comp comp = + List.iter + (fun f -> + let tr = C_comp comp in + let te = Ctypes.object_of f.ftype in + let pool = F.pool () in + let xm = F.p_fresh pool "m" (Model M.tau_of_mem) in + let xa,loc = M.forall_loc pool in + let xv = F.p_fresh pool "e" (Model (M.tau_of_object te)) in + let mem = F.var xm in + let loc' = M.field loc f in + let mem' = M.store_mem mem te loc' (M.value_of_logic te (F.var xv)) in + let r0 = M.logic_of_value (M.load_mem mem tr loc) in + let r1 = M.logic_of_value (M.load_mem mem' tr loc) in + let r2 = F.wrap (F.upd_field (F.unwrap r0) f (F.var xv)) in + let prop = F.p_forall (xm::xv::xa) (M.equal tr r1 r2) in + let name = F.Compinfo.basename comp in + let path = Pretty_utils.sfprintf "%s.%s" name f.fname in + add_axiom name (F.Compinfo.location comp) name path prop + ) comp.cfields + + let () = on_array define_array + let () = on_record define_comp + + end + + (* -------------------------------------------------------------------------- *) + (* --- API --- *) + (* -------------------------------------------------------------------------- *) + + let record_format comp = F.e_app0 (Cformat.get_definition comp).d_name + let array_format arr = F.e_app0 (Aformat.get_definition arr).d_name + + (* -------------------------------------------------------------------------- *) + (* --- Registration --- *) + (* -------------------------------------------------------------------------- *) + + let loaded te = LoadedCompound.define te ; UpdatedCompound.define te + let stored te = StoredCompound.define te + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/data_mem.mli frama-c-20111001+nitrogen+dfsg/src/wp/data_mem.mli --- frama-c-20110201+carbon+dfsg/src/wp/data_mem.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/data_mem.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,39 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Proof Environment to deal with Arrays and Record in Memory Models --- *) +(* -------------------------------------------------------------------------- *) + +open Cil_types +open Ctypes + +module Create(M : Mvalues.Data) : +sig + + val record_format : compinfo -> 'a M.F.term + val array_format : arrayinfo -> 'a M.F.term + + val loaded : c_object -> unit + val stored : c_object -> unit + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_cc.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_cc.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_cc.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_cc.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,130 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(* --- Remove let with Closure Conversion *) +(* ------------------------------------------------------------------------ *) + +open Fol + +(* I. such as closure conversion : + This section is for generated terms and predicate + for ergo and for coq output. + Tlet (x,t1,t2) becomes Tapp(f,t1::free_vars t2) + when f is a function such that : + {name = f; param =x::free_vars t2 ; body = t2} + Plet (x,t,p) becomes Pforall(nx,Pimplies(Papp("eq",[Tvar nx;t]),p) + +*) + +(* [free_vars bvars fvars t] computes the free variables of [t] without + repetition, accroding to the already bound variables [bvars] and + the already found free variables [fvars] *) +let rec free_vars bvars fvars = function + | Tlet(x,t1,t2) -> + let f1 = free_vars bvars fvars t1 in + free_vars (Vset.add x bvars) f1 t2 + | Tapp(_f,tl) -> + (List.fold_left (fun f t -> free_vars bvars f t) fvars tl) + | Tif (c,tt,tf) -> + let fc = free_vars bvars fvars c in + let ftt = free_vars bvars fc tt in + free_vars bvars ftt tf + | Tvar x -> + if Vset.mem x bvars then fvars else (Vset.add x fvars) + | _ -> fvars + + +type f_let = + { name : string ; + param : Var.t list ; + body : term;} + +let mk_def xl t defs = + let f = "_let_"^(string_of_int (snd !defs) ) in + defs := + ({name = f ; param = xl; body = t}::(fst !defs)), + 1+(snd !defs);f + +let new_name x sigma cpt = + incr cpt; + let sx = Var.basename x^(string_of_int !cpt) in + let nx = Var.fresh_named_var sx (Var.var_type x) in + nx,(Vmap.add x nx sigma) + +let rec unlet_term sigma bvars defs = function + | Tlet(x,t1,t2) -> + let fvars = free_vars (Vset.add x bvars) Vset.empty t2 in + let args = x::(Vset.elements fvars) in + let t2' = unlet_term sigma (Vset.add x bvars) defs t2 in + let f = mk_def args t2' defs in + e_app f + ((unlet_term sigma bvars defs t1):: + (List.map (fun x -> e_var x) args)) + | Tapp(f,tl) -> + e_app f (List.map (fun t -> unlet_term sigma bvars defs t) tl) + | Tif (c,tt,tf) -> + e_if (unlet_term sigma bvars defs c) + (unlet_term sigma bvars defs tt) + (unlet_term sigma bvars defs tf) + | Tvar x -> e_var (try Vmap.find x sigma with Not_found -> x) + | t -> t + +let rec unlet_pred sigma bvars defs cpt = function + | Papp (f, tl) -> + p_app f (List.map (fun t -> unlet_term sigma bvars defs t) tl) + | Pimplies (p1,p2) -> + Pimplies(unlet_pred sigma bvars defs cpt p1, + unlet_pred sigma bvars defs cpt p2) + | Pif (t,p1,p2) -> + Pif(unlet_term sigma bvars defs t, + unlet_pred sigma bvars defs cpt p1, + unlet_pred sigma bvars defs cpt p2) + | Pand (p1,p2) -> + Pand(unlet_pred sigma bvars defs cpt p1, unlet_pred sigma bvars defs cpt p2) + | Por (p1,p2) -> + Por(unlet_pred sigma bvars defs cpt p1, unlet_pred sigma bvars defs cpt p2) + | Piff (p1,p2) -> + Piff(unlet_pred sigma bvars defs cpt p1, unlet_pred sigma bvars defs cpt p2) + | Pnot p -> Pnot (unlet_pred sigma bvars defs cpt p) + | Pforall (x,p) -> + let nx,nsigma = new_name x sigma cpt in + Pforall(nx,unlet_pred nsigma (Vset.add x bvars) defs cpt p) + | Pexists(x,p) -> + let nx,nsigma = new_name x sigma cpt in + Pexists(nx,unlet_pred nsigma (Vset.add x bvars) defs cpt p) + | Plet (x,t,p) -> + let nx,nsigma = new_name x sigma cpt in + let b = Vset.add x bvars in + p_forall nx + (p_implies + (p_app "eq" [e_var nx;unlet_term sigma b defs t]) + (unlet_pred nsigma b defs cpt p)) + | Pnamed(s,p) -> Pnamed(s,unlet_pred sigma bvars defs cpt p) + | p -> p + + +let unlet p = + let cpt = ref 0 in + let defs= ref ([] , 0) in + let p' = unlet_pred Vmap.empty Vset.empty defs cpt p in + (fst !defs),p' diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_coq.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_coq.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_coq.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_coq.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,422 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Fol +open Fol_norm +open Formula +open Format + +(* -------------------------------------------------------------------------- *) +(* --- Coq Export --- *) +(* -------------------------------------------------------------------------- *) + +let get_ufield f = "get_"^(f.Cil_types.fname)^"_"^(f.Cil_types.fcomp.Cil_types.cname) +let set_ufield f = "set_"^(f.Cil_types.fname)^"_"^(f.Cil_types.fcomp.Cil_types.cname) + +let constant fmt = function + | ConstInt n -> + let k = Big_int.big_int_of_string n in + if Big_int.lt_big_int k Big_int.zero_big_int then + pp_print_string fmt ("( "^n^" )") + else pp_print_string fmt n + | ConstBool b -> pp_print_string fmt (if b then "true" else "false") + | ConstUnit -> pp_print_string fmt "void" + | ConstFloat f -> fprintf fmt "%s%%R" (Kreal.convert f) + +let pp_list pp fmt = function + | [] -> () + | x::xs -> + pp fmt x ; + List.iter (fun x -> fprintf fmt " @,%a" pp x) xs + +let pp_typelist pp fmt = function + | [] -> () + | x::xs -> + pp fmt x ; + List.iter (fun x -> fprintf fmt " @,->%a" pp x) xs + +let pp_flow fmt nil op pp = function + | [] -> + pp_print_string fmt nil + | x::xs -> + fprintf fmt "@[<hov 1>(%a" pp x ; + List.iter (fun x -> fprintf fmt "@, %s%a" op pp x) xs ; + fprintf fmt ")@]" + +let pp_block fmt tab op pp ps = + match ps with + | [] -> () + | p::ps -> + fprintf fmt "%s %a" tab pp p ; + List.iter (fun p -> fprintf fmt "@\n%s %a" op pp p) ps + +let pp_var fmt v = + let name = Fol_decl.identifier (Var.var_name v) in + fprintf fmt "%s" name + +let rec collect_assoc op xs = function + | [] -> List.rev xs + | Tapp(id,ts) :: others when id = op -> + collect_assoc op (collect_assoc op xs ts) others + | t::others -> + collect_assoc op (t::xs) others + +let field f = "field_"^f.Cil_types.fname^"_"^f.Cil_types.fcomp.Cil_types.cname +let ufield f = "field_"^f.Cil_types.fname^"_"^f.Cil_types.fcomp.Cil_types.cname + +let fpp_term term fmt t = + match t with + | Tconst c -> constant fmt c + | Tvar v -> pp_var fmt v + | Tapp (id, []) -> pp_print_string fmt id + | Tapp ("ite",[c;a;b]) | Tif (c,a,b) -> + fprintf fmt "(@[<v 0>if %a@ then %a@ else %a@])" + term c term a term b + | Tapp ("neg_int",[a]) -> + fprintf fmt "@[<hov 1> (-%a)@]" term a + | Tapp ("add_int", ts) -> + let xs = collect_assoc "add_int" [] ts in + pp_flow fmt "0" "+" term xs + | Tapp ("sub_int", [a;b]) -> + fprintf fmt "@[<hov 1>(%a@ -%a)@]" term a term b + | Tapp ("mul_int", ts) -> + let xs = collect_assoc "mul_int" [] ts in + pp_flow fmt "1" "*" term xs + | Tapp (id, t::ts) -> + fprintf fmt "@[<hov 2>(%s@, %a" id term t ; + List.iter (fun t -> fprintf fmt " @, %a" term t) ts ; + fprintf fmt ")@]" + | Tlet (x,v,t) -> + fprintf fmt "(@[<v 0>let %a@ := %a@ in %a@])" + pp_var x term v term t + | Taccess(t,i) -> + fprintf fmt "@[<hov 2>(access@, %a@, %a)@]" term t term i + | Tupdate(t,i,v) -> + fprintf fmt "@[<hov 2>(update@, %a@, %a@, %a)@]" term t term i term v + | Tgetfield(f,r) -> + if f.Cil_types.fcomp.Cil_types.cstruct then + fprintf fmt "@[<hov 2>(%a.(%s))@]" term r (field f) + else (fprintf fmt "@[<hov 2>(%s @, %a)@]"(get_ufield f) term r) + | Tsetfield(f,r,v) -> + let cp = f.Cil_types.fcomp in + if cp.Cil_types.cstruct then + begin + let built_rec = "mk"^(String.capitalize cp.Cil_types.cname) in + fprintf fmt "@[<hov 2> ( %s " built_rec; + List.iter (fun g -> + (if Cil_datatype.Fieldinfo.equal g f then + Format.fprintf fmt"(%a)@]" term v + else + Format.fprintf fmt "%a.(%s)" term r (field g)) + ) cp.Cil_types.cfields ; + fprintf fmt ")@]" + end + else fprintf fmt "@[<hov 2>(%s @, %a @, %a)@]"(set_ufield f) term r term v + +let rec collect_or ps = function + | Por(a,b) -> collect_or (collect_or ps b) a + | p -> p :: ps + +let rec collect_and ps = function + | Pand(a,b) -> collect_and (collect_and ps b) a + | p -> p :: ps + +let rec collect_imply ps = function + | Pimplies(a,b) -> collect_and (collect_imply ps b) a + | p -> p :: ps + +let rec collect_iff ps = function + | Piff(a,b) -> collect_iff (collect_iff ps b) a + | p -> p :: ps + +type 'a pp = Format.formatter -> 'a -> unit +type pp_env = { + pp_type : Formula.tau pp ; + pp_term : term pp ; + pp_pred : pred pp ; +} + +let pp_args pp_tau fmt = function + | [] -> () + | [x] -> Format.fprintf fmt "(%a@,:@,%a)@,:%a@,=@," + pp_var x pp_tau (Var.var_type x) pp_tau (Var.var_type x) + | x::m -> + Format.fprintf fmt "(%a@,:@,%a)@," + pp_var x pp_tau (Var.var_type x); + List.iter (fun x -> Format.fprintf fmt "@,(%a@,:@,%a)@," + pp_var x pp_tau (Var.var_type x) ) m; + Format.fprintf fmt "@,:%a@,=@\n" pp_tau (Var.var_type x) + +open Fol_cc + +let fpp_f_let pp_tau pp_term fmt fl = + Format.fprintf fmt "@[<hov 2>Definition %s@,%a%a@]" + fl.name (pp_args pp_tau) fl.param + pp_term fl.body + +let fpp_lf_let pp_tau pp_term fmt = function + | [] -> () + | x::xs -> + let pp = fpp_f_let pp_tau pp_term in + pp fmt x ; + List.iter (fun x -> fprintf fmt "%a@\n" pp x ) xs + +let rec epp_pred_vbox env fmt p = + match p with + | Pand _ -> pp_block fmt " " " /\\ " env.pp_pred (collect_and [] p) + | Por _ -> pp_block fmt " " " \\/ " env.pp_pred (collect_or [] p) + | Pimplies _ -> pp_block fmt " " "->" env.pp_pred (collect_imply [] p) + | Piff _ -> pp_block fmt " " "<->" env.pp_pred (collect_iff [] p) + | Pforall(x,p) -> + fprintf fmt "forall (%a:%a),@\n" pp_var x env.pp_type (Var.var_type x) ; + epp_pred_vbox env fmt p + | Pexists(x,p) -> + fprintf fmt "exists %a:%a,@\n" pp_var x env.pp_type (Var.var_type x) ; + epp_pred_vbox env fmt p + | Plet(x,t,p) -> + fprintf fmt "@[<hov 2>let %a:=@ %a@ in @]@\n" pp_var x env.pp_term t ; + epp_pred_vbox env fmt p + | Pif(t,p,q) -> + fprintf fmt "@[<hov 0>if @[<hov 2>%a@]@ then@]@\n %a@\nelse@\n %a" + env.pp_term t env.pp_pred p env.pp_pred q + | (Ptrue | Pfalse | Papp _ | Pnot _ | Pnamed _) -> + env.pp_pred fmt p + +let rec epp_pred_atom env fmt p = + match p with + | Pand _ | Por _ | Pimplies _ | Piff _ | Pif _ + | Pforall _ | Pexists _ | Plet _ -> + fprintf fmt "@[<v 1>(%a)@]" (epp_pred_vbox env) p + | Pnot p -> + fprintf fmt "@[<hov 2>(~@ %a)@]" (epp_pred_atom env) p + | Pnamed(tag,p) -> + fprintf fmt "@[<hov 0>(*%s:*)@,%a@]" tag (epp_pred_atom env) p + | Ptrue -> pp_print_string fmt "True" + | Pfalse -> pp_print_string fmt "False" + | Papp(id,[]) -> pp_print_string fmt id + | Papp (("eq" | "eq_int" | "eq_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ =@ %a)@]" env.pp_term t1 env.pp_term t2 + | Papp (("neq" | "neq_int" | "neq_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ <>@ %a)@]" env.pp_term t1 env.pp_term t2 + | Papp (("lt_int"| "lt_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ <@ %a)@]" env.pp_term t1 env.pp_term t2 + | Papp (("le_int"| "le_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ <=@ %a)@]" env.pp_term t1 env.pp_term t2 + | Papp(id,t::ts) -> + fprintf fmt "@[<hov 2>(%s @,%a" id env.pp_term t ; + List.iter (fun t -> fprintf fmt "@ %a" env.pp_term t) ts ; + fprintf fmt ")@]" + +let fpp_pred predicate pp_term pp_type fmt p = + match p with + | Ptrue -> fprintf fmt "True" + | Pfalse -> fprintf fmt "False" + | Papp (id, [])-> fprintf fmt "%s" id + | Papp ("eq", [t1; t2]) -> fprintf fmt "(%a =@ %a)" pp_term t1 pp_term t2 + | Papp ("neq", [t1; t2]) -> fprintf fmt "(%a <>@ %a)" pp_term t1 pp_term t2 + | Papp (id, l) -> fprintf fmt "@[(%s @, %a)@]" id (pp_list pp_term) l + | Pimplies (a, b) -> fprintf fmt "(@[%a ->@ %a@])" predicate a predicate b + | Piff (a, b) -> fprintf fmt "(@[%a <->@ %a@])" predicate a predicate b + | Pand (a, b) -> fprintf fmt "(@[%a /\\ @ %a@])" predicate a predicate b + | Por (a, b) -> fprintf fmt "(@[%a \\/ @ %a@])" predicate a predicate b + | Pnot a -> fprintf fmt "(~ %a)" predicate a + | Pif (a, b, c) -> + fprintf fmt "(@[if %a then@ %a else@ %a@])" + pp_term a predicate b predicate c + | Pforall (v,p) -> + fprintf fmt "@[<hov 0>(forall (%a:%a),@ %a@])" + pp_var v pp_type (Var.var_type v) predicate p + | Pexists (v,p) -> + fprintf fmt "@[<hov 0>(exists %a:%a,@ %a@])" + pp_var v pp_type (Var.var_type v) predicate p + | Plet (x,v,p) -> + fprintf fmt "@[<hov 0>(let %a :=@[<hov 2>@ %a@ in@]@ %a@])" + pp_var x pp_term v predicate p + | Pnamed (n, p) -> + fprintf fmt "@[(*%s:*) %a@]" n predicate p + + +let rec fpp_fields pp_tau tau_of_ctype_logic fmt = function + | [] -> () + | [f] -> Format.fprintf fmt "%s@,:@,%a@\n" (field f) pp_tau + (tau_of_ctype_logic f.Cil_types.ftype) + | f::m -> + Format.fprintf fmt "%s@,:@,%a;@\n" (field f) pp_tau + (tau_of_ctype_logic f.Cil_types.ftype); + fpp_fields pp_tau tau_of_ctype_logic fmt m + +let pp_param pp_tau fmt x = + Format.fprintf fmt "%a:%a" pp_var x pp_tau (Fol.Var.var_type x) + +let fpp_item predicate pp_tau tau_of_ctype_logic pp_term fmt x = + function + | Formula.Cons k -> + fprintf fmt "Definition %s:Z:= %d.@\n" x k + | Formula.Function ([], t) -> + fprintf fmt "Parameter %s: %a.@\n" x pp_tau t + | Formula.Function (tl, t) -> + fprintf fmt "Parameter %s: @[<hov 0>%a -> %a@].@\n" x (pp_typelist pp_tau) tl pp_tau t + | Formula.Predicate [] -> + fprintf fmt "Parameter %s: Prop.@\n" x + | Formula.Predicate tl -> + fprintf fmt "Parameter %s: @[<hov 0>%a -> Prop.@]@\n" x (pp_typelist pp_tau) tl + | Formula.FunctionDef (xs,tr,exp) -> + Format.fprintf fmt "@[<hv 2>Definition %s (%a) : %a :=@ @[<hov 0>%a.@]@]@\n" + x (pp_list (pp_param pp_tau)) xs pp_tau tr pp_term exp + | Formula.PredicateDef (xs,prop) -> + Format.fprintf fmt "@[<hv 2>Definition %s (%a): Prop :=@ @[<hov 0>%a.@]@]@\n" + x (pp_list (pp_param pp_tau)) xs predicate prop + | Formula.Axiom p -> + begin + match Fol_norm.compile p with + | Pred p' -> fprintf fmt "@[<hv 2>Axiom %s:@ %a.@\n@]@\n" x predicate p' + | Conv (defs,p') -> + fpp_lf_let pp_tau pp_term fmt defs ; + fprintf fmt "@[<hv 2>Axiom %s:@ %a.@\n@]@\n" x predicate p' + end + | Formula.Type 0 -> + fprintf fmt "Definition %s:=Set.@\n" x + | Formula.Type n -> + fprintf fmt "@[<hov 2>Definition %s:=Set" x; + for k=1 to n do fprintf fmt " -> Set" done ; + fprintf fmt ".@]@\n" + | Formula.Trecord c -> + let rname = String.capitalize c.Cil_types.cname in + if c.Cil_types.cstruct then + begin + fprintf fmt "@[<hov 2> Record %s : Set := mk%s@\n" rname rname ; + fprintf fmt "{ @\n" ; + fpp_fields pp_tau tau_of_ctype_logic fmt c.Cil_types.cfields ; + fprintf fmt "}.@]@\n" + end + else + begin + fprintf fmt "@[<hov 2> Definition %s:=Set.@\n" rname; + let l = c.Cil_types.cfields in + List.iter (fun f -> + let fd = field f in + let t = tau_of_ctype_logic f.Cil_types.ftype in + Format.pp_print_newline fmt () ; + fprintf fmt "Parameter %s: %s -> %a.@\n " + (get_ufield f) rname pp_tau t; + Format.pp_print_newline fmt () ; + fprintf fmt "Parameter %s: %s -> %a -> %s.@\n " + (set_ufield f) rname pp_tau t rname; + Format.pp_print_newline fmt () ; + fprintf fmt "Axiom get_set_same_%s:@\n" fd; + fprintf fmt " forall r v, %s (%s r v) = v.@\n" + (get_ufield f) (set_ufield f) + ) l + + end + + + +let fpp_header fmt d = + begin + d.d_title fmt ; + Format.pp_print_newline fmt () ; + ( match d.d_source with + | Some { Lexing.pos_fname=f ; Lexing.pos_lnum=k } -> + Format.fprintf fmt "%s:%d: " f k + | None -> () ) ; + d.d_descr fmt ; + end + +let fpp_decl predicate pp_tau tau_of_ctype_logic pp_term fmt d = + begin + fpp_header fmt d ; + Format.pp_print_newline fmt () ; + fpp_item predicate pp_tau tau_of_ctype_logic pp_term fmt d.d_name d.d_item ; + Format.pp_print_newline fmt () ; + end + +let fpp_goal predicate fmt x p = + fprintf fmt "@[<hv 2>Lemma %s:@ %a.@]@." x predicate p + + +module ECoq(L:sig val tau_of_ctype_logic : Cil_types.typ -> Formula.tau end) = +struct + +type pred = Fol.pred +type decl = Fol.decl + +let rec export_tau fmt = function + | Integer -> pp_print_string fmt "Z" + | Real -> pp_print_string fmt "R" + | Boolean -> pp_print_string fmt "bool" + | Pointer t -> export_tau fmt t + | Record c -> + let rname = String.capitalize c.Cil_types.cname in + Format.fprintf fmt "%s" rname + | Array arr -> + Format.fprintf fmt "(array %a)" + export_tau (L.tau_of_ctype_logic arr.Ctypes.arr_element) + | Set te -> + Format.fprintf fmt "(set %a)" export_tau te + | ADT(s,[]) -> pp_print_string fmt s + | ADT("farray",[t]) -> Format.fprintf fmt "(array %a)" export_tau t + | ADT(s,[t]) -> Format.fprintf fmt "(%s %a)" s export_tau t + | ADT(s,t::ts) -> + Format.fprintf fmt "@ (%s " s; + Format.fprintf fmt "@ %a " export_tau t ; + List.iter (fun t -> Format.fprintf fmt "@ %a" export_tau t) ts; + Format.fprintf fmt ")" + + +let rec export_term fmt t = fpp_term export_term fmt t + +let rec pp_pred_atom fmt p = + epp_pred_atom { + pp_type = export_tau; + pp_term = export_term ; + pp_pred = pp_pred_atom; + } fmt p + +let export_pred fmt p = + epp_pred_vbox { + pp_type = export_tau; + pp_term = export_term ; + pp_pred = pp_pred_atom; + } fmt p + +let export_item fmt name item = fpp_item export_pred export_tau fmt name item + +let export_section fmt title = + begin + Format.fprintf fmt "(*----------------------------------------*)@\n" ; + Format.fprintf fmt "(*--- %-32s --- *)@\n" title ; + Format.fprintf fmt "(*----------------------------------------*)@\n" ; + end + +let export_decl fmt d = + Pretty_utils.pp_trail fpp_header fmt d ; + Format.pp_print_newline fmt () ; + fpp_item export_pred export_tau L.tau_of_ctype_logic export_term fmt d.d_name d.d_item + +let export_goal fmt x g = + match Fol_norm.compile g with + | Pred p' -> fpp_goal export_pred fmt x p' + | Conv (defs,p') -> + fpp_lf_let export_tau export_term fmt defs ; + fpp_goal export_pred fmt x p' +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_decl.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_decl.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_decl.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_decl.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,201 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Linked identifiers --- *) +(* -------------------------------------------------------------------------- *) + +let mk_empty = "empty" +let mk_singleton = "singleton" +let mk_union = "union" +let mk_inter = "inter" +let mk_remove = "remove" + +let mk_range = "range" +let mk_range_inf = "range_inf" +let mk_range_sup = "range_sup" +let mk_integers = "integers_set" +let mk_radd = "plus_int" +let mk_rmult = "mult_int" +let mk_rneg = "neg_int" + +let set_range_index = "set_range_index" + + +let mk_imodulo i = Pretty_utils.sfprintf "as_%a" Ctypes.pp_int i +let mk_iguard i = Pretty_utils.sfprintf "is_%a" Ctypes.pp_int i + + +let mk_fguard f = Pretty_utils.sfprintf "is_%a" Ctypes.pp_float f + +(* -------------------------------------------------------------------------- *) +(* --- PRELUDE.why --- *) +(* -------------------------------------------------------------------------- *) + +let neg_int = "neg_int" +let add_int = "add_int" +let sub_int = "sub_int" +let mul_int = "mul_int" +let div_int = "computer_div" +let mod_int = "computer_mod" +let eq_int = "eq" +let ne_int = "neq" +let lt_int = "lt_int" +let le_int = "le_int" + +(* -------------------------------------------------------------------------- *) +(* --- BOOL.why --- *) +(* -------------------------------------------------------------------------- *) + +let bool_not = "bool_not" +let bool_and = "bool_and" +let bool_or = "bool_or" + +(* -------------------------------------------------------------------------- *) +(* --- INTEGERS.why --- *) +(* -------------------------------------------------------------------------- *) + +let eq_int_bool = "eq_int_bool" +let ne_int_bool = "neq_int_bool" +let lt_int_bool = "lt_int_bool" +let le_int_bool = "le_int_bool" + +(* -------------------------------------------------------------------------- *) +(* --- REAL.why --- *) +(* -------------------------------------------------------------------------- *) + +let neg_real = "neg_real" +let add_real = "add_real" +let sub_real = "sub_real" +let mul_real = "mul_real" +let fract_real = "div_real" + +let eq_real_bool = "eq_real_bool" +let ne_real_bool = "neq_real_bool" +let lt_real_bool = "lt_real_bool" +let le_real_bool = "le_real_bool" + +let eq_real = "eq_real" +let ne_real = "neq_real" +let lt_real = "lt_real" +let le_real = "le_real" + +let integer_of_real = "truncate_real_to_int" +let real_of_integer = "real_of_int" + +(* -------------------------------------------------------------------------- *) +(* --- Lexically correct identifiers and reserved Prefixes --- *) +(* -------------------------------------------------------------------------- *) + +let identifier x = + let range a c b = a <= c && c <= b in + let buffer = Buffer.create 80 in + for i=0 to String.length x - 1 do + let c = x.[i] in + if range 'a' c 'z' + || range 'A' c 'Z' + || (i > 0 && range '0' c '9') + || c = '_' + then + Buffer.add_char buffer c ; + done ; + Buffer.contents buffer + +(* Does not need to be projectified but could be. *) + +let reserved_prefix_tbl = Hashtbl.create 17 +let register_prefix s = + Hashtbl.replace reserved_prefix_tbl s () +let has_reserved_prefix name = + try + let index = String.index name '_' in + let prefix = String.sub name 0 index in + Hashtbl.mem reserved_prefix_tbl prefix + with Not_found -> false + +(* --------------------------------------------------------------------- *) +(* --- Pure Type Conversions --- *) +(* --------------------------------------------------------------------- *) + +open Cil_types +open Format +open Ctypes + +module Tau = +struct +(* These pretty print functions are just for pretty print and debugs - file fol_pretty and + F.pp_tau for debug ;) *) + + let tau_of_object = function + | C_int _ -> Formula.Integer + | C_float _ -> Formula.Real + | C_pointer _ -> Formula.Pointer Formula.Integer (*useless and non sense value *) + | C_comp c -> Formula.Record c + | C_array a -> Formula.Array a + + let tau_of_ctype_logic t = tau_of_object (object_of t) + + let rec pp_tau fmt = function + | Formula.Integer -> pp_print_string fmt "int" + | Formula.Real -> pp_print_string fmt "real" + | Formula.Boolean -> pp_print_string fmt "bool" + | Formula.Pointer _ -> pp_print_string fmt "pointer" + | Formula.Record c -> Format.fprintf fmt "%s" c.Cil_types.cname + | Formula.Array a -> + Format.fprintf fmt "%a farray" pp_tau + (tau_of_object (object_of a.arr_element)) + | Formula.Set te -> + if Wp_parameters.verbose_atleast 2 + then Format.fprintf fmt "%a set" pp_tau te + else pp_print_string fmt "set" + | Formula.ADT(s,[]) -> pp_print_string fmt s + | Formula.ADT(s,[t]) -> Format.fprintf fmt "%a %s" pp_tau t s + | Formula.ADT(s,t::ts) -> + Format.fprintf fmt "@[(%a" pp_tau t ; + List.iter (fun t -> Format.fprintf fmt ",@,%a" pp_tau t) ts ; + Format.fprintf fmt ") %s@]" s + + + let tau_of_ctype t = tau_of_object (Ctypes.object_of t) + + let name_of_adt = ref (fun lt -> Printf.sprintf "<%s>" lt.lt_name) + + let rec tau_of_logic_type = function + | Ctype c -> tau_of_object (object_of c) + | Linteger -> Formula.Integer + | Lreal -> Formula.Real + | Ltype( d , [] ) when d.lt_name = Utf8_logic.boolean -> Formula.Boolean + | Ltype( {lt_name="set"} , [t] ) -> Formula.Set (tau_of_logic_type t) + | Ltype( lt , ts) -> + let d = !name_of_adt lt in + Formula.ADT (d,List.map tau_of_logic_type ts) + | Lvar _ -> Wp_parameters.not_yet_implemented "logic type variables" + | Larrow _ -> Wp_parameters.not_yet_implemented "type of logic function" + +end + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_eqs.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_eqs.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_eqs.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_eqs.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,103 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(* --- Remove let with unversally quantified variables *) +(* ------------------------------------------------------------------------ *) + +open Fol + +module Smap = Datatype.String.Map + +let fresh global sigma x = + let base = Var.basename x in + let tau = Var.var_type x in + let k = try Smap.find base !global with Not_found -> 0 in + let v = Var.ident_named_var base k tau in + global := Smap.add base (succ k) !global ; + v , Vmap.add x (e_var v) sigma + +let alpha sigma x = + try Vmap.find x sigma + with Not_found -> Wp_parameters.fatal "Unbound fol-variable %s (eqs)" (Var.var_name x) + + +(* -------------------------------------------------------------------------- *) +(* --- Removal of lets --- *) +(* -------------------------------------------------------------------------- *) + +let rec term global defs sigma = function + | Tconst _ as c -> c + | Tvar v -> alpha sigma v + | Tgetfield(f,r) -> e_getfield f (term global defs sigma r) + | Tsetfield(f,r,v) -> e_setfield f (term global defs sigma r) (term global defs sigma v) + | Taccess(t,i) -> e_access (term global defs sigma t) (term global defs sigma i) + | Tupdate(t,i,v) -> e_update (term global defs sigma t) (term global defs sigma i) (term global defs sigma v) + | Tapp (n,tl) -> e_app n (List.map (term global defs sigma) tl) + | Tif (t1,t2,t3) -> e_if (term global defs sigma t1) (term global defs sigma t2) (term global defs sigma t3) + | Tlet (x,v,t) -> + let v = term global defs sigma v in + let x,sigma = fresh global sigma x in + defs := (x,v) :: !defs ; + term global defs sigma t + +let flush defs p = + List.fold_left + (fun p (x,_) -> p_forall x p) + (List.fold_left + (fun p (x,v) -> + p_implies (p_eq (e_var x) v) p + ) p defs) + defs + +let rec pred global sigma = function + | Ptrue -> Ptrue + | Pfalse -> Pfalse + | Pimplies(p,q) -> p_implies (pred global sigma p) (pred global sigma q) + | Pand(p,q) -> p_and (pred global sigma p) (pred global sigma q) + | Por(p,q) -> p_or (pred global sigma p) (pred global sigma q) + | Piff(p,q) -> p_iff (pred global sigma p) (pred global sigma q) + | Pnot p -> p_not (pred global sigma p) + | Pnamed(a,p) -> p_named a (pred global sigma p) + | Pforall(x,p) -> let x,sigma = fresh global sigma x in p_forall x (pred global sigma p) + | Pexists(x,p) -> let x,sigma = fresh global sigma x in p_exists x (pred global sigma p) + + | Papp(f,es) -> + let defs = ref [] in + let es = List.map (term global defs sigma) es in + flush !defs (p_app f es) + + | Pif(e,p,q) -> + let defs = ref [] in + let e = term global defs sigma e in + let p = pred global sigma p in + let q = pred global sigma q in + flush !defs (p_if e p q) + + | Plet(x,v,p) -> + let defs = ref [] in + let v = term global defs sigma v in + let x,sigma = fresh global sigma x in + let p = pred global sigma p in + flush ( (x,v)::!defs ) p + +let compile p = pred (ref Smap.empty) Vmap.empty p diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_ergo.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_ergo.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_ergo.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_ergo.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,452 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + +open Format + +(* -------------------------------------------------------------------------- *) +(* --- Alt-ergo Export --- *) +(* -------------------------------------------------------------------------- *) + +let get_field f = "get_"^(f.Cil_types.fname)^"_"^(f.Cil_types.fcomp.Cil_types.cname) +let set_field f = "set_"^(f.Cil_types.fname)^"_"^(f.Cil_types.fcomp.Cil_types.cname) + + +let constant fmt = function + | Fol.ConstInt n -> + if n.[0] = '-' + then Format.fprintf fmt "(%s)" n + else pp_print_string fmt n + | Fol.ConstBool b -> pp_print_string fmt (if b then "true" else "false") + | Fol.ConstUnit -> pp_print_string fmt "void" + | Fol.ConstFloat f -> + if f.[0] = '-' + then Format.fprintf fmt "(%s)" f + else pp_print_string fmt f + +let pp_list pp fmt = function + | [] -> () + | x::xs -> + pp fmt x ; + List.iter (fun x -> fprintf fmt ",@,%a" pp x) xs + +let pp_flow fmt nil op pp = function + | [] -> + pp_print_string fmt nil + | x::xs -> + fprintf fmt "@[<hov 1>(%a" pp x ; + List.iter (fun x -> fprintf fmt "@,%s%a" op pp x) xs ; + fprintf fmt ")@]" + +let pp_block fmt tab op pp ps = + match ps with + | [] -> () + | p::ps -> + fprintf fmt "%s %a" tab pp p ; + List.iter (fun p -> fprintf fmt "@\n%s %a" op pp p) ps + +let pp_var fmt v = + let name = Fol_decl.identifier (Fol.Var.var_name v) in + fprintf fmt "%s" name + +let rec collect_assoc op xs = function + | [] -> List.rev xs + | Fol.Tapp(id,ts) :: others when id = op -> + collect_assoc op (collect_assoc op xs ts) others + | t::others -> + collect_assoc op (t::xs) others + +let rec fpp_term fmt t = + match t with + | Fol.Tconst c -> constant fmt c + | Fol.Tvar v -> pp_var fmt v + | Fol.Tapp (id, []) -> pp_print_string fmt id + | Fol.Tapp ("ite",[c;a;b]) | Fol.Tif (c,a,b) -> + fprintf fmt "(@[<v 0>if %a@ then %a@ else %a@])" + fpp_term c fpp_term a fpp_term b + + (* INT *) + | Fol.Tapp ("neg_int", [t]) -> + fprintf fmt "@[<hov 1>(-%a)@]" fpp_term t + | Fol.Tapp ("add_int", ts) -> + let xs = collect_assoc "add_int" [] ts in + pp_flow fmt "0" "+" fpp_term xs + | Fol.Tapp ("sub_int", [a;b]) -> + fprintf fmt "@[<hov 1>(%a@,-%a)@]" fpp_term a fpp_term b + | Fol.Tapp ("mul_int", ts) -> + let xs = collect_assoc "mul_int" [] ts in + pp_flow fmt "1" "*" fpp_term xs + + (* REAL *) + | Fol.Tapp ("neg_real", [t]) -> + fprintf fmt "@[<hov 1>(-%a)@]" fpp_term t + | Fol.Tapp ("add_real", ts) -> + let xs = collect_assoc "add_real" [] ts in + pp_flow fmt "0.0" "+" fpp_term xs + | Fol.Tapp ("sub_real", [a;b]) -> + fprintf fmt "@[<hov 1>(%a@,-%a)@]" fpp_term a fpp_term b + | Fol.Tapp ("mul_real", ts) -> + let xs = collect_assoc "mul_real" [] ts in + pp_flow fmt "1.0" "*" fpp_term xs + | Fol.Tapp ("div_real", [a;b]) -> + fprintf fmt "@[<hov 1>(%a@,/%a)@]" fpp_term a fpp_term b + + (* OTHER *) + | Fol.Taccess(a,k) -> + Format.fprintf fmt "@[<hv 2>%a[%a]@]" fpp_term a fpp_term k + | Fol.Tupdate(a,k,b) -> + Format.fprintf fmt "@[<hv 2>%a[%a@,<-%a]@]" + fpp_term a fpp_term k fpp_term b + | Fol.Tgetfield(f,r) -> + Format.fprintf fmt "@[<hv 2>%s(%a)@]" (get_field f) fpp_term r + | Fol.Tsetfield(f,r,v) -> + Format.fprintf fmt "@[<hv 2>%s(%a,%a)@]" (set_field f) fpp_term r fpp_term v + | Fol.Tapp (id, t::ts) -> + fprintf fmt "@[<hov 2>%s(@,%a" id fpp_term t ; + List.iter (fun t -> fprintf fmt ",@,%a" fpp_term t) ts ; + fprintf fmt ")@]" + | Fol.Tlet (x,v,t) -> + fprintf fmt "(@[<hov 0>let %a=%a in@ %a@])" + pp_var x fpp_term v fpp_term t + +let rec collect_or ps = function + | Fol.Por(a,b) -> collect_or (collect_or ps b) a + | p -> p :: ps + +let rec collect_and ps = function + | Fol.Pand(a,b) -> collect_and (collect_and ps b) a + | p -> p :: ps + +let rec collect_imply ps = function + | Fol.Pimplies(a,b) -> collect_and (collect_imply ps b) a + | p -> p :: ps + +let rec collect_iff ps = function + | Fol.Piff(a,b) -> collect_iff (collect_iff ps b) a + | p -> p :: ps + + +type 'a pp = Format.formatter -> 'a -> unit +type pp_env = { + pp_type : Formula.tau pp ; + pp_term : Fol.term pp ; + pp_pred : Fol.pred pp ; +} + +open Fol_cc + +let rec export_tau tau_of_ctype_logic fmt = function + | Formula.Integer -> pp_print_string fmt "int" + | Formula.Real -> pp_print_string fmt "real" + | Formula.Boolean -> pp_print_string fmt "bool" + | Formula.Pointer t -> (export_tau tau_of_ctype_logic) fmt t + | Formula.Record c -> Format.fprintf fmt "%s" c.Cil_types.cname + | Formula.Array arr -> + let t = tau_of_ctype_logic arr.Ctypes.arr_element in + Format.fprintf fmt "%a farray" (export_tau tau_of_ctype_logic) t + | Formula.Set te -> + Format.fprintf fmt "%a set" (export_tau tau_of_ctype_logic) te + | Formula.ADT("farray",[t]) -> + Format.fprintf fmt "%a farray" (export_tau tau_of_ctype_logic) t + | Formula.ADT(s,[]) -> pp_print_string fmt s + | Formula.ADT(s,[t]) -> Format.fprintf fmt "%a %s" (export_tau tau_of_ctype_logic) t s + | Formula.ADT(s,t::ts) -> + Format.fprintf fmt "@[(%a"(export_tau tau_of_ctype_logic) t ; + List.iter (fun t -> Format.fprintf fmt ",@,%a" ( export_tau tau_of_ctype_logic) t) ts ; + Format.fprintf fmt ") %s@]" s + + +let pp_args tau_of_ctype_logic fmt = function + | [] -> () + | [x] -> Format.fprintf fmt "(%a@,:@,%a)@,:%a@,=@," + pp_var x (export_tau tau_of_ctype_logic) (Fol.Var.var_type x) + (export_tau tau_of_ctype_logic) (Fol.Var.var_type x) + | x::m -> + Format.fprintf fmt "(%a@,:@,%a@," + pp_var x (export_tau tau_of_ctype_logic) (Fol.Var.var_type x); + List.iter (fun x -> Format.fprintf fmt ",@,%a@,:@,%a@," + pp_var x (export_tau tau_of_ctype_logic) (Fol.Var.var_type x) ) m; + Format.fprintf fmt ")@,:%a@,=@\n" (export_tau tau_of_ctype_logic) (Fol.Var.var_type x) + +let fpp_f_let tau_of_ctype_logic fmt fl = + Format.fprintf fmt "@[<hov 2>function %s@,%a%a@]" + fl.name (pp_args tau_of_ctype_logic) fl.param + fpp_term fl.body + +let fpp_lf_let tau_of_ctype_logic fmt = function + | [] -> () + | x::xs -> + let pp = fpp_f_let tau_of_ctype_logic in + pp fmt x ; + List.iter (fun x -> fprintf fmt "%a@\n" pp x ) xs + + +let rec epp_pred_vbox env fmt p = + match p with + | Fol.Pand _ -> pp_block fmt " " "and" env.pp_pred (collect_and [] p) + | Fol.Por _ -> pp_block fmt " " "or" env.pp_pred (collect_or [] p) + | Fol.Pimplies _ -> pp_block fmt " " "->" env.pp_pred (collect_imply [] p) + | Fol.Piff _ -> pp_block fmt " " "<->" env.pp_pred (collect_iff [] p) + | Fol.Pforall(x,p) -> + fprintf fmt "forall %a:%a.@\n" pp_var x env.pp_type (Fol.Var.var_type x) ; + epp_pred_vbox env fmt p + | Fol.Pexists(x,p) -> + fprintf fmt "exists %a:%a.@\n" pp_var x env.pp_type (Fol.Var.var_type x) ; + epp_pred_vbox env fmt p + |Fol.Pif(t,p,q) -> + fprintf fmt "@[<hov 0>if @[<hov 2>%a@]@ then@]@\n %a@\nelse@\n %a" + env.pp_term t env.pp_pred p env.pp_pred q + | (Fol.Ptrue | Fol.Pfalse | Fol.Papp _ | Fol.Pnot _ | Fol.Pnamed _) -> + env.pp_pred fmt p + | Fol.Plet(x,t,p) -> + fprintf fmt "let %a = @[%a@] in@\n" pp_var x env.pp_term t ; + epp_pred_vbox env fmt p + +(*TODO : ensures that label are different from keywords of the host language*) +let tag_named tag = "tag_"^tag + + +let rec epp_pred_atom env fmt p = + match p with + | Fol.Pand _ | Fol.Por _ | Fol.Pimplies _ | Fol.Piff _ | Fol.Pif _ + | Fol.Pforall _ | Fol.Pexists _ | Fol.Plet _ -> + fprintf fmt "@[<v 1>(%a)@]" (epp_pred_vbox env) p + | Fol.Pnot p -> + fprintf fmt "@[<hov 2>(not@ %a)@]" (epp_pred_atom env) p + | Fol.Pnamed(tag,p) -> + fprintf fmt "@[<hov 0>%s:@,%a@]" (tag_named tag) (epp_pred_atom env) p + | Fol.Ptrue -> pp_print_string fmt "true" + | Fol.Pfalse -> pp_print_string fmt "false" + | Fol.Papp(id,[]) -> pp_print_string fmt id + | Fol.Papp (("eq" | "eq_int" | "eq_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ =@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp (("neq" | "neq_int" |"neq_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ <>@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp (("lt_int"| "lt_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ <@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp (("le_int"|"le_real"), [t1; t2]) -> + fprintf fmt "@[<hov 1>(%a@ <=@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp(id,t::ts) -> + fprintf fmt "@[<hov 2>%s(@,%a" id env.pp_term t ; + List.iter (fun t -> fprintf fmt ",@ %a" env.pp_term t) ts ; + fprintf fmt ")@]" + +let fpp_pred predicate tau_of_ctype_logic fmt p = + match p with + | Fol.Ptrue -> fprintf fmt "true" + | Fol.Pfalse -> fprintf fmt "false" + | Fol.Papp (id, [])-> fprintf fmt "%s" id + | Fol.Papp ("eq", [t1; t2]) -> fprintf fmt "(%a =@ %a)" fpp_term t1 fpp_term t2 + | Fol.Papp ("neq", [t1; t2]) -> fprintf fmt "(%a <>@ %a)" fpp_term t1 fpp_term t2 + | Fol.Papp (id, l) -> fprintf fmt "@[%s(%a)@]" id (pp_list fpp_term) l + | Fol.Pimplies (a, b) -> fprintf fmt "(@[%a ->@ %a@])" predicate a predicate b + | Fol.Piff (a, b) -> fprintf fmt "(@[%a <->@ %a@])" predicate a predicate b + | Fol.Pand (a, b) -> fprintf fmt "(@[%a and@ %a@])" predicate a predicate b + | Fol.Por (a, b) -> fprintf fmt "(@[%a or@ %a@])" predicate a predicate b + | Fol.Pnot a -> fprintf fmt "(not %a)" predicate a + | Fol.Pif (a, b, c) -> + fprintf fmt "(@[if %a then@ %a else@ %a@])" + fpp_term a predicate b predicate c + | Fol.Pforall (v,p) -> + fprintf fmt "@[<hov 0>(forall %a:%a.@ %a@])" + pp_var v (export_tau tau_of_ctype_logic) (Fol.Var.var_type v) predicate p + | Fol.Pexists (v,p) -> + fprintf fmt "@[<hov 0>(exists %a:%a.@ %a@])" + pp_var v(export_tau tau_of_ctype_logic) (Fol.Var.var_type v) predicate p + | Fol.Plet (x,v,p) -> + fprintf fmt "@[<hov 0>(let %a=%a in@ %a@])" + pp_var x fpp_term v predicate p + | Fol.Pnamed (n, p) -> + fprintf fmt "@[%s: %a@]" (tag_named n) predicate p + +let export_get_set_field tau_of_ctype_logic fmt f = + let cn = f.Cil_types.fcomp.Cil_types.cname in + let fn = tau_of_ctype_logic f.Cil_types.ftype in + let get_f = get_field f in + let set_f = set_field f in + Format.fprintf fmt "logic %s: %s -> %a @\n" + get_f cn (export_tau tau_of_ctype_logic) fn; + Format.fprintf fmt "logic %s: %s , %a -> %s @\n" set_f cn + (export_tau tau_of_ctype_logic) fn cn + + +let export_get_set_other tau_of_ctype_logic fmt f get_f g = + let set_g = set_field g in + Format.pp_print_newline fmt () ; + Format.fprintf fmt + "(* Definition of the commutativity of the get field %s over the set field %s*)@\n" + f.Cil_types.fname g.Cil_types.fname; + Format.pp_print_newline fmt () ; + Format.fprintf fmt "axiom GetSetOther_%s_%s@,:@\n" f.Cil_types.fname g.Cil_types.fname; + Format.fprintf fmt "forall r:%s.@,forall v:%a.@\n" + f.Cil_types.fcomp.Cil_types.cname + (export_tau tau_of_ctype_logic) (tau_of_ctype_logic g.Cil_types.ftype); + Format.fprintf fmt "%s(%s(r,v))@,=@, %s(r)@\n" get_f set_g get_f; + Format.pp_print_newline fmt () + +let export_generated_axiomatics tau_of_ctype_logic fmt f = + let get_f = get_field f in + let set_f = set_field f in + Format.fprintf fmt + "(* Definition of the good properties of the field %s*)@\n" f.Cil_types.fname; + Format.pp_print_newline fmt () ; + Format.fprintf fmt "axiom GetSetSame_%s@,:@\n" f.Cil_types.fname; + Format.fprintf fmt "forall r:%s.@,forall v:%a.@\n" + f.Cil_types.fcomp.Cil_types.cname + (export_tau tau_of_ctype_logic) (tau_of_ctype_logic f.Cil_types.ftype); + Format.fprintf fmt "%s(%s(r,v))@,=@, v@\n" get_f set_f ; + Format.pp_print_newline fmt () ; + if f.Cil_types.fcomp.Cil_types.cstruct then + (List.iter (fun g -> + if Cil_datatype.Fieldinfo.equal f g then () else + export_get_set_other tau_of_ctype_logic fmt f get_f g ) + f.Cil_types.fcomp.Cil_types.cfields ;) + else (); + Format.pp_print_newline fmt () ; + Format.pp_print_newline fmt () + +let pp_param tau_of_ctype_logic fmt x = + Format.fprintf fmt "%a:%a" pp_var x (export_tau tau_of_ctype_logic) (Fol.Var.var_type x) + +let fpp_item term predicate tau_of_ctype_logic fmt x = + function + | Formula.Cons k -> + fprintf fmt "function %s (): int = %d@\n" x k + | Formula.Function ([], t) -> + fprintf fmt "logic %s: %a@\n" x (export_tau tau_of_ctype_logic) t + | Formula.Function (tl, t) -> + fprintf fmt "logic %s: @[<hov 0>%a -> %a@]@\n" x + (pp_list (export_tau tau_of_ctype_logic) ) tl (export_tau tau_of_ctype_logic) t + | Formula.Predicate [] -> + fprintf fmt "logic %s: prop@\n" x + | Formula.Predicate tl -> + fprintf fmt "logic %s: @[<hov 0>%a -> prop@]@\n" x + (pp_list (export_tau tau_of_ctype_logic)) tl + | Formula.FunctionDef (xs,tr,exp) -> + Format.fprintf fmt "@[<hv 2>function %s (%a) : %a =@ @[<hov 0>%a@]@]@\n" + x (pp_list (pp_param tau_of_ctype_logic)) xs (export_tau tau_of_ctype_logic) tr term exp + | Formula.PredicateDef (xs,prop) -> + Format.fprintf fmt "@[<hv 2>predicate %s (%a) =@ @[<hov 0>%a@]@]@\n" + x (pp_list (pp_param tau_of_ctype_logic)) xs predicate prop + | Formula.Axiom p -> + begin + match Fol_norm.compile p with + | Fol_norm.Pred p' -> fprintf fmt "@[<hv 2>axiom %s:@ %a@]@\n" x predicate p' + | Fol_norm.Conv (defs,p') -> + fpp_lf_let tau_of_ctype_logic fmt defs ; + fprintf fmt "@[<hv 2>axiom %s:@ %a@]@\n" x predicate p' + end + | Formula.Type 0 -> + fprintf fmt "type %s@\n" x + | Formula.Type 1 -> + fprintf fmt "type 'a %s@\n" x + | Formula.Type n -> + fprintf fmt "@[<hov 2>type ('a" ; + for k=2 to n do + fprintf fmt ",%c" (char_of_int (int_of_char 'a'+k-1)) + done ; + Format.fprintf fmt ") %s@]@\n" x + | Formula.Trecord c -> + begin + Format.fprintf fmt "type %s@\n" c.Cil_types.cname ; + let l = c.Cil_types.cfields in + List.iter (fun f -> export_get_set_field tau_of_ctype_logic fmt f) l ; + List.iter (fun f -> export_generated_axiomatics tau_of_ctype_logic fmt f) l + end + + +let fpp_header fmt d = + begin + d.Formula.d_title fmt ; + Format.pp_print_newline fmt () ; + ( match d.Formula.d_source with + | Some { Lexing.pos_fname=f ; pos_lnum=k } -> + Format.fprintf fmt "%s:%d: " f k + | None -> () ) ; + d.Formula.d_descr fmt ; + end + +let fpp_decl term predicate tau_of_ctype_logic fmt d = + begin + fpp_header fmt d ; + Format.pp_print_newline fmt () ; + fpp_item term predicate tau_of_ctype_logic fmt d.Formula.d_name d.Formula.d_item ; + Format.pp_print_newline fmt () ; + end + +let fpp_goal predicate fmt x p = + fprintf fmt "@[<hv 2>goal %s:@ %a@]@." x predicate p + +let export_term fmt t = fpp_term fmt t + +let rec pp_pred_atom tau_of_ctype_logic fmt p = + epp_pred_atom { + pp_type = export_tau tau_of_ctype_logic; + pp_term = export_term ; + pp_pred = pp_pred_atom tau_of_ctype_logic ; + } fmt p + +let export_pred tau_of_ctype_logic fmt p = + epp_pred_vbox { + pp_type = export_tau tau_of_ctype_logic; + pp_term = export_term ; + pp_pred = pp_pred_atom tau_of_ctype_logic; + } fmt p + +let export_item tau_of_ctype_logic fmt name item = +fpp_item (export_pred tau_of_ctype_logic) fmt name item + +let export_decl tau_of_ctype_logic fmt d = + Pretty_utils.pp_trail fpp_header fmt d ; + Format.pp_print_newline fmt () ; + fpp_item export_term (export_pred tau_of_ctype_logic) tau_of_ctype_logic fmt d.Formula.d_name d.Formula.d_item + +let export_goal tau_of_ctype_logic fmt x g= + match Fol_norm.compile g with + | Fol_norm.Pred p' -> fpp_goal (export_pred tau_of_ctype_logic) fmt x p' + | Fol_norm.Conv (defs,p') -> + fpp_lf_let tau_of_ctype_logic fmt defs ; + fpp_goal (export_pred tau_of_ctype_logic) fmt x p' + + +module Make(L: sig val tau_of_ctype_logic : Cil_types.typ -> Formula.tau end) = +struct + type pred = Fol.pred + type decl = Fol.decl + + let export_section fmt title = + begin + Format.fprintf fmt "(*----------------------------------------*)@\n" ; + Format.fprintf fmt "(*--- %-32s ---*)@\n" title ; + Format.fprintf fmt "(*----------------------------------------*)@\n" ; + end + + let export_tau fmt t = + export_tau L.tau_of_ctype_logic fmt t + + let export_decl fmt d = + export_decl L.tau_of_ctype_logic fmt d + + let export_goal fmt g p = + export_goal L.tau_of_ctype_logic fmt g p + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_eval.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_eval.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_eval.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_eval.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,80 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Fol + +(* III. let expansion *) + +let new_fname f x sigma cpt = + incr cpt; + let sx = Var.basename x in + let nx = Var.ident_named_var sx !cpt (Var.var_type x) in + nx,(Vmap.add x (f nx) sigma) + +let rec expt sigma = function + | Tlet(x,t1,t2) -> + let t1 = expt sigma t1 in + expt (Vmap.add x t1 sigma) t2 + | Tapp(f,tl) -> + e_app f (List.map (expt sigma) tl) + | Tif (c,ta,tb) -> + e_if (expt sigma c)(expt sigma ta)(expt sigma tb) + | Tconst _ as c -> c + | Taccess(t,i) -> e_access(expt sigma t) (expt sigma i) + | Tupdate(t,i,v) -> e_update(expt sigma t) (expt sigma i) (expt sigma v) + | Tgetfield(f,r) -> e_getfield f (expt sigma r) + | Tsetfield(f,r,v) -> e_setfield f (expt sigma r) (expt sigma v) + | Tvar x as t -> + begin + try Vmap.find x sigma + with Not_found -> t + end + + let rec expp sigma cpt = function + | Pimplies (p1,p2) -> + p_implies (expp sigma cpt p1)(expp sigma cpt p2) + + | Pif (t,p1,p2) -> + p_if (expt sigma t) + (expp sigma cpt p1)(expp sigma cpt p2) + | Pand (p1,p2) -> p_and(expp sigma cpt p1)(expp sigma cpt p2) + | Por (p1,p2) -> p_or(expp sigma cpt p1)(expp sigma cpt p2) + | Piff (p1,p2) -> p_iff (expp sigma cpt p1)(expp sigma cpt p2) + | Pnot p -> p_not (expp sigma cpt p) + | Papp (f, tl) -> p_app f (List.map (expt sigma) tl) + | Pexists(x,p) -> + let nx,sigma = new_fname e_var x sigma cpt in + p_exists nx (expp sigma cpt p) + | Pforall (x,p) -> + let nx,sigma = new_fname e_var x sigma cpt in + p_forall nx (expp sigma cpt p) + | Plet (x,t,p) -> + let t1 = expt sigma t in + expp (Vmap.add x t1 sigma) cpt p + | Pnamed(s,p) -> Pnamed(s,expp sigma cpt p) + | p -> p + + let plet_expansion p = + expp Vmap.empty (ref 0) p + + let elet_expansion t = + expt Vmap.empty t diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_formula.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_formula.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_formula.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_formula.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,1104 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Fol_decl +open Formula + +(* -------------------------------------------------------------------------- *) +(* --- OPERATORS --- *) +(* -------------------------------------------------------------------------- *) + +let i_pred = function + | Ceq -> eq_int + | Cneq -> ne_int + | Clt -> lt_int + | Cleq -> le_int + +let i_bool = function + | Ceq -> eq_int_bool + | Cneq -> ne_int_bool + | Clt -> lt_int_bool + | Cleq -> le_int_bool + +let i_op = function + | Iadd -> add_int + | Isub -> sub_int + | Imul -> mul_int + | Idiv -> div_int + | Imod -> mod_int + +let r_pred = function + | Ceq -> eq_real + | Cneq -> ne_real + | Clt -> lt_real + | Cleq -> le_real + +let r_bool = function + | Ceq -> eq_real_bool + | Cneq -> ne_real_bool + | Clt -> lt_real_bool + | Cleq -> le_real_bool + +let r_op = function + | Radd -> add_real + | Rsub -> sub_real + | Rmul -> mul_real + | Rdiv -> fract_real + + +type 'a term = Fol.term +type pred = Fol.pred +type decl = Fol.decl + +type abstract = m_abstract term +type integer = m_integer term +type real = m_real term +type boolean = m_boolean term +type record = m_record term +type urecord = m_array term +type array = m_array term +type set = m_set term +type name = m_integer term + +type var = Fol.Var.t + +let e_true = Fol.e_true +let e_false = Fol.e_false + +let e_int k = Fol.e_int k +let e_int64 k = Fol.e_int64 k +let e_float k = Fol.e_float k +let e_icst z = Fol.e_cnst (Fol.c_int_of_str z) +let e_rcst z = Fol.e_cnst (Fol.c_float_of_str z) + +let wrap t = t +let unwrap t = t + +let e_call f ts = Fol.e_app f ts +let p_call f xs = Fol.p_app f xs + +let e_access = Fol.e_access +let e_update = Fol.e_update +let e_getfield = Fol.e_getfield +let e_setfield = Fol.e_setfield + +let unop f a = unwrap (e_call f [wrap a]) +let binop f a b = unwrap (e_call f [wrap a;wrap b]) +let predop f a b = p_call f [wrap a;wrap b] + +let e_ineg = unop neg_int +let e_rneg = unop neg_real + +let e_icmp op = binop (i_bool op) +let p_icmp op = predop (i_pred op) + +let e_rcmp op = binop (r_bool op) +let p_rcmp op = predop (r_pred op) + +let e_iop op = binop (i_op op) +let e_rop op = binop (r_op op) + +let real_of_integer = unop real_of_integer +let integer_of_real = unop integer_of_real + +let a_true = wrap (e_int 1) +let a_false = wrap (e_int 0) + +let e_bool (c : boolean) : integer = + unwrap (e_call "ite" [wrap c;a_true;a_false]) + +let e_cond (c : boolean) (a : 'a term) (b : 'a term) : 'a term = + unwrap (e_call "ite" [wrap c;wrap a;wrap b]) + +let e_not = unop bool_not +let e_and = binop bool_and +let e_or = binop bool_or + +let e_bnot = unop "bnot" +let e_band = binop "band" +let e_bor = binop "bor" +let e_bxor = binop "bxor" +let e_lshift = binop "lshift" +let e_rshift = binop "rshift" + +let i_zero = e_int 0 +let i_one = e_int 1 +let i_sub = e_iop Isub +let i_add = e_iop Iadd +let i_mult = e_iop Imul + +let r_zero = e_float 0.0 + +(* --------------------------------------------------------------------- *) +(* --- Declaration --- *) +(* --------------------------------------------------------------------- *) + +open Cil_types +open Ctypes +open Format + +let rec is_incl_comp c1 c2 = + match object_of c2 with + | C_comp c -> Cil_datatype.Compinfo.equal c1 c || + List.exists (fun t -> is_incl_comp c1 t.ftype) c.cfields + | C_array arr -> is_incl_comp c1 arr.arr_element + | _ -> false + +(* Ensures that structures comes in the correct order *) + +let comp_compare c1 c2 = + if (List.exists (fun t -> is_incl_comp c1 t.ftype) c2.cfields) then -1 + else + if (List.exists (fun t -> is_incl_comp c2 t.ftype) c1.cfields) then 1 + else Cil_datatype.Compinfo.compare c1 c2 + +let part_of_item = function + | Formula.Type _ -> 1 + | Formula.Cons _ -> 2 + | Formula.FunctionDef _ + | Formula.PredicateDef _ + | Formula.Function _ + | Formula.Predicate _ -> 3 + | Formula.Axiom _ -> 4 + | Formula.Trecord _ -> 5 + +let compare_item d1 d2 = + let p = part_of_item d1.Formula.d_item - part_of_item d2.Formula.d_item in + if p = 0 then + match d1.Formula.d_item , d2.Formula.d_item with + | Formula.Trecord c1 , Formula.Trecord c2 -> comp_compare c1 c2 + | Formula.Cons i , Formula.Cons j -> i - j + | _ ,_ -> String.compare d1.Formula.d_name d2.Formula.d_name + else p + + +module Dset = Set.Make + (struct + type t = decl + let compare = compare_item + end) + +let gindex : (string,decl) Hashtbl.t = Hashtbl.create 731 +let gfresh = Hashtbl.create 131 + +let fresh_name prefix basename = + let x = identifier basename in + let m = if x="" then prefix else Printf.sprintf "%s_%s" prefix x in + try + let p = Hashtbl.find gfresh m in + incr p ; Printf.sprintf "%s_%d" m !p + with Not_found -> + Hashtbl.add gfresh m (ref 0) ; m + +(* order not really import, but they are in order *) + +let s_index = function + | Formula.S_Type -> 0 + | Formula.S_Cons -> 1 + | Formula.S_Logic_Sig -> 2 + | Formula.S_Logic_Def -> 3 + | Formula.S_Logic_Prop -> 4 + | Formula.S_Model_Sig -> 5 + | Formula.S_Model_Def -> 6 + | Formula.S_Model_Prop -> 7 + | Formula.S_User_Sig -> 8 + | Formula.S_User_Prop -> 9 + +let gsection = Array.create 10 Dset.empty + +(* order is important, and they are in order *) + +let gtoc = [| + Formula.S_Type , "Type Definitions" ; + Formula.S_Cons , "Type Constructors" ; + Formula.S_Logic_Sig , "Logic Signatures" ; + Formula.S_Logic_Def , "Logic Definitions" ; + Formula.S_Logic_Prop , "Logic Properties" ; + Formula.S_Model_Sig , "Model Signatures" ; + Formula.S_Model_Def , "Model Definitions" ; + Formula.S_Model_Prop , "Model Properties" ; + Formula.S_User_Sig , "User-defined Signatures" ; + Formula.S_User_Prop , "User-defined Properties" ; +|] + +let gclear = ref [] + +let clear () = + begin + Hashtbl.clear gfresh ; + Hashtbl.clear gindex ; + Array.fill gsection 0 (Array.length gsection) Dset.empty ; + List.iter (fun f -> f ()) !gclear ; + end +let on_clear f = gclear := !gclear @ [f] + +let locked = ref false + (* ensures that no declaration has been added during the iteration *) + +let has_declaration = Hashtbl.mem gindex + +let compile_let_item = function + | (Formula.Cons _ | Formula.Type _ + | Formula.Function _ | Formula.Predicate _ | Formula.Trecord _) as item -> item + | Formula.FunctionDef(xs,t,e) -> Formula.FunctionDef(xs,t,Fol_eval.elet_expansion e) + | Formula.PredicateDef(xs,p) -> + let xs,p = Fol_let.compile_def xs p in + Formula.PredicateDef(xs,p) + | Formula.Axiom p -> Formula.Axiom (Fol_let.compile p) + +let compile_let_decl d = + { + Formula.d_section = d.Formula.d_section ; + Formula.d_name = d.Formula.d_name ; + Formula.d_title = d.Formula.d_title ; + Formula.d_descr = d.Formula.d_descr ; + Formula.d_source = d.Formula.d_source ; + Formula.d_item = compile_let_item d.Formula.d_item ; + } + +let rec add_declaration d = + try + Wp_parameters.debug ~dkey:"logic" "Adding declaration %s (%t)@." + d.Formula.d_name d.Formula.d_title ; + if !locked then Wp_parameters.fatal + "Locked datalib (when declaring %t)" d.Formula.d_title ; + let old = Hashtbl.find gindex d.Formula.d_name in + Wp_parameters.fatal + "Duplicate definition for name '%s':@ Old: %t@ New: %t" + d.Formula.d_name old.Formula.d_title d.Formula.d_title + with Not_found -> + begin + Hashtbl.add gindex d.Formula.d_name (compile_let_decl d) ; + let s = s_index d.Formula.d_section in + gsection.(s) <- Dset.add d gsection.(s) + end + +(* -------------------------------------------------------------------------- *) +(* --- Dependencies for macros --- *) +(* -------------------------------------------------------------------------- *) + +open Fol + +module Mset = Datatype.String.Set + +let exported_macros = ref Mset.empty + +let is_macro d = match d.d_item with + | FunctionDef _ | PredicateDef _ -> true + | _ -> false + +let is_macro_section = function + | S_Type | S_Cons + | S_Logic_Sig | S_Logic_Prop + | S_Model_Sig | S_Model_Prop + | S_User_Sig | S_User_Prop -> false + | S_Logic_Def | S_Model_Def -> true + +let rec do_export f d = + export_depends_for_item f d.d_item ; + if not (Mset.mem d.d_name !exported_macros) then + ( f d ; exported_macros := Mset.add d.d_name !exported_macros ) + +and export_depends_for_item f = function + | Type _ | Cons _ | Function _ | Predicate _ | Trecord _ | Axiom _ -> () + | FunctionDef(_,_,exp) -> export_depends_for_term f exp + | PredicateDef(_,prop) -> export_depends_for_pred f prop + +and export_depends_for_name f x = + try + let d = Hashtbl.find gindex x in + if is_macro d then do_export f d + with Not_found -> () + +and export_depends_for_term f = function + | Tconst _ | Tvar _ -> () + | Tapp(x,ts) -> + export_depends_for_name f x ; + List.iter (export_depends_for_term f) ts + | Tgetfield(_,t) -> + export_depends_for_term f t + | Tsetfield(_,t,v) | Taccess(t,v) | Tlet(_,t,v) -> + export_depends_for_term f t ; + export_depends_for_term f v + | Tupdate(t,v,w) | Tif(t,v,w) -> + export_depends_for_term f t ; + export_depends_for_term f v ; + export_depends_for_term f w + +and export_depends_for_pred f = function + | Papp(x,ts) -> + export_depends_for_name f x ; + List.iter (export_depends_for_term f) ts + | Ptrue | Pfalse -> () + | Pimplies(p,q) | Pand(p,q) | Por(p,q) | Piff(p,q) -> + export_depends_for_pred f p ; + export_depends_for_pred f q + | Pif(c,p,q) -> + export_depends_for_term f c ; + export_depends_for_pred f p ; + export_depends_for_pred f q + | Pnot p | Pnamed(_,p) | Pexists(_,p) | Pforall(_,p) -> + export_depends_for_pred f p + | Plet(_,t,p) -> + export_depends_for_term f t ; + export_depends_for_pred f p + +let iter_all section f = + try + locked := true ; + exported_macros := Mset.empty ; + Array.iter + (fun (s,t) -> + let k = s_index s in + if not (Dset.is_empty gsection.(k)) then + begin + let job = if is_macro_section s then do_export f else f in + section t ; Dset.iter job gsection.(k) ; + end + ) gtoc ; + locked := false ; + exported_macros := Mset.empty ; + with e -> + locked := false ; + exported_macros := Mset.empty ; + raise e + +(* -------------------------------------------------------------------------- *) +(* --- Declaration Functors --- *) +(* -------------------------------------------------------------------------- *) + +module type Identifiable = +sig + type t + module H : Hashtbl.S + val index : t -> H.key + val prefix : string + val basename : t -> string + val location : t -> Lexing.position option + val pp_title : Format.formatter -> t -> unit + val pp_descr : Format.formatter -> t -> unit +end + +module type Registry = +sig + type t + val define : t -> unit + val get_definition : t -> Fol.decl + val on_definition : (t -> Fol.decl -> unit) -> unit +end + +module type Declarator = +sig + include Identifiable + val clear : unit -> unit + val section : Formula.section + val declare : t -> string -> (Fol.Var.t,Fol.term,Fol.pred) Formula.item +end + +module DRegister + (D : Declarator) : + (Registry with type t = D.t) = +struct + let () = register_prefix D.prefix + + type t = D.t + let index : Fol.decl D.H.t = D.H.create 131 + let demons : (t -> Fol.decl -> unit) list ref = ref [] + + let () = on_clear (fun () -> D.clear () ; D.H.clear index) + + let get_definition x = + let k = D.index x in + try D.H.find index k + with Not_found -> + let name = fresh_name D.prefix (D.basename x) in + let item = D.declare x name in + let d = { + Formula.d_name = name ; + Formula.d_section = D.section ; + Formula.d_source = D.location x ; + Formula.d_item = item ; + Formula.d_title = (fun fmt -> D.pp_title fmt x) ; + Formula.d_descr = (fun fmt -> D.pp_descr fmt x) ; + } in + add_declaration d ; + D.H.add index k d ; + List.iter (fun f -> f x d) !demons ; + d + + let define x = ignore (get_definition x) + let on_definition f = demons := !demons @ [f] +end + + + +(* -------------------------------------------------------------------------- *) +(* --- Built-in Identifiables --- *) +(* -------------------------------------------------------------------------- *) +let rec pp_dim fmt = function + | TArray (typ_elt,lo,_,_) -> + (match lo with + | Some lo -> + Format.fprintf fmt "[%a]" !Ast_printer.d_exp lo + | None -> + Format.fprintf fmt "[]"); pp_dim fmt typ_elt + | _ -> () + + +let rec pp_ctype dim fmt = function + | TInt(ikind,_) -> Format.fprintf fmt "%a" Cil.d_ikind ikind + | TFloat(fkind,_) -> Format.fprintf fmt "%a" Cil.d_fkind fkind + | TPtr(typ,_) -> Format.fprintf fmt "%a*" (pp_ctype dim) typ + | TFun _ as t -> Format.fprintf fmt "%a*" (pp_ctype dim) t + | TEnum (e,_) -> Format.fprintf fmt "enum %s " e.ename + | TComp (comp,_,_) -> + Format.fprintf fmt + "%s %s" + (if comp.cstruct then "struct" else "union") + comp.cname + + | TArray (typ_elt,_,_,_) as t -> + pp_ctype false fmt typ_elt ; + if dim then pp_dim fmt t; + + | TBuiltin_va_list _ -> pp_print_string fmt "builtin type" + | TVoid _ -> pp_print_string fmt "void" + | TNamed (t,_) -> Format.fprintf fmt "%s" t.tname + +module Varinfo : Identifiable with type t = varinfo = +struct + type t = varinfo + let prefix = "X" + let index x = x + let basename x = x.vname + let location x = Some(fst x.vdecl) + module H = Cil_datatype.Varinfo.Hashtbl + let pp_title fmt x = + if x.vglob + then Format.fprintf fmt "Global '%a'" !Ast_printer.d_var x + else Format.fprintf fmt "Local '%a'" !Ast_printer.d_var x + let pp_descr fmt x = + Format.fprintf fmt "%a %a ;" + (pp_ctype true) x.vtype !Ast_printer.d_var x +end + +module Varaddr : Identifiable with type t = varinfo = +struct + include Varinfo + let prefix = "A" + let pp_title fmt x = Format.fprintf fmt "Address of '%a'" pp_title x +end + +module Fieldinfo : Identifiable with type t = fieldinfo = +struct + type t = fieldinfo + let prefix = "F" + let index f = f + let basename f = f.fname + let location f = Some(fst f.floc) + module H = Cil_datatype.Fieldinfo.Hashtbl + let pp_title fmt f = Format.fprintf fmt "Field '%s'" f.fname + let pp_descr fmt f = + Format.fprintf fmt "@[<hov 0>@[<hov 2>%s %s {@ ... ;@ %a %s ;@ ...@]@ }@]" + (if f.fcomp.cstruct then "struct" else "union") + f.fcomp.cname + !Ast_printer.d_type f.ftype f.fname +end + +module Compinfo : Identifiable with type t = compinfo = +struct + type t = compinfo + let prefix = "C" + let index c = c + let basename c = c.cname + let location c = + match c.cfields with + | f :: _ -> + let s = fst f.floc in + if s.Lexing.pos_fname = "" then None else Some s + | [] -> None + module H = Cil_datatype.Compinfo.Hashtbl + let pp_title fmt c = + Format.fprintf fmt "%s '%s'" + (if c.cstruct then "Struct" else "Union") c.cname + let pp_descr fmt c = + Format.fprintf fmt "typedef %s %s { ... }" + (if c.cstruct then "struct" else "union") c.cname +end + +module Arrayinfo : Identifiable with type t = arrayinfo = +struct + type t = arrayinfo + let prefix = "A" + module H = Hashtbl.Make(AinfoComparable) + let index a = a + let location _ = None + let basename a = Ctypes.basename (C_array a) + let pp_title fmt a = Ctypes.pretty fmt (C_array a) + let pp_descr fmt _ = Format.fprintf fmt "Logic array" +end + +module LTypeinfo : Identifiable with type t = Cil_types.logic_type = +struct + type t = Cil_types.logic_type + let prefix = "AT" + let index c = c + let basename ty = + let rec typ_basename ty = + match object_of ty with + | C_int i -> Pretty_utils.sfprintf "%a" Ctypes.pp_int i + | C_float f -> Pretty_utils.sfprintf "%a" Ctypes.pp_float f + | C_pointer _ -> "pointer" + | C_comp c -> (if c.cstruct then "struct_" else "union_")^ + c.cname + | C_array arr -> typ_basename arr.Ctypes.arr_element^"_array" + in + match ty with + | Ctype c -> "is_"^typ_basename c + | Linteger | Lreal -> "" + | Lvar x -> x + | Ltype (lt,_) -> lt.lt_name + | Larrow _ ->"" + + let location _ = None + module H = Cil_datatype.Logic_type.Hashtbl + let pp_title fmt _ = + Format.fprintf fmt "Acsl type" + let pp_descr fmt _ = + Format.fprintf fmt "Declaration" +end + +module Logicvar : Identifiable with type t = logic_var = +struct + type t = logic_var + let prefix = "D" + let index x = x + let basename x = x.lv_name + let location _ = None + module H = Cil_datatype.Logic_var.Hashtbl + let pp_title fmt x = Format.fprintf fmt "Logic variable '%s'" x.lv_name + let pp_descr fmt _x = Format.fprintf fmt "Declaration" +end + + +module HC_object = +struct + type t = Ctypes.c_object + let equal = Ctypes.equal + let hash = Ctypes.hash +end + +module Cobject : Identifiable with type t = Ctypes.c_object = +struct + type t = Ctypes.c_object + let prefix = "Ct" + let index t = t + let basename x = Ctypes.basename x + let location _ = None + module H = Hashtbl.Make(HC_object) + let pp_title fmt x = Format.fprintf fmt "C type '%a'" Ctypes.pp_object x + let pp_descr fmt _ = Format.fprintf fmt "Declaration" +end + +module HC_ArrayDim = +struct + type t = Ctypes.c_object * int (* object with n-dimensions (number of []) *) + let equal (ta,n) (tb,m) = (n=m) && Ctypes.equal ta tb + let hash (ta,n) = 31*n + 73*Ctypes.hash ta +end + +module ArrayDim : Identifiable with type t = Ctypes.c_object * int = +struct + type t = Ctypes.c_object * int + let prefix = "Ca" + let index t = t + let basename (te,n) = + if n > 1 then Printf.sprintf "%s_d%d" (Ctypes.basename te) n + else Ctypes.basename te + let location _ = None + module H = Hashtbl.Make(HC_ArrayDim) + let pp_title fmt (te,n) = + Format.fprintf fmt "Array %a" Ctypes.pp_object te ; + for i = 1 to n do Format.fprintf fmt "[]" done + let pp_descr fmt _ = Format.fprintf fmt "Declaration" +end + +(* ----------------------------------------------------------------------- *) +(* --- User Type Registry --- *) +(* ----------------------------------------------------------------------- *) + +module LTinfo = +struct + type t = logic_type_info + let compare t1 t2 = String.compare t1.lt_name t2.lt_name + let hash v = Hashtbl.hash v.lt_name + let equal t1 t2 = t1.lt_name = t2.lt_name +end + +module LTinfoId : Identifiable with type t = logic_type_info = +struct + type t = logic_type_info + let prefix = "T" + let index t = t + let basename c = c.lt_name + let location _c = None + module H = Hashtbl.Make(LTinfo) + let pp_title fmt x = + Format.fprintf fmt "Logic type '%s'" x.lt_name + let pp_descr fmt _x = + Format.fprintf fmt "Declaration" +end + +module ADTDecl = DRegister + (struct + include LTinfoId + let declare t _ = + Formula.Type (List.length t.lt_params) + let section = Formula.S_Type + let clear () = () + end) + +let adt_decl lt = (ADTDecl.get_definition lt).Formula.d_name +let () = Fol_decl.Tau.name_of_adt := adt_decl + +(* --------------------------------------------------------------------- *) +(* --- HOL --- *) +(* --------------------------------------------------------------------- *) + +type pool = (string,int option) Hashtbl.t + +let pool () = Hashtbl.create 7 + +let fresh_var pool basename = + let new_contents = + try + let counter = Hashtbl.find pool basename in + match counter with + | None -> Some 0 + | Some i -> Some (succ i) + with Not_found -> None + in + Hashtbl.replace pool basename new_contents; + new_contents + +let p_fresh pool x kind = + let x = + if Fol_decl.has_reserved_prefix (x^"_") then + let new_name = "G_"^x in + if Fol_decl.has_reserved_prefix new_name then + Wp_parameters.fatal + "Reserved prefix for '%s' is clashing. Frama-C WP plugin cannot reserve the prefix 'G'" + new_name + else new_name + else x + in + let vx = + let tau, ltype = match kind with + | Formula.Model t -> t, None + | Formula.Acsl(t,ty) -> t, Some (ty) + in Fol.Var.mk x (fresh_var pool x) tau ltype + in vx + +let var v = Fol.e_var v + +let tau_of_var = Fol.Var.var_type +let name_of_var = Fol.Var.var_name +let basename_of_var = Fol.Var.basename +let kind_of_var = Fol.Var.kind_of_var + +let p_freshen pool v = p_fresh pool (Fol.Var.basename v) (Fol.Var.kind_of_var v) + +let p_true = Fol.Ptrue +let p_false = Fol.Pfalse + +let p_not a = Fol.p_not a +let p_bool a = Fol.p_eq e_true a + +let equal_terms e1 e2 = Fol.eq_terms e1 e2 + +let p_and a b = Fol.p_and a b +let p_or a b = Fol.p_or a b +let p_xor a b = Fol.p_xor a b +let p_eq a b = Fol.p_eq a b +let p_neq a b = Fol.p_neq a b +let p_iff a b = Fol.p_iff a b +let p_conj l = Fol.p_conj l +let p_disj l = Fol.p_disj l +let p_cond b pt pf = Fol.p_if (wrap b) pt pf +let p_named = Fol.p_named +let is_true = Fol.is_true +let is_false = Fol.is_false + +let eq_var = Fol.Var.equal + +let e_subst alpha x v t = + match v with + | Fol.Tvar y when (Fol.Var.equal x y) -> t (* v is equal to x *) + + | (Fol.Tconst _ | Fol.Tvar _ | Fol.Tapp(_,[])) + when Wp_parameters.Simpl.get () -> + Fol.term_replace alpha x v t + + | _ -> Fol.e_let x v t + +let p_forall xs p = + List.fold_right Fol.p_forall xs p + +let p_exists xs p = + List.fold_right Fol.p_exists xs p + +let p_subst alpha x v p = + match v with + | Fol.Tvar y when (Fol.Var.equal x y) -> p (* v is equal to x *) + + | (Fol.Tconst _ | Fol.Tvar _ | Fol.Tapp(_,[])) + when Wp_parameters.Simpl.get () -> + Fol.pred_replace alpha x v p + + | _ -> Fol.p_let x v p + +let p_implies h p = Fol.p_implies h p + +let rec apply alpha x = match alpha with + | [] -> None + | (y,y')::s -> + if Fol.Var.equal x y then Some y' else apply s x + +let rec e_rename s t = + match t with + | Fol.Tconst _ -> t + | Fol.Tvar x -> + ( match apply s x with + | None -> t + | Some y -> Fol.e_var y ) + | Fol.Tapp(f,ts) -> Fol.e_app f (List.map (e_rename s) ts) + | Fol.Taccess(t,i) -> e_access (e_rename s t) (e_rename s i) + | Fol.Tupdate(t,i,v) -> e_update (e_rename s t) (e_rename s i) (e_rename s v) + | Fol.Tgetfield(f,r) -> e_getfield f (e_rename s r) + | Fol.Tsetfield(f,r,v) -> e_setfield f (e_rename s r) (e_rename s v) + | Fol.Tif(a,b,c) -> Fol.e_if (e_rename s a) (e_rename s b) (e_rename s c) + | Fol.Tlet(y,a,b) -> + let a' = e_rename s a in + let s' = (y,y)::s in (* defensive ! *) + Fol.e_let y a' (e_rename s' b) + +let term_has_var = Fol.e_has_var +let pred_has_var = Fol.p_has_var + +let term_calls = Fol.term_calls +let pred_calls = Fol.pred_calls + +let term_closed t = Fol.e_closed [] t +let pred_closed p = Fol.p_closed [] p + +type alpha = Fol.Var.t Fol.Vmap.t +let empty_alpha = Fol.Vmap.empty +let fold_alpha = Fol.Vmap.fold +let p_more_alpha_cv = Fol.pred_alpha_cv +let p_alpha_cv p = Fol.p_alpha_cv p + + +(* -------------------------------------------------------------------------- *) +(* --- Free Variables --- *) +(* -------------------------------------------------------------------------- *) + + +let rec free_term xs = function + | Tconst _ -> xs + | Tvar x -> Vset.add x xs + | Tapp(_,ts) -> List.fold_left free_term xs ts + | Tgetfield(_,t) -> free_term xs t + | Tsetfield(_,t,t') | Taccess(t,t') -> free_term (free_term xs t) t' + | Tupdate(t1,t2,t3) | Tif(t1,t2,t3) -> free_term (free_term (free_term xs t1) t2) t3 + | Tlet(x,a,b) -> + if Vset.mem x xs then + free_term (free_term xs b) a + else + free_term (Vset.remove x (free_term xs b)) a + +let rec free_pred xs = function + | Papp(_,ts) -> List.fold_left free_term xs ts + | Ptrue | Pfalse -> xs + | Pimplies(p,q) | Pand(p,q) | Por(p,q) | Piff(p,q) -> free_pred (free_pred xs p) q + | Pnot p | Pnamed(_,p) -> free_pred xs p + | Pif(a,p,q) -> free_pred (free_pred (free_term xs a) p) q + | Plet(x,t,p) -> + if Vset.mem x xs then + free_term (free_pred xs p) t + else + free_term (Vset.remove x (free_pred xs p)) t + | Pexists(x,p) | Pforall(x,p) -> + if Vset.mem x xs then + free_pred xs p + else + Vset.remove x (free_pred xs p) + +let freevars p = Vset.elements (free_pred Vset.empty p) + +(* -------------------------------------------------------------------------- *) +(* --- Pretty Print --- *) +(* -------------------------------------------------------------------------- *) + +let rec pp_term fmt t = Fol_pretty.fpretty_term pp_term fmt t + +let () = Fol.pp_term := pp_term + +(*Be careful, only for debug *) +let pp_tau = Fol_pretty.pp_tau + +let rec pp_pred_atom fmt p = + Fol_pretty.epp_pred_atom { + Fol_pretty.pp_type = Fol_pretty.pp_tau ; + Fol_pretty.pp_term = pp_term; + Fol_pretty.pp_pred = pp_pred_atom ; + } fmt p + +let pp_pred_vbox fmt p = + Fol_pretty.epp_pred_vbox { + Fol_pretty.pp_type = Fol_pretty.pp_tau ; + Fol_pretty.pp_term = pp_term ; + Fol_pretty.pp_pred = pp_pred_atom ; + } fmt p + +let rec pp_pred_debug fmt p = + Fol_pretty.fpp_pred pp_pred_debug pp_tau pp_term fmt p + +let pp_pred fmt p = + if Wp_parameters.debug_atleast 1 then + pp_pred_debug fmt p + else + pp_pred_vbox fmt p + +let pp_section = Fol_pretty.pp_section +let pp_term fmt t = pp_term fmt t +let pp_decl fmt d = Fol_pretty.fpp_decl pp_term pp_pred fmt d +let pp_goal fmt x g = Fol_pretty.fpp_goal pp_pred fmt x g + +let pp_var fmt x = pp_term fmt (Fol.e_var x) + +let pp_vkind fmt = function + | Formula.Model t -> pp_tau fmt t + | Formula.Acsl (_t,ty) -> !Ast_printer.d_logic_type fmt ty + +let huge_term = Fol.huge_term +let huge_pred = Fol.huge_pred + +(* -------------------------------------------------------------------------- *) +(* --- Creates the Data Library --- *) +(* -------------------------------------------------------------------------- *) + +type interval = { + inf : integer option ; + sup : integer option ; +} + +type 'a assigned = + | Aloc of Ctypes.c_object * 'a + | Arange of Ctypes.c_object * 'a * interval + +type havoc = + | Fresh of var + | Update of var * ((var * var) list -> abstract) + +let pp_interval fmt rg = + let pp_opt fmt = function + | None -> () + | Some d -> pp_term fmt d + in + Format.fprintf fmt "[%a..%a]" pp_opt rg.inf pp_opt rg.sup + +(* ------------------------------------------------------------------------ *) +(* --- Calling Logic Functions and Predicates --- *) +(* ------------------------------------------------------------------------ *) + +let p_app0 f = p_call f [] +let p_app1 f a = p_call f [wrap a] +let p_app2 f a b = p_call f [wrap a;wrap b] +let p_app3 f a b c = p_call f [wrap a;wrap b;wrap c] +let p_app4 f a b c d = p_call f [wrap a;wrap b;wrap c;wrap d] +let p_app5 f a b c d e = p_call f [wrap a; wrap b; wrap c; wrap d; wrap e] + +let e_app0 f = unwrap (e_call f []) +let e_app1 f a = unwrap (e_call f [wrap a]) +let e_app2 f a b = unwrap (e_call f [wrap a;wrap b]) +let e_app3 f a b c = unwrap (e_call f [wrap a;wrap b;wrap c]) +let e_app4 f a b c d = + unwrap (e_call f [wrap a;wrap b;wrap c;wrap d]) +let e_app5 f a b c d e = + unwrap (e_call f [wrap a;wrap b;wrap c;wrap d; wrap e]) + +(* -------------------------------------------------------------------------- *) +(* --- Dummy --- *) +(* -------------------------------------------------------------------------- *) + +let gdummy = ref 0 + +let () = on_clear (fun () -> gdummy :=0) +let dummy () = incr gdummy; p_app1 "dummy" (e_int !gdummy) + +(* ------------------------------------------------------------------------ *) +(* --- Logic Integer Cast --- *) +(* ------------------------------------------------------------------------ *) + +let modulo ti e = e_app1 (mk_imodulo ti) e +let guard ti e = p_app1 (mk_iguard ti) e +let i_convert tfrom tto e = + if Ctypes.sub_c_int tfrom tto then e else modulo tto e + +(* ------------------------------------------------------------------------ *) +(* --- Set Interface --- *) +(* ------------------------------------------------------------------------ *) + +let empty = e_app0 mk_empty +let singleton e = e_app1 mk_singleton e + +let union a b = e_app2 mk_union a b + +let unions l = + let rec unions_aux l s = + match l with + | [] -> s + | a::m -> unions_aux m (union a s) + in + match l with + | [] -> empty + | a::m -> unions_aux m a + +let inter a b = e_app2 mk_inter a b +let remove a b = e_app2 mk_remove a b +let add_set s1 s2 = e_app2 mk_radd s1 s2 + +let mult_set s1 s2 = e_app2 mk_rmult s1 s2 +let neg_set s1 = e_app1 mk_rneg s1 + +(* ------------------------------------------------------------------------ *) +(* --- Integer Range Inteface --- *) +(* ------------------------------------------------------------------------ *) + +let loc_range = e_app2 mk_range +let range_inf = e_app1 mk_range_inf +let range_sup = e_app1 mk_range_sup +let integers = e_app0 mk_integers + +let rec set_of_list = function + | [] -> empty + | a::m -> union (singleton a) (set_of_list m) + +let interval r = + match r.inf,r.sup with + | None,None -> integers + | Some i, None -> range_inf i + | None, Some j -> range_sup j + | Some i, Some j -> loc_range i j + +let seed = ref 0 + +let set_range_index t ri = + let rdm = e_int (incr seed ; !seed) in + e_app3 set_range_index t (interval ri) rdm + + +(* ------------------------------------------------------------------------ *) +(* --- Records, Unions and Arrays as First Class Values --- *) +(* ------------------------------------------------------------------------ *) + +module RecName = DRegister + (struct + include Compinfo + let declare tcomp _eqname = + Formula.Trecord tcomp + let prefix = " " + let section = S_Type + let clear () = () + let pp_title _fmt _x = () + end) + +let acc_field (s:record) (f:Cil_types.fieldinfo) = + RecName.define f.Cil_types.fcomp ; e_getfield f s + +let upd_field (s:record) f v : record = + RecName.define f.Cil_types.fcomp ; e_setfield f s v + + +let acc_index = e_access +let upd_index = e_update + +(* -------------------------------------------------------------------------- *) +(* --- Index Functor --- *) +(* -------------------------------------------------------------------------- *) + +let gindexref = ref 0 + +module type Indexed = +sig + include Registry + val get_ind : t -> integer + val has_ind : t -> pred -> bool +end + +module Dindex + (I : Identifiable) : + (Indexed with type t = I.t) = +struct + let hindex = I.H.create 131 + include DRegister + (struct + include I + let clear () = I.H.clear hindex + let section = S_Cons + let declare _ _ = + (* MUST BE INCREMENTED BEFORE: 0 is reserved for models *) + incr gindexref ; + Formula.Cons (!gindexref) + end) + let get_ind x = + let k = I.index x in + try I.H.find hindex k + with Not_found -> + let d = get_definition x in + let t : integer = unwrap (e_call d.d_name []) in + I.H.add hindex k t ; t + + let has_ind x p = + try + let d = get_definition x in + Fol.pred_calls d.d_name p + with Not_found -> false + +end + +(* -------------------------------------------------------------------------- *) +(* --- Built-in Names --- *) +(* -------------------------------------------------------------------------- *) + +module Findex = Dindex(Fieldinfo) +module Xindex = Dindex(Varinfo) +module Tindex = Dindex(Compinfo) +module Aindex = Dindex(Varaddr) +module LTindex = Dindex(LTypeinfo) + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_formula.mli frama-c-20111001+nitrogen+dfsg/src/wp/fol_formula.mli --- frama-c-20110201+carbon+dfsg/src/wp/fol_formula.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_formula.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,30 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Formula +open Ctypes + + +include Formula.S with type 'a term = Fol.term + and type pred = Fol.pred + and type var = Fol.Var.t + and type decl = Fol.decl diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_let.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_let.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_let.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_let.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,130 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Fol + +(* -------------------------------------------------------------------------- *) +(* --- Alpha Conversion --- *) +(* -------------------------------------------------------------------------- *) + +(* alpha-conversion *) + +module Smap = Datatype.String.Map + +type sigma = { + cpt : int Smap.t ; + var : term Vmap.t ; +} + +let fresh sigma x = + let base = Var.basename x in + let tau = Var.var_type x in + let k = try Smap.find base sigma.cpt with Not_found -> 0 in + let y = Var.ident_named_var base k tau in + y , { cpt = Smap.add base (succ k) sigma.cpt ; + var = Vmap.add x (e_var y) sigma.var } + +let alpha sigma x = + try Vmap.find x sigma.var + with Not_found -> Wp_parameters.fatal "Unbound fol-variable %s (let)" (Var.var_name x) + +let rec def = function Pnamed(_,p) -> def p | p -> p +let rec redef p p' = match p with Pnamed(a,p0) -> Pnamed(a,redef p0 p') | _ -> p' +let rec is_simple = function (Tvar _ | Tconst _ | Tapp(_,[])) -> true | _ -> false +let bind x v sigma = { sigma with var = Vmap.add x v sigma.var } + +let rec term sigma = function + | Tconst _ as c -> c + | Tvar v -> alpha sigma v + | Tgetfield(f,r) -> e_getfield f (term sigma r) + | Tsetfield(f,r,v) -> e_setfield f (term sigma r) (term sigma v) + | Taccess(t,i) -> e_access (term sigma t) (term sigma i) + | Tupdate(t,i,v) -> e_update (term sigma t) (term sigma i) (term sigma v) + | Tapp (n,tl) -> e_app n (List.map (term sigma) tl) + | Tif (t1,t2,t3) -> e_if (term sigma t1) (term sigma t2) (term sigma t3) + | Tlet (x,v,t) -> + let v = term sigma v in + if is_simple v && Wp_parameters.Simpl.get() + then + term (bind x v sigma) t + else + let x,sigma = fresh sigma x in + e_let x v (term sigma t) + +let rec pred sigma = function + | Papp(f,ts) -> p_app f (List.map (term sigma) ts) + | Ptrue -> Ptrue + | Pfalse -> Pfalse + | Pif(e,p,q) -> p_if (term sigma e) (pred sigma p) (pred sigma q) + | Pand(p,q) -> p_and (pred sigma p) (pred sigma q) + | Por(p,q) -> p_or (pred sigma p) (pred sigma q) + | Piff(p,q) -> p_iff (pred sigma p) (pred sigma q) + | Pnot p -> p_not (pred sigma p) + | Pnamed(a,p) -> p_named a (pred sigma p) + | Pforall(x,p) -> let x,sigma = fresh sigma x in p_forall x (pred sigma p) + | Pexists(x,p) -> let x,sigma = fresh sigma x in p_exists x (pred sigma p) + | Plet(x,v,p) -> + let v = term sigma v in + if is_simple v && Wp_parameters.Simpl.get() + then + pred (bind x v sigma) p + else + let x,sigma = fresh sigma x in + p_let x v (pred sigma p) + | Pimplies(p,q) -> + match def p with + | Papp(("eq"|"eq_int"|"eq_real"),([Tvar x;e] | [e;Tvar x])) when Wp_parameters.Simpl.get() -> + let ve = term sigma e in + if is_simple ve then + let vx = alpha sigma x in + let q = pred (bind x ve sigma) q in + let p = redef p (Papp("eq",[vx;ve])) in + p_implies p q + else + let vx = alpha sigma x in + let q = pred sigma q in + let p = redef p (Papp("eq",[vx;ve])) in + p_implies p q + | _ -> + let p = pred sigma p in + let q = pred sigma q in + match def p with + | Papp("eq",([Tvar x;v] | [v;Tvar x])) + when is_simple v && Wp_parameters.Simpl.get() -> + let q = Fol.pred_replace (fun _ -> None) x v q in + p_implies p q + | _ -> p_implies p q + +let empty = { cpt = Smap.empty ; var = Vmap.empty } + +let compile = pred empty + +let rec fresh_params ys sigma = function + | [] -> List.rev ys , sigma + | x::xs -> + let y,sigma = fresh sigma x in + fresh_params (y::ys) sigma xs + +let compile_def xs p = + let ys,sigma = fresh_params [] empty xs in + ys , pred sigma p + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_let.mli frama-c-20111001+nitrogen+dfsg/src/wp/fol_let.mli --- frama-c-20110201+carbon+dfsg/src/wp/fol_let.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_let.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- FOL Alpha-Normalization --- *) +(* -------------------------------------------------------------------------- *) + +val compile : Fol.pred -> Fol.pred +val compile_def : Fol.Var.t list -> Fol.pred -> Fol.Var.t list * Fol.pred diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,937 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_datatype + +(* ------------------------------------------------------------------------ *) +(** {2 Constants} *) + +type constant = + | ConstInt of string + | ConstBool of bool + | ConstUnit + | ConstFloat of string + +let c_bool b = ConstBool b +let c_int_of_str s = ConstInt s +let c_int i = ConstInt (string_of_int i) +let c_float_of_str s = ConstFloat s +let c_float f = ConstFloat (string_of_float f) + +(* ------------------------------------------------------------------------ *) +(** {2 Variables} *) + +module Var = struct + + type t = + (string * int option * Formula.tau * Cil_types.logic_type option) + + let var_type (_, _, t,_)= t + + let var_name (v,p,_,_)= + match p with + | None -> v + | Some id -> Printf.sprintf "%s_%d" v id + + let basename (x,_,_,_) = x + + let kind_of_var (_,_,t,p)= + match p with + | Some ty -> Formula.Acsl(t,ty) + | None -> Formula.Model t + + let var_counter = ref 0 + + (* ensures that the counter is still ok even if some numbers are used + * by external function through [mk] or [ident_named_var] *) + let check_cpt k = if k > !var_counter then var_counter := k + + let fresh_named_var name t = + incr var_counter; + (name, Some !var_counter, t,None) + + let fresh_var (name, _, t,_) = fresh_named_var name t + + let mk x k_opt tau ltype_opt = + (match k_opt with None -> () | Some k -> check_cpt k); + (x, k_opt, tau, ltype_opt) + + let ident_named_var name k t = + check_cpt k; (name,Some k,t,None) + + let equal v1 v2 = match v1, v2 with + | (x,c,_,_) , (y,d,_,_) -> c=d && x=y + + let compare v1 v2 = match v1, v2 with + | (v1, id1, _,_), (v2, id2, _,_) -> + let cmp = String.compare v1 v2 in + if cmp <> 0 then cmp + else + begin + match id1 , id2 with + | None , None -> 0 + | Some _ , None -> 1 + | None , Some _ -> (-1) + | Some id1 , Some id2 -> Pervasives.compare id1 id2 + end + +end + +module Vset = Set.Make(Var) +module Vmap = Map.Make(Var) + +(* ------------------------------------------------------------------------ *) +(** {2 Terms} *) +(* ------------------------------------------------------------------------ *) + +type term = + | Tconst of constant + | Tvar of Var.t + | Tapp of string * term list + | Tgetfield of Cil_types.fieldinfo * term + | Tsetfield of Cil_types.fieldinfo * term * term + | Taccess of term * term + | Tupdate of term * term * term + | Tif of term * term * term + | Tlet of Var.t * term * term + +(* -----------------------------------*) +(** {3 Term comparison} *) + +let rec eq_terms e1 e2 = + match e1, e2 with + | Tconst c1, Tconst c2 -> Pervasives.compare c1 c2 = 0 + | Tvar v1, Tvar v2 -> Var.equal v1 v2 + | Tapp (f1, args1), Tapp (f2, args2) -> + f1 = f2 && List.for_all2 eq_terms args1 args2 + | Tif (c1, t1, e1), Tif (c2, t2, e2) -> + eq_terms c1 c2 && eq_terms t1 t2 && eq_terms e1 e2 + | Tlet (x,v,t),Tlet(x',v',t') -> + Var.equal x x' && eq_terms v v' && eq_terms t t' + | Tgetfield (f,r) , Tgetfield(g,s) -> + Fieldinfo.equal f g && eq_terms r s + | Tsetfield (f,r,v) , Tsetfield(g,s,w) -> + Fieldinfo.equal f g && eq_terms r s && eq_terms v w + | Taccess (t,i) , Taccess (u,j) -> + eq_terms t u && eq_terms i j + | Tupdate (t,i,v), Tupdate(u,j,w) -> + eq_terms t u && eq_terms i j && eq_terms v w + | _ -> false + +(* -----------------------------------*) +(** {3 Term visitors} *) + +let rec e_has_var xs e = + let frec = e_has_var xs in + match e with + | Tconst _ -> false + | Tvar y -> List.exists (Var.equal y) xs + | Tapp(_,ts) -> List.exists (frec) ts + | Tgetfield(_,r) -> frec r + | Tsetfield(_,r,v) -> frec r || frec v + | Taccess(t,i) -> frec t || frec i + | Tupdate (t,i,v) -> frec t || frec i || frec v + | Tif(a,b,c) -> frec a || frec b || frec c + | Tlet(x,v,t) -> + frec v || + (let xs = List.filter (fun y -> not (Var.equal x y)) xs in + xs <> [] && e_has_var xs t) + +let rec e_closed xs = function + | Tconst _ -> true + | Tvar y -> List.exists (Var.equal y) xs + | Tgetfield(_,r) -> e_closed xs r + | Tsetfield(_,r,v) -> e_closed xs r && e_closed xs v + | Taccess(t,i) -> e_closed xs t && e_closed xs i + | Tupdate(t,i,v) -> e_closed xs t && e_closed xs i && e_closed xs v + | Tapp(_,ts) -> List.for_all (e_closed xs) ts + | Tif(a,b,c) -> e_closed xs a && e_closed xs b && e_closed xs c + | Tlet(x,v,t) -> e_closed xs v && e_closed (x::xs) t + +(* -----------------------------------*) +(** {3 Term smart constructors} *) + +let e_true = Tconst (c_bool true) +let e_false = Tconst (c_bool false) +let e_int i = Tconst (c_int i) +let e_int64 i = Tconst (ConstInt (Int64.to_string i)) +let e_float f = Tconst (c_float f) +let e_cnst c = Tconst c +let e_var v = Tvar v + +let e_if c t f = match c with + | Tconst (ConstBool true) -> t + | Tconst (ConstBool false) -> f + | _ -> if eq_terms t f then t else Tif (c, t, f) + +let i_compute zop a b = + let z_a = Big_int.big_int_of_string a in + let z_b = Big_int.big_int_of_string b in + Tconst(ConstInt(Big_int.string_of_big_int (zop z_a z_b))) + +let i_apply zop a = + let z_a = Big_int.big_int_of_string a in + Tconst(ConstInt(Big_int.string_of_big_int (zop z_a))) + +let simpl() = Wp_parameters.Simpl.get() + + +let signed_in_bound b z opt_z def_z = + let bz = Big_int.big_int_of_string z in + if (Big_int.le_big_int (Big_int.minus_big_int b) bz && Big_int.lt_big_int bz b) + then opt_z else def_z + +let unsigned_in_bound b z opt_z def_z = + let bz = Big_int.big_int_of_string z in + if (Big_int.le_big_int Big_int.zero_big_int bz && Big_int.lt_big_int bz b) + then opt_z else def_z + +let as_int_format fmt z = + let def = Tapp ("as_int",[Tapp(fmt,[]) ; Tconst(ConstInt z)]) in + let opt = Tconst (ConstInt z) in + let signed_in_bound b = signed_in_bound b z opt def in + let unsigned_in_bound b =unsigned_in_bound b z opt def in + match fmt with + | "uint8_format" -> + let b = Big_int.big_int_of_int 256 in unsigned_in_bound b + | "sint8_format" -> + let b = Big_int.big_int_of_int 128 in signed_in_bound b + | "uint16_format" -> + let b = Big_int.big_int_of_int 65536 in unsigned_in_bound b + | "sint16_format" -> + let b = Big_int.big_int_of_int 32768 in signed_in_bound b + | "uint32_format" -> + let b = Big_int.big_int_of_string ("4294967296") in + unsigned_in_bound b + | "sint32_format" -> + let b = Big_int.big_int_of_string ("2147483648") in + signed_in_bound b + | "uint64_format" -> + let b = Big_int.big_int_of_string ("18446744073709551616") in + unsigned_in_bound b + | "sint64_format" -> + let b = Big_int.big_int_of_string ("9223372036854775808") in + signed_in_bound b + |_ -> def + + +let as_int s z = + let def = Tapp (s,[Tconst(ConstInt z)]) in + let opt = Tconst (ConstInt z) in + let signed_in_bound b = signed_in_bound b z opt def in + let unsigned_in_bound b = unsigned_in_bound b z opt def in + match s with + | "as_uint8" -> + let b = Big_int.big_int_of_int 256 in unsigned_in_bound b + | "as_sint8" -> + let b = Big_int.big_int_of_int 128 in signed_in_bound b + | "as_uint16" -> + let b = Big_int.big_int_of_int 65536 in unsigned_in_bound b + | "as_sint16" -> + let b = Big_int.big_int_of_int 32768 in signed_in_bound b + | "as_uint32" -> + let b = Big_int.big_int_of_string ("4294967296") in + unsigned_in_bound b + | "as_sint32" -> + let b = Big_int.big_int_of_string ("2147483648") in + signed_in_bound b + | "as_uint64" -> + let b = Big_int.big_int_of_string ("18446744073709551616") in + unsigned_in_bound b + | "as_sint64" -> + let b = Big_int.big_int_of_string ("9223372036854775808") in + signed_in_bound b + |_ -> def + + + +let coercion f g d = + let def = Tapp (f , [Tapp(g,[d])]) in + match f,g,d with + | "data_of_addr", "addr_of_data",_ + | "data_of_uint8", "uint8_of_data",_ + | "data_of_sint8", "sint8_of_data",_ + | "data_of_uint16", "uint16_of_data",_ + | "data_of_sint16", "sint16_of_data",_ + | "data_of_uint32", "uint32_of_data",_ + | "data_of_sint32", "sint32_of_data",_ + | "data_of_uint64", "uint64_of_data",_ + | "data_of_sint64", "sint64_of_data",_ + | "data_of_float16", "float16_of_data",_ + | "data_of_float32", "float32_of_data",_ + | "data_of_float64", "float64_of_data",_ + | "data_of_float128", "float128_of_data",_ -> d + | "uint8_of_data", "data_of_uint8",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_int 256 in unsigned_in_bound b z d def + | "sint8_of_data", "data_of_sint8",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_int 128 in signed_in_bound b z d def + | "uint16_of_data", "data_of_uint16",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_int 65536 in unsigned_in_bound b z d def + | "sint16_of_data", "data_of_sint16",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_int 32768 in signed_in_bound b z d def + | "uint32_of_data", "data_of_uint32",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_string ("4294967296") in unsigned_in_bound b z d def + | "sint32_of_data", "data_of_sint32",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_string ("2147483648") in signed_in_bound b z d def + | "uint64_of_data", "data_of_uint64",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_string ("18446744073709551616") in unsigned_in_bound b z d def + | "sint64_of_data", "data_of_sint64",Tconst(ConstInt z) -> + let b = Big_int.big_int_of_string ("9223372036854775808") in signed_in_bound b z d def + | _ -> def + + +let e_app f args = + if not (simpl()) then Tapp(f,args) + else + match f , args with + | "neg_int" , [ Tapp( "neg_int" , [a] ) ] -> a + | "neg_real" , [ Tapp( "neg_real" , [a] ) ] -> a + | "neg_int" , [ Tconst (ConstInt a) ] -> + i_apply Big_int.minus_big_int a + | "add_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] -> + i_compute Big_int.add_big_int a b + | "sub_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] -> + i_compute Big_int.sub_big_int a b + | "mul_int" , [ Tconst (ConstInt a) ; Tconst (ConstInt b) ] -> + i_compute Big_int.mult_big_int a b + | "add_int" , [ Tconst (ConstInt "0") ; x ] -> x + | "add_int" , [ x ; Tconst (ConstInt "0") ] -> x + | "sub_int" , [ x ; Tconst (ConstInt "0") ] -> x + | "mul_int" , [ Tconst (ConstInt "1") ; x ] -> x + | "mul_int" , [ x ; Tconst (ConstInt "1") ] -> x + | "mul_int" , [ (Tconst (ConstInt "0")) as z ; _ ] -> z + | "mul_int" , [ _ ; (Tconst (ConstInt "0")) as z ] -> z + | "add_int" , [ b ; Tapp("sub_int",[a;c]) ] when eq_terms b c -> a ; + | "add_int" , [ Tapp("sub_int",[a;b]) ; c ] when eq_terms b c -> a + | "sub_int" , [ Tapp("add_int",[a;b]) ; c ] when eq_terms b c -> a + | "encode" , [ Tapp("decode" , [ a ; fmt ]) ; fmt' ] when eq_terms fmt fmt' -> a + | "decode" , [ Tapp("encode" , [ a ; fmt ]) ; fmt' ] when eq_terms fmt fmt' -> a + | "as_int" , [Tapp(fmt,[]) ; Tconst(ConstInt z)] -> as_int_format fmt z + | f , [Tconst(ConstInt z)] -> as_int f z + | f , [Tapp(g,[d])] -> coercion f g d + | _ -> Tapp (f, args) + +let e_let x exp t = if e_has_var [x] t then Tlet (x, exp, t) else t + +let case_of = function + | Tconst(ConstInt s) -> Some s + | _ -> None + +let e_update t i v = Tupdate(t,i,v) +let e_access t i = + match t with + | Tupdate(_,j,v) when simpl() && eq_terms i j -> v + | t -> Taccess(t,i) + +let e_setfield f r v = Tsetfield(f,r,v) +let e_getfield f r = + match r with + | Tsetfield(g,s,w) when simpl() -> + if Fieldinfo.equal f g + then w (* get set same field *) + else + if f.Cil_types.fcomp.Cil_types.cstruct then + Tgetfield(f,s) (* get set other of record only *) + else + Tgetfield(f,r) + | r -> Tgetfield(f,r) + + +(* -----------------------------------*) +(** {3 Term transformation} *) + +(** Apply [do_var] in term subexpressions.*) +let rec change_in_exp do_var exp = + let frec = change_in_exp do_var in + match exp with + | Tconst c -> e_cnst c + | Tvar v -> (match do_var v with Some e -> e | None -> e_var v) + | Tgetfield(f,r) -> e_getfield f (frec r) + | Tsetfield(f,r,v) -> e_setfield f (frec r) (frec v) + | Taccess(t,i) -> e_access (frec t) (frec i) + | Tupdate(t,i,v) -> e_update (frec t) (frec i) (frec v) + | Tapp (n,tl) -> e_app n (List.map (frec) tl) + | Tif (t1,t2,t3) -> e_if (frec t1) (frec t2) (frec t3) + | Tlet (x,v,t) -> e_let x (frec v) (frec t) + +let rec term_replace alpha x exp t = + let frec = term_replace alpha x exp in + match t with + | Tconst _ -> t + | Tvar x0 -> if Var.equal x0 x then exp else t + | Tapp (f, ts) -> e_app f (List.map (frec) ts) + | Tif (a, b, c) -> e_if (frec a) (frec b) (frec c) + | Tgetfield(f,r) -> e_getfield f (frec r) + | Tsetfield(f,r,v) -> e_setfield f (frec r) (frec v) + | Taccess(t,i) -> e_access (frec t) (frec i) + | Tupdate(t,i,v) -> e_update (frec t) (frec i) (frec v) + | Tlet (x0, a, b) -> + if e_has_var [x0] exp then + match alpha x with + | None -> Tlet(x,exp,t) + | Some y -> + let by = term_replace alpha x0 (Tvar y) b in + Tlet(y,frec a,frec by) + else + let b' = if Var.equal x0 x then b else frec b in + Tlet(x0,frec a,b') + +let alpha_bound_var alpha v = + let old = try Some (Vmap.find v alpha) with Not_found -> None in + old, Vmap.add v v alpha + +let alpha_unbound alpha v old = match old with + | Some v' -> Vmap.add v v' alpha + | None -> Vmap.remove v alpha + +let apply_alpha alpha v = + try alpha, Vmap.find v alpha + with Not_found -> + let v' = Var.fresh_var v in + let alpha = Vmap.add v v' alpha in + alpha, v' + +let rec term_alpha_cv alpha t = + let do_term alpha t = term_alpha_cv alpha t in + let rec do_terms alpha l = terms_alpha_cv alpha l in + match t with + | Tconst _ -> alpha, t + | Tvar v -> + let alpha, v = apply_alpha alpha v in alpha, Tvar v + | Tapp (f, ts) -> + let alpha, ts = do_terms alpha ts in + alpha, e_app f ts + | Tgetfield(f,r) -> + let alpha, r = do_term alpha r in + alpha,e_getfield f r + |Tsetfield(f,r,v) -> + let alpha,r = do_term alpha r in + let alpha,v = do_term alpha v in + alpha, e_setfield f r v + | Taccess(t,i) -> + let alpha,t = do_term alpha t in + let alpha,i = do_term alpha i in + alpha,e_access t i + | Tupdate(t,i,v) -> + let alpha,t = do_term alpha t in + let alpha,i = do_term alpha i in + let alpha,v = do_term alpha v in + alpha, e_update t i v + | Tif (a, b, c) -> + let alpha, a = do_term alpha a in + let alpha, b = do_term alpha b in + let alpha, c = do_term alpha c in + alpha, e_if a b c + | Tlet (x, a, b) -> + let alpha, a = do_term alpha a in (* a doesn't see x *) + let old_x, alpha = alpha_bound_var alpha x in + let alpha, b = do_term alpha b in + let alpha = alpha_unbound alpha x old_x in (* restore old_x *) + alpha, e_let x a b +and terms_alpha_cv alpha l = match l with [] -> alpha, [] + | t::l -> + let alpha, t = term_alpha_cv alpha t in + let alpha, l = terms_alpha_cv alpha l in + alpha, t::l + +(* ------------------------------------------------------------------------ *) +(** {2 Predicates} *) +(* ------------------------------------------------------------------------ *) + +type pred = + | Papp of string * term list + | Ptrue + | Pfalse + | Pimplies of pred * pred + | Pif of term * pred * pred + | Pand of pred * pred + | Por of pred * pred + | Piff of pred * pred + | Pnot of pred + | Pforall of Var.t * pred + | Pexists of Var.t * pred + | Plet of Var.t * term * pred + | Pnamed of string * pred + +let rec eq_preds p q = + match p,q with + | Papp(f,xs) , Papp(g,ys) -> + f = g && List.for_all2 eq_terms xs ys + | Ptrue , Ptrue -> true + | Pfalse , Pfalse -> true + | Pnamed(_,p) , q -> eq_preds p q + | p , Pnamed(_,q) -> eq_preds p q + | Pnot p , Pnot q -> eq_preds p q + | _ -> false + +let rec p_has_var xs = function + | Papp(_,ts) -> List.exists (e_has_var xs) ts + | Ptrue | Pfalse -> false + | Pimplies(p,q) | Pand(p,q) | Por(p,q) | Piff(p,q) -> + p_has_var xs p || p_has_var xs q + | Pif(t,p,q) -> + e_has_var xs t || p_has_var xs p || p_has_var xs q + | Pnot p | Pnamed(_,p) -> p_has_var xs p + | Pforall(x,p) | Pexists(x,p) -> + let xs = List.filter (fun y -> not (Var.equal x y)) xs in + xs <> [] && p_has_var xs p + | Plet(x,a,p) -> + e_has_var xs a || + (let xs = List.filter (fun y -> not (Var.equal x y)) xs in + xs <> [] && p_has_var xs p) + +let rec p_closed xs = function + | Papp(_,ts) -> List.for_all (e_closed xs) ts + | Ptrue | Pfalse -> true + | Pimplies(p,q) | Pand(p,q) | Por(p,q) | Piff(p,q) -> + p_closed xs p && p_closed xs q + | Pif(t,p,q) -> + e_closed xs t && p_closed xs p && p_closed xs q + | Pnot p | Pnamed(_,p) -> p_closed xs p + | Pforall(x,p) | Pexists(x,p) -> p_closed (x::xs) p + | Plet(x,a,p) -> + e_closed xs a && p_closed (x::xs) p + +(* -----------------------------------*) +(** {3 Predicates smart constructors} *) + +let pp_term : (Format.formatter -> term -> unit) ref = ref (fun _ _ -> ()) + +let i_compare zop a b = + if zop (Big_int.big_int_of_string a) (Big_int.big_int_of_string b) + then Ptrue else Pfalse + +let p_app name args = + if not (simpl()) then Papp(name,args) + else + match name , args with + | "eq", [ a ; b ] when eq_terms a b -> Ptrue + | "neq", [ a ; b ] when eq_terms a b -> Pfalse + | "le_int" , [a;b] when eq_terms a b -> Ptrue + | "lt_int" , [a;b] when eq_terms a b -> Pfalse + | "eq" , [ Tconst(ConstInt a) ; Tconst(ConstInt b) ] -> + i_compare Big_int.eq_big_int a b + | "neq" , [ Tconst(ConstInt a) ; Tconst(ConstInt b) ] -> + i_compare (fun za zb -> not (Big_int.eq_big_int za zb)) a b + | "le_int" , [ Tconst(ConstInt a) ; Tconst(ConstInt b) ] -> + i_compare Big_int.le_big_int a b + | "lt_int" , [ Tconst(ConstInt a) ; Tconst(ConstInt b) ] -> + i_compare Big_int.lt_big_int a b + | _ -> Papp (name,args) + +let rec val_of = function Pnamed (_,p) -> val_of p | p -> p +let rec cut p = function Pnamed (a,q) -> Pnamed(a,cut p q) | _ -> p + +let rec is_true = function + | Ptrue -> true + | Pnamed(_,p) -> is_true p + | _ -> false + +let rec is_false = function + | Pfalse -> true + | Pnamed(_,p) -> is_false p + | _ -> false + +let p_not p = match val_of p with + | Ptrue -> cut Pfalse p + | Pfalse -> cut Ptrue p + | Papp( "eq" , w ) -> p_app "neq" w + | Papp( "neq" , w ) -> p_app "eq" w + | Papp( "le_int" , [a;b] ) -> p_app "lt_int" [b;a] + | Papp( "lt_int" , [a;b] ) -> p_app "le_int" [b;a] + | _ -> Pnot p + +let p_and p1 p2 = match val_of p1, val_of p2 with + | Ptrue, _ -> p2 + | _, Ptrue -> p1 + | Pfalse,_-> cut Pfalse p1 + | _,Pfalse -> cut Pfalse p2 + | _ -> Pand (p1, p2) + +let p_or p1 p2 = match val_of p1, val_of p2 with + | Ptrue, _ -> cut Ptrue p1 + | _ , Ptrue -> cut Ptrue p2 + | Pfalse ,_ -> p2 + | _ ,Pfalse -> p1 + | _ -> Por (p1,p2) + +let p_xor p1 p2 = match val_of p1, val_of p2 with + | Ptrue , Ptrue -> cut (cut Pfalse p2) p1 + | Ptrue ,_ -> cut Ptrue p1 + | _,Ptrue -> cut Ptrue p2 + | Pfalse , _ -> p2 + | _ , Pfalse -> p1 + | _ -> Pnot(Piff(p1,p2)) + +let p_implies p1 p2 = + match val_of p1, val_of p2 with + | Ptrue, _ -> p2 + | Pfalse, _ -> cut Ptrue p1 + | _, Ptrue -> cut Ptrue p2 + | _ -> Pimplies (p1, p2) + +let rec p_conj = function + | [] -> Ptrue + | [p] -> p + | p::ps -> p_and p (p_conj ps) + +let rec p_disj = function + | [] -> Pfalse + | [p] -> p + | p::ps -> p_or p (p_disj ps) + +let p_if c p1 p2 = match c, val_of p1, val_of p2 with + | (_,Ptrue, Ptrue ) -> cut (cut Ptrue p2) p1 + | (_,Pfalse, Pfalse ) -> cut (cut Pfalse p2) p1 + | (t,_ , _) -> Pif (t,p1,p2) + +let p_iff p1 p2 = + match val_of p1,val_of p2 with + | Ptrue ,_ -> p2 + | _ ,Ptrue -> p1 + | Pfalse, _ -> p_not p2 + | _ , Pfalse -> p_not p1 + | _ -> Piff (p1,p2) + +let p_eq e1 e2 = + if eq_terms e1 e2 then Ptrue else p_app "eq" [e1; e2] +let p_neq e1 e2 = + if eq_terms e1 e2 then Pfalse else p_app "neq" [e1; e2] + +let p_forall x p = + match val_of p with + | Ptrue | Pfalse | Papp ("dummy",_) -> p + | _ -> if p_has_var [x] p then Pforall(x,p) else p + +let p_exists x p = + match val_of p with + | Ptrue | Pfalse | Papp ("dummy",_) -> p + | _ -> if p_has_var [x] p then Pexists(x,p) else p + +let p_let x v p = + match val_of p with + | Ptrue | Pfalse| Papp ("dummy",_) -> p + | _ -> if p_has_var [x] p then Plet(x,v,p) else p + +let p_named name p = Pnamed(name,p) + +(* ------------------------------------------------------------------------ *) +(* --- Propagation of transformations --- *) +(* ------------------------------------------------------------------------ *) + + +(** apply [do_exp] on each sub expression of the predicate. +* [quantif_do_exp] is called to change [do_exp] if needed +* when we go under a quantification. +* This version makes possible to have a different flavor of term, +* ie. it can be used for translation. +* TODOopt: we could have another optimized version if the types of terms +* are the same in order to avoid building new terms when there is no +* modification. +* *) +let rec change_exp_in_pred (do_exp:term -> term) + (quantif_do_exp: (term -> term) -> Var.t -> + (term -> term)) p = + let subst_pred = change_exp_in_pred do_exp quantif_do_exp in + match p with + | Ptrue -> Ptrue + | Pfalse -> Pfalse + | Pif (t,p1,p2) -> + Pif (do_exp t, subst_pred p1, subst_pred p2) + | Pnot p -> p_not (subst_pred p) + | Pforall (v,p') -> + let f = quantif_do_exp do_exp v in + Pforall (v,change_exp_in_pred f quantif_do_exp p') + | Pexists (v,p') -> + let f = quantif_do_exp do_exp v in + Pexists (v,change_exp_in_pred f quantif_do_exp p') + | Plet (x,v,p) -> + let f = quantif_do_exp do_exp x in + Plet (x, do_exp v,change_exp_in_pred f quantif_do_exp p) + | Pnamed (n,p) -> Pnamed (n,subst_pred p) + | Pimplies (p1,p2) -> p_implies (subst_pred p1) (subst_pred p2) + | Pand (p1,p2) -> p_and (subst_pred p1) (subst_pred p2) + | Por (p1,p2) -> p_or (subst_pred p1) (subst_pred p2) + | Piff (p1,p2) -> p_iff (subst_pred p1) (subst_pred p2) + | Papp (n,t) -> p_app n (List.map do_exp t) + +let no_quantif_do_exp do_exp qqvar = + let var_term = e_var qqvar in + match do_exp var_term with + | Tvar v when Var.equal qqvar v -> do_exp + | _ -> assert false +(* +let change_data_in_pred do_data_rec p = + change_exp_in_pred (change_data_in_exp do_data_rec) no_quantif_do_exp p +*) +(* ------------------------------------------------------------------------ *) +(* --- Alpha-conversion --- *) +(* ------------------------------------------------------------------------ *) + +let rec pred_alpha_cv alpha p = + let do_pred alpha p = pred_alpha_cv alpha p in + let rec do_preds alpha l = match l with [] -> alpha, l + | p::l -> + let alpha, p = do_pred alpha p in + let alpha, l = do_preds alpha l in + alpha, p::l + in + match p with + | Ptrue | Pfalse -> alpha, p + | Pif (t,p1,p2) -> + let alpha, t = term_alpha_cv alpha t in + let alpha, p1 = do_pred alpha p1 in + let alpha, p2 = do_pred alpha p2 in + alpha, Pif (t,p1,p2) + | Pnot p -> let alpha, p = do_pred alpha p in alpha, Pnot p + | Pforall (x,p) -> + let old_x, alpha = alpha_bound_var alpha x in + let alpha, p = do_pred alpha p in + let alpha = alpha_unbound alpha x old_x in + alpha, Pforall (x,p) + | Pexists (x,p) -> + let old_x, alpha = alpha_bound_var alpha x in + let alpha, p = do_pred alpha p in + let alpha = alpha_unbound alpha x old_x in + alpha, Pexists (x,p) + | Plet (x,t,p) -> + let alpha, t = term_alpha_cv alpha t in + let old_x, alpha = alpha_bound_var alpha x in + let alpha, p = do_pred alpha p in + let alpha = alpha_unbound alpha x old_x in + alpha, Plet (x,t,p) + | Pnamed (n,p) -> let alpha, p = do_pred alpha p in alpha, Pnamed (n,p) + | Pimplies (p1,p2) -> + let alpha, p1 = do_pred alpha p1 in + let alpha, p2 = do_pred alpha p2 in + alpha, Pimplies (p1,p2) + | Pand (p1,p2) -> + let alpha, p1 = do_pred alpha p1 in + let alpha, p2 = do_pred alpha p2 in + alpha, Pand (p1,p2) + | Por (p1,p2) -> + let alpha, p1 = do_pred alpha p1 in + let alpha, p2 = do_pred alpha p2 in + alpha, Por (p1,p2) + | Piff (p1,p2) -> + let alpha, p1 = do_pred alpha p1 in + let alpha, p2 = do_pred alpha p2 in + alpha, Piff (p1,p2) + | Papp (n,lt) -> + let alpha, lt = terms_alpha_cv alpha lt in alpha, p_app n lt + + +let p_alpha_cv p = + let alpha, p = pred_alpha_cv Vmap.empty p in + let vars = Vmap.fold (fun _v v' acc -> v'::acc) alpha [] in + vars, p + +(* ------------------------------------------------------------------------ *) +(* --- Translation (data type can be modified) --- *) +(* ------------------------------------------------------------------------ *) + +let change_exp_in_pred do_exp = change_exp_in_pred do_exp no_quantif_do_exp + +(* ------------------------------------------------------------------------ *) +(* --- Variable substitutions *) +(* ------------------------------------------------------------------------ *) + +(** Similar to [change_vars_in_exp] but on predicates. +* Notice that we assume (and check) that [var_subst] only works on free +* variables (and that they are different from bounded ones). +*) +let subst_vars_in_pred var_subst p = + let rec do_exp exp = change_in_exp var_subst exp + in change_exp_in_pred do_exp p + +(** Specialized version of [subst_vars_in_pred] to substitute one variable [v] +* by and expression [exp] in a predicate [p]. *) +let subst_in_pred x exp p = + let var_subst v = if Var.equal v x then Some exp else None in + subst_vars_in_pred var_subst p + + (* +let nb_var_in_pred prop_in_data v p = + let nb_occ = ref 0 in + let do_var () var = if Var.equal v var then nb_occ := !nb_occ + 1 in + let rec do_exp () e = fold_data_in_exp do_var do_data () e + and do_data () d = ignore (prop_in_data (fun e -> do_exp () e; e) d) in + let _ = fold_exp_in_pred do_exp () p in + !nb_occ +*) + +(** Build a predicate equivalent to [let v = e in p] but may use the +* substitution in some simple cases (like substitute a variable by another +* variable for instance). +* [fresh] is only meaningfull when the [let] is actually built: it tells if we +* have to build a new variable for [v]. +*) +let let_pred ~fresh v e p = + if p = Ptrue then Ptrue + else begin + match e with + | Tconst _ | Tvar _ -> subst_in_pred v e p + | _ -> + (* let nb_occ = nb_var_in_pred prop_in_data v p in + (* TODOopt : do only one visit *) + if nb_occ = 0 then p + (* else if nb_occ = 1 then subst_in_pred prop_in_data v e p *) + else *) + if fresh then + let v' = Var.fresh_var v in + let p = subst_in_pred v (e_var v') p in + p_let v' e p + else p_let v e p + end + +let rec pred_replace alpha x exp p = + let frec = pred_replace alpha x exp in + match p with + | Papp(f,ts) -> p_app f (List.map (term_replace alpha x exp) ts) + | (Ptrue | Pfalse) as p -> p + | Pimplies(p,q) -> p_implies (frec p) (frec q) + | Pif(a,p,q) -> p_if (term_replace alpha x exp a) (frec p) (frec q) + | Pand(p,q) -> p_and (frec p) (frec q) + | Por(p,q) -> p_or (frec p) (frec q) + | Piff(p,q) -> p_iff (frec p) (frec q) + | Pnot(p) -> p_not (frec p) + | Pforall(x0,p) as p0 -> + begin + if Var.equal x x0 then p0 + else if e_has_var [x0] exp then + match alpha x with + | None -> Plet(x,exp,p0) + | Some y -> + let py = pred_replace alpha x0 (Tvar y) p in + let py' = frec py in + Pforall( y , py' ) + else Pforall(x0, frec p) + end + | Pexists(x0,p) as p0 -> + begin + if Var.equal x x0 then p0 + else if e_has_var [x0] exp then + match alpha x with + | None -> Plet(x,exp,p0) + | Some y -> + let py = pred_replace alpha x0 (Tvar y) p in + let py' = frec py in + Pexists( y , py' ) + else Pexists(x0,frec p) + end + | Plet(x0,t,p) as p0 -> + begin + if e_has_var [x0] exp then + match alpha x with + | None -> Plet(x,exp,p0) + | Some y -> + let t' = term_replace alpha x exp t in + let py = pred_replace alpha x0 (Tvar y) p in + let py' = frec py in + Plet( y , t' , py' ) + else + let t' = term_replace alpha x exp t in + let p' = if Var.equal x0 x then p else frec p in + Plet(x0,t',p') + end + | Pnamed(a,p) -> Pnamed(a,frec p) + +(* ------------------------------------------------------------------------ *) +(* --- Quantification *) +(* ------------------------------------------------------------------------ *) + +let fresh_vars_in_pred vars p = + let do_var (vars, p) v = + let v' = Var.fresh_var v in + let p = subst_in_pred v (e_var v') p in + v'::vars, p + in List.fold_left do_var ([], p) vars + +let p_forall_vars vars (p: pred) : pred = + let vars, p = fresh_vars_in_pred vars p in + List.fold_left (fun p v -> p_forall v p) p vars + +let p_exists_vars vars (p: pred) : pred = + let vars, p = fresh_vars_in_pred vars p in + List.fold_left (fun p v -> p_exists v p) p vars + +let rec term_calls f = function + | Tconst _ | Tvar _ -> false + | Tapp(g,ts) -> f=g || List.exists (term_calls f) ts + | Tgetfield(_,a) -> term_calls f a + | Tsetfield(_,a,b) | Taccess(a,b) | Tlet(_,a,b) -> + term_calls f a || term_calls f b + | Tupdate(a,b,c) | Tif(a,b,c) -> + term_calls f a || term_calls f b || term_calls f c + +let rec pred_calls f = function + | Ptrue | Pfalse -> false + | Papp(g,ts) -> f=g || List.exists (term_calls f) ts + | Pimplies(a,b) | Pand(a,b) | Por(a,b) | Piff(a,b) -> + pred_calls f a || pred_calls f b + | Pnamed(_,p) | Pnot p | Pforall(_,p) | Pexists(_,p) -> + pred_calls f p + | Pif(a,p,q) -> + term_calls f a || pred_calls f p || pred_calls f q + | Plet(_,a,p) -> + term_calls f a || pred_calls f p + +(* ------------------------------------------------------------------------ *) +(* --- Huge *) +(* ------------------------------------------------------------------------ *) + +exception Huge + +let rec check_term m t = + if m < 0 then raise Huge ; + match t with + | Tconst _ | Tvar _ -> pred m + | Tapp(_,ts) -> List.fold_left check_term (pred m) ts + | Tgetfield(_,r) -> check_term (pred m) r + | Tsetfield(_,r,v) -> check_term (check_term (pred m) r) v + | Taccess(t,i) -> check_term (check_term (pred m) t) i + | Tupdate(t,i,v) -> check_term (check_term (check_term (pred m) t) i) v + | Tif(a,b,c) -> check_term (check_term (check_term (pred m) a) b) c + | Tlet(_,a,b) -> check_term (check_term (pred m) a) b + +let rec check_pred m p = + if m < 0 then raise Huge ; + match p with + | Ptrue | Pfalse -> pred m + | Papp(_,ts) -> List.fold_left check_term (pred m) ts + | Pimplies(a,b) | Pand(a,b) | Por(a,b) | Piff(a,b) -> check_pred (check_pred (pred m) a) b + | Pnamed(_,p) | Pnot p | Pforall(_,p) | Pexists(_,p) -> check_pred (pred m) p + | Pif(a,p,q) -> check_pred (check_pred (check_term (pred m) a) p) q + | Plet(_,t,p) -> check_pred (check_term (pred m) t) p + +let huge_term m t = try ignore (check_term m t) ; false with Huge -> true +let huge_pred m p = try ignore (check_pred m p) ; false with Huge -> true + +(* ------------------------------------------------------------------------ *) + +type decl = (Var.t,term,pred) Formula.declaration + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol.mli frama-c-20111001+nitrogen+dfsg/src/wp/fol.mli --- frama-c-20110201+carbon+dfsg/src/wp/fol.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,164 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +type constant = private + | ConstInt of string + | ConstBool of bool + | ConstUnit + | ConstFloat of string + +val c_bool : bool -> constant +val c_int_of_str : string -> constant +val c_int : int -> constant +val c_float : float -> constant +val c_float_of_str : string -> constant + +(** Fol Variable definition*) +module Var : sig + + type t + (* = (string * int option * Formula.tau * Cil_types.logic_type option) *) + + val mk : + string -> int option -> Formula.tau -> Cil_types.logic_type option -> t + val ident_named_var : string -> int -> Formula.tau -> t + val fresh_named_var : string -> Formula.tau -> t + val fresh_var : t -> t + val var_type : t -> Formula.tau + val var_name : t -> string + val basename : t -> string + val kind_of_var : t -> Formula.kind + val equal : t -> t -> bool + val compare : t -> t -> int + +end + +module Vset : Set.S with type elt = Var.t +module Vmap : Map.S with type key = Var.t + +(*----------------------------------------------------------------------------*) +(** Terms *) + +type term = private + | Tconst of constant + | Tvar of Var.t + | Tapp of string * term list + | Tgetfield of Cil_types.fieldinfo * term + | Tsetfield of Cil_types.fieldinfo * term * term + | Taccess of term * term + | Tupdate of term * term * term + | Tif of term * term * term + | Tlet of Var.t * term * term + +val e_true : term +val e_false : term +val e_int : int -> term +val e_int64 : int64 -> term +val e_float : float -> term +val e_cnst : constant -> term +val e_var : Var.t -> term +val e_if : term -> term -> term -> term +val e_app : string -> term list -> term +val e_getfield : Cil_types.fieldinfo -> term -> term +val e_setfield : Cil_types.fieldinfo -> term -> term -> term + +val e_access : term -> term -> term +val e_update : term -> term -> term -> term +val e_let : Var.t -> term -> term -> term + +val change_in_exp : (Var.t -> term option) -> term -> term +val term_replace : (Var.t -> Var.t option) -> Var.t -> term ->term -> term + +(*----------------------------------------------------------------------------*) +(** Predicates *) + +type pred = + | Papp of string * term list + | Ptrue + | Pfalse + | Pimplies of pred * pred + | Pif of term * pred * pred + | Pand of pred * pred + | Por of pred * pred + | Piff of pred * pred + | Pnot of pred + | Pforall of Var.t * pred + | Pexists of Var.t * pred + | Plet of Var.t * term * pred + | Pnamed of string * pred + +val eq_terms : term -> term -> bool (** structural equality *) +val eq_preds : pred -> pred -> bool (** (partial) structural equality *) + +val p_and : pred -> pred -> pred +val p_app: string -> term list -> pred +val p_or : pred -> pred -> pred +val p_xor : pred -> pred -> pred +val p_iff : pred -> pred -> pred +val p_not : pred -> pred +val p_if : term -> pred -> pred -> pred +val p_implies: pred -> pred -> pred +val p_conj : pred list -> pred +val p_disj : pred list -> pred + +val p_eq : term -> term -> pred +val p_neq : term -> term -> pred + +val p_forall : Var.t -> pred -> pred +val p_exists : Var.t -> pred -> pred +val p_let : Var.t -> term -> pred -> pred +val p_named : string -> pred -> pred + +val is_true : pred -> bool +val is_false : pred -> bool + +val e_has_var : Var.t list -> term -> bool +val p_has_var : Var.t list -> pred -> bool +val e_closed : Var.t list -> term -> bool +val p_closed : Var.t list -> pred -> bool + +val term_calls : string -> term -> bool +val pred_calls : string -> pred -> bool + +val subst_in_pred : Var.t -> term -> pred -> pred +val pred_replace : (Var.t -> Var.t option) -> Var.t -> term -> pred -> pred + +val let_pred : fresh:bool -> Var.t -> term -> pred -> pred + +val p_forall_vars : Var.t list -> pred -> pred + +val p_exists_vars : Var.t list -> pred -> pred + + +(** [pred_alpha_c data_alpha alpha p] -> [alpha', p']*) +val pred_alpha_cv : Var.t Vmap.t -> pred -> Var.t Vmap.t * pred + +val p_alpha_cv : pred -> Var.t list * pred + +(*----------------------------------------------------------------------------*) +val huge_term : int -> term -> bool +val huge_pred : int -> pred -> bool +(*----------------------------------------------------------------------------*) + +type decl = (Var.t,term,pred) Formula.declaration + +val pp_term : (Format.formatter -> term -> unit) ref diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_norm.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_norm.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_norm.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_norm.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Fol + +type normalized = + | Pred of pred + | Conv of Fol_cc.f_let list * pred + +let compile p = + match Wp_parameters.get_norm () with + | Wp_parameters.Let -> Pred p + | Wp_parameters.Exp -> Pred (Fol_eval.plet_expansion p) + | Wp_parameters.Cc -> let defs,p = Fol_cc.unlet p in Conv (defs,p) + | Wp_parameters.Eqs -> Pred (Fol_eqs.compile p) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_norm.mli frama-c-20111001+nitrogen+dfsg/src/wp/fol_norm.mli --- frama-c-20110201+carbon+dfsg/src/wp/fol_norm.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_norm.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Fol + +type normalized = + | Pred of pred + | Conv of Fol_cc.f_let list * pred + +val compile : pred -> normalized diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_pretty.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_pretty.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_pretty.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_pretty.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,377 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cilutil + + + + +let f_suffixe f = (f.Cil_types.fname)^"_"^(f.Cil_types.fcomp.Cil_types.cname) +let get_field f = "get_"^(f_suffixe f) +let set_field f = "set_"^(f_suffixe f) + + + +(* ---------------------------------------------------------------------- *) +(* --- Output Utilities --- *) +(* ---------------------------------------------------------------------- *) + + + +let constant fmt = function + | Fol.ConstInt n -> Format.pp_print_string fmt n + | Fol.ConstBool b -> Format.pp_print_string fmt (if b then "true" else "false") + | Fol.ConstUnit -> Format.pp_print_string fmt "void" + | Fol.ConstFloat f -> Format.pp_print_string fmt f + +let pp_list pp fmt = function + | [] -> () + | x::xs -> + pp fmt x ; + List.iter (fun x -> Format.fprintf fmt ",@,%a" pp x) xs + +let pp_flow fmt nil op pp = function + | [] -> + Format.pp_print_string fmt nil + | x::xs -> + Format.fprintf fmt "@[<hov 1>(%a" pp x ; + List.iter (fun x -> Format.fprintf fmt "@,%s%a" op pp x) xs ; + Format.fprintf fmt ")@]" + + +let pp_block fmt op pp ps = + Pretty_utils.pp_list + ~pre:"@[<hv>" ~sep:("@ " ^^ op ^^ "@ ") ~suf:"@]" + pp fmt ps + +let pp_block_implies fmt op pp ps = + Pretty_utils.pp_list + ~pre:"@[<v>" ~sep:(" " ^^ op ^^ "@ ") ~suf:"@]" + pp fmt ps + +let pp_var fmt v = + let name = Fol_decl.identifier (Fol.Var.var_name v) in + Format.fprintf fmt "%s" name + +let rec collect_assoc op xs = function + | [] -> List.rev xs + | Fol.Tapp(id,ts) :: others when id = op -> + collect_assoc op (collect_assoc op xs ts) others + | t::others -> + collect_assoc op (t::xs) others + +let fpp_term term fmt t = + match t with + | Fol.Tconst c -> constant fmt c + | Fol.Tvar v -> pp_var fmt v + | Fol.Tapp (id, []) -> Format.pp_print_string fmt id + | Fol.Tapp ("ite",[c;a;b]) | Fol.Tif (c,a,b) -> + Format.fprintf fmt "(@[<hv>if %a@ then %a@ else %a@])" + term c term a term b + + (* INT *) + | Fol.Tapp ("neg_int", [t]) -> + Format.fprintf fmt "@[<hov 1>(-%a)@]" term t + | Fol.Tapp ("add_int", ts) -> + let xs = collect_assoc "add_int" [] ts in + pp_flow fmt "0" "+" term xs + | Fol.Tapp ("sub_int", [a;b]) -> + Format.fprintf fmt "@[<hov 1>(%a@,-%a)@]" term a term b + | Fol.Tapp ("mul_int", ts) -> + let xs = collect_assoc "mul_int" [] ts in + pp_flow fmt "1" "*" term xs + + (* REAL *) + | Fol.Tapp ("neg_real", [t]) -> + Format.fprintf fmt "@[<hov 1>(-%a)@]" term t + | Fol.Tapp ("add_real", ts) -> + let xs = collect_assoc "add_real" [] ts in + pp_flow fmt "0.0" "+" term xs + | Fol.Tapp ("sub_real", [a;b]) -> + Format.fprintf fmt "@[<hov 1>(%a@,-%a)@]" term a term b + | Fol.Tapp ("mul_real", ts) -> + let xs = collect_assoc "mul_real" [] ts in + pp_flow fmt "1.0" "*" term xs + | Fol.Tapp ("div_real", [a;b]) -> + Format.fprintf fmt "@[<hov 1>(%a@,/%a)@]" term a term b + + | Fol.Tapp (id, t::ts) -> + Format.fprintf fmt "@[<hov 2>%s(@,%a" id term t ; + List.iter (fun t -> Format.fprintf fmt ",@,%a" term t) ts ; + Format.fprintf fmt ")@]" + | Fol.Tlet (x,v,t) -> + Format.fprintf fmt "(@[<hv 0>let %a@ = %a@ in %a@])" + pp_var x term v term t + | Fol.Taccess(a,k) -> Format.fprintf fmt "access(%a,@,%a)" term a term k + | Fol.Tupdate(a,k,b) -> + Format.fprintf fmt "@[<hv 2>update(%a,@,%a,@,%a)@]" + term a term k term b + + | Fol.Tgetfield (f,r) -> + Format.fprintf fmt "@[<hv 2>%s(%a)@]" (get_field f) term r + | Fol.Tsetfield (f,r,v) -> + Format.fprintf fmt "@[<hv 2>%s(%a,@,%a)@]" (set_field f) + term r term v + + +let fpretty_term term fmt t = + if Wp_parameters.verbose_atleast 2 + then fpp_term term fmt t + else match t with + | Fol.Tapp(("encode"|"decode"),[_;v]) -> + Format.fprintf fmt "{%a}" term v + | Fol.Taccess(a,k) -> Format.fprintf fmt "%a[%a]" term a term k + | Fol.Tupdate(a,k,b) -> + Format.fprintf fmt "@[<hv 2>%a[%a@,->%a]@]" + term a term k term b + + | t -> + fpp_term term fmt t + +let rec collect_or ps = function + | Fol.Por(a,b) -> collect_or (collect_or ps b) a + | p -> p :: ps + +let rec collect_and ps = function + | Fol.Pand(a,b) -> collect_and (collect_and ps b) a + | p -> p :: ps + +let rec collect_imply ps = function + | Fol.Pimplies(a,b) -> collect_and (collect_imply ps b) a + | p -> p :: ps + +let rec collect_iff ps = function + | Fol.Piff(a,b) -> collect_iff (collect_iff ps b) a + | p -> p :: ps + +type 'a pp = Format.formatter -> 'a -> unit +type pp_env = { + pp_type : Formula.tau pp ; + pp_term : Fol.term pp ; + pp_pred : Fol.pred pp ; +} + +(*TODO : ensures that label are different from keywords of the host language*) +let tag_named tag = "tag_"^tag + + +let pp_tau = Fol_decl.Tau.pp_tau + +let rec epp_pred_vbox env fmt p = + match p with + | Fol.Pand _ -> pp_block fmt "and" env.pp_pred (collect_and [] p) + | Fol.Por _ -> pp_block fmt "or" env.pp_pred (collect_or [] p) + | Fol.Pimplies _ -> + pp_block_implies fmt "->" env.pp_pred (collect_imply [] p) + | Fol.Piff _ -> pp_block fmt "<->" env.pp_pred (collect_iff [] p) + | Fol.Pforall(x,p) -> + Format.fprintf fmt "forall %a:%a.@\n" pp_var x env.pp_type (Fol.Var.var_type x) ; + epp_pred_vbox env fmt p + | Fol.Pexists(x,p) -> + Format.fprintf fmt "exists %a:%a.@\n" pp_var x env.pp_type (Fol.Var.var_type x) ; + epp_pred_vbox env fmt p + | Fol.Plet(x,t,p) -> + Format.fprintf fmt "@[<hov 2>let %a =@ %a@ in@]@\n" pp_var x env.pp_term t ; + epp_pred_vbox env fmt p + | Fol.Pif(t,p,q) -> + Format.fprintf fmt "@[<hov 0>if @[<hov 2>%a@]@ then@]@\n %a@\nelse@\n %a" + env.pp_term t env.pp_pred p env.pp_pred q + | (Fol.Ptrue | Fol.Pfalse | Fol.Papp _ | Fol.Pnot _ | Fol.Pnamed _) -> + env.pp_pred fmt p + +let rec epp_pred_atom env fmt p = + match p with + | Fol.Pand _ | Fol.Por _ | Fol.Pimplies _ | Fol.Piff _ | Fol.Pif _ + | Fol.Pforall _ | Fol.Pexists _ | Fol.Plet _ -> + Format.fprintf fmt "@[<v 1>(%a)@]" (epp_pred_vbox env) p + | Fol.Pnot p -> + Format.fprintf fmt "@[<hov 2>(not@ %a)@]" (epp_pred_atom env) p + | Fol.Ptrue -> Format.pp_print_string fmt "true" + | Fol.Pfalse -> Format.pp_print_string fmt "false" + | Fol.Papp(id,[]) -> Format.pp_print_string fmt id + | Fol.Papp (("eq" | "eq_int" | "eq_real"), [t1; t2]) -> + Format.fprintf fmt "@[<hov 1>(%a@ =@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp (("neq" | "neq_int"| "neq_real"), [t1; t2]) -> + Format.fprintf fmt "@[<hov 1>(%a@ <>@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp (("lt_int"| "lt_real"), [t1; t2]) -> + Format.fprintf fmt "@[<hov 1>(%a@ <@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp (("le_int"| "le_real"), [t1; t2]) -> + Format.fprintf fmt "@[<hov 1>(%a@ <=@ %a)@]" env.pp_term t1 env.pp_term t2 + | Fol.Papp(id,t::ts) -> + Format.fprintf fmt "@[<hov 2>%s(@,%a" id env.pp_term t ; + List.iter (fun t -> Format.fprintf fmt ",@ %a" env.pp_term t) ts ; + Format.fprintf fmt ")@]" + | Fol.Pnamed(tag,p) -> + Format.fprintf fmt "@[<hov 0>@[<hov 0>%s:%a@]" + (tag_named tag) (epp_pred_named env) p + +and epp_pred_named env fmt = function + | Fol.Pnamed(tag,p) -> + Format.fprintf fmt "@,%s:" (tag_named tag) ; + epp_pred_named env fmt p + | p -> + Format.fprintf fmt "@]@,%a" (epp_pred_atom env) p + +let fpp_pred predicate pp_tau pp_term fmt p = + match p with + | Fol.Ptrue -> Format.fprintf fmt "true" + | Fol.Pfalse -> Format.fprintf fmt "false" + | Fol.Papp (id, [])-> Format.fprintf fmt "%s" id + | Fol.Papp ("eq", [t1; t2]) -> Format.fprintf fmt "(%a =@ %a)" pp_term t1 pp_term t2 + | Fol.Papp ("neq", [t1; t2]) -> Format.fprintf fmt "(%a <>@ %a)" pp_term t1 pp_term t2 + | Fol.Papp (id, l) -> Format.fprintf fmt "@[%s(%a)@]" id (pp_list pp_term) l + | Fol.Pimplies (a, b) -> Format.fprintf fmt "(@[%a ->@ %a@])" predicate a predicate b + | Fol.Piff (a, b) -> Format.fprintf fmt "(@[%a <->@ %a@])" predicate a predicate b + | Fol.Pand (a, b) -> Format.fprintf fmt "(@[%a and@ %a@])" predicate a predicate b + | Fol.Por (a, b) -> Format.fprintf fmt "(@[%a or@ %a@])" predicate a predicate b + | Fol.Pnot a -> Format.fprintf fmt "(not %a)" predicate a + | Fol.Pif (a, b, c) -> + Format.fprintf fmt "(@[if %a then@ %a else@ %a@])" + pp_term a predicate b predicate c + | Fol.Pforall (v,p) -> + Format.fprintf fmt "@[<hov 0>(forall %a:%a.@ %a@])" + pp_var v pp_tau (Fol.Var.var_type v) predicate p + | Fol.Pexists (v,p) -> + Format.fprintf fmt "@[<hov 0>(exists %a:%a.@ %a@])" + pp_var v pp_tau (Fol.Var.var_type v) predicate p + | Fol.Plet (x,v,p) -> + Format.fprintf fmt "@[<hov 0>(let %a =@[<hov 2>@ %a@ in@]@ %a@])" + pp_var x pp_term v predicate p + | Fol.Pnamed (n, p) -> + Format.fprintf fmt "@[%s: %a@]" (tag_named n) predicate p + + +let export_get_set_field fmt pp_tau f = + let cn = f.Cil_types.fcomp.Cil_types.cname in + let fn = Fol_decl.Tau.tau_of_ctype_logic f.Cil_types.ftype in + let get_f = get_field f in + let set_f = set_field f in + Format.fprintf fmt "logic %s: %s -> %a @\n" get_f cn pp_tau fn; + Format.fprintf fmt "logic %s: %s , %a -> %s @\n" set_f cn pp_tau fn cn + + +let export_get_set_other fmt pp_tau f get_f g = + let set_g = set_field g in + Format.pp_print_newline fmt () ; + Format.fprintf fmt + "(* Definition of the commutativity of the get field %s over the set field %s*)@\n" + f.Cil_types.fname g.Cil_types.fname; + Format.pp_print_newline fmt () ; + Format.fprintf fmt "axiom GetSetOther_%s_%s@,:@\n" f.Cil_types.fname g.Cil_types.fname; + Format.fprintf fmt "forall r:%s.@,forall v:%a.@\n" + f.Cil_types.fcomp.Cil_types.cname + pp_tau (Fol_decl.Tau.tau_of_ctype_logic g.Cil_types.ftype); + Format.fprintf fmt "%s(%s(r,v))@,=@, %s(r)@\n" get_f set_g get_f; + Format.pp_print_newline fmt () + +let export_generated_axiomatics fmt pp_tau f = + let get_f = get_field f in + let set_f = set_field f in + Format.fprintf fmt + "(* Definition of the good properties of the field %s*)@\n" f.Cil_types.fname; + Format.pp_print_newline fmt () ; + Format.fprintf fmt "axiom GetSetSame_%s@,:@\n" f.Cil_types.fname; + Format.fprintf fmt "forall r:%s.@,forall v:%a.@\n" + f.Cil_types.fcomp.Cil_types.cname + pp_tau (Fol_decl.Tau.tau_of_ctype_logic f.Cil_types.ftype); + Format.fprintf fmt "%s(%s(r,v))@,=@, v@\n" get_f set_f ; + Format.pp_print_newline fmt () ; + if f.Cil_types.fcomp.Cil_types.cstruct then + (List.iter (fun g -> + if Cil_datatype.Fieldinfo.equal f g then () else + export_get_set_other fmt pp_tau f get_f g) + f.Cil_types.fcomp.Cil_types.cfields ;) + else (); + Format.pp_print_newline fmt () ; + Format.pp_print_newline fmt () + +let pp_section fmt title = + begin + Format.fprintf fmt "----------------------------------------@\n" ; + Format.fprintf fmt "--- %s@\n" title ; + Format.fprintf fmt "----------------------------------------@\n@\n" ; + end + +let pp_param pp_tau fmt x = + Format.fprintf fmt "%a:%a" pp_var x pp_tau (Fol.Var.var_type x) + +let fpp_item term predicate pp_tau fmt x = + function + | Formula.Cons k -> + Format.fprintf fmt "function %s () : int = %d@\n" x k + | Formula.Function ([], t) -> + Format.fprintf fmt "logic %s: %a@\n" x pp_tau t + | Formula.Function (tl, t) -> + Format.fprintf fmt "logic %s: @[<hov 0>%a -> %a@]@\n" x (pp_list pp_tau) tl pp_tau t + | Formula.Predicate([]) -> + Format.fprintf fmt "logic %s: prop@\n" x + | Formula.Predicate(tl) -> + Format.fprintf fmt "logic %s: @[<hov 0>%a -> prop@]@\n" x (pp_list pp_tau) tl + | Formula.FunctionDef (xs,tr,exp) -> + Format.fprintf fmt "@[<hv 2>function %s (%a) : %a =@ @[<hov 0>%a@]@]@\n" + x (pp_list (pp_param pp_tau)) xs pp_tau tr term exp + | Formula.PredicateDef(xs,p) -> + Format.fprintf fmt "@[<hv 2>predicate %s (%a) =@ @[<hov 0>%a@]@]@\n" + x (pp_list (pp_param pp_tau)) xs predicate p + | Formula.Axiom p -> + Format.fprintf fmt "@[<hv 2>axiom %s:@ %a@]@\n" x predicate p + | Formula.Type 0 -> + Format.fprintf fmt "type %s@\n" x + | Formula.Type 1 -> + Format.fprintf fmt "type 'a %s@\n" x + | Formula.Type n -> + Format.fprintf fmt "@[<hov 2>type ('a" ; + for k=2 to n do Format.fprintf fmt ",%c" (char_of_int (int_of_char 'a'+k-1)) done ; + Format.fprintf fmt ") %s@]@\n" x + | Formula.Trecord c -> + begin + Format.fprintf fmt "type %s@\n" c.Cil_types.cname ; + let l = c.Cil_types.cfields in + List.iter (fun f -> export_get_set_field fmt pp_tau f) l ; + List.iter (fun f -> export_generated_axiomatics fmt pp_tau f) l + end + +let fpp_header fmt d = + begin + d.Formula.d_title fmt ; + Format.pp_print_newline fmt () ; + ( match d.Formula.d_source with + | Some { Lexing.pos_fname=f ; pos_lnum=k } -> + Format.fprintf fmt "%s:%d: " f k + | None -> () ) ; + d.Formula.d_descr fmt ; + end + +let fpp_decl term predicate fmt d = + begin + fpp_header fmt d ; + Format.pp_print_newline fmt () ; + fpp_item term predicate pp_tau fmt d.Formula.d_name d.Formula.d_item ; + Format.pp_print_newline fmt () ; + end + +let fpp_goal predicate fmt x p = + Format.fprintf fmt "@[<hv 2>goal %s:@ %a@]@." x predicate p; + + + + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_split.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_split.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_split.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_split.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,216 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let dkey = "split" (* Debugging key *) + +(* ------------------------------------------------------------------------ *) +(* --- Splitter for FOL --- *) +(* ------------------------------------------------------------------------ *) + +open Fol + + +module Env = Map.Make(Fol.Var) + +type term = Fol.term +type pred = Fol.pred + +let is_zone = function + | Tapp(s,_) -> List.mem s + [ "zunion" ; "zempty" ; "zrange" ; + "zrange_of_addr" ; "zrange_of_addr_range" ; + "zs_empty" ; "zs_singleton" ; "zs_union" ; + ] + | _ -> false + +let rec e_unfold env = function + | Tvar x as t -> (try Env.find x env with Not_found -> t) + | Tlet(x,a,b) -> + let a0 = e_unfold env a in + if is_zone a0 + then e_unfold (Env.add x a0 env) b + else e_let x a0 (e_unfold (Env.remove x env) b) + | Tapp(f,xs) -> e_app f (List.map (e_unfold env) xs) + | Taccess(t,i) -> e_access (e_unfold env t) (e_unfold env i) + | Tupdate(t,i,v) -> e_update (e_unfold env t) ( e_unfold env i) (e_unfold env v) + | Tgetfield(f,r) -> e_getfield f (e_unfold env r) + | Tsetfield(f,r,v) -> e_setfield f (e_unfold env r) (e_unfold env v) + | Tif(c,a,b) -> e_if (e_unfold env c) (e_unfold env a) (e_unfold env b) + | Tconst _ as t -> t + +let rec p_unfold env = function + | Plet(x,t,p) -> + let t0 = e_unfold env t in + if is_zone t0 + then p_unfold (Env.add x t0 env) p + else p_let x t0 (p_unfold (Env.remove x env) p) + | Pnamed(a,p) -> Pnamed(a,p_unfold env p) + | (Ptrue | Pfalse) as p -> p + | Papp(f,es) -> p_app f (List.map (e_unfold env) es) + | Pimplies(p,q) -> p_implies (p_unfold env p) (p_unfold env q) + | Pif(c,p,q) -> p_if (e_unfold env c) (p_unfold env p) (p_unfold env q) + | Pand(p,q) -> p_and (p_unfold env p) (p_unfold env q) + | Por(p,q) -> p_or (p_unfold env p) (p_unfold env q) + | Piff(p,q) -> p_iff (p_unfold env p) (p_unfold env q) + | Pnot p -> p_not (p_unfold env p) + | Pforall(x,p) -> p_forall x (p_unfold env p) + | Pexists(x,p) -> p_exists x (p_unfold env p) + +(* ------------------------------------------------------------------------ *) +(* --- Case Split --- *) +(* ------------------------------------------------------------------------ *) + +module SplitZoneInclusion (M : + sig + val union : string (* symbol for union *) + val empty : string (* symbol for empty *) + val included : string (* symbol for inclusion *) + end) + = +struct + + let rec flatten xs = function + | Tapp( f , es ) when f = M.union -> List.fold_left flatten xs es + | Tapp( f , [] ) when f = M.empty -> xs + | t -> t::xs + + let rec zunion = function + | [z] -> z + | [] -> e_app M.empty [] + | z::zs -> e_app M.union [ z ; zunion zs ] + + let included a b = + let zas = flatten [] a in + let zbs = flatten [] b in + let zb = zunion zbs in + List.fold_left + (fun acc z -> + if Wp_parameters.Simpl.get () && List.exists (Fol.eq_terms z) zbs + then acc + else Bag.add (p_app M.included [z;zb]) acc) + Bag.empty zas + +end + +module StoreInclusion = SplitZoneInclusion + (struct + let union = "zunion" + let empty = "zempty" + let included = "included" + end) + +module RuntimeInclusion = SplitZoneInclusion + (struct + let union = "zs_union" + let empty = "zs_empty" + let included = "zs_incl" + end) + +(* Do not bound the depth when [max_depth]=0, + otherwise, the spliting is pruned and [max_split] bound may be not reached. *) +let dispatch max_depth max_split p = + let rec nb_splits = ref 1 + + and concat depth pol orig d1 b1 d2 b2 = + let rec incr_depth kid = + (* sometime, depth is not incremented *) + match orig, kid with + | _, Pnamed(_,p) -> incr_depth p + | Por _, Por _ -> depth + | Pand _, Pand _ -> depth + | _, _ -> depth + 1 + in + if (!nb_splits >= max_split) || ((depth >= max_depth) && (max_depth <> 0)) + then Bag.elt (if pol then orig else (p_not orig)) + else (incr nb_splits ; Bag.concat (d1 (incr_depth b1) b1) (d2 (incr_depth b2) b2)) + + and choose p bag = + let nb = !nb_splits + (Bag.length bag) - 1 + in if nb >= max_split + then Bag.elt p + else (nb_splits := nb ; bag) + + and concat_if depth pol orig d c p q = + if (!nb_splits >= max_split) || ((depth >= max_depth) && (max_depth <> 0)) + then Bag.elt (if pol then orig else (p_not orig)) + else (incr nb_splits ; + Bag.concat + (Bag.map (fun p -> p_implies (p_eq c e_true) p) (d (depth+1) p)) + (Bag.map (fun q -> p_implies (p_eq c e_false) q) (d (depth+1) q))) + + and dispatch_neg depth = function + | Pfalse -> Bag.empty + | Pnot p -> dispatch_pos depth p + | (Ptrue|Pand _|Piff _|Papp _ |Pforall _) as p -> Bag.elt (p_not p) + | Por(p,q) as full -> concat depth false full dispatch_neg p dispatch_neg q + | Pimplies(h,p)as full -> concat depth false full dispatch_pos h dispatch_neg p + | Pif(c,p,q) as full -> concat_if depth false full dispatch_neg c p q + | Pnamed(a,p) -> Bag.map (fun p -> Pnamed(a,p)) (dispatch_neg depth p) + | Pexists(x,p) -> Bag.map (p_forall x) (dispatch_neg depth p) + | Plet(x,t,p) -> Bag.map (p_let x t) (dispatch_neg depth p) + + and dispatch_pos depth = function + | Ptrue -> Bag.empty + | Pnot p -> dispatch_neg depth p + | Papp( "included" , [a;b]) as p -> choose p (StoreInclusion.included a b) + | Papp( "zs_incl" , [a;b]) as p -> choose p (RuntimeInclusion.included a b) + + | (Pfalse|Por _|Piff _|Papp _ |Pexists _) as p -> Bag.elt p + | Pimplies(h,p) -> Bag.map (fun p -> p_implies h p) (dispatch_pos depth p) + | Pand(p,q) as full -> concat depth true full dispatch_pos p dispatch_pos q + | Pif(c,p,q) as full -> concat_if depth true full dispatch_pos c p q + | Pnamed(a,p) -> Bag.map (fun p -> Pnamed(a,p)) (dispatch_pos depth p) + | Pforall(x,p) -> Bag.map (p_forall x) (dispatch_pos depth p) + | Plet(x,t,p) -> Bag.map (p_let x t) (dispatch_pos depth p) + in + + dispatch_pos 1 p + +(* ------------------------------------------------------------------------ *) +(* --- Splitter Interface --- *) +(* ------------------------------------------------------------------------ *) + +let simplify = Fol_let.compile + +(* [split] may deliver stronger sub-predicates *) +let split meth p = + let nb = Wp_parameters.SplitDim.get() + in let max_depth = if nb < 0 then 0 (* <- do not prune the search *) else (2 + nb) + and max_split = (* 2**|nb| *) + try + Big_int.int_of_big_int (Big_int.power_int_positive_int 2 (if nb < 0 then -nb else nb)) + with (Invalid_argument _ | Failure _) -> + Wp_parameters.debug ~dkey "Invalid value for option %s@." Wp_parameters.SplitDim.name; + 0 (* <- do not split *) + in + let bag = + match meth with + | Mcfg.EffectAssigns -> dispatch max_depth max_split (p_unfold Env.empty p) + | _ -> dispatch max_depth max_split p + in let nb = Bag.length bag + (* TODO: + if the bag is not full and [max_depth]<>0 + then it could be possible to iter once more + on the elements of the bag with [max_depth]=0 *) + in if nb > 1 then + Wp_parameters.debug ~dkey "Predicate splited into %d parts@." nb; + bag diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_split.mli frama-c-20111001+nitrogen+dfsg/src/wp/fol_split.mli --- frama-c-20110201+carbon+dfsg/src/wp/fol_split.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_split.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(** Splitting Goals *) +(* ------------------------------------------------------------------------ *) + +(** {2 Zone-unions Flattening} + The [unfolding] methods below only applies to variables that holds + a union of [zone] values. Other variables are left letified. *) + +module Env : Map.S with type key = Fol.Var.t + +val e_unfold : Fol.term Env.t -> Fol.term -> Fol.term +val p_unfold : Fol.term Env.t -> Fol.pred -> Fol.pred + +(** {2 Splitter Interface} *) + +type pred = Fol.pred +val simplify : pred -> pred +val split : Mcfg.assigns_method -> pred -> pred Bag.t + (** First, unfold zones when method is effect-assigns. + Then applies [dispatch]. + Note: [split] may deliver stronger sub-predicates *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/fol_why.ml frama-c-20111001+nitrogen+dfsg/src/wp/fol_why.ml --- frama-c-20110201+carbon+dfsg/src/wp/fol_why.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/fol_why.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,88 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- WHY Export --- *) +(* -------------------------------------------------------------------------- *) + + +module EWhy (L:sig val tau_of_ctype_logic : Cil_types.typ -> Formula.tau end)= +struct + +type pred = Fol.pred +type decl = Fol.decl + +let rec export_tau fmt = function + | Formula.Integer -> Format.pp_print_string fmt "int" + | Formula.Real -> Format.pp_print_string fmt "real" + | Formula.Boolean -> Format.pp_print_string fmt "bool" + | Formula.Pointer t -> export_tau fmt t + | Formula.Record c -> Format.fprintf fmt "%s" c.Cil_types.cname + | Formula.Array arr -> + let t = L.tau_of_ctype_logic arr.Ctypes.arr_element in + Format.fprintf fmt "%a farray" export_tau t + | Formula.Set te -> + Format.fprintf fmt "%a set" export_tau te + | Formula.ADT(s,[]) -> Format.pp_print_string fmt s + | Formula.ADT(s,[t]) -> Format.fprintf fmt "%a %s" export_tau t s + | Formula.ADT(s,t::ts) -> + Format.fprintf fmt "@[(%a" export_tau t ; + List.iter (fun t -> Format.fprintf fmt ",@,%a" export_tau t) ts ; + Format.fprintf fmt ") %s@]" s + +let rec export_term fmt t = Fol_pretty.fpp_term export_term fmt t + + +let rec pp_pred_atom fmt p = + Fol_pretty.epp_pred_atom { + Fol_pretty.pp_type = export_tau ; + Fol_pretty.pp_term = export_term ; + Fol_pretty.pp_pred = pp_pred_atom; + } fmt p + +let export_pred fmt p = + Fol_pretty.epp_pred_vbox { + Fol_pretty.pp_type = export_tau ; + Fol_pretty.pp_term = export_term ; + Fol_pretty.pp_pred = pp_pred_atom ; + } fmt p + + +let export_section fmt title = + begin + Format.fprintf fmt "(*----------------------------------------*)@\n" ; + Format.fprintf fmt "(*--- %-32s ---*)@\n" title ; + Format.fprintf fmt "(*----------------------------------------*)@\n" ; + end + +let export_item fmt name item = + Fol_pretty.fpp_item export_term export_pred export_tau fmt name item + +let export_decl fmt d = + Pretty_utils.pp_trail Fol_pretty.fpp_header fmt d ; + Format.pp_print_newline fmt () ; + export_item fmt d.Formula.d_name d.Formula.d_item + +let export_goal fmt x g = + Fol_pretty.fpp_goal export_pred fmt x g; + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/formula.mli frama-c-20111001+nitrogen+dfsg/src/wp/formula.mli --- frama-c-20110201+carbon+dfsg/src/wp/formula.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/formula.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,519 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + +open Cil_types +open Ctypes + + +(* -------------------------------------------------------------------------- *) +(** Logic Formulae *) +(* -------------------------------------------------------------------------- *) + +(** {2 Logic types }*) + +type tau = + | Integer + | Real + | Boolean + | Pointer of tau + | Set of tau + | Record of Cil_types.compinfo + | Array of Ctypes.arrayinfo + | ADT of string * (tau list) + +type kind = + | Model of tau + | Acsl of tau * Cil_types.logic_type + + + +(** {2 Pure types} *) + +type m_boolean (** The set of two elements [{true,false}]. *) +type m_integer (** Natural signed integers ({b Z}). *) +type m_real (** Real numbers ({b R}). *) +type m_abstract (** Abstract Data Types (user-defined WHY-types). *) + +type m_name (** type name [data_lib.why] *) + +type m_pointer (** type pointer [data_lib.why] *) +type m_array (** type 'a farray [array.why] *) +type m_record (** type record [data_lib.why] *) +type m_urecord (** type urecord [data_lib.why] *) +type m_set (** type 'a set [data_lib.why] *) +type m_zone (** type of elementary regions *) + + + +(** {2 Arithmetics Operators} *) + +type int_op = Iadd | Isub | Imul | Idiv | Imod +type real_op = Radd | Rsub | Rmul | Rdiv +type cmp_op = Ceq | Cneq | Clt | Cleq + +(** {2 Declarations} *) + +type section = + | S_Type (** LOGIC type definition *) + | S_Cons (** LOGIC type constructor *) + | S_Logic_Sig (** Signature of Functions and Predicates *) + | S_Logic_Def (** Definitions for Functions and Predicates *) + | S_Logic_Prop (** Axioms on Functions and Predicates *) + | S_Model_Sig (** Signature of Functions and Predicates *) + | S_Model_Def (** Definitions for Functions and Predicates *) + | S_Model_Prop (** Axioms on Functions and Predicates *) + | S_User_Sig (** Signature of User-defined function and predicates *) + | S_User_Prop (** Axioms on User-defined function and predicates *) + +type ('x,'t,'p) item = + | Type of int + | Cons of int + | Function of tau list * tau + | Predicate of tau list + | FunctionDef of 'x list * tau * 't + | PredicateDef of 'x list * 'p + | Axiom of 'p + | Trecord of compinfo + +type ('x,'t,'p) declaration = + { + d_section : section ; + d_name : string ; + d_title : (Format.formatter -> unit) ; + d_descr : (Format.formatter -> unit) ; + d_source : Lexing.position option ; + d_item : ('x,'t,'p) item ; + } + +(** {2 Signature for logic formulae} *) + +module type S = +sig + + type var + type 'a term + type pred + + + type abstract = m_abstract term + type integer = m_integer term + type real = m_real term + type boolean = m_boolean term + type record = m_record term + type urecord = m_array term + type array = m_array term + type set = m_set term + type name = m_integer term + + type decl = (var,abstract,pred) declaration + + val e_int : int -> integer + val e_call : string -> abstract list -> abstract + val p_call : string -> abstract list -> pred + val wrap : 'a term -> abstract + val unwrap : abstract -> 'a term + + (** {2 Global Declarations} *) + + val clear : unit -> unit + val on_clear : (unit -> unit) -> unit + val fresh_name : string -> string -> string + val add_declaration : decl -> unit + val has_declaration : string -> bool + val iter_all : (string -> unit) -> (decl -> unit) -> unit + + (** {2 Functors and Types for Declaration} *) + + module type Identifiable = + sig + type t + module H : Hashtbl.S + val index : t -> H.key + val prefix : string + val basename : t -> string + val location : t -> Lexing.position option + val pp_title : Format.formatter -> t -> unit + val pp_descr : Format.formatter -> t -> unit + end + + module type Registry = + sig + type t + val define : t -> unit + val get_definition : t -> decl + val on_definition : (t -> decl -> unit) -> unit + end + + module type Declarator = + sig + include Identifiable + val clear : unit -> unit + val section : section + val declare : t -> string -> (var,abstract,pred) item + end + + module DRegister + (D : Declarator) : + (Registry with type t = D.t) + + (** {2 Build-int Identifiables and Registry} *) + + module Varinfo : Identifiable with type t = varinfo + module Varaddr : Identifiable with type t = varinfo + module Fieldinfo : Identifiable with type t = fieldinfo + module Compinfo : Identifiable with type t = compinfo + module Arrayinfo : Identifiable with type t = arrayinfo + module Logicvar : Identifiable with type t = logic_var + module LTypeinfo : Identifiable with type t = logic_type + module Cobject : Identifiable with type t = Ctypes.c_object + module ArrayDim : Identifiable with type t = Ctypes.c_object * int + + val adt_decl : Cil_types.logic_type_info -> string + + + (**Be careful, this one is only used for debuging message! + Do not use for extraction *) + val pp_tau : Format.formatter -> tau -> unit + + (** {2 Terms} *) + + val e_true : boolean + val e_false : boolean + + val e_float : float -> real + val e_icst : string -> integer + val e_rcst : string -> real + val e_int64 : int64 -> integer + + (** {2 Arithmetics} *) + + val e_ineg : integer -> integer + val e_rneg : real -> real + val e_iop : int_op -> integer -> integer -> integer + val e_rop : real_op -> real -> real -> real + val e_icmp : cmp_op -> integer -> integer -> boolean + val e_rcmp : cmp_op -> real -> real -> boolean + val p_icmp : cmp_op -> integer -> integer -> pred + val p_rcmp : cmp_op -> real -> real -> pred + + val e_bnot : integer -> integer + val e_band : integer -> integer -> integer + val e_bor : integer -> integer -> integer + val e_bxor : integer -> integer -> integer + val e_lshift : integer -> integer -> integer + val e_rshift : integer -> integer -> integer + + val integer_of_real : real -> integer + val real_of_integer : integer -> real + + (** {2 Booleans} *) + + val e_bool : boolean -> integer + val e_not : boolean -> boolean + val e_and : boolean -> boolean -> boolean + val e_or : boolean -> boolean -> boolean + + (** {2 Conditional} *) + + val e_cond : boolean -> 'a term -> 'a term -> 'a term + val p_cond : boolean -> pred -> pred -> pred + + (** {2 records field} *) + + val e_getfield: Cil_types.fieldinfo -> record -> abstract + val e_setfield: Cil_types.fieldinfo -> record -> abstract -> record + + + val e_access : array -> integer -> abstract + val e_update : array -> integer -> abstract -> array + + (** {2 Predicates} *) + + val p_true : pred + val p_false : pred + val p_bool : boolean -> pred + val p_and : pred -> pred -> pred + val p_or : pred -> pred -> pred + val p_xor : pred -> pred -> pred + val p_not : pred -> pred + val p_implies : pred -> pred -> pred + val p_iff : pred ->pred -> pred + val p_eq : 'a term -> 'a term -> pred + val p_neq : 'a term -> 'a term -> pred + val p_conj : pred list -> pred + val p_disj : pred list -> pred + val p_named : string -> pred -> pred + + (** {2 Utilities} *) + + val is_true : pred -> bool + val is_false : pred -> bool + val huge_term : int -> 'a term -> bool + val huge_pred : int -> pred -> bool + + (** {2 Variables} + + Pools are used to generate fresh free variables. Do not mix + non-closed terms from different pools. + *) + + type pool + + val pool : unit -> pool + val p_fresh : pool -> string -> kind -> var + val p_freshen : pool -> var -> var + + val var : var -> 'a term + val eq_var : var -> var -> bool + val name_of_var : var -> string + val basename_of_var : var -> string + val tau_of_var : var -> tau + val kind_of_var : var -> kind + + val term_has_var : var list -> 'a term -> bool (* any of vars *) + val pred_has_var : var list -> pred -> bool (* any of vars *) + + val term_calls : string -> 'a term -> bool + val pred_calls : string -> pred -> bool + + val term_closed : 'a term -> bool + val pred_closed : pred -> bool + val freevars : pred -> var list + + val p_forall : var list -> pred -> pred + val p_exists : var list -> pred -> pred + val p_subst : (var -> var option) -> var -> 'a term -> pred -> pred + val e_subst : (var -> var option) -> var -> 'a term -> 'b term -> 'b term + + (** Requires domain to be disjoint from co-domain *) + val e_rename : (var * var) list -> 'a term -> 'a term + + (** Returns true when the two terms are syntactically equals *) + val equal_terms : 'a term -> 'a term -> bool + + (** {3 Alpha conversion} *) + + (** Maping from old var to new var *) + type alpha + (** Empty mapping *) + val empty_alpha : alpha + val fold_alpha : (var -> var -> 'a -> 'a) -> alpha -> 'a -> 'a + + (** [alpha', p' = p_more_alpha_cv alpha p] build p' from p by renaming + * all the variable v into v' according to the mapping alpha. + * Add new mappings for the variables that are not already mapped. *) + val p_more_alpha_cv : alpha -> pred -> alpha * pred + + (** easier to use when doing a simple alpha conversion. + * @return the new predicate and the newly created variables. *) + val p_alpha_cv : pred -> var list * pred + + + (** {2 Pretty printers} *) + + val pp_var : Format.formatter -> var -> unit + val pp_section : Format.formatter -> string -> unit + val pp_term : Format.formatter -> 'a term -> unit + val pp_pred : Format.formatter -> pred -> unit + val pp_decl : Format.formatter -> decl -> unit + val pp_goal : Format.formatter -> string -> pred -> unit + val pp_vkind : Format.formatter -> kind -> unit + + + (** {2 FOL Helpers} *) + + val e_app0 : string -> 'a term + val e_app1 : string -> 'a term -> 'b term + val e_app2 : string -> 'a term -> 'b term -> 'c term + val e_app3 : string -> 'a term -> 'b term -> 'c term -> 'd term + val e_app4 : + string -> 'a term -> 'b term -> 'c term -> 'd term -> 'e term + val e_app5 : + string -> 'a term -> 'b term -> 'c term -> 'd term -> 'e term -> + 'f term + + val p_app0 : string -> pred + val p_app1 : string -> 'a term -> pred + val p_app2 : string -> 'a term -> 'b term -> pred + val p_app3 : string -> 'a term -> 'b term -> 'c term -> pred + val p_app4 : string -> + 'a term -> 'b term -> 'c term -> 'd term -> pred + val p_app5 : string -> + 'a term -> 'b term -> 'c term -> 'd term -> 'e term -> pred + + val dummy : unit -> pred + + val i_zero : integer + val r_zero : real + val i_one : integer + val i_add : integer -> integer -> integer + val i_mult : integer -> integer -> integer + val i_sub : integer -> integer -> integer + + + (** {2 Integer Logic Cast} *) + + val guard : Ctypes.c_int -> integer -> pred + val modulo : Ctypes.c_int -> integer -> integer + val i_convert: Ctypes.c_int -> Ctypes.c_int -> integer -> integer + + (**{2 Fol data } *) + type interval = { + inf : integer option ; + sup : integer option ; + } + + type 'a assigned = + | Aloc of c_object * 'a + | Arange of c_object * 'a * interval + + type havoc = + | Fresh of var + | Update of var * ((var * var) list -> abstract) + + val pp_interval : Format.formatter -> interval -> unit + + (** {2 Sub-arrays} *) + + val set_range_index : array -> interval -> array + + (** {2 Set and Range as first Class Value} *) + + val empty : set + (**[empty()] returns the polymorphic empty set. *) + + val singleton : abstract -> set + (** [singleton a] returns the singleton set containning [a]. *) + + val union : set -> set -> set + (** [union s0 s1] returns the union set of [s0] and [s1]. *) + + val unions : set list -> set + + val inter : set -> set -> set + (**[inter s0 s1] returns the intersection set of [s0] and [s1]. *) + + val remove : set -> set -> set + (** [remove s0 s1] returns a set [s'] such as \{b in s' | b in s0 + and !(b in s1) \}.*) + + val set_of_list : abstract list -> set + + val add_set : set -> set -> set + + val mult_set : set -> set -> set + + val neg_set : set -> set + + val interval : interval -> set + (** [range l h] returns the integer set [s] such as \{ i in s | l <= + i <= h \}. *) + (** {2 Formats} *) + + (** {2 Record as First Class Value}*) + + val acc_field : + record -> Cil_types.fieldinfo -> abstract + (** Takes a record term of type (tau_of F.fcomp) and + returns the term of type (tau_of F) for its field 'F' *) + + val upd_field : + record -> Cil_types.fieldinfo -> abstract -> record + (** Takes a record term of type (tau_of F.fcomp) and + a new term of type (tau_of F) for its field 'F' + and return the updated record. *) + + (** {2 Array as first Class Value} *) + + val acc_index : array -> integer -> abstract + (** Takes term of type ['a farray] and returns the ['a] at index [i]. *) + + val upd_index : array -> integer -> abstract -> array + + + + (** {2 Buitin Indexd Declaration } *) + module type Indexed = + sig + include Registry + val get_ind : t -> integer + val has_ind : t -> pred -> bool + end + + module Dindex (I : Identifiable): + sig include Indexed with type t = I.t end + + module Findex : Indexed with type t = fieldinfo + module Xindex : Indexed with type t = varinfo + module Aindex : Indexed with type t = varinfo + module Tindex : Indexed with type t = compinfo + module LTindex : Indexed with type t = logic_type + +end + + +module type Logic = +sig + module F: S + + (** {2 Constrained Terms Construction} *) + type context + type bindings + + val closed : bindings + val close : bindings -> F.pred -> F.pred + + val push : string -> F.pool -> bindings -> context + val pop : string -> context -> bindings + val kill: string -> context -> unit + val flush : string -> context -> F.pred -> F.pred (* pop and close *) + + val term_such_that : tau -> ('a F.term -> F.pred) -> 'a F.term + + val forall : F.var list -> F.pred -> F.pred + val exists : F.var list -> F.pred -> F.pred + val subst : F.var -> 'a F.term -> F.pred -> F.pred + val fresh : string -> kind -> F.var + val alpha : F.var -> F.var option + val pool : unit -> F.pool + val vkind_of_var : F.var -> kind + val has_context_vars : F.var list -> F.pred -> bool + val has_type : F.abstract -> logic_type -> F.pred + val is_comp : Cil_types.compinfo -> F.abstract -> F.pred + val is_array: Ctypes.arrayinfo -> F.abstract -> F.pred + + (** {2 Generalized substitutions} *) + + + val apply : (F.var * F.var) list -> 'a F.term -> 'a F.term + + val havoc_static : F.havoc list -> F.pred -> F.pred + val havoc_inductive : F.havoc list -> F.pred -> F.pred + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/funvar_mem.ml frama-c-20111001+nitrogen+dfsg/src/wp/funvar_mem.ml --- frama-c-20110201+carbon+dfsg/src/wp/funvar_mem.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/funvar_mem.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,1000 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + + +(* -------------------------------------------------------------------------- *) +(* --- Functional Variable Memory Model Functor --- *) +(* -------------------------------------------------------------------------- *) + +module WpLog = Wp_parameters +open Cil_types +open Cil_datatype +open Formula +open Ctypes +open Clabels + + +let debug = WpLog.debug ~dkey:"funvar" +let oracle = WpLog.debug ~dkey:"var_kind" + +module type Criteria = +sig + val isHoare : bool +end + + +module Create + (Crit:Criteria) + (M:Mwp.S) + = +struct + (* ------------------------------------------------------------------------ *) + (* --- Helper to move --- *) + (* ------------------------------------------------------------------------ *) + + (* [make_array ty] builts the cil type of an array of element of type [ty]*) + let make_array ty = + debug "[make_array] %a" !Ast_printer.d_type ty; + TArray(ty,None,{scache=Cil_types.Not_Computed},[]) + + (*[array_of typ] transforms a pointer type [typ] into an cil array type, + recursivly*) + let rec array_of typ = + debug "[object_array_of] %a" !Ast_printer.d_type typ; + match Cil.unrollType typ with + | TPtr(typ,_) -> + begin + match Cil.unrollType typ with + | TVoid _ -> make_array (TInt (IChar,[])) + | t -> make_array (array_of t) + end + | _ -> typ + + +(* [pointed_of_arity n typ] makes the cil type : [*^n typ]*) + let rec pointed_of_arity n typ = + debug "[pointed_of_arity] %a,%d" !Ast_printer.d_type typ n ; + if n > 0 + then pointed_of_arity (pred n) (Cil.typeOf_pointed typ) + else typ + + +(*[brackets_and_stars_typ typ], first computes the stars number of typ [n] and + the inner type [t] if typ = *^n t returns (n,t). Secondly, + computes the number of brackets in [t] [m]. + Finally returns the number of stars and the number of brackets [(n,m)].*) + let brackets_and_stars_typ typ = + let rec stars_and_elt typ = + match Cil.unrollType typ with + | TPtr (typ,_) -> + let (n,t) = stars_and_elt (Cil.unrollType typ) in + (n+1),t + | TInt(_,_) | TFloat(_,_) | TFun _ | TEnum (_,_) | TComp (_,_,_) + | TArray (_,_,_,_) + | TBuiltin_va_list _ | TVoid _ | TNamed _ as t-> (0,t) + in + let (n,t) = stars_and_elt typ in (n,Variables_analysis.brackets_typ t) + +(* the same in logic type*) + let brackets_and_stars_lv_typ = function + | Ctype t -> brackets_and_stars_typ t | _ -> 0,0 + + + +(* Path *) + module Lookup = + struct + + module F = M.F + + (* In a first intention, a path can be view as a pair + of a root and a list of offset use to describe an l-value.*) + + (* offset of path*) + type poffset = + | Ofield of fieldinfo (* a field*) + | Oindex of F.integer * Ctypes.c_object (*an index and its type*) + + (*root of a path*) + type root = + | Cvar of varinfo (*a C variable *) + | Lvar of logic_var (* a purely logic variable (ie.lv_origin = None)*) + + (* Definition of a path*) + + (* NB : the field p_cvar only occurs if the root is a purely logic by + reference parameter when its inner model location it is required + for the translation of the predicate or function body. + Then and additional formal parameters has to been created. + This creation is global to a frame of the translation, then the + fol-variable has to been created in translate_prop and carry + to the memory model to be used in memory made formula. + *) + type path = { + p_root : root ; (* root *) + p_mem : M.mem ; (* in model memory model *) + p_arity : int ; (* arity such as define in by reference arity; + 0 otherwise*) + p_off : poffset list ; (* the list of offset to form the current + l-value*) + p_type : Ctypes.c_object option; + (* the type of the entire l-value represented + by this path*) + p_cvar : F.var option ; (* the fol-variable represented the address + of the root.*) + } + + (* Some smart constructors and helper to manage root and path. *) + + (* Pretty-printers *) + let pp_root fmt = function + | Cvar x -> !Ast_printer.d_var fmt x + | Lvar lv -> !Ast_printer.d_logic_var fmt lv + + let pp_path fmt p = + Format.fprintf fmt "PATH:%a of %d" + pp_root p.p_root (List.length p.p_off) + + (* [object_of_root r] returns the c_object of a root [r].*) + let object_of_root = function + Cvar x -> Some (object_of x.vtype) + | Lvar lv -> + begin + match lv.lv_type with + | Ctype t -> Some (object_of t) + | _ -> None + end + + (* [object_array_of_root r] transforms the type of the root[r] + into an array type,c_object, if it was a pointer type. *) + let object_array_of_root = function + Cvar x -> Some (object_of (array_of x.vtype)) + | Lvar lv-> + begin + match lv.lv_type with + | Ctype t -> Some (object_of (array_of t)) + | _ -> None + end + + (*[object_of_n_pointed n typ] makes the c_object type of a [n]-ary pointer + on inner type [typ] : [*^n typ]*) + let rec object_of_n_pointed n typ = + if n=0 then typ else + match typ with + | C_pointer typ -> object_of_n_pointed (pred n) (object_of typ) + | t -> WpLog.fatal + "[object_of_n_pointed] calls with mismatched arguments :%d and %a" + n pp_object t + + + let object_of_pointed_opt = function + | None -> None + | Some ty -> Some (Ctypes.object_of_pointed ty) + + let object_of_n_pointed_opt n = function + | None -> None + | Some ty -> Some (object_of_n_pointed n ty) + + + + + (* [pointed_of_path p] makes the deferenced path of [p].*) + let pointed_of_path p = + debug "[pointed_of_path] %a" pp_path p; + { p with p_type = object_of_pointed_opt p.p_type } + + (* [pointed_of_n_path n p] makes the [n] time deferenced path of [p].*) + let pointed_of_n_path n p = + debug "[pointed_of_n_path] %d %a" n pp_path p; + { p with p_type = object_of_n_pointed_opt n p.p_type } + + (* [sizeof_poffset off] returns de C sizeof of an offset.*) + let sizeof_poffset = function + | Ofield fd -> F.e_int + (Int64.to_int (Ctypes.sizeof_object (object_of fd.ftype))) + | Oindex (i,o) -> + let typeof_obj = F.e_int64 (Ctypes.sizeof_object o) + in + F.e_iop Formula.Imul i typeof_obj + + (* [sizeof_path offs] returns the C sizeof of an offsets list.*) + let sizeof_path offs = + List.fold_left + (fun acc i -> F.e_iop Iadd acc (sizeof_poffset i)) F.i_zero offs + + (* [access_poffset p off] makes the l-value from the term [p] and + the offset [off] : [p.f] or [p[i]] . *) + let access_poffset p = function + | Ofield f -> F.acc_field (F.unwrap p) f + | Oindex (i,_) -> F.acc_index (F.unwrap p) i + + (* [access t offs] makes the l-value from [t] with the offset list [offs]*) + let access t offs = List.fold_left access_poffset t offs + + (* [mcvar m r opt_cv] according to the root [r] calls the approriate + function of the inner memory model to translate the root [r] in + the memory state [m]. + If [r] is a C variable then [cvar] else [lvar ]*) + let mcvar m r opt_cv= + debug "[mcvar] of %a" pp_root r; + match r with + | Cvar x -> + debug "[mcvar] case of mem"; M.cvar m x + | Lvar lv -> + debug "[mcvar] case of logic %a" !Ast_printer.d_logic_var lv; + let ty = + match lv.lv_type with + | Ctype ty -> ty + | ty -> Wp_parameters.fatal + "[mcvar] c type of a pure logic type %a" + !Ast_printer.d_logic_type ty + in + let obj = Ctypes.object_of ty in + match opt_cv with + | None -> (* can't happen*) + debug "[mcvar] case of none associated cvar"; + let tau = Formula.Pointer (M.tau_of_loc) in + debug "[mcvar] called fresh"; + let x = M.L.fresh lv.lv_name (Formula.Model tau) in + debug "[mcvar] binds %a to %a" + !Ast_printer.d_logic_var lv F.pp_var x ; + M.loc_of_term obj (F.var x) + | Some cx -> + debug "[mcvar] case of associated c varaible :%a" F.pp_var cx ; + M.loc_of_term obj (F.var cx) + + (* [mloc_of_path p] computes the location of the inner memory model + from the path [p].*) + let mloc_of_path p = + debug "[mloc_of_path] %a" pp_path p; + List.fold_left + (fun loc offset -> + match offset with + | Ofield f -> M.field loc f + | Oindex(k,te) -> M.index loc te k + ) (mcvar p.p_mem p.p_root p.p_cvar) p.p_off + + end + + module Model = + struct + + open Lookup + + module F = M.F + module A = M.A + module R = M.R + + type loc = + Path of path (*Functional Variable*) + | PRef of path (*Pointer Reference effective Argument*) + | ARef of path (*Array Reference effective Argument*) + | PRpar of path * int (*Pointer by Reference Formal path and arity*) + | ARpar of path * int (*Array by Reference Formal path and arity*) + | Mloc of M.loc (* Memory Location *) + + (* Pretty-printers *) + let pp_ref r fmt p opt_arity= + match opt_arity with + | None -> + Format.fprintf fmt "%s :%a of %d" r pp_root p.p_root + (List.length p.p_off) + | Some ari -> + Format.fprintf fmt "%s :(%a,%d) of %d" + r pp_root p.p_root ari (List.length p.p_off) + + let pp_loc fmt = function + | Mloc l -> M.pp_loc fmt l + | Path p -> pp_path fmt p + | PRef p -> pp_ref "Ptr REF" fmt p None + | PRpar (p,n) -> pp_ref "Ptr REF PARAM" fmt p (Some n) + | ARef p -> pp_ref "Array REF" fmt p None + | ARpar (p,n) -> pp_ref "Array REF PARAM" fmt p (Some n) + + let cast_loc_to_int ty l ty2 = + match l with + | Mloc l -> M.cast_loc_to_int ty l ty2 + | Path p | PRef p | PRpar (p,_) | ARef p | ARpar (p,_) -> + M.cast_loc_to_int ty (Lookup.mloc_of_path p) ty2 + + + let cast_int_to_loc ty i ty2 = Mloc (M.cast_int_to_loc ty i ty2) + + (*[mloc_of_loc l] returns the location of the inner memory model + corresponding to the location [l].*) + let mloc_of_loc = function + | Path p | PRef p | PRpar (p,_) | ARef p | ARpar (p,_) -> + Lookup.mloc_of_path p + | Mloc loc -> + debug "[mloc_of_loc] already a loc %a" M.pp_loc loc ; loc + + + let loc_of_term o t = Mloc (M.loc_of_term o t) + let term_of_loc l = M.term_of_loc (mloc_of_loc l) + + let null = Mloc M.null + let is_null l = M.is_null (mloc_of_loc l) + + + let root_equal a b = + match a,b with + | Cvar x, Cvar y -> Varinfo.equal x y + | Lvar l, Lvar p -> Logic_var.equal l p + | _,_ -> false + + let op_loc mop pop l1 l2= + match l1,l2 with + | Mloc l1 , Mloc l2 -> mop l1 l2 + | Path xp, Path yq | PRef xp, PRef yq | ARef xp,ARef yq + when root_equal xp.p_root yq.p_root -> + pop (sizeof_path xp.p_off) (sizeof_path yq.p_off) + | ARpar (xp,xn),ARpar (yq,ym) + | PRpar (xp,xn), PRpar(yq,ym) + when root_equal xp.p_root yq.p_root && xn = ym -> + pop (sizeof_path xp.p_off) (sizeof_path yq.p_off) + | l1,l2 -> mop (mloc_of_loc l1) (mloc_of_loc l2) + + let minus_loc = op_loc M.minus_loc (F.e_iop Isub) + let lt_loc = op_loc M.lt_loc (F.p_icmp Clt) + let le_loc = op_loc M.le_loc (F.p_icmp Cleq) + let le_loc_bool = op_loc M.le_loc_bool (F.e_icmp Cleq) + let lt_loc_bool = op_loc M.lt_loc_bool (F.e_icmp Clt) + let equal_loc_bool = op_loc M.equal_loc_bool (F.e_icmp Ceq) + let equal_loc = op_loc M.equal_loc (F.p_icmp Ceq) + let tau_of_loc = M.tau_of_loc + + + end + + open Model + open Lookup + + include Datalib.Cvalues(Model) + + module L = M.L + + type decl = M.F.decl + + (* ------------------------------------------------------------------------ *) + (* --- Values Coersion --- *) + (* ------------------------------------------------------------------------ *) + + + (*[value_of_mvalue v] returns the value corresponding to value [v] + of the inner memory model*) + let value_of_mvalue = function + | M.V_int (i,t) -> V_int (i,t) + | M.V_float (f,t) -> V_float (f,t) + | M.V_array (a,t) -> V_array(a,t) + | M.V_record (c,t) -> V_record (c,t) + | M.V_union (c,t) -> V_union (c,t) + | M.V_pointer (te,l) -> V_pointer (te,Mloc l) + + (*[mvalue_of_value v] returns the value of the inner memory model + correspondig to the value [v]*) + let mvalue_of_value = function + | V_int (i,t) -> M.V_int (i,t) + | V_float (f,t) -> M.V_float (f,t) + | V_array (a,t) -> M.V_array(a,t) + | V_record (c,t) -> M.V_record (c,t) + | V_union (c,t) -> M.V_union (c,t) + | V_pointer (te,Mloc l) -> M.V_pointer (te, l) + | V_pointer (_,Path _) + | V_pointer (_,PRef _ ) + | V_pointer (_,PRpar _) + | V_pointer (_,ARef _ ) + | V_pointer (_,ARpar _) -> + WpLog.fatal "[mvalue_of_value] of logical pointer" + + + + + (* ------------------------------------------------------------------------ *) + (* --- Env and Memory --- *) + (* ------------------------------------------------------------------------ *) + + module Xmap = Cil_datatype.Varinfo.Map + + (* translation information associated to a C variable.*) + type var_info = + { v_var : F.var ; (* the fol-variable associated*) + v_arity : int ; (* the arity as define for by reference*) + v_is_array : bool ; (* true if it is an array reference*) + v_type : Ctypes.c_object; (* the C_object type of the variable.*) + + } + + (* C-variables translation environment*) + type vars = var_info Xmap.t + + module Lmap = Cil_datatype.Logic_var.Map + + (* kind of a by-reference formal of userdef predicate*) + type formal = + Fpref of int (* pointer by reference formal of arity [n] *) + | Faref of int (* array by reference formal of ... .*) + + (* translation information associated to a by reference formal + of a user-definition*) + type byrefparam = { + bref_var : F.var ; (* the fol-variable associated*) + bref_formal : formal ; (* the kind of the by-reference formal + of user-definition *) + } + + (* The heap is compounded by 3 elements in the funvar memory model: + 1) [mem] which is the C inner memory model ; + 2) [vars] which is the environment of translation of the optimized + variable. + 3) [formals] which is the environment oftranslation of the by-reference + formal of user-definition.*) + type mem = { + mem : M.mem ; + mutable vars : vars ; + mutable formals : byrefparam Lmap.t ; + } + + let mem () = { mem = M.mem () ; vars = Xmap.empty ; formals = Lmap.empty} + + + (* ------------------------------------------------------------------------ *) + (* --- Locations --- *) + (* ------------------------------------------------------------------------ *) + +(* Globals mamagment *) + let global_scope _ p = p + let global _ = () + + (* Logic Parameters translation *) + let get_logic_funvar mem arity lv ap = + let s = "[get_logic_funvar]" in + try + let x = (Lmap.find lv mem.formals).bref_var in + debug "%s %a already recorded" s !Ast_printer.d_logic_var lv; x + with Not_found -> + debug "%s %a not yet recorded" s !Ast_printer.d_logic_var lv; + let t = match lv.lv_type with + | Ctype t -> t + | t -> WpLog.fatal "%s c type of pure logic type %a" + s !Ast_printer.d_logic_type t + in + let typ_logicvar = if ap then array_of t else pointed_of_arity arity t in + let obj_logicvar = Ctypes.object_of typ_logicvar in + let tau_logicvar = tau_of_object obj_logicvar in + let var = L.fresh lv.lv_name (Acsl(tau_logicvar,Ctype typ_logicvar)) in + debug "%s records %a" s F.pp_var var ; + let brefparam = { + bref_var = var ; + bref_formal = + if ap then Faref arity else Fpref arity ; + } in + mem.formals <- Lmap.add lv brefparam mem.formals; var + + (* C variable translation *) + let get_c_funvar mem arity vinfo ap = + let s = "[get_funvar]" in + try let x = (Xmap.find vinfo mem.vars).v_var in + debug "%s %a as %a already recorded" s !Ast_printer.d_var vinfo F.pp_var x; + x + with Not_found -> + debug "%s %a not yet recorded" s !Ast_printer.d_var vinfo; + let t = vinfo.vtype in + let typ_logicvar = if ap then array_of t else pointed_of_arity arity t in + let obj_logicvar = Ctypes.object_of typ_logicvar in + let tau_logicvar = tau_of_object obj_logicvar in + let var = L.fresh vinfo.vname (Acsl(tau_logicvar,Ctype typ_logicvar)) in + let v_info = + {v_var = var ; v_arity = arity ;v_is_array = ap ; v_type = obj_logicvar} + in + debug "%s (%a,%d,%b,%a)" s F.pp_var var arity ap pp_object obj_logicvar ; + mem.vars <- Xmap.add vinfo v_info mem.vars ; var + +(* Variables translation*) + let get_funvar mem arity root ap = + match root with + | Cvar x -> get_c_funvar mem arity x ap + | Lvar lv -> get_logic_funvar mem arity lv ap + +(* [mk_path r m ] makes a path of root [r], + with memory [m], arity [0] and type of value. Used for all kind of + variable with path excepted by-reference parameter without C variable.*) + let mk_path r m = + { p_root= r ; p_mem = m ; p_off=[] ; + p_arity=0 ; p_type=object_of_root r ; p_cvar = None ; } + + (* [mk_pref r m n opt_cv] makes the path of a pointer by-reference parameter + with root (r] memory [m], arity [n] and p_cvar [opt_cv].*) + let mk_pref r m n opt_cv = + { p_root= r; p_mem = m ; p_off=[] ; p_arity=n ; + p_type=object_of_root r ; p_cvar = opt_cv ;} + + (* [mk_aref r m n opt_cv] makes the path of an array by-reference parameter + with root [r] memory [m], arity [n] and p_cvar [opt_cv].*) + let mk_aref r m n opt_cv = + {p_root= r ; p_mem = m; p_off=[] ; p_arity=n ; + p_type=object_array_of_root r ; p_cvar = opt_cv;} + + let cvar m vi = + let r = Cvar vi in + match Variables_analysis.dispatch_cvar vi with + | Variables_analysis.Fvar -> + oracle + "%a is a funvar @." !Ast_printer.d_var vi ; + Path (mk_path r m.mem) + | Variables_analysis.Cvar when Crit.isHoare -> + oracle + "%a is a funvar @." !Ast_printer.d_var vi ; + Path (mk_path r m.mem) + | Variables_analysis.Cvar -> + oracle + "%a is a memvar @." !Ast_printer.d_var vi ; + Mloc (M.cvar m.mem vi) + | Variables_analysis.ARarg -> + oracle + "%a is a array refvar @." !Ast_printer.d_var vi; + if vi.vglob then M.global vi; + ARef (mk_path r m.mem) + | Variables_analysis.PRarg -> + oracle + "%a is a ptr refvar @." !Ast_printer.d_var vi ; + PRef (mk_path r m.mem) + | Variables_analysis.PRpar n -> + oracle + "%a is a ptr ref param of arity %d @." !Ast_printer.d_var vi n; + PRpar (mk_pref r m.mem n None, n) + | Variables_analysis.ARpar n -> + oracle + "%a is a array ref param of arity %d @." !Ast_printer.d_var vi n; + let (n0,_) = brackets_and_stars_typ vi.vtype in + if vi.vglob then global vi; + ARpar (mk_aref r m.mem n None, n0) + + + let lvar m lv x= + let r = Lvar lv in + match Variables_analysis.dispatch_lvar lv with + | Variables_analysis.Fvar -> + oracle + "%a is a funvar @." !Ast_printer.d_logic_var lv ; + Path (mk_path r m.mem) + | Variables_analysis.Cvar when Crit.isHoare -> + oracle + "%a is a funvar @." !Ast_printer.d_logic_var lv ; + Path (mk_path r m.mem) + | Variables_analysis.Cvar -> + oracle + "%a is a memvar @." !Ast_printer.d_logic_var lv ; + Mloc (M.lvar m.mem lv x) + | Variables_analysis.ARarg -> + oracle + "%a is a array refvar @." !Ast_printer.d_logic_var lv; + ARef (mk_path r m.mem) + | Variables_analysis.PRarg -> + oracle + "%a is a ptr refvar @." !Ast_printer.d_logic_var lv ; + PRef (mk_path r m.mem) + | Variables_analysis.PRpar n -> + oracle + "%a is a ptr ref param of arity %d @." + !Ast_printer.d_logic_var lv n; + PRpar (mk_pref r m.mem n (Some x), n) + | Variables_analysis.ARpar n -> + oracle + "%a is a array ref param of arity %d @." + !Ast_printer.d_logic_var lv n; + let (n0,_) = brackets_and_stars_lv_typ lv.lv_type in + ARpar (mk_aref r m.mem n (Some x), n0) + + let inner_loc loc = M.term_of_loc (mloc_of_loc loc) + + (* [add_index p i ty] makes the path of the l-value of the path (p] and + the index [i] with type [ty].*) + let add_index p i ty = + { p with + p_off = p.p_off @ [Lookup.Oindex (i,ty)] ; + p_type = Some ty } + + let shift l ty i = + match l with + | Mloc l -> Mloc (M.shift l ty i) + | PRef p -> Path (add_index p i ty) + | ARef p -> ARef (add_index p i ty) + | PRpar (p,0) | Path p -> + let loc = Lookup.mloc_of_path p in + Mloc (M.shift loc ty i) + | PRpar (p,n) -> PRpar (add_index p i ty,n) + | ARpar (p,n) -> ARpar (add_index p i ty,n) + + let index l ty i = + match l with + | Mloc l -> Mloc (M.index l ty i) + | Path p -> Path (add_index p i ty) + | PRef p -> PRef (add_index p i ty) + | ARef p -> ARef (add_index p i ty) + | PRpar(p,n)-> PRpar (add_index p i ty,n) + | ARpar (p,n) -> ARpar (add_index p i ty,n) + + (*[add_field p finfo] makes the path of the l-value of the path [p] + and the field access to [finfo].*) + let add_field p finfo = + { p with + p_off = p.p_off@[Lookup.Ofield finfo] ; + p_type = Some (object_of finfo.ftype) } + + let field l finfo = + match l with + | Mloc l -> Mloc (M.field l finfo) + | Path p -> Path(add_field p finfo) + | PRef p -> PRef(add_field p finfo) + | PRpar (p,n) -> PRpar(add_field p finfo,n) + | ARef p -> ARef(add_field p finfo) + | ARpar (p,n) -> ARpar(add_field p finfo,n) + + let startof l ty = + match l with + | ARef p -> debug "[startof] %a" pp_path p ; ARef p + | ARpar (p,n) -> ARpar(p,n) + | _ -> Mloc (M.startof (mloc_of_loc l) ty) + + (* ------------------------------------------------------------------------ *) + (* --- Pointers --- *) + (* ------------------------------------------------------------------------ *) + + let cast_loc_to_loc t1 t2 = function + | Mloc l -> Mloc (M.cast_loc_to_loc t1 t2 l) + | ARef p -> debug "[cast_loc_to_loc %a from %a to %a]" + pp_path p !Ast_printer.d_type t1 !Ast_printer.d_type t2; + index (ARef p) (object_of t2) F.i_zero + | Path _ | PRef _ | PRpar _ | ARpar _ -> + WpLog.not_yet_implemented + "Cast from %a to %a of over a logical-variable (try -wp-no-logicvar)" + !Ast_printer.d_type t1 !Ast_printer.d_type t2 + + (* ------------------------------------------------------------------------ *) + (* --- Load --- *) + (* ------------------------------------------------------------------------ *) + (* [fun_load m p ap] returns the load value of the path [p] in the + memory state [m] according to the test of being an + array by-reference [ap].*) + let fun_load m p ap = + let xv = F.var(get_funvar m p.p_arity p.p_root ap) in + match p.p_off, p.p_type with + | [],Some ty -> value_of_logic ty xv + | off,Some ty -> + let vload = Lookup.access xv off in + value_of_logic ty vload + | _ , None -> Wp_parameters.fatal + "[fun_load] offset none null for pure logic type" + + let load m cv l = + match l with + | Mloc l -> value_of_mvalue (M.load m.mem cv l) + | PRef p | Path p -> fun_load m p false + | ARef p -> fun_load m p true + | PRpar (p,0) -> fun_load m p false + | ARpar (p,0) -> fun_load m p true + | ARpar (p,n) -> V_pointer(cv,ARpar(pointed_of_path p,n-1)) + | PRpar (p,n) -> V_pointer(cv,PRpar (pointed_of_path p,n-1)) + + + (* ------------------------------------------------------------------------ *) + (* --- Zones --- *) + (* ------------------------------------------------------------------------ *) + + let massigned = function + | F.Aloc(te,l) -> + debug "massigned case loc : %a" pp_loc l; + F.Aloc(te,mloc_of_loc l) + | F.Arange(te,l,rg) -> + debug "massigned case range : %a becomes %a" + pp_loc l M.pp_loc (mloc_of_loc l); + F.Arange(te,mloc_of_loc l,rg) + + type m_dzone = M.m_dzone + type dzone = M.dzone + let tau_of_dzone = M.tau_of_dzone + + let dzone_assigned m z = M.dzone_assigned m.mem (massigned z) + let dzone_subset = M.dzone_subset + let dzone_union = M.dzone_union + let dzone_empty = M.dzone_empty + + let effect_supported = M.effect_supported + + (* ------------------------------------------------------------------------ *) + (* --- Pointers Logic Properties --- *) + (* ------------------------------------------------------------------------ *) + + let base_address m l = Mloc (M.base_address m.mem (mloc_of_loc l)) + let block_length m l = M.block_length m.mem (mloc_of_loc l) + let valid m z = M.valid m.mem (massigned z) + let separated m z1 z2 = M.separated m.mem (massigned z1) (massigned z2) + + (* ------------------------------------------------------------------------ *) + (* --- By Reference Parameters of User-definitions --- *) + (* ------------------------------------------------------------------------ *) + + let pp_formal_simple fmt = function + | Fpref n -> Format.fprintf fmt "Fpref %d" n + | Faref n -> Format.fprintf fmt "Faref %d" n + + let pp_formal (fmt:Format.formatter) (formal,lv) = + match formal with + | Fpref n -> + Format.fprintf fmt "%s%s" (String.make n '*') lv.lv_name + | Faref n -> + Format.fprintf fmt "%s%t" + lv.lv_name + (fun fmt -> for i=1 to n do Format.pp_print_string fmt "[]" done) + + + let userdef_ref_has_cvar (lv : logic_var) : bool = + Variables_analysis.is_user_formal_in_builtin lv + + (* [userdef_is_ref_param lv] tests if a pure logic variable [lv] is + a by reference formal parameter of a user definition. *) + let userdef_is_ref_param lv = + match Variables_analysis.dispatch_lvar lv with + | Variables_analysis.Fvar | Variables_analysis.Cvar + | Variables_analysis.ARarg | Variables_analysis.PRarg -> false + | Variables_analysis.PRpar _ | Variables_analysis.ARpar _ -> true + + (* [userdef_ref_signature mem] returns the part of the signature + of a user definition corresponding to its by-reference parameters.*) + let userdef_ref_signature mem : ( F.var * logic_var * formal ) list = + let s = "[userdef_ref_signature]" in + debug "%s" s; + Lmap.fold + (fun lv param signature -> + debug "%s of %a" s !Ast_printer.d_logic_var lv ; + (param.bref_var , lv , param.bref_formal) :: signature + ) mem.formals [] + + + let userdef_ref_apply m fml loc = + debug "[userdef_ref_apply] calls with formal %a and loc %a" + pp_formal_simple fml pp_loc loc ; + begin + match fml, loc with + | Fpref 1, PRef p -> fun_load m p false + | Faref 1, ARef p -> fun_load m p true + | Fpref k, PRpar (p,r) -> + let n = k-r-1 in + if n = 0 then fun_load m p false + else + ( + match p.p_type with + | None -> Wp_parameters.fatal + "[userdef_ref_apply] pure type" + | Some ty -> + let obj = object_of_n_pointed n ty in + V_pointer(obj, PRpar(pointed_of_n_path n p,n))) + | Faref k, ARpar(p,r) -> + let n = k-r-1 in + if n = 0 then fun_load m p true + else + ( + match p.p_type with + | None -> Wp_parameters.fatal + "[userdef_ref_apply] pure type" + | Some ty -> + let obj = object_of_n_pointed n ty in + V_pointer(obj, ARpar(pointed_of_n_path n p,n))) + | f , l -> WpLog.fatal + "[userdef_ref_apply] calls with fml:%a and loc:%a" + pp_formal_simple f pp_loc l + end + + (* ------------------------------------------------------------------------ *) + (* --- Functional Closure --- *) + (* ------------------------------------------------------------------------ *) + + type closure = + | Fclos of int * bool * Cil_types.varinfo (* arity, isArray *) + | Mclos of M.closure + + let pp_closure fmt = function + | Mclos cl -> M.pp_closure fmt cl + | Fclos(k,ap,vinfo) -> + if ap then + (* array *) + Format.fprintf fmt "value of %s%t" + vinfo.vname (* C-original name *) + (fun fmt -> for i=1 to k do Format.pp_print_string fmt "[]" done) + else + (* ref. *) + Format.fprintf fmt "value of %s%s" + (String.make k '*') vinfo.vname + + let userdef_mem_signature m = + Xmap.fold + (fun v vi fs -> (vi.v_var,Fclos(vi.v_arity,vi.v_is_array,v))::fs) + m.vars + (List.map (fun (y,c) -> y,Mclos c) (M.userdef_mem_signature m.mem)) + + let userdef_mem_apply m = function + | Fclos(k,ap,vinfo) -> F.var (get_c_funvar m k vinfo ap) + | Mclos mc -> M.userdef_mem_apply m.mem mc + + (* ------------------------------------------------------------------------ *) + (* --- Labels & Quantification --- *) + (* ------------------------------------------------------------------------ *) + + let update ~(at:mem) ~(here:mem) p = + Xmap.fold + (fun v vi p -> + let x_here = get_c_funvar here vi.v_arity v vi.v_is_array in + L.subst vi.v_var (F.var x_here) p) + at.vars + (M.update at.mem here.mem p) + + let quantify m p = + let xs = Xmap.fold (fun _ vi xs -> vi.v_var::xs) m.vars [] in + L.forall xs (M.quantify m.mem p) + + (* ------------------------------------------------------------------------ *) + (* --- Assignments --- *) + (* ------------------------------------------------------------------------ *) + + (*[update_offset phi current offs] applies the l-value made + from the l-value [current] and the list of offset [offs] to the + hole-term [phi]. *) + let rec update_offset phi current offs = + match offs with + | [] -> phi current + | off::m -> + let v = Lookup.access_poffset current off in + let r = update_offset phi v m in + begin + match off with + | Lookup.Ofield f -> + F.wrap (F.upd_field (F.unwrap current) f r) + | Lookup.Oindex (i,_obj) -> + F.wrap (F.upd_index (F.unwrap current) i r) + end + + (* [store m p v ap wp] firts, stores in the memory state [m] + the value [v] to the path [p] according the by-reference array test [ap] + and returns the property [wp] in this new memory state.*) + let store m p v ap wp = + let x = get_funvar m p.p_arity p.p_root ap in + let v' = update_offset (fun _ -> logic_of_value v) (F.var x) p.p_off in + L.subst x v' wp + + let subst_lval m obj loc v wp = + match loc with + | Mloc l -> M.subst_lval m.mem obj l (mvalue_of_value v) wp + | Path ph | PRef ph | PRpar (ph,_)| ARef ph -> + store m ph v false wp + | ARpar (ph,_) -> store m ph v true wp + + (* ------------------------------------------------------------------------ *) + (* --- Zone Havoc --- *) + (* ------------------------------------------------------------------------ *) + + let subst_havoc (m:mem) = function + + | F.Aloc(_,(Path p| PRef p | PRpar(p,_))) + when p.p_off=[] -> + let x = get_funvar m p.p_arity p.p_root false in + let v = L.fresh (F.basename_of_var x) (F.kind_of_var x) in + [F.Fresh v;F.Update(x,fun _ -> F.var v)] + | F.Aloc(_, (ARpar(p,_)| ARef p)) when p.p_off=[] -> + let x = get_funvar m p.p_arity p.p_root true in + let v = L.fresh (F.basename_of_var x) (F.kind_of_var x) in + [F.Fresh v;F.Update(x,fun _ -> F.var v)] + + | F.Aloc(_,(Path p| PRef p | PRpar(p,_))) -> + let x = get_funvar m p.p_arity p.p_root false in + let v = + match p.p_type with + | None -> Wp_parameters.fatal "[subst_havoc] pure logic var" + | Some ty -> + L.fresh "v" (Model (tau_of_object ty)) + in + let newterm (sigma : (F.var * F.var) list ) : F.abstract = + F.wrap ( update_offset + (fun _ -> F.var v) + (L.apply sigma (F.var x)) p.p_off ) + in + [F.Fresh v;F.Update(x,newterm)] + + | F.Aloc(_, (ARpar(p,_)| ARef p)) -> + let x = get_funvar m p.p_arity p.p_root true in + let v = + match p.p_type with + | None -> Wp_parameters.fatal "[subst_havoc] of pure logic var" + | Some ty -> L.fresh "v" (Model (tau_of_object ty)) + in + let newterm (sigma : (F.var * F.var) list ) : F.abstract = + F.wrap ( update_offset + (fun _ -> F.var v) + (L.apply sigma (F.var x)) p.p_off ) + in + [F.Fresh v;F.Update(x,newterm)] + + | F.Arange(_,(Path p| PRef p | PRpar(p,_)),rg) -> + let x = get_funvar m p.p_arity p.p_root false in + let upd_range rg = fun array -> + F.wrap (F.set_range_index (F.unwrap array) rg) + in + let newterm (sigma :(F.var * F.var) list ) : F.abstract = + F.wrap (update_offset (upd_range rg) (L.apply sigma (F.var x)) + p.p_off) + in + [F.Update(x,newterm)] + + | F.Arange(_, (ARpar(p,_)| ARef p),rg) -> + let x = get_funvar m p.p_arity p.p_root true in + let upd_range rg = fun array -> + F.wrap (F.set_range_index (F.unwrap array) rg) + in + let newterm (sigma :(F.var * F.var) list ) : F.abstract = + F.wrap (update_offset (upd_range rg) (L.apply sigma (F.var x)) + p.p_off) + in + [F.Update(x,newterm)] + + | F.Aloc(te,Mloc l) -> + M.subst_havoc m.mem (F.Aloc(te,l)) + + | F.Arange(te,Mloc l,rg) -> + M.subst_havoc m.mem (F.Arange(te,l,rg)) + + let assigns_goal m1 reg m2 = + (* Not very usefull, since assigns_supported = false !! *) + let region = + List.map + (function + | F.Aloc(_,Path _) | F.Arange(_,Path _,_) + | F.Aloc(_,PRef _) | F.Arange(_,PRef _,_) + | F.Aloc(_,PRpar _) | F.Arange(_,PRpar _,_) + | F.Aloc(_,ARef _) | F.Arange(_,ARef _,_) + | F.Aloc(_,ARpar _) | F.Arange(_,ARpar _,_) -> + WpLog.fatal + "Proof of assigns-clause with hoare-region" + | F.Aloc(te,Mloc l) -> F.Aloc(te,l) + | F.Arange(te,Mloc l,rg) -> F.Arange(te,l,rg)) + reg + in + M.assigns_goal m1.mem region m2.mem + + let assigns_supported = false + + (* ------------------------------------------------------------------------ *) + (* --- Local Scope --- *) + (* ------------------------------------------------------------------------ *) + + let local_scope m lx b p = + let xs = List.filter Variables_analysis.is_to_scope lx in + M.local_scope m.mem xs b p + +end + + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/funvar_mem.mli frama-c-20111001+nitrogen+dfsg/src/wp/funvar_mem.mli --- frama-c-20110201+carbon+dfsg/src/wp/funvar_mem.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/funvar_mem.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,57 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Memory Model for functional variables. *) +(** Optimisation for variables which address is never taken. *) +(* -------------------------------------------------------------------------- *) + +(** The interaction between M and funvar depends on criteria. + For instance, the Store model discharges the traitment of + functional variables to funvar and traits the variables + which addresses are taken. + For the Hoare model thing are different : + the traitment of functional variables is discharged to funvar. + A variable which address is taken has to be represented by + two locations : + 1) One for itself traits by funvar + 2) Another for its address traits by M. + Hence, to drive the set of variables manage by M (mem) of + funvar (fun), use the module Criteria. +*) + + + +(** Define the criteria of variables trait by funvar of by M *) +module type Criteria = +sig + val isHoare : bool +end + +module Create (Crit:Criteria)(M:Mwp.S) : Mwp.S with module F=M.F + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/hoare_mem.ml frama-c-20111001+nitrogen+dfsg/src/wp/hoare_mem.ml --- frama-c-20110201+carbon+dfsg/src/wp/hoare_mem.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/hoare_mem.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,425 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Memory Model for Hoare. *) +(* -------------------------------------------------------------------------- *) + +(* TODO, ZD : + A lot of the code of hoare model is identical to the code of store. + Mayby, we can try to share more (even some) *) + +open Cil_types +open Cil_datatype + +module Create + (F:Formula.S) + (A:Mint.S with module F = F) + (R:Mfloat.S with module F = F) + = +struct + type m_pointer + type pointer = m_pointer F.term + + type decl = F.decl + + let unsupported = Wp_error.unsupported + + type m_alloc = Formula.m_array + let t_alloc : Formula.tau = Formula.ADT("farray",[Formula.Integer]) + type alloc = m_alloc F.term + + let model_ptr = F.e_app2 "ptr" + let model_base = F.e_app1 "base" + let model_offset = F.e_app1 "offset" + let model_shift = F.e_app2 "shift" + + let model_range = F.e_app3 "range_ptr" + let model_rbase = F.e_app1 "rbase" + let model_roffset = F.e_app1 "roffset" + let model_range_of_ptr = F.e_app2 "range_of_ptr" + let model_range_of_ptr_range = F.e_app3 "range_of_ptr_range" + let model_separated = F.p_app2 "separated" + let model_valid = F.p_app2 "valid" + + + + let sizeof te = F.e_int64 (Ctypes.sizeof_object te) + let n_size n te = F.i_mult n (sizeof te) + let add_offset d te k = F.i_add d (n_size k te) + let cardinal a b = F.i_add F.i_one (F.i_sub b a) + + let offset_of_field f = + let rec acc sz l f = + match l with + | [] -> Wp_parameters.fatal "[offset_of_field] not found %s" f.fname + | fi::m -> + if Cil_datatype.Fieldinfo.equal f fi + then sz + else acc (F.i_add sz (sizeof (Ctypes.object_of fi.ftype))) m f + in + acc F.i_zero f.fcomp.cfields f + + module Model = struct + module F = F + module A = A + module R = R + + + + let tau_of_loc = Formula.ADT("pointer",[]) + + type loc = | Addr of F.integer * F.integer | Ptr of pointer + + let ptr = function + | Addr(b,d) -> model_ptr b d + | Ptr p -> p + + let base = function + | Addr(b,_) -> b + | Ptr p -> model_base p + + let offset = function + | Addr(_,d) -> d + | Ptr p -> model_offset p + + let loc_of_term _ p = Ptr (F.unwrap p) + let term_of_loc loc = F.wrap (ptr loc) + + + let rec pp_loc fmt l = match l with + | Addr (x,i) -> Format.fprintf fmt "@@ptr(%a,%a)" + F.pp_term x F.pp_term i + | Ptr p -> Format.fprintf fmt "%a" F.pp_term p + + + let equal_loc_bool l1 l2 = + F.e_app2 "eq_ptr_bool" (ptr l1) (ptr l2) + let lt_loc_bool l1 l2 = + F.e_app2 "lt_ptr_bool" (ptr l1) (ptr l2) + let le_loc_bool l1 l2 = + F.e_app2 "le_ptr_bool" (ptr l1) (ptr l2) + let equal_loc l1 l2 = + F.p_app2 "eq_ptr" (ptr l1) (ptr l2) + let lt_loc l1 l2 = + F.p_app2 "lt_ptr" (ptr l1) (ptr l2) + let le_loc l1 l2 = + F.p_app2 "le_ptr" (ptr l1) (ptr l2) + let minus_loc l1 l2 = + F.e_app2 "minus_ptr" (ptr l1) (ptr l2) + + let null = Addr(F.i_zero,F.i_zero) + let is_null l = + F.e_app2 "addr_eq" (ptr l) (model_ptr F.i_zero F.i_zero) + + let cast_loc_to_int _tp _p _ti = unsupported "cast from pointer to int" + let cast_int_to_loc _ti _i _tp = unsupported "cast from int to pointer" + end + + let cast_loc_to_loc ty1 ty2 l = + if Ctypes.equal (Ctypes.object_of ty1)(Ctypes.object_of ty2) then l + else + unsupported "cast from pointer (%a) to pointer (%a)" + !Ast_printer.d_type ty1 !Ast_printer.d_type ty2 + + module V = Datalib.Cvalues(Model) + module L = Datalib.Create(V) + include V + open Model + + module Globals = F.DRegister + (struct + include F.Varinfo + + let declare x _ = + let pool = F.pool () in + let xa = F.p_fresh pool "ta" (Formula.Model t_alloc) in + let sx = sizeof (Ctypes.object_of x.vtype) in + let xk = F.Xindex.get_ind x in + let sa = F.e_access (F.var xa) xk in + let gta = F.p_app1 "global" (F.var xa) in + Formula.Axiom (F.p_forall [xa] + (F.p_implies gta (F.p_eq (F.unwrap sa) sx))) + + let section = Formula.S_Model_Prop + let prefix = "Alloc" + let basename x = x.vname + let clear () = () + let pp_descr fmt _x = + Format.fprintf fmt "Global allocation table" + end) + + + + let global v = Globals.define v + + let cvar _m vi = + if vi.vglob then global vi ; + Addr (F.Xindex.get_ind vi,F.i_zero ) + + + let inner_loc _ = Wp_parameters.fatal "[inner_loc] reserved to funvar" + + let lvar _m lv x = + let ty = + match lv.lv_type with + | Ctype ty -> ty + | ty -> Wp_parameters.fatal + "[lvar] c type of pure logic type %a" + !Ast_printer.d_logic_type ty + in + loc_of_term (Ctypes.object_of ty)(F.var x) + + let offset loc te n = + match loc with + | Model.Addr(b,d) -> Model.Addr(b,add_offset d te n) + | Model.Ptr p -> Model.Ptr (model_shift p (n_size n te )) + + let field l f = + if f.fcomp.cstruct then + let pos = offset_of_field f in + match l with + | Model.Addr(b,d) -> Model.Addr(b,(F.i_add d pos)) + | Model.Ptr p -> Model.Ptr (model_shift p pos) + else l + + + let shift = offset + let index = offset + let startof l _cv = l + + + + type mem = + { vars : F.var Varinfo.Hashtbl.t ; + x_alloc : F.var ; + alloc : alloc ; + } + + let mem () = + let x_t = L.fresh "ta" (Formula.Model t_alloc) in + { + vars = Varinfo.Hashtbl.create 10; + x_alloc = x_t ; + alloc = F.var x_t; + } + + (************************************************************************************) + + (** Get the wp variable of the C variable. *) + let get_var m lv = + try Varinfo.Hashtbl.find m lv + with Not_found -> + let ty = lv.vtype in + let t = tau_of_object (Ctypes.object_of ty) in + let v = L.fresh lv.vname (Formula.Acsl(t,Ctype ty)) in + Varinfo.Hashtbl.add m lv v; v + + let load _m _cobj _loc = unsupported "undirect access" + + let base_address _ = function + | Model.Addr(b,_) -> Model.Addr(b,F.i_zero) + | Model.Ptr p -> Model.Ptr (model_ptr (model_base p) F.i_zero) + + let block_length mem l = F.unwrap (F.e_access mem.alloc (base l)) + + + (* --- WP Calculus *) + + let update ~(at:mem) ~(here:mem) p = + let dov vi v_l p = + let v_here = get_var here.vars vi in + L.subst v_l (F.var v_here) p + in + L.subst at.x_alloc here.alloc + (Varinfo.Hashtbl.fold dov at.vars p) + + let quantify m p = + let xs = Varinfo.Hashtbl.fold (fun _ v xs -> v::xs) m.vars [] in + L.forall (m.x_alloc::xs) p + + let subst_lval _env _t _loc _v_exp _p = unsupported "undirect access" + + let alloc ta v sz = F.e_update ta v sz + let free ta v = F.e_update ta v (F.wrap F.i_zero) + + let alloc_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + let sz_x = F.wrap (sizeof (Ctypes.object_of x.vtype)) in + L.subst m.x_alloc (alloc m.alloc v_x sz_x) p + ) p xs + + let free_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + L.subst m.x_alloc (free m.alloc v_x) p + ) p xs + + let notexists_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + let q = F.p_eq (F.unwrap(F.e_access m.alloc v_x)) F.i_zero in + F.p_implies q p + ) p xs + + + let global_scope m p = + if L.has_context_vars [m.x_alloc] p + then F.p_implies (F.p_app1 "global" m.alloc) p + else p + + + let local_scope m vars scope p = + match scope with + | Mcfg.SC_Function_frame -> p + | Mcfg.SC_Block_in | Mcfg.SC_Function_in -> + notexists_vars m vars (alloc_vars m vars p) + | Mcfg.SC_Block_out | Mcfg.SC_Function_out -> + free_vars m vars p + | Mcfg.SC_Global -> + if L.has_context_vars [m.x_alloc] p + then F.p_implies (F.p_app1 "global" m.alloc) p + else p + + (* ----------------------------------------------------------------------- *) + (* --- Setof Locations --- *) + (* ----------------------------------------------------------------------- *) + + let range_of_assignable = function + | F.Aloc(te,loc) -> + let size = sizeof te in + begin + match loc with + | Model.Addr(b,d) -> model_range b d size + | Model.Ptr p -> model_range_of_ptr p size + end + | F.Arange(te,loc,rg) -> + begin + match rg with + |{F.inf=None;F.sup=Some h} -> + let size = n_size (F.i_add h F.i_one) te in + (match loc with + | Model.Addr(b,d) -> model_range b d size + | Model.Ptr p -> model_range_of_ptr p size + ) + | {F.inf=Some l;F.sup=Some h} -> + let delta = n_size l te in + let size = n_size (cardinal l h) te in + (match loc with + | Model.Addr(b,d) -> + model_range b (F.i_add d delta) size + | Model.Ptr p -> + model_range_of_ptr (model_shift p delta) size + ) + | _ -> unsupported "infinite range for array" + + end + + let valid mem z = + let r = range_of_assignable z in model_valid mem.alloc r + + let separated _ z1 z2 = + let r1 = range_of_assignable z1 in + let r2 = range_of_assignable z2 in + model_separated r1 r2 + + + (* ----------------------------------------------------------------------- *) + (* --- Zone Assigns --- *) + (* ----------------------------------------------------------------------- *) + + type m_dzone + type dzone = m_dzone F.term + let tau_of_dzone = Formula.ADT("zone",[]) + + let dzone_assigned _ _ = + Wp_parameters.not_yet_implemented "zone representation in Hoare" + + let dzone_subset _z1 _z2 = + Wp_parameters.not_yet_implemented "zone subset in Hoare" + + let dzone_union _z1 _z2 = + Wp_parameters.not_yet_implemented "zone union in Hoare" + + let dzone_empty () = + Wp_parameters.not_yet_implemented "empty zone in Hoare" + + let effect_supported = false + + + (* ----------------------------------------------------------------------- *) + (* --- Normal Assigns --- *) + (* ----------------------------------------------------------------------- *) + + let assigns_goal _env _sloc _lto = unsupported "proof of assigns clauses" + + let assigns_supported = false + + (* ----------------------------------------------------------------------- *) + (* --- Havoc --- *) + (* ----------------------------------------------------------------------- *) + + let subst_havoc _ _ = + Wp_parameters.not_yet_implemented "subst_havoc of pointer" + + (* ----------------------------------------------------------------------- *) + (* --- User Predicate environment --- *) + (* ----------------------------------------------------------------------- *) + + type closure = Var of Cil_types.varinfo | Alloc + + let pp_closure fmt = function + | Var vinfo -> Format.fprintf fmt "value of %a" !Ast_printer.d_var vinfo + | Alloc -> Format.fprintf fmt "allocation table" + + let userdef_mem_signature m = + Varinfo.Hashtbl.fold + (fun varinfo fvar signature -> (fvar,Var varinfo)::signature) + m.vars [m.x_alloc,Alloc] + + let userdef_mem_apply mem = function + | Var varinfo -> F.var (get_var mem.vars varinfo) + | Alloc -> F.wrap mem.alloc + + (* ------------------------------------------------------------------------ *) + (* --- Functional Closure --- *) + (* ------------------------------------------------------------------------ *) + + type formal = unit + let pp_formal (_:Format.formatter) _ = () + let userdef_is_ref_param (_:logic_var) : bool = false + let userdef_ref_signature (_:mem) : ( F.var * logic_var * formal ) list = [] + let userdef_ref_apply (_:mem) (_:formal) (_:loc) : value = + Wp_parameters.fatal "[userdef_ref_apply] of model Hoare" + let userdef_ref_has_cvar (_ : logic_var) : bool = false + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/hoare_mem.mli frama-c-20111001+nitrogen+dfsg/src/wp/hoare_mem.mli --- frama-c-20110201+carbon+dfsg/src/wp/hoare_mem.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/hoare_mem.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Create + (F:Formula.S) + (A:Mint.S with module F = F) + (R:Mfloat.S with module F = F) + : Mwp.S with module F = F and module A = A and module R = R diff -Nru frama-c-20110201+carbon+dfsg/src/wp/kreal.ml frama-c-20111001+nitrogen+dfsg/src/wp/kreal.ml --- frama-c-20110201+carbon+dfsg/src/wp/kreal.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/kreal.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,103 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Coq Real Constants --- *) +(* -------------------------------------------------------------------------- *) + +let error () = raise (Invalid_argument "invalid real constant") + +type sign = Positive | Negative +type state = Integral | Fraction | Exponent + +type env = { + mantiss : Buffer.t ; + exponent : Buffer.t ; + mutable sign : sign ; + mutable coma : int ; (* number of digits afer '.' *) + mutable state : state ; +} + +type token = + | Digit + | Plus + | Minus + | Exp + | Dot + +let token = function + | ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') -> Digit + | '.' -> Dot + | '-' -> Minus + | '+' -> Plus + | 'e' | 'E' -> Exp + | _ -> error () + +let trail m = + let n = String.length m in + let rec first k = if k < n && m.[k] = '0' then first (succ k) else k in + let rec last k = if k >= 0 && m.[k] = '0' then last (pred k) else k in + let a = first 0 in + let b = last (n-1) in + if a <= b then Some(a , n-b-1) else None + +let convert r = + let e = { + mantiss = Buffer.create 64 ; sign = Positive ; + exponent = Buffer.create 64 ; + coma = 0 ; state = Integral ; + } in + String.iter + (fun c -> + let tk = token c in + match e.state , tk with + | _ , Dot -> e.state <- Fraction ; + | _ , Exp -> e.state <- Exponent ; + | (Integral|Fraction) , Plus -> e.sign <- Positive + | (Integral|Fraction) , Minus -> e.sign <- Negative + | Integral , Digit -> Buffer.add_char e.mantiss c + | Fraction , Digit -> Buffer.add_char e.mantiss c ; e.coma <- succ e.coma + | Exponent , (Plus|Minus|Digit) -> Buffer.add_char e.exponent c + ) r ; + let m = Buffer.contents e.mantiss in + begin + match trail m with + | None -> "0" + | Some(a,b) -> + let digits = String.sub m a (String.length m - a - b) in + let exp = + let ex = Buffer.contents e.exponent in + if ex = "" then b - e.coma else int_of_string ex + b - e.coma + in + let size = 4 + String.length m + abs exp in + let buffer = Buffer.create size in + let parent = e.sign = Negative || exp <> 0 in + if parent then Buffer.add_char buffer '(' ; + if e.sign = Negative then Buffer.add_char buffer '-' ; + Buffer.add_string buffer digits ; + if exp > 0 then Buffer.add_string buffer (String.make exp '0') ; + if exp < 0 then + (Buffer.add_string buffer "/1" ; + Buffer.add_string buffer (String.make (-exp) '0')) ; + if parent then Buffer.add_char buffer ')' ; + Buffer.contents buffer + end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/kreal.mli frama-c-20111001+nitrogen+dfsg/src/wp/kreal.mli --- frama-c-20110201+carbon+dfsg/src/wp/kreal.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/kreal.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,25 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Converting real constants with only integral values *) + +val convert : string -> string diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicDef.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicDef.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicDef.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicDef.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,447 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Logic Database --- *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau +open LogicLang + +type item = + | TYPE of int + | RECORD of field list + | FUNCTION of var list * tau * term option + | PREDICATE of var list * pred option + | AXIOM of pred + +type description = { + t_source : Lexing.position ; + t_short : string ; + t_descr : string ; +} + +type declaration = { + d_name : id ; + d_item : item ; + d_descr : description ; +} + +type registered = { + r_declaration : declaration ; + r_localdeps : Iset.t ; + r_age : int ; +} + +type logic_model = { + model_name : string ; + model_pointer : tau ; + model_index : registered Ihmap.t ; + mutable model_locked : Iset.t ; (* cofix compiled *) + mutable model_history : int ; (* age of exportations *) + mutable model_updated : bool ; (* modified at this age *) +} + +module LogicModel : Datatype.S with type t = logic_model = + Datatype.Make + (struct + include Datatype.Undefined + type t = logic_model + let name = "Wp.LogicDef.LogicModel" + let reprs = [{ + model_name=""; + model_pointer = Integer; + model_index = Ihmap.create 0; + model_locked = Iset.empty ; + model_history = 0; + model_updated = false; + }] + end) + +module MODELS = State_builder.Hashtbl(Datatype.String.Hashtbl)(LogicModel) + (struct + let name = "Wp.LogicDef.Declarations" + let dependencies = [Ast.self] + let kind = `Tuning (* TODO[LC]: to check with JS. *) + let size = 7 + end) + +let register ~name ~pointer = + if MODELS.mem name then Wp_parameters.fatal "Duplicate logic model {%s}" name ; + MODELS.add name { + model_name = name ; + model_pointer = pointer ; + model_index = Ihmap.create 231 ; + model_locked = Iset.empty ; + model_history = 0 ; + model_updated = false ; + } + +let current_model = ref None + +let on_model model job data = + match !current_model with + | Some m -> + Wp_parameters.fatal + "Re-entrant logic model {%s,%s}" m.model_name model + | None -> + current_model := Some (MODELS.find model) ; + try let result = job data in current_model := None ; result + with exn -> current_model := None ; raise exn + +let the_model () = + match !current_model with Some m -> m | None -> + Wp_parameters.fatal "No logic model" + +(* -------------------------------------------------------------------------- *) +(* --- Registry --- *) +(* -------------------------------------------------------------------------- *) + +let lookup id = + let model = the_model () in + Ihmap.find model.model_index id + +let get_item id = (lookup id).r_declaration.d_item +let get_description id = (lookup id).r_declaration.d_descr +let get_declaration id = (lookup id).r_declaration +let get_local_depends id = + try (lookup id).r_localdeps with Not_found -> Iset.empty + +let add_depend_var ids x = add_depend_tau ids (tau_of_var x) +let add_depend_field ids f = add_depend_tau ids f.f_type + +let dependencies = function + | TYPE _ -> Iset.empty + | RECORD fs -> List.fold_left add_depend_field Iset.empty fs + | FUNCTION (xs,t,None) -> + List.fold_left add_depend_var (add_depend_tau Iset.empty t) xs + | FUNCTION (xs,t,Some e) -> + let core = add_depend_term Iset.empty e in + List.fold_left add_depend_var (add_depend_tau core t) xs + | PREDICATE(xs,None) -> + List.fold_left add_depend_var Iset.empty xs + | PREDICATE(xs,Some p) -> + List.fold_left add_depend_var (add_depend_pred Iset.empty p) xs + | AXIOM p -> add_depend_pred Iset.empty p + +let declare d = + let m = the_model () in + if Iset.mem d.d_name m.model_locked then + Wp_parameters.fatal "Locked symbol '%a'" LogicId.pretty d.d_name ; + m.model_updated <- true ; + Ihmap.replace m.model_index d.d_name { + r_declaration = d ; + r_age = m.model_history ; + r_localdeps = dependencies d.d_item ; + } + +let lock f = + let m = the_model () in + m.model_locked <- Iset.add f m.model_locked + +let unlock f = + let m = the_model () in + m.model_locked <- Iset.remove f m.model_locked + +let mark_history () = + let m = the_model () in + if m.model_updated then + ( m.model_history <- succ m.model_history ; m.model_updated <- false ) + +let model_age () = (the_model ()).model_history + +(* -------------------------------------------------------------------------- *) +(* --- Fixpoint Compilation --- *) +(* -------------------------------------------------------------------------- *) + +module Cofix = +struct + + let stack : id list ref = ref [] + let push f = stack := f :: !stack + let pop f = + match !stack with + | [] -> Wp_parameters.fatal "Logic.cofix: empty stack" + | f0::stk -> + if LogicId.equal f f0 then stack := stk + else Wp_parameters.fatal "Logic.cofix: corrupted stack" + + let recursive f = + List.exists (LogicId.equal f) !stack + + type state = + | Undefined + | Defined of item + | Cyclic of cycle + + and cycle = { + mutable ccitem : ccitem ; + mutable stable : bool ; (* stable or not during fixpoint *) + mutable inners : Iset.t ; (* set of symbols in the cycle, except root *) + } and ccitem = + | Cnone + | Cdefault of item + | Cupdated of item * description + + let cofix : cycle Ihmap.t = Ihmap.create 31 (* Cycle state only *) + + let lookup f = + try Defined(get_item f) + with Not_found -> + try Cyclic(Ihmap.find cofix f) + with Not_found -> Undefined + + let is_stable f = match lookup f with + | Undefined | Defined _ + | Cyclic { ccitem=Cupdated _ ; stable=true } -> true + | Cyclic _ -> false + + let current = function + | Cnone -> + Wp_parameters.fatal "logic:undefined value" + | Cdefault item | Cupdated(item,_) -> item + + let define f = + try + let c = Ihmap.find cofix f in + Ihmap.remove cofix f ; + match c.ccitem with + | Cnone | Cdefault _ -> + Wp_parameters.fatal "unstable definition (%a)" LogicId.pretty f ; + | Cupdated (item,descr) -> + unlock f ; + declare { d_name=f ; d_item=item ; d_descr=descr } + with Not_found -> () + + let is_stable f = + match lookup f with + | Undefined -> false + | Defined _ -> true + | Cyclic c -> c.stable + + exception Unstable + + let all_stable fs = + try Iset.iter + (fun f -> + if not (is_stable f) then raise Unstable + ) fs ; true + with Unstable -> false + + let set_stable f = + try let c = Ihmap.find cofix f in c.stable <- true + with Not_found -> () + + let rec get_cycle f = function + | [] -> [] + | g::stk -> if LogicId.equal f g then [] else (g :: get_cycle f stk) + + let add_cycle fs g = + try + let c = Ihmap.find cofix g in + c.inners <- List.fold_right Iset.add fs c.inners + with Not_found -> () + + let rec compatible_signature xs ys = + match xs , ys with + | [] , [] -> true + | [] , _ | _ , [] -> false + | x::xs , y::ys -> + (compare_tau (tau_of_var x) (tau_of_var y) = 0) && + compatible_signature xs ys + + let compatible item0 item1 = + match item0,item1 with + | FUNCTION(_,_,Some _) , FUNCTION(_,_,None) -> false + | PREDICATE(_,Some _) , PREDICATE(_,None) -> false + | FUNCTION(sig0,r0,_) , FUNCTION(sig1,r1,_) -> + (compatible_signature sig0 sig1) && + (compare_tau r0 r1 = 0) + | PREDICATE(sig0,_) , PREDICATE(sig1,_) -> + (compatible_signature sig0 sig1) + | TYPE n , TYPE n' -> n=n' + | RECORD fs , RECORD fs' -> + (List.length fs = List.length fs') && + List.for_all2 (fun f f' -> compare_field f f'=0) fs fs' + | AXIOM _ , AXIOM _ -> true + | _ -> false + + let default f item = + try + let c = Ihmap.find cofix f in + if c.ccitem=Cnone then c.ccitem <- Cdefault item + with Not_found -> + Ihmap.add cofix f { + ccitem = Cdefault item ; + stable = true ; + inners = Iset.empty ; + } + + let update f item descr = + match lookup f with + | Undefined | Defined _ -> + declare { d_name=f ; d_item=item ; d_descr=descr } + | Cyclic c -> + if c.stable then + begin + match c.ccitem with + | Cnone -> () + | Cdefault item0 | Cupdated(item0,_) -> + c.stable <- compatible item0 item + end ; + c.ccitem <- Cupdated(item,descr) + + let compute f cc = + try push f ; cc f ; pop f ; + with error -> pop f ; raise error + + let rec fixpoint c f cc = + compute f cc ; + if Iset.mem f c.inners then + (* inside cycle *) + ( current c.ccitem ) + else + (* cycle root *) + if c.stable && all_stable c.inners then + begin + define f ; + Iset.iter define c.inners ; + current c.ccitem + end + else + begin + c.stable <- true ; + Iset.iter set_stable c.inners ; + fixpoint c f cc + end + + let obtain f cc = + match lookup f with + | Defined item -> item + | Undefined -> + let c = { ccitem=Cnone ; stable=true ; inners=Iset.empty } in + Ihmap.replace cofix f c ; + lock f ; fixpoint c f cc + | Cyclic c -> + if recursive f then + let fs = get_cycle f !stack in + List.iter (add_cycle fs) (f::fs) ; + ( current c.ccitem ) + else + ( fixpoint c f cc ) + +end + +let fixpoint = Cofix.obtain +let default = Cofix.default +let update = Cofix.update + +(* -------------------------------------------------------------------------- *) +(* --- Exportation --- *) +(* -------------------------------------------------------------------------- *) + + +module Components = +struct + + (*[LC] From ocamlgraph/components with added feature *) + + module G = + struct + (* here, G.t = unit and G.V=LogicId *) + let iter_succ f (*g*) id = Iset.iter f (get_local_depends id) + end + module H = Ihmap + module S = Iset + + (*[LC] Added an iterator for some 'roots' There is no need for + G.iter_vertex. Only an iterator over the requested nodes is + necessary. The compute hashcomp table is enough to build the + array of components. *) + + let scc_roots (*g*) iter_roots = + let root = H.create 997 in + let hashcomp = H.create 997 in + let stack = ref [] in + let numdfs = ref 0 in + let numcomp = ref 0 in + let rec pop x c = function + | (y, w) :: l when y > x -> + H.add hashcomp w !numcomp; + pop x (S.add w c) l + | l -> c,l + in + let rec visit v = + if not (H.mem root v) then + begin + let n = incr numdfs; !numdfs in + H.add root v n; + G.iter_succ + (fun w -> + visit w; + if not (H.mem hashcomp w) then + H.replace root v (min (H.find root v) (H.find root w))) + (*g*) v; + if H.find root v = n then + (H.add hashcomp v !numcomp; + let _,s = pop n (S.add v S.empty) !stack in + stack:= s; + incr numcomp) + else stack := (n,v)::!stack; + end + in + iter_roots visit (*g*) ; + let t = Array.make !numcomp [] in + H.iter + (fun v i -> t.(i) <- v::t.(i)) + hashcomp ; t + +end + +let declarations ids = + let section = function + | TYPE _ | RECORD _ -> 0 + | FUNCTION _ -> 1 + | PREDICATE _ -> 2 + | AXIOM _ -> 3 + in + let sort d1 d2 = section d1.d_item - section d2.d_item in + let acc = ref [] in + List.iter + (fun f -> + try acc := get_declaration f :: !acc + with Not_found -> ()) + ids ; + List.sort sort !acc + +let export f roots_iter = + Array.iter + (fun ids -> f (declarations ids)) + (Components.scc_roots roots_iter) + +let export_items f ids = + export f (fun visit -> List.iter visit ids) + +let export_goal f p = + let ids = add_depend_pred Iset.empty p in + export f (fun visit -> Iset.iter visit ids) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicDef.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicDef.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicDef.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicDef.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,99 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Logic Database *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau +open LogicLang + +(** {3 Model Registration} *) + +val register : name:string -> pointer:tau -> unit +val on_model : string -> ('a -> 'b) -> 'a -> 'b + +(** {3 Declarations} *) + +type item = + | TYPE of int + | RECORD of field list + | FUNCTION of var list * tau * term option + | PREDICATE of var list * pred option + | AXIOM of pred + +type description = { + t_source : Lexing.position ; + t_short : string ; + t_descr : string ; +} + +type declaration = { + d_name : id ; + d_item : item ; + d_descr : description ; +} + +val declare : declaration -> unit (** Simple declaration. *) + +(** {3 Recursive Compilations} *) + +val fixpoint : id -> (id -> unit) -> item + (** Retrieve the definition of [f] if already defined. + Otherwise compile it with the provided compiler. + + The compiler should set an initial value with [default] before + any recursive call to [fixpoint]. Then, the compiler should + updates item for [f] or any other mutually-recursive symbol with + [f] by using [update]. It is a fatal-error to call [declare] on + a symbol currently compiled by [fixpoint]. + + The mutually recursive calls to [fixpoint] are detected, and + associated compilers are run until stabilisation. All + mutually-recursive symbols are finally declared and defined with + their last updates. *) + +val default : id -> item -> unit +val update : id -> item -> description -> unit + +(** {3 Retrieving Definitions} *) + +val get_item : id -> item + (** Raise [Not_found] if the symbol is undefined. *) + +val get_description : id -> description + (** Raise [Not_found] if the symbol is undefined. *) + +val get_declaration : id -> declaration + (** Raise [Not_found] if the symbol is undefined. *) + +(* -------------------------------------------------------------------------- *) +(* --- History Management --- *) +(* -------------------------------------------------------------------------- *) + +val mark_history : unit -> unit +val model_age : unit -> int + +val export_items : (declaration list -> unit) -> id list -> unit +val export_goal : (declaration list -> unit) -> pred -> unit + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicHavoc.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicHavoc.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicHavoc.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicHavoc.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,140 @@ +(* -------------------------------------------------------------------------- *) +(* --- Havoc --- *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau +open LogicLang + +type region = + | Full + | Empty + | Field of field_region list (* SORTED & MERGED *) + | Index of tau list * index_region list (* SAME SIGNATURE *) + +and field_region = field * region +and index_region = ( term list -> pred ) * region (* FULL or FIELD region *) + +(* -------------------------------------------------------------------------- *) +(* --- Merge Operations --- *) +(* -------------------------------------------------------------------------- *) + +let rec merge_signature ts1 ts2 = + match ts1,ts2 with + | [],ts | ts,[] -> ts + | t1::ts1 , t2::ts2 -> + if compare_tau t1 t2 <> 0 then + failwith "merge incompatible index during havoc" ; + t1 :: merge_signature ts1 ts2 + +let rec merge r1 r2 = + match r1 , r2 with + | Full , _ | _ , Full -> Full + | Empty , r | r , Empty -> r + | Field _ , Index _ | Index _ , Field _ -> + failwith "merge field and index during havoc" + | Field fs1 , Field fs2 -> Field (merge_fields fs1 fs2) + | Index (ts1,ks1) , Index (ts2,ks2) -> + let ts = merge_signature ts1 ts2 in + Index( ts , ks1 @ ks2 ) (* Extension is natural *) + +and merge_fields fs1 fs2 = + match fs1 , fs2 with + | [] , fs | fs , [] -> fs + | ((f1,r1) as h1)::ftail1 , ((f2,r2) as h2)::ftail2 -> + let cmp = compare_field f1 f2 in + if cmp < 0 then h1 :: merge_fields ftail1 fs2 else + if cmp > 0 then h2 :: merge_fields fs1 ftail2 else + (f1 , merge r1 r2) :: merge_fields ftail1 ftail2 + +(* -------------------------------------------------------------------------- *) +(* --- Constructors --- *) +(* -------------------------------------------------------------------------- *) + +let rec shift d = function + | _::xs when d>0 -> shift (pred d) xs + | xs -> xs + +let fsort (f1,_) (f2,_) = compare_field f1 f2 + +let empty = Empty +let full = Full + +let field fs f r = + if r = Empty then Empty else + Field (List.map + (fun g -> g , if compare_field f g = 0 then r else Empty) + (List.sort compare_field fs)) + +let fields frs = + if List.for_all (fun (_,r) -> r = Empty) frs then Empty else + if List.for_all (fun (_,r) -> r = Full) frs then Full else + Field (List.sort fsort frs) + +let matrix ts cond = function + | Empty -> Empty + | (Field _ | Full) as r -> Index(ts,[cond,r]) + | Index(ts0,kregions) -> + let d = List.length ts in + let gregions = List.map + (fun (cond0,r0) -> + let gcond = fun xs -> p_and (cond xs) (cond0 (shift d xs)) in + gcond , r0) + kregions + in + Index( ts @ ts0 , gregions ) + +let array t cond = function + | Empty -> Empty + | region -> matrix [t] (fun ts -> cond (List.hd ts)) region + +let in_range a b k = p_and (p_icmp Cleq a k) (p_icmp Cleq k b) +let index term r = array Integer (p_equal term) r +let range a b r = array Integer (in_range a b) r + +(* -------------------------------------------------------------------------- *) +(* --- Havoc Relation --- *) +(* -------------------------------------------------------------------------- *) + +let forall xs p = List.fold_right p_forall xs p +let access a ks = List.fold_left e_access a ks + +let only_one_region vs kregions : ( pred * region ) list = + let kregions = Array.of_list kregions in + Array.to_list + (Array.mapi + (fun i (_,region) -> + let conds_i = + Array.mapi + (fun j (cond,_) -> + let p = cond vs in + if i=j then p else p_not p) + kregions + in + p_conj (Array.to_list conds_i) , region + ) kregions) + +let rec is_havoc pool x1 x2 = function + | Empty -> p_equal x1 x2 + | Full -> p_true + | Field fs -> + List.fold_left + (fun w (f,r) -> + p_and w (is_havoc pool (e_getfield x1 f) (e_getfield x2 f) r)) + p_true fs + | Index(ts,ks) -> + let xs = List.map (LogicLib.fresh pool) ts in + let vs = List.map e_var xs in + let a1_xs = access x1 vs in + let a2_xs = access x2 vs in + let all_diff_then_equal = + forall xs + (p_implies + (p_conj (List.map (fun (cond,_) -> p_not (cond vs)) ks)) + (p_equal a1_xs a2_xs)) in + let only_once_then_region = + List.map + (fun (condition,region) -> + forall xs (p_implies condition (is_havoc pool a1_xs a2_xs region)) + ) (only_one_region vs ks) in + p_conj (all_diff_then_equal :: only_once_then_region) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicHavoc.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicHavoc.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicHavoc.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicHavoc.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,21 @@ + +open LogicId +open LogicTau +open LogicLang + +type region + +val empty : region +val full : region + +val fields : ( field * region ) list -> region +val field : field list -> field -> region -> region + (** [field fs f r] is [empty] for all [fs] except [f] for which it is [r] *) + +val index : term -> region -> region +val range : term -> term -> region -> region +val array : tau -> (term -> pred) -> region -> region +val matrix : tau list -> (term list -> pred) -> region -> region + +val is_havoc : pool -> term -> term -> region -> pred + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicId.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicId.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicId.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicId.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,257 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Logic Identifiers --- *) +(* -------------------------------------------------------------------------- *) + +type id = string * int + +module S = +struct + + type t = id + let compare = Pervasives.compare + let hash = Hashtbl.hash + let equal = (=) + let pretty fmt (x,k) = Format.fprintf fmt "%s%%%d" x k + +end + +include S + +module Iset = Set.Make(S) +module Imap = Map.Make(S) +module Ihmap = Hashtbl.Make(S) +module Kset = Set.Make(String) +module Kmap = Map.Make(String) + +let idref = ref 0 +let idfree = ref [] +let dummy = ("",0) +let extern = ref Kmap.empty + +let create a = + match !idfree with + | [] -> incr idref ; a , !idref + | k::ks -> idfree := ks ; a , k + +let basename a = fst a + +let library lnk = + try Kmap.find lnk !extern + with Not_found -> + let eid = create lnk in + extern := Kmap.add lnk eid !extern ; eid + +type allocator = { + mutable index : int ; (* last used indice *) + mutable free : int list ; (* free list *) + mutable based : bool ; (* base only allocated *) + mutable count : int ; (* touched *) +} + +type space = { + mutable alloc : (string,allocator) Hashtbl.t ; + mutable locals : Iset.t ; + mutable reserved : Kset.t ; + indices : indice Ihmap.t ; +} and indice = + | Base | Idx of int | Link of string + +let allocator space base = + try Hashtbl.find space.alloc base + with Not_found -> + let a = { index=0 ; based=false ; free=[] ; count=0 } in + Hashtbl.add space.alloc base a ; a + +let unalloc space id = + idfree := snd id :: !idfree ; + try + let k = Ihmap.find space.indices id in + let a = Hashtbl.find space.alloc (fst id) in + match k with + | Base -> a.based <- false + | Idx k -> a.free <- k :: a.free + | Link k -> space.reserved <- Kset.remove k space.reserved + with Not_found -> () + +let push space a = + let id = create a in + space.locals <- Iset.add id space.locals ; id + +let pop space id = + if not (Iset.mem id space.locals) then + Wp_parameters.fatal "LogicId: non-local %a" pretty id ; + space.locals <- Iset.remove id space.locals ; + unalloc space id + +type mark = Iset.t + +let mark space = space.locals +let unmark space mark = + Iset.iter + (fun id -> + if not (Iset.mem id mark) then unalloc space id + ) space.locals ; + space.locals <- mark + +let clear space = + Iset.iter (unalloc space) space.locals ; + space.locals <- Iset.empty + +let reserve1 space key = + if Kset.mem key space.reserved then + Wp_parameters.fatal "Already reserved name '%s'" key ; + space.reserved <- Kset.add key space.reserved ; + try + let a = Hashtbl.find space.alloc key in + if a.based then Wp_parameters.fatal + "Reserved name '%s' clashes with named identifier" key + with Not_found -> () + +let reserved space = List.iter (reserve1 space) + +let link space id key = + reserve1 space key ; + Ihmap.add space.indices id (Link key) + +let space () = + let s = { + alloc = Hashtbl.create 131 ; + locals = Iset.empty ; + indices = Ihmap.create 257 ; + reserved = Kset.empty ; + } in + Kmap.iter (fun lnk id -> link s id lnk) !extern ; s + +let indice space unique id = + try Ihmap.find space.indices id + with Not_found -> + let base = fst id in + let a = allocator space base in + let idx = + if not a.based && + (unique || ( a.index=0 && a.count=1 )) && + not (Kset.mem base space.reserved) + then (a.based <- true ; Base) + else match a.free with + | [] -> + let k = succ a.index in + a.index <- k ; Idx k + | k::ks -> + a.free <- ks ; Idx k + in + Ihmap.add space.indices id idx ; idx + +let name space ?(unique=false) id = + match indice space unique id with + | Base -> fst id + | Idx k -> Printf.sprintf "%s_%d" (fst id) k + | Link s -> s + +let unique space id = ignore (indice space true id) + +let pp_id space fmt id = + match indice space false id with + | Base -> Format.pp_print_string fmt (fst id) + | Idx k -> Format.fprintf fmt "%s_%d" (fst id) k + | Link s -> Format.pp_print_string fmt s + +let touch space id = + let a = allocator space (fst id) in + a.count <- succ a.count + +let copy space = { + alloc = Hashtbl.copy space.alloc ; + indices = Ihmap.copy space.indices ; + locals = space.locals ; + reserved = space.reserved ; +} + +let iter f space = + Ihmap.iter + (fun id idx -> + let name = match idx with + | Base -> fst id + | Idx k -> Printf.sprintf "%s_%d" (fst id) k + | Link s -> s + in f id name) + space.indices + +(* -------------------------------------------------------------------------- *) +(* --- Alphanumerical Sorting --- *) +(* -------------------------------------------------------------------------- *) + +type tk = Letter | Digit | Symbol | End + +let letter s k = + if k < String.length s then + let c = s.[k] in + if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') then Letter + else if ('0' <= c && c <= '9') then Digit else Symbol + else End + +let rec extend s k u = + let k = succ k in + let v = letter s k in + if v == u then extend s k u else k + +let rec compare_token a b ka kb = + let ca = letter a ka in + let cb = letter b kb in + match ca , cb with + | End , End -> 0 + | End , _ -> (-1) + | _ , End -> 1 + | Letter , Letter -> + let pa = extend a ka Letter in + let pb = extend b kb Letter in + let sa = String.sub a ka (pa-ka) in + let sb = String.sub b kb (pb-kb) in + let ua = String.uppercase sa in + let ub = String.uppercase sb in + let ucmp = String.compare ua ub in + if ucmp <> 0 then ucmp else + let scmp = String.compare sa sb in + if scmp <> 0 then scmp else + compare_token a b pa pb + | Letter , _ -> (-1) + | _ , Letter -> 1 + | Digit , Digit -> + let pa = extend a ka Digit in + let pb = extend b kb Digit in + let sa = String.sub a ka (pa-ka) in + let sb = String.sub b kb (pb-kb) in + let kcmp = Pervasives.compare (int_of_string sa) (int_of_string sb) in + if kcmp <> 0 then kcmp else + let scmp = String.compare sa sb in + if scmp <> 0 then scmp else + compare_token a b pa pb + | Digit , _ -> (-1) + | _ , Digit -> 1 + | Symbol , Symbol -> + let cmp = Char.compare a.[ka] b.[kb] in + if cmp <> 0 then cmp else + compare_token a b (succ ka) (succ kb) + +let alpha x y = compare_token x y 0 0 diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicId.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicId.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicId.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicId.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,89 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Logical Identifiers *) + +type id +val library : string -> id (** Returns an id for an external symbol *) +val create : string -> id (** Create a new fresh identifier with the given basename *) +val basename : id -> string + +(** {3 Datatype} *) + +type t = id +val compare : id -> id -> int +val equal : id -> id -> bool +val hash : id -> int +val pretty : Format.formatter -> id -> unit +val dummy : id (** Only usable for represent in projectified definitions *) + +(** {3 Map and Set} *) + +module Iset : Set.S with type elt = t +module Imap : Map.S with type key = t +module Ihmap : Hashtbl.S with type key = t + +(** {3 Name Spaces} *) + +type space +val space : unit -> space (** Creates an empty name space (but with the external names). *) +val copy : space -> space (** Duplicates a name space. *) + +val link : space -> id -> string -> unit + (** Link the identifier to some absolute name. + Also reserves this name. *) + +val reserved : space -> string list -> unit + (** Reserves the given names to avoid clash with generated ones. *) + +val name : space -> ?unique:bool -> id -> string + (** Assigns a unique string to an identifier in the space. + When flag [unique] is set to true, the generated name + is preferrably the basename of the identifier. *) + +val pp_id : space -> Format.formatter -> id -> unit + (** Combines [name] and [Format]. *) + +val unique : space -> id -> unit + (** Reserves the identifier to be assigned its basename as name, if possible. + Same as using [name space ~unique:true id]. *) + +val touch : space -> id -> unit + (** Count the identifier in the space. + If the identifier has been counted exactly once, + the first time its name is asked, the basename would be + assigned to it. *) + +val push : space -> string -> id (* Allocate a local identifier in the space name *) +val pop : space -> id -> unit (* Deallocate a local identifier from the space name *) +val clear : space -> unit (* Deallocate all local identifiers *) + +type mark +val mark : space -> mark (* Marks all current locals *) +val unmark : space -> mark -> unit (* Deallocate non-marked locals *) + +val iter : (id -> string -> unit) -> space -> unit + +(** {3 Sorting} *) + +val alpha : string -> string -> int + (** User-friendly name sorting. Namely: [a<A<b] and [1<10]. *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicLang.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicLang.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicLang.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicLang.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,214 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Logical Language --- *) +(* -------------------------------------------------------------------------- *) + +open LogicTau +open LogicRaw + +(* -------------------------------------------------------------------------- *) +(* --- Primitives --- *) +(* -------------------------------------------------------------------------- *) + +type integer_op = Iadd | Isub | Imul | Idiv | Imod +type real_op = Radd | Rsub | Rmul | Rdiv +type cmp_op = Ceq | Cneq | Clt | Cleq + +(* -------------------------------------------------------------------------- *) +(* --- Primitives --- *) +(* -------------------------------------------------------------------------- *) + +type term = TERM.t +type pred = PRED.t + +let e_call f ts = TERM.e_call f ts +let p_call f xs = PRED.p_call f xs + +(* -------------------------------------------------------------------------- *) +(* --- Arithmetics --- *) +(* -------------------------------------------------------------------------- *) + +let e_true = TERM.Ttrue +let e_false = TERM.Tfalse +let e_zero = TERM.e_zero +let e_int = TERM.e_int +let e_float k = TERM.Treal(string_of_float k) +let e_bigint z = TERM.Tint(My_bigint.to_string z) +let e_icst z = TERM.Tint z +let e_rcst z = TERM.Treal z + +let unop f a = TERM.e_prim f [a] +let binop f a b = TERM.e_prim f [a;b] +let predop f a b = PRED.p_prim f [a;b] + +let i_pred = function + | Ceq -> PRED.L_eq + | Cneq -> PRED.L_neq + | Clt -> PRED.I_lt + | Cleq -> PRED.I_leq + +let i_bool = function + | Ceq -> TERM.L_eq + | Cneq -> TERM.L_neq + | Clt -> TERM.I_lt + | Cleq -> TERM.I_leq + +let i_op = function + | Iadd -> TERM.I_add + | Isub -> TERM.I_sub + | Imul -> TERM.I_mul + | Idiv -> TERM.I_div + | Imod -> TERM.I_mod + +let r_pred = function + | Ceq -> PRED.L_eq + | Cneq -> PRED.L_neq + | Clt -> PRED.R_lt + | Cleq -> PRED.R_leq + +let r_bool = function + | Ceq -> TERM.L_eq + | Cneq -> TERM.L_neq + | Clt -> TERM.R_lt + | Cleq -> TERM.R_leq + +let r_op = function + | Radd -> TERM.R_add + | Rsub -> TERM.R_sub + | Rmul -> TERM.R_mul + | Rdiv -> TERM.R_div + +let e_ineg = unop TERM.I_opp +let e_rneg = unop TERM.R_opp + +let e_icmp op = binop (i_bool op) +let p_icmp op = predop (i_pred op) + +let e_rcmp op = binop (r_bool op) +let p_rcmp op = predop (r_pred op) + +let p_equal = predop PRED.L_eq +let p_neq = predop PRED.L_neq + +let e_iop op = binop (i_op op) +let e_rop op = binop (r_op op) + +let e_real_of_int = unop TERM.R_of_I +let e_int_of_real = unop TERM.I_of_R + +let a_true = e_int 1 +let a_false = e_int 0 + +let e_bool c = TERM.e_cond c a_true a_false +let e_cond c a b = TERM.e_cond c a b + +let e_not = TERM.e_not +let e_and = TERM.e_and +let e_or = TERM.e_or + +let e_bnot = unop TERM.I_bnot +let e_band = binop TERM.I_band +let e_bor = binop TERM.I_bor +let e_bxor = binop TERM.I_bxor +let e_lshift = binop TERM.I_lsl +let e_rshift = binop TERM.I_lsr + +let e_getfield = TERM.e_getfield +let e_setfield = TERM.e_setfield +let e_access = TERM.e_access +let e_update = TERM.e_update + +(* -------------------------------------------------------------------------- *) +(* --- Predicates --- *) +(* -------------------------------------------------------------------------- *) + +let p_true = PRED.Ptrue +let p_false = PRED.Pfalse +let p_bool = PRED.p_bool +let p_not = PRED.p_not +let p_implies = PRED.p_implies +let p_and = PRED.p_and +let p_or = PRED.p_or +let p_xor = PRED.p_xor +let p_iff = PRED.p_iff +let p_cond = PRED.p_cond + +let p_named label p = PRED.Pnamed(label,p) +let p_hide p = p + +let rec p_conj = function + | [] -> PRED.Ptrue | [p] -> p + | p::ps -> PRED.p_and p (p_conj ps) + +let rec p_disj = function + | [] -> PRED.Pfalse | [p] -> p + | p::ps -> PRED.p_or p (p_disj ps) + +let rec p_goal hs p = match hs with + | [] -> p + | h::hs -> PRED.p_implies h (p_goal hs p) + +(* -------------------------------------------------------------------------- *) +(* --- Variables --- *) +(* -------------------------------------------------------------------------- *) + +type var = VAR.t +type pool = VAR.pool + +let tau_of_var = VAR.tau_of_var +let pool = VAR.pool +let fresh = VAR.fresh +let e_var x = TERM.Tvar x +let e_let = SUBST.e_let +let p_let = SUBST.p_let +let p_forall = PRED.p_forall +let p_exists = PRED.p_exists +let is_atomic = SUBST.is_atomic + +module Vmap = VMAP +module Vset = VSET + +(* -------------------------------------------------------------------------- *) +(* --- PRETTY PRINTING --- *) +(* -------------------------------------------------------------------------- *) + +let space = LogicId.space () +let () = LogicId.reserved space [ + "if" ; "then" ; "let" ; "in" ; + "pointer" ; + "and" ; "or" ; "not" ; "forall" ; "exists" ; +] + +let pretty = new LogicPretty.engine space +let pp_tau = pretty#pp_tau +let pp_term = pretty#alpha pretty#pp_term +let pp_pred = pretty#alpha pretty#pp_pred + +(* -------------------------------------------------------------------------- *) +(* --- DEPENDENCIES --- *) +(* -------------------------------------------------------------------------- *) + +let add_depend_tau = LogicTau.depend +let add_depend_term = TERM.depend +let add_depend_pred = PRED.depend diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicLang.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicLang.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicLang.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicLang.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,151 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Logical Language *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau + +(* -------------------------------------------------------------------------- *) +(** {2 Primitives} *) +(* -------------------------------------------------------------------------- *) + +type integer_op = Iadd | Isub | Imul | Idiv | Imod +type real_op = Radd | Rsub | Rmul | Rdiv +type cmp_op = Ceq | Cneq | Clt | Cleq + +(* -------------------------------------------------------------------------- *) +(** {2 Terms} *) +(* -------------------------------------------------------------------------- *) + +type term + +(** {3 Primitives} *) + +val e_true : term +val e_false : term +val e_zero : term +val e_int : int -> term +val e_float : float -> term +val e_bigint : My_bigint.t -> term +val e_icst : string -> term +val e_rcst : string -> term + +(** {3 Arithmetics} *) + +val e_ineg : term -> term +val e_rneg : term -> term +val e_iop : integer_op -> term -> term -> term +val e_rop : real_op -> term -> term -> term +val e_icmp : cmp_op -> term -> term -> term +val e_rcmp : cmp_op -> term -> term -> term + +val e_bnot : term -> term +val e_band : term -> term -> term +val e_bor : term -> term -> term +val e_bxor : term -> term -> term +val e_lshift : term -> term -> term +val e_rshift : term -> term -> term + +val e_int_of_real : term -> term +val e_real_of_int : term -> term + +(** {3 Booleans} *) + +val e_not : term -> term +val e_and : term -> term -> term +val e_or : term -> term -> term + +(** {3 Structures} *) + +val e_getfield : term -> field -> term +val e_setfield : term -> field -> term -> term +val e_access : term -> term -> term +val e_update : term -> term -> term -> term + +(** {2 Predicates} *) + +type pred + +val p_true : pred +val p_false : pred +val p_bool : term -> pred +val p_not : pred -> pred +val p_and : pred -> pred -> pred +val p_or : pred -> pred -> pred +val p_xor : pred -> pred -> pred +val p_implies : pred -> pred -> pred +val p_iff : pred -> pred -> pred + +val p_icmp : cmp_op -> term -> term -> pred +val p_rcmp : cmp_op -> term -> term -> pred +val p_equal : term -> term -> pred +val p_neq : term -> term -> pred + +val p_conj : pred list -> pred +val p_disj : pred list -> pred +val p_goal : pred list -> pred -> pred + +(** {2 Generic Terms and Formulas} *) + +val e_call : id -> term list -> term +val p_call : id -> term list -> pred + +val e_cond : term -> term -> term -> term +val p_cond : term -> pred -> pred -> pred + +val p_named : id -> pred -> pred +val p_hide : pred -> pred + +(** {2 Variables} *) + +type var +type pool + +val pool : unit -> pool +val fresh : pool -> string -> tau -> var + +val e_var : var -> term +val e_let : ?pool:pool -> var -> term -> term -> term +val p_let : ?pool:pool -> var -> term -> pred -> pred +val p_forall : var -> pred -> pred +val p_exists : var -> pred -> pred + +val tau_of_var : var -> tau +val is_atomic : term -> bool + +module Vset : Set.S with type elt = var +module Vmap : Map.S with type key = var + +(** {2 Pretty Printers} *) + +val pp_tau : Format.formatter -> tau -> unit +val pp_term : Format.formatter -> term -> unit +val pp_pred : Format.formatter -> pred -> unit + +(** {2 Dependencies} *) + +val add_depend_tau : Iset.t -> tau -> Iset.t +val add_depend_term : Iset.t -> term -> Iset.t +val add_depend_pred : Iset.t -> pred -> Iset.t diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicLib.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicLib.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicLib.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicLib.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,28 @@ +(* -------------------------------------------------------------------------- *) +(* --- LogicLang Tools w.r.t access paths --- *) +(* -------------------------------------------------------------------------- *) + +open LogicTau +open LogicLang + +let basename = function + | Integer -> "k" + | Real -> "z" + | Boolean -> "c" + | Pointer -> "p" + | ADT(id,_) | Record id -> LogicId.basename id + | Array _ -> "A" + | Set _ -> "S" + | ALPHA _ -> "x" + +let fresh pool tau = fresh pool (basename tau) tau + +let e_shared pool tau term f = + if is_atomic term then f term else + let x = fresh pool tau in + e_let x term (f (e_var x)) + +let p_shared pool tau term f = + if is_atomic term then f term else + let x = fresh pool tau in + p_let x term (f (e_var x)) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicLib.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicLib.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicLib.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicLib.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,9 @@ +(** Logic Path & Regions *) + +open LogicTau +open LogicLang + +val basename : tau -> string +val fresh : pool -> tau -> var +val e_shared : pool -> tau -> term -> (term -> term) -> term +val p_shared : pool -> tau -> term -> (term -> pred) -> pred diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicPretty.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicPretty.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicPretty.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicPretty.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,541 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Logical Language --- *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau +open LogicRaw +let dkey = "pretty" (* debugging key *) + +type u_printer = Format.formatter -> unit +type 'a printer = Format.formatter -> 'a -> unit +type ('a,'b) printer2 = Format.formatter -> 'a -> 'b -> unit +type 'a fun_printer = Format.formatter -> 'a -> TERM.t list -> unit + +(* -------------------------------------------------------------------------- *) +(* --- Tools --- *) +(* -------------------------------------------------------------------------- *) + +let pp_coma sep pp fmt = function + | [] -> () + | x::xs -> pp fmt x ; List.iter (fun y -> Format.fprintf fmt "%s@ %a" sep pp y) xs + +let pp_assoc nil op pp fmt = function + | [] -> Format.pp_print_string fmt nil + | x::xs -> pp fmt x ; List.iter (fun y -> Format.fprintf fmt "@ %s@ %a" op pp y) xs + +let rec pp_fold_op nil op pp fmt = function + | [] -> Format.pp_print_string fmt nil + | [x] -> pp fmt x + | [x;y] -> Format.fprintf fmt "%a@ %s@ %a" pp x op pp y ; + | x::xs -> Format.fprintf fmt "%a@ %s@ (%a)" pp x op (pp_fold_op nil op pp) xs + +let rec pp_fold_call nil op pp fmt = function + | [] -> Format.pp_print_string fmt nil + | [x] -> pp fmt x + | x::xs -> Format.fprintf fmt "@[<hov 1>%s(%a,@,%a)@]" + op pp x (pp_fold_call nil op pp) xs + +let rec pp_fold_apply nil op pp fmt = function + | [] -> Format.pp_print_string fmt nil + | [x] -> pp fmt x + | x::xs -> Format.fprintf fmt "@[<hov 1>(%s@ %a@ %a)@]" + op pp x (pp_fold_apply nil op pp) xs + +let pp_tuple pp fmt xs = Format.fprintf fmt "@[<hov 1>(%a)@]" (pp_coma "," pp) xs + +let pp_string op fmt = Format.pp_print_string fmt op + +let pp_tuple_call pp fmt f xs = + Format.fprintf fmt "@[<hov 1>%s%a@]" f (pp_tuple pp) xs + +let pp_apply_call pp fmt f = function + | [] -> Format.pp_print_string fmt f + | xs -> + Format.fprintf fmt "@[<hov 1>(%s" f ; + List.iter (fun x -> Format.fprintf fmt "@ %a" pp x) xs ; + Format.fprintf fmt ")@]" + +open VAR +open TERM +open PRED + +let rec apply_labels p = function + | [] -> p | label::labels -> Pnamed(label,apply_labels p labels) + +let rec fold_and acc labels = function + | Pnamed(label,p) -> fold_and acc (label::labels) p + | Pand(p,q) -> fold_and (fold_and acc labels q) labels p + | Ptrue -> acc + | p -> apply_labels p labels :: acc + +let rec fold_hyp acc labels = function + | Pnamed(label,p) -> fold_hyp acc (label::labels) p + | Pand(p,q) -> fold_hyp (fold_hyp acc labels p) labels q + | Ptrue -> acc + | p -> apply_labels p labels :: acc + +let rec fold_or acc labels = function + | Pnamed(label,p) -> fold_or acc (label::labels) p + | Por(p,q) -> fold_or (fold_or acc labels q) labels p + | Pfalse -> acc + | p -> apply_labels p labels :: acc + +let rec fold_implies hs labels = function + | Pimplies(p,q) -> fold_implies (fold_and hs labels p) [] q + | Pnamed(label,p) -> fold_implies hs (label::labels) p + | p -> List.rev hs , apply_labels p labels + +let collect_and p = fold_and [] [] p +let collect_or p = fold_or [] [] p +let collect_implies p = fold_implies [] [] p + +let rec fold_assoc op acc = function + | Tprim( f , ts ) when op = f -> List.fold_left (fold_assoc op) acc ts + | e -> e::acc + +let associative op es = List.fold_left (fold_assoc op) [] es + +let rec collect_labels ls = function + | Pnamed(l,p) -> collect_labels (l::ls) p + | p -> List.rev ls , p + +let rec collect_forall xs = function + | Pforall(x,p) -> collect_forall (x::xs) p + | p -> List.rev xs , p + +let rec collect_exists xs = function + | Pexists(x,p) -> collect_exists (x::xs) p + | p -> List.rev xs , p + +type call_style = + | FunCall + | VFunCall + | ApplyCall + +let pp_call_style style pp_atom pp_free fmt f es = + match style , es with + | (VFunCall|ApplyCall) , [] -> Format.pp_print_string fmt f + | (VFunCall|FunCall) , _ -> pp_tuple_call pp_free fmt f es + | ApplyCall , _ -> pp_apply_call pp_atom fmt f es + +type operator = + | Infix of string + | Prefix of string + | Postfix of string + | Assoc of string * string + | Extern of string + | Call of id + +let operator_atomic = function + | Prefix _ | Postfix _ | Call _ | Extern _ -> true + | Infix _ | Assoc _ -> false + +type binder = VAR.t * id + +class engine (space:LogicId.space) = +object(self) + + (* -------------------------------------------------------------------------- *) + (* --- Names --- *) + (* -------------------------------------------------------------------------- *) + + method id x = LogicId.name space x + method pp_id fmt x = Format.pp_print_string fmt (self#id x) + + (* -------------------------------------------------------------------------- *) + (* --- Types --- *) + (* -------------------------------------------------------------------------- *) + + method pp_tau_int = pp_string "int" + method pp_tau_real = pp_string "real" + method pp_tau_bool = pp_string "bool" + method pp_tau_pointer = pp_string "pointer" + method pp_tau_set fmt te = Format.fprintf fmt "{%a..}" self#pp_tau te + method pp_tau_array fmt ta tb = + match ta with + | Integer -> Format.fprintf fmt "@[%a[]@]" self#pp_tau tb + | _ -> Format.fprintf fmt "@[%a[%a]@]" self#pp_tau tb self#pp_tau ta + method pp_tau_record = self#pp_id + method pp_tau_adt fmt a ts = + match ts with + | [] -> self#pp_id fmt a + | [t] -> Format.fprintf fmt "@[%a %a@]" self#pp_tau t self#pp_id a + | ts -> Format.fprintf fmt "@[%a %a@]" (pp_tuple self#pp_tau) ts self#pp_id a + method pp_tau_alpha fmt k = + if 0<= k && k < 26 + then Format.fprintf fmt "'%c" (char_of_int (int_of_char 'a' + k)) + else Format.fprintf fmt "'a%d" k + + method pp_tau fmt = function + | Integer -> self#pp_tau_int fmt + | Real -> self#pp_tau_real fmt + | Boolean -> self#pp_tau_bool fmt + | Pointer -> self#pp_tau_pointer fmt + | Set te -> self#pp_tau_set fmt te + | Array(ta,tb) -> self#pp_tau_array fmt ta tb + | Record r -> self#pp_tau_record fmt r + | ADT(a,ts) -> self#pp_tau_adt fmt a ts + | ALPHA n -> self#pp_tau_alpha fmt n + + (* -------------------------------------------------------------------------- *) + (* --- Variables --- *) + (* -------------------------------------------------------------------------- *) + + val mutable sigma : id VMAP.t = VMAP.empty + val mutable alpha : bool = false + + method bind (xs:VAR.t list) (pp:unit -> unit) = + let mark = LogicId.mark space in + let sigma0 = sigma in + sigma <- List.fold_left + (fun sigma x -> + let xid = LogicId.push space (VAR.basename x) in + VMAP.add x xid sigma) + sigma xs ; + try + pp () ; + sigma <- sigma0 ; + if not alpha then LogicId.unmark space mark ; + with error -> + sigma <- sigma0 ; + if not alpha then LogicId.unmark space mark ; + raise error + + method binder (x:VAR.t) (pp:binder -> unit) = + let xid = LogicId.push space (VAR.basename x) in + try + pp (x,xid) ; + if not alpha then LogicId.pop space xid ; + with error -> + if not alpha then LogicId.pop space xid ; + raise error + + method pp_binder fmt (_,id) = self#pp_id fmt id + method with_binder : 'a. binder -> 'a printer -> 'a printer = + fun (x,xid) pp fmt data -> + let sigma0 = sigma in + sigma <- VMAP.add x xid sigma ; + try + pp fmt data ; + sigma <- sigma0 ; + with error -> + sigma <- sigma0 ; + raise error + + method alpha : 'a. 'a printer -> 'a printer = fun pp fmt data -> + if alpha then pp fmt data + else + let mark = LogicId.mark space in + alpha <- true ; + try + pp fmt data ; + alpha <- false ; + LogicId.unmark space mark ; + with error -> + alpha <- false ; + LogicId.unmark space mark ; + raise error + + method var_id x = VMAP.find x sigma + method pp_var fmt x = + try self#pp_id fmt (VMAP.find x sigma) + with Not_found -> Format.fprintf fmt "?%a" VAR.pretty x + + method pp_vartype fmt x = self#pp_tau fmt (VAR.tau_of_var x) + + (* -------------------------------------------------------------------------- *) + (* --- Terms --- *) + (* -------------------------------------------------------------------------- *) + + method term_call = VFunCall + + method term_atomic = function + | Tint s | Treal s -> not ( String.length s > 0 && s.[0] = '-' ) + | Tvar _ | Tcall _ | Tprim(_,[]) | Ttrue | Tfalse -> true + | Tprim(pi,_) -> operator_atomic (self#term_operator pi) + | Tgetfield _ -> true + | Tsetfield _ -> true + | Taccess _ -> true + | Tupdate _ -> true + | Tif _ -> false + | Tlet _ -> false + + method term_operator = function + | I_add | R_add -> Assoc("0","+") + | I_mul | R_mul -> Assoc("1","*") + | I_div -> Infix("div") + | I_mod -> Infix("mod") + | I_sub | R_sub -> Infix("-") + | R_div -> Infix("/") + | I_opp | R_opp -> Prefix("-") + | I_of_R -> Prefix("(int)") + | R_of_I -> Prefix("") + | TERM.L_eq -> Infix("=") + | TERM.L_neq -> Infix("<>") + | TERM.I_lt | TERM.R_lt -> Infix("<") + | TERM.I_leq | TERM.R_leq -> Infix("<=") + | B_not -> Prefix("!") + | B_and -> Assoc("true","&&") + | B_or -> Assoc("false","||") + | I_bnot -> Prefix("~") + | I_band -> Infix("(&)") + | I_bor -> Infix("(|)") + | I_bxor -> Infix("(+)") + | I_lsl -> Infix("(>>)") + | I_lsr -> Infix("(<<)") + + method pp_term_int = Format.pp_print_string + method pp_term_real = Format.pp_print_string + method pp_term_true = pp_string "true" + method pp_term_false = pp_string "false" + + method pp_term_call fmt id es = + pp_call_style self#term_call self#pp_term_atom self#pp_term fmt (self#id id) es + + method pp_term_extern fmt f es = + pp_call_style self#term_call self#pp_term_atom self#pp_term fmt f es + + method pp_term_operator fmt op es = + match op , es with + | Infix s , [a;b] -> Format.fprintf fmt "%a@ %s@ %a" + self#pp_term_atom a s self#pp_term_atom b + | Prefix s , [a] -> Format.fprintf fmt "%s%a" s self#pp_term_atom a + | Postfix s , [a] -> Format.fprintf fmt "%a%s" self#pp_term_atom a s + | (Infix s | Postfix s | Prefix s) , _ -> + Wp_parameters.fatal "Logic:operator(%s) with %d arguments" s + (List.length es) + | Assoc(nil,op) , _ -> pp_assoc nil op self#pp_term_atom fmt es + | Call id , _ -> self#pp_term_call fmt id es + | Extern f , _ -> self#pp_term_extern fmt f es + + method pp_term_primitive fmt pi es = + let op = self#term_operator pi in + let es = match op with Assoc _ -> associative pi es | _ -> es in + self#pp_term_operator fmt op es + + method pp_term_getfield fmt r f = + Format.fprintf fmt "%a.%a" self#pp_term_atom r self#pp_id f.f_name + method pp_term_setfield fmt r f v = + Format.fprintf fmt "@[<hv 2>%a@,.{%a <-@ %a}@]" + self#pp_term_atom r self#pp_id f.f_name self#pp_term v + method pp_term_access fmt r k = + Format.fprintf fmt "%a[%a]" self#pp_term_atom r self#pp_term k + method pp_term_update fmt r k v = + Format.fprintf fmt "@[<hv 2>%a@,[%a <-@ %a]@]" + self#pp_term_atom r self#pp_term k self#pp_term v + + method pp_term_let fmt x a b = + self#binder x + (fun bind -> + Format.fprintf fmt "@[<hv 2>let %a = %a in@ @]%a" + self#pp_binder bind + self#pp_term a + (self#with_binder bind self#pp_term) b) + + method pp_term_cond fmt c a b = + if self#term_atomic a && self#term_atomic b then + Format.fprintf fmt "%a?%a:%a" + self#pp_term_atom c self#pp_term b self#pp_term c + else + Format.fprintf fmt "@[<hv 2>if %a@ then %a@ else %a@]" + self#pp_term c self#pp_term a self#pp_term b + + method pp_term_atom fmt e = + if self#term_atomic e then self#pp_term fmt e + else Format.fprintf fmt "@[<hov 1>(%a)@]" self#pp_term e + + method pp_term fmt = function + | Tvar x -> self#pp_var fmt x + | Ttrue -> self#pp_term_true fmt + | Tfalse -> self#pp_term_false fmt + | Tint z -> self#pp_term_int fmt z + | Treal z -> self#pp_term_real fmt z + | Tcall(f,ts) -> self#pp_term_call fmt f ts + | Tprim(pi,ts) -> self#pp_term_primitive fmt pi ts + | Tgetfield(r,f) -> self#pp_term_getfield fmt r f + | Tsetfield(r,f,v) -> self#pp_term_setfield fmt r f v + | Taccess(r,k) -> self#pp_term_access fmt r k + | Tupdate(r,k,v) -> self#pp_term_update fmt r k v + | Tlet(x,a,b) -> self#pp_term_let fmt x a b + | Tif(c,a,b) -> self#pp_term_cond fmt c a b + + (* -------------------------------------------------------------------------- *) + (* --- Predicates --- *) + (* -------------------------------------------------------------------------- *) + + method pred_atomic = function + | Ptrue | Pfalse | Prel(_,[]) | Pcall _ -> true + | Prel(r,_) -> operator_atomic (self#pred_relation r) + | _ -> false + + method pred_relation = function + | PRED.I_lt | PRED.R_lt -> Infix("<") + | PRED.I_leq | PRED.R_leq -> Infix("<=") + | PRED.L_eq -> Infix("=") + | PRED.L_neq -> Infix("<>") + | B_false -> Prefix "" + | B_true -> Prefix "" + + method pp_pred_true = pp_string "True" + method pp_pred_false = pp_string "False" + method pp_pred_relation fmt rel es = + self#pp_term_operator fmt (self#pred_relation rel) es + method pp_pred_call fmt id ts = + self#pp_term_call fmt id ts + + method pp_pred_and = pp_assoc "True" "/\\" self#pp_pred_atom + method pp_pred_or = pp_assoc "False" "\\/" self#pp_pred_atom + method pp_pred_not fmt p = Format.fprintf fmt "not %a" self#pp_pred_atom p + method pp_pred_iff fmt p q = Format.fprintf fmt "%a@ <->@ %a" + self#pp_pred_atom p self#pp_pred_atom q + + method pp_pred_cond fmt c p q = + Format.fprintf fmt "if %a@ then %a@ else %a" + self#pp_term c self#pp_pred p self#pp_pred q + + method pp_pred_let fmt x a p = + self#binder x + (fun bind -> + Format.fprintf fmt "@[<hv 2>let %a = %a in@ @]%a" + self#pp_binder bind + self#pp_term a + (self#with_binder bind self#pp_pred) p) + + method pp_pred_named fmt labels p = + List.iter + (fun label -> Format.fprintf fmt "%a:@," self#pp_id label) + labels ; + self#pp_pred_atom fmt p + + method pp_pred_implies fmt hs p = + List.iter + (fun h -> Format.fprintf fmt "%a ->@ " self#pp_pred_atom h) hs ; + self#pp_pred fmt p + + method pp_pred_forall fmt xs p = + Format.fprintf fmt "@[<hov 2>forall " ; + self#bind xs + (fun () -> + pp_coma "," + (fun fmt x -> + Format.fprintf fmt "%a:%a" + self#pp_var x self#pp_vartype x) + fmt xs ; + Format.fprintf fmt ".@]@ %a" self#pp_pred p) + + method pp_pred_exists fmt xs p = + Format.fprintf fmt "@[<hov 2>exists " ; + self#bind xs + (fun () -> + pp_coma "," + (fun fmt x -> + Format.fprintf fmt "%a:%a" + self#pp_var x self#pp_vartype x) + fmt xs ; + Format.fprintf fmt ".@]@ %a" self#pp_pred p) + + method pp_pred fmt = function + | Ptrue -> self#pp_pred_true fmt + | Pfalse -> self#pp_pred_false fmt + | Prel(r,es) -> self#pp_pred_relation fmt r es + | Pcall(f,es) -> self#pp_pred_call fmt f es + | Pand _ as p -> self#pp_pred_and fmt (collect_and p) + | Por _ as p -> self#pp_pred_or fmt (collect_or p) + | Pnot p -> self#pp_pred_not fmt p + | Piff(p,q) -> self#pp_pred_iff fmt p q + | Pcond(c,p,q) -> self#pp_pred_cond fmt c p q + | Plet(x,a,p) -> self#pp_pred_let fmt x a p + | Pnamed(label,p) -> + let labels,p = collect_labels [label] p in + self#pp_pred_named fmt labels p + | Pimplies _ as p -> + let hs,p = collect_implies p in + self#pp_pred_implies fmt hs p + | Pforall(x,p) -> + let xs,p = collect_forall [x] p in + self#pp_pred_forall fmt xs p + | Pexists(x,p) -> + let xs,p = collect_exists [x] p in + self#pp_pred_exists fmt xs p + + method pp_pred_atom fmt p = + if self#pred_atomic p then self#pp_pred fmt p + else Format.fprintf fmt "@[<hov 1>(%a)@]" self#pp_pred p + +end + +(* -------------------------------------------------------------------------- *) + +(* WHY names, for informations + +(* --- PRELUDE.why --- *) + +let neg_int = "neg_int" +let add_int = "add_int" +let sub_int = "sub_int" +let mul_int = "mul_int" +let div_int = "computer_div" +let mod_int = "computer_mod" +let eq_int = "eq" +let ne_int = "neq" +let lt_int = "lt_int" +let le_int = "le_int" + +(* --- BOOL.why --- *) + +let bool_not = "bool_not" +let bool_and = "bool_and" +let bool_or = "bool_or" + +(* --- INTEGERS.why --- *) + +let eq_int_bool = "eq_int_bool" +let ne_int_bool = "neq_int_bool" +let lt_int_bool = "lt_int_bool" +let le_int_bool = "le_int_bool" + +(* --- REAL.why --- *) + +let neg_real = "neg_real" +let add_real = "add_real" +let sub_real = "sub_real" +let mul_real = "mul_real" +let fract_real = "div_real" + +let eq_real_bool = "eq_real_bool" +let ne_real_bool = "neq_real_bool" +let lt_real_bool = "lt_real_bool" +let le_real_bool = "le_real_bool" + +let eq_real = "eq_real" +let ne_real = "neq_real" +let lt_real = "lt_real" +let le_real = "le_real" + +let integer_of_real = "truncate_real_to_int" +let real_of_integer = "real_of_int" + +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicPretty.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicPretty.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicPretty.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicPretty.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,203 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Pretty Printing Library for Logic *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau +open LogicRaw + +type u_printer = Format.formatter -> unit (** Suitable for [%t] formatter *) +type 'a printer = Format.formatter -> 'a -> unit (** Suitable for [%a] formatter *) +type ('a,'b) printer2 = Format.formatter -> 'a -> 'b -> unit (** Non-formatter usage *) +type 'a fun_printer = Format.formatter -> 'a -> TERM.t list -> unit + +(** {2 Utilities} *) + +val pp_coma : string -> 'a printer -> 'a list printer + (** [pp_coma ","] produces ["x1, x2, ... xn"] *) + +val pp_assoc : string -> string -> 'a printer -> 'a list printer + (** [pp_assoc "0" "+"] produces ["x1 + x2 + ... + xn"] and ["0"] for empty list *) + +val pp_tuple : 'a printer -> 'a list printer + (** [pp_tuple] produces ["(x1, x2, ... )"] and ["()"] for empty list *) + +val pp_string : string -> u_printer + (** The [%t] printer that print the string *) + +val pp_tuple_call : 'a printer -> (string,'a list) printer2 + (** Prints ["f(x1,...,xn)"] and ["f()"] for empty list. *) + +val pp_apply_call : 'a printer -> (string,'a list) printer2 + (** Printts ["(f x1 ... xn)"] of ["f"] for empty list. *) + +val pp_fold_op : string -> string -> 'a printer -> 'a list printer + (** [pp_fold_op "0" "+"] prints ["x+(...(y+z))"] or ["0"]. *) + +val pp_fold_call : string -> string -> 'a printer -> 'a list printer + (** [pp_fold_call "e" "f"] prints ["f(x,f(...,f(y,z)))"] or ["e"]. *) + +val pp_fold_apply : string -> string -> 'a printer -> 'a list printer + (** [pp_fold_apply "e" "f"] prints ["(f x (f...(f y z)))"] or ["e"]. *) + +(** {2 Pretty printer engine} *) + +type binder + +type call_style = + | FunCall (** the [pp_tuple_call] style *) + | VFunCall (** the [pp_tuple_call] style with ["f"] for empty lists *) + | ApplyCall (** the [pp_apply_call] style *) + +type operator = + | Infix of string (** ["x (op) y"] *) + | Prefix of string (** ["x (op)"] *) + | Postfix of string (** ["(op) x"] *) + | Assoc of string * string + (** [Assoc(nil,op)] prints [nil] + for empty lists and associatively flatten infix [op] *) + | Extern of string (** call [s] with current call-style *) + | Call of id (** call [id] with current space and call-style *) + +class engine : LogicId.space -> +object + + (** {3 Names} *) + + method id : id -> string + method pp_id : id printer + + (** {3 Types} *) + + method pp_tau_int : u_printer + method pp_tau_real : u_printer + method pp_tau_bool : u_printer + method pp_tau_pointer : u_printer + method pp_tau_set : tau printer + method pp_tau_array : (tau,tau) printer2 + method pp_tau_record : id printer + method pp_tau_adt : (id,tau list) printer2 + method pp_tau_alpha : int printer + method pp_tau : tau printer + + (** {3 Variables} *) + + method alpha : 'a. 'a printer -> 'a printer + (** Runs the printer in an environment with global + alpha-conversion. The global alpha-conversion mode is + reverted after [alpha]. Successive calls to [alpha] keep the + global mode until the first call to [alpha] returns. + Exceptions are correctly tracked. *) + + method bind : 'a. VAR.t list -> (unit -> unit) -> unit + (** [bind x pp] runs [pp] with variable [x] bound to a new + identifier. The identifier is released after [bind] unless + the engine is in global alpha-conversion mode (see [alpha]). + Exceptions are correctly tracked. *) + + method var_id : VAR.t -> id + (** Current identifier associated to a variable. + Raises [Not_found] if unbound. *) + + method pp_var : VAR.t printer + (** Pretty print the variable with its associated identifier. + Prints a debugging name with format ["?<base>#<vid>"] if unbound. *) + + method pp_vartype : VAR.t printer + (** Prints the type of the variable. *) + + method binder : VAR.t -> (binder -> unit) -> unit + (** Allocates an identifier for binder, not-yet linked to the variable. + The bind is release after job. *) + + method pp_binder : binder printer + (** Prints the identifier of the associated variable. *) + + method with_binder : 'a. binder -> 'a printer -> 'a printer + (** Run the printer with the variable locally bound to its identifier. + Exception are correctly tracked. *) + + (** {3 Terms} *) + + method term_call : call_style + method term_atomic : TERM.t -> bool (** Uses [term_operator] *) + method term_operator : TERM.primitive -> operator + + method pp_term_int : string printer + method pp_term_real : string printer + method pp_term_true : u_printer + method pp_term_false : u_printer + method pp_term_extern : string fun_printer + (** Uses [term_call] style *) + method pp_term_call : id fun_printer + (** Uses [term_call] style *) + method pp_term_operator : operator fun_printer + method pp_term_primitive : TERM.primitive fun_printer + (** Uses [term_operator] and [pp_term_operator] + with flattening for associative cases. *) + method pp_term_access : Format.formatter -> TERM.t -> TERM.t -> unit + method pp_term_update : Format.formatter -> TERM.t -> TERM.t -> TERM.t -> unit + method pp_term_getfield : Format.formatter -> TERM.t -> field -> unit + method pp_term_setfield : Format.formatter -> TERM.t -> field -> TERM.t -> unit + method pp_term_cond : Format.formatter -> TERM.t -> TERM.t -> TERM.t -> unit + method pp_term_let : Format.formatter -> VAR.t -> TERM.t -> TERM.t -> unit + + method pp_term_atom : TERM.t printer + (** Prints with [pp_term] with parentheses for only non-atomic terms, + with respect to [term_atomic] method. *) + method pp_term : TERM.t printer + (** Might result in non lexically-atomic print. + Use [pp_term_atom] for safe boxing. *) + + (** {3 Predicates} *) + + method pred_atomic : PRED.t -> bool + method pred_relation : PRED.relation -> operator + + method pp_pred_true : u_printer + method pp_pred_false : u_printer + method pp_pred_relation : PRED.relation fun_printer + (** Uses [pred_operator] and [pp_term_operator] *) + method pp_pred_call : id fun_printer + (** Uses [pp_term_call] *) + method pp_pred_and : PRED.t list printer + method pp_pred_or : PRED.t list printer + method pp_pred_not : PRED.t printer + method pp_pred_iff : (PRED.t,PRED.t) printer2 + method pp_pred_named : (id list,PRED.t) printer2 + method pp_pred_cond : Format.formatter -> TERM.t -> PRED.t -> PRED.t -> unit + method pp_pred_let : Format.formatter -> VAR.t -> TERM.t -> PRED.t -> unit + method pp_pred_forall : (VAR.t list,PRED.t) printer2 + method pp_pred_exists : (VAR.t list,PRED.t) printer2 + method pp_pred_implies : (PRED.t list,PRED.t) printer2 + + method pp_pred_atom : PRED.t printer + (** Prints with [pp_term] with parentheses for only non-atomic terms, + with respect to [pred_atomic] method. *) + method pp_pred : PRED.t printer + (** Might result in non lexically-atomic print. + USe [pp_pred_atom] for safe boxing. *) + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicRaw.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicRaw.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicRaw.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicRaw.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,543 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Logical Language --- *) +(* -------------------------------------------------------------------------- *) + +open LogicId +open LogicTau + +let dkey = "logic" (* debugging key *) +let simpl = Wp_parameters.Simpl.get + +(* [LC] no file LogicRaw.mli to make internal representation visible *) + +(* -------------------------------------------------------------------------- *) +(* --- Variables --- *) +(* -------------------------------------------------------------------------- *) + +module VAR = +struct + + type t = { + var_vid : int ; + var_base : string ; + var_tau : tau ; + } + + type pool = int ref + + let pool () = ref 0 + + let basename x = x.var_base + let tau_of_var x = x.var_tau + let fresh pool base tau = + incr pool ; { var_base=base ; var_tau=tau ; var_vid= !pool } + let freshen pool x = + incr pool ; { x with var_vid= !pool } + + let different x y = x.var_vid <> y.var_vid + let equal x y = (x.var_vid = y.var_vid) + let compare x y = Pervasives.compare x.var_vid y.var_vid + let hash x = x.var_vid + + let pretty fmt x = Format.fprintf fmt "%s#%d" x.var_base x.var_vid + +end + +module VMAP = Map.Make(VAR) +module VSET = Set.Make(VAR) + +(* -------------------------------------------------------------------------- *) +(* --- Terms --- *) +(* -------------------------------------------------------------------------- *) + +module TERM = +struct + + type primitive = + + | L_eq | L_neq + + (* I operations & comparisons *) + | I_add | I_sub | I_mul | I_div | I_mod | I_opp + | I_lt | I_leq + | I_lsl | I_lsr | I_band | I_bor | I_bxor | I_bnot + + (* R operations & comparisons *) + | R_add | R_sub | R_mul | R_div | R_opp + | R_lt | R_leq + + (* R&I conversions *) + | R_of_I | I_of_R + + (* B operations *) + | B_and | B_or | B_not + + type t = + | Ttrue + | Tfalse + | Tint of string + | Treal of string + | Tprim of primitive * t list + | Tcall of id * t list + | Tgetfield of t * field + | Tsetfield of t * field * t + | Taccess of t * t + | Tupdate of t * t * t + | Tif of t * t * t + | Tlet of VAR.t * t * t + | Tvar of VAR.t + + (* Functorial iterator *) + let iter f = function + | Ttrue | Tfalse | Tint _ | Treal _ | Tvar _ -> () + | Tprim(_,ts) | Tcall(_,ts) -> List.iter f ts + | Tgetfield(a,_) -> f a + | Tsetfield(a,_,b) | Taccess(a,b) | Tlet(_,a,b) -> f a ; f b + | Tupdate(a,b,c) | Tif(a,b,c) -> f a ; f b ; f c + + let rec depend ids = function + | Ttrue | Tfalse | Tint _ | Treal _ | Tvar _ -> ids + | Tprim(_,ts) -> List.fold_left depend ids ts + | Tcall(f,ts) -> List.fold_left depend (Iset.add f ids) ts + | Tgetfield(a,f) -> depend (Iset.add f.f_record ids) a + | Tsetfield(a,f,b) -> + depend (depend (Iset.add f.f_record ids) a) b + | Taccess(a,b) | Tlet(_,a,b) -> + depend (depend ids a) b + | Tupdate(a,b,c) | Tif(a,b,c) -> + depend (depend (depend ids a) b) c + + let rec equal e1 e2 = + match e1, e2 with + | Tint x1, Tint x2 -> x1=x2 + | Treal x1, Treal x2 -> x1=x2 + | Ttrue , Ttrue -> true + | Tfalse , Tfalse -> false + | Tcall (f1, args1), Tcall (f2, args2) -> + (LogicId.equal f1 f2) && + (List.length args1 = List.length args2) && + (List.for_all2 equal args1 args2) + | Tprim (f1, args1), Tprim (f2, args2) -> + (f1=f2) && + (List.length args1 = List.length args2) && + (List.for_all2 equal args1 args2) + | Tif (c1, t1, e1), Tif (c2, t2, e2) -> + equal c1 c2 && equal t1 t2 && equal e1 e2 + | Tlet (x,v,t),Tlet(x',v',t') -> + VAR.equal x x' && equal v v' && equal t t' + | Tgetfield (r,f) , Tgetfield(s,g) -> + LogicId.equal f.f_name g.f_name && equal r s + | Tsetfield (r,f,v) , Tsetfield(s,g,w) -> + LogicId.equal f.f_name g.f_name && equal r s && equal v w + | Taccess (t,i) , Taccess (u,j) -> + equal t u && equal i j + | Tupdate (t,i,v), Tupdate(u,j,w) -> + equal t u && equal i j && equal v w + | _ -> false + + let rec different e1 e2 = + match e1 , e2 with + | Tint x1 , Tint x2 -> + not (My_bigint.equal (My_bigint.of_string x1) (My_bigint.of_string x2)) + | _ -> false + + let i_compute f x y = + Tint (My_bigint.to_string (f (My_bigint.of_string x) (My_bigint.of_string y))) + + let i_compare f x y = + if f (My_bigint.compare (My_bigint.of_string x) (My_bigint.of_string y)) then Ttrue else Tfalse + + let rec e_not = function + | Tprim(B_not,[p]) -> p + | Tprim(B_and,[p;q]) -> Tprim(B_or,[e_not p;e_not q]) + | Tprim(B_or,[p;q]) -> Tprim(B_and,[e_not p;e_not q]) + | Tprim(I_lt,[a;b]) -> Tprim(I_leq,[b;a]) + | Tprim(I_leq,[a;b]) -> Tprim(I_lt,[b;a]) + | p -> Tprim(B_not,[p]) + + let e_and a b = + match a,b with + | Ttrue,c | c,Ttrue -> c + | Tfalse,_ | _,Tfalse -> Tfalse + | _ -> Tprim(B_and,[a;b]) + + let e_or a b = + match a,b with + | Tfalse,c | c,Tfalse -> c + | Ttrue,_ | _,Ttrue -> Ttrue + | _ -> Tprim(B_or,[a;b]) + + let e_zero = Tint "0" + let e_int = function 0 -> e_zero | n -> Tint (string_of_int n) + + let rec e_prim f ts = + if not (simpl()) then Tprim(f,ts) else + match f , ts with + | I_opp , [ Tprim(I_opp,[a]) ] -> a + | R_opp , [ Tprim(R_opp,[a]) ] -> a + | I_add , [ Tint a ; Tint b ] -> i_compute My_bigint.add a b + | I_sub , [ Tint a ; Tint b ] -> i_compute My_bigint.sub a b + | I_mul , [ Tint a ; Tint b ] -> i_compute My_bigint.mul a b + | I_add , [ Tint "0" ; x ] -> x + | I_add , [ x ; Tint "0" ] -> x + | I_sub , [ Tint "0" ; x ] -> e_prim I_opp [x] + | I_sub , [ x ; Tint "0" ] -> x + | I_opp , [ Tint a ] -> i_compute My_bigint.sub "0" a + | I_mul , [ Tint "1" ; x ] -> x + | I_mul , [ x ; Tint "1" ] -> x + | I_mul , [ Tint "0" ; _ ] -> e_zero + | I_mul , [ _ ; Tint "0" ] -> e_zero + | I_add , [ b ; Tprim(I_sub,[a;c]) ] when equal b c -> a ; + | I_add , [ Tprim(I_sub,[a;b]) ; c ] when equal b c -> a + | I_sub , [ Tprim(I_add,[a;b]) ; c ] when equal b c -> a + | L_eq , [ Tint a ; Tint b ] -> i_compare (fun r -> r=0) a b + | L_neq , [ Tint a ; Tint b ] -> i_compare (fun r -> r<>0) a b + | I_lt , [ Tint a ; Tint b ] -> i_compare (fun r -> r<0) a b + | L_eq , [a;b] when equal a b -> Ttrue + | L_neq , [a;b] when equal a b -> Tfalse + | I_leq , [ Tint a ; Tint b ] -> i_compare (fun r -> r<=0) a b + | I_of_R , [ Tprim(R_of_I,[a]) ] -> a + | B_not , [p] -> e_not p + | B_and , [a;b] -> e_and a b + | B_or , [a;b] -> e_or a b + | _ -> Tprim(f,ts) + + let e_call f ts = Tcall(f,ts) + + let e_cond c a b = + match c with + | Ttrue -> a + | Tfalse -> b + | Tprim(B_not,[p]) -> Tif(p,b,a) + | _ -> Tif(c,a,b) + + let rec e_getfield r f = + match r with + | Tsetfield(r0,g,v) when simpl () -> if LogicId.equal f.f_name g.f_name then v else e_getfield r0 f + | _ -> Tgetfield(r,f) + + let e_setfield r f v = + match r with + | Tsetfield(r0,g,_) when simpl () && LogicId.equal f.f_name g.f_name -> Tsetfield(r0,f,v) + | _ -> Tsetfield(r,f,v) + + let rec e_access r k = + match r with + | Tupdate(_,k0,v0) when simpl () && equal k k0 -> v0 + | Tupdate(r0,k0,_) when simpl () && different k k0 -> e_access r0 k + | _ -> Taccess(r,k) + + let e_update r k v = + match r with + | Tupdate(r0,k0,_) when simpl () && equal k k0 -> Tupdate(r0,k,v) + | _ -> Tupdate(r,k,v) + + let rec e_hasvar xs = function + | Tvar x -> List.exists (VAR.equal x) xs + | Tcall(_,ts) | Tprim(_,ts) -> List.exists (e_hasvar xs) ts + | Ttrue | Tfalse | Tint _ | Treal _ -> false + | Tif(a,b,c) | Tupdate(a,b,c) -> e_hasvar xs a || e_hasvar xs b || e_hasvar xs c + | Taccess(a,b) | Tsetfield(a,_,b) -> e_hasvar xs a || e_hasvar xs b + | Tgetfield(a,_) -> e_hasvar xs a + | Tlet(x,a,b) -> + e_hasvar xs a || + let ys = List.filter (VAR.different x) xs in + ys <> [] && e_hasvar ys b + +end + +module PRED = +struct + + open TERM + + type relation = + | L_eq | L_neq + | I_lt | I_leq + | R_lt | R_leq + | B_true | B_false + + type t = + | Ptrue + | Pfalse + | Prel of relation * TERM.t list + | Pcall of id * TERM.t list + | Pimplies of t * t + | Pand of t * t + | Por of t * t + | Piff of t * t + | Pnot of t + | Pnamed of id * t + | Pcond of TERM.t * t * t + | Plet of VAR.t * TERM.t * t + | Pforall of VAR.t * t + | Pexists of VAR.t * t + + let iter fp ft = function + | Ptrue | Pfalse -> () + | Prel(_,ts) | Pcall(_,ts) -> List.iter ft ts + | Pimplies(a,b) | Pand(a,b) | Por(a,b) | Piff(a,b) -> fp a ; fp b + | Pcond(t,a,b) -> ft t ; fp a ; fp b + | Plet(_,t,a) -> ft t ; fp a + | Pnot a | Pnamed(_,a) | Pforall(_,a) | Pexists(_,a) -> fp a + + let rec depend ids = function + | Ptrue | Pfalse -> ids + | Prel(_,ts) -> List.fold_left TERM.depend ids ts + | Pcall(id,ts) -> List.fold_left TERM.depend (Iset.add id ids) ts + | Pimplies(p,q) | Pand(p,q) | Por(p,q) | Piff(p,q) -> + depend (depend ids p) q + | Pnot p | Pnamed(_,p) | Pforall(_,p) | Pexists(_,p) -> + depend ids p (* names are not declared *) + | Pcond(t,p,q) -> + depend (depend (TERM.depend ids t) p) q + | Plet(_,a,p) -> + depend (TERM.depend ids a) p + + let i_compare f x y = + let r = My_bigint.compare (My_bigint.of_string x) (My_bigint.of_string y) in + if f r then Ptrue else Pfalse + + let p_call p ts = Pcall(p,ts) + + let rec val_of = function Pnamed(_,p) -> val_of p | p -> p + let rec cut pnew = function Pnamed(label,p) -> Pnamed(label,cut pnew p) | _ -> pnew + + let rec p_not p = match val_of p with + | Ptrue -> cut Pfalse p + | Pfalse -> cut Ptrue p + | Pnot p -> p + | Pand(p,q) -> Por(p_not p,p_not q) + | Por(p,q) -> Pand(p_not p,p_not q) + | Pimplies(p,q) -> Pand(p,p_not q) + | Prel( L_eq , [a;b] ) -> Prel( L_neq , [a;b] ) + | Prel( L_neq , [a;b] ) -> Prel( L_eq , [a;b] ) + | Prel( I_lt , [a;b] ) -> Prel( I_leq , [b;a] ) + | Prel( I_leq , [a;b] ) -> Prel( I_lt , [b;a] ) + | Prel( R_lt , [a;b] ) -> Prel( R_leq , [b;a] ) + | Prel( R_leq , [a;b] ) -> Prel( R_lt , [b;a] ) + | Prel( B_true , [a] ) -> Prel( B_false , [a] ) + | Prel( B_false , [a] ) -> Prel( B_true , [a] ) + | Pforall( x , p ) -> Pexists( x , p_not p ) + | Pexists( x , p ) -> Pforall( x , p_not p ) + | _ -> Pnot p + + let p_and p1 p2 = match val_of p1, val_of p2 with + | Ptrue, _ -> p2 + | _, Ptrue -> p1 + | Pfalse,_-> cut Pfalse p1 + | _,Pfalse -> cut Pfalse p2 + | _ -> Pand (p1, p2) + + let p_or p1 p2 = match val_of p1, val_of p2 with + | Ptrue, _ -> cut Ptrue p1 + | _ , Ptrue -> cut Ptrue p2 + | Pfalse ,_ -> p2 + | _ ,Pfalse -> p1 + | _ -> Por (p1,p2) + + let p_xor p1 p2 = match val_of p1, val_of p2 with + | Ptrue , Ptrue -> cut (cut Pfalse p2) p1 + | Ptrue ,_ -> cut Ptrue p1 + | _,Ptrue -> cut Ptrue p2 + | Pfalse , _ -> p2 + | _ , Pfalse -> p1 + | _ -> Pnot(Piff(p1,p2)) + + let p_implies p1 p2 = + match val_of p1, val_of p2 with + | Ptrue, _ -> p2 + | Pfalse, _ -> cut Ptrue p1 + | _, Ptrue -> cut Ptrue p2 + | _ -> Pimplies (p1, p2) + + let p_cond c p1 p2 = match c, val_of p1, val_of p2 with + | _, Ptrue, Ptrue -> cut (cut Ptrue p2) p1 + | _, Pfalse, Pfalse -> cut (cut Pfalse p2) p1 + | Ttrue , _ , _ -> p1 + | Tfalse , _ , _ -> p2 + | Tprim(B_not,[t]) , _ , _ -> Pcond(t,p2,p1) + | _ -> Pcond(c,p1,p2) + + let p_iff p1 p2 = + match val_of p1,val_of p2 with + | Ptrue ,_ -> p2 + | _ ,Ptrue -> p1 + | Pfalse, _ -> p_not p2 + | _ , Pfalse -> p_not p1 + | _ -> Piff (p1,p2) + + let rec p_bool = function + | Ttrue -> Ptrue + | Tfalse -> Pfalse + | Tprim(TERM.L_eq ,[a;b]) -> Prel(L_eq ,[a;b]) + | Tprim(TERM.L_neq,[a;b]) -> Prel(L_neq,[a;b]) + | Tprim(TERM.I_lt ,[a;b]) -> Prel(I_lt ,[a;b]) + | Tprim(TERM.I_leq ,[a;b]) -> Prel(I_leq ,[a;b]) + | Tprim(TERM.R_lt ,[a;b]) -> Prel(R_lt ,[a;b]) + | Tprim(TERM.R_leq ,[a;b]) -> Prel(R_leq ,[a;b]) + | Tprim(B_and,[a;b]) -> p_and (p_bool a) (p_bool b) + | Tprim(B_or,[a;b]) -> p_or (p_bool a) (p_bool b) + | Tprim(B_not,[a]) -> p_not (p_bool a) + | p -> Prel(B_true,[p]) + + let p_prim f ts = + if not (simpl()) then Prel(f,ts) else + match f , ts with + | L_eq , [a;b] when TERM.equal a b -> Ptrue + | L_neq , [a;b] when TERM.equal a b -> Pfalse + | L_eq , [Tint x;Tint y] -> i_compare (fun r -> r=0) x y + | L_neq , [Tint x;Tint y] -> i_compare (fun r -> r<>0) x y + | I_lt , [Tint x;Tint y] -> i_compare (fun r -> r<0) x y + | I_leq , [Tint x;Tint y] -> i_compare (fun r -> r<=0) x y + | B_true , [t] -> p_bool t + | B_false , [t] -> p_not (p_bool t) + | _ -> Prel(f,ts) + + let rec p_hasvar xs = function + | Ptrue | Pfalse -> false + | Pcall(_,ts) | Prel(_,ts) -> List.exists (e_hasvar xs) ts + | Pimplies(p,q) | Pand(p,q) | Por(p,q) | Piff(p,q) -> p_hasvar xs p || p_hasvar xs q + | Pnamed(_,p) | Pnot p -> p_hasvar xs p + | Pcond(a,p,q) -> e_hasvar xs a || p_hasvar xs p || p_hasvar xs q + | Pforall(x,p) | Pexists(x,p) -> + let ys = List.filter (VAR.different x) xs in + ys <> [] && p_hasvar ys p + | Plet(x,a,p) -> + e_hasvar xs a || + let ys = List.filter (VAR.different x) xs in + ys <> [] && p_hasvar ys p + + let p_forall x p = if p_hasvar [x] p then Pforall(x,p) else p + let p_exists x p = if p_hasvar [x] p then Pexists(x,p) else p + let p_let x a p = if p_hasvar [x] p then Plet(x,a,p) else p + +end + +(* -------------------------------------------------------------------------- *) +(* --- Substitution & Bindings --- *) +(* -------------------------------------------------------------------------- *) + +module SUBST = +struct + + open TERM + open PRED + + let is_atomic = function + | Tint _ | Treal _ | Ttrue | Tfalse | Tcall(_,[]) | Tvar _ -> true + | _ -> false + + let rec e_bind ?pool x e t = + let frec = e_bind ?pool x e in + match t with + | Tvar x0 -> if VAR.equal x0 x then e else t + | Ttrue | Tfalse | Tint _ | Treal _ -> t + | Tcall(f,ts) -> Tcall(f,List.map frec ts) + | Tprim(p,ts) -> e_prim p (List.map frec ts) + | Tif(a,b,c) -> e_cond (frec a) (frec b) (frec c) + | Tgetfield(r,f) -> e_getfield (frec r) f + | Tsetfield(r,f,v) -> e_setfield (frec r) f (frec v) + | Taccess(r,k) -> e_access (frec r) (frec k) + | Tupdate(r,k,v) -> e_update (frec r) (frec k) (frec v) + | Tlet(x0,a,b) -> + begin + if e_hasvar [x0] e then + match pool with + | None -> Tlet(x,e,t) + | Some thepool -> + let y = VAR.freshen thepool x in + let b = e_bind ?pool x0 (Tvar y) b in + e_let ?pool y (frec a) (frec b) + else + let b' = if VAR.equal x0 x then b else frec b in + e_let ?pool x0 (frec a) b' + end + + and e_let ?pool x a b = + if e_hasvar [x] b then + if is_atomic a then e_bind ?pool x a b else Tlet(x,a,b) + else b + + let rec p_bind ?pool x e p = + let prec = p_bind ?pool x e in + let erec = e_bind ?pool x e in + match p with + | Ptrue | Pfalse -> p + | Prel(f,ts) -> p_prim f (List.map erec ts) + | Pcall(p,ts) -> Pcall(p,List.map erec ts) + | Pimplies(p,q) -> p_implies (prec p) (prec q) + | Pcond(a,p,q) -> p_cond (erec a) (prec p) (prec q) + | Pand(p,q) -> p_and (prec p) (prec q) + | Por(p,q) -> p_or (prec p) (prec q) + | Piff(p,q) -> p_iff (prec p) (prec q) + | Pnot(p) -> p_not (prec p) + | Pnamed(a,p) -> Pnamed(a,prec p) + | Pforall(x0,p) as p0 -> + begin + if VAR.equal x x0 then p0 + else if e_hasvar [x0] e then + match pool with + | None -> Plet(x,e,p0) + | Some thepool -> + let y = VAR.freshen thepool x in + let py = p_bind ?pool x0 (Tvar y) p in + PRED.p_forall y (prec py) + else PRED.p_forall x0 (prec p) + end + | Pexists(x0,p) as p0 -> + begin + if VAR.equal x x0 then p0 + else if e_hasvar [x0] e then + match pool with + | None -> Plet(x,e,p0) + | Some thepool -> + let y = VAR.freshen thepool x in + let py = p_bind ?pool x0 (Tvar y) p in + PRED.p_exists y (prec py) + else PRED.p_exists x0 (prec p) + end + | Plet(x0,t,p) as p0 -> + begin + if e_hasvar [x0] e then + match pool with + | None -> Plet(x,e,p0) + | Some thepool -> + let y = VAR.freshen thepool x in + let py = p_bind ?pool x0 (Tvar y) p in + p_let ?pool y (erec t) (prec py) + else + let p' = if VAR.equal x0 x then p else prec p in + p_let ?pool x0 (erec t) p' + end + + and p_let ?pool x a p = + if p_hasvar [x] p then + if is_atomic a then p_bind ?pool x a p else Plet(x,a,p) + else p + +end + +(* -------------------------------------------------------------------------- *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicTau.ml frama-c-20111001+nitrogen+dfsg/src/wp/LogicTau.ml --- frama-c-20110201+carbon+dfsg/src/wp/LogicTau.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicTau.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,105 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Logical Language --- *) +(* -------------------------------------------------------------------------- *) + +open LogicId + +(* -------------------------------------------------------------------------- *) +(* --- Types --- *) +(* -------------------------------------------------------------------------- *) + +type tau = + | Integer + | Real + | Boolean + | Pointer + | Set of tau + | Array of tau * tau + | Record of id + | ADT of id * tau list + | ALPHA of int + +type field = { + f_record : id ; + f_name : id ; + f_type : tau ; +} + +let rec compare_tau t1 t2 = + match t1 , t2 with + + | Integer , Integer -> 0 + | Integer , _ -> (-1) + | _ , Integer -> 1 + + | Real , Real -> 0 + | Real , _ -> (-1) + | _ , Real -> 1 + + | Boolean , Boolean -> 0 + | Boolean , _ -> (-1) + | _ , Boolean -> 1 + + | Pointer , Pointer -> 0 + | Pointer , _ -> (-1) + | _ , Pointer -> 1 + + | ALPHA k , ALPHA k' -> Pervasives.compare k k' + | ALPHA _ , _ -> (-1) + | _ , ALPHA _ -> 1 + + | Set ta , Set tb -> compare_tau ta tb + | Set _ , _ -> (-1) + | _ , Set _ -> 1 + + | Array(ta,tb) , Array(ta',tb') -> compare_sig [ta;tb] [ta';tb'] + | Array _ , _ -> (-1) + | _ , Array _ -> 1 + + | Record ra , Record rb -> LogicId.compare ra rb + | Record _ , _ -> (-1) + | _ , Record _ -> 1 + + | ADT(a,ps) , ADT(b,qs) -> + let cid = LogicId.compare a b in + if cid<>0 then cid else compare_sig ps qs + +and compare_sig ps qs = + match ps , qs with + | [] , [] -> 0 + | [] , _ -> (-1) + | _ , [] -> 1 + | t1::ps , t2::qs -> + let ct = compare_tau t1 t2 in + if ct<>0 then ct else compare_sig ps qs + +let compare_field f1 f2 = LogicId.compare f1.f_name f2.f_name + +let rec depend ids = function + | Integer | Real | Boolean | Pointer | ALPHA _ -> ids + | Set te -> depend ids te + | Array(ta,tb) -> depend (depend ids ta) tb + | Record r -> Iset.add r ids + | ADT(a,ts) -> List.fold_left depend (Iset.add a ids) ts diff -Nru frama-c-20110201+carbon+dfsg/src/wp/LogicTau.mli frama-c-20111001+nitrogen+dfsg/src/wp/LogicTau.mli --- frama-c-20110201+carbon+dfsg/src/wp/LogicTau.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/LogicTau.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Logical Language *) +(* -------------------------------------------------------------------------- *) + +open LogicId + +(* -------------------------------------------------------------------------- *) +(** {2 Types} *) +(* -------------------------------------------------------------------------- *) + +type tau = + | Integer (** Mathematical Z numbers *) + | Real (** Mathematical R numbers *) + | Boolean (** Finite set [{true,false}] *) + | Pointer (** Pointer datatype in current model (see LogicDef.register) *) + | Set of tau (** [Set t]: Mathematical sets with elements of type [t] *) + | Array of tau * tau (** [Array(ta,tb)]: Total functions from [ta] to [tb] *) + | Record of id (** Tuples [(fi,vi)] with [vi] of type [fi.ftype] and [fi] in [rfields] *) + | ADT of id * tau list (** Polymorphic instance of datatype [a] with parameters [ti] *) + | ALPHA of int (** [i-th] parameter of a polymorphic type in its definition. Starts with [0]. *) + +type field = { + f_record : id ; + f_name : id ; + f_type : tau ; +} + +val compare_tau : tau -> tau -> int +val compare_sig : tau list -> tau list -> int +val compare_field : field -> field -> int + +val depend : Iset.t -> tau -> Iset.t diff -Nru frama-c-20110201+carbon+dfsg/src/wp/Makefile.in frama-c-20111001+nitrogen+dfsg/src/wp/Makefile.in --- frama-c-20110201+carbon+dfsg/src/wp/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/Makefile.in 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,159 @@ +########################################################################## +# # +# This file is part of WP plug-in of Frama-C. # +# # +# Copyright (C) 2007-2011 # +# CEA (Commissariat a l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It 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 Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +## TODO: bug in Makefile.in with generated wp_version.ml +.PHONY: version + +## WP_KERNEL=Carbon-20110201+dev +## WP_VERSION=0.3+dev + +# Do not use ?= to initialize both below variables +# (fixed efficiency issue, see GNU Make manual, Section 8.11) +ifndef FRAMAC_SHARE +FRAMAC_SHARE :=$(shell frama-c -journal-disable -print-path) +endif +ifndef FRAMAC_LIBDIR +FRAMAC_LIBDIR :=$(shell frama-c -journal-disable -print-libpath) +endif +PLUGIN_DIR ?=. + +ALTERGO_VERSION=@ALTERGO_VERSION@ +WHY=@WHY@ +COQ=@COQ@ +ALTERGO=@ALTERGO@ +WHYDP=@WHYDP@ + +include $(FRAMAC_SHARE)/Makefile.config + +MODELS:= share/wp.v \ + share/hoare_model.v \ + share/hoare_model.why \ + share/hoare_ergo.why \ + share/store_model.v \ + share/store_model.why \ + share/store_ergo.why \ + share/runtime_model.v \ + share/runtime_model.why \ + share/runtime_ergo.why \ + +# Extension of the GUI for wp is compilable +# only if gnomecanvas is available +ifeq ($(HAS_GNOMECANVAS),yes) +PLUGIN_GUI_CMO:= po_navigator wp_gui +PLUGIN_UNDOC:= +else +PLUGIN_UNDOC:= po_navigator.ml wp_gui.ml +endif + +PLUGIN_ENABLE:=@ENABLE_WP@ +PLUGIN_DYNAMIC:=@DYNAMIC_WP@ +PLUGIN_NAME:=Wp +PLUGIN_CMO:= \ + wprop \ + wp_parameters wp_error \ + ctypes clabels \ + cil2cfg normAtLabels \ + wpPropId wpStrategy wpFroms wpAnnot \ + script proof \ + wpo prover \ + variables_analysis datalib \ + fol fol_let fol_decl fol_pretty \ + data_mem \ + mint_natural mfloat_natural \ + funvar_mem runtime_mem store_mem hoare_mem \ + fol_cc fol_eqs fol_eval fol_norm \ + fol_split fol_why fol_ergo kreal fol_coq \ + fol_formula \ + LogicId LogicTau LogicRaw LogicPretty LogicLang \ + LogicLib LogicHavoc LogicDef \ + ACSL \ + translate_expr \ + translate_prop \ + calculus cfgpropid \ + cfgWeakestPrecondition \ + cfgProof \ + register + +PLUGIN_CMI:= \ + mcfg formula \ + mint mfloat mvalues mlogic mwp + +PLUGIN_GENERATED:= $(PLUGIN_DIR)/script.ml +# $(PLUGIN_DIR)/wp_version.ml + +PLUGIN_UNDOC+= fol_qed.mli fol_qed.ml +PLUGIN_INTRO:=$(FRAMAC_SRC)/doc/code/intro_wp.txt +PLUGIN_HAS_MLI:=yes +PLUGIN_DISTRIBUTED:=$(PLUGIN_ENABLE) +PLUGIN_DISTRIB_EXTERNAL:= Makefile.in configure.ac configure $(MODELS) + +ifeq ("$(OCAMLGRAPH_LOCAL)","") +OFLAGS+=-I +ocamlgraph +BFLAGS+=-I +ocamlgraph +endif + +# -------------------------------------------------------------------------- +# --- Tests --- +# -------------------------------------------------------------------------- + +PLUGIN_TESTS_DIRS:= wp wp_plugin wp_acsl wp_store wp_hoare wp_runtime wp_bts wp_engine +#PLUGIN_NO_TESTS:=no +#PLUGIN_NO_DEFAULT_TEST:=yes + +# -------------------------------------------------------------------------- +# --- Dynamic Plugin --- +# -------------------------------------------------------------------------- + +include $(FRAMAC_SHARE)/Makefile.dynamic + +# Regenerating the Makefile on need + +ifeq ("$(FRAMAC_INTERNAL)","yes") +CONFIG_STATUS_DIR=$(FRAMAC_SRC) +else +CONFIG_STATUS_DIR=. +endif + +## Bug with Makefile.in : the wp_version.ml is systematically re-generated +## [BM] 04/22/2011 seems to be fixed +# $(Wp_DIR)/wp_version.ml: $(Wp_DIR)/Makefile.in +# @echo "Generate wp_version.ml" +# @echo 'let kernel = "$(WP_KERNEL)"' > $@ +# @echo 'let version = "$(WP_VERSION)"' >> $@ +# @headache -c headers/headache_config.txt -h headers/CEA_LGPL $@ + +## Removing dependency to headache. +# @headache -c headers/headache_config.txt -h headers/CEA_LGPL $@ + +$(Wp_DIR)/Makefile: $(Wp_DIR)/Makefile.in $(CONFIG_STATUS_DIR)/config.status + @cd $(CONFIG_STATUS_DIR) && ./config.status + @make depend + +install:: + $(MKDIR) $(FRAMAC_DATADIR)/wp + $(CP) $(addprefix $(Wp_DIR)/,$(MODELS)) $(FRAMAC_DATADIR)/wp + +# -------------------------------------------------------------------------- +# --- WP Release Stuff (CEA-LIST Only) +# -------------------------------------------------------------------------- +sinclude MakeDistrib +# -------------------------------------------------------------------------- diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mcfg.mli frama-c-20111001+nitrogen+dfsg/src/wp/mcfg.mli --- frama-c-20110201+carbon+dfsg/src/wp/mcfg.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mcfg.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,131 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +type scope = + | SC_Global + | SC_Function_in (* Just before the pre-state *) + | SC_Function_frame (* Just after the introduction of formals *) + | SC_Function_out (* Post-state *) + | SC_Block_in + | SC_Block_out + +type assigns_method = + | NoAssigns + | NormalAssigns + | EffectAssigns + +module type Export = +sig + type pred + type decl + val export_section : Format.formatter -> string -> unit + val export_goal : Format.formatter -> string -> pred -> unit + val export_decl : Format.formatter -> decl -> unit +end + +module type Splitter = +sig + type pred + val simplify : pred -> pred + val split : assigns_method -> pred -> pred Bag.t +end + +(** + * This is what is really needed to propagate something through the CFG. + * Usually, the propagated thing should be a predicate, + * but it can be more sophisticated like lists of predicates, + * or maybe a structure to keep hypotheses and goals separated. + * Moreover, proof obligations may also need to be handeled. + **) +module type S = sig + + type t_prop + val pretty : Format.formatter -> t_prop -> unit + val merge : t_prop -> t_prop -> t_prop + val empty : t_prop + + type t_env + + (** optionally init env with user logic variables *) + val new_env : ?lvars:Cil_types.logic_var list -> kernel_function -> t_env + + val add_axiom : WpPropId.prop_id -> string -> logic_label list -> predicate named -> unit + val add_hyp : t_env -> WpPropId.pred_info -> t_prop -> t_prop + val add_goal : t_env -> WpPropId.pred_info -> t_prop -> t_prop + + val add_assigns : t_env -> WpPropId.assigns_info -> t_prop -> t_prop + + (** [use_assigns env hid kind assgn goal] performs the havoc on the goal. + * [hid] should be [None] iff [assgn] is [WritesAny], + * and tied to the corresponding identified_property otherwise.*) + val use_assigns : t_env -> WpPropId.prop_id option -> + WpPropId.assigns_desc -> t_prop -> t_prop + + val assigns_method : unit -> assigns_method + + val label : t_env -> Clabels.c_label -> t_prop -> t_prop + val assign : t_env -> lval -> exp -> t_prop -> t_prop + val return : t_env -> exp option -> t_prop -> t_prop + val test : t_env -> exp -> t_prop -> t_prop -> t_prop + val switch : t_env -> exp -> (exp list * t_prop) list -> t_prop -> t_prop + val init_value : t_env -> lval -> typ -> exp option -> t_prop -> t_prop + (** init_value env lv t v_opt wp: + put value of type t (or default if None) in lv *) + val init_range : t_env -> lval -> typ -> int64 -> int64 -> t_prop -> t_prop + (** init_range env lv t_elt a b wp : + put default values of type t_elt in lv[k] with a <= k < b *) + + val tag : string -> t_prop -> t_prop + + (* -------------------------------------------------------------------------- *) + (* --- Call Rules --- *) + (* -------------------------------------------------------------------------- *) + + val call_goal_precond : t_env -> stmt -> + kernel_function -> exp list -> + pre: WpPropId.pred_info list -> + t_prop -> t_prop + + val call : t_env -> stmt -> + lval option -> kernel_function -> exp list -> + pre: WpPropId.pred_info list -> + post: WpPropId.pred_info list -> + pexit: WpPropId.pred_info list -> + assigns: identified_term assigns -> + p_post: t_prop -> + p_exit: t_prop -> + t_prop + + (* -------------------------------------------------------------------------- *) + (* --- SCOPING RULES --- *) + (* -------------------------------------------------------------------------- *) + + val scope : t_env -> varinfo list -> scope -> t_prop -> t_prop + + (** build [p => alpha(p)] for functional dependencies verification. *) + val build_prop_of_from : t_env -> WpPropId.pred_info list -> t_prop -> t_prop + + val close : t_env -> t_prop -> t_prop + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mfloat.mli frama-c-20111001+nitrogen+dfsg/src/wp/mfloat.mli --- frama-c-20110201+carbon+dfsg/src/wp/mfloat.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mfloat.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,41 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Float and Real Model *) +(* -------------------------------------------------------------------------- *) + +open Formula +open Ctypes + +module type S = +sig + + module F : Formula.S + + (** {2 Float Operators} *) + + val f_neg : c_float -> F.real -> F.real + val f_op : c_float -> real_op -> F.real -> F.real -> F.real + val f_cmp : c_float -> cmp_op -> F.real -> F.real -> F.boolean + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mfloat_natural.ml frama-c-20111001+nitrogen+dfsg/src/wp/mfloat_natural.ml --- frama-c-20110201+carbon+dfsg/src/wp/mfloat_natural.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mfloat_natural.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Basic Real Model --- *) +(* -------------------------------------------------------------------------- *) + +open Formula + +module Create (F:Formula.S) : (Mfloat.S with module F = F) = +struct + + module F = F + + let tau_of_cfloat _ = Real + + let format_of_cfloat _ = F.unwrap (F.e_call "real_format" []) + + (*Float cst *) + + let f_float _f k = F.e_rcst k + + (* arithmetic operations on R in why *) + + let f_neg _i = F.e_rneg + let f_op _i = F.e_rop + let f_cmp _i = F.e_rcmp + + (* conversion on R in why *) + + let f_convert _t1 _t2 e = e + let real_of_float _te e = e + let float_of_real _t1 e = e + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mint.mli frama-c-20111001+nitrogen+dfsg/src/wp/mint.mli --- frama-c-20110201+carbon+dfsg/src/wp/mint.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mint.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,50 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Integer Model *) +(* -------------------------------------------------------------------------- *) + +open Formula +open Ctypes + +module type S = +sig + + module F : Formula.S + + (** {2 Integer Operators} *) + + val i_neg : c_int -> F.integer -> F.integer + val i_op : c_int -> int_op -> F.integer -> F.integer -> F.integer + val i_cmp : c_int -> cmp_op -> F.integer -> F.integer -> F.boolean + + (** {2 Bitwise Operators} *) + + val bits_not : c_int -> F.integer -> F.integer + val bits_and : c_int -> F.integer -> F.integer -> F.integer + val bits_or : c_int -> F.integer -> F.integer -> F.integer + val bits_xor : c_int -> F.integer -> F.integer -> F.integer + val bits_lshift : c_int -> F.integer -> F.integer -> F.integer + val bits_rshift : c_int -> F.integer -> F.integer -> F.integer + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mint_natural.ml frama-c-20111001+nitrogen+dfsg/src/wp/mint_natural.ml --- frama-c-20110201+carbon+dfsg/src/wp/mint_natural.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mint_natural.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,70 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Basic Implementation (Arithmetics is mapped to Z) --- *) +(* -------------------------------------------------------------------------- *) + +open Ctypes +open Formula + +module Create (F:Formula.S) : (Mint.S with module F = F) = +struct + + module F = F + + (* integer cst *) + let i_int _i k = F.e_icst k + + (* arithmetic operations on Z in why *) + + let i_neg i e = + let k = F.e_ineg e in + if (Ctypes.signed i) then k else F.modulo i k + let i_op _i iop e1 e2 = F.e_iop iop e1 e2 + let i_cmp _i cmp e1 e2 = (F.e_icmp cmp e1 e2) + + (* bitwise operations on Z in why *) + + let sizeof i = F.e_int (Ctypes.i_sizeof i) + let signess i = if (Ctypes.signed i) then F.e_true else F.e_false + + let bits_not _ = F.e_app1 "int_not" + let bits_and _ = F.e_app2 "int_and" + let bits_or _ = F.e_app2 "int_or" + let bits_xor _ = F.e_app2 "int_xor" + let bits_lshift _ = F.e_app2 "int_lsh" + let bits_rshift i = + F.e_app2 (if (Ctypes.signed i) then "int_rshs" else "int_rshu") + + (* integers conversions *) + + let i_convert t1 t2 e = + if Ctypes.sub_c_int t1 t2 then e else F.modulo t2 e + + let integer_of_int _ e = e + (* Z-representatives live in the correct range. *) + + let int_of_integer _ e = e + (* Conversions are never necessary for this model, since no overflow are allowed. *) + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mlogic.mli frama-c-20111001+nitrogen+dfsg/src/wp/mlogic.mli --- frama-c-20110201+carbon+dfsg/src/wp/mlogic.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mlogic.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,94 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Model for the interpretation of ACSL/C *) +(* -------------------------------------------------------------------------- *) + +open Ctypes +open Clabels +open Formula +open Cil_types + +module type S = +sig + + (** {2 Term Values} *) + + include Mvalues.S + + val lvar : mem -> logic_var -> F.var-> loc + (** [lvar m lv p] returns a location associated to the + location variable [lv] with variable root name [x]. + [x] for all model except in funvar. *) + + val inner_loc : loc -> F.abstract + (** [inner_loc l] returns the location corresponding + to [l] in the inner memory model in funvar. + Not implemented in other models. *) + + + (** {2 Pointers} *) + + val base_address : mem -> loc -> loc + (** [base_address m l] return the [base address] of [l].*) + + val block_length : mem -> loc -> F.integer + (** [block_length m l t] return the [block_length] + of the location [l]. *) + + (** {2 Validity }*) + + val valid : mem -> loc F.assigned -> F.pred + + (** {2 Separation} *) + + val separated : mem -> loc F.assigned -> loc F.assigned -> F.pred + + (** {2 User-defined Predicates} *) + + type formal + val pp_formal : Format.formatter -> ( formal * logic_var ) -> unit + + val userdef_ref_has_cvar : logic_var -> bool + (** [userdef_ref_has_cvar p] tests if the by reference + logic formal parameter [p] needs a C addresses.*) + + val userdef_is_ref_param : logic_var -> bool + (** [userdef_ref_param p] tests if [p] is a by reference logic + formal parameter.*) + + val userdef_ref_signature : mem -> ( F.var * logic_var * formal ) list + val userdef_ref_apply : mem -> formal -> loc -> value + + type closure + val pp_closure : Format.formatter -> closure -> unit + + val userdef_mem_signature : mem -> ( F.var * closure ) list + val userdef_mem_apply : mem -> closure -> F.abstract + +end +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mvalues.mli frama-c-20111001+nitrogen+dfsg/src/wp/mvalues.mli --- frama-c-20110201+carbon+dfsg/src/wp/mvalues.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mvalues.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,193 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Memory Model Signature *) +(* -------------------------------------------------------------------------- *) + +open Ctypes +open Clabels +open Formula +open Cil_types + +module type Model = +sig + + module F : Formula.S + module A : Mint.S with module F = F + module R : Mfloat.S with module F = F + + type loc + + val tau_of_loc :tau + + val term_of_loc : loc -> F.abstract + val loc_of_term : c_object -> F.abstract -> loc + + + (** {2 Loc arithmetics} *) + + val equal_loc_bool : loc -> loc -> F.boolean + (** [equal_loc_bool p q] is the boolean that is true when + locs [p] and [q], that points to elements of type [ty], + are equal. Returns a term of type [bool]. *) + + val lt_loc_bool : loc -> loc -> F.boolean + (** [lt_loc_bool p q] is the less than comparison + of locs [p] and [q], that points to elements of type [ty], + ie. [p<q]. Returns a term of type [boolean]. + *) + + val le_loc_bool : loc -> loc -> F.boolean + (** [le_loc_bool p q] is the less than or equal comparison + of locs [p] and [q], that points to elements of type [ty], + ie. [p<=q]. Returns a term of type [boolean]. + *) + + val lt_loc : loc -> loc -> F.pred + (** [lt_loc p q] is the less than comparison + of locs [p] and [q], that points to elements of type [ty], + ie. [p<q]. + *) + + val le_loc : loc -> loc -> F.pred + (** [le_loc p q] is the less than or equal comparison + of locs [p] and [q], that points to elements of type [ty], + ie. [p<=q]. + *) + + val equal_loc: loc -> loc -> F.pred + + val minus_loc : loc -> loc -> F.integer + (** [minus_loc ty p q] is the arithmetics difference of + locs [p] and [q], that points to elements of type [ty], + ie. [p-q]. Returns a term of type [integer]. *) + + val is_null : loc -> F.boolean + (** Take a term representing an [address] and returns a + term of type [bool]. *) + + (** {2 Special locations} *) + + val null : loc + (** [null] return the special location of the memory model designing + the null loc. *) + + (** + * [cast_loc_to_int t p c_int] : + * cast [loc] if type [t*] into a term of type [c_int] + **) + + val cast_loc_to_int : Cil_types.typ -> loc -> Ctypes.c_int -> F.integer + val cast_int_to_loc : Ctypes.c_int -> F.integer -> Cil_types.typ -> loc + + val pp_loc : Format.formatter -> loc -> unit + +end + +module type Values = +sig + + include Model + + (** The internal representation of an ACSL value *) + type value = + | V_int of Ctypes.c_int * F.integer + | V_float of Ctypes.c_float * F.real + | V_pointer of Ctypes.c_object * loc + | V_record of compinfo * F.record + | V_union of compinfo * F.urecord + | V_array of arrayinfo * F.array + + val pp_value : Format.formatter -> value -> unit + + (** Conversion between internal representation of ACSL value and FOL term *) + + + val equal : c_object -> F.abstract -> F.abstract -> F.pred + val eq_array : arrayinfo -> F.array -> F.array -> F.pred + val eq_record : compinfo -> F.record -> F.record -> F.pred + + val logic_of_value : value -> F.abstract + val value_of_logic : c_object -> F.abstract -> value + val tau_of_object : c_object -> tau + val tau_of_object_array : c_object -> int -> tau + val tau_of_logic_type : Cil_types.logic_type -> tau + val pp_tau: Format.formatter -> tau -> unit + val symb_is_init : c_object -> string option + val symb_is_init_range : c_object -> string option + +end + +module type Data = +sig + + include Values + + type m_of_mem + val tau_of_mem : tau + val forall_loc : F.pool -> F.var list * loc + + val index : loc -> c_object -> F.integer -> loc + val field : loc -> fieldinfo -> loc + + val load_mem : m_of_mem F.term -> c_object -> loc -> value + val store_mem : m_of_mem F.term -> c_object -> loc -> value -> m_of_mem F.term + +end + +module type S = +sig + + include Values + module L:Formula.Logic with module F = F + + (** {2 Memory, Field and Array access} *) + + type mem + + val mem : unit -> mem + + val global : varinfo -> unit + + val cvar : mem -> varinfo -> loc + + val shift : loc -> c_object -> F.integer -> loc + (** [shift ptr tau k] computes the location + of [ptr+k], where [ptr] is a pointer to a value of type [tau]. *) + + val index : loc -> c_object -> F.integer -> loc + (** [index tab tau k] computes the location + of [tab[k]], where [tab] is an array with elements of type [tau]. *) + + val startof : loc -> c_object -> loc + (** [startof] return a pointer to the first element of an array *) + + val field : loc -> fieldinfo -> loc + + val load : mem -> c_object -> loc -> value + + val cast_loc_to_loc : typ -> typ -> loc -> loc + (** [cast_loc_to_loc t1 t2 l] returns the casted location of type [t2] + from the location [l] of type [t1] *) + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/mwp.mli frama-c-20111001+nitrogen+dfsg/src/wp/mwp.mli --- frama-c-20110201+carbon+dfsg/src/wp/mwp.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/mwp.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,125 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Model for the interpretation of ACSL/C *) +(* -------------------------------------------------------------------------- *) + +open Ctypes +open Clabels +open Formula +open Cil_types + +module type Export = +sig + type pred + type decl + val export_goal : Format.formatter -> string -> pred -> unit + val export_decl : Format.formatter -> decl -> unit +end + +module type S = +sig + + include Mlogic.S + + (** + [update m h p] binds free variables in [p] representing + the state [m] to the current memory [h]. + *) + + val update : at:mem -> here:mem -> F.pred -> F.pred + + (** [quantify_at_label m p] quantifies the free variables in [p] + representing the memort state [m]. + + It generalize the goal up-to the state [m]. + *) + + val quantify : mem -> F.pred -> F.pred + + (** [subst_lval frame l te v p] binds in [p] the free variables + representing the value at location [l] in the current memory to + the actual value [v]. + + It updates the memory-map [frame] such that now the current memory in [p] + has been updated by storing [v] at [l]. + *) + + val subst_lval : mem -> Ctypes.c_object -> loc -> value -> F.pred -> F.pred + + (** Binds the free variables in + the wp representing the memory locations that live in [zone]. + Actually, subst_havoc must no do the substitution it-self to avoid + any variable capture un region. Rather, [subst_havoc] should returns the + list of substitutions to be applied modulo alpha-conversion. + *) + val subst_havoc : mem -> loc F.assigned -> F.havoc list + + (** {2 Assigns} *) + + (** [assigns_goal M1 region M2] returns a predicates + establishing the assigns clause [region] with dependencies [depends]. + - [M1] is the memory {i before} of the execution of the assigning statement. + - [M2] is the memory {i after} of the execution of the assigning statement. + *) + + val assigns_goal : + mem -> + loc F.assigned list -> + mem -> + F.pred + + val assigns_supported : bool + + (** {2 Assigns with Zones} *) + + type m_dzone + type dzone = m_dzone F.term + val tau_of_dzone : tau + + val dzone_assigned : mem -> loc F.assigned -> dzone + val dzone_subset : dzone -> dzone -> F.pred + val dzone_union : dzone -> dzone -> dzone + val dzone_empty : unit -> dzone + + val effect_supported : bool + + + + val global_scope : mem -> F.pred -> F.pred + + (** [local_scope m l] transforms the predicate [p] at the + enter-point of a block or function that + declares the local variables in the list. It is time to add + hypotheses about those local variables. *) + val local_scope : mem -> Cil_types.varinfo list -> Mcfg.scope -> F.pred -> F.pred + +end + + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/normAtLabels.ml frama-c-20111001+nitrogen+dfsg/src/wp/normAtLabels.ml --- frama-c-20110201+carbon+dfsg/src/wp/normAtLabels.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/normAtLabels.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,227 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +type label_mapping = Cil_types.logic_label -> Cil_types.logic_label + + +(** push the Tat down to the 'data' operations. +* This can be useful in cases like \at (x + \at(y, Ly), Lx) because +* it gives \at(x, Lx) + \at(y, Ly) so there is no more \at imbrications. + * Also try to "normalize" label : + * - remove Here because its meaning change when propagating, + * - remove Old because its meaning depend on where it comes from. +* *) +class norm_at label_map = object(self) + inherit Visitor.generic_frama_c_visitor (Project.current()) (Cil.copy_visit()) + + val mutable current_label = None + + method private change_label label = + let label = label_map label in + let old_label = current_label in + current_label <- Some label; old_label + + method private restore_term old_label x = + current_label <- old_label; + let x = match x.term_node with + | Ttypeof x -> (* Ttypeof is used as a dummy unary construct *) x + | _ -> assert false + in x + + method private restore_pred old_label x = + current_label <- old_label; + let x = match x.content with + | Pnot x -> (* Pnot is used as a dummy unary construct *) x + | _ -> assert false + in x + + + method vterm t = + match t.term_node with + | Tat (t, l) -> + let old_label = self#change_label l in + let new_t = {t with term_node = Ttypeof t} in + Cil.ChangeDoChildrenPost (new_t, self#restore_term old_label) + | TAddrOf (h, _) | TLval (h, _) | TStartOf (h, _) -> + let old_label = current_label in + let at_label = match h with + | TResult _ -> Some Logic_const.post_label + | _ -> old_label + in + current_label <- None; + let post t = + current_label <- old_label; + match at_label with + | Some label -> {t with term_node = Tat (t, label)} + | None -> t + in Cil.ChangeDoChildrenPost (t, post) + | Tapp _ -> + let post = function + | {term_node=Tapp(predicate,labels,args)} as t -> + let new_labels = + List.map + (fun (logic_lab, stmt_lab) -> logic_lab, label_map stmt_lab) + labels + in { t with term_node=Tapp(predicate,new_labels,args) } + | _ -> assert false + in + Cil.ChangeDoChildrenPost (t,post) + | _ -> Cil.DoChildren + + method vpredicate_named p = match p.content with + | Pat (p, l) -> + let old_label = self#change_label l in + let new_p = {p with content = Pnot p} in + Cil.ChangeDoChildrenPost (new_p, self#restore_pred old_label) + | Papp _ -> + let post = function + | {content=Papp(predicate,labels,args)} as p -> + let new_labels = + List.map + (fun (logic,stmt) -> logic, label_map stmt) + labels + in { p with content=Papp(predicate,new_labels,args) } + | _ -> assert false + in + Cil.ChangeDoChildrenPost (p,post) + | _ -> Cil.DoChildren +end + +exception LabelError of logic_label + +let labels_empty l = raise (LabelError l) + +(* -------------------------------------------------------------------------- *) +(* --- Function Contracts --- *) +(* -------------------------------------------------------------------------- *) + +let labels_fct_pre = function + | LogicLabel (None, ("Pre" | "Here")) -> Logic_const.pre_label + | l -> raise (LabelError l) + + +let labels_fct_post = function + | LogicLabel (None, ("Pre" | "Old")) -> Logic_const.pre_label + | LogicLabel (None, ("Post" | "Here")) -> Logic_const.post_label + | l -> raise (LabelError l) + +let labels_fct_assigns = function + | LogicLabel (None, "Post") -> Logic_const.post_label + | LogicLabel (None, ("Pre" | "Old")) -> Logic_const.pre_label + | l -> raise (LabelError l) + +(* -------------------------------------------------------------------------- *) +(* --- Statements Contracts --- *) +(* -------------------------------------------------------------------------- *) +let labels_stmt_pre s = function + | LogicLabel (None, "Pre") -> Logic_const.pre_label (* fct pre-state *) + | LogicLabel (None, "Here") -> Clabels.mk_logic_label s + | LogicLabel (Some s, _) -> Clabels.mk_logic_label s + | StmtLabel rs -> Clabels.mk_logic_label !rs + | l -> raise (LabelError l) + +let labels_stmt_post s l_post = function + | LogicLabel (None, "Pre") -> Logic_const.pre_label (* fct pre-state *) + | LogicLabel (None, "Old") -> Clabels.mk_logic_label s (* contract pre-state *) + | LogicLabel (None, ("Here" | "Post")) as l -> + begin match l_post with Some l -> l + | None -> (* TODO ? *) raise (LabelError l) + end + | LogicLabel (Some s, _) -> Clabels.mk_logic_label s + | StmtLabel rs -> Clabels.mk_logic_label !rs + | l -> raise (LabelError l) + +let labels_stmt_assigns s l_post = function + | LogicLabel (None, "Pre") -> Logic_const.pre_label (* fct pre-state *) + | LogicLabel (None, ("Here" | "Old")) -> (* contract pre-state *) + Clabels.mk_logic_label s + | LogicLabel (None, "Post") -> labels_stmt_post s l_post Logic_const.post_label + | LogicLabel (Some s, _) -> Clabels.mk_logic_label s + | StmtLabel rs -> Clabels.mk_logic_label !rs + | l -> raise (LabelError l) + +(* -------------------------------------------------------------------------- *) +(* --- User Assertions in Functions Code --- *) +(* -------------------------------------------------------------------------- *) + +let labels_assert_before s = function + | LogicLabel (None, "Pre") -> Logic_const.pre_label + | LogicLabel (None, "Here") -> Clabels.mk_logic_label s + | LogicLabel (Some s, _) -> Clabels.mk_logic_label s + | StmtLabel rs -> Clabels.mk_logic_label !rs + | l -> raise (LabelError l) + +let labels_assert_after s l_post = function + | LogicLabel (None, "Pre") -> Logic_const.pre_label + | LogicLabel (None, "Here") -> + labels_stmt_post s l_post Logic_const.post_label + | LogicLabel (Some s, _) -> Clabels.mk_logic_label s + | StmtLabel rs -> Clabels.mk_logic_label !rs + | l -> raise (LabelError l) + +let labels_loop_inv _s = function + | LogicLabel (None, "Pre") -> Logic_const.pre_label + | LogicLabel (None, "Here") -> Logic_const.here_label + | LogicLabel (None, ("Old" | "Post")) as l -> raise (LabelError l) + | l -> l + +let labels_loop_assigns s l = labels_loop_inv s l + +(* -------------------------------------------------------------------------- *) +(* --- User Defined Predicates --- *) +(* -------------------------------------------------------------------------- *) + +let labels_predicate lab_pairs = fun l -> + try List.assoc l lab_pairs + with Not_found -> l + +let labels_axiom = function + | LogicLabel (None, ("Pre"|"Old"|"Post")) as l -> raise (LabelError l) + | LogicLabel (None, _) as l -> l + | l -> raise (LabelError l) + +(* -------------------------------------------------------------------------- *) +(* --- Apply Normalization --- *) +(* -------------------------------------------------------------------------- *) + +(** @raise LabelError if there is a label in [p] that is incompatible +* with the [labels] translation *) +let preproc_annot labels p = + let visitor = new norm_at labels in + Visitor.visitFramacPredicateNamed visitor p + +(** @raise LabelError if there is a label in [p] that is incompatible +* with the [labels] translation *) +let preproc_assigns labels asgns = + let visitor = new norm_at labels in + List.map (Visitor.visitFramacFrom visitor) asgns + +let preproc_label labels l = labels l + +let catch_label_error ex txt1 txt2 = match ex with + | LabelError lab -> + Wp_parameters.warning + "Unexpected label %a in %s : ignored %s" + Wp_error.pp_logic_label lab txt1 txt2 + | _ -> raise ex diff -Nru frama-c-20110201+carbon+dfsg/src/wp/normAtLabels.mli frama-c-20111001+nitrogen+dfsg/src/wp/normAtLabels.mli --- frama-c-20110201+carbon+dfsg/src/wp/normAtLabels.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/normAtLabels.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,49 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* exception LabelError of logic_label *) +val catch_label_error : exn -> string -> string -> unit + +type label_mapping + +val labels_empty : label_mapping +val labels_fct_pre : label_mapping +val labels_fct_post : label_mapping +val labels_fct_assigns : label_mapping +val labels_assert_before : stmt -> label_mapping +val labels_assert_after : stmt -> logic_label option -> label_mapping +val labels_loop_inv : stmt -> label_mapping +val labels_loop_assigns : stmt -> label_mapping +val labels_stmt_pre : stmt -> label_mapping +val labels_stmt_post : stmt -> logic_label option -> label_mapping +val labels_stmt_assigns : stmt -> logic_label option -> label_mapping +val labels_predicate : (logic_label * logic_label) list -> label_mapping +val labels_axiom : label_mapping + +val preproc_annot : label_mapping -> predicate named -> predicate named + +val preproc_assigns : + label_mapping -> identified_term from list -> identified_term from list + +val preproc_label : label_mapping -> logic_label -> logic_label diff -Nru frama-c-20110201+carbon+dfsg/src/wp/po_navigator.ml frama-c-20111001+nitrogen+dfsg/src/wp/po_navigator.ml --- frama-c-20110201+carbon+dfsg/src/wp/po_navigator.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/po_navigator.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,280 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* This is the panel to control the status of proof obligations. *) + +open Design +open Cil_types +open Wpo + +type row = { + wpo: Wpo.t; + visible : bool +} + +(* Contains the prover associated to the given column *) +module Prover_Column = struct + let column_tbl = Hashtbl.create 7 + let get (col:GTree.view_column) = + try Some (Hashtbl.find column_tbl col#misc#get_oid) + with Not_found -> None + let register col prover = Hashtbl.add column_tbl col#misc#get_oid prover +end + +module SelectionHook=Hook.Build(struct type t = Wpo.t end) + +let refresh_current_wpo = ref (None : (Wpo.t * (prover * result) list) option) +let refresh_panel_callback = ref (fun () -> ()) +let refresh_status_callback = ref (fun () -> ()) + +let make_panel (main_ui:main_window_extension_points) = + let container = GPack.vbox () in + let paned = GPack.paned `VERTICAL + ~packing:(container#pack ~expand:true ~fill:true) + () + in + (* Save position of the vpaned *) + let _ = paned#event#connect#button_release + ~callback:(fun _ -> + Gtk_helper.save_paned_ratio "po_navigator_paned" paned; false) + in + let module MODEL = Gtk_helper.MAKE_CUSTOM_LIST(struct type t = row end) in + let model = MODEL.custom_list () in + + let model_age = ref 0 in + let append m = + incr model_age; + if m.visible then model#insert m + in + let clear () = incr model_age; model#clear () in + let sc = + GBin.scrolled_window + ~vpolicy:`AUTOMATIC + ~hpolicy:`AUTOMATIC + ~packing:paned#add1 + () + in + let view = + GTree.view ~rules_hint:true ~headers_visible:true ~packing:sc#add () + in + ignore + (view#connect#row_activated + ~callback:(fun path col -> + match model#custom_get_iter path,Prover_Column.get col with + | Some ({MODEL.finfo= {wpo=wpo}} as custom), Some prover when prover <> WP + -> + (* copy to prevent Gtk to free it too soon. + Bug in all pre 2.14 versions of Lablgtk2 *) + let path = GtkTree.TreePath.copy path in + + Gui_parameters.debug "Activate %s prover:%a" + wpo.Wpo.po_name Wpo.pp_prover prover ; + let current_model_age = !model_age in + let callout _wpo _prover _result = + if current_model_age = !model_age then + begin + model#custom_row_changed path custom; + Gui_parameters.debug "Custom row changed"; + end; + main_ui#rehighlight () + in + Wpo.set_result wpo prover Wpo.Computing ; + model#custom_row_changed path custom ; + let server = Prover.server () in + let task = + Prover.prove ~callout wpo ~interactive:true prover + in + Task.spawn server task ; + Task.launch server + | _ -> ())); + view#selection#set_select_function + (fun path currently_selected -> + if not currently_selected then + begin match model#custom_get_iter path with + | Some {MODEL.finfo = {wpo=wpo};} -> + Gui_parameters.debug "Select %s@." wpo.Wpo.po_name; + SelectionHook.apply wpo + | None -> () + end; + true); + + let top = `YALIGN 0.0 in + + (* Generic function to add a textual column to the panel. *) + let add_text_column ~title f = + let cview = MODEL.make_view_column model + (GTree.cell_renderer_text [top]) + (fun {wpo=wpo} -> [`TEXT (f wpo)]) + ~title + in + cview#set_resizable true; + ignore (view#append_column cview) + in + + add_text_column + ~title:"Module" + (fun wpo -> + ((fst(Kernel_function.get_location wpo.Wpo.po_fun)).Lexing.pos_fname)) ; + + add_text_column + ~title:"Function" + (fun wpo -> (Kernel_function.get_name wpo.Wpo.po_fun)); + + add_text_column + ~title:"Behavior" + (fun wpo -> match wpo.Wpo.po_bhv with + | None -> "" + | Some b -> b); + + add_text_column + ~title:"Model" + (fun wpo -> wpo.Wpo.po_model); + + add_text_column + ~title:"Property" + (fun wpo -> WpPropId.name_of_prop_id wpo.Wpo.po_pid) ; + + add_text_column + ~title:"Kind" + (fun wpo -> WpPropId.label_of_prop_id wpo.Wpo.po_pid); + + let icon_of_result = function + | Wpo.Valid -> "gtk-yes" + | Wpo.Failed _ -> "gtk-dialog-error" + | Wpo.Unknown -> "gtk-dialog-question" + | Wpo.Timeout -> "gtk-cut" + | Wpo.Invalid -> "gtk-no" + | Wpo.Computing -> "gtk-execute" + in + + let name_of_prover = function + | Why s -> String.capitalize s + | AltErgo -> "Alt-Ergo" + | Coq -> "Coq" + | WP -> "WP" + in + + (* Prover columns *) + let make_prover_status prover = + let cview = MODEL.make_view_column model + (GTree.cell_renderer_pixbuf [top]) + (fun {wpo=wpo} -> + match Wpo.get_result wpo prover with + | Some r -> [ `STOCK_ID (icon_of_result r) ] + | None -> + if prover=WP + then [ `PIXBUF(Gtk_helper.Icon.get Gtk_helper.Icon.Unmark) ] + else [ `STOCK_ID "" ]) + ~title:(name_of_prover prover) + in + cview#set_resizable true; + cview#set_clickable true; + ignore (cview#connect#clicked + (fun () -> + Gui_parameters.debug "Clicked on column %a" Wpo.pp_prover prover)) ; + ignore (view#append_column cview); + Prover_Column.register cview prover + in + List.iter make_prover_status Wpo.gui_provers ; + + (* Last column is empty and juste uses the extra white space *) + let last_column = GTree.view_column ~title:"" () in + ignore (view#append_column last_column); + + view#set_model (Some model#coerce); + + let information_window = Source_manager.make ~packing:paned#add2 ~tab_pos:`RIGHT () in + SelectionHook.extend + (fun wpo -> + let results = Wpo.get_results wpo in + match !refresh_current_wpo with + | Some (wold,rold) when + (wold.po_gid = wpo.po_gid) && (Pervasives.compare rold results = 0) -> () + | _ -> + begin + refresh_current_wpo := Some (wpo,results) ; + Source_manager.clear information_window ; + List.iter + (fun (title,filename) -> + Source_manager.load_file information_window ~title ~filename ~line:1 ()) + [ + "Obligation" , Wpo.file_for_body ~gid:wpo.po_gid ; + "Description" , Wpo.file_for_head ~gid:wpo.po_gid ; + "Environment" , Wpo.file_for_ctxt ~env:wpo.po_env ; + ] ; + List.iter + (fun (prover,result) -> + if prover <> Wpo.WP && result <> Wpo.Computing then + let title = name_of_prover prover in + let filename = Wpo.file_for_log_proof ~gid:wpo.Wpo.po_gid prover in + Source_manager.load_file information_window ~title ~filename () + ) results ; + Source_manager.select_name information_window "Obligation" ; + end + ) ; + + let fill_model () = + Wpo.iter ~on_goal:(fun wpo -> append {wpo=wpo; visible=true}) () + in + + refresh_panel_callback := + (fun () -> + main_ui#protect ~cancelable:false + (fun () -> + clear (); + if paned#position < 64 then paned#set_position 64 ; + fill_model ())) ; + + refresh_status_callback := + (fun () -> + model#foreach (fun p i -> model#row_changed p i;false) ; + match !refresh_current_wpo with + | None -> () + | Some (wpo,_) -> SelectionHook.apply wpo + ) ; + + (*To position the panels at startup:*) + let (_:GtkSignal.id) = view#misc#connect#after#realize + (fun () -> + !refresh_panel_callback () ; + Gtk_helper.place_paned paned + (Gtk_helper.Configuration.find_float + ~default:0.60 + "po_navigator_paned")) + in + ignore (main_ui#lower_notebook#append_page + ~tab_label:(GMisc.label ~text:"WP Proof Obligations" ())#coerce + (container#coerce)) + +let extend (main_ui:main_window_extension_points) = + make_panel main_ui + +let () = Design.register_extension extend + +let refresh_panel () = !refresh_panel_callback () +let refresh_status () = !refresh_status_callback () + +(* + Local Variables: + compile-command: "make -C ../.." + End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/po_navigator.mli frama-c-20111001+nitrogen+dfsg/src/wp/po_navigator.mli --- frama-c-20110201+carbon+dfsg/src/wp/po_navigator.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/po_navigator.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Extension of the GUI in order to navigate in Proof obligations. + No function is exported. *) + +val refresh_panel : unit -> unit + (** To be called when the set of POs has changed *) + +val refresh_status : unit -> unit + (** To be called when the status of POs has changed *) + +(* + Local Variables: + compile-command: "make -C ../.." + End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/proof.ml frama-c-20111001+nitrogen+dfsg/src/wp/proof.ml --- frama-c-20110201+carbon+dfsg/src/wp/proof.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/proof.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,200 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Proof Script Database --- *) +(* -------------------------------------------------------------------------- *) + +let scriptbase = Hashtbl.create 81 +let scriptfile = ref None (* current file script name *) +let needback = ref true (* file script need backup before modification *) +let needsave = ref true (* file script need to be saved *) + +let clear () = + begin + Hashtbl.clear scriptbase ; + scriptfile := None ; + needback := false ; + needsave := false ; + end + +let register_script goal keys proof = + Hashtbl.replace scriptbase goal (List.sort String.compare keys,proof) + +(* -------------------------------------------------------------------------- *) +(* --- Proof Scripts Parsers --- *) +(* -------------------------------------------------------------------------- *) + +open Script + +let parse_coqproof file = + let input = Script.open_file file in + try + let rec fetch_proof input = + match token input with + | Proof p -> Some p + | Eof -> None + | _ -> skip input ; fetch_proof input + in + let proof = fetch_proof input in + Script.close input ; proof + with e -> + Script.close input ; + raise e + +let rec collect_scripts input = + while key input "Goal" do + let g = ident input in + eat input "." ; + let xs = + if key input "Hint" then + let xs = idents input in + eat input "." ; xs + else [] in + let p = + match token input with + | Proof p -> skip input ; p + | _ -> error input "Missing proof" + in + register_script g xs p + done ; + if token input <> Eof + then error input "Unexpected script declaration" + +let parse_scripts file = + if Sys.file_exists file then + begin + let input = Script.open_file file in + try + collect_scripts input ; + Script.close input ; + with e -> + Script.close input ; + raise e + end + +let dump_scripts file = + let out = open_out file in + let fmt = Format.formatter_of_out_channel out in + try + Format.fprintf fmt "(* Generated by Frama-C (WP) *)@\n@\n" ; + Hashtbl.iter + (fun goal (keys,proof) -> + Format.fprintf fmt "Goal %s.@\n" goal ; + (match keys with + | [] -> () + | k::ks -> + Format.fprintf fmt "Hint %s" k ; + List.iter (fun k -> Format.fprintf fmt ",%s" k) ks ; + Format.fprintf fmt ".@\n"); + Format.fprintf fmt "Proof.@\n%sQed.@\n@." proof) + scriptbase ; + Format.pp_print_newline fmt () ; + close_out out ; + with e -> + Format.pp_print_newline fmt () ; + close_out out ; + raise e + +(* -------------------------------------------------------------------------- *) +(* --- Scripts Management --- *) +(* -------------------------------------------------------------------------- *) + +let rec choose k = + let file = Printf.sprintf "wp%d.script" k in + if Sys.file_exists file then choose (succ k) else file + +let savescripts () = + if !needsave then + match !scriptfile with + | None -> () + | Some file -> + try + if !needback then + ( Command.copy file (file ^ ".back") ; needback := false ) ; + dump_scripts file ; + needsave := false ; + with e -> + Wp_parameters.abort + "Error when dumping script file '%s':@\n%s" file + (Printexc.to_string e) + +let loadscripts () = + let user = Wp_parameters.Script.get () in + if !scriptfile <> Some user then + begin + savescripts () ; + let file = + if user = "" then + let ftmp = choose 0 in + Wp_parameters.warning + "No script file specified.@\n\ + Your proofs would be saved in '%s'@\n\ + Use -wp-script '%s' to re-run them." + ftmp ftmp ; + Wp_parameters.Script.set ftmp ; + ftmp + else + user + in + scriptfile := Some file ; + (* keep needsave *) + if Sys.file_exists file then + begin + needback := true ; + try parse_scripts user ; + with e -> + Wp_parameters.abort + "Error in script file '%s':@\n%s" user + (Printexc.to_string e) + end + else + needback := false + end + +let find_script_for_goal goal = + loadscripts () ; + try Some(snd (Hashtbl.find scriptbase goal)) + with Not_found -> None + +let rec suitable h mask keys = + match mask , keys with + | m::ms , k::ks -> + let c = String.compare m k in + if c < 0 then suitable h ms keys else + if c > 0 then suitable h mask ks else + suitable (succ h) ms ks + | _ -> h + +let most_suitable (h,_) (h',_) = h'-h + +let find_script_for_keywords keys = + loadscripts () ; + Hashtbl.fold + (fun _ (xs,p) scripts -> + let h = suitable 0 xs keys in + if h>0 then List.merge most_suitable [h,p] scripts + else scripts) + scriptbase [] + +let add_script goal keys proof = + needsave := true ; register_script goal keys proof diff -Nru frama-c-20110201+carbon+dfsg/src/wp/proof.mli frama-c-20111001+nitrogen+dfsg/src/wp/proof.mli --- frama-c-20110201+carbon+dfsg/src/wp/proof.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/proof.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,60 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Proof Script Database *) +(* -------------------------------------------------------------------------- *) + +(** {2 Database} *) + +val add_script : string -> string list -> string -> unit + (** [new_script goal keys proof] registers the script [proof] for goal [goal] + and keywords [keys] *) + +val find_script_for_goal : string -> string option + (** Retrieve script file for one specific goal. The file specified + by [-wp-script f] is loaded if necessary. *) + +val find_script_for_keywords : string list -> (int * string) list + (** Retrieve matchable script files for w.r.t provided keywords. + Most suitable scripts comes first. *) + +val clear : unit -> unit + +val loadscripts : unit -> unit + (** Load scripts from [-wp-script f]. Automatically invoked by [find_xxx] unless + [loadscripts] flags is unset. *) + +val savescripts : unit -> unit + (** If necessary, dump the scripts database into the file + specified by [-wp-script f]. *) + +(** {2 Low-level Parsers and Printers} *) + +val parse_coqproof : string -> string option + (** [parse_coqproof f] parses a coq-file [f] and fetch the first proof. *) + +val parse_scripts : string -> unit + (** [parse_scripts f] parses all scripts from file [f] and put them in the database. *) + +val dump_scripts : string -> unit + (** [dump_scripts f] saves all scripts from the database into file [f]. *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/prover.ml frama-c-20111001+nitrogen+dfsg/src/wp/prover.ml --- frama-c-20110201+carbon+dfsg/src/wp/prover.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/prover.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,604 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Prover Implementation against Task API --- *) +(* -------------------------------------------------------------------------- *) + +open Task +open Wpo +type verdict = Valid | Invalid | Unknown + +(* -------------------------------------------------------------------------- *) +(* --- File Preparation Utilities --- *) +(* -------------------------------------------------------------------------- *) + +let cat files cout = + let buffer = String.create 2048 in + List.iter + (fun f -> + let cin = open_in f in + try + Command.bincopy buffer cin cout ; + close_in cin + with e -> + close_in cin ; raise e) + files + +let export file preludes pp = + let cout = open_out file in + try + cat preludes cout ; + flush cout ; + let fmt = Format.formatter_of_out_channel cout in + pp fmt ; + Format.pp_print_newline fmt () ; + Format.pp_print_flush fmt () ; + close_out cout ; + with err -> + close_out cout ; + raise err + +(* managment of the file PO_log.txt generated into the output_dir *) +module Logs = +struct + + type t = { + logid : string ; + logout : out_channel ; + logfmt : Format.formatter ; + mutable logcmd : (string * string array) option ; + mutable files : string list ; + } + + let create w logfile = + let outc = open_out logfile in + let fmt = Format.formatter_of_out_channel outc in + { + logid = w.po_gid ; + logout = outc ; + logfmt = fmt ; + logcmd = None ; + files = [] ; + } + + let pp_command fmt cmd args = + begin + Format.fprintf fmt "@[<hov 4>%s" cmd ; + Array.iter + (fun arg -> Format.fprintf fmt "@ %s" arg) + args ; + Format.fprintf fmt "@]@." ; + end + + let pp_current fmt t = + match t.logcmd with + | None -> () + | Some (cmd,args) -> pp_command fmt cmd args + + let pp_status fmt = + function + | Task.Result res -> + if res <> 0 then Format.fprintf fmt "Exit [%d]@." res + | Task.Canceled -> + Format.fprintf fmt "Timeout@." + | Task.Failed exn -> + Format.fprintf fmt "Failed \"%s\"@." (Printexc.to_string exn) + + let command t cmd args = + begin + t.logcmd <- Some (cmd,args) ; + pp_command t.logfmt cmd args ; + end + + let add_file t f = t.files <- f :: t.files + + let log_status t st = Format.fprintf t.logfmt "Run %a" pp_status st + + let is_error ?(status=[0]) = function + | Task.Result r -> not (List.mem r status) + | Task.Canceled -> false + | Task.Failed _ -> true + + let output t ?status (stdout:Buffer.t) st = + let msg = Buffer.contents stdout in + begin + log_status t st ; + Format.pp_print_string t.logfmt msg ; + Format.pp_print_newline t.logfmt () ; + if is_error ?status st then + begin + let cname = match t.logcmd with None -> "<?>" | Some (cmd,_) -> cmd in + Wp_parameters.error "command '%s' failed." cname ; + if not !Config.is_gui then + Log.print_on_output (fun fmt -> Format.fprintf fmt "%a%s" pp_current t msg) ; + end + end + + let clean files = + if not (Wp_parameters.is_out ()) then + List.iter + (fun file -> + try if Sys.file_exists file then Unix.unlink file ; + with Unix.Unix_error(err,_,_) -> + Wp_parameters.debug ~dkey:"tmp" "removing tmp file '%s':@ %s" + file (Unix.error_message err) + ) files + + let close_out t = + try + Format.pp_print_flush t.logfmt () ; + Pervasives.close_out t.logout ; + with exn -> + Wp_parameters.failure "Can not close log file (%s)" + (Printexc.to_string exn) + + let close t = + begin + close_out t ; + clean t.files ; + t.files <- [] ; + t.logcmd <- None ; + end + +end + +(* -------------------------------------------------------------------------- *) +(* --- Why & Other SMT --- *) +(* -------------------------------------------------------------------------- *) + +module PO = +struct + + let make language w = + let gfile = Wpo.file_for_po ~gid:w.po_gid language in + export gfile [ + file_for_model ~model:w.po_model language ; + file_for_env ~env:w.po_env language ; + file_for_goal ~gid:w.po_gid language ; + ] (fun _fmt -> ()) ; + gfile + +end + +module SMT = +struct + + type t = { + ext : string ; (* file extension *) + why : string array ; (* why options *) + wdp : string array ; (* why-dp options *) + } + + let yices = { + ext = "smt" ; + why = [| "--smtlib" |] ; + wdp = [| "-smt-solver" ; "yices" |] ; + } + + let cvc3 = { + ext = "smt" ; + why = [| "--smtlib" |] ; + wdp = [| "-smt-solver" ; "cvc3" |] ; + } + + let z3 = { + ext = "z3.smt" ; + why = [| "--z3" |] ; + wdp = [| "-smt-solver" ; "z3" |] ; + } + + let simplify = { + ext = "sx" ; + why = [| "--simplify" |] ; + wdp = [| |] ; + } + + let vampire = { + ext = "vp"; + why = [| "--vampire" |]; + wdp = [| |]; + } + + let altergo = { + ext = "why" ; + why = [| "--alt-ergo" |] ; + wdp = [| |] ; + } + + let zenon = { + ext = "znn" ; + why = [| "--zenon" |] ; + wdp = [| |] ; + } + + let of_name dp = + match String.lowercase dp with + | "yices" -> yices + | "cvc3" -> cvc3 + | "z3" -> z3 + | "vampire" -> vampire + | "simplify" -> simplify + | "alt-ergo" -> altergo + | "zenon" -> zenon + | _ -> Wp_parameters.abort "Unknown prover '%s'" dp + + let translate logs smt w = + let goal = PO.make L_why w in + Logs.add_file logs goal ; + let base = Filename.chop_suffix goal ".why" in + let file = Printf.sprintf "%s_why.%s" base smt.ext in + Logs.add_file logs file ; + let args = Array.append smt.why [| goal |] in + let stdout = Buffer.create 512 in + Logs.command logs "why" args ; + Task.command ~stdout "why" args + >>? Logs.output logs stdout + >>= fun res -> + if res = 0 then Task.return file + else Task.failed "Why exit %d" res + + let whydp logs smt file = + let timeout = Wp_parameters.Timeout.get () in + let stdout = Buffer.create 80 in + let stderr = Buffer.create 80 in + let my_args = + if Wp_parameters.ProofTrace.get () then + [| "-batch"; "-debug"; file |] + else + [| "-batch"; file |] + in + let args = Array.append smt.wdp my_args in + Logs.command logs "why-dp" args ; + Task.command ~timeout ~stdout ~stderr "why-dp" args + >>? Logs.output logs ~status:[0;1;2;3;4] stdout + >>? Logs.output logs stderr + (* why-dp returns the output of the prover on stderr *) + >>= fun res -> + if res = 0 then Task.return Valid + else + if (1<= res && res <= 4) then Task.return Unknown + else Task.failed "Why-dp exit %d" res + + let prove dp log w = + let smt = of_name dp in + translate log smt w >>= whydp log smt + + let check logs w = + let timeout = Wp_parameters.Timeout.get () in + let stdout = Buffer.create 80 in + let goal = PO.make L_why w in + Logs.add_file logs goal ; + let args = [| "--type-only" ; goal|] in + Logs.command logs "why" args; + Task.command ~timeout ~stdout "why" args + >>? Logs.output logs stdout + >>= fun res -> + if res = 0 then Task.return Valid else Task.return Invalid + +end + +(* -------------------------------------------------------------------------- *) +(* --- Prover Alt-Ergo --- *) +(* -------------------------------------------------------------------------- *) + +module AltErgo = +struct + + let valid = Str.regexp "\\bValid\\b" + + let prove logs w = + let timeout = Wp_parameters.Timeout.get () in + let stdout = Buffer.create 80 in + let goal = PO.make L_altergo w in + Logs.add_file logs goal ; + let args = + if Wp_parameters.ProofTrace.get () + then [| "-proof" ; goal |] + else [| goal |] + in + Logs.command logs "alt-ergo" args ; + Task.command ~timeout ~stdout "alt-ergo" args + >>? Logs.output logs stdout + >>= fun s -> + if s=0 then + let response = Buffer.contents stdout in + try + ignore (Str.search_forward valid response 0) ; + Task.return Valid + with Not_found -> + Task.return Unknown + else + Task.failed "Alt-Ergo exit %d" s + + let check logs w = + let timeout = Wp_parameters.Timeout.get () in + let stdout = Buffer.create 80 in + let goal = PO.make L_altergo w in + Logs.add_file logs goal ; + let args = [| "-type-only"; goal |] in + Logs.command logs "alt-ergo" args ; + Task.command ~timeout ~stdout "alt-ergo" args + >>? Logs.output logs stdout + >>= fun s -> + if (s = 0) then Task.return Valid + else Task.return Invalid + +end + + +(* -------------------------------------------------------------------------- *) +(* --- Prover Coq --- *) +(* -------------------------------------------------------------------------- *) + + +module Coq = +struct + + let compiled : (string,unit Task.task) Hashtbl.t = Hashtbl.create 83 + let revert_on_error key = function + | Task.Result _ -> () + | _ -> Hashtbl.remove compiled key + let once key cc = + try Hashtbl.find compiled key + with Not_found -> + let t = Task.nop >>= cc >>? revert_on_error key in + Hashtbl.add compiled key t ; t + + let result_compile file r = + if r<>0 + then Task.failed "Compilation of '%s' failed" file + else Task.return () + + let require_wp logs = + once "wp" + (fun () -> + let denv = Wp_parameters.get_output () in + let dshare = Wp_parameters.get_share() in + let shared = Format.sprintf "%s/wp.v" dshare in + let work = Format.sprintf "%s/wp.v" denv in + Command.copy shared work ; + (* no added ! -> incremental compilation *) + let args = [| "-noglob" ; work |] in + let stdout = Buffer.create 512 in + let timeout = Wp_parameters.Timeout.get() in + Logs.command logs "coqc" args ; + Task.command ~timeout ~stdout "coqc" args + >>? Logs.output logs stdout + >>= result_compile work) + + let require_model logs w = + let model = w.po_model in + once model + (fun () -> + let file = Wpo.file_for_model ~model L_coq in + let fcoq = Wpo.coqc_for_model ~model in + Command.copy file fcoq ; + (* not added ! -> incremental compilation *) + let denv = Wp_parameters.get_output () in + let args = [| "-noglob" ; "-I" ; denv ; fcoq |] in + let stdout = Buffer.create 512 in + let timeout = Wp_parameters.Timeout.get() in + Logs.command logs "coqc" args ; + Task.command ~timeout ~stdout "coqc" args + >>? Logs.output logs stdout + >>= result_compile fcoq) + + let require_env logs w = + let env = w.po_env in + once env + (fun () -> + let denv = Wp_parameters.get_output () in + let file = file_for_env env L_coq in + (* not added ! -> incremental compilation *) + let args = [| "-noglob"; "-I" ; denv ; file |] in + let stdout = Buffer.create 512 in + let timeout = Wp_parameters.Timeout.get() in + Logs.command logs "coqc" args ; + Task.command ~timeout ~stdout "coqc" args + >>? Logs.output logs stdout + >>= result_compile file) + + let default = + " (** FILL PROOF HERE.**)\n \ + intros; repeat(split; intros); auto;\n \ + try contradiction; auto; eauto ; try omega.\n" + + let proof logs w script = + let gid = w.po_gid in + let env = w.po_env in + let model = w.po_model in + let goal = Wpo.file_for_goal ~gid L_coq in + let proof = Wpo.file_for_po ~gid L_coq in + Command.pp_to_file proof + (fun fmt -> + Format.fprintf fmt "Require Import Reals.@\n"; + Format.fprintf fmt "Require Import wp.@\n"; + Format.fprintf fmt "Require Import %s.@\n" (Wpo.coq_for_model ~model); + Format.fprintf fmt "Require Import %s.@\n" (Wpo.coq_for_env ~env); + Command.pp_from_file fmt goal ; + begin + match script with + | Some script -> + Format.fprintf fmt "Proof.@\n%sQed.@\n@." script ; + | None -> (* This case is for check*) + Format.fprintf fmt "Proof.@\nAdmitted.@\n@." ; + end + ) ; + Logs.add_file logs proof ; + Task.return proof + + let coqc logs w script = + proof logs w script >>= + fun fgoal -> + let fgoal = Filename.chop_suffix fgoal ".v" in + Logs.add_file logs (fgoal ^ ".vo") ; + let denv = Wp_parameters.get_output() in + let timeout = Wp_parameters.Timeout.get() in + let stdout = Buffer.create 512 in + let args = [| "-noglob";"-I" ; denv ; "-compile"; fgoal |] in + Logs.command logs "coqtop" args ; + Task.command ~timeout ~stdout "coqtop" args + >>? Logs.output logs ~status:[0;1] stdout + + let script_for w = + Some + ( match Proof.find_script_for_goal w.po_gid with + | None -> default + | Some script -> script ) + + let prove log w = + require_wp log + >>= fun _ -> require_model log w + >>= fun _ -> require_env log w + >>= fun _ -> coqc log w (script_for w) + >>= Task.call (fun r -> if r=0 then Valid else Unknown) + + let check log w = + require_wp log + >>= fun _ -> require_model log w + >>= fun _ -> require_env log w + >>= fun _ -> coqc log w None + >>= Task.call (fun r -> if r=0 then Valid else Invalid) + + +end + +module Coqide = +struct + + let coqidelock = Task.mutex () + + let run_coqide logs w proof = + let denv = Wp_parameters.get_output() in + let gid = w.po_gid in + let coqide () = + let head = Wpo.file_for_head gid in + let env = Wpo.file_for_env w.po_env L_coq in + let model = Wpo.coqc_for_model ~model:w.po_model in + let dshare = Wp_parameters.get_share() in + let wp_share = Format.sprintf "%s/wp.v" dshare in + let args = + match Wp_parameters.Script.get() with + | fscript when Sys.file_exists fscript -> + [| "-I" ; denv ; proof; head; env; model; wp_share; fscript |] + | _ -> + [| "-I" ; denv ; proof; head; env; model; wp_share |] + in + Logs.command logs "coqide" args ; + Task.command "coqide" args + >>? Logs.log_status logs + in + Task.sync coqidelock coqide >>= + fun s -> + if s <> 0 then Task.return Unknown + else + match Proof.parse_coqproof proof with + | None -> + Wp_parameters.feedback "No proof found" ; + Task.return Unknown + | Some script -> + Wp_parameters.feedback "Check proof" ; + Coq.coqc logs w (Some script) >>= + Task.call + (fun s -> + Proof.add_script gid [] script ; + if s=0 then Valid else Unknown) + + let prove log w = + Coq.prove log w >>= function + | Unknown | Invalid -> + Coq.proof log w (Coq.script_for w) >>= + run_coqide log w + | Valid -> Task.return Valid + +end + +(* -------------------------------------------------------------------------- *) +(* --- Main Dispatcher --- *) +(* -------------------------------------------------------------------------- *) + +let task_for interactive = function + | AltErgo -> AltErgo.prove + | Why dp -> SMT.prove dp + | Coq -> if interactive then Coqide.prove else Coq.prove + | WP -> fun _ _ -> Task.return Unknown + +let result = function + | Task.Result Valid -> Wpo.Valid + | Task.Result Invalid -> Wpo.Invalid + | Task.Result Unknown -> Wpo.Unknown + | Task.Canceled -> Wpo.Timeout + | Task.Failed exn -> Wpo.Failed (Printexc.to_string exn) + +let prove + ?(callin=fun _ _ -> ()) + ?(callout=fun _ _ _ -> ()) + wpo ~interactive prover + = + Task.todo + begin + fun () -> + let logf = Wpo.file_for_log_proof ~gid:wpo.po_gid prover in + let logs = Logs.create wpo logf in + (callin wpo prover ; + task_for interactive prover logs wpo) + >>! fun s -> + let r = result s in + Logs.close logs ; + Wpo.set_result wpo prover r ; + callout wpo prover r + end + +let check_by = function + | L_altergo -> AltErgo.check + | L_why -> SMT.check + | L_coq -> Coq.check + +let check + ?(callout=fun _ _ _ -> ()) + wpo lang + = + Task.todo + begin + fun () -> + let logf = Wpo.file_for_log_check ~gid:wpo.po_gid lang in + let log = Logs.create wpo logf in + check_by lang log wpo + >>! fun s -> + let r = result s in + Logs.close log ; + callout wpo lang r + end + +let server = ref None + +let server () = + match !server with + | Some s -> + let procs = Wp_parameters.Procs.get () in + Task.set_procs s procs ; s + | None -> + let procs = Wp_parameters.Procs.get () in + let s = Task.server ~procs () in + Task.on_server_stop s Proof.savescripts ; + server := Some s ; s diff -Nru frama-c-20110201+carbon+dfsg/src/wp/prover.mli frama-c-20111001+nitrogen+dfsg/src/wp/prover.mli --- frama-c-20110201+carbon+dfsg/src/wp/prover.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/prover.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,42 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Prover Implementation against Task API --- *) +(* -------------------------------------------------------------------------- *) + +val server : unit -> Task.server + +(** {1 Prover Implementations} *) + +type verdict = Valid | Invalid | Unknown + +val prove : + ?callin:(Wpo.t -> Wpo.prover -> unit) -> + ?callout:(Wpo.t -> Wpo.prover -> Wpo.result -> unit) -> + Wpo.t -> interactive:bool -> Wpo.prover -> unit Task.task + +(** The task will run the prover and update the Wpo base accordingly. *) + +val check : + ?callout:(Wpo.t -> Wpo.language -> Wpo.result -> unit) -> + Wpo.t -> Wpo.language -> unit Task.task diff -Nru frama-c-20110201+carbon+dfsg/src/wp/register.ml frama-c-20111001+nitrogen+dfsg/src/wp/register.ml --- frama-c-20110201+carbon+dfsg/src/wp/register.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/register.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,572 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + + +(* -------------------------------------------------------------------------- *) +(* --- WP Models for VC generation --- *) +(* -------------------------------------------------------------------------- *) + + +module F = Fol_formula +module A = Mint_natural.Create(F) +module R = Mfloat_natural.Create(F) + +module Hoare = Hoare_mem.Create(F)(A)(R) +module Store = Store_mem.Create(F)(A)(R) +module Runtime = Runtime_mem.Create(F)(A)(R) + +module Th = +struct + let tau_of_ctype_logic t = + Hoare.tau_of_object (Ctypes.object_of t) +end +module HW = Fol_why.EWhy(Th) +module HQ = Fol_coq.ECoq(Th) +module HE = Fol_ergo.Make(Th) + +module Ts = +struct + let tau_of_ctype_logic t = + Store.tau_of_object (Ctypes.object_of t) +end +module SW = Fol_why.EWhy(Ts) +module SQ = Fol_coq.ECoq(Ts) +module SE = Fol_ergo.Make(Ts) + +module Tr = +struct + let tau_of_ctype_logic t = + Runtime.tau_of_object (Ctypes.object_of t) +end +module RW = Fol_why.EWhy(Tr) +module RQ = Fol_coq.ECoq(Tr) +module RE = Fol_ergo.Make(Tr) + +module MCriteria : Funvar_mem.Criteria = struct let isHoare = false end + +module HCriteria : Funvar_mem.Criteria = struct let isHoare = true end + +(* +module FQed = Fol_qed.F +module DQed = Datalib.Create(FQed) +module AQed = Mint_natural.Create(DQed) +module RQed = Mfloat_natural.Create(DQed) +module EQed = Fol_qed.E +*) + +(* --------- WP Calculus Engines ------------------ *) + +module WP_Hoare = + CfgProof.Create(Funvar_mem.Create(HCriteria)(Hoare))(HW)(HQ)(HE) + (Fol_split) + (struct + let shared = "hoare" + let context = "hoare" + let updater = "Hoare" + let name = "Hoare" + end) + +module WP_Store = CfgProof.Create(Store)(SW)(SQ)(SE) + (Fol_split) + (struct + let shared = "store" + let context = "store_full" + let updater = "Store-Full" + let name = "Store(full memory)" + end) + +module WP_Storefun = + CfgProof.Create(Funvar_mem.Create(MCriteria)(Store))(SW)(SQ)(SE) + (Fol_split) + (struct + let shared = "store" + let context = "store" + let updater = "Store" + let name = "Store" + end) + +module WP_Runtime = CfgProof.Create(Runtime)(RW)(RQ)(RE) + (Fol_split) + (struct + let shared = "runtime" + let context = "runtime_full" + let updater = "Runtime-Full" + let name = "Runtime(full memory)" + end) + +module WP_Runtimefun = + CfgProof.Create(Funvar_mem.Create(MCriteria)(Runtime))(RW)(RQ)(RE) + (Fol_split) + (struct + let shared = "runtime" + let context = "runtime" + let updater = "Runtime" + let name = "Runtime" + end) + +(* --------- WP Dispatcher ------------------ *) + +type feature = NA | Yes | No + +type wp_model = { + wp_name : string ; + wp_qed : feature ; + wp_logicvar : feature ; + wp_method : unit -> Mcfg.assigns_method ; + wp_computer : unit -> CfgProof.computer ; + wp_altmodel : (unit -> CfgProof.computer) option ; +} + +let wp_model name = { + wp_name = name ; + wp_qed = NA ; + wp_logicvar = NA ; + wp_method = (fun () -> Wp_parameters.fatal "no method implemented") ; + wp_computer = (fun () -> Wp_parameters.fatal "computer not implemented") ; + wp_altmodel = None ; +} + +let option opt = function + | NA -> true + | Yes -> opt () + | No -> not (opt ()) + +type 'a computing_methods = + | OneforBoth of 'a + | NonAssigns of 'a + | OneforEach of 'a * 'a (*non assigns, assigns only*) + +let dispatch models = + try + let model = List.find + (fun m -> + List.for_all + (fun (opt,f) -> + match f with + | NA -> true + | Yes -> opt () + | No -> not (opt ()) ) + [ + (fun () -> false) (*Wp_parameters.Qed.get*) , m.wp_qed ; + Wp_parameters.LogicVar.get , m.wp_logicvar ; + ] + ) models in + let computer = model.wp_computer () in + match model.wp_method () , model.wp_altmodel with + | Mcfg.NoAssigns , None -> NonAssigns computer + | Mcfg.NoAssigns , Some alt -> OneforEach( computer , alt () ) + | _ -> OneforBoth computer + with Not_found -> + Wp_parameters.abort "No model found with provided criteria" + +(* --------- WP Computer -------------------- *) + +(* + computer returns : + - either one computer for both assigns and non-assigns + - or a unique computer for only non-assigns + - or two computers, one for assigns and one for non-assigns +*) + +let computer = function + + | Wp_parameters.M_Hoare -> + NonAssigns (WP_Hoare.create ()) + | Wp_parameters.M_Store -> + dispatch [ + { (wp_model "Store") with + wp_logicvar = Yes ; + wp_method = WP_Storefun.assigns_method ; + wp_computer = WP_Storefun.create ; + wp_altmodel = Some WP_Store.create ; + } ; + { (wp_model "Store") with + wp_logicvar = No ; + wp_method = WP_Store.assigns_method ; + wp_computer = WP_Store.create ; + } + ] + + | Wp_parameters.M_Runtime -> + dispatch [ + { (wp_model "Runtime") with + wp_logicvar = Yes ; + wp_method = WP_Runtimefun.assigns_method ; + wp_computer = WP_Runtimefun.create ; + wp_altmodel = Some WP_Runtime.create ; + } ; + { (wp_model "Runtime") with + wp_logicvar = No ; + wp_method = WP_Runtime.assigns_method ; + wp_computer = WP_Runtime.create ; + } + ] + +(* ------------------------------------------------------------------------ *) +(* --- Iterators --- *) +(* ------------------------------------------------------------------------ *) + +(* TODO: clean that because we now do the same thing on functions with or +* without definition... +*) + +let on_definition phi kf = + match kf.Cil_types.fundec with + | Cil_types.Declaration _ (* -> + Wp_parameters.warning ~current:false "Function %s has no body (skipped)" + (Kernel_function.get_name kf) *) + | Cil_types.Definition _ -> phi kf + +let on_all_functions = fun do_body -> + Globals.Functions.iter (fun kf -> + !Db.progress (); + (*match kf.fundec with + | Declaration _ -> () + | Definition _ -> *) + on_definition do_body kf) + +let on_function_names fcts = fun do_body -> + List.iter + (fun fname -> + try + let kf = Globals.Functions.find_by_name fname in + on_definition do_body kf + with Not_found -> + Wp_parameters.error "Unknown function '%s' (skipped)" fname + ) fcts + +let on_function kf = fun do_body -> on_definition do_body kf + +(* ------------------------------------------------------------------------ *) +(* --- Shared Functions for both GUI and command line --- *) +(* ------------------------------------------------------------------------ *) + + +let dot_lannots lannots = + let do_dot annots = + let cfg = WpStrategy.cfg_of_strategy annots in + let pp_annots fmt e = + WpStrategy.pp_annots fmt (WpStrategy.get_annots annots e) + in + let bhv = WpStrategy.behavior_name_of_strategy annots in + ignore (Cil2cfg.dot_annots cfg bhv pp_annots) + in List.iter do_dot lannots + +type prop = + | NamedProp of string + | IdProp of Property.t + +let do_compute + (goals : Wpo.t Bag.t ref) + (computer : CfgProof.computer) + fun_iter assigns behaviors property call_stmt_opt + = + let do_kf kf = + !Db.progress () ; + let annots = match behaviors, property with + | [], None -> + let s = match call_stmt_opt with + | Some stmt -> WpAnnot.get_call_pre_strategies stmt + | None -> + if Wp_parameters.Froms.get () + then WpFroms.get_strategies_for_froms kf + else WpAnnot.get_function_strategies ~assigns kf + in s + | (_ :: _) as bhvs, None -> + WpAnnot.get_behavior_strategies ~assigns kf bhvs + | _, Some (IdProp p) -> + WpAnnot.get_id_prop_strategies ~assigns p + | _, Some (NamedProp p) -> + WpAnnot.get_prop_strategies ~assigns kf (behaviors, p) + in + if Wp_parameters.Dot.get () then dot_lannots annots; + computer#add annots + in + begin + fun_iter do_kf ; + goals := Bag.concat !goals (Bag.list computer#compute) ; + end + +(* ------------------------------------------------------------------------ *) +(* --- Printing informations --- *) +(* ------------------------------------------------------------------------ *) + +let do_wp_print () = + (* Printing *) + if Wp_parameters.Print.get () then + try + Wpo.iter ~on_goal:(fun _ -> raise Exit) () ; + Wp_parameters.result "No proof obligations" + with Exit -> + Log.print_on_output + (fun fmt -> + Wpo.iter + ~on_environment:(Wpo.pp_environment fmt) + ~on_behavior:(Wpo.pp_function fmt) + ~on_goal:(Wpo.pp_goal_flow fmt) ()) + +let do_wp_print_for goals = + if Wp_parameters.Print.get () then + if Bag.is_empty goals + then Wp_parameters.result "No proof obligations" + else Log.print_on_output + (fun fmt -> Bag.iter (Wpo.pp_goal_flow fmt) goals) + +(* ------------------------------------------------------------------------ *) +(* --- Proving --- *) +(* ------------------------------------------------------------------------ *) + +let do_wpo_feedback g prover result = + Wp_parameters.feedback "[%a] Goal %s : %a" + Wpo.pp_prover prover g.Wpo.po_gid Wpo.pp_result result + +let do_wp_proof server interactive prover g = + let already_valid (_,r) = r=Wpo.Valid in + if not (List.exists already_valid (Wpo.get_results g)) + then begin + Task.spawn server + (Prover.prove ~callout:do_wpo_feedback g ~interactive prover) + end +let do_wp_proofs () = + let pname = Wp_parameters.Prover.get () in + match Wpo.prover_of_name pname with + | None -> () + | Some prover -> + let interactive = Wpo.is_interactive pname in + let server = Prover.server () in + try + Wpo.iter ~on_goal:(do_wp_proof server interactive prover) () ; + Task.launch server ; + with e -> + Task.cancel_all server ; + raise e + +let do_wp_proofs_for goals = + let pname = Wp_parameters.Prover.get () in + match Wpo.prover_of_name pname with + | None -> () + | Some prover -> + let interactive = Wpo.is_interactive pname in + let server = Prover.server () in + try + Bag.iter (do_wp_proof server interactive prover) goals ; + Task.launch server ; + with e -> + Task.cancel_all server ; + raise e + +(* ------------------------------------------------------------------------ *) +(* --- Type Checking prover's inputs --- *) +(* ------------------------------------------------------------------------ *) + +let do_check_feedback g lang result = + Wp_parameters.feedback "[%a] Goal %s : %a" + Wpo.pp_language lang g.Wpo.po_gid Wpo.pp_result result + +let do_wp_check server lang g = + Task.spawn server (Prover.check ~callout:do_check_feedback g lang) + +let do_wp_checks () = + match Wpo.language_of_name (Wp_parameters.Check.get ()) with + | None -> () + | Some lang -> + let server = Prover.server () in + try + Wpo.iter ~on_goal:(do_wp_check server lang) () ; + Task.launch server ; + with e -> + Task.cancel_all server ; + raise e + +let do_wp_checks_for goals = + match Wpo.language_of_name (Wp_parameters.Check.get ()) with + | None -> () + | Some lang -> + let server = Prover.server () in + try + Bag.iter (do_wp_check server lang) goals ; + Task.launch server ; + with e -> + Task.cancel_all server ; + raise e + +(* ------------------------------------------------------------------------ *) +(* --- Filtering WP passes --- *) +(* ------------------------------------------------------------------------ *) + +let do_wp_passes fun_iter behaviors property call_stmt_opt = + let model = Wp_parameters.get_model () in + let goals = ref Bag.empty in + let wp_pass computer assigns = + do_compute goals computer fun_iter assigns behaviors property call_stmt_opt + in + begin + match computer model with + | NonAssigns c -> + Wp_parameters.warning + ~current:false ~once:true + "Ignored Assigns-Goals with '%s' model" + (Wp_parameters.Model.get ()) ; + wp_pass c WpAnnot.NoAssigns + | OneforBoth c -> + wp_pass c WpAnnot.WithAssigns + | OneforEach(c1,c2) -> + match property with + | None + | Some + (NamedProp _ | IdProp(Property.IPOther _ + | Property.IPBehavior _ + | (* [JS 2011/08/05] I put this case here + but not sure of that *) + Property.IPUnreachable _)) + -> + begin + wp_pass c1 WpAnnot.NoAssigns ; + wp_pass c2 WpAnnot.OnlyAssigns ; + end + | Some(IdProp(Property.IPPredicate _ + | Property.IPAxiom _ | Property.IPLemma _ + | Property.IPAxiomatic _ + | Property.IPCodeAnnot _ | Property.IPComplete _ + | Property.IPDisjoint _ | Property.IPDecrease _ )) -> + wp_pass c1 WpAnnot.NoAssigns + | Some (IdProp(Property.IPAssigns _ | Property.IPFrom _)) -> + wp_pass c2 WpAnnot.OnlyAssigns + end; + !goals + +let generic_compute kf_opt behaviors p call_stmt = + let fun_iter = + match kf_opt with + | Some kf -> on_function kf + | None -> on_all_functions + in + let goals = do_wp_passes fun_iter behaviors p call_stmt in + if not (Bag.is_empty goals) then do_wp_proofs_for goals + +(* ------------------------------------------------------------------------ *) +(* --- Secondary Entry Points --- *) +(* ------------------------------------------------------------------------ *) + +(* Registered entry point in Dynamic. *) + +let wp_compute kf_opt behaviors property = + let p = match property with None -> None | Some p -> Some (IdProp p) in + generic_compute kf_opt behaviors p None + +let wp_compute_call ~kf_caller ~kf_called stmt = + ignore kf_called ; + generic_compute (Some kf_caller) [] None (Some stmt) + +(* ------------------------------------------------------------------------ *) +(* --- Command-line Entry Points --- *) +(* ------------------------------------------------------------------------ *) + +let cmdline_run () = + let wp_main kf_list = + Ast.compute (); + Variables_analysis.precondition_compute (); + let fun_iter = match kf_list with + | [] -> on_all_functions + | names -> on_function_names names + in + let bhvs = Wp_parameters.Behaviors.get () in + let property = + match Wp_parameters.Properties.get () with + | [] -> None + | [ p ] -> Some (NamedProp p) + | ps -> + Wp_parameters.not_yet_implemented + "several properties (%a) in -wp-prop" + (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) ps + in + do_wp_passes fun_iter bhvs property None + in + match Wp_parameters.job () with + | Wp_parameters.WP_None -> () + | Wp_parameters.WP_All -> + ignore (wp_main []); + do_wp_checks (); + do_wp_proofs (); + do_wp_print () + | Wp_parameters.WP_Select fcts -> + let goals = wp_main fcts in + do_wp_checks_for goals ; + do_wp_proofs_for goals ; + do_wp_print_for goals + +(* ------------------------------------------------------------------------ *) +(* --- Register external functions --- *) +(* ------------------------------------------------------------------------ *) + +let property_of_id = + Dynamic.register ~plugin:"Wp" "WpAnnot.property_of_id" ~journalize:false + (Datatype.func WpPropId.Prop_id_datatype.ty Property.ty) + WpPropId.property_of_id + +let wp_compute = + let module OLS = Datatype.List(Datatype.String) in + let module OKF = Datatype.Option(Kernel_function) in + let module OP = Datatype.Option(Property) in + Dynamic.register ~plugin:"Wp" "wp_compute" + (Datatype.func3 OKF.ty OLS.ty OP.ty Datatype.unit) + ~journalize:false (*LC: Because of Property is not journalizable. *) + wp_compute + +(** Use options to know what to do *) +let run = Dynamic.register ~plugin:"Wp" "run" + (Datatype.func Datatype.unit Datatype.unit) + ~journalize:true + cmdline_run + +(* ------------------------------------------------------------------------ *) +(* --- Main Entry Point --- *) +(* ------------------------------------------------------------------------ *) + +let do_finally job1 job2 () = + let r1 = try job1 () ; None with error -> Some error in + let r2 = try job2 () ; None with error -> Some error in + match r1 , r2 with + | None , None -> () + | Some e1 , None -> raise e1 + | _ , Some e2 -> raise e2 + +let tracelog () = + let ks = Wp_parameters.get_debug_keyset () in + if ks <> [] then + let pp_keys : Format.formatter -> string list -> unit = + Pretty_utils.pp_flowlist ~left:"" ~sep:"," ~right:"." Format.pp_print_string + in Wp_parameters.debug ~level:0 "Logging keys : %a" pp_keys ks + +let (&&&) = do_finally + +let main = cmdline_run &&& tracelog &&& Wp_parameters.reset + +let () = Db.Main.extend main + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/runtime_mem.ml frama-c-20111001+nitrogen+dfsg/src/wp/runtime_mem.ml --- frama-c-20110201+carbon+dfsg/src/wp/runtime_mem.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/runtime_mem.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,935 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Memory Model for Runtime: +* more information about it in {{:../../wp/Notes/m3.html}this document} +* *) +(* -------------------------------------------------------------------------- *) + +let dkey = "runtime" (* debugging key *) + +open Cil_types +open Cil_datatype + +let unsupported = Wp_error.unsupported + +type compute_int_mode = CIMterms | CIMvalues | CIMcompute + +module Create + (F:Formula.S) + (A:Mint.S with module F = F) + (R:Mfloat.S with module F = F) + = +struct + + type decl = F.decl + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** The memory is composed of 2 parts: one that deals with the values, + * and the other one that handle allocation information. More over, there + * is a table in the [Pre] memory to handle logic variables that are used for + * the initial value of the parameters. + * *) + + type m_mbits + let t_mbits : Formula.tau = Formula.ADT ("memory", []) + type mem_bits = m_mbits F.term + + type m_alloc + let t_alloc : Formula.tau = Formula.ADT ("memalloc", []) + type mem_alloc = m_alloc F.term + + type m_mem + let t_mem : Formula.tau = Formula.ADT ("memory", []) + type mem = { vbits : F.var ; valloc : F.var ;} + + + + type m_format + type format = m_format F.term + (** ----- Formats : *) + + let mk_iformat i = Pretty_utils.sfprintf "%a_format" Ctypes.pp_int i + let mk_fformat f = Pretty_utils.sfprintf "%a_format" Ctypes.pp_float f + let int_format = F.e_app0 "int_format" + let real_format = F.e_app0 "real_format" + let i_format i = F.e_app0 (mk_iformat i) + let f_format f = F.e_app0 (mk_fformat f) + let format_of_addr _ty = + (* format_of_c_int_type (Ctypes.c_ptr()) *) + F.e_app0 "rt_addr_format" + + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + let tcomp_of_comp comp = (* TODO: we shouldn't loose the TComp ! *) + TComp (comp, {scache = Not_Computed}, []) + + let cil_field_info f = + let t = tcomp_of_comp (f.fcomp) in + try + let offset = Field (f, NoOffset) in + Cil.bitsOffset t offset + with Cil.SizeOfError (msg,t) -> + unsupported "sizeof %a : %s for field '%s'" + !Ast_printer.d_type t msg f.fname + let cil_field_offset f = fst (cil_field_info f) + let cil_field_size f = snd (cil_field_info f) + + let name_of_var vi : F.name = F.Xindex.get_ind vi + let name_of_field f = F.Findex.get_ind f + + + + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** Size and offset are sometimes known constants. We can choose to + * represent them are simple [int] and compute values as far as possible, + * or to keep them as named terms. + * The first solution gives smaller - yet easier provable - goals, + * but if if fails, the user has few information the understand the problem. + * We will try to have both solutions in order to be able to test them. + *) + + let compute_int_mode = CIMterms (* TODO: add an option ? *) + + (** integer terms with a phantom type to mark what kind of object it is. *) + type 'a tint = F.integer + + module Aint : sig + type 'a t + + val of_int : int -> 'a t + val of_int64 : Int64.t -> 'a t + val of_term : 'a tint -> 'a t + + val add : 'a t -> 'b t -> 'a t + val sub : 'a t -> 'b t -> 'a t + val cnst_mult : Int64.t -> 'a t -> 'a t + val mult : 'b t -> 'a t -> 'a t + + val to_term : 'a t -> 'a tint + + val eq_pred : 'a t -> 'a t -> F.pred + + end = struct + + let compute = (compute_int_mode = CIMcompute) + + type aint = + | AIcnst of Int64.t + | AIterm of F.integer + | AImult of Int64.t * F.integer + | AIadd of aint * Int64.t + + type 'a t = aint + + let term_of_cnst i = F.e_icst (Int64.to_string i) + + let of_int64 i = if compute then AIcnst i else AIterm (term_of_cnst i) + let of_int (i:int) = of_int64 (Int64.of_int i) + let of_term t = AIterm t + + let term_of_add t1 t2 = F.e_iop Formula.Iadd t1 t2 + let term_of_sub t1 t2 = F.e_iop Formula.Isub t1 t2 + let term_of_mult t1 t2 = F.e_iop Formula.Imul t1 t2 + + let rec to_term (ai: 'a t) : 'a tint = match ai with + | AIcnst i -> term_of_cnst i + | AImult (i, t) -> term_of_mult (term_of_cnst i) t + | AIadd (t, i) -> term_of_add (to_term t) (term_of_cnst i) + | AIterm t -> t + + let cnst_is_zero i = 0 = Int64.compare i (Int64.zero) + + let is_zero ai = match ai with + | AIcnst i -> cnst_is_zero i + | _ -> false + + let add_cnst ai i = match ai with + | AIcnst i' when compute -> AIcnst (Int64.add i i') + | AIadd (t, i') when compute -> + AIadd (t, Int64.add i i') + | _ when cnst_is_zero i && compute -> ai + | _ -> AIadd (ai, i) + + let rec cnst_mult i ai = + if compute then match ai with + | AIcnst i' -> AIcnst (Int64.mul i i') + | AImult (i', t) -> AImult (Int64.mul i i', t) + | _ when cnst_is_zero i -> AIcnst Int64.zero + | AIadd (t, i') -> + add_cnst (cnst_mult i t) (Int64.mul i i') + | AIterm t -> AImult (i, t) + else of_term (term_of_mult (term_of_cnst i) (to_term ai)) + + let mult ai1 ai2 = match ai1, ai2 with + | AIcnst i1, _ -> cnst_mult i1 ai2 + | _, AIcnst i2 -> cnst_mult i2 ai1 + | AImult (i1, t1), AImult (i2, t2) when compute -> + cnst_mult (Int64.mul i1 i2) (AIterm (term_of_mult t1 t2)) + | _, _ -> (* TODO: develop other cases ? *) + let t1 = to_term ai1 in + let t2 = to_term ai2 in + AIterm (term_of_mult t1 t2) + + let rec add ai1 ai2 = match ai1, ai2 with + | AIcnst i1, _ -> add_cnst ai2 i1 + | _, AIcnst i2 -> add_cnst ai1 i2 + | AIadd (t1, i1), AIadd (t2, i2) when compute -> + add_cnst (add t1 t2) (Int64.add i1 i2) + | _, _ -> (* TODO: develop other cases ? *) + let t1 = to_term ai1 in + let t2 = to_term ai2 in + AIterm (term_of_add t1 t2) + + let sub ai1 ai2 = match ai1, ai2 with (* TODO: compute... *) + | _, _ -> + let t1 = to_term ai1 in + let t2 = to_term ai2 in + AIterm (term_of_sub t1 t2) + + let eq_cnst i1 i2 = 0 = Int64.compare i1 i2 + + let eq_pred ai1 ai2 = match ai1, ai2 with + | AIcnst i1, AIcnst i2 when compute -> + if eq_cnst i1 i2 then F.p_true else F.p_false + | _, _ -> (* TODO: develop other cases ? *) + F.p_eq (to_term ai1) (to_term ai2) + end + + (** Phantom types to tag the terms *) + type m_addr + type m_offset + type m_size + type m_zone + + (** Specialized type of F.integer terms *) + type t_addr = m_addr tint + type t_offset = m_offset tint + type t_size = m_size tint + type t_zone = m_zone F.term + + module Tint : sig + + type x_addr + val xaddr_of_var : mem_alloc -> varinfo -> x_addr + val xaddr_of_integer : F.integer -> x_addr + val integer_of_xaddr : x_addr -> F.integer + val varinfo_of_xaddr : x_addr -> varinfo option + val pp_addr : Format.formatter -> x_addr -> unit + val base : mem_alloc -> x_addr -> x_addr + val term_of_xaddr : x_addr -> t_addr + + type x_size + val size_of_int : int -> x_size + val size_of_int64 : Int64.t -> x_size + val cnst_mult_size : Int64.t -> x_size -> x_size + val xsize_of_range : F.integer -> F.integer -> x_size -> x_size + val term_of_xsize : x_size -> t_size + + val shift_n_elem : x_addr -> F.integer -> x_size -> x_addr + val shift_field : x_addr -> fieldinfo -> x_addr + + val toffset_of_field : ?mode:compute_int_mode -> fieldinfo -> t_offset + val tsize_of_field : ?mode:compute_int_mode -> fieldinfo -> t_size + + type x_zone + val mk_xzone : x_addr -> x_size -> x_zone + val xzone_of_var : mem_alloc -> varinfo -> x_size -> x_zone + val pp_xzone : Format.formatter -> x_zone -> unit + val term_of_xzone : x_zone -> m_zone F.term + val eq_zone : x_zone -> x_zone -> F.pred + val xzone_disj : x_zone -> x_zone -> F.pred + + end = struct + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {2 Extracted specification from runtime.why} + * see definitions and axioms in + * {{:../../../share/why/runtime.why}runtime.why} + *) + module L = struct + let vaddr : mem_alloc -> F.name -> t_addr = F.e_app2 "rt_vaddr" + + let zone : t_addr -> t_size -> t_zone = F.e_app2 "rt_zone" + let vzone : mem_alloc -> F.name-> t_zone = F.e_app2 "rt_vzone" + + let foffset : F.name -> t_offset = F.e_app1 "rt_foffset" + let fsize : F.name -> t_size = F.e_app1 "rt_fsize" + + let shift : t_addr -> t_offset -> t_addr = F.e_app2 "rt_shift" + + let disj : t_zone -> t_zone -> F.pred = F.p_app2 "rt_disj" + + let base : mem_alloc -> t_addr -> t_addr = F.e_app2 "rt_abase" + end + + type x_addr = + | Lvaddr of (mem_alloc * varinfo) + | Laddr of m_addr Aint.t + + type x_offset = m_offset Aint.t + type x_size = m_size Aint.t + type x_zone = + | Zterm of t_zone + | Zpair of x_addr * x_size + + let xaddr_of_var ma v = Lvaddr (ma, v) + + let term_of_xaddr ai : t_addr = match ai with + | Lvaddr (ma, v) -> L.vaddr ma (name_of_var v) + | Laddr ai -> Aint.to_term ai + + let aint_of_xaddr a : m_addr Aint.t = match a with + | Laddr a -> a + | _ -> Aint.of_term (term_of_xaddr a) + + let varinfo_of_xaddr a = match a with + | Lvaddr (_, vi) -> Some vi + | _ -> None + + let pp_addr fmt a = F.pp_term fmt (term_of_xaddr a) + + let xaddr_of_integer ti = Laddr (Aint.of_term ti) + let integer_of_xaddr xa = term_of_xaddr xa + + let base ma a = Laddr (Aint.of_term (L.base ma (term_of_xaddr a))) + + let offset_of_int i : x_offset = Aint.of_int i + let size_of_int sz : x_size = Aint.of_int sz + let size_of_int64 sz : x_size = Aint.of_int64 sz + let cnst_mult_size n (sz:x_size) : x_size = Aint.cnst_mult n sz + + let xsize_of_range min max sz = + let nb = Aint.sub (Aint.of_term max) (Aint.of_term min) in + let nb = Aint.add nb (Aint.of_int 1) in + Aint.mult nb sz + + let term_of_xsize ai : t_size = Aint.to_term ai + + let xoffset_of_field ?(mode=compute_int_mode) f = + if mode = CIMterms then + Aint.of_term (L.foffset (name_of_field f)) + else offset_of_int (cil_field_offset f) + + let toffset_of_field ?(mode=compute_int_mode) f = + Aint.to_term (xoffset_of_field ~mode f) + + let xsize_of_field ?(mode=compute_int_mode) f = + if mode = CIMterms then + Aint.of_term (L.fsize (name_of_field f)) + else size_of_int (cil_field_size f) + + let tsize_of_field ?(mode=compute_int_mode) f = + Aint.to_term (xsize_of_field ~mode f) + + let shift (a:x_addr) (offset:x_offset) : x_addr = + if compute_int_mode = CIMcompute then + Laddr (Aint.add (aint_of_xaddr a) offset) + else + Laddr (Aint.of_term + (L.shift (term_of_xaddr a) (Aint.to_term offset))) + + let shift_n_elem a n sz = + let o : x_offset = Aint.of_term n in + let o = Aint.mult sz o in + shift a o + + let shift_field a f = shift a (xoffset_of_field f) + + let xzone_of_var ma v sz = + if compute_int_mode = CIMterms then + Zterm (L.vzone ma (name_of_var v)) + else + Zpair (xaddr_of_var ma v, sz) + + let mk_xzone a sz : x_zone = match a with + | Lvaddr (ma, v) -> xzone_of_var ma v sz + | _ -> Zpair (a, sz) + + let term_of_xzone xz = match xz with + | Zterm t -> t + | Zpair (a, sz) -> L.zone (term_of_xaddr a) (term_of_xsize sz) + + let pp_xzone fmt xz = F.pp_term fmt (term_of_xzone xz) + + let eq_zone z1 z2 = (* TODO: SMP *) + F.p_eq (term_of_xzone z1) (term_of_xzone z2) + + let xzone_disj z1 z2 = (* TODO: SMP *) + L.disj (term_of_xzone z1) (term_of_xzone z2) + end + + (* open Tint *) + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {3 about size and offset} *) + + let rec sizeof_c_object t : Tint.x_size = match t with + | Ctypes.C_comp comp -> + begin + try + let t = tcomp_of_comp comp in + let sz = Cil.bitsSizeOf t in + Tint.size_of_int sz + with Cil.SizeOfError (msg, t) -> + unsupported "sizeof %a : %s" !Ast_printer.d_type t msg + end + | Ctypes.C_array {Ctypes.arr_flat = Some flat} -> + let nb = flat.Ctypes.arr_cell_nbr in + let sz = sizeof_c_object (Ctypes.object_of flat.Ctypes.arr_cell) in + Tint.cnst_mult_size nb sz + | _ -> Tint.size_of_int64 (Ctypes.sizeof_object t) + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {2 Extracted specification from runtime.why} + * see definitions and axioms in + * {{:../../../share/why/runtime.why}runtime.why} + *) + + type m_bits + type t_bits = m_bits F.term + + type m_dzone + type dzone = m_dzone F.term + + module RtLib = struct + let rt_global : F.name -> F.pred = F.p_app1 "rt_global" + + let rt_vsize : F.name -> t_size = F.e_app1 "rt_vsize" + + (* let rt_vformat : F.name -> F.format = F.e_app1 "rt_vformat" + let rt_fformat : F.name -> F.format = F.e_app1 "rt_fformat" *) + + let load : mem_bits -> t_zone -> t_bits = F.e_app2 "rt_load" + let store : mem_bits -> t_addr -> t_bits -> mem_bits = F.e_app3 "rt_store" + let havoc : mem_bits -> t_zone -> mem_bits = F.e_app2 "rt_havoc" + + let to_bits : format -> F.abstract -> t_bits = F.e_app2 "rt_to_bits" + let from_bits : t_bits -> format -> F.abstract = F.e_app2 "rt_from_bits" + + let alloc : mem_alloc -> F.name -> mem_alloc = F.e_app2 "rt_valloc" + + let block_length : mem_alloc -> t_addr -> t_size + = F.e_app2 "rt_block_length" + let valid : mem_alloc -> t_zone -> F.pred = F.p_app2 "rt_valid" + + let is_havoc : mem_alloc -> mem_bits -> dzone -> mem_bits -> F.pred = + F.p_app4 "rt_is_havoc" + + let free : mem_alloc -> F.name -> mem_alloc = F.e_app2 "rt_vfree" + + let zs_empty : dzone = F.e_app0 "zs_empty" + let zs_singleton : t_zone -> dzone = F.e_app1 "zs_singleton" + let zs_union : dzone -> dzone -> dzone = F.e_app2 "zs_union" + let zs_incl : dzone -> dzone -> F.pred = F.p_app2 "zs_incl" + end + + let z_from_bits b fmt : F.integer = F.unwrap (RtLib.from_bits b fmt) + let real_from_bits b fmt : F.real = F.unwrap (RtLib.from_bits b fmt) + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + + module Model = + struct + + module F = F + module A = A + module R = R + + type loc = Tint.x_addr + + let pp_loc fmt l = Tint.pp_addr fmt l + + let cast_loc_to_int _tp loc ti : F.integer = + let int_term = Tint.term_of_xaddr loc in + F.i_convert (Ctypes.c_ptr()) ti int_term + + + let cast_int_to_loc ti (i:F.integer) _tp : loc = + let i = F.i_convert ti (Ctypes.c_ptr()) i in + (Tint.xaddr_of_integer i) + + + let null = Tint.xaddr_of_integer F.i_zero + + let is_null l = + F.e_icmp Formula.Ceq (Tint.integer_of_xaddr l) F.i_zero + + let minus_loc l1 l2 = + F.e_app2 "rt_addr_minus" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + let le_loc_bool l1 l2 = + F.e_app2 "rt_addr_le_bool" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + let lt_loc_bool l1 l2 = + F.e_app2 "rt_addr_lt_bool" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + let equal_loc_bool l1 l2 = + F.e_app2 "rt_addr_eq_bool" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + let le_loc l1 l2 = F.p_app2 "rt_addr_le" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + let lt_loc l1 l2 = F.p_app2 "rt_addr_lt" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + let equal_loc l1 l2 = F.p_app2 "rt_addr_eq" (Tint.term_of_xaddr l1) + (Tint.term_of_xaddr l2) + + + let term_of_loc a = F.wrap (Tint.term_of_xaddr a) + let loc_of_term _ t = Tint.xaddr_of_integer (F.unwrap t) + + let tau_of_loc = Formula.Integer + + end + + let startof loc _ = loc + + let cast_loc_to_loc _t1 _t2 p = p + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {3 about zone} *) + (** + * Mwp requires a type [dzone] defined as [m_zone F.term] + * that represent why formula of the model why zone type + * (which name is given by [tau_of_zone] below). + * + * Because we need to provide function such as [dzone_union], + * this [dzone] is defined as a set of the [rt_zone] defined in WHY. + *) + + let tau_of_dzone = Formula.ADT("zones",[]) + + + let xzone_assigned = function + | F.Aloc( te , loc ) -> + Tint.mk_xzone loc (sizeof_c_object te) + | F.Arange( te , loc , rg ) -> + match rg with + | {F.inf = Some min; F.sup = Some max} -> + let sz = sizeof_c_object te in + let addr = Tint.shift_n_elem loc min sz in + let size = Tint.xsize_of_range min max sz in + Tint.mk_xzone addr size + | _ -> unsupported "unbounded range" + + let dzone_assigned _m a = RtLib.zs_singleton (Tint.term_of_xzone (xzone_assigned a)) + let dzone_empty () = RtLib.zs_empty + + let dzone_subset dz1 dz2 = RtLib.zs_incl dz1 dz2 + + let dzone_union dz1 dz2 = RtLib.zs_union dz1 dz2 + + let effect_supported = true + + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + + let int_format_for_hyp t = match t with + | Ctypes.C_int cint -> Some (i_format cint) + | Ctypes.C_pointer ty -> Some (format_of_addr ty) + | _ -> None + + let add_int_format_hyp vformat t h = match int_format_for_hyp t with + | None -> h + | Some fmt -> + let h_format = F.p_eq vformat fmt in + F.p_and h_format h + + module VarDecl = F.DRegister + (struct + include F.Varinfo + + (** Global variable has a fixed zone in any allocation memory. + * [forall ma, rt_vsize (ma, v) = sz /\ rt_vaddr (ma, v) = rt_gaddr v] *) + let declare v _ = + let t = Ctypes.object_of v.vtype in + let h = + if v.vglob then RtLib.rt_global (name_of_var v) + else F.p_true + in + let sz = sizeof_c_object t in + let size = RtLib.rt_vsize (name_of_var v) in + let h_size = F.p_eq size (Tint.term_of_xsize sz) in + let h = F.p_and h h_size in + (* let vformat = RtLib.rt_vformat (name_of_var v) in + let h = add_int_format_hyp vformat t h in *) + (* TODO: size info might be redondant with format... *) + (* TODO: format for other types... *) + Formula.Axiom h + + let section = Formula.S_Model_Prop + let prefix = "Decl" + let basename x = x.vname + let clear () = () + let pp_descr fmt _x = + Format.fprintf fmt "Global declaration" + end) + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + module Fields = F.DRegister + (struct + include F.Fieldinfo + + let declare f _ = + let foff = Tint.toffset_of_field ~mode:CIMterms f in + let off = Tint.toffset_of_field ~mode:CIMvalues f in + let hoff = F.p_eq foff off in + + let fsz = Tint.tsize_of_field ~mode:CIMterms f in + let sz = Tint.tsize_of_field ~mode:CIMvalues f in + let hsz = F.p_eq fsz sz in + let h = F.p_and hoff hsz in + + (* + let t = Ctypes.object_of f.ftype in + let fformat = RtLib.rt_fformat (name_of_field f) in + let h = add_int_format_hyp fformat t h in + *) + + Formula.Axiom h + + let section = Formula.S_Model_Prop + let prefix = "Finfo" + let basename x = + let name = F.Compinfo.basename x.fcomp in + (name^"_"^x.fname) + let clear () = () + let pp_descr fmt _x = + Format.fprintf fmt "Field info" + end) + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + module V = Datalib.Cvalues(Model) + module L = Datalib.Create(V) + + module Data = struct + include V + + type m_of_mem = m_mbits + + let tau_of_mem = t_mbits + + let forall_loc pool = + let p = F.p_fresh pool "p" (Formula.Model Formula.Integer) in + [p] , (Tint.xaddr_of_integer (F.var p)) + + + let global vi = VarDecl.define vi + + let cvar m vi = + VarDecl.define vi ; + Tint.xaddr_of_var (F.var m.valloc) vi + + let inner_loc _ = Wp_parameters.fatal "[inner_loc] reserved to funvar" + + let lvar _m lv x = + let ty = + match lv.lv_type with | Ctype ty -> ty | _ -> assert false + in + loc_of_term (Ctypes.object_of ty)(F.var x) + + let shift (l:loc) t i : loc = Tint.shift_n_elem l i (sizeof_c_object t) + + let index = shift + + (** Even if union field has 0 offset, we have to use on operation because + * the size of the location to be consider might change from one field to + * another. *) + let field (l:loc) f = + Fields.define f; + Tint.shift_field l f + + let value_of_bits = ref (fun _ _ -> assert false) + let bits_of_value = ref (fun _ _ -> assert false) + + (** Read a data of type [te] at [loc] and returns it as a logic value. *) + let load_mem mb te loc = + let xzone = Tint.mk_xzone loc (sizeof_c_object te) in + let tzone = Tint.term_of_xzone xzone in + let bits = RtLib.load mb tzone in + (!value_of_bits te bits) + + let store_mem mb te loc v = + let tzone = Tint.term_of_xaddr loc in + RtLib.store mb tzone (!bits_of_value te v) + + end + + module DF = Data_mem.Create(Data) + + + + + + let load m te loc = + DF.loaded te; + Data.load_mem (F.var m.vbits) te loc + (* + match Tint.varinfo_of_xaddr loc (*, logic_of_mem m *) with + | Some vi, Some tbl when vi.vformal -> + (* Pre state : vformal value is a logic variable + * which reprent the initial value of the parameter. *) + let v = + try Varinfo.Hashtbl.find tbl vi + with Not_found -> + let ct = Ctype vi.vtype in + let t = Data.tau_of_object (Ctypes.object_of vi.vtype) in + let v = L.fresh vi.vname (Formula.Acsl (t,ct)) in + (Varinfo.Hashtbl.add tbl vi v; v) + in (Data.value_of_logic te (F.var v)) + | _, _ -> + + *) + + let store m loc t exp_val = + DF.stored t; + Data.store_mem (F.var m.vbits) t loc exp_val + + include Data + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {3 about bits} + * [bits] type is used to represent the values that are stored in the memory. + * We have functions that encode/decode bits to/from ACSL logic values + * depending on the intermediate C type [t]. + * *) + + let format_of_compinfo comp = DF.record_format comp + (* if comp.cstruct then DF.record_format comp + else unsupported "format of union" *) + + let format_of_array arr = DF.array_format arr + + let rt_format_of_ctype t = match t with + | Ctypes.C_int c_int -> i_format c_int + | Ctypes.C_float c_float -> f_format c_float + | Ctypes.C_comp comp -> format_of_compinfo comp + | Ctypes.C_array arr -> format_of_array arr + | Ctypes.C_pointer ty -> format_of_addr ty + + (** Compute the logic value from bits interpreted with type [t]. *) + let rec value_of_bits t bits : Data.value = match t with + | Ctypes.C_int c_int -> + let c_val = z_from_bits bits (i_format c_int) in + V_int (c_int, c_val) + | Ctypes.C_float c_float -> + let ft = f_format c_float in + let c_val = real_from_bits bits ft in + V_float (c_float, c_val) + | Ctypes.C_comp comp -> + let ft = format_of_compinfo comp in + let c_val = RtLib.from_bits bits ft in + V_record (comp, F.unwrap c_val) + | Ctypes.C_array arr -> + let ft = format_of_array arr in + let c_val = RtLib.from_bits bits ft in + let logic_val = (* D.encode ft*) (F.unwrap c_val) in + V_array (arr, F.unwrap logic_val) + | Ctypes.C_pointer ty -> + let cv = Ctypes.object_of ty in + let c_val = z_from_bits bits (format_of_addr cv) in + let addr = Tint.xaddr_of_integer c_val in + V_pointer (cv, addr) + + (* TODO: is it normal that we don't use t? + * Maybe we should check that it is the same than in the value ??? *) + let rec bits_of_value _t value : t_bits = match value with + | V_int (c_int, i) -> + let ft = i_format c_int in + RtLib.to_bits ft (F.wrap i) + | V_float (c_float, f) -> + let ft = f_format c_float in + RtLib.to_bits ft (F.wrap f) + | V_pointer (ty, loc) -> + let ft = format_of_addr ty in + RtLib.to_bits ft (F.wrap (Tint.integer_of_xaddr loc)) + | V_union _ -> unsupported "bits_of_value of union" + | V_record (comp, r) -> + let ft = format_of_compinfo comp in + let e = (*D.decode ft*) (F.wrap r) in + RtLib.to_bits ft e + | V_array (arr, t) -> + let ft = format_of_array arr in + let e = (* D.decode ft*) (F.wrap t) in + RtLib.to_bits ft e + + (** Horrible thing but no (known) way to avoid... *) + let () = + begin + Data.value_of_bits := value_of_bits ; + Data.bits_of_value := bits_of_value ; + end + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + + (** {3 Frame Environment} *) + + let mem ()= + let va = L.fresh "ma" (Formula.Model t_alloc) in + let vb = L.fresh "mb" (Formula.Model t_mbits) in + { vbits = vb ; valloc = va ;} + + (** {3 Validity }*) + + let valid m a = + let xzone = xzone_assigned a in + RtLib.valid (F.var m.valloc) (Tint.term_of_xzone xzone) + + let separated _m z1 z2 = + Tint.xzone_disj (xzone_assigned z1) (xzone_assigned z2) + + let tbits_of_var a : t_bits = F.var a + + let subst_havoc m a = + let xzone = xzone_assigned a in + (* let v = L.fresh "v" (Mdata.Vmodel(Formula.ADT("bits",[]))) in + let bits = tbits_of_var v in *) + let new_vmh sigma = + let mb = L.apply sigma (F.var m.vbits) in + F.wrap (RtLib.havoc mb (Tint.term_of_xzone xzone)) + in + [F.Update( m.vbits, new_vmh)] + + let assigns_goal m1 region m2 = + let zones = + match region with + | [] -> dzone_empty () + | [a] -> dzone_assigned m1 a + | a::others -> + List.fold_left + (fun dz a -> + dzone_union dz (dzone_assigned m1 a) + ) (dzone_assigned m1 a) others + in + RtLib.is_havoc (F.var m1.valloc) (F.var m1.vbits) zones (F.var m2.vbits) + + let assigns_supported = true + + (** {3 Special locations} *) + + let base_address m loc = Tint.base (F.var m.valloc) loc + + let block_length m p = + RtLib.block_length (F.var m.valloc) (Tint.term_of_xaddr p) + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {3 User-defined Predicates} *) + + type closure = + | Mem + | Alloc + + let pp_closure fmt = function + | Mem ->Format.fprintf fmt "memory store" + | Alloc ->Format.fprintf fmt "allocation table" + + let userdef_mem_signature m = [m.vbits,Mem ; m.valloc,Alloc] + + let userdef_mem_apply m cl = match cl with + | Mem -> F.wrap (F.var m.vbits) + | Alloc -> F.wrap (F.var m.valloc) + + (* ------------------------------------------------------------------------ *) + (* --- Functional Closure --- *) + (* ------------------------------------------------------------------------ *) + + type formal = unit + let pp_formal _ _ = () + let userdef_is_ref_param (_:logic_var): bool = false + let userdef_ref_signature (_:mem) : ( F.var * logic_var * formal ) list = [] + let userdef_ref_apply (_:mem) (_:formal) (_:loc) : value = assert false + let userdef_ref_has_cvar (_ : logic_var) : bool = false + + + (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + (** {2 Mwp.S requirements} *) + + let update ~(at:mem) ~(here:mem) p = + let p = L.subst at.vbits (F.var here.vbits) p in + let p = L.subst at.valloc (F.var here.valloc) p in + p + + let quantify m p = + L.forall [m.vbits;m.valloc] p + + let subst_lval m t ptr exp p = + let s = F.wrap (store m ptr t exp) in + L.subst m.vbits s p + + (* ------------------------------------------------------------------------ *) + (* --- Local Scope --- *) + (* ------------------------------------------------------------------------ *) + + let local_scope m vars scope_kind p = + let vmh = m.vbits in + let mh = F.var vmh in + let do_var p v = + let alloc v p = + Wp_parameters.debug ~dkey "[local_scope] alloc %s@." v.vname; + let ma = RtLib.alloc mh (name_of_var v) in + let p = L.subst vmh ma p in + p + in +(* + let init v p = (* initialize parameter : v@Here = v@Pre *) + let m_pre = mem_at env Clabels.Pre in + let v_loc = cvar m_here v in + let v_pre = load m_pre t v_loc in + let p = subst_lval env t v_loc v_pre p in + p + in +*) + let p = match scope_kind with + | Mcfg.SC_Function_in -> + let p = alloc v p in p + (* + let p = match logic_of_mem (mem_at env Clabels.Pre) with + | None -> p + | Some tbl -> + try let lv = Varinfo.Hashtbl.find tbl v in + L.forall [lv] p + with Not_found -> p + in p *) + | Mcfg.SC_Function_frame -> + (* let p = init v p in *) + let p = alloc v p in + p + | Mcfg.SC_Block_in -> + let p = alloc v p in + (*let h = add_int_format_hyp (name_of_var v) t F.p_true in + F.p_implies h p + *) p + | Mcfg.SC_Block_out | Mcfg.SC_Function_out -> + Wp_parameters.debug ~dkey "[local_scope] free %s@." v.vname; + L.subst vmh (RtLib.free mh (name_of_var v)) p + | Mcfg.SC_Global -> (* nothing to do *) p + in p + in List.fold_left do_var p vars + + let global_scope _ p = p + +end + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/runtime_mem.mli frama-c-20111001+nitrogen+dfsg/src/wp/runtime_mem.mli --- frama-c-20110201+carbon+dfsg/src/wp/runtime_mem.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/runtime_mem.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,30 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Create + (F:Formula.S) + (A:Mint.S with module F = F) + (R:Mfloat.S with module F = F) + : + Mwp.S with module F = F + and module A = A + and module R = R diff -Nru frama-c-20110201+carbon+dfsg/src/wp/script.ml frama-c-20111001+nitrogen+dfsg/src/wp/script.ml --- frama-c-20110201+carbon+dfsg/src/wp/script.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/script.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,475 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +# 23 "src/wp/script.mll" + + + type token = + | Id of string + | Key of string + | Proof of string + | Word + | Eof + + let keywords = [ "Goal" ; "Hint" ] + + let fill buffer lexbuf = + Buffer.add_string buffer (Lexing.lexeme lexbuf) + + open Lexing + + let newline lexbuf = + lexbuf.lex_curr_p <- + { lexbuf.lex_curr_p with pos_lnum = succ lexbuf.lex_curr_p.pos_lnum } + + +# 24 "src/wp/script.ml" +let __ocaml_lex_tables = { + Lexing.lex_base = + "\000\000\246\255\248\255\000\000\250\255\075\000\160\000\254\255\ + \002\000\235\000\054\001\129\001\206\001\007\000\253\255\249\255\ + \105\001\251\255\252\255\253\255\001\000\000\000\255\255\254\255\ + \106\001\250\255\251\255\252\255\004\000\005\000\036\000\033\000\ + \035\000\014\000\255\255\018\000\036\000\015\000\254\255\253\255\ + "; + Lexing.lex_backtrk = + "\255\255\255\255\255\255\009\000\255\255\004\000\004\000\255\255\ + \000\000\004\000\004\000\004\000\004\000\003\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\004\000\004\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\005\000\005\000\005\000\005\000\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + "; + Lexing.lex_default = + "\001\000\000\000\000\000\255\255\000\000\255\255\255\255\000\000\ + \255\255\255\255\255\255\255\255\255\255\255\255\000\000\000\000\ + \017\000\000\000\000\000\000\000\255\255\255\255\000\000\000\000\ + \025\000\000\000\000\000\000\000\255\255\255\255\255\255\255\255\ + \255\255\255\255\000\000\255\255\255\255\255\255\000\000\000\000\ + "; + Lexing.lex_trans = + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\008\000\007\000\008\000\000\000\008\000\000\000\008\000\ + \013\000\014\000\000\000\000\000\013\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \008\000\000\000\008\000\000\000\000\000\000\000\000\000\013\000\ + \003\000\022\000\015\000\023\000\004\000\039\000\004\000\038\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\004\000\004\000\034\000\034\000\000\000\000\000\ + \000\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \006\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\000\000\000\000\000\000\000\000\005\000\ + \000\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\035\000\032\000\033\000\ + \036\000\037\000\000\000\000\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\000\000\000\000\ + \000\000\000\000\005\000\000\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\000\000\000\000\000\000\000\000\005\000\ + \002\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\009\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\000\000\000\000\ + \000\000\000\000\005\000\000\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\010\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \000\000\000\000\000\000\018\000\026\000\000\000\000\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\020\000\029\000\021\000\028\000\005\000\000\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\011\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\031\000\000\000\030\000\000\000\000\000\ + \000\000\000\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\000\000\000\000\000\000\000\000\ + \005\000\000\000\005\000\005\000\005\000\005\000\005\000\012\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\013\000\000\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\000\000\000\000\000\000\000\000\005\000\000\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\019\000\027\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000"; + Lexing.lex_check = + "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\000\000\000\000\008\000\255\255\000\000\255\255\008\000\ + \013\000\013\000\255\255\255\255\013\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \000\000\255\255\008\000\255\255\255\255\255\255\255\255\013\000\ + \000\000\021\000\003\000\020\000\000\000\028\000\000\000\029\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\033\000\037\000\255\255\255\255\ + \255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\255\255\255\255\255\255\255\255\000\000\ + \255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\030\000\031\000\032\000\ + \035\000\036\000\255\255\255\255\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\255\255\255\255\ + \255\255\255\255\005\000\255\255\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\ + \005\000\005\000\005\000\005\000\005\000\005\000\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\006\000\255\255\255\255\255\255\255\255\006\000\ + \000\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\ + \006\000\006\000\006\000\009\000\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\009\000\255\255\255\255\ + \255\255\255\255\009\000\255\255\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\009\000\009\000\009\000\ + \009\000\009\000\009\000\009\000\009\000\009\000\010\000\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \255\255\255\255\255\255\016\000\024\000\255\255\255\255\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \010\000\016\000\024\000\016\000\024\000\010\000\255\255\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \010\000\010\000\010\000\010\000\010\000\010\000\010\000\010\000\ + \010\000\011\000\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\024\000\255\255\024\000\255\255\255\255\ + \255\255\255\255\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\011\000\255\255\255\255\255\255\255\255\ + \011\000\255\255\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\011\000\011\000\011\000\011\000\011\000\ + \011\000\011\000\011\000\011\000\012\000\255\255\012\000\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \012\000\255\255\255\255\255\255\255\255\012\000\255\255\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\ + \012\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\016\000\024\000\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255"; + Lexing.lex_base_code = + ""; + Lexing.lex_backtrk_code = + ""; + Lexing.lex_default_code = + ""; + Lexing.lex_trans_code = + ""; + Lexing.lex_check_code = + ""; + Lexing.lex_code = + ""; +} + +let rec token lexbuf = + __ocaml_lex_token_rec lexbuf 0 +and __ocaml_lex_token_rec lexbuf __ocaml_lex_state = + match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with + | 0 -> +# 48 "src/wp/script.mll" + ( token lexbuf ) +# 250 "src/wp/script.ml" + + | 1 -> +# 49 "src/wp/script.mll" + ( newline lexbuf ; token lexbuf ) +# 255 "src/wp/script.ml" + + | 2 -> +# 51 "src/wp/script.mll" + ( + newline lexbuf ; + let buffer = Buffer.create 512 in + proof buffer 0 lexbuf ; + Proof (Buffer.contents buffer) + ) +# 265 "src/wp/script.ml" + + | 3 -> +# 58 "src/wp/script.mll" + ( + let buffer = Buffer.create 512 in + proof buffer 0 lexbuf ; + Proof (Buffer.contents buffer) + ) +# 274 "src/wp/script.ml" + + | 4 -> +# 64 "src/wp/script.mll" + ( + let a = Lexing.lexeme lexbuf in + if List.mem a keywords then Key a else Id a + ) +# 282 "src/wp/script.ml" + + | 5 -> +# 68 "src/wp/script.mll" + ( Key(Lexing.lexeme lexbuf) ) +# 287 "src/wp/script.ml" + + | 6 -> +# 69 "src/wp/script.mll" + ( comment 0 lexbuf ) +# 292 "src/wp/script.ml" + + | 7 -> +# 70 "src/wp/script.mll" + ( Eof ) +# 297 "src/wp/script.ml" + + | 8 -> +# 71 "src/wp/script.mll" + ( Key(Lexing.lexeme lexbuf) ) +# 302 "src/wp/script.ml" + + | 9 -> +# 72 "src/wp/script.mll" + ( Word ) +# 307 "src/wp/script.ml" + + | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state + +and comment n lexbuf = + __ocaml_lex_comment_rec n lexbuf 16 +and __ocaml_lex_comment_rec n lexbuf __ocaml_lex_state = + match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with + | 0 -> +# 75 "src/wp/script.mll" + ( if n > 0 then comment (pred n) lexbuf else token lexbuf ) +# 318 "src/wp/script.ml" + + | 1 -> +# 76 "src/wp/script.mll" + ( comment (succ n) lexbuf ) +# 323 "src/wp/script.ml" + + | 2 -> +# 77 "src/wp/script.mll" + ( failwith "Non-terminated comment" ) +# 328 "src/wp/script.ml" + + | 3 -> +# 78 "src/wp/script.mll" + ( newline lexbuf ; comment n lexbuf ) +# 333 "src/wp/script.ml" + + | 4 -> +# 79 "src/wp/script.mll" + ( comment n lexbuf ) +# 338 "src/wp/script.ml" + + | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_comment_rec n lexbuf __ocaml_lex_state + +and proof buffer n lexbuf = + __ocaml_lex_proof_rec buffer n lexbuf 24 +and __ocaml_lex_proof_rec buffer n lexbuf __ocaml_lex_state = + match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with + | 0 -> +# 83 "src/wp/script.mll" + ( + if n > 0 then proof buffer (pred n) lexbuf + ) +# 351 "src/wp/script.ml" + + | 1 -> +# 86 "src/wp/script.mll" + ( fill buffer lexbuf ; proof buffer (succ n) lexbuf ) +# 356 "src/wp/script.ml" + + | 2 -> +# 87 "src/wp/script.mll" + ( fill buffer lexbuf ; + if n>0 then proof buffer (pred n) lexbuf + else failwith "Non-terminated comment (inside proof)" ) +# 363 "src/wp/script.ml" + + | 3 -> +# 90 "src/wp/script.mll" + ( failwith "Non-terminated proof" ) +# 368 "src/wp/script.ml" + + | 4 -> +# 91 "src/wp/script.mll" + ( fill buffer lexbuf ; newline lexbuf ; proof buffer n lexbuf ) +# 373 "src/wp/script.ml" + + | 5 -> +# 92 "src/wp/script.mll" + ( fill buffer lexbuf ; proof buffer n lexbuf ) +# 378 "src/wp/script.ml" + + | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_proof_rec buffer n lexbuf __ocaml_lex_state + +;; + +# 94 "src/wp/script.mll" + + + type input = { + src : string ; + inc : in_channel ; + lexbuf : Lexing.lexbuf ; + mutable token : token ; + mutable tik : int ; + } + + let open_file f = + let inc = open_in f in + let lex = Lexing.from_channel inc in + let tok = token lex in + { src=f ; tik=0 ; inc=inc ; lexbuf=lex ; token=tok } + + let pp_token lexbuf fmt = function + | Id x -> Format.fprintf fmt "ident '%s'" x + | Key k -> Format.fprintf fmt "'%s'" k + | Proof _ -> Format.fprintf fmt "Proof...Qed" + | Eof -> Format.fprintf fmt "end-of-file" + | Word -> Format.fprintf fmt "start of '%s'" (Lexing.lexeme lexbuf) + + + let skip input = + if input.token <> Eof then + ( input.tik <- 0 ; input.token <- token input.lexbuf ) + let token input = + input.tik <- succ input.tik ; + if input.tik > 1000 then failwith "Blocked" ; + input.token + let close input = close_in input.inc + let error input text = + let buffer = Buffer.create 80 in + let fmt = Format.formatter_of_buffer buffer in + let line = (Lexing.lexeme_start_p input.lexbuf).Lexing.pos_lnum in + Format.fprintf fmt "%s:%d: " input.src line ; + Format.kfprintf + (fun fmt -> + Format.fprintf fmt "(at %a)" (pp_token input.lexbuf) input.token ; + Format.pp_print_flush fmt () ; + failwith (Buffer.contents buffer) + ) fmt text + + let eraise input = function + | Failure msg -> error input "Failure '%s'" msg + | exn -> error input "Failure '%s'" (Printexc.to_string exn) + + let key input k = + match input.token with + | Key a when a=k -> skip input ; true + | _ -> false + + let eat input k = + if not (key input k) then error input "Missing '%s'" k + + let ident input = + match input.token with + | Id a -> skip input ; a + | _ -> error input "Missing identifier" + + let rec idents input = + match input.token with + | Id a -> + skip input ; + if key input "," then a :: idents input else [a] + | _ -> [] + + +# 454 "src/wp/script.ml" diff -Nru frama-c-20110201+carbon+dfsg/src/wp/script.mli frama-c-20111001+nitrogen+dfsg/src/wp/script.mli --- frama-c-20110201+carbon+dfsg/src/wp/script.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/script.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,45 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Lexer for Script files --- *) +(* -------------------------------------------------------------------------- *) + +type token = + | Id of string + | Key of string + | Proof of string + | Word + | Eof + +type input + +val open_file : string -> input +val close : input -> unit +val skip : input -> unit +val token : input -> token +val error : input -> ('a,Format.formatter,unit,'b) format4 -> 'a + +val key : input -> string -> bool +val eat : input -> string -> unit +val ident : input -> string +val idents : input -> string list diff -Nru frama-c-20110201+carbon+dfsg/src/wp/script.mll frama-c-20111001+nitrogen+dfsg/src/wp/script.mll --- frama-c-20110201+carbon+dfsg/src/wp/script.mll 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/script.mll 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,162 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +{ + + type token = + | Id of string + | Key of string + | Proof of string + | Word + | Eof + + let keywords = [ "Goal" ; "Hint" ] + + let fill buffer lexbuf = + Buffer.add_string buffer (Lexing.lexeme lexbuf) + + open Lexing + + let newline lexbuf = + lexbuf.lex_curr_p <- + { lexbuf.lex_curr_p with pos_lnum = succ lexbuf.lex_curr_p.pos_lnum } + +} + +let space = [' ' '\t' '\r'] + +rule token = parse + space+ { token lexbuf } + | '\n' { newline lexbuf ; token lexbuf } + | "Proof." space* '\n' + { + newline lexbuf ; + let buffer = Buffer.create 512 in + proof buffer 0 lexbuf ; + Proof (Buffer.contents buffer) + } + | "Proof." space* + { + let buffer = Buffer.create 512 in + proof buffer 0 lexbuf ; + Proof (Buffer.contents buffer) + } + | [ 'a'-'z' 'A'-'Z' '0'-'9' '_' ]+ + { + let a = Lexing.lexeme lexbuf in + if List.mem a keywords then Key a else Id a + } + | [ '.' ':' ',' ';' ] { Key(Lexing.lexeme lexbuf) } + | "(*" { comment 0 lexbuf } + | eof { Eof } + | [ ',' '.' ] { Key(Lexing.lexeme lexbuf) } + | _ { Word } + +and comment n = parse + "*)" { if n > 0 then comment (pred n) lexbuf else token lexbuf } + | "(*" { comment (succ n) lexbuf } + | eof { failwith "Non-terminated comment" } + | '\n' { newline lexbuf ; comment n lexbuf } + | _ { comment n lexbuf } + +and proof buffer n = parse + ( "Qed." | "Save." ) + { + if n > 0 then proof buffer (pred n) lexbuf + } + | "(*" { fill buffer lexbuf ; proof buffer (succ n) lexbuf } + | "*)" { fill buffer lexbuf ; + if n>0 then proof buffer (pred n) lexbuf + else failwith "Non-terminated comment (inside proof)" } + | eof { failwith "Non-terminated proof" } + | '\n' { fill buffer lexbuf ; newline lexbuf ; proof buffer n lexbuf } + | _ { fill buffer lexbuf ; proof buffer n lexbuf } + +{ + + type input = { + src : string ; + inc : in_channel ; + lexbuf : Lexing.lexbuf ; + mutable token : token ; + mutable tik : int ; + } + + let open_file f = + let inc = open_in f in + let lex = Lexing.from_channel inc in + let tok = token lex in + { src=f ; tik=0 ; inc=inc ; lexbuf=lex ; token=tok } + + let pp_token lexbuf fmt = function + | Id x -> Format.fprintf fmt "ident '%s'" x + | Key k -> Format.fprintf fmt "'%s'" k + | Proof _ -> Format.fprintf fmt "Proof...Qed" + | Eof -> Format.fprintf fmt "end-of-file" + | Word -> Format.fprintf fmt "start of '%s'" (Lexing.lexeme lexbuf) + + + let skip input = + if input.token <> Eof then + ( input.tik <- 0 ; input.token <- token input.lexbuf ) + let token input = + input.tik <- succ input.tik ; + if input.tik > 1000 then failwith "Blocked" ; + input.token + let close input = close_in input.inc + let error input text = + let buffer = Buffer.create 80 in + let fmt = Format.formatter_of_buffer buffer in + let line = (Lexing.lexeme_start_p input.lexbuf).Lexing.pos_lnum in + Format.fprintf fmt "%s:%d: " input.src line ; + Format.kfprintf + (fun fmt -> + Format.fprintf fmt "(at %a)" (pp_token input.lexbuf) input.token ; + Format.pp_print_flush fmt () ; + failwith (Buffer.contents buffer) + ) fmt text + + let eraise input = function + | Failure msg -> error input "Failure '%s'" msg + | exn -> error input "Failure '%s'" (Printexc.to_string exn) + + let key input k = + match input.token with + | Key a when a=k -> skip input ; true + | _ -> false + + let eat input k = + if not (key input k) then error input "Missing '%s'" k + + let ident input = + match input.token with + | Id a -> skip input ; a + | _ -> error input "Missing identifier" + + let rec idents input = + match input.token with + | Id a -> + skip input ; + if key input "," then a :: idents input else [a] + | _ -> [] + +} diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/hoare_ergo.why frama-c-20111001+nitrogen+dfsg/src/wp/share/hoare_ergo.why --- frama-c-20110201+carbon+dfsg/src/wp/share/hoare_ergo.why 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/hoare_ergo.why 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,904 @@ +logic eq_unit : unit,unit -> prop + +logic neq_unit : unit,unit -> prop + +logic eq_bool : bool,bool -> prop + +logic neq_bool : bool,bool -> prop + +logic lt_int : int,int -> prop + +logic le_int : int,int -> prop + +logic gt_int : int,int -> prop + +logic ge_int : int,int -> prop + +logic eq_int : int,int -> prop + +logic neq_int : int,int -> prop + +logic add_int : int,int -> int + +logic sub_int : int,int -> int + +logic mul_int : int,int -> int + +logic neg_int : int -> int + +predicate zwf_zero(a:int,b:int) = ((0<=b) and (a<b)) + +logic bool_and : bool,bool -> bool + +logic bool_or : bool,bool -> bool + +logic bool_xor : bool,bool -> bool + +logic bool_not : bool -> bool + +axiom bool_and_def : (forall a:bool.(forall b:bool. +((bool_and(a,b)=true) <-> ((a=true) and (b=true))))) + +axiom bool_or_def : (forall a:bool.(forall b:bool. +((bool_or(a,b)=true) <-> ((a=true) or (b=true))))) + +axiom bool_xor_def : (forall a:bool.(forall b:bool. +((bool_xor(a,b)=true) <-> (a<>b)))) + +axiom bool_not_def : (forall a:bool. +((bool_not(a)=true) <-> (a=false))) + +logic ite : bool,'a1,'a1 -> 'a1 + +axiom ite_true : (forall x:'a1.(forall y:'a1. +(ite(true,x,y)=x))) + +axiom ite_false : (forall x:'a1.(forall y:'a1. +(ite(false,x,y)=y))) + +logic lt_int_bool : int,int -> bool + +logic le_int_bool : int,int -> bool + +logic gt_int_bool : int,int -> bool + +logic ge_int_bool : int,int -> bool + +logic eq_int_bool : int,int -> bool + +logic neq_int_bool : int,int -> bool + +axiom lt_int_bool_axiom : (forall x:int.(forall y:int. +((lt_int_bool(x,y)=true) <-> (x<y)))) + +axiom le_int_bool_axiom : (forall x:int.(forall y:int. +((le_int_bool(x,y)=true) <-> (x<=y)))) + +axiom gt_int_bool_axiom : (forall x:int.(forall y:int. +((gt_int_bool(x,y)=true) <-> (x>y)))) + +axiom ge_int_bool_axiom : (forall x:int.(forall y:int. +((ge_int_bool(x,y)=true) <-> (x>=y)))) + +axiom eq_int_bool_axiom : (forall x:int.(forall y:int. +((eq_int_bool(x,y)=true) <-> (x=y)))) + +axiom neq_int_bool_axiom : (forall x:int.(forall y:int. +((neq_int_bool(x,y)=true) <-> (x<>y)))) + +logic abs_int : int -> int + +axiom abs_int_pos : (forall x:int. +((x>=0) -> (abs_int(x)=x))) + +axiom abs_int_neg : (forall x:int. +((x<=0) -> (abs_int(x)=(-x)))) + +logic int_max : int,int -> int + +logic int_min : int,int -> int + +axiom int_max_is_ge : (forall x:int.(forall y:int. +((int_max(x,y)>=x) and (int_max(x,y)>=y)))) + +axiom int_max_is_some : (forall x:int.(forall y:int. +((int_max(x,y)=x) or (int_max(x,y)=y)))) + +axiom int_min_is_le : (forall x:int.(forall y:int. +((int_min(x,y)<=x) and (int_min(x,y)<=y)))) + +axiom int_min_is_some : (forall x:int.(forall y:int. +((int_min(x,y)=x) or (int_min(x,y)=y)))) + +logic lt_real : real,real -> prop + +logic le_real : real,real -> prop + +logic gt_real : real,real -> prop + +logic ge_real : real,real -> prop + +logic eq_real : real,real -> prop + +logic neq_real : real,real -> prop + +logic add_real : real,real -> real + +logic sub_real : real,real -> real + +logic mul_real : real,real -> real + +logic div_real : real,real -> real + +logic neg_real : real -> real + +logic real_of_int : int -> real + +axiom real_of_int_zero : (real_of_int(0)=0.0) + +axiom real_of_int_one : (real_of_int(1)=1.0) + +axiom real_of_int_add : (forall x:int.(forall y:int. +(real_of_int((x+y))=(real_of_int(x)+real_of_int(y))))) + +axiom real_of_int_sub : (forall x:int.(forall y:int. +(real_of_int((x-y))=(real_of_int(x)-real_of_int(y))))) + +logic truncate_real_to_int : real -> int + +axiom truncate_down_pos : (forall x:real. +((x>=0.0) -> ((real_of_int(truncate_real_to_int(x))<=x) and (x<real_of_int((truncate_real_to_int(x)+1)))))) + +axiom truncate_up_neg : (forall x:real. +((x<=0.0) -> ((real_of_int((truncate_real_to_int(x)-1))<x) and (x<=real_of_int(truncate_real_to_int(x)))))) + +logic floor_real_to_int : real -> int + +logic ceil_real_to_int : real -> int + +logic lt_real_bool : real,real -> bool + +logic le_real_bool : real,real -> bool + +logic gt_real_bool : real,real -> bool + +logic ge_real_bool : real,real -> bool + +logic eq_real_bool : real,real -> bool + +logic neq_real_bool : real,real -> bool + +axiom lt_real_bool_axiom : (forall x:real.(forall y:real. +((lt_real_bool(x,y)=true) <-> (x<y)))) + +axiom le_real_bool_axiom : (forall x:real.(forall y:real. +((le_real_bool(x,y)=true) <-> (x<=y)))) + +axiom gt_real_bool_axiom : (forall x:real.(forall y:real. +((gt_real_bool(x,y)=true) <-> (x>y)))) + +axiom ge_real_bool_axiom : (forall x:real.(forall y:real. +((ge_real_bool(x,y)=true) <-> (x>=y)))) + +axiom eq_real_bool_axiom : (forall x:real.(forall y:real. +((eq_real_bool(x,y)=true) <-> (x=y)))) + +axiom neq_real_bool_axiom : (forall x:real.(forall y:real. +((neq_real_bool(x,y)=true) <-> (x<>y)))) + +logic real_max : real,real -> real + +logic real_min : real,real -> real + +axiom real_max_is_ge : (forall x:real.(forall y:real. +((real_max(x,y)>=x) and (real_max(x,y)>=y)))) + +axiom real_max_is_some : (forall x:real.(forall y:real. +((real_max(x,y)=x) or (real_max(x,y)=y)))) + +axiom real_min_is_le : (forall x:real.(forall y:real. +((real_min(x,y)<=x) and (real_min(x,y)<=y)))) + +axiom real_min_is_some : (forall x:real.(forall y:real. +((real_min(x,y)=x) or (real_min(x,y)=y)))) + +function sqr_real(x:real) : real = (x*x) + +logic sqrt_real : real -> real + +axiom sqrt_pos : (forall x:real. +((x>=0.0) -> (sqrt_real(x)>=0.0))) + +axiom sqrt_sqr : (forall x:real. +((x>=0.0) -> (sqr_real(sqrt_real(x))=x))) + +axiom sqr_sqrt : (forall x:real. +((x>=0.0) -> (sqrt_real((x*x))=x))) + +logic pow_real : real,real -> real + +logic abs_real : real -> real + +axiom abs_real_pos : (forall x:real[abs_real(x)]. +((x>=0.0) -> (abs_real(x)=x))) + +axiom abs_real_neg : (forall x:real[abs_real(x)]. +((x<=0.0) -> (abs_real(x)=(-x)))) + +logic exp : real -> real + +logic log : real -> real + +logic log10 : real -> real + +axiom log_exp : (forall x:real. +(log(exp(x))=x)) + +axiom exp_log : (forall x:real. +((x>0.0) -> (exp(log(x))=x))) + +logic cos : real -> real + +logic sin : real -> real + +logic tan : real -> real + +logic pi : real + +logic cosh : real -> real + +logic sinh : real -> real + +logic tanh : real -> real + +logic acos : real -> real + +logic asin : real -> real + +logic atan : real -> real + +logic atan2 : real,real -> real + +logic hypot : real,real -> real + +axiom prod_pos : (forall x:real.(forall y:real. +((((x>0.0) and (y>0.0)) -> ((x*y)>0.0)) and (((x<0.0) and (y<0.0)) -> ((x*y)>0.0))))) + +axiom abs_minus : (forall x:real. +(abs_real((-x))=abs_real(x))) + + +logic access : 'a1 farray,int -> 'a1 + +logic update : 'a1 farray,int,'a1 -> 'a1 farray + +axiom access_update : (forall a:'a1 farray.(forall i:int.(forall v:'a1. +(a[i<-v][i]=v)))) + +axiom access_update_neq : (forall a:'a1 farray.(forall i:int.(forall j:int. +(forall v:'a1. +((i<>j) -> (a[i<-v][j]=a[j])))))) + +logic array_length : 'a1 farray -> int + +predicate sorted_array(t:int farray,i:int,j:int) = (forall k1:int. +(forall k2:int. +((((i<=k1) and (k1<=k2)) and (k2<=j)) -> (t[k1]<=t[k2])))) + +predicate exchange(a1:'a1 farray,a2:'a1 farray,i:int,j:int) = ((array_length(a1)=array_length(a2)) and ((a1[i]=a2[j]) and ((a2[i]=a1[j]) and ( +forall k:int. +(((k<>i) and (k<>j)) -> (a1[k]=a2[k])))))) + +logic permut : 'a1 farray,'a1 farray,int,int -> prop + +axiom permut_refl : (forall t:'a1 farray.(forall l:int.(forall u:int. +permut(t,t,l, +u)))) + +axiom permut_sym : (forall t1:'a1 farray.(forall t2:'a1 farray.(forall l:int. +(forall u:int.(permut(t1,t2,l,u) -> permut(t2,t1,l, +u)))))) + +axiom permut_trans : (forall t1:'a1 farray.(forall t2:'a1 farray. +(forall t3:'a1 farray.(forall l:int.(forall u:int.(permut(t1,t2,l, +u) -> (permut(t2,t3,l,u) -> permut(t1,t3,l, +u)))))))) + +axiom permut_exchange : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l:int.(forall u:int.(forall i:int.(forall j:int. +(((l<=i) and (i<=u)) -> (((l<=j) and (j<=u)) -> (exchange(a1,a2,i, +j) -> permut(a1,a2,l, +u)))))))))) + +axiom exchange_upd : (forall a:'a1 farray.(forall i:int.(forall j:int. +exchange(a,a[i<-a[j]][j<-a[i]],i, +j)))) + +axiom permut_weakening : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l1:int.(forall r1:int.(forall l2:int.(forall r2:int. +((((l1<=l2) and (l2<=r2)) and (r2<=r1)) -> (permut(a1,a2,l2,r2) -> permut(a1, +a2,l1, +r1))))))))) + +axiom permut_eq : (forall a1:'a1 farray.(forall a2:'a1 farray.(forall l:int. +(forall u:int.((l<=u) -> (permut(a1,a2,l,u) -> (forall i:int. +(((i<l) or (u<i)) -> (a2[i]=a1[i]))))))))) + +predicate permutation(a1:'a1 farray,a2:'a1 farray) = permut(a1,a2,0, +(array_length(a1)-1)) + +axiom array_length_update : (forall a:'a1 farray.(forall i:int.(forall v:'a1. +(array_length(a[i<-v])=array_length(a))))) + +axiom permut_array_length : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l:int.(forall u:int.(permut(a1,a2,l, +u) -> (array_length(a1)=array_length(a2))))))) + +logic computer_div : int,int -> int + +logic computer_mod : int,int -> int + +logic math_div : int,int -> int + +logic math_mod : int,int -> int + +axiom math_div_mod : (forall x:int.(forall y:int. +((y<>0) -> (x=((y*math_div(x,y))+math_mod(x,y)))))) + +axiom math_mod_bound : (forall x:int.(forall y:int. +((y<>0) -> ((0<=math_mod(x,y)) and (math_mod(x,y)<abs_int(y)))))) + +axiom computer_div_mod : (forall x:int. +(forall y:int[computer_div(x,y),computer_mod(x,y)]. +((y<>0) -> (x=((y*computer_div(x,y))+computer_mod(x,y)))))) + +axiom computer_div_bound : (forall x:int.(forall y:int. +(((x>=0) and (y>0)) -> ((0<=computer_div(x,y)) and (computer_div(x,y)<=x))))) + +axiom computer_mod_bound : (forall x:int.(forall y:int. +((y<>0) -> (abs_int(computer_mod(x,y))<abs_int(y))))) + +axiom computer_mod_sign_pos : (forall x:int.(forall y:int. +(((x>=0) and (y<>0)) -> (computer_mod(x,y)>=0)))) + +axiom computer_mod_sign_neg : (forall x:int.(forall y:int. +(((x<=0) and (y<>0)) -> (computer_mod(x,y)<=0)))) + +axiom computer_rounds_toward_zero : (forall x:int.(forall y:int. +((y<>0) -> (abs_int((computer_div(x,y)*y))<=abs_int(x))))) + +logic dummy : int -> prop + +logic assigns : int -> prop + +axiom positive_computer_div_div : (forall x:int.(forall y:int. +((x>0) -> ((y>0) -> (computer_div(x,y)=math_div(x,y)))))) + +type 'a set + +logic empty : 'a1 set + +logic singleton : 'a1 -> 'a1 set + +logic range : int,int -> int set + +logic union : 'a1 set,'a1 set -> 'a1 set + +logic inter : 'a1 set,'a1 set -> 'a1 set + +logic plus_int : int set,int set -> int set + +logic subset : 'a1 set,'a1 set -> prop + +logic range_inf : int -> int set + +logic range_sup : int -> int set + +logic integers_set : int set + +logic equiv : 'a1 set,'a1 set -> prop + +logic member : 'a1,'a1 set -> prop + +axiom singleton_def : (forall x:'a1.member(x, +singleton(x))) + +axiom singleton_eq : (forall x:'a1.(forall y:'a1.(member(x, +singleton(y)) <-> (x=y)))) + +axiom union_member : (forall x:'a1.(forall s1:'a1 set. +(forall s2:'a1 set[member(x,union(s1,s2))].(member(x, +union(s1,s2)) <-> (member(x,s1) or member(x, +s2)))))) + +axiom union_of_empty : (forall x:'a1 set[union(x,empty)]. +(union(x,empty)=x)) + +axiom inter_of_empty : (forall x:'a1 set[inter(x,empty)]. +(inter(x,empty)=empty)) + +axiom union_comm : (forall x:'a1 set.(forall y:'a1 set. +(union(x,y)=union(y,x)))) + +axiom inter_comm : (forall x:'a1 set.(forall y:'a1 set. +(inter(x,y)=inter(y,x)))) + +axiom inter_member : (forall x:'a1.(forall s1:'a1 set. +(forall s2:'a1 set[member(x,inter(s1,s2))].(member(x, +inter(s1,s2)) <-> (member(x,s1) and member(x, +s2)))))) + +axiom plus_int_member_1 : (forall sa:int set.(forall sb:int set. +(forall a:int.(forall b:int[member((a+b),plus_int(sa,sb))].(member(a, +sa) -> (member(b,sb) -> member((a+b), +plus_int(sa,sb)))))))) + +axiom plus_int_member_2 : (forall sa:int set.(forall sb:int set. +(forall c:int.(member(c,plus_int(sa,sb)) -> (exists a:int.(exists b:int. +(member(a,sa) and (member(b, +sb) and (c=(a+b)))))))))) + +axiom subset_empty : (forall sa:'a1 set.subset(empty, +sa)) + +axiom subset_sym : (forall sa:'a1 set.subset(sa, +sa)) + +axiom subset_trans : (forall sa:'a1 set.(forall sb:'a1 set. +(forall sc:'a1 set.(subset(sa,sb) -> (subset(sb,sc) -> subset(sa, +sc)))))) + +axiom subset_def : (forall sa:'a1 set.(forall sb:'a1 set[subset(sa,sb)]. +((forall a:'a1.(member(a,sa) -> member(a,sb))) <-> subset(sa, +sb)))) + +axiom range_def : (forall i:int.(forall j:int.(forall k:int. +(((i<=k) and (k<=j)) <-> member(k, +range(i,j)))))) + +axiom range_def1 : (forall i:int.(forall j:int.(forall k:int. +(((i<=k) and (k<=j)) -> member(k, +range(i,j)))))) + +axiom range_def2 : (forall i:int.(forall j:int.(forall k:int.(member(k, +range(i,j)) -> ((i<=k) and (k<=j)))))) + +axiom range_inf_def : (forall i:int.(forall k:int.((i<=k) <-> member(k, +range_inf(i))))) + +axiom range_sup_def : (forall j:int.(forall k:int.((k<=j) <-> member(k, +range_sup(j))))) + +axiom integers_set_def : (forall k:int.((k>=0) <-> member(k, +integers_set))) + +axiom equiv_def : (forall s1:'a1 set.(forall s2:'a1 set[equiv(s1,s2)]. +(((forall a:'a1.(member(a,s1) -> member(a,s2))) and (forall b:'a1.(member(b, +s2) -> member(b,s1)))) <-> equiv(s1, +s2)))) + +axiom equiv_refl : (forall s:'a1 set.equiv(s, +s)) + +axiom equiv_sym : (forall s1:'a1 set.(forall s2:'a1 set.(equiv(s1, +s2) -> equiv(s2, +s1)))) + +axiom equiv_trans : (forall s1:'a1 set.(forall s2:'a1 set.(forall s3:'a1 set. +(equiv(s1,s2) -> (equiv(s2,s3) -> equiv(s1, +s3)))))) + +logic as_uint8 : int -> int + +predicate is_uint8(x:int) = ((0<=x) and (x<256)) + +axiom as_uint8_def : (forall x:int. +is_uint8(as_uint8(x))) + +axiom as_uint8_involve : (forall x:int[as_uint8(as_uint8(x))]. +(as_uint8(as_uint8(x))=as_uint8(x))) + +axiom is_as_uint8 : (forall x:int[as_uint8(x)]. +(is_uint8(x) -> (as_uint8(x)=x))) + +logic as_sint8 : int -> int + +predicate is_sint8(x:int) = (((-128)<=x) and (x<128)) + +axiom as_sint8_def : (forall x:int. +is_sint8(as_sint8(x))) + +axiom as_sint8_involve : (forall x:int[as_sint8(as_sint8(x))]. +(as_sint8(as_sint8(x))=as_sint8(x))) + +axiom is_as_sint8 : (forall x:int[as_sint8(x)]. +(is_sint8(x) -> (as_sint8(x)=x))) + +logic as_uint16 : int -> int + +predicate is_uint16(x:int) = ((0<=x) and (x<65536)) + +axiom as_uint16_def : (forall x:int. +is_uint16(as_uint16(x))) + +axiom as_uint16_involve : (forall x:int[as_uint16(as_uint16(x))]. +(as_uint16(as_uint16(x))=as_uint16(x))) + +axiom is_as_uint16 : (forall x:int[as_uint16(x)]. +(is_uint16(x) -> (as_uint16(x)=x))) + +logic as_sint16 : int -> int + +predicate is_sint16(x:int) = (((-32768)<=x) and (x<32768)) + +axiom as_sint16_def : (forall x:int. +is_sint16(as_sint16(x))) + +axiom as_sint16_involve : (forall x:int[as_sint16(as_sint16(x))]. +(as_sint16(as_sint16(x))=as_sint16(x))) + +axiom is_as_sint16 : (forall x:int[as_sint16(x)]. +(is_sint16(x) -> (as_sint16(x)=x))) + +logic as_uint32 : int -> int + +predicate is_uint32(x:int) = ((0<=x) and (x<4294967296)) + +axiom as_uint32_def : (forall x:int. +is_uint32(as_uint32(x))) + +axiom as_uint32_involve : (forall x:int[as_uint32(as_uint32(x))]. +(as_uint32(as_uint32(x))=as_uint32(x))) + +axiom is_as_uint32 : (forall x:int[as_uint32(x)]. +(is_uint32(x) -> (as_uint32(x)=x))) + +logic as_sint32 : int -> int + +predicate is_sint32(x:int) = (((-2147483648)<=x) and (x<2147483648)) + +axiom as_sint32_def : (forall x:int. +is_sint32(as_sint32(x))) + +axiom as_sint32_involve : (forall x:int[as_sint32(as_sint32(x))]. +(as_sint32(as_sint32(x))=as_sint32(x))) + +axiom is_as_sint32 : (forall x:int[as_sint32(x)]. +(is_sint32(x) -> (as_sint32(x)=x))) + +logic as_uint64 : int -> int + +predicate is_uint64(x:int) = ((0<=x) and (x<18446744073709551616)) + +axiom as_uint64_def : (forall x:int. +is_uint64(as_uint64(x))) + +axiom as_uint64_involve : (forall x:int[as_uint64(as_uint64(x))]. +(as_uint64(as_uint64(x))=as_uint64(x))) + +axiom is_as_uint64 : (forall x:int[as_uint64(x)]. +(is_uint64(x) -> (as_uint64(x)=x))) + +logic as_sint64 : int -> int + +predicate is_sint64(x:int) = (((-9223372036854775808)<=x) and (x<9223372036854775808)) + +axiom as_sint64_def : (forall x:int. +is_sint64(as_sint64(x))) + +axiom as_sint64_involve : (forall x:int[as_sint64(as_sint64(x))]. +(as_sint64(as_sint64(x))=as_sint64(x))) + +axiom is_as_sint64 : (forall x:int[as_sint64(x)]. +(is_sint64(x) -> (as_sint64(x)=x))) + +logic as_float16 : real -> real + +logic is_float16 : real -> prop + +axiom as_float16_def : (forall x:real. +is_float16(as_float16(x))) + +axiom as_float16_involve : (forall x:real[as_float16(as_float16(x))]. +(as_float16(as_float16(x))=as_float16(x))) + +axiom is_as_float16 : (forall x:real[as_float16(x)]. +(is_float16(x) -> (as_float16(x)=x))) + +logic as_float32 : real -> real + +logic is_float32 : real -> prop + +axiom as_float32_def : (forall x:real. +is_float32(as_float32(x))) + +axiom as_float32_involve : (forall x:real[as_float32(as_float32(x))]. +(as_float32(as_float32(x))=as_float32(x))) + +axiom is_as_float32 : (forall x:real[as_float32(x)]. +(is_float32(x) -> (as_float32(x)=x))) + +logic as_float64 : real -> real + +logic is_float64 : real -> prop + +axiom as_float64_def : (forall x:real. +is_float64(as_float64(x))) + +axiom as_float64_involve : (forall x:real[as_float64(as_float64(x))]. +(as_float64(as_float64(x))=as_float64(x))) + +axiom is_as_float64 : (forall x:real[as_float64(x)]. +(is_float64(x) -> (as_float64(x)=x))) + +logic as_float128 : real -> real + +logic is_float128 : real -> prop + +axiom as_float128_def : (forall x:real. +is_float128(as_float128(x))) + +axiom as_float128_involve : (forall x:real[as_float128(as_float128(x))]. +(as_float128(as_float128(x))=as_float128(x))) + +axiom is_as_float128 : (forall x:real[as_float128(x)]. +(is_float128(x) -> (as_float128(x)=x))) + +type data + +logic data_of_uint8 : int -> data + +logic uint8_of_data : data -> int + +axiom is_uint8_of_data : (forall d:data[is_uint8(uint8_of_data(d))]. +is_uint8(uint8_of_data(d))) + +axiom uint8ofdata_dataofuint8 : (forall x:int[data_of_uint8(x)]. +(is_uint8(x) -> (uint8_of_data(data_of_uint8(x))=x))) + +logic data_of_sint8 : int -> data + +logic sint8_of_data : data -> int + +axiom is_sint8_of_data : (forall d:data[is_sint8(sint8_of_data(d))]. +is_sint8(sint8_of_data(d))) + +axiom sint8ofdata_dataofsint8 : (forall x:int[data_of_sint8(x)]. +(is_sint8(x) -> (sint8_of_data(data_of_sint8(x))=x))) + +logic data_of_uint16 : int -> data + +logic uint16_of_data : data -> int + +axiom is_uint16_of_data : (forall d:data[is_uint16(uint16_of_data(d))]. +is_uint16(uint16_of_data(d))) + +axiom uint16ofdata_dataofuint16 : (forall x:int[uint16_of_data(data_of_uint16(x))]. +(is_uint16(x) -> (uint16_of_data(data_of_uint16(x))=x))) + +logic data_of_sint16 : int -> data + +logic sint16_of_data : data -> int + +axiom is_sint16_of_data : (forall d:data[is_sint16(sint16_of_data(d))]. +is_sint16(sint16_of_data(d))) + +axiom sint16ofdata_dataofsint16 : (forall x:int[data_of_sint16(x)]. +(is_sint16(x) -> (sint16_of_data(data_of_sint16(x))=x))) + +logic data_of_uint32 : int -> data + +logic uint32_of_data : data -> int + +axiom is_uint32_of_data : (forall d:data[is_uint32(uint32_of_data(d))]. +is_uint32(uint32_of_data(d))) + +axiom uint32ofdata_dataofuint32 : (forall x:int[data_of_uint32(x)]. +(is_uint32(x) -> (uint32_of_data(data_of_uint32(x))=x))) + +logic data_of_sint32 : int -> data + +logic sint32_of_data : data -> int + +axiom is_sint32_of_data : (forall d:data[is_sint32(sint32_of_data(d))]. +is_sint32(sint32_of_data(d))) + +axiom sint32ofdata_dataofsint32 : (forall x:int[data_of_sint32(x)]. +(is_sint32(x) -> (sint32_of_data(data_of_sint32(x))=x))) + +logic data_of_uint64 : int -> data + +logic uint64_of_data : data -> int + +axiom is_uint64_of_data : (forall d:data[is_uint64(uint64_of_data(d))]. +is_uint64(uint64_of_data(d))) + +axiom uint64ofdata_dataofuint64 : (forall x:int[data_of_uint64(x)]. +(is_uint64(x) -> (uint64_of_data(data_of_uint64(x))=x))) + +logic data_of_sint64 : int -> data + +logic sint64_of_data : data -> int + +axiom is_sint64_of_data : (forall d:data[is_sint64(sint64_of_data(d))]. +is_sint64(sint64_of_data(d))) + +axiom sint64ofdata_dataofsint64 : (forall x:int[data_of_sint64(x)]. +(is_sint64(x) -> (sint64_of_data(data_of_sint64(x))=x))) + +logic data_of_float16 : real -> data + +logic float16_of_data : data -> real + +axiom is_float16_of_data : (forall d:data[is_float16(float16_of_data(d))]. +is_float16(float16_of_data(d))) + +axiom float16ofdata_dataoffloat16 : (forall x:real[data_of_float16(x)]. +(is_float16(x) -> (float16_of_data(data_of_float16(x))=x))) + +logic data_of_float32 : real -> data + +logic float32_of_data : data -> real + +axiom is_float32_of_data : (forall d:data[is_float32(float32_of_data(d))]. +is_float32(float32_of_data(d))) + +axiom float32ofdata_dataoffloat32 : (forall x:real[data_of_float32(x)]. +(is_float32(x) -> (float32_of_data(data_of_float32(x))=x))) + +logic data_of_float64 : real -> data + +logic float64_of_data : data -> real + +axiom is_float64_of_data : (forall d:data[is_float64(float64_of_data(d))]. +is_float64(float64_of_data(d))) + +axiom float64ofdata_dataoffloat64 : (forall x:real[data_of_float64(x)]. +(is_float64(x) -> (float64_of_data(data_of_float64(x))=x))) + +logic data_of_float128 : real -> data + +logic float128_of_data : data -> real + +axiom is_float128_of_data : (forall d:data[is_float128(float128_of_data(d))]. +is_float128(float128_of_data(d))) + +axiom float128ofdata_dataoffloat128 : (forall x:real[data_of_float128(x)]. +(is_float128(x) -> (float128_of_data(data_of_float128(x))=x))) + +logic set_range_index : 'a1 farray,int set,int -> 'a1 farray + +axiom set_range_def : (forall t:'a1 farray.(forall rg:int set.(forall k:int. +(forall i:int[set_range_index(t,rg,k)[i]].((not member(i, +rg)) -> (set_range_index(t,rg,k)[i]=t[i])))))) + +logic bnot : int -> int + +logic band : int,int -> int + +logic bor : int,int -> int + +logic bxor : int,int -> int + +logic lshift : int,int -> int + +logic rshift : int,int -> int + +logic int_not : int -> int + +logic int_and : int,int -> int + +logic int_or : int,int -> int + +logic int_xor : int,int -> int + +logic int_lsh : int,int -> int + +logic int_rshs : int,int -> int + +logic int_rshu : int,int -> int + +type pointer + +logic ptr : int,int -> pointer + +logic base : pointer -> int + +logic offset : pointer -> int + +axiom base_def : (forall b:int.(forall d:int[base(ptr(b,d))]. +(base(ptr(b,d))=b))) + +axiom offset_def : (forall b:int.(forall d:int[offset(ptr(b,d))]. +(offset(ptr(b,d))=d))) + +logic minus_ptr : pointer,pointer -> int + +axiom minus_ptr_def : (forall p1:pointer. +(forall p2:pointer[minus_ptr(p1,p2)]. +((base(p1)=base(p2)) -> (minus_ptr(p1,p2)=(offset(p1)-offset(p2)))))) + +predicate eq_ptr(a:pointer,b:pointer) = ((base(a)=base(b)) and (offset(a)=offset(b))) + +function eq_ptr_bool(a:pointer,b:pointer) : bool = bool_and(eq_int_bool(base(a),base(b)),eq_int_bool(offset(a),offset(b))) + +predicate lt_ptr(a:pointer,b:pointer) = ((base(a)=base(b)) and (offset(a)<offset(b))) + +function lt_ptr_bool(a:pointer,b:pointer) : bool = bool_and(eq_int_bool(base(a),base(b)),lt_int_bool(offset(a),offset(b))) + +predicate le_ptr(a:pointer,b:pointer) = ((base(a)=base(b)) and (offset(a)<=offset(b))) + +function le_ptr_bool(a:pointer,b:pointer) : bool = bool_and(eq_int_bool(base(a),base(b)),le_int_bool(offset(a),offset(b))) + +function shift(p:pointer,i:int) : pointer = ptr(base(p),(offset(p)+i)) + +axiom shift_0 : (forall p:pointer[shift(p,0)]. +(shift(p,0)=p)) + +axiom shift_shift : (forall p:pointer.(forall i:int. +(forall j:int[shift(shift(p,i),j)]. +(shift(shift(p,i),j)=shift(p,(i+j)))))) + +type trange + +logic range_ptr : int,int,int -> trange + +logic rbase : trange -> int + +logic roffset : trange -> int + +logic rsize : trange -> int + +axiom rbase_def : (forall b:int.(forall d:int. +(forall sz:int[rbase(range_ptr(b,d,sz))]. +(rbase(range_ptr(b,d,sz))=b)))) + +axiom roffset_def : (forall b:int.(forall d:int. +(forall sz:int[roffset(range_ptr(b,d,sz))]. +(roffset(range_ptr(b,d,sz))=d)))) + +axiom rsize_def : (forall b:int.(forall d:int. +(forall sz:int[rsize(range_ptr(b,d,sz))]. +(rsize(range_ptr(b,d,sz))=sz)))) + +function range_of_ptr(p:pointer,sz:int) : trange = range_ptr(base(p),offset(p),sz) + +axiom rbase_of_ptr : (forall p:pointer. +(forall sz:int[rbase(range_of_ptr(p,sz))]. +(rbase(range_of_ptr(p,sz))=base(p)))) + +axiom roffset_of_ptr : (forall p:pointer. +(forall sz:int[roffset(range_of_ptr(p,sz))]. +(roffset(range_of_ptr(p,sz))=offset(p)))) + +axiom rsize_of_ptr : (forall p:pointer. +(forall sz:int[rsize(range_of_ptr(p,sz))]. +(rsize(range_of_ptr(p,sz))=sz))) + +function range_of_ptr_range(p:pointer,d:int,sz:int) : trange = range_ptr(base(p),(offset(p)+d),sz) + +axiom rbase_of_ptr_range : (forall p:pointer.(forall d:int. +(forall sz:int[rbase(range_of_ptr_range(p,d,sz))]. +(rbase(range_of_ptr_range(p,d,sz))=base(p))))) + +axiom roffset_of_ptr_range : (forall p:pointer.(forall d:int. +(forall sz:int[roffset(range_of_ptr_range(p,d,sz))]. +(roffset(range_of_ptr_range(p,d,sz))=(offset(p)+d))))) + +axiom rsize_of_ptr_range : (forall p:pointer.(forall d:int. +(forall sz:int[rsize(range_of_ptr_range(p,d,sz))]. +(rsize(range_of_ptr_range(p,d,sz))=sz)))) + +predicate separated(r0:trange,r1:trange) = ((rbase(r0)=rbase(r1)) -> (((roffset(r0)+rsize(r0))<=roffset(r1)) or (roffset(r0)>=(roffset(r1)+rsize(r1))))) + +predicate valid(ta:int farray,r:trange) = ((rsize(r)>0) -> ((0<=roffset(r)) and ((roffset(r)+rsize(r))<=ta[rbase(r)]))) + +predicate included(r0:trange,r1:trange) = ((rbase(r0)=rbase(r1)) and ((roffset(r0)>=roffset(r1)) and ((roffset(r0)+rsize(r0))<=(roffset(r1)+rsize(r1))))) + +axiom valid_included : (forall r0:trange.(forall r1:trange. +(forall ta:int farray.(included(r0,r1) -> (valid(ta,r1) -> valid(ta, +r0)))))) + +logic global : int farray -> prop + + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/hoare_model.v frama-c-20111001+nitrogen+dfsg/src/wp/share/hoare_model.v --- frama-c-20110201+carbon+dfsg/src/wp/share/hoare_model.v 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/hoare_model.v 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,1332 @@ +(* This file was originally generated by why. + It can be modified; only the generated parts will be overwritten. *) +Require Import Reals. Require Import wp. + +(*Why logic*) Definition bool_and : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_or : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_xor : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_not : bool -> bool. +Admitted. + +(*Why axiom*) Lemma bool_and_def : + (forall (a:bool), + (forall (b:bool), ((bool_and a b) = true <-> a = true /\ b = true))). +Admitted. + +(*Why axiom*) Lemma bool_or_def : + (forall (a:bool), + (forall (b:bool), ((bool_or a b) = true <-> a = true \/ b = true))). +Admitted. + +(*Why axiom*) Lemma bool_xor_def : + (forall (a:bool), (forall (b:bool), ((bool_xor a b) = true <-> ~(a = b)))). +Admitted. + +(*Why axiom*) Lemma bool_not_def : + (forall (a:bool), ((bool_not a) = true <-> a = false)). +Admitted. + +(*Why logic*) Definition ite : forall (A1:Set), bool -> A1 -> A1 -> A1. +Admitted. +Implicit Arguments ite. + +(*Why axiom*) Lemma ite_true : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), (if_then_else true x y) = x)). +Admitted. + +(*Why axiom*) Lemma ite_false : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), (if_then_else false x y) = y)). +Admitted. + +(*Why logic*) Definition lt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition le_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition gt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition ge_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition eq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition neq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why axiom*) Lemma lt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((lt_int_bool x y) = true <-> x < y))). +Admitted. + +(*Why axiom*) Lemma le_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((le_int_bool x y) = true <-> x <= y))). +Admitted. + +(*Why axiom*) Lemma gt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((gt_int_bool x y) = true <-> x > y))). +Admitted. + +(*Why axiom*) Lemma ge_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((ge_int_bool x y) = true <-> x >= y))). +Admitted. + +(*Why axiom*) Lemma eq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((eq_int_bool x y) = true <-> x = y))). +Admitted. + +(*Why axiom*) Lemma neq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((neq_int_bool x y) = true <-> x <> y))). +Admitted. + +(*Why logic*) Definition abs_int : Z -> Z. +Admitted. + +(*Why axiom*) Lemma abs_int_pos : + (forall (x:Z), (x >= 0 -> (abs_int x) = x)). +Admitted. + +(*Why axiom*) Lemma abs_int_neg : + (forall (x:Z), (x <= 0 -> (abs_int x) = (Zopp x))). +Admitted. + +(*Why logic*) Definition int_max : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_min : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma int_max_is_ge : + (forall (x:Z), (forall (y:Z), (int_max x y) >= x /\ (int_max x y) >= y)). +Admitted. + +(*Why axiom*) Lemma int_max_is_some : + (forall (x:Z), (forall (y:Z), (int_max x y) = x \/ (int_max x y) = y)). +Admitted. + +(*Why axiom*) Lemma int_min_is_le : + (forall (x:Z), (forall (y:Z), (int_min x y) <= x /\ (int_min x y) <= y)). +Admitted. + +(*Why axiom*) Lemma int_min_is_some : + (forall (x:Z), (forall (y:Z), (int_min x y) = x \/ (int_min x y) = y)). +Admitted. + +(*Why logic*) Definition lt_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition le_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition gt_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition ge_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition eq_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition neq_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition add_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition sub_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition mul_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition div_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition neg_real : R -> R. +Admitted. + +(*Why logic*) Definition real_of_int : Z -> R. +Admitted. + +(*Why axiom*) Lemma real_of_int_zero : (eq (IZR 0) (0)%R). +Admitted. + +(*Why axiom*) Lemma real_of_int_one : (eq (IZR 1) (1)%R). +Admitted. + +(*Why axiom*) Lemma real_of_int_add : + (forall (x:Z), (forall (y:Z), (eq (IZR (x + y)) (Rplus (IZR x) (IZR y))))). +Admitted. + +(*Why axiom*) Lemma real_of_int_sub : + (forall (x:Z), (forall (y:Z), (eq (IZR (x - y)) (Rminus (IZR x) (IZR y))))). +Admitted. + +(*Why logic*) Definition truncate_real_to_int : R -> Z. +Admitted. + +(*Why axiom*) Lemma truncate_down_pos : + (forall (x:R), + ((Rge x (0)%R) -> (Rle (IZR (truncate_real_to_int x)) x) /\ + (Rlt x (IZR ((truncate_real_to_int x) + 1))))). +Admitted. + +(*Why axiom*) Lemma truncate_up_neg : + (forall (x:R), + ((Rle x (0)%R) -> (Rlt (IZR ((truncate_real_to_int x) - 1)) x) /\ + (Rle x (IZR (truncate_real_to_int x))))). +Admitted. + +(*Why logic*) Definition floor_real_to_int : R -> Z. +Admitted. + +(*Why logic*) Definition ceil_real_to_int : R -> Z. +Admitted. + +(*Why logic*) Definition lt_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition le_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition gt_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition ge_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition eq_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition neq_real_bool : R -> R -> bool. +Admitted. + +(*Why axiom*) Lemma lt_real_bool_axiom : + (forall (x:R), (forall (y:R), ((lt_real_bool x y) = true <-> (Rlt x y)))). +Admitted. + +(*Why axiom*) Lemma le_real_bool_axiom : + (forall (x:R), (forall (y:R), ((le_real_bool x y) = true <-> (Rle x y)))). +Admitted. + +(*Why axiom*) Lemma gt_real_bool_axiom : + (forall (x:R), (forall (y:R), ((gt_real_bool x y) = true <-> (Rgt x y)))). +Admitted. + +(*Why axiom*) Lemma ge_real_bool_axiom : + (forall (x:R), (forall (y:R), ((ge_real_bool x y) = true <-> (Rge x y)))). +Admitted. + +(*Why axiom*) Lemma eq_real_bool_axiom : + (forall (x:R), (forall (y:R), ((eq_real_bool x y) = true <-> (eq x y)))). +Admitted. + +(*Why axiom*) Lemma neq_real_bool_axiom : + (forall (x:R), (forall (y:R), ((neq_real_bool x y) = true <-> ~(eq x y)))). +Admitted. + +(*Why logic*) Definition real_max : R -> R -> R. +Admitted. + +(*Why logic*) Definition real_min : R -> R -> R. +Admitted. + +(*Why axiom*) Lemma real_max_is_ge : + (forall (x:R), + (forall (y:R), (Rge (real_max x y) x) /\ (Rge (real_max x y) y))). +Admitted. + +(*Why axiom*) Lemma real_max_is_some : + (forall (x:R), + (forall (y:R), (eq (real_max x y) x) \/ (eq (real_max x y) y))). +Admitted. + +(*Why axiom*) Lemma real_min_is_le : + (forall (x:R), + (forall (y:R), (Rle (real_min x y) x) /\ (Rle (real_min x y) y))). +Admitted. + +(*Why axiom*) Lemma real_min_is_some : + (forall (x:R), + (forall (y:R), (eq (real_min x y) x) \/ (eq (real_min x y) y))). +Admitted. + +(*Why function*) Definition sqr_real (x:R) := (Rmult x x). + +(*Why logic*) Definition sqrt_real : R -> R. +Admitted. + +(*Why axiom*) Lemma sqrt_pos : + (forall (x:R), ((Rge x (0)%R) -> (Rge (sqrt x) (0)%R))). +Admitted. + +(*Why axiom*) Lemma sqrt_sqr : + (forall (x:R), ((Rge x (0)%R) -> (eq (sqr_real (sqrt x)) x))). +Admitted. + +(*Why axiom*) Lemma sqr_sqrt : + (forall (x:R), ((Rge x (0)%R) -> (eq (sqrt (Rmult x x)) x))). +Admitted. + +(*Why logic*) Definition pow_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition abs_real : R -> R. +Admitted. + +(*Why axiom*) Lemma abs_real_pos : + (forall (x:R), ((Rge x (0)%R) -> (eq (Rabs x) x))). +Admitted. + +(*Why axiom*) Lemma abs_real_neg : + (forall (x:R), ((Rle x (0)%R) -> (eq (Rabs x) (Ropp x)))). +Admitted. + +(*Why logic*) Definition exp : R -> R. +Admitted. + +(*Why logic*) Definition log : R -> R. +Admitted. + +(*Why logic*) Definition log10 : R -> R. +Admitted. + +(*Why axiom*) Lemma log_exp : (forall (x:R), (eq (log (exp x)) x)). +Admitted. + +(*Why axiom*) Lemma exp_log : + (forall (x:R), ((Rgt x (0)%R) -> (eq (exp (log x)) x))). +Admitted. + +(*Why logic*) Definition cos : R -> R. +Admitted. + +(*Why logic*) Definition sin : R -> R. +Admitted. + +(*Why logic*) Definition tan : R -> R. +Admitted. + +(*Why logic*) Definition pi : R. +Admitted. + +(*Why logic*) Definition cosh : R -> R. +Admitted. + +(*Why logic*) Definition sinh : R -> R. +Admitted. + +(*Why logic*) Definition tanh : R -> R. +Admitted. + +(*Why logic*) Definition acos : R -> R. +Admitted. + +(*Why logic*) Definition asin : R -> R. +Admitted. + +(*Why logic*) Definition atan : R -> R. +Admitted. + +(*Why logic*) Definition atan2 : R -> R -> R. +Admitted. + +(*Why logic*) Definition hypot : R -> R -> R. +Admitted. + +(*Why axiom*) Lemma prod_pos : + (forall (x:R), + (forall (y:R), + (((Rgt x (0)%R) /\ (Rgt y (0)%R) -> (Rgt (Rmult x y) (0)%R))) /\ + (((Rlt x (0)%R) /\ (Rlt y (0)%R) -> (Rgt (Rmult x y) (0)%R))))). +Admitted. + +(*Why axiom*) Lemma abs_minus : + (forall (x:R), (eq (Rabs (Ropp x)) (Rabs x))). +Admitted. + +(*Why type*) Definition farray: Set ->Set. +Admitted. + +(*Why logic*) Definition access : forall (A1:Set), (array A1) -> Z -> A1. +Admitted. +Implicit Arguments access. + +(*Why logic*) Definition update : + forall (A1:Set), (array A1) -> Z -> A1 -> (array A1). +Admitted. +Implicit Arguments update. + +(*Why axiom*) Lemma access_update : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), (forall (v:A1), (access (update a i v) i) = v))). +Admitted. + +(*Why axiom*) Lemma access_update_neq : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (j:Z), + (forall (v:A1), (i <> j -> (access (update a i v) j) = (access a j)))))). +Admitted. + +(*Why logic*) Definition array_length : forall (A1:Set), (array A1) -> Z. +Admitted. +Implicit Arguments array_length. + +(*Why predicate*) Definition sorted_array (t:(array Z)) (i:Z) (j:Z) + := (forall (k1:Z), + (forall (k2:Z), + ((i <= k1 /\ k1 <= k2) /\ k2 <= j -> (access t k1) <= (access t k2)))). + +(*Why predicate*) Definition exchange (A191:Set) (a1:(array A191)) (a2:(array A191)) (i:Z) (j:Z) + := (array_length a1) = (array_length a2) /\ + (access a1 i) = (access a2 j) /\ (access a2 i) = (access a1 j) /\ + (forall (k:Z), (k <> i /\ k <> j -> (access a1 k) = (access a2 k))). +Implicit Arguments exchange. + +(*Why logic*) Definition permut : + forall (A1:Set), (array A1) -> (array A1) -> Z -> Z -> Prop. +Admitted. +Implicit Arguments permut. + +(*Why axiom*) Lemma permut_refl : + forall (A1:Set), + (forall (t:(array A1)), (forall (l:Z), (forall (u:Z), (permut t t l u)))). +Admitted. + +(*Why axiom*) Lemma permut_sym : + forall (A1:Set), + (forall (t1:(array A1)), + (forall (t2:(array A1)), + (forall (l:Z), (forall (u:Z), ((permut t1 t2 l u) -> (permut t2 t1 l u)))))). +Admitted. + +(*Why axiom*) Lemma permut_trans : + forall (A1:Set), + (forall (t1:(array A1)), + (forall (t2:(array A1)), + (forall (t3:(array A1)), + (forall (l:Z), + (forall (u:Z), + ((permut t1 t2 l u) -> ((permut t2 t3 l u) -> (permut t1 t3 l u)))))))). +Admitted. + +(*Why axiom*) Lemma permut_exchange : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + (forall (i:Z), + (forall (j:Z), + (l <= i /\ i <= u -> + (l <= j /\ j <= u -> ((exchange a1 a2 i j) -> (permut a1 a2 l u)))))))))). +Admitted. + +(*Why axiom*) Lemma exchange_upd : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (j:Z), + (exchange a (update (update a i (access a j)) j (access a i)) i j)))). +Admitted. + +(*Why axiom*) Lemma permut_weakening : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l1:Z), + (forall (r1:Z), + (forall (l2:Z), + (forall (r2:Z), + ((l1 <= l2 /\ l2 <= r2) /\ r2 <= r1 -> + ((permut a1 a2 l2 r2) -> (permut a1 a2 l1 r1))))))))). +Admitted. + +(*Why axiom*) Lemma permut_eq : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + (l <= u -> + ((permut a1 a2 l u) -> + (forall (i:Z), (i < l \/ u < i -> (access a2 i) = (access a1 i))))))))). +Admitted. + +(*Why predicate*) Definition permutation (A200:Set) (a1:(array A200)) (a2:(array A200)) + := (permut a1 a2 0 ((array_length a1) - 1)). +Implicit Arguments permutation. + +(*Why axiom*) Lemma array_length_update : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (v:A1), (array_length (update a i v)) = (array_length a)))). +Admitted. + +(*Why axiom*) Lemma permut_array_length : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + ((permut a1 a2 l u) -> (array_length a1) = (array_length a2)))))). +Admitted. + +(*Why logic*) Definition computer_div : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition computer_mod : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition math_div : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition math_mod : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma math_div_mod : + (forall (x:Z), + (forall (y:Z), (y <> 0 -> x = (y * (math_div x y) + (math_mod x y))))). +Admitted. + +(*Why axiom*) Lemma math_mod_bound : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> 0 <= (math_mod x y) /\ (math_mod x y) < (abs_int y)))). +Admitted. + +(*Why axiom*) Lemma computer_div_mod : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> x = (y * (computer_div x y) + (computer_mod x y))))). +Admitted. + +(*Why axiom*) Lemma computer_div_bound : + (forall (x:Z), + (forall (y:Z), + (x >= 0 /\ y > 0 -> 0 <= (computer_div x y) /\ (computer_div x y) <= x))). +Admitted. + +(*Why axiom*) Lemma computer_mod_bound : + (forall (x:Z), + (forall (y:Z), (y <> 0 -> (abs_int (computer_mod x y)) < (abs_int y)))). +Admitted. + +(*Why axiom*) Lemma computer_mod_sign_pos : + (forall (x:Z), + (forall (y:Z), (x >= 0 /\ y <> 0 -> (computer_mod x y) >= 0))). +Admitted. + +(*Why axiom*) Lemma computer_mod_sign_neg : + (forall (x:Z), + (forall (y:Z), (x <= 0 /\ y <> 0 -> (computer_mod x y) <= 0))). +Admitted. + +(*Why axiom*) Lemma computer_rounds_toward_zero : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> (abs_int ((computer_div x y) * y)) <= (abs_int x)))). +Admitted. + +(*Why logic*) Definition dummy : Z -> Prop. +Admitted. + +(*Why logic*) Definition assigns : Z -> Prop. +Admitted. + +(*Why axiom*) Lemma positive_computer_div_div : + (forall (x:Z), + (forall (y:Z), (x > 0 -> (y > 0 -> (computer_div x y) = (math_div x y))))). +Admitted. + +(*Why type*) Definition set: Set ->Set. +Admitted. + +(*Why logic*) Definition empty : forall (A1:Set), (set A1). +Admitted. +Set Contextual Implicit. +Implicit Arguments empty. +Unset Contextual Implicit. + +(*Why logic*) Definition singleton : forall (A1:Set), A1 -> (set A1). +Admitted. +Implicit Arguments singleton. + +(*Why logic*) Definition range : Z -> Z -> (set Z). +Admitted. + +(*Why logic*) Definition union : + forall (A1:Set), (set A1) -> (set A1) -> (set A1). +Admitted. +Implicit Arguments union. + +(*Why logic*) Definition inter : + forall (A1:Set), (set A1) -> (set A1) -> (set A1). +Admitted. +Implicit Arguments inter. + +(*Why logic*) Definition plus_int : (set Z) -> (set Z) -> (set Z). +Admitted. + +(*Why logic*) Definition subset : + forall (A1:Set), (set A1) -> (set A1) -> Prop. +Admitted. +Implicit Arguments subset. + +(*Why logic*) Definition range_inf : Z -> (set Z). +Admitted. + +(*Why logic*) Definition range_sup : Z -> (set Z). +Admitted. + +(*Why logic*) Definition integers_set : (set Z). +Admitted. + +(*Why logic*) Definition equiv : + forall (A1:Set), (set A1) -> (set A1) -> Prop. +Admitted. +Implicit Arguments equiv. + +(*Why logic*) Definition member : forall (A1:Set), A1 -> (set A1) -> Prop. +Admitted. +Implicit Arguments member. + +(*Why axiom*) Lemma singleton_def : + forall (A1:Set), (forall (x:A1), (member x (singleton x))). +Admitted. + +(*Why axiom*) Lemma singleton_eq : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), ((member x (singleton y)) <-> x = y))). +Admitted. + +(*Why axiom*) Lemma union_member : + forall (A1:Set), + (forall (x:A1), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((member x (union s1 s2)) <-> (member x s1) \/ (member x s2))))). +Admitted. + +(*Why axiom*) Lemma union_of_empty : + forall (A1:Set), (forall (x:(set A1)), (union x (@empty A1)) = x). +Admitted. + +(*Why axiom*) Lemma inter_of_empty : + forall (A1:Set), (forall (x:(set A1)), (inter x (@empty A1)) = (@empty A1)). +Admitted. + +(*Why axiom*) Lemma union_comm : + forall (A1:Set), + (forall (x:(set A1)), (forall (y:(set A1)), (union x y) = (union y x))). +Admitted. + +(*Why axiom*) Lemma inter_comm : + forall (A1:Set), + (forall (x:(set A1)), (forall (y:(set A1)), (inter x y) = (inter y x))). +Admitted. + +(*Why axiom*) Lemma inter_member : + forall (A1:Set), + (forall (x:A1), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((member x (inter s1 s2)) <-> (member x s1) /\ (member x s2))))). +Admitted. + +(*Why axiom*) Lemma plus_int_member_1 : + (forall (sa:(set Z)), + (forall (sb:(set Z)), + (forall (a:Z), + (forall (b:Z), + ((member a sa) -> ((member b sb) -> (member (a + b) (plus_int sa sb)))))))). +Admitted. + +(*Why axiom*) Lemma plus_int_member_2 : + (forall (sa:(set Z)), + (forall (sb:(set Z)), + (forall (c:Z), + ((member c (plus_int sa sb)) -> + (exists a:Z, + (exists b:Z, (member a sa) /\ (member b sb) /\ c = (a + b))))))). +Admitted. + +(*Why axiom*) Lemma subset_empty : + forall (A1:Set), (forall (sa:(set A1)), (subset (@empty A1) sa)). +Admitted. + +(*Why axiom*) Lemma subset_sym : + forall (A1:Set), (forall (sa:(set A1)), (subset sa sa)). +Admitted. + +(*Why axiom*) Lemma subset_trans : + forall (A1:Set), + (forall (sa:(set A1)), + (forall (sb:(set A1)), + (forall (sc:(set A1)), + ((subset sa sb) -> ((subset sb sc) -> (subset sa sc)))))). +Admitted. + +(*Why axiom*) Lemma subset_def : + forall (A1:Set), + (forall (sa:(set A1)), + (forall (sb:(set A1)), + ((forall (a:A1), ((member a sa) -> (member a sb))) <-> (subset sa sb)))). +Admitted. + +(*Why axiom*) Lemma range_def : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), (i <= k /\ k <= j <-> (member k (range i j)))))). +Admitted. + +(*Why axiom*) Lemma range_def1 : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), (i <= k /\ k <= j -> (member k (range i j)))))). +Admitted. + +(*Why axiom*) Lemma range_def2 : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), ((member k (range i j)) -> i <= k /\ k <= j)))). +Admitted. + +(*Why axiom*) Lemma range_inf_def : + (forall (i:Z), (forall (k:Z), (i <= k <-> (member k (range_inf i))))). +Admitted. + +(*Why axiom*) Lemma range_sup_def : + (forall (j:Z), (forall (k:Z), (k <= j <-> (member k (range_sup j))))). +Admitted. + +(*Why axiom*) Lemma integers_set_def : + (forall (k:Z), (k >= 0 <-> (member k integers_set))). +Admitted. + +(*Why axiom*) Lemma equiv_def : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((forall (a:A1), ((member a s1) -> (member a s2))) /\ + (forall (b:A1), ((member b s2) -> (member b s1))) <-> (equiv s1 s2)))). +Admitted. + +(*Why axiom*) Lemma equiv_refl : + forall (A1:Set), (forall (s:(set A1)), (equiv s s)). +Admitted. + +(*Why axiom*) Lemma equiv_sym : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), ((equiv s1 s2) -> (equiv s2 s1)))). +Admitted. + +(*Why axiom*) Lemma equiv_trans : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + (forall (s3:(set A1)), + ((equiv s1 s2) -> ((equiv s2 s3) -> (equiv s1 s3)))))). +Admitted. + +(*Why logic*) Definition as_uint8 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint8 (x:Z) := 0 <= x /\ x < 256. + +(*Why axiom*) Lemma as_uint8_def : (forall (x:Z), (is_uint8 (as_uint8 x))). +Admitted. + +(*Why axiom*) Lemma as_uint8_involve : + (forall (x:Z), (as_uint8 (as_uint8 x)) = (as_uint8 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint8 : + (forall (x:Z), ((is_uint8 x) -> (as_uint8 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint8 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint8 (x:Z) := (-128) <= x /\ x < 128. + +(*Why axiom*) Lemma as_sint8_def : (forall (x:Z), (is_sint8 (as_sint8 x))). +Admitted. + +(*Why axiom*) Lemma as_sint8_involve : + (forall (x:Z), (as_sint8 (as_sint8 x)) = (as_sint8 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint8 : + (forall (x:Z), ((is_sint8 x) -> (as_sint8 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint16 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint16 (x:Z) := 0 <= x /\ x < 65536. + +(*Why axiom*) Lemma as_uint16_def : + (forall (x:Z), (is_uint16 (as_uint16 x))). +Admitted. + +(*Why axiom*) Lemma as_uint16_involve : + (forall (x:Z), (as_uint16 (as_uint16 x)) = (as_uint16 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint16 : + (forall (x:Z), ((is_uint16 x) -> (as_uint16 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint16 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint16 (x:Z) := (-32768) <= x /\ x < 32768. + +(*Why axiom*) Lemma as_sint16_def : + (forall (x:Z), (is_sint16 (as_sint16 x))). +Admitted. + +(*Why axiom*) Lemma as_sint16_involve : + (forall (x:Z), (as_sint16 (as_sint16 x)) = (as_sint16 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint16 : + (forall (x:Z), ((is_sint16 x) -> (as_sint16 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint32 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint32 (x:Z) := 0 <= x /\ x < 4294967296. + +(*Why axiom*) Lemma as_uint32_def : + (forall (x:Z), (is_uint32 (as_uint32 x))). +Admitted. + +(*Why axiom*) Lemma as_uint32_involve : + (forall (x:Z), (as_uint32 (as_uint32 x)) = (as_uint32 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint32 : + (forall (x:Z), ((is_uint32 x) -> (as_uint32 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint32 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint32 (x:Z) + := (-2147483648) <= x /\ x < 2147483648. + +(*Why axiom*) Lemma as_sint32_def : + (forall (x:Z), (is_sint32 (as_sint32 x))). +Admitted. + +(*Why axiom*) Lemma as_sint32_involve : + (forall (x:Z), (as_sint32 (as_sint32 x)) = (as_sint32 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint32 : + (forall (x:Z), ((is_sint32 x) -> (as_sint32 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint64 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint64 (x:Z) + := 0 <= x /\ x < 18446744073709551616. + +(*Why axiom*) Lemma as_uint64_def : + (forall (x:Z), (is_uint64 (as_uint64 x))). +Admitted. + +(*Why axiom*) Lemma as_uint64_involve : + (forall (x:Z), (as_uint64 (as_uint64 x)) = (as_uint64 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint64 : + (forall (x:Z), ((is_uint64 x) -> (as_uint64 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint64 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint64 (x:Z) + := (-9223372036854775808) <= x /\ x < 9223372036854775808. + +(*Why axiom*) Lemma as_sint64_def : + (forall (x:Z), (is_sint64 (as_sint64 x))). +Admitted. + +(*Why axiom*) Lemma as_sint64_involve : + (forall (x:Z), (as_sint64 (as_sint64 x)) = (as_sint64 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint64 : + (forall (x:Z), ((is_sint64 x) -> (as_sint64 x) = x)). +Admitted. + +(*Why logic*) Definition as_float16 : R -> R. +Admitted. + +(*Why logic*) Definition is_float16 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float16_def : + (forall (x:R), (is_float16 (as_float16 x))). +Admitted. + +(*Why axiom*) Lemma as_float16_involve : + (forall (x:R), (eq (as_float16 (as_float16 x)) (as_float16 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float16 : + (forall (x:R), ((is_float16 x) -> (eq (as_float16 x) x))). +Admitted. + +(*Why logic*) Definition as_float32 : R -> R. +Admitted. + +(*Why logic*) Definition is_float32 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float32_def : + (forall (x:R), (is_float32 (as_float32 x))). +Admitted. + +(*Why axiom*) Lemma as_float32_involve : + (forall (x:R), (eq (as_float32 (as_float32 x)) (as_float32 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float32 : + (forall (x:R), ((is_float32 x) -> (eq (as_float32 x) x))). +Admitted. + +(*Why logic*) Definition as_float64 : R -> R. +Admitted. + +(*Why logic*) Definition is_float64 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float64_def : + (forall (x:R), (is_float64 (as_float64 x))). +Admitted. + +(*Why axiom*) Lemma as_float64_involve : + (forall (x:R), (eq (as_float64 (as_float64 x)) (as_float64 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float64 : + (forall (x:R), ((is_float64 x) -> (eq (as_float64 x) x))). +Admitted. + +(*Why logic*) Definition as_float128 : R -> R. +Admitted. + +(*Why logic*) Definition is_float128 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float128_def : + (forall (x:R), (is_float128 (as_float128 x))). +Admitted. + +(*Why axiom*) Lemma as_float128_involve : + (forall (x:R), (eq (as_float128 (as_float128 x)) (as_float128 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float128 : + (forall (x:R), ((is_float128 x) -> (eq (as_float128 x) x))). +Admitted. + +(*Why type*) Definition data: Set. +Admitted. + +(*Why logic*) Definition data_of_uint8 : Z -> data. +Admitted. + +(*Why logic*) Definition uint8_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint8_of_data : + (forall (d:data), (is_uint8 (uint8_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint8ofdata_dataofuint8 : + (forall (x:Z), ((is_uint8 x) -> (uint8_of_data (data_of_uint8 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint8 : Z -> data. +Admitted. + +(*Why logic*) Definition sint8_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint8_of_data : + (forall (d:data), (is_sint8 (sint8_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint8ofdata_dataofsint8 : + (forall (x:Z), ((is_sint8 x) -> (sint8_of_data (data_of_sint8 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint16 : Z -> data. +Admitted. + +(*Why logic*) Definition uint16_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint16_of_data : + (forall (d:data), (is_uint16 (uint16_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint16ofdata_dataofuint16 : + (forall (x:Z), ((is_uint16 x) -> (uint16_of_data (data_of_uint16 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint16 : Z -> data. +Admitted. + +(*Why logic*) Definition sint16_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint16_of_data : + (forall (d:data), (is_sint16 (sint16_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint16ofdata_dataofsint16 : + (forall (x:Z), ((is_sint16 x) -> (sint16_of_data (data_of_sint16 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint32 : Z -> data. +Admitted. + +(*Why logic*) Definition uint32_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint32_of_data : + (forall (d:data), (is_uint32 (uint32_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint32ofdata_dataofuint32 : + (forall (x:Z), ((is_uint32 x) -> (uint32_of_data (data_of_uint32 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint32 : Z -> data. +Admitted. + +(*Why logic*) Definition sint32_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint32_of_data : + (forall (d:data), (is_sint32 (sint32_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint32ofdata_dataofsint32 : + (forall (x:Z), ((is_sint32 x) -> (sint32_of_data (data_of_sint32 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint64 : Z -> data. +Admitted. + +(*Why logic*) Definition uint64_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint64_of_data : + (forall (d:data), (is_uint64 (uint64_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint64ofdata_dataofuint64 : + (forall (x:Z), ((is_uint64 x) -> (uint64_of_data (data_of_uint64 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint64 : Z -> data. +Admitted. + +(*Why logic*) Definition sint64_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint64_of_data : + (forall (d:data), (is_sint64 (sint64_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint64ofdata_dataofsint64 : + (forall (x:Z), ((is_sint64 x) -> (sint64_of_data (data_of_sint64 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_float16 : R -> data. +Admitted. + +(*Why logic*) Definition float16_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float16_of_data : + (forall (d:data), (is_float16 (float16_of_data d))). +Admitted. + +(*Why axiom*) Lemma float16ofdata_dataoffloat16 : + (forall (x:R), + ((is_float16 x) -> (eq (float16_of_data (data_of_float16 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float32 : R -> data. +Admitted. + +(*Why logic*) Definition float32_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float32_of_data : + (forall (d:data), (is_float32 (float32_of_data d))). +Admitted. + +(*Why axiom*) Lemma float32ofdata_dataoffloat32 : + (forall (x:R), + ((is_float32 x) -> (eq (float32_of_data (data_of_float32 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float64 : R -> data. +Admitted. + +(*Why logic*) Definition float64_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float64_of_data : + (forall (d:data), (is_float64 (float64_of_data d))). +Admitted. + +(*Why axiom*) Lemma float64ofdata_dataoffloat64 : + (forall (x:R), + ((is_float64 x) -> (eq (float64_of_data (data_of_float64 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float128 : R -> data. +Admitted. + +(*Why logic*) Definition float128_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float128_of_data : + (forall (d:data), (is_float128 (float128_of_data d))). +Admitted. + +(*Why axiom*) Lemma float128ofdata_dataoffloat128 : + (forall (x:R), + ((is_float128 x) -> (eq (float128_of_data (data_of_float128 x)) x))). +Admitted. + +(*Why logic*) Definition set_range_index : + forall (A1:Set), (array A1) -> (set Z) -> Z -> (array A1). +Admitted. +Implicit Arguments set_range_index. + +(*Why axiom*) Lemma set_range_def : + forall (A1:Set), + (forall (t:(array A1)), + (forall (rg:(set Z)), + (forall (k:Z), + (forall (i:Z), + (~(member i rg) -> (access (set_range_index t rg k) i) = (access t i)))))). +Admitted. + +(*Why logic*) Definition bnot : Z -> Z. +Admitted. + +(*Why logic*) Definition band : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition bor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition bxor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition lshift : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition rshift : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_not : Z -> Z. +Admitted. + +(*Why logic*) Definition int_and : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_or : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_xor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_lsh : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_rshs : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_rshu : Z -> Z -> Z. +Admitted. + +(*Why type*) Definition pointer: Set. +Admitted. + +(*Why logic*) Definition ptr : Z -> Z -> pointer. +Admitted. + +(*Why logic*) Definition base : pointer -> Z. +Admitted. + +(*Why logic*) Definition offset : pointer -> Z. +Admitted. + +(*Why axiom*) Lemma base_def : + (forall (b:Z), (forall (d:Z), (base (ptr b d)) = b)). +Admitted. + +(*Why axiom*) Lemma offset_def : + (forall (b:Z), (forall (d:Z), (offset (ptr b d)) = d)). +Admitted. + +(*Why logic*) Definition minus_ptr : pointer -> pointer -> Z. +Admitted. + +(*Why axiom*) Lemma minus_ptr_def : + (forall (p1:pointer), + (forall (p2:pointer), + ((base p1) = (base p2) -> (minus_ptr p1 p2) = ((offset p1) - (offset p2))))). +Admitted. + +(*Why predicate*) Definition eq_ptr (a:pointer) (b:pointer) + := (base a) = (base b) /\ (offset a) = (offset b). + +(*Why function*) Definition eq_ptr_bool (a:pointer) (b:pointer) + := (bool_and + (eq_int_bool (base a) (base b)) (eq_int_bool (offset a) (offset b))). + +(*Why predicate*) Definition lt_ptr (a:pointer) (b:pointer) + := (base a) = (base b) /\ (offset a) < (offset b). + +(*Why function*) Definition lt_ptr_bool (a:pointer) (b:pointer) + := (bool_and + (eq_int_bool (base a) (base b)) (lt_int_bool (offset a) (offset b))). + +(*Why predicate*) Definition le_ptr (a:pointer) (b:pointer) + := (base a) = (base b) /\ (offset a) <= (offset b). + +(*Why function*) Definition le_ptr_bool (a:pointer) (b:pointer) + := (bool_and + (eq_int_bool (base a) (base b)) (le_int_bool (offset a) (offset b))). + +(*Why function*) Definition shift (p:pointer) (i:Z) + := (ptr (base p) ((offset p) + i)). + +(*Why axiom*) Lemma shift_0 : (forall (p:pointer), (shift p 0) = p). +Admitted. + +(*Why axiom*) Lemma shift_shift : + (forall (p:pointer), + (forall (i:Z), (forall (j:Z), (shift (shift p i) j) = (shift p (i + j))))). +Admitted. + +(*Why type*) Definition trange: Set. +Admitted. + +(*Why logic*) Definition range_ptr : Z -> Z -> Z -> trange. +Admitted. + +(*Why logic*) Definition rbase : trange -> Z. +Admitted. + +(*Why logic*) Definition roffset : trange -> Z. +Admitted. + +(*Why logic*) Definition rsize : trange -> Z. +Admitted. + +(*Why axiom*) Lemma rbase_def : + (forall (b:Z), + (forall (d:Z), (forall (sz:Z), (rbase (range_ptr b d sz)) = b))). +Admitted. + +(*Why axiom*) Lemma roffset_def : + (forall (b:Z), + (forall (d:Z), (forall (sz:Z), (roffset (range_ptr b d sz)) = d))). +Admitted. + +(*Why axiom*) Lemma rsize_def : + (forall (b:Z), + (forall (d:Z), (forall (sz:Z), (rsize (range_ptr b d sz)) = sz))). +Admitted. + +(*Why function*) Definition range_of_ptr (p:pointer) (sz:Z) + := (range_ptr (base p) (offset p) sz). + +(*Why axiom*) Lemma rbase_of_ptr : + (forall (p:pointer), + (forall (sz:Z), (rbase (range_of_ptr p sz)) = (base p))). +Admitted. + +(*Why axiom*) Lemma roffset_of_ptr : + (forall (p:pointer), + (forall (sz:Z), (roffset (range_of_ptr p sz)) = (offset p))). +Admitted. + +(*Why axiom*) Lemma rsize_of_ptr : + (forall (p:pointer), (forall (sz:Z), (rsize (range_of_ptr p sz)) = sz)). +Admitted. + +(*Why function*) Definition range_of_ptr_range (p:pointer) (d:Z) (sz:Z) + := (range_ptr (base p) ((offset p) + d) sz). + +(*Why axiom*) Lemma rbase_of_ptr_range : + (forall (p:pointer), + (forall (d:Z), + (forall (sz:Z), (rbase (range_of_ptr_range p d sz)) = (base p)))). +Admitted. + +(*Why axiom*) Lemma roffset_of_ptr_range : + (forall (p:pointer), + (forall (d:Z), + (forall (sz:Z), (roffset (range_of_ptr_range p d sz)) = ((offset p) + d)))). +Admitted. + +(*Why axiom*) Lemma rsize_of_ptr_range : + (forall (p:pointer), + (forall (d:Z), (forall (sz:Z), (rsize (range_of_ptr_range p d sz)) = sz))). +Admitted. + +(*Why predicate*) Definition separated (r0:trange) (r1:trange) + := ((rbase r0) = (rbase r1) -> ((roffset r0) + (rsize r0)) <= + (roffset r1) \/ (roffset r0) >= ((roffset r1) + (rsize r1))). + +(*Why predicate*) Definition valid (ta:(array Z)) (r:trange) + := ((rsize r) > 0 -> 0 <= (roffset r) /\ ((roffset r) + (rsize r)) <= + (access ta (rbase r))). + +(*Why predicate*) Definition included (r0:trange) (r1:trange) + := (rbase r0) = (rbase r1) /\ (roffset r0) >= (roffset r1) /\ + ((roffset r0) + (rsize r0)) <= ((roffset r1) + (rsize r1)). + +(*Why axiom*) Lemma valid_included : + (forall (r0:trange), + (forall (r1:trange), + (forall (ta:(array Z)), + ((included r0 r1) -> ((valid ta r1) -> (valid ta r0)))))). +Admitted. + +(*Why logic*) Definition global : (array Z) -> Prop. +Admitted. + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/hoare_model.why frama-c-20111001+nitrogen+dfsg/src/wp/share/hoare_model.why --- frama-c-20110201+carbon+dfsg/src/wp/share/hoare_model.why 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/hoare_model.why 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,562 @@ +(* --- Headers for WHY --- *) + +include "bool.why" +include "integer.why" +include "real.why" +include "arrays.why" +include "divisions.why" +(* -------------------------------------------------------------------------- *) +(* --- ACSL Definitions --- *) +(* -------------------------------------------------------------------------- *) + +logic dummy : int -> prop +logic assigns : int -> prop + + +(* -------------------------------------------------------------------------- *) +(* --- Divisions enhanced specification --- *) +(* -------------------------------------------------------------------------- *) + +axiom positive_computer_div_div: + forall x,y:int. + x >0 -> y >0 -> computer_div(x,y) = math_div(x,y) + + +(**************************************************************************) +(*** Specification of Set as First Class Value ***) +(**************************************************************************) +(* From Figure 2.6 in ACSL:ANSI/ISO C Specification Language *) + +type 'a set + +logic empty : 'a set +logic singleton : 'a -> 'a set +logic range : int,int -> int set +logic union : 'a set , 'a set -> 'a set +logic inter : 'a set , 'a set -> 'a set +logic plus_int : int set, int set -> int set +logic subset : 'a set,'a set -> prop +logic range_inf: int -> int set +logic range_sup:int->int set +logic integers_set : int set +logic equiv : 'a set ,'a set -> prop +logic member : 'a,'a set -> prop + +axiom singleton_def : + forall x:'a. member (x, singleton(x)) + +axiom singleton_eq: + forall x,y:'a. member(x,singleton(y)) <-> x=y + +axiom union_member : + forall x:'a. forall s1,s2:'a set [member(x, union(s1,s2))]. + member(x, union(s1,s2)) <-> member(x,s1) or member(x,s2) + +axiom union_of_empty : + forall x:'a set [union(x,empty)]. union(x,empty) = x + +axiom inter_of_empty : + forall x:'a set [inter(x,empty)]. inter(x,empty) = empty + +axiom union_comm : + forall x,y:'a set. union(x,y) = union(y,x) + +axiom inter_comm : + forall x,y:'a set. inter(x,y) = inter(y,x) + +axiom inter_member : + forall x:'a. forall s1,s2:'a set [member(x,inter(s1,s2))]. + member(x,inter(s1,s2)) <-> member(x,s1) and member(x,s2) + +axiom plus_int_member_1: + forall sa,sb:int set. + forall a,b:int [member((a+b), plus_int(sa,sb))]. + member(a,sa) -> member(b,sb) -> + member((a+b), plus_int(sa,sb)) + +axiom plus_int_member_2: + forall sa,sb:int set. + forall c:int. + member(c,plus_int(sa,sb)) -> + exists a:int. exists b:int. + member(a,sa) and member(b,sb) and c=a+b + +axiom subset_empty : + forall sa:'a set. subset(empty,sa) + +axiom subset_sym: + forall sa:'a set. subset(sa,sa) + +axiom subset_trans : + forall sa,sb,sc: 'a set. + subset(sa,sb) -> + subset(sb,sc) -> + subset(sa,sc) + +axiom subset_def: + forall sa,sb:'a set [subset(sa,sb)]. + (forall a:'a. member(a,sa) -> member(a,sb)) <-> subset(sa,sb) + + +axiom range_def: + forall i,j,k:int. i <= k<= j <-> member (k,range(i,j)) + +axiom range_def1: + forall i,j,k:int. i <= k<= j -> member (k,range(i,j)) + +axiom range_def2: + forall i,j,k:int.member (k,range(i,j)) -> i <= k<= j + +axiom range_inf_def: (* range_inf(i) is [ i .. ] *) + forall i,k: int. i <= k <-> member (k,range_inf(i)) + +axiom range_sup_def: (* range_sup(j) is [ .. j ] *) + forall j,k: int. k <= j <-> member (k,range_sup(j)) + +axiom integers_set_def: + forall k:int. k >= 0 <-> member(k,integers_set) + +axiom equiv_def: + forall s1,s2:'a set [equiv(s1,s2)]. ( + (forall a:'a. member(a,s1) -> member(a,s2)) and + (forall b:'a. member(b,s2) -> member(b,s1))) <-> + equiv(s1,s2) + +axiom equiv_refl: + forall s:'a set. equiv(s,s) + +axiom equiv_sym: + forall s1,s2:'a set. equiv(s1,s2) -> equiv(s2,s1) + +axiom equiv_trans: + forall s1,s2,s3:'a set. + equiv(s1,s2) -> equiv(s2,s3) -> equiv(s1,s3) + + + +(**************************************************************************) +(*** Integers and Reals ***) +(**************************************************************************) + + +logic as_uint8 :int -> int +predicate is_uint8(x:int) = 0 <= x < 256 +axiom as_uint8_def : forall x:int. is_uint8(as_uint8(x)) +axiom as_uint8_involve : + forall x:int [as_uint8(as_uint8(x))]. as_uint8(as_uint8(x)) = as_uint8(x) +axiom is_as_uint8: forall x:int [as_uint8(x)]. is_uint8(x) -> as_uint8(x) = x + +logic as_sint8 :int -> int +predicate is_sint8(x:int) = -128 <= x < 128 +axiom as_sint8_def : forall x:int. is_sint8(as_sint8(x)) +axiom as_sint8_involve : + forall x:int [as_sint8(as_sint8(x))]. as_sint8(as_sint8(x)) = as_sint8(x) +axiom is_as_sint8: forall x:int[as_sint8(x)]. is_sint8(x) -> as_sint8(x) = x + + +logic as_uint16 :int -> int +predicate is_uint16(x:int) = 0 <= x < 65536 +axiom as_uint16_def : forall x:int. is_uint16(as_uint16(x)) +axiom as_uint16_involve : + forall x:int [as_uint16(as_uint16(x))]. + as_uint16(as_uint16(x)) = as_uint16(x) +axiom is_as_uint16: forall x:int [as_uint16(x)]. is_uint16(x) -> as_uint16(x) = x + +logic as_sint16 :int -> int +predicate is_sint16(x:int) = -32768 <= x < 32768 +axiom as_sint16_def : forall x:int. is_sint16(as_sint16(x)) +axiom as_sint16_involve : + forall x:int [as_sint16(as_sint16(x))]. + as_sint16(as_sint16(x)) = as_sint16(x) +axiom is_as_sint16: forall x:int [as_sint16(x)]. is_sint16(x) -> as_sint16(x) = x + + +logic as_uint32 :int -> int +predicate is_uint32(x:int) = 0 <= x < 4294967296 +axiom as_uint32_def : forall x:int. is_uint32(as_uint32(x)) +axiom as_uint32_involve : + forall x:int [as_uint32(as_uint32(x))]. + as_uint32(as_uint32(x)) = as_uint32(x) +axiom is_as_uint32: forall x:int [as_uint32(x)]. is_uint32(x) -> as_uint32(x) = x + +logic as_sint32 :int -> int +predicate is_sint32(x:int) = -2147483648 <= x < 2147483648 +axiom as_sint32_def : forall x:int. is_sint32(as_sint32(x)) +axiom as_sint32_involve : + forall x:int [as_sint32(as_sint32(x))]. + as_sint32(as_sint32(x)) = as_sint32(x) +axiom is_as_sint32: forall x:int [as_sint32(x)]. is_sint32(x) -> as_sint32(x) = x + + +logic as_uint64 :int -> int +predicate is_uint64(x:int) = 0 <= x < 18446744073709551616 +axiom as_uint64_def : forall x:int. is_uint64(as_uint64(x)) +axiom as_uint64_involve : + forall x:int [as_uint64(as_uint64(x))]. + as_uint64(as_uint64(x)) = as_uint64(x) +axiom is_as_uint64: forall x:int [as_uint64(x)]. is_uint64(x) -> as_uint64(x) = x + +logic as_sint64 :int -> int +predicate is_sint64(x:int) = -9223372036854775808 <= x < 9223372036854775808 +axiom as_sint64_def : forall x:int. is_sint64(as_sint64(x)) +axiom as_sint64_involve : + forall x:int [as_sint64(as_sint64(x))]. + as_sint64(as_sint64(x)) = as_sint64(x) +axiom is_as_sint64: forall x:int [as_sint64(x)]. is_sint64(x) -> as_sint64(x) = x + + +logic as_float16 :real -> real +logic is_float16 :real -> prop +axiom as_float16_def : forall x:real. is_float16(as_float16(x)) +axiom as_float16_involve : + forall x:real [as_float16(as_float16(x))]. + as_float16(as_float16(x)) = as_float16(x) +axiom is_as_float16: forall x:real [as_float16(x)]. is_float16(x) -> as_float16(x) = x + + +logic as_float32 :real -> real +logic is_float32 :real -> prop +axiom as_float32_def : forall x:real. is_float32(as_float32(x)) +axiom as_float32_involve : + forall x:real [as_float32(as_float32(x))]. + as_float32(as_float32(x)) = as_float32(x) +axiom is_as_float32: + forall x:real [as_float32(x)]. is_float32(x) -> as_float32(x) = x + + +logic as_float64 :real -> real +logic is_float64 :real -> prop +axiom as_float64_def : + forall x:real. is_float64(as_float64(x)) +axiom as_float64_involve : + forall x:real [as_float64(as_float64(x))]. + as_float64(as_float64(x)) = as_float64(x) +axiom is_as_float64: + forall x:real [as_float64(x)]. is_float64(x) -> as_float64(x) = x + + +logic as_float128 :real -> real +logic is_float128 :real -> prop +axiom as_float128_def : + forall x:real. is_float128(as_float128(x)) +axiom as_float128_involve : + forall x:real [as_float128(as_float128(x))]. + as_float128(as_float128(x)) = as_float128(x) +axiom is_as_float128: + forall x:real [as_float128(x)]. is_float128(x) -> as_float128(x) = x + +(**************************************************************************) +(*** Memory Data Type ***) +(**************************************************************************) + +type data + +logic data_of_uint8: int -> data +logic uint8_of_data: data -> int + +axiom is_uint8_of_data: + forall d:data [is_uint8(uint8_of_data(d))].is_uint8(uint8_of_data(d)) + +axiom uint8ofdata_dataofuint8: + forall x:int [data_of_uint8(x)]. + is_uint8(x) -> uint8_of_data(data_of_uint8(x)) = x + +logic data_of_sint8: int -> data +logic sint8_of_data: data -> int + +axiom is_sint8_of_data: + forall d:data [is_sint8(sint8_of_data(d))]. is_sint8(sint8_of_data(d)) + +axiom sint8ofdata_dataofsint8: + forall x:int [data_of_sint8(x)]. + is_sint8(x) -> sint8_of_data(data_of_sint8(x)) = x + +logic data_of_uint16: int -> data +logic uint16_of_data: data -> int + +axiom is_uint16_of_data: + forall d:data [is_uint16(uint16_of_data(d))]. is_uint16(uint16_of_data(d)) + +axiom uint16ofdata_dataofuint16: + forall x:int [uint16_of_data(data_of_uint16(x))]. + is_uint16(x) -> uint16_of_data(data_of_uint16(x)) = x + +logic data_of_sint16: int -> data +logic sint16_of_data: data -> int + +axiom is_sint16_of_data: + forall d:data [is_sint16(sint16_of_data(d))]. is_sint16(sint16_of_data(d)) + +axiom sint16ofdata_dataofsint16: + forall x:int [data_of_sint16(x)]. + is_sint16(x) -> sint16_of_data(data_of_sint16(x)) = x + +logic data_of_uint32: int -> data +logic uint32_of_data: data -> int + +axiom is_uint32_of_data: + forall d:data [is_uint32(uint32_of_data(d))]. is_uint32(uint32_of_data(d)) + +axiom uint32ofdata_dataofuint32: + forall x:int [data_of_uint32(x)]. + is_uint32(x) -> uint32_of_data(data_of_uint32(x)) = x + +logic data_of_sint32: int -> data +logic sint32_of_data: data -> int + +axiom is_sint32_of_data: + forall d:data [is_sint32(sint32_of_data(d))]. is_sint32(sint32_of_data(d)) + +axiom sint32ofdata_dataofsint32: + forall x:int [data_of_sint32(x)]. + is_sint32(x) -> sint32_of_data(data_of_sint32(x)) = x + +logic data_of_uint64: int -> data +logic uint64_of_data: data -> int + +axiom is_uint64_of_data: + forall d:data [is_uint64(uint64_of_data(d))]. is_uint64(uint64_of_data(d)) + +axiom uint64ofdata_dataofuint64: + forall x:int [data_of_uint64(x)]. + is_uint64(x) -> uint64_of_data(data_of_uint64(x)) = x + +logic data_of_sint64: int -> data +logic sint64_of_data: data -> int + +axiom is_sint64_of_data: + forall d:data [is_sint64(sint64_of_data(d))]. is_sint64(sint64_of_data(d)) + +axiom sint64ofdata_dataofsint64: + forall x:int [data_of_sint64(x)]. + is_sint64(x) -> sint64_of_data(data_of_sint64(x)) = x + +logic data_of_float16: real -> data +logic float16_of_data: data -> real + +axiom is_float16_of_data: + forall d:data [is_float16(float16_of_data(d))]. is_float16(float16_of_data(d)) +axiom float16ofdata_dataoffloat16: + forall x:real [data_of_float16(x)]. + is_float16(x) -> float16_of_data(data_of_float16(x)) = x + +logic data_of_float32: real -> data +logic float32_of_data: data -> real + +axiom is_float32_of_data: + forall d:data [is_float32(float32_of_data(d))]. is_float32(float32_of_data(d)) +axiom float32ofdata_dataoffloat32: + forall x:real [data_of_float32(x)]. + is_float32(x) -> float32_of_data(data_of_float32(x)) = x + +logic data_of_float64: real -> data +logic float64_of_data: data -> real + +axiom is_float64_of_data: + forall d:data [is_float64(float64_of_data(d))]. is_float64(float64_of_data(d)) +axiom float64ofdata_dataoffloat64: + forall x:real [data_of_float64(x)]. + is_float64(x) -> float64_of_data(data_of_float64(x)) = x + +logic data_of_float128: real -> data +logic float128_of_data: data -> real + +axiom is_float128_of_data: + forall d:data [is_float128(float128_of_data(d))]. is_float128(float128_of_data(d)) +axiom float128ofdata_dataoffloat128: + forall x:real [data_of_float128(x)]. + is_float128(x) -> float128_of_data(data_of_float128(x)) = x + + +(**************************************************************************) +(*** Update of Arrays over a set of Index ***) +(**************************************************************************) + + +logic set_range_index: + 'a farray (* array*), int set (* set of index*), int (*uniq key*) -> 'a farray + +axiom set_range_def : + forall t: 'a farray. + forall rg: int set. + forall k:int. + forall i:int [access(set_range_index(t,rg,k),i)]. + not (member(i,rg)) -> + access(set_range_index(t,rg,k),i) = access(t,i) + +(**************************************************************************) +(*** Bitwise Operations ***) +(**************************************************************************) + +logic bnot: int -> int +logic band: int,int -> int +logic bor: int,int -> int +logic bxor: int,int -> int +logic lshift: int,int -> int +logic rshift: int,int -> int + +logic int_not: int -> int +logic int_and: int,int -> int +logic int_or: int,int -> int +logic int_xor: int,int -> int +logic int_lsh: int,int -> int +logic int_rshs: int,int -> int +logic int_rshu: int,int -> int +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2010 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* INRIA (Institut National de Recherche en Informatique et en *) +(* Automatique) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version v2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(*TODO : waiting for pair theory in alt-ergo to use them here ! *) + +type pointer + +logic ptr: int(*base*), int(*offset*) -> pointer +logic base : pointer -> int +logic offset : pointer -> int + +axiom base_def: + forall b,d:int [base(ptr(b,d))]. base(ptr(b,d)) = b + +axiom offset_def: + forall b,d:int [offset(ptr(b,d))]. offset(ptr(b,d)) = d + + +logic minus_ptr: pointer,pointer -> int + +axiom minus_ptr_def: + forall p1,p2:pointer [minus_ptr(p1,p2)]. + base(p1) =base(p2) -> + minus_ptr(p1,p2) = offset(p1) - offset(p2) + +predicate eq_ptr (a:pointer, b:pointer) = + base(a) = base(b) and offset(a) = offset(b) + +function eq_ptr_bool (a:pointer, b:pointer): bool = + bool_and (eq_int_bool(base(a), base(b)), + eq_int_bool(offset(a),offset(b))) + + +predicate lt_ptr (a:pointer, b:pointer) = + base(a) = base(b) and + offset(a) < offset(b) + +function lt_ptr_bool (a:pointer, b:pointer): bool = + bool_and (eq_int_bool(base(a), base(b)), + lt_int_bool(offset(a),offset(b))) + + +predicate le_ptr (a:pointer, b:pointer) = + base(a) = base(b) and + offset(a) <= offset(b) + +function le_ptr_bool (a:pointer, b:pointer): bool = + bool_and (eq_int_bool(base(a), base(b)), + le_int_bool(offset(a),offset(b))) + + +function shift (p:pointer, i:int): pointer = + ptr(base(p),offset(p)+i) + +axiom shift_0: + forall p:pointer [shift(p,0)]. shift(p,0) = p + +axiom shift_shift: + forall p:pointer. forall i,j:int [shift(shift(p,i),j)]. + shift(shift(p,i),j) = shift(p,i+j) + + + +type trange + +logic range_ptr : int(*base*) , int (*offset*), int (*size*) -> trange + +logic rbase : trange -> int +logic roffset : trange -> int +logic rsize : trange -> int + +axiom rbase_def : + forall b,d,sz:int [rbase(range_ptr(b,d,sz))]. + rbase(range_ptr(b,d,sz)) = b + +axiom roffset_def : + forall b,d,sz:int [roffset(range_ptr(b,d,sz))]. + roffset(range_ptr(b,d,sz)) = d + +axiom rsize_def : + forall b,d,sz:int [rsize(range_ptr(b,d,sz))]. + rsize(range_ptr(b,d,sz)) = sz + +function range_of_ptr (p:pointer,sz:int) :trange = + range_ptr(base(p),offset(p),sz) + +axiom rbase_of_ptr : + forall p:pointer. forall sz:int [rbase(range_of_ptr(p,sz))]. + rbase(range_of_ptr(p,sz)) = base(p) + +axiom roffset_of_ptr : + forall p:pointer. forall sz:int [roffset(range_of_ptr(p,sz))]. + roffset(range_of_ptr(p,sz)) = offset(p) + +axiom rsize_of_ptr : + forall p:pointer. forall sz:int [rsize(range_of_ptr(p,sz))]. + rsize(range_of_ptr(p,sz)) = sz + +function range_of_ptr_range (p:pointer,d:int,sz:int) : trange = + range_ptr(base(p),offset(p)+d,sz) + +axiom rbase_of_ptr_range : + forall p:pointer. forall d,sz:int [rbase(range_of_ptr_range(p,d,sz))]. + rbase(range_of_ptr_range(p,d,sz)) = base(p) + +axiom roffset_of_ptr_range : + forall p:pointer. forall d,sz:int [roffset(range_of_ptr_range(p,d,sz))]. + roffset(range_of_ptr_range(p,d,sz)) = offset(p)+d + +axiom rsize_of_ptr_range : + forall p:pointer. forall d,sz:int [rsize(range_of_ptr_range(p,d,sz))]. + rsize(range_of_ptr_range(p,d,sz)) = sz + + +predicate separated (r0:trange, r1:trange) = + rbase(r0) = rbase(r1) -> + roffset(r0)+ rsize(r0) <= roffset(r1) or + roffset(r0) >= roffset(r1) + rsize(r1) + + +predicate valid (ta:int farray, r : trange) = + rsize(r) > 0 -> + ( 0 <= roffset(r) and roffset(r) + rsize(r) <= access(ta,rbase(r))) + +predicate included(r0:trange, r1:trange) = + rbase(r0) = rbase(r1) and + roffset(r0) >= roffset(r1) and + roffset(r0) + rsize(r0) <= roffset(r1) + rsize(r1) + +axiom valid_included : + forall r0,r1:trange. + forall ta: int farray. + included(r0,r1) -> valid(ta,r1) -> valid(ta,r0) + +logic global : int farray -> prop + + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/runtime_ergo.why frama-c-20111001+nitrogen+dfsg/src/wp/share/runtime_ergo.why --- frama-c-20110201+carbon+dfsg/src/wp/share/runtime_ergo.why 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/runtime_ergo.why 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,1514 @@ +logic eq_unit : unit,unit -> prop + +logic neq_unit : unit,unit -> prop + +logic eq_bool : bool,bool -> prop + +logic neq_bool : bool,bool -> prop + +logic lt_int : int,int -> prop + +logic le_int : int,int -> prop + +logic gt_int : int,int -> prop + +logic ge_int : int,int -> prop + +logic eq_int : int,int -> prop + +logic neq_int : int,int -> prop + +logic add_int : int,int -> int + +logic sub_int : int,int -> int + +logic mul_int : int,int -> int + +logic neg_int : int -> int + +predicate zwf_zero(a:int,b:int) = ((0<=b) and (a<b)) + +logic bool_and : bool,bool -> bool + +logic bool_or : bool,bool -> bool + +logic bool_xor : bool,bool -> bool + +logic bool_not : bool -> bool + +axiom bool_and_def : (forall a:bool.(forall b:bool. +((bool_and(a,b)=true) <-> ((a=true) and (b=true))))) + +axiom bool_or_def : (forall a:bool.(forall b:bool. +((bool_or(a,b)=true) <-> ((a=true) or (b=true))))) + +axiom bool_xor_def : (forall a:bool.(forall b:bool. +((bool_xor(a,b)=true) <-> (a<>b)))) + +axiom bool_not_def : (forall a:bool. +((bool_not(a)=true) <-> (a=false))) + +logic ite : bool,'a1,'a1 -> 'a1 + +axiom ite_true : (forall x:'a1.(forall y:'a1. +(ite(true,x,y)=x))) + +axiom ite_false : (forall x:'a1.(forall y:'a1. +(ite(false,x,y)=y))) + +logic lt_int_bool : int,int -> bool + +logic le_int_bool : int,int -> bool + +logic gt_int_bool : int,int -> bool + +logic ge_int_bool : int,int -> bool + +logic eq_int_bool : int,int -> bool + +logic neq_int_bool : int,int -> bool + +axiom lt_int_bool_axiom : (forall x:int.(forall y:int. +((lt_int_bool(x,y)=true) <-> (x<y)))) + +axiom le_int_bool_axiom : (forall x:int.(forall y:int. +((le_int_bool(x,y)=true) <-> (x<=y)))) + +axiom gt_int_bool_axiom : (forall x:int.(forall y:int. +((gt_int_bool(x,y)=true) <-> (x>y)))) + +axiom ge_int_bool_axiom : (forall x:int.(forall y:int. +((ge_int_bool(x,y)=true) <-> (x>=y)))) + +axiom eq_int_bool_axiom : (forall x:int.(forall y:int. +((eq_int_bool(x,y)=true) <-> (x=y)))) + +axiom neq_int_bool_axiom : (forall x:int.(forall y:int. +((neq_int_bool(x,y)=true) <-> (x<>y)))) + +logic abs_int : int -> int + +axiom abs_int_pos : (forall x:int. +((x>=0) -> (abs_int(x)=x))) + +axiom abs_int_neg : (forall x:int. +((x<=0) -> (abs_int(x)=(-x)))) + +logic int_max : int,int -> int + +logic int_min : int,int -> int + +axiom int_max_is_ge : (forall x:int.(forall y:int. +((int_max(x,y)>=x) and (int_max(x,y)>=y)))) + +axiom int_max_is_some : (forall x:int.(forall y:int. +((int_max(x,y)=x) or (int_max(x,y)=y)))) + +axiom int_min_is_le : (forall x:int.(forall y:int. +((int_min(x,y)<=x) and (int_min(x,y)<=y)))) + +axiom int_min_is_some : (forall x:int.(forall y:int. +((int_min(x,y)=x) or (int_min(x,y)=y)))) + +logic lt_real : real,real -> prop + +logic le_real : real,real -> prop + +logic gt_real : real,real -> prop + +logic ge_real : real,real -> prop + +logic eq_real : real,real -> prop + +logic neq_real : real,real -> prop + +logic add_real : real,real -> real + +logic sub_real : real,real -> real + +logic mul_real : real,real -> real + +logic div_real : real,real -> real + +logic neg_real : real -> real + +logic real_of_int : int -> real + +axiom real_of_int_zero : (real_of_int(0)=0.0) + +axiom real_of_int_one : (real_of_int(1)=1.0) + +axiom real_of_int_add : (forall x:int.(forall y:int. +(real_of_int((x+y))=(real_of_int(x)+real_of_int(y))))) + +axiom real_of_int_sub : (forall x:int.(forall y:int. +(real_of_int((x-y))=(real_of_int(x)-real_of_int(y))))) + +logic truncate_real_to_int : real -> int + +axiom truncate_down_pos : (forall x:real. +((x>=0.0) -> ((real_of_int(truncate_real_to_int(x))<=x) and (x<real_of_int((truncate_real_to_int(x)+1)))))) + +axiom truncate_up_neg : (forall x:real. +((x<=0.0) -> ((real_of_int((truncate_real_to_int(x)-1))<x) and (x<=real_of_int(truncate_real_to_int(x)))))) + +logic floor_real_to_int : real -> int + +logic ceil_real_to_int : real -> int + +logic lt_real_bool : real,real -> bool + +logic le_real_bool : real,real -> bool + +logic gt_real_bool : real,real -> bool + +logic ge_real_bool : real,real -> bool + +logic eq_real_bool : real,real -> bool + +logic neq_real_bool : real,real -> bool + +axiom lt_real_bool_axiom : (forall x:real.(forall y:real. +((lt_real_bool(x,y)=true) <-> (x<y)))) + +axiom le_real_bool_axiom : (forall x:real.(forall y:real. +((le_real_bool(x,y)=true) <-> (x<=y)))) + +axiom gt_real_bool_axiom : (forall x:real.(forall y:real. +((gt_real_bool(x,y)=true) <-> (x>y)))) + +axiom ge_real_bool_axiom : (forall x:real.(forall y:real. +((ge_real_bool(x,y)=true) <-> (x>=y)))) + +axiom eq_real_bool_axiom : (forall x:real.(forall y:real. +((eq_real_bool(x,y)=true) <-> (x=y)))) + +axiom neq_real_bool_axiom : (forall x:real.(forall y:real. +((neq_real_bool(x,y)=true) <-> (x<>y)))) + +logic real_max : real,real -> real + +logic real_min : real,real -> real + +axiom real_max_is_ge : (forall x:real.(forall y:real. +((real_max(x,y)>=x) and (real_max(x,y)>=y)))) + +axiom real_max_is_some : (forall x:real.(forall y:real. +((real_max(x,y)=x) or (real_max(x,y)=y)))) + +axiom real_min_is_le : (forall x:real.(forall y:real. +((real_min(x,y)<=x) and (real_min(x,y)<=y)))) + +axiom real_min_is_some : (forall x:real.(forall y:real. +((real_min(x,y)=x) or (real_min(x,y)=y)))) + +function sqr_real(x:real) : real = (x*x) + +logic sqrt_real : real -> real + +axiom sqrt_pos : (forall x:real. +((x>=0.0) -> (sqrt_real(x)>=0.0))) + +axiom sqrt_sqr : (forall x:real. +((x>=0.0) -> (sqr_real(sqrt_real(x))=x))) + +axiom sqr_sqrt : (forall x:real. +((x>=0.0) -> (sqrt_real((x*x))=x))) + +logic pow_real : real,real -> real + +logic abs_real : real -> real + +axiom abs_real_pos : (forall x:real[abs_real(x)]. +((x>=0.0) -> (abs_real(x)=x))) + +axiom abs_real_neg : (forall x:real[abs_real(x)]. +((x<=0.0) -> (abs_real(x)=(-x)))) + +logic exp : real -> real + +logic log : real -> real + +logic log10 : real -> real + +axiom log_exp : (forall x:real. +(log(exp(x))=x)) + +axiom exp_log : (forall x:real. +((x>0.0) -> (exp(log(x))=x))) + +logic cos : real -> real + +logic sin : real -> real + +logic tan : real -> real + +logic pi : real + +logic cosh : real -> real + +logic sinh : real -> real + +logic tanh : real -> real + +logic acos : real -> real + +logic asin : real -> real + +logic atan : real -> real + +logic atan2 : real,real -> real + +logic hypot : real,real -> real + +axiom prod_pos : (forall x:real.(forall y:real. +((((x>0.0) and (y>0.0)) -> ((x*y)>0.0)) and (((x<0.0) and (y<0.0)) -> ((x*y)>0.0))))) + +axiom abs_minus : (forall x:real. +(abs_real((-x))=abs_real(x))) + + +logic access : 'a1 farray,int -> 'a1 + +logic update : 'a1 farray,int,'a1 -> 'a1 farray + +axiom access_update : (forall a:'a1 farray.(forall i:int.(forall v:'a1. +(a[i<-v][i]=v)))) + +axiom access_update_neq : (forall a:'a1 farray.(forall i:int.(forall j:int. +(forall v:'a1. +((i<>j) -> (a[i<-v][j]=a[j])))))) + +logic array_length : 'a1 farray -> int + +predicate sorted_array(t:int farray,i:int,j:int) = (forall k1:int. +(forall k2:int. +((((i<=k1) and (k1<=k2)) and (k2<=j)) -> (t[k1]<=t[k2])))) + +predicate exchange(a1:'a1 farray,a2:'a1 farray,i:int,j:int) = ((array_length(a1)=array_length(a2)) and ((a1[i]=a2[j]) and ((a2[i]=a1[j]) and ( +forall k:int. +(((k<>i) and (k<>j)) -> (a1[k]=a2[k])))))) + +logic permut : 'a1 farray,'a1 farray,int,int -> prop + +axiom permut_refl : (forall t:'a1 farray.(forall l:int.(forall u:int. +permut(t,t,l, +u)))) + +axiom permut_sym : (forall t1:'a1 farray.(forall t2:'a1 farray.(forall l:int. +(forall u:int.(permut(t1,t2,l,u) -> permut(t2,t1,l, +u)))))) + +axiom permut_trans : (forall t1:'a1 farray.(forall t2:'a1 farray. +(forall t3:'a1 farray.(forall l:int.(forall u:int.(permut(t1,t2,l, +u) -> (permut(t2,t3,l,u) -> permut(t1,t3,l, +u)))))))) + +axiom permut_exchange : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l:int.(forall u:int.(forall i:int.(forall j:int. +(((l<=i) and (i<=u)) -> (((l<=j) and (j<=u)) -> (exchange(a1,a2,i, +j) -> permut(a1,a2,l, +u)))))))))) + +axiom exchange_upd : (forall a:'a1 farray.(forall i:int.(forall j:int. +exchange(a,a[i<-a[j]][j<-a[i]],i, +j)))) + +axiom permut_weakening : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l1:int.(forall r1:int.(forall l2:int.(forall r2:int. +((((l1<=l2) and (l2<=r2)) and (r2<=r1)) -> (permut(a1,a2,l2,r2) -> permut(a1, +a2,l1, +r1))))))))) + +axiom permut_eq : (forall a1:'a1 farray.(forall a2:'a1 farray.(forall l:int. +(forall u:int.((l<=u) -> (permut(a1,a2,l,u) -> (forall i:int. +(((i<l) or (u<i)) -> (a2[i]=a1[i]))))))))) + +predicate permutation(a1:'a1 farray,a2:'a1 farray) = permut(a1,a2,0, +(array_length(a1)-1)) + +axiom array_length_update : (forall a:'a1 farray.(forall i:int.(forall v:'a1. +(array_length(a[i<-v])=array_length(a))))) + +axiom permut_array_length : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l:int.(forall u:int.(permut(a1,a2,l, +u) -> (array_length(a1)=array_length(a2))))))) + +logic computer_div : int,int -> int + +logic computer_mod : int,int -> int + +logic math_div : int,int -> int + +logic math_mod : int,int -> int + +axiom math_div_mod : (forall x:int.(forall y:int. +((y<>0) -> (x=((y*math_div(x,y))+math_mod(x,y)))))) + +axiom math_mod_bound : (forall x:int.(forall y:int. +((y<>0) -> ((0<=math_mod(x,y)) and (math_mod(x,y)<abs_int(y)))))) + +axiom computer_div_mod : (forall x:int. +(forall y:int[computer_div(x,y),computer_mod(x,y)]. +((y<>0) -> (x=((y*computer_div(x,y))+computer_mod(x,y)))))) + +axiom computer_div_bound : (forall x:int.(forall y:int. +(((x>=0) and (y>0)) -> ((0<=computer_div(x,y)) and (computer_div(x,y)<=x))))) + +axiom computer_mod_bound : (forall x:int.(forall y:int. +((y<>0) -> (abs_int(computer_mod(x,y))<abs_int(y))))) + +axiom computer_mod_sign_pos : (forall x:int.(forall y:int. +(((x>=0) and (y<>0)) -> (computer_mod(x,y)>=0)))) + +axiom computer_mod_sign_neg : (forall x:int.(forall y:int. +(((x<=0) and (y<>0)) -> (computer_mod(x,y)<=0)))) + +axiom computer_rounds_toward_zero : (forall x:int.(forall y:int. +((y<>0) -> (abs_int((computer_div(x,y)*y))<=abs_int(x))))) + +logic dummy : int -> prop + +logic assigns : int -> prop + +axiom positive_computer_div_div : (forall x:int.(forall y:int. +((x>0) -> ((y>0) -> (computer_div(x,y)=math_div(x,y)))))) + +type 'a set + +logic empty : 'a1 set + +logic singleton : 'a1 -> 'a1 set + +logic range : int,int -> int set + +logic union : 'a1 set,'a1 set -> 'a1 set + +logic inter : 'a1 set,'a1 set -> 'a1 set + +logic plus_int : int set,int set -> int set + +logic subset : 'a1 set,'a1 set -> prop + +logic range_inf : int -> int set + +logic range_sup : int -> int set + +logic integers_set : int set + +logic equiv : 'a1 set,'a1 set -> prop + +logic member : 'a1,'a1 set -> prop + +axiom singleton_def : (forall x:'a1.member(x, +singleton(x))) + +axiom singleton_eq : (forall x:'a1.(forall y:'a1.(member(x, +singleton(y)) <-> (x=y)))) + +axiom union_member : (forall x:'a1.(forall s1:'a1 set. +(forall s2:'a1 set[member(x,union(s1,s2))].(member(x, +union(s1,s2)) <-> (member(x,s1) or member(x, +s2)))))) + +axiom union_of_empty : (forall x:'a1 set[union(x,empty)]. +(union(x,empty)=x)) + +axiom inter_of_empty : (forall x:'a1 set[inter(x,empty)]. +(inter(x,empty)=empty)) + +axiom union_comm : (forall x:'a1 set.(forall y:'a1 set. +(union(x,y)=union(y,x)))) + +axiom inter_comm : (forall x:'a1 set.(forall y:'a1 set. +(inter(x,y)=inter(y,x)))) + +axiom inter_member : (forall x:'a1.(forall s1:'a1 set. +(forall s2:'a1 set[member(x,inter(s1,s2))].(member(x, +inter(s1,s2)) <-> (member(x,s1) and member(x, +s2)))))) + +axiom plus_int_member_1 : (forall sa:int set.(forall sb:int set. +(forall a:int.(forall b:int[member((a+b),plus_int(sa,sb))].(member(a, +sa) -> (member(b,sb) -> member((a+b), +plus_int(sa,sb)))))))) + +axiom plus_int_member_2 : (forall sa:int set.(forall sb:int set. +(forall c:int.(member(c,plus_int(sa,sb)) -> (exists a:int.(exists b:int. +(member(a,sa) and (member(b, +sb) and (c=(a+b)))))))))) + +axiom subset_empty : (forall sa:'a1 set.subset(empty, +sa)) + +axiom subset_sym : (forall sa:'a1 set.subset(sa, +sa)) + +axiom subset_trans : (forall sa:'a1 set.(forall sb:'a1 set. +(forall sc:'a1 set.(subset(sa,sb) -> (subset(sb,sc) -> subset(sa, +sc)))))) + +axiom subset_def : (forall sa:'a1 set.(forall sb:'a1 set[subset(sa,sb)]. +((forall a:'a1.(member(a,sa) -> member(a,sb))) <-> subset(sa, +sb)))) + +axiom range_def : (forall i:int.(forall j:int.(forall k:int. +(((i<=k) and (k<=j)) <-> member(k, +range(i,j)))))) + +axiom range_def1 : (forall i:int.(forall j:int.(forall k:int. +(((i<=k) and (k<=j)) -> member(k, +range(i,j)))))) + +axiom range_def2 : (forall i:int.(forall j:int.(forall k:int.(member(k, +range(i,j)) -> ((i<=k) and (k<=j)))))) + +axiom range_inf_def : (forall i:int.(forall k:int.((i<=k) <-> member(k, +range_inf(i))))) + +axiom range_sup_def : (forall j:int.(forall k:int.((k<=j) <-> member(k, +range_sup(j))))) + +axiom integers_set_def : (forall k:int.((k>=0) <-> member(k, +integers_set))) + +axiom equiv_def : (forall s1:'a1 set.(forall s2:'a1 set[equiv(s1,s2)]. +(((forall a:'a1.(member(a,s1) -> member(a,s2))) and (forall b:'a1.(member(b, +s2) -> member(b,s1)))) <-> equiv(s1, +s2)))) + +axiom equiv_refl : (forall s:'a1 set.equiv(s, +s)) + +axiom equiv_sym : (forall s1:'a1 set.(forall s2:'a1 set.(equiv(s1, +s2) -> equiv(s2, +s1)))) + +axiom equiv_trans : (forall s1:'a1 set.(forall s2:'a1 set.(forall s3:'a1 set. +(equiv(s1,s2) -> (equiv(s2,s3) -> equiv(s1, +s3)))))) + +logic as_uint8 : int -> int + +predicate is_uint8(x:int) = ((0<=x) and (x<256)) + +axiom as_uint8_def : (forall x:int. +is_uint8(as_uint8(x))) + +axiom as_uint8_involve : (forall x:int[as_uint8(as_uint8(x))]. +(as_uint8(as_uint8(x))=as_uint8(x))) + +axiom is_as_uint8 : (forall x:int[as_uint8(x)]. +(is_uint8(x) -> (as_uint8(x)=x))) + +logic as_sint8 : int -> int + +predicate is_sint8(x:int) = (((-128)<=x) and (x<128)) + +axiom as_sint8_def : (forall x:int. +is_sint8(as_sint8(x))) + +axiom as_sint8_involve : (forall x:int[as_sint8(as_sint8(x))]. +(as_sint8(as_sint8(x))=as_sint8(x))) + +axiom is_as_sint8 : (forall x:int[as_sint8(x)]. +(is_sint8(x) -> (as_sint8(x)=x))) + +logic as_uint16 : int -> int + +predicate is_uint16(x:int) = ((0<=x) and (x<65536)) + +axiom as_uint16_def : (forall x:int. +is_uint16(as_uint16(x))) + +axiom as_uint16_involve : (forall x:int[as_uint16(as_uint16(x))]. +(as_uint16(as_uint16(x))=as_uint16(x))) + +axiom is_as_uint16 : (forall x:int[as_uint16(x)]. +(is_uint16(x) -> (as_uint16(x)=x))) + +logic as_sint16 : int -> int + +predicate is_sint16(x:int) = (((-32768)<=x) and (x<32768)) + +axiom as_sint16_def : (forall x:int. +is_sint16(as_sint16(x))) + +axiom as_sint16_involve : (forall x:int[as_sint16(as_sint16(x))]. +(as_sint16(as_sint16(x))=as_sint16(x))) + +axiom is_as_sint16 : (forall x:int[as_sint16(x)]. +(is_sint16(x) -> (as_sint16(x)=x))) + +logic as_uint32 : int -> int + +predicate is_uint32(x:int) = ((0<=x) and (x<4294967296)) + +axiom as_uint32_def : (forall x:int. +is_uint32(as_uint32(x))) + +axiom as_uint32_involve : (forall x:int[as_uint32(as_uint32(x))]. +(as_uint32(as_uint32(x))=as_uint32(x))) + +axiom is_as_uint32 : (forall x:int[as_uint32(x)]. +(is_uint32(x) -> (as_uint32(x)=x))) + +logic as_sint32 : int -> int + +predicate is_sint32(x:int) = (((-2147483648)<=x) and (x<2147483648)) + +axiom as_sint32_def : (forall x:int. +is_sint32(as_sint32(x))) + +axiom as_sint32_involve : (forall x:int[as_sint32(as_sint32(x))]. +(as_sint32(as_sint32(x))=as_sint32(x))) + +axiom is_as_sint32 : (forall x:int[as_sint32(x)]. +(is_sint32(x) -> (as_sint32(x)=x))) + +logic as_uint64 : int -> int + +predicate is_uint64(x:int) = ((0<=x) and (x<18446744073709551616)) + +axiom as_uint64_def : (forall x:int. +is_uint64(as_uint64(x))) + +axiom as_uint64_involve : (forall x:int[as_uint64(as_uint64(x))]. +(as_uint64(as_uint64(x))=as_uint64(x))) + +axiom is_as_uint64 : (forall x:int[as_uint64(x)]. +(is_uint64(x) -> (as_uint64(x)=x))) + +logic as_sint64 : int -> int + +predicate is_sint64(x:int) = (((-9223372036854775808)<=x) and (x<9223372036854775808)) + +axiom as_sint64_def : (forall x:int. +is_sint64(as_sint64(x))) + +axiom as_sint64_involve : (forall x:int[as_sint64(as_sint64(x))]. +(as_sint64(as_sint64(x))=as_sint64(x))) + +axiom is_as_sint64 : (forall x:int[as_sint64(x)]. +(is_sint64(x) -> (as_sint64(x)=x))) + +logic as_float16 : real -> real + +logic is_float16 : real -> prop + +axiom as_float16_def : (forall x:real. +is_float16(as_float16(x))) + +axiom as_float16_involve : (forall x:real[as_float16(as_float16(x))]. +(as_float16(as_float16(x))=as_float16(x))) + +axiom is_as_float16 : (forall x:real[as_float16(x)]. +(is_float16(x) -> (as_float16(x)=x))) + +logic as_float32 : real -> real + +logic is_float32 : real -> prop + +axiom as_float32_def : (forall x:real. +is_float32(as_float32(x))) + +axiom as_float32_involve : (forall x:real[as_float32(as_float32(x))]. +(as_float32(as_float32(x))=as_float32(x))) + +axiom is_as_float32 : (forall x:real[as_float32(x)]. +(is_float32(x) -> (as_float32(x)=x))) + +logic as_float64 : real -> real + +logic is_float64 : real -> prop + +axiom as_float64_def : (forall x:real. +is_float64(as_float64(x))) + +axiom as_float64_involve : (forall x:real[as_float64(as_float64(x))]. +(as_float64(as_float64(x))=as_float64(x))) + +axiom is_as_float64 : (forall x:real[as_float64(x)]. +(is_float64(x) -> (as_float64(x)=x))) + +logic as_float128 : real -> real + +logic is_float128 : real -> prop + +axiom as_float128_def : (forall x:real. +is_float128(as_float128(x))) + +axiom as_float128_involve : (forall x:real[as_float128(as_float128(x))]. +(as_float128(as_float128(x))=as_float128(x))) + +axiom is_as_float128 : (forall x:real[as_float128(x)]. +(is_float128(x) -> (as_float128(x)=x))) + +type data + +logic data_of_uint8 : int -> data + +logic uint8_of_data : data -> int + +axiom is_uint8_of_data : (forall d:data[is_uint8(uint8_of_data(d))]. +is_uint8(uint8_of_data(d))) + +axiom uint8ofdata_dataofuint8 : (forall x:int[data_of_uint8(x)]. +(is_uint8(x) -> (uint8_of_data(data_of_uint8(x))=x))) + +logic data_of_sint8 : int -> data + +logic sint8_of_data : data -> int + +axiom is_sint8_of_data : (forall d:data[is_sint8(sint8_of_data(d))]. +is_sint8(sint8_of_data(d))) + +axiom sint8ofdata_dataofsint8 : (forall x:int[data_of_sint8(x)]. +(is_sint8(x) -> (sint8_of_data(data_of_sint8(x))=x))) + +logic data_of_uint16 : int -> data + +logic uint16_of_data : data -> int + +axiom is_uint16_of_data : (forall d:data[is_uint16(uint16_of_data(d))]. +is_uint16(uint16_of_data(d))) + +axiom uint16ofdata_dataofuint16 : (forall x:int[uint16_of_data(data_of_uint16(x))]. +(is_uint16(x) -> (uint16_of_data(data_of_uint16(x))=x))) + +logic data_of_sint16 : int -> data + +logic sint16_of_data : data -> int + +axiom is_sint16_of_data : (forall d:data[is_sint16(sint16_of_data(d))]. +is_sint16(sint16_of_data(d))) + +axiom sint16ofdata_dataofsint16 : (forall x:int[data_of_sint16(x)]. +(is_sint16(x) -> (sint16_of_data(data_of_sint16(x))=x))) + +logic data_of_uint32 : int -> data + +logic uint32_of_data : data -> int + +axiom is_uint32_of_data : (forall d:data[is_uint32(uint32_of_data(d))]. +is_uint32(uint32_of_data(d))) + +axiom uint32ofdata_dataofuint32 : (forall x:int[data_of_uint32(x)]. +(is_uint32(x) -> (uint32_of_data(data_of_uint32(x))=x))) + +logic data_of_sint32 : int -> data + +logic sint32_of_data : data -> int + +axiom is_sint32_of_data : (forall d:data[is_sint32(sint32_of_data(d))]. +is_sint32(sint32_of_data(d))) + +axiom sint32ofdata_dataofsint32 : (forall x:int[data_of_sint32(x)]. +(is_sint32(x) -> (sint32_of_data(data_of_sint32(x))=x))) + +logic data_of_uint64 : int -> data + +logic uint64_of_data : data -> int + +axiom is_uint64_of_data : (forall d:data[is_uint64(uint64_of_data(d))]. +is_uint64(uint64_of_data(d))) + +axiom uint64ofdata_dataofuint64 : (forall x:int[data_of_uint64(x)]. +(is_uint64(x) -> (uint64_of_data(data_of_uint64(x))=x))) + +logic data_of_sint64 : int -> data + +logic sint64_of_data : data -> int + +axiom is_sint64_of_data : (forall d:data[is_sint64(sint64_of_data(d))]. +is_sint64(sint64_of_data(d))) + +axiom sint64ofdata_dataofsint64 : (forall x:int[data_of_sint64(x)]. +(is_sint64(x) -> (sint64_of_data(data_of_sint64(x))=x))) + +logic data_of_float16 : real -> data + +logic float16_of_data : data -> real + +axiom is_float16_of_data : (forall d:data[is_float16(float16_of_data(d))]. +is_float16(float16_of_data(d))) + +axiom float16ofdata_dataoffloat16 : (forall x:real[data_of_float16(x)]. +(is_float16(x) -> (float16_of_data(data_of_float16(x))=x))) + +logic data_of_float32 : real -> data + +logic float32_of_data : data -> real + +axiom is_float32_of_data : (forall d:data[is_float32(float32_of_data(d))]. +is_float32(float32_of_data(d))) + +axiom float32ofdata_dataoffloat32 : (forall x:real[data_of_float32(x)]. +(is_float32(x) -> (float32_of_data(data_of_float32(x))=x))) + +logic data_of_float64 : real -> data + +logic float64_of_data : data -> real + +axiom is_float64_of_data : (forall d:data[is_float64(float64_of_data(d))]. +is_float64(float64_of_data(d))) + +axiom float64ofdata_dataoffloat64 : (forall x:real[data_of_float64(x)]. +(is_float64(x) -> (float64_of_data(data_of_float64(x))=x))) + +logic data_of_float128 : real -> data + +logic float128_of_data : data -> real + +axiom is_float128_of_data : (forall d:data[is_float128(float128_of_data(d))]. +is_float128(float128_of_data(d))) + +axiom float128ofdata_dataoffloat128 : (forall x:real[data_of_float128(x)]. +(is_float128(x) -> (float128_of_data(data_of_float128(x))=x))) + +logic set_range_index : 'a1 farray,int set,int -> 'a1 farray + +axiom set_range_def : (forall t:'a1 farray.(forall rg:int set.(forall k:int. +(forall i:int[set_range_index(t,rg,k)[i]].((not member(i, +rg)) -> (set_range_index(t,rg,k)[i]=t[i])))))) + +logic bnot : int -> int + +logic band : int,int -> int + +logic bor : int,int -> int + +logic bxor : int,int -> int + +logic lshift : int,int -> int + +logic rshift : int,int -> int + +logic int_not : int -> int + +logic int_and : int,int -> int + +logic int_or : int,int -> int + +logic int_xor : int,int -> int + +logic int_lsh : int,int -> int + +logic int_rshs : int,int -> int + +logic int_rshu : int,int -> int + +type 'a format + +logic format_size : 'a1 format -> int + +logic is_in_format : 'a1 format,'a1 -> prop + +logic signed_format : int format -> bool + +logic uint8_format : int format + +axiom uint8_format_size : (format_size(uint8_format)=8) + +axiom uint8_format_sign : (signed_format(uint8_format)=false) + +logic sint8_format : int format + +axiom sint8_format_size : (format_size(sint8_format)=8) + +axiom sint8_format_sign : (signed_format(sint8_format)=true) + +logic uint16_format : int format + +axiom uint16_format_size : (format_size(uint16_format)=16) + +axiom uint16_format_sign : (signed_format(uint16_format)=false) + +logic sint16_format : int format + +axiom sint16_format_size : (format_size(sint16_format)=16) + +axiom sint16_format_sign : (signed_format(sint16_format)=true) + +logic uint32_format : int format + +axiom uint32_format_size : (format_size(uint32_format)=32) + +axiom uint32_format_sign : (signed_format(uint32_format)=false) + +logic sint32_format : int format + +axiom sint32_format_size : (format_size(sint32_format)=32) + +axiom sint32_format_sign : (signed_format(sint32_format)=true) + +logic uint64_format : int format + +axiom uint64_format_size : (format_size(uint64_format)=64) + +axiom uint64_format_sign : (signed_format(uint64_format)=false) + +logic sint64_format : int format + +axiom sint64_format_size : (format_size(sint64_format)=64) + +axiom sint64_format_sign : (signed_format(sint64_format)=true) + +axiom is_in_format_sint8 : (forall x:int[is_in_format(sint8_format,x)]. +(is_in_format(sint8_format, +x) <-> (((-128)<=x) and (x<128)))) + +axiom is_in_format_uint8 : (forall x:int[is_in_format(uint8_format,x)]. +(is_in_format(uint8_format, +x) <-> ((0<=x) and (x<256)))) + +axiom is_in_format_sint16 : (forall x:int[is_in_format(sint16_format,x)]. +(is_in_format(sint16_format, +x) <-> (((-32768)<=x) and (x<32768)))) + +axiom is_in_format_uint16 : (forall x:int[is_in_format(uint16_format,x)]. +(is_in_format(uint16_format, +x) <-> ((0<=x) and (x<65536)))) + +axiom is_in_format_sint32 : (forall x:int[is_in_format(sint32_format,x)]. +(is_in_format(sint32_format, +x) <-> (((-2147483648)<=x) and (x<2147483648)))) + +axiom is_in_format_uint32 : (forall x:int[is_in_format(uint32_format,x)]. +(is_in_format(uint32_format, +x) <-> ((0<=x) and (x<4294967296)))) + +axiom is_in_format_sint64 : (forall x:int[is_in_format(sint64_format,x)]. +(is_in_format(sint64_format, +x) <-> (((-9223372036854775808)<=x) and (x<9223372036854775808)))) + +axiom is_in_format_uint64 : (forall x:int[is_in_format(uint64_format,x)]. +(is_in_format(uint64_format, +x) <-> ((0<=x) and (x<18446744073709551616)))) + +logic float16_format : real format + +axiom float16_format_size : (format_size(float16_format)=16) + +logic float32_format : real format + +axiom float32_format_size : (format_size(float32_format)=32) + +logic float64_format : real format + +axiom float64_format_size : (format_size(float64_format)=64) + +logic float96_format : real format + +axiom float96_format_size : (format_size(float96_format)=96) + +logic float128_format : real format + +axiom float128_format_size : (format_size(float128_format)=128) + +logic encode : 'a1 format,'a1 -> data + +logic decode : 'a1 format,data -> 'a1 + +axiom encode_decode : (forall f:'a1 format.(forall d:data. +(encode(f,decode(f,d))=d))) + +axiom decode_encode : (forall f:'a1 format.(forall x:'a1. +(decode(f,encode(f,x))=x))) + +axiom decode_inj : (forall d:data.(forall d':data.(forall f:'a1 format. +((decode(f,d)<>decode(f,d')) <-> (d<>d'))))) + +axiom decode_eq : (forall d:data.(forall d':data.(forall f:'a1 format. +((decode(f,d)=decode(f,d')) <-> (d=d'))))) + +logic int_format : int format + +logic real_format : real format + +logic as_int : int format,int -> int + +axiom simpl_as_int : (forall f:int format.(forall x:int.(is_in_format(f, +x) -> (as_int(f,x)=x)))) + +axiom as_int_def : (forall f:int format.(forall x:int.is_in_format(f, +as_int(f,x)))) + +axiom involve_as_int : (forall f:int format.(forall x:int. +(as_int(f,as_int(f,x))=as_int(f,x)))) + +logic as_float : real format,real -> real + +axiom simpl_as_float : (forall f:real format.(forall x:real.(is_in_format(f, +x) -> (as_float(f,x)=x)))) + +axiom as_float_def : (forall f:real format.(forall x:real.is_in_format(f, +as_float(f,x)))) + +axiom involve_as_float : (forall f:real format.(forall x:real. +(as_float(f,as_float(f,x))=as_float(f,x)))) + +type zone + +logic rt_zone : int,int -> zone + +logic z_addr : zone -> int + +logic z_size : zone -> int + +axiom addr_zone : (forall a:int.(forall sz:int. +(z_addr(rt_zone(a,sz))=a))) + +axiom size_zone : (forall a:int.(forall sz:int. +((0<=sz) -> (z_size(rt_zone(a,sz))=sz)))) + +axiom rt_zone_inj : (forall a1:int.(forall a2:int.(forall sz1:int. +(forall sz2:int. +((rt_zone(a1,sz1)=rt_zone(a2,sz2)) <-> ((a1=a2) and (sz1=sz2))))))) + +predicate rt_disj(z1:zone,z2:zone) = (((z_addr(z1)+z_size(z1))<=z_addr(z2)) or ((z_addr(z2)+z_size(z2))<=z_addr(z1))) + +predicate rt_incl(z1:zone,z2:zone) = ((z_addr(z2)<=z_addr(z1)) and ((z_addr(z1)+z_size(z1))<=(z_addr(z2)+z_size(z2)))) + +predicate addr_in_zone(a:int,z:zone) = ((z_addr(z)<=a) and (a<(z_addr(z)+z_size(z)))) + +function rt_shift(addr:int,offset:int) : int = (addr+offset) + +logic rt_foffset : int -> int + +logic rt_fsize : int -> int + +logic rt_fformat : int -> int format + +type zones + +logic zs_empty : zones + +logic zs_singleton : zone -> zones + +logic zs_union : zones,zones -> zones + +logic zs_incl : zones,zones -> prop + +logic zs_disj : zones,zones -> prop + +predicate zs_z_incl(z:zone,zs:zones) = zs_incl(zs_singleton(z), +zs) + +predicate zs_z_disj(z:zone,zs:zones) = zs_disj(zs_singleton(z), +zs) + +axiom zs_empty_incl : (forall zs:zones.zs_incl(zs_empty, +zs)) + +axiom zs_z_not_incl_empty : (forall z:zone.(not zs_incl(zs_singleton(z), +zs_empty))) + +axiom zs_incl_singleton : (forall z1:zone.(forall z2:zone.(rt_incl(z1, +z2) <-> zs_incl(zs_singleton(z1), +zs_singleton(z2))))) + +axiom zs_incl_union_1 : (forall z:zones.(forall z1:zones.(forall z2:zones. +(zs_incl(z,z1) -> zs_incl(z, +zs_union(z1,z2)))))) + +axiom zs_incl_union_2 : (forall z:zones.(forall z1:zones.(forall z2:zones. +(zs_incl(z,z2) -> zs_incl(z, +zs_union(z1,z2)))))) + +axiom zs_incl_union_3 : (forall z:zones.(forall z1:zones.(forall z2:zones. +(zs_incl(z1,z) -> (zs_incl(z2,z) -> zs_incl(zs_union(z1,z2), +z)))))) + +axiom zs_disj_singleton : (forall z1:zone.(forall z2:zone.(rt_disj(z1, +z2) <-> zs_disj(zs_singleton(z1), +zs_singleton(z2))))) + +axiom zs_incl_disj : (forall z:zones.(forall zi:zones.(forall zd:zones. +(zs_incl(zi,z) -> (zs_disj(zd,z) -> zs_disj(zi, +zd)))))) + +type bits + +logic bits_size : bits -> int + +axiom bits_size_pos : (forall b:bits. +(bits_size(b)>=0)) + +logic nth_bit : bits,int -> bool + +axiom eq_bits : (forall b1:bits.(forall b2:bits.(forall sz:int. +((bits_size(b1)=sz) -> ((bits_size(b2)=sz) -> ((forall i:int. +(((0<=i) and (i<sz)) -> (nth_bit(b1,i)=nth_bit(b2,i)))) <-> (b1=b2))))))) + +predicate zero_bits(b:bits) = (forall i:int. +(((0<=i) and (i<bits_size(b))) -> (nth_bit(b,i)=false))) + +logic bits_part : bits,int,int -> bits + +axiom bits_part_size : (forall b:bits.(forall off:int.(forall sz:int. +((0<=off) -> (((off+sz)<=bits_size(b)) -> (bits_size(bits_part(b,off,sz))=sz)))))) + +axiom nth_bits_part : (forall b:bits.(forall off:int.(forall i:int. +(forall sz:int. +(((0<=i) and (i<sz)) -> ((0<=off) -> (((off+sz)<=bits_size(b)) -> (nth_bit(bits_part(b,off,sz),i)=nth_bit(b,(off+i)))))))))) + +logic bits_concat : bits,bits -> bits + +axiom bits_concat_size : (forall b1:bits.(forall b2:bits. +(bits_size(bits_concat(b1,b2))=(bits_size(b1)+bits_size(b2))))) + +axiom nth_bits_concat_l : (forall b1:bits.(forall b2:bits.(forall i:int. +(((0<=i) and (i<bits_size(b1))) -> (nth_bit(bits_concat(b1,b2),i)=nth_bit(b1,i)))))) + +axiom nth_bits_concat_r : (forall b1:bits.(forall b2:bits.(forall i:int. +(forall sz1:int.(forall sz2:int. +((sz1=bits_size(b1)) -> ((sz2=bits_size(b2)) -> (((sz1<=i) and (i<(sz1+sz2))) -> (nth_bit(bits_concat(b1,b2),i)=nth_bit(b2,(i-sz1))))))))))) + +logic wr_bits_part : bits,int,bits -> bits + +axiom wr_bits_part_size : (forall b:bits.(forall bw:bits.(forall o:int. +(bits_size(wr_bits_part(b,o,bw))=bits_size(b))))) + +axiom nth_wr_bits_part_1 : (forall b:bits.(forall b':bits.(forall off:int. +(forall i:int. +(((0<=i) and (i<off)) -> (nth_bit(wr_bits_part(b,off,b'),i)=nth_bit(b,i))))))) + +axiom nth_wr_bits_part_2 : (forall b:bits.(forall b':bits.(forall off:int. +(forall i:int. +((((0<=off) and (off<=i)) and (i<(off+bits_size(b')))) -> (nth_bit(wr_bits_part(b,off,b'),i)=nth_bit(b',(i-off)))))))) + +axiom nth_wr_bits_part_3 : (forall b:bits.(forall b':bits.(forall off:int. +(forall i:int. +((((0<=(off+bits_size(b'))) and ((off+bits_size(b'))<=i)) and (i<bits_size(b))) -> (nth_bit(wr_bits_part(b,off,b'),i)=nth_bit(b,i))))))) + +logic rt_from_bits : bits,'a1 format -> 'a1 + +axiom rt_from_bits_format : (forall b:bits.(forall fmt:'a1 format. +((bits_size(b)=format_size(fmt)) -> is_in_format(fmt, +rt_from_bits(b,fmt))))) + +logic rt_to_bits : 'a1 format,'a1 -> bits + +axiom rt_to_bits_size : (forall fmt:'a1 format. +(forall x:'a1[bits_size(rt_to_bits(fmt,x))]. +(bits_size(rt_to_bits(fmt,x))=format_size(fmt)))) + +axiom rt_to_bits_from_bits : (forall fmt:'a1 format. +(forall b:bits[rt_to_bits(fmt,rt_from_bits(b,fmt))]. +((bits_size(b)=format_size(fmt)) -> (rt_to_bits(fmt,rt_from_bits(b,fmt))=b)))) + +axiom rt_from_bits_to_bits : (forall fmt:'a1 format. +(forall v:'a1[rt_from_bits(rt_to_bits(fmt,v),fmt)].(is_in_format(fmt, +v) -> (rt_from_bits(rt_to_bits(fmt,v),fmt)=v)))) + +axiom same_int_val_same_bits : (forall b1:bits.(forall b2:bits. +(forall fmt:int format. +((bits_size(b1)=format_size(fmt)) -> ((bits_size(b2)=format_size(fmt)) -> ((rt_from_bits(b1,fmt)=rt_from_bits(b2,fmt)) -> (b1=b2))))))) + +axiom rt_to_bits_zero : (forall fmt:int format.(forall b:bits. +((b=rt_to_bits(fmt,0)) -> zero_bits(b)))) + +axiom rt_from_bits_zero : (forall b:bits.(forall fmt:int format. +(zero_bits(b) -> (rt_from_bits(b,fmt)=0)))) + +logic mbyte_to_bbits : bits -> bool farray + +axiom mbyte_to_bbits_def : (forall b:bits.((bits_size(b)=8) -> (forall i:int. +(((0<=i) and (i<8)) -> (mbyte_to_bbits(b)[i]=nth_bit(b,(7-i))))))) + +logic nth_mbyte : int,bits -> bits + +axiom nth_mbyte_size : (forall b:bits.(forall k:int. +(bits_size(nth_mbyte(k,b))=8))) + +axiom nth_byte_def : (forall b:bits.(forall k:int. +(((0<=(8*(k+1))) and ((8*(k+1))<=bits_size(b))) -> (forall i:int. +(((0<=i) and (i<8)) -> (nth_bit(nth_mbyte(k,b),i)=nth_bit(b,((8*k)+i)))))))) + +function nth_byte(k:int,b:bits) : bool farray = mbyte_to_bbits(nth_mbyte(k,b)) + +logic little_endian : prop + +logic concat_bytes : bool farray,bool farray -> bool farray + +axiom concat_bytes_left : (forall w:bool farray.(forall b:bool farray. +(forall i:int. +((8<=i) -> (concat_bytes(w,b)[i]=w[(i-8)]))))) + +axiom concat_bytes_right : (forall w:bool farray.(forall b:bool farray. +(forall i:int. +(((0<=i) and (i<8)) -> (concat_bytes(w,b)[i]=b[i]))))) + +logic uint_of_bits : int,bool farray -> int + +logic sint_of_bits : int,bool farray -> int + +function cint_of_bits(fmt:int format,b:bool farray) : int = ite(signed_format(fmt),sint_of_bits((format_size(fmt)-1),b),uint_of_bits((format_size(fmt)-1),b)) + +logic bits_of_sint : int,int -> bool farray + +logic bits_of_uint : int,int -> bool farray + +function bits_of_cint(fmt:int format,x:int) : bool farray = ite(signed_format(fmt),bits_of_sint((format_size(fmt)-1),x),bits_of_uint((format_size(fmt)-1),x)) + +logic mbits_to_bbits : bits -> bool farray + +axiom mb8_to_bbits : (forall b:bits. +((bits_size(b)=8) -> (mbits_to_bbits(b)=nth_byte(0,b)))) + +axiom little_mb16_to_bbits : (forall b:bits. +((bits_size(b)=16) -> (little_endian -> (mbits_to_bbits(b)=concat_bytes(nth_byte(1,b),nth_byte(0,b)))))) + +axiom big_mb16_to_bbits : (forall b:bits. +((bits_size(b)=16) -> ((not little_endian) -> (mbits_to_bbits(b)=concat_bytes(nth_byte(0,b),nth_byte(1,b)))))) + +axiom little_mb32_to_bbits : (forall b:bits. +((bits_size(b)=32) -> (little_endian -> (mbits_to_bbits(b)=concat_bytes(concat_bytes(concat_bytes(nth_byte(3,b),nth_byte(2,b)),nth_byte(1,b)),nth_byte(0,b)))))) + +axiom big_mb32_to_bbits : (forall b:bits. +((bits_size(b)=32) -> ((not little_endian) -> (mbits_to_bbits(b)=concat_bytes(concat_bytes(concat_bytes(nth_byte(0,b),nth_byte(1,b)),nth_byte(2,b)),nth_byte(3,b)))))) + +axiom rt_int_from_bits : (forall b:bits.(forall fmt:int format. +(rt_from_bits(b,fmt)=cint_of_bits(fmt,mbits_to_bbits(b))))) + +logic bbits_to_mbyte : int,bool farray -> bits + +axiom bbits_to_mbyte_size : (forall b:bool farray.(forall k:int. +(bits_size(bbits_to_mbyte(k,b))=8))) + +axiom bbits_to_mbyte_def : (forall b:bool farray.(forall k:int.(forall i:int. +(((0<=i) and (i<8)) -> (nth_bit(bbits_to_mbyte(k,b),i)=b[(((8*k)+7)-i)]))))) + +logic bbits_to_mbits : int,bool farray -> bits + +axiom bbits_to_mb8 : (forall b:bool farray. +(bbits_to_mbits(8,b)=bbits_to_mbyte(0,b))) + +axiom bbits_to_little_mb16 : (forall b:bool farray. +(little_endian -> (bbits_to_mbits(16,b)=bits_concat(bbits_to_mbyte(0,b),bbits_to_mbyte(1,b))))) + +axiom bbits_to_big_mb16 : (forall b:bool farray. +((not little_endian) -> (bbits_to_mbits(16,b)=bits_concat(bbits_to_mbyte(1,b),bbits_to_mbyte(0,b))))) + +axiom bbits_to_little_mb32 : (forall b:bool farray. +(little_endian -> (bbits_to_mbits(32,b)=bits_concat(bbits_to_mbyte(0,b),bits_concat(bbits_to_mbyte(1,b),bits_concat(bbits_to_mbyte(2,b),bbits_to_mbyte(3,b))))))) + +axiom bbits_to_not_mb32 : (forall b:bool farray. +((not little_endian) -> (bbits_to_mbits(32,b)=bits_concat(bbits_to_mbyte(3,b),bits_concat(bbits_to_mbyte(2,b),bits_concat(bbits_to_mbyte(1,b),bbits_to_mbyte(0,b))))))) + +axiom rt_int_to_bits : (forall x:int.(forall fmt:int format. +(rt_to_bits(fmt,x)=bbits_to_mbits(format_size(fmt),bits_of_cint(fmt,x))))) + +type memory + +type memalloc + +logic rt_valid : memalloc,zone -> prop + +axiom incl_valid : (forall m:memalloc.(forall z:zone.(forall z':zone. +(rt_incl(z',z) -> (rt_valid(m,z) -> rt_valid(m, +z')))))) + +axiom disj_valid : (forall m:memalloc.(forall z:zone. +(forall z':zone[rt_disj(z,z')].(rt_valid(m,z) -> ((not rt_valid(m, +z')) -> rt_disj(z, +z')))))) + +logic rt_zbase : memalloc,int -> zone + +function rt_abase(m:memalloc,addr:int) : int = z_addr(rt_zbase(m,addr)) + +logic rt_block_length : memalloc,int -> int + +type mz + +logic mem_of_mz : mz -> memalloc + +logic addr_of_mz : mz -> int + +logic rt_alloc : memalloc,int -> mz + +function alloc_zone(m:memalloc,sz:int) : zone = rt_zone(addr_of_mz(rt_alloc(m,sz)),sz) + +axiom alloc_is_base : (forall m:memalloc.(forall sz:int. +(rt_zbase(mem_of_mz(rt_alloc(m,sz)),addr_of_mz(rt_alloc(m,sz)))=alloc_zone(m,sz)))) + +axiom valid_alloc : (forall m:memalloc.(forall sz:int. +rt_valid(mem_of_mz(rt_alloc(m,sz)), +alloc_zone(m,sz)))) + +axiom not_valid_before_alloc : (forall m:memalloc.(forall sz:int. +(not rt_valid(m, +alloc_zone(m,sz))))) + +axiom alloc_keep_valid : (forall m:memalloc.(forall sz:int.(forall z:zone. +(rt_valid(m,z) -> rt_valid(mem_of_mz(rt_alloc(m,sz)), +z))))) + +axiom alloc_keep_invalid : (forall m:memalloc.(forall sz:int.(forall z:zone. +(rt_valid(mem_of_mz(rt_alloc(m,sz)),z) -> (rt_disj(alloc_zone(m,sz), +z) -> rt_valid(m, +z)))))) + +logic rt_free : memalloc,int -> memalloc + +axiom not_valid_after_free : (forall m:memalloc.(forall addr:int. +(forall z:zone. +((z=rt_zbase(m,addr)) -> ((addr=z_addr(z)) -> (not rt_valid(rt_free(m,addr), +z))))))) + +axiom valid_free_disj : (forall m:memalloc.(forall z:zone.(forall z':zone. +(rt_valid(rt_free(m,z_addr(z)),z') <-> rt_disj(z, +z'))))) + +logic rt_vaddr : memalloc,int -> int + +logic rt_vsize : int -> int + +function rt_vzone(ma:memalloc,var:int) : zone = rt_zone(rt_vaddr(ma,var),rt_vsize(var)) + +logic rt_global : int -> prop + +axiom rt_global_vaddr : (forall v:int.(rt_global(v) -> (forall ma:memalloc. +(forall ma':memalloc. +(rt_vaddr(ma,v)=rt_vaddr(ma',v)))))) + +axiom rt_global_valid : (forall ma:memalloc.(forall v:int. +(rt_global(v) -> (forall ma:memalloc. +(forall ma':memalloc[rt_valid(ma,rt_vzone(ma',v))].rt_valid(ma, +rt_vzone(ma',v))))))) + +axiom vzone_disj : (forall ma:memalloc.(forall v1:int.(forall v2:int. +((v1<>v2) -> (rt_valid(ma,rt_vzone(ma,v1)) -> (rt_valid(ma, +rt_vzone(ma,v2)) -> rt_disj(rt_vzone(ma,v1), +rt_vzone(ma,v2)))))))) + +logic rt_valloc : memalloc,int -> memalloc + +axiom rt_valloc_mem : (forall ma:memalloc.(forall var:int. +(rt_valloc(ma,var)=mem_of_mz(rt_alloc(ma,rt_vsize(var)))))) + +axiom rt_valloc_addr : (forall ma:memalloc.(forall var:int. +(forall ma':memalloc.((ma'=rt_valloc(ma,var)) -> (forall mz:mz. +((mz=rt_alloc(ma,rt_vsize(var))) -> (rt_vaddr(ma',var)=addr_of_mz(mz)))))))) + +axiom vzone_valloc_neq : (forall ma:memalloc.(forall v1:int.(forall v2:int. +(forall ma':memalloc. +((ma'=rt_valloc(ma,v1)) -> ((v1<>v2) -> (rt_vzone(ma',v2)=rt_vzone(ma,v2)))))))) + +function rt_vfree(ma:memalloc,var:int) : memalloc = rt_free(ma,rt_vaddr(ma,var)) + +axiom rt_vaddr_vfree : (forall ma:memalloc.(forall v1:int.(forall v2:int. +((v1<>v2) -> (rt_vaddr(rt_vfree(ma,v1),v2)=rt_vaddr(ma,v2)))))) + +axiom addr_base : (forall m:memalloc.(forall v:int. +(rt_abase(m,rt_vaddr(m,v))=rt_vaddr(m,v)))) + +logic rt_load : memory,zone -> bits + +logic rt_store : memory,int,bits -> memory + +axiom load_store_same : (forall m:memory.(forall a:int.(forall z:zone. +(forall v:bits[rt_load(rt_store(m,a,v),z)]. +((z=rt_zone(a,bits_size(v))) -> (rt_load(rt_store(m,a,v),z)=v)))))) + +axiom load_store_disj : (forall m:memory.(forall a:int.(forall z:zone. +(forall v:bits[rt_load(rt_store(m,a,v),z)].(rt_disj(rt_zone(a,bits_size(v)), +z) -> (rt_load(rt_store(m,a,v),z)=rt_load(m,z))))))) + +axiom load_store_incl_part : (forall m:memory.(forall a:int.(forall z1:zone. +(forall z2:zone.(forall v:bits.((z2=rt_zone(a,bits_size(v))) -> (rt_incl(z1, +z2) -> (rt_load(rt_store(m,a,v),z1)=bits_part(v,(z_addr(z1)-a),z_size(z1)))))))))) + +axiom load_incl_part_store : (forall m:memory.(forall z1:zone. +(forall z2:zone.(forall v:bits.(forall a:int. +((z1=rt_zone(a,bits_size(v))) -> (forall off:int. +((off=(a-z_addr(z2))) -> (rt_incl(z1, +z2) -> (rt_load(rt_store(m,a,v),z2)=wr_bits_part(rt_load(m,z2),off,v))))))))))) + +axiom rt_load_size : (forall m:memory.(forall z:zone. +(bits_size(rt_load(m,z))=z_size(z)))) + +axiom bits_part_rt_load : (forall z:zone.(forall z':zone.(forall a':int. +(forall off:int.(forall sz:int. +((a'=(z_addr(z)+off)) -> ((z'=rt_zone(a',sz)) -> (rt_incl(z', +z) -> (forall m:memory. +(rt_load(m,z')=bits_part(rt_load(m,z),off,sz))))))))))) + +axiom rt_same_mem : (forall m1:memory.(forall m2:memory.((forall z:zone. +(rt_load(m1,z)=rt_load(m2,z))) -> (m1=m2)))) + +logic rt_havoc : memory,zone -> memory + +predicate rt_is_havoc(ma:memalloc,m1:memory,zs:zones,m2:memory) = (forall z:zone. +(rt_valid(ma,z) -> (zs_z_disj(z, +zs) -> (rt_load(m1,z)=rt_load(m2,z))))) + +axiom rt_havoc_is_havoc : (forall ma:memalloc.(forall m:memory. +(forall zs:zones.(forall z:zone.(zs_z_incl(z,zs) -> rt_is_havoc(ma,m,zs, +rt_havoc(m,z))))))) + +logic rt_addr_format : int format + +axiom rt_vaddr_format : (forall ma:memalloc.(forall v:int. +is_in_format(rt_addr_format, +rt_vaddr(ma,v)))) + +axiom bits_part_vs_access : (forall bs:bits.(forall fs:data farray format. +(forall f:int.(forall off:int.(forall sz:int. +((off=rt_foffset(f)) -> ((sz=rt_fsize(f)) -> (rt_from_bits(bits_part(bs,off,sz),rt_fformat(f))=decode(int_format,rt_from_bits(bs,fs)[f]))))))))) + +logic rt_addr_lt : int,int -> prop + +logic rt_addr_le : int,int -> prop + +logic rt_addr_lt_bool : int,int -> bool + +logic rt_addr_le_bool : int,int -> bool + +logic rt_addr_minus : int,int -> int + +logic rt_addr_eq : int,int -> prop + +logic rt_addr_eq_bool : int,int -> bool + +axiom rt_disj_sym : (forall z1:zone.(forall z2:zone.(rt_disj(z1, +z2) <-> rt_disj(z2, +z1)))) + +axiom rt_disj_shift : (forall addr:int.(forall i:int.(forall j:int. +(forall sz:int. +((sz>0) -> ((i<>j) -> rt_disj(rt_zone(rt_shift(addr,(i*sz)),sz), +rt_zone(rt_shift(addr,(j*sz)),sz)))))))) + +axiom vzone_of_zone : (forall ma:memalloc.(forall v:int.(forall a:int. +(forall sz:int. +((a=rt_vaddr(ma,v)) -> ((sz=rt_vsize(v)) -> (rt_zone(a,sz)=rt_vzone(ma,v)))))))) + +axiom bits_part_full : (forall v:bits.(forall sz:int. +((sz=bits_size(v)) -> (bits_part(v,0,sz)=v)))) + +axiom bits_part_of_bits_part : (forall b:bits.(forall o1:int.(forall o2:int. +(forall sz1:int.(forall sz2:int. +((0<=o1) -> (((o1+sz1)<=bits_size(b)) -> ((0<=o2) -> (((o2+sz2)<=sz1) -> (bits_part(bits_part(b,o1,sz1),o2,sz2)=bits_part(b,(o1+o2),sz2))))))))))) + +axiom eq_bits_split : (forall b1:bits.(forall b2:bits.(forall sz:int. +((bits_size(b1)=sz) -> ((bits_size(b2)=sz) -> (forall sz1:int. +(forall sz2:int. +((sz1>=0) -> ((sz2>=0) -> (((sz1+sz2)=sz) -> ((bits_part(b1,0,sz1)=bits_part(b2,0,sz1)) -> ((bits_part(b1,sz1,sz2)=bits_part(b2,sz1,sz2)) -> (b1=b2))))))))))))) + +axiom wr_bits_part_all : (forall v:bits.(forall v':bits. +((bits_size(v)=bits_size(v')) -> (wr_bits_part(v,0,v')=v')))) + +axiom wr_bits_part_concat : (forall b:bits.(forall b':bits.(forall sz1:int. +(forall sz2:int.(forall sz3:int. +((0<=sz1) -> ((sz2=bits_size(b')) -> ((0<=sz3) -> ((((sz1+sz2)+sz3)=bits_size(b)) -> (wr_bits_part(b,sz1,b')=bits_concat(bits_part(b,0,sz1),bits_concat(b',bits_part(b,(sz1+sz2),sz3))))))))))))) + +axiom wr_bits_part_same : (forall b1:bits.(forall b2:bits.(forall off:int. +((0<=off) -> (((off+bits_size(b2))<=bits_size(b1)) -> (bits_part(wr_bits_part(b1,off,b2),off,bits_size(b2))=b2)))))) + +axiom wr_bits_part_disj : (forall b:bits.(forall b1:bits.(forall off2:int. +(forall off1:int.(forall sz:int.(forall sz1:int.(forall sz2:int. +((sz=bits_size(b)) -> ((sz1=bits_size(b1)) -> ((0<=off1) -> (((off1+sz1)<=sz) -> ((0<=off2) -> (((off2+sz2)<=sz) -> ((((off2+sz2)<=off1) or ((off1+sz1)<=off2)) -> (bits_part(wr_bits_part(b,off1,b1),off2,sz2)=bits_part(b,off2,sz2)))))))))))))))) + +axiom rt_z_from_bits_to_bits_zero : (forall fmt:int format. +(forall fmt':int format. +(rt_from_bits(rt_to_bits(fmt,0),fmt')=0))) + +axiom bits_part_zero : (forall b:bits.(forall b':bits.(forall off:int. +(forall sz:int. +((0<=off) -> (((off+sz)<=bits_size(b)) -> ((b'=bits_part(b,off,sz)) -> (zero_bits(b) -> zero_bits(b'))))))))) + +axiom rw_same_var : (forall m:memory.(forall ma:memalloc.(forall v:int. +(forall val:bits[rt_load(rt_store(m,rt_vaddr(ma,v),val),rt_vzone(ma,v))]. +((bits_size(val)=rt_vsize(v)) -> (rt_load(rt_store(m,rt_vaddr(ma,v),val),rt_vzone(ma,v))=val)))))) + +axiom rw_disj_var : (forall ma:memalloc.(forall m:memory.(forall v1:int. +(forall v2:int.(forall z1:zone.(forall z2:zone. +(forall b:bits[rt_load(rt_store(m,rt_vaddr(ma,v2),b),rt_vzone(ma,v1))]. +((v1<>v2) -> ((z1=rt_vzone(ma,v1)) -> ((z2=rt_vzone(ma,v2)) -> (rt_valid(ma, +z1) -> (rt_valid(ma, +z2) -> ((rt_vsize(v2)=bits_size(b)) -> (rt_load(rt_store(m,rt_vaddr(ma,v2),b),z1)=rt_load(m,z1))))))))))))))) + +axiom store_concat : (forall m:memory.(forall m1:memory.(forall a:int. +(forall b1:bits.(forall b2:bits.(forall sz1:int. +((sz1=bits_size(b1)) -> ((m1=rt_store(m,a,b1)) -> (rt_store(m1,(a+sz1),b2)=rt_store(m,a,bits_concat(b1,b2))))))))))) + +axiom store_disj_commut : (forall m:memory.(forall a1:int.(forall a2:int. +(forall b1:bits.(forall b2:bits.(rt_disj(rt_zone(a1,bits_size(b1)), +rt_zone(a2,bits_size(b2))) -> (rt_store(rt_store(m,a1,b1),a2,b2)=rt_store(rt_store(m,a2,b2),a1,b1)))))))) + +axiom not_valid_before_valloc : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc.((ma'=rt_valloc(ma,v)) -> (not rt_valid(ma, +rt_vzone(ma',v))))))) + +axiom valid_valloc : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc[rt_valid(ma',rt_vzone(ma',v))]. +((ma'=rt_valloc(ma,v)) -> rt_valid(ma', +rt_vzone(ma',v)))))) + +axiom valloc_keep_valid_zone : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc.((ma'=rt_valloc(ma,v)) -> (forall z:zone.(rt_valid(ma, +z) -> rt_valid(ma', +z))))))) + +axiom valloc_keep_valid_disj_zone : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc.((ma'=rt_valloc(ma,v)) -> (forall z:zone. +(rt_disj(rt_vzone(ma',v),z) -> (rt_valid(ma',z) -> rt_valid(ma, +z)))))))) + +axiom valloc_keep_invalid_zone : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc.((ma'=rt_valloc(ma,v)) -> (forall z:zone. +(rt_disj(rt_vzone(ma',v),z) -> ((not rt_valid(ma,z)) -> (not rt_valid(ma', +z))))))))) + +axiom valloc_keep_invalid_zone_rev : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc.((ma'=rt_valloc(ma,v)) -> (forall z:zone. +(rt_disj(rt_vzone(ma',v),z) -> ((not rt_valid(ma',z)) -> (not rt_valid(ma, +z))))))))) + +axiom valloc_keep_valid_var : (forall ma:memalloc.(forall v1:int. +(forall v:int.(forall ma':memalloc. +((ma'=rt_valloc(ma,v)) -> ((v<>v1) -> (rt_valid(ma, +rt_vzone(ma,v1)) -> rt_valid(ma', +rt_vzone(ma',v1))))))))) + +axiom valloc_keep_vaddr : (forall ma:memalloc.(forall v1:int.(forall v:int. +(forall ma':memalloc. +((ma'=rt_valloc(ma,v)) -> ((v<>v1) -> (rt_vaddr(ma',v1)=rt_vaddr(ma,v1)))))))) + +axiom valloc_keep_vzone : (forall ma:memalloc.(forall v1:int.(forall v:int. +(forall ma':memalloc. +((ma'=rt_valloc(ma,v)) -> ((v<>v1) -> (rt_vzone(ma',v1)=rt_vzone(ma,v1)))))))) + +axiom vzone_vfree : (forall ma:memalloc.(forall v1:int.(forall v2:int. +(forall ma':memalloc. +((ma'=rt_vfree(ma,v1)) -> ((v1<>v2) -> (rt_vzone(ma',v2)=rt_vzone(ma,v2)))))))) + +axiom not_valid_after_vfree : (forall ma:memalloc.(forall v:int. +(forall ma':memalloc.((ma'=rt_vfree(ma,v)) -> (forall z:zone. +((z=rt_vzone(ma,v)) -> (not rt_valid(ma', +z)))))))) + +axiom havoc_store : (forall ma:memalloc.(forall m1:memory.(forall m2:memory. +(forall zs:zones.(forall z:zone.(forall x:bits.(forall a:int. +((z=rt_zone(a,bits_size(x))) -> (rt_is_havoc(ma,m1,zs,m2) -> (zs_z_incl(z, +zs) -> rt_is_havoc(ma,m1,zs, +rt_store(m2,a,x)))))))))))) + +axiom havoc_invalid : (forall ma:memalloc.(forall m1:memory. +(forall m2:memory.(forall zs:zones.(forall z:zone.(forall x:bits. +(forall a:int.((z=rt_zone(a,bits_size(x))) -> (rt_is_havoc(ma,m1,zs, +m2) -> ((not rt_valid(ma,z)) -> rt_is_havoc(ma,m1,zs, +rt_store(m2,a,x)))))))))))) + +axiom same_bits_same_val : (forall b1:bits.(forall b2:bits. +(forall fmt:'a1 format. +((b1=b2) -> (rt_from_bits(b1,fmt)=rt_from_bits(b2,fmt)))))) + +axiom valid_vglob : (forall v:int.(rt_global(v) -> (forall ma:memalloc. +(forall ma':memalloc.rt_valid(ma, +rt_vzone(ma',v)))))) + + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/runtime_model.v frama-c-20111001+nitrogen+dfsg/src/wp/share/runtime_model.v --- frama-c-20110201+carbon+dfsg/src/wp/share/runtime_model.v 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/runtime_model.v 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,2515 @@ +(* This file was originally generated by why. + It can be modified; only the generated parts will be overwritten. *) +Require Import Reals. Require Import wp. + +(*Why logic*) Definition bool_and : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_or : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_xor : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_not : bool -> bool. +Admitted. + +(*Why axiom*) Lemma bool_and_def : + (forall (a:bool), + (forall (b:bool), ((bool_and a b) = true <-> a = true /\ b = true))). +Admitted. + +(*Why axiom*) Lemma bool_or_def : + (forall (a:bool), + (forall (b:bool), ((bool_or a b) = true <-> a = true \/ b = true))). +Admitted. + +(*Why axiom*) Lemma bool_xor_def : + (forall (a:bool), (forall (b:bool), ((bool_xor a b) = true <-> ~(a = b)))). +Admitted. + +(*Why axiom*) Lemma bool_not_def : + (forall (a:bool), ((bool_not a) = true <-> a = false)). +Admitted. + +(*Why logic*) Definition ite : forall (A1:Set), bool -> A1 -> A1 -> A1. +Admitted. +Implicit Arguments ite. + +(*Why axiom*) Lemma ite_true : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), (if_then_else true x y) = x)). +Admitted. + +(*Why axiom*) Lemma ite_false : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), (if_then_else false x y) = y)). +Admitted. + +(*Why logic*) Definition lt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition le_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition gt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition ge_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition eq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition neq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why axiom*) Lemma lt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((lt_int_bool x y) = true <-> x < y))). +Admitted. + +(*Why axiom*) Lemma le_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((le_int_bool x y) = true <-> x <= y))). +Admitted. + +(*Why axiom*) Lemma gt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((gt_int_bool x y) = true <-> x > y))). +Admitted. + +(*Why axiom*) Lemma ge_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((ge_int_bool x y) = true <-> x >= y))). +Admitted. + +(*Why axiom*) Lemma eq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((eq_int_bool x y) = true <-> x = y))). +Admitted. + +(*Why axiom*) Lemma neq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((neq_int_bool x y) = true <-> x <> y))). +Admitted. + +(*Why logic*) Definition abs_int : Z -> Z. +Admitted. + +(*Why axiom*) Lemma abs_int_pos : + (forall (x:Z), (x >= 0 -> (abs_int x) = x)). +Admitted. + +(*Why axiom*) Lemma abs_int_neg : + (forall (x:Z), (x <= 0 -> (abs_int x) = (Zopp x))). +Admitted. + +(*Why logic*) Definition int_max : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_min : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma int_max_is_ge : + (forall (x:Z), (forall (y:Z), (int_max x y) >= x /\ (int_max x y) >= y)). +Admitted. + +(*Why axiom*) Lemma int_max_is_some : + (forall (x:Z), (forall (y:Z), (int_max x y) = x \/ (int_max x y) = y)). +Admitted. + +(*Why axiom*) Lemma int_min_is_le : + (forall (x:Z), (forall (y:Z), (int_min x y) <= x /\ (int_min x y) <= y)). +Admitted. + +(*Why axiom*) Lemma int_min_is_some : + (forall (x:Z), (forall (y:Z), (int_min x y) = x \/ (int_min x y) = y)). +Admitted. + +(*Why logic*) Definition lt_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition le_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition gt_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition ge_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition eq_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition neq_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition add_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition sub_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition mul_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition div_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition neg_real : R -> R. +Admitted. + +(*Why logic*) Definition real_of_int : Z -> R. +Admitted. + +(*Why axiom*) Lemma real_of_int_zero : (eq (IZR 0) (0)%R). +Admitted. + +(*Why axiom*) Lemma real_of_int_one : (eq (IZR 1) (1)%R). +Admitted. + +(*Why axiom*) Lemma real_of_int_add : + (forall (x:Z), (forall (y:Z), (eq (IZR (x + y)) (Rplus (IZR x) (IZR y))))). +Admitted. + +(*Why axiom*) Lemma real_of_int_sub : + (forall (x:Z), (forall (y:Z), (eq (IZR (x - y)) (Rminus (IZR x) (IZR y))))). +Admitted. + +(*Why logic*) Definition truncate_real_to_int : R -> Z. +Admitted. + +(*Why axiom*) Lemma truncate_down_pos : + (forall (x:R), + ((Rge x (0)%R) -> (Rle (IZR (truncate_real_to_int x)) x) /\ + (Rlt x (IZR ((truncate_real_to_int x) + 1))))). +Admitted. + +(*Why axiom*) Lemma truncate_up_neg : + (forall (x:R), + ((Rle x (0)%R) -> (Rlt (IZR ((truncate_real_to_int x) - 1)) x) /\ + (Rle x (IZR (truncate_real_to_int x))))). +Admitted. + +(*Why logic*) Definition floor_real_to_int : R -> Z. +Admitted. + +(*Why logic*) Definition ceil_real_to_int : R -> Z. +Admitted. + +(*Why logic*) Definition lt_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition le_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition gt_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition ge_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition eq_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition neq_real_bool : R -> R -> bool. +Admitted. + +(*Why axiom*) Lemma lt_real_bool_axiom : + (forall (x:R), (forall (y:R), ((lt_real_bool x y) = true <-> (Rlt x y)))). +Admitted. + +(*Why axiom*) Lemma le_real_bool_axiom : + (forall (x:R), (forall (y:R), ((le_real_bool x y) = true <-> (Rle x y)))). +Admitted. + +(*Why axiom*) Lemma gt_real_bool_axiom : + (forall (x:R), (forall (y:R), ((gt_real_bool x y) = true <-> (Rgt x y)))). +Admitted. + +(*Why axiom*) Lemma ge_real_bool_axiom : + (forall (x:R), (forall (y:R), ((ge_real_bool x y) = true <-> (Rge x y)))). +Admitted. + +(*Why axiom*) Lemma eq_real_bool_axiom : + (forall (x:R), (forall (y:R), ((eq_real_bool x y) = true <-> (eq x y)))). +Admitted. + +(*Why axiom*) Lemma neq_real_bool_axiom : + (forall (x:R), (forall (y:R), ((neq_real_bool x y) = true <-> ~(eq x y)))). +Admitted. + +(*Why logic*) Definition real_max : R -> R -> R. +Admitted. + +(*Why logic*) Definition real_min : R -> R -> R. +Admitted. + +(*Why axiom*) Lemma real_max_is_ge : + (forall (x:R), + (forall (y:R), (Rge (real_max x y) x) /\ (Rge (real_max x y) y))). +Admitted. + +(*Why axiom*) Lemma real_max_is_some : + (forall (x:R), + (forall (y:R), (eq (real_max x y) x) \/ (eq (real_max x y) y))). +Admitted. + +(*Why axiom*) Lemma real_min_is_le : + (forall (x:R), + (forall (y:R), (Rle (real_min x y) x) /\ (Rle (real_min x y) y))). +Admitted. + +(*Why axiom*) Lemma real_min_is_some : + (forall (x:R), + (forall (y:R), (eq (real_min x y) x) \/ (eq (real_min x y) y))). +Admitted. + +(*Why function*) Definition sqr_real (x:R) := (Rmult x x). + +(*Why logic*) Definition sqrt_real : R -> R. +Admitted. + +(*Why axiom*) Lemma sqrt_pos : + (forall (x:R), ((Rge x (0)%R) -> (Rge (sqrt x) (0)%R))). +Admitted. + +(*Why axiom*) Lemma sqrt_sqr : + (forall (x:R), ((Rge x (0)%R) -> (eq (sqr_real (sqrt x)) x))). +Admitted. + +(*Why axiom*) Lemma sqr_sqrt : + (forall (x:R), ((Rge x (0)%R) -> (eq (sqrt (Rmult x x)) x))). +Admitted. + +(*Why logic*) Definition pow_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition abs_real : R -> R. +Admitted. + +(*Why axiom*) Lemma abs_real_pos : + (forall (x:R), ((Rge x (0)%R) -> (eq (Rabs x) x))). +Admitted. + +(*Why axiom*) Lemma abs_real_neg : + (forall (x:R), ((Rle x (0)%R) -> (eq (Rabs x) (Ropp x)))). +Admitted. + +(*Why logic*) Definition exp : R -> R. +Admitted. + +(*Why logic*) Definition log : R -> R. +Admitted. + +(*Why logic*) Definition log10 : R -> R. +Admitted. + +(*Why axiom*) Lemma log_exp : (forall (x:R), (eq (log (exp x)) x)). +Admitted. + +(*Why axiom*) Lemma exp_log : + (forall (x:R), ((Rgt x (0)%R) -> (eq (exp (log x)) x))). +Admitted. + +(*Why logic*) Definition cos : R -> R. +Admitted. + +(*Why logic*) Definition sin : R -> R. +Admitted. + +(*Why logic*) Definition tan : R -> R. +Admitted. + +(*Why logic*) Definition pi : R. +Admitted. + +(*Why logic*) Definition cosh : R -> R. +Admitted. + +(*Why logic*) Definition sinh : R -> R. +Admitted. + +(*Why logic*) Definition tanh : R -> R. +Admitted. + +(*Why logic*) Definition acos : R -> R. +Admitted. + +(*Why logic*) Definition asin : R -> R. +Admitted. + +(*Why logic*) Definition atan : R -> R. +Admitted. + +(*Why logic*) Definition atan2 : R -> R -> R. +Admitted. + +(*Why logic*) Definition hypot : R -> R -> R. +Admitted. + +(*Why axiom*) Lemma prod_pos : + (forall (x:R), + (forall (y:R), + (((Rgt x (0)%R) /\ (Rgt y (0)%R) -> (Rgt (Rmult x y) (0)%R))) /\ + (((Rlt x (0)%R) /\ (Rlt y (0)%R) -> (Rgt (Rmult x y) (0)%R))))). +Admitted. + +(*Why axiom*) Lemma abs_minus : + (forall (x:R), (eq (Rabs (Ropp x)) (Rabs x))). +Admitted. + +(*Why type*) Definition farray: Set ->Set. +Admitted. + +(*Why logic*) Definition access : forall (A1:Set), (array A1) -> Z -> A1. +Admitted. +Implicit Arguments access. + +(*Why logic*) Definition update : + forall (A1:Set), (array A1) -> Z -> A1 -> (array A1). +Admitted. +Implicit Arguments update. + +(*Why axiom*) Lemma access_update : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), (forall (v:A1), (access (update a i v) i) = v))). +Admitted. + +(*Why axiom*) Lemma access_update_neq : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (j:Z), + (forall (v:A1), (i <> j -> (access (update a i v) j) = (access a j)))))). +Admitted. + +(*Why logic*) Definition array_length : forall (A1:Set), (array A1) -> Z. +Admitted. +Implicit Arguments array_length. + +(*Why predicate*) Definition sorted_array (t:(array Z)) (i:Z) (j:Z) + := (forall (k1:Z), + (forall (k2:Z), + ((i <= k1 /\ k1 <= k2) /\ k2 <= j -> (access t k1) <= (access t k2)))). + +(*Why predicate*) Definition exchange (A302:Set) (a1:(array A302)) (a2:(array A302)) (i:Z) (j:Z) + := (array_length a1) = (array_length a2) /\ + (access a1 i) = (access a2 j) /\ (access a2 i) = (access a1 j) /\ + (forall (k:Z), (k <> i /\ k <> j -> (access a1 k) = (access a2 k))). +Implicit Arguments exchange. + +(*Why logic*) Definition permut : + forall (A1:Set), (array A1) -> (array A1) -> Z -> Z -> Prop. +Admitted. +Implicit Arguments permut. + +(*Why axiom*) Lemma permut_refl : + forall (A1:Set), + (forall (t:(array A1)), (forall (l:Z), (forall (u:Z), (permut t t l u)))). +Admitted. + +(*Why axiom*) Lemma permut_sym : + forall (A1:Set), + (forall (t1:(array A1)), + (forall (t2:(array A1)), + (forall (l:Z), (forall (u:Z), ((permut t1 t2 l u) -> (permut t2 t1 l u)))))). +Admitted. + +(*Why axiom*) Lemma permut_trans : + forall (A1:Set), + (forall (t1:(array A1)), + (forall (t2:(array A1)), + (forall (t3:(array A1)), + (forall (l:Z), + (forall (u:Z), + ((permut t1 t2 l u) -> ((permut t2 t3 l u) -> (permut t1 t3 l u)))))))). +Admitted. + +(*Why axiom*) Lemma permut_exchange : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + (forall (i:Z), + (forall (j:Z), + (l <= i /\ i <= u -> + (l <= j /\ j <= u -> ((exchange a1 a2 i j) -> (permut a1 a2 l u)))))))))). +Admitted. + +(*Why axiom*) Lemma exchange_upd : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (j:Z), + (exchange a (update (update a i (access a j)) j (access a i)) i j)))). +Admitted. + +(*Why axiom*) Lemma permut_weakening : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l1:Z), + (forall (r1:Z), + (forall (l2:Z), + (forall (r2:Z), + ((l1 <= l2 /\ l2 <= r2) /\ r2 <= r1 -> + ((permut a1 a2 l2 r2) -> (permut a1 a2 l1 r1))))))))). +Admitted. + +(*Why axiom*) Lemma permut_eq : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + (l <= u -> + ((permut a1 a2 l u) -> + (forall (i:Z), (i < l \/ u < i -> (access a2 i) = (access a1 i))))))))). +Admitted. + +(*Why predicate*) Definition permutation (A311:Set) (a1:(array A311)) (a2:(array A311)) + := (permut a1 a2 0 ((array_length a1) - 1)). +Implicit Arguments permutation. + +(*Why axiom*) Lemma array_length_update : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (v:A1), (array_length (update a i v)) = (array_length a)))). +Admitted. + +(*Why axiom*) Lemma permut_array_length : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + ((permut a1 a2 l u) -> (array_length a1) = (array_length a2)))))). +Admitted. + +(*Why logic*) Definition computer_div : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition computer_mod : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition math_div : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition math_mod : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma math_div_mod : + (forall (x:Z), + (forall (y:Z), (y <> 0 -> x = (y * (math_div x y) + (math_mod x y))))). +Admitted. + +(*Why axiom*) Lemma math_mod_bound : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> 0 <= (math_mod x y) /\ (math_mod x y) < (abs_int y)))). +Admitted. + +(*Why axiom*) Lemma computer_div_mod : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> x = (y * (computer_div x y) + (computer_mod x y))))). +Admitted. + +(*Why axiom*) Lemma computer_div_bound : + (forall (x:Z), + (forall (y:Z), + (x >= 0 /\ y > 0 -> 0 <= (computer_div x y) /\ (computer_div x y) <= x))). +Admitted. + +(*Why axiom*) Lemma computer_mod_bound : + (forall (x:Z), + (forall (y:Z), (y <> 0 -> (abs_int (computer_mod x y)) < (abs_int y)))). +Admitted. + +(*Why axiom*) Lemma computer_mod_sign_pos : + (forall (x:Z), + (forall (y:Z), (x >= 0 /\ y <> 0 -> (computer_mod x y) >= 0))). +Admitted. + +(*Why axiom*) Lemma computer_mod_sign_neg : + (forall (x:Z), + (forall (y:Z), (x <= 0 /\ y <> 0 -> (computer_mod x y) <= 0))). +Admitted. + +(*Why axiom*) Lemma computer_rounds_toward_zero : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> (abs_int ((computer_div x y) * y)) <= (abs_int x)))). +Admitted. + +(*Why logic*) Definition dummy : Z -> Prop. +Admitted. + +(*Why logic*) Definition assigns : Z -> Prop. +Admitted. + +(*Why axiom*) Lemma positive_computer_div_div : + (forall (x:Z), + (forall (y:Z), (x > 0 -> (y > 0 -> (computer_div x y) = (math_div x y))))). +Admitted. + +(*Why type*) Definition set: Set ->Set. +Admitted. + +(*Why logic*) Definition empty : forall (A1:Set), (set A1). +Admitted. +Set Contextual Implicit. +Implicit Arguments empty. +Unset Contextual Implicit. + +(*Why logic*) Definition singleton : forall (A1:Set), A1 -> (set A1). +Admitted. +Implicit Arguments singleton. + +(*Why logic*) Definition range : Z -> Z -> (set Z). +Admitted. + +(*Why logic*) Definition union : + forall (A1:Set), (set A1) -> (set A1) -> (set A1). +Admitted. +Implicit Arguments union. + +(*Why logic*) Definition inter : + forall (A1:Set), (set A1) -> (set A1) -> (set A1). +Admitted. +Implicit Arguments inter. + +(*Why logic*) Definition plus_int : (set Z) -> (set Z) -> (set Z). +Admitted. + +(*Why logic*) Definition subset : + forall (A1:Set), (set A1) -> (set A1) -> Prop. +Admitted. +Implicit Arguments subset. + +(*Why logic*) Definition range_inf : Z -> (set Z). +Admitted. + +(*Why logic*) Definition range_sup : Z -> (set Z). +Admitted. + +(*Why logic*) Definition integers_set : (set Z). +Admitted. + +(*Why logic*) Definition equiv : + forall (A1:Set), (set A1) -> (set A1) -> Prop. +Admitted. +Implicit Arguments equiv. + +(*Why logic*) Definition member : forall (A1:Set), A1 -> (set A1) -> Prop. +Admitted. +Implicit Arguments member. + +(*Why axiom*) Lemma singleton_def : + forall (A1:Set), (forall (x:A1), (member x (singleton x))). +Admitted. + +(*Why axiom*) Lemma singleton_eq : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), ((member x (singleton y)) <-> x = y))). +Admitted. + +(*Why axiom*) Lemma union_member : + forall (A1:Set), + (forall (x:A1), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((member x (union s1 s2)) <-> (member x s1) \/ (member x s2))))). +Admitted. + +(*Why axiom*) Lemma union_of_empty : + forall (A1:Set), (forall (x:(set A1)), (union x (@empty A1)) = x). +Admitted. + +(*Why axiom*) Lemma inter_of_empty : + forall (A1:Set), (forall (x:(set A1)), (inter x (@empty A1)) = (@empty A1)). +Admitted. + +(*Why axiom*) Lemma union_comm : + forall (A1:Set), + (forall (x:(set A1)), (forall (y:(set A1)), (union x y) = (union y x))). +Admitted. + +(*Why axiom*) Lemma inter_comm : + forall (A1:Set), + (forall (x:(set A1)), (forall (y:(set A1)), (inter x y) = (inter y x))). +Admitted. + +(*Why axiom*) Lemma inter_member : + forall (A1:Set), + (forall (x:A1), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((member x (inter s1 s2)) <-> (member x s1) /\ (member x s2))))). +Admitted. + +(*Why axiom*) Lemma plus_int_member_1 : + (forall (sa:(set Z)), + (forall (sb:(set Z)), + (forall (a:Z), + (forall (b:Z), + ((member a sa) -> ((member b sb) -> (member (a + b) (plus_int sa sb)))))))). +Admitted. + +(*Why axiom*) Lemma plus_int_member_2 : + (forall (sa:(set Z)), + (forall (sb:(set Z)), + (forall (c:Z), + ((member c (plus_int sa sb)) -> + (exists a:Z, + (exists b:Z, (member a sa) /\ (member b sb) /\ c = (a + b))))))). +Admitted. + +(*Why axiom*) Lemma subset_empty : + forall (A1:Set), (forall (sa:(set A1)), (subset (@empty A1) sa)). +Admitted. + +(*Why axiom*) Lemma subset_sym : + forall (A1:Set), (forall (sa:(set A1)), (subset sa sa)). +Admitted. + +(*Why axiom*) Lemma subset_trans : + forall (A1:Set), + (forall (sa:(set A1)), + (forall (sb:(set A1)), + (forall (sc:(set A1)), + ((subset sa sb) -> ((subset sb sc) -> (subset sa sc)))))). +Admitted. + +(*Why axiom*) Lemma subset_def : + forall (A1:Set), + (forall (sa:(set A1)), + (forall (sb:(set A1)), + ((forall (a:A1), ((member a sa) -> (member a sb))) <-> (subset sa sb)))). +Admitted. + +(*Why axiom*) Lemma range_def : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), (i <= k /\ k <= j <-> (member k (range i j)))))). +Admitted. + +(*Why axiom*) Lemma range_def1 : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), (i <= k /\ k <= j -> (member k (range i j)))))). +Admitted. + +(*Why axiom*) Lemma range_def2 : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), ((member k (range i j)) -> i <= k /\ k <= j)))). +Admitted. + +(*Why axiom*) Lemma range_inf_def : + (forall (i:Z), (forall (k:Z), (i <= k <-> (member k (range_inf i))))). +Admitted. + +(*Why axiom*) Lemma range_sup_def : + (forall (j:Z), (forall (k:Z), (k <= j <-> (member k (range_sup j))))). +Admitted. + +(*Why axiom*) Lemma integers_set_def : + (forall (k:Z), (k >= 0 <-> (member k integers_set))). +Admitted. + +(*Why axiom*) Lemma equiv_def : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((forall (a:A1), ((member a s1) -> (member a s2))) /\ + (forall (b:A1), ((member b s2) -> (member b s1))) <-> (equiv s1 s2)))). +Admitted. + +(*Why axiom*) Lemma equiv_refl : + forall (A1:Set), (forall (s:(set A1)), (equiv s s)). +Admitted. + +(*Why axiom*) Lemma equiv_sym : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), ((equiv s1 s2) -> (equiv s2 s1)))). +Admitted. + +(*Why axiom*) Lemma equiv_trans : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + (forall (s3:(set A1)), + ((equiv s1 s2) -> ((equiv s2 s3) -> (equiv s1 s3)))))). +Admitted. + +(*Why logic*) Definition as_uint8 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint8 (x:Z) := 0 <= x /\ x < 256. + +(*Why axiom*) Lemma as_uint8_def : (forall (x:Z), (is_uint8 (as_uint8 x))). +Admitted. + +(*Why axiom*) Lemma as_uint8_involve : + (forall (x:Z), (as_uint8 (as_uint8 x)) = (as_uint8 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint8 : + (forall (x:Z), ((is_uint8 x) -> (as_uint8 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint8 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint8 (x:Z) := (-128) <= x /\ x < 128. + +(*Why axiom*) Lemma as_sint8_def : (forall (x:Z), (is_sint8 (as_sint8 x))). +Admitted. + +(*Why axiom*) Lemma as_sint8_involve : + (forall (x:Z), (as_sint8 (as_sint8 x)) = (as_sint8 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint8 : + (forall (x:Z), ((is_sint8 x) -> (as_sint8 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint16 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint16 (x:Z) := 0 <= x /\ x < 65536. + +(*Why axiom*) Lemma as_uint16_def : + (forall (x:Z), (is_uint16 (as_uint16 x))). +Admitted. + +(*Why axiom*) Lemma as_uint16_involve : + (forall (x:Z), (as_uint16 (as_uint16 x)) = (as_uint16 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint16 : + (forall (x:Z), ((is_uint16 x) -> (as_uint16 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint16 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint16 (x:Z) := (-32768) <= x /\ x < 32768. + +(*Why axiom*) Lemma as_sint16_def : + (forall (x:Z), (is_sint16 (as_sint16 x))). +Admitted. + +(*Why axiom*) Lemma as_sint16_involve : + (forall (x:Z), (as_sint16 (as_sint16 x)) = (as_sint16 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint16 : + (forall (x:Z), ((is_sint16 x) -> (as_sint16 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint32 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint32 (x:Z) := 0 <= x /\ x < 4294967296. + +(*Why axiom*) Lemma as_uint32_def : + (forall (x:Z), (is_uint32 (as_uint32 x))). +Admitted. + +(*Why axiom*) Lemma as_uint32_involve : + (forall (x:Z), (as_uint32 (as_uint32 x)) = (as_uint32 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint32 : + (forall (x:Z), ((is_uint32 x) -> (as_uint32 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint32 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint32 (x:Z) + := (-2147483648) <= x /\ x < 2147483648. + +(*Why axiom*) Lemma as_sint32_def : + (forall (x:Z), (is_sint32 (as_sint32 x))). +Admitted. + +(*Why axiom*) Lemma as_sint32_involve : + (forall (x:Z), (as_sint32 (as_sint32 x)) = (as_sint32 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint32 : + (forall (x:Z), ((is_sint32 x) -> (as_sint32 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint64 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint64 (x:Z) + := 0 <= x /\ x < 18446744073709551616. + +(*Why axiom*) Lemma as_uint64_def : + (forall (x:Z), (is_uint64 (as_uint64 x))). +Admitted. + +(*Why axiom*) Lemma as_uint64_involve : + (forall (x:Z), (as_uint64 (as_uint64 x)) = (as_uint64 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint64 : + (forall (x:Z), ((is_uint64 x) -> (as_uint64 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint64 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint64 (x:Z) + := (-9223372036854775808) <= x /\ x < 9223372036854775808. + +(*Why axiom*) Lemma as_sint64_def : + (forall (x:Z), (is_sint64 (as_sint64 x))). +Admitted. + +(*Why axiom*) Lemma as_sint64_involve : + (forall (x:Z), (as_sint64 (as_sint64 x)) = (as_sint64 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint64 : + (forall (x:Z), ((is_sint64 x) -> (as_sint64 x) = x)). +Admitted. + +(*Why logic*) Definition as_float16 : R -> R. +Admitted. + +(*Why logic*) Definition is_float16 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float16_def : + (forall (x:R), (is_float16 (as_float16 x))). +Admitted. + +(*Why axiom*) Lemma as_float16_involve : + (forall (x:R), (eq (as_float16 (as_float16 x)) (as_float16 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float16 : + (forall (x:R), ((is_float16 x) -> (eq (as_float16 x) x))). +Admitted. + +(*Why logic*) Definition as_float32 : R -> R. +Admitted. + +(*Why logic*) Definition is_float32 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float32_def : + (forall (x:R), (is_float32 (as_float32 x))). +Admitted. + +(*Why axiom*) Lemma as_float32_involve : + (forall (x:R), (eq (as_float32 (as_float32 x)) (as_float32 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float32 : + (forall (x:R), ((is_float32 x) -> (eq (as_float32 x) x))). +Admitted. + +(*Why logic*) Definition as_float64 : R -> R. +Admitted. + +(*Why logic*) Definition is_float64 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float64_def : + (forall (x:R), (is_float64 (as_float64 x))). +Admitted. + +(*Why axiom*) Lemma as_float64_involve : + (forall (x:R), (eq (as_float64 (as_float64 x)) (as_float64 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float64 : + (forall (x:R), ((is_float64 x) -> (eq (as_float64 x) x))). +Admitted. + +(*Why logic*) Definition as_float128 : R -> R. +Admitted. + +(*Why logic*) Definition is_float128 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float128_def : + (forall (x:R), (is_float128 (as_float128 x))). +Admitted. + +(*Why axiom*) Lemma as_float128_involve : + (forall (x:R), (eq (as_float128 (as_float128 x)) (as_float128 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float128 : + (forall (x:R), ((is_float128 x) -> (eq (as_float128 x) x))). +Admitted. + +(*Why type*) Definition data: Set. +Admitted. + +(*Why logic*) Definition data_of_uint8 : Z -> data. +Admitted. + +(*Why logic*) Definition uint8_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint8_of_data : + (forall (d:data), (is_uint8 (uint8_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint8ofdata_dataofuint8 : + (forall (x:Z), ((is_uint8 x) -> (uint8_of_data (data_of_uint8 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint8 : Z -> data. +Admitted. + +(*Why logic*) Definition sint8_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint8_of_data : + (forall (d:data), (is_sint8 (sint8_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint8ofdata_dataofsint8 : + (forall (x:Z), ((is_sint8 x) -> (sint8_of_data (data_of_sint8 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint16 : Z -> data. +Admitted. + +(*Why logic*) Definition uint16_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint16_of_data : + (forall (d:data), (is_uint16 (uint16_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint16ofdata_dataofuint16 : + (forall (x:Z), ((is_uint16 x) -> (uint16_of_data (data_of_uint16 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint16 : Z -> data. +Admitted. + +(*Why logic*) Definition sint16_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint16_of_data : + (forall (d:data), (is_sint16 (sint16_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint16ofdata_dataofsint16 : + (forall (x:Z), ((is_sint16 x) -> (sint16_of_data (data_of_sint16 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint32 : Z -> data. +Admitted. + +(*Why logic*) Definition uint32_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint32_of_data : + (forall (d:data), (is_uint32 (uint32_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint32ofdata_dataofuint32 : + (forall (x:Z), ((is_uint32 x) -> (uint32_of_data (data_of_uint32 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint32 : Z -> data. +Admitted. + +(*Why logic*) Definition sint32_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint32_of_data : + (forall (d:data), (is_sint32 (sint32_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint32ofdata_dataofsint32 : + (forall (x:Z), ((is_sint32 x) -> (sint32_of_data (data_of_sint32 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint64 : Z -> data. +Admitted. + +(*Why logic*) Definition uint64_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint64_of_data : + (forall (d:data), (is_uint64 (uint64_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint64ofdata_dataofuint64 : + (forall (x:Z), ((is_uint64 x) -> (uint64_of_data (data_of_uint64 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint64 : Z -> data. +Admitted. + +(*Why logic*) Definition sint64_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint64_of_data : + (forall (d:data), (is_sint64 (sint64_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint64ofdata_dataofsint64 : + (forall (x:Z), ((is_sint64 x) -> (sint64_of_data (data_of_sint64 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_float16 : R -> data. +Admitted. + +(*Why logic*) Definition float16_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float16_of_data : + (forall (d:data), (is_float16 (float16_of_data d))). +Admitted. + +(*Why axiom*) Lemma float16ofdata_dataoffloat16 : + (forall (x:R), + ((is_float16 x) -> (eq (float16_of_data (data_of_float16 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float32 : R -> data. +Admitted. + +(*Why logic*) Definition float32_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float32_of_data : + (forall (d:data), (is_float32 (float32_of_data d))). +Admitted. + +(*Why axiom*) Lemma float32ofdata_dataoffloat32 : + (forall (x:R), + ((is_float32 x) -> (eq (float32_of_data (data_of_float32 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float64 : R -> data. +Admitted. + +(*Why logic*) Definition float64_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float64_of_data : + (forall (d:data), (is_float64 (float64_of_data d))). +Admitted. + +(*Why axiom*) Lemma float64ofdata_dataoffloat64 : + (forall (x:R), + ((is_float64 x) -> (eq (float64_of_data (data_of_float64 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float128 : R -> data. +Admitted. + +(*Why logic*) Definition float128_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float128_of_data : + (forall (d:data), (is_float128 (float128_of_data d))). +Admitted. + +(*Why axiom*) Lemma float128ofdata_dataoffloat128 : + (forall (x:R), + ((is_float128 x) -> (eq (float128_of_data (data_of_float128 x)) x))). +Admitted. + +(*Why logic*) Definition set_range_index : + forall (A1:Set), (array A1) -> (set Z) -> Z -> (array A1). +Admitted. +Implicit Arguments set_range_index. + +(*Why axiom*) Lemma set_range_def : + forall (A1:Set), + (forall (t:(array A1)), + (forall (rg:(set Z)), + (forall (k:Z), + (forall (i:Z), + (~(member i rg) -> (access (set_range_index t rg k) i) = (access t i)))))). +Admitted. + +(*Why logic*) Definition bnot : Z -> Z. +Admitted. + +(*Why logic*) Definition band : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition bor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition bxor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition lshift : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition rshift : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_not : Z -> Z. +Admitted. + +(*Why logic*) Definition int_and : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_or : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_xor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_lsh : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_rshs : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_rshu : Z -> Z -> Z. +Admitted. + +(*Why type*) Definition format: Set ->Set. +Admitted. + +(*Why logic*) Definition format_size : forall (A1:Set), (format A1) -> Z. +Admitted. +Implicit Arguments format_size. + +(*Why logic*) Definition is_in_format : + forall (A1:Set), (format A1) -> A1 -> Prop. +Admitted. +Implicit Arguments is_in_format. + +(*Why logic*) Definition signed_format : (format Z) -> bool. +Admitted. + +(*Why logic*) Definition uint8_format : (format Z). +Admitted. + +(*Why axiom*) Lemma uint8_format_size : (format_size uint8_format) = 8. +Admitted. + +(*Why axiom*) Lemma uint8_format_sign : (signed_format uint8_format) = false. +Admitted. + +(*Why logic*) Definition sint8_format : (format Z). +Admitted. + +(*Why axiom*) Lemma sint8_format_size : (format_size sint8_format) = 8. +Admitted. + +(*Why axiom*) Lemma sint8_format_sign : (signed_format sint8_format) = true. +Admitted. + +(*Why logic*) Definition uint16_format : (format Z). +Admitted. + +(*Why axiom*) Lemma uint16_format_size : (format_size uint16_format) = 16. +Admitted. + +(*Why axiom*) Lemma uint16_format_sign : + (signed_format uint16_format) = false. +Admitted. + +(*Why logic*) Definition sint16_format : (format Z). +Admitted. + +(*Why axiom*) Lemma sint16_format_size : (format_size sint16_format) = 16. +Admitted. + +(*Why axiom*) Lemma sint16_format_sign : + (signed_format sint16_format) = true. +Admitted. + +(*Why logic*) Definition uint32_format : (format Z). +Admitted. + +(*Why axiom*) Lemma uint32_format_size : (format_size uint32_format) = 32. +Admitted. + +(*Why axiom*) Lemma uint32_format_sign : + (signed_format uint32_format) = false. +Admitted. + +(*Why logic*) Definition sint32_format : (format Z). +Admitted. + +(*Why axiom*) Lemma sint32_format_size : (format_size sint32_format) = 32. +Admitted. + +(*Why axiom*) Lemma sint32_format_sign : + (signed_format sint32_format) = true. +Admitted. + +(*Why logic*) Definition uint64_format : (format Z). +Admitted. + +(*Why axiom*) Lemma uint64_format_size : (format_size uint64_format) = 64. +Admitted. + +(*Why axiom*) Lemma uint64_format_sign : + (signed_format uint64_format) = false. +Admitted. + +(*Why logic*) Definition sint64_format : (format Z). +Admitted. + +(*Why axiom*) Lemma sint64_format_size : (format_size sint64_format) = 64. +Admitted. + +(*Why axiom*) Lemma sint64_format_sign : + (signed_format sint64_format) = true. +Admitted. + +(*Why axiom*) Lemma is_in_format_sint8 : + (forall (x:Z), ((is_in_format sint8_format x) <-> (-128) <= x /\ x < 128)). +Admitted. + +(*Why axiom*) Lemma is_in_format_uint8 : + (forall (x:Z), ((is_in_format uint8_format x) <-> 0 <= x /\ x < 256)). +Admitted. + +(*Why axiom*) Lemma is_in_format_sint16 : + (forall (x:Z), + ((is_in_format sint16_format x) <-> (-32768) <= x /\ x < 32768)). +Admitted. + +(*Why axiom*) Lemma is_in_format_uint16 : + (forall (x:Z), ((is_in_format uint16_format x) <-> 0 <= x /\ x < 65536)). +Admitted. + +(*Why axiom*) Lemma is_in_format_sint32 : + (forall (x:Z), + ((is_in_format sint32_format x) <-> (-2147483648) <= x /\ x < 2147483648)). +Admitted. + +(*Why axiom*) Lemma is_in_format_uint32 : + (forall (x:Z), + ((is_in_format uint32_format x) <-> 0 <= x /\ x < 4294967296)). +Admitted. + +(*Why axiom*) Lemma is_in_format_sint64 : + (forall (x:Z), + ((is_in_format sint64_format x) <-> (-9223372036854775808) <= x /\ x < + 9223372036854775808)). +Admitted. + +(*Why axiom*) Lemma is_in_format_uint64 : + (forall (x:Z), + ((is_in_format uint64_format x) <-> 0 <= x /\ x < 18446744073709551616)). +Admitted. + +(*Why logic*) Definition float16_format : (format R). +Admitted. + +(*Why axiom*) Lemma float16_format_size : (format_size float16_format) = 16. +Admitted. + +(*Why logic*) Definition float32_format : (format R). +Admitted. + +(*Why axiom*) Lemma float32_format_size : (format_size float32_format) = 32. +Admitted. + +(*Why logic*) Definition float64_format : (format R). +Admitted. + +(*Why axiom*) Lemma float64_format_size : (format_size float64_format) = 64. +Admitted. + +(*Why logic*) Definition float96_format : (format R). +Admitted. + +(*Why axiom*) Lemma float96_format_size : (format_size float96_format) = 96. +Admitted. + +(*Why logic*) Definition float128_format : (format R). +Admitted. + +(*Why axiom*) Lemma float128_format_size : + (format_size float128_format) = 128. +Admitted. + +(*Why logic*) Definition encode : forall (A1:Set), (format A1) -> A1 -> data. +Admitted. +Implicit Arguments encode. + +(*Why logic*) Definition decode : forall (A1:Set), (format A1) -> data -> A1. +Admitted. +Implicit Arguments decode. + +(*Why axiom*) Lemma encode_decode : + forall (A1:Set), + (forall (f:(format A1)), (forall (d:data), (encode f (decode f d)) = d)). +Admitted. + +(*Why axiom*) Lemma decode_encode : + forall (A1:Set), + (forall (f:(format A1)), (forall (x:A1), (decode f (encode f x)) = x)). +Admitted. + +(*Why axiom*) Lemma decode_inj : + forall (A1:Set), + (forall (d:data), + (forall (d':data), + (forall (f:(format A1)), (~((decode f d) = (decode f d')) <-> ~(d = d'))))). +Admitted. + +(*Why axiom*) Lemma decode_eq : + forall (A1:Set), + (forall (d:data), + (forall (d':data), + (forall (f:(format A1)), ((decode f d) = (decode f d') <-> d = d')))). +Admitted. + +(*Why logic*) Definition int_format : (format Z). +Admitted. + +(*Why logic*) Definition real_format : (format R). +Admitted. + +(*Why logic*) Definition as_int : (format Z) -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma simpl_as_int : + (forall (f:(format Z)), + (forall (x:Z), ((is_in_format f x) -> (as_int f x) = x))). +Admitted. + +(*Why axiom*) Lemma as_int_def : + (forall (f:(format Z)), (forall (x:Z), (is_in_format f (as_int f x)))). +Admitted. + +(*Why axiom*) Lemma involve_as_int : + (forall (f:(format Z)), + (forall (x:Z), (as_int f (as_int f x)) = (as_int f x))). +Admitted. + +(*Why logic*) Definition as_float : (format R) -> R -> R. +Admitted. + +(*Why axiom*) Lemma simpl_as_float : + (forall (f:(format R)), + (forall (x:R), ((is_in_format f x) -> (eq (as_float f x) x)))). +Admitted. + +(*Why axiom*) Lemma as_float_def : + (forall (f:(format R)), (forall (x:R), (is_in_format f (as_float f x)))). +Admitted. + +(*Why axiom*) Lemma involve_as_float : + (forall (f:(format R)), + (forall (x:R), (eq (as_float f (as_float f x)) (as_float f x)))). +Admitted. + +(*Why type*) Definition zone: Set. +Admitted. + +(*Why logic*) Definition rt_zone : Z -> Z -> zone. +Admitted. + +(*Why logic*) Definition z_addr : zone -> Z. +Admitted. + +(*Why logic*) Definition z_size : zone -> Z. +Admitted. + +(*Why axiom*) Lemma addr_zone : + (forall (a:Z), (forall (sz:Z), (z_addr (rt_zone a sz)) = a)). +Admitted. + +(*Why axiom*) Lemma size_zone : + (forall (a:Z), (forall (sz:Z), (0 <= sz -> (z_size (rt_zone a sz)) = sz))). +Admitted. + +(*Why axiom*) Lemma rt_zone_inj : + (forall (a1:Z), + (forall (a2:Z), + (forall (sz1:Z), + (forall (sz2:Z), + ((rt_zone a1 sz1) = (rt_zone a2 sz2) <-> a1 = a2 /\ sz1 = sz2))))). +Admitted. + +(*Why predicate*) Definition rt_disj (z1:zone) (z2:zone) + := ((z_addr z1) + (z_size z1)) <= (z_addr z2) \/ + ((z_addr z2) + (z_size z2)) <= (z_addr z1). + +(*Why predicate*) Definition rt_incl (z1:zone) (z2:zone) + := (z_addr z2) <= (z_addr z1) /\ ((z_addr z1) + (z_size z1)) <= + ((z_addr z2) + (z_size z2)). + +(*Why predicate*) Definition addr_in_zone (a:Z) (z:zone) + := (z_addr z) <= a /\ a < ((z_addr z) + (z_size z)). + +(*Why function*) Definition rt_shift (addr:Z) (offset:Z) := (addr + offset). + +(*Why logic*) Definition rt_foffset : Z -> Z. +Admitted. + +(*Why logic*) Definition rt_fsize : Z -> Z. +Admitted. + +(*Why logic*) Definition rt_fformat : Z -> (format Z). +Admitted. + +(*Why type*) Definition zones: Set. +Admitted. + +(*Why logic*) Definition zs_empty : zones. +Admitted. + +(*Why logic*) Definition zs_singleton : zone -> zones. +Admitted. + +(*Why logic*) Definition zs_union : zones -> zones -> zones. +Admitted. + +(*Why logic*) Definition zs_incl : zones -> zones -> Prop. +Admitted. + +(*Why logic*) Definition zs_disj : zones -> zones -> Prop. +Admitted. + +(*Why predicate*) Definition zs_z_incl (z:zone) (zs:zones) + := (zs_incl (zs_singleton z) zs). + +(*Why predicate*) Definition zs_z_disj (z:zone) (zs:zones) + := (zs_disj (zs_singleton z) zs). + +(*Why axiom*) Lemma zs_empty_incl : + (forall (zs:zones), (zs_incl zs_empty zs)). +Admitted. + +(*Why axiom*) Lemma zs_z_not_incl_empty : + (forall (z:zone), ~(zs_incl (zs_singleton z) zs_empty)). +Admitted. + +(*Why axiom*) Lemma zs_incl_singleton : + (forall (z1:zone), + (forall (z2:zone), + ((rt_incl z1 z2) <-> (zs_incl (zs_singleton z1) (zs_singleton z2))))). +Admitted. + +(*Why axiom*) Lemma zs_incl_union_1 : + (forall (z:zones), + (forall (z1:zones), + (forall (z2:zones), ((zs_incl z z1) -> (zs_incl z (zs_union z1 z2)))))). +Admitted. + +(*Why axiom*) Lemma zs_incl_union_2 : + (forall (z:zones), + (forall (z1:zones), + (forall (z2:zones), ((zs_incl z z2) -> (zs_incl z (zs_union z1 z2)))))). +Admitted. + +(*Why axiom*) Lemma zs_incl_union_3 : + (forall (z:zones), + (forall (z1:zones), + (forall (z2:zones), + ((zs_incl z1 z) -> ((zs_incl z2 z) -> (zs_incl (zs_union z1 z2) z)))))). +Admitted. + +(*Why axiom*) Lemma zs_disj_singleton : + (forall (z1:zone), + (forall (z2:zone), + ((rt_disj z1 z2) <-> (zs_disj (zs_singleton z1) (zs_singleton z2))))). +Admitted. + +(*Why axiom*) Lemma zs_incl_disj : + (forall (z:zones), + (forall (zi:zones), + (forall (zd:zones), + ((zs_incl zi z) -> ((zs_disj zd z) -> (zs_disj zi zd)))))). +Admitted. + +(*Why type*) Definition bits: Set. +Admitted. + +(*Why logic*) Definition bits_size : bits -> Z. +Admitted. + +(*Why axiom*) Lemma bits_size_pos : (forall (b:bits), (bits_size b) >= 0). +Admitted. + +(*Why logic*) Definition nth_bit : bits -> Z -> bool. +Admitted. + +(*Why axiom*) Lemma eq_bits : + (forall (b1:bits), + (forall (b2:bits), + (forall (sz:Z), + ((bits_size b1) = sz -> + ((bits_size b2) = sz -> + ((forall (i:Z), (0 <= i /\ i < sz -> (nth_bit b1 i) = (nth_bit b2 i))) <-> + b1 = b2)))))). +Admitted. + +(*Why predicate*) Definition zero_bits (b:bits) + := (forall (i:Z), (0 <= i /\ i < (bits_size b) -> (nth_bit b i) = false)). + +(*Why logic*) Definition bits_part : bits -> Z -> Z -> bits. +Admitted. + +(*Why axiom*) Lemma bits_part_size : + (forall (b:bits), + (forall (off:Z), + (forall (sz:Z), + (0 <= off -> + ((off + sz) <= (bits_size b) -> (bits_size (bits_part b off sz)) = sz))))). +Admitted. + +(*Why axiom*) Lemma nth_bits_part : + (forall (b:bits), + (forall (off:Z), + (forall (i:Z), + (forall (sz:Z), + (0 <= i /\ i < sz -> + (0 <= off -> + ((off + sz) <= (bits_size b) -> + (nth_bit (bits_part b off sz) i) = (nth_bit b (off + i))))))))). +Admitted. + +(*Why logic*) Definition bits_concat : bits -> bits -> bits. +Admitted. + +(*Why axiom*) Lemma bits_concat_size : + (forall (b1:bits), + (forall (b2:bits), (bits_size (bits_concat b1 b2)) = + ((bits_size b1) + (bits_size b2)))). +Admitted. + +(*Why axiom*) Lemma nth_bits_concat_l : + (forall (b1:bits), + (forall (b2:bits), + (forall (i:Z), + (0 <= i /\ i < (bits_size b1) -> + (nth_bit (bits_concat b1 b2) i) = (nth_bit b1 i))))). +Admitted. + +(*Why axiom*) Lemma nth_bits_concat_r : + (forall (b1:bits), + (forall (b2:bits), + (forall (i:Z), + (forall (sz1:Z), + (forall (sz2:Z), + (sz1 = (bits_size b1) -> + (sz2 = (bits_size b2) -> + (sz1 <= i /\ i < (sz1 + sz2) -> + (nth_bit (bits_concat b1 b2) i) = (nth_bit b2 (i - sz1)))))))))). +Admitted. + +(*Why logic*) Definition wr_bits_part : bits -> Z -> bits -> bits. +Admitted. + +(*Why axiom*) Lemma wr_bits_part_size : + (forall (b:bits), + (forall (bw:bits), + (forall (o:Z), (bits_size (wr_bits_part b o bw)) = (bits_size b)))). +Admitted. + +(*Why axiom*) Lemma nth_wr_bits_part_1 : + (forall (b:bits), + (forall (b':bits), + (forall (off:Z), + (forall (i:Z), + (0 <= i /\ i < off -> + (nth_bit (wr_bits_part b off b') i) = (nth_bit b i)))))). +Admitted. + +(*Why axiom*) Lemma nth_wr_bits_part_2 : + (forall (b:bits), + (forall (b':bits), + (forall (off:Z), + (forall (i:Z), + ((0 <= off /\ off <= i) /\ i < (off + (bits_size b')) -> + (nth_bit (wr_bits_part b off b') i) = (nth_bit b' (i - off))))))). +Admitted. + +(*Why axiom*) Lemma nth_wr_bits_part_3 : + (forall (b:bits), + (forall (b':bits), + (forall (off:Z), + (forall (i:Z), + ((0 <= (off + (bits_size b')) /\ (off + (bits_size b')) <= i) /\ i < + (bits_size b) -> (nth_bit (wr_bits_part b off b') i) = (nth_bit b i)))))). +Admitted. + +(*Why logic*) Definition rt_from_bits : + forall (A1:Set), bits -> (format A1) -> A1. +Admitted. +Implicit Arguments rt_from_bits. + +(*Why axiom*) Lemma rt_from_bits_format : + forall (A1:Set), + (forall (b:bits), + (forall (fmt:(format A1)), + ((bits_size b) = (format_size fmt) -> + (is_in_format fmt (rt_from_bits b fmt))))). +Admitted. + +(*Why logic*) Definition rt_to_bits : + forall (A1:Set), (format A1) -> A1 -> bits. +Admitted. +Implicit Arguments rt_to_bits. + +(*Why axiom*) Lemma rt_to_bits_size : + forall (A1:Set), + (forall (fmt:(format A1)), + (forall (x:A1), (bits_size (rt_to_bits fmt x)) = (format_size fmt))). +Admitted. + +(*Why axiom*) Lemma rt_to_bits_from_bits : + forall (A1:Set), + (forall (fmt:(format A1)), + (forall (b:bits), + ((bits_size b) = (format_size fmt) -> + (rt_to_bits fmt (rt_from_bits b fmt)) = b))). +Admitted. + +(*Why axiom*) Lemma rt_from_bits_to_bits : + forall (A1:Set), + (forall (fmt:(format A1)), + (forall (v:A1), + ((is_in_format fmt v) -> (rt_from_bits (rt_to_bits fmt v) fmt) = v))). +Admitted. + +(*Why axiom*) Lemma same_int_val_same_bits : + (forall (b1:bits), + (forall (b2:bits), + (forall (fmt:(format Z)), + ((bits_size b1) = (format_size fmt) -> + ((bits_size b2) = (format_size fmt) -> + ((rt_from_bits b1 fmt) = (rt_from_bits b2 fmt) -> b1 = b2)))))). +Admitted. + +(*Why axiom*) Lemma rt_to_bits_zero : + (forall (fmt:(format Z)), + (forall (b:bits), (b = (rt_to_bits fmt 0) -> (zero_bits b)))). +Admitted. + +(*Why axiom*) Lemma rt_from_bits_zero : + (forall (b:bits), + (forall (fmt:(format Z)), ((zero_bits b) -> (rt_from_bits b fmt) = 0))). +Admitted. + +(*Why logic*) Definition mbyte_to_bbits : bits -> (array bool). +Admitted. + +(*Why axiom*) Lemma mbyte_to_bbits_def : + (forall (b:bits), + ((bits_size b) = 8 -> + (forall (i:Z), + (0 <= i /\ i < 8 -> (access (mbyte_to_bbits b) i) = (nth_bit b (7 - i)))))). +Admitted. + +(*Why logic*) Definition nth_mbyte : Z -> bits -> bits. +Admitted. + +(*Why axiom*) Lemma nth_mbyte_size : + (forall (b:bits), (forall (k:Z), (bits_size (nth_mbyte k b)) = 8)). +Admitted. + +(*Why axiom*) Lemma nth_byte_def : + (forall (b:bits), + (forall (k:Z), + (0 <= (8 * (k + 1)) /\ (8 * (k + 1)) <= (bits_size b) -> + (forall (i:Z), + (0 <= i /\ i < 8 -> + (nth_bit (nth_mbyte k b) i) = (nth_bit b (8 * k + i))))))). +Admitted. + +(*Why function*) Definition nth_byte (k:Z) (b:bits) + := (mbyte_to_bbits (nth_mbyte k b)). + +(*Why logic*) Definition little_endian : Prop. +Admitted. + +(*Why logic*) Definition concat_bytes : + (array bool) -> (array bool) -> (array bool). +Admitted. + +(*Why axiom*) Lemma concat_bytes_left : + (forall (w:(array bool)), + (forall (b:(array bool)), + (forall (i:Z), + (8 <= i -> (access (concat_bytes w b) i) = (access w (i - 8)))))). +Admitted. + +(*Why axiom*) Lemma concat_bytes_right : + (forall (w:(array bool)), + (forall (b:(array bool)), + (forall (i:Z), + (0 <= i /\ i < 8 -> (access (concat_bytes w b) i) = (access b i))))). +Admitted. + +(*Why logic*) Definition uint_of_bits : Z -> (array bool) -> Z. +Admitted. + +(*Why logic*) Definition sint_of_bits : Z -> (array bool) -> Z. +Admitted. + +(*Why function*) Definition cint_of_bits (fmt:(format Z)) (b:(array bool)) + := (if_then_else (signed_format fmt) + (sint_of_bits ((format_size fmt) - 1) b) + (uint_of_bits ((format_size fmt) - 1) b)). + +(*Why logic*) Definition bits_of_sint : Z -> Z -> (array bool). +Admitted. + +(*Why logic*) Definition bits_of_uint : Z -> Z -> (array bool). +Admitted. + +(*Why function*) Definition bits_of_cint (fmt:(format Z)) (x:Z) + := (if_then_else (signed_format fmt) + (bits_of_sint ((format_size fmt) - 1) x) + (bits_of_uint ((format_size fmt) - 1) x)). + +(*Why logic*) Definition mbits_to_bbits : bits -> (array bool). +Admitted. + +(*Why axiom*) Lemma mb8_to_bbits : + (forall (b:bits), + ((bits_size b) = 8 -> (mbits_to_bbits b) = (nth_byte 0 b))). +Admitted. + +(*Why axiom*) Lemma little_mb16_to_bbits : + (forall (b:bits), + ((bits_size b) = 16 -> + (little_endian -> + (mbits_to_bbits b) = (concat_bytes (nth_byte 1 b) (nth_byte 0 b))))). +Admitted. + +(*Why axiom*) Lemma big_mb16_to_bbits : + (forall (b:bits), + ((bits_size b) = 16 -> + (~little_endian -> + (mbits_to_bbits b) = (concat_bytes (nth_byte 0 b) (nth_byte 1 b))))). +Admitted. + +(*Why axiom*) Lemma little_mb32_to_bbits : + (forall (b:bits), + ((bits_size b) = 32 -> + (little_endian -> + (mbits_to_bbits b) = + (concat_bytes + (concat_bytes + (concat_bytes (nth_byte 3 b) (nth_byte 2 b)) (nth_byte 1 b)) ( + nth_byte 0 b))))). +Admitted. + +(*Why axiom*) Lemma big_mb32_to_bbits : + (forall (b:bits), + ((bits_size b) = 32 -> + (~little_endian -> + (mbits_to_bbits b) = + (concat_bytes + (concat_bytes + (concat_bytes (nth_byte 0 b) (nth_byte 1 b)) (nth_byte 2 b)) ( + nth_byte 3 b))))). +Admitted. + +(*Why axiom*) Lemma rt_int_from_bits : + (forall (b:bits), + (forall (fmt:(format Z)), (rt_from_bits b fmt) = + (cint_of_bits fmt (mbits_to_bbits b)))). +Admitted. + +(*Why logic*) Definition bbits_to_mbyte : Z -> (array bool) -> bits. +Admitted. + +(*Why axiom*) Lemma bbits_to_mbyte_size : + (forall (b:(array bool)), + (forall (k:Z), (bits_size (bbits_to_mbyte k b)) = 8)). +Admitted. + +(*Why axiom*) Lemma bbits_to_mbyte_def : + (forall (b:(array bool)), + (forall (k:Z), + (forall (i:Z), + (0 <= i /\ i < 8 -> + (nth_bit (bbits_to_mbyte k b) i) = (access b (8 * k + 7 - i)))))). +Admitted. + +(*Why logic*) Definition bbits_to_mbits : Z -> (array bool) -> bits. +Admitted. + +(*Why axiom*) Lemma bbits_to_mb8 : + (forall (b:(array bool)), (bbits_to_mbits 8 b) = (bbits_to_mbyte 0 b)). +Admitted. + +(*Why axiom*) Lemma bbits_to_little_mb16 : + (forall (b:(array bool)), + (little_endian -> + (bbits_to_mbits 16 b) = + (bits_concat (bbits_to_mbyte 0 b) (bbits_to_mbyte 1 b)))). +Admitted. + +(*Why axiom*) Lemma bbits_to_big_mb16 : + (forall (b:(array bool)), + (~little_endian -> + (bbits_to_mbits 16 b) = + (bits_concat (bbits_to_mbyte 1 b) (bbits_to_mbyte 0 b)))). +Admitted. + +(*Why axiom*) Lemma bbits_to_little_mb32 : + (forall (b:(array bool)), + (little_endian -> + (bbits_to_mbits 32 b) = + (bits_concat + (bbits_to_mbyte 0 b) (bits_concat + (bbits_to_mbyte 1 b) (bits_concat + (bbits_to_mbyte 2 b) ( + bbits_to_mbyte 3 b)))))). +Admitted. + +(*Why axiom*) Lemma bbits_to_not_mb32 : + (forall (b:(array bool)), + (~little_endian -> + (bbits_to_mbits 32 b) = + (bits_concat + (bbits_to_mbyte 3 b) (bits_concat + (bbits_to_mbyte 2 b) (bits_concat + (bbits_to_mbyte 1 b) ( + bbits_to_mbyte 0 b)))))). +Admitted. + +(*Why axiom*) Lemma rt_int_to_bits : + (forall (x:Z), + (forall (fmt:(format Z)), + (rt_to_bits fmt x) = + (bbits_to_mbits (format_size fmt) (bits_of_cint fmt x)))). +Admitted. + +(*Why type*) Definition memory: Set. +Admitted. + +(*Why type*) Definition memalloc: Set. +Admitted. + +(*Why logic*) Definition rt_valid : memalloc -> zone -> Prop. +Admitted. + +(*Why axiom*) Lemma incl_valid : + (forall (m:memalloc), + (forall (z:zone), + (forall (z':zone), + ((rt_incl z' z) -> ((rt_valid m z) -> (rt_valid m z')))))). +Admitted. + +(*Why axiom*) Lemma disj_valid : + (forall (m:memalloc), + (forall (z:zone), + (forall (z':zone), + ((rt_valid m z) -> (~(rt_valid m z') -> (rt_disj z z')))))). +Admitted. + +(*Why logic*) Definition rt_zbase : memalloc -> Z -> zone. +Admitted. + +(*Why function*) Definition rt_abase (m:memalloc) (addr:Z) + := (z_addr (rt_zbase m addr)). + +(*Why logic*) Definition rt_block_length : memalloc -> Z -> Z. +Admitted. + +(*Why type*) Definition mz: Set. +Admitted. + +(*Why logic*) Definition mem_of_mz : mz -> memalloc. +Admitted. + +(*Why logic*) Definition addr_of_mz : mz -> Z. +Admitted. + +(*Why logic*) Definition rt_alloc : memalloc -> Z -> mz. +Admitted. + +(*Why function*) Definition alloc_zone (m:memalloc) (sz:Z) + := (rt_zone (addr_of_mz (rt_alloc m sz)) sz). + +(*Why axiom*) Lemma alloc_is_base : + (forall (m:memalloc), + (forall (sz:Z), + let mz := (rt_alloc m sz) in + (rt_zbase (mem_of_mz mz) (addr_of_mz mz)) = (alloc_zone m sz))). +Admitted. + +(*Why axiom*) Lemma valid_alloc : + (forall (m:memalloc), + (forall (sz:Z), + let mz := (rt_alloc m sz) in + (rt_valid (mem_of_mz mz) (alloc_zone m sz)))). +Admitted. + +(*Why axiom*) Lemma not_valid_before_alloc : + (forall (m:memalloc), (forall (sz:Z), ~(rt_valid m (alloc_zone m sz)))). +Admitted. + +(*Why axiom*) Lemma alloc_keep_valid : + (forall (m:memalloc), + (forall (sz:Z), + (forall (z:zone), + ((rt_valid m z) -> + let mz := (rt_alloc m sz) in + (rt_valid (mem_of_mz mz) z))))). +Admitted. + +(*Why axiom*) Lemma alloc_keep_invalid : + (forall (m:memalloc), + (forall (sz:Z), + (forall (z:zone), + let mz := (rt_alloc m sz) in + ((rt_valid (mem_of_mz mz) z) -> + ((rt_disj (alloc_zone m sz) z) -> (rt_valid m z)))))). +Admitted. + +(*Why logic*) Definition rt_free : memalloc -> Z -> memalloc. +Admitted. + +(*Why axiom*) Lemma not_valid_after_free : + (forall (m:memalloc), + (forall (addr:Z), + (forall (z:zone), + (z = (rt_zbase m addr) -> + (addr = (z_addr z) -> ~(rt_valid (rt_free m addr) z)))))). +Admitted. + +(*Why axiom*) Lemma valid_free_disj : + (forall (m:memalloc), + (forall (z:zone), + (forall (z':zone), + ((rt_valid (rt_free m (z_addr z)) z') <-> (rt_disj z z'))))). +Admitted. + +(*Why logic*) Definition rt_vaddr : memalloc -> Z -> Z. +Admitted. + +(*Why logic*) Definition rt_vsize : Z -> Z. +Admitted. + +(*Why function*) Definition rt_vzone (ma:memalloc) (var:Z) + := (rt_zone (rt_vaddr ma var) (rt_vsize var)). + +(*Why logic*) Definition rt_global : Z -> Prop. +Admitted. + +(*Why axiom*) Lemma rt_global_vaddr : + (forall (v:Z), + ((rt_global v) -> + (forall (ma:memalloc), + (forall (ma':memalloc), (rt_vaddr ma v) = (rt_vaddr ma' v))))). +Admitted. + +(*Why axiom*) Lemma rt_global_valid : + (forall (ma:memalloc), + (forall (v:Z), + ((rt_global v) -> + (forall (ma:memalloc), + (forall (ma':memalloc), (rt_valid ma (rt_vzone ma' v))))))). +Admitted. + +(*Why axiom*) Lemma vzone_disj : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v2:Z), + (v1 <> v2 -> + let z1 := (rt_vzone ma v1) in + let z2 := (rt_vzone ma v2) in + ((rt_valid ma z1) -> ((rt_valid ma z2) -> (rt_disj z1 z2))))))). +Admitted. + +(*Why logic*) Definition rt_valloc : memalloc -> Z -> memalloc. +Admitted. + +(*Why axiom*) Lemma rt_valloc_mem : + (forall (ma:memalloc), + (forall (var:Z), + (rt_valloc ma var) = (mem_of_mz (rt_alloc ma (rt_vsize var))))). +Admitted. + +(*Why axiom*) Lemma rt_valloc_addr : + (forall (ma:memalloc), + (forall (var:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma var) -> + (forall (mz:mz), + (mz = (rt_alloc ma (rt_vsize var)) -> (rt_vaddr ma' var) = + (addr_of_mz mz))))))). +Admitted. + +(*Why axiom*) Lemma vzone_valloc_neq : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v2:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v1) -> + (v1 <> v2 -> (rt_vzone ma' v2) = (rt_vzone ma v2))))))). +Admitted. + +(*Why function*) Definition rt_vfree (ma:memalloc) (var:Z) + := (rt_free ma (rt_vaddr ma var)). + +(*Why axiom*) Lemma rt_vaddr_vfree : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v2:Z), + (v1 <> v2 -> (rt_vaddr (rt_vfree ma v1) v2) = (rt_vaddr ma v2))))). +Admitted. + +(*Why axiom*) Lemma addr_base : + (forall (m:memalloc), + (forall (v:Z), (rt_abase m (rt_vaddr m v)) = (rt_vaddr m v))). +Admitted. + +(*Why logic*) Definition rt_load : memory -> zone -> bits. +Admitted. + +(*Why logic*) Definition rt_store : memory -> Z -> bits -> memory. +Admitted. + +(*Why axiom*) Lemma load_store_same : + (forall (m:memory), + (forall (a:Z), + (forall (z:zone), + (forall (v:bits), + (z = (rt_zone a (bits_size v)) -> (rt_load (rt_store m a v) z) = v))))). +Admitted. + +(*Why axiom*) Lemma load_store_disj : + (forall (m:memory), + (forall (a:Z), + (forall (z:zone), + (forall (v:bits), + ((rt_disj (rt_zone a (bits_size v)) z) -> + (rt_load (rt_store m a v) z) = (rt_load m z)))))). +Admitted. + +(*Why axiom*) Lemma load_store_incl_part : + (forall (m:memory), + (forall (a:Z), + (forall (z1:zone), + (forall (z2:zone), + (forall (v:bits), + (z2 = (rt_zone a (bits_size v)) -> + ((rt_incl z1 z2) -> + (rt_load (rt_store m a v) z1) = + (bits_part v ((z_addr z1) - a) (z_size z1))))))))). +Admitted. + +(*Why axiom*) Lemma load_incl_part_store : + (forall (m:memory), + (forall (z1:zone), + (forall (z2:zone), + (forall (v:bits), + (forall (a:Z), + (z1 = (rt_zone a (bits_size v)) -> + (forall (off:Z), + (off = (a - (z_addr z2)) -> + ((rt_incl z1 z2) -> + (rt_load (rt_store m a v) z2) = + (wr_bits_part (rt_load m z2) off v)))))))))). +Admitted. + +(*Why axiom*) Lemma rt_load_size : + (forall (m:memory), + (forall (z:zone), (bits_size (rt_load m z)) = (z_size z))). +Admitted. + +(*Why axiom*) Lemma bits_part_rt_load : + (forall (z:zone), + (forall (z':zone), + (forall (a':Z), + (forall (off:Z), + (forall (sz:Z), + (a' = ((z_addr z) + off) -> + (z' = (rt_zone a' sz) -> + ((rt_incl z' z) -> + (forall (m:memory), + (rt_load m z') = (bits_part (rt_load m z) off sz)))))))))). +Admitted. + +(*Why axiom*) Lemma rt_same_mem : + (forall (m1:memory), + (forall (m2:memory), + ((forall (z:zone), (rt_load m1 z) = (rt_load m2 z)) -> m1 = m2))). +Admitted. + +(*Why logic*) Definition rt_havoc : memory -> zone -> memory. +Admitted. + +(*Why predicate*) Definition rt_is_havoc (ma:memalloc) (m1:memory) (zs:zones) (m2:memory) + := (forall (z:zone), + ((rt_valid ma z) -> + ((zs_z_disj z zs) -> (rt_load m1 z) = (rt_load m2 z)))). + +(*Why axiom*) Lemma rt_havoc_is_havoc : + (forall (ma:memalloc), + (forall (m:memory), + (forall (zs:zones), + (forall (z:zone), + ((zs_z_incl z zs) -> (rt_is_havoc ma m zs (rt_havoc m z))))))). +Admitted. + +(*Why logic*) Definition rt_addr_format : (format Z). +Admitted. + +(*Why axiom*) Lemma rt_vaddr_format : + (forall (ma:memalloc), + (forall (v:Z), (is_in_format rt_addr_format (rt_vaddr ma v)))). +Admitted. + +(*Why axiom*) Lemma bits_part_vs_access : + (forall (bs:bits), + (forall (fs:(format (array data))), + (forall (f:Z), + (forall (off:Z), + (forall (sz:Z), + (off = (rt_foffset f) -> + (sz = (rt_fsize f) -> + (rt_from_bits (bits_part bs off sz) (rt_fformat f)) = + (decode int_format (access (rt_from_bits bs fs) f))))))))). +Admitted. + +(*Why logic*) Definition rt_addr_lt : Z -> Z -> Prop. +Admitted. + +(*Why logic*) Definition rt_addr_le : Z -> Z -> Prop. +Admitted. + +(*Why logic*) Definition rt_addr_lt_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition rt_addr_le_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition rt_addr_minus : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition rt_addr_eq : Z -> Z -> Prop. +Admitted. + +(*Why logic*) Definition rt_addr_eq_bool : Z -> Z -> bool. +Admitted. + +(*Why axiom*) Lemma rt_disj_sym : + (forall (z1:zone), + (forall (z2:zone), ((rt_disj z1 z2) <-> (rt_disj z2 z1)))). +Admitted. + +(*Why axiom*) Lemma rt_disj_shift : + (forall (addr:Z), + (forall (i:Z), + (forall (j:Z), + (forall (sz:Z), + (sz > 0 -> + (i <> j -> + (rt_disj + (rt_zone (rt_shift addr (i * sz)) sz) (rt_zone + (rt_shift addr (j * sz)) sz)))))))). +Admitted. + +(*Why axiom*) Lemma vzone_of_zone : + (forall (ma:memalloc), + (forall (v:Z), + (forall (a:Z), + (forall (sz:Z), + (a = (rt_vaddr ma v) -> + (sz = (rt_vsize v) -> (rt_zone a sz) = (rt_vzone ma v))))))). +Admitted. + +(*Why axiom*) Lemma bits_part_full : + (forall (v:bits), + (forall (sz:Z), (sz = (bits_size v) -> (bits_part v 0 sz) = v))). +Admitted. + +(*Why axiom*) Lemma bits_part_of_bits_part : + (forall (b:bits), + (forall (o1:Z), + (forall (o2:Z), + (forall (sz1:Z), + (forall (sz2:Z), + (0 <= o1 -> + ((o1 + sz1) <= (bits_size b) -> + (0 <= o2 -> + ((o2 + sz2) <= sz1 -> + (bits_part (bits_part b o1 sz1) o2 sz2) = + (bits_part b (o1 + o2) sz2)))))))))). +Admitted. + +(*Why axiom*) Lemma eq_bits_split : + (forall (b1:bits), + (forall (b2:bits), + (forall (sz:Z), + ((bits_size b1) = sz -> + ((bits_size b2) = sz -> + (forall (sz1:Z), + (forall (sz2:Z), + (sz1 >= 0 -> + (sz2 >= 0 -> + ((sz1 + sz2) = sz -> + ((bits_part b1 0 sz1) = (bits_part b2 0 sz1) -> + ((bits_part b1 sz1 sz2) = (bits_part b2 sz1 sz2) -> b1 = b2)))))))))))). +Admitted. + +(*Why axiom*) Lemma wr_bits_part_all : + (forall (v:bits), + (forall (v':bits), + ((bits_size v) = (bits_size v') -> (wr_bits_part v 0 v') = v'))). +Admitted. + +(*Why axiom*) Lemma wr_bits_part_concat : + (forall (b:bits), + (forall (b':bits), + (forall (sz1:Z), + (forall (sz2:Z), + (forall (sz3:Z), + (0 <= sz1 -> + (sz2 = (bits_size b') -> + (0 <= sz3 -> + ((sz1 + sz2 + sz3) = (bits_size b) -> + (wr_bits_part b sz1 b') = + (bits_concat + (bits_part b 0 sz1) (bits_concat b' (bits_part b (sz1 + sz2) sz3)))))))))))). +Admitted. + +(*Why axiom*) Lemma wr_bits_part_same : + (forall (b1:bits), + (forall (b2:bits), + (forall (off:Z), + (0 <= off -> + ((off + (bits_size b2)) <= (bits_size b1) -> + (bits_part (wr_bits_part b1 off b2) off (bits_size b2)) = b2))))). +Admitted. + +(*Why axiom*) Lemma wr_bits_part_disj : + (forall (b:bits), + (forall (b1:bits), + (forall (off2:Z), + (forall (off1:Z), + (forall (sz:Z), + (forall (sz1:Z), + (forall (sz2:Z), + (sz = (bits_size b) -> + (sz1 = (bits_size b1) -> + (0 <= off1 -> + ((off1 + sz1) <= sz -> + (0 <= off2 -> + ((off2 + sz2) <= sz -> + ((off2 + sz2) <= off1 \/ (off1 + sz1) <= off2 -> + (bits_part (wr_bits_part b off1 b1) off2 sz2) = + (bits_part b off2 sz2))))))))))))))). +Admitted. + +(*Why axiom*) Lemma rt_z_from_bits_to_bits_zero : + (forall (fmt:(format Z)), + (forall (fmt':(format Z)), (rt_from_bits (rt_to_bits fmt 0) fmt') = 0)). +Admitted. + +(*Why axiom*) Lemma bits_part_zero : + (forall (b:bits), + (forall (b':bits), + (forall (off:Z), + (forall (sz:Z), + (0 <= off -> + ((off + sz) <= (bits_size b) -> + (b' = (bits_part b off sz) -> ((zero_bits b) -> (zero_bits b'))))))))). +Admitted. + +(*Why axiom*) Lemma rw_same_var : + (forall (m:memory), + (forall (ma:memalloc), + (forall (v:Z), + (forall (val:bits), + ((bits_size val) = (rt_vsize v) -> + (rt_load (rt_store m (rt_vaddr ma v) val) (rt_vzone ma v)) = val))))). +Admitted. + +(*Why axiom*) Lemma rw_disj_var : + (forall (ma:memalloc), + (forall (m:memory), + (forall (v1:Z), + (forall (v2:Z), + (forall (z1:zone), + (forall (z2:zone), + (forall (b:bits), + (v1 <> v2 -> + (z1 = (rt_vzone ma v1) -> + (z2 = (rt_vzone ma v2) -> + ((rt_valid ma z1) -> + ((rt_valid ma z2) -> + ((rt_vsize v2) = (bits_size b) -> + (rt_load (rt_store m (rt_vaddr ma v2) b) z1) = (rt_load m z1)))))))))))))). +Admitted. + +(*Why axiom*) Lemma store_concat : + (forall (m:memory), + (forall (m1:memory), + (forall (a:Z), + (forall (b1:bits), + (forall (b2:bits), + (forall (sz1:Z), + (sz1 = (bits_size b1) -> + (m1 = (rt_store m a b1) -> + (rt_store m1 (a + sz1) b2) = (rt_store m a (bits_concat b1 b2)))))))))). +Admitted. + +(*Why axiom*) Lemma store_disj_commut : + (forall (m:memory), + (forall (a1:Z), + (forall (a2:Z), + (forall (b1:bits), + (forall (b2:bits), + ((rt_disj (rt_zone a1 (bits_size b1)) (rt_zone a2 (bits_size b2))) -> + (rt_store (rt_store m a1 b1) a2 b2) = + (rt_store (rt_store m a2 b2) a1 b1))))))). +Admitted. + +(*Why axiom*) Lemma not_valid_before_valloc : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> ~(rt_valid ma (rt_vzone ma' v)))))). +Admitted. + +(*Why axiom*) Lemma valid_valloc : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> (rt_valid ma' (rt_vzone ma' v)))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_valid_zone : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (forall (z:zone), ((rt_valid ma z) -> (rt_valid ma' z))))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_valid_disj_zone : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (forall (z:zone), + ((rt_disj (rt_vzone ma' v) z) -> ((rt_valid ma' z) -> (rt_valid ma z)))))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_invalid_zone : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (forall (z:zone), + ((rt_disj (rt_vzone ma' v) z) -> + (~(rt_valid ma z) -> ~(rt_valid ma' z)))))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_invalid_zone_rev : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (forall (z:zone), + ((rt_disj (rt_vzone ma' v) z) -> + (~(rt_valid ma' z) -> ~(rt_valid ma z)))))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_valid_var : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (v <> v1 -> + ((rt_valid ma (rt_vzone ma v1)) -> (rt_valid ma' (rt_vzone ma' v1))))))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_vaddr : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (v <> v1 -> (rt_vaddr ma' v1) = (rt_vaddr ma v1))))))). +Admitted. + +(*Why axiom*) Lemma valloc_keep_vzone : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_valloc ma v) -> + (v <> v1 -> (rt_vzone ma' v1) = (rt_vzone ma v1))))))). +Admitted. + +(*Why axiom*) Lemma vzone_vfree : + (forall (ma:memalloc), + (forall (v1:Z), + (forall (v2:Z), + (forall (ma':memalloc), + (ma' = (rt_vfree ma v1) -> + (v1 <> v2 -> (rt_vzone ma' v2) = (rt_vzone ma v2))))))). +Admitted. + +(*Why axiom*) Lemma not_valid_after_vfree : + (forall (ma:memalloc), + (forall (v:Z), + (forall (ma':memalloc), + (ma' = (rt_vfree ma v) -> + (forall (z:zone), (z = (rt_vzone ma v) -> ~(rt_valid ma' z))))))). +Admitted. + +(*Why axiom*) Lemma havoc_store : + (forall (ma:memalloc), + (forall (m1:memory), + (forall (m2:memory), + (forall (zs:zones), + (forall (z:zone), + (forall (x:bits), + (forall (a:Z), + (z = (rt_zone a (bits_size x)) -> + ((rt_is_havoc ma m1 zs m2) -> + ((zs_z_incl z zs) -> (rt_is_havoc ma m1 zs (rt_store m2 a x)))))))))))). +Admitted. + +(*Why axiom*) Lemma havoc_invalid : + (forall (ma:memalloc), + (forall (m1:memory), + (forall (m2:memory), + (forall (zs:zones), + (forall (z:zone), + (forall (x:bits), + (forall (a:Z), + (z = (rt_zone a (bits_size x)) -> + ((rt_is_havoc ma m1 zs m2) -> + (~(rt_valid ma z) -> (rt_is_havoc ma m1 zs (rt_store m2 a x)))))))))))). +Admitted. + +(*Why axiom*) Lemma same_bits_same_val : + forall (A1:Set), + (forall (b1:bits), + (forall (b2:bits), + (forall (fmt:(format A1)), + (b1 = b2 -> (rt_from_bits b1 fmt) = (rt_from_bits b2 fmt))))). +Admitted. + +(*Why axiom*) Lemma valid_vglob : + (forall (v:Z), + ((rt_global v) -> + (forall (ma:memalloc), + (forall (ma':memalloc), (rt_valid ma (rt_vzone ma' v)))))). +Admitted. + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/runtime_model.why frama-c-20111001+nitrogen+dfsg/src/wp/share/runtime_model.why --- frama-c-20110201+carbon+dfsg/src/wp/share/runtime_model.why 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/runtime_model.why 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,1514 @@ +(* --- Headers for WHY --- *) + +include "bool.why" +include "integer.why" +include "real.why" +include "arrays.why" +include "divisions.why" +(* -------------------------------------------------------------------------- *) +(* --- ACSL Definitions --- *) +(* -------------------------------------------------------------------------- *) + +logic dummy : int -> prop +logic assigns : int -> prop + + +(* -------------------------------------------------------------------------- *) +(* --- Divisions enhanced specification --- *) +(* -------------------------------------------------------------------------- *) + +axiom positive_computer_div_div: + forall x,y:int. + x >0 -> y >0 -> computer_div(x,y) = math_div(x,y) + + +(**************************************************************************) +(*** Specification of Set as First Class Value ***) +(**************************************************************************) +(* From Figure 2.6 in ACSL:ANSI/ISO C Specification Language *) + +type 'a set + +logic empty : 'a set +logic singleton : 'a -> 'a set +logic range : int,int -> int set +logic union : 'a set , 'a set -> 'a set +logic inter : 'a set , 'a set -> 'a set +logic plus_int : int set, int set -> int set +logic subset : 'a set,'a set -> prop +logic range_inf: int -> int set +logic range_sup:int->int set +logic integers_set : int set +logic equiv : 'a set ,'a set -> prop +logic member : 'a,'a set -> prop + +axiom singleton_def : + forall x:'a. member (x, singleton(x)) + +axiom singleton_eq: + forall x,y:'a. member(x,singleton(y)) <-> x=y + +axiom union_member : + forall x:'a. forall s1,s2:'a set [member(x, union(s1,s2))]. + member(x, union(s1,s2)) <-> member(x,s1) or member(x,s2) + +axiom union_of_empty : + forall x:'a set [union(x,empty)]. union(x,empty) = x + +axiom inter_of_empty : + forall x:'a set [inter(x,empty)]. inter(x,empty) = empty + +axiom union_comm : + forall x,y:'a set. union(x,y) = union(y,x) + +axiom inter_comm : + forall x,y:'a set. inter(x,y) = inter(y,x) + +axiom inter_member : + forall x:'a. forall s1,s2:'a set [member(x,inter(s1,s2))]. + member(x,inter(s1,s2)) <-> member(x,s1) and member(x,s2) + +axiom plus_int_member_1: + forall sa,sb:int set. + forall a,b:int [member((a+b), plus_int(sa,sb))]. + member(a,sa) -> member(b,sb) -> + member((a+b), plus_int(sa,sb)) + +axiom plus_int_member_2: + forall sa,sb:int set. + forall c:int. + member(c,plus_int(sa,sb)) -> + exists a:int. exists b:int. + member(a,sa) and member(b,sb) and c=a+b + +axiom subset_empty : + forall sa:'a set. subset(empty,sa) + +axiom subset_sym: + forall sa:'a set. subset(sa,sa) + +axiom subset_trans : + forall sa,sb,sc: 'a set. + subset(sa,sb) -> + subset(sb,sc) -> + subset(sa,sc) + +axiom subset_def: + forall sa,sb:'a set [subset(sa,sb)]. + (forall a:'a. member(a,sa) -> member(a,sb)) <-> subset(sa,sb) + + +axiom range_def: + forall i,j,k:int. i <= k<= j <-> member (k,range(i,j)) + +axiom range_def1: + forall i,j,k:int. i <= k<= j -> member (k,range(i,j)) + +axiom range_def2: + forall i,j,k:int.member (k,range(i,j)) -> i <= k<= j + +axiom range_inf_def: (* range_inf(i) is [ i .. ] *) + forall i,k: int. i <= k <-> member (k,range_inf(i)) + +axiom range_sup_def: (* range_sup(j) is [ .. j ] *) + forall j,k: int. k <= j <-> member (k,range_sup(j)) + +axiom integers_set_def: + forall k:int. k >= 0 <-> member(k,integers_set) + +axiom equiv_def: + forall s1,s2:'a set [equiv(s1,s2)]. ( + (forall a:'a. member(a,s1) -> member(a,s2)) and + (forall b:'a. member(b,s2) -> member(b,s1))) <-> + equiv(s1,s2) + +axiom equiv_refl: + forall s:'a set. equiv(s,s) + +axiom equiv_sym: + forall s1,s2:'a set. equiv(s1,s2) -> equiv(s2,s1) + +axiom equiv_trans: + forall s1,s2,s3:'a set. + equiv(s1,s2) -> equiv(s2,s3) -> equiv(s1,s3) + + + +(**************************************************************************) +(*** Integers and Reals ***) +(**************************************************************************) + + +logic as_uint8 :int -> int +predicate is_uint8(x:int) = 0 <= x < 256 +axiom as_uint8_def : forall x:int. is_uint8(as_uint8(x)) +axiom as_uint8_involve : + forall x:int [as_uint8(as_uint8(x))]. as_uint8(as_uint8(x)) = as_uint8(x) +axiom is_as_uint8: forall x:int [as_uint8(x)]. is_uint8(x) -> as_uint8(x) = x + +logic as_sint8 :int -> int +predicate is_sint8(x:int) = -128 <= x < 128 +axiom as_sint8_def : forall x:int. is_sint8(as_sint8(x)) +axiom as_sint8_involve : + forall x:int [as_sint8(as_sint8(x))]. as_sint8(as_sint8(x)) = as_sint8(x) +axiom is_as_sint8: forall x:int[as_sint8(x)]. is_sint8(x) -> as_sint8(x) = x + + +logic as_uint16 :int -> int +predicate is_uint16(x:int) = 0 <= x < 65536 +axiom as_uint16_def : forall x:int. is_uint16(as_uint16(x)) +axiom as_uint16_involve : + forall x:int [as_uint16(as_uint16(x))]. + as_uint16(as_uint16(x)) = as_uint16(x) +axiom is_as_uint16: forall x:int [as_uint16(x)]. is_uint16(x) -> as_uint16(x) = x + +logic as_sint16 :int -> int +predicate is_sint16(x:int) = -32768 <= x < 32768 +axiom as_sint16_def : forall x:int. is_sint16(as_sint16(x)) +axiom as_sint16_involve : + forall x:int [as_sint16(as_sint16(x))]. + as_sint16(as_sint16(x)) = as_sint16(x) +axiom is_as_sint16: forall x:int [as_sint16(x)]. is_sint16(x) -> as_sint16(x) = x + + +logic as_uint32 :int -> int +predicate is_uint32(x:int) = 0 <= x < 4294967296 +axiom as_uint32_def : forall x:int. is_uint32(as_uint32(x)) +axiom as_uint32_involve : + forall x:int [as_uint32(as_uint32(x))]. + as_uint32(as_uint32(x)) = as_uint32(x) +axiom is_as_uint32: forall x:int [as_uint32(x)]. is_uint32(x) -> as_uint32(x) = x + +logic as_sint32 :int -> int +predicate is_sint32(x:int) = -2147483648 <= x < 2147483648 +axiom as_sint32_def : forall x:int. is_sint32(as_sint32(x)) +axiom as_sint32_involve : + forall x:int [as_sint32(as_sint32(x))]. + as_sint32(as_sint32(x)) = as_sint32(x) +axiom is_as_sint32: forall x:int [as_sint32(x)]. is_sint32(x) -> as_sint32(x) = x + + +logic as_uint64 :int -> int +predicate is_uint64(x:int) = 0 <= x < 18446744073709551616 +axiom as_uint64_def : forall x:int. is_uint64(as_uint64(x)) +axiom as_uint64_involve : + forall x:int [as_uint64(as_uint64(x))]. + as_uint64(as_uint64(x)) = as_uint64(x) +axiom is_as_uint64: forall x:int [as_uint64(x)]. is_uint64(x) -> as_uint64(x) = x + +logic as_sint64 :int -> int +predicate is_sint64(x:int) = -9223372036854775808 <= x < 9223372036854775808 +axiom as_sint64_def : forall x:int. is_sint64(as_sint64(x)) +axiom as_sint64_involve : + forall x:int [as_sint64(as_sint64(x))]. + as_sint64(as_sint64(x)) = as_sint64(x) +axiom is_as_sint64: forall x:int [as_sint64(x)]. is_sint64(x) -> as_sint64(x) = x + + +logic as_float16 :real -> real +logic is_float16 :real -> prop +axiom as_float16_def : forall x:real. is_float16(as_float16(x)) +axiom as_float16_involve : + forall x:real [as_float16(as_float16(x))]. + as_float16(as_float16(x)) = as_float16(x) +axiom is_as_float16: forall x:real [as_float16(x)]. is_float16(x) -> as_float16(x) = x + + +logic as_float32 :real -> real +logic is_float32 :real -> prop +axiom as_float32_def : forall x:real. is_float32(as_float32(x)) +axiom as_float32_involve : + forall x:real [as_float32(as_float32(x))]. + as_float32(as_float32(x)) = as_float32(x) +axiom is_as_float32: + forall x:real [as_float32(x)]. is_float32(x) -> as_float32(x) = x + + +logic as_float64 :real -> real +logic is_float64 :real -> prop +axiom as_float64_def : + forall x:real. is_float64(as_float64(x)) +axiom as_float64_involve : + forall x:real [as_float64(as_float64(x))]. + as_float64(as_float64(x)) = as_float64(x) +axiom is_as_float64: + forall x:real [as_float64(x)]. is_float64(x) -> as_float64(x) = x + + +logic as_float128 :real -> real +logic is_float128 :real -> prop +axiom as_float128_def : + forall x:real. is_float128(as_float128(x)) +axiom as_float128_involve : + forall x:real [as_float128(as_float128(x))]. + as_float128(as_float128(x)) = as_float128(x) +axiom is_as_float128: + forall x:real [as_float128(x)]. is_float128(x) -> as_float128(x) = x + +(**************************************************************************) +(*** Memory Data Type ***) +(**************************************************************************) + +type data + +logic data_of_uint8: int -> data +logic uint8_of_data: data -> int + +axiom is_uint8_of_data: + forall d:data [is_uint8(uint8_of_data(d))].is_uint8(uint8_of_data(d)) + +axiom uint8ofdata_dataofuint8: + forall x:int [data_of_uint8(x)]. + is_uint8(x) -> uint8_of_data(data_of_uint8(x)) = x + +logic data_of_sint8: int -> data +logic sint8_of_data: data -> int + +axiom is_sint8_of_data: + forall d:data [is_sint8(sint8_of_data(d))]. is_sint8(sint8_of_data(d)) + +axiom sint8ofdata_dataofsint8: + forall x:int [data_of_sint8(x)]. + is_sint8(x) -> sint8_of_data(data_of_sint8(x)) = x + +logic data_of_uint16: int -> data +logic uint16_of_data: data -> int + +axiom is_uint16_of_data: + forall d:data [is_uint16(uint16_of_data(d))]. is_uint16(uint16_of_data(d)) + +axiom uint16ofdata_dataofuint16: + forall x:int [uint16_of_data(data_of_uint16(x))]. + is_uint16(x) -> uint16_of_data(data_of_uint16(x)) = x + +logic data_of_sint16: int -> data +logic sint16_of_data: data -> int + +axiom is_sint16_of_data: + forall d:data [is_sint16(sint16_of_data(d))]. is_sint16(sint16_of_data(d)) + +axiom sint16ofdata_dataofsint16: + forall x:int [data_of_sint16(x)]. + is_sint16(x) -> sint16_of_data(data_of_sint16(x)) = x + +logic data_of_uint32: int -> data +logic uint32_of_data: data -> int + +axiom is_uint32_of_data: + forall d:data [is_uint32(uint32_of_data(d))]. is_uint32(uint32_of_data(d)) + +axiom uint32ofdata_dataofuint32: + forall x:int [data_of_uint32(x)]. + is_uint32(x) -> uint32_of_data(data_of_uint32(x)) = x + +logic data_of_sint32: int -> data +logic sint32_of_data: data -> int + +axiom is_sint32_of_data: + forall d:data [is_sint32(sint32_of_data(d))]. is_sint32(sint32_of_data(d)) + +axiom sint32ofdata_dataofsint32: + forall x:int [data_of_sint32(x)]. + is_sint32(x) -> sint32_of_data(data_of_sint32(x)) = x + +logic data_of_uint64: int -> data +logic uint64_of_data: data -> int + +axiom is_uint64_of_data: + forall d:data [is_uint64(uint64_of_data(d))]. is_uint64(uint64_of_data(d)) + +axiom uint64ofdata_dataofuint64: + forall x:int [data_of_uint64(x)]. + is_uint64(x) -> uint64_of_data(data_of_uint64(x)) = x + +logic data_of_sint64: int -> data +logic sint64_of_data: data -> int + +axiom is_sint64_of_data: + forall d:data [is_sint64(sint64_of_data(d))]. is_sint64(sint64_of_data(d)) + +axiom sint64ofdata_dataofsint64: + forall x:int [data_of_sint64(x)]. + is_sint64(x) -> sint64_of_data(data_of_sint64(x)) = x + +logic data_of_float16: real -> data +logic float16_of_data: data -> real + +axiom is_float16_of_data: + forall d:data [is_float16(float16_of_data(d))]. is_float16(float16_of_data(d)) +axiom float16ofdata_dataoffloat16: + forall x:real [data_of_float16(x)]. + is_float16(x) -> float16_of_data(data_of_float16(x)) = x + +logic data_of_float32: real -> data +logic float32_of_data: data -> real + +axiom is_float32_of_data: + forall d:data [is_float32(float32_of_data(d))]. is_float32(float32_of_data(d)) +axiom float32ofdata_dataoffloat32: + forall x:real [data_of_float32(x)]. + is_float32(x) -> float32_of_data(data_of_float32(x)) = x + +logic data_of_float64: real -> data +logic float64_of_data: data -> real + +axiom is_float64_of_data: + forall d:data [is_float64(float64_of_data(d))]. is_float64(float64_of_data(d)) +axiom float64ofdata_dataoffloat64: + forall x:real [data_of_float64(x)]. + is_float64(x) -> float64_of_data(data_of_float64(x)) = x + +logic data_of_float128: real -> data +logic float128_of_data: data -> real + +axiom is_float128_of_data: + forall d:data [is_float128(float128_of_data(d))]. is_float128(float128_of_data(d)) +axiom float128ofdata_dataoffloat128: + forall x:real [data_of_float128(x)]. + is_float128(x) -> float128_of_data(data_of_float128(x)) = x + + +(**************************************************************************) +(*** Update of Arrays over a set of Index ***) +(**************************************************************************) + + +logic set_range_index: + 'a farray (* array*), int set (* set of index*), int (*uniq key*) -> 'a farray + +axiom set_range_def : + forall t: 'a farray. + forall rg: int set. + forall k:int. + forall i:int [access(set_range_index(t,rg,k),i)]. + not (member(i,rg)) -> + access(set_range_index(t,rg,k),i) = access(t,i) + +(**************************************************************************) +(*** Bitwise Operations ***) +(**************************************************************************) + +logic bnot: int -> int +logic band: int,int -> int +logic bor: int,int -> int +logic bxor: int,int -> int +logic lshift: int,int -> int +logic rshift: int,int -> int + +logic int_not: int -> int +logic int_and: int,int -> int +logic int_or: int,int -> int +logic int_xor: int,int -> int +logic int_lsh: int,int -> int +logic int_rshs: int,int -> int +logic int_rshu: int,int -> int + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) +(* WARNING: Generated file: any modifications will be lost ! *) +(* See in the main file [data_lib.why] for more information. *) +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) + +type 'a format + +(* [format_size f] number of bits of the format [f] *) +logic format_size : 'a format -> (* size *) int + +(* [is_in_format f x] is true if [x] fits in the format [f] *) +(* Ex: [is_in_format (uint8, 100)], but not is_in_format (uint8, (-1)) *) +logic is_in_format : 'a format, 'a -> prop + +(***********************************************************************) +(*** Integer Cast into Machine ***) +(***********************************************************************) + +(* [signed_format f] is the format [f] a signed one *) +logic signed_format : int format -> bool + + +(*** Definitions and sizes *) + +logic uint8_format : int format +axiom uint8_format_size : format_size (uint8_format) = 8 +axiom uint8_format_sign : signed_format (uint8_format) = false + +logic sint8_format : int format +axiom sint8_format_size : format_size (sint8_format) = 8 +axiom sint8_format_sign : signed_format (sint8_format) = true + +logic uint16_format : int format +axiom uint16_format_size : format_size (uint16_format) = 16 +axiom uint16_format_sign : signed_format (uint16_format) = false + +logic sint16_format : int format +axiom sint16_format_size : format_size (sint16_format) = 16 +axiom sint16_format_sign : signed_format (sint16_format) = true + +logic uint32_format : int format +axiom uint32_format_size : format_size (uint32_format) = 32 +axiom uint32_format_sign : signed_format (uint32_format) = false + +logic sint32_format : int format +axiom sint32_format_size : format_size (sint32_format) = 32 +axiom sint32_format_sign : signed_format (sint32_format) = true + +logic uint64_format : int format +axiom uint64_format_size : format_size (uint64_format) = 64 +axiom uint64_format_sign : signed_format (uint64_format) = false + +logic sint64_format : int format +axiom sint64_format_size : format_size (sint64_format) = 64 +axiom sint64_format_sign : signed_format (sint64_format) = true + +(*** Specifications *) + +axiom is_in_format_sint8 : forall x:int + [ is_in_format (sint8_format, x)]. + is_in_format (sint8_format, x) <-> -128 <= x < 128 + +axiom is_in_format_uint8 : forall x:int + [ is_in_format (uint8_format, x)]. + is_in_format (uint8_format, x) <-> 0 <= x < 256 + +axiom is_in_format_sint16 : forall x:int + [ is_in_format (sint16_format, x)]. + is_in_format (sint16_format, x) <-> -32768 <= x < 32768 + +axiom is_in_format_uint16 : forall x:int + [ is_in_format (uint16_format, x)]. + is_in_format (uint16_format, x) <-> 0 <= x < 65536 + +axiom is_in_format_sint32 : forall x:int + [ is_in_format (sint32_format, x)]. + is_in_format (sint32_format, x) <-> -2147483648 <= x < 2147483648 + +axiom is_in_format_uint32 : forall x:int + [ is_in_format (uint32_format, x)]. + is_in_format (uint32_format, x) <-> 0 <= x < 4294967296 + +axiom is_in_format_sint64 : forall x:int + [ is_in_format (sint64_format, x)]. + is_in_format (sint64_format, x) <-> -9223372036854775808 <= x < 9223372036854775808 + +axiom is_in_format_uint64 : forall x:int + [ is_in_format (uint64_format, x)]. + is_in_format (uint64_format, x) <-> 0 <= x < 18446744073709551616 + + +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) +(*** Floating point vs real *) + +(* Be careful that [is_in_format] problably means that the real value + can be represented EXACTLY in the format... *) + +(*** Definitions and sizes *) + +logic float16_format : real format +axiom float16_format_size : format_size (float16_format) = 16 + +logic float32_format : real format +axiom float32_format_size : format_size (float32_format) = 32 + +logic float64_format : real format +axiom float64_format_size : format_size (float64_format) = 64 + +logic float96_format : real format +axiom float96_format_size : format_size (float96_format) = 96 + +logic float128_format : real format +axiom float128_format_size : format_size (float128_format) = 128 + +(* ~~~ End of generated file data_int.why *) +(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *) + +(* -------------------------------------------------------------------------- *) +(* --- Runtime Memory Model --- *) +(* -------------------------------------------------------------------------- *) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* This file provides the definitions and axioms for the Runtime memory model. +Some lemmas, proved in coq from these definitions, are given in the file +[runtime_lemmas.why]. + +The Runtime memory model is a low level model where the memory can be seen +as an array of bits. + +Many types in his model are coded by [int] (address, size, etc.). +Because WHY doesn't allow type renaming, we'll try to specify them in comments. +*) + + +(**************************************************************************) +(*** Encode/Decode ***) +(**************************************************************************) + +logic encode : 'a format,'a -> data +logic decode : 'a format,data -> 'a + +axiom encode_decode: + forall f:'a format. forall d:data. + encode(f,decode(f,d)) = d + +axiom decode_encode: + forall f:'a format. forall x:'a. + decode(f,encode(f,x)) = x + +axiom decode_inj: + forall d,d':data. forall f:'a format. + decode(f,d) <> decode(f,d') <-> d<>d' + +axiom decode_eq: + forall d,d':data. forall f:'a format. + decode(f,d) = decode(f,d') <-> d=d' + + +logic int_format : int format +logic real_format : real format + + + +(*========================================================================*) +(*** Casts ***) +(*========================================================================*) + +(*------------------------------------------------------------------------*) +(*** Cast between [int format] ***) + +logic as_int : int format, int -> int + +axiom simpl_as_int : forall f: int format. forall x:int. + is_in_format (f, x) -> as_int (f, x) = x +axiom as_int_def : forall f: int format. forall x:int. + is_in_format (f, (as_int (f, x))) +axiom involve_as_int : forall f: int format. forall x:int. + as_int (f, as_int (f, x)) = as_int (f, x) + +(*------------------------------------------------------------------------*) +(*** Cast between [real format] ***) + +logic as_float : real format, real -> real + +axiom simpl_as_float : forall f: real format. forall x:real. + is_in_format (f, x) -> as_float (f, x) = x +axiom as_float_def : forall f: real format. forall x:real. + is_in_format (f, (as_float (f, x))) +axiom involve_as_float : forall f: real format. forall x:real. + as_float (f, as_float (f, x)) = as_float (f, x) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* === Addresses and zones === *) + +(* New version of WHY support these new definitions, but unfortunatly, + it doesn't export them correctly to coq yet... + +type address = A (int) +type zone = rt_zone (int, int) (* = (address * size) *) +function z_addr (z:zone) : int = match z with rt_zone (a, sz) -> a end +function z_size (z:zone) : int = match z with rt_zone (a, sz) -> sz end + +*) + +(* --- addresses --- *) +(* An [address] is a kind of index in the memory. *) + +(* type address = (* address *) int *) + +(* --- zones --- *) +(* A [zone] is composed of an address and a size. *) + +(* type size = (* size *) int *) + +type zone (* = rt_zone (int, int) = (address * size) *) + +logic rt_zone : (* address *) int, (* size *) int -> zone + +logic z_addr : zone -> (* address *) int +logic z_size : zone -> (* size *) int +axiom addr_zone : forall a, sz: int. z_addr (rt_zone (a, sz)) = a +axiom size_zone : forall a, sz: int. 0 <= sz -> z_size (rt_zone (a, sz)) = sz + +axiom rt_zone_inj : forall a1, a2, sz1, sz2 : int. + rt_zone (a1, sz1) = rt_zone (a2, sz2) <-> a1 = a2 and sz1 = sz2 + +predicate rt_disj (z1:zone, z2:zone) + = (z_addr (z1) + z_size (z1) <= z_addr (z2)) + or (z_addr (z2) + z_size (z2) <= z_addr (z1)) + +predicate rt_incl (z1:zone, z2:zone) + = z_addr (z2) <= z_addr (z1) +and z_addr (z1) + z_size (z1) <= z_addr (z2) + z_size (z2) + +predicate addr_in_zone (a:int, z:zone) = + z_addr (z) <= a and a < z_addr (z) + z_size (z) + +(* --- offset --- *) +(* Offset can be added to address to compute another address *) + +(* type offset = (* offset *) int *) + +function rt_shift (addr:int, offset:int) : (* address *) int = addr + offset + +(* We can get field information from its identifier : +type field : (* field *) int +*) + +logic rt_foffset : (* field *) int -> (* offset *) int +logic rt_fsize : (* field *) int -> (* size *) int + +(* TODO: we would prefer to have any format as result but why fail to +generate correct COQ files is the result is polymorphic *) +logic rt_fformat : (* name *) int -> int format + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* === Zones === *) + +(* Because we need to provide function such as [dzone_union] in the model, + we need more than simple [zone]. +TODO: [zones] might be defined as set of integers ? +*) + +type zones + +logic zs_empty : zones +logic zs_singleton : zone -> zones +logic zs_union : zones, zones -> zones +logic zs_incl : zones, zones -> prop +logic zs_disj : zones, zones -> prop + +predicate zs_z_incl (z:zone, zs:zones) = zs_incl (zs_singleton (z), zs) +predicate zs_z_disj (z:zone, zs:zones) = zs_disj (zs_singleton (z), zs) + +(* Some axioms but we need to add more (TODO if we don't use [set]) *) + +axiom zs_empty_incl : forall zs:zones. zs_incl (zs_empty, zs) +axiom zs_z_not_incl_empty : forall z:zone. + not zs_incl (zs_singleton (z), zs_empty) +axiom zs_incl_singleton : forall z1, z2:zone. + rt_incl (z1, z2) <-> zs_incl (zs_singleton(z1), zs_singleton(z2)) +axiom zs_incl_union_1 : forall z, z1, z2:zones. + zs_incl (z, z1) -> zs_incl (z, zs_union (z1, z2)) +axiom zs_incl_union_2 : forall z, z1, z2:zones. + zs_incl (z, z2) -> zs_incl (z, zs_union (z1, z2)) +axiom zs_incl_union_3: forall z, z1, z2 : zones. + zs_incl (z1, z) -> zs_incl (z2, z) -> zs_incl (zs_union (z1, z2), z) + + +axiom zs_disj_singleton : forall z1, z2:zone. + rt_disj (z1, z2) <-> zs_disj (zs_singleton(z1), zs_singleton(z2)) +axiom zs_incl_disj : forall z, zi, zd : zones. + zs_incl (zi, z) -> zs_disj (zd, z) -> zs_disj (zi, zd) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* === Values === *) + +(* We define a value as a word of bits with a given size. +To know more about these [bits] interpretation, see the next section. *) + +type bits +logic bits_size : bits -> (* size *) int + +axiom bits_size_pos : forall b:bits. bits_size (b) >= 0 + +(* [bits] elements are numbered from 0. +Precondition: [0 <= i < bits_size (b)] *) +logic nth_bit : bits, int -> bool + +axiom eq_bits : forall b1, b2:bits. forall sz: int. + bits_size (b1) = sz -> bits_size (b2) = sz -> + (forall i:int. 0 <= i < sz -> nth_bit (b1, i) = nth_bit (b2, i)) + <-> b1 = b2 + +(* Test is zero. *) +predicate zero_bits (b:bits) = + forall i:int. 0 <= i < bits_size (b) -> nth_bit (b, i) = false + +(* --- Extract parts of [bits] --- *) + +(* Notice that [bits_part] is only defined when the zone defined by offset +and size is compatible with the initial bits size. +Precondition: [ offset+size <= bits_size (b) ] +*) +logic bits_part : bits, (* offset *) int, (* size *) int -> bits + +axiom bits_part_size : forall b:bits. forall off, sz:int. + 0 <= off -> off + sz <= bits_size (b) -> + bits_size (bits_part (b, off, sz)) = sz + +axiom nth_bits_part : forall b:bits. forall off, i, sz:int. + 0 <= i < sz -> 0 <= off -> off + sz <= bits_size (b) -> + nth_bit (bits_part (b, off, sz), i) = nth_bit (b, off+i) + +(* --- Concatenation of [bits] --- *) + +logic bits_concat : bits, bits -> bits + +axiom bits_concat_size : forall b1, b2:bits. + bits_size (bits_concat (b1, b2)) = bits_size (b1) + bits_size (b2) + +axiom nth_bits_concat_l : forall b1, b2: bits. forall i:int. + 0 <= i < bits_size (b1) -> + nth_bit (bits_concat (b1, b2), i) = nth_bit (b1, i) + +axiom nth_bits_concat_r : forall b1, b2: bits. forall i:int. + forall sz1, sz2:int. sz1 = bits_size (b1) -> sz2 = bits_size (b2) -> + sz1 <= i < sz1 + sz2 -> + nth_bit (bits_concat (b1, b2), i) = nth_bit (b2, i - sz1) + +(* --- Write parts of [bits] --- *) + +(* Notice that [wr_bits_part] is only defined when the zone defined by offset +and size of the second bits size is compatible with the initial bits size. +Precondition: [offset + size2 <= size1]. *) +logic wr_bits_part : bits, (* offset *) int, bits -> bits + +axiom wr_bits_part_size : forall b, bw:bits. forall o:int. + bits_size (wr_bits_part (b, o, bw)) = bits_size (b) + +axiom nth_wr_bits_part_1 : forall b, b': bits. forall off, i:int. + 0 <= i < off -> + nth_bit (wr_bits_part (b, off, b'), i) = nth_bit (b, i) + +axiom nth_wr_bits_part_2 : forall b, b': bits. forall off, i:int. + 0 <= off <= i < off+bits_size (b') -> + nth_bit (wr_bits_part (b, off, b'), i) = nth_bit (b', i - off) + +axiom nth_wr_bits_part_3 : forall b, b': bits. forall off, i:int. + 0 <= off + bits_size (b') <= i < bits_size (b) -> + nth_bit (wr_bits_part (b, off, b'), i) = nth_bit (b, i) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* === Interpretation to and from bits === *) + +(* The [bits] defined above are used to represent the array of bits +as stored in the memory, so it depend on the memory architecture (endianness). +Moreover, the bits order is from the smaller bit address. +Example: if [b8] is [rt_to_bits uint8 1] we have: + [nth (b8, 7) = true] and [forall i. 0 <= i < 7 -> nth (b8, i) = false]. + but [b16 = rt_to_bits uint16 1] depend on the value of the + [little_endian] parameter. +Then finally, beware that [bits] is quite different from the usual bit +representation of a number. *) + + +(* [rt_from_bits b f] is to interpret bits [b] to a typed value [f]. +The interpretation is valid only if the [bits] size match the size of the asked +format. +Precondition: [bits_size b = format_size f] *) +logic rt_from_bits : bits, 'a format -> 'a + +axiom rt_from_bits_format : forall b:bits. forall fmt: 'a format. + bits_size (b) = format_size (fmt) -> + is_in_format (fmt, rt_from_bits (b, fmt)) + +(* [rt_to_bits] build the [bits] representation of a typed value. +This function is supposed to take care of the endianness because it should +return the bit vector stored in the memory from the smaller address to the +bigger one. +Precondition: [is_in_format f v]. +*) +logic rt_to_bits : 'a format, 'a -> bits + +axiom rt_to_bits_size : forall fmt: 'a format. forall x: 'a + [bits_size (rt_to_bits (fmt, x))]. + bits_size (rt_to_bits (fmt, x)) = format_size (fmt) + +axiom rt_to_bits_from_bits : forall fmt:'a format. forall b:bits + [rt_to_bits (fmt, rt_from_bits (b, fmt))]. + bits_size (b) = format_size (fmt) -> + rt_to_bits (fmt, rt_from_bits (b, fmt)) = b + +axiom rt_from_bits_to_bits :forall fmt: 'a format. forall v:'a + [rt_from_bits (rt_to_bits (fmt, v), fmt)]. + is_in_format (fmt, v) -> + rt_from_bits (rt_to_bits (fmt, v), fmt) = v + +(*---------------------------------------------------------------------------*) +(* --- Interpretation of integer --- *) + +(* Be careful that this is not true for any format ! +For structures, for instance, the bits of padding can be anything +and still have the same interpretation... +But we know that the representation is unique for [int format] *) +axiom same_int_val_same_bits : forall b1, b2:bits. forall fmt: int format. + bits_size (b1) = format_size (fmt) -> + bits_size (b2) = format_size (fmt) -> + rt_from_bits (b1, fmt) = rt_from_bits (b2, fmt) -> b1 = b2 + +axiom rt_to_bits_zero : forall fmt: int format. + forall b:bits. b = rt_to_bits (fmt, 0) -> zero_bits (b) + +axiom rt_from_bits_zero : forall b:bits. forall fmt: int format. + zero_bits (b) -> rt_from_bits (b, fmt) = 0 + +(* --- [bits] to and from [bool farray] in order to use [bits.why] --- *) + +(** [mbyte_to_bbits] only takes 8 bits from the memory representation, + and revert them to get a traditional binary representation. *) +logic mbyte_to_bbits : bits -> bool farray + +axiom mbyte_to_bbits_def : forall b:bits. bits_size (b) = 8 -> + forall i:int. 0 <= i < 8 -> + access (mbyte_to_bbits (b), i) = nth_bit (b, 7 - i) + +(** [nth_mbyte k b] returns the k-th byte of [b] *) +logic nth_mbyte : int, bits -> bits + +axiom nth_mbyte_size : forall b:bits. forall k:int. + bits_size (nth_mbyte (k, b)) = 8 + +axiom nth_byte_def : forall b:bits. + forall k:int. 0 <= 8 * (k+1) <= bits_size (b) -> + forall i:int. 0 <= i < 8 -> + nth_bit (nth_mbyte (k, b), i) = nth_bit (b, 8 * k + i) + +function nth_byte (k:int, b:bits) : bool farray = + mbyte_to_bbits (nth_mbyte (k, b)) + +(*----------------------------------------------------------------------------*) +(** Interpretation of memory bits from and to binary representation *) + +logic little_endian : -> prop + +(** [concat_bytes w b] : [b] is a byte (8 bits) + to be added at the right of [w] word. *) + +logic concat_bytes : bool farray, bool farray -> bool farray + +axiom concat_bytes_left : forall w, b: bool farray. forall i:int. + 8 <= i -> access (concat_bytes (w, b), i) = access (w, i-8) + +axiom concat_bytes_right : forall w, b: bool farray. forall i:int. + 0 <= i < 8 -> access (concat_bytes (w, b), i) = access (b, i) + +(*----------------------------------------------------------------------------*) +(** Some definitions related to binary representation (should be in data.why) *) + +logic uint_of_bits : int, bool farray -> int +logic sint_of_bits: int, bool farray -> int +function cint_of_bits (fmt:int format, b:bool farray) : int = + ite (signed_format (fmt), + sint_of_bits (format_size (fmt) - 1, b), + uint_of_bits (format_size (fmt) - 1, b)) + +logic bits_of_sint: int, int -> bool farray +logic bits_of_uint: int, int -> bool farray +function bits_of_cint (fmt: int format, x: int) : bool farray = + ite (signed_format (fmt), + bits_of_sint (format_size (fmt) - 1, x), + bits_of_uint (format_size (fmt) - 1, x)) + +(*----------------------------------------------------------------------------*) +(** From memory to binary *) + +logic mbits_to_bbits : bits -> bool farray + +axiom mb8_to_bbits : forall b:bits. bits_size (b) = 8 -> + mbits_to_bbits (b) = nth_byte (0, b) + +axiom little_mb16_to_bbits : forall b:bits. bits_size (b) = 16 -> + little_endian -> + mbits_to_bbits (b) = concat_bytes (nth_byte (1, b), nth_byte (0, b)) + +axiom big_mb16_to_bbits : forall b:bits. bits_size (b) = 16 -> + not little_endian -> + mbits_to_bbits (b) = concat_bytes (nth_byte (0, b), nth_byte (1, b)) + +axiom little_mb32_to_bbits : forall b:bits. bits_size (b) = 32 -> + little_endian -> + mbits_to_bbits (b) = concat_bytes (concat_bytes ( + concat_bytes (nth_byte (3, b), + nth_byte (2, b)), + nth_byte (1, b)), + nth_byte (0, b)) + +axiom big_mb32_to_bbits : forall b:bits. bits_size (b) = 32 -> + not little_endian -> + mbits_to_bbits (b) = concat_bytes (concat_bytes ( + concat_bytes (nth_byte (0, b), + nth_byte (1, b)), + nth_byte (2, b)), + nth_byte (3, b)) + +axiom rt_int_from_bits : forall b:bits. forall fmt: int format. + rt_from_bits (b, fmt) = cint_of_bits (fmt, mbits_to_bbits (b)) + +(*----------------------------------------------------------------------------*) +(** From binary to memory *) + +(** Build the 8 bits to store in the memory from the nth byte of binary +representation. *) +logic bbits_to_mbyte : int, bool farray -> bits + +axiom bbits_to_mbyte_size : forall b:bool farray. forall k:int. + bits_size (bbits_to_mbyte (k, b)) = 8 + +axiom bbits_to_mbyte_def : forall b:bool farray. forall k, i:int. + 0 <= i < 8 -> + nth_bit (bbits_to_mbyte (k, b), i) = access (b, 8*k + 7-i) + +(** [bbits_to_mbits n b] use b[(n-1)..0] so gives n bits. *) +logic bbits_to_mbits : int, bool farray -> bits + +axiom bbits_to_mb8 : forall b:bool farray. + bbits_to_mbits (8, b) = bbits_to_mbyte (0, b) + +axiom bbits_to_little_mb16 : forall b:bool farray. + little_endian -> + bbits_to_mbits (16, b) = bits_concat (bbits_to_mbyte (0, b), + bbits_to_mbyte (1, b)) + +axiom bbits_to_big_mb16 : forall b:bool farray. + not little_endian -> + bbits_to_mbits (16, b) = bits_concat (bbits_to_mbyte (1, b), + bbits_to_mbyte (0, b)) + +axiom bbits_to_little_mb32 : forall b:bool farray. + little_endian -> + bbits_to_mbits (32, b) = bits_concat (bbits_to_mbyte (0, b), + bits_concat (bbits_to_mbyte (1, b), + bits_concat (bbits_to_mbyte (2, b), + bbits_to_mbyte (3, b)))) + +axiom bbits_to_not_mb32 : forall b:bool farray. + not little_endian -> + bbits_to_mbits (32, b) = bits_concat (bbits_to_mbyte (3, b), + bits_concat (bbits_to_mbyte (2, b), + bits_concat (bbits_to_mbyte (1, b), + bbits_to_mbyte (0, b)))) + +axiom rt_int_to_bits : forall x:int. forall fmt: int format. + rt_to_bits (fmt, x) = + bbits_to_mbits (format_size (fmt), bits_of_cint (fmt, x)) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* --- Memory --- *) + +(* The memory is an abstract object that can be seen as a list of bits, +but we also assume that it stores information about the allocation table, +ie. it can provide the allocated zone which contains a given address. +*) + +(* from addresses to values. *) +type memory + +(* allocation information. *) +type memalloc + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* --- Allocation management --- *) + +(* --- valid zone --- *) + +(* a zone is valid when it is allocated in the memory, +ie. we can read/write in it. *) + +logic rt_valid : memalloc, zone -> prop + +axiom incl_valid : forall m:memalloc. forall z, z':zone. + rt_incl (z', z) -> rt_valid (m, z) -> rt_valid (m, z') + +axiom disj_valid : forall m:memalloc. forall z,z':zone [rt_disj (z, z')]. + rt_valid (m, z) -> not rt_valid (m, z') -> rt_disj (z, z') + +(* --- base --- *) + +(* [rt_zbase] returns the allocated zone in which the address is. +Notice that it returns a valid zone only is the address is allocated. *) +logic rt_zbase : memalloc, (* address *) int -> zone + +function rt_abase (m:memalloc, addr:int) : (* address *) int = + z_addr (rt_zbase (m, addr)) + +(* TODO: check the meaning of that in ACSL and then add axioms *) +logic rt_block_length : memalloc, (* address *) int -> (* size *) int + + +(* --- allocation --- *) + +(* the [rt_alloc] function takes the size of the zone that we want to allocate, +and it returns a base address, and a new memory in which the zone is allocated. +Notice that at the moment, we assume that there is enough memory, +so that the allocation never fails. +*) + +(* Because we cannot use pairs in WHY, we have to define : *) +type mz (* = (memalloc * address) *) +logic mem_of_mz : mz -> memalloc +logic addr_of_mz : mz -> (* address *) int + +(* Pre : size > 0 *) +logic rt_alloc : memalloc, (* size *) int -> mz + +function alloc_zone (m:memalloc, sz:int) : zone = + rt_zone (addr_of_mz (rt_alloc (m, sz)), sz) + +axiom alloc_is_base : forall m:memalloc. forall sz:int. + let mz = rt_alloc (m, sz) in + rt_zbase (mem_of_mz (mz), addr_of_mz (mz)) = alloc_zone (m, sz) + +(* Of course, a new allocated zone is valid *) +axiom valid_alloc : forall m:memalloc. forall sz:int. + let mz = rt_alloc (m, sz) in + rt_valid (mem_of_mz (mz), alloc_zone (m, sz)) + +(* The zone is not valid before having been allocated. *) +axiom not_valid_before_alloc: forall m:memalloc. forall sz:int. + not rt_valid (m, alloc_zone (m, sz)) + +(* A previously allocated zone is still the same after a new allocation. *) +axiom alloc_keep_valid: forall m:memalloc. forall sz:int. forall z:zone. + rt_valid (m, z) -> + let mz = rt_alloc (m, sz) in rt_valid (mem_of_mz (mz), z) + +(* All the zones that were invalid before the allocation and that are disjoint +from the newly allocation zone stays invalid. *) +axiom alloc_keep_invalid: forall m:memalloc. forall sz:int. forall z:zone. + let mz = rt_alloc (m, sz) in + rt_valid (mem_of_mz (mz), z) -> + rt_disj (alloc_zone (m, sz), z) -> + rt_valid (m, z) + +(* --- free --- *) + +logic rt_free : memalloc, (* address *) int -> memalloc + +axiom not_valid_after_free : forall m:memalloc. forall addr:int. + forall z:zone. z = rt_zbase (m, addr) -> + addr = z_addr (z) -> not rt_valid (rt_free (m, addr), z) + +(* This might be a lemma : *) +axiom valid_free_disj : forall m:memalloc. forall z, z':zone. + rt_valid (rt_free (m, z_addr (z)), z') <-> rt_disj (z, z') + + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* --- Program objects --- *) + +(* Program variables are also indexed by [int]s : + +type name = (* name *) int +*) + + +(* We can find the address of a variable from its name in a given memory. +We could have returned a [option address] but it is much more complicated +to write functions. Instead of that, we assume that this function can return +an invalid address when the variable is not allocated +(for instance, a negative one). +*) +logic rt_vaddr : memalloc, (* name *) int -> (* address *) int + +(* TODO: we would prefer to have any format as result but WHY fails to +generate correct COQ files if the result is polymorphic *) +(* logic rt_vformat : (* name *) int -> int format *) + +(* We would like to have : + function rt_vsize (v:int) : (* size *) int = format_size (rt_vformat (v)) +but it is not possible at the moment because of the limitation of [rt_vformat] +*) +logic rt_vsize : (* name *) int -> (* size *) int +(* axiom rt_vformat_vsize : forall v:int. + format_size (rt_vformat (v)) = rt_vsize (v) *) + +function rt_vzone (ma:memalloc, var:int) : zone = + rt_zone (rt_vaddr (ma, var), rt_vsize (var)) + +(* Global variables always have the same zone, and are always valid *) +logic rt_global : (* name *) int -> prop + +axiom rt_global_vaddr : forall v:int. rt_global (v) -> + forall ma, ma':memalloc. rt_vaddr (ma, v) = rt_vaddr (ma', v) + +axiom rt_global_valid : forall ma:memalloc. forall v:int. + rt_global (v) -> + forall ma, ma':memalloc [rt_valid (ma, rt_vzone (ma', v))]. + rt_valid (ma, rt_vzone (ma', v)) + +(* In a given memory, different variables have disjoint zones. *) +axiom vzone_disj : forall ma:memalloc. forall v1, v2:int. + v1 <> v2 -> + let z1 = rt_vzone (ma, v1) in + let z2 = rt_vzone (ma, v2) in + rt_valid (ma, z1) -> rt_valid (ma, z2) -> rt_disj (z1, z2) + +logic rt_valloc : memalloc, (* name *) int -> memalloc + +(* TODO: put this as a definition ? *) +axiom rt_valloc_mem : forall ma:memalloc. forall var:int. + rt_valloc (ma, var) = mem_of_mz (rt_alloc (ma, rt_vsize (var))) + +axiom rt_valloc_addr : forall ma:memalloc. forall var:int. + forall ma':memalloc. ma' = rt_valloc (ma, var) -> + forall mz:mz. mz = rt_alloc (ma, rt_vsize (var)) -> + rt_vaddr (ma', var) = addr_of_mz (mz) + +axiom vzone_valloc_neq : forall ma:memalloc. forall v1, v2:int. + forall ma':memalloc. ma' = rt_valloc (ma, v1) -> + v1 <> v2 -> rt_vzone (ma', v2) = rt_vzone (ma, v2) + +(*---------------------------*) + +function rt_vfree (ma:memalloc, var:int) : memalloc = + rt_free (ma, rt_vaddr (ma, var)) + +(* +axiom vfree_not_valid : forall ma:memalloc. forall v:int. + not (rt_valid (rt_vfree (ma, v), rt_vzone (ma, v))) + +axiom vfree_valid_neq : forall ma:memalloc. forall v1, v2:int. + v1 <> v2 -> rt_valid (ma, rt_vzone (ma, v1)) -> + rt_valid (rt_vfree (ma, v2), rt_vzone (ma, v1)) +*) + +(* lemma *) +axiom rt_vaddr_vfree : forall ma:memalloc. forall v1, v2:int. + v1 <> v2 -> rt_vaddr (rt_vfree (ma, v1), v2) = rt_vaddr (ma, v2) + +(* lemma *) +(* +axiom rt_vsize_vfree : forall ma:memalloc. forall v1, v2:int. + v1 <> v2 -> rt_vsize (rt_vfree (ma, v1), v2) = rt_vsize (ma, v2) +*) + +axiom addr_base : forall m:memalloc. forall v:int. + rt_abase (m, rt_vaddr (m, v)) = rt_vaddr (m, v) + + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* === R/W in the memory === *) + +logic rt_load : memory, zone -> bits + +(* Precondition: [z_size (zone) = bits_size (bits)] *) +logic rt_store : memory, (* address *) int, bits -> memory + +axiom load_store_same : forall m:memory. forall a:int. + forall z:zone. forall v:bits + [ rt_load(rt_store(m,a,v),z) ]. + z = rt_zone (a, bits_size (v)) -> + rt_load (rt_store (m, a, v), z) = v + +axiom load_store_disj : forall m: memory. forall a: int. + forall z:zone. forall v:bits + [ rt_load(rt_store(m,a,v),z) ]. + rt_disj ( rt_zone (a, bits_size(v)) , z ) -> + rt_load ( rt_store (m, a, v), z ) = rt_load(m, z) + +axiom load_store_incl_part : forall m: memory. + forall a:int. forall z1, z2 : zone. forall v:bits. + z2 = rt_zone (a, bits_size (v)) -> rt_incl (z1, z2) -> + rt_load (rt_store (m, a, v), z1) + = bits_part (v, z_addr (z1) - a, z_size (z1)) + +(** Write [v] at address [a], and load [z2] zone, + when writed zone [z1] included in [z2]. *) +axiom load_incl_part_store : forall m: memory. + forall z1, z2 : zone. forall v:bits. + forall a:int. z1 = rt_zone (a, bits_size (v)) -> + forall off : int. off = a - z_addr (z2) -> + rt_incl (z1, z2) -> + rt_load (rt_store (m, a, v), z2) + = wr_bits_part (rt_load (m, z2), off, v) + +axiom rt_load_size : forall m:memory. forall z:zone. + bits_size (rt_load (m, z)) = z_size (z) + +(* +axiom rt_load_var_in_format : forall ma:memalloc. forall mb:memory. + forall v : int. + let fmt = rt_vformat (v) in + let bits = rt_load (mb, rt_vzone (ma, v)) in + let x = rt_from_bits (bits, fmt) in + is_in_format (fmt, x) +*) + +axiom bits_part_rt_load : forall z, z':zone. forall a', off, sz:int. + a' = z_addr (z) + off -> + z' = rt_zone (a', sz) -> + rt_incl (z', z) -> + forall m:memory. rt_load (m, z') = bits_part (rt_load (m, z), off, sz) + +(* --- eq mem --- *) + +axiom rt_same_mem : forall m1, m2:memory. + (forall z:zone. rt_load (m1, z) = rt_load (m2, z)) -> m1 = m2 + +(* --- is_havoc --- *) + +logic rt_havoc : memory, zone -> memory + +(* [rt_is_havoc] is used to compare 2 memory states. +It is valid when for each zone that is valid in [memalloc], +either it is included in the excluded [zones], +or the value of the zone is the same in both memory. *) + +predicate rt_is_havoc (ma:memalloc, m1:memory, zs:zones, m2:memory) = + forall z:zone. rt_valid (ma, z) -> zs_z_disj (z, zs) -> + rt_load (m1, z) = rt_load (m2, z) + +axiom rt_havoc_is_havoc : forall ma:memalloc. forall m:memory. + forall zs:zones. forall z:zone. zs_z_incl (z, zs) -> + rt_is_havoc (ma, m, zs, rt_havoc (m, z)) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* === Relation with DataLib === *) + +(* --- pointer vs address --- *) + + +logic rt_addr_format : int format + +(* IMPORTANT TODO: this should be generated according to the configuration !!!*) +(* axiom rt_addr_format_size : format_size (rt_addr_format) = 32 *) + +axiom rt_vaddr_format : forall ma: memalloc. forall v:int. + is_in_format (rt_addr_format, rt_vaddr (ma, v)) + +(* ----------------------------------- *) +(* --- logic value vs memory value --- *) + +(* For each [struct] type, a format is defined automatically in the why file. +logic Cfmt_str: data farray format +It means that the result of [rt_from_bits (x, Cfmt_str)] is a [data farray] +which is the coded type for structures in logic. We still have to use +[encode/decode] functions to transform the [data] into real typed values. *) + +(* --- bits_part vs access --- *) + +axiom bits_part_vs_access : forall bs: bits. + forall fs : data farray format. + forall f : int. forall off, sz:int. + off = rt_foffset (f) -> sz = rt_fsize (f) -> + rt_from_bits (bits_part (bs, off, sz), rt_fformat (f)) + = decode (int_format, access (rt_from_bits (bs, fs), f)) + +(* --- wr_bits_part vs update --- *) + +(* because the function [rt_fformat : ( field ) int -> 'a format ] +is not usable in COQ files, we have to generate this axiom in caml +for each field : + +axiom wr_bits_part_vs_update : forall bs, bx: bits. + forall fs : data farray format. forall fx : 'x format. + forall f : int. bits_size (bx) = rt_fsize (f) -> rt_fformat (f) = fx -> + rt_from_bits (wr_bits_part (bs, rt_foffset (f), bx), fs) + = update (rt_from_bits (bs, fs), f, encode (fx, rt_from_bits (bx, fx))) +*) + + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* ==== Pointer Arithmetic ==== *) +logic rt_addr_lt: int (*address*), int (*address*) -> prop +logic rt_addr_le: int (*address*), int (*address*) -> prop +logic rt_addr_lt_bool: int (*address*), int (*address*) -> bool +logic rt_addr_le_bool: int (*address*), int (*address*) -> bool +logic rt_addr_minus : int (*address*), int (*address*) -> int +logic rt_addr_eq: int (*address*), int (*address*) -> prop +logic rt_addr_eq_bool: int (*address*), int (*address*) -> bool + + + + + +(* ~~~ End of runtime.why ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(*========================================================================*) +(* Helper Lemmas for Runtime Model *) +(*------------------------------------------------------------------------*) + +(* This file contains some lemmas that can be proved using the definitions +given in [runtime.why]. It is used to build a COQ file in order to check the +proofs, and then it can be used to help the ATP. +*) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* About zones : *) + +axiom rt_disj_sym : forall z1, z2:zone. + rt_disj (z1, z2) <-> rt_disj (z2, z1) + +axiom rt_disj_shift : forall addr:int. forall i, j, sz:int. + sz > 0 -> i <> j -> + rt_disj (rt_zone (rt_shift (addr, i*sz), sz), + rt_zone (rt_shift (addr, j*sz), sz)) + +axiom vzone_of_zone : forall ma:memalloc. forall v, a, sz:int. + a = rt_vaddr (ma, v) -> sz = rt_vsize (v) -> + rt_zone (a, sz) = rt_vzone (ma, v) + +(* +axiom rt_vsize_of_format : forall ma:memalloc. forall v:int [rt_vsize (ma, v)]. + rt_valid (ma, rt_vzone (ma, v)) -> + rt_vsize (ma, v) = format_size (rt_vformat (v)) +*) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* About bits : *) + +axiom bits_part_full : forall v:bits. forall sz:int. + sz = bits_size (v) -> bits_part (v, 0, sz) = v + +axiom bits_part_of_bits_part : forall b:bits. forall o1, o2, sz1, sz2 : int. + 0 <= o1 -> o1 + sz1 <= bits_size (b) -> + 0 <= o2 -> o2 + sz2 <= sz1 -> + bits_part (bits_part (b, o1, sz1), o2, sz2) = bits_part (b, o1+o2, sz2) + +axiom eq_bits_split : forall b1, b2:bits. forall sz:int. + bits_size (b1) = sz -> bits_size (b2) = sz -> + forall sz1, sz2:int. sz1 >= 0 -> sz2 >= 0 -> sz1 + sz2 = sz -> + bits_part (b1, 0, sz1) = bits_part (b2, 0, sz1) -> + bits_part (b1, sz1, sz2) = bits_part (b2, sz1, sz2) -> + b1 = b2 + +axiom wr_bits_part_all : forall v, v':bits. + bits_size(v) = bits_size(v') -> wr_bits_part (v, 0, v') = v' + +axiom wr_bits_part_concat : + forall b, b':bits. + forall sz1, sz2, sz3:int. 0 <= sz1 -> sz2 = bits_size (b') -> 0 <= sz3 -> + sz1 + sz2 + sz3 = bits_size (b) -> + wr_bits_part (b, sz1, b') = + bits_concat (bits_part (b, 0, sz1), + bits_concat (b', bits_part (b, sz1+sz2, sz3))) + +(* R/W in the same bit part and included in the valid zone *) +axiom wr_bits_part_same : forall b1, b2: bits. forall off: int. + 0 <= off -> off + bits_size (b2) <= bits_size (b1) -> + bits_part (wr_bits_part (b1, off, b2), off, bits_size (b2)) = b2 + +axiom wr_bits_part_disj : + forall b, b1: bits. forall off2, off1: int. forall sz, sz1, sz2:int. + sz = bits_size (b) -> sz1 = bits_size (b1) -> + 0 <= off1 -> off1 + sz1 <= sz -> + 0 <= off2 -> off2 + sz2 <= sz -> + off2 + sz2 <= off1 or off1 + sz1 <= off2 -> + bits_part (wr_bits_part (b, off1, b1), off2, sz2) = bits_part (b, off2, sz2) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* About rt_from_bits/rt_to_bits : *) + +(* 0 is 0 in any integer format. *) +axiom rt_z_from_bits_to_bits_zero: forall fmt, fmt': int format. + rt_from_bits (rt_to_bits (fmt, 0), fmt') = 0 + +axiom bits_part_zero : forall b, b':bits. forall off, sz: int. + 0 <= off -> off + sz <= bits_size (b) -> b' = bits_part (b, off, sz) -> + zero_bits (b) -> zero_bits (b') + +axiom rw_same_var : forall m:memory. forall ma:memalloc. + forall v:int. forall val: bits + [rt_load (rt_store (m, rt_vaddr (ma, v), val), rt_vzone (ma, v))]. + bits_size (val) = rt_vsize (v) -> + rt_load (rt_store (m, rt_vaddr (ma, v), val), rt_vzone (ma, v)) = val + +axiom rw_disj_var : forall ma:memalloc. forall m:memory. forall v1, v2: int. + forall z1, z2: zone. forall b:bits + [rt_load (rt_store (m, rt_vaddr (ma, v2), b), rt_vzone (ma, v1))] . + v1 <> v2 -> z1 = rt_vzone (ma, v1) -> z2 = rt_vzone (ma, v2) -> + rt_valid (ma, z1) -> rt_valid (ma, z2) -> rt_vsize (v2) = bits_size (b) -> + rt_load (rt_store (m, rt_vaddr (ma, v2), b), z1) = rt_load(m, z1) + +axiom store_concat : + forall m, m1: memory. forall a: int. forall b1, b2: bits. + forall sz1:int. sz1 = bits_size (b1) -> m1 = rt_store (m, a, b1) -> + rt_store (m1, a + sz1, b2) = rt_store (m, a, bits_concat (b1, b2)) + +axiom store_disj_commut : forall m:memory. + forall a1, a2: int. forall b1, b2: bits. + rt_disj (rt_zone (a1, bits_size (b1)), rt_zone (a2, bits_size (b2))) -> + rt_store (rt_store (m, a1, b1), a2, b2) += rt_store (rt_store (m, a2, b2), a1, b1) + +(* +axiom mbyte_to_bbits_to_mbyte : forall b:bool farray. + n_bits_eq (7, mbyte_to_bbits (bbits_to_mbyte (0, b)), b) + +axiom bbits_to_mbyte_to_bbits : forall b:bits. bits_size (b) = 8 -> + bbits_to_mbyte (0, mbyte_to_bbits (b)) = b + +axiom nth_byte_0 : forall b:bits. bits_size (b) = 8 -> + nth_byte (0, b) = mbyte_to_bbits (b) + +axiom bits_concat_nth_byte_left : forall b1, b2: bits. forall k:int. + 8*(k+1) <= bits_size (b1) -> + nth_byte (k, bits_concat (b1, b2)) = nth_byte (k, b1) + +axiom bits_concat_nth_byte_right : forall b1, b2: bits. forall k1, k:int. + bits_size (b1) = 8 * k1 -> k1 <= k -> 8*((k-k1)+1) <= bits_size (b2) -> + nth_byte (k, bits_concat (b1, b2)) = nth_byte (k-k1, b2) +*) +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) +(* About allocation : *) + +axiom not_valid_before_valloc : forall ma:memalloc. forall v:int + (* [ not rt_valid (ma, rt_vzone (ma', v)) ] *) . + forall ma':memalloc. ma' = rt_valloc (ma, v) -> + not rt_valid (ma, rt_vzone (ma', v)) + +axiom valid_valloc : forall ma:memalloc. forall v:int. forall ma':memalloc + [ rt_valid (ma', rt_vzone (ma', v)) ]. + ma' = rt_valloc (ma, v) -> rt_valid (ma', rt_vzone (ma', v)) + +axiom valloc_keep_valid_zone : forall ma:memalloc. forall v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> + forall z:zone. rt_valid (ma, z) -> rt_valid (ma', z) + +axiom valloc_keep_valid_disj_zone : forall ma:memalloc. forall v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> + forall z:zone. rt_disj (rt_vzone (ma', v), z) -> + rt_valid (ma', z) -> rt_valid (ma, z) + +axiom valloc_keep_invalid_zone : forall ma:memalloc. forall v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> + forall z:zone. rt_disj (rt_vzone (ma', v), z) -> + not rt_valid (ma, z) -> not rt_valid (ma', z) + +axiom valloc_keep_invalid_zone_rev : forall ma:memalloc. forall v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> + forall z:zone. rt_disj (rt_vzone (ma', v), z) -> + not rt_valid (ma', z) -> not rt_valid (ma, z) + +(* TODO hyp v<>v1 shouldn't be needed since v1 is valid before alloc v *) +axiom valloc_keep_valid_var : forall ma:memalloc. forall v1, v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> v <> v1 -> + rt_valid (ma, rt_vzone (ma, v1)) -> rt_valid (ma', rt_vzone (ma', v1)) + +axiom valloc_keep_vaddr : forall ma:memalloc. forall v1, v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> v <> v1 -> + rt_vaddr (ma', v1) = rt_vaddr (ma, v1) + +(* +axiom valloc_keep_vsize : forall ma:memalloc. forall v1, v, sz:int. + forall ma':memalloc. ma' = rt_valloc (ma, v, sz) -> v <> v1 -> + rt_vsize (ma', v1) = rt_vsize (ma, v1) +*) + +axiom valloc_keep_vzone : forall ma:memalloc. forall v1, v:int. + forall ma':memalloc. ma' = rt_valloc (ma, v) -> v <> v1 -> + rt_vzone (ma', v1) = rt_vzone (ma, v1) + +axiom vzone_vfree : forall ma:memalloc. forall v1, v2: int. + forall ma':memalloc. ma' = rt_vfree (ma, v1) -> v1 <> v2 -> + rt_vzone (ma', v2) = rt_vzone (ma, v2) + +axiom not_valid_after_vfree : forall ma:memalloc. forall v:int. + forall ma':memalloc. ma' = rt_vfree (ma, v) -> + forall z:zone. z = rt_vzone (ma, v) -> + not (rt_valid (ma', z)) + + +axiom havoc_store: forall ma:memalloc. forall m1,m2:memory. forall zs:zones. + forall z:zone. forall x:bits. forall a:int. z = rt_zone (a, bits_size (x)) -> + rt_is_havoc (ma, m1, zs, m2) -> zs_z_incl (z, zs) -> + rt_is_havoc (ma, m1, zs, rt_store (m2, a, x)) + +axiom havoc_invalid : forall ma:memalloc. forall m1,m2:memory. forall zs:zones. + forall z:zone. forall x:bits. forall a:int. z = rt_zone (a, bits_size (x)) -> + rt_is_havoc (ma, m1, zs, m2) -> not rt_valid (ma, z) -> + rt_is_havoc (ma, m1, zs, rt_store (m2, a, x)) + +axiom same_bits_same_val : forall b1, b2:bits. forall fmt: 'a format. + b1 = b2 -> rt_from_bits (b1, fmt) = rt_from_bits (b2, fmt) + +axiom valid_vglob : forall v:int. rt_global (v) -> + forall ma, ma':memalloc. rt_valid (ma, rt_vzone (ma', v)) + +(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/store_ergo.why frama-c-20111001+nitrogen+dfsg/src/wp/share/store_ergo.why --- frama-c-20110201+carbon+dfsg/src/wp/share/store_ergo.why 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/store_ergo.why 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,1156 @@ +logic eq_unit : unit,unit -> prop + +logic neq_unit : unit,unit -> prop + +logic eq_bool : bool,bool -> prop + +logic neq_bool : bool,bool -> prop + +logic lt_int : int,int -> prop + +logic le_int : int,int -> prop + +logic gt_int : int,int -> prop + +logic ge_int : int,int -> prop + +logic eq_int : int,int -> prop + +logic neq_int : int,int -> prop + +logic add_int : int,int -> int + +logic sub_int : int,int -> int + +logic mul_int : int,int -> int + +logic neg_int : int -> int + +predicate zwf_zero(a:int,b:int) = ((0<=b) and (a<b)) + +logic bool_and : bool,bool -> bool + +logic bool_or : bool,bool -> bool + +logic bool_xor : bool,bool -> bool + +logic bool_not : bool -> bool + +axiom bool_and_def : (forall a:bool.(forall b:bool. +((bool_and(a,b)=true) <-> ((a=true) and (b=true))))) + +axiom bool_or_def : (forall a:bool.(forall b:bool. +((bool_or(a,b)=true) <-> ((a=true) or (b=true))))) + +axiom bool_xor_def : (forall a:bool.(forall b:bool. +((bool_xor(a,b)=true) <-> (a<>b)))) + +axiom bool_not_def : (forall a:bool. +((bool_not(a)=true) <-> (a=false))) + +logic ite : bool,'a1,'a1 -> 'a1 + +axiom ite_true : (forall x:'a1.(forall y:'a1. +(ite(true,x,y)=x))) + +axiom ite_false : (forall x:'a1.(forall y:'a1. +(ite(false,x,y)=y))) + +logic lt_int_bool : int,int -> bool + +logic le_int_bool : int,int -> bool + +logic gt_int_bool : int,int -> bool + +logic ge_int_bool : int,int -> bool + +logic eq_int_bool : int,int -> bool + +logic neq_int_bool : int,int -> bool + +axiom lt_int_bool_axiom : (forall x:int.(forall y:int. +((lt_int_bool(x,y)=true) <-> (x<y)))) + +axiom le_int_bool_axiom : (forall x:int.(forall y:int. +((le_int_bool(x,y)=true) <-> (x<=y)))) + +axiom gt_int_bool_axiom : (forall x:int.(forall y:int. +((gt_int_bool(x,y)=true) <-> (x>y)))) + +axiom ge_int_bool_axiom : (forall x:int.(forall y:int. +((ge_int_bool(x,y)=true) <-> (x>=y)))) + +axiom eq_int_bool_axiom : (forall x:int.(forall y:int. +((eq_int_bool(x,y)=true) <-> (x=y)))) + +axiom neq_int_bool_axiom : (forall x:int.(forall y:int. +((neq_int_bool(x,y)=true) <-> (x<>y)))) + +logic abs_int : int -> int + +axiom abs_int_pos : (forall x:int. +((x>=0) -> (abs_int(x)=x))) + +axiom abs_int_neg : (forall x:int. +((x<=0) -> (abs_int(x)=(-x)))) + +logic int_max : int,int -> int + +logic int_min : int,int -> int + +axiom int_max_is_ge : (forall x:int.(forall y:int. +((int_max(x,y)>=x) and (int_max(x,y)>=y)))) + +axiom int_max_is_some : (forall x:int.(forall y:int. +((int_max(x,y)=x) or (int_max(x,y)=y)))) + +axiom int_min_is_le : (forall x:int.(forall y:int. +((int_min(x,y)<=x) and (int_min(x,y)<=y)))) + +axiom int_min_is_some : (forall x:int.(forall y:int. +((int_min(x,y)=x) or (int_min(x,y)=y)))) + +logic lt_real : real,real -> prop + +logic le_real : real,real -> prop + +logic gt_real : real,real -> prop + +logic ge_real : real,real -> prop + +logic eq_real : real,real -> prop + +logic neq_real : real,real -> prop + +logic add_real : real,real -> real + +logic sub_real : real,real -> real + +logic mul_real : real,real -> real + +logic div_real : real,real -> real + +logic neg_real : real -> real + +logic real_of_int : int -> real + +axiom real_of_int_zero : (real_of_int(0)=0.0) + +axiom real_of_int_one : (real_of_int(1)=1.0) + +axiom real_of_int_add : (forall x:int.(forall y:int. +(real_of_int((x+y))=(real_of_int(x)+real_of_int(y))))) + +axiom real_of_int_sub : (forall x:int.(forall y:int. +(real_of_int((x-y))=(real_of_int(x)-real_of_int(y))))) + +logic truncate_real_to_int : real -> int + +axiom truncate_down_pos : (forall x:real. +((x>=0.0) -> ((real_of_int(truncate_real_to_int(x))<=x) and (x<real_of_int((truncate_real_to_int(x)+1)))))) + +axiom truncate_up_neg : (forall x:real. +((x<=0.0) -> ((real_of_int((truncate_real_to_int(x)-1))<x) and (x<=real_of_int(truncate_real_to_int(x)))))) + +logic floor_real_to_int : real -> int + +logic ceil_real_to_int : real -> int + +logic lt_real_bool : real,real -> bool + +logic le_real_bool : real,real -> bool + +logic gt_real_bool : real,real -> bool + +logic ge_real_bool : real,real -> bool + +logic eq_real_bool : real,real -> bool + +logic neq_real_bool : real,real -> bool + +axiom lt_real_bool_axiom : (forall x:real.(forall y:real. +((lt_real_bool(x,y)=true) <-> (x<y)))) + +axiom le_real_bool_axiom : (forall x:real.(forall y:real. +((le_real_bool(x,y)=true) <-> (x<=y)))) + +axiom gt_real_bool_axiom : (forall x:real.(forall y:real. +((gt_real_bool(x,y)=true) <-> (x>y)))) + +axiom ge_real_bool_axiom : (forall x:real.(forall y:real. +((ge_real_bool(x,y)=true) <-> (x>=y)))) + +axiom eq_real_bool_axiom : (forall x:real.(forall y:real. +((eq_real_bool(x,y)=true) <-> (x=y)))) + +axiom neq_real_bool_axiom : (forall x:real.(forall y:real. +((neq_real_bool(x,y)=true) <-> (x<>y)))) + +logic real_max : real,real -> real + +logic real_min : real,real -> real + +axiom real_max_is_ge : (forall x:real.(forall y:real. +((real_max(x,y)>=x) and (real_max(x,y)>=y)))) + +axiom real_max_is_some : (forall x:real.(forall y:real. +((real_max(x,y)=x) or (real_max(x,y)=y)))) + +axiom real_min_is_le : (forall x:real.(forall y:real. +((real_min(x,y)<=x) and (real_min(x,y)<=y)))) + +axiom real_min_is_some : (forall x:real.(forall y:real. +((real_min(x,y)=x) or (real_min(x,y)=y)))) + +function sqr_real(x:real) : real = (x*x) + +logic sqrt_real : real -> real + +axiom sqrt_pos : (forall x:real. +((x>=0.0) -> (sqrt_real(x)>=0.0))) + +axiom sqrt_sqr : (forall x:real. +((x>=0.0) -> (sqr_real(sqrt_real(x))=x))) + +axiom sqr_sqrt : (forall x:real. +((x>=0.0) -> (sqrt_real((x*x))=x))) + +logic pow_real : real,real -> real + +logic abs_real : real -> real + +axiom abs_real_pos : (forall x:real[abs_real(x)]. +((x>=0.0) -> (abs_real(x)=x))) + +axiom abs_real_neg : (forall x:real[abs_real(x)]. +((x<=0.0) -> (abs_real(x)=(-x)))) + +logic exp : real -> real + +logic log : real -> real + +logic log10 : real -> real + +axiom log_exp : (forall x:real. +(log(exp(x))=x)) + +axiom exp_log : (forall x:real. +((x>0.0) -> (exp(log(x))=x))) + +logic cos : real -> real + +logic sin : real -> real + +logic tan : real -> real + +logic pi : real + +logic cosh : real -> real + +logic sinh : real -> real + +logic tanh : real -> real + +logic acos : real -> real + +logic asin : real -> real + +logic atan : real -> real + +logic atan2 : real,real -> real + +logic hypot : real,real -> real + +axiom prod_pos : (forall x:real.(forall y:real. +((((x>0.0) and (y>0.0)) -> ((x*y)>0.0)) and (((x<0.0) and (y<0.0)) -> ((x*y)>0.0))))) + +axiom abs_minus : (forall x:real. +(abs_real((-x))=abs_real(x))) + + +logic access : 'a1 farray,int -> 'a1 + +logic update : 'a1 farray,int,'a1 -> 'a1 farray + +axiom access_update : (forall a:'a1 farray.(forall i:int.(forall v:'a1. +(a[i<-v][i]=v)))) + +axiom access_update_neq : (forall a:'a1 farray.(forall i:int.(forall j:int. +(forall v:'a1. +((i<>j) -> (a[i<-v][j]=a[j])))))) + +logic array_length : 'a1 farray -> int + +predicate sorted_array(t:int farray,i:int,j:int) = (forall k1:int. +(forall k2:int. +((((i<=k1) and (k1<=k2)) and (k2<=j)) -> (t[k1]<=t[k2])))) + +predicate exchange(a1:'a1 farray,a2:'a1 farray,i:int,j:int) = ((array_length(a1)=array_length(a2)) and ((a1[i]=a2[j]) and ((a2[i]=a1[j]) and ( +forall k:int. +(((k<>i) and (k<>j)) -> (a1[k]=a2[k])))))) + +logic permut : 'a1 farray,'a1 farray,int,int -> prop + +axiom permut_refl : (forall t:'a1 farray.(forall l:int.(forall u:int. +permut(t,t,l, +u)))) + +axiom permut_sym : (forall t1:'a1 farray.(forall t2:'a1 farray.(forall l:int. +(forall u:int.(permut(t1,t2,l,u) -> permut(t2,t1,l, +u)))))) + +axiom permut_trans : (forall t1:'a1 farray.(forall t2:'a1 farray. +(forall t3:'a1 farray.(forall l:int.(forall u:int.(permut(t1,t2,l, +u) -> (permut(t2,t3,l,u) -> permut(t1,t3,l, +u)))))))) + +axiom permut_exchange : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l:int.(forall u:int.(forall i:int.(forall j:int. +(((l<=i) and (i<=u)) -> (((l<=j) and (j<=u)) -> (exchange(a1,a2,i, +j) -> permut(a1,a2,l, +u)))))))))) + +axiom exchange_upd : (forall a:'a1 farray.(forall i:int.(forall j:int. +exchange(a,a[i<-a[j]][j<-a[i]],i, +j)))) + +axiom permut_weakening : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l1:int.(forall r1:int.(forall l2:int.(forall r2:int. +((((l1<=l2) and (l2<=r2)) and (r2<=r1)) -> (permut(a1,a2,l2,r2) -> permut(a1, +a2,l1, +r1))))))))) + +axiom permut_eq : (forall a1:'a1 farray.(forall a2:'a1 farray.(forall l:int. +(forall u:int.((l<=u) -> (permut(a1,a2,l,u) -> (forall i:int. +(((i<l) or (u<i)) -> (a2[i]=a1[i]))))))))) + +predicate permutation(a1:'a1 farray,a2:'a1 farray) = permut(a1,a2,0, +(array_length(a1)-1)) + +axiom array_length_update : (forall a:'a1 farray.(forall i:int.(forall v:'a1. +(array_length(a[i<-v])=array_length(a))))) + +axiom permut_array_length : (forall a1:'a1 farray.(forall a2:'a1 farray. +(forall l:int.(forall u:int.(permut(a1,a2,l, +u) -> (array_length(a1)=array_length(a2))))))) + +logic computer_div : int,int -> int + +logic computer_mod : int,int -> int + +logic math_div : int,int -> int + +logic math_mod : int,int -> int + +axiom math_div_mod : (forall x:int.(forall y:int. +((y<>0) -> (x=((y*math_div(x,y))+math_mod(x,y)))))) + +axiom math_mod_bound : (forall x:int.(forall y:int. +((y<>0) -> ((0<=math_mod(x,y)) and (math_mod(x,y)<abs_int(y)))))) + +axiom computer_div_mod : (forall x:int. +(forall y:int[computer_div(x,y),computer_mod(x,y)]. +((y<>0) -> (x=((y*computer_div(x,y))+computer_mod(x,y)))))) + +axiom computer_div_bound : (forall x:int.(forall y:int. +(((x>=0) and (y>0)) -> ((0<=computer_div(x,y)) and (computer_div(x,y)<=x))))) + +axiom computer_mod_bound : (forall x:int.(forall y:int. +((y<>0) -> (abs_int(computer_mod(x,y))<abs_int(y))))) + +axiom computer_mod_sign_pos : (forall x:int.(forall y:int. +(((x>=0) and (y<>0)) -> (computer_mod(x,y)>=0)))) + +axiom computer_mod_sign_neg : (forall x:int.(forall y:int. +(((x<=0) and (y<>0)) -> (computer_mod(x,y)<=0)))) + +axiom computer_rounds_toward_zero : (forall x:int.(forall y:int. +((y<>0) -> (abs_int((computer_div(x,y)*y))<=abs_int(x))))) + +logic dummy : int -> prop + +logic assigns : int -> prop + +axiom positive_computer_div_div : (forall x:int.(forall y:int. +((x>0) -> ((y>0) -> (computer_div(x,y)=math_div(x,y)))))) + +type 'a set + +logic empty : 'a1 set + +logic singleton : 'a1 -> 'a1 set + +logic range : int,int -> int set + +logic union : 'a1 set,'a1 set -> 'a1 set + +logic inter : 'a1 set,'a1 set -> 'a1 set + +logic plus_int : int set,int set -> int set + +logic subset : 'a1 set,'a1 set -> prop + +logic range_inf : int -> int set + +logic range_sup : int -> int set + +logic integers_set : int set + +logic equiv : 'a1 set,'a1 set -> prop + +logic member : 'a1,'a1 set -> prop + +axiom singleton_def : (forall x:'a1.member(x, +singleton(x))) + +axiom singleton_eq : (forall x:'a1.(forall y:'a1.(member(x, +singleton(y)) <-> (x=y)))) + +axiom union_member : (forall x:'a1.(forall s1:'a1 set. +(forall s2:'a1 set[member(x,union(s1,s2))].(member(x, +union(s1,s2)) <-> (member(x,s1) or member(x, +s2)))))) + +axiom union_of_empty : (forall x:'a1 set[union(x,empty)]. +(union(x,empty)=x)) + +axiom inter_of_empty : (forall x:'a1 set[inter(x,empty)]. +(inter(x,empty)=empty)) + +axiom union_comm : (forall x:'a1 set.(forall y:'a1 set. +(union(x,y)=union(y,x)))) + +axiom inter_comm : (forall x:'a1 set.(forall y:'a1 set. +(inter(x,y)=inter(y,x)))) + +axiom inter_member : (forall x:'a1.(forall s1:'a1 set. +(forall s2:'a1 set[member(x,inter(s1,s2))].(member(x, +inter(s1,s2)) <-> (member(x,s1) and member(x, +s2)))))) + +axiom plus_int_member_1 : (forall sa:int set.(forall sb:int set. +(forall a:int.(forall b:int[member((a+b),plus_int(sa,sb))].(member(a, +sa) -> (member(b,sb) -> member((a+b), +plus_int(sa,sb)))))))) + +axiom plus_int_member_2 : (forall sa:int set.(forall sb:int set. +(forall c:int.(member(c,plus_int(sa,sb)) -> (exists a:int.(exists b:int. +(member(a,sa) and (member(b, +sb) and (c=(a+b)))))))))) + +axiom subset_empty : (forall sa:'a1 set.subset(empty, +sa)) + +axiom subset_sym : (forall sa:'a1 set.subset(sa, +sa)) + +axiom subset_trans : (forall sa:'a1 set.(forall sb:'a1 set. +(forall sc:'a1 set.(subset(sa,sb) -> (subset(sb,sc) -> subset(sa, +sc)))))) + +axiom subset_def : (forall sa:'a1 set.(forall sb:'a1 set[subset(sa,sb)]. +((forall a:'a1.(member(a,sa) -> member(a,sb))) <-> subset(sa, +sb)))) + +axiom range_def : (forall i:int.(forall j:int.(forall k:int. +(((i<=k) and (k<=j)) <-> member(k, +range(i,j)))))) + +axiom range_def1 : (forall i:int.(forall j:int.(forall k:int. +(((i<=k) and (k<=j)) -> member(k, +range(i,j)))))) + +axiom range_def2 : (forall i:int.(forall j:int.(forall k:int.(member(k, +range(i,j)) -> ((i<=k) and (k<=j)))))) + +axiom range_inf_def : (forall i:int.(forall k:int.((i<=k) <-> member(k, +range_inf(i))))) + +axiom range_sup_def : (forall j:int.(forall k:int.((k<=j) <-> member(k, +range_sup(j))))) + +axiom integers_set_def : (forall k:int.((k>=0) <-> member(k, +integers_set))) + +axiom equiv_def : (forall s1:'a1 set.(forall s2:'a1 set[equiv(s1,s2)]. +(((forall a:'a1.(member(a,s1) -> member(a,s2))) and (forall b:'a1.(member(b, +s2) -> member(b,s1)))) <-> equiv(s1, +s2)))) + +axiom equiv_refl : (forall s:'a1 set.equiv(s, +s)) + +axiom equiv_sym : (forall s1:'a1 set.(forall s2:'a1 set.(equiv(s1, +s2) -> equiv(s2, +s1)))) + +axiom equiv_trans : (forall s1:'a1 set.(forall s2:'a1 set.(forall s3:'a1 set. +(equiv(s1,s2) -> (equiv(s2,s3) -> equiv(s1, +s3)))))) + +logic as_uint8 : int -> int + +predicate is_uint8(x:int) = ((0<=x) and (x<256)) + +axiom as_uint8_def : (forall x:int. +is_uint8(as_uint8(x))) + +axiom as_uint8_involve : (forall x:int[as_uint8(as_uint8(x))]. +(as_uint8(as_uint8(x))=as_uint8(x))) + +axiom is_as_uint8 : (forall x:int[as_uint8(x)]. +(is_uint8(x) -> (as_uint8(x)=x))) + +logic as_sint8 : int -> int + +predicate is_sint8(x:int) = (((-128)<=x) and (x<128)) + +axiom as_sint8_def : (forall x:int. +is_sint8(as_sint8(x))) + +axiom as_sint8_involve : (forall x:int[as_sint8(as_sint8(x))]. +(as_sint8(as_sint8(x))=as_sint8(x))) + +axiom is_as_sint8 : (forall x:int[as_sint8(x)]. +(is_sint8(x) -> (as_sint8(x)=x))) + +logic as_uint16 : int -> int + +predicate is_uint16(x:int) = ((0<=x) and (x<65536)) + +axiom as_uint16_def : (forall x:int. +is_uint16(as_uint16(x))) + +axiom as_uint16_involve : (forall x:int[as_uint16(as_uint16(x))]. +(as_uint16(as_uint16(x))=as_uint16(x))) + +axiom is_as_uint16 : (forall x:int[as_uint16(x)]. +(is_uint16(x) -> (as_uint16(x)=x))) + +logic as_sint16 : int -> int + +predicate is_sint16(x:int) = (((-32768)<=x) and (x<32768)) + +axiom as_sint16_def : (forall x:int. +is_sint16(as_sint16(x))) + +axiom as_sint16_involve : (forall x:int[as_sint16(as_sint16(x))]. +(as_sint16(as_sint16(x))=as_sint16(x))) + +axiom is_as_sint16 : (forall x:int[as_sint16(x)]. +(is_sint16(x) -> (as_sint16(x)=x))) + +logic as_uint32 : int -> int + +predicate is_uint32(x:int) = ((0<=x) and (x<4294967296)) + +axiom as_uint32_def : (forall x:int. +is_uint32(as_uint32(x))) + +axiom as_uint32_involve : (forall x:int[as_uint32(as_uint32(x))]. +(as_uint32(as_uint32(x))=as_uint32(x))) + +axiom is_as_uint32 : (forall x:int[as_uint32(x)]. +(is_uint32(x) -> (as_uint32(x)=x))) + +logic as_sint32 : int -> int + +predicate is_sint32(x:int) = (((-2147483648)<=x) and (x<2147483648)) + +axiom as_sint32_def : (forall x:int. +is_sint32(as_sint32(x))) + +axiom as_sint32_involve : (forall x:int[as_sint32(as_sint32(x))]. +(as_sint32(as_sint32(x))=as_sint32(x))) + +axiom is_as_sint32 : (forall x:int[as_sint32(x)]. +(is_sint32(x) -> (as_sint32(x)=x))) + +logic as_uint64 : int -> int + +predicate is_uint64(x:int) = ((0<=x) and (x<18446744073709551616)) + +axiom as_uint64_def : (forall x:int. +is_uint64(as_uint64(x))) + +axiom as_uint64_involve : (forall x:int[as_uint64(as_uint64(x))]. +(as_uint64(as_uint64(x))=as_uint64(x))) + +axiom is_as_uint64 : (forall x:int[as_uint64(x)]. +(is_uint64(x) -> (as_uint64(x)=x))) + +logic as_sint64 : int -> int + +predicate is_sint64(x:int) = (((-9223372036854775808)<=x) and (x<9223372036854775808)) + +axiom as_sint64_def : (forall x:int. +is_sint64(as_sint64(x))) + +axiom as_sint64_involve : (forall x:int[as_sint64(as_sint64(x))]. +(as_sint64(as_sint64(x))=as_sint64(x))) + +axiom is_as_sint64 : (forall x:int[as_sint64(x)]. +(is_sint64(x) -> (as_sint64(x)=x))) + +logic as_float16 : real -> real + +logic is_float16 : real -> prop + +axiom as_float16_def : (forall x:real. +is_float16(as_float16(x))) + +axiom as_float16_involve : (forall x:real[as_float16(as_float16(x))]. +(as_float16(as_float16(x))=as_float16(x))) + +axiom is_as_float16 : (forall x:real[as_float16(x)]. +(is_float16(x) -> (as_float16(x)=x))) + +logic as_float32 : real -> real + +logic is_float32 : real -> prop + +axiom as_float32_def : (forall x:real. +is_float32(as_float32(x))) + +axiom as_float32_involve : (forall x:real[as_float32(as_float32(x))]. +(as_float32(as_float32(x))=as_float32(x))) + +axiom is_as_float32 : (forall x:real[as_float32(x)]. +(is_float32(x) -> (as_float32(x)=x))) + +logic as_float64 : real -> real + +logic is_float64 : real -> prop + +axiom as_float64_def : (forall x:real. +is_float64(as_float64(x))) + +axiom as_float64_involve : (forall x:real[as_float64(as_float64(x))]. +(as_float64(as_float64(x))=as_float64(x))) + +axiom is_as_float64 : (forall x:real[as_float64(x)]. +(is_float64(x) -> (as_float64(x)=x))) + +logic as_float128 : real -> real + +logic is_float128 : real -> prop + +axiom as_float128_def : (forall x:real. +is_float128(as_float128(x))) + +axiom as_float128_involve : (forall x:real[as_float128(as_float128(x))]. +(as_float128(as_float128(x))=as_float128(x))) + +axiom is_as_float128 : (forall x:real[as_float128(x)]. +(is_float128(x) -> (as_float128(x)=x))) + +type data + +logic data_of_uint8 : int -> data + +logic uint8_of_data : data -> int + +axiom is_uint8_of_data : (forall d:data[is_uint8(uint8_of_data(d))]. +is_uint8(uint8_of_data(d))) + +axiom uint8ofdata_dataofuint8 : (forall x:int[data_of_uint8(x)]. +(is_uint8(x) -> (uint8_of_data(data_of_uint8(x))=x))) + +logic data_of_sint8 : int -> data + +logic sint8_of_data : data -> int + +axiom is_sint8_of_data : (forall d:data[is_sint8(sint8_of_data(d))]. +is_sint8(sint8_of_data(d))) + +axiom sint8ofdata_dataofsint8 : (forall x:int[data_of_sint8(x)]. +(is_sint8(x) -> (sint8_of_data(data_of_sint8(x))=x))) + +logic data_of_uint16 : int -> data + +logic uint16_of_data : data -> int + +axiom is_uint16_of_data : (forall d:data[is_uint16(uint16_of_data(d))]. +is_uint16(uint16_of_data(d))) + +axiom uint16ofdata_dataofuint16 : (forall x:int[uint16_of_data(data_of_uint16(x))]. +(is_uint16(x) -> (uint16_of_data(data_of_uint16(x))=x))) + +logic data_of_sint16 : int -> data + +logic sint16_of_data : data -> int + +axiom is_sint16_of_data : (forall d:data[is_sint16(sint16_of_data(d))]. +is_sint16(sint16_of_data(d))) + +axiom sint16ofdata_dataofsint16 : (forall x:int[data_of_sint16(x)]. +(is_sint16(x) -> (sint16_of_data(data_of_sint16(x))=x))) + +logic data_of_uint32 : int -> data + +logic uint32_of_data : data -> int + +axiom is_uint32_of_data : (forall d:data[is_uint32(uint32_of_data(d))]. +is_uint32(uint32_of_data(d))) + +axiom uint32ofdata_dataofuint32 : (forall x:int[data_of_uint32(x)]. +(is_uint32(x) -> (uint32_of_data(data_of_uint32(x))=x))) + +logic data_of_sint32 : int -> data + +logic sint32_of_data : data -> int + +axiom is_sint32_of_data : (forall d:data[is_sint32(sint32_of_data(d))]. +is_sint32(sint32_of_data(d))) + +axiom sint32ofdata_dataofsint32 : (forall x:int[data_of_sint32(x)]. +(is_sint32(x) -> (sint32_of_data(data_of_sint32(x))=x))) + +logic data_of_uint64 : int -> data + +logic uint64_of_data : data -> int + +axiom is_uint64_of_data : (forall d:data[is_uint64(uint64_of_data(d))]. +is_uint64(uint64_of_data(d))) + +axiom uint64ofdata_dataofuint64 : (forall x:int[data_of_uint64(x)]. +(is_uint64(x) -> (uint64_of_data(data_of_uint64(x))=x))) + +logic data_of_sint64 : int -> data + +logic sint64_of_data : data -> int + +axiom is_sint64_of_data : (forall d:data[is_sint64(sint64_of_data(d))]. +is_sint64(sint64_of_data(d))) + +axiom sint64ofdata_dataofsint64 : (forall x:int[data_of_sint64(x)]. +(is_sint64(x) -> (sint64_of_data(data_of_sint64(x))=x))) + +logic data_of_float16 : real -> data + +logic float16_of_data : data -> real + +axiom is_float16_of_data : (forall d:data[is_float16(float16_of_data(d))]. +is_float16(float16_of_data(d))) + +axiom float16ofdata_dataoffloat16 : (forall x:real[data_of_float16(x)]. +(is_float16(x) -> (float16_of_data(data_of_float16(x))=x))) + +logic data_of_float32 : real -> data + +logic float32_of_data : data -> real + +axiom is_float32_of_data : (forall d:data[is_float32(float32_of_data(d))]. +is_float32(float32_of_data(d))) + +axiom float32ofdata_dataoffloat32 : (forall x:real[data_of_float32(x)]. +(is_float32(x) -> (float32_of_data(data_of_float32(x))=x))) + +logic data_of_float64 : real -> data + +logic float64_of_data : data -> real + +axiom is_float64_of_data : (forall d:data[is_float64(float64_of_data(d))]. +is_float64(float64_of_data(d))) + +axiom float64ofdata_dataoffloat64 : (forall x:real[data_of_float64(x)]. +(is_float64(x) -> (float64_of_data(data_of_float64(x))=x))) + +logic data_of_float128 : real -> data + +logic float128_of_data : data -> real + +axiom is_float128_of_data : (forall d:data[is_float128(float128_of_data(d))]. +is_float128(float128_of_data(d))) + +axiom float128ofdata_dataoffloat128 : (forall x:real[data_of_float128(x)]. +(is_float128(x) -> (float128_of_data(data_of_float128(x))=x))) + +logic set_range_index : 'a1 farray,int set,int -> 'a1 farray + +axiom set_range_def : (forall t:'a1 farray.(forall rg:int set.(forall k:int. +(forall i:int[set_range_index(t,rg,k)[i]].((not member(i, +rg)) -> (set_range_index(t,rg,k)[i]=t[i])))))) + +logic bnot : int -> int + +logic band : int,int -> int + +logic bor : int,int -> int + +logic bxor : int,int -> int + +logic lshift : int,int -> int + +logic rshift : int,int -> int + +logic int_not : int -> int + +logic int_and : int,int -> int + +logic int_or : int,int -> int + +logic int_xor : int,int -> int + +logic int_lsh : int,int -> int + +logic int_rshs : int,int -> int + +logic int_rshu : int,int -> int + +logic addr : int,int -> int + +logic offset : int -> int + +logic base : int -> int + +axiom addr_def : (forall a:int.(forall b:int.(forall d:int. +((addr(b,d)=a) -> ((base(a)=b) and (offset(a)=d)))))) + +axiom addr_id : (forall p:int[addr(base(p),offset(p))]. +(addr(base(p),offset(p))=p)) + +logic minus_addr : int,int -> int + +axiom minus_addr_def : (forall a:int.(forall b:int. +((base(a)=base(b)) -> (minus_addr(a,b)=(offset(a)-offset(b)))))) + +predicate addr_lt(a:int,b:int) = ((base(a)=base(b)) and (offset(a)<offset(b))) + +function addr_lt_bool(a:int,b:int) : bool = bool_and(eq_int_bool(base(a),base(b)),lt_int_bool(offset(a),offset(b))) + +predicate addr_le(a:int,b:int) = ((base(a)=base(b)) and (offset(a)<=offset(b))) + +function addr_le_bool(a:int,b:int) : bool = bool_and(eq_int_bool(base(a),base(b)),le_int_bool(offset(a),offset(b))) + +predicate addr_eq(a:int,b:int) = ((base(a)=base(b)) and (offset(a)=offset(b))) + +function addr_eq_bool(a:int,b:int) : bool = bool_and(eq_int_bool(base(a),base(b)),eq_int_bool(offset(a),offset(b))) + +axiom cmp_null : (forall p:int[addr_eq(p,0)].((p=0) <-> addr_eq(p, +0))) + +axiom cmp_null_bool : (forall p:int[addr_eq_bool(p,0)]. +((p=0) <-> (addr_eq_bool(p,0)=true))) + +axiom cmp_null_not : (forall p:int.((p<>0) <-> (not addr_eq(p, +0)))) + +axiom cmp_null_bool_not : (forall p:int[addr_eq_bool(p,0)]. +((p<>0) <-> (addr_eq_bool(p,0)=false))) + +logic addr_of_data : data -> int + +logic data_of_addr : int -> data + +axiom addrofdata_dataofaddr : (forall p:int[data_of_addr(p)]. +(addr_of_data(data_of_addr(p))=p)) + +predicate valid(ta:int farray,p:int,n:int) = ((n>0) -> ((0<=offset(p)) and ((offset(p)+n)<=ta[base(p)]))) + +logic global : int farray -> prop + +logic is_fresh : data farray,int farray,int -> prop + +axiom fresh : (forall mem:data farray.(forall ta:int farray. +(forall ta':int farray.(forall x:int.(forall p:int. +(forall n:int[valid(ta',p,n),is_fresh(mem,ta,x)].(is_fresh(mem,ta, +x) -> ((ta[x]=0) -> ((ta[base(p)]=ta'[base(p)]) -> (valid(ta',p, +n) -> (forall d:int.(forall sz:int. +(addr(x,d)<>p))))))))))))) + +axiom fresh_access : (forall mem:data farray.(forall mem':data farray. +(forall ta:int farray.(forall ta':int farray.(forall b:int.(forall p:int. +(forall n:int[is_fresh(mem,ta,b),valid(ta',p,n),addr_of_data(mem'[p])]. +(is_fresh(mem,ta,b) -> ((ta[b]=0) -> (valid(ta',p, +n) -> ((ta[base(p)]=ta'[base(p)]) -> ((mem[p]=mem'[p]) -> (forall d:int. +(addr(b,d)<>addr_of_data(mem'[p]))))))))))))))) + +function addr_shift(p:int,dofs:int) : int = addr(base(p),(offset(p)+dofs)) + +predicate separated_on_addr(p:int,p':int,n1:int,n2:int) = ((base(p)=base(p')) -> (((offset(p)+n1)<=offset(p')) or (offset(p)>=(offset(p')+n2)))) + +type zone + +logic zrange : int,int,int -> zone + +logic zempty : zone + +logic zunion : zone,zone -> zone + +logic included : zone,zone -> prop + +logic is_havoc : int farray,data farray,zone,data farray -> prop + +logic is_block : zone -> prop + +axiom is_block_zrange : (forall x:int.(forall ofs:int.(forall len:int. +((len>0) -> is_block(zrange(x,ofs,len)))))) + +axiom is_not_block_zempty : (not is_block(zempty)) + +function zrange_of_addr(p:int) : zone = zrange(base(p),offset(p),1) + +function zrange_of_addr_range(p:int,dofs:int,n:int) : zone = zrange(base(p),(offset(p)+dofs),n) + +logic separated : zone,zone -> prop + +axiom sep_zrange : (forall b:int.(forall b':int.(forall d:int.(forall d':int. +(forall sz:int.(forall sz':int[separated(zrange(b,d,sz),zrange(b',d',sz'))]. +(separated(zrange(b,d,sz),zrange(b',d',sz')) <-> separated_on_addr(addr(b,d), +addr(b',d'),sz, +sz')))))))) + +axiom separated_sym : (forall z:zone.(forall z':zone.(separated(z, +z') -> separated(z', +z)))) + +axiom sep_empty : (forall z:zone.separated(zempty, +z)) + +axiom sep_union : (forall z:zone.(forall z':zone. +(forall r:zone[separated(z,zunion(z',r))].(separated(z, +zunion(z',r)) <-> (separated(z,z') and separated(z, +r)))))) + +axiom left_empty : (forall z:zone. +(zunion(z,zempty)=z)) + +axiom right_empty : (forall z:zone. +(zunion(zempty,z)=z)) + +axiom union_same : (forall z:zone. +(zunion(z,z)=z)) + +axiom union_sym : (forall z:zone.(forall z':zone. +(zunion(z,z')=zunion(z',z)))) + +axiom union_assoc : (forall z:zone.(forall r:zone.(forall s:zone. +(zunion(zunion(z,r),s)=zunion(z,zunion(r,s)))))) + +axiom inc_range_range : (forall b:int.(forall d:int.(forall sz:int. +(forall b':int.(forall d':int. +(forall sz':int[included(zrange(b,d,sz),zrange(b',d',sz'))]. +(included(zrange(b,d,sz), +zrange(b',d',sz')) <-> ((d<=(d+sz)) -> ((b=b') and ((d'<=d) and ((d+sz)<=(d'+sz')))))))))))) + +axiom inc_empty : (forall z:zone.included(zempty, +z)) + +axiom inc_same : (forall z:zone.included(z, +z)) + +axiom inc_range_empty : (forall b:int.(forall d:int. +(forall sz:int[included(zrange(b,d,sz),zempty)].(included(zrange(b,d,sz), +zempty) <-> (b>(b+sz)))))) + +axiom inc_union_right : (forall z:zone.(forall r:zone. +(forall s:zone[included(z,zunion(r,s))].((included(z,r) or included(z, +s)) -> included(z, +zunion(r,s)))))) + +axiom inc_union_left : (forall s:zone.(forall z:zone. +(forall z':zone[included(zunion(s,z'),z)].(included(s,z) -> (included(z', +z) -> included(zunion(s,z'), +z)))))) + +logic access_range : data farray,zone -> data + +logic update_range : data farray,zone,data -> data farray + +axiom access_update_range_same : (forall m:data farray.(forall z:zone. +(forall d:data. +(is_block(z) -> (access_range(update_range(m,z,d),z)=d))))) + +axiom access_update_range_sep : (forall m:data farray.(forall v:data. +(forall z:zone.(forall z':zone[access_range(update_range(m,z,v),z')]. +(is_block(z) -> (is_block(z') -> (separated(z, +z') -> (access_range(update_range(m,z,v),z')=access_range(m,z'))))))))) + +axiom access_range_update_addr_sep : (forall m:data farray.(forall v:data. +(forall z:zone.(forall p:int[access_range(m[p<-v],z)]. +(is_block(z) -> (separated(z, +zrange_of_addr(p)) -> (access_range(m[p<-v],z)=access_range(m,z)))))))) + +axiom access_update_range_addr_sep : (forall m:data farray.(forall v:data. +(forall z:zone.(forall p:int[update_range(m,z,v)[p]]. +(is_block(z) -> (separated(z, +zrange_of_addr(p)) -> (update_range(m,z,v)[p]=m[p]))))))) + +axiom access_update_sep : (forall m:data farray.(forall v:data.(forall p:int. +(forall q:int[m[p<-v][q]].(separated(zrange_of_addr(p), +zrange_of_addr(q)) -> (m[p<-v][q]=m[q])))))) + +logic update_havoc : data farray,zone,data -> data farray + +axiom load_havoc : (forall m:data farray.(forall v:data.(forall z:zone. +(forall p:int[update_havoc(m,z,v)[p]].(separated(z, +zrange_of_addr(p)) -> (update_havoc(m,z,v)[p]=m[p])))))) + +axiom load_is_havoc : (forall alloc:int farray.(forall mem:data farray. +(forall mem':data farray.(forall p:int. +(forall z:zone[mem[p],is_havoc(alloc,mem,z,mem')]. +(included(zrange_of_addr(p),z) -> (is_havoc(alloc,mem,z, +mem') -> (mem'[p]=mem[p])))))))) + +logic is_assignable : int farray,zone,zone -> prop + +axiom is_assignable_range_free : (forall alloc:int farray.(forall p:int. +(forall z:zone[is_assignable(alloc,zrange_of_addr(p),z)]. +((alloc[base(p)]=0) -> is_assignable(alloc,zrange_of_addr(p), +z))))) + +axiom is_assignable_included : (forall alloc:int farray.(forall z:zone. +(forall z':zone[is_assignable(alloc,z,z')].(included(z, +z') -> is_assignable(alloc,z, +z'))))) + +axiom same_havoc : (forall alloc:int farray.(forall mem:data farray. +(forall z:zone.is_havoc(alloc,mem,z, +mem)))) + +axiom havoc_sym : (forall alloc:int farray.(forall m1:data farray. +(forall m2:data farray.(forall z:zone.(is_havoc(alloc,m2,z, +m1) -> is_havoc(alloc,m1,z, +m2)))))) + +axiom store_havoc : (forall alloc:int farray.(forall mem:data farray. +(forall mem':data farray.(forall p:int.(forall v:data. +(forall z:zone[is_havoc(alloc,mem,z,mem'[p<-v])].(is_assignable(alloc, +zrange_of_addr(p),z) -> (is_havoc(alloc,mem,z,mem') -> is_havoc(alloc,mem,z, +mem'[p<-v]))))))))) + +axiom store_havoc_havoc : (forall alloc:int farray.(forall mem:data farray. +(forall mem':data farray.(forall v:data.(forall z':zone. +(forall z:zone[is_havoc(alloc,mem,z,update_havoc(mem',z',v))]. +(is_assignable(alloc,z',z) -> (is_havoc(alloc,mem,z,mem') -> is_havoc(alloc, +mem,z, +update_havoc(mem',z',v)))))))))) + +axiom store_range_havoc : (forall alloc:int farray.(forall mem:data farray. +(forall mem':data farray.(forall v:data.(forall z':zone. +(forall z:zone[is_havoc(alloc,mem,z,update_range(mem',z',v))]. +(is_block(z') -> (is_assignable(alloc,z',z) -> (is_havoc(alloc,mem,z, +mem') -> is_havoc(alloc,mem,z, +update_range(mem',z',v))))))))))) + +axiom addr_base : (forall b:int.(forall d:int. +(base(addr(b,d))=b))) + +axiom addr_offset : (forall b:int.(forall d:int. +(offset(addr(b,d))=d))) + +axiom base_sep : (forall b:int.(forall b':int.(forall d:int.(forall d':int. +((b<>b') -> (addr(b,d)<>addr(b',d'))))))) + +axiom addr_inj1 : (forall b:int.(forall b':int.(forall d:int. +((b=b') <-> (addr(b,d)=addr(b',d)))))) + +axiom addr_inj2 : (forall b:int.(forall d:int.(forall d':int. +((d=d') <-> (addr(b,d)=addr(b,d')))))) + +axiom addr_lt_eq : (forall a:int[addr_lt(a,a)].(not addr_lt(a, +a))) + +axiom addr_le_eq : (forall a:int[addr_le(a,a)].addr_le(a, +a)) + +axiom minus_pos_lt : (forall a:int.(forall b:int[addr_lt(a,b)]. +((base(a)=base(b)) -> (((offset(b)-offset(a))>0) -> addr_lt(a, +b))))) + +axiom minus_pos_le : (forall a:int.(forall b:int[addr_le(a,b)]. +((base(a)=base(b)) -> (((offset(b)-offset(a))>=0) -> addr_le(a, +b))))) + +axiom addr_lt_le : (forall a:int.(forall b:int[addr_le(a,b)].(addr_lt(a, +b) -> addr_le(a, +b)))) + +axiom havoc_union_update_left : (forall alloc:int farray. +(forall m:data farray.(forall m':data farray.(forall p:int.(forall v:data. +(forall asgns:zone.(is_havoc(alloc,m,zunion(zrange_of_addr(p),asgns), +m') -> is_havoc(alloc,m,zunion(zrange_of_addr(p),asgns), +m'[p<-v])))))))) + +axiom havoc_union_update_right : (forall alloc:int farray. +(forall m:data farray.(forall m':data farray.(forall p:int.(forall v:data. +(forall z:zone.(forall asgns:zone.(included(zrange_of_addr(p), +asgns) -> (is_havoc(alloc,m,zunion(z,asgns),m') -> is_havoc(alloc,m, +zunion(z,asgns), +m'[p<-v])))))))))) + +axiom havoc_union_update_range_left : (forall alloc:int farray. +(forall m:data farray.(forall m':data farray.(forall v:data.(forall p:int. +(forall asgns:zone.(is_havoc(alloc,m,zunion(zrange_of_addr(p),asgns), +m') -> is_havoc(alloc,m,zunion(zrange_of_addr(p),asgns), +update_range(m',zrange_of_addr(p),v))))))))) + +axiom havoc_union_update_range_right : (forall alloc:int farray. +(forall m:data farray.(forall m':data farray.(forall v:data.(forall p:int. +(forall z:zone.(forall asgns:zone.(included(zrange_of_addr(p), +asgns) -> (is_havoc(alloc,m,zunion(z,asgns),m') -> is_havoc(alloc,m, +zunion(z,asgns), +update_range(m',zrange_of_addr(p),v))))))))))) + +axiom inc_union_union : (forall z0:zone.(forall z1:zone.(forall z2:zone. +(forall z3:zone.(included(z0,z2) -> (included(z1, +z3) -> included(zunion(z0,z1), +zunion(z2,z3)))))))) + +axiom inc_sub_zone : (forall z:zone.(forall z':zone. +included(zunion(zunion(z,z'),zunion(z',z)), +zunion(z',z)))) + +axiom inc_permut_union : (forall z:zone.(forall z':zone.(forall r:zone. +included(zunion(zunion(z,z'),r), +zunion(zunion(z,r),z'))))) + +axiom inc_permut2 : (forall z:zone.(forall s:zone.(forall r:zone. +included(zunion(zunion(zunion(zunion(z,s),r),r),s), +zunion(zunion(z,r),s))))) + +axiom union_assoc2 : (forall z:zone.(forall z':zone. +(zunion(z,zunion(z,z'))=zunion(z,z')))) + +axiom addr_shift_0 : (forall p:int[addr_shift(p,0)]. +(addr_shift(p,0)=p)) + +axiom addr_shift_shift : (forall p:int.(forall d:int. +(forall d':int[addr_shift(addr_shift(p,d),d')]. +(addr_shift(addr_shift(p,d),d')=addr_shift(p,(d+d')))))) + +axiom valid_elt : (forall ta:int farray.(forall p:int.(forall i:int. +(forall n:int.((n>0) -> (valid(ta,p,n) -> ((0<=i) -> (((i+1)<=n) -> valid(ta, +addr_shift(p,i), +1))))))))) + +axiom separated_on_addr_sym : (forall p:int.(forall q:int.(forall n:int. +(forall m:int.(separated_on_addr(p,q,n,m) -> separated_on_addr(q,p,m, +n)))))) + +axiom separated_on_addr_inc : (forall b:int.(forall d:int.(forall d':int. +(forall sz:int.(forall sz':int.(forall b1:int.(forall d1:int.(forall sz1:int. +(separated_on_addr(addr(b1,d1),addr(b,d),sz1, +sz) -> ((d<=d') -> (((d'+sz')<=(d+sz)) -> separated_on_addr(addr(b1,d1), +addr(b,d'),sz1, +sz')))))))))))) + +axiom separated_inc : (forall b:int.(forall d:int.(forall d':int. +(forall sz:int.(forall sz':int.(forall b1:int.(forall d1:int.(forall sz1:int. +(separated(zrange(b1,d1,sz1), +zrange(b,d,sz)) -> ((d<=d') -> (((d'+sz')<=(d+sz)) -> separated(zrange(b1,d1,sz1), +zrange(b,d',sz'))))))))))))) + +axiom separated_one_elt : (forall n:int.(forall m:int.(forall b:int. +(forall d:int.(forall sz:int.(forall b':int.(forall d':int.(forall sz':int. +((0<n) -> ((0<m) -> (separated(zrange(b,d,(sz*n)), +zrange(b',d',(sz'*m))) -> (forall i:int.(forall j:int. +((0<=i) -> ((0<=j) -> ((((d+i)+sz)<=(d+(sz*n))) -> ((((d'+j)+sz')<=(d'+(sz'*m))) -> separated(zrange(b,(d+i),sz), +zrange(b',(d'+j),sz'))))))))))))))))))) + +axiom store_pointer : (forall x:int.(forall ofs:int.(forall y:int. +(forall ofs':int.(separated_on_addr(addr(x,ofs),addr(y,ofs'),1, +1) or (addr(x,ofs)=addr(y,ofs'))))))) + + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/store_model.v frama-c-20111001+nitrogen+dfsg/src/wp/share/store_model.v --- frama-c-20110201+carbon+dfsg/src/wp/share/store_model.v 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/store_model.v 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,1785 @@ +(* This file was originally generated by why. + It can be modified; only the generated parts will be overwritten. *) +Require Import Reals. Require Import wp. + +(*Why logic*) Definition bool_and : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_or : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_xor : bool -> bool -> bool. +Admitted. + +(*Why logic*) Definition bool_not : bool -> bool. +Admitted. + +(*Why axiom*) Lemma bool_and_def : + (forall (a:bool), + (forall (b:bool), ((bool_and a b) = true <-> a = true /\ b = true))). +Admitted. + +(*Why axiom*) Lemma bool_or_def : + (forall (a:bool), + (forall (b:bool), ((bool_or a b) = true <-> a = true \/ b = true))). +Admitted. + +(*Why axiom*) Lemma bool_xor_def : + (forall (a:bool), (forall (b:bool), ((bool_xor a b) = true <-> ~(a = b)))). +Admitted. + +(*Why axiom*) Lemma bool_not_def : + (forall (a:bool), ((bool_not a) = true <-> a = false)). +Admitted. + +(*Why logic*) Definition ite : forall (A1:Set), bool -> A1 -> A1 -> A1. +Admitted. +Implicit Arguments ite. + +(*Why axiom*) Lemma ite_true : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), (if_then_else true x y) = x)). +Admitted. + +(*Why axiom*) Lemma ite_false : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), (if_then_else false x y) = y)). +Admitted. + +(*Why logic*) Definition lt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition le_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition gt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition ge_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition eq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition neq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why axiom*) Lemma lt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((lt_int_bool x y) = true <-> x < y))). +Admitted. + +(*Why axiom*) Lemma le_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((le_int_bool x y) = true <-> x <= y))). +Admitted. + +(*Why axiom*) Lemma gt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((gt_int_bool x y) = true <-> x > y))). +Admitted. + +(*Why axiom*) Lemma ge_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((ge_int_bool x y) = true <-> x >= y))). +Admitted. + +(*Why axiom*) Lemma eq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((eq_int_bool x y) = true <-> x = y))). +Admitted. + +(*Why axiom*) Lemma neq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((neq_int_bool x y) = true <-> x <> y))). +Admitted. + +(*Why logic*) Definition abs_int : Z -> Z. +Admitted. + +(*Why axiom*) Lemma abs_int_pos : + (forall (x:Z), (x >= 0 -> (abs_int x) = x)). +Admitted. + +(*Why axiom*) Lemma abs_int_neg : + (forall (x:Z), (x <= 0 -> (abs_int x) = (Zopp x))). +Admitted. + +(*Why logic*) Definition int_max : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_min : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma int_max_is_ge : + (forall (x:Z), (forall (y:Z), (int_max x y) >= x /\ (int_max x y) >= y)). +Admitted. + +(*Why axiom*) Lemma int_max_is_some : + (forall (x:Z), (forall (y:Z), (int_max x y) = x \/ (int_max x y) = y)). +Admitted. + +(*Why axiom*) Lemma int_min_is_le : + (forall (x:Z), (forall (y:Z), (int_min x y) <= x /\ (int_min x y) <= y)). +Admitted. + +(*Why axiom*) Lemma int_min_is_some : + (forall (x:Z), (forall (y:Z), (int_min x y) = x \/ (int_min x y) = y)). +Admitted. + +(*Why logic*) Definition lt_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition le_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition gt_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition ge_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition eq_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition neq_real : R -> R -> Prop. +Admitted. + +(*Why logic*) Definition add_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition sub_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition mul_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition div_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition neg_real : R -> R. +Admitted. + +(*Why logic*) Definition real_of_int : Z -> R. +Admitted. + +(*Why axiom*) Lemma real_of_int_zero : (eq (IZR 0) (0)%R). +Admitted. + +(*Why axiom*) Lemma real_of_int_one : (eq (IZR 1) (1)%R). +Admitted. + +(*Why axiom*) Lemma real_of_int_add : + (forall (x:Z), (forall (y:Z), (eq (IZR (x + y)) (Rplus (IZR x) (IZR y))))). +Admitted. + +(*Why axiom*) Lemma real_of_int_sub : + (forall (x:Z), (forall (y:Z), (eq (IZR (x - y)) (Rminus (IZR x) (IZR y))))). +Admitted. + +(*Why logic*) Definition truncate_real_to_int : R -> Z. +Admitted. + +(*Why axiom*) Lemma truncate_down_pos : + (forall (x:R), + ((Rge x (0)%R) -> (Rle (IZR (truncate_real_to_int x)) x) /\ + (Rlt x (IZR ((truncate_real_to_int x) + 1))))). +Admitted. + +(*Why axiom*) Lemma truncate_up_neg : + (forall (x:R), + ((Rle x (0)%R) -> (Rlt (IZR ((truncate_real_to_int x) - 1)) x) /\ + (Rle x (IZR (truncate_real_to_int x))))). +Admitted. + +(*Why logic*) Definition floor_real_to_int : R -> Z. +Admitted. + +(*Why logic*) Definition ceil_real_to_int : R -> Z. +Admitted. + +(*Why logic*) Definition lt_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition le_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition gt_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition ge_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition eq_real_bool : R -> R -> bool. +Admitted. + +(*Why logic*) Definition neq_real_bool : R -> R -> bool. +Admitted. + +(*Why axiom*) Lemma lt_real_bool_axiom : + (forall (x:R), (forall (y:R), ((lt_real_bool x y) = true <-> (Rlt x y)))). +Admitted. + +(*Why axiom*) Lemma le_real_bool_axiom : + (forall (x:R), (forall (y:R), ((le_real_bool x y) = true <-> (Rle x y)))). +Admitted. + +(*Why axiom*) Lemma gt_real_bool_axiom : + (forall (x:R), (forall (y:R), ((gt_real_bool x y) = true <-> (Rgt x y)))). +Admitted. + +(*Why axiom*) Lemma ge_real_bool_axiom : + (forall (x:R), (forall (y:R), ((ge_real_bool x y) = true <-> (Rge x y)))). +Admitted. + +(*Why axiom*) Lemma eq_real_bool_axiom : + (forall (x:R), (forall (y:R), ((eq_real_bool x y) = true <-> (eq x y)))). +Admitted. + +(*Why axiom*) Lemma neq_real_bool_axiom : + (forall (x:R), (forall (y:R), ((neq_real_bool x y) = true <-> ~(eq x y)))). +Admitted. + +(*Why logic*) Definition real_max : R -> R -> R. +Admitted. + +(*Why logic*) Definition real_min : R -> R -> R. +Admitted. + +(*Why axiom*) Lemma real_max_is_ge : + (forall (x:R), + (forall (y:R), (Rge (real_max x y) x) /\ (Rge (real_max x y) y))). +Admitted. + +(*Why axiom*) Lemma real_max_is_some : + (forall (x:R), + (forall (y:R), (eq (real_max x y) x) \/ (eq (real_max x y) y))). +Admitted. + +(*Why axiom*) Lemma real_min_is_le : + (forall (x:R), + (forall (y:R), (Rle (real_min x y) x) /\ (Rle (real_min x y) y))). +Admitted. + +(*Why axiom*) Lemma real_min_is_some : + (forall (x:R), + (forall (y:R), (eq (real_min x y) x) \/ (eq (real_min x y) y))). +Admitted. + +(*Why function*) Definition sqr_real (x:R) := (Rmult x x). + +(*Why logic*) Definition sqrt_real : R -> R. +Admitted. + +(*Why axiom*) Lemma sqrt_pos : + (forall (x:R), ((Rge x (0)%R) -> (Rge (sqrt x) (0)%R))). +Admitted. + +(*Why axiom*) Lemma sqrt_sqr : + (forall (x:R), ((Rge x (0)%R) -> (eq (sqr_real (sqrt x)) x))). +Admitted. + +(*Why axiom*) Lemma sqr_sqrt : + (forall (x:R), ((Rge x (0)%R) -> (eq (sqrt (Rmult x x)) x))). +Admitted. + +(*Why logic*) Definition pow_real : R -> R -> R. +Admitted. + +(*Why logic*) Definition abs_real : R -> R. +Admitted. + +(*Why axiom*) Lemma abs_real_pos : + (forall (x:R), ((Rge x (0)%R) -> (eq (Rabs x) x))). +Admitted. + +(*Why axiom*) Lemma abs_real_neg : + (forall (x:R), ((Rle x (0)%R) -> (eq (Rabs x) (Ropp x)))). +Admitted. + +(*Why logic*) Definition exp : R -> R. +Admitted. + +(*Why logic*) Definition log : R -> R. +Admitted. + +(*Why logic*) Definition log10 : R -> R. +Admitted. + +(*Why axiom*) Lemma log_exp : (forall (x:R), (eq (log (exp x)) x)). +Admitted. + +(*Why axiom*) Lemma exp_log : + (forall (x:R), ((Rgt x (0)%R) -> (eq (exp (log x)) x))). +Admitted. + +(*Why logic*) Definition cos : R -> R. +Admitted. + +(*Why logic*) Definition sin : R -> R. +Admitted. + +(*Why logic*) Definition tan : R -> R. +Admitted. + +(*Why logic*) Definition pi : R. +Admitted. + +(*Why logic*) Definition cosh : R -> R. +Admitted. + +(*Why logic*) Definition sinh : R -> R. +Admitted. + +(*Why logic*) Definition tanh : R -> R. +Admitted. + +(*Why logic*) Definition acos : R -> R. +Admitted. + +(*Why logic*) Definition asin : R -> R. +Admitted. + +(*Why logic*) Definition atan : R -> R. +Admitted. + +(*Why logic*) Definition atan2 : R -> R -> R. +Admitted. + +(*Why logic*) Definition hypot : R -> R -> R. +Admitted. + +(*Why axiom*) Lemma prod_pos : + (forall (x:R), + (forall (y:R), + (((Rgt x (0)%R) /\ (Rgt y (0)%R) -> (Rgt (Rmult x y) (0)%R))) /\ + (((Rlt x (0)%R) /\ (Rlt y (0)%R) -> (Rgt (Rmult x y) (0)%R))))). +Admitted. + +(*Why axiom*) Lemma abs_minus : + (forall (x:R), (eq (Rabs (Ropp x)) (Rabs x))). +Admitted. + +(*Why type*) Definition farray: Set ->Set. +Admitted. + +(*Why logic*) Definition access : forall (A1:Set), (array A1) -> Z -> A1. +Admitted. +Implicit Arguments access. + +(*Why logic*) Definition update : + forall (A1:Set), (array A1) -> Z -> A1 -> (array A1). +Admitted. +Implicit Arguments update. + +(*Why axiom*) Lemma access_update : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), (forall (v:A1), (access (update a i v) i) = v))). +Admitted. + +(*Why axiom*) Lemma access_update_neq : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (j:Z), + (forall (v:A1), (i <> j -> (access (update a i v) j) = (access a j)))))). +Admitted. + +(*Why logic*) Definition array_length : forall (A1:Set), (array A1) -> Z. +Admitted. +Implicit Arguments array_length. + +(*Why predicate*) Definition sorted_array (t:(array Z)) (i:Z) (j:Z) + := (forall (k1:Z), + (forall (k2:Z), + ((i <= k1 /\ k1 <= k2) /\ k2 <= j -> (access t k1) <= (access t k2)))). + +(*Why predicate*) Definition exchange (A226:Set) (a1:(array A226)) (a2:(array A226)) (i:Z) (j:Z) + := (array_length a1) = (array_length a2) /\ + (access a1 i) = (access a2 j) /\ (access a2 i) = (access a1 j) /\ + (forall (k:Z), (k <> i /\ k <> j -> (access a1 k) = (access a2 k))). +Implicit Arguments exchange. + +(*Why logic*) Definition permut : + forall (A1:Set), (array A1) -> (array A1) -> Z -> Z -> Prop. +Admitted. +Implicit Arguments permut. + +(*Why axiom*) Lemma permut_refl : + forall (A1:Set), + (forall (t:(array A1)), (forall (l:Z), (forall (u:Z), (permut t t l u)))). +Admitted. + +(*Why axiom*) Lemma permut_sym : + forall (A1:Set), + (forall (t1:(array A1)), + (forall (t2:(array A1)), + (forall (l:Z), (forall (u:Z), ((permut t1 t2 l u) -> (permut t2 t1 l u)))))). +Admitted. + +(*Why axiom*) Lemma permut_trans : + forall (A1:Set), + (forall (t1:(array A1)), + (forall (t2:(array A1)), + (forall (t3:(array A1)), + (forall (l:Z), + (forall (u:Z), + ((permut t1 t2 l u) -> ((permut t2 t3 l u) -> (permut t1 t3 l u)))))))). +Admitted. + +(*Why axiom*) Lemma permut_exchange : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + (forall (i:Z), + (forall (j:Z), + (l <= i /\ i <= u -> + (l <= j /\ j <= u -> ((exchange a1 a2 i j) -> (permut a1 a2 l u)))))))))). +Admitted. + +(*Why axiom*) Lemma exchange_upd : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (j:Z), + (exchange a (update (update a i (access a j)) j (access a i)) i j)))). +Admitted. + +(*Why axiom*) Lemma permut_weakening : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l1:Z), + (forall (r1:Z), + (forall (l2:Z), + (forall (r2:Z), + ((l1 <= l2 /\ l2 <= r2) /\ r2 <= r1 -> + ((permut a1 a2 l2 r2) -> (permut a1 a2 l1 r1))))))))). +Admitted. + +(*Why axiom*) Lemma permut_eq : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + (l <= u -> + ((permut a1 a2 l u) -> + (forall (i:Z), (i < l \/ u < i -> (access a2 i) = (access a1 i))))))))). +Admitted. + +(*Why predicate*) Definition permutation (A235:Set) (a1:(array A235)) (a2:(array A235)) + := (permut a1 a2 0 ((array_length a1) - 1)). +Implicit Arguments permutation. + +(*Why axiom*) Lemma array_length_update : + forall (A1:Set), + (forall (a:(array A1)), + (forall (i:Z), + (forall (v:A1), (array_length (update a i v)) = (array_length a)))). +Admitted. + +(*Why axiom*) Lemma permut_array_length : + forall (A1:Set), + (forall (a1:(array A1)), + (forall (a2:(array A1)), + (forall (l:Z), + (forall (u:Z), + ((permut a1 a2 l u) -> (array_length a1) = (array_length a2)))))). +Admitted. + +(*Why logic*) Definition computer_div : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition computer_mod : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition math_div : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition math_mod : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma math_div_mod : + (forall (x:Z), + (forall (y:Z), (y <> 0 -> x = (y * (math_div x y) + (math_mod x y))))). +Admitted. + +(*Why axiom*) Lemma math_mod_bound : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> 0 <= (math_mod x y) /\ (math_mod x y) < (abs_int y)))). +Admitted. + +(*Why axiom*) Lemma computer_div_mod : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> x = (y * (computer_div x y) + (computer_mod x y))))). +Admitted. + +(*Why axiom*) Lemma computer_div_bound : + (forall (x:Z), + (forall (y:Z), + (x >= 0 /\ y > 0 -> 0 <= (computer_div x y) /\ (computer_div x y) <= x))). +Admitted. + +(*Why axiom*) Lemma computer_mod_bound : + (forall (x:Z), + (forall (y:Z), (y <> 0 -> (abs_int (computer_mod x y)) < (abs_int y)))). +Admitted. + +(*Why axiom*) Lemma computer_mod_sign_pos : + (forall (x:Z), + (forall (y:Z), (x >= 0 /\ y <> 0 -> (computer_mod x y) >= 0))). +Admitted. + +(*Why axiom*) Lemma computer_mod_sign_neg : + (forall (x:Z), + (forall (y:Z), (x <= 0 /\ y <> 0 -> (computer_mod x y) <= 0))). +Admitted. + +(*Why axiom*) Lemma computer_rounds_toward_zero : + (forall (x:Z), + (forall (y:Z), + (y <> 0 -> (abs_int ((computer_div x y) * y)) <= (abs_int x)))). +Admitted. + +(*Why logic*) Definition dummy : Z -> Prop. +Admitted. + +(*Why logic*) Definition assigns : Z -> Prop. +Admitted. + +(*Why axiom*) Lemma positive_computer_div_div : + (forall (x:Z), + (forall (y:Z), (x > 0 -> (y > 0 -> (computer_div x y) = (math_div x y))))). +Admitted. + +(*Why type*) Definition set: Set ->Set. +Admitted. + +(*Why logic*) Definition empty : forall (A1:Set), (set A1). +Admitted. +Set Contextual Implicit. +Implicit Arguments empty. +Unset Contextual Implicit. + +(*Why logic*) Definition singleton : forall (A1:Set), A1 -> (set A1). +Admitted. +Implicit Arguments singleton. + +(*Why logic*) Definition range : Z -> Z -> (set Z). +Admitted. + +(*Why logic*) Definition union : + forall (A1:Set), (set A1) -> (set A1) -> (set A1). +Admitted. +Implicit Arguments union. + +(*Why logic*) Definition inter : + forall (A1:Set), (set A1) -> (set A1) -> (set A1). +Admitted. +Implicit Arguments inter. + +(*Why logic*) Definition plus_int : (set Z) -> (set Z) -> (set Z). +Admitted. + +(*Why logic*) Definition subset : + forall (A1:Set), (set A1) -> (set A1) -> Prop. +Admitted. +Implicit Arguments subset. + +(*Why logic*) Definition range_inf : Z -> (set Z). +Admitted. + +(*Why logic*) Definition range_sup : Z -> (set Z). +Admitted. + +(*Why logic*) Definition integers_set : (set Z). +Admitted. + +(*Why logic*) Definition equiv : + forall (A1:Set), (set A1) -> (set A1) -> Prop. +Admitted. +Implicit Arguments equiv. + +(*Why logic*) Definition member : forall (A1:Set), A1 -> (set A1) -> Prop. +Admitted. +Implicit Arguments member. + +(*Why axiom*) Lemma singleton_def : + forall (A1:Set), (forall (x:A1), (member x (singleton x))). +Admitted. + +(*Why axiom*) Lemma singleton_eq : + forall (A1:Set), + (forall (x:A1), (forall (y:A1), ((member x (singleton y)) <-> x = y))). +Admitted. + +(*Why axiom*) Lemma union_member : + forall (A1:Set), + (forall (x:A1), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((member x (union s1 s2)) <-> (member x s1) \/ (member x s2))))). +Admitted. + +(*Why axiom*) Lemma union_of_empty : + forall (A1:Set), (forall (x:(set A1)), (union x (@empty A1)) = x). +Admitted. + +(*Why axiom*) Lemma inter_of_empty : + forall (A1:Set), (forall (x:(set A1)), (inter x (@empty A1)) = (@empty A1)). +Admitted. + +(*Why axiom*) Lemma union_comm : + forall (A1:Set), + (forall (x:(set A1)), (forall (y:(set A1)), (union x y) = (union y x))). +Admitted. + +(*Why axiom*) Lemma inter_comm : + forall (A1:Set), + (forall (x:(set A1)), (forall (y:(set A1)), (inter x y) = (inter y x))). +Admitted. + +(*Why axiom*) Lemma inter_member : + forall (A1:Set), + (forall (x:A1), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((member x (inter s1 s2)) <-> (member x s1) /\ (member x s2))))). +Admitted. + +(*Why axiom*) Lemma plus_int_member_1 : + (forall (sa:(set Z)), + (forall (sb:(set Z)), + (forall (a:Z), + (forall (b:Z), + ((member a sa) -> ((member b sb) -> (member (a + b) (plus_int sa sb)))))))). +Admitted. + +(*Why axiom*) Lemma plus_int_member_2 : + (forall (sa:(set Z)), + (forall (sb:(set Z)), + (forall (c:Z), + ((member c (plus_int sa sb)) -> + (exists a:Z, + (exists b:Z, (member a sa) /\ (member b sb) /\ c = (a + b))))))). +Admitted. + +(*Why axiom*) Lemma subset_empty : + forall (A1:Set), (forall (sa:(set A1)), (subset (@empty A1) sa)). +Admitted. + +(*Why axiom*) Lemma subset_sym : + forall (A1:Set), (forall (sa:(set A1)), (subset sa sa)). +Admitted. + +(*Why axiom*) Lemma subset_trans : + forall (A1:Set), + (forall (sa:(set A1)), + (forall (sb:(set A1)), + (forall (sc:(set A1)), + ((subset sa sb) -> ((subset sb sc) -> (subset sa sc)))))). +Admitted. + +(*Why axiom*) Lemma subset_def : + forall (A1:Set), + (forall (sa:(set A1)), + (forall (sb:(set A1)), + ((forall (a:A1), ((member a sa) -> (member a sb))) <-> (subset sa sb)))). +Admitted. + +(*Why axiom*) Lemma range_def : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), (i <= k /\ k <= j <-> (member k (range i j)))))). +Admitted. + +(*Why axiom*) Lemma range_def1 : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), (i <= k /\ k <= j -> (member k (range i j)))))). +Admitted. + +(*Why axiom*) Lemma range_def2 : + (forall (i:Z), + (forall (j:Z), + (forall (k:Z), ((member k (range i j)) -> i <= k /\ k <= j)))). +Admitted. + +(*Why axiom*) Lemma range_inf_def : + (forall (i:Z), (forall (k:Z), (i <= k <-> (member k (range_inf i))))). +Admitted. + +(*Why axiom*) Lemma range_sup_def : + (forall (j:Z), (forall (k:Z), (k <= j <-> (member k (range_sup j))))). +Admitted. + +(*Why axiom*) Lemma integers_set_def : + (forall (k:Z), (k >= 0 <-> (member k integers_set))). +Admitted. + +(*Why axiom*) Lemma equiv_def : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + ((forall (a:A1), ((member a s1) -> (member a s2))) /\ + (forall (b:A1), ((member b s2) -> (member b s1))) <-> (equiv s1 s2)))). +Admitted. + +(*Why axiom*) Lemma equiv_refl : + forall (A1:Set), (forall (s:(set A1)), (equiv s s)). +Admitted. + +(*Why axiom*) Lemma equiv_sym : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), ((equiv s1 s2) -> (equiv s2 s1)))). +Admitted. + +(*Why axiom*) Lemma equiv_trans : + forall (A1:Set), + (forall (s1:(set A1)), + (forall (s2:(set A1)), + (forall (s3:(set A1)), + ((equiv s1 s2) -> ((equiv s2 s3) -> (equiv s1 s3)))))). +Admitted. + +(*Why logic*) Definition as_uint8 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint8 (x:Z) := 0 <= x /\ x < 256. + +(*Why axiom*) Lemma as_uint8_def : (forall (x:Z), (is_uint8 (as_uint8 x))). +Admitted. + +(*Why axiom*) Lemma as_uint8_involve : + (forall (x:Z), (as_uint8 (as_uint8 x)) = (as_uint8 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint8 : + (forall (x:Z), ((is_uint8 x) -> (as_uint8 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint8 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint8 (x:Z) := (-128) <= x /\ x < 128. + +(*Why axiom*) Lemma as_sint8_def : (forall (x:Z), (is_sint8 (as_sint8 x))). +Admitted. + +(*Why axiom*) Lemma as_sint8_involve : + (forall (x:Z), (as_sint8 (as_sint8 x)) = (as_sint8 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint8 : + (forall (x:Z), ((is_sint8 x) -> (as_sint8 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint16 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint16 (x:Z) := 0 <= x /\ x < 65536. + +(*Why axiom*) Lemma as_uint16_def : + (forall (x:Z), (is_uint16 (as_uint16 x))). +Admitted. + +(*Why axiom*) Lemma as_uint16_involve : + (forall (x:Z), (as_uint16 (as_uint16 x)) = (as_uint16 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint16 : + (forall (x:Z), ((is_uint16 x) -> (as_uint16 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint16 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint16 (x:Z) := (-32768) <= x /\ x < 32768. + +(*Why axiom*) Lemma as_sint16_def : + (forall (x:Z), (is_sint16 (as_sint16 x))). +Admitted. + +(*Why axiom*) Lemma as_sint16_involve : + (forall (x:Z), (as_sint16 (as_sint16 x)) = (as_sint16 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint16 : + (forall (x:Z), ((is_sint16 x) -> (as_sint16 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint32 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint32 (x:Z) := 0 <= x /\ x < 4294967296. + +(*Why axiom*) Lemma as_uint32_def : + (forall (x:Z), (is_uint32 (as_uint32 x))). +Admitted. + +(*Why axiom*) Lemma as_uint32_involve : + (forall (x:Z), (as_uint32 (as_uint32 x)) = (as_uint32 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint32 : + (forall (x:Z), ((is_uint32 x) -> (as_uint32 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint32 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint32 (x:Z) + := (-2147483648) <= x /\ x < 2147483648. + +(*Why axiom*) Lemma as_sint32_def : + (forall (x:Z), (is_sint32 (as_sint32 x))). +Admitted. + +(*Why axiom*) Lemma as_sint32_involve : + (forall (x:Z), (as_sint32 (as_sint32 x)) = (as_sint32 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint32 : + (forall (x:Z), ((is_sint32 x) -> (as_sint32 x) = x)). +Admitted. + +(*Why logic*) Definition as_uint64 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_uint64 (x:Z) + := 0 <= x /\ x < 18446744073709551616. + +(*Why axiom*) Lemma as_uint64_def : + (forall (x:Z), (is_uint64 (as_uint64 x))). +Admitted. + +(*Why axiom*) Lemma as_uint64_involve : + (forall (x:Z), (as_uint64 (as_uint64 x)) = (as_uint64 x)). +Admitted. + +(*Why axiom*) Lemma is_as_uint64 : + (forall (x:Z), ((is_uint64 x) -> (as_uint64 x) = x)). +Admitted. + +(*Why logic*) Definition as_sint64 : Z -> Z. +Admitted. + +(*Why predicate*) Definition is_sint64 (x:Z) + := (-9223372036854775808) <= x /\ x < 9223372036854775808. + +(*Why axiom*) Lemma as_sint64_def : + (forall (x:Z), (is_sint64 (as_sint64 x))). +Admitted. + +(*Why axiom*) Lemma as_sint64_involve : + (forall (x:Z), (as_sint64 (as_sint64 x)) = (as_sint64 x)). +Admitted. + +(*Why axiom*) Lemma is_as_sint64 : + (forall (x:Z), ((is_sint64 x) -> (as_sint64 x) = x)). +Admitted. + +(*Why logic*) Definition as_float16 : R -> R. +Admitted. + +(*Why logic*) Definition is_float16 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float16_def : + (forall (x:R), (is_float16 (as_float16 x))). +Admitted. + +(*Why axiom*) Lemma as_float16_involve : + (forall (x:R), (eq (as_float16 (as_float16 x)) (as_float16 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float16 : + (forall (x:R), ((is_float16 x) -> (eq (as_float16 x) x))). +Admitted. + +(*Why logic*) Definition as_float32 : R -> R. +Admitted. + +(*Why logic*) Definition is_float32 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float32_def : + (forall (x:R), (is_float32 (as_float32 x))). +Admitted. + +(*Why axiom*) Lemma as_float32_involve : + (forall (x:R), (eq (as_float32 (as_float32 x)) (as_float32 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float32 : + (forall (x:R), ((is_float32 x) -> (eq (as_float32 x) x))). +Admitted. + +(*Why logic*) Definition as_float64 : R -> R. +Admitted. + +(*Why logic*) Definition is_float64 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float64_def : + (forall (x:R), (is_float64 (as_float64 x))). +Admitted. + +(*Why axiom*) Lemma as_float64_involve : + (forall (x:R), (eq (as_float64 (as_float64 x)) (as_float64 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float64 : + (forall (x:R), ((is_float64 x) -> (eq (as_float64 x) x))). +Admitted. + +(*Why logic*) Definition as_float128 : R -> R. +Admitted. + +(*Why logic*) Definition is_float128 : R -> Prop. +Admitted. + +(*Why axiom*) Lemma as_float128_def : + (forall (x:R), (is_float128 (as_float128 x))). +Admitted. + +(*Why axiom*) Lemma as_float128_involve : + (forall (x:R), (eq (as_float128 (as_float128 x)) (as_float128 x))). +Admitted. + +(*Why axiom*) Lemma is_as_float128 : + (forall (x:R), ((is_float128 x) -> (eq (as_float128 x) x))). +Admitted. + +(*Why type*) Definition data: Set. +Admitted. + +(*Why logic*) Definition data_of_uint8 : Z -> data. +Admitted. + +(*Why logic*) Definition uint8_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint8_of_data : + (forall (d:data), (is_uint8 (uint8_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint8ofdata_dataofuint8 : + (forall (x:Z), ((is_uint8 x) -> (uint8_of_data (data_of_uint8 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint8 : Z -> data. +Admitted. + +(*Why logic*) Definition sint8_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint8_of_data : + (forall (d:data), (is_sint8 (sint8_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint8ofdata_dataofsint8 : + (forall (x:Z), ((is_sint8 x) -> (sint8_of_data (data_of_sint8 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint16 : Z -> data. +Admitted. + +(*Why logic*) Definition uint16_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint16_of_data : + (forall (d:data), (is_uint16 (uint16_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint16ofdata_dataofuint16 : + (forall (x:Z), ((is_uint16 x) -> (uint16_of_data (data_of_uint16 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint16 : Z -> data. +Admitted. + +(*Why logic*) Definition sint16_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint16_of_data : + (forall (d:data), (is_sint16 (sint16_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint16ofdata_dataofsint16 : + (forall (x:Z), ((is_sint16 x) -> (sint16_of_data (data_of_sint16 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint32 : Z -> data. +Admitted. + +(*Why logic*) Definition uint32_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint32_of_data : + (forall (d:data), (is_uint32 (uint32_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint32ofdata_dataofuint32 : + (forall (x:Z), ((is_uint32 x) -> (uint32_of_data (data_of_uint32 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint32 : Z -> data. +Admitted. + +(*Why logic*) Definition sint32_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint32_of_data : + (forall (d:data), (is_sint32 (sint32_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint32ofdata_dataofsint32 : + (forall (x:Z), ((is_sint32 x) -> (sint32_of_data (data_of_sint32 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_uint64 : Z -> data. +Admitted. + +(*Why logic*) Definition uint64_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_uint64_of_data : + (forall (d:data), (is_uint64 (uint64_of_data d))). +Admitted. + +(*Why axiom*) Lemma uint64ofdata_dataofuint64 : + (forall (x:Z), ((is_uint64 x) -> (uint64_of_data (data_of_uint64 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_sint64 : Z -> data. +Admitted. + +(*Why logic*) Definition sint64_of_data : data -> Z. +Admitted. + +(*Why axiom*) Lemma is_sint64_of_data : + (forall (d:data), (is_sint64 (sint64_of_data d))). +Admitted. + +(*Why axiom*) Lemma sint64ofdata_dataofsint64 : + (forall (x:Z), ((is_sint64 x) -> (sint64_of_data (data_of_sint64 x)) = x)). +Admitted. + +(*Why logic*) Definition data_of_float16 : R -> data. +Admitted. + +(*Why logic*) Definition float16_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float16_of_data : + (forall (d:data), (is_float16 (float16_of_data d))). +Admitted. + +(*Why axiom*) Lemma float16ofdata_dataoffloat16 : + (forall (x:R), + ((is_float16 x) -> (eq (float16_of_data (data_of_float16 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float32 : R -> data. +Admitted. + +(*Why logic*) Definition float32_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float32_of_data : + (forall (d:data), (is_float32 (float32_of_data d))). +Admitted. + +(*Why axiom*) Lemma float32ofdata_dataoffloat32 : + (forall (x:R), + ((is_float32 x) -> (eq (float32_of_data (data_of_float32 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float64 : R -> data. +Admitted. + +(*Why logic*) Definition float64_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float64_of_data : + (forall (d:data), (is_float64 (float64_of_data d))). +Admitted. + +(*Why axiom*) Lemma float64ofdata_dataoffloat64 : + (forall (x:R), + ((is_float64 x) -> (eq (float64_of_data (data_of_float64 x)) x))). +Admitted. + +(*Why logic*) Definition data_of_float128 : R -> data. +Admitted. + +(*Why logic*) Definition float128_of_data : data -> R. +Admitted. + +(*Why axiom*) Lemma is_float128_of_data : + (forall (d:data), (is_float128 (float128_of_data d))). +Admitted. + +(*Why axiom*) Lemma float128ofdata_dataoffloat128 : + (forall (x:R), + ((is_float128 x) -> (eq (float128_of_data (data_of_float128 x)) x))). +Admitted. + +(*Why logic*) Definition set_range_index : + forall (A1:Set), (array A1) -> (set Z) -> Z -> (array A1). +Admitted. +Implicit Arguments set_range_index. + +(*Why axiom*) Lemma set_range_def : + forall (A1:Set), + (forall (t:(array A1)), + (forall (rg:(set Z)), + (forall (k:Z), + (forall (i:Z), + (~(member i rg) -> (access (set_range_index t rg k) i) = (access t i)))))). +Admitted. + +(*Why logic*) Definition bnot : Z -> Z. +Admitted. + +(*Why logic*) Definition band : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition bor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition bxor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition lshift : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition rshift : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_not : Z -> Z. +Admitted. + +(*Why logic*) Definition int_and : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_or : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_xor : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_lsh : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_rshs : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition int_rshu : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition addr : Z -> Z -> Z. +Admitted. + +(*Why logic*) Definition offset : Z -> Z. +Admitted. + +(*Why logic*) Definition base : Z -> Z. +Admitted. + +(*Why axiom*) Lemma addr_def : + (forall (a:Z), + (forall (b:Z), + (forall (d:Z), ((addr b d) = a -> (base a) = b /\ (offset a) = d)))). +Admitted. + +(*Why axiom*) Lemma addr_id : (forall (p:Z), (addr (base p) (offset p)) = p). +Admitted. + +(*Why logic*) Definition minus_addr : Z -> Z -> Z. +Admitted. + +(*Why axiom*) Lemma minus_addr_def : + (forall (a:Z), + (forall (b:Z), + ((base a) = (base b) -> (minus_addr a b) = ((offset a) - (offset b))))). +Admitted. + +(*Why predicate*) Definition addr_lt (a:Z) (b:Z) + := (base a) = (base b) /\ (offset a) < (offset b). + +(*Why function*) Definition addr_lt_bool (a:Z) (b:Z) + := (bool_and + (eq_int_bool (base a) (base b)) (lt_int_bool (offset a) (offset b))). + +(*Why predicate*) Definition addr_le (a:Z) (b:Z) + := (base a) = (base b) /\ (offset a) <= (offset b). + +(*Why function*) Definition addr_le_bool (a:Z) (b:Z) + := (bool_and + (eq_int_bool (base a) (base b)) (le_int_bool (offset a) (offset b))). + +(*Why predicate*) Definition addr_eq (a:Z) (b:Z) + := (base a) = (base b) /\ (offset a) = (offset b). + +(*Why function*) Definition addr_eq_bool (a:Z) (b:Z) + := (bool_and + (eq_int_bool (base a) (base b)) (eq_int_bool (offset a) (offset b))). + +(*Why axiom*) Lemma cmp_null : (forall (p:Z), (p = 0 <-> (addr_eq p 0))). +Admitted. + +(*Why axiom*) Lemma cmp_null_bool : + (forall (p:Z), (p = 0 <-> (addr_eq_bool p 0) = true)). +Admitted. + +(*Why axiom*) Lemma cmp_null_not : + (forall (p:Z), (p <> 0 <-> ~(addr_eq p 0))). +Admitted. + +(*Why axiom*) Lemma cmp_null_bool_not : + (forall (p:Z), (p <> 0 <-> (addr_eq_bool p 0) = false)). +Admitted. + +(*Why logic*) Definition addr_of_data : data -> Z. +Admitted. + +(*Why logic*) Definition data_of_addr : Z -> data. +Admitted. + +(*Why axiom*) Lemma addrofdata_dataofaddr : + (forall (p:Z), (addr_of_data (data_of_addr p)) = p). +Admitted. + +(*Why predicate*) Definition valid (ta:(array Z)) (p:Z) (n:Z) + := (n > 0 -> 0 <= (offset p) /\ ((offset p) + n) <= (access ta (base p))). + +(*Why logic*) Definition global : (array Z) -> Prop. +Admitted. + +(*Why logic*) Definition is_fresh : (array data) -> (array Z) -> Z -> Prop. +Admitted. + +(*Why axiom*) Lemma fresh : + (forall (mem:(array data)), + (forall (ta:(array Z)), + (forall (ta':(array Z)), + (forall (x:Z), + (forall (p:Z), + (forall (n:Z), + ((is_fresh mem ta x) -> + ((access ta x) = 0 -> + ((access ta (base p)) = (access ta' (base p)) -> + ((valid ta' p n) -> + (forall (d:Z), (forall (sz:Z), (addr x d) <> p)))))))))))). +Admitted. + +(*Why axiom*) Lemma fresh_access : + (forall (mem:(array data)), + (forall (mem':(array data)), + (forall (ta:(array Z)), + (forall (ta':(array Z)), + (forall (b:Z), + (forall (p:Z), + (forall (n:Z), + ((is_fresh mem ta b) -> + ((access ta b) = 0 -> + ((valid ta' p n) -> + ((access ta (base p)) = (access ta' (base p)) -> + ((access mem p) = (access mem' p) -> + (forall (d:Z), (addr b d) <> (addr_of_data (access mem' p))))))))))))))). +Admitted. + +(*Why function*) Definition addr_shift (p:Z) (dofs:Z) + := (addr (base p) ((offset p) + dofs)). + +(*Why predicate*) Definition separated_on_addr (p:Z) (p':Z) (n1:Z) (n2:Z) + := ((base p) = (base p') -> ((offset p) + n1) <= (offset p') \/ + (offset p) >= ((offset p') + n2)). + +(*Why type*) Definition zone: Set. +Admitted. + +(*Why logic*) Definition zrange : Z -> Z -> Z -> zone. +Admitted. + +(*Why logic*) Definition zempty : zone. +Admitted. + +(*Why logic*) Definition zunion : zone -> zone -> zone. +Admitted. + +(*Why logic*) Definition included : zone -> zone -> Prop. +Admitted. + +(*Why logic*) Definition is_havoc : + (array Z) -> (array data) -> zone -> (array data) -> Prop. +Admitted. + +(*Why logic*) Definition is_block : zone -> Prop. +Admitted. + +(*Why axiom*) Lemma is_block_zrange : + (forall (x:Z), + (forall (ofs:Z), + (forall (len:Z), (len > 0 -> (is_block (zrange x ofs len)))))). +Admitted. + +(*Why axiom*) Lemma is_not_block_zempty : ~(is_block zempty). +Admitted. + +(*Why function*) Definition zrange_of_addr (p:Z) + := (zrange (base p) (offset p) 1). + +(*Why function*) Definition zrange_of_addr_range (p:Z) (dofs:Z) (n:Z) + := (zrange (base p) ((offset p) + dofs) n). + +(*Why logic*) Definition separated : zone -> zone -> Prop. +Admitted. + +(*Why axiom*) Lemma sep_zrange : + (forall (b:Z), + (forall (b':Z), + (forall (d:Z), + (forall (d':Z), + (forall (sz:Z), + (forall (sz':Z), + ((separated (zrange b d sz) (zrange b' d' sz')) <-> + (separated_on_addr (addr b d) (addr b' d') sz sz')))))))). +Admitted. + +(*Why axiom*) Lemma separated_sym : + (forall (z:zone), + (forall (z':zone), ((separated z z') -> (separated z' z)))). +Admitted. + +(*Why axiom*) Lemma sep_empty : (forall (z:zone), (separated zempty z)). +Admitted. + +(*Why axiom*) Lemma sep_union : + (forall (z:zone), + (forall (z':zone), + (forall (r:zone), + ((separated z (zunion z' r)) <-> (separated z z') /\ (separated z r))))). +Admitted. + +(*Why axiom*) Lemma left_empty : (forall (z:zone), (zunion z zempty) = z). +Admitted. + +(*Why axiom*) Lemma right_empty : (forall (z:zone), (zunion zempty z) = z). +Admitted. + +(*Why axiom*) Lemma union_same : (forall (z:zone), (zunion z z) = z). +Admitted. + +(*Why axiom*) Lemma union_sym : + (forall (z:zone), (forall (z':zone), (zunion z z') = (zunion z' z))). +Admitted. + +(*Why axiom*) Lemma union_assoc : + (forall (z:zone), + (forall (r:zone), + (forall (s:zone), (zunion (zunion z r) s) = (zunion z (zunion r s))))). +Admitted. + +(*Why axiom*) Lemma inc_range_range : + (forall (b:Z), + (forall (d:Z), + (forall (sz:Z), + (forall (b':Z), + (forall (d':Z), + (forall (sz':Z), + ((included (zrange b d sz) (zrange b' d' sz')) <-> + (d <= (d + sz) -> b = b' /\ d' <= d /\ (d + sz) <= (d' + sz'))))))))). +Admitted. + +(*Why axiom*) Lemma inc_empty : (forall (z:zone), (included zempty z)). +Admitted. + +(*Why axiom*) Lemma inc_same : (forall (z:zone), (included z z)). +Admitted. + +(*Why axiom*) Lemma inc_range_empty : + (forall (b:Z), + (forall (d:Z), + (forall (sz:Z), ((included (zrange b d sz) zempty) <-> b > (b + sz))))). +Admitted. + +(*Why axiom*) Lemma inc_union_right : + (forall (z:zone), + (forall (r:zone), + (forall (s:zone), + ((included z r) \/ (included z s) -> (included z (zunion r s)))))). +Admitted. + +(*Why axiom*) Lemma inc_union_left : + (forall (s:zone), + (forall (z:zone), + (forall (z':zone), + ((included s z) -> ((included z' z) -> (included (zunion s z') z)))))). +Admitted. + +(*Why logic*) Definition access_range : (array data) -> zone -> data. +Admitted. + +(*Why logic*) Definition update_range : + (array data) -> zone -> data -> (array data). +Admitted. + +(*Why axiom*) Lemma access_update_range_same : + (forall (m:(array data)), + (forall (z:zone), + (forall (d:data), + ((is_block z) -> (access_range (update_range m z d) z) = d)))). +Admitted. + +(*Why axiom*) Lemma access_update_range_sep : + (forall (m:(array data)), + (forall (v:data), + (forall (z:zone), + (forall (z':zone), + ((is_block z) -> + ((is_block z') -> + ((separated z z') -> + (access_range (update_range m z v) z') = (access_range m z')))))))). +Admitted. + +(*Why axiom*) Lemma access_range_update_addr_sep : + (forall (m:(array data)), + (forall (v:data), + (forall (z:zone), + (forall (p:Z), + ((is_block z) -> + ((separated z (zrange_of_addr p)) -> + (access_range (update m p v) z) = (access_range m z))))))). +Admitted. + +(*Why axiom*) Lemma access_update_range_addr_sep : + (forall (m:(array data)), + (forall (v:data), + (forall (z:zone), + (forall (p:Z), + ((is_block z) -> + ((separated z (zrange_of_addr p)) -> + (access (update_range m z v) p) = (access m p))))))). +Admitted. + +(*Why axiom*) Lemma access_update_sep : + (forall (m:(array data)), + (forall (v:data), + (forall (p:Z), + (forall (q:Z), + ((separated (zrange_of_addr p) (zrange_of_addr q)) -> + (access (update m p v) q) = (access m q)))))). +Admitted. + +(*Why logic*) Definition update_havoc : + (array data) -> zone -> data -> (array data). +Admitted. + +(*Why axiom*) Lemma load_havoc : + (forall (m:(array data)), + (forall (v:data), + (forall (z:zone), + (forall (p:Z), + ((separated z (zrange_of_addr p)) -> + (access (update_havoc m z v) p) = (access m p)))))). +Admitted. + +(*Why axiom*) Lemma load_is_havoc : + (forall (alloc:(array Z)), + (forall (mem:(array data)), + (forall (mem':(array data)), + (forall (p:Z), + (forall (z:zone), + ((included (zrange_of_addr p) z) -> + ((is_havoc alloc mem z mem') -> (access mem' p) = (access mem p)))))))). +Admitted. + +(*Why logic*) Definition is_assignable : (array Z) -> zone -> zone -> Prop. +Admitted. + +(*Why axiom*) Lemma is_assignable_range_free : + (forall (alloc:(array Z)), + (forall (p:Z), + (forall (z:zone), + ((access alloc (base p)) = 0 -> + (is_assignable alloc (zrange_of_addr p) z))))). +Admitted. + +(*Why axiom*) Lemma is_assignable_included : + (forall (alloc:(array Z)), + (forall (z:zone), + (forall (z':zone), ((included z z') -> (is_assignable alloc z z'))))). +Admitted. + +(*Why axiom*) Lemma same_havoc : + (forall (alloc:(array Z)), + (forall (mem:(array data)), (forall (z:zone), (is_havoc alloc mem z mem)))). +Admitted. + +(*Why axiom*) Lemma havoc_sym : + (forall (alloc:(array Z)), + (forall (m1:(array data)), + (forall (m2:(array data)), + (forall (z:zone), ((is_havoc alloc m2 z m1) -> (is_havoc alloc m1 z m2)))))). +Admitted. + +(*Why axiom*) Lemma store_havoc : + (forall (alloc:(array Z)), + (forall (mem:(array data)), + (forall (mem':(array data)), + (forall (p:Z), + (forall (v:data), + (forall (z:zone), + ((is_assignable alloc (zrange_of_addr p) z) -> + ((is_havoc alloc mem z mem') -> + (is_havoc alloc mem z (update mem' p v)))))))))). +Admitted. + +(*Why axiom*) Lemma store_havoc_havoc : + (forall (alloc:(array Z)), + (forall (mem:(array data)), + (forall (mem':(array data)), + (forall (v:data), + (forall (z':zone), + (forall (z:zone), + ((is_assignable alloc z' z) -> + ((is_havoc alloc mem z mem') -> + (is_havoc alloc mem z (update_havoc mem' z' v)))))))))). +Admitted. + +(*Why axiom*) Lemma store_range_havoc : + (forall (alloc:(array Z)), + (forall (mem:(array data)), + (forall (mem':(array data)), + (forall (v:data), + (forall (z':zone), + (forall (z:zone), + ((is_block z') -> + ((is_assignable alloc z' z) -> + ((is_havoc alloc mem z mem') -> + (is_havoc alloc mem z (update_range mem' z' v))))))))))). +Admitted. + +(*Why axiom*) Lemma addr_base : + (forall (b:Z), (forall (d:Z), (base (addr b d)) = b)). +Admitted. + +(*Why axiom*) Lemma addr_offset : + (forall (b:Z), (forall (d:Z), (offset (addr b d)) = d)). +Admitted. + +(*Why axiom*) Lemma base_sep : + (forall (b:Z), + (forall (b':Z), + (forall (d:Z), (forall (d':Z), (b <> b' -> (addr b d) <> (addr b' d')))))). +Admitted. + +(*Why axiom*) Lemma addr_inj1 : + (forall (b:Z), + (forall (b':Z), (forall (d:Z), (b = b' <-> (addr b d) = (addr b' d))))). +Admitted. + +(*Why axiom*) Lemma addr_inj2 : + (forall (b:Z), + (forall (d:Z), (forall (d':Z), (d = d' <-> (addr b d) = (addr b d'))))). +Admitted. + +(*Why axiom*) Lemma addr_lt_eq : (forall (a:Z), ~(addr_lt a a)). +Admitted. + +(*Why axiom*) Lemma addr_le_eq : (forall (a:Z), (addr_le a a)). +Admitted. + +(*Why axiom*) Lemma minus_pos_lt : + (forall (a:Z), + (forall (b:Z), + ((base a) = (base b) -> (((offset b) - (offset a)) > 0 -> (addr_lt a b))))). +Admitted. + +(*Why axiom*) Lemma minus_pos_le : + (forall (a:Z), + (forall (b:Z), + ((base a) = (base b) -> (((offset b) - (offset a)) >= 0 -> (addr_le a b))))). +Admitted. + +(*Why axiom*) Lemma addr_lt_le : + (forall (a:Z), (forall (b:Z), ((addr_lt a b) -> (addr_le a b)))). +Admitted. + +(*Why axiom*) Lemma havoc_union_update_left : + (forall (alloc:(array Z)), + (forall (m:(array data)), + (forall (m':(array data)), + (forall (p:Z), + (forall (v:data), + (forall (asgns:zone), + ((is_havoc alloc m (zunion (zrange_of_addr p) asgns) m') -> + (is_havoc alloc m (zunion (zrange_of_addr p) asgns) (update m' p v))))))))). +Admitted. + +(*Why axiom*) Lemma havoc_union_update_right : + (forall (alloc:(array Z)), + (forall (m:(array data)), + (forall (m':(array data)), + (forall (p:Z), + (forall (v:data), + (forall (z:zone), + (forall (asgns:zone), + ((included (zrange_of_addr p) asgns) -> + ((is_havoc alloc m (zunion z asgns) m') -> + (is_havoc alloc m (zunion z asgns) (update m' p v))))))))))). +Admitted. + +(*Why axiom*) Lemma havoc_union_update_range_left : + (forall (alloc:(array Z)), + (forall (m:(array data)), + (forall (m':(array data)), + (forall (v:data), + (forall (p:Z), + (forall (asgns:zone), + ((is_havoc alloc m (zunion (zrange_of_addr p) asgns) m') -> + (is_havoc + alloc m (zunion (zrange_of_addr p) asgns) (update_range + m' (zrange_of_addr p) v))))))))). +Admitted. + +(*Why axiom*) Lemma havoc_union_update_range_right : + (forall (alloc:(array Z)), + (forall (m:(array data)), + (forall (m':(array data)), + (forall (v:data), + (forall (p:Z), + (forall (z:zone), + (forall (asgns:zone), + ((included (zrange_of_addr p) asgns) -> + ((is_havoc alloc m (zunion z asgns) m') -> + (is_havoc + alloc m (zunion z asgns) (update_range m' (zrange_of_addr p) v))))))))))). +Admitted. + +(*Why axiom*) Lemma inc_union_union : + (forall (z0:zone), + (forall (z1:zone), + (forall (z2:zone), + (forall (z3:zone), + ((included z0 z2) -> + ((included z1 z3) -> (included (zunion z0 z1) (zunion z2 z3)))))))). +Admitted. + +(*Why axiom*) Lemma inc_sub_zone : + (forall (z:zone), + (forall (z':zone), + (included (zunion (zunion z z') (zunion z' z)) (zunion z' z)))). +Admitted. + +(*Why axiom*) Lemma inc_permut_union : + (forall (z:zone), + (forall (z':zone), + (forall (r:zone), + (included (zunion (zunion z z') r) (zunion (zunion z r) z'))))). +Admitted. + +(*Why axiom*) Lemma inc_permut2 : + (forall (z:zone), + (forall (s:zone), + (forall (r:zone), + (included + (zunion (zunion (zunion (zunion z s) r) r) s) (zunion (zunion z r) s))))). +Admitted. + +(*Why axiom*) Lemma union_assoc2 : + (forall (z:zone), + (forall (z':zone), (zunion z (zunion z z')) = (zunion z z'))). +Admitted. + +(*Why axiom*) Lemma addr_shift_0 : (forall (p:Z), (addr_shift p 0) = p). +Admitted. + +(*Why axiom*) Lemma addr_shift_shift : + (forall (p:Z), + (forall (d:Z), + (forall (d':Z), (addr_shift (addr_shift p d) d') = + (addr_shift p (d + d'))))). +Admitted. + +(*Why axiom*) Lemma valid_elt : + (forall (ta:(array Z)), + (forall (p:Z), + (forall (i:Z), + (forall (n:Z), + (n > 0 -> + ((valid ta p n) -> + (0 <= i -> ((i + 1) <= n -> (valid ta (addr_shift p i) 1))))))))). +Admitted. + +(*Why axiom*) Lemma separated_on_addr_sym : + (forall (p:Z), + (forall (q:Z), + (forall (n:Z), + (forall (m:Z), + ((separated_on_addr p q n m) -> (separated_on_addr q p m n)))))). +Admitted. + +(*Why axiom*) Lemma separated_on_addr_inc : + (forall (b:Z), + (forall (d:Z), + (forall (d':Z), + (forall (sz:Z), + (forall (sz':Z), + (forall (b1:Z), + (forall (d1:Z), + (forall (sz1:Z), + ((separated_on_addr (addr b1 d1) (addr b d) sz1 sz) -> + (d <= d' -> + ((d' + sz') <= (d + sz) -> + (separated_on_addr (addr b1 d1) (addr b d') sz1 sz')))))))))))). +Admitted. + +(*Why axiom*) Lemma separated_inc : + (forall (b:Z), + (forall (d:Z), + (forall (d':Z), + (forall (sz:Z), + (forall (sz':Z), + (forall (b1:Z), + (forall (d1:Z), + (forall (sz1:Z), + ((separated (zrange b1 d1 sz1) (zrange b d sz)) -> + (d <= d' -> + ((d' + sz') <= (d + sz) -> + (separated (zrange b1 d1 sz1) (zrange b d' sz'))))))))))))). +Admitted. + +(*Why axiom*) Lemma separated_one_elt : + (forall (n:Z), + (forall (m:Z), + (forall (b:Z), + (forall (d:Z), + (forall (sz:Z), + (forall (b':Z), + (forall (d':Z), + (forall (sz':Z), + (0 < n -> + (0 < m -> + ((separated (zrange b d (sz * n)) (zrange b' d' (sz' * m))) -> + (forall (i:Z), + (forall (j:Z), + (0 <= i -> + (0 <= j -> + ((d + i + sz) <= (d + sz * n) -> + ((d' + j + sz') <= (d' + sz' * m) -> + (separated (zrange b (d + i) sz) (zrange b' (d' + j) sz'))))))))))))))))))). +Admitted. + +(*Why axiom*) Lemma store_pointer : + (forall (x:Z), + (forall (ofs:Z), + (forall (y:Z), + (forall (ofs':Z), (separated_on_addr (addr x ofs) (addr y ofs') 1 1) \/ + (addr x ofs) = (addr y ofs'))))). +Admitted. + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/store_model.why frama-c-20111001+nitrogen+dfsg/src/wp/share/store_model.why --- frama-c-20110201+carbon+dfsg/src/wp/share/store_model.why 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/store_model.why 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,912 @@ +(* --- Headers for WHY --- *) + +include "bool.why" +include "integer.why" +include "real.why" +include "arrays.why" +include "divisions.why" +(* -------------------------------------------------------------------------- *) +(* --- ACSL Definitions --- *) +(* -------------------------------------------------------------------------- *) + +logic dummy : int -> prop +logic assigns : int -> prop + + +(* -------------------------------------------------------------------------- *) +(* --- Divisions enhanced specification --- *) +(* -------------------------------------------------------------------------- *) + +axiom positive_computer_div_div: + forall x,y:int. + x >0 -> y >0 -> computer_div(x,y) = math_div(x,y) + + +(**************************************************************************) +(*** Specification of Set as First Class Value ***) +(**************************************************************************) +(* From Figure 2.6 in ACSL:ANSI/ISO C Specification Language *) + +type 'a set + +logic empty : 'a set +logic singleton : 'a -> 'a set +logic range : int,int -> int set +logic union : 'a set , 'a set -> 'a set +logic inter : 'a set , 'a set -> 'a set +logic plus_int : int set, int set -> int set +logic subset : 'a set,'a set -> prop +logic range_inf: int -> int set +logic range_sup:int->int set +logic integers_set : int set +logic equiv : 'a set ,'a set -> prop +logic member : 'a,'a set -> prop + +axiom singleton_def : + forall x:'a. member (x, singleton(x)) + +axiom singleton_eq: + forall x,y:'a. member(x,singleton(y)) <-> x=y + +axiom union_member : + forall x:'a. forall s1,s2:'a set [member(x, union(s1,s2))]. + member(x, union(s1,s2)) <-> member(x,s1) or member(x,s2) + +axiom union_of_empty : + forall x:'a set [union(x,empty)]. union(x,empty) = x + +axiom inter_of_empty : + forall x:'a set [inter(x,empty)]. inter(x,empty) = empty + +axiom union_comm : + forall x,y:'a set. union(x,y) = union(y,x) + +axiom inter_comm : + forall x,y:'a set. inter(x,y) = inter(y,x) + +axiom inter_member : + forall x:'a. forall s1,s2:'a set [member(x,inter(s1,s2))]. + member(x,inter(s1,s2)) <-> member(x,s1) and member(x,s2) + +axiom plus_int_member_1: + forall sa,sb:int set. + forall a,b:int [member((a+b), plus_int(sa,sb))]. + member(a,sa) -> member(b,sb) -> + member((a+b), plus_int(sa,sb)) + +axiom plus_int_member_2: + forall sa,sb:int set. + forall c:int. + member(c,plus_int(sa,sb)) -> + exists a:int. exists b:int. + member(a,sa) and member(b,sb) and c=a+b + +axiom subset_empty : + forall sa:'a set. subset(empty,sa) + +axiom subset_sym: + forall sa:'a set. subset(sa,sa) + +axiom subset_trans : + forall sa,sb,sc: 'a set. + subset(sa,sb) -> + subset(sb,sc) -> + subset(sa,sc) + +axiom subset_def: + forall sa,sb:'a set [subset(sa,sb)]. + (forall a:'a. member(a,sa) -> member(a,sb)) <-> subset(sa,sb) + + +axiom range_def: + forall i,j,k:int. i <= k<= j <-> member (k,range(i,j)) + +axiom range_def1: + forall i,j,k:int. i <= k<= j -> member (k,range(i,j)) + +axiom range_def2: + forall i,j,k:int.member (k,range(i,j)) -> i <= k<= j + +axiom range_inf_def: (* range_inf(i) is [ i .. ] *) + forall i,k: int. i <= k <-> member (k,range_inf(i)) + +axiom range_sup_def: (* range_sup(j) is [ .. j ] *) + forall j,k: int. k <= j <-> member (k,range_sup(j)) + +axiom integers_set_def: + forall k:int. k >= 0 <-> member(k,integers_set) + +axiom equiv_def: + forall s1,s2:'a set [equiv(s1,s2)]. ( + (forall a:'a. member(a,s1) -> member(a,s2)) and + (forall b:'a. member(b,s2) -> member(b,s1))) <-> + equiv(s1,s2) + +axiom equiv_refl: + forall s:'a set. equiv(s,s) + +axiom equiv_sym: + forall s1,s2:'a set. equiv(s1,s2) -> equiv(s2,s1) + +axiom equiv_trans: + forall s1,s2,s3:'a set. + equiv(s1,s2) -> equiv(s2,s3) -> equiv(s1,s3) + + + +(**************************************************************************) +(*** Integers and Reals ***) +(**************************************************************************) + + +logic as_uint8 :int -> int +predicate is_uint8(x:int) = 0 <= x < 256 +axiom as_uint8_def : forall x:int. is_uint8(as_uint8(x)) +axiom as_uint8_involve : + forall x:int [as_uint8(as_uint8(x))]. as_uint8(as_uint8(x)) = as_uint8(x) +axiom is_as_uint8: forall x:int [as_uint8(x)]. is_uint8(x) -> as_uint8(x) = x + +logic as_sint8 :int -> int +predicate is_sint8(x:int) = -128 <= x < 128 +axiom as_sint8_def : forall x:int. is_sint8(as_sint8(x)) +axiom as_sint8_involve : + forall x:int [as_sint8(as_sint8(x))]. as_sint8(as_sint8(x)) = as_sint8(x) +axiom is_as_sint8: forall x:int[as_sint8(x)]. is_sint8(x) -> as_sint8(x) = x + + +logic as_uint16 :int -> int +predicate is_uint16(x:int) = 0 <= x < 65536 +axiom as_uint16_def : forall x:int. is_uint16(as_uint16(x)) +axiom as_uint16_involve : + forall x:int [as_uint16(as_uint16(x))]. + as_uint16(as_uint16(x)) = as_uint16(x) +axiom is_as_uint16: forall x:int [as_uint16(x)]. is_uint16(x) -> as_uint16(x) = x + +logic as_sint16 :int -> int +predicate is_sint16(x:int) = -32768 <= x < 32768 +axiom as_sint16_def : forall x:int. is_sint16(as_sint16(x)) +axiom as_sint16_involve : + forall x:int [as_sint16(as_sint16(x))]. + as_sint16(as_sint16(x)) = as_sint16(x) +axiom is_as_sint16: forall x:int [as_sint16(x)]. is_sint16(x) -> as_sint16(x) = x + + +logic as_uint32 :int -> int +predicate is_uint32(x:int) = 0 <= x < 4294967296 +axiom as_uint32_def : forall x:int. is_uint32(as_uint32(x)) +axiom as_uint32_involve : + forall x:int [as_uint32(as_uint32(x))]. + as_uint32(as_uint32(x)) = as_uint32(x) +axiom is_as_uint32: forall x:int [as_uint32(x)]. is_uint32(x) -> as_uint32(x) = x + +logic as_sint32 :int -> int +predicate is_sint32(x:int) = -2147483648 <= x < 2147483648 +axiom as_sint32_def : forall x:int. is_sint32(as_sint32(x)) +axiom as_sint32_involve : + forall x:int [as_sint32(as_sint32(x))]. + as_sint32(as_sint32(x)) = as_sint32(x) +axiom is_as_sint32: forall x:int [as_sint32(x)]. is_sint32(x) -> as_sint32(x) = x + + +logic as_uint64 :int -> int +predicate is_uint64(x:int) = 0 <= x < 18446744073709551616 +axiom as_uint64_def : forall x:int. is_uint64(as_uint64(x)) +axiom as_uint64_involve : + forall x:int [as_uint64(as_uint64(x))]. + as_uint64(as_uint64(x)) = as_uint64(x) +axiom is_as_uint64: forall x:int [as_uint64(x)]. is_uint64(x) -> as_uint64(x) = x + +logic as_sint64 :int -> int +predicate is_sint64(x:int) = -9223372036854775808 <= x < 9223372036854775808 +axiom as_sint64_def : forall x:int. is_sint64(as_sint64(x)) +axiom as_sint64_involve : + forall x:int [as_sint64(as_sint64(x))]. + as_sint64(as_sint64(x)) = as_sint64(x) +axiom is_as_sint64: forall x:int [as_sint64(x)]. is_sint64(x) -> as_sint64(x) = x + + +logic as_float16 :real -> real +logic is_float16 :real -> prop +axiom as_float16_def : forall x:real. is_float16(as_float16(x)) +axiom as_float16_involve : + forall x:real [as_float16(as_float16(x))]. + as_float16(as_float16(x)) = as_float16(x) +axiom is_as_float16: forall x:real [as_float16(x)]. is_float16(x) -> as_float16(x) = x + + +logic as_float32 :real -> real +logic is_float32 :real -> prop +axiom as_float32_def : forall x:real. is_float32(as_float32(x)) +axiom as_float32_involve : + forall x:real [as_float32(as_float32(x))]. + as_float32(as_float32(x)) = as_float32(x) +axiom is_as_float32: + forall x:real [as_float32(x)]. is_float32(x) -> as_float32(x) = x + + +logic as_float64 :real -> real +logic is_float64 :real -> prop +axiom as_float64_def : + forall x:real. is_float64(as_float64(x)) +axiom as_float64_involve : + forall x:real [as_float64(as_float64(x))]. + as_float64(as_float64(x)) = as_float64(x) +axiom is_as_float64: + forall x:real [as_float64(x)]. is_float64(x) -> as_float64(x) = x + + +logic as_float128 :real -> real +logic is_float128 :real -> prop +axiom as_float128_def : + forall x:real. is_float128(as_float128(x)) +axiom as_float128_involve : + forall x:real [as_float128(as_float128(x))]. + as_float128(as_float128(x)) = as_float128(x) +axiom is_as_float128: + forall x:real [as_float128(x)]. is_float128(x) -> as_float128(x) = x + +(**************************************************************************) +(*** Memory Data Type ***) +(**************************************************************************) + +type data + +logic data_of_uint8: int -> data +logic uint8_of_data: data -> int + +axiom is_uint8_of_data: + forall d:data [is_uint8(uint8_of_data(d))].is_uint8(uint8_of_data(d)) + +axiom uint8ofdata_dataofuint8: + forall x:int [data_of_uint8(x)]. + is_uint8(x) -> uint8_of_data(data_of_uint8(x)) = x + +logic data_of_sint8: int -> data +logic sint8_of_data: data -> int + +axiom is_sint8_of_data: + forall d:data [is_sint8(sint8_of_data(d))]. is_sint8(sint8_of_data(d)) + +axiom sint8ofdata_dataofsint8: + forall x:int [data_of_sint8(x)]. + is_sint8(x) -> sint8_of_data(data_of_sint8(x)) = x + +logic data_of_uint16: int -> data +logic uint16_of_data: data -> int + +axiom is_uint16_of_data: + forall d:data [is_uint16(uint16_of_data(d))]. is_uint16(uint16_of_data(d)) + +axiom uint16ofdata_dataofuint16: + forall x:int [uint16_of_data(data_of_uint16(x))]. + is_uint16(x) -> uint16_of_data(data_of_uint16(x)) = x + +logic data_of_sint16: int -> data +logic sint16_of_data: data -> int + +axiom is_sint16_of_data: + forall d:data [is_sint16(sint16_of_data(d))]. is_sint16(sint16_of_data(d)) + +axiom sint16ofdata_dataofsint16: + forall x:int [data_of_sint16(x)]. + is_sint16(x) -> sint16_of_data(data_of_sint16(x)) = x + +logic data_of_uint32: int -> data +logic uint32_of_data: data -> int + +axiom is_uint32_of_data: + forall d:data [is_uint32(uint32_of_data(d))]. is_uint32(uint32_of_data(d)) + +axiom uint32ofdata_dataofuint32: + forall x:int [data_of_uint32(x)]. + is_uint32(x) -> uint32_of_data(data_of_uint32(x)) = x + +logic data_of_sint32: int -> data +logic sint32_of_data: data -> int + +axiom is_sint32_of_data: + forall d:data [is_sint32(sint32_of_data(d))]. is_sint32(sint32_of_data(d)) + +axiom sint32ofdata_dataofsint32: + forall x:int [data_of_sint32(x)]. + is_sint32(x) -> sint32_of_data(data_of_sint32(x)) = x + +logic data_of_uint64: int -> data +logic uint64_of_data: data -> int + +axiom is_uint64_of_data: + forall d:data [is_uint64(uint64_of_data(d))]. is_uint64(uint64_of_data(d)) + +axiom uint64ofdata_dataofuint64: + forall x:int [data_of_uint64(x)]. + is_uint64(x) -> uint64_of_data(data_of_uint64(x)) = x + +logic data_of_sint64: int -> data +logic sint64_of_data: data -> int + +axiom is_sint64_of_data: + forall d:data [is_sint64(sint64_of_data(d))]. is_sint64(sint64_of_data(d)) + +axiom sint64ofdata_dataofsint64: + forall x:int [data_of_sint64(x)]. + is_sint64(x) -> sint64_of_data(data_of_sint64(x)) = x + +logic data_of_float16: real -> data +logic float16_of_data: data -> real + +axiom is_float16_of_data: + forall d:data [is_float16(float16_of_data(d))]. is_float16(float16_of_data(d)) +axiom float16ofdata_dataoffloat16: + forall x:real [data_of_float16(x)]. + is_float16(x) -> float16_of_data(data_of_float16(x)) = x + +logic data_of_float32: real -> data +logic float32_of_data: data -> real + +axiom is_float32_of_data: + forall d:data [is_float32(float32_of_data(d))]. is_float32(float32_of_data(d)) +axiom float32ofdata_dataoffloat32: + forall x:real [data_of_float32(x)]. + is_float32(x) -> float32_of_data(data_of_float32(x)) = x + +logic data_of_float64: real -> data +logic float64_of_data: data -> real + +axiom is_float64_of_data: + forall d:data [is_float64(float64_of_data(d))]. is_float64(float64_of_data(d)) +axiom float64ofdata_dataoffloat64: + forall x:real [data_of_float64(x)]. + is_float64(x) -> float64_of_data(data_of_float64(x)) = x + +logic data_of_float128: real -> data +logic float128_of_data: data -> real + +axiom is_float128_of_data: + forall d:data [is_float128(float128_of_data(d))]. is_float128(float128_of_data(d)) +axiom float128ofdata_dataoffloat128: + forall x:real [data_of_float128(x)]. + is_float128(x) -> float128_of_data(data_of_float128(x)) = x + + +(**************************************************************************) +(*** Update of Arrays over a set of Index ***) +(**************************************************************************) + + +logic set_range_index: + 'a farray (* array*), int set (* set of index*), int (*uniq key*) -> 'a farray + +axiom set_range_def : + forall t: 'a farray. + forall rg: int set. + forall k:int. + forall i:int [access(set_range_index(t,rg,k),i)]. + not (member(i,rg)) -> + access(set_range_index(t,rg,k),i) = access(t,i) + +(**************************************************************************) +(*** Bitwise Operations ***) +(**************************************************************************) + +logic bnot: int -> int +logic band: int,int -> int +logic bor: int,int -> int +logic bxor: int,int -> int +logic lshift: int,int -> int +logic rshift: int,int -> int + +logic int_not: int -> int +logic int_and: int,int -> int +logic int_or: int,int -> int +logic int_xor: int,int -> int +logic int_lsh: int,int -> int +logic int_rshs: int,int -> int +logic int_rshu: int,int -> int +(* ------------------------------------------------------------------------ *) +(* --- Store is a basic Load/Store Memory Model --- *) +(* ------------------------------------------------------------------------ *) + +(* Array theory version's of store memory model (store.why) *) + +logic addr : + int(* base address*), int(* offset*) -> int(*addr *) + +logic offset : int(*addr*) -> int(*offset*) +logic base : int(*addr*) -> int(*base address*) + +axiom addr_def: + forall a, b, d: int. + addr(b,d) = a ->(base (a) = b and offset (a) = d ) + +axiom addr_id: + forall p: int [addr(base(p),offset(p))]. + addr(base(p),offset(p)) = p + +logic minus_addr : int (*address*), int (*address*) -> int (*integer*) + +axiom minus_addr_def: + forall a,b:int. + base (a) = base(b) -> minus_addr(a,b) = offset(a) - offset(b) + +predicate addr_lt (a:int,b:int) = + base(a) = base(b) and offset(a) < offset(b) + +function addr_lt_bool (a:int,b:int) : bool = + bool_and ( eq_int_bool(base(a),base(b)) , lt_int_bool( offset(a) , offset(b) ) ) + +predicate addr_le (a:int,b:int) = + base(a) = base(b) and offset(a) <= offset(b) + +function addr_le_bool (a:int,b:int) : bool = + bool_and ( eq_int_bool(base(a),base(b)) , le_int_bool( offset(a) , offset(b) ) ) + +predicate addr_eq (a:int,b:int) = + base(a) = base(b) and offset(a) = offset(b) + +function addr_eq_bool (a:int,b:int) : bool = + bool_and ( eq_int_bool(base(a),base(b)) , eq_int_bool( offset(a) , offset(b) ) ) + + +axiom cmp_null: + forall p:int [addr_eq(p,0)]. p = 0 <-> addr_eq(p,0) + +axiom cmp_null_bool: + forall p:int [addr_eq_bool(p,0)]. p = 0 <-> addr_eq_bool(p,0) = true + +axiom cmp_null_not: + forall p:int. p <> 0 <-> not addr_eq(p,0) + +axiom cmp_null_bool_not: + forall p:int [addr_eq_bool(p,0)]. p <> 0 <-> addr_eq_bool(p,0) = false + + +(* ------------------------------------------------------------------------ *) +(* --- Decoding Values --- *) +(* ------------------------------------------------------------------------ *) + +logic addr_of_data: data -> int +logic data_of_addr: int -> data + +axiom addrofdata_dataofaddr: + forall p:int [data_of_addr(p)]. addr_of_data(data_of_addr(p)) = p + + +(* ------------------------------------------------------------------------ *) +(* --- Pointer Validity --- *) +(* ------------------------------------------------------------------------ *) + +predicate valid (ta: int farray, p:int, n : int ) = + n > 0 -> ( 0 <= offset(p) and offset(p) + n <= access(ta,base(p)) ) + +logic global : int farray -> prop + +(*is_fresh is the only relation between a memory state and an allocation + table since we can't specify an unsucced load *) +logic is_fresh : data farray,int farray,int -> prop + + +(** a fresh base is different of all valid bases **) +axiom fresh : + forall mem: data farray. (* memory store *) + forall ta,ta': int farray. + forall x,p,n:int [valid(ta',p,n),is_fresh(mem,ta,x)]. + is_fresh(mem,ta,x) -> + ta[x] = 0 -> (* ZD: keep this hypothesis*) + access(ta,base(p)) = access(ta',base(p)) -> (*help alt-ergo trigger *) + valid(ta',p,n) -> + forall d,sz:int. addr(x,d)<>p + +(** a fresh base can't been read in memory **) +axiom fresh_access : + forall mem,mem': data farray. (* memory store *) + forall ta,ta': int farray. + forall b,p,n:int + [is_fresh(mem,ta,b), + valid(ta',p,n), + addr_of_data(access(mem',p))]. + is_fresh(mem,ta,b) -> + ta[b] = 0 -> (* ZD: keep this hypothesis*) + valid(ta',p,n) -> + access(ta,base(p)) = access(ta',base(p)) -> (*help alt-ergo trigger *) + access(mem,p)=access(mem',p) -> (**) + forall d:int. addr(b,d)<>addr_of_data(access(mem',p)) + + + +function addr_shift (p:int,dofs:int) : int = + addr( base(p),offset(p)+dofs ) + + +(* ------------------------------------------------------------------------ *) +(* --- Separated --- *) +(* ------------------------------------------------------------------------ *) + + + +predicate separated_on_addr (p:int,p':int, n1: int , n2 : int ) = + base(p) = base(p') -> + offset(p)+n1 <= offset(p') or offset(p) >= offset(p') + n2 +(* ------------------------------------------------------------------------ *) +(* --- Zone --- *) +(* ------------------------------------------------------------------------ *) + +type zone + +logic zrange : int,int,int -> zone +logic zempty : zone +logic zunion : zone,zone -> zone + +logic included : zone,zone -> prop + +logic is_havoc : int farray,data farray,zone,data farray -> prop + +logic is_block : zone -> prop + +axiom is_block_zrange : + forall x,ofs,len : int. + len > 0 -> is_block(zrange(x,ofs,len)) + +axiom is_not_block_zempty : not (is_block(zempty)) + + + + +(*ZD: only for pointer on atomic type. *) +function zrange_of_addr (p:int): zone = + zrange( base(p),offset(p),1) + +function zrange_of_addr_range (p:int,dofs:int,n:int) : zone = + zrange( base(p),offset(p)+dofs,n) + +logic separated : zone , zone -> prop + +axiom sep_zrange : + forall b,b',d,d',sz,sz':int[separated(zrange(b,d,sz),zrange(b',d',sz'))]. + separated(zrange(b,d,sz),zrange(b',d',sz')) + <->separated_on_addr(addr(b,d),addr(b',d'),sz,sz') + +axiom separated_sym: + forall z,z': zone. separated(z,z') -> separated(z',z) + +axiom sep_empty : + forall z:zone. separated(zempty,z) + +axiom sep_union: + forall z,z',r: zone [separated(z,zunion(z',r))]. + separated(z,zunion(z',r)) <-> + (separated(z,z') and separated(z,r)) + +(* extension of included with empty and union *) + +axiom left_empty : forall z:zone. zunion(z,zempty) = z +axiom right_empty : forall z:zone. zunion(zempty,z) = z +axiom union_same : forall z:zone. zunion(z,z)=z +axiom union_sym : forall z,z':zone. zunion(z,z') = zunion(z',z) +axiom union_assoc : forall z,r,s : zone. + zunion(zunion(z,r),s) = zunion(z,zunion(r,s)) + +axiom inc_range_range : + forall b,d,sz,b',d',sz' : int + [included(zrange(b,d,sz),zrange(b',d',sz'))]. + included(zrange(b,d,sz),zrange(b',d',sz')) <-> + (d<=d+sz -> ( b=b' and d'<= d and d+sz <= d'+sz' )) + +axiom inc_empty : + forall z:zone. included(zempty,z) + +axiom inc_same : + forall z:zone. included(z,z) + +axiom inc_range_empty : + forall b,d,sz:int [ included(zrange(b,d,sz),zempty) ]. + included(zrange(b,d,sz),zempty) <-> b>b+sz + +axiom inc_union_right : + forall z,r,s:zone [included(z,zunion(r,s))]. + (included(z,r) or included(z,s)) -> included(z,zunion(r,s)) + +axiom inc_union_left : + forall s,z,z':zone [included(zunion(s,z'),z)]. + included(s,z) -> included(z',z) -> included(zunion(s,z'),z) + +(* ------------------------------------------------------------------------ *) +(* --- Access and Update with Ranges --- *) +(* ------------------------------------------------------------------------ *) + +logic access_range : data farray,zone -> data +logic update_range : data farray,zone,data -> data farray + +axiom access_update_range_same : + forall m : data farray. + forall z : zone. + forall d : data. + is_block (z) -> + access_range(update_range(m,z,d),z)=d + +axiom access_update_range_sep : + forall m : data farray. + forall v : data. + forall z,z' :zone [access_range(update_range(m,z,v),z')]. + is_block(z) -> is_block(z') -> + separated(z,z') -> + access_range(update_range(m,z,v),z') = access_range(m,z') + +axiom access_range_update_addr_sep: + forall m : data farray. + forall v : data. + forall z:zone. + forall p: int [access_range(update(m,p,v),z)]. + is_block(z) -> + separated(z,zrange_of_addr(p)) -> + access_range(update(m,p,v),z)= access_range(m,z) + +axiom access_update_range_addr_sep : + forall m : data farray. + forall v : data. + forall z: zone. + forall p : int [access(update_range(m,z,v),p)]. + is_block(z) -> + separated(z,zrange_of_addr(p)) -> + access(update_range(m,z,v),p)=access(m,p) + +axiom access_update_sep : + forall m : data farray. + forall v : data. + forall p,q : int [access(update(m,p,v),q)]. + separated(zrange_of_addr(p),zrange_of_addr(q)) -> + access(update(m,p,v),q) = access(m,q) + +(* ------------------------------------------------------------------------ *) +(* --- Havoc --- *) +(* ------------------------------------------------------------------------ *) + +logic update_havoc : data farray,zone,data -> data farray + +(* access and is_havoc *) + +axiom load_havoc : + forall m:data farray. + forall v:data. + forall z:zone. + forall p:int [access(update_havoc(m,z,v),p)]. + separated(z,zrange_of_addr(p)) -> + access(update_havoc(m,z,v),p) = access(m,p) + +axiom load_is_havoc : + forall alloc:int farray. + forall mem,mem':data farray. + forall p:int. + forall z:zone [access(mem,p),is_havoc(alloc,mem,z,mem')]. + included(zrange_of_addr(p),z) -> + is_havoc(alloc,mem,z,mem') -> + access(mem',p) = access(mem,p) + +(* not assigned is free or in region *) + +logic is_assignable : int farray,zone,zone -> prop + +axiom is_assignable_range_free : + forall alloc:int farray. + forall p:int. + forall z:zone [is_assignable(alloc,zrange_of_addr(p),z)]. + access(alloc,base(p))=0 -> + is_assignable(alloc,zrange_of_addr(p),z) + +axiom is_assignable_included : + forall alloc:int farray. + forall z,z':zone [is_assignable(alloc,z,z')]. + included(z,z') -> is_assignable(alloc,z,z') + +(* updates and is_havoc *) + +axiom same_havoc : + forall alloc:int farray. + forall mem:data farray. + forall z:zone. + is_havoc(alloc,mem,z,mem) + +axiom havoc_sym : + forall alloc:int farray. + forall m1, m2:data farray. + forall z:zone. + is_havoc(alloc,m2,z,m1) -> + is_havoc(alloc,m1,z,m2) + +axiom store_havoc : + forall alloc:int farray. + forall mem,mem':data farray. + forall p:int. + forall v:data. + forall z:zone [is_havoc(alloc,mem,z,update(mem',p,v))]. + is_assignable(alloc,zrange_of_addr(p),z) -> + is_havoc(alloc,mem,z,mem') -> + is_havoc(alloc,mem,z,update(mem',p,v)) + +axiom store_havoc_havoc : + forall alloc:int farray. + forall mem,mem':data farray. + forall v:data. + forall z',z:zone [is_havoc(alloc,mem,z,update_havoc(mem',z',v))]. + is_assignable(alloc,z',z) -> + is_havoc(alloc,mem,z,mem') -> + is_havoc(alloc,mem,z,update_havoc(mem',z',v)) + + +axiom store_range_havoc : + forall alloc:int farray. + forall mem,mem':data farray. + forall v:data. + forall z',z:zone [is_havoc(alloc,mem,z,update_range(mem',z',v))]. + is_block(z') -> + is_assignable(alloc,z',z) -> + is_havoc(alloc,mem,z,mem') -> + is_havoc(alloc,mem,z,update_range(mem',z',v)) +(*========================================================================*) +(* Helper Lemmas for Store Model *) +(*------------------------------------------------------------------------*) + +axiom addr_base: + forall b,d:int. + base(addr(b,d)) = b + +axiom addr_offset: + forall b,d:int. + offset(addr(b,d)) = d + + +axiom base_sep: + forall b,b',d,d':int. + b<>b' -> addr(b,d) <> addr(b',d') + +axiom addr_inj1: + forall b,b',d:int. + b=b' <-> addr(b,d)=addr(b',d) + +axiom addr_inj2: + forall b,d,d':int. + d=d' <-> addr(b,d)=addr(b,d') + + +axiom addr_lt_eq: + forall a:int [addr_lt(a,a)]. not (addr_lt(a,a)) + +axiom addr_le_eq: + forall a:int [addr_le(a,a)]. addr_le(a,a) + +axiom minus_pos_lt : + forall a,b:int [addr_lt(a,b)]. + base(a) = base(b) -> + offset(b) - offset (a) > 0 -> + addr_lt(a,b) + +axiom minus_pos_le : + forall a,b:int [addr_le(a,b)]. + base(a) = base(b) -> + offset(b) - offset (a) >= 0 -> + addr_le(a,b) + +axiom addr_lt_le: + forall a,b:int [addr_le(a,b)]. + addr_lt(a,b) -> addr_le(a,b) + +axiom havoc_union_update_left : + forall alloc:int farray. + forall m,m':data farray. + forall p:int. forall v:data. + forall asgns:zone. + is_havoc (alloc, m, zunion (zrange_of_addr(p) , asgns), m') -> + is_havoc (alloc, m, zunion (zrange_of_addr(p) , asgns), update(m',p, v)) + +axiom havoc_union_update_right : + forall alloc:int farray. + forall m,m':data farray. + forall p:int. forall v:data. + forall z, asgns:zone. + included (zrange_of_addr(p), asgns) -> + is_havoc (alloc, m, zunion (z , asgns), m') -> + is_havoc (alloc, m, zunion (z , asgns), update(m',p, v)) + +axiom havoc_union_update_range_left : + forall alloc:int farray. + forall m,m':data farray. + forall v:data. forall p:int. + forall asgns:zone. + is_havoc (alloc, m, zunion (zrange_of_addr(p) , asgns), m') -> + is_havoc (alloc, m, zunion (zrange_of_addr(p) , asgns), + update_range (m',zrange_of_addr(p), v)) + +axiom havoc_union_update_range_right : + forall alloc:int farray. + forall m,m':data farray. + forall v:data. forall p:int. + forall z, asgns:zone. + included (zrange_of_addr(p), asgns) -> + is_havoc (alloc, m, zunion (z , asgns), m') -> + is_havoc (alloc, m, zunion (z , asgns), + update_range (m',zrange_of_addr(p), v)) + + +axiom inc_union_union : + forall z0,z1,z2,z3: zone. + included(z0,z2) -> included(z1,z3) -> + included(zunion(z0,z1),zunion(z2,z3)) + + +axiom inc_sub_zone: + forall z,z':zone. + included(zunion(zunion(z,z'),zunion(z',z)),zunion(z',z)) + +axiom inc_permut_union: + forall z,z',r: zone. + included (zunion(zunion(z,z'),r),zunion(zunion(z,r),z')) + + +axiom inc_permut2: + forall z,s,r : zone. + included (zunion(zunion(zunion(zunion(z,s),r),r),s) + ,zunion(zunion(z,r),s)) + +axiom union_assoc2: + forall z,z':zone. zunion(z,zunion(z,z'))= zunion(z,z') + + +axiom addr_shift_0: + forall p: int [addr_shift(p,0)]. + addr_shift(p,0) = p + + +axiom addr_shift_shift : + forall p,d,d': int + [addr_shift(addr_shift(p,d),d')]. + addr_shift(addr_shift(p,d),d') = addr_shift(p,d+d') + + +axiom valid_elt : + forall ta:int farray. + forall p,i,n:int. + n > 0 -> + valid(ta,p,n) -> + 0 <= i -> + i +1 <= n -> + valid(ta,addr_shift(p,i),1) + + +axiom separated_on_addr_sym: + forall p,q,n,m:int. + separated_on_addr(p,q,n,m) -> separated_on_addr(q,p,m,n) + +axiom separated_on_addr_inc: + forall b,d,d',sz,sz', b1,d1,sz1 : int. + separated_on_addr(addr(b1,d1),addr(b,d),sz1,sz) -> + d <= d' -> + d'+sz' <= d+sz -> + separated_on_addr(addr(b1,d1),addr(b,d'),sz1,sz') + + +axiom separated_inc : + forall b,d,d',sz,sz', b1,d1,sz1 : int. + separated(zrange(b1,d1,sz1),zrange(b,d,sz)) -> + d <= d' -> + d'+sz' <= d+sz -> + separated(zrange(b1,d1,sz1),zrange(b,d',sz')) + +axiom separated_one_elt: + forall n,m,b,d,sz,b',d',sz' : int. + 0 <n -> 0 < m -> + separated(zrange(b,d,sz*n),zrange(b',d',sz'*m)) -> + forall i,j : int. + 0 <=i -> 0<=j -> + d+i+sz <= d+sz*n -> + d'+j+sz'<= d'+sz'*m -> + separated (zrange(b,d+i,sz),zrange(b',d'+j,sz')) + +axiom store_pointer : + forall x,ofs,y,ofs':int. + separated_on_addr(addr(x,ofs),addr(y,ofs'),1,1) or + addr(x,ofs) = addr(y,ofs') + + + + + +(*--------------End of Store Lemmas ---------------------------------*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/share/wp.v frama-c-20111001+nitrogen+dfsg/src/wp/share/wp.v --- frama-c-20110201+carbon+dfsg/src/wp/share/wp.v 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/share/wp.v 2011-10-10 08:38:11.000000000 +0000 @@ -0,0 +1,104 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* + * The Why certification tool + * Copyright (C) 2002 Jean-Christophe FILLIATRE + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation. + * + * This software 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 version 2 for more details + * (enclosed in the file GPL). + *) + +Require Export Bool_nat. +Require Export Zwf. +Require Export ZArith. +Require Export ZArith_dec. +Require Export Zdiv. +Require Import Sumbool. +Require Import Omega. +Require Import ZArithRing. + + +(** From WhyCompat ***) + +Require Import LegacyRing. +Tactic Notation "ring" constr(t) := legacy ring. +Open Scope Z_scope. + + + +(*Why logic*) Definition lt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition le_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition gt_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition ge_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition eq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why logic*) Definition neq_int_bool : Z -> Z -> bool. +Admitted. + +(*Why axiom*) Lemma lt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((lt_int_bool x y) = true <-> x < y))). +Admitted. + +(*Why axiom*) Lemma le_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((le_int_bool x y) = true <-> x <= y))). +Admitted. + +(*Why axiom*) Lemma gt_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((gt_int_bool x y) = true <-> x > y))). +Admitted. + +(*Why axiom*) Lemma ge_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((ge_int_bool x y) = true <-> x >= y))). +Admitted. + +(*Why axiom*) Lemma eq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((eq_int_bool x y) = true <-> x = y))). +Admitted. + +(*Why axiom*) Lemma neq_int_bool_axiom : + (forall (x:Z), (forall (y:Z), ((neq_int_bool x y) = true <-> x <> y))). +Admitted. + +Definition if_then_else (A:Set) (a:bool) (b c:A) := if a then b else c. +Implicit Arguments if_then_else. + +Definition array: Set ->Set. +Admitted. + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/store_mem.ml frama-c-20111001+nitrogen+dfsg/src/wp/store_mem.ml --- frama-c-20110201+carbon+dfsg/src/wp/store_mem.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/store_mem.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,859 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Memory Model with separation *) +(* -------------------------------------------------------------------------- *) + +module WpLog = Wp_parameters +open Cil_types +open Formula +open Ctypes +open Clabels + +module Create + (F:Formula.S) + (A:Mint.S with module F = F) + (R:Mfloat.S with module F = F) + = + +struct + + let unsupported = Wp_error.unsupported + + (* ------------------------------------------------------------------------ *) + (* --- Term Types --- *) + (* ------------------------------------------------------------------------ *) + + type decl = F.decl + + + let t_data: tau = Formula.ADT("data",[]) + + type m_memory = m_array + let t_memory : tau = Formula.ADT("farray",[t_data]) + type store = m_memory F.term + + type m_alloc = m_array + let t_alloc : tau = Formula.ADT("farray",[Formula.Integer]) + type alloc = m_alloc F.term + + type m_dzone + type dzone = m_dzone F.term + + + (* ----------------------------------------------------------------------- *) + (* --- Extracted specification from store.why --- *) + (* ----------------------------------------------------------------------- *) + + (* Data and basic typed Data conversions *) + let data_of_int (i: Ctypes.c_int) = + F.e_app1 ((Pretty_utils.sfprintf "data_of_%a") Ctypes.pp_int i) + let int_of_data (i:Ctypes.c_int) = + F.e_app1 ((Pretty_utils.sfprintf "%a_of_data") Ctypes.pp_int i) + let data_of_float (f: Ctypes.c_float) = + F.e_app1 ((Pretty_utils.sfprintf "data_of_%a") Ctypes.pp_float f) + let float_of_data (f:Ctypes.c_float) = + F.e_app1 ((Pretty_utils.sfprintf "%a_of_data") Ctypes.pp_float f) + let addr_of_data = F.e_app1 "addr_of_data" + let data_of_addr = F.e_app1 "data_of_addr" + + + + + + (* Address *) + + let model_addr : F.integer -> F.integer -> F.integer = F.e_app2 "addr" + let model_base : F.integer -> F.integer = F.e_app1 "base" + let model_offset : F.integer -> F.integer = F.e_app1 "offset" + + let model_addr_shift : F.integer -> F.integer -> F.integer = + F.e_app2 "addr_shift" + + + (* Allocation *) + + let model_valid : alloc -> F.integer -> F.integer -> F.pred = + F.p_app3 "valid" + + let model_isfresh : store -> alloc -> F.integer -> F.pred = + F.p_app3 "is_fresh" + + let model_alloc (talloc:alloc) (p:F.integer) (sz:F.integer) : alloc = + F.e_update talloc p (F.wrap sz) + + let model_free (talloc : alloc) (p: F.integer) : alloc = + F.e_update talloc p (F.wrap F.i_zero) + + let model_block (talloc : alloc) (p: F.integer) : F.integer = + F.unwrap (F.e_access talloc p) + + (* Zone *) + + let model_zempty : dzone = F.e_app0 "zempty" + let model_zunion : dzone -> dzone -> dzone = F.e_app2 "zunion" + let model_included : dzone -> dzone -> F.pred = F.p_app2 "included" + + let model_zrange : F.integer -> F.integer -> F.integer -> dzone = + F.e_app3 "zrange" + + let model_zrange_of_addr_range : + F.integer -> F.integer -> F.integer -> dzone = + F.e_app3 "zrange_of_addr_range" + + let model_separated : dzone -> dzone -> F.pred = F.p_app2 "separated" + + (* Record, Array acces, update *) + + let model_update_range: store -> dzone -> F.abstract -> store = + F.e_app3 "update_range" + let model_access_range: store -> dzone -> F.abstract = + F.e_app2 "access_range" + + + let model_update_havoc: store -> dzone -> F.abstract -> store = + F.e_app3 "update_havoc" + let model_ishavoc : alloc -> store -> dzone -> store -> F.pred = + F.p_app4 "is_havoc" + + type mem = { + x_store : F.var ; + x_alloc : F.var ; + store : store ; + alloc : alloc ; + } + + let encode fmt v = F.e_app2 "encode" fmt v + let decode fmt x = F.e_app2 "decode" fmt x + + (* ----------------------------------------------------------------------- *) + (* --- Instanciation of MVALUE and MLOGIC : Store implemantation --- *) + (* ----------------------------------------------------------------------- *) + + let rec sizeof = function + | C_comp cinfo -> + List.fold_left + (fun sz f -> F.i_add sz + (sizeof (object_of f.ftype))) F.i_zero cinfo.cfields + | C_array ainfo -> + begin + match ainfo.arr_flat with + | Some a -> F.i_mult + (sizeof (object_of a.arr_cell)) + (F.e_int64 a.arr_cell_nbr) + | None -> WpLog.not_yet_implemented "[Store] Sizeof unknown-size array" + end + | _ -> F.i_one + + let n_size n te = F.i_mult (sizeof te) n + let add_offset d te k = F.i_add d (n_size k te) + let cardinal a b = F.i_add F.i_one (F.i_sub b a) + + let offset_of_field f = + let rec acc sz l f = + match l with + | [] -> Wp_parameters.fatal "[offset_of_field] not found %s" f.fname + | fi::m -> + if Cil_datatype.Fieldinfo.equal f fi + then sz + else acc (F.i_add sz (sizeof (object_of fi.ftype))) m f + in + acc F.i_zero f.fcomp.cfields f + + + module Model = + struct + + module A=A + module R=R + module F=F + + type st_loc = + { base :F.integer ; + off:F.integer ; + obj : Ctypes.c_object} + + let upd_base l b = {base = b; off=l.off; obj = l.obj} + let upd_off l d = {base = l.base ; off = d ; obj = l.obj} + let upd_obj l cv = {base = l.base ; off = l.off ; obj = cv} + + type loc = + | Loc of st_loc + | Addr of F.integer * Ctypes.c_object (*address,type*) + + let addr = function + | Loc l -> model_addr l.base l.off + | Addr (p,_) -> p + + let base = function + | Loc l -> l.base + | Addr (p,_) -> model_base p + + let offset = function + | Loc l -> l.off + | Addr (p,_) -> model_offset p + + let object_of_loc = function + | Loc l -> l.obj + | Addr (_,cv) -> cv + + let sizeof_loc l = + let size = Ctypes.sizeof_object (object_of_loc l) in + F.e_int64 size + + + let loc_of_term ty p = Addr (F.unwrap p,ty) + let term_of_loc loc = F.wrap (addr loc) + + + + let null = + let null_obj = Ctypes.C_pointer Cil.charType in + Addr (F.i_zero,null_obj) + + let is_null l = F.e_app2 "addr_eq" (addr l) (F.i_zero) + let lt_loc l1 l2 = F.p_app2 "addr_lt" (addr l1) (addr l2) + let le_loc l1 l2 = F.p_app2 "addr_le" (addr l1) (addr l2) + let equal_loc l1 l2 = F.p_app2 "addr_eq" (addr l1) (addr l2) + let lt_loc_bool l1 l2 = F.e_app2 "addr_lt_bool" (addr l1) (addr l2) + let le_loc_bool l1 l2 = F.e_app2 "addr_le_bool" (addr l1) (addr l2) + let equal_loc_bool l1 l2 = F.e_app2 "addr_eq_bool" (addr l1) (addr l2) + + let minus_loc l1 l2 = + F.e_app2 "minus_addr" (addr l1) (addr l2) + + + let cast_loc_to_int _tp loc _ti = addr loc + + let cast_int_to_loc _ti i tp = Addr (i, Ctypes.object_of tp) + + let pp_loc fmt = function + | Loc l -> + Format.fprintf fmt "addr(%a,%a)" + F.pp_term l.base F.pp_term l.off + | Addr(p,_t) -> F.pp_term fmt p + + let tau_of_loc = Formula.Integer + end + + module Globals = F.DRegister + (struct + include F.Varinfo + + let declare x _ = + let pool = F.pool () in + let xa = F.p_fresh pool "ta" (Model t_alloc) in + let sx = sizeof (Ctypes.object_of x.vtype) in + let xk = F.Xindex.get_ind x in + let sa = F.e_access (F.var xa) xk in + let gta = F.p_app1 "global" (F.var xa) in + Axiom (F.p_forall [xa] + (F.p_implies gta (F.p_eq (F.unwrap sa) sx))) + + let section = S_Model_Prop + let prefix = "Alloc" + let basename x = x.vname + let clear () = () + let pp_descr fmt _x = + Format.fprintf fmt "Global allocation table" + end) + + + + + + module Data = + struct + + module V = Datalib.Cvalues(Model) + module L = Datalib.Create(V) + include V + open Model + + type m_of_mem = m_memory + let tau_of_mem = t_memory + + (* ZD : Be carreful, here [dummy_obj] must be useless. *) + let forall_loc pool = + let b = F.p_fresh pool "b" (Model Integer) in + let d = F.p_fresh pool "d" (Model Integer) in + let dummy_obj = Ctypes.C_int (Ctypes.c_char()) in + let l = {base = F.var b ; off = F.var d ; obj = dummy_obj} in + [b;d] , Loc l + + let load_rec = ref (fun _ _ _ -> assert false) + let store_rec = ref (fun _ _ _ _ -> assert false) + + + + let define_vinfo x = + if x.vglob && (Ctypes.no_infinite_array (Ctypes.object_of x.vtype)) + then Globals.define x + + let global = define_vinfo + + let cvar_of_var vinfo = + define_vinfo vinfo ; + Loc + {base = F.Xindex.get_ind vinfo; + off = F.i_zero; + obj = (Ctypes.object_of (vinfo.vtype))} + + let cvar _mem vinfo = cvar_of_var vinfo + + let inner_loc _ = Wp_parameters.fatal "[inner_loc] reserved to funvar" + + let lvar _m lv x = + let ty = + match lv.lv_type with + | Ctype ty -> ty + | ty -> Wp_parameters.fatal + "[lvar] c type of a pure logic type %a" + !Ast_printer.d_logic_type ty + in + loc_of_term (Ctypes.object_of ty)(F.var x) + + let offset loc te n = + if F.equal_terms n F.i_zero then loc else + match loc with + | Loc l -> + Loc (upd_obj (upd_off l (add_offset l.off te n)) te) + | Addr (p,_) -> + Addr(model_addr_shift p (n_size n te),te) + + let shift = offset + let index = offset + + let field loc f = + if f.fcomp.cstruct then + let pos = offset_of_field f in + let cv = Ctypes.object_of f.ftype in + match loc with + | Loc l -> + Loc (upd_obj (upd_off l (F.i_add l.off pos)) cv) + | Addr (p,_) -> Addr (model_addr_shift p pos,cv) + else + unsupported "union field" + + let load_mem m t l = !load_rec m t l + let store_mem m t l v = !store_rec m t l v + + let mem () = + let x_m = L.fresh "m" (Formula.Model t_memory) in + let x_t = L.fresh "ta" (Formula.Model t_alloc) in + { + x_store = x_m ; + x_alloc = x_t ; + store = F.var x_m ; + alloc = F.var x_t ; + } + + end + + module DF = Data_mem.Create(Data) + + include Data + open Model + let startof l _cv = l + + + let base_address _mem = function + | Loc l -> Loc (upd_off l F.i_zero) + | Addr (p,cv) -> Addr(model_addr (model_base p) F.i_zero,cv) + + let block_length _mem loc = sizeof_loc loc + + let cast_loc_to_loc ty1 ty2 l = + let o1 = object_of ty1 in + let o2 = object_of ty2 in + if Ctypes.equal o1 o2 then l else + match o1,o2 with + | C_array ar, C_pointer ty2 -> + if Ctypes.equal (Ctypes.object_of ar.arr_element) (Ctypes.object_of ty2) then + l + else + (match ar.arr_flat with + | Some {Ctypes.arr_cell = ty1} -> + if Ctypes.equal (Ctypes.object_of ty1) (Ctypes.object_of ty2) + then l + else (unsupported "pointer cast from %a to %a " + !Ast_printer.d_type ty1 + !Ast_printer.d_type ty2) + | None -> (unsupported "pointer cast from %a to %a " + !Ast_printer.d_type ty1 + !Ast_printer.d_type ty2) + ) + | _,_ -> (unsupported "pointer cast from %a to %a " + !Ast_printer.d_type ty1 + !Ast_printer.d_type ty2) + + let zrange loc n = + match loc with + | Loc l -> model_zrange l.base l.off n + | Addr (p,_) -> model_zrange_of_addr_range p F.i_zero n + + + + (* ------------------------------------------------------------------------ *) + (* --- Type Coersion Data/Records --- *) + (* ------------------------------------------------------------------------ *) + + (* record of data *) + module SofData = F.DRegister + (struct + include F.Compinfo + let prefix = "SofData" + let section = S_Model_Def + let clear () = () + let pp_title fmt c = + Format.fprintf fmt "SofData for %s '%s'" + (if c.cstruct then "struct" else "union") c.cname + let declare comp _ = + Function ([t_data],Record comp) + end) + + + (* data of record *) + module DataofS = F.DRegister + (struct + include F.Compinfo + let prefix = "DataofS" + let section = S_Model_Def + let clear () = () + let pp_title fmt c = + Format.fprintf fmt "DataofS for %s '%s'" + (if c.cstruct then "struct" else "union") c.cname + let declare comp _ = + Function ([Record comp],t_data) + end) + + let s_of_data comp = F.e_app1 (SofData.get_definition comp).d_name + let data_of_s comp = F.e_app1 (DataofS.get_definition comp).d_name + + (* if is record [comp] s -> record of data (data of record s) = s*) + module Ax2SofData = F.DRegister + (struct + include F.Compinfo + let prefix = "SofDataofS" + let section = S_Model_Prop + let clear () = () + let pp_title fmt c = + Format.fprintf fmt "DataofS for %s '%s'" + (if c.cstruct then "struct" else "union") c.cname + let declare comp _ = + let xs = F.p_fresh (F.pool()) "s" (Model (Record comp)) in + let s = F.var xs in + Axiom (F.p_forall [xs] + (F.p_implies (L.is_comp comp s) + (F.p_eq ((s_of_data comp (data_of_s comp s))) s))) + end) + + (* is record [comp] (record [comp] of data d) *) + module Ax3IsSofData = F.DRegister + (struct + include F.Compinfo + let prefix = "ISSofData" + let section = S_Model_Prop + let clear () = () + let pp_title fmt c = + Format.fprintf fmt "IsSofData for %s '%s'" + (if c.cstruct then "struct" else "union") c.cname + let declare comp _ = + let xd = F.p_fresh (F.pool()) "d" (Model t_data) in + let d = F.var xd in + Axiom (F.p_forall [xd] (L.is_comp comp (s_of_data comp d))) + end) + + let coerce_comp comp = + SofData.define comp; DataofS.define comp; + Ax2SofData.define comp; Ax3IsSofData.define comp + + let s_of_data comp = coerce_comp comp ; s_of_data comp + let data_of_s comp = coerce_comp comp ; data_of_s comp + + + (* ------------------------------------------------------------------------ *) + (* --- Type Coersion Data/Arrays --- *) + (* ------------------------------------------------------------------------ *) + + (* arrayof data *) + module AofData = F.DRegister + (struct + include F.Arrayinfo + let prefix = "AofData" + let section = S_Model_Def + let clear () = () + let pp_title fmt arr = + Format.fprintf fmt "AofData for %a " + Ctypes.pretty (C_array arr) + let declare arr _ = + Function ([t_data],Array arr) + end) + + + (* data of array*) + module DataofA = F.DRegister + (struct + include F.Arrayinfo + let prefix = "DataofA" + let section = S_Model_Def + let clear () = () + let pp_title fmt arr = + Format.fprintf fmt "DataofA for %a" + Ctypes.pretty (C_array arr) + let declare arr _ = + Function ([Array arr],t_data) + end) + + let a_of_data arr = F.e_app1 (AofData.get_definition arr).d_name + let data_of_a arr = F.e_app1 (DataofA.get_definition arr).d_name + + (* if is array[arr] s -> arrayof data (data of arrays) = s*) + module Ax2AofData = F.DRegister + (struct + include F.Arrayinfo + let prefix = "AofDataofA" + let section = S_Model_Prop + let clear () = () + let pp_title fmt arr = + Format.fprintf fmt "DataofA for %a" + Ctypes.pretty (C_array arr) + let declare arr _ = + let xt = F.p_fresh (F.pool()) "t" (Model (Array arr)) in + let t = F.var xt in + Axiom (F.p_forall [xt] + (F.p_implies (L.is_array arr t) + (F.p_eq ((a_of_data arr (data_of_a arr t))) t))) + end) + + (* is array[arr] (array[arr] of data d) *) + module Ax3IsAofData = F.DRegister + (struct + include F.Arrayinfo + let prefix = "IAAofData" + let section = S_Model_Prop + let clear () = () + let pp_title fmt arr = + Format.fprintf fmt "IsAofData for %a" + Ctypes.pretty (C_array arr) + let declare arr _ = + let xd = F.p_fresh (F.pool()) "d" (Model t_data) in + let d = F.var xd in + Axiom (F.p_forall [xd] (L.is_array arr (a_of_data arr d))) + end) + + + let coerce_arr arr = + AofData.define arr; DataofA.define arr; + Ax2AofData.define arr; Ax3IsAofData.define arr + + let a_of_data arr = coerce_arr arr ; a_of_data arr + let data_of_a arr = coerce_arr arr ; data_of_a arr + + + + + (* ------------------------------------------------------------------------ *) + (* --- Lod --- *) + (* ------------------------------------------------------------------------ *) + + + let load_with fmt mem loc = + decode fmt (F.e_access mem (addr loc)) + + let load_mem mem te loc = + match te with + | C_pointer ty -> + let cv = Ctypes.object_of ty in + V_pointer(cv, Addr(addr_of_data (F.e_access mem (addr loc)),cv)) + | C_int i -> + V_int(i,int_of_data i (F.e_access mem (addr loc))) + | C_float f -> + V_float(f, float_of_data f (F.e_access mem (addr loc)) ) + | C_comp comp -> + if comp.cstruct then + let z = zrange loc (sizeof te) in + let d = model_access_range mem z in + V_record(comp,s_of_data comp d) + else Wp_parameters.not_yet_implemented "load of union" + | C_array arr -> + let z = zrange loc (sizeof te) in + let d = model_access_range mem z in + V_array(arr,a_of_data arr d) + + let store_with mem loc fmt v = + F.e_update mem (addr loc) (encode fmt v) + + let store_mem mem te loc v = + match v with + | V_int(i,t) -> F.e_update mem (addr loc) (data_of_int i t) + | V_float(f,t) -> F.e_update mem (addr loc) (data_of_float f t) + | V_pointer(_,lv) -> F.e_update mem (addr loc) (data_of_addr (addr lv)) + | V_record (comp,r) -> + let dr = data_of_s comp r in + let zp = zrange loc (sizeof te) in + model_update_range mem zp dr + | V_union _ -> unsupported "union" + | V_array (arr,r) -> + let dr = data_of_a arr r in + let zp = zrange loc (sizeof te) in + model_update_range mem zp dr + + let () = + begin + Data.load_rec := load_mem ; + Data.store_rec := store_mem ; + end + + let load m te loc = + DF.loaded te ; load_mem m.store te loc + + (* ------------------------------------------------------------------------ *) + (* --- Zone --- *) + (* ------------------------------------------------------------------------ *) + + (* --- Effect Assigns Method --- *) + + let tau_of_dzone = Formula.ADT("zone",[]) + + (* Elementary Zones *) + type assignable = + | Xrange of F.integer * F.integer * F.integer (* BASE,OFS,LEN *) + | Arange of F.integer * F.integer * F.integer (* ADDR,OFS,LEN *) + | Ablock of F.integer (* ADDR,0,1 *) + + let addr_of_assignable = function + | Xrange(x,ofs,_) -> model_addr x ofs + | Ablock p -> p + | Arange(p,ofs,_sz) -> model_addr_shift p ofs + + let zone_of_assignable = function + | Xrange(x,ofs,sz) -> model_zrange x ofs sz + | Ablock p -> model_zrange_of_addr_range p F.i_zero F.i_one + | Arange(p,ofs,sz) -> model_zrange_of_addr_range p ofs sz + + let assignable_loc te loc = + match loc with + | Loc l -> Xrange(l.base,l.off,sizeof te) + | Addr (p,_) -> Ablock p + + let assignable_range mem te loc rg = + match loc with + | Loc lc -> + begin + match rg with + | {F.inf = Some l ; F.sup = Some h} -> + Xrange(lc.base,add_offset lc.off te l,n_size (cardinal l h) te) + | {F.inf = None ; F.sup = Some h} -> + Xrange(lc.base,lc.off,n_size (F.i_add h F.i_one) te) + | {F.inf = Some l;F.sup = None} -> + let h = + F.i_sub (F.unwrap (F.e_access mem.alloc lc.base)) F.i_one + in + Xrange(lc.base,add_offset lc.off te l,n_size (cardinal l h) te) + | {F.inf = None ; F.sup = None} -> + let h = F.unwrap (F.e_access mem.alloc lc.base) in + Xrange(lc.base,lc.off,n_size h te) + end + | Addr (p,_) -> + begin + match rg with + | {F.inf = Some l;F.sup = Some h} -> + Arange(p,n_size l te,n_size (cardinal l h) te) + | {F.inf = None;F.sup = Some h} -> + Arange(p,F.i_zero,n_size (F.i_add h F.i_one) te) + | {F.inf = Some l ; F.sup = None} -> + let h = + F.i_sub (F.unwrap (F.e_access mem.alloc (model_base p))) + F.i_one + in + Arange(p,n_size l te,n_size (cardinal l h) te) + |{F.inf = None ; F.sup = None} -> + let b = model_base p in + let h = F.unwrap (F.e_access mem.alloc b) in + Xrange(b,F.i_zero,n_size h te) + end + + let assignable m = function + | F.Aloc( te , loc ) -> assignable_loc te loc + | F.Arange( te , loc , rg ) -> assignable_range m te loc rg + + let dzone_assigned m a = zone_of_assignable (assignable m a) + let dzone_subset = model_included + let dzone_union = model_zunion + let dzone_empty () = model_zempty + + let effect_supported = true + + let assignable_sizeof = function + | F.Aloc( te , _ ) -> sizeof te + | F.Arange( te , _ , {F.inf=Some l;F.sup=Some h} ) -> + n_size (cardinal l h) te + | F.Arange _ -> unsupported "infinite range for array" + + let valid mem a = + model_valid mem.alloc + (addr_of_assignable (assignable mem a)) + (assignable_sizeof a) + + let get_zrange_opt = function + | F.Aloc( te , loc ) -> + Some( loc , sizeof te ) + | F.Arange( te , loc , {F.inf=Some a;F.sup=Some b} ) -> + Some( shift loc te a , n_size (cardinal a b) te ) + | F.Arange( te , loc , {F.inf=None;F.sup=Some b} ) -> + Some( loc , n_size (cardinal F.i_zero b) te ) + | _ -> None + + let separated mem a1 a2 = + match get_zrange_opt a1 , get_zrange_opt a2 with + | Some(p,n) , Some(q,m) -> F.p_app4 "separated_on_addr" (addr p) (addr q) n m + | _ -> + model_separated (dzone_assigned mem a1) (dzone_assigned mem a2) + + (* ----------------------------------------------------------------------- *) + (* --- Instanciation of MWP : WP Calculus --- *) + (* ----------------------------------------------------------------------- *) + + let update ~(at:mem) ~(here:mem) p = + L.subst at.x_store here.store + (L.subst at.x_alloc here.alloc p) + + let quantify m p = + L.forall [m.x_store;m.x_alloc] p + + let subst_lval m te loc v p = + DF.stored te ; + L.subst m.x_store (store_mem m.store te loc v) p + + let alloc_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + let sz_x = sizeof (object_of x.vtype) in + L.subst m.x_alloc (model_alloc m.alloc v_x sz_x) p + ) p xs + + let free_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + L.subst m.x_alloc (model_free m.alloc v_x) p + ) p xs + + let fresh_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + let q = model_isfresh m.store m.alloc v_x in + F.p_implies q p + ) p xs + + let notexists_vars m xs p = + List.fold_left + (fun p x -> + let v_x = F.Xindex.get_ind x in + let q = F.p_eq (F.unwrap(F.e_access m.alloc v_x)) F.i_zero in + F.p_implies q p + ) p xs + + let global_scope m p = + if L.has_context_vars [m.x_alloc] p + then F.p_implies (F.p_app1 "global" m.alloc) p + else p + + let filter_scope p vars = + List.filter (fun x -> F.Xindex.has_ind x p) vars + + let local_scope m vars scope p = + match scope with + | Mcfg.SC_Function_frame -> (* nothing to do *) p + | Mcfg.SC_Block_in | Mcfg.SC_Function_in -> + let vars = filter_scope p vars in + notexists_vars m vars + (fresh_vars m vars + (alloc_vars m vars p)) + | Mcfg.SC_Block_out | Mcfg.SC_Function_out -> + let vars = filter_scope p vars in + free_vars m vars + (fresh_vars m vars p) + | Mcfg.SC_Global -> + if L.has_context_vars [m.x_alloc] p + then F.p_implies (F.p_app1 "global" m.alloc) p + else p + + let subst_havoc m a = + let addr = zone_of_assignable (assignable m a) in + let v = L.fresh "v" (Formula.Model(ADT("data",[]))) in + let km sigma = + let m0 = L.apply sigma m.store in + F.wrap(model_update_havoc m0 addr (F.var v)) + in + [F.Fresh v;F.Update(m.x_store,km)] + + let rec region m = function + | [] -> model_zempty + | [a] -> dzone_assigned m a + | a :: others -> model_zunion (dzone_assigned m a) (region m others) + + let assigns_goal m1 assigned m2 = + model_ishavoc m1.alloc m1.store (region m1 assigned) m2.store + + let assigns_supported = true + + (* ----------------------------------------------------------------------- *) + (* --- User Predicate environment --- *) + (* ----------------------------------------------------------------------- *) + + type closure = Mem | Alloc + + let pp_closure fmt = function + | Mem -> Format.fprintf fmt "memory store" + | Alloc -> Format.fprintf fmt "allocation table" + + let userdef_mem_signature m = [ m.x_store,Mem ; m.x_alloc,Alloc ] + + let userdef_mem_apply mem = function + | Mem -> F.wrap mem.store + | Alloc -> F.wrap mem.alloc + + (* ------------------------------------------------------------------------ *) + (* --- Functional Closure --- *) + (* ------------------------------------------------------------------------ *) + + type formal = unit + let pp_formal (_:Format.formatter) _ = () + let userdef_is_ref_param (_:logic_var) : bool = false + let userdef_ref_signature (_:mem) :( F.var * logic_var * formal ) list = [] + let userdef_ref_apply (_:mem) (_:formal) (_:loc) : value = + Wp_parameters.fatal "[userdef_ref_apply] of model Store" + let userdef_ref_has_cvar (_ : logic_var) : bool = false + + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/store_mem.mli frama-c-20111001+nitrogen+dfsg/src/wp/store_mem.mli --- frama-c-20110201+carbon+dfsg/src/wp/store_mem.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/store_mem.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Create + (F:Formula.S) + (A:Mint.S with module F = F) + (R:Mfloat.S with module F = F) + : +sig + + include Mwp.S with module F = F + and module A = A + and module R = R + +end diff -Nru frama-c-20110201+carbon+dfsg/src/wp/translate_expr.ml frama-c-20111001+nitrogen+dfsg/src/wp/translate_expr.ml --- frama-c-20110201+carbon+dfsg/src/wp/translate_expr.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/translate_expr.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,787 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Translation of Expressions --- *) +(* -------------------------------------------------------------------------- *) + +open Ctypes +open Cil_types +open Cil_datatype +module WpLog = Wp_parameters + + +let dkey = "translate_exp" (* debugging key*) + +let debug = Wp_parameters.debug ~dkey + + +module Create (M:Mvalues.S) = +struct + + module F = M.F + module A = M.A + module R = M.R + + (*------------------------------------------------------------------------ *) + (*--- Utilities --- *) + (*------------------------------------------------------------------------ *) + + let c_int_of_typ t = + match object_of t with + | C_int i -> i + | _ -> WpLog.fatal "non-integer offset" + + + let int_of_value = function + | M.V_int(_,t) -> t + | v -> WpLog.fatal "[int_of_value] of non integer value %a" M.pp_value v + + let float_of_value = function + | M.V_float(_,t) -> t + | v -> WpLog.fatal "[float_of_value] of non float value %a" M.pp_value v + + let loc_of_value = function + | M.V_pointer(_,loc) -> loc + | M.V_array _ as v -> + debug "[loc_of_value] ARRAY %a" M.pp_value v ; + WpLog.fatal "[loc_of_value] ARRAY %a" M.pp_value v + | v -> debug "[loc_of_value] %a" M.pp_value v ; + WpLog.fatal "[loc_of_value] %a" M.pp_value v + + let value_of_integer i z = M.V_int(i,z) + let value_of_boolean b = value_of_integer (Ctypes.c_bool()) (F.e_bool b) + let boolean_of_loc p = F.e_not (M.is_null p) + let boolean_of_integer z = F.e_icmp Formula.Cneq z F.i_zero + let boolean_of_int v = boolean_of_integer v + let boolean_of_float v = F.e_rcmp Formula.Cneq v F.r_zero + + let boolean_of_value = function + | M.V_int(_,t) -> boolean_of_int t + | M.V_float(_,t) -> boolean_of_float t + | M.V_pointer(_,loc) -> boolean_of_loc loc + | v -> WpLog.fatal "[loc_of_value] %a"M.pp_value v + + let prop_of_loc p = F.p_not (F.p_bool (M.is_null p)) + let prop_of_integer z = F.p_icmp Formula.Cneq z F.i_zero + let prop_of_int z = prop_of_integer z + let prop_of_float r = F.p_rcmp Formula.Cneq r F.r_zero + + let prop_of_value = function + | M.V_int(_,t) -> prop_of_int t + | M.V_float(_,t) -> prop_of_float t + | M.V_pointer(_,loc) -> prop_of_loc loc + | v -> WpLog.fatal "[prop_of_value] %a" M.pp_value v + + let not_of_loc p = F.p_bool (M.is_null p) + let not_of_integer z = F.p_icmp Formula.Ceq z F.i_zero + let not_of_int z = not_of_integer z + let not_of_float r = F.p_rcmp Formula.Ceq r F.r_zero + + let not_of_value = function + | M.V_int(_,t) -> not_of_int t + | M.V_float(_,t) -> not_of_float t + | M.V_pointer(_,loc) -> not_of_loc loc + | v -> WpLog.fatal "[not_of_value] %a" M.pp_value v + + (* ----------------------------------------------------------------------- *) + (* --- Deep Recursion over Expressions, Conditions and binary operators -- *) + (* ----------------------------------------------------------------------- *) + + let expr_rec = ref (fun _ _ -> assert false) + let cond_rec = ref (fun _ _ -> assert false) + + let prop_rec = ref (fun _ _ -> assert false) + + (* [expr_int mem ie ir e] interprets an expression [e] in the memory + [mem] as an integer of size [ie] and converts this integer as an + integer of size [ir]. *) + let expr_int mem ie ir e = + F.i_convert ie ir (int_of_value (!expr_rec mem e)) + + (* [expr_float mem fe fr e] interprets an expression [e] in the + memory [mem] as a float of size [fe] and converts this float as a + float of size [fr]. *) + let expr_float mem _fe _fr e = + (float_of_value (!expr_rec mem e)) + + (* ----------------------------------------------------------------------- *) + (* --- Casts --- *) + (* ----------------------------------------------------------------------- *) + + (*[expr_cast tyv tyr v] converts a value [v] of type [tyv] to type + [tyr].*) + let expr_cast tyv tyr v = + if Typ.equal tyv tyr then v else + match object_of tyv, object_of tyr with + | C_int i1 , C_int i2 -> + M.V_int(i2,F.i_convert i1 i2 (int_of_value v)) + | C_float _f1 , C_float f2 -> + M.V_float(f2,float_of_value v) + | C_int _ , C_float f2 -> + let z = int_of_value v in + let r = F.real_of_integer z in + M.V_float(f2,r) + | C_float _ , C_int i2 -> + let r = float_of_value v in + let z = F.integer_of_real r in + M.V_int(i2,M.F.modulo i2 z) + (* TODO : specify non-modulo Cf. ISO-C 6.3.1.4 *) + | C_pointer t1 , C_pointer t2 -> + M.V_pointer + (Ctypes.object_of t2, + M.cast_loc_to_loc t1 t2 (loc_of_value v)) + | C_pointer t1 , C_int i2 -> + M.V_int (i2,M.cast_loc_to_int t1 (loc_of_value v)i2) + | C_int i1 , C_pointer t2 -> + M.V_pointer + (Ctypes.object_of t2, + M.cast_int_to_loc i1 (int_of_value v) t2) + | a,b -> + WpLog.not_yet_implemented "cast from %a to %a" + pp_object a pp_object b + + let prop_cast tyv tyr v = + match object_of tyv , object_of tyr with + | C_int i1 , C_int i2 -> + prop_of_int (F.i_convert i1 i2 (int_of_value v)) + | C_float _f1 , C_float _f2 -> + prop_of_float (float_of_value v) + | C_int _i1 , C_float _ -> + let z = int_of_value v in + let r = F.real_of_integer z in + prop_of_float r + | C_float _ , C_int i2 -> + let r = float_of_value v in + let z = F.integer_of_real r in + prop_of_int (F.modulo i2 z) + (* TODO : specify non-modulo Cf. ISO-C 6.3.1.4 *) + | C_pointer t1 , C_pointer t2 -> + prop_of_loc (M.cast_loc_to_loc t1 t2 (loc_of_value v)) + | C_pointer t1 , C_int i2 -> + prop_of_int (M.cast_loc_to_int t1 (loc_of_value v) i2) + | C_int i1 , C_pointer t2 -> + prop_of_loc (M.cast_int_to_loc i1 (int_of_value v) t2) + | a,b -> + WpLog.not_yet_implemented "cast from %a to %a" + pp_object a pp_object b + + + + (* ----------------------------------------------------------------------- *) + (* --- Constants --- *) + (* ----------------------------------------------------------------------- *) + + (* [expr_const m c] interprets a constant [c] in memory [m].*) + let expr_const mem = function + | CInt64(k,ik,_) -> + M.V_int(Ctypes.c_int ik,F.e_icst (My_bigint.to_string k)) + | CChr c -> + M.V_int(Ctypes.c_char (),F.e_icst (Int64.to_string (Ctypes.char c))) + | CReal(f,fk,_) -> + M.V_float(Ctypes.c_float fk, F.e_float f) + | CEnum e -> + !expr_rec mem e.eival + | CWStr _ -> + WpLog.not_yet_implemented "wide character string constant" + | CStr s -> + WpLog.not_yet_implemented "character string constant (%S)" s + + let prop_const mem = function + | CInt64(k,_,_) -> + if My_bigint.equal k My_bigint.zero then F.p_false else F.p_true + | CChr c -> + if c ='0' then F.p_false else F.p_true + | CReal(f,_,_) -> + if f = 0.0 then F.p_false else F.p_true + | CEnum e -> + !prop_rec mem e.eival + | CWStr _ -> F.p_false (* pointer to constant string is non-null *) + | CStr _ -> F.p_false (* pointer to constant string is non-null *) + + (* ----------------------------------------------------------------------- *) + (* --- Address --- *) + (* ----------------------------------------------------------------------- *) + + (* [shift_loc mem l typ_l path] interprets [path] in memory [mem] from + the location [l] of type [typ_l]. *) + let rec shift_loc (mem:M.mem) l typ_l = function + | NoOffset -> l + | Field(f,next) -> + shift_loc mem (M.field l f) f.ftype next + | Index(e,next) -> + let v = !expr_rec mem e in + let k = int_of_value v in + let typ_elt = Cil.typeOf_array_elem typ_l in + shift_loc mem (M.index l (Ctypes.object_of typ_elt) k) typ_elt next + + let typeOf_array_elem = function + | C_array arr -> object_of arr.arr_element + | t -> WpLog.fatal + "[typeOf_array_elem] of non array type %a" Ctypes.pp_object t + + (* [addr mem l] interprets the left-value [l] as memory path + (address) in the memory of [mem].*) + let addr mem l = + match l with + | (Var x,off) -> + let te = x.vtype in + shift_loc mem (M.cvar mem x) te off + | (Mem e,off) -> + let te = Cil.typeOf e in + let tl = Cil.typeOf_pointed te in + let loc = loc_of_value (!expr_rec mem e) in + shift_loc mem loc tl off + + (* [startof mem t_elt lv] compute the location of l-value [lv], casted + as pointer to an object of type [t] *) + let startof mem t_elt lv = + M.startof (addr mem lv) t_elt + + (* ---------------------------------------------------------------------- *) + (* --- Binary Expressions --- *) + (* ---------------------------------------------------------------------- *) + + let int_operator iota = function + | PlusA -> A.i_op iota Formula.Iadd + | MinusA -> A.i_op iota Formula.Isub + | Mult -> A.i_op iota Formula.Imul + | Div -> A.i_op iota Formula.Idiv + | Mod -> A.i_op iota Formula.Imod + | BAnd -> A.bits_and iota + | BXor -> A.bits_xor iota + | BOr -> A.bits_or iota + | Shiftlt -> A.bits_lshift iota + | Shiftrt -> A.bits_rshift iota + | _ -> WpLog.fatal "[int_operator] non integer operator" + + let float_operator phi = function + | PlusA -> R.f_op phi Formula.Radd + | MinusA -> R.f_op phi Formula.Rsub + | Mult -> R.f_op phi Formula.Rmul + | Div -> R.f_op phi Formula.Rdiv + | _ -> WpLog.fatal "[float_operator] non float operator" + + let icmp_operator iota op x y = + match op with + | Eq -> A.i_cmp iota Formula.Ceq x y + | Ne -> A.i_cmp iota Formula.Cneq x y + | Lt -> A.i_cmp iota Formula.Clt x y + | Le -> A.i_cmp iota Formula.Cleq x y + | Ge -> A.i_cmp iota Formula.Cleq y x + | Gt -> A.i_cmp iota Formula.Clt y x + | _ -> WpLog.fatal "[icmp_operator] non integer comparator" + + let prop_icmp op x y = + match op with + | Eq -> F.p_icmp Formula.Ceq x y + | Ne -> F.p_icmp Formula.Cneq x y + | Lt -> F.p_icmp Formula.Clt x y + | Le -> F.p_icmp Formula.Cleq x y + | Ge -> F.p_icmp Formula.Cleq y x + | Gt -> F.p_icmp Formula.Clt y x + | _ -> WpLog.fatal "[prop_icmp] non integer relation" + + let fcmp_operator phi op x y = + match op with + | Eq -> R.f_cmp phi Formula.Ceq x y + | Ne -> R.f_cmp phi Formula.Cneq x y + | Lt -> R.f_cmp phi Formula.Clt x y + | Le -> R.f_cmp phi Formula.Cleq x y + | Ge -> R.f_cmp phi Formula.Cleq y x + | Gt -> R.f_cmp phi Formula.Clt y x + | _ -> WpLog.fatal "[fcmp_operator] non float comparator" + + let prop_rcmp op x y = + match op with + | Eq -> F.p_rcmp Formula.Ceq x y + | Ne -> F.p_rcmp Formula.Cneq x y + | Lt -> F.p_rcmp Formula.Clt x y + | Le -> F.p_rcmp Formula.Cleq x y + | Ge -> F.p_rcmp Formula.Cleq y x + | Gt -> F.p_rcmp Formula.Clt y x + | _ -> WpLog.fatal "[prop_rcmp] non real relation" + + + let pcmp_operator op x y = + match op with + | Eq -> M.equal_loc_bool x y + | Ne -> F.e_not ( M.equal_loc_bool x y) + | Lt -> M.lt_loc_bool x y + | Le -> M.le_loc_bool x y + | Ge -> M.le_loc_bool y x + | Gt -> M.lt_loc_bool y x + | _ -> WpLog.fatal "[pcmp_operator] non comparator" + + + let pcmp_rel op x y = + match op with + | Eq -> M.equal_loc x y + | Ne -> F.p_not (M.equal_loc x y) + | Lt -> M.lt_loc x y + | Le -> M.le_loc x y + | Ge -> M.le_loc y x + | Gt -> M.lt_loc y x + | _ -> WpLog.fatal "[pcmp_rel] non relation" + + (* special pointer arithmetic interpretation of Zero. *) + let expr_rec_spec_null mem e1 = + if Cil.isZero e1 then + let t = Ctypes.object_of (Cil.typeOf e1) in + M.V_pointer(t, M.null) else (!expr_rec mem e1) + + (*Interpretation of pointer comparisons. *) + let expr_cond_cmp_ptr mem cmpop e1 e2 = + let t1 = loc_of_value (expr_rec_spec_null mem e1) in + let t2 = loc_of_value (expr_rec_spec_null mem e2) in + pcmp_operator cmpop t1 t2 + + let prop_cmp_ptr mem cmpop e1 e2 = + let t1 = loc_of_value (expr_rec_spec_null mem e1) in + let t2 = loc_of_value (expr_rec_spec_null mem e2) in + pcmp_rel cmpop t1 t2 + + (*Interpretation of arithmetic comparisons. *) + let expr_cond_cmp_arith mem cmpop ct1 e1 ct2 e2 = + let ctr = Ctypes.promote ct1 ct2 in + begin + match ctr , ct1 , ct2 with + | C_int ir , C_int i1 , C_int i2 -> + let t1 = expr_int mem i1 ir e1 in + let t2 = expr_int mem i2 ir e2 in + icmp_operator ir cmpop t1 t2 + | C_float fr, C_float f1, C_float f2 -> + let t1 = expr_float mem f1 fr e1 in + let t2 = expr_float mem f2 fr e2 in + fcmp_operator fr cmpop t1 t2 + | _ -> WpLog.fatal "[expr_cond_cmp_arith] non arithmetics comparison" + end + + (* [expr_cond_cmp mem cmpop t1 e1 t2 e2] returns the interpreation + of the comparison [cmpop] of expression [e1] of type [t1] and + expression [e2] of type [t2] in memory [mem]. *) + let expr_cond_cmp mem cmpop t1 e1 t2 e2 = + let ct1 = Ctypes.object_of t1 in + let ct2 = Ctypes.object_of t2 in + begin + match ct1,ct2 with + | C_pointer _,C_pointer _ -> expr_cond_cmp_ptr mem cmpop e1 e2 + | _ -> expr_cond_cmp_arith mem cmpop ct1 e1 ct2 e2 + end + + + + let prop_cmp mem cmpop t1 e1 t2 e2 = + let ct1 = Ctypes.object_of t1 in + let ct2 = Ctypes.object_of t2 in + match ct1,ct2 with + | C_pointer _,C_pointer _ -> + (prop_cmp_ptr mem cmpop e1 e2) + | _ -> + let ctr = Ctypes.promote ct1 ct2 in + begin + match ctr , ct1 , ct2 with + | C_int ir , C_int i1 , C_int i2 -> + let t1 = expr_int mem i1 ir e1 in + let t2 = expr_int mem i2 ir e2 in + prop_icmp cmpop t1 t2 + | C_float fr, C_float f1, C_float f2 -> + let t1 = expr_float mem f1 fr e1 in + let t2 = expr_float mem f2 fr e2 in + prop_rcmp cmpop t1 t2 + | _ -> WpLog.fatal "[prop_cmp] non arithmetic relation" + end + + (* Interpretation of integer arithmetics. *) + let expr_int_operator mem ir binop i1 e1 i2 e2 = + let t1 = expr_int mem i1 ir e1 in + let t2 = expr_int mem i2 ir e2 in + int_operator ir binop t1 t2 + + + (* Interpretation of float arithmetics *) + let expr_float_operator mem fr binop f1 e1 f2 e2 = + let t1 = expr_float mem f1 fr e1 in + let t2 = expr_float mem f2 fr e2 in + float_operator fr binop t1 t2 + + + (* [expr_binop mem binop tr e1 t1 e2 t2] interprets the binary + operation [binop] as a value of type [tr] of expression [e1] of + type [t1] and expression [e2] of type [t2].*) + let expr_binop mem binop tr e1 t1 e2 t2 = + match binop with + | IndexPI | PlusPI -> + let ty = Ctypes.object_of_pointed (Ctypes.object_of t1) in + let loc = loc_of_value (!expr_rec mem e1) in + let idx = int_of_value (!expr_rec mem e2) in + M.V_pointer(ty,M.shift loc ty idx) + + | MinusPI -> + let ty = Ctypes.object_of_pointed (Ctypes.object_of t1) in + let loc = loc_of_value (!expr_rec mem e1) in + let neg_idx = int_of_value (!expr_rec mem e2) in + let idx = F.e_ineg neg_idx in + M.V_pointer(ty,M.shift loc ty idx) + + | MinusPP -> + let iota = c_int_of_typ tr in + value_of_integer iota + (M.minus_loc + (loc_of_value (!expr_rec mem e1)) + (loc_of_value (!expr_rec mem e2))) + + | (Eq | Ne | Ge | Le | Gt | Lt) -> + value_of_boolean (expr_cond_cmp mem binop t1 e1 t2 e2) + + | PlusA | MinusA | Mult | Div | Mod + | BAnd | BXor | BOr | Shiftlt | Shiftrt -> + let ct1 = Ctypes.object_of t1 in + let ct2 = Ctypes.object_of t2 in + let ctr = Ctypes.object_of tr in + begin + match ctr , ct1 , ct2 with + | C_int ir , C_int i1 , C_int i2 -> + M.V_int(ir,expr_int_operator mem ir binop i1 e1 i2 e2) + | C_float fr, C_float f1, C_float f2 -> + M.V_float(fr,expr_float_operator mem fr binop f1 e1 f2 e2) + | _ -> WpLog.fatal "non arithmetics arguments" + end + + | LAnd -> + value_of_boolean (F.e_and (!cond_rec mem e1) (!cond_rec mem e2)) + | LOr -> + value_of_boolean (F.e_or (!cond_rec mem e1) (!cond_rec mem e2)) + + (* [cond_binop mem binop tr e1 t1 e2 t2] interprets the binary + operation [binop] as a boolean of expression [e1] of type [t1] + and expression [e2] of type [t2].*) + let cond_binop mem binop tr e1 t1 e2 t2 = + match binop with + | IndexPI | PlusPI -> + let te = Ctypes.object_of_pointed (Ctypes.object_of t1) in + let loc = loc_of_value (!expr_rec mem e1) in + let idx = int_of_value (!expr_rec mem e2) in + boolean_of_loc (M.shift loc te idx) + + | MinusPI -> + let te = Ctypes.object_of_pointed (Ctypes.object_of t1) in + let loc = loc_of_value (!expr_rec mem e1) in + let neg_idx = int_of_value (!expr_rec mem e2) in + let idx = F.e_ineg neg_idx in + boolean_of_loc (M.shift loc te idx) + + | MinusPP -> + boolean_of_integer + (M.minus_loc + (loc_of_value (!expr_rec mem e1)) + (loc_of_value (!expr_rec mem e2))) + + | (Eq | Ne | Ge | Le | Gt | Lt) -> + expr_cond_cmp mem binop t1 e1 t2 e2 + + | PlusA | MinusA | Mult | Div | Mod + | BAnd | BXor | BOr | Shiftlt | Shiftrt -> + let ct1 = Ctypes.object_of t1 in + let ct2 = Ctypes.object_of t2 in + let ctr = Ctypes.object_of tr in + begin + match ctr , ct1 , ct2 with + | C_int ir , C_int i1 , C_int i2 -> + boolean_of_int (expr_int_operator mem ir binop i1 e1 i2 e2) + | C_float fr, C_float f1, C_float f2 -> + boolean_of_float + (expr_float_operator mem fr binop f1 e1 f2 e2) + | _ -> WpLog.fatal "non arithmetics arguments" + end + + | LAnd -> F.e_and (!cond_rec mem e1) (!cond_rec mem e2) + | LOr -> F.e_or (!cond_rec mem e1) (!cond_rec mem e2) + + + let prop_binop mem binop tr e1 t1 e2 t2 = + match binop with + | IndexPI | PlusPI -> + let te = Ctypes.object_of_pointed (Ctypes.object_of t1) in + let loc = loc_of_value (!expr_rec mem e1) in + let idx = int_of_value (!expr_rec mem e2) in + prop_of_loc (M.shift loc te idx) + + | MinusPI -> + let te = Ctypes.object_of_pointed (Ctypes.object_of t1) in + let loc = loc_of_value (!expr_rec mem e1) in + let neg_idx = int_of_value (!expr_rec mem e2) in + let idx = F.e_ineg neg_idx in + prop_of_loc (M.shift loc te idx) + + | MinusPP -> + prop_of_integer + (M.minus_loc + (loc_of_value (!expr_rec mem e1)) + (loc_of_value (!expr_rec mem e2))) + + | (Eq | Ne | Ge | Le | Gt | Lt) -> + prop_cmp mem binop t1 e1 t2 e2 + + | PlusA | MinusA | Mult | Div | Mod + | BAnd | BXor | BOr | Shiftlt | Shiftrt -> + let ct1 = Ctypes.object_of t1 in + let ct2 = Ctypes.object_of t2 in + let ctr = Ctypes.object_of tr in + begin + match ctr , ct1 , ct2 with + | C_int ir , C_int i1 , C_int i2 -> + prop_of_int (expr_int_operator mem ir binop i1 e1 i2 e2) + | C_float fr, C_float f1, C_float f2 -> + prop_of_float + (expr_float_operator mem fr binop f1 e1 f2 e2) + | _ -> WpLog.fatal "non arithmetics arguments" + end + + | LAnd -> F.p_and (!prop_rec mem e1) (!prop_rec mem e2) + | LOr -> F.p_or (!prop_rec mem e1) (!prop_rec mem e2) + + + (* ----------------------------------------------------------------------- *) + (* --- Unary Operator --- *) + (* ----------------------------------------------------------------------- *) + + (* [cond_unop mem op tyr e te ] interprets the unary operation [op] + as a boolean of expression [e] of type [te].*) + let cond_unop mem op tyr e te = + let ct1 = object_of te in + let ctr = object_of tyr in + match op with + | Neg -> + begin + match ctr,ct1 with + | C_int ir , C_int i1 -> + boolean_of_int (A.i_neg ir (expr_int mem i1 ir e)) + | C_float fr , C_float f1 -> + boolean_of_float (R.f_neg fr (expr_float mem f1 fr e)) + | _ ->WpLog.fatal "non arithmetics argument" + end + | BNot -> + begin + match ctr,ct1 with + | C_int ir , C_int i1 -> + boolean_of_int (A.bits_not ir (expr_int mem i1 ir e)) + | _ -> WpLog.fatal "non integer argument" + end + | LNot -> + let term = !expr_rec mem e in + begin + match ct1 with + | C_int i1 -> + (A.i_cmp i1 Formula.Ceq (int_of_value term) F.i_zero) + | C_float f1 -> + (R.f_cmp f1 Formula.Ceq (float_of_value term) F.r_zero) + | C_pointer _ -> + (M.is_null (loc_of_value term)) + | _ -> WpLog.fatal "non arithmetics nor pointer argument" + + end + + (* [expr_unop mem op tyr e te ] interprets the unary operation [op] + as a value of type [tyr] of expression [e] of type [te].*) + let expr_unop mem op tyr e te = + let ct1 = object_of te in + let ctr = object_of tyr in + match op with + | Neg -> + begin + match ctr,ct1 with + | C_int ir , C_int i1 -> + M.V_int(ir,A.i_neg ir (expr_int mem i1 ir e)) + | C_float fr , C_float f1 -> + M.V_float(fr,R.f_neg fr (expr_float mem f1 fr e)) + | _ -> WpLog.fatal "non arithmetic argument" + end + | BNot -> + begin + match ctr,ct1 with + | C_int ir , C_int i1 -> + M.V_int(ir,expr_int mem i1 ir e) + | _ -> WpLog.fatal "non intger argument" + end + | LNot -> + let term = !expr_rec mem e in + begin + match ct1 with + | C_int i1 -> + value_of_boolean (A.i_cmp i1 Formula.Ceq + (int_of_value term) F.i_zero) + | C_float f1 -> + value_of_boolean (R.f_cmp f1 Formula.Ceq + (float_of_value term) F.r_zero) + | C_pointer _ -> + value_of_boolean + (M.is_null (loc_of_value term)) + | _ -> WpLog.fatal "non arithmetic nor pointer argument" + end + + let prop_unop mem op tyr e te = + let ct1 = object_of te in + let ctr = object_of tyr in + match op with + | Neg -> + begin + match ctr,ct1 with + | C_int ir , C_int i1 -> + prop_of_int (A.i_neg ir (expr_int mem i1 ir e)) + | C_float fr , C_float f1 -> + prop_of_float (R.f_neg fr (expr_float mem f1 fr e)) + | _ -> WpLog.fatal "non arithmetic argument" + end + | BNot -> + begin + match ctr,ct1 with + | C_int ir , C_int i1 -> not_of_int (expr_int mem i1 ir e) + | _ -> WpLog.fatal "non integer argument" + end + | LNot -> let term = !expr_rec mem e in not_of_value term + + (* ----------------------------------------------------------------------- *) + (* --- Expressions --- *) + (* ----------------------------------------------------------------------- *) + + let rec expr mem e = + match (Cil.stripInfo e).enode with + | Info _ -> WpLog.fatal "non translation for info type expression" + | Const (cnst) -> expr_const mem cnst + | CastE (ty,e) -> + if Cil.isPointerType ty && Cil.isZero e then + (let t = Ctypes.object_of_pointed (Ctypes.object_of ty) in + M.V_pointer(t, M.null)) + else + expr_cast (Cil.typeOf e) ty (expr mem e) + | BinOp (op, e1, e2, ty) -> + expr_binop mem op ty + e1 (Cil.typeOf e1) + e2 (Cil.typeOf e2) + | UnOp (op, e1, ty) -> + expr_unop mem op ty e1 (Cil.typeOf e1) + + | Lval lval -> + let t = Cil.typeOf e in + let l = addr mem lval in + M.load mem (Ctypes.object_of t) l + + | StartOf lval -> + let ty_elt = + Ctypes.object_of_pointed (Ctypes.object_of (Cil.typeOf e)) in + M.V_pointer(ty_elt,startof mem ty_elt lval) + + | AddrOf lval -> + let ty_elt = + Ctypes.object_of_pointed (Ctypes.object_of (Cil.typeOf e)) + in + M.V_pointer(ty_elt,addr mem lval) + + | AlignOfE _ | AlignOf _ + | SizeOfE _ | SizeOf _ | SizeOfStr _ -> + let e' = Cil.constFold true e in + match e'.enode with + | Const _ -> expr mem e' + | _ -> + WpLog.not_yet_implemented "sizeof(%a)" + !Ast_printer.d_exp e + + + (* ----------------------------------------------------------------------- *) + (* --- Conditional Expression --- *) + (* ----------------------------------------------------------------------- *) + + let cond mem e = + match (Cil.stripInfo e).enode with + + | BinOp (op, e1, e2, ty) -> + cond_binop mem op ty e1 (Cil.typeOf e1) e2 (Cil.typeOf e2) + | UnOp (op, e1, ty) -> + cond_unop mem op ty e1 (Cil.typeOf e1) + + | _ -> boolean_of_value (expr mem e) + + + + + (* ----------------------------------------------------------------------- *) + (* --- Predicative translation of Conditional --- *) + (* ----------------------------------------------------------------------- *) + + let prop mem e = + match (Cil.stripInfo e).enode with + | Info _ -> WpLog.fatal "non translation for info type expression" + | Const (cnst) -> prop_const mem cnst + | CastE (ty,e) -> + if Cil.isPointerType ty && Cil.isZero e then + F.p_false + else + prop_cast (Cil.typeOf e) ty (expr mem e) + + | BinOp (op, e1, e2, ty) -> + prop_binop mem op ty + e1 (Cil.typeOf e1) + e2 (Cil.typeOf e2) + | UnOp (op, e1, ty) -> + prop_unop mem op ty e1 (Cil.typeOf e1) + + | Lval lval -> + let t = Cil.typeOf e in + let l = addr mem lval in + prop_of_value (M.load mem (Ctypes.object_of t) l) + + | StartOf lval -> + let ty_elt = + Ctypes.object_of_pointed (Ctypes.object_of (Cil.typeOf e)) + in + prop_of_loc (startof mem ty_elt lval) + + | AddrOf lval -> + prop_of_loc (addr mem lval) + + | AlignOfE _ | AlignOf _ + | SizeOfE _ | SizeOf _ | SizeOfStr _ -> + let e' = Cil.constFold true e in + match e'.enode with + | Const c -> prop_const mem c + | _ -> WpLog.not_yet_implemented "sizeof(%a)" + !Ast_printer.d_exp e + + (* ----------------------------------------------------------------------- *) + (* --- Recursion Bindings --- *) + (* ----------------------------------------------------------------------- *) + + let () = + begin + expr_rec := expr ; + cond_rec := cond ; + prop_rec := prop; + end + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/translate_expr.mli frama-c-20111001+nitrogen+dfsg/src/wp/translate_expr.mli --- frama-c-20110201+carbon+dfsg/src/wp/translate_expr.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/translate_expr.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(** Translation of Expressions *) +(* -------------------------------------------------------------------------- *) + +open Formula + +module Create (M : Mvalues.S): +sig + + + (** [addr mem lv] interprets the left value [lv] as + an address (memory location) in the memory [mem].**) + val addr : M.mem -> Cil_types.lval -> M.loc + + + (** [expr mem e] interprets the expression[e] as a value + in memory [mem] **) + val expr : M.mem -> Cil_types.exp -> M.value + + (** [cond mem e] interprets [e] as a boolean + in memory [mem]. **) + val cond : M.mem -> Cil_types.exp -> M.F.boolean + + (** [prop mem e] interprets the expression[e] as a predicate + in memory [mem] **) + val prop : M.mem -> Cil_types.exp -> M.F.pred + + (**[expr_cast mem ty_to ty_from e] casts [e] of type [ty_from] to type + type [ty_to] in memory [mem] **) + + val expr_cast : Cil_types.typ -> Cil_types.typ -> M.value -> M.value + +end + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/translate_prop.ml frama-c-20111001+nitrogen+dfsg/src/wp/translate_prop.ml --- frama-c-20110201+carbon+dfsg/src/wp/translate_prop.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/translate_prop.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,2217 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(* --- Translation of Term and Predicats --- *) +(* ------------------------------------------------------------------------ *) + +module WpLog = Wp_parameters + +open Ctypes +open Clabels +open Formula +open Cil_types +open Cil_datatype + +let debug = WpLog.debug ~dkey:"trans" + +module Create + (M : Mlogic.S) + = + +struct + + module F = M.F + module L = M.L + + (* ----------------------------------------------------------------------- *) + (* --- Registration of User-defined Predicate and Functions --- *) + (* ----------------------------------------------------------------------- *) + + type user_formal = + | UF_logic of logic_var * F.var + | UF_references of + logic_var * F.var option * ( F.var * M.formal * string ) list + (*lv, associated C var, list of formals at each label *) + | UF_closure of F.var * M.closure * string + (* a model variable (closure) required at a given label *) + + type userdef = { + d_info : logic_info ; + d_callname : string ; + d_formals : user_formal list ; + } + + type axiomlabel = { + a_name : string ; + a_defname : string ; + a_property : F.pred ; + a_memory : user_formal list ; + } + + module Hdef = Logic_var.Hashtbl + + (* Memoization of axioms compilation tables *) + let user_axioms : (string,F.pred option) Hashtbl.t = Hashtbl.create 131 + let user_axiomlabels : (string,axiomlabel option) Hashtbl.t = + Hashtbl.create 131 + let user_definitions = Hdef.create 131 + + let () = F.on_clear + (fun () -> + Hashtbl.clear user_axioms ; + Hashtbl.clear user_axiomlabels ; + Hdef.clear user_definitions ; + ) + + let rec pp_closures fmt (xs,cs) = + match xs , cs with + | [] , [] -> () + | x::xs , (c,l)::cs -> + Format.fprintf fmt "{%s:%a=%a@@%s}@," + (F.name_of_var x) + M.pp_tau (F.tau_of_var x) + M.pp_closure c l ; + pp_closures fmt (xs,cs) + | x::xs , [] -> + Format.fprintf fmt "{%s:%a=?}@," + (F.name_of_var x) + M.pp_tau (F.tau_of_var x) ; + pp_closures fmt (xs,[]) + | [] , (c,l)::cs -> + Format.fprintf fmt "{?=%a@@%s}@," + M.pp_closure c l ; + pp_closures fmt ([],cs) + + let pp_formals fmt xs = + List.iter + (fun x -> + Format.fprintf fmt "(%s:%a)@," + (F.name_of_var x) + M.pp_tau (F.tau_of_var x) ; + ) xs + + module UserDefinition = + struct + let lock : unit Hdef.t = Hdef.create 131 + let () = F.on_clear (fun () -> Hdef.clear lock) + + let pp_userdef_title fmt d = + let f = d.d_info in + let x = f.l_var_info.lv_name in + match f.l_type with + | Some _ -> + if f.l_tparams=[] && f.l_labels=[] + then Format.fprintf fmt "User-defined constant %s" x + else Format.fprintf fmt "User-defined function %s" x + | None -> + Format.fprintf fmt "User-defined predicate %s" x + + let pp_userformals fmt ufs = + List.iter + (function + | UF_logic(lv,x) -> + Format.fprintf fmt + "@\n * (%a:%a) parameter '%s' in ACSL definition" + F.pp_var x F.pp_tau (F.tau_of_var x) + (* original name of lv *) lv.lv_name + | UF_references(lv,opt_cx,refs) -> + begin + match opt_cx with + | None -> () + | Some y -> + Format.fprintf fmt "@\n * (%a:%a) C reference to %a" + F.pp_var y F.pp_tau (F.tau_of_var y) + !Ast_printer.d_logic_var lv + end; + List.iter + (fun (x,formal,label) -> + Format.fprintf fmt "@\n * (%a:%a) reference to %a at %s" + F.pp_var x F.pp_tau (F.tau_of_var x) + M.pp_formal (formal,lv) label ) + refs + | UF_closure(x,closure,label) -> + Format.fprintf fmt "@\n * (%a:%a) %a at %s" + F.pp_var x F.pp_tau (F.tau_of_var x) + M.pp_closure closure label + ) ufs + + let pp_userdef_descr fmt d = + if d.d_formals <> [] then + begin + Format.fprintf fmt "Signature:" ; + pp_userformals fmt d.d_formals ; + end + + let define duser items = + let k = duser.d_info.l_var_info in + List.iter + (fun (name,item) -> + let section = + match item with + | Function _ | Predicate _ -> S_User_Sig + | Axiom _ -> S_User_Prop + | _ -> assert false + in + F.add_declaration { + d_name = name ; + d_section = section ; + d_title = (fun fmt -> pp_userdef_title fmt duser) ; + d_descr = (fun fmt -> pp_userdef_descr fmt duser) ; + d_source = None ; + d_item = item ; + }) + items ; + Hdef.remove lock k + + let unlock xdef = + Hdef.remove lock xdef + + let lock xdef = + if Hdef.mem lock xdef then + ( Wp_parameters.not_yet_implemented "Recursive definition (in '%a')" + !Ast_printer.d_logic_var xdef ) ; + Hdef.add lock xdef () + + end + + module UserAxiom = F.DRegister + (struct + type t = string + module H = Hashtbl.Make + (struct + type t = string + let hash = Hashtbl.hash + let equal: string -> string -> bool = (=) + end) + let section = S_User_Prop + let source = None + let prefix = "Hyp" + let clear () = () + let index x = x + let basename x = x + let location _x = None + let declare x _ = + try + match Hashtbl.find user_axioms x with + | Some p -> Formula.Axiom p + | None -> raise Not_found + with Not_found -> Wp_parameters.fatal "Uncompiled axiom (%s)" x + let pp_title fmt x = Format.fprintf fmt "User-defined axiom %s" x + let pp_descr fmt _x = Format.fprintf fmt "No labels." + end) + + module UserAxiomDefs = + struct + + let pp_labels fmt = function + | [] -> () + | x::xs -> + Format.fprintf fmt "@[{%s" x ; + List.iter (fun x -> Format.fprintf fmt ",%s" x) xs ; + Format.fprintf fmt "}@]" + + let pp_axiomdef_title fmt a = + Format.fprintf fmt "User defined axiom %s" a.a_name + + let pp_axiomdef_descr fmt a = + if a.a_memory <> [] then + begin + Format.fprintf fmt "Memory parameters: " ; + UserDefinition.pp_userformals fmt a.a_memory ; + end + + let define axdef = + F.add_declaration { + d_name = axdef.a_defname ; + d_section = S_User_Prop ; + d_title = (fun fmt -> pp_axiomdef_title fmt axdef) ; + d_descr = (fun fmt -> pp_axiomdef_descr fmt axdef) ; + d_source = None ; + d_item = Formula.Axiom axdef.a_property ; + } + + let is_defined name = F.has_declaration ("Hyp_" ^ name) + + end + + (* ----------------------------------------------------------------------- *) + (* --- Frame Environment --- *) + (* ----------------------------------------------------------------------- *) + + module Lmap = Map.Make + (struct + type t = c_label + let compare = Pervasives.compare + end) + + type frame = { + mutable states : M.mem Lmap.t ; + mutable result : F.var option ; + mutable status : F.var option ; + mutable return : Cil_types.typ option ; + } + + let new_frame kf ?m_here ?m_pre ?m_post ?x_result ?x_status () = + let bind l x s = match x with None -> s | Some m -> Lmap.add l m s in + let states = + bind Clabels.Here m_here + (bind Clabels.Pre m_pre + (bind Clabels.Post m_post + Lmap.empty)) + in { + states = states ; + result = x_result ; + status = x_status ; + return = Some(Kernel_function.get_return_type kf) ; + } + + let user_frame () = + { + states = Lmap.empty ; + result = None ; + status = None ; + return = None ; + } + + let result frame = + match frame.result with + | Some x -> x + | None -> + match frame.return with + | Some typ -> + let tau = M.tau_of_logic_type (Ctype typ) in + let x = L.fresh "result" (Formula.Acsl(tau,Ctype typ)) in + frame.result <- Some x ; x + | None -> + Wp_parameters.fatal "Result type undefined" + + let status frame = + match frame.status with + | Some x -> x + | None -> + let x = L.fresh "status" (Formula.Model Formula.Integer) in + frame.status <- Some x ; x + + (* ----------------------------------------------------------------------- *) + (* --- Translation Environment --- *) + (* ----------------------------------------------------------------------- *) + + type lvar_kind = (* What represents a given logic_var (lv) *) + | Logic_cvar of varinfo (* (lv) is a varinfo *) + | Logic_value of M.value (* (lv) mapsto a value in the model *) + | Logic_term of F.abstract (* (lv) mapsto an arbitrary ACSL value *) + | Logic_var of F.var (* (lv) mapsto a collectable FOL variable *) + | Logic_byref (* (lv) is a formal parameter of logic passed by reference *) + + type env = { + formals_in_pre : bool ; + frame : frame ; + label : c_label ; + xvars : M.value Varinfo.Map.t ; + (* maping of logic_vars when lv_origin<>None *) + lvars : lvar_kind Logic_var.Map.t ; + (* lvar_kind of logic_vars when lv_origin=None *) + mutable laddr : F.var Logic_var.Map.t ; + (* addresses of by-reference user formal *) + } + + + + let fresh_addr lv : F.var = + debug "[fresh_addr] of %a" !Ast_printer.d_logic_var lv; + let tau = Formula.Pointer (M.tau_of_loc) in + let x = L.fresh lv.lv_name (Formula.Model tau) in + debug "[fresh_addr] of %a : %a" !Ast_printer.d_logic_var lv F.pp_var x; + x + + let addr_of_ref env lv = + debug "[addr_of_ref] of %a" !Ast_printer.d_logic_var lv; + try + let x = Logic_var.Map.find lv env.laddr in + debug "[addr_of_ref] of %a already recorded :%a" + !Ast_printer.d_logic_var lv F.pp_var x ; x + with + Not_found -> + debug "[addr_of_ref] %a not yet in" + !Ast_printer.d_logic_var lv; + let x = fresh_addr lv in + env.laddr <-Logic_var.Map.add lv x env.laddr ; + debug "[addr_of_ref] of %a recorded with %a" + !Ast_printer.d_logic_var lv F.pp_var x ; x + + + +(* -------------------------------------------------------------------------- *) +(* --- Global Recursion for Logic Functions (for logic constants) --- *) +(* -------------------------------------------------------------------------- *) + + let rec_apply_function + : (env -> logic_info -> + (logic_label * logic_label) list -> + term list -> F.abstract) ref + = ref (fun _ _ _ _ -> assert false) + +(* -------------------------------------------------------------------------- *) +(* --- Logic-Variable access --- *) +(* -------------------------------------------------------------------------- *) + + let lvar env lv : lvar_kind = + match lv.lv_origin with + | None -> + begin + try Logic_var.Map.find lv env.lvars + with Not_found -> + try + let cst = Logic_env.find_logic_cons lv in + Logic_term (!rec_apply_function env cst [] []) + with Not_found -> + Wp_parameters.abort "Unknown logic constant %s" lv.lv_name + end + | Some vi -> + begin + try Logic_value (Varinfo.Map.find vi env.xvars) + with Not_found -> Logic_cvar vi + end + + let xvar env vi : M.value option = + try Some(Varinfo.Map.find vi env.xvars) with Not_found -> None + +(* -------------------------------------------------------------------------- *) +(* --- Allocation of (collectable) logic variables --- *) +(* -------------------------------------------------------------------------- *) + + let fresh_local lv : F.var = + let lt = lv.lv_type in + let tau = M.tau_of_logic_type lt in + L.fresh lv.lv_name (Formula.Acsl(tau,lt)) + + let fresh_logic_var pool lv = + let lt = lv.lv_type in + let t = M.tau_of_logic_type lt in + F.p_fresh pool lv.lv_name (Formula.Acsl(t,lt)) + + let add_logic_vars env pool lvs = + let lvars = + List.fold_left + (fun lvars lv -> + let x = fresh_logic_var pool lv in + Logic_var.Map.add lv (Logic_var x) lvars) + env.lvars lvs + in { env with lvars = lvars } + + let collect_logic_vars env = + Logic_var.Map.fold + (fun _lv lk acc -> + match lk with + | Logic_var x -> x::acc + | _ -> acc) + env.lvars [] + + (* -------------------------------------------------------------------------- *) + (* --- Local Bindings of logic variables to values --- *) + (* -------------------------------------------------------------------------- *) + + let bind_lvars env (bindings : (logic_var * F.abstract) list) = + let lvars = + List.fold_left + (fun lvars (lv,term) -> Logic_var.Map.add lv (Logic_term term) lvars) + env.lvars bindings + in { env with lvars = lvars } + + let bind_lvar env lv term = + { env with lvars = Logic_var.Map.add lv (Logic_term term) env.lvars } + + let bind_fresh env lv : (F.var * env) = + let x = fresh_local lv in + x , bind_lvar env lv (F.var x) + +(* -------------------------------------------------------------------------- *) +(* --- Access to memory label in environment --- *) +(* -------------------------------------------------------------------------- *) + + let env_at e label = { + formals_in_pre = e.formals_in_pre ; + frame = e.frame ; + label = label ; + lvars = e.lvars ; + xvars = e.xvars ; + laddr = e.laddr; + } + + let find_mem env label = + try Some (Lmap.find label env.frame.states) + with Not_found -> None + + let mem_at env label = + try Lmap.find label env.frame.states + with Not_found -> + let m = M.mem () in + env.frame.states <- Lmap.add label m env.frame.states ; m + + let mem_at_env env = mem_at env env.label + +(* -------------------------------------------------------------------------- *) +(* --- Return & Exit-Status variables --- *) +(* -------------------------------------------------------------------------- *) + + let subst_result env vopt p = + if env.frame.result = None then p + else + let x = result env.frame in + match vopt with + | None -> L.forall [x] p + | Some v -> L.subst x (M.logic_of_value v) p + + let result_type env = + match env.frame.return with + | None -> Wp_parameters.fatal "no result type" + | Some t -> t + + let exit_status env = status env.frame + +(* -------------------------------------------------------------------------- *) +(* --- Environment Constructors --- *) +(* -------------------------------------------------------------------------- *) + + let env kf ?m_here ?m_pre ?m_post ?x_result () = + { + formals_in_pre = false ; + frame = new_frame kf ?m_here ?m_pre ?m_post ?x_result () ; + label = Here ; + lvars = Logic_var.Map.empty ; + xvars = Varinfo.Map.empty ; + laddr = Logic_var.Map.empty; + } + +(* -------------------------------------------------------------------------- *) +(* --- Environment Constructors for Calling Functions --- *) +(* -------------------------------------------------------------------------- *) + + (* Associates formal parameters to values *) + let bind_formals called_kf vs = + let rec bind xvars xs vs = + match xs , vs with + | x::xs , v::vs -> bind (Varinfo.Map.add x v xvars) xs vs + | _ -> xvars + in (* prototypes have exactly the good number of variables *) + bind Varinfo.Map.empty (Kernel_function.get_formals called_kf) vs + + let call_pre caller_env called_kf vs m_pre = + let frame = new_frame called_kf ~m_here:m_pre ~m_pre:m_pre () in + { + formals_in_pre = false ; + frame = frame ; + label = Here ; + lvars = caller_env.lvars ; + xvars = bind_formals called_kf vs ; + laddr = caller_env.laddr ; + } + + let call_post caller_env called_kf vs m_pre m_post x_result = + let frame = + new_frame called_kf ~m_here:m_post ~m_pre ~m_post ?x_result () + in + { + formals_in_pre = true ; + frame = frame ; + label = Here ; + lvars = caller_env.lvars ; + xvars = bind_formals called_kf vs ; + laddr = caller_env.laddr + } + + let call_exit caller_env called_kf vs m_pre m_post x_status = + let frame = + new_frame called_kf ~m_here:m_post ~m_pre ~m_post ~x_status () + in + { + formals_in_pre = false ; + frame = frame ; + label = Here ; + lvars = caller_env.lvars ; + xvars = bind_formals called_kf vs ; + laddr = caller_env.laddr ; + } + + (* ----------------------------------------------------------------------- *) + (* --- Translation Values --- *) + (* ----------------------------------------------------------------------- *) + + (* kinds are logic types *) + type kind = + | Kcint of Ctypes.c_int + | Kint + | Kreal + | Kbool + | Kptr of Cil_types.typ + | Kset of kind + | Kstruct of compinfo + | Karray of arrayinfo + | Kadt of string * kind list + + + let rec kind_equal ka kb = + match ka,kb with + | Kcint i, Kcint j -> i = j + | Kint, Kint | Kreal, Kreal | Kbool, Kbool -> true + | Kptr t, Kptr t' -> Typ.equal t t' + | Kset k, Kset k' -> kind_equal k k' + | Kstruct cp, Kstruct cp' -> Compinfo.equal cp cp' + | Karray a, Karray a' -> AinfoComparable.equal a a' + | Kadt (s,ks), Kadt(s',ks') -> + s=s' && List.for_all2 kind_equal ks ks' + | _, _ -> false + + let pp_kind fmt = function + | Kcint i -> Ctypes.pp_int fmt i + | Kint -> Format.pp_print_string fmt "int" + | Kreal -> Format.pp_print_string fmt "real" + | Kptr _-> Format.pp_print_string fmt "pointer" + | Kset _-> Format.pp_print_string fmt "set" + | Kstruct c -> Format.pp_print_string fmt c.cname + | Karray a -> Ctypes.pretty fmt (C_array a) + | Kadt (s,_) -> Format.pp_print_string fmt s + | Kbool -> Format.pp_print_string fmt "bool" + + type data = + | Data of F.abstract (* Singleton *) + | Loc of M.loc + | Value of M.value + | Interval of F.interval + | Range of c_object * M.loc * F.interval + | List of data list + | Set of F.set + + let pp_data fmt = function + | Data d -> Format.fprintf fmt "Data=%a" F.pp_term d + | Loc l -> Format.fprintf fmt "Loc=%a" M.pp_loc l + | Value v -> Format.fprintf fmt "Value=%a" M.pp_value v + | _ -> Format.fprintf fmt "Blob" + + let data_of_integer (x : F.integer) : data = Data (F.wrap x) + let data_of_real (x : F.real) : data = Data(F.wrap x) + let data_of_boolean (x:F.boolean) : data = Data (F.wrap x) + + let integer_of_value = function + | M.V_int(_,t) -> t + | v -> Wp_parameters.fatal "integer_of_value %a" M.pp_value v + + let real_of_value = function + | M.V_float(_,t) -> t + | M.V_int(_,t) -> F.real_of_integer t + | v -> WpLog.fatal "[real_of_value] of %a" M.pp_value v + + let extract_from_data = function + | Data d -> F.unwrap d + | Value v -> F.unwrap (M.logic_of_value v) + | d -> WpLog.fatal "[extract_from_data] of %a" pp_data d + + let boolean_of_data d : F.boolean = extract_from_data d + let array_of_data d : F.array = extract_from_data d + let record_of_data d : F.record = extract_from_data d + let urecord_of_data d : F.urecord = extract_from_data d + + let loc_of_data obj d = + match d with + | Value(M.V_pointer(_,l)) -> l + | Value v -> M.loc_of_term obj (F.unwrap (M.logic_of_value v)) + | Data l -> M.loc_of_term obj (F.unwrap l) + | Loc l -> l + | _ -> + Wp_parameters.fatal ~current:true "not a loc (%a)" pp_data d + + let integer_of_data k d : F.integer = + match d with + | Data d -> + begin + match k with + | Kint | Kcint _ -> F.unwrap d + | k -> WpLog.fatal ~current:true "not an integer (%a : %a)" + F.pp_term d pp_kind k + end + | Value v -> integer_of_value v + | _ -> WpLog.fatal ~current:true "not an integer (%a)" pp_data d + + let real_of_data k d = + match k with + | Kint | Kcint _-> F.real_of_integer (integer_of_data k d) + | Kreal -> + begin + match d with + | Data d -> F.unwrap d + | Value v -> real_of_value v + | _ -> WpLog.fatal ~current:true "not a real (%a)" pp_data d + end + | _ -> WpLog.fatal ~current:true "not a real (%a)" pp_data d + + + let rec set_of = function + | Value v -> F.singleton (M.logic_of_value v) + | Data d -> F.singleton d + | Loc l -> F.singleton (M.term_of_loc l) + | List ds -> F.unions (List.map set_of ds) + | Interval i -> F.interval i + | Set s -> s + | Range _ -> Wp_parameters.not_yet_implemented "set of zone" + + let list_of = function + | (Value _|Data _|Loc _|Interval _|Range _) as d -> [d] + | List xs -> xs + | Set _ -> WpLog.fatal "[list_of] a set" + + let union_data a b = + match a,b with + | Set a , b | b, Set a -> Set (F.union a (set_of b)) + | List _ , _ | _ , List _ -> List (list_of a @ list_of b) + | ( (Value _|Data _|Loc _|Range _|Interval _ ) , + (Value _|Data _|Loc _|Range _|Interval _ ) ) -> List[a;b] + + let union_map f = function + | [] -> List [] + | d::ds -> + List.fold_left + (fun w x -> union_data w (f x)) + (f d) ds + + let term_of_data = function + | Data t -> t + | Value v -> M.logic_of_value v + | Loc l -> F.wrap (M.term_of_loc l) + | Set s -> F.wrap s + | List dl -> F.wrap (F.unions (List.map (set_of) dl)) + | Range _ -> Wp_parameters.not_yet_implemented "set of zone" + | Interval i -> F.wrap (F.interval i ) + + let neg_interval r = + match r.F.inf,r.F.sup with + | Some j, None -> {F.inf = None ; F.sup = Some (F.e_ineg j)} + | None , Some j -> {F.inf = Some (F.e_ineg j) ; F.sup = None} + | Some j, Some k -> + {F.inf = Some (F.e_ineg k) ; F.sup = Some (F.e_ineg j)} + | None, None -> r + + (* ----------------------------------------------------------------------- *) + (* --- Logic Types --- *) + (* ----------------------------------------------------------------------- *) + + let rec object_of_pointed = function + | Kptr te | Kset(Kptr te) -> Ctypes.object_of te + | _ -> WpLog.fatal "Dereferencing a non-pointer value" + + let kind_of_typ c= + match object_of c with + | C_int i -> Kcint i + | C_float _ -> Kreal + | C_pointer te -> Kptr te + | C_comp comp -> Kstruct comp + | C_array arr -> Karray arr + + let kind_of_data ty = function + | (Data _ | Loc _ | Value _) -> kind_of_typ ty + | (Interval _ | Range _ | List _ | Set _) -> Kset (kind_of_typ ty) + + let rec kind_of = function + | Ctype c -> kind_of_typ c + | Linteger -> Kint + | Lreal -> Kreal + | Ltype ({lt_name="ð”¹"}, _) -> Kbool + | Ltype( {lt_name="set"} , [elt] ) -> Kset(kind_of elt) + | Ltype( {lt_name=adt} , args ) -> Kadt(adt,List.map kind_of args) + | Lvar _ -> WpLog.not_yet_implemented "logic type variables" + | Larrow _ -> WpLog.not_yet_implemented "type of logic function" + + let typ_of_elements = function + | Ctype c -> + let o = object_of c in + begin + match o with + | C_pointer te -> te + | C_array arr -> arr.arr_element + | _ -> + WpLog.fatal "elements of non-pointer type %a" Ctypes.pp_object o + end + | t -> WpLog.fatal "elements of non-pointer type: %a" + !Ast_printer.d_logic_type t + + (* ----------------------------------------------------------------------- *) + (* --- Global Recursions --- *) + (* ----------------------------------------------------------------------- *) + + let data_rec : (env -> term -> data) ref = ref (fun _ _ -> assert false) + + (* ---------------------------------------------------------------------- *) + (* --- Data memory predicate --- *) + (* ---------------------------------------------------------------------- *) + + let rec assigned_of_data te acc d = + match d with + | (Data _|Value _|Loc _) -> + F.Aloc(te,loc_of_data te d)::acc + | Range(te,loc,range) -> + F.Arange(te,loc,range)::acc + | List ds -> List.fold_left (assigned_of_data te) acc ds + | _ -> Wp_parameters.not_yet_implemented "arbitrary zone" + + let data_valid m k d = + let t = + match k with + | Kptr te -> te + | Kset (Kptr te) -> te + | _ -> WpLog.fatal "unexpected type for valid predicate" + in + let te = Ctypes.object_of t in + F.p_conj (List.map (M.valid m) (assigned_of_data te [] d)) + + let data_separated m (t1, d1) (t2, d2) = + let r1 = assigned_of_data t1 [] d1 in + let r2 = assigned_of_data t2 [] d2 in + let p = ref F.p_true in + List.iter + (fun a -> + List.iter + (fun b -> + p := F.p_and !p (M.separated m a b) + ) r2 + ) r1 ; + !p + + (* ---------------------------------------------------------------------- *) + (* --- Data memory operation --- *) + (* ---------------------------------------------------------------------- *) + + let rec data_shift_range tobj loc kbi dindex ~is_pos = + match dindex with + | Data _ | Value _ | Loc _ as d -> + let idx =integer_of_data kbi d in + let idx = if is_pos then idx else F.e_ineg idx in + Loc (M.shift loc tobj idx) + | List il -> union_map (data_shift_range tobj loc kbi ~is_pos) il + | Interval r -> + let r = if is_pos then r else neg_interval r in Range(tobj,loc,r) + | Set _ | Range _ -> + Wp_parameters.not_yet_implemented "pointer shift over arbitrary sets" + + let rec data_index_range tobj loc kbi dindex = + match dindex with + | Data _ | Value _ | Loc _ as d -> + Loc (M.index loc tobj (integer_of_data kbi d)) + | List il -> union_map (data_index_range tobj loc kbi ) il + | Interval r -> Range(tobj,loc,r) + | Set _ | Range _ -> + Wp_parameters.not_yet_implemented "array access over arbitrary sets" + + + let data_shift ka ga kb gb ~is_pos = + match ka,kb with + | (Karray _ | Kptr _ ) , (Kint | Kcint _) -> + let obj = object_of_pointed ka in + let gb = integer_of_data kb gb in + let gb = if is_pos then gb else (F.e_ineg gb) in + Loc (M.shift + (loc_of_data obj ga) + obj gb) + | (Kptr _ | Karray _) , (Kset ((Kint | Kcint _) as kbi)) -> + let obj = object_of_pointed ka in + data_shift_range obj (loc_of_data obj ga) kbi gb ~is_pos + | _ -> WpLog.not_yet_implemented "shift over arbitrary sets of pointers" + + let data_index ta ka ga kb gb = + match ka,kb with + | (Karray _ | Kptr _) , (Kint | Kcint _) -> + Loc (M.index (loc_of_data ta ga) ta (integer_of_data kb gb)) + | (Karray _ | Kptr _) , (Kset ((Kint |Kcint _) as kbi)) -> + data_index_range ta (loc_of_data ta ga) kbi gb + | _ -> WpLog.not_yet_implemented "shift over arbitrary sets of pointers" + + let data_field ka ga f = + match ka with + | Kset _ -> Wp_parameters.not_yet_implemented "field access over sets" + | _ -> let obj = object_of f.ftype in Loc (M.field (loc_of_data obj ga) f) + + let rec data_startof_set ta ga = + match ga with + | Value _ | Data _ | Loc _ -> + Loc (M.startof (loc_of_data ta ga) ta) + | Set _ | Range _ -> + Wp_parameters.not_yet_implemented "start-of over sets" + | List pl -> + union_map (fun p -> data_startof_set ta p ) pl + | Interval _ -> WpLog.fatal "unexpected argument for [startof]" + + let data_startof ta ka ga = + match ka with + | Kset _ -> data_startof_set ta ga + | _ -> Loc( M.startof (loc_of_data ta ga) ta ) + + let rec data_load env ty = function + | Loc _ | Data _ | Value _ as d -> + let obj = object_of ty in + Value (M.load (mem_at_env env) obj (loc_of_data obj d)) + | Range _ -> + Wp_parameters.not_yet_implemented "load of arbitrary region" + | Set _ -> + Wp_parameters.not_yet_implemented "load of arbitrary sets" + | List pl -> union_map (data_load env ty) pl + | _ -> WpLog.fatal "unexpected argument for [load]" + + + (* ---------------------------------------------------------------------- *) + (* --- Offsets inside functional memory model --- *) + (* ---------------------------------------------------------------------- *) + + let rec logic_offset env a = function + | TNoOffset -> Data a + | TField(f,off) -> + let fieldvalue = F.acc_field (F.unwrap a) f in + logic_offset env fieldvalue off + | TIndex (t,off) -> + let i = integer_of_data (kind_of t.term_type) (!data_rec env t) in + logic_offset env (F.acc_index (F.unwrap a) i) off + + let rec loc_offset env loc ty = function + | TNoOffset -> loc + | TField(f,off) -> + loc_offset env (M.field loc f) (Ctypes.object_of f.ftype) off + | TIndex(t,off) -> + let k = integer_of_data (kind_of t.term_type) (!data_rec env t) in + let te = Ctypes.object_of_array_elem ty in + loc_offset env (M.index loc te k) te off + + (* ---------------------------------------------------------------------- *) + (* --- Offsets in the C-memory model --- *) + (* ---------------------------------------------------------------------- *) + + let rec memory_offset env ty (dp:data) = function + | TNoOffset -> ty,dp + | TIndex(t,off) -> + let kp = kind_of_data ty dp in + let ki = kind_of t.term_type in + let di = !data_rec env t in + let te = Cil.typeOf_array_elem ty in + let ta = object_of te in + let dq = data_index ta kp dp ki di in + memory_offset env te dq off + | TField(f,off) as offset -> + (match dp with + | Range _ | Set _ | List _ -> + Datalib.Collector.add_warning + ~reason:"field access over set of l-values" + "Ignored offset '%a' in assign clause" + !Ast_printer.d_term_offset offset ; + ty, dp + | dp -> + let dq = data_field (kind_of_typ ty) dp f in + memory_offset env f.ftype dq off ) + + let gaddress_of_cvar tenv x off : (typ * data) = + let tenv = + if tenv.formals_in_pre && x.vformal + then (env_at tenv Pre) else tenv + in + memory_offset tenv x.vtype (Loc (M.cvar (mem_at_env tenv) x)) off + + + let gaddress_of_ref tenv lv off : data = + let loc = M.lvar (mem_at_env tenv) lv (addr_of_ref tenv lv) in + match lv.lv_type with + | Ctype ty -> + let tr,gloc = memory_offset tenv ty (Loc loc) off in + data_load tenv tr gloc + | ty -> + begin + match off with + | TNoOffset -> Loc loc + | _ -> + let s = "[gaddress_of_ref] C offset of logic_var" in + WpLog.fatal "%s %a with a pure logic type %a" + s !Ast_printer.d_logic_var lv + !Ast_printer.d_logic_type ty + end + + + + + let gaddress_of_mem tenv e off : (typ * data) = + let g = !data_rec tenv e in + let te = + match kind_of e.term_type with + | Kptr telt -> telt + | Kset(Kptr telt) -> telt + | _ -> WpLog.fatal "expected pointer" + in + memory_offset tenv te g off + + let gstartof (ty,g) = + let te = Cil.typeOf_array_elem ty in + let ta = object_of te in + data_startof ta (kind_of_typ ty) g + + let gstartof_cvar env x off = + gstartof (gaddress_of_cvar env x off) + + let gstartof_mem env e off = + gstartof (gaddress_of_mem env e off) + + let gstartof_value env ty v off = + gstartof (memory_offset env ty (Value v) off) + + (* ---------------------------------------------------------------------- *) + (* --- Arithmetics Cast --- *) + (* ---------------------------------------------------------------------- *) + + let cast v ty_from ty_to = + if kind_equal ty_from ty_to then v + else + match ty_from with + | Kcint i -> + let vi = integer_of_data ty_from v in + begin match ty_to with + | Kcint j -> + if Ctypes.sub_c_int i j then v + else + Value (M.V_int(j,F.modulo j vi)) + | Kint -> Data(F.wrap vi) + | Kreal -> Data(F.wrap (F.real_of_integer vi)) + | Kptr te -> Loc (M.cast_int_to_loc i vi te) + | k -> WpLog.not_yet_implemented "logic cast from %a to %a" + Ctypes.pp_int i pp_kind k + end + | Kint -> + let vi = integer_of_data ty_from v in + begin match ty_to with + | Kcint j -> Value (M.V_int(j,F.modulo j vi)) + | Kint -> Data(F.wrap vi) + | Kptr te -> Loc (M.cast_int_to_loc (Ctypes.c_ptr()) vi te) + | Kreal -> Data(F.wrap (F.real_of_integer vi)) + | k -> WpLog.not_yet_implemented + "logic cast from integer to %a" pp_kind k + end + | Kreal -> + let vr = real_of_data ty_from v in + begin match ty_to with + | Kcint j -> Value(M.V_int(j,F.modulo j + (F.integer_of_real vr))) + | Kint -> Data(F.wrap (F.integer_of_real vr)) + | Kreal -> Data(F.wrap vr) + | k -> WpLog.not_yet_implemented + "logic cast from real to %a" pp_kind k + end + | Kptr tfrom -> + let loc = loc_of_data (object_of tfrom) v in + begin match ty_to with + | Kcint j -> Value (M.V_int(j, M.cast_loc_to_int tfrom loc j)) + | Kptr tto -> Loc (M.cast_loc_to_loc tfrom tto loc) + | k -> WpLog.not_yet_implemented + "logic cast from pointer over %a to %a" + !Ast_printer.d_type tfrom pp_kind k + end + | k -> WpLog.not_yet_implemented "logic cast from %a to %a" + pp_kind k pp_kind ty_to + + + (* ---------------------------------------------------------------------- *) + (* --- Binary Operators --- *) + (* ---------------------------------------------------------------------- *) + + let int_op = function + | PlusA -> F.e_iop Formula.Iadd + | MinusA -> F.e_iop Formula.Isub + | Mult -> F.e_iop Formula.Imul + | Div -> F.e_iop Formula.Idiv + | Mod -> F.e_iop Formula.Imod + | BAnd -> F.e_band + | BXor -> F.e_bxor + | BOr -> F.e_bor + | Shiftlt -> F.e_lshift + | Shiftrt -> F.e_rshift + | _ -> WpLog.fatal "[int_op] non integer operator" + + let real_op = function + | PlusA -> F.e_rop Formula.Radd + | MinusA -> F.e_rop Formula.Rsub + | Mult -> F.e_rop Formula.Rmul + | Div -> F.e_rop Formula.Rdiv + | _ -> WpLog.fatal "[real_op] non real operator" + + let rel_op = function + | Rlt -> Lt + | Rgt -> Gt + | Rle -> Le + | Rge -> Ge + | Req -> Eq + | Rneq -> Ne + + let real_cmp op r1 r2 = + match op with + | Lt -> F.e_rcmp Formula.Clt r1 r2 + | Gt -> F.e_rcmp Formula.Clt r2 r1 + | Le -> F.e_rcmp Formula.Cleq r1 r2 + | Ge -> F.e_rcmp Formula.Cleq r2 r1 + | Eq -> F.e_rcmp Formula.Ceq r1 r2 + | Ne -> F.e_rcmp Formula.Cneq r1 r2 + | _ -> WpLog.fatal "[real_cmp] non real comparator" + + let int_cmp op i1 i2 = + match op with + | Lt -> F.e_icmp Formula.Clt i1 i2 + | Gt -> F.e_icmp Formula.Clt i2 i1 + | Le -> F.e_icmp Formula.Cleq i1 i2 + | Ge -> F.e_icmp Formula.Cleq i2 i1 + | Eq -> F.e_icmp Formula.Ceq i1 i2 + | Ne -> F.e_icmp Formula.Cneq i1 i2 + | _ -> WpLog.fatal "[int_cmp] non intger comparator" + + let preal_cmp op r1 r2 = + match op with + | Lt -> F.p_rcmp Formula.Clt r1 r2 + | Gt -> F.p_rcmp Formula.Clt r2 r1 + | Le -> F.p_rcmp Formula.Cleq r1 r2 + | Ge -> F.p_rcmp Formula.Cleq r2 r1 + | Eq -> F.p_rcmp Formula.Ceq r1 r2 + | Ne -> F.p_rcmp Formula.Cneq r1 r2 + | _ -> WpLog.fatal "[preal_cmp] non real relation" + + let pint_cmp op i1 i2 = + match op with + | Lt -> F.p_icmp Formula.Clt i1 i2 + | Gt -> F.p_icmp Formula.Clt i2 i1 + | Le -> F.p_icmp Formula.Cleq i1 i2 + | Ge -> F.p_icmp Formula.Cleq i2 i1 + | Eq -> F.p_icmp Formula.Ceq i1 i2 + | Ne -> F.p_icmp Formula.Cneq i1 i2 + | _ -> WpLog.fatal "[pint_cmp] non integer relation" + + let ptr_rel op l1 l2 = + match op with + | Lt -> M.lt_loc l1 l2 + | Gt -> M.lt_loc l2 l1 + | Le -> M.le_loc l1 l2 + | Ge -> M.le_loc l2 l1 + | Eq -> M.equal_loc l1 l2 + | Ne -> F.p_not (M.equal_loc l1 l2) + | _ -> WpLog.fatal "[ptr_rel] non pointer relation" + + let ptr_cmp op l1 l2 = + match op with + | Lt -> M.lt_loc_bool l1 l2 + | Gt -> M.lt_loc_bool l2 l1 + | Le -> M.le_loc_bool l1 l2 + | Ge -> M.le_loc_bool l2 l1 + | Eq -> M.equal_loc_bool l1 l2 + | Ne -> F.e_not (M.equal_loc_bool l1 l2) + | _ -> WpLog.fatal "[ptr_cmp] non pointer comparator" + + let plus i j = F.e_iop Formula.Iadd i j + + let plus_interval r i = + match r.F.inf , r.F.sup with + | None , None -> r + | Some j, None -> {F.inf = Some (plus i j ); F.sup = None} + | None, Some k -> {F.inf = None ; F.sup = Some (plus i k)} + | Some j, Some k -> {F.inf = Some (plus i j );F.sup = Some (plus i k)} + + let plus_interval_interval a b = + match a , b with + | ({ F.sup=None ; F.inf=None } as top) , _ + | _ , ({ F.sup=None ; F.inf=None } as top) -> Interval top + | _ -> Set (F.add_set (F.interval a) (F.interval b)) + + + let rec add_integer ka ga kb gb = + match ga,gb with + | Set _ , _ | _ , Set _ -> Set (F.add_set (set_of ga) (set_of gb)) + | (Value _ | Data _), (Value _ | Data _) -> + data_of_integer (plus (integer_of_data ka ga) (integer_of_data kb gb)) + | Interval r1 , Interval r2 ->plus_interval_interval r1 r2 + | (Value _ | Data _ ),Interval r -> + Interval (plus_interval r (integer_of_data ka ga)) + | Interval r,(Value _ | Data _ ) -> + Interval (plus_interval r (integer_of_data kb gb)) + | List _ , List _ -> Set (F.add_set (set_of ga) (set_of gb)) + | List ds , b -> union_map (add_integer kb b ka) ds + | b , List ds -> union_map (add_integer ka b kb) ds + | _ -> WpLog.fatal "unsuitable arguments for integer addition" + + let data_cmp binop ka ga kb gb = + match ka,kb with + |( Kint | Kcint _) , (Kint| Kcint _) -> + int_cmp binop (integer_of_data ka ga) (integer_of_data kb gb) + | (Kreal|Kint| Kcint _) , (Kreal|Kint| Kcint _) -> + real_cmp binop (real_of_data ka ga) (real_of_data kb gb) + | Kptr ty , Kptr _ -> + let obj = object_of ty in + ptr_cmp binop (loc_of_data obj ga) (loc_of_data obj gb) + | _ -> + Wp_error.not_yet_implemented + "boolean comparison between %a and %a" + pp_kind ka pp_kind kb + + let data_binop kr binop ka ga kb gb = + match binop with + + (* pointer arithmetics *) + + | (IndexPI | PlusPI) -> data_shift ka ga kb gb ~is_pos:true + | MinusPI -> data_shift ka ga kb gb ~is_pos:false + | MinusPP -> + begin + match ka with + | Kptr te -> + let obj = object_of te in + data_of_integer + (M.minus_loc (loc_of_data obj ga) (loc_of_data obj gb)) + | _ -> WpLog.fatal "wrong parameters for pointer arithmetics" + end + + (* scalar arithmetics *) + + | PlusA | MinusA | Mult | Div | Mod + | BAnd | BXor | BOr | Shiftlt | Shiftrt -> + begin + match kr with + | (Kint | Kcint _) -> data_of_integer + (int_op binop + (integer_of_data ka ga) (integer_of_data kb gb)) + | Kreal -> data_of_real + (real_op binop (real_of_data ka ga) (real_of_data kb gb)) + | (Kset Kint |Kset (Kcint _)) when binop = PlusA -> + add_integer ka ga kb gb + | _ -> WpLog.fatal "wrong parameters for scalar arithmetics" + end + + (* comparisons *) + | Eq | Ne | Gt | Ge | Lt | Le -> + data_of_boolean (data_cmp binop ka ga kb gb) + + (*logic or *) + | LOr -> + data_of_boolean (F.e_or (boolean_of_data ga) (boolean_of_data gb)) + + (* logic and *) + | LAnd -> + data_of_boolean (F.e_and (boolean_of_data ga) (boolean_of_data gb)) + + (* ------------------------------------------------------------------------ *) + (* --- Unary Operators --- *) + (* ------------------------------------------------------------------------ *) + + let data_unop kr unop ka ga = + match unop with + | Neg -> + begin + match kr with + | (Kint | Kcint _) -> + data_of_integer (F.e_ineg (integer_of_data ka ga)) + | Kreal -> data_of_real (F.e_rneg (real_of_data ka ga)) + | _ -> WpLog.fatal + "wrong type of parameter for negation operator" + end + | LNot -> + let b = + match kr with + |(Kint | Kcint _)-> + F.e_icmp Ceq (integer_of_data ka ga) (F.e_icst "0") + |Kreal -> F.e_rcmp Ceq (real_of_data ka ga) (F.e_rcst "0.0") + |Kptr ty -> + let obj = object_of ty in + M.is_null (loc_of_data obj ga) + | Kbool -> + F.e_not (boolean_of_data ga) + | k -> WpLog.fatal + "%a : wrong type of parameter for logic not operator" pp_kind k + in data_of_boolean b + | BNot -> + begin + match kr with + | (Kint | Kcint _) -> + data_of_integer (F.e_bnot (integer_of_data ka ga)) + | _ -> WpLog.fatal + "wrong type of parameter for bitwise not operator" + end + + (* ------------------------------------------------------------------------ *) + (* --- Constants --- *) + (* ------------------------------------------------------------------------ *) + + let data_const = function + | CInt64(k,_,_) -> + data_of_integer (F.e_icst (My_bigint.to_string k)) + + | CChr c -> + data_of_integer (F.e_icst (Int64.to_string (Ctypes.char c))) + + | CReal(f,_,_) -> + data_of_real (F.e_rcst (string_of_float f)) + + | CEnum e -> + let machdep = true in + let e' = Cil.constFold machdep e.eival in + begin + match e'.enode with + | Const CInt64(k,_,_) -> + data_of_integer (F.e_icst (My_bigint.to_string k)) + | Const CChr c -> + data_of_integer (F.e_icst (string_of_int (Char.code c))) + | _ -> WpLog.fatal "unrecognized sizeof/alignof " + end + | CWStr _ -> + WpLog.not_yet_implemented "wide character string constant" + | CStr s -> + WpLog.not_yet_implemented "character string constant (%S)" s + + (* ------------------------------------------------------------------------ *) + (* --- Terms --- *) + (* ------------------------------------------------------------------------ *) + + let rec data_of_term env term = + match term.term_node with + + (* Constants *) + | TConst c -> data_const c + + (* Operators *) + + | TUnOp (unop,a) -> + data_unop (kind_of term.term_type) unop + (kind_of a.term_type) (data_of_term env a) + + | TBinOp(binop,a,b) -> + data_binop + (kind_of term.term_type) binop + (kind_of a.term_type) (data_of_term env a) + (kind_of b.term_type) (data_of_term env b) + + (* L-Values *) + + | TLval(TResult _ ,off) -> + logic_offset env (F.var(result env.frame)) off + + | TLval (TVar{lv_name = "\\exit_status"},_) -> + Data (F.var (status env.frame)) + + | TLval (TVar lv,off) -> + begin + match lvar env lv with + | Logic_cvar x -> + let tr,gloc = gaddress_of_cvar env x off in + data_load env tr gloc + | Logic_value (M.V_pointer(ty,loc)) -> + Loc (loc_offset env loc ty off) + | Logic_value v -> + let t = M.logic_of_value v in + logic_offset env t off + | Logic_term t -> + logic_offset env t off + | Logic_var x -> logic_offset env (F.var x) off + | Logic_byref -> gaddress_of_ref env lv off + end + + | TLval(TMem e,off) -> + let tr,gloc = gaddress_of_mem env e off in + data_load env tr gloc + + | TAddrOf(TVar{lv_origin=Some x},off) -> + begin + match xvar env x with + | None -> snd (gaddress_of_cvar env x off) + | Some v -> snd (memory_offset env x.vtype (Value v) off) + end + + | TStartOf(TVar{lv_origin=Some x},off) -> + begin + match xvar env x with + | None -> gstartof_cvar env x off + | Some v -> gstartof_value env x.vtype v off + end + + | TAddrOf(TMem e,off) -> + snd (gaddress_of_mem env e off) + | TStartOf(TMem e,off) -> + gstartof_mem env e off + + | TAddrOf(TResult _,_) + | TStartOf(TResult _,_) -> WpLog.not_yet_implemented "&\\result" + + | TAddrOf(TVar {lv_origin=None},_) -> + WpLog.fatal "taking address of a logic variable" + + | TStartOf(TVar {lv_origin=None},_) -> + WpLog.not_yet_implemented "reference to a logic array" + + (* At *) + + | Tat(t,label) -> data_of_term (env_at env (c_label label)) t + + (* Sizeof and alignment *) + + | TSizeOf _ + | TSizeOfE _ + | TSizeOfStr _ + | TAlignOf _ + | TAlignOfE _ -> + let machdep = true in + let e' = Cil.constFoldTerm machdep term in + begin + match e'.term_node with + | TConst _ -> data_of_term env e' + | _ -> WpLog.fatal "unrecognized sizeof/alignof (%a)" + !Ast_printer.d_term term + end + + (* Conditional *) + + | Tif (b, t, f) -> + Data + (F.e_cond (boolean_of_data (data_of_term env b)) + (term_of_data (data_of_term env t)) + (term_of_data (data_of_term env f))) + + (* Memory call *) + + | Tbase_addr t -> + let obj = match t.term_type with + | Ctype ty -> object_of ty + | _ -> WpLog.fatal "Base-address of logic type object" + in + Loc (M.base_address + (mem_at_env env) + (loc_of_data obj (data_of_term env t))) + + | Tblock_length t -> + let obj = match t.term_type with + | Ctype ty -> object_of ty + | _ -> WpLog.fatal "Block-length of logic type object" + in + data_of_integer + (M.block_length + (mem_at_env env) + (loc_of_data obj (data_of_term env t))) + + (* Range *) + + | Trange (ti,tj ) -> + let option_int env = function + | None -> None + | Some x -> Some (integer_of_data (kind_of x.term_type) + (data_of_term env x)) + in + let r = {F.inf =(option_int env ti); + F.sup =(option_int env tj)} in + Interval r + + | Tempty_set -> List [] + + | Tunion xs -> union_map (data_of_term env) xs + + + | Tinter(a::b) -> + Set (List.fold_left + (fun s1 s2 -> + F.inter s1 (set_of (data_of_term env s2))) + (set_of (data_of_term env a)) b) + + | Tinter [] -> WpLog.fatal "empty intersection" + + | Tcomprehension (_, _, _) -> + WpLog.not_yet_implemented "Set comprehension" + + (* Conversions *) + + | Tnull -> Loc M.null + + | TCastE (ty,t) -> + if Cil.isPointerType ty && Cil.isLogicZero t then + Loc M.null + else + cast (data_of_term env t) (kind_of t.term_type) (kind_of_typ ty) + + (* Logic ADT *) + + | TUpdate (_,TNoOffset,tv) -> + data_of_term env tv + + | TUpdate (r,TField (f, TNoOffset),tv) -> + begin + match kind_of (r.term_type) with + | Kstruct _ -> + let record = record_of_data (data_of_term env r) in + let v = term_of_data (data_of_term env tv) in + let r = F.upd_field record f v in + Data (F.wrap r) + + | _ -> + WpLog.fatal "Functional update of a non-record value" + end + + | TUpdate (r,TIndex(k, TNoOffset),tv) -> + begin + match kind_of (r.term_type) with + | Karray _ -> + let array = array_of_data (data_of_term env r) in + let idx = integer_of_data (kind_of k.term_type) + (data_of_term env k) in + let v = term_of_data (data_of_term env tv) in + let r = F.upd_index array idx v in + Data (F.wrap r) + + | _ -> + WpLog.fatal "Functional update of a non-array value" + end + + | TUpdate (_,_,_) -> + WpLog.not_yet_implemented "ACSL extension for functional update" + + | TDataCons({ctor_name="\\true"},[]) -> Data(F.wrap F.e_true) + | TDataCons({ctor_name="\\false"},[]) -> Data(F.wrap F.e_false) + + | TDataCons (c,_) -> + WpLog.not_yet_implemented "Constructor (%s)" c.ctor_name + + (* Jessie *) + | TCoerce (_,_) + | TCoerceE (_,_) -> + WpLog.fatal "Only produced by Jessie plugin" + + (* Type *) + + | Ttypeof _ + | Ttype _ -> + WpLog.not_yet_implemented "Type Tag" + + (* Let binding *) + + | Tlet (({l_var_info =x; + l_labels=[];l_tparams=[]; + l_profile =[];l_body=(LBterm t1); l_type=Some _ } as linfo),t2) -> + if Logic_env.Logic_builtin_used.mem linfo then + Wp_parameters.not_yet_implemented "Built-ins symbols" + else + let var,env2 = bind_fresh env x in + let t1' = term_of_data (data_of_term env t1) in + let t2' = term_of_data (data_of_term env2 t2) in + Data (F.e_subst L.alpha var t1' t2') + | Tlet _ -> + WpLog.not_yet_implemented + "Complex Let-binding" + + (* Logic-Function Call *) + + | Tapp (lfun,labels,args) -> + if Logic_env.Logic_builtin_used.mem lfun then + Wp_parameters.not_yet_implemented "Built-ins symbols" + else + Data (!rec_apply_function env lfun labels args) + + (* Higer order function *) + + | Tlambda (_,_) -> + WpLog.not_yet_implemented "Higher order functions" + + let () = data_rec := data_of_term + + let term env t = term_of_data (data_of_term env t) + + (* ------------------------------------------------------------------------ *) + (* --- Assignable --- *) + (* ------------------------------------------------------------------------ *) + + let rec data_of_assignable env t= + match t.term_node with + + | TLval (TVar{lv_origin=Some x}, off) -> + begin + match xvar env x with + | None -> snd (gaddress_of_cvar env x off) + | Some v -> Value v + end + + | TLval (TMem e, off) -> + snd (gaddress_of_mem env e off) + + | TStartOf (TVar{lv_origin=Some x}, off) -> + begin + match xvar env x with + | None -> gstartof_cvar env x off + | Some v -> gstartof_value env x.vtype v off + end + + | TStartOf (TMem e, off) -> gstartof_mem env e off + + | Tempty_set | TLval (TResult _, _ )-> List [] + + | Tat(t ,lab) -> data_of_assignable (env_at env (c_label lab)) t + + | TBinOp((IndexPI | PlusPI),a,b) -> + data_shift + (kind_of a.term_type) (data_of_term env a) + (kind_of b.term_type) (data_of_term env b) + ~is_pos:true + + | TBinOp (MinusPI,a,b) -> + data_shift + (kind_of a.term_type) (data_of_term env a) + (kind_of b.term_type) (data_of_term env b) + ~is_pos:false + + | Tunion ts -> union_map (data_of_assignable env) ts + | Tinter (t::ts) -> + let f t = set_of (data_of_assignable env t) in + Set(List.fold_left + (fun s t -> F.inter s (f t)) (f t) ts) + | Tinter [] -> WpLog.fatal "empty intersection" + + | TStartOf (TResult _, _ ) + | Tlet (_, _) | Tcomprehension (_, _, _) + | Tif (_, _, _) | Tapp (_, _, _) | TCastE (_, _) + + -> WpLog.not_yet_implemented "assignation of (%a)" + !Ast_printer.d_term t + + | TLval (TVar {lv_origin=None}, _) + | TAddrOf _ + | TStartOf (TVar {lv_origin=None}, _) + | Trange (_, _)|Ttype _|Ttypeof _|TCoerceE (_, _)|TCoerce (_, _) + | TUpdate (_, _, _)|Tblock_length _ + | TDataCons (_, _)|Tlambda (_, _) + | TUnOp (_, _)|TAlignOfE _|TAlignOf _|TSizeOfStr _|TSizeOfE _|TSizeOf _ + | TConst _ | Tnull | Tbase_addr _ + | TBinOp( + (LOr|LAnd|BOr|BXor|BAnd|Ne|Eq|Ge|Le|Gt|Lt| + Shiftrt|Shiftlt|Mod|Div|Mult| + MinusPP|MinusA|PlusA),_,_) + -> WpLog.fatal "not assignable terms" + + let assigned env t = + (* (ZD) DO preserve this filter, as \empty is polymorphic! *) + match t.term_node with + | Tempty_set | TLval (TResult _, _ ) -> [] + | _ -> + let data = data_of_assignable env t in + let te = + match t.term_type with + | Ctype te -> te + | Ltype( {lt_name="set"} , [Ctype elt] ) -> elt + | _ -> WpLog.fatal + "unexpected logic-type for assignable term %a" + !Ast_printer.d_logic_type t.term_type + in + assigned_of_data (object_of te) [] data + + (* ------------------------------------------------------------------------ *) + (* --- Properties --- *) + (* ------------------------------------------------------------------------ *) + + let rec_apply_predicate + : (env -> logic_info -> + (logic_label * logic_label) list -> term list -> F.pred) ref + = ref (fun _ _ _ _ -> assert false) + + let pred_cmp binop ka ga kb gb = + match ka,kb with + | (Kint | Kcint _) , (Kint | Kcint _) -> + pint_cmp binop (integer_of_data ka ga) (integer_of_data kb gb) + | (Kreal|Kint| Kcint _) , (Kreal|Kint| Kcint _) -> + preal_cmp binop (real_of_data ka ga) (real_of_data kb gb) + | Kptr ty , Kptr _ -> + let obj = object_of ty in + ptr_rel binop (loc_of_data obj ga) (loc_of_data obj gb) + | Kstruct s, Kstruct s' when (s.Cil_types.ckey=s'.Cil_types.ckey) -> + M.eq_record s (record_of_data ga) (record_of_data gb) + | Karray arr, Karray arr' when Ctypes.AinfoComparable.equal arr arr' -> + M.eq_array arr (array_of_data ga) (array_of_data gb) + | _ -> + begin + match binop with + | Eq -> F.p_eq (term_of_data ga) (term_of_data gb) + | Ne -> F.p_not (F.p_eq (term_of_data ga) (term_of_data gb)) + | _ -> WpLog.fatal ~current:true "Unexpected comparison" + end + + let rec prop env p = + List.fold_right F.p_named p.name (prop_body env p) + + and prop_body env p = + match p.content with + | Pfalse -> F.p_false + + | Ptrue -> F.p_true + + | Pand(p1,p2) -> + F.p_and (prop env p1)(prop env p2) + + | Por(p1,p2) -> + F.p_or (prop env p1)(prop env p2) + + | Pxor(p1,p2) -> + (*TODO : no primitive translation for XOR in WHY *) + (*Infact in bool.why there is bool_xor *) + F.p_xor(prop env p1)(prop env p2) + + | Pimplies(p1,p2) -> + F.p_implies(prop env p1)(prop env p2) + + | Piff(p1,p2)-> + F.p_iff(prop env p1)(prop env p2) + + | Pnot p -> F.p_not (prop env p) + + | Pif(c,pt,pf) -> + F.p_cond (F.unwrap (term env c)) + (prop env pt) + (prop env pf) + + | Pat (p,l) -> prop (env_at env (c_label l)) p + + | Prel ( rel ,t1,t2) -> + let ct1 = kind_of t1.term_type in + let ct2 = kind_of t2.term_type in + let m1 = data_of_term env t1 in + let m2 = data_of_term env t2 in + pred_cmp (rel_op rel) ct1 m1 ct2 m2 + + | Pvalid t -> + let k = kind_of t.term_type in + let d = data_of_term env t in + data_valid (mem_at_env env) k d + + | Pvalid_index(tp,ti) -> + let ty = match tp.term_type with + | Ctype te -> te + | _ -> WpLog.fatal "expected a non logic type" + in + let kp = kind_of_typ ty in + let ki = kind_of ti.term_type in + let dp = data_of_term env tp in + let di = data_of_term env ti in + if Cil.isArrayType ty then + let te = Cil.typeOf_array_elem ty in + let ta = object_of te in + let d = data_index ta kp dp ki di in + data_valid (mem_at_env env) kp d + else + if Cil.isPointerType ty then + let d = data_shift kp dp ki di ~is_pos:true in + data_valid (mem_at_env env) kp d + else WpLog.fatal "unexepected type for valid index" + + | Pvalid_range(b,l,h) -> + let tb = b.term_type in + let k = kind_of tb in + begin + match k with + | Kptr _ -> + let ty = typ_of_elements tb in + let obj = object_of ty in + let loc = loc_of_data obj (data_of_term env b) in + let rg = { + F.inf = Some (integer_of_data (kind_of l.term_type) + (data_of_term env l)); + F.sup = Some (integer_of_data (kind_of h.term_type) + (data_of_term env h)); + } in + M.valid (mem_at_env env) (F.Arange(obj,loc,rg)) + | _ -> WpLog.fatal "unsuitable argument for [valid_range]" + end + + | Pfresh _t -> WpLog.not_yet_implemented "fresh" + + | Pinitialized _t -> WpLog.not_yet_implemented "initialized" + + | Psubtype (_t1,_t2) -> WpLog.not_yet_implemented "subtype" + + | Plet(def, p) -> + begin + let lv = def.l_var_info in + match def.l_body, def.l_profile with + LBterm t, [] -> + let x = fresh_local lv in + L.subst x (term env t) + (prop (bind_lvar env lv (F.var x)) p) + | _ -> WpLog.not_yet_implemented "local binding" + end + + | Pforall (xs,p) -> + let freshes = List.map (fun x -> x , fresh_local x) xs in + let quantified = List.map snd freshes in + let assoc = List.map (fun (x,v) -> x,F.var v) freshes in + L.forall quantified (prop (bind_lvars env assoc) p) + + | Pexists (xs,p) -> + let freshes = List.map (fun x -> x , fresh_local x) xs in + let quantified = List.map snd freshes in + let assoc = List.map (fun (x,v) -> x,F.var v) freshes in + L.exists quantified (prop (bind_lvars env assoc) p) + + | Pseparated tl -> + let gs = + List.map + (fun t -> + let te = + match kind_of t.term_type with + | Kptr te -> te + | Kset (Kptr te) -> te + | k -> WpLog.fatal "separated on non pointer type : %a " pp_kind k + in + Ctypes.object_of te, data_of_term env t) tl in + let ags = Array.of_list gs in + let p = ref F.p_true in + let m = mem_at_env env in + for i=0 to Array.length ags - 2 do + for j=i+1 to Array.length ags - 1 do + p := F.p_and !p (data_separated m ags.(i) ags.(j)) + done + done ; + !p + + | Papp (predicate,labels,args) -> + if Logic_env.Logic_builtin_used.mem predicate then + Wp_parameters.not_yet_implemented "Built-ins symbol %a (%d)" + !Ast_printer.d_logic_var predicate.l_var_info predicate.l_var_info.lv_id + else + !rec_apply_predicate env predicate labels args + + + + + (* ------------------------------------------------------------------------ *) + (* --- Accessing User-Definitions --- *) + (* ------------------------------------------------------------------------ *) + + let get_definition cc fdef = + let xdef = fdef.l_var_info in + try Hdef.find user_definitions xdef + with Not_found -> + UserDefinition.lock xdef ; + try + let udef , items = cc fdef in + Hdef.add user_definitions xdef udef ; + UserDefinition.define udef items ; udef + with error -> + UserDefinition.unlock xdef ; raise error + + (* ----------------------------------------------------------------------- *) + (* --- Compilation of User-defined Predicate and Functions --- *) + (* ----------------------------------------------------------------------- *) + + let push_context where = + L.push where (F.pool()) L.closed + + let flush_context where context p = + L.flush where context p + + let kill_context where context = + L.kill where context + + let user_default_label = function + | [] -> Clabels.Here + | LogicLabel (None, first) :: _ -> Clabels.LabelParam first + | LogicLabel (Some _, _) :: _ -> + Wp_parameters.fatal + "Unexpected redefined labels in user-defined predicates" + | StmtLabel _ :: _ -> + Wp_parameters.fatal + "Unexpected stmt-labels in user-defined predicates" + + let user_env pdef = + let context = push_context "user" in + try + let frame = user_frame () in + let lvars = ref Logic_var.Map.empty in + let laddr = ref Logic_var.Map.empty in + let profile = List.map + (fun lv -> + if M.userdef_is_ref_param lv then + begin + lvars := Logic_var.Map.add lv Logic_byref !lvars ; + let opt_cx = + if M.userdef_ref_has_cvar lv + then + let x = fresh_addr lv in + laddr := Logic_var.Map.add lv x !laddr ; + Some x else None + in + UF_references ( lv ,opt_cx, [] ) (* initially empty *) + end + else + begin + let x = fresh_local lv in + lvars := Logic_var.Map.add lv (Logic_term (F.var x)) !lvars ; + UF_logic ( lv , x ) + end) + pdef.l_profile + in + let env = { + formals_in_pre = false ; + frame = frame ; + label = user_default_label pdef.l_labels ; + lvars = !lvars ; + xvars = Varinfo.Map.empty ; + laddr = !laddr; + } + in ( context , profile , env ) + with err -> + kill_context "user env" context; raise err + + let collect_signature profile filter env = + let closures = ref [] in + let references = ref Logic_var.Map.empty in + let get_refs lv refs = + try Logic_var.Map.find lv refs + with Not_found -> [] + in + Lmap.iter + (fun label mem -> + match label with + | LabelParam label -> + begin + (* Collecting reference parameters *) + List.iter + (fun (x,lv,formal) -> if filter x then + let refs = + (x,formal,label) :: (get_refs lv !references) in + references := Logic_var.Map.add lv refs !references) + (M.userdef_ref_signature mem) ; + (* Collecting memory parameters *) + List.iter + (fun (x,clos) -> if filter x then + closures := UF_closure(x,clos,label) :: !closures) + (M.userdef_mem_signature mem) ; + end + | _ -> ()) + env.frame.states ; + begin + List.rev !closures @ + List.map + (function + | (UF_logic _ | UF_closure _) as p -> p + | UF_references(lv,opt_cx,_) -> + UF_references(lv, opt_cx, List.rev (get_refs lv !references)) + ) profile + end + + (* WARNING: should be the same order of binding that apply_formals *) + let rec flatten_formals = function + | [] -> [] + | UF_logic(_,x)::ufs -> x :: flatten_formals ufs + | UF_closure(x,_,_)::ufs -> x :: flatten_formals ufs + | UF_references(_,None,refs)::ufs -> flatten_references refs ufs + | UF_references(_,Some x,refs)::ufs -> x :: flatten_references refs ufs + + and flatten_references refs ufs = + match refs with + | [] -> flatten_formals ufs + | (x,_,_)::refs -> x :: flatten_references refs ufs + + let all_filter (_:F.var) = true + let term_filter t x = F.term_has_var [x] t + let pred_filter p x = F.pred_has_var [x] p + + let compile_predicate pdef = + let o_name = Fol_decl.identifier (pdef.l_var_info.lv_name) in + let p_name = "D_" ^ o_name in + let d_name = "Def_" ^ o_name in + let context, profile, env = user_env pdef in + try + let body,filter = + match pdef.l_body with + | LBpred named -> + let v = prop env named in Some v , pred_filter v + | LBterm def -> + let v = term env def in Some (F.p_bool (F.unwrap v)) , term_filter v + | LBnone -> + Wp_parameters.warning ~once:true ~current:false + "No definition for '%s' interpreted as reads nothing" o_name ; + None , all_filter + | LBreads xs -> + (*TODO: Below is an incorrect translation (LC+BM) (Idem for "\from") + (LC) Reason : xs are to be interpreted as left-values. + (Use case : f reads t[0..n]) + let vs = List.map (fun x -> term env x.it_content) xs in + None,vs,[] + *) + Wp_parameters.warning ~once:true ~current:false + "Interpreting reads-definition as expressions rather than tsets" ; + List.iter (fun x -> ignore (term env x.it_content)) xs ; + None , all_filter + | LBinductive _ -> + Wp_parameters.not_yet_implemented "Inductive predicates" + in + let signature = collect_signature profile filter env in + let formals = flatten_formals signature in + let declaration = + p_name , Formula.Predicate(List.map F.tau_of_var formals) in + let definitions = + match body with + | None -> kill_context "compile" context ; [] + | Some body -> + let p_axiom = + L.forall formals + (F.p_iff + (F.p_call p_name (List.map F.var formals)) + (flush_context "compile" context body)) + in + [ d_name , Formula.Axiom p_axiom ] + in + { + d_info = pdef ; + d_callname = p_name ; + d_formals = signature ; + } , + declaration :: definitions + with err -> + kill_context "compile" context ; + raise err + + let compile_function fdef = + let o_name = Fol_decl.identifier (fdef.l_var_info.lv_name) in + let f_name = "D_" ^ o_name in + let d_name = "Def_" ^ o_name in + let context, profile, env = user_env fdef in + try + let body,filter = + match fdef.l_body with + | LBterm def -> + let v = term env def in Some v , term_filter v + | LBreads xs -> + (*TODO: Incorrect translation (Cf. predicates) + None,List.map (fun x -> term env x.it_content) xs + *) + Wp_parameters.warning ~once:true ~current:false + "Interpreting reads-definition as expressions rather than tsets" ; + List.iter (fun x -> ignore (term env x.it_content)) xs ; + None , all_filter + | LBnone -> + Wp_parameters.warning ~once:true ~current:false + "No definition for '%s' interpreted as reads nothing" o_name ; + None , all_filter + | LBinductive _ -> + Wp_parameters.fatal "Inductive function" + | LBpred _ -> + Wp_parameters.fatal "Function defined by a predicate" + in + let ltyp = + match fdef.l_type with + | Some ltyp -> ltyp + | None -> Wp_parameters.fatal "Function defined with not result type" + in + let t_result = M.tau_of_logic_type ltyp in + let signature = collect_signature profile filter env in + let formals = flatten_formals signature in + let declaration = + f_name , Formula.Function(List.map F.tau_of_var formals,t_result) in + let call_f = F.e_call f_name (List.map F.var formals) in + let definitions = + match body with + | None -> kill_context "compile" context ; [] + | Some def -> + let f_axiom = F.p_forall formals + (flush_context "compile" context (F.p_eq call_f def)) + in + [ d_name , Formula.Axiom f_axiom ] + in + let guards = + let cond = L.has_type call_f ltyp in + if F.is_true cond then [] + else [ f_name ^ "_result" , Formula.Axiom (L.forall formals cond) ] + in + { + d_info = fdef ; + d_callname = f_name ; + d_formals = signature ; + } , + declaration :: (definitions @ guards) + with err -> + kill_context "compile" context ; + raise err + + (* ----------------------------------------------------------------------- *) + (* --- Compilation of User-defined Axiom --- *) + (* ----------------------------------------------------------------------- *) + + let axiom_env here = + let frame = user_frame () in + let here = Clabels.LabelParam here (* Non-expected ! *) in + { + formals_in_pre = false ; + frame = frame ; + label = here ; + lvars = Logic_var.Map.empty ; + xvars = Varinfo.Map.empty ; + laddr = Logic_var.Map.empty ; + } + + let compile_user_axiom _name predicate = + let context = push_context "axiom" in + try + let env = axiom_env "WP_nowhere" in + let def = prop env predicate in + flush_context "axiom" context def + with err -> + kill_context "axiom" context ; + raise err + + let compile_user_axiom_labels name (labels,predicate) = + let d_name = "Hyp_" ^ name in + let context = push_context "axiom-labels" in + try + let here = + match labels with + | LogicLabel (None, l)::_ -> l + | _ -> Wp_parameters.fatal "No logic label for Axiom '%s'" name + in + let env = axiom_env here in + let body = prop env predicate in + let signature = collect_signature [] (pred_filter body) env in + let formals = flatten_formals signature in + let property = L.forall formals (flush_context "axiom-labels" context body) + in { + a_name = name ; + a_defname = d_name ; + a_memory = signature ; + a_property = property ; + } + with err -> + kill_context "axiom-labels" context ; + raise err + + let compile_and_define hdefs name data compiler definer = + let cdata = + try Hashtbl.find hdefs name with Not_found -> + try + let cdata = Some (compiler name data) in + Hashtbl.add hdefs name cdata ; cdata + with error -> + Hashtbl.add hdefs name None ; raise error + in match cdata with + | None -> () + | Some data -> definer name data + + let add_axiom name labels predicate = + if not (UserAxiomDefs.is_defined name) then + if labels = [] then + compile_and_define user_axioms name predicate + compile_user_axiom + (fun name _ -> UserAxiom.define name) + else + compile_and_define user_axiomlabels name (labels,predicate) + compile_user_axiom_labels + (fun _ axdef -> UserAxiomDefs.define axdef) + + (* ------------------------------------------------------------------------ *) + (* --- Applying Definitions --- *) + (* ------------------------------------------------------------------------ *) + + (* Binds formal parameters to their actual arguments *) + (* - ufs: user_formal list *) + (* - dargs: data list *) + (* - returns: F.abstract list *) + + (* WARNING: apply_formals must bind formals in the same way that + flatten_formals collect the formals *) + + let bool_of_option = function Some _ -> true | None -> false + + let rec apply_formals env labels ufs dargs = + let s = "[apply_formals]" in + match ufs , dargs with + | [] , [] -> [] + | [] , d :: _ -> + Wp_parameters.fatal + "WP.UserDefs: signature mismatch (args) to much args %a" + pp_data d ; + | UF_logic (lv,_) :: ufs_tail , data :: dargs_tail -> + debug "%s : %a binds to %a, ufs_tail:%d, darg_tail:%d" + s !Ast_printer.d_logic_var lv pp_data data + (List.length ufs_tail) (List.length dargs_tail); + term_of_data data :: apply_formals env labels ufs_tail dargs_tail + | UF_logic (lv,_) :: _ , [] -> + Wp_parameters.fatal + "WP.UserDefs: signature mismatch (args) %a have no value" + !Ast_printer.d_logic_var lv; + | UF_closure(_,closure,at) :: ufs_tail , _ -> + let label = Clabels.lookup labels at in + let mem = mem_at env label in + let varg = M.userdef_mem_apply mem closure in + varg :: apply_formals env labels ufs_tail dargs + + | UF_references(_,_,_)::_ , [] -> + Wp_parameters.fatal "WP.UserDefs: signature mismatch (refs)" + + | UF_references(_,None,refs)::ufs_tail , data::dargs -> + apply_references env labels refs data ufs_tail dargs + + | UF_references(_,Some _,refs)::ufs_tail , data::dargs -> + let loc = + match data with + | Value(M.V_pointer(_,loc)) -> loc + | Loc loc -> loc + | _ -> Wp_parameters.fatal "WP.UserDefs: no reference found" + in + let inner_loc = M.inner_loc loc in + debug "%s the location of %a : %a the C loc : %a" s + pp_data data M.pp_loc loc F.pp_term inner_loc; + + inner_loc :: apply_references env labels refs data ufs_tail dargs + + + and apply_references env labels refs data ufs dargs = + match refs with + | [] -> apply_formals env labels ufs dargs + + | (_,formal,at) :: refs_tail -> + let loc = + match data with + | Value(M.V_pointer(_,loc)) -> loc + | Loc loc -> loc + | _ -> Wp_parameters.fatal "WP.UserDefs: no reference found" + in + let label = Clabels.lookup labels at in + let mem = mem_at env label in + let value = M.logic_of_value (M.userdef_ref_apply mem formal loc) in + value :: apply_references env labels refs_tail data ufs dargs + + let apply_predicate env def labels args = + let definition = get_definition compile_predicate def in + let arguments = List.map (data_of_term env) args in + let bindings = apply_formals env labels definition.d_formals arguments in + F.p_call definition.d_callname bindings + + let apply_function env def labels args = + let definition = get_definition compile_function def in + let arguments = List.map (data_of_term env) args in + let bindings = apply_formals env labels definition.d_formals arguments in + F.e_call definition.d_callname bindings + + let () = + begin + rec_apply_predicate := apply_predicate ; + rec_apply_function := apply_function ; + end + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/translate_prop.mli frama-c-20111001+nitrogen+dfsg/src/wp/translate_prop.mli --- frama-c-20110201+carbon+dfsg/src/wp/translate_prop.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/translate_prop.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,93 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(* --- Translation of Term and Predicates --- *) +(* ------------------------------------------------------------------------ *) + +open Ctypes +open Clabels +open Formula +open Cil_types + +module Create + (M : Mlogic.S) + + : +sig + + (** {2 Translation environments} *) + + type env + + val env: Kernel_function.t -> + ?m_here:M.mem -> + ?m_pre:M.mem -> + ?m_post:M.mem -> + ?x_result:M.F.var -> + unit -> env + + val env_at : env -> c_label -> env + val mem_at : env -> c_label -> M.mem + val find_mem : env -> c_label -> M.mem option + val subst_result : env -> M.value option -> M.F.pred -> M.F.pred + val result_type : env -> typ + val exit_status : env -> M.F.var + val call_pre : env -> Kernel_function.t -> M.value list -> M.mem -> env + + val call_post : + env -> Kernel_function.t -> M.value list -> M.mem -> M.mem -> + M.F.var option -> env + + val call_exit : + env -> Kernel_function.t -> M.value list -> M.mem -> M.mem -> + M.F.var -> env + + (** {2 Translation functions} *) + + (** to be used to retreive variable add through [add_logic_vars]. *) + val collect_logic_vars : env -> M.F.var list + val add_logic_vars : env -> M.F.pool -> logic_var list -> env + + (** [term e t] interprets the C terms [t] in memory model environment [e] + as a logic term.**) + val term : env -> term -> M.F.abstract + + (** [prop e p] interprets an ACSL predicate as a logic predicats + in memory model environment [e]. **) + val prop : env -> predicate named -> M.F.pred + + (** Compiles an arbitrary term representing a set of left-values into a zone *) + val assigned : env -> Cil_types.term -> M.loc M.F.assigned list + + (** {2 Axiomatics management} *) + + (** Compile an axiom and add it to the list of global declarations. *) + val add_axiom : string -> Cil_types.logic_label list -> Cil_types.predicate named -> unit + +end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/variables_analysis.ml frama-c-20111001+nitrogen+dfsg/src/wp/variables_analysis.ml --- frama-c-20110201+carbon+dfsg/src/wp/variables_analysis.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/variables_analysis.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,2159 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* + This analysis performs a classification of the variables of the input + program. The aim of this classification is to optimize the translation + of variables by WP: + 1) optimization of the by-reference call and + 2) functional variables. +*) + +open Cil_types +open Cil + +let dkey = "var_analysis" (* debugging key*) + +let debug = Wp_parameters.debug ~dkey + +let dkey = "var_kind" + +let oracle = Wp_parameters.debug ~dkey + +(* -------------------------------------------------------------------------- *) +(* --- Variable Analysis --- *) +(* -------------------------------------------------------------------------- *) + + +(* + At the end, the analysis associates an [var_kind] information to each + variables: + 1) [Fvar] functional variable, variable such as its address is never + taken, + + 2) [PRarg] by_pointer_reference argument, variable such as its + address is only taken in by reference calls (one or more), + + 3) [ARarg] by_array_reference argument, variable such as its + address is only taken in by array reference calls (one or more), + + 4) [PRpar n] by_pointer_reference parameter of arity , + variable which is a formal parameter use for a by reference call + and can be invoked in a chain of by reference call such as their + arity are less or equal than n, + + 5) [ARpar n] by_array_reference parameter of arity , + variable which is a formal parameter use for a by array reference + call and can be invoked in a chain of by array reference call + such as their arity are less or equal than n, + + 6) [Cvar] other variable. + +*) + +type var_kind = + Fvar | Cvar | PRarg | ARarg | PRpar of int | ARpar of int + + +(**********************************************************************) +(*** I - By reference call optimisation. ****) +(**********************************************************************) + +(* + A by pointer reference call is characterized by 2 facts : + 1p) the formal parameters [p] is of pointer type [*..<n>..*t], + p always occurs with <n>*:[<n>* p] except in call. + As call argument, + p can occurs with less than <n>*: [<k>*p], k<=n in case of + by pointer reference call (ie. if p has the characteristic of a + by pointer reference argument.) + + 2p) the by pointer reference argument [x] is a variable which + is not a formal parameter and which appears as argument + to the match place of a by pointer reference parameter, in one or + more of those patterns [by_pref_pattern]: + - &x+offset + - x+i with x of pointer type and + as +PI. + - *<n>x, n <= stars(typ(x)) + + A by array reference call is characterized by 2 facts : + 1a) the formal parameters [p] is of pointer type [*..<n>..*t], + p always occurs with <n> indexes:[p<n>[i]] except in call. + As call argument, + p can occurs with less than <n> indexes: [p<k>[i]], k<=n in case of + by array reference call (ie. if p has the characteristic of a + by array reference argument.) + + 2a) the by array reference argument [x] is a variable which + is not a formal parameter and which appears as argument + to the match place of a by pointer reference parameter, in one or + more of those patterns [by_array_reference_pattern]: + - x+offset (StarOf) + - x<k>[], k <= bracket(typ(x)) . + - &(x+i) + ==+PI +*) + + + +(**********************************************************************) +(*** Helper section with some smart constructors for ***) +(*** patterns identifications ***) +(**********************************************************************) + +(* [stars_typ typ] accounts the number of * if typ is a pointer type.*) +let rec stars_typ typ = + match Cil.unrollType typ with + | TPtr (typ,_) -> 1+ stars_typ (Cil.unrollType typ) + | TInt(_,_) | TFloat(_,_) | TFun _ | TEnum (_,_) | TComp (_,_,_) + | TArray (_,_,_,_) | TBuiltin_va_list _ | TVoid _ | TNamed _ -> 0 + +(* [bracket_typ typ] accounts the number of [dim] if typ is an array + type. *) +let rec brackets_typ typ = + match Cil.unrollType typ with + | TArray (typ,_,_,_) -> 1+ brackets_typ (Cil.unrollType typ) + | TInt(_,_) | TFloat(_,_) | TFun _ | TEnum (_,_) | TComp (_,_,_) + | TPtr (_,_) | TBuiltin_va_list _ | TVoid _ | TNamed _ -> 0 + + +(* [bracket_and_stars_typ typ] accounts the number of [dim] and the number of + pointer if typ is a pointer on array type. *) +let brackets_and_stars_typ typ = + let rec stars_and_elt typ = + match Cil.unrollType typ with + | TPtr (typ,_) -> + let (n,t) = stars_and_elt (Cil.unrollType typ) in + (n+1),t + | TInt(_,_) | TFloat(_,_) | TFun _ | TEnum (_,_) | TComp (_,_,_) + | TArray (_,_,_,_) + | TBuiltin_va_list _ | TVoid _ | TNamed _ as t-> (0,t) + in + let (n,t) = stars_and_elt typ in n+brackets_typ t + +(* [stars_lv_typ] same as stars_typ on logic_type*) +let stars_lv_typ = function | Ctype t -> stars_typ t | _ -> 0 + +(* [brackets_lv_typ] same as brackets_typ on logic_type*) +let brackets_lv_typ = function | Ctype t -> brackets_typ t | _ -> 0 + +let brackets_and_stars_lv_typ = + function | Ctype t -> brackets_and_stars_typ t | _ -> 0 + + + +(* [stars_exp e] returns Some (x,ty,n) if e == <n>* x and ty is the type of the + entire inner lval else returns none. *) +let rec stars_exp = function + | Lval (Var x,off ) -> Some(x,Cil.typeOfLval (Var x,off),0) + | Lval (Mem e, _) -> + (match stars_exp (Cil.stripInfo e).enode with + | None -> None + | Some (x,ty,n) -> Some (x, ty ,n+1)) + | _ -> None + + +(* [stars_term t] returns Some (x,ty,n) if t == <n>* x and ty is the + type of the entire inner lval else returns none. *) +let rec stars_term = function + | TLval (TVar lvar,off ) + | Tat ({term_node = + TLval (TVar lvar,off )}, _ ) -> + Some(lvar,(Cil.typeOfTermLval(TVar lvar,off ) ),0) + | TLval (TMem t,_ ) + | Tat ({term_node = + TLval (TMem t,_)}, _ ) -> + (match stars_term t.term_node with + | None -> None + | Some (x,ty,n) -> Some (x,ty,n+1)) + | _ -> None + +(* [brackets_off off] returns Some n if off == <n>[] else returns none. *) +let rec brackets_off = function + | Index (_,off) -> + (match brackets_off off with + | Some n ->Some (1+n) + | None -> None ) + | NoOffset -> Some 0 + | _ -> None + +(* [brackets_toff off] returns Some n if off == <n>[] else returns none. *) +let rec brackets_toff = function + | TIndex(_,toff) -> + (match brackets_toff toff with + | Some n ->Some (1+n) + | None -> None ) + | TNoOffset -> Some 0 + | _ -> None + +(* [bracket_exp e] returns Some(x,n) if e == x<n>[] else returns none*) +let bracket_exp = function + | Lval (Var x,off) -> + (match brackets_off off with + | Some n -> Some(x,n) + | None -> None) + | _ -> None + +(* [bracket_term t] returns Some(x,n) if t == x<n>[] else returns none*) +let bracket_term = function + | TLval (TVar x,off) + | Tat ({term_node = + TLval (TVar x,off)}, _ ) -> + (match brackets_toff off with + | Some n -> Some(x,n) + | None -> None) + | _ -> None + +(* [delta_ptr e] returns Some x if e == x+i and x has pointer type + returns None *) +let delta_ptr = function + | BinOp ((PlusPI|MinusPI), + {enode = Lval (Var x,off)},_ , _ ) -> + Some (x, stars_typ (Cil.typeOfLval (Var x,off))) + | _ -> None + +(* variante of delta_ptr on term; takes care of labelled term *) +let delta_ptr_term = function + | TBinOp((PlusPI|MinusPI),{term_node = TLval (TVar lvar,off)},_) + | Tat + ({term_node = + TBinOp((PlusPI|MinusPI),{term_node = TLval (TVar lvar,off)},_) + },_) + | TLval (TMem + {term_node = + Tat + ({term_node = + TBinOp((PlusPI|MinusPI), + {term_node = TLval (TVar lvar,off)},_) + },_)},_) + | TLval (TMem + {term_node = + TBinOp((PlusPI|MinusPI), + {term_node = Tat({term_node = TLval (TVar lvar,off)},_)},_)},_) + | TLval (TMem + {term_node = + TBinOp((PlusPI|MinusPI), + {term_node = TLval (TVar lvar,off)},_)},_) + | TBinOp((PlusPI|MinusPI), + {term_node = + TLval (TMem + {term_node = + Tat({term_node = TLval (TVar lvar,off)},_)},_)},_) + + -> Some (lvar, stars_lv_typ (Cil.typeOfTermLval (TVar lvar,off))) + | _ -> None + +(* [delta_array e] returns Some x if e == x[i] and x has pointer type + else returns None *) +let delta_array = function + | BinOp (IndexPI,{enode = Lval (Var x,off)}, _ ,_) + -> Some (x, stars_typ (Cil.typeOfLval (Var x,off))) + | e -> debug "[delta_array] calls delta_ptr"; delta_ptr e + +let delta_array_term = function + | TBinOp(IndexPI,{term_node = TLval (TVar lvar,off)},_) + | Tat + ({term_node = TBinOp(IndexPI,{term_node = TLval (TVar lvar,off)},_) + },_) + | TLval (TMem + {term_node = + TBinOp(IndexPI,{term_node = TLval (TVar lvar,off)},_)} + , _) + | TLval (TMem + {term_node = Tat + ({term_node = TBinOp(IndexPI,{term_node = TLval (TVar lvar,off)},_) + },_)},_) + | TBinOp(IndexPI, + {term_node = + Tat({term_node = TLval (TVar lvar,off)},_)},_) + -> Some (lvar, stars_lv_typ (Cil.typeOfTermLval (TVar lvar,off))) + | t -> + debug "[delta_array_term] calls delta_ptr_term"; delta_ptr_term t + +(**********************************************************************) +(*** A - Identification of by reference formal parameters usage and ***) +(*** Identification of reference argument by usage. ***) +(*** and accounting of addresss taken of each variable ***) +(*** We also protect the translation of pure logic variables bound ***) +(*** by pforall and pexists. ***) +(**********************************************************************) +(* Table of logic parameters, parameters of logic functions and predicate. + The associated boolean is used to tagged the user parameters as + an argument of a ACSL builtin predicates or functions which + parameters are by reference: \valid and family, \block_length, + \separated, \initialized*) +module LogicParam = + State_builder.Hashtbl + (Cil_datatype.Logic_var.Hashtbl) + (Datatype.Bool) + (struct let name = "WP : logic parameters" + let dependencies = [Ast.self] + let kind = `Internal + let size = 40 + end) + +let logic_param_memory_info x = + debug "[LogicParam] %a" !Ast_printer.d_logic_var x; + if LogicParam.mem x then + (debug "[LogicParam] %a in " !Ast_printer.d_logic_var x; + LogicParam.replace x true) + else + (debug "[LogicParam] %a out"!Ast_printer.d_logic_var x;()) + +(* Type of ACSL Variable, C-variable or Logic Variable or Formal parameters + of builtin predicates/functions.*) +type var_type = + | Cv of varinfo (*C formal parameter*) + | Lv of logic_var (*Logic formal parameter*) + | Prop (*Parameter of valid or separated or initialized, + ie builtin predicate*) + +(* tests if a logic variable is a formal parameter.*) +let is_lformal = function + | {lv_origin = Some x} -> x.vformal + | lv -> LogicParam.mem lv + +(* according to a logicvar returns the more specified var_type*) +let var_type_of_lvar = function + |{lv_origin = Some x} -> Cv x + | l -> Lv l + +let pp_var_type fmt = function + | Cv x -> !Ast_printer.d_var fmt x + | Lv p -> !Ast_printer.d_logic_var fmt p + | Prop -> Format.pp_print_string fmt "Prop" + +let brackets_var_type_typ = function + | Cv x -> brackets_typ x.vtype + | Lv lv -> brackets_lv_typ lv.lv_type + | Prop -> 0 + +let brackets_and_stars_var_type_typ = function + | Cv x -> brackets_and_stars_typ x.vtype + | Lv lv -> brackets_and_stars_lv_typ lv.lv_type + | Prop -> 0 + +let stars_var_type_typ = function + | Cv x -> stars_typ x.vtype + | Lv lv -> stars_lv_typ lv.lv_type + | Prop -> 0 + +let isVarTypePointerType =function + | Cv x -> Cil.isPointerType x.vtype + | Lv lv -> Logic_utils.isLogicPointerType lv.lv_type + | Prop -> false + +let is_formal_var_type = function + | Cv x -> x.vformal + | Lv lv -> LogicParam.mem lv + | Prop -> false + + + +module VarType = + (Datatype.Make_with_collections + (struct + include Datatype.Undefined + let name = "WpVarType" + type t = var_type + let reprs = + let cp_repr = List.hd Cil_datatype.Varinfo.reprs in + let lp_repr = List.hd Cil_datatype.Logic_var.reprs in + [Cv cp_repr ; Lv lp_repr ; Prop] + let equal a b = + match a,b with + | Cv a, Cv b -> Cil_datatype.Varinfo.equal a b + | Lv a, Lv b -> Cil_datatype.Logic_var.equal a b + | Prop, Prop -> true + | _ , _ -> false + + let compare a b = + match a,b with + | Cv a, Cv b -> Cil_datatype.Varinfo.compare a b + | Cv _ , _ -> (-1) + | _ , Cv _ -> (1) + | Lv a, Lv b -> Cil_datatype.Logic_var.compare a b + | Prop , Prop -> 0 + | Lv _ , _ -> (-1) + | _ , Lv _ -> (1) + + let hash = function + | Cv v -> (Cil_datatype.Varinfo.hash v)*121 + | Lv p -> (Cil_datatype.Logic_var.hash p)*147 + | Prop -> 147 + end)) + +(*Table of other kind of variables *) +module AnyVar = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Unit) + (struct let name = "WP: argument multi pattern" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + +(* only used to records universally and existentially bound variables as + value variables. (ie. do not have to be optimized) *) +let add_logics_value l = + List.iter (fun lv -> AnyVar.replace (Lv lv) ()) l + + + + +(* Table of variables which addresses are taken. + Each variable [x] is associated to a pair of integer (plus,minus) such as + [plus] is the total occurences of address taken of [x] and + [minus] is the number of occurences of address taken of [x] in + a by reference pattern. *) +module AddrTaken = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Pair (Datatype.Int) (Datatype.Int)) + (struct let name = "WP: addr_taken" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + + +let string_addr b = if b then "address taken" else "not address taken" + +(*[incr_addr_taken var] adds [1] to the total occurences of address taken + of [var]*) +let incr_addr_taken var = + debug "[incr_addr] %a" pp_var_type var; + oracle "[incr_addr] %a" pp_var_type var; + let (n,r) = try AddrTaken.find var with Not_found -> (0,0) in + AddrTaken.replace var (n+1,r) + +(*[decr_addr_taken var] adds [1] to the numbre of occurences of + address taken of [var] in by reference pattern*) +let decr_addr_taken var = + debug "[decr_addr] %a" pp_var_type var; + oracle "[decr_addr] %a" pp_var_type var; + let (n,r) = try AddrTaken.find var with Not_found -> (0,0) in + AddrTaken.replace var (n,r+1) + +(* variant occurs only if [b] is true else do nothing *) +let decr_addr_taken_bool var b = if b then decr_addr_taken var + + + +(* Visitor which : + - collects the totale occurences of address taken ; + - collects all logic parameters ; + - collects all existentially and universally bound variables, as + variables which have not to be optimized. *) +class logic_parameters_and_addr_taken_collection : + Visitor.frama_c_visitor = object + inherit Visitor.frama_c_inplace + + method vexpr e = + match (Cil.stripInfo e).enode with + | StartOf (Var vinfo,_) + | AddrOf (Var vinfo,_) -> incr_addr_taken (Cv vinfo); DoChildren + | _ -> DoChildren + + method vterm t = + match t.term_node with + | TAddrOf(TVar lv,_) + | TStartOf(TVar lv,_) -> + incr_addr_taken (var_type_of_lvar lv); DoChildren + | _ -> DoChildren + + method vpredicate = function + | Pforall (xl,_) | Pexists (xl,_) -> + add_logics_value xl ; DoChildren + | _ -> DoChildren + + + method vannotation = function + | Dfun_or_pred (linfo,_) -> + List.iter (fun lv -> + oracle "[logicParam] %a" !Ast_printer.d_logic_var lv; + LogicParam.replace lv false) linfo.l_profile; + DoChildren + | _ ->DoChildren + + end + +let compute_logic_params () = + debug "[LP+AT] logic parameters and address taken computation"; + if not (LogicParam.is_computed()) || not (AddrTaken.is_computed()) then + ( Visitor.visitFramacFile + (new logic_parameters_and_addr_taken_collection)(Ast.get()); + LogicParam.mark_as_computed();AddrTaken.mark_as_computed()) + + + +(**********************************************************************) +(*** Parameters Tables ***) +(**********************************************************************) + +(* A [call] represents the binding at call time of an effective argument + to a formal parameter. A [call] is then a triplet : + - an arity using in the effective argument; + - a test of address taken in the effective argument; + - a vartype represented the the formal parameter. +*) +(* A [ChainCalls] is a list of [call]s. + For a vartype [x], a [ChainCalls] the list of all call binding + when [x] is (the root of) the effective argument.*) +module ChainCalls = + (Datatype.List (Datatype.Pair (Datatype.Int) + (Datatype.Pair (Datatype.Bool)(VarType)))) + + +let pp_call fmt (n,(b,p)) = + Format.fprintf fmt "%a of arity:%d with %s " pp_var_type p n (string_addr b) + +let pp_chaincall l = (Pretty_utils.pp_list ~sep:";@, " pp_call) l + +(* Table of the parameters of by pointer reference passing call *) +module ByPReference = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Pair (Datatype.Int) (ChainCalls)) + (struct let name = "WP: by pointer reference parameters" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + +(* Table of the parameters of by array reference passing call *) +module ByAReference = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Pair (Datatype.Int) (ChainCalls)) + (struct let name = "WP: by array reference parameters" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + +(* Table of the parameter of by value passing call *) +module ByValue = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Unit) + (struct let name = "WP: by value parameters" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + +let is_pure_logic = function + | Lv lv -> (LogicParam.mem lv) && (lv.lv_origin = None) + | _ -> false + +(*[add_ptr_reference_param x n] tries to add the paramtype [x] with + an arity of [n] in the table of by pointer reference parameters. + - If [x] is already in the table 2 case : + * [n] does not the recorded arity the [x] is removed from + this table and added to the by value table. + * Else nothing has to be done + - If [x] is not in the table : + * [x] is in Byvalue table, nothing has to be done + * [x] is in the table of by array reference parameter, [x] + is removed from this table and puts in ByValue table. + * [x] is not already registered in any tables, then + [x] is registered in the by pointer reference parameter + with arity [n] and an empty chaincalls. +*) +let add_ptr_reference_param x n = + oracle "[ByPRef] first step + (%a,%d)" pp_var_type x n; + if n = 0 && (is_pure_logic x) then + (ByPReference.remove x ; ByValue.replace x ()) + else ( + try + if not (fst(ByPReference.find x) = n) then + (oracle "[ByPRef] remove %a: ko arity -> + ByValue" pp_var_type x; + ByPReference.remove x ; ByValue.replace x ()) + else (oracle "[ByPRef] (%a,%d) already" pp_var_type x n;()) + with Not_found -> + oracle "[ByPRef] %a not yet"pp_var_type x; + if ByValue.mem x then + (oracle "[ByPRef] not add %a : byValue" pp_var_type x; ()) + else + (if ByAReference.mem x then + (oracle "[ByPRef] %a in byARef : remove -> add in ByValue" + pp_var_type x; + ByAReference.remove x;ByValue.replace x()) + else + (oracle "[ByPRef] add (%a,%d)" pp_var_type x n; + ByPReference.replace x (n,[]))) ) + + +(*[remove_ptr_reference_param x] tries to removed [x] from the + table of by pointer reference parameters. +*) +let remove_ptr_reference_param x = + oracle "[ByPRef] remove %a" pp_var_type x; + if ByPReference.mem x then + ( oracle "[ByPRef] remove %a of ByPref" pp_var_type x; + ByPReference.remove x) ; + oracle "[ByPRef] add in ByValue %a"pp_var_type x; + ByValue.replace x () + + +(*[add_array_reference_param x n] tries to register [x] with arity [n] + in the table of by array reference parameters. + - If [x] already in this table : + *[n] is not the correct arity : [x] is removed from this table + and add to the by value parameters table. + * Else nothing has to be done + - If [x] is not yet in this table : + *[x] is a by value parameter, nothing has to be done + *[x] is a by pointer reference parameter then [x] is removed + from the table of by pointer reference parameter and adds to + the by array reference parameter. + *[x] is not in any table, [x] is registered in the by array + reference parameters with arity [n] and the empty chaincall. + +NB : As the behavior of a by pointer reference parameter is included + in the behavior of a by array reference parameter; a vartype [x] + in ByPReference has to be "promoted" to the ByAReference table + in this function. + +*) +let add_array_reference_param x n = + oracle "[ByARef] first step + (%a,%d)" pp_var_type x n; + try + if not (fst (ByAReference.find x) = n) then + (oracle "[ByARef] remove %a: ko arity" pp_var_type x; + ByAReference.remove x ; ByValue.replace x ()) + else (oracle "[ByARef] (%a,%d) already" pp_var_type x n;()) + with Not_found -> + oracle "[ByARef] %a not yet"pp_var_type x; + if ByValue.mem x then + (oracle "[ByARef] not add %a : byValue" pp_var_type x; ()) + else + begin + try let (_,calls) = ByPReference.find x in + oracle "[ByARef] %a in byPRef : promote to byAref" + pp_var_type x; + ByAReference.replace x (n,calls); ByPReference.remove x + with Not_found -> + (oracle "[ByARef] add (%a,%d)" pp_var_type x n; + ByAReference.replace x (n,[])) + end + +let remove_array_reference_param x = + oracle "[ByARef] remove %a" pp_var_type x; + if ByAReference.mem x then + (oracle "[ByARef] remove %a of ByAref" pp_var_type x; + ByAReference.remove x) ; + oracle "[ByARef] add in ByValue %a"pp_var_type x; + ByValue.replace x () + + + +(*************************************************************************) +(*** Usage of formal parameter as by reference parameter out of call ***) +(*************************************************************************) +type 'a usage = Ok of 'a | Ko of 'a | Any + +(* Invariant : + by_pointerXXX must always been called before by_arrayXXX + then by_pointer can never returns KO*) + +(* [by_pointer_reference_usage e] implemants 1p *) +let by_pointer_reference_usage e = + match stars_exp e with + | None -> Any + | Some (x,ty,n) -> + if x.vformal then + (if (stars_typ ty = n) then Ok (x,n) else Any) + else Any + +let by_pointer_reference_usage_term e = + match stars_term e with + | None -> Any + | Some (x,ty,n) -> + if (is_lformal x) then + (if (stars_lv_typ ty = n) then Ok (x,n) else Any) + else Any + +(* [by_array_reference_usage e] implements 1a*) +let by_array_reference_usage e = + let s = "[by_array_ref_usage]" in + debug "%s" s; + match delta_array e with + | None -> + (match bracket_exp e with + | None -> + debug "%s not a bracket pattern" s; + Any + | Some (x,n) -> + debug "%s %a[]<%d>" s !Ast_printer.d_var x n; + if x.vformal then + (debug "%s %a is a formal" s !Ast_printer.d_var x; + let arr = brackets_and_stars_typ x.vtype in + if (arr >= n) then + (debug "%s %a has dim %d ok!" s !Ast_printer.d_var x arr; + Ok (x,arr)) else + (debug "%s %a has dim %d when need %d ko!" + s !Ast_printer.d_var x arr n; + Ko(x,arr)) + ) + else + ( debug "%s %a is not a formal" s !Ast_printer.d_var x; + Any) ) + | Some (x,n) -> + debug "%s %a[]" s !Ast_printer.d_var x ; + if x.vformal then Ok (x,n) else Any + + +let by_array_reference_usage_term e = + let s = "[by_array_ref_usage_term]" in + debug "%s" s; + match delta_array_term e with + | None -> + (match bracket_term e with + | None -> + debug "%s not a bracket pattern" s; Any + | Some (x,n) -> + begin + debug "%s %a[]<%d>" s !Ast_printer.d_logic_var x n; + if (is_lformal x) then + ( debug "%s %a is a formal" s !Ast_printer.d_logic_var x; + let arr = brackets_and_stars_lv_typ x.lv_type in + if (arr >= n) then + (debug "%s %a has dim %d ok!" s + !Ast_printer.d_logic_var x arr ;Ok (x,arr)) + else + (debug "%s %a has dim %d when need %d ko!" + s !Ast_printer.d_logic_var x arr n + ;Ko (x,arr))) + else + ( debug "%s %a is not a formal" + s !Ast_printer.d_logic_var x;Any) + end) + + |Some (x,n) -> + debug "%s %a[]" s !Ast_printer.d_logic_var x ; + if is_lformal x then Ok (x,n) else Any + +(*[reference_parameter_usage e] implements the recognition of the patterns + of by reference parameters *) +let reference_parameter_usage e = + debug "[reference_parameter_usage]" ; + match by_pointer_reference_usage e with + | Ok(x,n) -> + debug " %a used as ptr reference param of arity %d" + !Ast_printer.d_var x n ; + add_ptr_reference_param (Cv x) n; true + | Ko(x,_) -> + debug " %a BADLY used as ptr reference param" + !Ast_printer.d_var x ; + remove_ptr_reference_param (Cv x); true + | Any -> + (match by_array_reference_usage e with + | Ok(x,n) -> + debug " %a used as array reference param of arity %d" + !Ast_printer.d_var x n ; + add_array_reference_param (Cv x) n ; true + | Ko(x,_) -> + debug " %a BADLY used as array reference param" + !Ast_printer.d_var x ; + remove_array_reference_param (Cv x);true + | Any -> (); false) + +let reference_parameter_usage_lval lv = reference_parameter_usage (Lval lv) + +let reference_parameter_usage_term e = + debug "[reference_parameter_usage_term]" ; + match by_pointer_reference_usage_term e with + | Ok(x,n) -> + debug " %a used as ptr reference param of arity %d" + !Ast_printer.d_logic_var x n ; + add_ptr_reference_param (var_type_of_lvar x) n ; true + | Ko(x,_) -> + debug " %a BADLY used as ptr reference param" + !Ast_printer.d_logic_var x ; + remove_ptr_reference_param (var_type_of_lvar x) ; true + | Any -> + (match by_array_reference_usage_term e with + | Ok(x,n) -> + debug " %a used as array reference param of arity %d" + !Ast_printer.d_logic_var x n ; + add_array_reference_param (var_type_of_lvar x) n ; true + | Ko(x,_) -> + debug " %a BADLY used as array reference param" + !Ast_printer.d_logic_var x ; + remove_array_reference_param (var_type_of_lvar x) ; true + | Any -> (); false) + + +(**********************************************************************) +(*** Parameters identification without call ***) +(**********************************************************************) + +(* This visitor dispatches all formal parameters according to their + usage in terms and expressions without inpecting the calls, + applications and application in ACSL builtin predicates and functions. +*) +class parameters_call_kind_analysis : Visitor.frama_c_visitor = object + inherit Visitor.frama_c_inplace + + method vinst = function + | Call (_ ,{enode =Lval(Var _,NoOffset)} , _,_) -> SkipChildren + | Set (lv,_,_) -> + if reference_parameter_usage_lval lv then SkipChildren else DoChildren + | _ -> DoChildren + + method vexpr e = + if reference_parameter_usage (Cil.stripInfo e).enode then SkipChildren + else DoChildren + + method vterm t = + match t.term_node with + | Tapp (_,_ , _) -> SkipChildren + | Tblock_length _ -> SkipChildren + | t1 -> + if reference_parameter_usage_term t1 then SkipChildren else DoChildren + + method vpredicate = function + | Papp (_, _, _) -> SkipChildren + | Pvalid _ | Pvalid_index(_,_) | Pvalid_range(_,_,_) + | Pinitialized _ | Pfresh _ | Pseparated _ -> SkipChildren + | _ -> DoChildren + +end + +let compute_parameters_usage () = + debug + "[Parameters Usage] logic parameters usage computation"; + debug + "[Parameters Usage] computing address taken and logic parameters first"; + compute_logic_params (); + if not (ByValue.is_computed()) || + not (ByPReference.is_computed() || not(ByAReference.is_computed())) + then + ( Visitor.visitFramacFile + (new parameters_call_kind_analysis)(Ast.get()); + ByPReference.mark_as_computed();ByAReference.mark_as_computed(); + ByValue.mark_as_computed()) + + +(*************************************************************************) +(*** Usage of effective parameter in by reference call ***) +(*************************************************************************) + + +(* [by_pointer_reference_pattern e] returns [Ok(x,b,n)] if [x] appears as + a root in [e] with arity [n] and a test of address taken [b]. + + A by pointer reference pattern is one a the following : + - &x+offset --> (x,true,arity of typ(x)) ; + - x+i with x of pointer type and + as +PI ----> (x,false, arity of typ(x+i)) + - *<n>x, n < stars(typ(x)) ----> (x,false,n). + + else returns: + - [Any] when the pattern is not significant ; + - [Ko] when the pattern is clearly uncompatible with a + by pointer reference pattern. +*) +let by_pointer_reference_pattern = function + | Lval (Var x,off) -> + let t = (Cil.typeOfLval (Var x,off)) in + if Cil.isPointerType t then + Ok (x,false, stars_typ t) + else Any + | AddrOf (Var x, off) -> Ok (x,true, stars_typ (Cil.typeOfLval (Var x,off))) + | e -> + begin + match delta_ptr e with + | None -> + (match stars_exp e with + | None -> Any + | Some (x,ty,n) -> + let stars = stars_typ ty in + if n < stars + then Ok (x,false,n) else + (if stars = n then Any else Ko (x,false,n))) + | Some (x,n) -> Ok (x,false,n) + end + +let by_pointer_reference_pattern_term = function + | TLval(TVar lvar, off) + | Tat ({term_node = TLval(TVar lvar, off) },_)-> + let t = Cil.typeOfTermLval (TVar lvar,off) in + if Logic_utils.isLogicPointerType t then + Ok (lvar,false,stars_lv_typ t) + else Any + | TAddrOf(TVar lvar, off) + | Tat ({term_node = TAddrOf(TVar lvar, off) },_)-> + Ok (lvar,true, stars_lv_typ (Cil.typeOfTermLval (TVar lvar,off))) + | Tat({term_node = t},_) | t -> + begin + match delta_ptr_term t with + | None -> + (match stars_term t with + | None -> Any + | Some (x,ty,n) -> + let stars = stars_lv_typ ty in + if n < stars + then Ok (x,false,n) else + (if n = stars then Any else Ko (x,false,n))) + | Some (x,n) -> Ok (x,false,n) + end + + + +(* help called in [by_array_reference_pattern e]*) +let help_by_array_reference_pattern e = + match delta_array e with + | None -> + (match bracket_exp e with + | None -> Any + | Some (x,n) -> + if x.vformal then + begin + let dim = brackets_typ x.vtype in + if n < dim + then (Ok (x,false,n)) else + (if n = dim then Any else Ko (x,false,n)) + end + else Ok(x,false,n)) + | Some (x,n) -> Ok (x,false,n) + + + +(*[by_array_reference_pattern e] returns [Ok (x,b,n)] + if [x] appears as a root in [e] with test of address taken (b] and arity [n]. + + A by array reference pattern is one of the following : + - x+offset (StarOf) ----> Ok(x,true,arity_of (typ(x))); + - x<k>[], k < bracket(typ(x)) ----->Ok(x,false,k); + - &(x+i) + ==+PI ----> Ok(x,true,n) + + else returns: + - [Any] when the pattern is not significant ; + - [Ko] when the pattern is clearly uncompatible with a + by array reference pattern. +*) + + +let by_array_reference_pattern = function + | StartOf (Var x,off) -> Ok (x,true,brackets_typ (Cil.typeOfLval (Var x,off))) + | CastE(ty,{enode = StartOf (Var x,off)}) when Cil.isPointerType ty -> + Ok (x,true,brackets_typ (Cil.typeOfLval (Var x,off))) + | AddrOf (Mem e, _) -> + (match delta_ptr (Cil.stripInfo e).enode with + | None -> Any + | Some (x,n) -> Ok (x,true,n)) + | CastE (t,e) -> + debug "[by_array_reference_pattern] cast case"; + if Cil.isPointerType t then + ( debug "is a pointer type"; + help_by_array_reference_pattern (Cil.stripInfo e).enode) + else + (debug "is NOT a pointer type " ;Any ) + | e -> help_by_array_reference_pattern e + + +let help_array_reference_pattern_term s t = + match delta_array_term t with + | None -> + (match bracket_term t with + | None -> Any + | Some (x,n) -> + if is_lformal x then + begin + debug "%s %a[]<%d>" s !Ast_printer.d_logic_var x n; + let dim = brackets_lv_typ x.lv_type in + if n < dim + then + (debug "%s %a has dimension %d ok!" + s !Ast_printer.d_logic_var x n; + Ok (x,false,n)) + else + ( if dim = n then Any else + (debug "%s %a has dimension %d when need %d!" + s !Ast_printer.d_logic_var x dim n; + Ko (x,false,n))) + end + else Ok(x,false,n) + ) + | Some (x,n) -> + debug "%s %a in delta_array term" s !Ast_printer.d_logic_var x; + Ok (x,false,n) + +let by_array_reference_pattern_term t = + let s = "[by_array_reference_pattern_term]" in + match t with + | TStartOf (TVar lvar,off) + | Tat ({term_node = TStartOf (TVar lvar,off) },_)-> + debug "%s %a " s!Ast_printer.d_logic_var lvar; + Ok(lvar,true,brackets_lv_typ (Cil.typeOfTermLval (TVar lvar,off))) + + |TCastE(ty,{term_node = ( TStartOf (TVar lvar,off) + | Tat ({term_node = TStartOf (TVar lvar,off) },_))}) when + Cil.isPointerType ty -> + debug "%s %a " s!Ast_printer.d_logic_var lvar; + Ok (lvar,true,brackets_lv_typ(Cil.typeOfTermLval (TVar lvar,off))) + + | TAddrOf (TMem t, _) + | Tat ({term_node = TAddrOf (TMem t, _) },_) -> + (match delta_ptr_term t.term_node with + | None -> Any + | Some (x,n) -> + debug "%s %a in delta_ptr term" s !Ast_printer.d_logic_var x; + Ok (x,true,n)) + | Tat({term_node = t},_)-> help_array_reference_pattern_term s t + | TCastE(ty,{term_node = t}) when (Cil.isPointerType ty)-> + help_array_reference_pattern_term s t + | t ->help_array_reference_pattern_term s t + + + + + +(**********************************************************************) +(*** Collection of potential Chain of by reference calls ***) +(**********************************************************************) + +(* [collect_calls_occurences (eargs,sgn)] visits a list of arguments and + a signature and collects each call of thus cases: + - [x<n>*] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a by pointer reference parameter. + Then, the [chain_call] of [x] is updated in the [ByPReference] table + with the call site [(n,p)]. + + - [x<n>[]] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a by array reference parameter. + Then, the [chain_call] of [x] is updated in the [ByAReference] table + with the call site [(n,p)]. + + - [x<n>*] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a none formal. + Then, the [chain_call] of [x] is updated in the [ArgPReference] table + with the call site [(n,p)]. + + - [x<n>[]] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a none formal. + Then, the [chain_call] of [x] is updated in the [ByAReference] table + with the call site [(n,p)]. + + - in all other case, nothing is done and the collection progress + in the tail of both lists. +*) + +(* Table of by pointer reference argument *) +module ArgPReference = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Pair (Datatype.Int) (ChainCalls)) + (struct let name = "WP: argument by pointer reference not formal" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + +(*Table of by array reference argument *) +module ArgAReference = + State_builder.Hashtbl + (VarType.Hashtbl) + (Datatype.Pair (Datatype.Int) (ChainCalls)) + (struct let name = "WP: argument by array reference not formal" + let dependencies = [Ast.self] + let kind = `Internal + let size = 47 + end) + + + +(* [add_ptr_reference_arg x n] tries to adds [x] of arity [n] in the + table of by pointer reference argument. + + -If [x] is in AnyVar table, then [x] can't been added to this table. + + -If [x] is already registered in by pointer reference argument, the + already recorded arity has to be [n] else [x] is removed from this + table and adds to the AnyVar table. + + - If [x] is not registered in the by pointer reference table: + *[x] is in the by array reference argument then [x] is removed + from this table and adds to the any var table. + *else [x] is registered in the by pointer reference argument with the + arity [n] and the empty chain call. +*) +let add_ptr_reference_arg x n = + oracle "[ArgPRef] try + %a" pp_var_type x; + if AnyVar.mem x then + (oracle "[ArgPRef] %a AnyVar"pp_var_type x;()) + else + begin + try + if not (fst (ArgPReference.find x) = n) then + (oracle "[ArgPRef] remove %a : ko arity ->+AnyVar" + pp_var_type x; + ArgPReference.remove x; AnyVar.replace x ()) + else + (oracle "[ArgPRef] %a already" pp_var_type x;()) + with Not_found -> + (if ArgAReference.mem x then + (oracle "[ArgPRef] %a ArgARef : remove -> + AnyVar" + pp_var_type x; + ArgAReference.remove x; AnyVar.add x ()) + else + (oracle "[ArgPRef] + %a"pp_var_type x; + ArgPReference.add x (n,[]))) + end + +let remove_ptr_reference_arg x = + oracle "[ArgPRef] remove %a" pp_var_type x; + if ArgPReference.mem x then + (oracle "[ArgPRef] remove %a of ArgPRef" pp_var_type x; + ArgPReference.remove x); + oracle "[ArgPRef] + %a AnyVar" pp_var_type x ; + AnyVar.replace x () + +(* [add_array_reference_arg x n] tries to add [x] with arity [n] in the table + of by array reference arguments. + - If [x] is in any var table, [x] can't been added to this table. + + - If [x] already registered in the by array reference argument; then + the already recorded arity has to been [n] otherwise + *[n] is not the correct arity, [x] is removed from this table + and adds to the any var table + *[n] is the correct arity, nothing has to be done + - If [x] is not yet in the table of by array reference argument: + *[x] is in the table of by pointer reference argument. [x] is removed + form this table and adds to the any var table + *[x] has not yet been registered, [x] is registered with the + arity [n] and the empty chaincalls in the table of by array reference + argument. +*) +let add_array_reference_arg x n = + oracle "[ArgARef] try + %a" pp_var_type x; + if AnyVar.mem x then + (oracle "[ArgARef] %a AnyVar"pp_var_type x;()) + else + begin + try + if not (fst (ArgAReference.find x) = n) then + (oracle "[ArgARef] remove %a : ko arity ->+AnyVar" + pp_var_type x; + ArgAReference.remove x; AnyVar.replace x ()) + else + (oracle "[ArgARef] %a already" pp_var_type x;()) + with Not_found -> + (if ArgPReference.mem x then + (oracle "[ArgARef] %a ArgPRef : remove -> + AnyVar" + pp_var_type x; + ArgPReference.remove x; AnyVar.add x ()) + else + (oracle "[ArgARef] + %a"pp_var_type x; + ArgAReference.add x (n,[]))) + end + +let remove_array_reference_arg x = + oracle "[ArgARef] remove %a" pp_var_type x; + if ArgAReference.mem x then + (oracle "[ArgARef] remove %a of ArgARef" pp_var_type x; + ArgAReference.remove x); + oracle "[ArgARef] + %a AnyVar" pp_var_type x ; + AnyVar.replace x () + + +(* [collect_calls_rec (eargs,sgn)] visits a list of arguments and + a signature and collects each call of thus cases: + - [x<n>*] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a by pointer reference parameter. + Then, the [chain_call] of [x] is updated in the [ByPReference] table + with the call site [(n,p)]. + - [x<n>[]] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a by array reference parameter. + Then, the [chain_call] of [x] is updated in the [ByAReference] table + with the call site [(n,p)]. + - [x<n>*] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a none formal. + Then, the [chain_call] of [x] is updated in the [ArgPReference] table + with the call site [(n,p)]. + - [x<n>[]] in [eargs] associates to the parameter [p] + into the signature [sgn] when [x] is a none formal. + Then, the [chain_call] of [x] is updated in the [ByAReference] table + with the call site [(n,p)]. + - in all other case, nothing is done and the collection progress + in the tail of both lists. + + Implements 2p) 2a) and computation of other kind of variables passed + by reference. +*) + +(*[collect_formal_array_call s x n b p] tries to collect in bellow function + characterized by [s] for debugging the by array reference call [(n,(b,p))] + in the chaincall of the by array reference parameter [x] with: + arity [n] with test of address taken [b] on prameter type [p] with + the effective argument containing the variable [x]. + -If [x] already in the table of by array reference parameter: + * [n] is convenient with the registered arity of [x] then + adds the call to the chain call of [x] + * else [x] is removed from the table of by array reference parameters + -If [x] is not yet registered in the table of by array reference parameters, + tries to add [x] in this table: + * if ok then computes the arity of [x], [arr]. + a) if [n] is convenient for [arr] then add [x] to the table of + by array reference parameter with arity [arr] and the call. + b) else nothing has to be done + *) +let collect_formal_array_call s x n b p = + try + let (arr,calls) = ByAReference.find x in + oracle "%s %a ByARef" s pp_var_type x; + if n <= arr then + ( oracle "%s %a + call(%a,%d,%s)" s pp_var_type x + pp_var_type p n (string_addr b); + ByAReference.replace x (arr,((n,(b, p))::calls))) + else + ( oracle "%s %a remove %d used %d" s pp_var_type x arr n; + remove_array_reference_param x) + with Not_found -> + oracle "%s %a not yet ByARef" s pp_var_type x; + let arr = brackets_and_stars_var_type_typ x in + add_array_reference_param x arr; + try let (_,calls) = ByAReference.find x in + ByAReference.replace x (arr,(n,(b,p))::calls) + with Not_found -> () + + +(* as collect_arg_array_call for by pointer reference call of argument.*) +let collect_arg_ptr_call s x n b p = + if AnyVar.mem x then + (oracle "%s %a AnyVar" s pp_var_type x ;()) + else + try + let (arr,calls) = ArgPReference.find x in + oracle "%s %a ArfPRef" s pp_var_type x; + if n <= arr then + (oracle "%s %a + call(%a,%d,%s)" s pp_var_type x + pp_var_type p n (string_addr b); + ArgPReference.replace x (arr,((n,(b,p))::calls))) + else + (oracle "%s %a remove %d used %d" s pp_var_type x arr n; + remove_ptr_reference_arg x) + with Not_found -> + oracle "%s %a not yet in ArgPref" s pp_var_type x; + let arr = stars_var_type_typ x in add_ptr_reference_arg x arr; + if ArgPReference.mem x then + (if n <= arr then + (oracle"%s %a + call(%a,%d,%s)" + s pp_var_type x pp_var_type p n (string_addr b); + ArgPReference.replace x (arr,[n,(b,p)])) + else ()) + + +(* [collect_arg_array_call s x n b p] tries to collect, in the bellow function + characterized by [s] for debugging, the calls [(n,(b,p))] in the chain call + of the by array reference argument [x]. + -If [x] is any var, nothing has to be done. + -If [x] is already registered in the table of by array reference argument, + according to the convenient of [n] to the registered arity of [x], + the calls is added to the chaincall of (x] or [x] is removed from this + table. + -If (x] is not yet registered, the arity of [x] is computed [arr] and + and tries to add [(x,arr)] in the table of by array reference argument. + If the add succeed adds the call else nothing has to be done +*) +let collect_arg_array_call s x n b p = + if AnyVar.mem x then + (oracle "%s %a AnyVar" s pp_var_type x ;()) + else + try + let (arr,calls) = ArgAReference.find x in + oracle "%s %a ArfARef" s pp_var_type x; + if n <= arr then + (oracle "%s %a + call(%a,%d,%s)" s pp_var_type x + pp_var_type p n (string_addr b); + ArgAReference.replace x (arr,((n,(b,p))::calls))) + else + (oracle "%s %a remove %d used %d" s pp_var_type x arr n; + remove_array_reference_arg x) + with Not_found -> + oracle "%s %a not yet in ArgAref" s pp_var_type x; + oracle "%s %a try to collect with %d" + s pp_var_type x n; + if isVarTypePointerType x then collect_arg_ptr_call s x n b p + else + (if n <> 0 then + (oracle"%s %a + call(%a,%d,%s)" + s pp_var_type x pp_var_type p n (string_addr b); + add_array_reference_arg x n; + try let (n,calls) = ArgAReference.find x in + ArgAReference.replace x (n,(n,(b,p))::calls) + with Not_found -> ()) + else ()) + +(* as collect_formal_array_call for by pointer reference parameters. + Note that is [px] not yet in the table of by pointer reference parameters + then if [px] is in the table of by array reference parameters then + tries to register this call as a formal array call -> + [collect_formal_array_call] In fact, the patterns of by array reference calls + contains the patterns of by pointer reference calls. +*) +let collect_formal_ptr_call s px n b p = + try + let (arr,calls) = ByPReference.find px in + oracle "%s %a ByPRef" s pp_var_type px; + if n <= arr then + ( oracle "%s %a + call(%a,%d,%s)" s pp_var_type px + pp_var_type p n (string_addr b); + ByPReference.replace px (arr,((n,(b,p))::calls))) + else + ( oracle "%s %a remove %d used %d" s pp_var_type px arr n; + remove_ptr_reference_param px) + with Not_found -> + oracle "%s %a not yet ByPRef" s pp_var_type px; + if ByAReference.mem px then collect_formal_array_call s px n b p + else + begin + let arr = stars_var_type_typ px in add_ptr_reference_param px arr; + if ByPReference.mem px then + (if n <= arr then + ( oracle "%s %a + call(%a,%d,%s)" + s pp_var_type px pp_var_type p n (string_addr b); + ByPReference.replace px (arr,[n,(b,p)]))) + else () + end + + + + +(*[collect_calls_rec (eargs,fmls)] collects, in a C call assigning the + effective arguments [eargs] to the formal parameter [fmls], + the calls, using preview functions according to the identified argument + patterns for each pair of effective argument [e] and formal parameter + [p]. + *) +let rec collect_calls_rec (eargs,fmls) = + let s = "[collect_calls]" in + match eargs,fmls with + | [],[] -> () + | [], _ | _, [] -> () (*TODO: check for variadyc functions *) + | e::args, p::fmls -> + debug "%s no empty list" s; + let e1 = (Cil.stripInfo e).enode in + (match by_array_reference_pattern e1 with + | Ok (x,b,n) -> + let sb =string_addr b in + debug "%s array pattern of %a with %s" s + !Ast_printer.d_var x sb; + let x = Cv x and p = Cv p in + if is_formal_var_type x then + collect_formal_array_call s x n b p + else + collect_arg_array_call s x n b p + + | Ko (x,_,_) -> + debug "%s not array pattern" s; + if x.vformal then + remove_array_reference_param (Cv x) + else ArgAReference.remove (Cv x) + | Any -> + ( match by_pointer_reference_pattern e1 with + | Ok (x,b,n) -> + let sb = string_addr b in + debug "%s ptr pattern of %a with %s and %d" + s !Ast_printer.d_var x sb n; + let x = Cv x and p = Cv p in + if is_formal_var_type x then + collect_formal_ptr_call s x n b p + else collect_arg_ptr_call s x n b p + + | Ko (x,_,_) -> + debug "%s not ptr pattern" s; + if x.vformal then remove_ptr_reference_param (Cv x) + else ArgPReference.remove (Cv x) + + | Any ->() + ) + ); collect_calls_rec (args,fmls) + + +let collect_calls f el = + let kf = Globals.Functions.get f in + let fmls = Kernel_function.get_formals kf in + debug "[collect_calls]"; + collect_calls_rec (el,fmls) + + +let ok_array_term_formal s x n b p = + collect_formal_array_call s x n b p + +let ok_array_term_arg s x n b p = + collect_arg_array_call s x n b p + +let ok_array_term s x n b p = + if is_formal_var_type x then ok_array_term_formal s x n b p + else ok_array_term_arg s x n b p + +let ok_ptr_term_formal s x n b p = + collect_formal_ptr_call s x n b p + +let ok_ptr_term_arg s x n b p = + collect_arg_ptr_call s x n b p + +let ok_pointer_term s x n b p = + if is_formal_var_type x then ok_ptr_term_formal s x n b p + else ok_ptr_term_arg s x n b p + +(* as collect_calls_rec on logic application*) +let rec collect_apps_rec = function + | [],[] -> () + | [], _ | _, [] -> () (*TODO: check correctness for variadyc functions *) + | t::args, p::fmls -> + let s = "collect_app" in + (match by_array_reference_pattern_term t.term_node with + | Ok (x,b,n) -> + debug "(%a,%b,%d) by_array in apps_rec" + !Ast_printer.d_logic_var x b n; + ok_array_term s (var_type_of_lvar x) n b (var_type_of_lvar p ) + | Ko (x,_,_) -> + let x = var_type_of_lvar x in + if is_formal_var_type x + then remove_array_reference_param x + else ArgAReference.remove x + + | Any -> + ( match by_pointer_reference_pattern_term t.term_node with + | Ok (x,b,n) -> + let p = var_type_of_lvar p in + let x = var_type_of_lvar x in + ok_pointer_term s x n b p + | Ko (x,_,_) -> + let x = var_type_of_lvar x in + if is_formal_var_type x + then remove_ptr_reference_param x + else ArgPReference.remove x + | Any ->() + ) + ); collect_apps_rec (args,fmls) + +let collect_apps lf tl = collect_apps_rec (tl,lf.l_profile) + + + +(* as collect_apps_rec on logic builtin application + if the argument is a userdef parameter, its information in + LogicParam is updated by the test of addresse taken *) +let rec collect_apps_builtin targs = + let s = "[BuiltinCall]" in + match targs with + | [] -> () + | t::args -> + (match by_array_reference_pattern_term t.term_node with + | Ok (x,b,n) -> + debug "%s %a in array ref position with %s with dim = %d" + s !Ast_printer.d_logic_var x (string_addr b) n; + logic_param_memory_info x; + ok_array_term s (var_type_of_lvar x) n b Prop + | Ko (x,_,_) -> + debug "%s %a is not in a array ref position" + s !Ast_printer.d_logic_var x ; + let x = var_type_of_lvar x in + if is_formal_var_type x + then remove_array_reference_param x + else ArgAReference.remove x + + | Any -> + ( match by_pointer_reference_pattern_term t.term_node with + | Ok (x,b,n) -> + debug "%s %a in ptr ref position with %s with %d *" + s !Ast_printer.d_logic_var x (string_addr b) n; + logic_param_memory_info x; + ok_pointer_term s (var_type_of_lvar x) n b Prop + | Ko (x,_,_) -> + debug "%s %a is not in a ptr ref position" + s !Ast_printer.d_logic_var x ; + let x = var_type_of_lvar x in + if is_formal_var_type x + then remove_ptr_reference_param x + else ArgPReference.remove x + | Any -> () + ) + ); collect_apps_builtin args + + +(**********************************************************************) +(*** Chain of calls collections ***) +(**********************************************************************) + +let calls_collection_computed = ref false + +(* This visitor inpects all calls,applications and ACSL builtin applications + and then : + - collects [call]s and builds [chaincalls] of each kind of variable; + - redefines the kind of a variable if needed. + Typically when patterns of a same variable are of different kinds + or for a formal when the usage (found in the last visitor) is not + compatible with a pttern (found in this visitor). + +NB: The resolution of an entire [ChainCall] can't been done here because + all [call] has to been inspected before. + +*) + +class calls_collection : Visitor.frama_c_visitor = object + inherit Visitor.frama_c_inplace + + method vinst = function + | Call (_ ,{enode =Lval(Var f,NoOffset)} , el,_) as e-> + debug "[Calls_collection] call %a" !Ast_printer.d_instr e; + collect_calls f el ; SkipChildren + | _ -> DoChildren + + method vterm t = + match t.term_node with + | Tapp (lf,_ , targs) -> + debug "[Calls_collection] app %a" !Ast_printer.d_term t; + collect_apps lf targs ; SkipChildren + | Tblock_length ta -> + debug "[Calls_collection] block_length %a" !Ast_printer.d_term t; + collect_apps_builtin [ta] ; SkipChildren + | _ -> DoChildren + + method vpredicate = function + | Papp (lf, _, targs) -> collect_apps lf targs ; SkipChildren + | Pvalid t | Pvalid_index(t,_) | Pvalid_range(t,_,_) + | Pinitialized t | Pfresh t -> + debug "[Calls_collection] predicate app on %a" !Ast_printer.d_term t; + collect_apps_builtin [t] ; SkipChildren + | Pseparated lt -> collect_apps_builtin lt ; SkipChildren + | _ -> DoChildren + +end + +let compute_calls_collection () = + debug + "[Calls Collection] collectinfg potential by reference calls"; + debug + "[Calls Collection] computing parameters usage first"; + compute_parameters_usage (); + if not !calls_collection_computed then + (Visitor.visitFramacFile (new calls_collection)(Ast.get()); + calls_collection_computed := true) + + + + +(**********************************************************************) +(*** Chain of calls Resolution ***) +(**********************************************************************) + + +(* + B - Chain of Calls Resolutions + The second part of the by-reference-parameters + identification, is the verification of the [ChainCalls] + for each formal parameter occured in ByPReference + or ByAReference table. + Concerning the argument by-reference, chain of calls has to be + resolved too. During this resolution, the addrtaken table is + updated : address taken in real by-reference call are + subtracted. + + The resolution of the [ChainCall] of formal parameters have to occur + before de resolution the [ChainCall]of other variable. + +*) + + +(* Chain of call resolution of the table of by pointer reference parameters. + A convenient [call] for a by pointer reference parameter [x] with + arity [n] is : + -a builtin application [(k,(b,Prop))], k <= [n] + -an application or call [(k,(b,p))], k <= n and [p] is a + by pointer reference parameter. + + For each convenient [call], if the test of address taken is true, then + the [minus] information of [x] in the address taken table is incremented. + + A [ChainCalls] is resolved when all is [call]s has been inspected. + If all [call]s of the [ChainCalls] [calls] are convenient, + [x] stays in by pointer reference parameter with arity [n]. + Otherwise, [x] is moved from the by pointer reference parameter + table to the by value parameter table. + + NB: For a call [(k,(b,p))], [p] can not yet occur in + the by pointer reference paramter table, then [p] has first to be + add in this table and its [ChainCalls] has to been resolved before + the resolution of this call. + +*) +let rec by_ptr_reference x n calls = + let s = "[by_ptr_reference]" in + debug "%s %a of arity %d" s pp_var_type x n; + match calls with + | [] -> + debug "%s %a: ok " s pp_var_type x; + oracle "%s %a ByPref" s pp_var_type x; + ByPReference.replace x (n,[]) + | (k,(b,Prop))::m -> + let sb = string_addr b in + debug "%s %a: (builtin,%d,%s)" s pp_var_type x k sb; + if k <= n then + (debug "%s arity of call ok" s; decr_addr_taken_bool x b; + by_ptr_reference x n m) + else + (debug "%s arity of call too big" s; remove_ptr_reference_param x) + | (k,(b,p))::m -> + let bv = ByValue.mem p in let ba = ByAReference.mem p in + let c = k > n in let sb = string_addr b in + if c || bv || ba then + (debug "%s: KO %a ByValue:%b ; Aref : %b; call arity:%b" + s pp_var_type p bv bv c ; remove_ptr_reference_param x) + else + (debug "%s: OK %a ByValue:%b ; Aref : %b; call ari:%b; with %s" + s pp_var_type p bv ba c sb ; + try (match ByPReference.find p with + | (i,[]) -> + debug "%s %a already resolved ; arity :%d" + s pp_var_type p i; + if k <= i then + (debug"%s arity OK" s; decr_addr_taken_bool x b; + by_ptr_reference x n m) + else + (debug "%s arity KO %a with %d and %a with %d used %d" + s pp_var_type x n pp_var_type p i k; + remove_ptr_reference_param x ) + | (i,lp) -> + debug "%s %a has to be resolved; with %d used %d" + s pp_var_type p i k; + if k <= i then + (by_ptr_reference p i lp; + by_ptr_reference x n ((k,(b,p))::m)) + else remove_ptr_reference_param x + ) + with Not_found -> + debug "%s %a NOT in PRef param" s pp_var_type p; + let i = stars_var_type_typ p in + add_ptr_reference_param p i; + if not (ByPReference.mem p) || ByValue.mem p + then remove_ptr_reference_param x + else by_ptr_reference x n ((k,(b,p))::m)) + + +(* Chain of call resolution of the table of by array reference parameters*) +let rec by_array_reference x n l = + let s = "[by_array_reference]" in + debug "%s %a of arity %d" s pp_var_type x n; + match l with + | [] -> + oracle "%s %a ByAref" s pp_var_type x; + ByAReference.replace x (n,[]) + | (k,(b,Prop))::m -> + if k <= n then + (decr_addr_taken_bool x b; by_array_reference x n m) + else remove_array_reference_param x + | (k,(b,p))::m -> + if k < n || ByValue.mem p || ByPReference.mem p then + remove_array_reference_param x + else + try (match ByAReference.find p with + | (i,[]) -> + if i <= k then + (decr_addr_taken_bool x b; by_array_reference x n m) + else remove_array_reference_param x + | (i,lp) -> + if i <= k then + (by_array_reference p i lp; + by_array_reference x n ((k,(b,p))::m)) + else remove_array_reference_param x + ) + with Not_found -> + debug "%s %a NOT in ARef param" s pp_var_type p; + let i = brackets_and_stars_var_type_typ p in + add_array_reference_param p i; + if not (ByAReference.mem p) || ByValue.mem p + then remove_array_reference_param x + else by_array_reference x n ((k,(b,p))::m) + +(* resolution of chain of call of formal parameters.*) +let resolved_call_chain_param () = + ByAReference.iter + (fun var (n,l) -> + debug "[resolve chaincall of param] array -> %a:%a" + pp_var_type var pp_chaincall l; + by_array_reference var n l) ; + ByPReference.iter + (fun var (n,l) -> + debug "[resolve chaincall of param] ptr -> %a:%a" + pp_var_type var pp_chaincall l; + by_ptr_reference var n l) + +(* Chain of call resolution of the table of by pointer reference argument*) +let rec ptr_reference x n calls = + let s = "[ptr_reference arg]" in + match calls with + | [] -> + debug "%s %a: arity %d ok" s pp_var_type x n; + oracle "%s %a ArgPref" s pp_var_type x; + ArgPReference.replace x (n,[]) + | (k,(b,Prop))::m -> + let sb = string_addr b in + debug "%s (%a,%d) used builtin %d and %s" s pp_var_type x n k sb; + if k <= n then + ( debug "%s builtin arity OK" s; decr_addr_taken_bool x b ; + ptr_reference x n m) + else + (debug "%s builtin arity KO" s; remove_ptr_reference_arg x) + | (k,(b,p))::m -> + let sb = string_addr b in + debug "%s (%a %d) ; used as (%a,%d) and %s" + s pp_var_type x n pp_var_type p k sb; + if k > n then + (debug "%s %a:arity KO " s pp_var_type p; + remove_ptr_reference_arg x) + else + try (match ByPReference.find p with + | (i,[]) -> + debug "%s %a is byPref resolved" s pp_var_type p; + if k <= i then + ( debug "%s arity OK" s; decr_addr_taken_bool x b; + ptr_reference x n m) + else (debug "%s arity KO" s; remove_ptr_reference_arg x) + | (i,lp) -> (* can't happen *) + debug "%s %a is byPref NOT resolved"s pp_var_type p; + if k <= i then + ( debug "%s arity OK"s ;by_ptr_reference p i lp; + debug "%s resolution of %a" s pp_var_type p; + ptr_reference x n ((k,(b,p))::m)) + else + (debug "%s arity KO" s; remove_ptr_reference_arg x ) + ) + with Not_found -> (* can't happen *) + debug "%s %a NOT ByPRef" s pp_var_type p; + let i = stars_var_type_typ p in + add_ptr_reference_param p i; + if not (ByPReference.mem p) || ByValue.mem p + then remove_ptr_reference_arg x + else ptr_reference x n ((k,(b,p))::m) + + +(* Chain of call resolution of the table of by array reference argument*) +let rec array_reference x n calls = + let s = "[array_reference arg]" in + match calls with + | [] -> + debug "%s %a: arity %d ok" s pp_var_type x n; + oracle "%s %a ArgAref" s pp_var_type x; + ArgAReference.replace x (n,[]) + | (k,(b,Prop))::m -> + if k <= n then + (decr_addr_taken_bool x b; array_reference x n m) + else remove_array_reference_arg x + | (k,(b,p))::m -> + if k > n then ArgAReference.remove x + else + ( + if ByPReference.mem p then + begin + try (match ByPReference.find p with + | (i,[]) -> + debug "%s %a is byPref resolved" s pp_var_type p; + if k <= i then + ( debug "%s arity OK" s; decr_addr_taken_bool x b; + array_reference x n m) + else + (debug "%s arity KO" s; + remove_array_reference_arg x) + | (i,lp) -> (* can't happen *) + debug "%s %a is byPref NOT resolved"s pp_var_type p; + if k <= i then + ( debug "%s arity OK"s ;by_ptr_reference p i lp; + debug "%s resolution of %a" s pp_var_type p; + array_reference x n ((k,(b,p))::m)) + else + (debug "%s arity KO" s; + remove_ptr_reference_arg x ) + ) + with Not_found -> remove_array_reference_arg x + end + else + begin + try (match ByAReference.find p with + | (_,[]) -> + decr_addr_taken_bool x b; array_reference x n m + | (i,lp) -> (* can't happen *) + by_array_reference p i lp; + array_reference x n ((k,(b,p))::m) + ) + with Not_found -> (* can't happen *) + debug "%s %a NOT ByARef" s pp_var_type p; + let i = brackets_and_stars_var_type_typ p in + add_array_reference_param p i; + if not (ByAReference.mem p) || ByValue.mem p + then remove_array_reference_arg x + else array_reference x n ((k,(b,p))::m) + end + ) + + +(* resolution of chain of call of arguments.*) +let resolved_call_chain_arg () = + ArgAReference.iter + (fun var (n,l) -> + debug "[resolve chaincall of arg] array -> %a:%a" + pp_var_type var pp_chaincall l; + array_reference var n l) ; + ArgPReference.iter + (fun var (n,l) -> + debug "[resolve chaincall of arg] ptr -> %a:%a" + pp_var_type var pp_chaincall l; + ptr_reference var n l) + + +(**********************************************************************) +(*** Address Taken Resolution ***) +(**********************************************************************) + +(* [resolve_addr_taken ()] iterates on Address Taken table. + For each variable [var] : + - if the occurences of address taken out of by reference call [m] + is strictly more than the occurences in by reference call [r] then + [var] stays in the address taken table and it is removes from the + by reference table. + - if [var] address taken occurs more or as much in by reference calls + [r] than in other case [m] then [var] is remove from the address taken + table.*) + + let resolve_addr_taken () = + let remove_from_refs var = + if is_formal_var_type var then + (remove_ptr_reference_param var; + remove_array_reference_param var) + else + (ArgPReference.remove var; ArgAReference.remove var) + in + let s = "[resolves addr taken]" in + AddrTaken.iter + (fun var (m,r) -> + debug "%s %a +:%d -:%d" s pp_var_type var m r ; + if m > r then + (debug "%s %a: addr taken %d et %d" s pp_var_type var m r; + oracle"%s %a: stays addrtaken"s pp_var_type var; + remove_from_refs var) + else + (debug "%s %a: not addr taken %d et %d" s pp_var_type var m r; + oracle"%s %a: remove addrtaken"s pp_var_type var; + AddrTaken.remove var)) + + + + +(**********************************************************************) +(*** Adding Separated hypothesis ***) +(**********************************************************************) + +(* The optimization of by reference calls supposing a quiet important + number of hypothesis about separation between variables. + One of this kind of separation hypothesis concerns + the separation between by pointer reference parameters of a same + signature and all their dereferenced pointers. In this case , + we add the pre-condition to the contract of the function. + Concerning other kind of separation hypothesis, we emit a warning.*) + + + (* Creates the l-value *lv *) + let deref loc (t:term) : term = + let typ = match t.term_type with + | Ctype (TPtr (typ,_)) -> Ctype typ + | _ -> Wp_parameters.fatal "[deref] on a pure logic type" + in + Logic_const.term ~loc (TLval (TMem t,TNoOffset)) typ + + type formal_kind = + | Formal_Value + | Formal_Ref of int + | Formal_Array of int + + let kind_of_formal x = + try + let (n,_calls) = ByPReference.find (Cv x) in + if Cil.isPointerType x.vtype then + Formal_Ref n + else + Formal_Value + with Not_found -> + try + let (n,_calls) = ByAReference.find (Cv x) in + Formal_Array n + with Not_found -> + Formal_Value + + let rec collect_sepstars loc n (t:term) (sep_terms:term list) = + let sep_terms = t :: sep_terms in + if n=1 then sep_terms else + let tstar = deref loc t in + collect_sepstars loc (pred n) tstar sep_terms + + + let pp_formals fmt = function + | [] -> () + | x::xs -> + Format.fprintf fmt "'%s'" x.vname (* user info *) ; + List.iter (fun x -> Format.fprintf fmt ",@ '%s'" x.vname) xs + + let rec collect_refparams kf loc arr_vars ref_vars sep_terms = function + | x::xs -> + begin + match kind_of_formal x with + | Formal_Value -> + collect_refparams kf loc arr_vars ref_vars sep_terms xs + | Formal_Array _ -> + collect_refparams kf loc (x::arr_vars) ref_vars sep_terms xs + | Formal_Ref n -> + let t = Logic_const.tvar ~loc (Cil.cvar_to_lvar x) in + let sep_terms = collect_sepstars loc n t sep_terms in + collect_refparams kf loc arr_vars (x::ref_vars) sep_terms xs + end + | [] -> + begin + match List.rev arr_vars , List.rev ref_vars with + | [] , _ -> () + | [_] , [] -> () + | xs , [] -> + Wp_parameters.warning + "For function %s,@ array reference parameters %a@ must be disjoint at call site" + (Kernel_function.get_name kf) pp_formals xs + | xs , ys -> + Wp_parameters.warning + "For function %s, reference parameters@ %a and %a@ must be disjoint at call site" + (Kernel_function.get_name kf) pp_formals xs pp_formals ys + end ; + match sep_terms with + | [] | [_] -> None + | ts -> Some(Logic_const.new_predicate (Logic_const.pseparated ts)) + + let add_requires hyp bhvs = + debug "[add_requires] size of bhs :%d" (List.length bhvs); + try + List.iter + (fun b -> + if Cil.is_default_behavior b then begin + b.b_requires <- hyp :: b.b_requires; + raise Exit + end) + bhvs + with Exit -> + () + + let kernel_functions_separation_hyps () = + debug "[kf separation hyps]"; + Globals.Functions.iter + (fun kf -> + debug "[kf separation hyps] %s" (Kernel_function.get_name kf); + let formals = Kernel_function.get_formals kf in + let loc = Kernel_function.get_location kf in + match collect_refparams kf loc [] [] [] formals with + | Some hyp -> + debug "[kf separation hyps] case hyp:%a" + Cil.d_identified_predicate hyp; + Kernel_function.set_spec + kf (fun fspec -> + add_requires hyp fspec.Cil_types.spec_behavior; + fspec ); + | None -> + debug "[kf separation hyps] case None"; + ()) + +(**********************************************************************) +(*** Variable Anaylisis Computation ***) +(**********************************************************************) + +(* + If both optimization are required : + + Computation of the variable analysis; calls all visitors and resolution + in the good order, which is the order of their definitions in this file: + - Computation of address taken, collection of logic formal parameters, + preserved universally and existentially bound variables from the + optimization ; + - Identification of usages of formal parameters without + inspecting calls, application and ACSL builtin application + to dispatch them into formal parameters tables. + - Collection of calls according to the pattern of the effective + arguments and, then, updating the [ChainCalls] of the variables tables. + Collecting the occurences of address taken into a by reference pattern + and updating the AddressTaken table. + - Resolution of [ChainCalls], first in formal parameters tables, + secondly in other kind of variables tables. + - Resolution of address taken table. + + If only logicVar is required : + - Computation of addresse taken table. + +*) + + +type case = + | All (* both optimizations are required*) + | Nothing (* none of the optimization are required *) + | Half (* only logic var is required*) + + +(* Discrimination of the case of the analysis *) +let case_of_optimization logicvar refvar = + if not logicvar then (if refvar then All else Nothing) + else (if refvar then All else Half) + +let not_half_computed () = + not (AddrTaken.is_computed()) || not (LogicParam.is_computed()) + +let not_param_computed () = + not (ByValue.is_computed()) || + not (ByPReference.is_computed()) || + not (ByAReference.is_computed()) + +let not_arg_computed() = + not (ArgPReference.is_computed()) || not (ArgAReference.is_computed()) + +let not_computed () = + not_half_computed () && not_param_computed () && not_arg_computed () + + +let compute () = + match case_of_optimization + (Wp_parameters.LogicVar.get ()) (Wp_parameters.RefVar.get()) with + | Nothing -> () + | Half -> + if not_half_computed() then + (debug + "[COMPUTE] DO address taken table computing"; + compute_logic_params ()) + else () + | All -> + if not_computed () then + begin + debug "[COMPUTE] DO all table computation"; + compute_calls_collection (); + debug "[COMPUTE] DONE all table computation"; + debug "[COMPUTE] DO resolution of formals calls"; + resolved_call_chain_param (); + debug + "[COMPUTE] DONE resolution of formals calls"; + debug + "[COMPUTE] DO resolution of arguments chain calls"; + resolved_call_chain_arg (); + debug + "[COMPUTE] DONE resolution of arguments chain calls"; + debug + "[COMPUTE] resolved address taken equation"; + resolve_addr_taken () + end + else () + +let dispatch_var var = + match case_of_optimization + (Wp_parameters.LogicVar.get ()) (Wp_parameters.RefVar.get()) with + | Nothing -> Cvar + | Half -> + compute(); + if AddrTaken.mem var then Cvar else Fvar + | All -> + compute(); + if is_formal_var_type var then + begin + if ByValue.mem var then + if AddrTaken.mem var then Cvar else Fvar + else + ( try let (n,_) = ByPReference.find var in PRpar n + with Not_found -> + (try let (n,_) = ByAReference.find var in ARpar n + with Not_found -> (* impossible case *) Cvar )) + end + else + begin + if AddrTaken.mem var then Cvar + else + (if ArgAReference.mem var then ARarg + else (if ArgPReference.mem var + then PRarg else Fvar)) + end + +let dispatch_cvar vinfo = dispatch_var (Cv vinfo) +let dispatch_lvar lv = dispatch_var (Lv lv) + +let is_user_formal_in_builtin lv = + try LogicParam.find lv with Not_found -> false + +let is_memvar case vinfo = + match case with + | Nothing -> true + | Half | All -> compute(); AddrTaken.mem (Cv vinfo) + +let is_ref case vinfo = + match case with + | Nothing -> false + | Half -> false + | All -> + compute(); + let cv = Cv vinfo in + if vinfo.vformal then + (try fst (ByPReference.find cv) = 0 with Not_found -> false) + else + (try fst (ArgPReference.find cv) = 0 with Not_found -> false) + +(* let dumped = Cil_datatype.Varinfo.Hashtbl.create 31 *) +(* let dump case x = *) +(* match case with Nothing | Half -> () | All -> *) +(* begin *) +(* compute (); *) +(* if not (Cil_datatype.Varinfo.Hashtbl.mem dumped x) then *) +(* begin *) +(* Cil_datatype.Varinfo.Hashtbl.add dumped x () ; *) +(* let cv = Cv x in *) +(* Format.eprintf "VAR %s" x.vname ; *) +(* if AddrTaken.mem cv then Format.eprintf " addr" ; *) +(* let pp name find = try Format.eprintf " %s:%d" name (fst (find cv)) with Not_found -> () in *) +(* pp "byref" ByPReference.find ; *) +(* pp "byarr" ByAReference.find ; *) +(* pp "fref" ArgPReference.find ; *) +(* pp "farr" ArgAReference.find ; *) +(* Format.eprintf "@." ; *) +(* end *) +(* end *) + +let is_to_scope vinfo = + let case = case_of_optimization + (Wp_parameters.LogicVar.get ()) (Wp_parameters.RefVar.get()) + in + is_ref case vinfo || is_memvar case vinfo + +let precondition_compute () = + if Wp_parameters.RefVar.get () then + begin + compute (); + kernel_functions_separation_hyps () + end + else () + + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/variables_analysis.mli frama-c-20111001+nitrogen+dfsg/src/wp/variables_analysis.mli --- frama-c-20110201+carbon+dfsg/src/wp/variables_analysis.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/variables_analysis.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,90 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** + This analysis performs a classification of the variables of the input + program. The aim of this classification is to optimize the translation + of variables by WP: + 1) optimization of the by-reference call and + 2) functional variables. +**) + +(** + At the end, the analysis associates an [var_kind] information to each + variables: + 1) [Fvar] functional variable, variable such as its address is never + taken, + + 2) [PRarg] by_pointer_reference argument, variable such as its + address is only taken in by reference calls (one or more), + + 3) [ARarg] by_array_reference argument, variable such as its + address is only taken in by array reference calls (one or more), + + 4) [PRpar n] by_pointer_reference parameter of arity , + variable which is a formal parameter use for a by reference call + and can be invoked in a chain of by reference call such as their + arity are less or equal than n, + + 5) [ARpar n] by_array_reference parameter of arity , + variable which is a formal parameter use for a by array reference + call and can be invoked in a chain of by array reference call + such as their arity are less or equal than n, + + 6) [Cvar] other variable. + +**) + +type var_kind = + Fvar | Cvar | PRarg | ARarg | PRpar of int | ARpar of int + + +(** [dispatch_cvar v] returns the var_kind associated to the C variable [v] + according the current optimisations activated.*) +val dispatch_cvar: Cil_types.varinfo -> var_kind + +(** [dispatch_lvar v] returns the var_kind associated to the logic variable [v] + according the current optimisations activated.*) +val dispatch_lvar: Cil_types.logic_var -> var_kind + +(** [is_to_scope v] returns true if [v] has to been scoped into the inner + memory model : cvar of ref*) +val is_to_scope : Cil_types.varinfo -> bool + +(** [precondition_compute ()] adds warnings and precondition suitable + to the current optimisations which are activated *) +val precondition_compute : unit -> unit + +(** [brackets_typ typ] returns the numbre of brackets of the type [typ].*) +val brackets_typ : Cil_types.typ -> int + +(** [is_user_formal_in_builtins lv] tests if the address + of the by-reference formal [lv] of user definition is an argument + of (one or more) ACSL builtin predicate(s) or function : + valid and family, separated, block_length, initialized*) +val is_user_formal_in_builtin : Cil_types.logic_var -> bool + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpAnnot.ml frama-c-20111001+nitrogen+dfsg/src/wp/wpAnnot.ml --- frama-c-20110201+carbon+dfsg/src/wp/wpAnnot.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpAnnot.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,1525 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let dkey = "annot" (* debugging key *) +let debug fmt = Wp_parameters.debug ~dkey fmt + +(* This file groups functions that extract some annotations + * and associates them with CFG edges. *) + +open Cil_types +open Cil_datatype + +(* -------------------------------------------------------------------------- *) +(* --- Global Status --- *) +(* -------------------------------------------------------------------------- *) + +let rte_find rte_st kf = let (_,_,status,_) = !rte_st () in status kf +let rte_precond_status = rte_find Db.RteGen.get_precond_status +let rte_signedOv_status = rte_find Db.RteGen.get_signedOv_status +let rte_divMod_status = rte_find Db.RteGen.get_divMod_status +let rte_downCast_status = rte_find Db.RteGen.get_downCast_status +let rte_memAccess_status = rte_find Db.RteGen.get_memAccess_status +let rte_unsignedOv_status = rte_find Db.RteGen.get_unsignedOv_status + +let rte_wp = + [ + "valid pointer dereferencing" , rte_memAccess_status , "-rte-mem" ; + "division by zero" , rte_divMod_status , "-rte-div" ; + "signed overflow" , rte_signedOv_status , "-rte-signed" ; + "unsigned overflow" , rte_unsignedOv_status , "-rte-unsigned-ov" ; + ] + +let rte_generated kf = + List.for_all (fun (_,rte,_) -> rte kf) rte_wp + +let missing_rte kf = + List.map + (fun (name,_,_) -> name) + (List.filter (fun (_,rte,_) -> not (rte kf)) rte_wp) + +let compute_rte_for kf = + begin + Dynamic.Parameter.Bool.set "-rte" true ; + List.iter (fun (_,_,opt) -> Dynamic.Parameter.Bool.set opt true) rte_wp ; + !Db.RteGen.annotate_kf kf ; + end + +let ip_complete f = Property.ip_complete_of_spec f Kglobal f.spec + +let ip_disjoint f = Property.ip_disjoint_of_spec f Kglobal f.spec + +(* +(* -------------------------------------------------------------------------- *) +(* --- Contract for functions --- *) +(* -------------------------------------------------------------------------- *) + +let wp_contract = + Emitter.create "WP Function" ~correctness:[] ~tuning:[] + +let wp_external = + Emitter.create "WP External Function" ~correctness:[] ~tuning:[] + +let ip_contract f = + let ip_rte = + if not (rte_generated f) then + Wp_parameters.warning ~current:false ~once:true + "Missing RTE guards" ; + [ (*TODO: these dependencies should be put on the emitter at Wpo level *) ] + in + ip_complete f @ ip_disjoint f @ ip_rte + +let ip_external f = + ip_complete f @ ip_disjoint f + +module FunctionContracts = Wprop.Indexed2(Kernel_function)(Datatype.String) + (struct + let name = "WP Function Contracts" + type key = kernel_function * string + let size = 81 + let kind = `Correctness + let dependencies = [ Kernel_function.self ] + let property (kf,model) = + let name = Printf.sprintf + "Function '%s' is consistent with %s" + (Kernel_function.get_name kf) model + in + let ip = Property.ip_other name (Some kf) Kglobal in + match kf.fundec with + | Definition _ -> + Wprop.Proxy( ip , wp_contract , ip_contract kf ) + | Declaration _ -> + Wprop.Proxy( ip , wp_external , ip_external kf ) + end) +*) + +(* -------------------------------------------------------------------------- *) +(* --- Local Preconditions for functions --- *) +(* -------------------------------------------------------------------------- *) + +let wp_preconditions = + Emitter.create "WP Call Preconditions" ~correctness:[] ~tuning:[] + +module PreCondAt = Wprop.Indexed2(Property)(Cil_datatype.Stmt) + (struct + let name = "WP Called Preconditions" + type key = Property.t * stmt + let size = 81 + let kind = `Correctness + let dependencies = [ Kernel_function.self ] + let property (pid,stmt) = + let kf = Kernel_function.find_englobing_kf stmt in + let name = Pretty_utils.to_string (Description.pp_localized ~kf:`Always ~ki:false) pid in + Wprop.Later (Property.ip_other name (Some kf) (Kstmt stmt)) + end) + +module PreCondProxyGenerated = + State_builder.Hashtbl(Property.Hashtbl)(Datatype.Unit) + (struct + let name = "WP Call Preconditions Generated" + let dependencies = [Ast.self] + let kind = `Internal + let size = 97 + end) + +let pre_cond_id = function + | Property.IPCodeAnnot(_,_,p) -> p.annot_id + | Property.IPPredicate(_,_,_,p) -> p.ip_id + | property -> + Wp_parameters.fatal "No precondition id for @[%a@]" Property.pretty property + +let setup_precondition_proxy called_kf precondition = + if not (PreCondProxyGenerated.mem precondition) then + begin + let called_preconditions = + List.map + (fun (_,stmt) -> PreCondAt.property precondition stmt) + (Kernel_function.find_syntactic_callsites called_kf) + in + Property_status.emit + wp_preconditions ~hyps:called_preconditions precondition + Property_status.True ; + PreCondProxyGenerated.add precondition () + end + +(* Properties for kf-preconditions at call-site stmt, IF CREATED only *) +let lookup_called_preconditions_at kf stmt = + let spec = Kernel_function.get_spec kf in + List.fold_left + (fun properties bhv -> + List.fold_left + (fun properties precond -> + let pid_spec = Property.ip_of_requires kf Kglobal bhv precond in + if PreCondAt.mem pid_spec stmt then + let pid_call = PreCondAt.property pid_spec stmt in + pid_call :: properties + else + properties + ) properties bhv.b_requires + ) [] spec.spec_behavior + +(* Properties for kf-preconditions at call-site stmt *) +let get_called_preconditions_at kf stmt = + let spec = Kernel_function.get_spec kf in + List.fold_left + (fun properties bhv -> + List.fold_left + (fun properties precond -> + let pid_spec = Property.ip_of_requires kf Kglobal bhv precond in + let pid_call = PreCondAt.property pid_spec stmt in + pid_call :: properties + ) properties bhv.b_requires + ) [] spec.spec_behavior + +(* Properties for kf-conditions of termination-kind 'tkind' *) +let get_called_postconds (tkind:termination_kind) kf = + let spec = Kernel_function.get_spec kf in + List.fold_left + (fun properties bhv -> + List.fold_left + (fun properties postcond -> + if tkind = fst postcond then + let pid_spec = Property.ip_of_ensures kf Kglobal bhv postcond in + pid_spec :: properties + else properties + ) properties bhv.b_post_cond + ) [] spec.spec_behavior + +let get_called_post_conditions = get_called_postconds Cil_types.Normal +let get_called_exit_conditions = get_called_postconds Cil_types.Exits + +(** Properties for assigns of kf *) +let get_called_assigns kf = + let spec = Kernel_function.get_spec kf in + List.fold_left + (fun properties bhv -> + if Cil.is_default_behavior bhv then + match Property.ip_assigns_of_behavior kf Kglobal bhv with + | None -> properties + | Some ip -> ip :: properties + else properties + ) [] spec.spec_behavior + +(* -------------------------------------------------------------------------- *) +(* --- Status of Unreachable Annotations --- *) +(* -------------------------------------------------------------------------- *) + +let wp_unreachable = + Emitter.create + "Unreachable Annotations" + ~correctness:[] (* TBC *) + ~tuning:[] (* TBC *) + +let set_unreachable pid = + debug + "unreachable annotation %a@." WpPropId.pp_id_name pid; + Property_status.emit + wp_unreachable ~hyps:[] (WpPropId.property_of_id pid) Property_status.True + +(*----------------------------------------------------------------------------*) +(* Proofs *) +(*----------------------------------------------------------------------------*) + +type proof = { + target : Property.t ; + proved : proofpart array ; + mutable dependencies : Property.Set.t ; +} and proofpart = + | Noproof + | Complete + | Parts of Bitvector.t + +let target p = p.target +let dependencies p = Property.Set.elements (Property.Set.remove p.target p.dependencies) + +let create_proof p = + let n = WpPropId.subproofs p in + { + target = WpPropId.property_of_id p ; + proved = Array.create n Noproof ; + dependencies = Property.Set.empty ; + } + +let add_proof pf p hs = + begin + if not (Property.equal (WpPropId.property_of_id p) pf.target) + then Wp_parameters.fatal "Partial proof inconsistency" ; + List.iter + (fun iph -> + if not (WpPropId.is_requires iph) then + pf.dependencies <- Property.Set.add iph pf.dependencies + ) hs ; + let k = WpPropId.subproof_idx p in + match WpPropId.parts_of_id p with + | None -> pf.proved.(k) <- Complete + | Some(p,n) -> + match pf.proved.(k) with + | Complete -> () + | Noproof -> + let bv = Bitvector.create n in + Bitvector.set_range bv 0 (p-1) ; + Bitvector.set_range bv (p+1) (n-1) ; + pf.proved.(k) <- Parts bv + | Parts bv -> + Bitvector.clear bv p ; + if Bitvector.is_empty bv + then pf.proved.(k) <- Complete + end + +let is_composed pf = + Array.length pf.proved > 1 + +let is_proved pf = + try Array.iter (fun r -> if r<>Complete then raise Exit) pf.proved ; true + with Exit -> false + +(* -------------------------------------------------------------------------- *) +(* --- PID for Functions --- *) +(* -------------------------------------------------------------------------- *) + +let mk_call_pre_id called_kf bhv s_call called_pre = + (* TODOclean : quite dirty here ! *) + let id = WpPropId.mk_pre_id called_kf Kglobal bhv called_pre in + let called_pre = WpPropId.property_of_id id in + setup_precondition_proxy called_kf called_pre ; + let called_pre_p = PreCondAt.property called_pre s_call in + WpPropId.mk_call_pre_id called_kf s_call called_pre called_pre_p + +(* -------------------------------------------------------------------------- *) +(* --- Prop Splitter --- *) +(* -------------------------------------------------------------------------- *) + +(* prop-id splitter *) + +let split job pid goals = + let n = Bag.length goals in + if n <= 1 then Bag.iter (job pid) goals else + let k = ref 0 in + Bag.iter + (fun g -> + let pid_k = WpPropId.mk_part pid (!k,n) in + incr k ; job pid_k g) + goals + +(*----------------------------------------------------------------------------*) +(* Strategy and annotations *) +(*----------------------------------------------------------------------------*) + +(* This is to code what kind of properties we want to process. *) +type asked_assigns = NoAssigns | OnlyAssigns | WithAssigns + +(* This is to code which behavior the computed strategy refers to. *) +type asked_bhv = + | FunBhv of funbehavior option (* None means default behavior + when the function has no spec. This is useful to process internal + properties even if the function has no default behavior *) + | StmtBhv of Cil2cfg.node * stmt * funbehavior + +let name_of_asked_bhv = function + | FunBhv (Some bhv) -> bhv.b_name + | FunBhv None -> Cil.default_behavior_name + | StmtBhv (_, _, bhv) -> bhv.b_name + +(* This is to code what properties the user asked for in a given behavior. *) +type asked_prop = + | AllProps + | OnlyPreconds + | NamedProp of string + | IdProp of Property.t + | CallPre of stmt * Property.t option (** No specified property means all *) + +(* a table to keep the information about the statement default specification + * associated with each edge in order to know in which strategy we should put a + * default annotation on this edge. When an edge has no information in the table, + * it means that the edge annotations belong to the [FunBhv] default behavior; + * and when we find a statement [s], it means that they belong to the [StmtBhv s] + * default behavior. The [int] information is only useful to build the table : + * when an edge is included in 2 different [StmtBhv] we only keep the one that + * has the fewer internal edges because it is necessarily included in the other. + *) +module HdefAnnotBhv = Cil2cfg.HE (struct type t = (stmt * int) end) + +(* Finally, a configuration is associated to a strategy computation to + * summarize what is to be computed. *) +type strategy_info = { + kf : Kernel_function.t; + cfg : Cil2cfg.t; + cur_bhv : asked_bhv; + asked_bhvs : asked_bhv list; + asked_prop : asked_prop; + assigns_filter : asked_assigns; + def_annots_info : HdefAnnotBhv.t; +} + +(*----------------------------------------------------------------------------*) +(* Adding things in the stategy *) +(*----------------------------------------------------------------------------*) + +(* Select annotations to take as Hyp/Goal/... *) + +let pp_assigns_mode fmt config = + let str = match config.assigns_filter with + | NoAssigns -> "without assigns" + | OnlyAssigns -> "only with assigns" + | WithAssigns -> "both assigns or not" + in Format.fprintf fmt "%s" str + +let pp_asked_prop fmt config = match config.asked_prop with + | AllProps -> Format.fprintf fmt "all properties" + | OnlyPreconds -> Format.fprintf fmt "main preconditions" + | NamedProp s -> Format.fprintf fmt "properties %s" s + | IdProp p -> Format.fprintf fmt "property %s" (WpPropId.id_prop_txt p) + | CallPre (s, Some p) -> Format.fprintf fmt "pre %s at stmt %a" + (WpPropId.id_prop_txt p) Stmt.pretty_sid s + | CallPre (s, None) -> Format.fprintf fmt "all call preconditions at stmt %a" + Stmt.pretty_sid s + +let pp_strategy_info fmt config = + Format.fprintf fmt "'%a', " Kernel_function.pretty config.kf; + let _ = match config.cur_bhv with + | FunBhv _bhv -> + Format.fprintf fmt "behavior '%s'" (name_of_asked_bhv config.cur_bhv) + | StmtBhv (_, s, bhv) -> + Format.fprintf fmt "behavior '%s' of statement %d" bhv.b_name s.sid + in Format.fprintf fmt ", %a, %a" + pp_asked_prop config pp_assigns_mode config + +let cur_fct_default_bhv config = match config.cur_bhv with + | FunBhv None -> true + | FunBhv (Some bhv) -> bhv.b_name = Cil.default_behavior_name + | _ -> false + +let filter_status id = + Wp_parameters.StatusAll.get () || + match Property_status.get (WpPropId.property_of_id id) with + | Property_status.Best(Property_status.True, _) -> + Wp_parameters.StatusTrue.get () + | Property_status.Best(Property_status.Dont_know, _) -> + Wp_parameters.StatusMaybe.get () + | Property_status.Best((Property_status.False_if_reachable + | Property_status.False_and_reachable), _) -> + Wp_parameters.StatusFalse.get () + | Property_status.Never_tried -> true + | Property_status.Inconsistent _ -> false + +let filter_precond pid = + match WpPropId.property_of_id pid with + | Property.IPPredicate( Property.PKRequires _ , _ , Kglobal , _ ) -> true + | _ -> false + +let goal_to_select config pid = + let asked, take_it = + match config.assigns_filter, WpPropId.property_of_id pid with + | NoAssigns, Property.IPAssigns _ -> + "no assigns", false + | (OnlyAssigns | WithAssigns), Property.IPAssigns _ -> + "", true + | OnlyAssigns, _ -> "only assigns", false + | (NoAssigns | WithAssigns), _ -> "", true + in + let asked, (take_it, msg) = + if take_it then begin + match config.asked_prop with + | AllProps -> + "all", + if not (filter_status pid) + then false, " (skipped w.r.t status)" + else true, " (selected)" + | OnlyPreconds -> + "main precondition", + if not (filter_status pid) || not (filter_precond pid) + then false, " (main precondition only)" + else true, " (selected)" + | IdProp idp -> + (* Notice that if the user has explicitly selected a property, + * we consider it as a goal even if it has been proved already *) + (WpPropId.id_prop_txt idp), + (Property.equal (WpPropId.property_of_id pid) idp, "") + | CallPre (s_call, asked_pre) -> + let take_it, msg = WpPropId.select_call_pre s_call asked_pre pid in + let pre_txt = match asked_pre with None -> "all pre " + | Some pre -> WpPropId.id_prop_txt pre + in + pre_txt ^ " at stmt " ^ (string_of_int s_call.sid), + (take_it, msg) + | NamedProp str -> str, WpPropId.select_by_name str pid + end + else asked, (take_it, "") + in + debug "[goal_to_select] %s vs %a -> %s%s@." + asked WpPropId.pp_id_name pid (if take_it then "select" else "ignore") msg; + take_it + +(*----------------------------------------------------------------------------*) +(* Add properties *) + +(* TODO: still have to remove these fonctions... *) + +let kind_to_select config kind id = match kind with + | WpStrategy.Agoal -> + if goal_to_select config id then Some WpStrategy.Agoal else None + | WpStrategy.Aboth goal -> + let goal = goal && goal_to_select config id in + Some (WpStrategy.Aboth goal) + | WpStrategy.AcutB goal -> + let goal = goal && goal_to_select config id in + Some (WpStrategy.AcutB goal) + | WpStrategy.AcallPre goal -> + let goal = goal && goal_to_select config id in + Some (WpStrategy.AcallPre goal) + | WpStrategy.Ahyp | WpStrategy.AcallHyp -> Some kind + +let add_prop_inv_establish config acc kind s ca p = + let id = WpPropId.mk_establish_id config.kf s ca in + match kind_to_select config kind id with None -> acc + | Some kind -> WpStrategy.add_prop_loop_inv acc kind s id p + +let add_prop_inv_preserve config acc kind s ca p = + let id = WpPropId.mk_preserve_id config.kf s ca in + match kind_to_select config kind id with None -> acc + | Some kind -> WpStrategy.add_prop_loop_inv acc kind s id p + +let add_prop_inv_fixpoint config acc kind s ca p = + let id = WpPropId.mk_inv_hyp_id config.kf s ca in + match kind_to_select config kind id with None -> acc + | Some kind -> WpStrategy.add_prop_loop_inv acc kind s id p + +(*----------------------------------------------------------------------------*) +(* Add Assigns *) + +let add_loop_assigns_goal config s (ca, assigns) acc = + let id = WpPropId.mk_loop_assigns_id config.kf s ca assigns in + match id with + None -> acc + | Some id -> + if goal_to_select config id then + let labels = NormAtLabels.labels_loop_assigns s in + let assigns' = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_loop_assigns_desc s assigns' in + WpStrategy.add_assigns acc WpStrategy.Agoal id a_desc + else acc + +let add_stmt_assigns_goal config s acc b l_post = match b.b_assigns with + | WritesAny -> acc + | Writes assigns -> + let id = WpPropId.mk_stmt_assigns_id config.kf s b assigns in + match id with + | None -> acc + | Some id -> + if goal_to_select config id then + let labels = NormAtLabels.labels_stmt_assigns s l_post in + let assigns = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_stmt_assigns_desc s assigns in + WpStrategy.add_assigns acc WpStrategy.Agoal id a_desc + else acc + +let add_fct_assigns_goal config acc tkind b = match b.b_assigns with + | WritesAny -> acc + | Writes assigns -> + let id = WpPropId.mk_fct_assigns_id config.kf b tkind assigns in + match id with + | None -> acc + | Some id -> + if goal_to_select config id then + let labels = NormAtLabels.labels_fct_assigns in + let assigns' = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_kf_assigns_desc assigns' in + WpStrategy.add_assigns acc WpStrategy.Agoal id a_desc + else acc + +(* ------------------------------------------------------------------------ *) +(* --- Get annotations according to the behavior --- *) +(* ------------------------------------------------------------------------ *) + +(** find the behavior named [name] in the list *) +let get_named_bhv name bhv_list = + try Some (List.find (fun b -> b.b_name = name) bhv_list) + with Not_found -> None + +(** Select in [bhv_list] the behavior that has to be processed + * according to [config] and [ki] current statement. *) +let get_behav config ki bh_list = match config.cur_bhv, ki with + | FunBhv _, Kglobal -> + get_named_bhv (name_of_asked_bhv config.cur_bhv) bh_list + | StmtBhv (_, s1, b), Kstmt s2 when s1.sid = s2.sid -> + get_named_bhv b.b_name bh_list + | _ -> None + +(** Tells weather the property belonging to the behaviors in [bhv_name_list] + * has to be considered according to [config]. *) +type test_behav_res = + | TBRno (* [cur_bhv] is not concerned *) + | TBRhyp (* the property belongs to [default_behavior], + but not to [cur_bhv] : it doesn't have to be a Goal + but can be considered as an hypothesis. *) + | TBRpart (* the property has to be taken as a Goal, but even if it is + proved for every [asked_bhvs], it will still be a partial proof. + TODO: use this to generate PKPartial ! *) + | TBRok (* Select as a Goal *) + +(** (see [test_behav_res] above). + * If the annotation doesn't have "for" names, it is a bit complicated because + * we have to know if the statement [s] is inside a stmt behavior or not. *) +let is_annot_for_config config node s_annot bhv_name_list = + let edges_before = Cil2cfg.pred_e config.cfg node in + debug "[is_annot_for_config] at sid:%d for %a ? @." + s_annot.sid (Wp_error.pp_string_list ~sep:" " ~empty:"<default>") + bhv_name_list; + let hyp_but_not_at_post n = (* don't take assert at post pgpt (see #564) *) + let s_post = match Cil2cfg.get_post_edges config.cfg n with + | [] -> None + | e::_ -> Cil2cfg.get_edge_next_stmt config.cfg e + in match s_post with + | Some s_post when s_post.sid = s_annot.sid -> TBRno + | _ -> TBRhyp + in + let res = match bhv_name_list with + | [] -> (* no spec 'for' in the property *) + begin + let e = match edges_before with + | e::_ -> e + | _ -> Wp_parameters.fatal "annot with no edge ?" + in + match config.cur_bhv with + | FunBhv _ when cur_fct_default_bhv config -> + begin + try + let _ = HdefAnnotBhv.find config.def_annots_info e in + TBRhyp + with Not_found -> TBRok + end + | StmtBhv (n, sb, b) when b.b_name = Cil.default_behavior_name -> + begin + try + let s,_ = HdefAnnotBhv.find config.def_annots_info e in + if s.sid = sb.sid then TBRok + else raise Not_found + with Not_found -> hyp_but_not_at_post n + end + | FunBhv _ -> TBRhyp + | StmtBhv (n,_,_) -> hyp_but_not_at_post n + end + | bhvs -> (* TODOopt : there is surely a better way to do this : *) + let asked_bhv = name_of_asked_bhv config.cur_bhv in + let goal = List.exists (fun bl -> bl = asked_bhv) bhvs in + if goal then + let full = (* TODO *) true + (* List.for_all (fun bl -> is_in bl config.asked_bhvs) bhvs *) + in (if full then TBRok else TBRpart) + else TBRno + in debug "[is_annot_for_config] -> %s@." + (match res with TBRok -> "ok" | TBRhyp -> "hyp" | TBRno -> "no" + | TBRpart -> "part"); + res + +let get_bhv_assumes spec l = + let rec get_assumes bhv_names = match bhv_names with [] -> [] + | bhv::tl -> + let l = match get_named_bhv bhv spec.spec_behavior with + | None -> Wp_parameters.warning "no %s behavior !?!?" bhv; + get_assumes tl + | Some b -> + (Ast_info.behavior_assumes b)::(get_assumes tl) + in l + in get_assumes l + +let add_fct_pre config acc spec = + let kf = config.kf in + let add_bhv_pre_hyp b acc = + let impl_assumes = false in + let kind = WpStrategy.Ahyp in + WpStrategy.add_prop_fct_bhv_pre acc kind kf b ~impl_assumes + in + let add_def_pre_hyp acc = + match Cil.find_default_behavior spec with None -> acc + | Some bdef -> add_bhv_pre_hyp bdef acc + in + let acc = match get_behav config Kglobal spec.spec_behavior with + | None -> add_def_pre_hyp acc + | Some b -> + let acc = + if not (Cil.is_default_behavior b) then add_def_pre_hyp acc else acc + in + let acc = + if WpStrategy.is_main_init kf then + let add_both acc p = + let id = WpPropId.mk_pre_id kf Kglobal b p in + let goal = goal_to_select config id in + let kind = WpStrategy.Aboth goal in + WpStrategy.add_prop_fct_pre acc kind kf b ~assumes:None p + in + let acc = List.fold_left add_both acc b.b_requires in + let add_hyp acc p = + let kind = WpStrategy.Ahyp in + WpStrategy.add_prop_fct_pre acc kind kf b ~assumes:None p + in List.fold_left add_hyp acc b.b_assumes + else add_bhv_pre_hyp b acc + in acc + in acc + + +let add_variant acc spec = (* TODO *) + let _ = match spec.spec_variant with None -> () + | Some v -> + Wp_parameters.warning "Ignored 'decrease' specification:@, %a@." + Cil.d_decreases v + in acc + +let add_terminates acc spec = (* TODO *) + let _ = match spec.spec_terminates with None -> () + | Some p -> Wp_parameters.warning + "Ignored 'terminates' specification:@, %a@." + !Ast_printer.d_predicate_named + (Logic_const.pred_of_id_pred p) + in acc + +let add_disjoint_behaviors_props config ki spec acc = + match spec.spec_disjoint_behaviors with [] -> acc + | l -> + let add_disj acc bhv_names = + let id = WpPropId.mk_disj_bhv_id (config.kf, ki, bhv_names) in + if goal_to_select config id then + begin + let prop = Ast_info.disjoint_behaviors spec bhv_names in + let labels = match ki with + | Kglobal -> NormAtLabels.labels_fct_pre + | Kstmt s -> NormAtLabels.labels_stmt_pre s + in WpStrategy.add_prop acc WpStrategy.Agoal labels id prop + end + else acc + in List.fold_left add_disj acc l + +let add_complete_behaviors_props config ki spec acc = + match spec.spec_complete_behaviors with [] -> acc + | l -> + let mk_prop acc bhv_names = + let id = WpPropId.mk_compl_bhv_id (config.kf, ki, bhv_names) in + if goal_to_select config id then + let prop = Ast_info.complete_behaviors spec bhv_names in + let labels = match ki with + | Kglobal -> NormAtLabels.labels_fct_pre + | Kstmt s -> NormAtLabels.labels_stmt_pre s + in WpStrategy.add_prop acc WpStrategy.Agoal labels id prop + else acc + in List.fold_left mk_prop acc l + +let add_behaviors_props config ki spec acc = + let add = match config.cur_bhv, ki with + | FunBhv _, Kglobal when cur_fct_default_bhv config -> true + | StmtBhv (_, cur_s, b), Kstmt s + when (s.sid = cur_s.sid && b.b_name = Cil.default_behavior_name) -> true + | _ -> false + in + if add then + let acc = add_complete_behaviors_props config ki spec acc in + let acc = add_disjoint_behaviors_props config ki spec acc in + acc + else acc + +(** Add the post condition of the whole spec as hypothesis. +* Add [old(assumes) => ensures] for all the behaviors, +* and also add an upper approximation of the merged assigns information. *) +let add_stmt_spec_post_as_hyp config v s spec acc = + let l_post = Cil2cfg.get_post_logic_label config.cfg v in + let add_bhv_post acc b = + let assumes = Some (Ast_info.behavior_assumes b) in + let add tk acc p = + WpStrategy.add_prop_stmt_post acc WpStrategy.Ahyp config.kf + s b tk l_post ~assumes p + in + let p_acc, e_acc = + WpStrategy.fold_bhv_post_cond ~warn:false (add Normal) (add Exits) acc b + in let p_acc = + WpStrategy.add_stmt_spec_assigns_hyp p_acc config.kf s l_post spec in + (* let e_acc = TODO, but crach at the moment... why ? + * add_spec_assigns_hyp config ki l_post e_acc spec in *) + p_acc, e_acc + in List.fold_left add_bhv_post acc spec.spec_behavior + +(** we want to prove this behavior: +* - add the requires as preconditions to both prove and use as hyp, +* - add the assumes as hypotheses, +* - add the postconditions as goals. +*) +let add_stmt_bhv_as_goal config v s b (b_acc, (p_acc, e_acc)) = + let l_post = Cil2cfg.get_post_logic_label config.cfg v in + let assumes = None in (* [assumes] are used as separate hypotheses *) + let add_pre_hyp acc p = + WpStrategy.add_prop_stmt_pre acc WpStrategy.Ahyp config.kf s b ~assumes p + in + let add_pre_goal acc p = + let id = WpPropId.mk_pre_id config.kf (Kstmt s) b p in + let goal = goal_to_select config id in + let kind = WpStrategy.Aboth goal in + WpStrategy.add_prop_stmt_pre acc kind config.kf s b ~assumes p + in + let add_post tk acc p = + let id = WpPropId.mk_stmt_post_id config.kf s b (tk, p) in + let goal = goal_to_select config id in + let kind = WpStrategy.Aboth goal in + WpStrategy.add_prop_stmt_post acc kind config.kf s b tk l_post ~assumes p + in + + let b_acc = List.fold_left add_pre_goal b_acc b.b_requires in + let b_acc = List.fold_left add_pre_hyp b_acc b.b_assumes in + + let p_acc, e_acc = WpStrategy.fold_bhv_post_cond ~warn:true + (add_post Normal) (add_post Exits) (p_acc, e_acc) b + in + let p_acc = add_stmt_assigns_goal config s p_acc b l_post in + (*let e_acc = TODO, but crach at the moment... why ? + add_stmt_assigns config s e_acc b l_post in *) + b_acc, (p_acc, e_acc) + +let add_stmt_spec_annots config v s spec ((b_acc, (p_acc, e_acc)) as acc) = + let acc = add_variant acc spec in + let acc = add_terminates acc spec in + match config.cur_bhv with + | StmtBhv (_n, cur_s, b) when s.sid = cur_s.sid -> + (* + begin match get_behav config (Kstmt s) spec.spec_behavior with + | None -> (* in some cases, it seems that we can have several spec + for the same statement -> not an error *) acc + | Some b -> + *) + let b_acc, a_acc = add_stmt_bhv_as_goal config v s b acc in + let b_acc = add_behaviors_props config (Kstmt s) spec b_acc in + b_acc, a_acc + | _ -> (* in all other cases, use the specification as hypothesis *) + let kind = WpStrategy.Aboth false in + let b_acc = + WpStrategy.add_prop_stmt_spec_pre b_acc kind config.kf s spec + in + let p_acc, e_acc = + add_stmt_spec_post_as_hyp config v s spec (p_acc, e_acc) + in b_acc, (p_acc, e_acc) + +(*----------------------------------------------------------------------------*) +(* Call annotations *) +(*----------------------------------------------------------------------------*) + +let add_called_pre config called_kf s spec = + debug "[add_called_pre] for %a@." + Kernel_function.pretty called_kf; + let add_behav acc b = (* pre for behavior is [assumes => requires] *) + let assumes = (Ast_info.behavior_assumes b) in + let add_pre acc pre = + let id = mk_call_pre_id called_kf b s pre in + let kind = WpStrategy.AcallPre (goal_to_select config id) in + WpStrategy.add_prop_call_pre acc kind id ~assumes pre + in List.fold_left add_pre acc b.b_requires + in + let acc = + List.fold_left add_behav WpStrategy.empty_acc spec.spec_behavior + in + if acc = WpStrategy.empty_acc then + debug "no called precond for %a@." + Kernel_function.pretty called_kf; + acc + +let add_called_post called_kf termination_kind = + let spec = Kernel_function.get_spec called_kf in + debug "[add_called_post] '%s' for %a@." + (WpPropId.string_of_termination_kind termination_kind) + Kernel_function.pretty called_kf; + let add_behav acc b = + (* post for behavior is [\old(assumes) => ensures] *) + let kind = WpStrategy.AcallHyp in + let assumes = (Ast_info.behavior_assumes b) in + let add_post acc (tk, p) = + if tk = termination_kind + then WpStrategy.add_prop_call_post acc kind called_kf b tk ~assumes p + else acc + in List.fold_left add_post acc b.b_post_cond + in + let acc = List.fold_left add_behav WpStrategy.empty_acc spec.spec_behavior in + if acc = WpStrategy.empty_acc then + debug "no called %s postcondition for %a@." + (WpPropId.string_of_termination_kind termination_kind) + Kernel_function.pretty called_kf; + acc + +let get_call_annots config v s fct = + let l_post = Cil2cfg.get_post_logic_label config.cfg v in + match WpStrategy.get_called_kf fct with + | Some kf -> + let spec = Kernel_function.get_spec kf in + let before_annots = + if rte_precond_status config.kf then WpStrategy.empty_acc + else add_called_pre config kf s spec + in + let post_annots = add_called_post kf Normal in + let post_annots = + WpStrategy.add_call_assigns_hyp post_annots config.kf s + l_post (Some spec) + in + let exits_annots = add_called_post kf Exits in + before_annots, (post_annots, exits_annots) + + | None -> + Wp_parameters.warning + "call through function pointer not implemented yet: \ + ignore called function properties."; + let assigns_annots = + WpStrategy.add_call_assigns_hyp WpStrategy.empty_acc config.kf s + l_post None + in WpStrategy.empty_acc, (assigns_annots, assigns_annots) + +(*----------------------------------------------------------------------------*) +let add_variant_annot config s ca var_exp loop_entry loop_back = + let (vpos_id, vpos), (vdecr_id, vdecr) = + WpStrategy.mk_variant_properties config.kf s ca var_exp + in + let add acc kind id p = + WpStrategy.add_prop_loop_inv acc kind s id p + in + let add_hyp acc = + let acc = add acc WpStrategy.Ahyp vdecr_id vdecr in + add acc WpStrategy.Ahyp vpos_id vpos + in + let add_goal acc = + let acc = + if goal_to_select config vdecr_id then + add acc WpStrategy.Agoal vdecr_id vdecr + else acc + in if goal_to_select config vpos_id then + add acc WpStrategy.Agoal vpos_id vpos + else acc + in + let loop_back = + if cur_fct_default_bhv config then add_goal loop_back else add_hyp loop_back + (*TODO: what about variant establishment ??? It seems that [0<v)] is not + * proved by induction anymore. Why ? *) + in loop_entry, loop_back + +let add_loop_invariant_annot config vloop s ca b_list inv acc = + let assigns, loop_entry, loop_back , loop_core = acc in + (* we have to prove that inv is true for each edge that goes + * in the loop, so we can assume that inv is true for each edge + * starting from this point. *) + match is_annot_for_config config vloop s b_list with + | TBRok + | TBRpart (* TODO: PKPartial *) + -> + if Wp_parameters.Invariants.get() then begin + let loop_core = add_prop_inv_fixpoint config loop_core + (WpStrategy.AcutB true) s ca inv + in assigns, loop_entry , loop_back , loop_core + end + else begin + let loop_entry = add_prop_inv_establish config loop_entry + WpStrategy.Agoal s ca inv in + let loop_back = add_prop_inv_preserve config loop_back + WpStrategy.Agoal s ca inv in + let loop_core = add_prop_inv_fixpoint config loop_core + WpStrategy.Ahyp s ca inv in + assigns, loop_entry , loop_back , loop_core + end + | TBRhyp -> (* TODO : add more inv hyp ? *) + let kind = + if Wp_parameters.Invariants.get() + then (WpStrategy.AcutB false) else WpStrategy.Ahyp + in + let loop_core = + add_prop_inv_fixpoint config loop_core kind s ca inv + in assigns, loop_entry , loop_back , loop_core + | TBRno -> acc + +let add_stmt_invariant_annot config v s ca b_list inv ((b_acc, a_acc) as acc) = + let add_to_acc k = + let b_acc = add_prop_inv_fixpoint config b_acc k s ca inv in + (b_acc, a_acc) + in + let acc = + match is_annot_for_config config v s b_list with + | TBRok | TBRpart -> add_to_acc (WpStrategy.AcutB true) + | TBRhyp -> add_to_acc (WpStrategy.AcutB false) + | TBRno -> acc + in acc + + +(** Returns the annotations for the three edges of the loop node: + * - loop_entry : goals for the edge entering in the loop + * - loop_back : goals for the edge looping to the entry point + * - loop_core : fix-point hypothesis for the edge starting the loop core + *) +let get_loop_annots config vloop s = + let do_annot a (assigns, loop_entry, loop_back , loop_core as acc) = + let ca = match a with User ca | AI (_, ca) -> ca in + match ca.annot_content with + | AInvariant (b_list, true, inv) -> + add_loop_invariant_annot config vloop s ca b_list inv acc + | AVariant (var_exp, None) -> + let loop_entry, loop_back = + add_variant_annot config s ca var_exp loop_entry loop_back + in assigns, loop_entry , loop_back , loop_core + | AVariant (_v, _rel) -> + Wp_parameters.warning "Ignoring loop variant with measure : %a" + !Ast_printer.d_code_annotation ca; + acc + | AAssigns (_,WritesAny) -> assert false + | AAssigns (b_list, Writes a) -> (* loop assigns *) + let h_assigns, g_assigns = assigns in + let check_assigns old cur = + match old with + None -> Some cur + | Some _ -> + Wp_parameters.fatal + "At most one loop assigns can be associated to a behavior" + in + let assigns = + match is_annot_for_config config vloop s b_list with + | TBRok | TBRpart -> + check_assigns h_assigns (ca,a), check_assigns g_assigns (ca,a) + | TBRhyp -> + check_assigns h_assigns (ca,a), g_assigns + | TBRno -> assigns + in (assigns, loop_entry , loop_back , loop_core) + | _ -> acc (* see get_stmt_annots *) + in + let acc = ((None,None), + WpStrategy.empty_acc, WpStrategy.empty_acc, WpStrategy.empty_acc) + in + let (h_assigns, g_assigns), loop_entry , loop_back , loop_core = + Annotations.single_fold_stmt do_annot s acc + in + let loop_back = match g_assigns with + | None -> loop_back + | Some a -> add_loop_assigns_goal config s a loop_back + in + let loop_core = + WpStrategy.add_loop_assigns_hyp loop_core config.kf s h_assigns + in (loop_entry , loop_back , loop_core) + +let get_stmt_annots config v s = + let do_annot a ((b_acc, (a_acc, e_acc)) as acc) = + let ca = Annotations.get_code_annotation a in + match ca.annot_content with + | AInvariant (b_list, loop_inv, inv) -> + if loop_inv then (* see get_loop_annots *) acc + else if Wp_parameters.Invariants.get() then + add_stmt_invariant_annot config v s ca b_list inv acc + else begin + Wp_parameters.warning + "ignored 'invariant' (use -wp-invariants option) : %a" + !Ast_printer.d_code_annotation ca; + acc + end + | AAssert (b_list,p) -> + let kf = config.kf in + let acc = match is_annot_for_config config v s b_list with + | TBRno -> acc + | TBRhyp -> + let b_acc = + WpStrategy.add_prop_assert b_acc WpStrategy.Ahyp kf s ca p + in (b_acc, (a_acc, e_acc)) + | TBRok | TBRpart -> + let id = WpPropId.mk_assert_id config.kf s ca in + let kind = WpStrategy.Aboth (goal_to_select config id) in + let b_acc = WpStrategy.add_prop_assert b_acc kind kf s ca p in + (b_acc, (a_acc, e_acc)) + in acc + | AAssigns (_b_list, _assigns) -> + (* loop assigns: see get_loop_annots *) acc + | AVariant (_v, _rel) -> (* see get_loop_annots *) acc + | APragma _ -> + Wp_parameters.warning "Ignored annotation:@ %a" + !Ast_printer.d_code_annotation ca; + acc + | AStmtSpec (b_list, spec) -> + if b_list <> [] then (* TODO ! *) + Wp_parameters.warning + "Ignored 'for %a' (generalize to all behavior)" + (Pretty_utils.pp_list ~sep:", " Format.pp_print_string) + b_list; + add_stmt_spec_annots config v s spec acc + in + let before_acc = WpStrategy.empty_acc in + let after_acc = WpStrategy.empty_acc in + let exits_acc = WpStrategy.empty_acc in + let acc = before_acc, (after_acc, exits_acc) in + Annotations.single_fold_stmt do_annot s acc + +let get_fct_pre_annots config spec = + let acc = WpStrategy.empty_acc in + let acc = add_fct_pre config acc spec in + let acc = add_behaviors_props config Kglobal spec acc in + let acc = add_variant acc spec in + let acc = add_terminates acc spec in + acc + +let get_fct_post_annots config tkind spec = + let acc = WpStrategy.empty_acc in + match get_behav config Kglobal spec.spec_behavior with + | None -> acc + | Some b -> + (* add the postconditions *) + let f_nothing () _ = () in + let add tk acc p = + let id = WpPropId.mk_fct_post_id config.kf b (tk, p) in + if goal_to_select config id then + WpStrategy.add_prop_fct_post acc WpStrategy.Agoal config.kf b tk p + else acc + in + let acc = match tkind with + | Normal -> + let acc, _ = + WpStrategy.fold_bhv_post_cond ~warn:true (add Normal) f_nothing (acc, ()) b + in acc + | Exits -> + let _, acc = + WpStrategy.fold_bhv_post_cond ~warn:false f_nothing (add Exits) ((), acc) b + in acc + | _ -> assert false + in (* also add the [assigns] *) + let acc = + if Kernel_function.is_definition config.kf + then add_fct_assigns_goal config acc tkind b + else WpStrategy.add_fct_bhv_assigns_hyp acc config.kf tkind b + in acc + +(*----------------------------------------------------------------------------*) +(* Build graph annotation for the strategy *) +(*----------------------------------------------------------------------------*) + +(** Builds tables that give hypotheses and goals relative to [b] behavior + * for edges of the cfg to consider during wp computation. + * [b = None] means that we only consider internal properties to select for the + * default behavior. This is useful when the function doesn't have any + * specification. + * @param asked_prop = Some id -> select only this goal (use all hyps). + *) +let get_behavior_annots config = + debug "build strategy for %a@." pp_strategy_info config; + let cfg = config.cfg in + let spec = Kernel_function.get_spec config.kf in + let annots = WpStrategy.create_tbl () in + + let get_node_annot v = + debug "get_node_annot for node %a" Cil2cfg.pp_node v; + match Cil2cfg.node_type v with + | Cil2cfg.Vstart | Cil2cfg.Vend -> () + + | Cil2cfg.VfctIn -> + let pre = get_fct_pre_annots config spec in + WpStrategy.add_on_edges annots pre (Cil2cfg.succ_e cfg v) + + | Cil2cfg.VfctOut -> + let post = get_fct_post_annots config Normal spec in + WpStrategy.add_on_edges annots post (Cil2cfg.succ_e cfg v) + + | Cil2cfg.Vexit -> + let post = get_fct_post_annots config Exits spec in + WpStrategy.add_on_edges annots post (Cil2cfg.succ_e cfg v) + + | Cil2cfg.VblkIn (Cil2cfg.Bstmt s, _) + | Cil2cfg.Vstmt s + | Cil2cfg.Vswitch (s,_) | Cil2cfg.Vtest (true, s, _) + -> + let stmt_annots = get_stmt_annots config v s in + WpStrategy.add_node_annots annots cfg v stmt_annots + + | Cil2cfg.Vcall (s,_,fct,_) -> + let stmt_annots = get_stmt_annots config v s in + WpStrategy.add_node_annots annots cfg v stmt_annots; + let call_annots = get_call_annots config v s fct in + WpStrategy.add_node_annots annots cfg v call_annots + + | Cil2cfg.Vloop (_, s) -> + let stmt_annots = get_stmt_annots config v s in + let before, _after = stmt_annots in + (* TODO: what about after ? *) + WpStrategy.add_loop_annots annots cfg v ~entry:before + ~back:WpStrategy.empty_acc ~core:WpStrategy.empty_acc; + debug "add_loop_annots stmt ok"; + let (entry , back , core) = get_loop_annots config v s in + debug "get_loop_annots ok"; + WpStrategy.add_loop_annots annots cfg v ~entry ~back ~core + + | Cil2cfg.Vloop2 _ -> (* nothing to do *) () + | Cil2cfg.VblkIn (_, _) | Cil2cfg.VblkOut (_, _) -> (* nothing *) () + | Cil2cfg.Vtest (false, _s, _) -> (* done in Cil2cfg.Vtest (true) *) () + in + Cil2cfg.iter_nodes get_node_annot cfg; + annots + +(* ------------------------------------------------------------------------ *) +(* --- Global Properties --- *) +(* ------------------------------------------------------------------------ *) + +let add_global_annotations annots = + let globs = Globals.Annotations.get_all () in + let globs = List.map (fun (g, _generated) -> g) globs in + let rec do_g g = + let (source,_) = Cil_datatype.Global_annotation.loc g in + match g with + | Daxiomatic (_ax_name, globs,_) -> do_globs globs + | Dvolatile _ -> + (* nothing to do *) () + | Dfun_or_pred _ -> + (* will be processed while translation is needed *) () + | Dtype _ -> + (* will be processed while translation is needed *) () + | Dtype_annot (linfo,_) -> + Wp_parameters.warning ~source + "Type invariant not handled yet ('%s' ignored)" + linfo.l_var_info.lv_name; + () + | Dmodel_annot (linfo,_) -> + Wp_parameters.warning ~source + "Model fields not handled yet (model field '%s' ignored)" + linfo.l_var_info.lv_name; + () + | Dinvariant (linfo,_) -> + Wp_parameters.warning ~source + "Global invariant not handled yet ('%s' ignored)" + linfo.l_var_info.lv_name; + () + | Dlemma (name, is_axiom, labels, _, pred,_) -> + if not is_axiom then + Wp_parameters.warning ~once:true ~source + "Proof obligation for property '%s' not generated." name ; + WpStrategy.add_axiom annots name labels pred + and do_globs globs = List.iter do_g globs in + do_globs globs; + annots + +(* ------------------------------------------------------------------------ *) +(* --- Main functions to build the strategies --- *) +(* ------------------------------------------------------------------------ *) + +let behavior_name_of_config config = + match config.cur_bhv with + | FunBhv None -> None + | FunBhv (Some b) when b.b_name = Cil.default_behavior_name -> None + | FunBhv (Some b) -> Some b.b_name + | StmtBhv (_, s, b) when b.b_name = Cil.default_behavior_name -> + Some ("default_for_stmt_"^(string_of_int s.sid))(*TODO better name ?*) + | StmtBhv (_, s, b) -> Some (b.b_name^"_stmt_"^(string_of_int s.sid)) + +let build_bhv_strategy config = + let annots = get_behavior_annots config in + let annots = add_global_annotations annots in + let desc = Pretty_utils.sfprintf "%a" pp_strategy_info config in + let new_loops = Wp_parameters.Invariants.get() in + WpStrategy.mk_strategy desc config.cfg (behavior_name_of_config config) + new_loops WpStrategy.SKannots annots + +(* Visit the CFG to find all the internal statement specifications. + * (see [HdefAnnotBhv] documentation for infomation about this table). + *) +let internal_function_behaviors cfg = + let def_annot_bhv = HdefAnnotBhv.create 42 in + let get_stmt_bhv node stmt acc = + let add_bhv_info acc b = + if b.b_name = Cil.default_behavior_name then + begin + let _, int_edges = Cil2cfg.get_internal_edges cfg node in + let n = Cil2cfg.Eset.cardinal int_edges in + let reg e = + try + let (_old_s, old_n) = HdefAnnotBhv.find def_annot_bhv e in + if n < old_n then + (* new spec is included in the old one : override. *) + raise Not_found + with Not_found -> + HdefAnnotBhv.replace def_annot_bhv e (stmt, n) + in + Cil2cfg.Eset.iter reg int_edges + end; + (node, stmt, b)::acc + in + let spec_bhv_names acc annot = match annot with + | {annot_content = AStmtSpec (_,spec)} -> + List.fold_left add_bhv_info acc spec.spec_behavior + | _ -> Wp_parameters.fatal "filter on is_contract didn't work ?" + in + let annots = Annotations.get_filter Logic_utils.is_contract stmt in + let annots = List.map Annotations.get_code_annotation annots in + List.fold_left spec_bhv_names acc annots + in + let get_bhv n ((seen_stmts, bhvs) as l) = + match Cil2cfg.start_stmt_of_node n with None -> l + | Some s -> + if List.mem s.sid seen_stmts then l + else + let seen_stmts = s.sid::seen_stmts in + let bhvs = get_stmt_bhv n s bhvs in + (seen_stmts, bhvs) + in + let _, bhvs = Cil2cfg.fold_nodes get_bhv cfg ([], []) in + bhvs, def_annot_bhv + + +(** empty [bhv_names] means all (whatever [ki] is) *) +let find_behaviors kf cfg ki bhv_names = + let spec = Kernel_function.get_spec kf in + let f_bhvs = spec.spec_behavior in + let s_bhvs, def_annot_bhv = internal_function_behaviors cfg in + + let add_fct_bhv (def, acc) b = + let add () = + let def = if Cil.is_default_behavior b then true else def in + def, (FunBhv (Some b))::acc + in + if bhv_names = [] then add() + else match ki with + | None (* not specified ki *) | Some Kglobal -> + if List.mem b.b_name bhv_names then add () else (def, acc) + | Some Kstmt _ -> def, acc + in + + let add_stmt_bhv acc (n,s,b) = + if bhv_names = [] then (StmtBhv (n,s,b))::acc + else if List.mem b.b_name bhv_names then + let acc = match ki with + | None -> (* not specified ki *) (StmtBhv (n, s, b))::acc + | Some (Kstmt stmt) when stmt.sid = s.sid -> + (StmtBhv (n, s, b))::acc + | _ -> (* specified ki but not this one *) acc + in acc + else acc + in + + let f_bhvs = List.rev f_bhvs in (* for compatibility with previous version *) + let def, bhvs = List.fold_left add_fct_bhv (false, []) f_bhvs in + let bhvs = List.fold_left add_stmt_bhv bhvs s_bhvs in + let bhvs = + if def then (* fct default behavior already in *) bhvs + else if bhv_names = [] then (FunBhv None)::bhvs + else match ki with + | None (* not specified ki *) | Some Kglobal -> + if List.mem Cil.default_behavior_name bhv_names + then (FunBhv None)::bhvs + else bhvs + | Some Kstmt _ -> bhvs + in def_annot_bhv, bhvs + +(*----------------------------------------------------------------------------*) +(* Unreachable *) +(*----------------------------------------------------------------------------*) + +let process_unreached_annots cfg = + debug "collecting unreachable annotations@."; + let unreached = Cil2cfg.unreachable_nodes cfg in + let kf = Cil2cfg.cfg_kf cfg in + let spec = Kernel_function.get_spec kf in + let add_id id acc = + if filter_status id then id::acc + else (* non-selected property : nothing to do *) acc + in + let do_post b tk acc (termk, _ as p) = + if tk = termk then add_id (WpPropId.mk_fct_post_id kf b p) acc else acc + in + let do_bhv termk acc b = List.fold_left (do_post b termk) acc b.b_post_cond in + let do_annot s a acc = + let ca = match a with User ca | AI (_, ca) -> ca in + add_id (WpPropId.mk_code_annot_id kf s ca) acc + in + let do_node acc n = + debug + "process annotations of unreachable node %a@." + Cil2cfg.pp_node_type n; + match n with + | Cil2cfg.Vstart -> Wp_parameters.fatal "Start must be reachable" + | Cil2cfg.VfctIn -> Wp_parameters.fatal "FctIn must be reachable" + | Cil2cfg.VfctOut -> List.fold_left (do_bhv Normal) acc spec.spec_behavior + | Cil2cfg.Vexit -> List.fold_left (do_bhv Exits) acc spec.spec_behavior + | Cil2cfg.Vstmt s + | Cil2cfg.VblkIn (Cil2cfg.Bstmt s, _) | Cil2cfg.Vcall (s, _, _, _) + | Cil2cfg.Vtest (true, s, _) | Cil2cfg.Vloop (_, s) | Cil2cfg.Vswitch (s,_) + -> Annotations.single_fold_stmt (do_annot s) s acc + | Cil2cfg.Vtest (false, _, _) | Cil2cfg.Vloop2 _ + | Cil2cfg.VblkIn _ | Cil2cfg.VblkOut _ | Cil2cfg.Vend -> acc + in + let annots = List.fold_left do_node [] unreached in + debug + "found %d unreachable annotations@." (List.length annots) ; + List.iter (fun pid -> set_unreachable pid) annots + +(*----------------------------------------------------------------------------*) +(* Everything must go through here. *) +(*----------------------------------------------------------------------------*) + +let get_cfg kf = + if Wp_parameters.RTE.get () then compute_rte_for kf ; + let cfg = Cil2cfg.get kf in + let _ = process_unreached_annots cfg in + let do_dot = Wp_parameters.Dot.get () in + let _dot = if do_dot then Some (Cil2cfg.dot_cfg cfg) else None in + cfg + +let build_configs assigns kf behaviors ki property = + debug "[get_strategies] for behaviors names: %a@." + (Wp_error.pp_string_list ~sep:" " ~empty:"<none>") + (match behaviors with [] -> ["<all>"] | _ :: _ as l -> l) ; + let _ = match ki with + | None -> () + | Some Kglobal -> + debug + "[get_strategies] select in function properies@." + | Some (Kstmt s) -> + debug + "[get_strategies] select stmt %d properties@." s.sid + in + let cfg = get_cfg kf in + let property = match property with + | AllProps -> if Cil2cfg.cfg_spec_only cfg then OnlyPreconds else AllProps + | _ -> property + in + let def_annot_bhv, bhvs = find_behaviors kf cfg ki behaviors in + if bhvs = [] then + Wp_parameters.warning "[get_strategies] no behaviors found" + else + debug "[get_strategies] %d behaviors" + (List.length bhvs); + let mk_bhv_config bhv = { kf = kf; + cfg = cfg; + cur_bhv = bhv; + asked_prop = property; + asked_bhvs = bhvs; + assigns_filter = assigns; + def_annots_info = def_annot_bhv } + in List.map mk_bhv_config bhvs + +let get_strategies assigns kf behaviors ki property = + let configs = build_configs assigns kf behaviors ki property in + let rec add_stgs l = match l with [] -> [] + | config::tl -> + let stg = build_bhv_strategy config in + let stgs = stg::(add_stgs tl) in + match config.cur_bhv, config.asked_prop with + | FunBhv (Some b), AllProps -> + let froms = Property.ip_from_of_behavior kf Kglobal b in + let add acc ip = match ip with + | Property.IPFrom id_from -> + (WpFroms.get_strategy_for_from id_from)::acc + | _ -> acc + in List.fold_left add stgs froms + + | _, _ -> (* TODO *) stgs + in add_stgs configs + +(*----------------------------------------------------------------------------*) +(* Public functions to build the strategies *) +(*----------------------------------------------------------------------------*) + +let get_precond_strategies p = + debug "[get_precond_strategies] %s@." + (WpPropId.id_prop_txt p); + match p with + | Property.IPPredicate (Property.PKRequires b, kf, Kglobal, _) -> + let strategies = + if WpStrategy.is_main_init kf then + get_strategies NoAssigns kf [b.b_name] None (IdProp p) + else [] + in + let call_sites = Kernel_function.find_syntactic_callsites kf in + let add_call_pre_stategy acc (kf_caller, stmt) = + let asked = CallPre (stmt, Some p) in + let strategies = get_strategies NoAssigns kf_caller [] None asked in + strategies @ acc + in + if call_sites = [] then + (Wp_parameters.warning + "no direct call sites for '%a': cannot check pre-conditions" + Kernel_function.pretty kf; + strategies) + else List.fold_left add_call_pre_stategy strategies call_sites + | _ -> + invalid_arg "[get_precond_strategies] not a function precondition" + +let get_call_pre_strategies stmt = + debug + "[get_call_pre_strategies] on statement %a@." Stmt.pretty_sid stmt; + match stmt.skind with + | Instr(Call(_,f,_,_)) -> + let strategies = match WpStrategy.get_called_kf f with + | None -> + Wp_parameters.warning + "call through function pointer not implemented yet: \ + cannot check pre-conditions for statement %a" + Stmt.pretty_sid stmt; + [] + | Some _kf_called -> + let kf_caller = Kernel_function.find_englobing_kf stmt in + let asked = CallPre (stmt, None) in + get_strategies NoAssigns kf_caller [] None asked + in strategies + | _ -> Wp_parameters.warning + "[get_call_pre_strategies] this is not a call statement"; [] + +let get_id_prop_strategies ?(assigns=WithAssigns) p = + debug "[get_id_prop_strategies] %s@." + (WpPropId.id_prop_txt p); + match p with + | Property.IPCodeAnnot (kf,_,ca) -> + let bhvs = match ca.annot_content with + | AAssert (l, _) | AInvariant (l, _, _) | AAssigns (l, _) -> l + | _ -> [] + in get_strategies assigns kf bhvs None (IdProp p) + | Property.IPAssigns (kf, _, Property.Id_code_annot _, _) + (*loop assigns: belongs to the default behavior *) + | Property.IPDecrease (kf,_,_,_) -> + (* any variant property is attached to the default behavior of + * the function, NOT to a statement behavior *) + let bhvs = [ Cil.default_behavior_name ] in + get_strategies assigns kf bhvs None (IdProp p) + | Property.IPPredicate (Property.PKRequires _, _kf, Kglobal, _p) -> + get_precond_strategies p + | Property.IPFrom id_from -> + [ WpFroms.get_strategy_for_from id_from ] + | _ -> + let strategies = match Property.get_kf p with + | None -> Wp_parameters.warning + "WP of property outside functions: ignore %s" + (WpPropId.id_prop_txt p); [] + | Some kf -> + let ki = Some (Property.get_kinstr p) in + let bhv = match Property.get_behavior p with + | None -> Cil.default_behavior_name + | Some fb -> fb.b_name + in get_strategies assigns kf [bhv] ki (IdProp p) + in strategies + +let get_behavior_strategies ?(assigns=WithAssigns) kf bhvs = + let ki = None in + let stgs = get_strategies assigns kf bhvs ki AllProps in + stgs + +let get_function_strategies ?(assigns=WithAssigns) kf = + get_strategies assigns kf [] None AllProps + +(* TODO: it could be better to first find the property in order + * to compute only in its functions and behaviors... + * At the moment [p_bhvs] is given as a hint (see [get_id_prop_strategies]) + *) +let get_prop_strategies ?(assigns=WithAssigns) kf (p_bhvs, prop_name) = + get_strategies assigns kf p_bhvs None (NamedProp prop_name) + +(*----------------------------------------------------------------------------*) +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) +(*----------------------------------------------------------------------------*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpAnnot.mli frama-c-20111001+nitrogen+dfsg/src/wp/wpAnnot.mli --- frama-c-20110201+carbon+dfsg/src/wp/wpAnnot.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpAnnot.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,120 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Every access to annotations have to go through here, + * so this is the place where we decide what the computation + * is allowed to use. *) + +open Cil_types + +(*----------------------------------------------------------------------------*) + +(** splits a prop_id goals into prop_id parts for each sub-goals *) +val split : ( WpPropId.prop_id -> 'a -> unit ) -> WpPropId.prop_id -> + 'a Bag.t -> unit + +(** A proof accumulator for a set of related prop_id *) +type proof + +val create_proof : WpPropId.prop_id -> proof + (** to be used only once for one of the related prop_id *) + +val add_proof : proof -> WpPropId.prop_id -> Property.t list -> unit + (** accumulate int the proof the partial proof for this prop_id *) + +val is_composed : proof -> bool + (** whether a proof needs several lemma to be complete *) + +val is_proved : proof -> bool + (** wether all partial proofs have been accumulated or not *) + +val target : proof -> Property.t +val dependencies : proof -> Property.t list +val missing_rte : kernel_function -> string list + +(*----------------------------------------------------------------------------*) + +val get_called_post_conditions : kernel_function -> Property.t list +val get_called_exit_conditions : kernel_function -> Property.t list +val get_called_assigns : kernel_function -> Property.t list +val get_called_preconditions_at : kernel_function -> stmt -> Property.t list +val lookup_called_preconditions_at : kernel_function -> stmt -> Property.t list + +(*----------------------------------------------------------------------------*) + +type asked_assigns = NoAssigns | OnlyAssigns | WithAssigns + +(** + * Defines how annotations are applied on the Cfg during the WP. + * - [~behaviors:bhv] : only annotations related + * to [b] in [bhv] are taken into account. + * Otherwise all behaviors are included. + * The default behavior is one behavior among the others. + * - [~property:pid] : only the mentioned property id is turned into a goal. + * Others are only used in hypothesis. + * Otherwise, annotations are generally turned into goals unless + * they already have a valid current status. + * - [~assigns] : filter in or out the assigns clauses. + * + **) +(* +val get_strategies : Cil2cfg.t + -> ?behaviors:string list + -> ?property:asked_prop + -> ?assigns:assigns + -> unit -> strategy list + *) + +(** Compute the strategies to prove the selected property. *) +val get_id_prop_strategies : + ?assigns:asked_assigns -> Property.t -> WpStrategy.strategy list + +val get_call_pre_strategies : stmt -> WpStrategy.strategy list + +(** Similar to [get_id_prop_strategies] but with a named property. +* (useful for command line option). +* The behavior list has to be the behaviors of the property. +* TODO: it should be removed when we will be able to compute it. *) +val get_prop_strategies : ?assigns:asked_assigns -> Kernel_function.t -> + (string list * string) -> WpStrategy.strategy list + +(** Compute the strategy to prove all the properties of the behavior. +* Notice that is a property is related to several behaviors, +* it might not be fully proved with this strategy. +* Can return more strategies than names in the input list +* because a name can be used for several (disjoint) statement spec. +* *) +val get_behavior_strategies : + ?assigns:asked_assigns -> Kernel_function.t -> string list -> WpStrategy.strategy list + +(** Compute the strategies to prove all the properties of the selected function. +* *) +val get_function_strategies : + ?assigns:asked_assigns -> Kernel_function.t -> WpStrategy.strategy list + +(*----------------------------------------------------------------------------*) +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) +(*----------------------------------------------------------------------------*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wp_error.ml frama-c-20111001+nitrogen+dfsg/src/wp/wp_error.ml --- frama-c-20110201+carbon+dfsg/src/wp/wp_error.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wp_error.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,137 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(* --- Exception Handling in WP --- *) +(* ------------------------------------------------------------------------ *) + +exception Error of string * string + +let current = ref "wp" +let set_model m = current := m + +let unsupported ?(model= !current) fmt = + let b = Buffer.create 80 in + Buffer.add_string b "unsupported " ; + let kf fmt = + Format.pp_print_flush fmt () ; + raise (Error(model,Buffer.contents b)) + in Format.kfprintf kf (Format.formatter_of_buffer b) fmt + +let not_yet_implemented ?(model= !current) fmt = + let b = Buffer.create 80 in + let kf fmt = + Format.pp_print_string fmt " not yet implemented" ; + Format.pp_print_flush fmt () ; + raise (Error(model,Buffer.contents b)) + in Format.kfprintf kf (Format.formatter_of_buffer b) fmt + +open Cil_types + +let pp_logic_label fmt label = + let name = match label with + | LogicLabel (_,l) -> l + | StmtLabel {contents=stmt} -> + let rec pickLabel = function + | [] -> Printf.sprintf "__unknown_label_%d" stmt.sid + | Label (l, _, _) :: _ -> l + | _ :: rest -> pickLabel rest + in pickLabel stmt.labels + in Format.pp_print_string fmt name + +let pp_assigns fmt asgns = + match asgns with + WritesAny -> Format.fprintf fmt "<undef>" + | _ -> + Format.fprintf fmt "@[<hov 2>%a@]" + (Cil.defaultCilPrinter#pAssigns "") asgns + +let pp_string_list ?(sep=Pretty_utils.space_sep) ~empty fmt l = + match l with [] -> Format.fprintf fmt "%s" empty + | _ -> Format.fprintf fmt "%a" + (Pretty_utils.pp_list ~sep Format.pp_print_string) l + + +type 'a cc = + | Result of 'a + | Warning of string * string (* model , message *) + +let protected = function + | Error (model, msg) -> + Some(model , msg) + | Log.FeatureRequest (plugin,msg) -> + Some(plugin , Printf.sprintf "%s not yet implemented" msg) + | Log.AbortError msg -> + Some("user error" , msg) + | _ -> None + +let protect exn = + match protected exn with + | Some(plugin,reason) -> plugin , reason + | None -> raise exn + +let protect_warning exn = + match protected exn with + | Some(src,reason) -> Warning(src,reason) + | None -> raise exn + +let protect_function f x = + try Result (f x) + with e -> protect_warning e + +let protect_translation f x y = + try Result (f x y) + with e -> protect_warning e + +let protect_translation3 f x y z = + try Result (f x y z) + with e -> protect_warning e + +let protect_translation4 f x y z t = + try Result (f x y z t) + with e -> protect_warning e + +let protect_translation5 f x y z t u = + try Result (f x y z t u) + with e -> protect_warning e + +let rec protect_map f = function + | [] -> Result [] + | x::xs -> + match f x with + | Result y -> + ( match protect_map f xs with + | Result ys -> Result (y :: ys) + | Warning _ as w -> w ) + | Warning(m,p) -> Warning(m,p) + +let rec name = function + | [] -> "" + | [x] -> x + | x::xs -> + let buffer = Buffer.create 80 in + Buffer.add_string buffer x ; + List.iter + (fun y -> if y <> "" then + ( Buffer.add_char buffer '-' ; + Buffer.add_string buffer y )) xs ; + Buffer.contents buffer diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wp_error.mli frama-c-20111001+nitrogen+dfsg/src/wp/wp_error.mli --- frama-c-20110201+carbon+dfsg/src/wp/wp_error.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wp_error.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val name : string list -> string + +(* ------------------------------------------------------------------------ *) +(* --- Exception Handling in WP --- *) +(* ------------------------------------------------------------------------ *) + +open Cil_types + +exception Error of string * string + (** To be raised a feature of C/ACSL cannot be supported by a memory model + or is not implemented, or ... *) + +val set_model : string -> unit + +val unsupported : ?model:string -> ('a,Format.formatter,unit,'b) format4 -> 'a +val not_yet_implemented : ?model:string -> ('a,Format.formatter,unit,'b) format4 -> 'a + +val pp_logic_label : Format.formatter -> logic_label -> unit + +val pp_assigns : + Format.formatter -> Cil_types.identified_term Cil_types.assigns -> unit + +val pp_string_list : ?sep:Pretty_utils.sformat -> empty:string -> + Format.formatter -> string list -> unit + +type 'a cc = + | Result of 'a + | Warning of string * string (* source , reason *) + +val protect : exn -> string * string (* source , reason *) + +val protect_function : ('a -> 'b) -> 'a -> 'b cc +val protect_translation : ('a -> 'b -> 'r) -> 'a -> 'b -> 'r cc +val protect_translation3 : ('a -> 'b -> 'c -> 'r) -> 'a -> 'b -> 'c -> 'r cc +val protect_translation4 : + ('a -> 'b -> 'c -> 'd -> 'r) -> 'a -> 'b -> 'c -> 'd -> 'r cc +val protect_translation5 : + ('a -> 'b -> 'c -> 'd -> 'e -> 'r) -> 'a -> 'b -> 'c -> 'd -> 'e -> 'r cc + +val protect_map : ('a -> 'b cc) -> 'a list -> 'b list cc diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpFroms.ml frama-c-20111001+nitrogen+dfsg/src/wp/wpFroms.ml --- frama-c-20110201+carbon+dfsg/src/wp/wpFroms.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpFroms.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,594 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let dkey = "froms" (* debugging key *) + +(** This file groups functions needed to check the fonctional dependencies *) + +open Cil_types + +exception NoFromForBhv +exception NoFromForLoop of stmt +exception NoFromForCall of stmt + +(* -------------------------------------------------------------------------- *) +(** Build a full qualified name for logic_info about the nth from in the b +* behavior of the kf function. *) +let mk_name prefix kf ki b nth sufix = + let ki_info = match ki with Kglobal -> "" + | Kstmt s -> ("_stmt"^(string_of_int s.sid)) + in + let bhv_name = + if b.b_name = Cil.default_behavior_name then "" else ("_"^b.b_name) + in + Pretty_utils.sfprintf "%s%a%s%s_%d%s" + prefix + Kernel_function.pretty kf + bhv_name + ki_info + nth + sufix + +(** Build the logic type of the function that takes parameters of [in_types] +* and return an [out_type] result ([None] for a predicate) *) +let mk_linfo_type (out_type, in_types) = + let lvar_out_type = match out_type with Some t -> t + | None -> (* TODO: ugly ! but see in Logic_typing.logic_decl *) + Ctype Cil.voidType + in + let ltype = match in_types with [] -> lvar_out_type + | _ -> Larrow (in_types, lvar_out_type) + in ltype + +(** Build a [logic_info] with [fname] and the signature given by +* [(out_type, in_types)] (see {!mk_linfo_type}) +* TODO: should be [Cil_const.make_logic_info] when it be finished. *) +let make_logic_info fname (out_type, in_types) = + let ltype = mk_linfo_type (out_type, in_types) in + let lvar = Cil_const.make_logic_var fname ltype in + let mk_in_lvar t = Cil_const.make_logic_var "x" t in + let in_vars = List.map mk_in_lvar in_types in + let linfo = { + l_var_info = lvar; + l_labels = []; + l_tparams = []; + l_type = out_type; + l_profile = in_vars; + l_body = LBnone; + } in linfo + +(** Find the [logic_info] for the given name and signature. +* Build and register it if it doesn't exist yet. +* *) +let get_linfo name sgn = + let ptype = mk_linfo_type sgn in + let info_ok info = Logic_utils.is_same_type info.l_var_info.lv_type ptype in + match Logic_env.find_all_logic_functions name with + | [] -> + let linfo = make_logic_info name sgn in + Logic_utils.add_logic_function linfo; + linfo + | info::[] when info_ok info -> info + | _ -> Wp_parameters.fatal "several function named %s ???" name + +let mk_bhv_implicit_fun_name kf ki b n = + mk_name "FI_" kf ki b n "" + +let mk_loop_implicit_fun_name s n = + Pretty_utils.sfprintf "Floop%d_%d" s.sid n + +let get_pred_linfo kf ki bhv nth t = + let name = mk_name "Pfrom_" kf ki bhv nth ""in + get_linfo name (None, [t]) + +let get_init_linfo kf ki bhv n_assigns n_from t = + let name = mk_name "Init_" kf ki bhv n_assigns ("_"^(string_of_int n_from)) in + get_linfo name (Some t, [(*Linteger*)]) + +(** Build the implicit function for the nth assign clause of behavior b +* in the ki element of function kf. *) +let get_implicit_fun name (out_type, inputs_type) = + let linfos = Logic_env.find_all_logic_functions name in + let f = match linfos with + | f::[] -> f + | _::_ -> Wp_parameters.fatal "several functions named %s" name + | [] -> + let linfo = make_logic_info name (Some out_type, inputs_type) in + Logic_utils.add_logic_function linfo; + linfo + in f +(** Build the lvalue [ \at (mlab, * (\at (addrlab, & elem))) ]. +* This is needed because the left part of assigns properties is an lvalue +* which address has to be interpreted in the pre-state ([addrlab]), +* but its value is to be considered in the post-state ([mlab]). *) +let build_elem_opt ~addrlab ~mlab elem = + let mk_mem_at t = + if Logic_utils.is_same_logic_label mlab Logic_const.here_label then t + else Logic_const.tat (t, mlab) + in + if Logic_utils.is_same_logic_label addrlab mlab then + Some (mk_mem_at elem) + else match elem.term_node with + | TLval (h, off) -> + let mk_addr_at t = Logic_const.tat (t, addrlab) in + let rec mk_at_off off = match off with TNoOffset -> off + | TField (f, off) -> TField (f, mk_at_off off) + | TIndex (i, off) -> TIndex (mk_addr_at i, mk_at_off off) + in + let off' = mk_at_off off in + let h' = match h with + | TVar _ | TResult _ -> h + | TMem p -> TMem (mk_addr_at p) + in + let lv' = TLval (h', off') in + let elem' = Logic_const.term lv' elem.term_type in + let elem' = mk_mem_at elem' in + Some (elem') + | _ -> + Wp_parameters.not_yet_implemented + "assigns left part is not a lvalue: %a" Cil.d_term elem + +(** see [build_elem_opt] above. *) +let build_elem ~addrlab ~mlab elem = + match build_elem_opt ~addrlab ~mlab elem with None -> assert false + | Some elem -> elem + +(** Build the left part of a contract [assigns] property +Process [\result] and [\exit_status] according to [termination_kind]. +Returns [None] if [out] is not compatible with [termination_kind]. +* *) +let build_post_output termination_kind output = + let out = output.it_content in + let out = match out.term_node with (* remove \at(\result,Post) *) + | Tat ({term_node=(TLval(TResult _,_) as tr)}, LogicLabel (_, "Post")) -> + Logic_const.term tr out.term_type + | _ -> out + in + match termination_kind, out.term_node with + | Exits, TLval (TResult _, _ ) -> None + | Normal, TLval (TVar{lv_name = "\\exit_status"},_) -> None + | _, _ -> + build_elem_opt + ~addrlab:Logic_const.old_label ~mlab:Logic_const.here_label out + +(** Build [P(out)] where [out] is the left part of the assigns property. +Process [\result] and [\exit_status] according to [termination_kind]. +Returns [None] if [out] is not compatible with [termination_kind]. +**) +let mk_assign_post kf bhv nth termination_kind (output, _) = + match build_post_output termination_kind output with + | None -> None + | Some out' -> + let linfos = get_pred_linfo kf Kglobal bhv nth out'.term_type in + let p = Logic_const.papp (linfos, [], [out']) in + Some (Logic_const.new_predicate p) + +module Vars = struct + let new_vars = ref [] + + let get_and_init () = + let vars = !new_vars in + new_vars := []; + vars + + let mk_new name ty = + (** Notice that [make_logic_var] create a frech variable. + * This is intended since several calls shouldn't share the same variable ! + **) + let v = Cil_const.make_logic_var name ty in + new_vars := v::!new_vars; + v +end + +(** Build [out = f_n (inputs)]. +* The correct label \at should already be in [output] and [inputs]. +* @raise NoFromForBhv if [inputs = None] meaning [FromAny]. +**) +let build_fimpl_eq fi_name output inputs = + let out_type = output.term_type in + let fun_impl = match inputs with + | None -> + let var = Vars.mk_new fi_name out_type in + Logic_const.tvar var + | Some inputs -> + let fimpl_sig = (out_type, List.map (fun i -> i.term_type) inputs) in + let fun_impl = get_implicit_fun fi_name fimpl_sig in + Logic_const.term (Tapp (fun_impl, [], inputs)) out_type + in let p_eq = Logic_const.prel (Req, output, fun_impl) in + p_eq + + +(** @return the list of pair [from, out_i = implicit_fun_i (inputs)] +* for each [out_i \from inputs] assigns property of the behavior. +* The [from] part is for identification purpose later on. +* [implicit_fun_i] is the implicit fonction for the output. +* [kf] and [ki] give information to know there the specification comes from +* in order to build the names for the implicit functions. +* [termination_kind] is used to filter [\result] and [\exit_status] when needed. +*) +let bhv_from_hyps kf ki bhv l_froms termination_kind = + let add_assign (n, acc) ((output, inputs) as from) = + let acc = + match build_post_output termination_kind output with + | None -> acc + | Some output -> + let inputs = match inputs with + | FromAny -> None + | From inputs -> + let mk_input x = build_elem ~addrlab:Logic_const.old_label + ~mlab:Logic_const.old_label x.it_content + in + let inputs = List.map mk_input inputs in + Some inputs + in + let fi_name = mk_bhv_implicit_fun_name kf ki bhv n in + let p_eq = build_fimpl_eq fi_name output inputs in + (from, p_eq)::acc + in n+1, acc + in snd (List.fold_left add_assign (1, []) l_froms) + +(** For each behavior of the specification, and for each \from in the behavior, +* return a predicate which is [assumes => out_i = implicit_fun_i (inputs)]. +* If the assigns information is missing from a behavior, try to use +* the whole assigns information of the spec. +* @raise NoFromForBhv if we don't manage to compute the assigns information. +* See [bhv_from_hyps] above. +* *) +let post_of_spec_assigns kf ki spec termination_kind = + let add_behav (compl, acc) bhv = + match bhv.b_assigns with + | WritesAny -> (* skip *) compl, acc + | Writes l -> + (* post for behavior is [\old(assumes) => out = f(in)]*) + let assumes = Ast_info.behavior_assumes bhv in + let compl = compl || Logic_utils.is_trivially_true assumes in + let assumes = Logic_const.pold assumes in + let l = bhv_from_hyps kf ki bhv l termination_kind in + let add_assume acc (from, p) = + let p = Logic_const.pimplies (assumes, p) in + (bhv, from, p)::acc + in let acc = List.fold_left add_assume acc l in + (compl, acc) + in + let compl = spec.spec_complete_behaviors <> [] in (* TODO: add dpds ? *) + let compl, acc = List.fold_left add_behav (compl, []) spec.spec_behavior in + if compl then acc + else (* some assigns information is missing: try to complete *) + match WpStrategy.assigns_upper_bound spec with + | None -> raise NoFromForBhv + | Some (b, l) -> + let l = bhv_from_hyps kf ki b l termination_kind in + List.fold_left (fun acc (from, p) -> (b, from, p)::acc) acc l + +(** Build the from hyp for the loop assigns *) +let inv_of_loop_from s n (output, inputs) = + let output = build_elem ~addrlab:Logic_const.here_label + ~mlab:Logic_const.here_label output.it_content + in + let pre_loop_lab = Clabels.mk_logic_label s in + let inputs =match inputs with + | FromAny -> None + | From inputs -> + let mk_input x = build_elem ~addrlab:Logic_const.here_label + ~mlab:pre_loop_lab x.it_content + in + let inputs = List.map mk_input inputs in + Some inputs + in + let fi_name = mk_loop_implicit_fun_name s n in + let p_eq = build_fimpl_eq fi_name output inputs in + p_eq + +(** Build [ xi = Init (i) /\ ...] forall inputs part of the assigns property. *) +let mk_assign_pre kf ki bhv nth inputs = + let get_init lv n = + let linfo = get_init_linfo kf ki bhv nth n lv.term_type in + Logic_const.term (Tapp (linfo, [], [(*Logic_const.tinteger n*)])) lv.term_type + in + let add_in (n, acc) input = + let lv = input.it_content in + let _name = lv.term_name in (* TODO process name *) + let init = get_init lv n in + let pre = Logic_const.prel (Req, lv, init) in + n+1, pre::acc + in + let _, pres = List.fold_left add_in (1, []) inputs in + Logic_const.new_predicate (Logic_const.pands pres) + +(* -------------------------------------------------------------------------- *) +(** {2 Build Strategy} *) +(* -------------------------------------------------------------------------- *) + +let annot_for_asked_bhv b_list asked_bhv = + b_list = [] || List.exists (fun x -> x = asked_bhv) b_list + +let get_loop_assigns_for_froms asked_bhv s = + let do_annot a acc = + let ca = match a with User ca | AI (_, ca) -> ca in + match ca.annot_content with + | AAssigns (b_list, Writes a) when annot_for_asked_bhv b_list asked_bhv -> + Some (ca,a) + | _ -> acc + in Annotations.single_fold_stmt do_annot s None + +let add_loop_assigns_hyp kf asked_bhv s acc = + let asgn_opt = get_loop_assigns_for_froms asked_bhv s in + let acc = WpStrategy.add_loop_assigns_hyp acc kf s asgn_opt in + match asgn_opt with + | None -> raise (NoFromForLoop s) + | Some (ca, assigns) -> + let add_assign (n, acc) from = + let inv = + try inv_of_loop_from s n from + with NoFromForBhv -> raise (NoFromForLoop s) + in + let id = WpPropId.mk_loop_from_id kf s ca from in + let labels = NormAtLabels.labels_loop_inv s in + let acc = WpStrategy.add_prop acc WpStrategy.Ahyp labels id inv in + n+1, acc + in + let _, acc = List.fold_left add_assign (1, acc) assigns in + acc + +let add_stmt_spec_assigns_hyp (p_acc, e_acc) kf s l_post spec = + let p_acc = + WpStrategy.add_stmt_spec_assigns_hyp p_acc kf s l_post spec + in (* TODO add_stmt_spec_assigns_hyp in e_acc but crach at the moment... *) + (p_acc, e_acc) + +let add_call_assigns_hyp (p_acc, e_acc) kf_caller s l_post spec = + let p_acc = + WpStrategy.add_call_assigns_hyp p_acc kf_caller s l_post (Some spec) + in (* TODO add_call_assigns_hyp in e_acc but crach at the moment... *) + (p_acc, e_acc) + +(** @raise NoFromForBhv is the assigns information is missing. *) +let add_spec_annots kf s l_post spec (b_acc, (p_acc, e_acc)) = + let kind = WpStrategy.Aboth false in + let b_acc = WpStrategy.add_prop_stmt_spec_pre b_acc kind kf s spec in + + let add_from acc (bhv, from, p) = + let id = + WpPropId.mk_bhv_from_id kf (Kstmt s) bhv from + in (* TODO use tk in id*) + let labels = NormAtLabels.labels_stmt_post s l_post in + WpStrategy.add_prop acc WpStrategy.Ahyp labels id p + in + let p_froms = post_of_spec_assigns kf (Kstmt s) spec Normal in + let p_acc = List.fold_left add_from p_acc p_froms in + let e_froms = post_of_spec_assigns kf (Kstmt s) spec Exits in + let e_acc = List.fold_left add_from e_acc e_froms in + + let a_acc = add_stmt_spec_assigns_hyp (p_acc, e_acc) kf s l_post spec in + (b_acc, a_acc) + +let get_stmt_hyp kf asked_bhv s l_post = + let do_annot a acc = + let ca = Annotations.get_code_annotation a in + match ca.annot_content with + | AStmtSpec (b_list, spec) when annot_for_asked_bhv b_list asked_bhv -> + (try add_spec_annots kf s l_post spec acc + with NoFromForBhv -> (* TODO: not sure this is correct!*) acc) + | _ -> (* ignore other annotations *) acc + in + let before_acc, after_acc, exits_acc = + WpStrategy.empty_acc, WpStrategy.empty_acc, WpStrategy.empty_acc in + let acc = before_acc, (after_acc, exits_acc) in + Annotations.single_fold_stmt do_annot s acc + +(** Collect the \from hypotheses of the function spectication. +* TODO: maybe we should also take the [ensures] properties ? +* @raise NoFromForBhv is the assigns information is missing. +**) +let get_called_post kf termination_kind = + let spec = Kernel_function.get_spec kf in + Wp_parameters.debug ~dkey "[get_called_post] '%s' for %a@." + (WpPropId.string_of_termination_kind termination_kind) + Kernel_function.pretty kf; + let posts = post_of_spec_assigns kf Kglobal spec termination_kind in + let mk_prop acc (bhv, from, post) = + let id = WpPropId.mk_bhv_from_id kf Kglobal bhv from in + let labels = NormAtLabels.labels_fct_post in + WpStrategy.add_prop acc WpStrategy.AcallHyp labels id post + in List.fold_left mk_prop WpStrategy.empty_acc posts + +let get_call_hyp kf_caller s l_post fct = + match WpStrategy.get_called_kf fct with + | Some kf -> + let spec = Kernel_function.get_spec kf in + let before_annots = WpStrategy.empty_acc in + let post_annots = + try get_called_post kf Normal + with NoFromForBhv -> raise (NoFromForCall s) + in + let exits_annots = + try get_called_post kf Exits + with NoFromForBhv -> raise (NoFromForCall s) + in + let after_annots = post_annots, exits_annots in + let after_annots = + add_call_assigns_hyp after_annots kf_caller s l_post spec + in + before_annots, after_annots + | None -> + Wp_parameters.warning + "call through function pointer not implemented yet: \ + ignore called function properties."; + raise (NoFromForCall s) + +(** Collect all the annotations to be used to prove one \from property of + * the function behavior **) +let get_fct_bhv_from_annots cfg bhv nth assign = + let kf = Cil2cfg.cfg_kf cfg in + let asked_bhv = bhv.b_name in + let annots = WpStrategy.create_tbl () in + let add_post v tk = match mk_assign_post kf bhv nth tk assign with + | None -> () + | Some post -> + let edges = Cil2cfg.succ_e cfg v in + let acc = WpStrategy.empty_acc in + (* TODO: goal_to_select for only one from *) + let kind = WpStrategy.Agoal in + let labels = NormAtLabels.labels_fct_assigns in + let id = WpPropId.mk_fct_from_id kf bhv tk assign in + let post = Logic_const.pred_of_id_pred post in + let acc = WpStrategy.add_prop acc kind labels id post in + WpStrategy.add_on_edges annots acc edges + in + let add_stmt_annots v s = + let l_post = Cil2cfg.get_post_logic_label cfg v in + let stmt_annots = get_stmt_hyp kf asked_bhv s l_post in + WpStrategy.add_node_annots annots cfg v stmt_annots + in + let get_node_annot v = + match Cil2cfg.node_type v with + | Cil2cfg.VfctIn -> () + (* Don't put the precondition here because we don't want to build + * (pre => post) => (pre' => post') but rather + * (pre /\ pre' /\ post => post') so we have to process the pre latter + * (see SKfroms) *) + + | Cil2cfg.VfctOut -> add_post v Normal + | Cil2cfg.Vexit -> add_post v Exits + + | Cil2cfg.VblkIn (Cil2cfg.Bstmt s, _) + | Cil2cfg.Vstmt s + | Cil2cfg.Vswitch (s,_) | Cil2cfg.Vtest (true, s, _) + -> add_stmt_annots v s + + | Cil2cfg.Vcall (s,_,fct,_) -> + let l_post = Cil2cfg.get_post_logic_label cfg v in + let call_annots = get_call_hyp kf s l_post fct in + WpStrategy.add_node_annots annots cfg v call_annots + + | Cil2cfg.Vloop (_, s) -> + add_stmt_annots v s; + let loop_core = + add_loop_assigns_hyp kf asked_bhv s WpStrategy.empty_acc in + let edges_to_head = Cil2cfg.succ_e cfg v in + WpStrategy.add_on_edges annots loop_core edges_to_head + | _ -> () + in + let _ = Cil2cfg.iter_nodes get_node_annot cfg in + annots + +let mk_strategy_for_fct_from cfg bhv pre ((out,from) as assign) = + let n = out.it_id in (* TODO: chose a better num with a user meaning ? *) + let kf = Cil2cfg.cfg_kf cfg in + let get_pre () = + let pre_init = match from with + | FromAny -> Wp_parameters.fatal "no from to prove" + | From inputs -> mk_assign_pre kf Kglobal bhv n inputs + in + let assumes = None in (* assumes are already hyp of the strategy. *) + WpStrategy.add_prop_fct_pre pre WpStrategy.Ahyp kf bhv ~assumes pre_init + in + let annots = get_fct_bhv_from_annots cfg bhv n assign in + let _ = WpStrategy.add_all_axioms annots in + let desc = + Pretty_utils.sfprintf "'%a', %d from property of '%s' behavior" + Kernel_function.pretty kf n bhv.b_name + in + let kind = WpStrategy.SKfroms { + WpStrategy.get_pre = get_pre; + WpStrategy.more_vars = Vars.get_and_init (); + } in + let new_loops = Wp_parameters.Invariants.get() in + let bname = if Cil.is_default_behavior bhv then "default" else bhv.b_name in + let bname = (bname^"_assign_"^(string_of_int n)) in + WpStrategy.mk_strategy desc cfg (Some bname) + new_loops kind annots + +let pp_err fmt e = + let no_from = "no \\from information" in + let pp_stmt_loc fmt s = + Format.fprintf fmt "@[%a@]" Cil.d_loc (Cil_datatype.Stmt.loc s) + in + match e with + | NoFromForCall s -> + Format.fprintf fmt "%s for call at @[%a@]" no_from pp_stmt_loc s + | NoFromForLoop s -> + Format.fprintf fmt "%s for loop at @[%a@]" no_from pp_stmt_loc s + | _ -> raise e + +let get_bhv_pre kf bhv = + let add_bhv_pre_hyp b acc = (* add both requires and assumes as precond *) + let kind = WpStrategy.Ahyp in + WpStrategy.add_prop_fct_bhv_pre acc kind kf b ~impl_assumes:false + in + let pre = add_bhv_pre_hyp bhv (WpStrategy.empty_acc) in + let pre = (* also add the default behavior precond *) + if (Cil.is_default_behavior bhv) then pre + else match Cil.find_default_behavior (Kernel_function.get_spec kf) with + | None -> pre + | Some bdef -> add_bhv_pre_hyp bdef pre + in + pre + +let get_strategy_for_from id_from = + let kf, ki, behavior_or_loop, from = id_from in + match ki, behavior_or_loop with + | Kglobal, Property.Id_behavior bhv -> + let cfg = Cil2cfg.get kf in + let pre = get_bhv_pre kf bhv in + mk_strategy_for_fct_from cfg bhv pre from + | _ -> Wp_parameters.not_yet_implemented "local \\from property check" + +(** Build strategies to prove the [from] properties of the function. +* At the moment, only the function behaviors are handled, +* but the strategies make use of the [from] properties of stmt spec, +* loops and called functions. *) +let get_strategies_for_froms kf = + if not (Kernel_function.is_definition kf) then + begin + Wp_parameters.warning + "Function %a has no body : cannot prove its \\from properties (skip)" + Kernel_function.pretty kf; + [] + end + else + let stmt_bhvs = Kernel_function.internal_function_behaviors kf in + if stmt_bhvs <> [] then + Wp_parameters.warning + "Not implemented: prove local \\from properties (skip)"; + (* TODO: \\from in loops. *) + let spec = Kernel_function.get_spec kf in + let cfg = Cil2cfg.get kf in + let add_bhv acc bhv = + let pre = get_bhv_pre kf bhv in + let add_assign_strategy acc (b,f) = + match f with + | FromAny -> acc + | From _l -> + let stg = mk_strategy_for_fct_from cfg bhv pre (b,f) in + stg::acc + in + match bhv.b_assigns with + | WritesAny -> acc + | Writes l -> + try List.fold_left add_assign_strategy acc l + with e -> + Wp_parameters.warning + "cannot check \\from properties of '%a':@,@[%a@]" + Kernel_function.pretty kf pp_err e; + acc + in List.fold_left add_bhv [] spec.spec_behavior diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpFroms.mli frama-c-20111001+nitrogen+dfsg/src/wp/wpFroms.mli --- frama-c-20110201+carbon+dfsg/src/wp/wpFroms.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpFroms.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,33 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + +(** Build a strategy for each of the \from property of the function behavior *) +val get_strategies_for_froms : Kernel_function.t -> WpStrategy.strategy list + +val get_strategy_for_from : Property.identified_from -> WpStrategy.strategy + +(* +* TODO: add strategies for [from] properties of [loop assigns]. +* TODO: add strategies for stmt behaviors +* *) + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wp_gui.ml frama-c-20111001+nitrogen+dfsg/src/wp/wp_gui.ml --- frama-c-20110201+carbon+dfsg/src/wp/wp_gui.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wp_gui.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,390 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* ------------------------------------------------------------------------ *) +(* --- RUN WP --- *) +(* ------------------------------------------------------------------------ *) + +exception Stop + +type strategy_code = { + sp_target : string ; + sp_kf : Kernel_function.t option ; + sp_bhv : string list ; + sp_ip : Property.t option ; +} + +type strategy_call = { + sc_caller : Kernel_function.t ; + sc_called : Kernel_function.t ; + sc_callat : stmt ; +} + +type strategy = + | Snone + | Scode of strategy_code + | Scall of strategy_call + +let kind_of_property = function + | Property.IPCodeAnnot _ -> "annotation" + | Property.IPPredicate( Property.PKRequires _ , _ , Kglobal , _ ) -> "preconditions for callers" + | _ -> "property" + +let get_strategy localizable : strategy = + match localizable with + | Pretty_source.PStmt( kf , stmt ) + | Pretty_source.PLval( Some kf , Kstmt stmt , _ ) + | Pretty_source.PTermLval( Some kf , Kstmt stmt , _ ) + -> + begin + match stmt with + | { skind=Instr(Call(_,e,_,_)) } -> + begin + match WpStrategy.get_called_kf e with + | None -> Snone + | Some called -> + Scall { + sc_caller = kf ; + sc_called = called ; + sc_callat = stmt ; + } + end + | _ -> Snone +(* + Scode { + sp_target = "function contract" ; + sp_kf = Some kf ; + sp_bhv = [] ; + sp_ip = None ; + } +*) + end + + | Pretty_source.PVDecl (Some kf,{vglob=true}) -> + Scode { + sp_target = "function contract" ; + sp_kf = Some kf ; + sp_bhv = [] ; + sp_ip = None ; + } + + | Pretty_source.PIP ip -> + Scode { + sp_target = kind_of_property ip ; + sp_kf = Property.get_kf ip ; + sp_bhv = + Extlib.may_map + ~dft:[] + (fun x -> [ x.b_name ]) + (Property.get_behavior ip) ; + sp_ip = Some ip ; + } + + | Pretty_source.PVDecl _ + | Pretty_source.PLval _ + | Pretty_source.PTermLval _ + | Pretty_source.PGlobal _ -> + Snone + +let run_and_prove (main_ui:Design.main_window_extension_points) strategy = + try + begin + match strategy with + | Snone -> raise Stop + | Scode s -> + Register.wp_compute + s.sp_kf s.sp_bhv s.sp_ip + | Scall s -> + Register.wp_compute_call + ~kf_caller:s.sc_caller + ~kf_called:s.sc_called + s.sc_callat + end ; + main_ui#rehighlight () ; + Po_navigator.refresh_panel () ; + Task.on_server_stop + (Prover.server ()) + (fun () -> + Po_navigator.refresh_status () ; + if Wp_parameters.RTE.get () (* TODO[LC] can be optimized *) + then main_ui#redisplay () + else main_ui#rehighlight () ) ; + with Stop -> () + +(* ------------------------------------------------------------------------ *) +(* --- Source Highlighter --- *) +(* ------------------------------------------------------------------------ *) + +let wp_highlight + (buffer:GSourceView2.source_buffer) + (localizable:Pretty_source.localizable) + ~(start:int) ~(stop:int) = + match localizable with + | Pretty_source.PStmt(_,({ skind=Instr(Call(_,e,_,_)) } as stmt)) -> + (match WpStrategy.get_called_kf e with + | Some kg -> + let ips = WpAnnot.lookup_called_preconditions_at kg stmt in + if ips <> [] then + let validity = Property_status.Feedback.get_conjunction ips in + Design.Feedback.mark buffer ~start ~stop validity + | None -> ()) + | _ -> () + +(* ------------------------------------------------------------------------ *) +(* --- Source Callback --- *) +(* ------------------------------------------------------------------------ *) + +let is_rte_generated kf = + List.for_all + (fun (_,_,lookup,_) -> lookup kf) + (!Db.RteGen.get_all_status ()) + +let is_rte_precond kf = + let (_,_,lookup,_) = !Db.RteGen.get_precond_status () in (lookup kf) + +let add_rte_menu + (popup_factory:GMenu.menu GMenu.factory) + (main_ui:Design.main_window_extension_points) localizable = + begin + match localizable with + | Pretty_source.PVDecl (Some kf,{vglob=true}) -> + if not (is_rte_generated kf) then + ignore (popup_factory#add_item "Insert WP-safety guards" + ~callback:(fun () -> !Db.RteGen.do_all_rte kf ; main_ui#redisplay ())) ; + if not (is_rte_precond kf) then + ignore (popup_factory#add_item "Insert all callees contract" + ~callback:(fun () -> !Db.RteGen.do_precond kf ; main_ui#redisplay ())) ; + | Pretty_source.PStmt(kf,({ skind=Instr(Call _) })) -> + if not (is_rte_precond kf) then + ignore (popup_factory#add_item "Insert callees contract (all calls)" + ~callback:(fun () -> !Db.RteGen.do_precond kf ; main_ui#redisplay ())) ; + | _ -> () + end + +let add_wp_menu + (popup_factory:GMenu.menu GMenu.factory) + (main_ui:Design.main_window_extension_points) + localizable = + let strategy = get_strategy localizable in + let add_wp_run descr = + ignore (popup_factory#add_item + (Printf.sprintf "Prove %s by WP" descr) + ~callback:(fun () -> run_and_prove main_ui strategy)) + in + match strategy with + | Snone -> () + | Scall _ -> add_wp_run "call preconditions" + | Scode { sp_target = descr } -> add_wp_run descr + +let wp_select + (popup_factory:GMenu.menu GMenu.factory) + (main_ui:Design.main_window_extension_points) + ~button localizable = + match button with + | 3 -> (* Popup Menu: *) + add_wp_menu popup_factory main_ui localizable ; + add_rte_menu popup_factory main_ui localizable ; + | _ -> (* Other buttons... *) () + +(* ------------------------------------------------------------------------ *) +(* --- WP Panel --- *) +(* ------------------------------------------------------------------------ *) + +let wp_model_menu = [ + "Hoare" , "Hoare" ; + "Store" , "Store" ; + "Runtime" , "Runtime" ; +] + +type p_select = + | NoProver + | Prover of string + +let wp_prover_menu = [ + "None" , NoProver ; + "Alt-Ergo" , Prover "alt-ergo" ; + "Coq" , Prover "coqide" ; + "Z3" , Prover "z3" ; + "Simplify" , Prover "simplify" ; + "Vampire" , Prover "vampire"; + "CVC3" , Prover "cvc3" ; + "Yices" , Prover "yices" ; + "Zenon" , Prover "zenon" ; +] + +let wp_prover_get () = + match Wp_parameters.Prover.get () with + | "alt-ergo" -> Prover "alt-ergo" + | "coqide" -> Prover "coqide" + | "coq" -> Wp_parameters.Prover.set "coqide" ; Prover "coqide" + | "simplify" -> Prover "simplify" + | "vampire" -> Prover "vampire" + | "z3" -> Prover "z3" + | "cvc3" -> Prover "cvc3" + | "yices" -> Prover "yices" + | "zenon" -> Prover "zenon" + | _ -> NoProver + +let wp_dir = ref + (try + let home = Sys.getenv "HOME" in + if Sys.file_exists home && Sys.is_directory home + then home else raise Not_found + with Not_found -> Sys.getcwd ()) + +let wp_script () = + let file = GToolbox.select_file + ~title:"Script File for Coq proofs" + ~dir:wp_dir ~filename:"wp.script" () + in + match file with + | Some f -> Wp_parameters.Script.set f + | None -> () + +let wp_prover_set = function + | Prover p -> + if p="coqide" && Wp_parameters.Script.get() = "" + then wp_script () ; + Wp_parameters.Prover.set p + | NoProver -> + Wp_parameters.Prover.set "none" + +let wp_panel (main_ui:Design.main_window_extension_points) = + let vbox = GPack.vbox () in + let demon = Gtk_form.demon () in + let packing = vbox#pack in + let form = new Gtk_form.form ~packing in + + form#label "Model" ; + Gtk_form.menu wp_model_menu + ~tooltip:"Memory model selection" ~packing:form#item + Wp_parameters.Model.get Wp_parameters.Model.set demon ; + + form#label "Prover" ; + Gtk_form.menu wp_prover_menu + ~tooltip:"Prover selection" + ~packing:form#item + wp_prover_get wp_prover_set demon ; + + let options = GPack.hbox ~spacing:8 ~packing () in + + Gtk_form.check ~label:"RTE" + ~tooltip:"Generates RTE guards for WP" + ~packing:options#pack + Wp_parameters.RTE.get Wp_parameters.RTE.set demon ; + + Gtk_form.check ~label:"Split" + ~tooltip:"Split cunjunctions into sub-goals" + ~packing:options#pack + Wp_parameters.Split.get Wp_parameters.Split.set + demon ; + + Gtk_form.check ~label:"Invariants" + ~tooltip:"Alternative WP for loop with arbitrary invariants" + ~packing:options#pack + Wp_parameters.Invariants.get Wp_parameters.Invariants.set demon ; + + Gtk_form.check ~label:"Trace" + ~tooltip:"Report proof information from the provers" + ~packing:options#pack + Wp_parameters.ProofTrace.get Wp_parameters.ProofTrace.set demon ; + + let control = GPack.hbox ~packing () in + + Gtk_form.button ~label:"Scripts" + ~tooltip:"Script file for saving Coq proofs" + ~callback:wp_script ~packing:control#pack () ; + + Gtk_form.label ~text:"Timeout" ~packing:control#pack () ; + Gtk_form.spinner ~lower:0 ~upper:100000 + ~tooltip:"Timeout for proving one proof obligation" + ~packing:control#pack + Wp_parameters.Timeout.get Wp_parameters.Timeout.set demon ; + + Gtk_form.label ~text:"Process" ~packing:control#pack () ; + Gtk_form.spinner ~lower:1 ~upper:32 + ~tooltip:"Maximum number of parallel running provers" + ~packing:control#pack + Wp_parameters.Procs.get + (fun n -> + Wp_parameters.Procs.set n ; + ignore (Prover.server ()) (* to make server procs updated is server exists *) + ) demon ; + + let pbox = GPack.hbox ~packing ~show:false () in + let progress = GRange.progress_bar ~packing:(pbox#pack ~expand:true ~fill:true) () in + let cancel = GButton.button ~packing:(pbox#pack ~expand:false) ~stock:`STOP () in + cancel#misc#set_sensitive false ; + let server = Prover.server () in + ignore (cancel#connect#released (fun () -> Task.cancel_all server)) ; + let inactive = (0,0) in + let state = ref inactive in + Task.on_server_activity server + (fun () -> + let scheduled = Task.scheduled server in + let terminated = Task.terminated server in + let remaining = scheduled - terminated in + + if remaining <= 0 then + ( pbox#misc#hide () ; state := inactive ; cancel#misc#set_sensitive false ) + else + begin + if !state = inactive then + ( pbox#misc#show () ; cancel#misc#set_sensitive true ) ; + + let s_term , s_sched = !state in + + if s_term <> terminated + then ( Po_navigator.refresh_status () ; main_ui#rehighlight () ) ; + if s_sched <> scheduled || s_term <> terminated then + begin + progress#set_text (Printf.sprintf "%d / %d" terminated scheduled) ; + progress#set_fraction + (if scheduled = 0 then 1.0 else (float terminated /. float scheduled)) ; + end ; + + state := (terminated,remaining) ; + end) ; + "WP" , vbox#coerce , Some (Gtk_form.refresh demon) + +(* ------------------------------------------------------------------------ *) +(* --- Registering WP GUI --- *) +(* ------------------------------------------------------------------------ *) + +let main main_ui = + begin + main_ui#register_source_highlighter wp_highlight ; + main_ui#register_source_selector wp_select ; + main_ui#register_panel wp_panel ; + end + +let () = Design.register_extension main + +(* ------------------------------------------------------------------------ *) + +(* + Local Variables: + compile-command: "make -C ../.." + End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/Wp.mli frama-c-20111001+nitrogen+dfsg/src/wp/Wp.mli --- frama-c-20110201+carbon+dfsg/src/wp/Wp.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/Wp.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* $Id: Wp.mli 15451 2011-10-04 11:34:51Z signoles $ *) + +(** Weakest preconditions. *) + +(** No function is directly exported: they are registered in + {!Db.Properties}. *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpo.ml frama-c-20111001+nitrogen+dfsg/src/wp/wpo.ml --- frama-c-20110201+carbon+dfsg/src/wp/wpo.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpo.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,585 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(* --- Proof Obligations --- *) +(* ------------------------------------------------------------------------ *) + +open Cil_types + +type po = t and t = +{ + po_fun : kernel_function ; (* function *) + po_bhv : string option ; (* behavior *) + po_pid : WpPropId.prop_id ; (* goal target property *) + po_gid : string ; (* goal identifier *) + po_env : string ; (* goal environment identifier *) + po_model : string ; (* model identifier *) + po_updater : Emitter.t ; (* property status updater *) + po_name : string ; (* goal informal name *) + po_dep : Property.t list ; (* dependencies *) + po_warn : warning list ; (* warnings *) +} + +and warning = { + wrn_loc : Lexing.position ; + wrn_severe : bool ; + wrn_source : string ; + wrn_reason : string ; + wrn_effect : string ; +} + +module PODatatype = + Datatype.Make( + struct + type t = po + include Datatype.Undefined + let name = "Wpo.po" + let reprs = + [ { po_fun = List.hd Kernel_function.reprs; + po_bhv = Some "Cil.default_behavior_name"; + po_pid = List.hd WpPropId.Prop_id_datatype.reprs; + po_gid = "xxx"; + po_env = ""; + po_model = "Store"; + po_updater = List.hd Emitter.reprs; + po_name = "dummy"; + po_dep = []; + po_warn = [];}] + end) + +type prover = + | Why of string (* Prover via WHY *) + | AltErgo (* Alt-Ergo *) + | Coq (* Coq and Coqide *) + | WP (* Simplifier *) + +module ProverType = + Datatype.Make + (struct + type t = prover + include Datatype.Undefined + let name = "Wpo.prover" + let reprs = [ AltErgo; Coq; WP; Why "z3" ] + end) + +type language = + | L_why + | L_coq + | L_altergo + +type result = + | Valid + | Invalid + | Unknown + | Timeout + | Computing + | Failed of string + +module ResultType = + Datatype.Make + (struct + type t = result + include Datatype.Undefined + let name = "Wpo.result" + let reprs = [ Valid; Invalid; Unknown; Timeout; + Computing; Failed "error" ] + end) + +(* -------------------------------------------------------------------------- *) +(* --- Pretty Printers --- *) +(* -------------------------------------------------------------------------- *) + +let pp_warning fmt w = + begin + Format.fprintf fmt + "@[<v 0>%s:%d: warning from %s:@\n" + w.wrn_loc.Lexing.pos_fname + w.wrn_loc.Lexing.pos_lnum + w.wrn_source ; + if w.wrn_severe then + Format.fprintf fmt " - Warning: %s, looking for context inconsistency" + w.wrn_effect + else + Format.fprintf fmt " - Warning: %s" w.wrn_effect ; + Format.fprintf fmt "@\n Reason: %s@]" w.wrn_reason ; + end + +let pp_dependency kf fmt d = + Format.fprintf fmt " - Assumes %a" (Description.pp_localized ~kf:(`Context kf) ~ki:false) d + +let pp_depend fmt d = + Format.fprintf fmt " - Assumes %a" (Description.pp_localized ~kf:`Always ~ki:false) d + +let pp_prover fmt = function + | AltErgo -> Format.pp_print_string fmt "Alt-Ergo" + | Coq -> Format.pp_print_string fmt "Coq" + | Why smt -> + if Wp_parameters.debug_atleast 1 then + Format.pp_print_string fmt ("Why:"^(String.capitalize smt)) + else + Format.pp_print_string fmt (String.capitalize smt) + | WP -> Format.fprintf fmt "WP" + +let pp_language fmt = function + | L_altergo -> Format.pp_print_string fmt "Alt-Ergo" + | L_coq -> Format.pp_print_string fmt "Coq" + | L_why -> Format.pp_print_string fmt "Why" + +let pp_result fmt = function + | Valid -> Format.pp_print_string fmt "Valid" + | Invalid -> Format.pp_print_string fmt "Invalid" + | Unknown -> Format.pp_print_string fmt "Unknown" + | Timeout -> Format.pp_print_string fmt "Timeout" + | Computing -> Format.pp_print_string fmt "Computing" + | Failed msg -> + if Wp_parameters.debug_atleast 1 + then Format.fprintf fmt "Failed@\nError: %s" msg + else Format.fprintf fmt "Failed" + +(* -------------------------------------------------------------------------- *) +(* --- Proof Collector --- *) +(* -------------------------------------------------------------------------- *) + +module Hproof = Hashtbl.Make(Datatype.Pair(Datatype.String)(Property)) + (* Table indexed by ( Model name , Property proved ) *) + +module Results = +struct + type t = (prover,result) Hashtbl.t + let create () = Hashtbl.create 7 + let replace t p r = Hashtbl.replace t p r + let clear t = Hashtbl.clear t + let remove t p = Hashtbl.remove t p + let get t p = try Some (Hashtbl.find t p) with Not_found -> None + let iter = Hashtbl.iter +end + +(* -------------------------------------------------------------------------- *) +(* --- Wpo Database --- *) +(* -------------------------------------------------------------------------- *) + +module WPO = +struct + type t = po + let hash t = Hashtbl.hash t.po_gid + let equal a b = (a.po_gid = b.po_gid) + let compare a b = + let c = String.compare a.po_model b.po_model in + if c<>0 then c else + let c = String.compare a.po_name b.po_name in + if c<>0 then c else + let c = WpPropId.compare_prop_id a.po_pid b.po_pid in + if c<>0 then c else String.compare a.po_gid b.po_gid +end + +module Kfmap = Kernel_function.Map +module Imap = Map.Make(String) +module WPOset = Set.Make(WPO) +module Hpo = Hashtbl.Make(WPO) + +type system = { + mutable environments : int Imap.t ; + (* context name -> # of environment *) + mutable last : (string * int * string) option ; + (* last environment generated *) + mutable index : WPOset.t Imap.t Kfmap.t ; + (* all Wpo added, indexed by kernel-function and behavior *) + proofs : WpAnnot.proof Hproof.t ; + (* proof collector *) + results : Results.t Hpo.t ; + (* results collector *) +} + +let system = { + last = None ; + environments = Imap.empty ; + index = Kfmap.empty ; + proofs = Hproof.create 131 ; + results = Hpo.create 131 ; +} + +(* -------------------------------------------------------------------------- *) +(* --- Getters --- *) +(* -------------------------------------------------------------------------- *) + +let get_gid = + Dynamic.register + ~plugin:"Wp" "Wpo.get_gid" ~journalize:false + (Datatype.func PODatatype.ty Datatype.string) + (fun g -> g.po_gid) + +let get_prop_id = + Dynamic.register + ~plugin:"Wp" "Wpo.get_prop_id" ~journalize:false + (Datatype.func PODatatype.ty WpPropId.Prop_id_datatype.ty) + (fun g -> g.po_pid) + +(* ------------------------------------------------------------------------ *) +(* --- WPO Construction --- *) +(* ------------------------------------------------------------------------ *) + +(* A WPO is uniquely determined by : + 1. The context name (unique per updater by construction) + 2. The kernel-function + 3. The behavior + 4. The target prop-id +*) + +let gid ~context ~kf ~bhv ~propid = + let gname = WpPropId.prop_id_name propid in + let fname = Kernel_function.get_name kf in + match bhv with + | Some b -> Printf.sprintf "%s_%s_%s_%s" context fname b gname + | None -> Printf.sprintf "%s_%s_%s" context fname gname + +(* -------------------------------------------------------------------------- *) +(* --- Registry of POs --- *) +(* -------------------------------------------------------------------------- *) + +let clear () = + begin + system.index <- Kfmap.empty ; + Hproof.clear system.proofs ; + Hpo.clear system.results ; + end + +let env_name model k = Printf.sprintf "%s_env%d" model k + +let new_env ~context = + let k = + try succ (Imap.find context system.environments) + with Not_found -> 1 in + system.environments <- Imap.add context k system.environments ; + let env = env_name context k in + system.last <- Some (context,k,env) ; env + +let release_env ~env = + match system.last with + | Some (model,k0,env0) -> + if env0 = env then + system.environments <- + Imap.add model (pred k0) system.environments + | None -> () + +let add g = + begin + let bmap = + try Kfmap.find g.po_fun system.index + with Not_found -> Imap.empty + in + let bhv = match g.po_bhv with None -> "" | Some b -> b in + let pset = + try Imap.find bhv bmap + with Not_found -> WPOset.empty + in + if WPOset.mem g pset then + begin + let pi = ( g.po_model , WpPropId.property_of_id g.po_pid ) in + Hproof.remove system.proofs pi ; + Hpo.remove system.results g ; + end ; + let pset' = WPOset.add g pset in + let bmap' = Imap.add bhv pset' bmap in + system.index <- Kfmap.add g.po_fun bmap' system.index ; + end + +let set_po_result g r = + try + let pi = ( g.po_model , WpPropId.property_of_id g.po_pid ) in + let proof = + try Hproof.find system.proofs pi + with Not_found -> + let proof = WpAnnot.create_proof g.po_pid in + Hproof.add system.proofs pi proof ; proof + in + if r = Valid then WpAnnot.add_proof proof g.po_pid g.po_dep ; + let status = + if WpAnnot.is_proved proof then Property_status.True + else Property_status.Dont_know + in + let target = WpAnnot.target proof in + let depends = WpAnnot.dependencies proof in + Property_status.emit g.po_updater ~hyps:depends target status ; + with + (* [JS 2011/01/28] Please do not catch Log.* exception. Let the kernel do + the job *) + | Log.AbortFatal plugin as err -> + Wp_parameters.failure + "Update-status failed (problem in %s)" plugin ; + raise err + | err -> + Wp_parameters.failure + "Update-status failed (%s)" (Printexc.to_string err); + raise err + +let set_result g p r = + begin + let rs = + try Hpo.find system.results g + with Not_found -> + let rs = Results.create () in + Hpo.add system.results g rs ; rs + in + Results.replace rs p r ; + set_po_result g r ; + if p = WP then Wp_parameters.result "[WP:simplified] Goal %s : Valid" g.po_gid ; + end + +let get_result g p = + try Results.get (Hpo.find system.results g) p + with Not_found -> None + +let get_result = + Dynamic.register ~plugin:"Wp" "Wpo.get_result" ~journalize:false + (Datatype.func2 PODatatype.ty ProverType.ty + (Datatype.option ResultType.ty)) + get_result + +let is_valid = + Dynamic.register ~plugin:"Wp" "Wpo.is_valid" ~journalize:false + (Datatype.func ResultType.ty Datatype.bool) + (function Valid -> true | _ -> false) + + + +let get_results g = + try + let a = ref [] in + Results.iter (fun p r -> a:=(p,r)::!a) (Hpo.find system.results g) ; !a + with Not_found -> [] + +(* -------------------------------------------------------------------------- *) +(* --- Iterator --- *) +(* -------------------------------------------------------------------------- *) + +let iter ?on_environment ?on_function ?on_behavior ?on_goal () = + begin + match on_environment with + | None -> () + | Some phi -> + Imap.iter + (fun m k -> + for i = 1 to k do + phi (env_name m i) + done) + system.environments + end ; + if on_function <> None || on_behavior <> None || on_goal <> None + then + let sorted_index = + List.sort + (fun (k1,_) (k2,_) -> + if Kernel_function.equal k1 k2 then 0 else + if Kernel_function.get_name k1 <= Kernel_function.get_name k2 + then -1 else 1) + (Kfmap.fold (fun k v a -> (k,v)::a) system.index []) + in + List.iter + (fun (kf,bmap) -> + if (on_behavior <> None || on_goal <> None) && + not (Imap.is_empty bmap) + then + begin + ( match on_function with + | None -> () + | Some phi -> phi kf ) ; + let sorted_behaviors = + List.sort + (fun (k1,_) (k2,_) -> String.compare k1 k2) + (Imap.fold (fun k v a -> (k,v)::a) bmap []) + in + List.iter + (fun (b,pset) -> + if not (WPOset.is_empty pset) then + begin + ( match on_behavior with + | None -> () + | Some phi -> + phi kf (if b="" then None else Some b) ) ; + match on_goal with + | None -> () + | Some f -> WPOset.iter f pset + end) + sorted_behaviors + end) + sorted_index + +let iter_on_goals = + Dynamic.register ~plugin:"Wp" "Wpo.iter_on_goals" + (Datatype.func (Datatype.func PODatatype.ty Datatype.unit) Datatype.unit) + ~journalize:true + (fun on_goal -> iter ~on_goal ()) + +(* -------------------------------------------------------------------------- *) +(* --- Prover and Files --- *) +(* -------------------------------------------------------------------------- *) + +let local base suffix = + let dir = Wp_parameters.get_output () in + Printf.sprintf "%s/%s%s" dir base suffix + +let file_for_lang base lang = + let dir = Wp_parameters.get_output () in + let suffix = + match lang with + | L_altergo -> "_ergo.why" + | L_why -> ".why" + | L_coq -> ".v" + in Printf.sprintf "%s/%s%s" dir base suffix + +let file_for_ctxt ~env = local env ".txt" +let file_for_head ~gid = local gid "_head.txt" +let file_for_body ~gid = local gid "_body.txt" +let file_for_log_proof ~gid = function + | Why s -> local gid ("_" ^s^".txt") + | Coq -> local gid "_coq.txt" + | AltErgo -> local gid "_ergo.txt" + | WP -> local gid "_wp.txt" + +let file_for_log_proof_ = + Dynamic.register ~plugin:"Wp" "Wpo.file_for_log_proof" ~journalize:false + (Datatype.func2 + ~label1:("gid",None) Datatype.string ProverType.ty Datatype.string) + (fun gid p -> file_for_log_proof ~gid p) + +let file_for_log_check ~gid = function + | L_why -> local gid "_why.txt" + | L_coq -> local gid "_coq.txt" + | L_altergo -> local gid "_ergo.txt" + +let file_for_goal ~gid lang = file_for_lang gid lang +let file_for_env ~env lang = file_for_lang env lang +let file_for_po ~gid lang = file_for_lang (gid ^ "_po") lang + +let file_for_model ~model lang = + let dshare = Wp_parameters.get_share() in + let suffix = + match lang with + | L_altergo -> "_ergo.why" + | L_why -> "_model.why" + | L_coq -> "_model.v" + in Printf.sprintf "%s/%s%s" dshare model suffix + +let coq_for_env ~env = env +let coq_for_model ~model = model^"_model" +let coqc_for_model ~model = + let dir = Wp_parameters.get_output () in + Printf.sprintf "%s/%s_model.v" dir model + +let prover_of_name = function + | "" | "none" -> None + | "alt-ergo" -> Some AltErgo + | "coq" | "coqide" -> Some Coq + | s -> Some (Why s) + +let prover_of_name = + Dynamic.register ~plugin:"Wp" "Wpo.prover_of_name" ~journalize:false + (Datatype.func Datatype.string (Datatype.option ProverType.ty)) + prover_of_name + +let language_of_name = function + | "" | "none" -> None + | "alt-ergo" -> Some L_altergo + | "coq" | "coqide"-> Some L_coq + | "why" -> Some L_why + | s -> Wp_parameters.abort "Language '%s' unknown" s + +let language_of_prover = function + | Why _ -> L_why + | Coq -> L_coq + | AltErgo -> L_altergo + | WP -> L_why + + +let language_of_prover_name = function + | "" | "none" -> None + | "alt-ergo" -> Some L_altergo + | "coq" | "coqide" -> Some L_coq + | _ -> Some L_why + + +let is_interactive = function + | "coqide" -> true + | _ -> false + +let gui_provers = [ WP ; AltErgo ; Coq ; + Why "z3" ; Why "simplify" ; + Why "vampire"; + Why "cvc3" ; Why "yices" ; + Why "zenon" ] + + +(* -------------------------------------------------------------------------- *) +(* --- Proof Obligations : Pretty-printing --- *) +(* -------------------------------------------------------------------------- *) + +let bar = String.make 60 '-' +let flow = ref false + +let pp_environment fmt env = + Format.fprintf fmt + "%s@\n Proof Environment %s@\n%s@\n@\n%a" + bar (String.capitalize env) bar + Command.pp_from_file (file_for_ctxt ~env) + +let pp_function fmt kf bhv = + flow := true ; + match bhv with + | None -> + Format.fprintf fmt + "%s@\n Function %s@\n%s@\n@\n" + bar (Kernel_function.get_name kf) bar + | Some bhv -> + Format.fprintf fmt + "%s@\n Function %s with behavior %s@\n%s@\n@\n" + bar (Kernel_function.get_name kf) bhv bar + +let pp_goal fmt g = + begin + Format.fprintf fmt "@[<v 0>Proof Obligation %s:@]@\n" g.po_name ; + List.iter + (fun (prover,result) -> + Format.fprintf fmt "Prover %a returns %a@\n" + pp_prover prover + pp_result result ; + ) (get_results g) ; + Format.fprintf fmt "Environment: %s@\n" (String.capitalize g.po_env) ; + List.iter (fun d -> Format.fprintf fmt "%a@\n" (pp_dependency g.po_fun) d) g.po_dep ; + List.iter (fun w -> Format.fprintf fmt "%a@\n" pp_warning w) g.po_warn ; + Format.fprintf fmt " + Proves %a@\n" (WpPropId.pretty_context g.po_fun) g.po_pid ; + Command.pp_from_file fmt (file_for_body ~gid:g.po_gid) + end + +let pp_goal_flow fmt g = + begin + if not !flow then Format.pp_print_newline fmt () ; + pp_goal fmt g ; + Format.fprintf fmt "@\n%s@." bar ; + flow := false ; + end + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpo.mli frama-c-20111001+nitrogen+dfsg/src/wp/wpo.mli --- frama-c-20110201+carbon+dfsg/src/wp/wpo.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpo.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,148 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(**{1 Proof Obligations} *) +(* ------------------------------------------------------------------------ *) + +open Cil_types + +(* Dynamically exported as ["Wpo.po"] *) +type t = +{ + po_fun : kernel_function ; (* function *) + po_bhv : string option ; (* behavior *) + po_pid : WpPropId.prop_id ; (* goal target property *) + po_gid : string ; (* goal identifier *) (** Uniquely Identify an object of type Wpo.t *) + po_env : string ; (* goal environment identifier *) + po_model : string ; (* model identifier *) + po_updater : Emitter.t ; (* property status updater *) + po_name : string ; (* goal informal name *) + po_dep : Property.t list ; (* dependencies *) + po_warn : warning list ; (* warnings *) +} + +and warning = { + wrn_loc : Lexing.position ; + wrn_severe : bool ; + wrn_source : string ; + wrn_reason : string ; + wrn_effect : string ; +} + +(** Dynamically exported. *) +type prover = + | Why of string (* Prover via WHY *) + | AltErgo (* Alt-Ergo *) + | Coq (* Coq and Coqide *) + | WP (* Simplifier *) + +type language = + | L_why + | L_coq + | L_altergo + +type result = + | Valid + | Invalid + | Unknown + | Timeout + | Computing + | Failed of string + +(** Dynamically exported + @since Nitrogen-20111001 +*) +val get_gid: t -> string + +val clear : unit -> unit + +val gid : context:string -> kf:kernel_function -> bhv:string option -> propid:WpPropId.prop_id -> string +val add : t -> unit +val new_env : context:string -> string (** Generates a fresh environment name. *) +val release_env : env:string -> unit (** Releases the last generated environment name. *) +val set_result : t -> prover -> result -> unit + +(** Dynamically exported. *) +val get_result : t -> prover -> result option +val get_results : t -> (prover * result) list + +(** [true] if the result is valid. Dynamically exported. + @since Nitrogen-20111001 +*) +val is_valid: result -> bool + +val iter : + ?on_environment:(string -> unit) -> + ?on_function:(kernel_function -> unit) -> + ?on_behavior:(kernel_function -> string option -> unit) -> + ?on_goal:(t -> unit) -> + unit -> unit + +(** Dynamically exported. + @since Nitrogen-20111001 +*) +val iter_on_goals: (t -> unit) -> unit + +val bar : string +val pp_warning : Format.formatter -> warning -> unit +val pp_depend : Format.formatter -> Property.t -> unit +val pp_dependency : Kernel_function.t -> Format.formatter -> Property.t -> unit +val pp_goal : Format.formatter -> t -> unit +val pp_environment : Format.formatter -> string -> unit +val pp_prover : Format.formatter -> prover -> unit +val pp_result : Format.formatter -> result -> unit +val pp_language : Format.formatter -> language -> unit + +val pp_function : Format.formatter -> Kernel_function.t -> string option -> unit +val pp_goal_flow : Format.formatter -> t -> unit + +(** {2 File access for WPO} *) + +val file_for_ctxt : env:string -> string +val file_for_head : gid:string -> string +val file_for_body : gid:string -> string +(** Dynamically exported. *) +val file_for_log_proof : gid:string -> prover -> string +val file_for_log_check : gid:string -> language -> string +val file_for_po : gid:string -> language -> string +val file_for_goal : gid:string -> language -> string +val file_for_env : env:string -> language -> string +val file_for_model : model:string -> language -> string + +val coq_for_env: env:string -> string +val coq_for_model : model:string -> string +val coqc_for_model : model:string -> string + +val language_of_prover : prover -> language +val language_of_name : string -> language option +(** Dynamically exported. *) +val prover_of_name : string -> prover option +val language_of_prover_name: string -> language option +val is_interactive : string -> bool +val gui_provers : prover list + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wp_parameters.ml frama-c-20111001+nitrogen+dfsg/src/wp/wp_parameters.ml --- frama-c-20110201+carbon+dfsg/src/wp/wp_parameters.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wp_parameters.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,584 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +include Plugin.Register + (struct + let name = "WP" (* Format.sprintf "WP %s" Wp_version.version *) + let shortname = "wp" + let help = "Weakest Preconditions Calculus" (* v%d Wp_version.version *) + end) + +(* localize all warnings inside WP *) + +let warning ?current = match current with + | None -> warning ~current:true + | Some b -> warning ~current:b + +let resetdemon = ref [] +let on_reset f = resetdemon := f :: !resetdemon +let reset () = List.iter (fun f -> f ()) !resetdemon + +module DebugKey = + StringList + (struct + let option_name = "-wp-log" + let arg_name = "..." + let help = "Undocumented feature" + let kind = `Irrelevant + end) +let () = DebugKey.add_set_hook (fun _old -> set_debug_keys) + +(* ------------------------------------------------------------------------ *) +(* --- WP Generation --- *) +(* ------------------------------------------------------------------------ *) + +let wp_generation = add_group "Goal Selection" + +let () = Plugin.set_group wp_generation +let () = Plugin.do_not_save () +module WP = + Action(struct + let option_name = "-wp" + let help = "Computes wp on all functions." + let kind = `Tuning + end) +let () = on_reset WP.clear + +let () = Plugin.set_group wp_generation +let () = Plugin.do_not_save () +module Functions = + StringList + (struct + let option_name = "-wp-fct" + let arg_name = "f,..." + let help = "Computes wp only for the selected functions." + let kind = `Tuning + end) +let () = on_reset Functions.clear + +let () = Plugin.set_group wp_generation +let () = Plugin.do_not_save () +module Behaviors = + StringList + (struct + let option_name = "-wp-bhv" + let arg_name = "b,..." + let help = "Computes wp only for the selected behaviors." + let kind = `Tuning + end) +let () = on_reset Behaviors.clear + +let () = Plugin.set_group wp_generation +let () = Plugin.do_not_save () +module Properties = + (* TODO [LC] : restablish several names *) + StringList + (struct + let option_name = "-wp-prop" + let arg_name = "p" + let help = "Computes wp only for the selected properties.\n\ + Type 'assigns' for all assigns clauses" + let kind = `Tuning + end) +let () = on_reset Properties.clear + +type job = + | WP_None + | WP_All + | WP_Select of string list + +let job () = + match Functions.get (), Behaviors.get () with + | [], [] -> + (if WP.get () then WP_All + else match Properties.get () with + | [] -> WP_None + | _ :: _ -> WP_Select []) + | (_ :: _ as fct, _) | fct, _ :: _ -> WP_Select fct + +let () = Plugin.set_group wp_generation +module StatusAll = + False(struct + let option_name = "-wp-status-all" + let help = "Select properties with any status (default: no)" + let kind = `Tuning + end) + +let () = Plugin.set_group wp_generation +module StatusTrue = + False(struct + let option_name = "-wp-status-valid" + let help = "Select properties with status 'Valid' (default: no)" + let kind = `Tuning + end) + +let () = Plugin.set_group wp_generation +module StatusFalse = + False(struct + let option_name = "-wp-status-invalid" + let help = "Select properties with status 'Invalid' (default: no)" + let kind = `Tuning + end) + +let () = Plugin.set_group wp_generation +module StatusMaybe = + True(struct + let option_name = "-wp-status-maybe" + let help = "Select properties with status 'Maybe' (default: yes)" + let kind = `Tuning + end) + +(* ------------------------------------------------------------------------ *) +(* --- Froms --- *) +(* ------------------------------------------------------------------------ *) + +let () = Plugin.set_group wp_generation +module Froms = + False(struct + let option_name = "-wp-froms" + let help = "Undocumented (dot not use)." + let kind = `Tuning + end) + +(* ------------------------------------------------------------------------ *) +(* --- Memory Models --- *) +(* ------------------------------------------------------------------------ *) + +let wp_model = add_group "Model Selection" + +type model_kind = + | M_Hoare + | M_Store + | M_Runtime + +let model_names = + [ "Hoare" ; "Store"; "Runtime" ] + +let model_of_name = function + | "Runtime" -> M_Runtime + | "Store" -> M_Store + | "Hoare" -> M_Hoare + | _ -> raise Not_found + +let () = Plugin.set_group wp_model +module Model = + String(struct + let option_name = "-wp-model" + let arg_name = "model" + let help = + "Memory model selection:\n\ + - 'Hoare': no indirect access to the memory\n\ + - 'Store': no heterogeneous casts (default)\n\ + - 'Runtime': low-level model" + (* "- 'Runtime': low-level model\n\ + - 'UnsafeCaveat': no alias\n\ + - 'Caveat': no alias with guards" *) + let default = "Store" + let kind = `Tuning + end) +let () = Model.set_possible_values model_names + +let get_model () = + let m = Model.get () in + try model_of_name m + with Not_found -> abort "Unknown model '%s'" m + +let get_models () = model_names + +let () = Plugin.set_group wp_model +module LogicVar = + True(struct + let option_name = "-wp-logicvar" + let help = "Apply Hoare model for variables when possible." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_model +module RefVar = + False(struct + let option_name = "-wp-byreference" + let help = "Apply Hoare model for arguments passed by reference." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_model +module Assigns = + String(struct + let option_name = "-wp-assigns" + let arg_name = "mth" + let help = "Method for proving assigns clauses:\n\ + - 'effect' one sub-goal per assignment (default)\n\ + - 'memory' strong proof (incompatible with Hoare)\n\ + - 'none' skip assigns clause (default with Hoare)" + let default = "effect" + let kind = `Tuning + end) +let () = Assigns.set_possible_values [ "effect" ; "memory" ; "none" ] +(* no reset for GUI *) + +let get_assigns_method () = + match Assigns.get () with + | "effect" -> Mcfg.EffectAssigns + | "memory" -> Mcfg.NormalAssigns + | "none" -> Mcfg.NoAssigns + | m -> abort "Unknown assigns method '%s'" m + +(* ------------------------------------------------------------------------ *) +(* --- WP Strategy --- *) +(* ------------------------------------------------------------------------ *) + +let wp_strategy = add_group "Computation Strategies" + +let () = Plugin.set_group wp_strategy +module RTE = + False(struct + let option_name = "-wp-rte" + let help = "Generates RTE guards before WP" + let kind = `Tuning + end) + +let () = Plugin.set_group wp_strategy +module Simpl = + True(struct + let option_name = "-wp-simpl" + let help = "Simplify constant terms and predicates." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_strategy +module Invariants = + False(struct + let option_name = "-wp-invariants" + let help = "Handle generalized invariants inside loops." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_strategy +module Split = + False(struct + let option_name = "-wp-split" + let help = "Split conjunctions into sub-goals." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_strategy +module SplitDim = + Int(struct + let option_name = "-wp-split-dim" + let arg_name = "n" + let default = 6 + let help = + Printf.sprintf + "Bounds the number of splited sub-goals to 2**n (default 2**%d)" default + let kind = `Tuning + end) + +let () = Plugin.set_group wp_strategy +module Norm = + String(struct + let option_name = "-wp-norm" + let arg_name = "norm" + let help = + "Predicate normalization for Coq and Alt-Ergo provers:\n\ + - Eqs: replace let-bindings by equalities (default).\n\ + - Let: preserve let-bindings.\n\ + - Exp: let-expansion.\n\ + - Cc: generates local functions by closure-conversion" + let default = "Eqs" + let kind = `Tuning + end) + +let () = Norm.set_possible_values [ "Let";"Exp";"Cc";"Eqs" ] + +type norm = Let | Exp | Eqs | Cc + +let get_norm () = + match Norm.get () with + | "Let" -> Let + | "Exp" -> Exp + | "Eqs" -> Eqs + | "Cc" -> Cc + | m -> abort "Unknown normalization '%s'" m + +let () = Plugin.set_group wp_strategy +module Huge = + Int(struct + let option_name = "-wp-huge" + let default = 30 + let arg_name = "s" + let help = + Printf.sprintf + "Limits the size for generated proof obligation.\n\ + Proof terms of size exceeding 2^s are not generated.\n\ + (default: 2^%d)" + default + let kind = `Tuning + end) + +(* ------------------------------------------------------------------------ *) +(* --- Prover Interface --- *) +(* ------------------------------------------------------------------------ *) + +let wp_prover = add_group "Prover Interface" + +let () = Plugin.set_group wp_prover +module Prover = + String(struct + let option_name = "-wp-proof" + let default = "alt-ergo" + let arg_name = "dp" + let help = + "Submit proof obligations to external prover:\n\ + - 'none' to skip proofs\n\ + Directly supported provers:\n\ + - 'alt-ergo' (default)\n\ + - 'coq', 'coqide' (see also -wp-script)\n\ + Supported provers via Why:\n\ + - 'simplify', 'vampire', 'yices', 'cvc3', 'z3', 'zenon'" + let kind = `Tuning + end) + +let prover_names = + [ "none" ; + "coq" ; "coqide" ; + "alt-ergo"; + "simplify"; + "vampire"; + "yices"; + "cvc3"; + "zenon"; + "z3" ] + +let () = Prover.set_possible_values prover_names +let get_provers () = prover_names + +let () = Plugin.set_group wp_prover +let () = Plugin.do_not_save () +module Check = + String(struct + let option_name = "-wp-check" + let default = "none" + let arg_name = "dp" + let help = + "Typecheck proof obligations for external prover:\n\ + - 'none' to skip checks (default)\n\ + - 'alt-ergo'\n\ + - 'coq'\n\ + - 'why' " + let kind = `Tuning + end) +let () = on_reset Check.clear + +let check_names = + [ "none" ; + "coq" ; + "alt-ergo"; + "why" ] + +let () = Plugin.set_group wp_prover +module Script = + String(struct + let option_name = "-wp-script" + let arg_name = "f.script" + let default = "" + let help = "Set user's file for saving Coq proofs." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_prover +module Timeout = + Int(struct + let option_name = "-wp-timeout" + let default = 10 + let arg_name = "n" + let help = + Printf.sprintf + "Set the timeout (in seconds) for provers (default: %d)." default + let kind = `Tuning + end) + +let () = Plugin.set_group wp_prover +module Procs = + Int(struct + let option_name = "-wp-par" + let arg_name = "p" + let default = 4 + let help = + Printf.sprintf + "Number of parallel proof process (default: %d)" default + let kind = `Tuning + end) + +let () = Plugin.set_group wp_prover +module Trace = + False(struct + let option_name = "-wp-trace" + let help = "Keep labels in proof obligations (default: no)." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_prover +module ShareDir = + String(struct + let option_name = "-wp-share" + let arg_name = "dir" + let default = "" + let help = "Directory where model specifications are found.\n\ + Defaults: installation directory $FRAMAC_SHARE/wp" + let kind = `Tuning + end) + +let () = Plugin.set_group wp_prover +module ProofTrace = + False + (struct + let option_name = "-wp-proof-trace" + let help = "Keeps output of provers for valid POs (default: no)" + let kind = `Tuning + end) + +(* ------------------------------------------------------------------------ *) +(* --- PO Management --- *) +(* ------------------------------------------------------------------------ *) + +let wp_po = add_group "Proof Obligations" + +let () = Plugin.set_group wp_po +let () = Plugin.do_not_save () +module Print = + Action(struct + let option_name = "-wp-print" + let help = "Pretty-prints proof obligations on standard output." + let kind = `Tuning + end) +let () = on_reset Print.clear + +let () = Plugin.set_group wp_po +let () = Plugin.do_not_save () +module Dot = + False(struct + let option_name = "-wp-dot" + let help = "Generates dot files for wp computations." + let kind = `Tuning + end) +let () = on_reset Dot.clear + +let () = Plugin.set_group wp_po +module OutputDir = + String(struct + let option_name = "-wp-out" + let arg_name = "dir" + let default = "" + let help = "Set working directory for generated files.\n\ + Defaults to some temporary directory." + let kind = `Tuning + end) + +let () = Plugin.set_group wp_po +module Details = + False(struct + let option_name = "-wp-warnings" + let help = "Print details about warnings for 'stronger' and 'degenerated' goals" + let kind = `Tuning + end) + +(* -------------------------------------------------------------------------- *) +(* --- OS environment variables --- *) +(* -------------------------------------------------------------------------- *) + +let get_env ?default var = + try + let varval = Sys.getenv var in + debug "ENV %s=%S" var varval ; varval + with Not_found -> + debug "ENV %s not set." var ; + match default with + | Some varval -> + debug "ENV %s default(%S)" var varval ; varval + | None -> + debug "ENV %s undefined." var ; + raise Not_found + +let is_out () = !Config.is_gui || OutputDir.get() <> "" + +(*TODO: Projectifier cette reference*) +let output_dir = ref None + +let make_output_dir dir = + if Sys.file_exists dir then + begin + if not (Sys.is_directory dir) then + abort "File '%s' is not a directory (WP aborted)" dir ; + dir + end + else + begin + try + Unix.mkdir dir 0o770 ; + debug "Created output directory '%s'" dir ; dir + with e -> + debug "System error '%s'" (Printexc.to_string e) ; + abort "Can not create output directory '%s'" dir + end + +let make_tmp_dir () = + begin + try Extlib.temp_dir_cleanup_at_exit "wp" + with Extlib.Temp_file_error s -> + abort "cannot create temporary file: %s" s + end + +let make_gui_dir () = + try + let home = try Sys.getenv "HOME" with Not_found -> "." in + make_output_dir (home ^ "/.frama-c-wp") + with _ -> + make_tmp_dir () + +let get_output () = + match !output_dir with + | Some dir -> dir + | None -> + let dir = + match OutputDir.get () with + | "" -> + if !Config.is_gui + then make_gui_dir () + else make_tmp_dir () + | dir -> + make_output_dir dir + in + output_dir := Some dir ; dir + +let get_share () = + match ShareDir.get() with + | "" -> Config.datadir^"/wp" + | dir -> + if Sys.file_exists dir && Sys.is_directory dir then dir + else abort "'%s': no such directory" dir + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wp_parameters.mli frama-c-20111001+nitrogen+dfsg/src/wp/wp_parameters.mli --- frama-c-20110201+carbon+dfsg/src/wp/wp_parameters.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wp_parameters.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,106 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +include Plugin.S + +val reset : unit -> unit + +(** {2 Goal Selection} *) + +module WP : Plugin.Bool +module Functions : Plugin.String_list +module Behaviors : Plugin.String_list +module Properties : Plugin.String_list +module StatusAll : Plugin.Bool +module StatusTrue : Plugin.Bool +module StatusFalse : Plugin.Bool +module StatusMaybe : Plugin.Bool + +type job = + | WP_None + | WP_All + | WP_Select of string list + +val job : unit -> job + +(** {2 Model Selection} *) + +type model_kind = + | M_Hoare + | M_Store + | M_Runtime + +val get_model : unit -> model_kind +val get_models : unit -> string list +val get_assigns_method : unit -> Mcfg.assigns_method + +module Model : Plugin.String +module LogicVar : Plugin.Bool +module RefVar : Plugin.Bool +module Assigns : Plugin.String + +(** {2 Computation Strategies} *) + +type norm = Let | Exp | Eqs | Cc +val get_norm : unit -> norm + +module RTE: Plugin.Bool +module Simpl: Plugin.Bool +module Split: Plugin.Bool +module Invariants: Plugin.Bool +module SplitDim: Plugin.Int +module Norm: Plugin.String +module Huge: Plugin.Int + +(** {2 Prover Interface} *) + +module Prover: Plugin.String +module Check : Plugin.String +module Script : Plugin.String +module Timeout: Plugin.Int +module Procs: Plugin.Int +module Trace: Plugin.Bool +module ProofTrace: Plugin.Bool + +(** {2 Proof Obligations} *) + +module Dot: Plugin.Bool +module Print: Plugin.Bool +module Details: Plugin.Bool + +(** {2 Experimental} *) + +module Froms: Plugin.Bool + +(** {2 Environment Variables} *) + +val get_env : ?default:string -> string -> string +val is_out : unit -> bool (* -wp-out <dir> positionned *) +val get_output : unit -> string +val get_share : unit -> string + + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpPropId.ml frama-c-20111001+nitrogen+dfsg/src/wp/wpPropId.ml --- frama-c-20110201+carbon+dfsg/src/wp/wpPropId.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpPropId.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,622 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + +(*----------------------------------------------------------------------------*) +(* Property identification *) +(*----------------------------------------------------------------------------*) + +(** Beside the property identification, it can be found in different contexts + * depending on which part of the computation is involved. + * For instance, properties on loops are split in 2 parts : establishment and + * preservation. + *) + +type prop_kind = + | PKProp (** normal property *) + | PKEstablished (** computation related to a loop property before the loop. *) + | PKPreserved (** computation related to a loop property inside the loop. *) + | PKPropLoop (** loop property used as hypothesis inside a loop. *) + | PKVarDecr (** computation related to the decreasing of a variant in a loop *) + | PKVarPos (** computation related to a loop variant being positive *) + | PKAFctOut (** computation related to the function assigns on normal termination *) + | PKAFctExit (** computation related to the function assigns on exit termination *) + | PKPre of kernel_function * stmt * Property.t (** precondition for function + at stmt, property of the require. Many information that should come + from the p_prop part of the prop_id, but in the PKPre case, + it seems that it is hiden in a IPBlob property ! *) + +type prop_id = { + p_kind : prop_kind ; + p_prop : Property.t ; + p_part : (int * int) option ; +} + +let parts_of_id p = p.p_part +let mk_part pid (k, n) = { pid with p_part = Some (k,n) } +let property_of_id p = p.p_prop + +exception Found of int +let num_of_bhv_from bhv (out, _) = + match bhv.b_assigns with + WritesAny -> Wp_parameters.fatal "no \\from in this behavior ???" + | Writes l -> + let add n (o, f) = match f with FromAny -> n + | From _ -> + if Logic_utils.is_same_identified_term out o then + raise (Found n) + else n+1 + in + try + let _ = List.fold_left add 1 l in + Wp_parameters.fatal "didn't found this \\from" + with Found n -> n + +(*----------------------------------------------------------------------------*) +(* Constructors *) +(*----------------------------------------------------------------------------*) + +let mk_annot_id kf stmt ca = Property.ip_of_code_annot_single kf stmt ca + +let mk_prop kind prop = { p_kind=kind ; p_prop=prop ; p_part=None } + +let mk_code_annot_id kf s ca = mk_prop PKProp (mk_annot_id kf s ca) +let mk_assert_id kf s ca = mk_prop PKProp (mk_annot_id kf s ca) +let mk_establish_id kf s ca = mk_prop PKEstablished (mk_annot_id kf s ca) +let mk_preserve_id kf s ca = mk_prop PKPreserved (mk_annot_id kf s ca) +let mk_inv_hyp_id kf s ca = mk_prop PKPropLoop (mk_annot_id kf s ca) +let mk_var_decr_id kf s ca = mk_prop PKVarDecr (mk_annot_id kf s ca) +let mk_var_pos_id kf s ca = mk_prop PKVarPos (mk_annot_id kf s ca) + +let mk_loop_from_id kf s ca from = + let id = Property.ip_of_from kf (Kstmt s) (Property.Id_code_annot ca) from in + mk_prop PKPropLoop id + +let mk_bhv_from_id kf ki bhv from = + let id = Property.ip_of_from kf ki (Property.Id_behavior bhv) from in + mk_prop PKProp id + +let get_kind_for_tk kf tkind = match tkind with + | Normal -> + if Cil2cfg.has_exit (Cil2cfg.get kf) then PKAFctOut else PKProp + | Exits -> PKAFctExit + | _ -> assert false + +let mk_fct_from_id kf bhv tkind from = + let id = Property.ip_of_from kf Kglobal (Property.Id_behavior bhv) from in + let kind = get_kind_for_tk kf tkind in + mk_prop kind id + +let mk_disj_bhv_id (kf,ki,disj) = + mk_prop PKProp (Property.ip_of_disjoint kf ki disj) +let mk_compl_bhv_id (kf,ki,comp) = + mk_prop PKProp (Property.ip_of_complete kf ki comp) +let mk_decrease_id (kf, s, x) = + mk_prop PKProp (Property.ip_of_decreases kf s x) + +let mk_axiom_id name = mk_prop PKProp (Property.ip_axiom name) + +let mk_stmt_assigns_id kf s b a = + let b = Property.Id_behavior b in + let p = Property.ip_of_assigns kf (Kstmt s) b (Writes a) in + Extlib.opt_map (mk_prop PKProp) p + +let mk_loop_assigns_id kf s ca a = + let ca = Property.Id_code_annot ca in + let p = Property.ip_of_assigns kf (Kstmt s) ca (Writes a) in + Extlib.opt_map (mk_prop PKPropLoop) p + +let mk_fct_assigns_id kf b tkind a = + let b = Property.Id_behavior b in + let kind = get_kind_for_tk kf tkind in + let p = Property.ip_of_assigns kf Kglobal b (Writes a) in + Extlib.opt_map (mk_prop kind) p + +let mk_pre_id kf ki b p = + mk_prop PKProp (Property.ip_of_requires kf ki b p) + +let mk_stmt_post_id kf s b p = + mk_prop PKProp (Property.ip_of_ensures kf (Kstmt s) b p) + +let mk_fct_post_id kf b p = + mk_prop PKProp (Property.ip_of_ensures kf Kglobal b p) + +let mk_call_pre_id called_kf s_call called_pre called_pre_p = + let kind = PKPre (called_kf, s_call, called_pre) in + mk_prop kind called_pre_p + +(*----------------------------------------------------------------------------*) + +module Prop_id_datatype = + Datatype.Make( + struct + type t = prop_id + include Datatype.Undefined + let name = "WpAnnot.prop_id" + let reprs = + List.map + (fun x -> { p_kind = PKProp; p_prop = x; p_part = None }) + Property.reprs + end) + + + + +(*----------------------------------------------------------------------------*) +(* Names and Printing *) +(* [JS 2011/08/04] This stuff seems to be related only to Property.t. + Maybe better to put it in a kernel-friendly way somewhere in module + [Property]? *) +(*----------------------------------------------------------------------------*) + +let pp_names fmt l = match l with [] -> () + | _ -> + Format.fprintf fmt "_%a" (Wp_error.pp_string_list ~empty:"" ~sep:"_") l + +let code_annot_names ca = match ca.annot_content with + | AAssert (_, named_pred) | AInvariant (_,_,named_pred) -> named_pred.name + | AVariant (term, _) -> term.term_name + | _ -> [] (* TODO : add some more names ? *) + +(** This is used to give the name of the property that the user can give + * to select it from the command line (-wp-prop option) *) +let user_prop_names p = match p with + | Property.IPPredicate (_,_,_,idp) -> idp.ip_name + | Property.IPCodeAnnot (_,_, ca) -> code_annot_names ca + | Property.IPComplete (_, _, lb) -> + let name = + Pretty_utils.sfprintf "complete_behaviors%a" pp_names lb + in [name] + | Property.IPDisjoint (_, _, lb) -> + let name = Pretty_utils.sfprintf "disjoint_behaviors%a" pp_names lb + in [name] + | Property.IPAssigns (_, _, _, l) -> + List.fold_left + (fun acc (t,_) -> t.it_content.term_name @ acc) ["assigns"] l + | Property.IPFrom _ -> ["from"] (* TODO: steal term names from assigns? *) + | Property.IPDecrease (_,_, Some ca,_) -> code_annot_names ca + | Property.IPDecrease _ -> ["decreases"](*TODO: add more names ? *) + | Property.IPAxiom _ + | Property.IPAxiomatic _ + | Property.IPLemma _ + | Property.IPBehavior _ + | Property.IPUnreachable _ + | Property.IPOther _ -> [] + +let string_of_termination_kind = function + Normal -> "post" + | Exits -> "exits" + | Breaks -> "breaks" + | Continues -> "continues" + | Returns -> "returns" + +let predicate_kind_txt pk ki = match pk, ki with + | Property.PKRequires _, Kglobal -> "pre" + | Property.PKRequires _, Kstmt _ -> "stmt_pre" + | Property.PKAssumes _, _ -> "assume" + | Property.PKEnsures (_, tk), Kglobal -> + string_of_termination_kind tk + | Property.PKEnsures (_, tk), Kstmt _ -> + "stmt_" ^ (string_of_termination_kind tk) + | Property.PKTerminates, _ -> "terminates" + +let id_prop_txt p = match p with + | Property.IPPredicate (pk,_,ki,idp) -> + Pretty_utils.sfprintf "%s_%d%a" + (predicate_kind_txt pk ki) idp.ip_id pp_names idp.ip_name + | Property.IPCodeAnnot (_,_, ca) -> + let name = match ca.annot_content with + | AAssert _ -> "assert" + | AInvariant _ -> "loop_inv" + | APragma _ -> "code_annot" + | _ -> assert false + in Pretty_utils.sfprintf "%s_%d%a" name ca.annot_id + pp_names (code_annot_names ca) + | Property.IPComplete (_, _, lb) -> + Pretty_utils.sfprintf "complete_behaviors%a" pp_names lb + | Property.IPDisjoint (_, _, lb) -> + Pretty_utils.sfprintf "disjoint_behaviors%a" pp_names lb + | Property.IPDecrease (_,_,None,_) -> "decreases" + | Property.IPDecrease _ -> "loop_variant" + | Property.IPAxiom name -> "axiom_" ^ name + | Property.IPAxiomatic(name, _) -> "axiomatic_" ^ name + | Property.IPLemma name -> "lemma_" ^ name + | Property.IPAssigns (_kf, ki, _bhv, _) -> + let name = match ki with + | Kglobal -> "function_assigns" + | Kstmt s -> + match s.skind with + | Loop _ -> "loop_assigns_" ^ string_of_int s.sid + | _ -> "stmt_assigns_" ^ string_of_int s.sid + in name + | Property.IPFrom (_, _, _, (out,_)) -> + "from_id_"^(string_of_int (out.it_id)) + | Property.IPUnreachable _ -> "unreachable stmt" + | Property.IPBehavior(_, _, b) -> b.b_name + | Property.IPOther(s,_,_) -> s + +let name_of_prop_id p = match p.p_kind , p.p_prop with + | PKProp , Property.IPAssigns (_kf, (Kstmt s), _, _) -> + "stmt_assigns_" ^ string_of_int s.sid + | PKProp , p -> id_prop_txt p + | PKPropLoop , Property.IPAssigns (_kf, (Kstmt s), _, _) -> + "loop_assigns_" ^ string_of_int s.sid + | PKPropLoop , p -> id_prop_txt p + | PKEstablished , p -> id_prop_txt p ^ "_established" + | PKPreserved , p -> id_prop_txt p ^ "_preserved" + | PKVarDecr , p -> id_prop_txt p ^ "_decrease" + | PKVarPos , p -> id_prop_txt p ^ "_positive" + | PKAFctOut , Property.IPFrom _ -> "normal_from" + | PKAFctExit , Property.IPFrom _ -> "exit_from" + | PKAFctOut , _ -> "normal_assigns" + | PKAFctExit , _ -> "exit_assigns" + | PKPre(kf,stmt,p) , _ -> + let pid = match p with + | Property.IPCodeAnnot(_,_,p) -> p.annot_id + | Property.IPPredicate(_,_,_,p) -> p.ip_id + | property -> Wp_parameters.fatal "No precondition id for @[%a@]" + Property.pretty property + in + Printf.sprintf "pre%d_%s_s%d" pid (Kernel_function.get_name kf) stmt.sid + +let prop_id_name p = match p.p_part with + | None -> name_of_prop_id p + | Some(k,_) -> Printf.sprintf "%s_part%d" (name_of_prop_id p) (succ k) + +let label_of_kind = function + | PKProp -> "Property" + | PKPropLoop -> "Invariant" (* should be assert false ??? *) + | PKEstablished -> "Establishment" + | PKPreserved -> "Preservation" + | PKVarDecr -> "Decreasing" + | PKVarPos -> "Positive" + | PKAFctOut -> "Function assigns" + | PKAFctExit -> "Exit assigns" + | PKPre(kf,_,_) -> + Printf.sprintf "Precondition for '%s'" (Kernel_function.get_name kf) + +let label_of_prop_id p = + match p.p_part with + | None -> label_of_kind p.p_kind + | Some(k,n) -> + Printf.sprintf "%s (%d/%d)" (label_of_kind p.p_kind) (succ k) n + +let pp_id_name fmt pid = Format.fprintf fmt "%s" (prop_id_name pid) + +(*----------------------------------------------------------------------------*) +(* Pretty-Print *) +(*----------------------------------------------------------------------------*) + +let pp_goal_kind fmt = function + | PKProp + | PKPropLoop + | PKAFctOut + | PKAFctExit + | PKPre _ -> () + | PKEstablished -> Format.pp_print_string fmt "Establishment of " + | PKPreserved -> Format.pp_print_string fmt "Preservation of " + | PKVarDecr -> Format.pp_print_string fmt "Decreasing of " + | PKVarPos -> Format.pp_print_string fmt "Positivity of " + +let pp_goal_part fmt = function + | None -> () + | Some(k,n) -> Format.fprintf fmt " (%d/%d)" (succ k) n + +let pretty fmt pid = + begin + pp_goal_kind fmt pid.p_kind ; + Description.pp_property fmt pid.p_prop ; + pp_goal_part fmt pid.p_part ; + end + +let pretty_context kf fmt pid = + begin + pp_goal_kind fmt pid.p_kind ; + Description.pp_localized ~kf:(`Context kf) ~ki:true fmt pid.p_prop ; + pp_goal_part fmt pid.p_part ; + end + +(*----------------------------------------------------------------------------*) +(* Comparison *) +(*----------------------------------------------------------------------------*) + +let kind_order = function + | PKProp -> 0 + | PKPre _ -> 0 + | PKEstablished -> 1 + | PKPreserved -> 2 + | PKVarPos -> 3 + | PKVarDecr -> 4 + | PKPropLoop -> 5 + | PKAFctOut -> 6 + | PKAFctExit -> 7 + +let compare_prop_id pid1 pid2 = + (* This order of compatison groups together prop_pids with same properties *) + let p1 = property_of_id pid1 in + let p2 = property_of_id pid2 in + let cmp = Property.compare p1 p2 in + if cmp <> 0 then cmp + else + let cmp = kind_order pid2.p_kind - kind_order pid1.p_kind in + if cmp <> 0 then cmp + else + Pervasives.compare pid1.p_part pid2.p_part + +let is_assigns p = + match property_of_id p with + | Property.IPAssigns _ -> true + | _ -> false + +let is_requires = function + | Property.IPPredicate (Property.PKRequires _,_,_,_) -> true + | _ -> false + +let select_by_name asked pid = + let p_prop = match pid.p_kind with + | PKPre (_,_,p_prop) -> p_prop + | _ -> property_of_id pid + in + let names = user_prop_names p_prop in + let take_it, msg = + if List.mem asked names + then true, " (asked named prop)" + else false, (match names with [] -> " (no names)" + | name::_ -> (" (asked name <> "^ name^")")) + in take_it, msg + +let select_call_pre s_call asked_pre pid = + let take_it, msg = match pid.p_kind with + | PKPre (_, p_stmt, p_prop) -> + if Stmt.equal s_call p_stmt then + let x = match asked_pre with + | None -> true, "" + | Some asked_pre -> + if Property.equal p_prop asked_pre then true, "" + else false, " (stmt ok, but not not the asked pre)" + in x + else false, " (not the asked stmt)" + | _ -> false, " (not a call pre)" + in take_it, msg + + +(*----------------------------------------------------------------------------*) +(* About assigns identification *) +(*----------------------------------------------------------------------------*) + +(** TODO: it seems that this type is not used anymore... *) +type a_fun = Assigns_FctOut | Assigns_FctExit | Assigns_Stmt | Assigns_Loop + +type a_kind = LoopAssigns | StmtAssigns + +type assigns_desc = { + a_label : Cil_types.logic_label ; + (* a_fun : a_fun ; *) + a_kind : a_kind ; + a_assigns : Cil_types.identified_term Cil_types.assigns ; +} + +let mk_loop_assigns_desc s assigns = { + a_label = Clabels.mk_logic_label s ; + (* a_fun = Assigns_Loop ; *) + a_kind = LoopAssigns ; + a_assigns = Writes assigns +} + +let mk_stmt_assigns_desc s assigns = { + a_label = Clabels.mk_logic_label s ; + (* a_fun = Assigns_Stmt ; *) + a_kind = StmtAssigns ; + a_assigns = Writes assigns ; +} + +(* +(** kf assigns for normal path when there is an exit path *) +let mk_fout_assigns_desc assigns = { + a_label = Logic_const.pre_label ; + (* a_fun = Assigns_FctOut ; *) + a_kind = StmtAssigns ; + a_assigns = Writes assigns ; +} + +(** kf assigns for exit path *) +let mk_exit_assigns_desc assigns = { + a_label = Logic_const.pre_label ; + (* a_fun = Assigns_FctExit ; *) + a_kind = StmtAssigns ; + a_assigns = Writes assigns ; +} +*) + +let mk_kf_assigns_desc assigns = { + a_label = Logic_const.pre_label ; + (* a_fun = Assigns_Stmt ; *) + a_kind = StmtAssigns ; + a_assigns = Writes assigns ; +} + +let pp_assigns_desc fmt a = Wp_error.pp_assigns fmt a.a_assigns +(*----------------------------------------------------------------------------*) +(** + * 2 kinds of annotations can be found : predicates and assigns. + * because assigns properties can only be translated into predicates + * by the memory model. + * - Assigns properties are composed of the assigns list from Cil, + * and a label to know where to stop. + * - Predicates are just the predicate type from Cil. + *) +(*----------------------------------------------------------------------------*) + +type pred_info = prop_id * Cil_types.predicate named + +let mk_pred_info id p = (id, p) +let pred_info_id (id, _) = id +let pp_pred_of_pred_info fmt (_id, p) = !Ast_printer.d_predicate_named fmt p +let pp_pred_info fmt (id, p) = + Format.fprintf fmt "(@[%a:@ %a@])" pp_id_name id !Ast_printer.d_predicate_named p + +type assigns_info = prop_id * assigns_desc + +let assigns_info_id (id,_) = id + +type assigns_full_info = + AssignsLocations of assigns_info + | AssignsAny of assigns_desc + | NoAssignsInfo + +let empty_assigns_info = NoAssignsInfo +let mk_assigns_info id a = AssignsLocations (id, a) + +let mk_stmt_any_assigns_info s = + let a = { a_label = Clabels.mk_logic_label s; (* a_fun = Assigns_Stmt; *) + a_kind = StmtAssigns; a_assigns = WritesAny } in + AssignsAny a + +let mk_kf_any_assigns_info () = + let a = { a_label = Logic_const.pre_label; (* a_fun = Assigns_Stmt; *) + a_kind = StmtAssigns; a_assigns = WritesAny } in + AssignsAny a + +let mk_loop_any_assigns_info s = + let a = { a_label = Clabels.mk_logic_label s; (* a_fun = Assigns_Loop; *) + a_kind = LoopAssigns; a_assigns = WritesAny } in + AssignsAny a + +let pp_assigns_id (id, _a) = pp_id_name id + +let pp_assign_info k fmt a = match a with + | NoAssignsInfo -> () + | AssignsAny a -> + let pkind = + match a.a_kind with + | StmtAssigns -> "" + | LoopAssigns -> "loop" + in + Format.fprintf fmt "%s(@@%a): %s assigns everything@." + k Wp_error.pp_logic_label a.a_label pkind + | AssignsLocations (_,a) -> Format.fprintf fmt "%s(@@%a): %a@." k + Wp_error.pp_logic_label a.a_label + pp_assigns_desc a + +let merge_assign_info a1 a2 = match a1,a2 with + | NoAssignsInfo, a | a, NoAssignsInfo -> a + | (AssignsLocations _ | AssignsAny _), + (AssignsLocations _ | AssignsAny _) -> + Wp_parameters.fatal "Several assigns ?" + + +type t_axiom = string * Cil_types.logic_label list * Cil_types.predicate named +type axiom_info = prop_id * t_axiom + +let mk_axiom_info name labels p = + let id = mk_axiom_id name in (id, (name, labels, p)) + +let pp_axiom_info fmt (id, (_name, _labels, p)) = + Format.fprintf fmt "(@[%a:@ %a@])" pp_id_name id !Ast_printer.d_predicate_named p + +(*----------------------------------------------------------------------------*) +(** About proofs *) +(*----------------------------------------------------------------------------*) +let subproofs id = match id.p_kind with + | PKProp | PKPre _ | PKPropLoop -> 1 + | PKEstablished | PKPreserved + | PKVarDecr | PKVarPos + | PKAFctExit | PKAFctOut -> 2 + +let subproof_idx id = match id.p_kind with + | PKProp | PKPre _ | PKPropLoop -> 0 (* 1/1 *) + | PKPreserved -> 0 (* 1/2 *) + | PKEstablished-> 1 (* 2/2 *) + | PKVarDecr -> 0 (* 1/2 *) + | PKVarPos -> 1 (* 2/2 *) + | PKAFctOut -> 0 (* 1/2 *) + | PKAFctExit -> 1 (* 2/2 *) +(** find the outer loop in which the stmt is. *) +let get_loop_stmt kf stmt = + (* because we don't have the cfg here, we can only use Cil information, + * and then we can only recognize syntactic loops... TODO: use the cfg ? *) + let rec is_in_blk b = List.exists is_in_stmt b.bstmts + and is_in_stmt s = if s.sid = stmt.sid then true + else match s.skind with + | If (_, b1, b2,_) -> is_in_blk b1 || is_in_blk b2 + | Switch (_, b, _, _) | Block b -> is_in_blk b + | UnspecifiedSequence seq -> + let b = Cil.block_from_unspecified_sequence seq in + is_in_blk b + | Loop (_, b, _, _, _) -> is_in_blk b + | _ -> false + and find_loop_in_blk blk = find_loop_in_stmts blk.bstmts + and find_loop_in_stmts l = match l with + | [] -> None + | s::tl -> + (match find_loop_in_stmt s with Some l -> Some l + | None -> find_loop_in_stmts tl) + and find_loop_in_stmt s = match s.skind with + | (Loop _) -> if is_in_stmt s then Some s else None + | If (_, b1, b2,_) -> + (match find_loop_in_blk b1 with Some l -> Some l + | None -> find_loop_in_blk b2) + | Switch (_, b, _, _) | Block b -> find_loop_in_blk b + | UnspecifiedSequence seq -> + let b = Cil.block_from_unspecified_sequence seq in + find_loop_in_blk b + | _ -> None + in let f = Kernel_function.get_definition kf in + find_loop_in_blk f.sbody + +(** Quite don't understand what is going on here... what is it supposed to do ? +* [2011-07-07-Anne] *) +let get_induction p = + let get_stmt = function + | Property.IPDecrease(kf,Kstmt stmt,_,_) -> Some (kf, stmt) + | Property.IPCodeAnnot(kf,stmt,_) -> Some (kf, stmt) + | Property.IPAssigns(kf,Kstmt stmt,_,_) -> Some (kf, stmt) + | _ -> None + in match p.p_kind with + | PKAFctOut|PKAFctExit|PKPre _ -> None + | PKProp -> + let loop_stmt_opt = match get_stmt (property_of_id p) with + | None -> None + | Some (kf, s) -> get_loop_stmt kf s + in loop_stmt_opt + | PKPropLoop -> + let loop_stmt_opt = match property_of_id p with + | Property.IPCodeAnnot(kf,stmt, + {annot_content = AInvariant(_, loop, _)}) + -> + if loop then (*loop invariant *) Some stmt + else (* invariant inside loop *) get_loop_stmt kf stmt + | Property.IPAssigns (_, Kstmt stmt, Property.Id_code_annot _, _) -> + (* loop assigns *) Some stmt + | _ -> None (* assert false ??? *) + in loop_stmt_opt + | PKEstablished|PKVarDecr|PKVarPos|PKPreserved -> + (match get_stmt (property_of_id p) with + | None -> None | Some (_, s) -> Some s) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpPropId.mli frama-c-20111001+nitrogen+dfsg/src/wp/wpPropId.mli --- frama-c-20110201+carbon+dfsg/src/wp/wpPropId.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpPropId.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,213 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** Beside the property identification, it can be found in different contexts + * depending on which part of the computation is involved. + * For instance, properties on loops are split in 2 parts : establishment and + * preservation. + *) + +(** Property.t information and kind of PO (establishment, preservation, etc) *) +type prop_id + +(** returns the annotation which lead to the given PO. + Dynamically exported. + *) +val property_of_id : prop_id -> Property.t + +(*----------------------------------------------------------------------------*) + +module Prop_id_datatype: Datatype.S with type t = prop_id + +(*----------------------------------------------------------------------------*) + +val compare_prop_id : prop_id -> prop_id -> int + +val is_assigns : prop_id -> bool +val is_requires : Property.t -> bool + +(** test if the prop_id has to be selected for the asked name. +* Also returns a debug message to explain then answer. *) +val select_by_name : string -> prop_id -> bool * string + +(** test if the prop_id has to be selected when we want to select the call +* precondition the the [stmt] call (None means all the call preconditions). +* Also returns a debug message to explain then answer. *) +val select_call_pre : stmt -> Property.t option -> prop_id -> bool * string + +(*----------------------------------------------------------------------------*) + +val prop_id_name : prop_id -> string +val pp_id_name : Format.formatter -> prop_id -> unit + +val pretty : Format.formatter -> prop_id -> unit +val pretty_context : Kernel_function.t -> Format.formatter -> prop_id -> unit + +(** Short description of the kind of PO *) +val label_of_prop_id: prop_id -> string + +(** Short description of the PO *) +val name_of_prop_id: prop_id -> string + +(** TODO: this one should be in Properties_status. *) +val id_prop_txt : Property.t -> string + +(** TODO: should probably be somewhere else *) +val string_of_termination_kind : termination_kind -> string + +val num_of_bhv_from : funbehavior -> identified_term from -> int +(*----------------------------------------------------------------------------*) + +val mk_code_annot_id : kernel_function -> stmt -> code_annotation -> prop_id + +val mk_assert_id : kernel_function -> stmt -> code_annotation -> prop_id + +(** Invariant establishment *) +val mk_establish_id : kernel_function -> stmt -> code_annotation -> prop_id + +(** Invariant preservation *) +val mk_preserve_id : kernel_function -> stmt -> code_annotation -> prop_id + +(** Invariant used as hypothesis *) +val mk_inv_hyp_id : kernel_function -> stmt -> code_annotation -> prop_id + +(** Variant decrease *) +val mk_var_decr_id : kernel_function -> stmt -> code_annotation -> prop_id + +(** Variant positive *) +val mk_var_pos_id : kernel_function -> stmt -> code_annotation -> prop_id + +(** \from property of loop assigns *) +val mk_loop_from_id : kernel_function -> stmt -> code_annotation -> + identified_term from -> prop_id + +(** \from property of function or statement behavior assigns *) +val mk_bhv_from_id : kernel_function -> kinstr -> funbehavior -> + identified_term from -> prop_id + +val mk_fct_from_id : kernel_function -> funbehavior -> + termination_kind -> identified_term from -> prop_id + +(** disjoint behaviors property. *) +val mk_disj_bhv_id : kernel_function * kinstr * string list -> prop_id + +(** complete behaviors property. *) +val mk_compl_bhv_id : kernel_function * kinstr * string list -> prop_id + +val mk_decrease_id : kernel_function * kinstr * term variant -> prop_id + +(** axiom identification *) +val mk_axiom_id : string -> prop_id + +val mk_stmt_assigns_id : kernel_function -> stmt -> funbehavior -> + identified_term from list -> prop_id option + +val mk_loop_assigns_id : kernel_function -> stmt -> code_annotation -> + identified_term from list -> prop_id option + +(** function assigns *) +val mk_fct_assigns_id : kernel_function -> funbehavior -> + termination_kind -> identified_term from list -> prop_id option + +val mk_pre_id : kernel_function -> kinstr -> funbehavior -> + identified_predicate -> prop_id + +val mk_stmt_post_id : kernel_function -> stmt -> funbehavior -> + termination_kind * identified_predicate -> prop_id + +val mk_fct_post_id : kernel_function -> funbehavior -> + termination_kind * identified_predicate -> prop_id + +(** [mk_call_pre_id called_kf s_call called_pre] *) +val mk_call_pre_id : kernel_function -> stmt -> + Property.t -> Property.t -> prop_id + +(*----------------------------------------------------------------------------*) + +type a_kind = LoopAssigns | StmtAssigns +type assigns_desc = private { + a_label : Cil_types.logic_label ; + a_kind : a_kind ; + a_assigns : Cil_types.identified_term Cil_types.assigns ; +} +val pp_assigns_desc : Format.formatter -> assigns_desc -> unit + +type assigns_info = prop_id * assigns_desc +val assigns_info_id : assigns_info -> prop_id + +type assigns_full_info = private + AssignsLocations of assigns_info + | AssignsAny of assigns_desc + | NoAssignsInfo + +val empty_assigns_info : assigns_full_info +val mk_assigns_info : prop_id -> assigns_desc -> assigns_full_info +val mk_stmt_any_assigns_info : stmt -> assigns_full_info +val mk_kf_any_assigns_info : unit -> assigns_full_info +val mk_loop_any_assigns_info : stmt -> assigns_full_info + +val pp_assign_info : string -> Format.formatter -> assigns_full_info -> unit +val merge_assign_info : + assigns_full_info -> assigns_full_info -> assigns_full_info + +val mk_loop_assigns_desc : stmt -> identified_term from list -> assigns_desc + +val mk_stmt_assigns_desc : stmt -> identified_term from list -> assigns_desc + +val mk_kf_assigns_desc : identified_term from list -> assigns_desc + +(*----------------------------------------------------------------------------*) + +type t_axiom = string * Cil_types.logic_label list * Cil_types.predicate named +type axiom_info = prop_id * t_axiom + +val mk_axiom_info : + string -> Cil_types.logic_label list -> Cil_types.predicate named -> axiom_info +val pp_axiom_info : Format.formatter -> axiom_info -> unit + +type pred_info = (prop_id * Cil_types.predicate named) + +val mk_pred_info : prop_id -> Cil_types.predicate named -> pred_info +val pred_info_id : pred_info -> prop_id +val pp_pred_of_pred_info : Format.formatter -> pred_info -> unit +val pp_pred_info : Format.formatter -> pred_info -> unit + +(*----------------------------------------------------------------------------*) + +(** [mk_part pid (k, n)] build the identification for the [k/n] part of [pid].*) +val mk_part : prop_id -> (int * int) -> prop_id + +(** get the 'part' infomation. *) +val parts_of_id : prop_id -> (int * int) option + +(** How many subproofs *) +val subproofs : prop_id -> int + +(** subproof index of this propr_id *) +val subproof_idx : prop_id -> int + +val get_induction : prop_id -> stmt option + +(*----------------------------------------------------------------------------*) + diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wprop.ml frama-c-20111001+nitrogen+dfsg/src/wp/wprop.ml --- frama-c-20110201+carbon+dfsg/src/wp/wprop.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wprop.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,133 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- WP Internal State --- *) +(* -------------------------------------------------------------------------- *) + +module WP = State_builder.Ref + (Datatype.Unit) + (struct + let name = "WP" + let kind = `Internal + let dependencies = [Ast.self] + let default () = () + end) + +(* -------------------------------------------------------------------------- *) +(* --- Indexed Interface --- *) +(* -------------------------------------------------------------------------- *) + +type property = + | Later of Property.t + | Proxy of Property.t * Emitter.t * Property.t list + +module type Info = +sig + include State_builder.Info_with_size + type key + val property : key -> property +end + +module type Indexed = +sig + type key + val mem : key -> bool + val property : key -> Property.t + val add_hook : (key -> Property.t -> unit) -> unit +end + +module type Indexed2 = +sig + type key1 + type key2 + val mem : key1 -> key2 -> bool + val property : key1 -> key2 -> Property.t + val add_hook : (key1 -> key2 -> Property.t -> unit) -> unit +end + +(* -------------------------------------------------------------------------- *) +(* --- Index-1 Implementation --- *) +(* -------------------------------------------------------------------------- *) + +module Indexed + (Key:Datatype.S_with_collections) + (Info:Info with type key = Key.t) = +struct + + open Cil_types + + type key = Key.t + + module H = State_builder.Hashtbl(Key.Hashtbl)(Property)(Info) + + let hooks = ref [] + let add_hook f = hooks := !hooks @ [f] + + let mem = H.mem + + let property (key:key) = + try H.find key + with Not_found -> + let ip = + match Info.property key with + | Later ip -> ip + | Proxy(ip,emitter,ips) -> + Property_status.logical_consequence emitter ip ips ; ip + in + List.iter (fun f -> f key ip) !hooks ; + H.add key ip ; ip + +end + +(* -------------------------------------------------------------------------- *) +(* --- Index-2 Wrapper --- *) +(* -------------------------------------------------------------------------- *) + +module Indexed2 + (Key1:Datatype.S_with_collections) + (Key2:Datatype.S_with_collections) + (Info:Info with type key = Key1.t * Key2.t) = +struct + + module P = Datatype.Pair_with_collections(Key1)(Key2) + (struct + let module_name = Info.name + end) + module I = Indexed(P)(Info) + + type key1 = Key1.t + type key2 = Key2.t + + let mem a b = I.mem (a,b) + let property a b = I.property (a,b) + let add_hook f = I.add_hook (fun (a,b) -> f a b) + +end + +(* -------------------------------------------------------------------------- *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wprop.mli frama-c-20111001+nitrogen+dfsg/src/wp/wprop.mli --- frama-c-20110201+carbon+dfsg/src/wp/wprop.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wprop.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,76 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ------------------------------------------------------------------------ *) +(**{2 Indexed API} *) +(* ------------------------------------------------------------------------ *) + +type property = + | Later of Property.t + | Proxy of Property.t * Emitter.t * Property.t list + +module type Info = +sig + include State_builder.Info_with_size + type key + val property : key -> property +end + +module type Indexed = +sig + type key + val mem : key -> bool + val property : key -> Property.t + val add_hook : (key -> Property.t -> unit) -> unit + (** Hooks are executed once at property creation *) +end + +module type Indexed2 = +sig + type key1 + type key2 + val mem : key1 -> key2 -> bool + val property : key1 -> key2 -> Property.t + val add_hook : (key1 -> key2 -> Property.t -> unit) -> unit + (** Hooks are executed once at property creation *) +end + +(* ------------------------------------------------------------------------ *) +(**{2 Indexes} *) +(* ------------------------------------------------------------------------ *) + +module Indexed + (Key:Datatype.S_with_collections) + (Info:Info with type key = Key.t) : + Indexed with type key = Key.t + +module Indexed2 + (Key1:Datatype.S_with_collections) + (Key2:Datatype.S_with_collections) + (Info:Info with type key = Key1.t * Key2.t) : + Indexed2 with type key1 = Key1.t and type key2 = Key2.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpStrategy.ml frama-c-20111001+nitrogen+dfsg/src/wp/wpStrategy.ml --- frama-c-20110201+carbon+dfsg/src/wp/wpStrategy.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpStrategy.ml 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,592 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let dkey = "strategy" (* debugging key *) +let debug fmt = Wp_parameters.debug ~dkey fmt + +open Cil_types + +(* -------------------------------------------------------------------------- *) +(** An annotation can be used for different purpose. *) +type annot_kind = + | Ahyp (** annotation is an hypothesis, + but not a goal (see Aboth) : A => ...*) + | Agoal (** annotation is a goal, + but not an hypothesis (see Aboth): A /\ ...*) + | Aboth of bool (** annotation can be used as both hypothesis and goal : + - with true : considerer as both : A /\ A=>.. + - with false : we just want to use it as hyp right now. *) + | AcutB of bool (** annotation is use as a cut : + - with true (A is also a goal) -> A (+ proof obligation A => ...) + - with false (A is an hyp only) -> True (+ proof obligation A => ...) *) + | AcallHyp + (** annotation is a called function property to consider as an Hyp. + * The pre are not here but in AcallPre since they can also + * be considered as goals. *) + | AcallPre of bool + (** annotation is a called function precondition : + to be considered as hyp, and goal if bool=true *) + +(* -------------------------------------------------------------------------- *) +(* --- Annotations for one program point. --- *) +(* -------------------------------------------------------------------------- *) + +(** Some elements can be used as both Hyp and Goal : because of the selection + * mecanism, we need to add a boolean [as_goal] to tell if the element is to be + * considered as a goal. If [false], the element can still be used as hypthesis. + *) +type annots = { + p_hyp : WpPropId.pred_info list; + p_goal : WpPropId.pred_info list; + p_both : (bool * WpPropId.pred_info) list; + p_cut : (bool * WpPropId.pred_info) list; + call_hyp : WpPropId.pred_info list; (* post and pre *) + call_pre : (bool * WpPropId.pred_info) list; (* goal only *) + a_goal : WpPropId.assigns_full_info; + a_hyp : WpPropId.assigns_full_info; + a_call : WpPropId.assigns_full_info; +} + +type t_annots = { has_asgn_goal : bool; has_prop_goal : bool; info: annots } + +(* --- Add annotations --- *) + +let empty_acc = + let a = { p_hyp = []; p_goal = []; p_both = []; p_cut = []; + call_hyp = []; call_pre = []; a_call = WpPropId.empty_assigns_info; + a_goal = WpPropId.empty_assigns_info; a_hyp = WpPropId.empty_assigns_info; } + in { has_asgn_goal = false; has_prop_goal = false; info = a; } + +let add_prop acc kind labels id p = + let get_p () = + let txt = WpPropId.prop_id_name id in + try + let p = NormAtLabels.preproc_annot labels p in + let _ = + debug "take (@[%s:@ %a@])@." txt !Ast_printer.d_predicate_named p + in Some (WpPropId.mk_pred_info id p) + with e -> NormAtLabels.catch_label_error e txt "annotation"; None + in + let add_hyp l = match get_p () with None -> l | Some p -> p::l in + let add_goal l = + (* if goal_to_select config id + then *) match get_p () with None -> l + | Some p -> ( (* has_prop_goal := true; *) p::l ) + (* else l *) + in + let add_both goal l = + match get_p () with None -> l + | Some p -> + (* if goal then has_prop_goal := true;*) + (goal, p)::l + in + let info = acc.info in + let goal, info = match kind with + | Ahyp -> + false, { info with p_hyp = add_hyp info.p_hyp } + | Agoal -> + true, { info with p_goal = add_goal info.p_goal } + | Aboth goal -> + goal, { info with p_both = add_both goal info.p_both } + | AcutB goal -> + goal, { info with p_cut = add_both goal info.p_cut } + | AcallHyp -> + false, { info with call_hyp = add_hyp info.call_hyp } + | AcallPre goal -> + goal, { info with call_pre = add_both goal info.call_pre } + in let acc = { acc with info = info } in + if goal then { acc with has_prop_goal = true} else acc + +(* -------------------------------------------------------------------------- *) +(* adding some specific properties. *) + +let add_prop_fct_pre acc kind kf bhv ~assumes pre = + let id = WpPropId.mk_pre_id kf Kglobal bhv pre in + let labels = NormAtLabels.labels_fct_pre in + let p = Logic_const.pred_of_id_pred pre in + let p = match assumes with None -> p + | Some assumes -> Logic_const.pimplies (assumes, p) + in + let p = Logic_const.pat (p, Logic_const.pre_label) in + (* TODO: why this at ??? [2011-07-08-Anne] *) + add_prop acc kind labels id p + +let add_prop_fct_post acc kind kf bhv tkind post = + let id = WpPropId.mk_fct_post_id kf bhv (tkind, post) in + let labels = NormAtLabels.labels_fct_post in + let p = Logic_const.pred_of_id_pred post in + add_prop acc kind labels id p + +let add_prop_fct_bhv_pre acc kind kf bhv ~impl_assumes = + let assumes = + if impl_assumes then Some (Ast_info.behavior_assumes bhv) else None + in + let add acc p = add_prop_fct_pre acc kind kf bhv ~assumes p in + let acc = List.fold_left add acc bhv.b_requires in + if impl_assumes then acc + else List.fold_left add acc bhv.b_assumes + +let add_prop_stmt_pre acc kind kf s bhv ~assumes pre = + let id = WpPropId.mk_pre_id kf (Kstmt s) bhv pre in + let labels = NormAtLabels.labels_stmt_pre s in + let p = Logic_const.pred_of_id_pred pre in + let p = match assumes with None -> p + | Some assumes -> Logic_const.pimplies (assumes, p) + in add_prop acc kind labels id p + +let add_prop_stmt_bhv_requires acc kind kf s bhv ~with_assumes = + let assumes = + if with_assumes then Some (Ast_info.behavior_assumes bhv) else None + in let add acc pre = + add_prop_stmt_pre acc kind kf s bhv ~assumes pre + in List.fold_left add acc bhv.b_requires + +(** Process the stmt spec precondition as an hypothesis for external properties. + * Add [assumes => requires] for all the behaviors. *) +let add_prop_stmt_spec_pre acc kind kf s spec = + let add_bhv_pre acc bhv = + add_prop_stmt_bhv_requires acc kind kf s bhv ~with_assumes:true + in List.fold_left add_bhv_pre acc spec.spec_behavior + +let add_prop_stmt_post acc kind kf s bhv tkind l_post ~assumes post = + let id = WpPropId.mk_stmt_post_id kf s bhv (tkind, post) in + let labels = NormAtLabels.labels_stmt_post s l_post in + let p = Logic_const.pred_of_id_pred post in + let p = match assumes with None -> p + | Some assumes -> + let assumes = Logic_const.pold assumes in + (* can use old because label normalisation will be called *) + Logic_const.pimplies (assumes, p) + in add_prop acc kind labels id p + +let add_prop_call_pre acc kind id ~assumes pre = + (* TODO: we don't build the id here yet because of strange things in wpAnnot. + * Find out how to deal with it. [2011-07-13-Anne] *) + let labels = NormAtLabels.labels_fct_pre in + let p = Logic_const.pred_of_id_pred pre in + let p = Logic_const.pimplies (assumes, p) in + add_prop acc kind labels id p + +let add_prop_call_post acc kind called_kf bhv tkind ~assumes post = + let id = WpPropId.mk_fct_post_id called_kf bhv (tkind, post) in + let labels = NormAtLabels.labels_fct_post in + let p = Logic_const.pred_of_id_pred post in + let assumes = Logic_const.pold assumes in + let p = Logic_const.pimplies (assumes, p) in + add_prop acc kind labels id p + +let add_prop_assert acc kind kf s ca p = + let id = WpPropId.mk_assert_id kf s ca in + let labels = NormAtLabels.labels_assert_before s in + add_prop acc kind labels id p + +let add_prop_loop_inv acc kind s id p = + let labels = NormAtLabels.labels_loop_inv s in + add_prop acc kind labels id p + +(** apply [f_normal] on the [Normal] postconditions, +* [f_exits] on the [Exits] postconditions, and warn on the others. *) +let fold_bhv_post_cond ~warn f_normal f_exits acc b = + let add (p_acc, e_acc) ((termination_kind, pe) as e) = + match termination_kind with + | Normal -> f_normal p_acc pe, e_acc + | Exits -> p_acc, f_exits e_acc pe + | (Breaks|Continues|Returns) -> (* TODO *) + begin + if warn then + Wp_parameters.warning + "Abrupt statement termination property ignored:@, %a" + (Cil.defaultCilPrinter)#pPost_cond e; + p_acc, e_acc + end + in List.fold_left add acc b.b_post_cond + +(* -------------------------------------------------------------------------- *) + +let add_assigns acc kind id a_desc = + let take_assigns () = + debug "take %a %a" WpPropId.pp_id_name id WpPropId.pp_assigns_desc a_desc; + WpPropId.mk_assigns_info id a_desc + in + let info = acc.info in + let goal, info = match kind with + | Ahyp -> false, {info with a_hyp = take_assigns ()} + | AcallHyp -> false, {info with a_call = take_assigns ()} + | Agoal -> true, {info with a_goal = take_assigns ()} + | _ -> Wp_parameters.fatal "Assigns prop can only be Hyp or Goal" + in let acc = { acc with info = info } in + if goal then { acc with has_asgn_goal = true} else acc + +let add_assigns_any acc kind asgn = + let take () = debug "take %a" (WpPropId.pp_assign_info "") asgn; asgn in + match kind with + | Ahyp -> {acc with info = { acc.info with a_hyp = take ()}} + | AcallHyp -> {acc with info = { acc.info with a_call = take ()}} + | _ -> Wp_parameters.fatal "Assigns Any prop can only be Hyp" + +let assigns_upper_bound spec = + let bhvs = spec.spec_behavior in + let upper a b = + match a, b.b_assigns with + | None, Writes a when Cil.is_default_behavior b -> + Some (b,a) (* default behavior always applies. *) + | None, _ -> None (* WritesAny U X -> WritesAny *) + | Some (b,_), _ when Cil.is_default_behavior b -> + a (* default behavior prevails over other behaviors. *) + | Some _, WritesAny -> + None (* No default behavior and one behavior assigns everything. *) + | Some(b,a1), Writes a2 -> Some (b,a1 @ a2) + (* take the whole list of assigns. *) + in + match bhvs with + | [] -> None + | bhv::bhvs -> + (* [VP 2011-02-04] Note that if there is no default and each + behavior has a proper assigns clause we put dependencies only + to the assigns of a more or less randomly selected behavior, + but the datatypes above can't handle anything better. *) + let acc = + match bhv.b_assigns with + WritesAny -> None + | Writes a -> Some(bhv,a) + in + List.fold_left upper acc bhvs + +(* [VP 2011-02-04] These two functions below mix all the assigns of + a function regardless of the behavior. At least now that we take + WritesAny as soon as at least one behavior has no assigns clause, + this is correct, but still imprecise. Needs refactoring of t_annots to + go further, though. + [AP 2011-03-11] I think that the merge of all assigns properties + is intended because we are using it as an hypothesis to skip the statement + or the function call. + *) +let add_stmt_spec_assigns_hyp acc kf s l_post spec = + match assigns_upper_bound spec with + | None -> + add_assigns_any acc Ahyp + (WpPropId.mk_stmt_any_assigns_info s) + | Some(bhv, assigns) -> + let id = WpPropId.mk_stmt_assigns_id kf s bhv assigns in + match id with + | None -> add_assigns_any acc Ahyp + (WpPropId.mk_stmt_any_assigns_info s) + | Some id -> + let labels = NormAtLabels.labels_stmt_assigns s l_post in + let assigns = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_stmt_assigns_desc s assigns in + add_assigns acc Ahyp id a_desc + +let add_call_assigns_hyp acc kf_caller s l_post spec_opt = + match spec_opt with + | None -> + let asgn = WpPropId.mk_stmt_any_assigns_info s in + add_assigns_any acc AcallHyp asgn + | Some spec -> + match assigns_upper_bound spec with + | None -> + let asgn = WpPropId.mk_stmt_any_assigns_info s in + add_assigns_any acc AcallHyp asgn + | Some(bhv, assigns) -> + let id = WpPropId.mk_stmt_assigns_id kf_caller s bhv assigns in + match id with + | None -> + let asgn = WpPropId.mk_stmt_any_assigns_info s in + add_assigns_any acc AcallHyp asgn + | Some id -> + let labels = NormAtLabels.labels_stmt_assigns s l_post in + let assigns = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_stmt_assigns_desc s assigns in + add_assigns acc AcallHyp id a_desc + +(* [VP 2011-01-28] following old behavior, not sure it is correct: + why should we give to add_assigns the assigns with unnormalized labels? + [AP 2011-03-11] to answer VP question, the source assigns are only used to + build an identifier for the property which is use later to update its status + and dependencies so we need to have the original one. +*) +let add_loop_assigns_hyp acc kf s asgn_opt = match asgn_opt with + | None -> + let asgn = WpPropId.mk_loop_any_assigns_info s in + add_assigns_any acc Ahyp asgn + | Some (ca, assigns) -> + let id = WpPropId.mk_loop_assigns_id kf s ca assigns in + match id with + | None -> + let asgn = WpPropId.mk_loop_any_assigns_info s in + add_assigns_any acc Ahyp asgn + | Some id -> + let labels = NormAtLabels.labels_loop_assigns s in + let assigns' = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_loop_assigns_desc s assigns' in + add_assigns acc Ahyp id a_desc + +let add_fct_bhv_assigns_hyp acc kf tkind b = match b.b_assigns with + | WritesAny -> + let id = WpPropId.mk_kf_any_assigns_info () in + add_assigns_any acc Ahyp id + | Writes assigns -> + let id = WpPropId.mk_fct_assigns_id kf b tkind assigns in + match id with + | None -> + let id = WpPropId.mk_kf_any_assigns_info () in + add_assigns_any acc Ahyp id + | Some id -> + let labels = NormAtLabels.labels_fct_assigns in + let assigns' = NormAtLabels.preproc_assigns labels assigns in + let a_desc = WpPropId.mk_kf_assigns_desc assigns' in + add_assigns acc Ahyp id a_desc + +(* --- Get annotations --- *) + +let get_goal_only annots = annots.info.p_goal + +let get_hyp_only annots = annots.info.p_hyp + +let filter_both l = + let add (h_acc, g_acc) (goal, p) = + p::h_acc, if goal then p::g_acc else g_acc + in List.fold_left add ([], []) l + +let get_both_hyp_goals annots = filter_both annots.info.p_both + +let get_call_hyp annots = annots.info.call_hyp +let get_call_pre annots = filter_both annots.info.call_pre + +let get_cut annots = annots.info.p_cut + +let get_asgn_hyp annots = annots.info.a_hyp + +let get_asgn_goal annots = annots.info.a_goal + +let get_call_asgn annots = annots.info.a_call + +(* --- Print annotations --- *) + +let pp_annots fmt acc = + let acc = acc.info in + let pp_pred k b p = + Format.fprintf fmt "%s%s: %a@." + k (if b then "" else " (h)") WpPropId.pp_pred_of_pred_info p + in + let pp_pred_list k l = List.iter (fun p -> pp_pred k true p) l in + let pp_pred_b_list k l = List.iter (fun (b, p) -> pp_pred k b p) l in + pp_pred_list "H" acc.p_hyp; + pp_pred_list "G" acc.p_goal; + pp_pred_b_list "H+G" acc.p_both; + pp_pred_b_list "C" acc.p_cut; + pp_pred_list "CallHyp" acc.call_hyp; + pp_pred_b_list "CallPre" acc.call_pre; + WpPropId.pp_assign_info "HA" fmt acc.a_hyp; + WpPropId.pp_assign_info "GA" fmt acc.a_goal; + WpPropId.pp_assign_info "CallA" fmt acc.a_call + +(* TODO: it should be possible to do without this, but needs a big refactoring*) +let merge_acc acc1 acc2 = +{ + p_hyp = acc1.p_hyp @ acc2.p_hyp; + p_goal = acc1.p_goal @ acc2.p_goal; + p_both = acc1.p_both @ acc2.p_both; + p_cut = acc1.p_cut @ acc2.p_cut; + call_hyp = acc1.call_hyp @ acc2.call_hyp; + call_pre = acc1.call_pre @ acc2.call_pre; + a_goal = WpPropId.merge_assign_info acc1.a_goal acc2.a_goal; + a_hyp = WpPropId.merge_assign_info acc1.a_hyp acc2.a_hyp; + a_call = WpPropId.merge_assign_info acc1.a_call acc2.a_call; +} + +(* -------------------------------------------------------------------------- *) +(* --- Annotation table --- *) +(* -------------------------------------------------------------------------- *) + +(** This is an Hashtbl where some predicates are stored on CFG edges. + * On each edge, we store hypotheses and goals. + *) +module Hannots = Cil2cfg.HE (struct type t = annots end) + +type annots_tbl = { + tbl_annots : Hannots.t; + mutable tbl_axioms : WpPropId.axiom_info list; + mutable tbl_has_prop_goal : bool; + mutable tbl_has_asgn_goal : bool; +} + +let create_tbl () = { + tbl_annots = Hannots.create 7; + tbl_axioms = []; + tbl_has_prop_goal = false; + tbl_has_asgn_goal = false; +} + +let add_on_edges tbl new_acc edges = + if new_acc.has_prop_goal then tbl.tbl_has_prop_goal <- true; + if new_acc.has_asgn_goal then tbl.tbl_has_asgn_goal <- true; + let add_on_edge e = + let acc = + try + let acc = Hannots.find tbl.tbl_annots e in + merge_acc new_acc.info acc + with Not_found -> new_acc.info + in Hannots.replace tbl.tbl_annots e acc; + in List.iter add_on_edge edges + +let add_node_annots tbl cfg v (before, (post, exits)) = + add_on_edges tbl before (Cil2cfg.get_pre_edges cfg v); + if post <> empty_acc then + begin + let edges_after = Cil2cfg.get_post_edges cfg v in + if edges_after = [] + then Wp_parameters.warning ~once:true + "Ignoring annotation rooted after statement with no succ" + else add_on_edges tbl post edges_after + end; + if exits <> empty_acc then + begin + let edges_exits = Cil2cfg.get_exit_edges cfg v in + if edges_exits = [] + then (* unreachable (see [process_unreached_annots]) *) () + else add_on_edges tbl exits edges_exits + end + +let add_loop_annots tbl cfg vloop ~entry ~back ~core = + debug "[add_loop_annots]@."; + let edges_to_head = Cil2cfg.succ_e cfg vloop in + debug "[add_loop_annots] %d edges_to_head" (List.length edges_to_head); + let edges_to_loop = Cil2cfg.pred_e cfg vloop in + debug "[add_loop_annots] %d edges_to_loop" (List.length edges_to_loop); + let back_edges, entry_edges = + List.partition Cil2cfg.is_back_edge edges_to_loop + in + debug "[add_loop_annots] %d back_edges + %d entry_edges" + (List.length back_edges) (List.length entry_edges); + add_on_edges tbl entry entry_edges; + debug "[add_loop_annots on entry_edges ok]@."; + add_on_edges tbl back back_edges; + debug "[add_loop_annots on back_edges ok]@."; + add_on_edges tbl core edges_to_head; + debug "[add_loop_annots on edges_to_head ok]@." + +let add_axiom tbl name labels a = + try + let a = NormAtLabels.preproc_annot NormAtLabels.labels_axiom a in + let labels = + List.map (NormAtLabels.preproc_label NormAtLabels.labels_axiom) labels in + let axiom = WpPropId.mk_axiom_info name labels a in + debug "take %a@." WpPropId.pp_axiom_info axiom; + tbl.tbl_axioms <- axiom::tbl.tbl_axioms + with e -> + NormAtLabels.catch_label_error e ("axiom "^name) "axiom" + +let add_all_axioms tbl = + let globs = Globals.Annotations.get_all () in + let globs = List.map (fun (g, _generated) -> g) globs in + let rec do_g g = + match g with + | Daxiomatic (_ax_name, globs,_) -> do_globs globs + | Dlemma (name, _is_axiom, labels, _, pred,_) -> + add_axiom tbl name labels pred + | _ -> () + and do_globs globs = List.iter do_g globs in + do_globs globs + +let get_annots tbl e = + try (* TODOclean : this is not very nice ! *) + let info = Hannots.find tbl.tbl_annots e in { empty_acc with info = info} + with Not_found -> empty_acc + +(* -------------------------------------------------------------------------- *) +(* --- Strategy --- *) +(* -------------------------------------------------------------------------- *) + +type strategy_for_froms = { + get_pre : unit -> t_annots; + more_vars : logic_var list +} + +type strategy_kind = + | SKannots (* normal mode for annotations *) + | SKfroms of strategy_for_froms + +(* an object of this type is the only access to annotations + * from the rest of the application. + * The idea is to be able to tune which properties to use for a computation. *) +type strategy = { + desc : string ; + cfg : Cil2cfg.t; + behavior_name : string option ; + + new_loops : bool; + + strategy_kind : strategy_kind; + annots : annots_tbl; +} + +let mk_strategy desc cfg bhv_name new_loops kind tbl = { + desc = desc; cfg = cfg; behavior_name = bhv_name; new_loops = new_loops; + strategy_kind = kind; annots = tbl; +} + +let cfg_of_strategy strat = strat.cfg +let behavior_name_of_strategy strat = strat.behavior_name +let global_axioms strat = strat.annots.tbl_axioms +let strategy_kind strat = strat.strategy_kind +let strategy_has_prop_goal strat = strat.annots.tbl_has_prop_goal +let strategy_has_asgn_goal strat = strat.annots.tbl_has_asgn_goal +let get_annots strat = get_annots strat.annots +let new_loop_computation strat = strat.new_loops + +let pp_info_of_strategy fmt strat = + Format.fprintf fmt "@[%s@]" strat.desc + +(* -------------------------------------------------------------------------- *) +(* --- Helpers --- *) +(* -------------------------------------------------------------------------- *) + +let is_main_init kf = + if Kernel.LibEntry.get () then false + else + let is_main = + try + let main, _ = Globals.entry_point () in + Kernel_function.equal kf main + with Globals.No_such_entry_point _ -> false + in + debug "'%a' is %sthe main entry point@." + Kernel_function.pretty kf (if is_main then "" else "NOT "); + is_main + +let get_called_kf fct = match fct.enode with + | Lval (Var vkf, NoOffset) -> Some (Globals.Functions.get vkf) + | _ -> None + +let mk_variant_properties kf s ca v = + let vpos_id = WpPropId.mk_var_pos_id kf s ca in + let vdecr_id = WpPropId.mk_var_decr_id kf s ca in + let loc = v.term_loc in + let lhead = Clabels.loop_head_label s in + let vhead = Logic_const.tat ~loc (v, lhead) in + let zero = Cil.lzero ~loc () in + let vpos = Logic_const.prel ~loc (Rle, zero, vhead) in + let vdecr = Logic_const.prel ~loc (Rlt, v, vhead) in + (vpos_id, vpos), (vdecr_id, vdecr) + +(* -------------------------------------------------------------------------- *) diff -Nru frama-c-20110201+carbon+dfsg/src/wp/wpStrategy.mli frama-c-20111001+nitrogen+dfsg/src/wp/wpStrategy.mli --- frama-c-20110201+carbon+dfsg/src/wp/wpStrategy.mli 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/src/wp/wpStrategy.mli 2011-10-10 08:38:21.000000000 +0000 @@ -0,0 +1,256 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2011 *) +(* CEA (Commissariat a l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It 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 Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* -------------------------------------------------------------------------- *) +(** This file provide all the functions to build a stategy that can then + * be used by the main generic calculus. *) +(* -------------------------------------------------------------------------- *) + +(* -------------------------------------------------------------------------- *) +(** {2 Annotations} *) +(* -------------------------------------------------------------------------- *) + +(** a set of annotations to be added to a program point. *) +type t_annots + +val empty_acc : t_annots + +(** {3 How to use an annotation} *) + +(** An annotation can be used for different purpose. *) +type annot_kind = + | Ahyp (** annotation is an hypothesis, + but not a goal (see Aboth) : A => ...*) + | Agoal (** annotation is a goal, + but not an hypothesis (see Aboth): A /\ ...*) + | Aboth of bool (** annotation can be used as both hypothesis and goal : + - with true : considerer as both : A /\ A=>.. + - with false : we just want to use it as hyp right now. *) + | AcutB of bool (** annotation is use as a cut : + - with true (A is also a goal) -> A (+ proof obligation A => ...) + - with false (A is an hyp only) -> True (+ proof obligation A => ...) *) + | AcallHyp + (** annotation is a called function property to consider as an Hyp. + * The pre are not here but in AcallPre since they can also + * be considered as goals. *) + | AcallPre of bool + (** annotation is a called function precondition : + to be considered as hyp, and goal if bool=true *) + +(** {3 Adding properties (predicates)} *) + +(** generic function to add a predicate property after normalisation. +* All the [add_prop_xxx] functions below use this one. *) +val add_prop : t_annots -> annot_kind -> + NormAtLabels.label_mapping -> WpPropId.prop_id -> + predicate named -> + t_annots + +(** Add the predicate as a function precondition. +* Add [assumes => pre] if [assumes] is given. *) +val add_prop_fct_pre : t_annots -> annot_kind -> + kernel_function -> funbehavior -> + assumes: predicate named option -> identified_predicate -> t_annots + +(** Add the preconditions of the behavior : +* if [impl_assumes], add [b_assumes => b_requires] +* else add both the [b_requires] and the [b_assumes] *) +val add_prop_fct_bhv_pre : t_annots -> annot_kind -> + kernel_function -> funbehavior -> impl_assumes:bool -> t_annots + +val add_prop_fct_post : t_annots -> annot_kind -> + kernel_function -> funbehavior -> termination_kind -> identified_predicate + -> t_annots + +(** Add the predicate as a stmt precondition. +* Add [assumes => pre] if [assumes] is given. *) +val add_prop_stmt_pre : t_annots -> annot_kind -> + kernel_function -> stmt -> funbehavior -> + assumes: predicate named option -> identified_predicate -> t_annots + +(** Add the predicate as a stmt precondition. +* Add [\old (assumes) => post] if [assumes] is given. *) +val add_prop_stmt_post :t_annots -> annot_kind -> + kernel_function -> stmt -> funbehavior -> termination_kind -> + logic_label option -> assumes:predicate named option -> identified_predicate + -> t_annots + +(** Add all the [b_requires]. Add [b_assumes => b_requires] if [with_assumes] *) +val add_prop_stmt_bhv_requires : t_annots -> annot_kind -> + kernel_function -> stmt -> funbehavior -> with_assumes:bool -> t_annots + +(** Process the stmt spec precondition as an hypothesis for external properties. + * Add [assumes => requires] for all the behaviors. *) +val add_prop_stmt_spec_pre : t_annots -> annot_kind -> + kernel_function -> stmt -> funspec -> t_annots + +val add_prop_call_pre : t_annots -> annot_kind -> WpPropId.prop_id -> + assumes:predicate named -> identified_predicate -> t_annots + +(** Add a postcondition of a called function. Beware that [kf] and [bhv] +* are the called one. *) +val add_prop_call_post : t_annots -> annot_kind -> + kernel_function -> funbehavior -> termination_kind -> + assumes:predicate named -> identified_predicate -> t_annots + +val add_prop_assert : t_annots -> annot_kind -> + kernel_function -> stmt -> code_annotation -> predicate named -> t_annots + +val add_prop_loop_inv : t_annots -> annot_kind -> + stmt -> WpPropId.prop_id -> predicate named -> t_annots + +(** {3 Adding assigns properties} *) + +(** generic function to add an assigns property. *) +val add_assigns : t_annots -> annot_kind -> + WpPropId.prop_id -> WpPropId.assigns_desc -> t_annots + +(** generic function to add a WriteAny assigns property. *) +val add_assigns_any : t_annots -> annot_kind -> + WpPropId.assigns_full_info -> t_annots + +(** shortcut to add a stmt spec assigns property as an hypothesis. *) +val add_stmt_spec_assigns_hyp : t_annots -> kernel_function -> stmt -> + logic_label option -> funspec -> t_annots + +(** shortcut to add a call assigns property as an hypothesis. *) +val add_call_assigns_hyp : t_annots -> kernel_function -> stmt -> + logic_label option -> funspec option -> t_annots + +(** shortcut to add a loop assigns property as an hypothesis. *) +val add_loop_assigns_hyp : t_annots -> kernel_function -> stmt -> + (code_annotation * identified_term from list) option -> t_annots + +val add_fct_bhv_assigns_hyp : t_annots -> kernel_function -> termination_kind -> + funbehavior -> t_annots + +val assigns_upper_bound : + funspec -> (funbehavior * identified_term from list) option + +(** {3 Getting information from annotations} *) + +val get_hyp_only : t_annots -> WpPropId.pred_info list +val get_goal_only : t_annots -> WpPropId.pred_info list +val get_both_hyp_goals : t_annots -> + WpPropId.pred_info list * WpPropId.pred_info list + +(** the [bool] in [get_cut] results says if the property has to be +* considered as a both goal and hyp ([goal=true], or hyp only ([goal=false]) *) +val get_cut : t_annots -> (bool * WpPropId.pred_info) list + +(** To be used as hypotheses arround a call, (the pre are in + * [get_call_pre_goal]) *) +val get_call_hyp : t_annots -> WpPropId.pred_info list + +(** Preconditions of a called function to be considered as hyp and goal +* (similar to [get_both_hyp_goals]). *) +val get_call_pre : t_annots -> WpPropId.pred_info list * WpPropId.pred_info list + +val get_asgn_hyp : t_annots -> WpPropId.assigns_full_info +val get_asgn_goal : t_annots -> WpPropId.assigns_full_info +val get_call_asgn : t_annots -> WpPropId.assigns_full_info + +(** {3 Printing} *) + +val pp_annots : Format.formatter -> t_annots -> unit + +(* -------------------------------------------------------------------------- *) +(** {2 Annotation table} *) +(* -------------------------------------------------------------------------- *) + +type annots_tbl + +val create_tbl : unit -> annots_tbl + +val add_on_edges : annots_tbl -> t_annots -> Cil2cfg.edge list -> unit + +(** [add_node_annots cfg annots v (before, (after, exits))] +* add the annotations for the node : +* @param before preconditions +* @param after postconditions +* @param exits \exits properties +*) +val add_node_annots : annots_tbl -> Cil2cfg.t -> Cil2cfg.node -> + (t_annots * (t_annots * t_annots)) -> unit + +val add_loop_annots : annots_tbl -> Cil2cfg.t -> Cil2cfg.node -> + entry:t_annots -> back:t_annots -> core:t_annots -> unit + +val add_axiom : annots_tbl -> + string -> logic_label list -> predicate named -> + unit + +val add_all_axioms : annots_tbl -> unit + +(* -------------------------------------------------------------------------- *) +(** {2 Strategy} *) +(* -------------------------------------------------------------------------- *) + +type strategy + +type strategy_for_froms = { + get_pre : unit -> t_annots; + more_vars : logic_var list +} + +type strategy_kind = + | SKannots (** normal mode for annotations *) + | SKfroms of strategy_for_froms + +val mk_strategy : string -> Cil2cfg.t -> string option -> bool -> + strategy_kind -> annots_tbl -> strategy + +val get_annots : strategy -> Cil2cfg.edge -> t_annots +val new_loop_computation : strategy -> bool +val strategy_has_asgn_goal : strategy -> bool +val strategy_has_prop_goal : strategy -> bool +val strategy_kind : strategy -> strategy_kind +val global_axioms : strategy -> WpPropId.axiom_info list +val behavior_name_of_strategy : strategy -> string option + +val cfg_of_strategy : strategy -> Cil2cfg.t + +val pp_info_of_strategy : Format.formatter -> strategy -> unit + +(* -------------------------------------------------------------------------- *) +(** {2 Other useful things} *) +(* -------------------------------------------------------------------------- *) + +(** The function is the main entry point AND it is not a lib entry *) +val is_main_init : Cil_types.kernel_function -> bool + +val get_called_kf : Cil_types.exp -> Cil_types.kernel_function option + +(** apply [f_normal] on the [Normal] postconditions, +* [f_exits] on the [Exits] postconditions, and warn on the others. *) +val fold_bhv_post_cond : warn:bool -> + ('n_acc -> Cil_types.identified_predicate -> 'n_acc) -> + ('e_acc -> Cil_types.identified_predicate -> 'e_acc) -> + 'n_acc * 'e_acc -> funbehavior -> 'n_acc * 'e_acc + +val mk_variant_properties : + kernel_function -> stmt -> code_annotation -> term -> + (WpPropId.prop_id * predicate named) + * (WpPropId.prop_id * predicate named) +(* -------------------------------------------------------------------------- *) diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/aorai_test.ml frama-c-20111001+nitrogen+dfsg/tests/aorai/aorai_test.ml --- frama-c-20110201+carbon+dfsg/tests/aorai/aorai_test.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/aorai_test.ml 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,43 @@ +(* Small script to test that the code generated by aorai can be parsed again + * by frama-c. + *) + +open Kernel + +include Plugin.Register +(struct + let name = "aorai testing module" + let shortname = "aorai-test" + let help = "utility script for aorai regtests" + end) + +let tmpfile = Filename.temp_file "aorai_test" ".i" + +let () = + at_exit (fun () -> + if Debug.get () >= 1 then + result "Keeping temp file %s" tmpfile + else + try Sys.remove tmpfile with Sys_error _ -> ()) + +let extend () = + let myrun = + let run = !Db.Toplevel.run in + fun f -> + let my_project = Project.create "Reparsing" in + run f; + let chan = open_out tmpfile in + let fmt = Format.formatter_of_out_channel chan in + File.pretty_ast ~prj:(Project.from_unique_name "aorai") ~fmt (); + close_out chan; + Project.set_current my_project; + Files.add tmpfile; + Constfold.off (); + File.pretty_ast (); + + in + Db.Toplevel.run := myrun + +let () = Cmdline.run_during_extending_stage extend + + diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/assigns.c frama-c-20111001+nitrogen+dfsg/tests/aorai/assigns.c --- frama-c-20110201+carbon+dfsg/tests/aorai/assigns.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/assigns.c 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,21 @@ +/* run.config + EXECNOW: make -s tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/assigns.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/assigns_det.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs +*/ + +int X; + +void f(void) { X++; } + +/*@ assigns X; + behavior foo: + assigns X; +*/ +int main () { + //@ assigns X; + X++; + //@ assigns X; + f(); + return X; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/call_tree.c frama-c-20111001+nitrogen+dfsg/tests/aorai/call_tree.c --- frama-c-20110201+carbon+dfsg/tests/aorai/call_tree.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/call_tree.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,4 +1,5 @@ /* run.config + EXECNOW: make tests/aorai/aorai_test.cmxs DONTRUN: small example related to U3CAT's WP2 */ int x; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/deterministic.i frama-c-20111001+nitrogen+dfsg/tests/aorai/deterministic.i --- frama-c-20110201+carbon+dfsg/tests/aorai/deterministic.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/deterministic.i 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,28 @@ +/* run.config + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/deterministic.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs +*/ + +int X; +int Y; + +void g(int x) { + Y=x; +} + +int f(int x) { + X=x; + g(X); + X++; + g(X); + return 0; +} + +int real_main (int c) { + if (c) f(4); + return 0; +} + +int main (int c) { + return real_main(c); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/goto.c frama-c-20111001+nitrogen+dfsg/tests/aorai/goto.c --- frama-c-20110201+carbon+dfsg/tests/aorai/goto.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/goto.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/goto.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/goto.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ int status=0; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/hoare_seq.i frama-c-20111001+nitrogen+dfsg/tests/aorai/hoare_seq.i --- frama-c-20110201+carbon+dfsg/tests/aorai/hoare_seq.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/hoare_seq.i 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config +EXECNOW: make -s tests/aorai/aorai_test.cmxs +OPT: -aorai-automata tests/aorai/hoare_seq.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test +*/ + +void f(void) { } + +/*@ behavior bhv: + assumes c > 0; + ensures \result == 0; +*/ +int main(int c) { + if (c <= 0) { f (); } + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/not_prm.i frama-c-20111001+nitrogen+dfsg/tests/aorai/not_prm.i --- frama-c-20110201+carbon+dfsg/tests/aorai/not_prm.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/not_prm.i 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,8 @@ +/* run.config + EXECNOW: make -s tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/not_prm.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test -main f +*/ + +int f(int x) { + return x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/other.c frama-c-20111001+nitrogen+dfsg/tests/aorai/other.c --- frama-c-20110201+carbon+dfsg/tests/aorai/other.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/other.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/other.ya -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/other.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ int x=0; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/seq.i frama-c-20111001+nitrogen+dfsg/tests/aorai/seq.i --- frama-c-20110201+carbon+dfsg/tests/aorai/seq.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/seq.i 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + EXECNOW: make -s tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/seq.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs -aorai-acceptance + */ + +void f() { } + +void g() { } + +int main(int c) { + if (c) f(); + g(); + if (c) g(); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/seq_loop.i frama-c-20111001+nitrogen+dfsg/tests/aorai/seq_loop.i --- frama-c-20110201+carbon+dfsg/tests/aorai/seq_loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/seq_loop.i 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,21 @@ +/* run.config + EXECNOW: make -s tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/seq_loop.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs -aorai-acceptance +*/ + +int f() {} + +int g() {} + +int main(int c) { + if (c<0) { c = 0; } + if (c>5) { c = 5; } + /*@ assert 0<=c<=5; */ + while (c) { + f(); + g(); + c--; + } + return 0; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/single_call.i frama-c-20111001+nitrogen+dfsg/tests/aorai/single_call.i --- frama-c-20110201+carbon+dfsg/tests/aorai/single_call.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/single_call.i 2011-10-10 08:38:52.000000000 +0000 @@ -0,0 +1,6 @@ +/* run.config + EXECNOW: make -s tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/single_call.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs -aorai-acceptance +*/ + +int main () {} diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_acces_params2.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_acces_params2.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_acces_params2.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_acces_params2.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_acces_params2.ya -aorai-test 1 + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_acces_params2.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_acces_params.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_acces_params.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_acces_params.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_acces_params.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_acces_params.ya -aorai-test 1 + EXECNOW: make -s tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_acces_params.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs */ int status=0; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle1.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle1.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle1.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle1.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_boucle1.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_boucle1.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ int cpt=3; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle2.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle2.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle2.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle2.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_boucle2.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_boucle2.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ int status=0; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle3.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle3.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle3.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle3.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_boucle3.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_boucle3.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_boucle.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_boucle.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ /*@ requires \true; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle_rechercheTableau.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle_rechercheTableau.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_boucle_rechercheTableau.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_boucle_rechercheTableau.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_boucle_rechercheTableau.ya -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_boucle_rechercheTableau.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_factorial2.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_factorial2.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_factorial2.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_factorial2.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_factorial.ya -aorai-test 1 + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_factorial.ya -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_factorial.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_factorial.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_factorial.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_factorial.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_factorial.ltl -aorai-test 1 + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_factorial.ltl -aorai-test 1 -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion1.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion1.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion1.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion1.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_recursion1.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_recursion1.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion2.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion2.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion2.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion2.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,6 +1,7 @@ /* run.config - OPT: -aorai-buchi tests/aorai/test_recursion2.promela -aorai-test 1 -aorai-acceptance - OPT: -aorai-buchi tests/aorai/test_recursion3.promela -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-buchi tests/aorai/test_recursion2.promela -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs + OPT: -aorai-buchi tests/aorai/test_recursion3.promela -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ /* diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion4.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion4.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion4.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion4.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_recursion4.ya -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_recursion4.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ # pragma JessieIntegerModel(math) diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion5.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion5.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_recursion5.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_recursion5.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_recursion5.ya -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_recursion5.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_struct.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_struct.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_struct.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_struct.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-automata tests/aorai/test_struct.ya -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-automata tests/aorai/test_struct.ya -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ struct People{ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_switch2.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch2.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_switch2.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch2.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_switch2.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_switch2.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ int status=0; diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_switch3.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_switch3.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ /* Calcul de la longueur cumulee des chaines de caracteres prises en parametre */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3_et_recursion.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3_et_recursion.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3_et_recursion.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3_et_recursion.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_switch3_et_recursion.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_switch3_et_recursion.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ /* Calcul de la longueur cumulee des chaines de caracteres prises en parametre */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3_if.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3_if.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3_if.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3_if.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_switch3.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_switch3.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ /* Calcul de la longueur cumulee des chaines de caracteres prises en parametre */ diff -Nru frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3_return.c frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3_return.c --- frama-c-20110201+carbon+dfsg/tests/aorai/test_switch3_return.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/aorai/test_switch3_return.c 2011-10-10 08:38:52.000000000 +0000 @@ -1,5 +1,6 @@ /* run.config - OPT: -aorai-ltl tests/aorai/test_switch3.ltl -aorai-test 1 -aorai-acceptance + EXECNOW: make tests/aorai/aorai_test.cmxs + OPT: -aorai-ltl tests/aorai/test_switch3.ltl -aorai-test 1 -aorai-acceptance -load-module tests/aorai/aorai_test.cmxs */ /* Calcul de la longueur cumulee des chaines de caracteres prises en parametre */ diff -Nru frama-c-20110201+carbon+dfsg/tests/bugs/switch.i frama-c-20111001+nitrogen+dfsg/tests/bugs/switch.i --- frama-c-20110201+carbon+dfsg/tests/bugs/switch.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/bugs/switch.i 2011-10-10 08:39:08.000000000 +0000 @@ -0,0 +1,8 @@ +int g(int); + +void f(void) { + int x = 0; + switch (1) { + case 1: x = (int)g(x); + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/cil/bts882.i frama-c-20111001+nitrogen+dfsg/tests/cil/bts882.i --- frama-c-20110201+carbon+dfsg/tests/cil/bts882.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/cil/bts882.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + OPT:-print +*/ +void main () { + int r; + switch(1) { + case 2: + r = (int) f(1); + break; + default: + break; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/cil/bts892.i frama-c-20111001+nitrogen+dfsg/tests/cil/bts892.i --- frama-c-20110201+carbon+dfsg/tests/cil/bts892.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/cil/bts892.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,15 @@ +int tab[16]; + +void* main(void) +{ + int i; + + static const int* t[] = { + &tab[1], + &tab[3], + &tab[4], + &i + }; + + return &t; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/cil/comments.c frama-c-20111001+nitrogen+dfsg/tests/cil/comments.c --- frama-c-20110201+carbon+dfsg/tests/cil/comments.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/cil/comments.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + OPT: -print -keep-comments +*/ +/* ABC */ +void f() {} +//ABD/*FOO*/ +/*ABC*/ +/*ABC + */ +/*@ requires \true ; // FOO */ +void g() {} diff -Nru frama-c-20110201+carbon+dfsg/tests/cil/empty_cond.c frama-c-20111001+nitrogen+dfsg/tests/cil/empty_cond.c --- frama-c-20110201+carbon+dfsg/tests/cil/empty_cond.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/cil/empty_cond.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,5 @@ +int y,z; +void main(int x) { + if(z++) ; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/cil/ocaml32bits3_11_0.i frama-c-20111001+nitrogen+dfsg/tests/cil/ocaml32bits3_11_0.i --- frama-c-20110201+carbon+dfsg/tests/cil/ocaml32bits3_11_0.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/cil/ocaml32bits3_11_0.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,4 @@ +enum { + OK=0x1111EEEEu, + KO=0x99996666u, // fixed bug of Ocaml 32bits 3.11.0 + } v ; diff -Nru frama-c-20110201+carbon+dfsg/tests/cil/union_to_union.i frama-c-20111001+nitrogen+dfsg/tests/cil/union_to_union.i --- frama-c-20110201+carbon+dfsg/tests/cil/union_to_union.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/cil/union_to_union.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,10 @@ +union X { + int a; + short b; +}; +int main() +{ + union X u,v; + v = (union X) u; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/constant_propagation/const_field_return_struct.i frama-c-20111001+nitrogen+dfsg/tests/constant_propagation/const_field_return_struct.i --- frama-c-20110201+carbon+dfsg/tests/constant_propagation/const_field_return_struct.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/constant_propagation/const_field_return_struct.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + OPT: -val -semantic-const-folding -journal-disable +*/ + +struct S { + const int f0; + int f1; } T, U; + +struct S main(int c) +{ + if (c) return T; + return U; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/constant_propagation/introduction_of_non_explicit_cast.ml frama-c-20111001+nitrogen+dfsg/tests/constant_propagation/introduction_of_non_explicit_cast.ml --- frama-c-20110201+carbon+dfsg/tests/constant_propagation/introduction_of_non_explicit_cast.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/constant_propagation/introduction_of_non_explicit_cast.ml 2011-10-10 08:39:04.000000000 +0000 @@ -3,7 +3,7 @@ let all = Datatype.String.Set.empty in let new_proj = !Db.Constant_Propagation.get all true in Project.set_current new_proj; - Parameters.CodeOutput.output "After Constant propagation :@."; + Kernel.CodeOutput.output (fun fmt -> Format.fprintf fmt "After Constant propagation :@.") ; File.pretty_ast ~prj:new_proj ();; let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/tests/dynamic/abstract2.ml frama-c-20111001+nitrogen+dfsg/tests/dynamic/abstract2.ml --- frama-c-20110201+carbon+dfsg/tests/dynamic/abstract2.ml 2011-02-07 13:41:25.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/dynamic/abstract2.ml 2011-10-10 08:38:38.000000000 +0000 @@ -3,7 +3,6 @@ type t = string let ty = Type.register ~name:"AA.t" ~ml_name:None Structural_descr.Unknown [ "" ] - let () = Type.is_dynamic_abstract ty let mk = Dynamic.register ~plugin:"AA" ~journalize:false "mk" (Datatype.func Datatype.unit ty) @@ -14,7 +13,6 @@ type t = float let ty = Type.register ~name:"BB.t" ~ml_name:None Structural_descr.Unknown [ 1.0 ] - let () = Type.is_dynamic_abstract ty let print = Dynamic.register ~plugin:"BB" ~journalize:false "print" (Datatype.func ty Datatype.unit) @@ -22,13 +20,14 @@ end let main () = - let a = Type.get "AA.t" in - let b = Type.get "BB.t" in - let s = Dynamic.get ~plugin:"AA" "mk" (Datatype.func Datatype.unit a) () in - try - Dynamic.get ~plugin:"BB" "print" (Datatype.func b Datatype.unit) s; - assert false - with Dynamic.Incompatible_type s -> - print_endline s + let module A = Type.Abstract(struct let name = "AA.t" end) in + let a = A.ty in + let module B = Type.Abstract(struct let name = "BB.t" end) in + let _b = B.ty in + let _s = Dynamic.get ~plugin:"AA" "mk" (Datatype.func Datatype.unit a) () in + (* is now statically checked and no more dynamically *) +(* Dynamic.get ~plugin:"BB" "print" (Datatype.func b Datatype.unit) s;*) + () + let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/tests/dynamic/abstract.ml frama-c-20111001+nitrogen+dfsg/tests/dynamic/abstract.ml --- frama-c-20110201+carbon+dfsg/tests/dynamic/abstract.ml 2011-02-07 13:41:25.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/dynamic/abstract.ml 2011-10-10 08:38:38.000000000 +0000 @@ -5,12 +5,10 @@ type u = float let mk () = 1.05 let f = function A n -> n | B false -> min_int | B true -> max_int - let t : t Type.t = + let t = Type.register ~name:"A.t" ~ml_name:None Structural_descr.Unknown [ A 1 ] - let () = Type.is_dynamic_abstract t - let u : u Type.t = + let u = Type.register ~ml_name:None ~name:"A.u" Structural_descr.Unknown [ 1.0 ] - let () = Type.is_dynamic_abstract u let mk = Dynamic.register ~plugin:"A" ~journalize:false "mk" (Datatype.func Datatype.unit u) @@ -46,11 +44,12 @@ (Datatype.func (Datatype.func t Datatype.int) (Datatype.func t u)) (fun f x -> float (f x)) - let _ = ignore (Dynamic.get ~plugin:"A" "mk" (Datatype.func Datatype.unit u) ()) + let _ = + ignore (Dynamic.get ~plugin:"A" "mk" (Datatype.func Datatype.unit u) ()) - let _ = - (Dynamic.get ~plugin:"A" "mk" - (Datatype.func Datatype.unit (Type.get "A.u")) ()) + module U = Type.Abstract(struct let name = "A.u" end) + let __ : U.t = + Dynamic.get ~plugin:"A" "mk" (Datatype.func Datatype.unit U.ty) () let _ = Dynamic.register ~journalize:false ~plugin:"A" "poly" @@ -64,10 +63,12 @@ (* use of the abstract functions *) module B = struct - let ty = Type.get "A.t" + module T = Type.Abstract(struct let name = "A.t" end) + let ty = T.ty let _ = Type.register ~ml_name:None ~name:"B.t" Structural_descr.Unknown [ 0.0 ] - let ty' = Type.get "A.u" + module U = Type.Abstract(struct let name = "A.u" end) + let ty' = U.ty let fut = Datatype.func Datatype.unit ty' let mk = Dynamic.get ~plugin:"A" "mk" fut let g = Dynamic.get ~plugin:"A" "g" (Datatype.func ty' Datatype.int) @@ -102,14 +103,14 @@ assert false with Dynamic.Incompatible_type s -> print_endline s - let () = + (* let () = (* is now statically checked and no more dynamically *) try List.iter (Dynamic.get ~plugin:"A" "ppu" (Datatype.func ty' Datatype.unit)) (Dynamic.get ~plugin:"A" "poly" (Datatype.list ty')); assert false with Dynamic.Incompatible_type s -> - print_endline s + print_endline s*) let () = List.iter (Dynamic.get ~plugin:"A" "ppu" (Datatype.func ty' Datatype.unit)) diff -Nru frama-c-20110201+carbon+dfsg/tests/dynamic/dynamic.i frama-c-20111001+nitrogen+dfsg/tests/dynamic/dynamic.i --- frama-c-20110201+carbon+dfsg/tests/dynamic/dynamic.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/dynamic/dynamic.i 2011-10-10 08:38:38.000000000 +0000 @@ -0,0 +1,4 @@ +/*run.config + COMMENT: cf test_config + OPT: -add-path tests/dynamic/file_path -add-path tests/dynamic/directory_path -add-path tests/dynamic/none -dynamic-test + */ diff -Nru frama-c-20110201+carbon+dfsg/tests/dynamic_plugin/apply.ml frama-c-20111001+nitrogen+dfsg/tests/dynamic_plugin/apply.ml --- frama-c-20110201+carbon+dfsg/tests/dynamic_plugin/apply.ml 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/dynamic_plugin/apply.ml 2011-10-10 08:39:08.000000000 +0000 @@ -21,7 +21,7 @@ let main () = - if Parameters.Dynamic.Bool.get "-dynamic-test" then begin + if Dynamic.Parameter.Bool.get "-dynamic-test" () then begin ignore (Dynamic.get ~plugin:"Register_mod2" "g_test" (func int int) 41); try Dynamic.get ~plugin:"Register_mod2" "g_test" diff -Nru frama-c-20110201+carbon+dfsg/tests/float/absorb.c frama-c-20111001+nitrogen+dfsg/tests/float/absorb.c --- frama-c-20110201+carbon+dfsg/tests/float/absorb.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/absorb.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,12 +1,13 @@ /* run.config - EXECNOW: BIN absorb.sav LOG absorb_sav.res LOG absorb_sav.err ./bin/toplevel.opt -memory-footprint 1 -val -journal-disable share/builtin.c -float-hex -save ./tests/float/result/absorb.sav tests/float/absorb.c > tests/float/result/absorb_sav.res 2> tests/float/result/absorb_sav.err - OPT: -load ./tests/float/result/absorb.sav -deps -out -input + EXECNOW: BIN absorb.sav LOG absorb_sav.res LOG absorb_sav.err ./bin/toplevel.opt -memory-footprint 1 -journal-disable share/builtin.c -save ./tests/float/result/absorb.sav tests/float/absorb.c > tests/float/result/absorb_sav.res 2> tests/float/result/absorb_sav.err + EXECNOW: BIN absorb.sav2 LOG absorb_sav2.res LOG absorb_sav2.err ./bin/toplevel.opt -load ./tests/float/result/absorb.sav -val -journal-disable -float-hex -save ./tests/float/result/absorb.sav2 > tests/float/result/absorb_sav2.res 2> tests/float/result/absorb_sav2.err + OPT: -load ./tests/float/result/absorb.sav2 -deps -out -input OPT: -all-rounding-modes -memory-footprint 1 -val -deps -out -input -journal-disable -float-hex share/builtin.c */ #include "share/builtin.h" -float x = 1.0, y = 0.0, z, t; +float x = 1.0, y = 0.0, z, t, min_f, min_fl, den; void main() { long long b = Frama_C_interval(-2000000001, 2000000001); @@ -17,4 +18,7 @@ y = x ; x+=1E-286; } t = b; + min_f = 1.175494351e-38; + min_fl = -1.1754943505e-38; + den = min_f / 128.; } diff -Nru frama-c-20110201+carbon+dfsg/tests/float/const.i frama-c-20111001+nitrogen+dfsg/tests/float/const.i --- frama-c-20110201+carbon+dfsg/tests/float/const.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/const.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,123 @@ +/* run.config + OPT: -memory-footprint 1 -val -out -deps -float-hex -journal-disable +*/ +typedef double mydouble; + +float f0, f_ , f00, f1 = 3.0, f2, f3, f_0, f13, f26, fic0,fic1,fic2,fic4, fec0,fec2,fec4; + +mydouble m0, m_ , m00, m1 = 3.0, m2, m3, m_0, m13, m26; + +double d0, d1 = 3.0, d2, d3, d4, d5, d6, d7; + +int A,B,C,D,E,F,G,H,I,J,K,L,P,Q,R; + +int Am,Bm,Cm,Dm,Em,Fm,Gm,Hm,Im,Jm,Km,Lm; + +int t1,t2,t3,t4,t5,t6,t7,t8,t9,C0=0,C2=2; +int s1,s2,s3,s4,s5,s6,s7,s8,s9; +int if1,if2,if3,ite1,ite2,ite3; +int ca1,ca2,ca3,ca4; + +void main(int c1, int c2) +{ + f_ = - f0; + f_0 = c1 ? f0 : f_; + f00 = - f_; + f2 = f1; + f13 = c1 ? 1.0 : 3.0; + f26 = f13 + f13; + +/*@ assert f26 >= -1.0 ; */ + + ca1 = f_0; + ca2 = f13; + ca3 = f0; + ca4 = f00; + + m_ = - m0; + m_0 = c1 ? m0 : m_; + m00 = - m_; + m2 = m1; + m13 = c1 ? 1.0 : 3.0; + m26 = m13 + m13; + + if (f2 == f1) + d2 = d1; + f3 = f1 + f0; + if (f3 == f1) + d6 = d1; + + f13 = c1 ? 1.0 : 3.0; + + A = f0 == f_; + B = f0 == f1; + C = f0 == f0; + D = f_ == f1; + E = f_ == f_; + + F = f_0 == f0; + G = f_0 == f_; + H = (c1 ? f0 : 3.0) == f_; + I = (c1 ? f0 : 3.0) == f0; + J = f13 == f_; + K = f13 == f0; + L = f13 == (c2? 3.0 : 5.0); + + P = f13 != (c2? 3.0 : 5.0); + Q = f0 != f_; + R = f0 != f1; + + Am = m0 == m_; + Bm = m0 == m1; + Cm = m0 == m0; + Dm = m_ == m1; + Em = m_ == m_; + + Fm = m_0 == m0; + Gm = m_0 == m_; + Hm = (c1 ? m0 : 3.0) == m_; + Im = (c1 ? m0 : 3.0) == m0; + Jm = m13 == m_; + Km = m13 == m0; + Lm = m13 == (c2? 3.0 : 5.0); + + t1 = f_0 <= f0; + t2 = f0 <= f_0; + t3 = f0 <= f13; + t4 = f13 <= f26; + t5 = f26 <= f13; + t6 = 1.0 <= f26; + t7 = f26 <= 1.0; + t8 = f1 <= f1; + + s1 = f_0 < f0; + s2 = f0 < f_0; + s3 = f0 < f13; + s4 = f13 < f26; + s5 = f26 < f13; + s6 = 1.0 < f26; + s7 = f26 < 1.0; + s8 = f1 < f1; + + d3 = d1 + 2.0; + d4 = d1 + 2; + + if (1.0) if1 = 1; + if (0.0) if2 = 1; + if (-0.0) if3 = 1; + + if (1.0) ite1 = 1; else ite1 = 2; + if (0.0) ite2 = 1; else ite2 = 2; + if (-0.0) ite3 = 1; else ite3 = 2; + + fic0 = C0; + fic1 = 1; + fic2 = C2; + fic4 = C2 + C2; + fec0 = (float) C0; + fec2 = (float) C2; + fec4 = (float) (C2 + C2); + + d5 = (c2 ? -3.0 : 9.0) / f13; + d7 = (c2 ? -3.0 : 9.0) / (-f13); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/float/cte_overflow.i frama-c-20111001+nitrogen+dfsg/tests/float/cte_overflow.i --- frama-c-20110201+carbon+dfsg/tests/float/cte_overflow.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/cte_overflow.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,9 @@ + +int main() +{ + double t=0.0; + + t = 1e500 * 1e500 * 1e500 * 1e500 * 1e500; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/float/float_cast_implicite.i frama-c-20111001+nitrogen+dfsg/tests/float/float_cast_implicite.i --- frama-c-20110201+carbon+dfsg/tests/float/float_cast_implicite.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/float_cast_implicite.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,18 @@ +int C0 = 0, C2 = 2, CBP = 2000000000; +float fic0, fic1, fic2, fic4, fec0, fec2, fec4, ficbp, ficbn, fecbp, fecbn; + +void main(void) +{ + fic0 = C0; + fic1 = 1; + fic2 = C2; + fic4 = C2 + C2; + fec0 = (float) C0; + fec2 = (float) C2; + fec4 = (float) (C2 + C2); + + ficbp = CBP; + fecbp = (float) CBP; + ficbn = -CBP; + fecbn = (float) (-CBP); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/float/init_float.i frama-c-20111001+nitrogen+dfsg/tests/float/init_float.i --- frama-c-20110201+carbon+dfsg/tests/float/init_float.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/init_float.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,30 @@ +/* run.config + OPT: -memory-footprint 1 -val -journal-disable -float-normal -lib-entry +*/ + +typedef struct S { float y; } S; + +S s; + +double r, cv, un, zp, zm, zs; + +long long l; + + +/*@ + requires -1000.0 <= x <= 1000.0; + requires 0.0 <= s.y <= 0.0; +*/ +int main(float x) +{ + if (l >= 4700000000000000000ll) l = 4700000000000000000ll; + if (l <= 4500000000000000001ll) l = 4500000000000000001ll; + cv = *(double*)&l + 1.0; + r = x; + s.y = s.y * 1.0; + un = 1.0; + zp = un - un; + zm = - (un - un); + zs = zp + zm; + return 1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/float/precise_cos_sin.i frama-c-20111001+nitrogen+dfsg/tests/float/precise_cos_sin.i --- frama-c-20110201+carbon+dfsg/tests/float/precise_cos_sin.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/precise_cos_sin.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,18 @@ +/* run.config + OPT: -memory-footprint 1 -val -obviously-terminates -journal-disable -float-normal share/builtin.c +*/ + +double Frama_C_cos_precise(double); +double Frama_C_sin_precise(double); +float Frama_C_float_interval(float, float); + +main(){ + float f = Frama_C_float_interval(-3.1875, -3.1875+0.25); + while (f <= 3.1875) + { + Frama_C_show_each_s((float)Frama_C_sin_precise(f)); + Frama_C_show_each_c((float)Frama_C_cos_precise(f)); + f += 0.25; + } +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/float/round10d.i frama-c-20111001+nitrogen+dfsg/tests/float/round10d.i --- frama-c-20110201+carbon+dfsg/tests/float/round10d.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/round10d.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,17 @@ +/* run.config + OPT: -memory-footprint 1 -val -float-normal -journal-disable -no-results +*/ +int main() +{ + double t=0.0; + int i; + Frama_C_show_each_dixieme(0.1); + //@ loop pragma UNROLL 10; + for(i=0;i<10;i++) + { + t = t + 0.1; + Frama_C_show_each_t(t); + } + //@ assert t>=1.0; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/float/s.i frama-c-20111001+nitrogen+dfsg/tests/float/s.i --- frama-c-20110201+carbon+dfsg/tests/float/s.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/float/s.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,265 @@ +/* run.config + OPT: -all-rounding-modes -memory-footprint 1 -val -deps -out -input -journal-disable -float-hex + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -float-hex +*/ + +typedef float T1; +typedef int T2; +typedef int T3; +extern int F1(int G1 ) ; +extern int F2(int G2 ) ; +int const G3 = (int const )42; +extern int F3(int G4 ) ; +T3 G5[64] ; +int const G6 = (int const )42; +int G7 ; +T2 G8 ; +T1 const G9[64] = + {(T1 const )2.000f, (T1 const )1.882f, + (T1 const )1.778f, (T1 const )1.684f, + (T1 const )1.600f, (T1 const )1.523f, + (T1 const )1.455f, (T1 const )1.391f, + (T1 const )1.333f, (T1 const )1.280f, + (T1 const )1.231f, (T1 const )1.185f, + (T1 const )1.143f, (T1 const )1.063f, + (T1 const )1.000f, (T1 const )0.944f, + (T1 const )0.895f, (T1 const )0.850f, + (T1 const )0.810f, (T1 const )0.773f, + (T1 const )0.739f, (T1 const )0.708f, + (T1 const )0.680f, (T1 const )0.654f, + (T1 const )0.630f, (T1 const )0.607f, + (T1 const )0.586f, (T1 const )0.567f, + (T1 const )0.548f, (T1 const )0.500f, + (T1 const )0.471f, (T1 const )0.444f, + (T1 const )0.421f, (T1 const )0.400f, + (T1 const )0.381f, (T1 const )0.364f, + (T1 const )0.348f, (T1 const )0.333f, + (T1 const )0.320f, (T1 const )0.308f, + (T1 const )0.296f, (T1 const )0.286f, + (T1 const )0.276f, (T1 const )0.267f, + (T1 const )0.258f, (T1 const )0.250f, + (T1 const )0.236f, (T1 const )0.222f, + (T1 const )0.211f, (T1 const )0.200f, + (T1 const )0.190f, (T1 const )0.182f, + (T1 const )0.174f, (T1 const )0.167f, + (T1 const )0.160f, (T1 const )0.154f, + (T1 const )0.148f, (T1 const )0.143f, + (T1 const )0.138f, (T1 const )0.133f, + (T1 const )0.129f, (T1 const )0.125f, + (T1 const )0.118f, (T1 const )0.111f}; +T1 const G10[64] = + {(T1 const )0.0510143148127383f, + (T1 const )0.0526807976019492f, + (T1 const )0.0547630669950585f, + (T1 const )0.0564281924367408f, + (T1 const )0.0585087059708387f, + (T1 const )0.0605881929148253f, + (T1 const )0.0630821707769080f, + (T1 const )0.0655745547964065f, + (T1 const )0.0680652820004121f, + (T1 const )0.0713835655737245f, + (T1 const )0.0742844385649674f, + (T1 const )0.0780103647018580f, + (T1 const )0.0817318560546706f, + (T1 const )0.0862740143728233f, + (T1 const )0.0908088461410527f, + (T1 const )0.0961582204249914f, + (T1 const )0.1023163627594810f, + (T1 const )0.1055941606958780f, + (T1 const )0.1088672156067600f, + (T1 const )0.1125435499383810f, + (T1 const )0.1166208530287330f, + (T1 const )0.1210964219228140f, + (T1 const )0.1255617070832910f, + (T1 const )0.1304207531449480f, + (T1 const )0.1356698301501220f, + (T1 const )0.1417064222370730f, + (T1 const )0.1481207659913060f, + (T1 const )0.1549068205428340f, + (T1 const )0.1624539893402380f, + (T1 const )0.1707476333220120f, + (T1 const )0.1797704190221740f, + (T1 const )0.1902769765139430f, + (T1 const )0.2014532178568310f, + (T1 const )0.2079499479102800f, + (T1 const )0.2144044999107600f, + (T1 const )0.2215668881520150f, + (T1 const )0.2290455646566350f, + (T1 const )0.2371977623669650f, + (T1 const )0.2452693886855440f, + (T1 const )0.2543404121628250f, + (T1 const )0.2640116929021380f, + (T1 const )0.2745989285199270f, + (T1 const )0.2860443073244380f, + (T1 const )0.2982805530233570f, + (T1 const )0.3112299993821370f, + (T1 const )0.3254401125978740f, + (T1 const )0.3407438063507600f, + (T1 const )0.3572363398164020f, + (T1 const )0.3749169970825380f, + (T1 const )0.3841864461394160f, + (T1 const )0.3939193988832260f, + (T1 const )0.4037685876851210f, + (T1 const )0.4141279920488020f, + (T1 const )0.4243935880669410f, + (T1 const )0.4350918773347630f, + (T1 const )0.4457881609076350f, + (T1 const )0.4562601664070490f, + (T1 const )0.4665646755216170f, + (T1 const )0.4764261613996570f, + (T1 const )0.4852153448066030f, + (T1 const )0.4927158273036620f, + (T1 const )0.4979548345880140f, + (T1 const )0.4999998245403760f, + (T1 const )0.4973478192101480f}; +T1 const G11[64] = + {(T1 const )1.98956292560627f, + (T1 const )1.98886795364206f, + (T1 const )1.98796783271076f, + (T1 const )1.98722262104002f, + (T1 const )1.98625972652367f, + (T1 const )1.98526198121786f, + (T1 const )1.98401870850080f, + (T1 const )1.98272530730105f, + (T1 const )1.98138181029787f, + (T1 const )1.97951261300748f, + (T1 const )1.97780412452634f, + (T1 const )1.97550756211798f, + (T1 const )1.97309869476763f, + (T1 const )1.97000221093885f, + (T1 const )1.96673843085462f, + (T1 const )1.96266592835235f, + (T1 const )1.95767765236944f, + (T1 const )1.95489078253260f, + (T1 const )1.95201610389272f, + (T1 const )1.94867729238996f, + (T1 const )1.94483758350707f, + (T1 const )1.94045626221254f, + (T1 const )1.93591015375954f, + (T1 const )1.93076327766655f, + (T1 const )1.92496731270757f, + (T1 const )1.91799599539423f, + (T1 const )1.91022611722130f, + (T1 const )1.90159460221914f, + (T1 const )1.89149126922623f, + (T1 const )1.87976698860229f, + (T1 const )1.86625870208647f, + (T1 const )1.84951743850643f, + (T1 const )1.83048234524184f, + (T1 const )1.81882080113072f, + (T1 const )1.80679034940091f, + (T1 const )1.79291099198876f, + (T1 const )1.77781047048834f, + (T1 const )1.76062362373384f, + (T1 const )1.74283872793243f, + (T1 const )1.72191035650916f, + (T1 const )1.69845965986100f, + (T1 const )1.67138471193539f, + (T1 const )1.64038363438451f, + (T1 const )1.60513531735156f, + (T1 const )1.56530322933083f, + (T1 const )1.51836086942351f, + (T1 const )1.46365929605818f, + (T1 const )1.39932668102673f, + (T1 const )1.32325202617558f, + (T1 const )1.28000484125813f, + (T1 const )1.23176301086518f, + (T1 const )1.17963335048658f, + (T1 const )1.12069982565629f, + (T1 const )1.05746929909226f, + (T1 const )0.98545468309658f, + (T1 const )0.90574093951495f, + (T1 const )0.81806269246518f, + (T1 const )0.71908167608869f, + (T1 const )0.60686885217797f, + (T1 const )0.48275988506435f, + (T1 const )0.34014381721778f, + (T1 const )0.18070894655987f, + (T1 const )(- 0.00167551588592f), + (T1 const )(- 0.20572395978728f)}; +T1 const G12[32] = + {(T1 const )0.666666666666667f, + (T1 const )0.592592592592593f, + (T1 const )0.533333333333333f, + (T1 const )0.484848484848485f, + (T1 const )0.444444444444444f, + (T1 const )0.410256410256410f, + (T1 const )0.380952380952381f, + (T1 const )0.355555555555556f, + (T1 const )0.333333333333333f, + (T1 const )0.296296296296296f, + (T1 const )0.266666666666667f, + (T1 const )0.242424242424242f, + (T1 const )0.222222222222222f, + (T1 const )0.205128205128205f, + (T1 const )0.190476190476191f, + (T1 const )0.177777777777778f, + (T1 const )0.166666666666667f, + (T1 const )0.148148148148148f, + (T1 const )0.133333333333333f, + (T1 const )0.121212121212121f, + (T1 const )0.111111111111111f, + (T1 const )0.102564102564103f, + (T1 const )0.095238095238095f, + (T1 const )0.088888888888889f, + (T1 const )0.083333333333333f, + (T1 const )0.074074074074074f, + (T1 const )0.066666666666667f, + (T1 const )0.060606060606061f, + (T1 const )0.055555555555556f, + (T1 const )0.051282051282051f, + (T1 const )0.047619047619048f, + (T1 const )0.044444444444445f}; +static T2 G13 ; +static T1 G14 ; +static T1 G15 ; +static T1 G16 ; +static T1 G17 ; +static T1 G18 ; +static T1 G19 ; +void F4(void) +{ T1 V1 ; + T1 V2 ; + T1 V3 ; + int V4 ; + int V5 ; + int V6 ; + int V7 ; + + {{V1 = (float )0.0; + V4 = F1(G13); + G16 = (float )G9[V4];} + + {V5 = F2(G13); +/* JLCo + G14 = (float )(G10[V5] / (T1 const )((float )G3)); + G14 = (float )(G10[V5] / (T1 const )G3); +*/ + G14 = (float )(G10[V5] / G3); +} + + {V6 = F2(G13); + G15 = (float )G11[V6];} + + {V7 = F3(G13); + G17 = (float )G12[V7];} + + {G18 = (float )(1.0 / ((double )G14 + 1.0)); + V2 = G15 * G18;} + + {V3 = (float )(((double )G14 - 1.0) * (double )G18); + G19 = (G16 * G14) * G18;} + + + return;} + +} +int main(void) +{ int V8 ; + + {F4(); + V8 = 0; + return (V8);} + +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/idct/ieee_1180_1990.c frama-c-20111001+nitrogen+dfsg/tests/idct/ieee_1180_1990.c --- frama-c-20110201+carbon+dfsg/tests/idct/ieee_1180_1990.c 2011-02-07 13:41:25.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/idct/ieee_1180_1990.c 2011-10-10 08:38:37.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -float-normal -val -deps -out -input tests/idct/idct.c share/math.c -journal-disable + OPT: -float-normal -val -deps -out -input tests/idct/idct.c share/math.c -journal-disable -remove-redundant-alarms */ /* IEEE_1180_1990: a testbed for IDCT accuracy * Copyright (C) 2001 Renaud Pacalet diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/alias.i frama-c-20111001+nitrogen+dfsg/tests/impact/alias.i --- frama-c-20110201+carbon+dfsg/tests/impact/alias.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/alias.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,20 @@ +/* run.config + STDOPT: +"-impact-pragma f" +"-lib-entry" +"-main f" +"-remove-redundant-alarms" + */ + +int P,c; + +/*@ requires \valid(x); */ +int f(int *x) { + /*@ impact pragma stmt; */ + int *y = x; + *y = 4; + int a = *x + 2; + *y = 2; + if (c) + return *x; + else { + y = P; + return *y; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/called.i frama-c-20111001+nitrogen+dfsg/tests/impact/called.i --- frama-c-20110201+carbon+dfsg/tests/impact/called.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/called.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,28 @@ +/* run.config + STDOPT: +"-impact-pragma g" +"-lib-entry" +"-main g" + STDOPT: +"-impact-pragma h" +"-lib-entry" +"-main h" + */ + +int X; + +int f(int x, int y) { X = x; return y; } + +void g() { + int a, b, c, d; + b = 0; + /*@ impact pragma stmt; */ + a = 0; + c = f(a,b); + d = X; + c = f(a,d); +} + +void h() { + int a, b, c, d; + /*@ impact pragma stmt; */ + b = 0; + a = 0; + c = f(a,b); + d = X; + c = f(a,d); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/call.i frama-c-20111001+nitrogen+dfsg/tests/impact/call.i --- frama-c-20110201+carbon+dfsg/tests/impact/call.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/call.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,56 @@ +/* run.config + GCC: + STDOPT: +"-impact-pragma main" + STDOPT: +"-impact-pragma main2" +"-main main2" + STDOPT: +"-impact-pragma main3" +"-main main3" + */ + +/*@ ghost int G; */ + +/*@ assigns G \from p; */ +void p1 (int p); +void p2 (int); +int X; + +void test (void) { + if (X) p1(1); else p2(0); +} + +/* ************************************************************************* */ + +void main (int x) { + /*@ impact pragma stmt; */ + X = x; + test (); +} + +/* ************************************************************************* */ + +void call_test (void) { + test (); +} + +void main2(int x) { + /*@ impact pragma stmt; */ + X = x; + call_test (); +} + +/* ************************************************************************* */ + +/*@ assigns G; */ +void p3 (int); + +void test3 (void) { + if (X) p3(1); else p2(0); +} + +void call_test3 (void) { + test3 (); +} + +void main3(int x) { + /*@ impact pragma stmt; */ + X = x; + call_test3 (); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/depend1.i frama-c-20111001+nitrogen+dfsg/tests/impact/depend1.i --- frama-c-20110201+carbon+dfsg/tests/impact/depend1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/depend1.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + STDOPT: +"-impact-pragma main" + */ + + +int find(int x) { return x; } + +int main() +{ + int a = find(1); + /*@ impact pragma stmt; */ + int b = find(2); + int c = find(b); + int d = find(3); + return c ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/depend2.i frama-c-20111001+nitrogen+dfsg/tests/impact/depend2.i --- frama-c-20110201+carbon+dfsg/tests/impact/depend2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/depend2.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + STDOPT: +"-impact-pragma main" + */ + +int find(int x) { return x; } + +int apply(int x,int y) { return find(x)+y; } + +int main() +{ + int a = apply(1,100); + /*@ impact pragma stmt; */ + int b = apply(2,200); + return a+b ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/first.i frama-c-20111001+nitrogen+dfsg/tests/impact/first.i --- frama-c-20110201+carbon+dfsg/tests/impact/first.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/first.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + GCC: + STDOPT: +"-impact-pragma impact" +"-lib-entry" +"-main impact" + */ + +int a, b, c, e, x, y, z, f, w; + +void impact() { + /*@ impact pragma stmt; */ + b = a; + if (c) { + x = b + c; + y = x + e; + } else + z = 12; + z = 13; + z = y + f; + w = b; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/loop.i frama-c-20111001+nitrogen+dfsg/tests/impact/loop.i --- frama-c-20110201+carbon+dfsg/tests/impact/loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/loop.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,17 @@ +/* run.config + GCC: + STDOPT: +"-impact-pragma loop" +"-lib-entry" +"-main loop" + */ + +int c,x,y,z,w; + +void loop () { + while (c) { + z = w + 1; + z = y + 1; + /*@ impact pragma stmt; */ + x = x + 1; + y = x + 1; + } + w = z; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/slicing.i frama-c-20111001+nitrogen+dfsg/tests/impact/slicing.i --- frama-c-20110201+carbon+dfsg/tests/impact/slicing.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/slicing.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,20 @@ +/* run.config + GCC: + STDOPT: +"-impact-pragma impact" +"-lib-entry" +"-main impact" +"-impact-slicing" +"-then-on 'impact slicing'" +"-print" + */ + +int a, b, c, e, x, y, z, f, w; + +void impact() { + if (c) a = 18; else x = 5; + /*@ impact pragma stmt; */ + b = a; + if (c) { + x = b + c; + y = x + e; + } else + z = 12; + z = 13; + z = y + f; + w = b; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/undef_function.i frama-c-20111001+nitrogen+dfsg/tests/impact/undef_function.i --- frama-c-20110201+carbon+dfsg/tests/impact/undef_function.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/undef_function.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + GCC: + STDOPT: +"-impact-pragma main" + */ +int y; + +int main() { + /*@ impact pragma stmt; */ + y=2; + g(y); + return y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/impact/variadic.i frama-c-20111001+nitrogen+dfsg/tests/impact/variadic.i --- frama-c-20110201+carbon+dfsg/tests/impact/variadic.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/impact/variadic.i 2011-10-10 08:39:10.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + STDOPT: +"-impact-pragma main" + */ + +int f(int, ...); + +int main () { + int i=0; + /*@ impact pragma stmt; */ + i++; + f(i); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/journal/control.i frama-c-20111001+nitrogen+dfsg/tests/journal/control.i --- frama-c-20110201+carbon+dfsg/tests/journal/control.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/journal/control.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + EXECNOW: BIN control_journal.ml BIN control_journal_bis.ml (./bin/toplevel.opt -journal-enable -memory-footprint 1 -val -deps -out -main f -journal-name tests/journal/result/control_journal tests/journal/control.i && cp tests/journal/result/control_journal.ml tests/journal/result/control_journal_bis.ml) > /dev/null 2> /dev/null + CMD: FRAMAC_LIB=lib/fc ./bin/toplevel.byte + OPT: -load-script tests/journal/result/control_journal -journal-disable + CMD: FRAMAC_LIB=lib/fc ./bin/toplevel.byte + OPT: -load-script tests/journal/result/control_journal_bis -calldeps -journal-disable +*/ + +int x,y,c,d; + + +void f() { + int i; + for(i=0; i<4 ; i++) { + if (c) { if (d) {y++;} else {x++;}} + else {}; + x=x+1; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/journal/intra.i frama-c-20111001+nitrogen+dfsg/tests/journal/intra.i --- frama-c-20110201+carbon+dfsg/tests/journal/intra.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/journal/intra.i 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,117 @@ +/* run.config + EXECNOW: make -s tests/journal/intra.opt tests/journal/intra.byte + EXECNOW: BIN intra_journal.ml ./tests/journal/intra.opt -journal-enable -journal-name tests/journal/result/intra_journal tests/journal/intra.i > /dev/null 2> /dev/null + CMD: FRAMAC_LIB=lib/fc ./tests/journal/intra.byte + OPT: -load-script tests/journal/result/intra_journal -journal-disable +*/ + +/* Waiting for results such as: + * spare code analysis removes statements having variables with + * prefix "spare_" + * + * slicing analysis removes statement having variables with + * prefix "spare_" and "any_" + */ + +int G; + +int tmp (int a) { + int x = a; + //@ assert x == a ; + int w = 1; + //@ assert w == 1 ; // w is not spare or else + // the assertion should be removed ! + int spare_z = 1; + int spare_y = a+spare_z; + return x; +} + +int param (int a, int spare_b) { + return a; +} + +int spare_called_fct (int a) { + return a; +} + +int two_outputs (int a, int b) { + G += b; + return a; +} + +int call_two_outputs (void) { + int x, spare_y; + int any_b = 1; + int any_a = 2; + int a = 1; + int b = any_b; + x = two_outputs (a, b); + G = 1; /* don't use b = any_b; */ + b = 2; + a = any_a; + spare_y = two_outputs (a, b); + /* don't use spare_y so don't use a = any_a */ + return x; +} + +void assign (int *p, int *q) { + *p = *q ; +} + +int loop (int x, int y, int z) { + int i = 0; + //@ assert i < z ; + //@ loop invariant i < y ; + /* should keep y in sparecode analysis even if it is not used in the function */ + while (i < x) { + i ++; + } + return i; +} + +void stop(void) __attribute__ ((noreturn)) ; + +int main (int noreturn, int halt) { + int res = 0; + int spare_tmp = 3; + int spare_param = 2 + spare_tmp; + int spare_ref = 3; + int x = 1; + int y = 2; + res += param (2, spare_param); + res += tmp (4); + spare_called_fct (5); + res += call_two_outputs (); + res += loop (10, 15, 20); + assign (&x, &spare_ref) ; /* <- Here, best can be done for spare analysis */ + assign (&x, &y) ; + if (noreturn) { + if (halt) + stop () ; + else + while (1); + //@ assert \false ; // What should be done with + // assertions related to dead code? + } + + return res + G + x; +} + +/*-------------------------------------*/ +struct { struct { int x; int y; } a; int b; } X10; +int Y10; +int f10 (int x) { + //@ slice pragma expr X10; + //@ slice pragma expr X10.a; + //@ slice pragma expr X10.a.x; + //@ slice pragma expr Y10; + //@ assert X10.a.x >= 0; + return x; +} +int main2 () { + Y10 = 0; + X10.b = 0; + X10.a.y += f10 (3); + return X10.a.x + X10.a.y; +} +/*-------------------------------------*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/metrics/func_ptr.c frama-c-20111001+nitrogen+dfsg/tests/metrics/func_ptr.c --- frama-c-20110201+carbon+dfsg/tests/metrics/func_ptr.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/metrics/func_ptr.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,32 @@ +/* run.config + OPT: -metrics -metrics-value-cover -metrics-cover main + OPT: -metrics -metrics-value-cover -main foobar -metrics-cover foobar +**/ + +void (*bar) (int); + +void baz (int j) { return; } + +int foobar () { + bar = baz; + bar (2); + return 0; +} + +void foo (int k) { + int i = 0; + return; +} + +/* foo is unreachable since j is always 0 */ +int main() { + int j = 0; + if (!j) { + return 1; + } + else { + bar = foo; + bar (1); + return 0; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/metrics/reach.c frama-c-20111001+nitrogen+dfsg/tests/metrics/reach.c --- frama-c-20110201+carbon+dfsg/tests/metrics/reach.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/metrics/reach.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,28 @@ +/* run.config + OPT: -metrics -metrics-by-function -metrics-value-cover +**/ + +void (*bar) (int); + +void baz (int j) { return; } + +void (*t[2])(int)= {baz, 0}; + +void foo (int k) { + int i = 0; + return; +} + +/* foo is unreachable since j is always 0; baz is not called */ +int main() { + int j = 0; + void (*(*pt)[2])(int) = &t; + if (!j) { + return 1; + } + else { + bar = foo; + bar (1); + return 0; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/metrics/unreachable.c frama-c-20111001+nitrogen+dfsg/tests/metrics/unreachable.c --- frama-c-20110201+carbon+dfsg/tests/metrics/unreachable.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/metrics/unreachable.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + OPT: -metrics -metrics-value-cover -then -main foo +**/ +void foo () { + int i = 0; + return; +} + +/* foo is unreachable since j is always 0 */ +int main() { + int j = 0; + if (!j) { + return 1; + } + else { + foo (); + return 0; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/abs_addr.i frama-c-20111001+nitrogen+dfsg/tests/misc/abs_addr.i --- frama-c-20110201+carbon+dfsg/tests/misc/abs_addr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/abs_addr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,47 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -absolute-valid-range 0x20000-0x3FFFF -journal-disable +*/ + +unsigned short AutoTest[1000]={0}; + +unsigned char TstRomUcmm(void) +{ + union {unsigned char byte[2];unsigned short word;} rom; + unsigned short chkrom; + unsigned short *ptrom; + + + ptrom = (unsigned short *)0x020000; + chkrom = 0; + + while(ptrom != (unsigned short *) 0x02FFFE) + { + rom.word = *ptrom; + chkrom = chkrom + rom.byte[0] + rom.byte[1]; + ptrom++; + } + if(chkrom != *ptrom) + { + AutoTest[73] = (unsigned short)1; + } + + + ptrom = (unsigned short *)0x030000; + chkrom = 0; + while(ptrom != (unsigned short *) 0x03FFFE) + { + rom.word = *ptrom; + chkrom = chkrom + rom.byte[0] + rom.byte[1]; + ptrom++; + } + if(chkrom != *ptrom) + { + AutoTest[73] = (unsigned short)1; + } + return(AutoTest[73]); +} + +void main(void){ + TstRomUcmm(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/abs.i frama-c-20111001+nitrogen+dfsg/tests/misc/abs.i --- frama-c-20110201+carbon+dfsg/tests/misc/abs.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/abs.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + STDOPT: +"-remove-redundant-alarms" + */ + + +//@ requires \valid(p); +void main (int* p) { + + if (*p<0) *p=-*p; + + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/absolute_pointer.i frama-c-20111001+nitrogen+dfsg/tests/misc/absolute_pointer.i --- frama-c-20110201+carbon+dfsg/tests/misc/absolute_pointer.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/absolute_pointer.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -absolute-valid-range 0-0x3 -journal-disable +*/ + +char R; +void main() { + *((char*)0)=2; + R = *((char*)1); + *((char*)2)=2; + R = *((char*)3); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/access_path.i frama-c-20111001+nitrogen+dfsg/tests/misc/access_path.i --- frama-c-20110201+carbon+dfsg/tests/misc/access_path.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/access_path.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int **p) { + (**p)++; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/add_approx.i frama-c-20111001+nitrogen+dfsg/tests/misc/add_approx.i --- frama-c-20110201+carbon+dfsg/tests/misc/add_approx.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/add_approx.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +int t[10]={0}; +int x; + +void main(int c) +{ + t[1]=1; + if (c) x = 0; else x = 1; + t[x]=2; + + t[3] = 77; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/addition.i frama-c-20111001+nitrogen+dfsg/tests/misc/addition.i --- frama-c-20110201+carbon+dfsg/tests/misc/addition.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/addition.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,97 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -absolute-valid-range 0x2D-0x30 -journal-disable +*/ + + +int t[10],x,y,z,zz; +int p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16; +unsigned int u1,u3; +int * q1; + +int quo1,rem1,quo2,rem2,quo3,rem3,quo4,rem4,quo5,rem5,mm1,mm2,mm3,quo6,c1,c2,qu1,qu2; +long long ll1,ll2; +struct {int a; int b:2; } tt[5]; +int ttt[5][6]; + +int square; + +int main(int u2, int u3) +{ + z = 37; + + quo1 = z/12; + rem1 = z%12; + quo2 = (-z)/12; + rem2 = (-z)%12; + quo3 = (-z)/(-12); + rem3 = (-z)%(-12); + quo4 = (z)/(-12); + rem4 = (z)%(-12); + quo5 = (z-1)/(-12); + rem5 = (z-1)%(-12); + + p1 = (int)(&p2 - &p3); + + p2 = ~((int)&p1); + + p3 = &(t[(char)(&p1)]); + + p4 = &(tt[(char)(&p1)].a); + + p5 = &(ttt[(char)(&p1)][(char)&p2]); + + p6 = &(ttt[(char)(&p1)][u2]); + + p7 = &(ttt[u2][(char)(&p2)]); + + p8 = (&p1 + 1) < &p2; + + p9 = (int)&p1 / 2 ; + + p10 = 12 & ((int)&p1); + + if (u2 < 0) p11 = u2 & (-4); + + p12 = (int)&p1 & (int)(&p2); + + q1 = &p1; + p13 = *((char*)&q1)+2; + + p14 = *((char*)&q1)+2; + + tt[0].b = 3; + p15 = tt[0].b; + + t[1] = **((int**)(45)); + p16=2+*((int*)((char*)t+2)); + + { + int s,t ; + if ((u3 <= 15) && (u3 >= -10)) + s = u3; + else s = 0; + if ((u2 <= 100) && (u2 >= -150)) + t = u2; + else t = 0; + mm1 = (16+32*t) * (2+3*s); + mm2 = (4+32*t) * (16+96*s); + mm3 = (1+15*t) * (1+35*s); + quo6 = (2007+15*s) / (-5); + qu1 = (2007+15*s) / (20 + s); + qu2 = (7+15*s) / (20 + s); + ll1 = (long long)(5*s+3) + 0xFFFFFFFFL; + ll2 = (long long)(5*s+1) + 0x100000003L; + c1 = (int)ll1; + c2 = (int)ll2; + CEA_1(s); + //@ assert (s >= 0) || (s < 0) ; + square = s * s; + } + + u2 = 34; + u1 = u2 >> 2 ; + + 2[t]=3; + return (*(2+t)) + t[2]; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/addr2.i frama-c-20111001+nitrogen+dfsg/tests/misc/addr2.i --- frama-c-20110201+carbon+dfsg/tests/misc/addr2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/addr2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,29 @@ + +int x ; +int t[13] ; +extern void CEA_F(int ) ; +void main(void) +{ int i ; + + { + i = 0; // (&x+i)-&x; + { + { + { + while (1) { + if (i <= 12) { + + } else { + goto L; + } + CEA_F(i); + i += 1; + } + } + } + L: ; + } + + return; +} +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/addr.i frama-c-20111001+nitrogen+dfsg/tests/misc/addr.i --- frama-c-20110201+carbon+dfsg/tests/misc/addr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/addr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable +*/ + + +int t[5]; +int x; +int *p,*q; + +void f(int i) { +// x = t[i]; + p = t+i; +// q = &t[i]; +} + +void main () { + t[2] = 77; + f(2); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/addrofstring.c frama-c-20111001+nitrogen+dfsg/tests/misc/addrofstring.c --- frama-c-20110201+carbon+dfsg/tests/misc/addrofstring.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/addrofstring.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +/* run.config + +*/ + +int main() { + + // String literals are lvalues + char (*p)[4] = &("bar"); + //wchar_t (*q)[4] = &(L"foO"); // Does not work yet + + if((*p)[1] != 'a') return -1; + //if((*q)[1] != 'o') {}; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/affect_corrupt.i frama-c-20111001+nitrogen+dfsg/tests/misc/affect_corrupt.i --- frama-c-20110201+carbon+dfsg/tests/misc/affect_corrupt.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/affect_corrupt.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -absolute-valid-range 0-0x3 -journal-disable +*/ +int *p,r=77; +void main () { + r = *p; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ai_annot.i frama-c-20111001+nitrogen+dfsg/tests/misc/ai_annot.i --- frama-c-20110201+carbon+dfsg/tests/misc/ai_annot.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ai_annot.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + STDOPT: +"-remove-redundant-alarms" + */ + + +int u,v,w; + +int main(int x,int *p) { + /*@ assert x >=0; */ + /*@ assert \valid(p); */ + /*@ assert \valid(p+1); */ + *p=x; + + return x+*(p+1); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/alias.i frama-c-20111001+nitrogen+dfsg/tests/misc/alias.i --- frama-c-20110201+carbon+dfsg/tests/misc/alias.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/alias.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,302 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -no-results-function f + OPT: -memory-footprint 1 -val -deps -out -input -main main3 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main4 -absolute-valid-range 0-0xFF -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main5 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main6 -absolute-valid-range 0-0xFF -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main11 -absolute-valid-range 0-0xFF -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main8 -absolute-valid-range 0-0xFF -journal-disable + +*/ +void f(char*x,int*y) { + (*x)++; + *x++; + (*x)++; + (*y)++; +} + +void f2(char*x) { + char *q; + (*x)++; + q = x+1; + (*q)++; + Frama_C_dump_each(); +} + +int A,B,C,D,E,F,G; +int p[5] = {0,0}; +int q[5] = {1,2,3,4,5}; + +int p2[5] = {0,0}; +int q2[5] = {1,2,3,4,5}; + +int p3[5]; + +int t,u,v,w,x,y,z,t2,v2,*PTR1,*PTR2,*PTR3,*PTR4,*PTR5, *PTR6; + +volatile int c,c1,c2,c3,c4; + +void main (void) { + volatile vol=0; + + /* SECTION 1 */ + A=1; + B=2; + f(&A,&B); + f(&A,&A); + f(&p,&B); + + /* SECTION 2 */ + x = 1; + y = 2; + z = 3; + PTR1 = c1? &y : &x; + PTR2 = c2? &y : &z; + PTR3 = PTR1; + + *PTR1 = 4; + t = *PTR1; + *PTR2 = 5; + v = *PTR1; + u = *PTR2; + w = *PTR3; +/* x in {1,4} + && y in {2,4,5} + && t = 4 + && v in {4,5} + && u = 5 + && z in {3,5} +*/ + +/* SECTION 3 */ + PTR4 = c3? &(p2[1]) : &(q2[2]); + *PTR4 = 6; + t2 = *PTR4; + PTR4 [-1] = 7; + v2 = *(PTR4+(v2-v2-1)); +/* t2 = 6 + && v2 = 7 +*/ + + p3[1] = vol; + Frama_C_show_each_d0(p3[1]-vol); + p3[0] = 0; + Frama_C_show_each_d2(p3[1]-vol); +} + +struct S { int a; int b; int c; } e,g; + +void main3() +{ + struct S *p,*q,s1={2,4,6},s2={1,3,5}; + p = c?&s1:&s2; + p-> a = 7; + t = p->b; + + z = 2; + u = (c+1)?0:1; + v = u; + if (w==v) + { + z = u; + } + + + PTR1 = & ( p2 [(c+1)?0:((c+2)?1:2)] ); + PTR2 = PTR1+1; + *PTR1 = (c+10) ? 96 : (c+11) ? 97 : 98; + PTR3 = p2 + ((c+3)?1:((c+4)?2:4)); + *PTR3 = 99; + PTR4 = PTR3; + x = *PTR1; + if (PTR4==PTR2) + { + t2 = *PTR1; + v2 = PTR3 - PTR1; + } + else{ + L: goto L; + } +} + +struct T { struct S s1; struct S s2; struct S s3; struct S s4;} h,i; +void main4() +{ + struct S *p,s,ss,sss; + struct T *pt, + t1= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12}, + t2 ={21,22,23,24,25,26,27,28,29,30,31,32}; + p = c?&(t1.s2):&(t2.s3); + pt = c?(struct T*)(&(t1.s2)):(struct T*)(&(t2.s3)); + + p->a = 777; + s = *p; + + pt -> s1.b = 888; + sss = pt-> s1; + pt = (struct S*)0; + ss = pt->s1; + + + z = 1000; + u = (c+1)?0:((c+2)?1:2); + v = u+1; + x = (c+3)?1:((c+4)?2:5); + y = x; + if (y==v) + { + z = u - x; + } +} + +void main5() +{ + struct S *p,s,ss,sss; + struct T *pt, + t1= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12}, + t2 ={21,22,23,24,25,26,27,28,29,30,31,32}; + if(c) { + pt = (struct T*)(&(t1.s2)); + pt -> s1.b = 888; + } + else { + pt = (struct T*)(&(t2.s3)); + pt -> s1.b = 999; + } + + sss = pt-> s1; + + + z = 2; + u = (c+1)?0:1; + v = u; + if (v==w) + { + z = u; + } +} + + +void main6(void) +{ + int i = 0; + if (c) PTR1 = &p[1]; else PTR1 = &q[2]; + *PTR1 = 77; + for (; i<100; i++) + { + x = i; + } + y = *PTR1; + PTR2 = (int*) *PTR2; + if (PTR2 == (char*)PTR1) + z = *PTR2; + else + z = -33; + + u = c?0:1; + v = u; + w = v; + u = (c+1)?0:1; +} + + +int tz1,tz2,tz3,tx,ty,tz; +void main8(void) +{ + + tx = c?2:3; + ty = tx+1; + tz = ty+2; + + tz1 = tz==ty+2; + tz2 = tz==tx+3; + tz3 = tx==ty-1; + + A = c1 ? 3 : 4; + B = A + 1; + y = B == (A+1); + t = (B + 3) - (A - 1); + PTR1 = c2 ? &p[2] : &q[3]; + PTR2 = (int*)((unsigned int)PTR1 + 4); + PTR3 = PTR2 - 1; + u = *PTR2; + PTR1[1] = 44; + v = *PTR2; + w = *PTR1; + *PTR1 = 33; + x = *PTR1; + z = *PTR3; + + if (c3) + { + PTR4 = &q2[1]; + *PTR4 = 33; + PTR5 = PTR1; + } + else + { + PTR4 = &q2[2]; + *PTR4 = 44; + PTR5 = PTR1 + 1; + } + C = *PTR4; + D = *PTR5; +} + + + +union u { long long ll ; int i ; char c ; }; + +union u U; +char char1; +long long ll1; + +void main11(void) +{ + int i = 0; + + PTR3 = &p2[1]; + *PTR3 = 33; + while (c) + { + int * tm = &p2[2]; + *tm = *tm; + PTR3 = tm-1; + } + D = *PTR3; + + f2(p2); + + t = c2?0:1; + ll1 = (c2+1)?15:16; + U.ll = ll1 + 1; + if (c2+2) + U.i = t + 2; + else { L: goto L; } + + if (c) PTR1 = &p[1]; else PTR1 = &q[2]; + *PTR1 = 77; + for (; i<100; i++) + { + x = i; + } + y = *PTR1; + PTR2 = (int*) *PTR2; + if (PTR2 == (char*)PTR1) + z = *PTR2; + else + z = -33; + + PTR4 = &q2[1]; + *PTR4 = 33; + while (c1++) + { + PTR4 = &q2[1]; + *(PTR4-1) = 33; + } + A = *(PTR4 - 1); + B = A - q2[0]; +} + + + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/align_char_array.c frama-c-20111001+nitrogen+dfsg/tests/misc/align_char_array.c --- frama-c-20110201+carbon+dfsg/tests/misc/align_char_array.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/align_char_array.c 2011-10-10 08:39:03.000000000 +0000 @@ -1,8 +1,9 @@ /* run.config OPT: -memory-footprint 1 -val -cpp-command "gcc -C -E -DPTEST" -journal-disable - OPT: -memory-footprint 1 -machdep ppc_32_diab -val -cpp-command "gcc -C -E -DPTEST" -journal-disable */ +// removed : OPT: -memory-footprint 1 -machdep ppc_32_diab -val -cpp-command "gcc -C -E -DPTEST" -journal-disable + #ifndef PTEST #include <stdio.h> #endif diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/align.i frama-c-20111001+nitrogen+dfsg/tests/misc/align.i --- frama-c-20110201+carbon+dfsg/tests/misc/align.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/align.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,18 @@ +int c[5][10]; +void main() { + char * d; + d = (char*)c; + d[2] = 'z'; + ((char*)c[2])[1] = (char)'y'; + ((char*)c)[1] = (char)'y'; +// ((long long*)c[2])[2] = (char)'y'; +// ((char**)c)[1][0] = (char)'y'; // seg fault ! + + *c[0] = (int)'x'; + + int l; + int *pl = &l; + *pl = 0; + *((char*)pl)= 2; +// l = l & 0b11111111000000000; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/annot.i frama-c-20111001+nitrogen+dfsg/tests/misc/annot.i --- frama-c-20110201+carbon+dfsg/tests/misc/annot.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/annot.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,42 @@ + +int A, B, C; +int u, v, w; + +/*@ requires u == argf && v == 0; + assigns u, v, w \from u; + ensures u != \result; +*/ +int main(int argf, int en1, int en2, int en3, int en4) { + int x,y,z,t; + + x = 1; + /*@ assert x == 1+u; */ + Frama_C_show_each_diff(x - u); + /*@ requires y != 2; + @ ensures y == 2; + */ + y = 2; + /*@ assert y == 2; */ + z = 3; + + A = en1 ? 0 : 1; + B = en2 ? 0 : 2; + if (en3) + { + //@ assert A == 0 <==> A != 0 ; + Frama_C_show_each_then_A_B(A,B); + } + else if (en4) + { + //@ assert ! (A == 0 <==> B == A) ; + Frama_C_show_each_elseif_A_B(A,B); + } + else + { + //@ assert A == 0 <==> B == A ; + Frama_C_show_each_else_A_B(A,B); + } + + /*@ assert y == z; */ + return z; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/annot_valid.i frama-c-20111001+nitrogen+dfsg/tests/misc/annot_valid.i --- frama-c-20110201+carbon+dfsg/tests/misc/annot_valid.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/annot_valid.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,55 @@ +int G; +int main (int u) { + int * p = &G; + char *c = &G; + + switch (u) { + case 0: + //@ assert \valid(p); + break; + case 1: + //@ assert \valid(p+1); + break; + case 2: + //@ assert \valid((char*)p+1); + break; + case 3: + //@ assert \valid(c+1); + break; + case 4: + //@ assert \valid(c+3); + break; + case 5: + //@ assert \valid(c+4); + break; + case 6: + //@ assert (char *)p < c; + break; + case 7: + //@ assert p <= (int*)1; + break; + case 8: + //@ assert (int)p == 3; + break; + case 9: + //@ assert (int)p != 3; + break; + case 10: + //@ assert \exists int x ; x != 0 ==> *p == x; + break; + case 11: + //@ assert \forall int x ; \true; + break; + case 12: + //@ assert \valid((long long *)5); + break; + case 13: + //@ assert \valid(p); + break; + case 14: + //@ assert (\valid((char*)5)); + break; + } + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/anonymous_field.i frama-c-20111001+nitrogen+dfsg/tests/misc/anonymous_field.i --- frama-c-20110201+carbon+dfsg/tests/misc/anonymous_field.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/anonymous_field.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +struct { + int a ; + struct { + int gcc_a ; + int gcc_b ; + } ; + int b ; +} Sa ; + +//@ ensures Sa.gcc_a == Sa.a && Sa.gcc_b == Sa.b; +void set_anonymous_struct (void) { + Sa.gcc_a = Sa.a ; + Sa.gcc_b = Sa.b ; +} + +int main () { + Sa.a = 42; + Sa.b = 3; + set_anonymous_struct(); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/arch.i frama-c-20111001+nitrogen+dfsg/tests/misc/arch.i --- frama-c-20110201+carbon+dfsg/tests/misc/arch.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/arch.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +int a,b,c; +unsigned long l; +int t[10]; + +void main(void) +{ + l = (unsigned long)t; + a = sizeof(int); + b = sizeof(long); + c = sizeof(int*); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/arg_array.i frama-c-20111001+nitrogen+dfsg/tests/misc/arg_array.i --- frama-c-20110201+carbon+dfsg/tests/misc/arg_array.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/arg_array.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,8 @@ +void main(int *ptr, int T[4]) { + *T=0; + ptr = T; + ptr[1]=1; + 2[ptr] = 2; + T=T; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/array_bounds.i frama-c-20111001+nitrogen+dfsg/tests/misc/array_bounds.i --- frama-c-20110201+carbon+dfsg/tests/misc/array_bounds.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/array_bounds.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -unsafe-arrays -val -deps -out -input -journal-disable +*/ + +struct { int a; int T[5]; int b; } s = {1,0,1,2,3,4,5}; + +void main(int c) { + s.a = 9; + s.b = 9; + for(int i=0; i+5<=10; i++) {s.T[i] = c;} + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/array_degenerating_loop.i frama-c-20111001+nitrogen+dfsg/tests/misc/array_degenerating_loop.i --- frama-c-20110201+carbon+dfsg/tests/misc/array_degenerating_loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/array_degenerating_loop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +int t[100]={1,1}; + + +void main(int arg) +{ + int G=55; + int i; + for (i=0; i<=arg; i++) + G += t[i]; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/array_loop.i frama-c-20111001+nitrogen+dfsg/tests/misc/array_loop.i --- frama-c-20110201+carbon+dfsg/tests/misc/array_loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/array_loop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +int t[20]={17,18,19,20,21,22,23,24,1,1,1,1,1,1,1,1,1,1}; +int tt[20]={17,18,19,20,21,22,23,24,1,1,1,1,1,1,1,1,1,1}; + +void main(void) +{ + int i; + for (i=0; i<=15; i++) + t[i/2] = -i+tt[i]; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/array_overlap.i frama-c-20111001+nitrogen+dfsg/tests/misc/array_overlap.i --- frama-c-20110201+carbon+dfsg/tests/misc/array_overlap.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/array_overlap.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,20 @@ +char T[10]={1,1,1,2,2,3,0}; +char U[10]={1,1,1,2,2,3,0}; + +struct S { char t[6]; }; + + +void main (int c) { + + struct S* ptr; + ptr = &T[1]; + *ptr = *(struct S*)(&T[0]); + + {int i; + if (c) i = 0; else i = 1; + ptr = &U[i]; + *ptr = *(struct S*)(&U[0]); + + } + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/array_ptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/array_ptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/array_ptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/array_ptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +int G = 1; + +typedef int param_check[20]; + +int f(param_check **x) { + G=(**x)[0]; + (**x)[0] = 2; +} + +param_check l={1}; + +int main() { + int g = &l; + f(&g); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/array_zero_length.i frama-c-20111001+nitrogen+dfsg/tests/misc/array_zero_length.i --- frama-c-20110201+carbon+dfsg/tests/misc/array_zero_length.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/array_zero_length.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -lib-entry -main main -journal-disable +*/ + +char T[]; + +void main() { + T[2]= 3; + T[1] = T[3] +3; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/assert_ptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/assert_ptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/assert_ptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/assert_ptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +int *ptr, **q, s_q, a, r; + +int main(int c, int d, int e) +{ + q = &s_q; + if (c) ptr = &a; + if (d) *q = (&a + e) ; + /*@ assert ptr == 0 || ptr != 0 ; */ + Frama_C_show_each_ptr(ptr); + if (ptr != 0) (*ptr)++; + + /*@ assert *q != 0 ; */ + Frama_C_show_each_q(s_q); + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/assigns.i frama-c-20111001+nitrogen+dfsg/tests/misc/assigns.i --- frama-c-20110201+carbon+dfsg/tests/misc/assigns.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/assigns.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + OPT: -memory-footprint 1 -journal-disable -main F2 -lib-entry -out +*/ + +int G; + +//@ assigns s[..]; +void F1(char *s); + +char T[100]; + +void F2(int c) +{ + if (c) F1(T); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/automalloc.i frama-c-20111001+nitrogen+dfsg/tests/misc/automalloc.i --- frama-c-20110201+carbon+dfsg/tests/misc/automalloc.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/automalloc.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +typedef unsigned int size_t; +void*malloc(size_t s); +void*realloc(void*ptr,size_t s); +void*alloca(size_t s); +void free (void * ptr); +void*calloc (size_t nmemb, size_t size); + +void main(int test) { + char * buf=0; + if (test) buf = (char*)malloc(sizeof(char)*5); + else buf = (char*)realloc(&test,sizeof(char)*6); + + if (test) buf[1] = 16; + + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bad_loop.i frama-c-20111001+nitrogen+dfsg/tests/misc/bad_loop.i --- frama-c-20110201+carbon+dfsg/tests/misc/bad_loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bad_loop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +volatile int c; +void main () { + int x; volatile int d=0,e=0; + x = 2; + + while(1) { + L1: if (c) goto FIN; + if (d) goto L2; + x = 0; + } + + while (1) { + L2: if (c) break; + if (e) goto L1; + x=1; + } + + FIN: ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/behavior_names.i frama-c-20111001+nitrogen+dfsg/tests/misc/behavior_names.i --- frama-c-20110201+carbon+dfsg/tests/misc/behavior_names.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/behavior_names.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + OPT: -load-script tests/misc/behavior_names.ml +*/ + +/*@ behavior foo: ensures \true; */ +void f () { + int x = 0; + /*@ behavior bar: ensures \true; */ + x++; + if (x) { /*@ behavior bli: ensures \true; */ x++; } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bigarray.c frama-c-20111001+nitrogen+dfsg/tests/misc/bigarray.c --- frama-c-20110201+carbon+dfsg/tests/misc/bigarray.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bigarray.c 2011-10-10 08:39:03.000000000 +0000 @@ -2,9 +2,9 @@ const int T[SIZE]={2,3}; const char*S = "uututututututu"; -int main() { +int main(int c) { int i; - *(char*)S = 'E'; + if (c) *(char*)S = 'E'; for(i=0; i < SIZE/4; i++) *(int*)&T[i] = 1; for(i=0; i< SIZE/8; i++) diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bitfield_assign.i frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield_assign.i --- frama-c-20110201+carbon+dfsg/tests/misc/bitfield_assign.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield_assign.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,36 @@ +int g_18; + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef short int16_t; +typedef long long int64_t; + +struct S0 { + uint32_t f0; + int16_t f1; + signed f2 : 26; + int64_t f3; +}; + +union U3 { + signed f0 : 7; + int32_t f1; + int32_t f2; + struct S0 f3; +}; + +static union U3 g_7[1] = {{0x00868BB4L}}; + +int g_5; +int g_2; + +void Frama_C_show_each(unsigned); + +main(){ + unsigned short l_8 = 1UL; + unsigned int l_16 = 0xBD4AA41AL; + + g_2 |= (g_7[g_5].f3.f2 = l_16); + Frama_C_show_each(g_2); +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bitfield.i frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield.i --- frama-c-20110201+carbon+dfsg/tests/misc/bitfield.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,68 @@ +struct t1 { unsigned int a:2; int b:4; int c:22;int d:32;} h; +struct t2 { unsigned int a:2; int b:4; int c:22; int d;} k,k8,kr8; + +struct t3 { int b:16; } ll; + +struct t1 ini = { 14, -55, 99999 } ; + +unsigned int VV=55; + +unsigned short q4 = 40000; + +int X; + +void f(int x) +{ + X=x; + Frama_C_dump_each(); +} + +int return_8(void) +{ + return 8; +} + +struct S { unsigned f:32; signed sf:32; } x = { 28349, 28349}; +unsigned short us = 0xDC23L; +int G,H; +int g(void) { + int r = (x.f ^ ((short)-87)) >= us; + H = (x.sf ^ ((short)-87)) >= us ; + return r; +} + +union U1 { + int f0 ; + int f1 : 15 ; +}; + +int main (int a, int b){ + struct t1 v,w; + + union U1 l_161; + l_161.f0 = (int)-1L; + Frama_C_show_each(1); + if ((!l_161.f0) <= l_161.f1) + Frama_C_show_each(2); + else + Frama_C_show_each(3); + + VV = h.a; + + h.a = VV; + + v.c = &v; + v.d = &v + 1; + v.d = v.d + 1; + v.a = 4; + v.b = 7; + f(v.b); + h.b = a+b + h.a + h.b; + h.c = &v +1; + + k8.b = 8; + kr8.b = return_8(); + + ll.b = q4; + G=g(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bitfield_longlong.c frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield_longlong.c --- frama-c-20110201+carbon+dfsg/tests/misc/bitfield_longlong.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield_longlong.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,33 @@ +/* run.config + OPT: -memory-footprint 1 -val -cpp-command "gcc -C -E -Dprintf=Frama_C_show_each" -journal-disable +*/ +struct X50 { + long long int z:50; +} s50 = { 2 }; + +struct X10 { + long long int z:10; +} s10 = { 2 }; + + +struct U32 { + unsigned long z:32; +} u32 = { -1 }; + +struct S32 { + signed long z:32; +} s32 = { -1 }; + + +int main() { + int x = u32.z >=0; + int y = s32.z >=0; + printf("%zu %zu %zu %zu\n", + sizeof(long long int), + sizeof(s10.z+0), + sizeof(s50.z+0), + sizeof(u32.z+0) + ); + printf("%d %d\n", x, y); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bitfield_receives_result.i frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield_receives_result.i --- frama-c-20110201+carbon+dfsg/tests/misc/bitfield_receives_result.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bitfield_receives_result.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +struct S { int b:31; } s; + +int f(void) +{ + return -1; +} + +main(){ + s.b = f(); + Frama_C_dump_each(); +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bitwise_or.i frama-c-20111001+nitrogen+dfsg/tests/misc/bitwise_or.i --- frama-c-20110201+carbon+dfsg/tests/misc/bitwise_or.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bitwise_or.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,26 @@ +/* run.config + OPT: -memory-footprint 1 -val -journal-disable share/builtin.c +*/ +#include "../../share/builtin.h" + +int or1, or2, or3, or4, or5; +int and1, and2, and3, and4, and5; +unsigned int uand1, uand2, uand3, uand4, uand5; +int a,b,c,d,e; + +main(){ + a = Frama_C_interval(3,17); + b = Frama_C_interval(-3,17); + c = Frama_C_interval(13,27); + or1 = a | b; + or2 = a | c; + or3 = b | c; + + and1 = a & b; + and2 = a & c; + and3 = b & c; + + uand4 = 0xFFFFFFF8U & (unsigned int) c; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bitwise_pointer.i frama-c-20111001+nitrogen+dfsg/tests/misc/bitwise_pointer.i --- frama-c-20110201+carbon+dfsg/tests/misc/bitwise_pointer.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bitwise_pointer.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,25 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -inout -journal-disable +*/ + +char t[100]={0,1,2,3,4,5,6,7,8,9}; +char *p; +int x; + +char t1[100]={0,1,2,3,4,5,6,7,8,9}; +char *p1; +int x1; + +void main(void) +{ + int mask = 7; + + p = (char*)(((int)(t + 7)) & ~7); + *p = 5; + x = *p; + + p1 = (char*)(((int)(t1 + mask)) & ~mask); + *p1 = 5; + x1 = *p1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/biz.i frama-c-20111001+nitrogen+dfsg/tests/misc/biz.i --- frama-c-20110201+carbon+dfsg/tests/misc/biz.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/biz.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f2 -journal-disable +*/ + +int *p, *q, G = 0; + +void f2() { + p = &G; + *(((char*)p)++) = 3; // specific test for biz.c:5: error: invalid lvalue in increment +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bool.c frama-c-20111001+nitrogen+dfsg/tests/misc/bool.c --- frama-c-20110201+carbon+dfsg/tests/misc/bool.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bool.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -#include<stdbool.h> -bool x; -int y; - -int main() { - x=false; - printf("%d\n",x); - x=2; - printf("%d\n",x); - y=x+1; - printf("%d,%d\n",x,y); - x=x+1; - printf("%d\n",x); - x=x+1; - printf("%d\n",x); - return y; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bool.i frama-c-20111001+nitrogen+dfsg/tests/misc/bool.i --- frama-c-20110201+carbon+dfsg/tests/misc/bool.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bool.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + STDOPT: +"-print" +*/ +_Bool x; +int y; + +int main() { + x=0; + printf("%d\n",x); + x=2; + printf("%d\n",x); + y=x+1; + printf("%d,%d\n",x,y); + x=x+1; + printf("%d\n",x); + x=x+1; + printf("%d\n",x); + return y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/branch2.i frama-c-20111001+nitrogen+dfsg/tests/misc/branch2.i --- frama-c-20110201+carbon+dfsg/tests/misc/branch2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/branch2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ + unsigned short i; + unsigned short etat_to; + signed short changepage; + int plein,NumFonct,NumSsPage; +void main(void) +{ + + + plein = 1; + /* 0 */ if(changepage != 0) + { + NumFonct = 0 ; + } else {} + while ( NumSsPage <= 0 ) + { + NumSsPage = NumSsPage + (unsigned short)9; + } + + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/branch.i frama-c-20111001+nitrogen+dfsg/tests/misc/branch.i --- frama-c-20110201+carbon+dfsg/tests/misc/branch.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/branch.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +int a, b,c,d,e; +void main() +{ + L: a=0; + if (c) goto L2; + L3: b=0; + goto L; + L2: d=0; + if (d) goto L; + if (e) goto L4; + goto L3; + L4: return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/broken_loop.i frama-c-20111001+nitrogen+dfsg/tests/misc/broken_loop.i --- frama-c-20110201+carbon+dfsg/tests/misc/broken_loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/broken_loop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main loop -journal-disable +*/ +int X; + +void loop(int d) { + + if(d) ; else ; + goto L; + X=0; + if(d) X=1; else L:; + X=2; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0442-2.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0442-2.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0442-2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0442-2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ +/* run.config +OPT: -print -check tests/misc/bts0442.i +*/ +enum E { E0=0, E1=1} ve1=E1; +void f (void) { + ve1=E0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0442.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0442.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0442.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0442.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,4 @@ +/* run.config +OPT: -print -check tests/misc/bts0442-2.i +*/ +enum E { E1=1, E2=2} ve2=E2; diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0451.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0451.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0451.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0451.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,28 @@ +/* run.config + COMMENT: running this test fails on purpose + OPT: -simplify-cfg -typecheck + */ + +/* small test cases to verify that break is accepted in while and switch */ +int f () { + + while (1) { + if (0) { + while (1) break; + } + switch (3) { + case 0: return 5; + default: + if (1) break; else break; + } + break; + } + + return 0; +} + +/* should abort with an error at type-checking */ +int main (void) { + break; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0452.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0452.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0452.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0452.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,88 @@ +/* run.config + OPT: -typecheck -load-script tests/misc/bts0452.ml +*/ + +/* must emit falls-through warning. */ +int f (int foo, char** args) { + switch(foo) { + case 1: + return 0; + break; + + default: + if (foo) return 1; + } +} + +/* must emit falls-through warning. */ +int h (int foo, char** args) { + switch(foo) { + case 1: + return 0; + break; + + default: + { if (foo) goto L ; + return 1; + L: break; } + } +} + +/* must NOT emit falls-through warning. */ + +int g (int foo, char** args) { + switch(foo) { + case 1: + return 0; + break; + + default: + if (foo) return 1; else return 2; + } +} + +/* must NOT emit falls-through warning. */ +int k (int foo, char** args) { + switch(foo) { + case 1: + return 0; + break; + + default: + { goto L ; + break; + L: return 0; } + } +} + +/* must NOT emit falls-through warning. */ +int l (int foo, char** args) { + switch(foo) { + case 1: + return 0; + break; + + default: + { L: goto L ; + break; + } + } +} + +/* must NOT emit falls-through warning */ +int main (int foo, char** args) { + switch(foo) { + case 1: + return 0; + break; + + default: + return 1; + } +} + +/* must NOT emit falls-through warning */ +int m (int foo, char** args) { + if (foo >= 0 && foo <=10) { return 0; } else { return 1; } + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0489.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0489.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0489.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0489.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,109 @@ +/* run.config + OPT: -load-script tests/misc/bts0489.ml +*/ + +typedef unsigned int uint8_t; +typedef int int8_t; +typedef unsigned int uint16_t; +typedef int int16_t; +typedef int int32_t; +typedef unsigned int uint32_t; + +void foo1(uint8_t x) {}; + +int16_t t1(void) +{ + uint8_t u8a, u8b, u8c; + int8_t s8a, s8b; + uint16_t u16a; + int16_t s16a; + int32_t s32a; + float f32a; + double f64a; + foo1(u8a); /* compliant */ + foo1(u8a + u8b); /* compliant */ + foo1(s8a); /* not compliant */ + foo1(u16a); /* not compliant */ + foo1(2); /* not compliant */ + foo1(2U); /* compliant */ + foo1((uint8_t)2); /* compliant */ + /*... s8a + u8a /* not compliant */ + /*... s8a + (int8_t)u8a /* compliant */ + s8b = u8a; /* not compliant */ + /*... u8a + 5 /* not compliant */ + /*... u8a + 5U /* compliant */ + /*... u8a + (uint8_t)5 /* compliant */ + u8a = u16a; /* not compliant */ + u8a = (uint8_t)u16a; /* compliant */ + u8a = 5UL; /* not compliant */ + /*... u8a + 10UL /* compliant */ + u8a = 5U; /* compliant */ + /*... u8a + 3 /* not compliant */ + /*... u8a >> 3 /* compliant */ + /*... u8a >> 3U /* compliant */ + + /*... s32a + 80000 /* compliant */ + /*... s32a + 80000L /* compliant */ + f32a = f64a; /* not compliant */ + f32a = 2.5; /* not compliant - + unsuffixed floating + constants are of type + double */ + u8a = u8b + u8c; /* compliant */ + s16a = u8b + u8b; /* not compliant */ + s32a = u8b + u8c; /* not compliant */ + f32a = 2.5F; /* compliant */ + u8a = f32a; /* not compliant */ + s32a = 1.0; /* not compliant */ + s32a = u8b + u8c; /* not compliant */ + f32a = 2.5F; /* compliant */ + u8a = f32a; /* not compliant */ + s32a = 1.0; /* not compliant */ + f32a = 1; /* not compliant */ + f32a = s16a; /* not compliant */ + /*... f32a + 1 /* not compliant */ + /*... f64a * s32a /* not compliant */ + /*...*/ + return (s32a); /* not compliant */ + /*...*/ + return (s16a); /* compliant */ + /*...*/ + return (20000); /* compliant */ + /*...*/ + return (20000L); /* not compliant */ + /*...*/ + return (s8a); /* not compliant */ + /*...*/ + return (u16a); /* not compliant */ +}; + +int16_t foo2(void) +{ + uint8_t u8a, u8b; + int8_t s8a; + uint16_t u16a,u16b; + int16_t s16a,s16b; + int32_t s32a,s32b; + uint32_t u32a; + float f32a,f32b; + double f64a,f64b ; + + /*... (u16a + u16b) + u32a /* not compliant */ + /*... s32a + s8a + s8b /* compliant */ + /*... s8a + s8b + s32a /* not compliant */ + f64a = f32a + f32b; /* not compliant */ + f64a = f64b + f32a; /* compliant */ + f64a = s32a / s32b; /* not compliant */ + u32a = u16a + u16a; /* not compliant */ + s16a = s8a; /* compliant */ + s16a = s16b + 20000; /* compliant */ + s32a = s16a + 20000; /* not compliant */ + s32a = s16a + (int32_t)20000; /* compliant */ + u16a = u16b + u8a; /* compliant */ + foo1(u16a); /* not compliant */ + foo1(u8a + u8b); /* compliant */ + /*...*/ + return s16a; /* compliant */ + /*...*/ + return s8a; /* not compliant */ +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0489.ml frama-c-20111001+nitrogen+dfsg/tests/misc/bts0489.ml --- frama-c-20110201+carbon+dfsg/tests/misc/bts0489.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0489.ml 2011-10-10 08:39:03.000000000 +0000 @@ -8,7 +8,7 @@ | Const(CInt64 (_,_,Some s)) -> Format.printf "Found representation %s@." s; Cil.SkipChildren | Const(CInt64(n,_,None)) -> - Format.printf "No representation for %s@." (Int64.to_string n); + Format.printf "No representation for %s@." (My_bigint.to_string n); Cil.SkipChildren | _ -> Cil.DoChildren end diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0506.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0506.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0506.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0506.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/*run.config +STDOPT: +"-no-collapse-call-cast" +"-print" +STDOPT: +"-collapse-call-cast" +"-print" +*/ + +int f(int x) { return x+1; } + +int main () { + short x = 4; + x = f(42); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0525-2.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0525-2.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0525-2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0525-2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + OPT: -typecheck -check tests/misc/bts0525.i +*/ + +typedef enum {E1=2, E2} T_EN1 ; + +int f2(T_EN1 p2) +{ + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0525.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0525.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0525.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0525.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + OPT: -check tests/misc/bts0525-2.i +*/ +typedef enum {E3=2, E4} T_EN2 ; +typedef enum {E1=2, E2} T_EN1 ; + +int f1(T_EN1 p1) +{ + if (p1==E1) return 1; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0577.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0577.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0577.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0577.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +/*run.config +OPT: -print +*/ +typedef enum { E1_a, E1_b, E1_c } E1; +typedef enum { E2_a = E1_a, E2_b } E2; +int f (E2 e) { return e; } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0588.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0588.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0588.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0588.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +/* run.config + OPT: -print -check +*/ + +//@ requires x>=0; +void g(int x); + +void g(int a) { + return; +} + +void f(int a){ a=1;} +//@ ensures x>0; +void f(int x); diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0769.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0769.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0769.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0769.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + OPT: -print -check +*/ + +struct s { + struct {int ui;} _; + union foo { int ii; }; +} S; + +int main(){ + return S._.ui + S.ii; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0775.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0775.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0775.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0775.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,4 @@ +main(){ + int r = 0xE2DB80EBBD4856CDLL >= 1; + return r; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0858.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts0858.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts0858.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0858.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +typedef long int64_t; +typedef unsigned long uint64_t; + + +int main() { + uint64_t tmp = 18446744073709551615UL ; + if (0xffffffffUL == tmp) + return 1; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts0916.c frama-c-20111001+nitrogen+dfsg/tests/misc/bts0916.c --- frama-c-20110201+carbon+dfsg/tests/misc/bts0916.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts0916.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + OPT: -keep-comments -print +*/ +/* Use frama-c with option -keep-comments */ + +void main() { + int port=10; + + while (port-->0) // ( port & 0x80 ) == 0 ) + { + ; /* wait for pin1 - Compliant*/ + /* wait for pin2 */ ; /* Not compliant/*, comment before ; */ + ;/* wait for pin3 - Not compliant, no white-space char after ; */ + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bts59.i frama-c-20111001+nitrogen+dfsg/tests/misc/bts59.i --- frama-c-20110201+carbon+dfsg/tests/misc/bts59.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bts59.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +/*run.config + OPT: -print -journal-disable + */ +float g() +{ + double __retres=2; + int first = 6; + + { int first = 5 ; + return __retres; + } + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/buffer_overflow.i frama-c-20111001+nitrogen+dfsg/tests/misc/buffer_overflow.i --- frama-c-20110201+carbon+dfsg/tests/misc/buffer_overflow.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/buffer_overflow.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,24 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -ulevel 15 -journal-disable +*/ +int main(int argc, char *argv[]) +{ + int test_value; + int loop_counter; + char buf[10]; + + test_value = 17; + + loop_counter = 0; + while(++loop_counter) + { + /* BAD */ + buf[loop_counter] = 'A'; + if (loop_counter >= test_value) break; + } + + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bug0223.i frama-c-20111001+nitrogen+dfsg/tests/misc/bug0223.i --- frama-c-20110201+carbon+dfsg/tests/misc/bug0223.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bug0223.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,36 @@ +/* run.config +STDOPT: +"-unspecified-access" +STDOPT: +"-no-unspecified-access" +*/ + +// No warning should be raised: we can syntactically ensure that +// the order of evaluation of expressions does not matter here. + +extern int F(int, int); + +extern int my_strcnmp(const char * const s1, const char * const s2, int +n); +extern char *ch1, *ch2; +void h2(void) { + int test; + test = (my_strcnmp(&ch1[3],&ch2[3],12) == 0) ; +} + +extern unsigned char get(unsigned int); + +extern void set(unsigned int *); + +void ptr_deref(unsigned int * const ui) { + unsigned int s=0; + set(&s); + *ui+=get(s) ; +} + +void main() +{ + int i=0, j=0, k=0, l; + int *p = &j; + l = (F(i,j) == k); + *p = (F(*p,j) == k); + h2(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bug_023.i frama-c-20111001+nitrogen+dfsg/tests/misc/bug_023.i --- frama-c-20110201+carbon+dfsg/tests/misc/bug_023.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bug_023.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +int i; +int x; + +int f(); + +int main() { + if (i == 0 || i == 1) { + i += f(); + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bug_0244.i frama-c-20111001+nitrogen+dfsg/tests/misc/bug_0244.i --- frama-c-20110201+carbon+dfsg/tests/misc/bug_0244.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bug_0244.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +int R,*p; + +void main(void) +{ + int a,i; + a=2; + for(i=0; i<2; i++) + { + int u=a; + p = &u; + } + R = *p; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bug0245.i frama-c-20111001+nitrogen+dfsg/tests/misc/bug0245.i --- frama-c-20110201+carbon+dfsg/tests/misc/bug0245.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bug0245.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,26 @@ +/* run.config + STDOPT: +"-slevel 3" +*/ +int R,*p,S,*q; + +void main(int c, int d) +{ + int a,i; + a=2; + p = q = &a; + for(i=0; i<2; i++) + { + int u=a; + p = &u; + toto: + { + int v; + v = 3; + v++; + q = &v; + } + } + if (c) R = *p; + if (d) S = *q; + //if (a-a) goto toto; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bug0277.i frama-c-20111001+nitrogen+dfsg/tests/misc/bug0277.i --- frama-c-20110201+carbon+dfsg/tests/misc/bug0277.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bug0277.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +/* run.config + OPT: -typecheck + */ +typedef enum { + DGI_ID_NB = 56 +} T_DGI_ID; + + + +const int T[DGI_ID_NB] = { 3 } ; + + + +/*@ + +requires P : T[0]==3 + ; + + +*/ +void main() ; diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/bug.i frama-c-20111001+nitrogen+dfsg/tests/misc/bug.i --- frama-c-20110201+carbon+dfsg/tests/misc/bug.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/bug.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable +*/ + +void f(unsigned short typemess) +{ + + unsigned short i; + unsigned short nbpompe; + unsigned short bitx; + + if (typemess == (unsigned short)0 ) + { + + goto L; + + goto L; + } + L:; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call_2.i frama-c-20111001+nitrogen+dfsg/tests/misc/call_2.i --- frama-c-20110201+carbon+dfsg/tests/misc/call_2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call_2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,30 @@ +int G = 0; +int H; + +int f (int x) { + G = x; + return 0; +} + +int i_auCyc () { + f(0); + G=17; + if (H) f(2); + else f(5); + f(6); + return 0; +} + +extern void fp (int*p); + +int G,x; +void main() { + x = 1; + G = 0; + while (x) { + G ++; + } + + +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call_3.i frama-c-20111001+nitrogen+dfsg/tests/misc/call_3.i --- frama-c-20110201+carbon+dfsg/tests/misc/call_3.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call_3.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,18 @@ +int GG; + +int f (void) +{ int G; + G = 2; + GG = 3; + return 1; } + + +int main (void) +{ int lm = 77; + + int res_f = f(); + GG = lm; + + return 0; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call_alias.i frama-c-20111001+nitrogen+dfsg/tests/misc/call_alias.i --- frama-c-20110201+carbon+dfsg/tests/misc/call_alias.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call_alias.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,34 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main main0 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main2 -journal-disable +*/ + +int X,c,u,v,w,G; + +int incr(int* a,int* b) { + (*a)++; + (*b)++; + return *a+*b; +} + + +int sum(int a,int b) { + return a+b; +} + +int G=0,H=0,I=0; +int main0 () { + I=incr(&G,&H); + return I; +} + +int main1 () { + I=incr(&G,&G); + return I; +} + +int main2() { + I = sum(G,H); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call_deep.i frama-c-20111001+nitrogen+dfsg/tests/misc/call_deep.i --- frama-c-20110201+carbon+dfsg/tests/misc/call_deep.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call_deep.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,35 @@ +int R=77; +int G; +int* pG; +int F0; +int f0(int *p0) { + F0 = R; + *p0 = R; + return R; +} + +int F1; + +int f1(int**pp1) { + F1 = R; + **pp1 = R; + *pp1 = pG; + f0(pG); + return **pp1; +} + +int H,XX; +int Fmain; + +#pragma no_return ("Pre a : H==0;") +int main() { + int *ph; + int **pph; + pG = &G; + ph = &H; + pph = &ph; + Fmain = f1(pph); + XX=0; + return 0; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call.i frama-c-20111001+nitrogen+dfsg/tests/misc/call.i --- frama-c-20110201+carbon+dfsg/tests/misc/call.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,64 @@ +int p[10],q[10]; +int *r; + +int res; + +void f(int*t) { + res = *(t+5); +} + +void leaf_fun_int(int x); +void leaf_fun_charp(char* x); + +/* @ + @ assigns \result , p[c] \from p[c..(c+3)], p[*], p[2]; + @ assigns q[5] \from p[1], c ; + @*/ +void main(int c, char **v) +{ + if (c&1) leaf_fun_int(v[2]); + if (c&2) leaf_fun_char(v[2]); + int lcount= 0; + res= 1111; + for (lcount=0; lcount<=6; lcount++) + { + p[lcount]=lcount; + q[lcount]=lcount+10;}; + + p[5] = 177; + q[5] = 188; + + int *tmp ; + { + if (c&4) { + tmp = p; + } else { + tmp = q; + } + + f(tmp); // t --> deps(tmp) + + } +} + +struct A {int a; int b;} x; + +void f_struct(struct A y) { + res = y.b; +} + +void caller_struct() { + struct A z = res?x:x; + f_struct(z); + +} + + +void f_ptr(int*X) { + res = *X; +} +void caller_ptr() { + int * e = res?&x.a:&x.b; + f_ptr(e); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call_multi.i frama-c-20111001+nitrogen+dfsg/tests/misc/call_multi.i --- frama-c-20110201+carbon+dfsg/tests/misc/call_multi.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call_multi.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,30 @@ +/* run.config + STDOPT: +"-unspecified-access" +*/ +int uppol2(int al1,int al2,int plt,int plt1,int plt2) +{ + long int wd2,wd4; + int apl2; + + wd2 = 4L*(long)al1; + if((long)plt*plt1 >= 0L) wd2 = -wd2; /* check same sign */ /* CONDITION */ + wd2 = wd2 >> 7; /* gain of 1/128 */ +// CEA_TEST(plt,plt2,(long)plt*plt2>= 0L); + if((long)plt*plt2 >= 0L) { /* CONDITION */ + wd4 = wd2 + 128; /* same sign case */ + } + else { + wd4 = wd2 - 128; + } + apl2 = wd4 + (127L*(long)al2 >> 7L); /* leak factor of 127/128 */ + printf("GOT:%d\n",wd4); + return(apl2); +} + +int G; +void main() { + G += uppol2(0,0,0,0,0); + G += uppol2(0,0,-1,1,0); + G += uppol2(0,0,-1,2,2); + G += uppol2(0,0,0,3,0); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/call_simple.i frama-c-20111001+nitrogen+dfsg/tests/misc/call_simple.i --- frama-c-20110201+carbon+dfsg/tests/misc/call_simple.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/call_simple.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,17 @@ +int X,c,u,v,w,G; + +void f(int* a,int b,int c) { + int *i=a; + *i = 0; + a = 0; + X = a+b+c; +} + +int main (int ll) { + u = 3; + v = G; + w = 17; + f(&u,v,w); + c = ll++; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/callsite.i frama-c-20111001+nitrogen+dfsg/tests/misc/callsite.i --- frama-c-20110201+carbon+dfsg/tests/misc/callsite.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/callsite.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,35 @@ +/* run.config + OPT: -debug 1 -load-script tests/misc/callsite.ml + */ + +void f(void); +void g(void); +void h(void); +void k(void); + +void f(void) +{ + g(); + h(); + g(); +} + +void g(void) +{ + h(); + k(); + h(); +} + +void h(void) +{ + k(); + k(); +} + +// Should have 8 call sites: +// CallSites of f : - +// CallSites of g : From f(2) +// CallSites of h : From f(1) + From g (2) +// CallSites of k : From g(1) + From h (2) + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/callsite.ml frama-c-20111001+nitrogen+dfsg/tests/misc/callsite.ml --- frama-c-20110201+carbon+dfsg/tests/misc/callsite.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/callsite.ml 2011-10-10 08:39:03.000000000 +0000 @@ -3,8 +3,9 @@ let dump f = let kf = Globals.Functions.find_by_name f in let csites = Kernel_function.find_syntactic_callsites kf in - Log.print_on_output "Call Sites for %s:@\n%t" f + Log.print_on_output (fun fmt -> + Format.fprintf fmt "Call Sites for %s:@\n" f ; List.iter (fun (ckf,stmt) -> Format.fprintf fmt " - From %s at #%03d@\n" diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/case_analysis.i frama-c-20111001+nitrogen+dfsg/tests/misc/case_analysis.i --- frama-c-20110201+carbon+dfsg/tests/misc/case_analysis.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/case_analysis.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + OPT: -memory-footprint 1 -val -slevel 30 -journal-disable -float-normal + OPT: -memory-footprint 1 -val -slevel 30 -journal-disable -float-normal -all-rounding-modes +*/ + +int sq,s; + +float rq,r; + +void main(int c) +{ + s = (c >= -10) ? ((c <= 10) ? c : 0) : 0; + r = s; + //@ assert s >= 0 || s < 0 ; + sq = s * s; + + //@ assert r >= 0.0 || r < 0.0 ; + rq = r * r; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cast1.i frama-c-20111001+nitrogen+dfsg/tests/misc/cast1.i --- frama-c-20110201+carbon+dfsg/tests/misc/cast1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cast1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,28 @@ +short si=0; +int i=0; +int S[5]={1}; +int I[5]={1}; + +void main(void) { + for (si=0;si<2;si++) S[i]=2; + for (i=0;i<2;i++) I[i]=2; +} + + +void with_if () +{ + long x; + short si=x?0:2; + + if ((unsigned short)si < 2) x=si; else x=3; + +} + +void with_if2 () +{ + long x; + short si=x?0:4; + + if ((signed short)si < 2) x=si; else x=3; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cast2.i frama-c-20111001+nitrogen+dfsg/tests/misc/cast2.i --- frama-c-20110201+carbon+dfsg/tests/misc/cast2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cast2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main g -journal-disable +*/ + +extern int any_int(void); + +void g() { + int t; + unsigned int G; + t = any_int(); + G = t; + t = t+1; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cast3.i frama-c-20111001+nitrogen+dfsg/tests/misc/cast3.i --- frama-c-20110201+carbon+dfsg/tests/misc/cast3.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cast3.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ +unsigned char G = (unsigned char)(-1); + +void main (void) { + G = -255; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cast_hetero.i frama-c-20111001+nitrogen+dfsg/tests/misc/cast_hetero.i --- frama-c-20110201+carbon+dfsg/tests/misc/cast_hetero.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cast_hetero.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,17 @@ +int X; +int*pt; +void f(int c) { + pt = &X; + *pt = c; +} + +int T[10]={0}; + +void g(int c){ + pt = &X; + T[X] = c; +} + +void main() { + g(1); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cast.i frama-c-20111001+nitrogen+dfsg/tests/misc/cast.i --- frama-c-20110201+carbon+dfsg/tests/misc/cast.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cast.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,78 @@ +char * X= "NULL"; +void MC3_COM_ARRET_68040(int i , char *c, int j) { + X = c; +} + +static void MC3_ANALYSER_CPTRENDU(int n , char num_station , + short cptrendu ) +{ + + MC3_COM_ARRET_68040(160, (char *)"mc3_mdb_emi_act.c", 506); + +} + + +int G,H,K,L,i,b; +unsigned int I; +signed char c,d,e; +unsigned char uc,ud; +long long ll,gg; +unsigned long long ull, ugg; + + +int any_int(void) +{ volatile int i = 0; + int j; + i =(int*)0 + i; + return (i/4);}; + +void all_cast() { + G=258; + H=any_int(); + + if (H>=258) {if (H<=268) {G = H;};}; + G = G&128?0xFFFFFF00|(G&255):(G&255); + G = (signed char)G; // 2..12 + + K=-10; + if (H>=-10) {if (H<=20) {K = H;};}; + c = (signed char)(K); // -10..20 + uc = c ; // (signed char)(K); // 0..255 + + K = c; + I = (unsigned int)(signed char)(int)(-1); + printf("%ud\n",I); + + L=-19; + if (H>=-2000) {if (H<=-10) {L = H;}} + d = L; // top + ull=1; + L=0; + if (H>=-2000) {if (H<=1) {L = 2*H;}} + e = L; // top + +} + +int main(void) +{ + int min = 130; + int max = 135; + int i; + int G; + for (i=min; i<=max; i++) + { + G = i&128?0xFFFFFF00|(i&255):(i&255); + printf("cast:%d formule:%d\n",(int)(signed char) i,G); + } + printf("usc: %ud",(unsigned int)(signed char)(int)(-1)); +} + + +void f() { + G=258; + if (H>=258) {if (H<=268) {G = H;};}; + I = (unsigned char)G; // = 2..12 + +} + +//int main(){all_cast();} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cert_exp35_c.i frama-c-20111001+nitrogen+dfsg/tests/misc/cert_exp35_c.i --- frama-c-20110201+carbon+dfsg/tests/misc/cert_exp35_c.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cert_exp35_c.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,34 @@ +struct X { char a[6]; }; + +struct X addressee(void) { + struct X result = { "world" }; + return result; +} + +int main(void) { + printf("Hello, %s!\n", addressee().a); + return 0; +} + +/* +From https://www.securecoding.cert.org/confluence/display/seccode/EXP35-C.+Do+not+access+or+modify+an+array+in+the+result+of+a+function+call+after+a+subsequent+sequence+point + +This solution is problematic because of three inherent properties of C: + +In C, the lifetime of a return value ends at the next sequence point. +Consequently by the time printf() is called, the struct returned by +the addressee() call is no longer considered valid, and may have been +overwritten. +C function arguments are passed by value. As a result, copies are made +of all objects generated by the arguments. For example, a copy is made of the +pointer to "Hello, %s!\n". Under most circumstances, these copies protect you +from the effects of sequence points described earlier. +Finally, C implicitly converts arrays to pointers when passing them as +function arguments. This means that a copy is made of the pointer to the +addresee().a array, and that pointer copy is passed to printf(). +But the array data itself is not copied, and may no longer exist when printf() +is called. +Consequently when printf() tries to dereference the pointer passed as +its 2nd argument, it is likely to find garbage. + +*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cfg.i frama-c-20111001+nitrogen+dfsg/tests/misc/cfg.i --- frama-c-20110201+carbon+dfsg/tests/misc/cfg.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cfg.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,25 @@ +/* run.config + DONTRUN: cannot find entry point: main +*/ + +struct bar { + int x; +}; +struct foo { + struct bar b; + int y; +}; + +int rand(void); + +void f(void) { + int t = rand(); + struct foo f = { + .b = { + .x = (t?2:3), + }, + .y = 42 + }; + return; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/char_ampamp.c frama-c-20111001+nitrogen+dfsg/tests/misc/char_ampamp.c --- frama-c-20110201+carbon+dfsg/tests/misc/char_ampamp.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/char_ampamp.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,17 @@ +/* run.config + OPT: -check + */ +char c=1; +int y; + +void g(int y, int x) +{ + Frama_C_show_each_x(x); +} + +main() +{ + y = 42 && c; + g(c, 42 && c); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cmp_ptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/cmp_ptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/cmp_ptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cmp_ptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,36 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -undefined-pointer-comparison-propagate-all +*/ + +int *p,T[10]={0,1,2,3,4,5,6,7,8,9}; +char C[10]={0,1,2,3,4,5,6,7,8,9}; +char *q; +int f(void) { /* make a top integer */ + int i = 0; + while (&i+(int)&i) { + i++;} + return i; +}; + +int g(void); + +int x,y,z,t,r; +float ff; +int main (int u) { + + p = &T[1] + f(); + q = &C[1] + f(); + + if (p >= &(T[5])) {*p=88;*q=77;} + x = !(&y+2); + *(int*)&ff = &y + 2; + y = !ff; + + + z = (u?&f:&g) == 0; + t = (1 + (int)(u?&f:&g)) == 0; + + r = (T-1) == 0; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cond2.i frama-c-20111001+nitrogen+dfsg/tests/misc/cond2.i --- frama-c-20110201+carbon+dfsg/tests/misc/cond2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cond2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,71 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -out-external -input -main zero_ou_un_0 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -out-external -input -main un_1 -journal-disable + +*/ + +volatile int Gx; +volatile int Gy; +int *px,*py,x,y; +int T[100]={0}; + int r = 0; + int s = 0; + int t = 0; + int u = 0; + +void zero_ou_un_0 (void) { + int i ; + + x = Gx ? 0 : 2 ; ; + if (x != 0) + r = 1; + + x = 1; + y = 0; + for (i = 0 ; i < Gx ; i++) x += 2; + for (i = 0 ; i < Gy ; i++) y += 5; + if (x != y) + s = 1; + + x = Gx ? 0 : 2 ; ; + y = Gy ? 1 : 2 ; ; + if (x != y) + t = 1; + + x = Gx ? 0 : 2 ; ; + if (x != 1) + u = 1; + +} + +int un_1 (void) { + int r = 0; + int i ; + x = Gx ? 0 : 2 ; ; + y = Gy ? 1 : 3 ; ; + if (x != y) + r = 1; + + x = 1; + y = 0; + for (i = 0 ; i < Gx ; i++) x += 2; + for (i = 0 ; i < Gy ; i++) y += 2; + if (x != y) + s = 1; + + x = Gx ? 0 : 2; + y = Gy ? 1 : 3; + for (i = 0 ; i < Gx ; i++) x += 4; + for (i = 0 ; i < Gy ; i++) y += 4; + if (x != y) + t = 1; + + px = Gx ? &(T[0]) : &(T[0]); + py = Gy ? &(T[1]) : &(T[1]); + for (i = 0 ; i < Gx ; i++) {px += 4; *px=1; } + for (i = 0 ; i < Gy ; i++) {py += 4; *py=2; } + if (px != py) + u = 1; + return u; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cond3.i frama-c-20111001+nitrogen+dfsg/tests/misc/cond3.i --- frama-c-20110201+carbon+dfsg/tests/misc/cond3.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cond3.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,88 @@ +int Gx,r,x; +int main(void) { + r = -1; + x = Gx ? 0 : 1 ; + if (x <= 0) {} + else goto fin; + r = x; + fin: + return r; +} + +int main1(void) { + r = -1; + x = Gx ? 0 : 1 ; + if (x <= 0) {goto fin;} + else r=x; + r = x; + fin: + return r; +} + + +int main2(void) { + r = -1; + x = Gx ? 0 : 1 ; + Gx = -2; + if (x <= 0) {Gx = x;} + else goto fin; + r = x; + fin: + return r; +} + + +int main3(void) { + r = -1; + x = Gx ? 0 : 1 ; + Gx = -2; + if (x <= 0) {goto fin;} + r = x; + fin: + return r; +} + + +int main4(void) { + r = -1; + x = Gx ? 0 : 1 ; + Gx = -2; + if (x <= 0) {Gx=5;} + r = x; + fin: + return r; +} + +int main5(void) { + r = -1; + x = Gx ? 0 : 1 ; + if (x <= 0) {} + else {Gx=5;} + r = x; + fin: + return r; +} + +int main6(void) { + r = -1; + x = Gx ? 0 : 1 ; + if (x <= 0) {Gx=5;} + else r=x; + r = x; + fin: + return r; +} + + +int main7(void) { + r = -1; + x = Gx ? 0 : 1 ; + Gx = -2; + if (x <= 0) {} + else {} + r = x; + fin: + return r; +} + + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/cond.i frama-c-20111001+nitrogen+dfsg/tests/misc/cond.i --- frama-c-20110201+carbon+dfsg/tests/misc/cond.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/cond.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,50 @@ +int G; +int x,y; + +int i_auSetEepromProgActive() { + return G?0:(-51); +} + +int i,t[]={ 1, 2, 3, 4, 5, 6, 7, 8 },(*p)[8],z, R; + +int main(int argc, char**argv) +{ + int r; + int inRet = (0); + char c = **argv; + short s = argc; + if(c < 0) + x = c; + if(s >= -10) + y = s; + r = i_auSetEepromProgActive() ; + if (r != (0)) + { + inRet = (-51); + + } + + p = t; + i = argc>=1?argc<=3?argc:1:1; + if ((*p)[i]==3) z = i; + + i = argc>=1?argc<=7?argc:1:1; + if (t[i]==4) R = i; + + unsigned u = unknf(); + if (u>=8) u = 8; + if (u!=3) + Frama_C_show_each_2(u); + Frama_C_show_each_3(u); + + unsigned v = 2 * u; + if (v!=3) + Frama_C_show_each_4(v); + Frama_C_show_each_5(v); + if (v!=10) + Frama_C_show_each_6(v); + Frama_C_show_each_7(v); + + return inRet; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/conditional_initializer.i frama-c-20111001+nitrogen+dfsg/tests/misc/conditional_initializer.i --- frama-c-20110201+carbon+dfsg/tests/misc/conditional_initializer.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/conditional_initializer.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,2 @@ +int T[1] = {0?(char)1:2}; +void main () {} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/const2.i frama-c-20111001+nitrogen+dfsg/tests/misc/const2.i --- frama-c-20110201+carbon+dfsg/tests/misc/const2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/const2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ + +struct S {unsigned char a; int b;}; +const struct S T[2] = {{.a=1,.b=2},{.a=3,.b=4}}; + +unsigned short int main () { + return (T[0].b); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/constarraylibentry.i frama-c-20111001+nitrogen+dfsg/tests/misc/constarraylibentry.i --- frama-c-20110201+carbon+dfsg/tests/misc/constarraylibentry.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/constarraylibentry.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + OPT: -memory-footprint 1 -val -lib-entry +*/ + +const int t[] = { 1, 2, 3, 4, 5 } ; + +const int t2[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 } ; + +typedef const int tt3[3]; + +tt3 t3[3] = { 10, 20, 30, 40, 50, 60, 70, 80, 90 } ; + +main() +{ + Frama_C_dump_each(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/const.i frama-c-20111001+nitrogen+dfsg/tests/misc/const.i --- frama-c-20110201+carbon+dfsg/tests/misc/const.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/const.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,57 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main semantique_const_1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main semantique_const_2 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main semantique_const_1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main semantique_const_2 -journal-disable +*/ +extern const int G; +extern int H; +extern int F; +extern const int I=2; + +int G; +int H; + +int X; + +int main () { + H++; + I++; + return G+F; +} + +/** Comportement des analyses au sujet des variables "const" et "non const" : + * + * Les valeurs des variables "const" peuvent évoluer au cours de l'exécution + * du code, comme pour toutes autres variables. + * + * Lors d'une analyse de type -lib-entry -main, les variables "const" ont pour + * valeurs initiales, la valeur correspondant à leur expression d'initialisation. + * + * Les valeurs initiales des autres variables sont d'une valeur inderterminée, mais + * dépendant de leur type. + */ +int cste const = 10 ; +int var = 3 ; + +int input_value_of_cste, output_value_of_cste ; + +void semantique_const_1 (void) { + input_value_of_cste = cste ; + + cste = var ; + + output_value_of_cste = cste ; + +} + +void semantique_const_2 (void) { + const int cste = 10 ; + input_value_of_cste = cste ; + + cste = var ; + + output_value_of_cste = cste ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/const_syntax.i frama-c-20111001+nitrogen+dfsg/tests/misc/const_syntax.i --- frama-c-20110201+carbon+dfsg/tests/misc/const_syntax.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/const_syntax.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ +const unsigned char INSTRU_N_00_01_001_CRC___1525983317999999999994352352523523993424999 = 0; +void main () { +const unsigned char INSTRU_N_00_01_001_CRC___1525983317999999999994352352523523993424999 = 0; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/context_free.i frama-c-20111001+nitrogen+dfsg/tests/misc/context_free.i --- frama-c-20110201+carbon+dfsg/tests/misc/context_free.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/context_free.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,53 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -lib-entry -main f -absolute-valid-range 0x200-0x199 -journal-disable +*/ + + +int a,b,c; + +int star_p, star_w___500; + +struct str { int s1; int s2; int *sp ; int (*sg)(char *) ; } s; + +struct str t; + +struct strstr { struct str ss1; int ss2; } tt; + +int u[12]; +int v[12][3]; +int *(w[12]); + +struct str ts[10]; + +union uni { int u1 ; struct str u2 ; } uu ; + +struct str_arith { int s1; int s2; float s3; } ; + +union uni_arith { int u1 ; struct str_arith u2 ; float u3 ; } uuu ; + +const int c_int = 34; + + +int f(int x, float y, int **p, int (*g)(char *), void *vv, void **vvv, int ta[5]) +{ + if (x >= 0) a = x; + b = s.s1 ; + t.s2 = 3; + tt.ss2 = c; + p = p; + *p = *p; + u[1]=2; + v[0][0]=5; + w[4]=&a; + (ts[3]).s1 = (ts[3]).s1 ; + vv = vv; + *vvv = *vvv; + c_int = c_int; + uu.u1 = uu.u1; + uuu.u1 = uuu.u1; + ta[1]=3; + ta=ta; + return g("toto"); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/context_free_simple.i frama-c-20111001+nitrogen+dfsg/tests/misc/context_free_simple.i --- frama-c-20110201+carbon+dfsg/tests/misc/context_free_simple.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/context_free_simple.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ + +int z=1; + +int f(int x,int y) +{ + z = x+y; + return y+1; +} + +void main(void) +{ + f(2,3); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/control.i frama-c-20111001+nitrogen+dfsg/tests/misc/control.i --- frama-c-20110201+carbon+dfsg/tests/misc/control.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/control.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable +*/ + +int x,y,c,d; + + +void f() { + int i; + for(i=0; i<4 ; i++) { + if (c) { if (d) {y++;} else {x++;}} + else {}; + x=x+1; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/copy_logic.i frama-c-20111001+nitrogen+dfsg/tests/misc/copy_logic.i --- frama-c-20110201+carbon+dfsg/tests/misc/copy_logic.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/copy_logic.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + OPT: -check -copy -val -print -journal-disable + */ + +/*@ predicate p(int x); */ +/*@ predicate q(int x) = x == 42; */ +/*@ logic int f (int y); */ +/*@ logic integer g (int x) = x + 42; */ + +int main (int x) { + int y = 42; + /*@ assert q(y) && p(x); */ + y+=x; + /*@ assert g(x) == f(y); */ + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/copy_paste_hidden_by_dummy_cast.i frama-c-20111001+nitrogen+dfsg/tests/misc/copy_paste_hidden_by_dummy_cast.i --- frama-c-20110201+carbon+dfsg/tests/misc/copy_paste_hidden_by_dummy_cast.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/copy_paste_hidden_by_dummy_cast.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,20 @@ +typedef unsigned short T_WORD16; +typedef unsigned int T_WORD32; +typedef short T_INT16; +typedef float T_FLOAT; + +struct S { + T_INT16 a ; + T_WORD32 b ; +}; +typedef struct S T_ERREUR_ANO; + +T_ERREUR_ANO const A4O1_Ci_sNO_ERREUR_ANO = {0, 0}; + +void main () { + struct S Rl_sErreurAno ; + Rl_sErreurAno = A4O1_Ci_sNO_ERREUR_ANO; + +} + + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/copy_paste.i frama-c-20111001+nitrogen+dfsg/tests/misc/copy_paste.i --- frama-c-20110201+carbon+dfsg/tests/misc/copy_paste.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/copy_paste.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +int t[12],G; + +void main(int c) { + volatile int l=0; + int i=c?3:4; + int j=c?(-3):4; + t[i] = i; + t[j] = j; + l = *(int*)l; + G=l; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/copy_stdin.i frama-c-20111001+nitrogen+dfsg/tests/misc/copy_stdin.i --- frama-c-20110201+carbon+dfsg/tests/misc/copy_stdin.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/copy_stdin.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +int * leaf(void); +void main () { + int * stdin, *toto; + stdin = leaf(); + toto = stdin; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/copy_visitor.i frama-c-20111001+nitrogen+dfsg/tests/misc/copy_visitor.i --- frama-c-20110201+carbon+dfsg/tests/misc/copy_visitor.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/copy_visitor.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,25 @@ +/* run.config + OPT: -check -copy -val -print -journal-disable + */ +struct S { + int a; + int b; +}; +struct S s = {.a = 1, .b=2}; + +/*@ + requires \valid(s); + assigns s->a; +*/ +int f(struct S* s){ + s->a=2; + return s->b; +} + +/*@ assigns s.a; */ +int main () { + s.a = 2; + /*@ assert s.a == 2; */ + f(&s); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/dead_code2.i frama-c-20111001+nitrogen+dfsg/tests/misc/dead_code2.i --- frama-c-20110201+carbon+dfsg/tests/misc/dead_code2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/dead_code2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +int G; +void main(void) { + int i,j,k,l; + + i=10; + G=0; + L: if (i=1) goto OUT; + i = i - 1 - G; + j+=i; + goto L; + OUT: + l=17; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/dead_code.i frama-c-20111001+nitrogen+dfsg/tests/misc/dead_code.i --- frama-c-20110201+carbon+dfsg/tests/misc/dead_code.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/dead_code.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +void main(int in) { + int i,j=6,k,l; + + i=10; + //@ impact pragma stmt; + i=1; + L: if (i) {l= 17 ; goto OUT;} +// i--; +// j+=i; +// goto L; +// while (1); + + OUT: j = l; + l=17; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/dead_inout.i frama-c-20111001+nitrogen+dfsg/tests/misc/dead_inout.i --- frama-c-20110201+carbon+dfsg/tests/misc/dead_inout.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/dead_inout.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + OPT: -out -input + */ + +int a, b; + +void f() { + a = b; +} + +void g () { + int x = 0; + if (x) f (); +} + +void main(){ + f (); + g (); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/deep_conditionals.i frama-c-20111001+nitrogen+dfsg/tests/misc/deep_conditionals.i --- frama-c-20110201+carbon+dfsg/tests/misc/deep_conditionals.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/deep_conditionals.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,3 @@ +void main(void) { char X,Y ; + Y = ((X=66, ((0 == 1) || (X=22,X=33,2==3)) && (4==5)))? (((X=66, ((0 == 1) || (X=22,X=33,2==3)) && (4==5))) ? 99:77):77 ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/degeneration2.i frama-c-20111001+nitrogen+dfsg/tests/misc/degeneration2.i --- frama-c-20110201+carbon+dfsg/tests/misc/degeneration2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/degeneration2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +void main (int c,int d) { +void *A,*B,*C,*D, *E; + + if (c) {A = (void*)&B; + B= (void*)&C; + C= (void*)&D; + D= (void*)&E; + }; + A = (void*)(-(int)A); + + while (c) { + A = (void*)*((int*)A); + } + + int offset_uninit; + char T[10][10]; + int x = (d<=10)?((d>=0)?d:0):0; + + int vv = T[x][offset_uninit]; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/degeneration.i frama-c-20111001+nitrogen+dfsg/tests/misc/degeneration.i --- frama-c-20110201+carbon+dfsg/tests/misc/degeneration.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/degeneration.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ + + +void main(char c) { + int **p; + int * pp = *p; + int ppp = **p; + int pppp = ppp; + int *qq = (c?&ppp:&pppp); + int qqq = *qq; + + int q = **p+1; + **p=1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/deps_addr.i frama-c-20111001+nitrogen+dfsg/tests/misc/deps_addr.i --- frama-c-20110201+carbon+dfsg/tests/misc/deps_addr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/deps_addr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ +int *t; +int a; +int tt[5][5]; +int main () { + + return *(&(t[(int)&a])); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/deps.i frama-c-20111001+nitrogen+dfsg/tests/misc/deps.i --- frama-c-20110201+carbon+dfsg/tests/misc/deps.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/deps.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,53 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main fonc1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main fonc2 -journal-disable +*/ +int f (int a, int b,int c){ + int w,d; + + if (c) b = 0; + return w; +} + +int fonc1 (int a, int b){ + int w; + struct t1 { int x; int y;} v1; + v1.x = a+b; + w = v1.x; + if (a) { + struct t1 { int x; int y;} v2; + struct t2 { int x; int y;} v3; + v2.x = a; + v3.x = b; + w = w + v2.x + v3.x; + } + return w; +} + +int fonc2 (int a, int b){ + int w; + struct t1 { int x; int y;} v1; + v1.x = a+b; + w = v1.x; + return w; +} + +struct Tstr { int a; int b; }; + +int h (struct Tstr * ps) { + return ps->a; +} +int ptr (int*pt) { + return *pt; +} +int i (int x, int y) { + struct Tstr s;// = {x, y}; + int g; + g=0; + return (*(&g)); + return ptr(&g); + s.a = 0; + return h(&s); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/deps_local.i frama-c-20111001+nitrogen+dfsg/tests/misc/deps_local.i --- frama-c-20110201+carbon+dfsg/tests/misc/deps_local.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/deps_local.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,23 @@ +int G,H; + +int h(int *argh) { +// G = *argh; + *argh = H; +} + +int g() { + int ga; + h(&ga); + return 0; +} + +int f() { + int fa; + h(&fa); + return 0; +} + +int main() { + f(); + g(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/deps_mixed.i frama-c-20111001+nitrogen+dfsg/tests/misc/deps_mixed.i --- frama-c-20110201+carbon+dfsg/tests/misc/deps_mixed.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/deps_mixed.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +int *p,*q; +int a,b; +int r=2; +int main (int c, int d) { + p=c?&a:(int*)3; + q=d?&b:(int*)2; + r = *((p+ (int)q)); + return ((int)(p+ (int)q)); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/deref.i frama-c-20111001+nitrogen+dfsg/tests/misc/deref.i --- frama-c-20110201+carbon+dfsg/tests/misc/deref.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/deref.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -deref -journal-disable +*/ +int a,b,c,d,e,*p, t[10]; + + +int main (void) +{ + int i = 0; + p = &a; + return *p + b + *(&c) + (&d)[i] + t[i]; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/div.i frama-c-20111001+nitrogen+dfsg/tests/misc/div.i --- frama-c-20110201+carbon+dfsg/tests/misc/div.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/div.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,38 @@ +/* run.config + STDOPT: +"-remove-redundant-alarms" + */ +int X,Y,Z1,Z2,T,U1,U2,V,W1,W2; +int a,b,d1,d2,d0,e; +int t[5]={1,2,3}; + +int *p; + +void main (void) +{ + int i; + volatile int c=0; + while (c+1) + { + if (c) X++; + if (c+2) X--; + } + Y = -5; + if ((X>=Y) && (X<=12) ) + Y = X; + Y = 27 * Y + 9; + Z1 = Y / 3; + Z2 = Y / 5; + V = Y + 1; + W1 = V / 3; + W2 = V / 5; + T = Y + 160; + U1 = T / 3; + U2 = T / 5; + p = &(t[3]); + a = 40000/Z2; + b = ((int)&Z2)/Z2; + d2 = 100 / (int)(&X + 2); + d1 = 100 / (int)(&X + 1); + d0 = 100 / (int)(&X); + e = - (int) &X; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/div_strange.i frama-c-20111001+nitrogen+dfsg/tests/misc/div_strange.i --- frama-c-20110201+carbon+dfsg/tests/misc/div_strange.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/div_strange.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +int main() { + + int x = -1; + + x /= sizeof(unsigned int); + + CEA_F(x); + +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/duff.i frama-c-20111001+nitrogen+dfsg/tests/misc/duff.i --- frama-c-20110201+carbon+dfsg/tests/misc/duff.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/duff.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,24 @@ +/* run.config + DONTRUN: +*/ + +int Ato[100]; +int Afrom[100]; + +void main(int count) { + int*to = &Ato; + int*from = &Afrom; +//@ assert count > 0 ; +switch (count % 8) /* count > 0 assumed */ + { + case 0: do { *to = *from++; + case 7: *to = *from++; + case 6: *to = *from++; + case 5: *to = *from++; + case 4: *to = *from++; + case 3: *to = *from++; + case 2: *to = *from++; + case 1: *to = *from++; + } while ((count -= 8) > 0); + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/dur.i frama-c-20111001+nitrogen+dfsg/tests/misc/dur.i --- frama-c-20110201+carbon+dfsg/tests/misc/dur.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/dur.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,182 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -float-normal -val -deps -out -input -main F2 -journal-disable +*/ + +struct T1 { + float M1 ; + unsigned short M2 ; + unsigned short M3 ; +}; +typedef struct T1 T2; +struct T3 { + unsigned short M4 ; + unsigned short M5 ; +}; +typedef struct T3 T4; +struct T5 { + float M6 ; + float M7 ; + float M8 ; + float M9 ; + float M10 ; + float M11 ; + float M12 ; + float M13 ; + float M14 ; + float M15 ; + float M16 ; + float M17 ; + float M18 ; + float M19 ; + float M20 ; + float M21 ; + float M22 ; + float M23 ; + float M24 ; + float M25 ; + float M26[(unsigned short)26] ; + float M27[(unsigned short)13] ; + float M28[(unsigned short)3] ; + float M29 ; + float M30 ; + float M31 ; + float M32 ; + float M33 ; + float M34 ; + float M35 ; + float M36 ; + float M37 ; + float M38 ; + float M39 ; + float M40 ; + float M41 ; + float M42 ; + float M43 ; + float M44 ; + float M45 ; + float M46 ; + float M47 ; + float M48 ; + float M49 ; + float M50 ; + float M51 ; + float M52 ; + float M53 ; + float M54 ; + float M55 ; + float M56 ; + float M57 ; + float M58 ; + float M59 ; + float M60 ; + float M61 ; + float M62 ; + float M63 ; + float M64[27] ; + float M65[27] ; + float M66[(unsigned short)48] ; + float M67[(unsigned short)48] ; + float M68[(unsigned short)48] ; + float M69[(unsigned short)48] ; + float M70[48] ; + float M71[48] ; + float M72[48] ; + float M73[48] ; + float M74[(unsigned short)10] ; +}; +typedef struct T5 T6; +struct T7 { + unsigned short M75 ; + T2 M76[(unsigned short)53] ; + T2 M77 ; + T2 M78 ; + T2 M79 ; + T2 M80 ; + T2 M81 ; + T2 M82 ; + T2 M83 ; + T2 M84 ; + T2 M85 ; + T2 M86 ; + T2 M87 ; + T2 M88 ; + T2 M89 ; + T4 M90[(unsigned short)4] ; + T4 M91 ; + T2 M92[(unsigned short)6] ; + T4 M93[(unsigned short)5] ; +}; +typedef struct T7 T8; +struct T9 { + unsigned short M94[(unsigned short)1][16] ; + unsigned short M95[(unsigned short)1] ; + unsigned short M96[(unsigned short)1] ; + unsigned short M97[(unsigned short)1] ; + unsigned short M98 ; +}; +typedef struct T9 T10; +int G1 ; +int G2 ; +extern unsigned char G3 ; +extern T6 const G4 ; +extern T8 G5 ; +extern T10 G6 ; +extern unsigned char G7[(unsigned short)161] ; +void F1(T2 *V1 , T2 *V2 , unsigned short const V3 , + unsigned short const V4 ) +{ + + {if ((int )V1->M2 != 0) + {if ((int )V1->M2 == 2) {G7[V3] = (unsigned char)1;} + else {G7[V3] = (unsigned char)0;} + + V1->M2 = (unsigned short)1; + if ((int )V2->M2 == 0) + {G7[V4] = (unsigned char)0; + if (V2->M1 <= G4.M16) {G7[V3] = (unsigned char)1; + if (V2->M1 <= G4.M17) {G7[V4] = (unsigned char)1; + V2->M2 = (unsigned short)1;} + } + } + else {G7[V4] = (unsigned char)1; + V2->M2 = (unsigned short)1;} + } + else {G7[V3] = (unsigned char)0; + V2->M2 = (unsigned short )((int )V2->M2 != 0); + G7[V4] = (unsigned char )V2->M2;} + + return;} + +} +void F2(unsigned short V8 ) +{ unsigned short V5 ; + unsigned short V6 ; + unsigned short V7 ; + + {G5.M75 = (unsigned short )G3; + if ((int )V8 == 0) {if ((((int )G6.M97[0] & 1) == 1) == 1) + {G5.M91.M4 = (unsigned short)0; + G5.M91.M5 = (unsigned short)1;} + else {G5.M91.M4 = (unsigned short )(((int )G6.M96[0] & 1) == 1); + G5.M91.M5 = (unsigned short)0;} + + V6 = (unsigned short)0; + V7 = (unsigned short)2; + V5 = (unsigned short)0; + while ((int )V5 < 4) {if (G2) + {G5.M90[V5].M4 = (unsigned short)0; + G5.M90[V5].M5 = (unsigned short)1;} + else {G5.M90[V5].M4 = (unsigned short )G1; + if ((int )G5.M90[V5].M4 == 1) {V6 = (unsigned short )( + (int )V6 + 1);} + + G5.M90[V5].M5 = (unsigned short)0;} + + V7 = (unsigned short )(2 * (int )V7); + V5 = (unsigned short )((int )V5 + 1);} + } + + return;} + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/endian.i frama-c-20111001+nitrogen+dfsg/tests/misc/endian.i --- frama-c-20110201+carbon+dfsg/tests/misc/endian.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/endian.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,40 @@ + +struct S {unsigned char a; unsigned char b; char c; unsigned char d;} v1; + +union U {unsigned int full; struct S part;} UU; +unsigned char b0,b1,b2,b3; +unsigned int f; + + +union U0 { + unsigned short f0 ; + int f1 ; + int f2 : 5 ; + unsigned char const f3 ; +}; + +unsigned short G0 ; +int G1 ; +int G2; +unsigned char G3 ; +union U0 G={(unsigned short)65532U}; + + + +void main (void) { + union U data0; + data0.full = 0xFF030201; + b0 = data0.part.a + 1 - 1; + b1 = data0.part.b + 1 - 1; + b2 = data0.part.c + 1 - 1; + b3 = data0.part.d + 1 - 1; + data0.part.a = 0; + f = data0.full + 1 -1; + + G0=G.f0; + G1=G.f1; + G2=G.f2; + G3=G.f3; + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ensures.i frama-c-20111001+nitrogen+dfsg/tests/misc/ensures.i --- frama-c-20110201+carbon+dfsg/tests/misc/ensures.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ensures.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +/* run.config_no_native_dynlink + CMD: bin/toplevel.byte + OPT: -load-script tests/misc/ensures.ml +*/ +/* run.config + OPT: -load-script tests/misc/ensures.ml +*/ +//@ ensures *p==1; +void main(int * p){ *p = 0; } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ensures.ml frama-c-20111001+nitrogen+dfsg/tests/misc/ensures.ml --- frama-c-20110201+carbon+dfsg/tests/misc/ensures.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ensures.ml 2011-10-10 08:39:03.000000000 +0000 @@ -1,7 +1,7 @@ open Cil_types let run () = - Parameters.Dynamic.Bool.set "-context-valid-pointers" true; + Dynamic.Parameter.Bool.set "-context-valid-pointers" true; !Db.Value.compute (); Globals.Functions.iter (fun kf -> @@ -10,21 +10,14 @@ let ip = Property.ip_of_spec kf Kglobal spec in List.iter (fun ip -> - let bname = - match Property.get_behavior ip with - Some b -> b.b_name - | None -> "Ook" + let bname = match Property.get_behavior ip with + | None -> "Ook" + | Some b -> b.b_name in - let function_name = - kf_name ^ ": behavior " ^ bname - in - let statuses = Properties_status.get_all ip in - List.iter - (fun status -> - Kernel.result "%s %a" - function_name Cil.d_annotation_status status) - statuses) + let function_name = kf_name ^ ": behavior " ^ bname in + let status = Property_status.get ip in + Kernel.result "@[%s@ @[%a@]@]" + function_name Property_status.pretty status) ip) -;; -Db.Main.extend run +let () = Db.Main.extend run diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/enum2.c frama-c-20111001+nitrogen+dfsg/tests/misc/enum2.c --- frama-c-20110201+carbon+dfsg/tests/misc/enum2.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/enum2.c 2011-10-10 08:39:03.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -cpp-command "gcc -C -E -I. %1 > %2" -memory-footprint 1 -val -deps -out -input -main sizeof_enum1 -journal-disable + OPT: -check -cpp-command "gcc -C -E -I. %1 -o %2" -memory-footprint 1 -val -deps -out -input -journal-disable */ /* This test of enums doubles with a test of the % syntax in -cpp-command */ @@ -12,8 +12,11 @@ E1_SGN1 = BIT_DE_SIGNE_1, E1_SGN0 = BIT_DE_SIGNE_0 } E1 ; + +E1 f(E1 x) { return x; } + unsigned char enum1_sgn1_positif (void) { - unsigned char res = E1_SGN1 > 0; + unsigned char res = (f((E1)E1_SGN1)) > 0; printf ("enum1_sgn1_positif = %d\n", res); return res; /* WARN : ppc->0 ; gcc->1 */ } @@ -22,8 +25,11 @@ printf ("enum1_sgn1_inf_sgn0 = %d\n", res); return res; /* WARN : ppc->1 ; gcc->0 */ } -int sizeof_enum1 (void) { +unsigned char must_be_one, must_be_zero; +int main (void) { int res = sizeof (E1); + must_be_zero = enum1_sgn1_inf_sgn0(); + must_be_one = enum1_sgn1_positif(); printf ("sizeof_enum1 = %d\n", res); - return res; /* WARN : ppc->4 ; gcc->8 */ + return res; } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/enum.i frama-c-20111001+nitrogen+dfsg/tests/misc/enum.i --- frama-c-20110201+carbon+dfsg/tests/misc/enum.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/enum.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable +*/ +typedef enum counter {ZERO,ONE,TWO,LAST=TWO}; + +int t [LAST + 1] = { 1 }; +int u [TWO + 1] = { 2 }; + +void f(void) +{ + int i[3]={0}; + t[2] = 42; + u[TWO] = 36; + enum counter j=0; + for(j=0;j<2;j++) + i[j] = 1; + + enum counter k = ZERO; + //@ assert k == ZERO; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/extern.i frama-c-20111001+nitrogen+dfsg/tests/misc/extern.i --- frama-c-20110201+carbon+dfsg/tests/misc/extern.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/extern.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,18 @@ +extern int T1; +extern const int T2; + +extern int T3[]; +extern const int T4[]; + +extern int T5[3]; +extern const int T6[3]; + +void main () { +// T1++; +// T2++; + T1= T3[3]; + T2= T4[3]; + T1= T5[1]; + T2= T6[1]; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/f1.i frama-c-20111001+nitrogen+dfsg/tests/misc/f1.i --- frama-c-20110201+carbon+dfsg/tests/misc/f1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/f1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ + +extern int f(int x); + +void main() { + f(5); + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/f2.i frama-c-20111001+nitrogen+dfsg/tests/misc/f2.i --- frama-c-20110201+carbon+dfsg/tests/misc/f2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/f2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable +*/ +int f(int x) { +/* Here we are */ +/*@ loop pragma UNROLL_LOOP 10; */ + while(1) { return 0 ;} + return 2; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/false.i frama-c-20111001+nitrogen+dfsg/tests/misc/false.i --- frama-c-20110201+carbon+dfsg/tests/misc/false.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/false.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/*@ requires i == 1; + requires i == 1; + requires i == 1; */ +void f (int i); + +/*@ ensures \result == 1; + ensures \result == 1; */ +int g (int i) { + return i; +} + +void main (int bla, int bli) { + int i=0; + if (bla) f(i); + if (bli) g(i); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/find_ivaltop.i frama-c-20111001+nitrogen+dfsg/tests/misc/find_ivaltop.i --- frama-c-20110201+carbon+dfsg/tests/misc/find_ivaltop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/find_ivaltop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +int t[20]={1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0}; + +int main(void) +{ + int i,j=0,X=0; + for (i=0;i<8;i++) + j=i; + if (j<=7) X=j; + X=t[X]; + return X; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/folding.i frama-c-20111001+nitrogen+dfsg/tests/misc/folding.i --- frama-c-20110201+carbon+dfsg/tests/misc/folding.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/folding.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,31 @@ +int f(int x) {return x;}; + +int g() { + int (*pfct)(int) = &f; + int un = 1; + int *p =&un; + int deux = 1+un; + int trois ; + p = &deux; + trois = *p+*p+un; + return (*pfct)(trois); +} + +int foo(int x, int y) { + volatile int unknown=0; + if (unknown) + return y+2; + return x+3; + } + +int main () { + int a,b,c; + g(); + a = foo(5,7) + foo(6,777); + b = 4; + c = b * b +a; + if (b > c) + return b-c; + else + return b+c; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/for_loops.i frama-c-20111001+nitrogen+dfsg/tests/misc/for_loops.i --- frama-c-20110201+carbon+dfsg/tests/misc/for_loops.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/for_loops.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,40 @@ +int x; + +int f(); + + +void main_2 () { + int i,j; + int nSelectors = Frama_C_interval(0,100); + int w=0,v = 0; + + for (j = 0; j < nSelectors; j++) { if (Frama_C_interval(0,1)) w += 1; + CEA_F(w);} + // w widens to top_int + +} + +void main () { + int i,j; + int nSelectors = Frama_C_interval(0,0x7FFFFFFF); + int w=0,v = 0; + + for (j = 0; j <= nSelectors; j++) + { v = j ; + while (v>0) v--; + CEA_F(j);} + +} + +void g () { + int j; + int T[1000]; + int nSelectors = Frama_C_interval(0,1000); + int w=0; + CEA_DUMP(); + for (j = 0; j < nSelectors; j++) T[j] = 1; + CEA_DUMP(); + for (j = 0; j < nSelectors; j++) w += T[j]; +//@ assert nSelectors == w ; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/FP5.i frama-c-20111001+nitrogen+dfsg/tests/misc/FP5.i --- frama-c-20110201+carbon+dfsg/tests/misc/FP5.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/FP5.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,31 @@ +/*@ requires \valid(b); + @ requires \valid(c); + @ requires \valid(&a); + @ assigns *b; + @ assigns *c; + @*/ +void main(int a, int *b, int *c) +{ + int i=0; + + if (a==1) + { + *b=1; + *c=1; + } + else if (a==-1) + { + *b=-1; + *c=-1; + } + else + { + while (i<a) + { + *b=0; + i++; + } + *c=0; + } + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/fptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/fptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/fptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/fptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,72 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -journal-disable + OPT: -memory-footprint 1 -val -deps -out -main main_uninit -journal-disable +*/ +int R=77; + +int f(int (*ptr(int x))) { + R = ptr(1); + return R; +} + +int X=77,XH=0,XHH=0; + +int h (int y) {X = y; XH= y; return X;} ; +int hh (int y) {X = y+y; XHH = y; return X;} ; + +extern int hhh(int y); + +typedef int (* PTR_FCT)(int); +typedef PTR_FCT TYPE[10]; +TYPE GLOBAL; +int G; + +short retshort(void) +{ + return 12; +} + +int retint(void) +{ + return 42; +} + +int TA; + +void main (int c) +{ + int in, pin; + short sh, psh; + + if (c&1) in = retshort(); + if (c&2) sh = retint(); + if (c&4) pin = (*((int (*)())retshort))(); + if (c&8) psh = (*((short (*)())retint))(); + + int i=0; + GLOBAL[0] = h; + GLOBAL[1] = hh; + for(i=0;i<3;i++) { + CEA_F(GLOBAL[i]); + G=f(GLOBAL[i]); + } + + PTR_FCT p = (c&16) ? &h : &hh; + if (c&32) TA=(*p)(1/(c&64)); +} + +void main_uninit (int c) +{ + int i=0; + volatile int j=0; + GLOBAL[2]=j; + GLOBAL[0] = h; + GLOBAL[1] = hh; + for(i=0;i<3;i++) { + CEA_F(GLOBAL[i]); + G=f(GLOBAL[i]); + } +} + + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from1.i frama-c-20111001+nitrogen+dfsg/tests/misc/from1.i --- frama-c-20110201+carbon+dfsg/tests/misc/from1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,28 @@ +int G; + +int cx,cy,cz,sx,sy,s; + +struct Tstr { int a; int b; }; + + +void f(void) +{ + cy = cx; +} + +int sf (struct Tstr * ps) { + return ps->a; +} + +int main(int x,int y) { + struct Tstr s = {sx, sy}; + + if (x) G=y; + + cx = cz; + f(); + + return sf(&s); +} + + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_call.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_call.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_call.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_call.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,97 @@ +/* run.config + OPT: -memory-footprint 1 -calldeps -users -val -journal-disable -input +*/ + +int a,b,c,d; +int x,y,z,t; + +int g(int w) +{ + return w + t; +} + +int h(int); + +int f(int *p) +{ + static int * previous = &a; + *p = *previous; + previous = p; + return g(h(x)+*p); +} + +int A1,A2,A3,A4,A5,A6,A7,A8; +int R1,R2,R3,S1,S2,S3; +int T0,T1,T2; + +int dispatcher(int c, int y, int z, int x) +{ + return c ? y : z; +} + +int return_A1(void) +{ + return A1; +} + +int return_A2(void) +{ + return A2; +} + +int dispatcher2(int c) +{ + return c ? return_A1() : return_A2(); +} + +int call_dispatcher2_1(void) +{ + return dispatcher2(1); +} + +int call_dispatcher2_0(void) +{ + return dispatcher2(0); +} + +int call_dispatcher2(int r) +{ + return dispatcher2(r); +} + +int tab[5]; + +int access_tab(int ind) +{ + return tab[ind]; +} + +int AA,AR,AS; +int At[2]={&AA}; +int Ar[2]={&AA}; +int *Ap=At; + +/*@ assigns AR \from Ap[..] ; + assigns AS \from Ar[..] ; + */ +void unavailable_f(void); + +void main(int r) +{ + y = f(&b); + z = f(&c) + f(&d); + R1 = dispatcher(1,A1,A2,A3); + R2 = dispatcher(0,A3,A4,A6); + R3 = dispatcher(r,A4,A5,A7); + S1 = call_dispatcher2_1(); + S2 = call_dispatcher2_0(); + S3 = call_dispatcher2(r); + tab[0]=A1; + tab[1]=A2+A3; + tab[2]=A4; + T0 = access_tab(0); + T1 = access_tab(1); + T2 = access_tab(2); + + unavailable_f(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_global.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_global.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_global.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_global.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +int A,B,C,D,E; + +int f(int x) +{ + B = A; + C = x; +} + +int main(void) +{ + A = D; + f(E); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_pb.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_pb.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_pb.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_pb.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,95 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main main0 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main2 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main3 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main4 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main4bis -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main5 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main5bis -journal-disable +*/ + +int k,i,j,x,c,d,T[10]; + +void main0(){ + + if (j) + {if (c) x=i; else x=d;} + else x=k; +} + +void main1(){ + + if (j) + {if (c) T[0]=i; else T[1]=d;} + else x=k; +} + +void main2(){ + if (j) + {if (c) ((int*)((char*)T+1))[0]=i; else T[1]=d;} + else x=k; +} + + +void main3(){ + int* p = ((int*)((char*)T+1)); + + if (c) { p[0]=i; p[1]=d;} else T[1] = x; + +} + +void main4() +{ + if (c) + { + T[0]=i; + T[2]=j; + } + else + { + T[0]=k; + } + +} + +void main4bis() +{ + if (c) + { + T[0]=k; + } + else + { + T[0]=i; + T[2]=j; + } +} + +void main5() +{ + if (c) + { + T[0]=i; + T[1]=j; + } + else + { + T[0]=k; + } + +} + +void main5bis() +{ + if (c) + { + T[0]=k; + } + else + { + T[0]=i; + T[1]=j; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_ptr2.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_ptr2.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_ptr2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_ptr2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +struct Tstr { int a; int b; }; +int f (struct Tstr * ps) { + return ps->a; +} +int main (int x, int y) { + struct Tstr s = {x, y}; + return f(&s); +} +/* +Function main: + \result FROM s.a; +*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_ptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_ptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_ptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_ptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,31 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main1 -journal-disable +*/ +long i,j,x,k,l,m,n,d,a,b; + +int p[10][10][10]={0}; +long *q; + +void main(int c) { + i = &p[11]; + i = &p[10]; + + if (c) + // This branch is assumed to be dead since "i" is an invalid pointer. + *((int*)i) = a; + + q = c ? &a : &b ; // So, "q" points only on "b". + d = *q; // "d" is only from "a" and "c". +} + +void main1(int c) { + i = &p[1]; + i = &p[0]; + + if (c) *((int*)i) = a; + + q = c ? &a : &b ; + d = *q; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_res_2.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_res_2.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_res_2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_res_2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,23 @@ +typedef unsigned char T; +// typedef int T; +int G; +T f (int left, int right ) { + return left + right; +} + +int A, C; + +struct S { int a; int b; int c;} x, y; + +struct S g(void){ + return x; +} + +void main (void) +{ int * p = &G; + *p = f (G, 3); + x.a = A; + x.c = C; + y = g(); + } + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/from_termin.i frama-c-20111001+nitrogen+dfsg/tests/misc/from_termin.i --- frama-c-20110201+carbon+dfsg/tests/misc/from_termin.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/from_termin.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +int b,c,d,e; + +void main(int a) +{ + if (a) + b = c; + else + while (1) d = e; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/function_return_serial_casts.i frama-c-20111001+nitrogen+dfsg/tests/misc/function_return_serial_casts.i --- frama-c-20110201+carbon+dfsg/tests/misc/function_return_serial_casts.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/function_return_serial_casts.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +short x = -10; +int y, z, t; + +unsigned short f(void) +{ + return x; +} + +unsigned short g(void) +{ + unsigned short l = *(unsigned short*)&x; + return l; +} + +main(){ + y = *(unsigned short*)&x; + z = f(); + t = g(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/fun_ptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/fun_ptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/fun_ptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/fun_ptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,43 @@ + + +int f(int x) +{ + return x+1; +} + +int g(int x, int y) +{ + return x+y; +} + +typedef int (*fptr1)(int); +typedef int (*fptr2)(int, int); +typedef double (*fptr3)(int); + +long t[2] = { (long)&f, (long)&g }; + +int R1, R2; +double R3; + +void test1(int nd) +{ + R1 = ((fptr1)(t[nd]))(3); +} + +void test2(int nd) +{ + R2 = ((fptr2)(t[nd]))(3, 4); +} + +void test3(int nd) +{ + R3 = ((fptr3)(t[nd]))(5); +} + +main(int c){ + test1(!(c&1)); + test2(!(c&2)); + if (c&4) test3(!(c&8)); + + return 0; +} \ No newline at end of file diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/g1.i frama-c-20111001+nitrogen+dfsg/tests/misc/g1.i --- frama-c-20110201+carbon+dfsg/tests/misc/g1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/g1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,2 @@ +extern int G = 1; +void main (){} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ghost.i frama-c-20111001+nitrogen+dfsg/tests/misc/ghost.i --- frama-c-20110201+carbon+dfsg/tests/misc/ghost.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ghost.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,29 @@ + +/* Commentaire avant G */ /* Commentaire avant G2 */ +int G; +/* Commentaire apres G avant main */ + +/*@ ghost int GHOST ; */ + +int main () { +/* Commentaire apres main */ + int i; +/* Commentaire apres int i */ + G = 0; +/*@ghost GHOST=G+G ; */ +/* Commentaire avant loop */ + /*@ loop pragma UNROLL_LOOP 0; */ + for(i=0; i<=10; i++) + G++; + +// AVANT j + {int /* milieu j*/ j; + j = /* milieu j 2*/ 0; } +// APRES j + + return i; +} + +/* ICI avant H */ +int H; +/* ICI après H */ diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ghost_lexing.i frama-c-20111001+nitrogen+dfsg/tests/misc/ghost_lexing.i --- frama-c-20110201+carbon+dfsg/tests/misc/ghost_lexing.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ghost_lexing.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,18 @@ +/* run.config + OPT: -journal-disable -print +*/ + +int G = 0; + +const char* foo = "foo"; + +void test(const char */*name*/); + +void test2(int x) { + /*@ ghost + int y = 0; + if (x>0) { y = x * x; }; + */ + G = x * x; + test(foo); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/global_bug.i frama-c-20111001+nitrogen+dfsg/tests/misc/global_bug.i --- frama-c-20110201+carbon+dfsg/tests/misc/global_bug.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/global_bug.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,8 @@ +int i = 1; +int G = 99<<63; +int j = 2; + +int main () { + G ++; + return (i == j); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/goto.i frama-c-20111001+nitrogen+dfsg/tests/misc/goto.i --- frama-c-20110201+carbon+dfsg/tests/misc/goto.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/goto.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +int stop () { + L: goto L; + +} + +int main() { + volatile int c=0; + c = c?1:0; + + if (c) stop (); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/if2.i frama-c-20111001+nitrogen+dfsg/tests/misc/if2.i --- frama-c-20110201+carbon+dfsg/tests/misc/if2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/if2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,25 @@ +typedef enum { + AU_NO_MODE = 0, + AU_ANLAUF = (0x0001), + AU_BETRIEB = (0x0002), + AU_PARAMETRIEREN = (0x0004), + AU_FUNKTIONSPRFNG = (0x0008), + AU_DIAGNOSE = (0x0010), + AU_RESET = (0x0020) +} auModeStates_t; + +static auModeStates_t mode; +auModeStates_t G = AU_NO_MODE; +int G_int = 75, mode_int; + +void main (void) { + + if ((AU_DIAGNOSE == mode)) // && ((void *) 0 != auDiagnostics_p)) + {G = mode;} + + if ((0 == mode_int)) // && ((void *) 0 != auDiagnostics_p)) + {G_int = mode_int;} + + return; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/if.i frama-c-20111001+nitrogen+dfsg/tests/misc/if.i --- frama-c-20110201+carbon+dfsg/tests/misc/if.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/if.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,96 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main main -journal-disable + OPT: -memory-footprint 1 -val -deps -main main6 -journal-disable + */ +int G,H,J; +int *p, *q; +int t[100]; + +int main0(void) { + G=0; + int c = 0; + if (c) G=1; else G=2; + + return c; +} + +int main1(void) +{ + if (G) ; + + return 1; +} + +int main2(void) { + int c = c?0:(c?1:2); + int d = c?1:(c?2:3); + + G = -20; + H = -30; + + if (c) {G=c; H=d;}; + +// if (d>c) G=3; else G=4; + +// if (!(d<=c)) G=3; else G=4; + + return c; +} + + +int main3(void){ + G=0; + H=1; + p = &G; + q = &H; + +// if (p==q) *p=2; + + return *q; +} + +int main4(void) { + int e1,e2; + int c = e1?0:((e2)?1:2); + int d = e1?1:((e2)?2:3); + + G = 20; + H = 30; + + if (d<c) {G=d; H=c; } else G=4; + +// if (!(d<=c)) G=3; else G=4; + + return c; +} + +void main(void) +{ + q = t; + p = t + G; + if ((p >= &t[10]) && (p <= &t[99])) + q = p; +} + +void def(void) +{ + if (J) + G = H; +} + +int main5(void) +{ + G = 0; + if (G) H=J; + + return 1; +} + +int main6(int c, int d) +{ + G = 0; + if (G) if (d) G=2; else G = 1; + // G isn't modified + return 1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/implies.i frama-c-20111001+nitrogen+dfsg/tests/misc/implies.i --- frama-c-20110201+carbon+dfsg/tests/misc/implies.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/implies.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +int A,B; + +int main(int c, int d) +{ + A = !!d; + /*@ assert ((A ==> \false) ==> \false); */ + + /*@ assert c ==> \false; */ + return 1 + c; + +} \ No newline at end of file diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/incorrect_reduce_expr.i frama-c-20111001+nitrogen+dfsg/tests/misc/incorrect_reduce_expr.i --- frama-c-20110201+carbon+dfsg/tests/misc/incorrect_reduce_expr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/incorrect_reduce_expr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + OPT: -memory-footprint 1 -val -absolute-valid-range 32-36 +*/ + +char t[5]; +int *p; +int x; +void main(int c) +{ + x = 13; + p = (int*)32; + if (c) p+=1; + *(char*)p = 13; +} + + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/infinite.i frama-c-20111001+nitrogen+dfsg/tests/misc/infinite.i --- frama-c-20110201+carbon+dfsg/tests/misc/infinite.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/infinite.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +int G; +void main () { + int count; + G++; + if (G==1) + while(1) { + G++; + if(G==5) break; + pause(3); + G--; + }; + G=0; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/init_from_cil.i frama-c-20111001+nitrogen+dfsg/tests/misc/init_from_cil.i --- frama-c-20110201+carbon+dfsg/tests/misc/init_from_cil.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/init_from_cil.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ +/* run.config + OPT: -load-script tests/misc/init_from_cil.ml +*/ + +int f(int x); + +int main () { return f(0); } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/init.i frama-c-20111001+nitrogen+dfsg/tests/misc/init.i --- frama-c-20110201+carbon+dfsg/tests/misc/init.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/init.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,18 @@ +const char S[5] = "12345"; + +struct t1 { int x; int y; int name[10];} v1; +struct t1 TS[29] = {1,3,01234567890}; +struct t2 { int x2; short int y2; char *ptr;} v2; +char C; +char PC[]= "lkjlj"; +struct t2 T2[50] = {{1,2,&PC[0]},{1,2,0}}; + +int T[10] = {1,0}; +int U[] = {3,4}; +int x = sizeof(U); +int y = sizeof(T); + + +int main (void) { + return sizeof(U); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/initialized.c frama-c-20111001+nitrogen+dfsg/tests/misc/initialized.c --- frama-c-20110201+carbon+dfsg/tests/misc/initialized.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/initialized.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,17 @@ +extern int b1, b2, b3; + +int main () { + int r1, x1, x2, r2, x3, r3; + + if (b1) x1 = 1; + //@ assert \initialized(&x1); + r1 = x1+1; + + if (b2) + x2 = r2 + 1; + + if (b3) x3 = 1; + r3 = x3 + 1; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/inout_formals.i frama-c-20111001+nitrogen+dfsg/tests/misc/inout_formals.i --- frama-c-20110201+carbon+dfsg/tests/misc/inout_formals.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/inout_formals.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +/*run.config + OPT: -inout -input-with-formals -inout-with-formals +*/ +int x, y; + +void main(int * const i) { + *i=0; + if (*i==x) *i=y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/inout.i frama-c-20111001+nitrogen+dfsg/tests/misc/inout.i --- frama-c-20110201+carbon+dfsg/tests/misc/inout.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/inout.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,69 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -inout -deps -main inout_11_0 -journal-disable + OPT: -memory-footprint 1 -inout -deps -main inout_11_3 -journal-disable + OPT: -memory-footprint 1 -inout -deps -main never_terminate -journal-disable + OPT: -memory-footprint 1 -inout -deps -main may_not_terminate -journal-disable + OPT: -memory-footprint 1 -inout -deps -main call_may_not_terminate -journal-disable +*/ + +int Xt, Xs, Xs_I, Ys, Ys_I, Z, I; + +void inout_11_0 (int i1, int i2, int *i) { + Xs_I = Xs_I + 1; + Xt = I ; + Xs = i1 ; + Ys = i1 + i2 ; + + *i = 0; + Z = *i; +} + + +const int I_size=8; + +const int Itab[8]={-40,-25,-15,-5,5,15,25,40}; +int inout_11_3 (int i1, int es, int i2) { + int r; + es = i1 ; + Xs = es ; + + if (i2 < Itab[0]) + r=-2; + else + if (i2>=Itab[I_size-1]) + r=-1; + else + for(Z=0;Z<I_size-1;Z++) + { + if ((i2>=Itab[Z])&&(i2<Itab[Z+1])) + r=Z; + } + return r; +} + +void never_terminate (int i1_nt, int i2_nt, int i3_nt, int es, int e) { + Xs = i1_nt; + es = i2_nt ; + Xs = es ; + Xs = i3_nt ; + while (1) ; + Z = e ; +} + +int I5_nt ; +void may_not_terminate (int i1, int i2, int i3, int i4, int i5_nt, int es, int e) { + Xs = i1; + es = i2 ; + if (i4) { + Xs = i5_nt + I5_nt ; + while (1) ; + Z = e ; + } + Xs = es ; + Xs = i3 ; +} + +void call_may_not_terminate (int j1, int j2, int j3, int j4, int j5, int c1, int c2) { + may_not_terminate(j1, j2, j3, j4, j5, c1, c2) ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/inout_proto.i frama-c-20111001+nitrogen+dfsg/tests/misc/inout_proto.i --- frama-c-20110201+carbon+dfsg/tests/misc/inout_proto.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/inout_proto.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,20 @@ +/*run.config + OPT: -inout -input-with-formals -inout-with-formals +*/ + +typedef unsigned char BYTE; +typedef BYTE * MESSAGE_ADDR_TYPE; + + +//@ assigns *RETURN_CODE \from MESSAGE_ADDR[0..length], length; +extern void SendBuffer + (const MESSAGE_ADDR_TYPE /* Array */ /* in */ MESSAGE_ADDR, + const int /* in */ length, + int * const /* out */ RETURN_CODE); + + +void main(const MESSAGE_ADDR_TYPE msg) +{ + int ret; + SendBuffer((MESSAGE_ADDR_TYPE) &msg, 4, &ret); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/input.i frama-c-20111001+nitrogen+dfsg/tests/misc/input.i --- frama-c-20110201+carbon+dfsg/tests/misc/input.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/input.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +int f(int x, ...); + +int a,b; + +int main () { + + return f(a,b); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/invalid_access.i frama-c-20111001+nitrogen+dfsg/tests/misc/invalid_access.i --- frama-c-20110201+carbon+dfsg/tests/misc/invalid_access.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/invalid_access.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +int t[10]; +int x,*p,y,z; + +void main (int c,int d) { + p=d?t:(t+1); + p[0]=5; + p[1]=6; + p[2]=5; + z = p[!d]; +/* p[3]=5; + p[4]=5; + p[5]=5; + p[6]=5; + p[7]=5; + p[8]=5; + p[9]=5;*/ +/* y=p[1]; + if (c>=0 && c <=15) x = p[c];*/ +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/invalid_lval_arg.i frama-c-20111001+nitrogen+dfsg/tests/misc/invalid_lval_arg.i --- frama-c-20110201+carbon+dfsg/tests/misc/invalid_lval_arg.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/invalid_lval_arg.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +void f(int); + +int X; + +void g(int x) +{ + X = x + 1; +} + +void (*p)(int); + +main(int c){ + p = c&1? f : g; + if (c&2) + f(**(int**)0); + else if (c&4) + g(**(int**)0); + else + p(**(int**)0); + return X; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/inversion2.i frama-c-20111001+nitrogen+dfsg/tests/misc/inversion2.i --- frama-c-20110201+carbon+dfsg/tests/misc/inversion2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/inversion2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +int T[3] = {3,1,2}; +int TT[3][5] = {{3,3,3,0,0}, {1,0,0,0,0}, {2,2,0,0,0}}; + +void main() { + int i,j=77,G=99; + for (i=0 ; i < 3 ; i++) { + for (j=0; j < T[i]; j++) + G = 15/(TT[i][j]);}; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/inversion.i frama-c-20111001+nitrogen+dfsg/tests/misc/inversion.i --- frama-c-20110201+carbon+dfsg/tests/misc/inversion.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/inversion.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,47 @@ + +int x = 0; +int y = 0; +int z = 0; +int *pz = &z ; +int *px = &x ; +int *py = &y ; + +int X = 0; +int *pX; + +struct s +{ int ok; + int **p; } t[5]={ {0,0}, {1,&pz}, {1,&py} , {0,0} }; + +struct s t2[5]={ {0,0}, {0,0}, {1,&px}, {0,0} }; +int ii[2]; + +void main(void) +{ + int i; volatile int k=0; + pX = k ? 0 : &X; + for (i=0 ; i < 5; i++) + { + if (t[i].ok) + **(t[i].p) = i; + X = i; + } + + for (ii[1]=0 ; ii[1] < 5; ii[1]++) + { + if (t2[ii[1]].ok) + **(t2[ii[1]].p) = ii[1]; + X = ii[1]; + } +} + +void g (void) +{ + int c = -25; + + + while (c) + { + c++; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/jacques.i frama-c-20111001+nitrogen+dfsg/tests/misc/jacques.i --- frama-c-20110201+carbon+dfsg/tests/misc/jacques.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/jacques.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,42 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable +*/ + +int t[4]; + +int *p; +int *q; + +void f(void) +{ + *p = 4; + *q = 5; +} + +int A,B,C; +void main(int a, int b, int *pp) +{ + + CEA_f(pp); + + //@ assert \valid(pp); + + CEA_f(pp); + + *pp = 5; + + //@ assert *pp + 1 == 6; + + A = 10; + B = 11; + + p = &A; + q = &B; + f(); + + p = &A; + q = &A; + f(); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/join_misaligned.i frama-c-20111001+nitrogen+dfsg/tests/misc/join_misaligned.i --- frama-c-20110201+carbon+dfsg/tests/misc/join_misaligned.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/join_misaligned.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,27 @@ + +int t[5]={0}; +int u[5]={1,1,1,1,1}; +int v[7]={1,1,1,1,1,1,1}; +int w[7]={0}; +char x[5]={0}; + +void main(int c) +{ + if (c) + { + ((char*)t)[6]='a'; + ((char*)u)[6]='c'; + *((short*)((char*)v+6))=27; + *((short*)((char*)w+6))=57; + } + else + { + ((char*)t)[6]='b'; + ((char*)u)[6]='d'; + *((short*)((char*)v+7))=29; + *((short*)((char*)w+7))=59; + x[0]=1; + x[1]=0; + x[2]=1; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/label.i frama-c-20111001+nitrogen+dfsg/tests/misc/label.i --- frama-c-20110201+carbon+dfsg/tests/misc/label.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/label.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,44 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable +*/ +int a,b,d,e,i,*p,*q; + +void f(int, int*); + +void main(int c) +{ + b = 1; + if (c) p = &a; else p = &b; + *p = 2; + + a = (int)(&d + 1); + + q = &a; + + L: *((char*)&p+i) = *((char*)&q+i); + i++; + if (i<4) goto L; +/* + *p = (int) &e; + + f(0, &i); + + f(1, &a); + + f(0, &a); +*/ + return; +} + +void f(int x, int *r) +{ + a = x; + (*r)++; + if (x - a != 0) + *p = a; + + q = x ? &a : (int*)0; + + //@ assert \valid(q); + *q = b; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/lazy.i frama-c-20111001+nitrogen+dfsg/tests/misc/lazy.i --- frama-c-20110201+carbon+dfsg/tests/misc/lazy.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/lazy.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -undefined-pointer-comparison-propagate-all +*/ +int a=-1; +int b, d; +int *q, *r, *s, *t; +void main (int *p, int c, int d) { + + q = &a - !c; + if (q) r=q; + + s = &a - !d; + if (!s) t=s; + + if (p && *p ) *p = 0 ; + if (&a) { a=0; b=1; } + if (&a+1) a+=2; + if (&a+2) a+=4; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/leaf2.i frama-c-20111001+nitrogen+dfsg/tests/misc/leaf2.i --- frama-c-20110201+carbon+dfsg/tests/misc/leaf2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/leaf2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +typedef int T; +extern T f(char* p,int q, int i); + +T G,H,I; +void main (void) { + G = f(&H,(int)&I,17); + if (G == -1) G++; + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/leaf.i frama-c-20111001+nitrogen+dfsg/tests/misc/leaf.i --- frama-c-20110201+carbon+dfsg/tests/misc/leaf.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/leaf.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,70 @@ +int T[30] = {1}; + +int f_int_int(int x); +int * f_int_star_int(int x); +int **f_int_star_int_star_int(int x); + +int f_star_int_cint(const int *x); + +/* 3 identicals prototypes */ +int f_star_int_int(int *x); +int f_tab_int_int(int x[]); +int f_tab3_int_int(int x[3]); + +int cv1=10, cv2=20, cv3=30 ; +struct _st_star_cint { const int * const p ; } + st_star_cint_1={&cv1}, + st_star_cint_2={&cv2}, + st_star_cint_3={&cv3} ; + +int v1=10, v2=20, v3=30 ; +struct _st_star_int { int * p ; } + st_star_int_1={&v1}, + st_star_int_2={&v2}, + st_star_int_3={&v3} ; + +struct _st_tab3_int { int t[3] ; } + st_tab3_int_1={10, 11, 12}, + st_tab3_int_2={20, 21, 22}, + st_tab3_int_3={30, 31, 32} ; + +struct _st_star_cint f_st_star_cint_st_star_cint(struct _st_star_cint s) ; +struct _st_star_int f_st_star_int_st_star_int (struct _st_star_int s) ; +struct _st_tab3_int f_st_tab3_int_st_tab3_int (struct _st_tab3_int s) ; + +int f_star_st_star_cint_int (struct _st_star_cint * s) ; +int f_star_st_star_int_int (struct _st_star_int * s) ; +int f_star_st_tab3_int_int (struct _st_tab3_int * s) ; + +void main() { + int c,d; + T[0]=f_int_int(0); /* T[0] modified */ + + int *p = f_int_star_int(0); + CEA_F(*p); + *p = 5; + CEA_F(*p); + + int **pp =f_int_star_int_star_int(0); + CEA_G(*pp); + CEA_F(**pp); +// if (*pp==&d) **pp = 6; + CEA_G(*pp); + CEA_F(**pp); + + T[2]=f_star_int_cint(&T[3]); /* T[2] modified */ + + f_star_int_int(&(T[4])); /* only T[4] modified */ + f_tab3_int_int(&T[6]); /* only T[6..8] modified */ + f_tab_int_int(&T[10]); /* only T[10] modified */ + + st_star_cint_1 = f_st_star_cint_st_star_cint(st_star_cint_2); /* only st_star_cint_1 modified */ + st_star_int_1 = f_st_star_int_st_star_int (st_star_int_2) ; /* st_star_int_1 modifed, v2 SHOULD BE modified */ + st_tab3_int_1 = f_st_tab3_int_st_tab3_int (st_tab3_int_2) ; /* only st_tab3_int_1 modified */ + + f_star_st_star_cint_int(&st_star_cint_3); /* st_star_cint_3.p modified */ + f_star_st_star_int_int (&st_star_int_3) ; /* v3 SHOULD BE modified */ + f_star_st_tab3_int_int (&st_tab3_int_3) ; /* st_tab3_int_3 SHOULD BE modified */ + +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/leaf_spec.i frama-c-20111001+nitrogen+dfsg/tests/misc/leaf_spec.i --- frama-c-20110201+carbon+dfsg/tests/misc/leaf_spec.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/leaf_spec.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,28 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main1 -journal-disable +*/ + +void f(int * x, int * y, int **z, int a, char b); + + +void f1(int y); + +int g(int x); + +int *h(int y); + +int *k( int *l); +int *k0( int const *l); + +void main () { + f1(0); + g(2); + h(0); + k(0);k0(0); +} + +void main1(void) +{ + f(0,0,0,0,0); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/library.i frama-c-20111001+nitrogen+dfsg/tests/misc/library.i --- frama-c-20110201+carbon+dfsg/tests/misc/library.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/library.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main main -context-depth 3 -journal-disable +*/ +int f_int(int x); +int *f_star_int(int x); + +int ****G; + +int G0,*G1; +void main(void) { + G0 = f_int(2); + G1 = f_star_int(5); + *G1 = 5; + ****G=1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/limits.c frama-c-20111001+nitrogen+dfsg/tests/misc/limits.c --- frama-c-20110201+carbon+dfsg/tests/misc/limits.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/limits.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,31 @@ +/* run.config + OPT: -memory-footprint 1 -val -journal-disable -val-signed-overflow-alarms -cpp-command "gcc -C -E -nostdinc -I. -Ishare/libc" +*/ +#include <limits.h> + +int cl, cu, ucu; +int il, iu, uiu; +long ll, lu; +unsigned long ulu; +long long lll, llu; +unsigned long long ullu; + +main() +{ + cl = CHAR_MIN; + cu = CHAR_MAX; + ucu = UCHAR_MAX; + + il = INT_MIN; + iu = INT_MAX; + uiu = UINT_MAX; + + ll = LONG_MIN; + lu = LONG_MAX; + ulu = ULONG_MAX; + + lll = LLONG_MIN; + llu = LLONG_MAX; + ullu = ULLONG_MAX; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/local.i frama-c-20111001+nitrogen+dfsg/tests/misc/local.i --- frama-c-20110201+carbon+dfsg/tests/misc/local.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/local.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,30 @@ +int *X, *Y, *Z, *T, *U, *V; + +int * f(void) +{ + int a,b,c; + X = &a; + return &b; +} + +int *g(void) +{ + volatile int d=0; + T = f(); + U = d ? T : &d; + return U; +} + +int *h(int *x) +{ + return x+1; +} + +void main(void) +{ + int e; + Y = f(); + Z = g(); + Frama_C_dump_each(); + V = h(&e); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/local_variables.i frama-c-20111001+nitrogen+dfsg/tests/misc/local_variables.i --- frama-c-20110201+carbon+dfsg/tests/misc/local_variables.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/local_variables.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,48 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -inout +*/ + +int A,B,C,D,R,S; + +int u() +{ + int ru, wu; + ru = C; + return w(&ru, &wu); +} + +int v() +{ + int rv, wv; + rv = D; + return w(&rv, &wv); +} + +int w(int *pr, int *pw) +{ + *pw = A; + if (unkn()) B = *pr; + return *pr; +} + +int main (int c, int * p) { + + R=u(); + S=v(); + + if (c) { + int x = 1; + p = &x; + } + { + int y = 0; + { int z = 1; + int t = y + z; + } + } + for (int i = 0; i<5; i++) { + int a = 0; + a += i; + } + return *p; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/lock.i frama-c-20111001+nitrogen+dfsg/tests/misc/lock.i --- frama-c-20110201+carbon+dfsg/tests/misc/lock.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/lock.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,53 @@ +/* run.config + STDOPT: +"-main locks0_good" + */ + +/*@ ghost int ghost_loctable[100] ;*/ + +/*@ axiomatic Locked { + @ predicate locked{L}(struct mutex *m); + @ // reads m, ghost_loctable[..] ; + @ + @ axiom locked_dummy_axiom_for_reads{L} : + @ \forall struct mutex *m; + @ locked(m) && ghost_loctable[0] == 0 ==> + @ locked(m) && ghost_loctable[0] == 0 ; + @ } + @*/ + +/*@ + requires !(locked(m)); + ensures locked(m); + assigns ghost_loctable[0..99]; + + */ +void acquire_lock(struct mutex *m); + +/*@ + requires locked(m); + ensures !(locked(m)); + assigns ghost_loctable[..]; + + */ +void release_lock(struct mutex *m); + +/*@ + requires !(locked(m)); + assigns ghost_loctable[..]; + behavior success: + ensures (\result != 0) ==> locked(m); + + behavior failure: + ensures (\result == 0) ==> !(locked(m)); + + */ +int try_acquire_lock(struct mutex *m); + +struct mutex *pmutex; + +/*@ requires !(locked(pmutex)); */ +void locks0_good(int flag) +{ + acquire_lock(pmutex); + release_lock(pmutex); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/logtrap.i frama-c-20111001+nitrogen+dfsg/tests/misc/logtrap.i --- frama-c-20110201+carbon+dfsg/tests/misc/logtrap.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/logtrap.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +/* run.config + DONTRUN: waiting ocaml 3.12 +*/ +// OPT: -load-script tests/misc/logtrap.ml +// Should raise an assertion-failure exception. + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/logtrap.ml frama-c-20111001+nitrogen+dfsg/tests/misc/logtrap.ml --- frama-c-20110201+carbon+dfsg/tests/misc/logtrap.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/logtrap.ml 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +let main () = + begin + Log.print_on_output + (fun fmt -> + Format.fprintf fmt "Start.@." ; + if true then assert false ; + Format.fprintf fmt "End.@." ; + ) + end + +let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/long_const.i frama-c-20111001+nitrogen+dfsg/tests/misc/long_const.i --- frama-c-20110201+carbon+dfsg/tests/misc/long_const.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/long_const.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +void main() { + unsigned long long i; + i = 0xFFFF804000000000UL; + unsigned long j= ((((((256ULL) >> 8) * 0xffff000000000000UL) | (256ULL << 39) )) + (1ULL << 39)/2ULL); + CEA_f(sizeof(long),i,j); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/long.i frama-c-20111001+nitrogen+dfsg/tests/misc/long.i --- frama-c-20110201+carbon+dfsg/tests/misc/long.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/long.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ + +int i,j,k; + +void f(void) +{ + for (i=0;i<1000;i++); +} + +void main(void) +{ + for (j=0;j<1000;j++) + f(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/long_ident.c frama-c-20111001+nitrogen+dfsg/tests/misc/long_ident.c --- frama-c-20110201+carbon+dfsg/tests/misc/long_ident.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/long_ident.c 2011-10-10 08:39:03.000000000 +0000 @@ -6,7 +6,6 @@ */ int f(int *q) ; - #define LV X_9999999999999999999999999999999999999999999999999999 int LV; enum { OK = 1, diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop1.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop1.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +char U[100]={1, 2}; +char NULL_GLOBAL_LOOSING_BITS_ONE_BY_ONE = 0; +int main () { + int i; + for(i=0;i<=100; i++) + { + U[i]=7; + } + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop2.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop2.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,83 @@ +int i,j,k,l,n,r; +struct T {int a,b;} G[5]={0}; + +void g(const int b) ; + +void main() { + n=5; + for (i=0; i<n ; i++) + { + G[i].a = i+55; + G[i].b = i+57; + } +} + + +static char Reg5; +void g(const int b) { + Reg5 = Reg5 & (~(0x80)); +} + +void main1(void) +{ + + { + n = 1; + i = 0; + { + { + { + + + if (i < n) { + + } else { + goto while_0_break; + } + G[i].a = 1; + i += 1; + + + if (i < n) { + + } else { + goto while_0_break; + } + G[i].a = 1; + i += 1; + while (1) { + while_1_continue: /* CIL Label */ ; + while_0_continue: /* CIL Label */ ; + if (i < n) { + + } else { + goto while_0_break; + } + G[i].a = 1; + i += 1; + } + } + while_1_break: /* CIL Label */ ; + } + while_0_break: /* CIL Label */ ; + } + + return; +} +} + + +void main2(void) +{ + main(); + l1: + main1(); + l2: + g(0); + if(i) goto l1; + k=0; + if(j) goto l2; + l=0; + +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_annot.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_annot.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_annot.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_annot.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + OPT: -simplify-cfg -keep-switch -print -check -journal-disable + OPT: -simplify-cfg -print -check -journal-disable +*/ + +void f() { + int i = 0; + //@ loop invariant 0 <= i <= 10; + while (i < 10) { // @ invariant 0 <= i < 10; + ++i; + //@ assert 0 <= i <= 10; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_array.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_array.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_array.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_array.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,23 @@ +long long T[10000]; +int U[10000]; +void main () { + int i,j; + for (i=0;i<5; i++) + T[i] = 2; + + for (j=6;j<10000; j++) + T[j] = 7; + + i=0; + while(1) + { + U[i]=0; + if (i == 200) U[i]=-1; + i = 1000 - i; + if (i < 500) + i++; + if (i == 400) + goto l_end_loop; + } + l_end_loop: +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,96 @@ +int i,j,k,n,r; + +void main() { + int i; + r=0; + n=50; + for (i=0; i<n ; i+=2) { + CEA_F(i); + r = i+r; } +} + +void main1() { + r=2; + k=j?0:1;/* ICI 1 */ + if (k) i = 1; else i = 4; + + if (i<2) i+=r; + +} + +void main2() { + int i,j,k; + r = 0; + n = 0; + for (i=0; i<(n+1) ; i++) +/* ICI 2 */ + for (j=0; j <(n+1) ;j /* ICI 3 */ ++) + for (k=0; k <(n+1); k++) + r = i+j+k+r+1;/* ICI 4 */ +} + +/* Infinite non trivial loop */ +void main3() { + int i; + r = 0; + n = 0; + for (i=0; i<(n+1) ; ) + r = i+1; +} + +void main4(void) +{ + i = 0; + j= 0; + while(1) + { + k = i; + if (i < j) break; + k = r; + } + /* k does not depend on r when exiting this loop. */ +} + +int G; + +void main5(void) +{ int i___0 ; + + { + G = -1; + r = 0; + n = 2; + i___0 = 1; + { + while (1) +{ + while_0_continue: /* CIL Label */ ; + if (i___0 < n+1 ) { + G=0; + r = r+1; + i___0 += 1; + } else { + G=1; + goto while_0_break; + } + } + while_0_break: /* CIL Label */ ; + } + + return; + } +} + + +void main6() { + int i, b; + r=0; + n=5; + + for (i=0; i<n ;) { + r = i+r; + if (b) i--; + b = b&&b; + if (r<b) i+=3; else i+=6; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loopinv.c frama-c-20111001+nitrogen+dfsg/tests/misc/loopinv.c --- frama-c-20110201+carbon+dfsg/tests/misc/loopinv.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loopinv.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,27 @@ +/* run.config +OPT: -pp-annot -val -then -report +*/ + +/*@ requires \valid(&t[0..s-1]); + requires 1 <= c < s; */ +void init (int *t, int c, int s) { + int* p = t; + /*@ loop invariant p < &t[s-1]; */ + while(1) { + *(++p) = 1; + if(p >= t+c) break; + } +} + + +void main (int c) { + int t1[72]; + int t2[11]; + + if (c >= 1 && c < 72) { + init(t1, c, 72); + + if (c < 8) + init(t2, c, 11); + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_join.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_join.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_join.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_join.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +int U[10000]; +void main () { + int i; + i=0; + while(1) + { + U[i]=0; + if (i == 200) U[i]=-1; + i = 1000 - i; + if (i < 500) + i++; + if (i == 400) + goto l_end_loop; + } + l_end_loop: +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_long.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_long.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_long.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_long.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +char T[368200]; + +int main(int c1, int c2) { + int i; + for(i = 0; i < 368; i++) { + T[i] = 33; + } + return i; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_no_var.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_no_var.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_no_var.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_no_var.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,4 @@ +int main() +{ + while(1) {} +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_simple.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_simple.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_simple.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_simple.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,29 @@ +int i,j,k,n,r; + +#if 0 +void main2() { + r=0; + goto L; + n=5; + + for (int i=0; i<n ; i++) { + L: + r = i+r; + if(r && n-- || n++ && n--) r=99; + + } + + r=10; +} +#endif + +int main() { + r = 0; + k= 0 ; + n = 2; + for (i=0; i<n; i++) + for (j=0;j<n; j++) + for (k=0; k<n; k++) + r = i+j+k+r+1; + return r; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_test.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_test.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_test.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_test.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,111 @@ +/* run.config + DONTRUN: cannot find entry point: cent_onzes + OPT: -memory-footprint 1 -val -main test_onzes -journal-disable + OPT: -memory-footprint 1 -val -main cent_onzes -journal-disable +*/ + +/***************** var CMP cste **********************/ +int onze_0 (void) { + int onze; for (onze=1000; onze >= 12 ; onze--) ; return onze ; +} +int onze_1 (void) { + int onze; for (onze=1000; onze > 11 ; onze--) ; return onze ; +} +int onze_2 (void) { + int onze; for (onze=0; onze < 11 ; onze++) ; return onze ; +} +int onze_3 (void) { + int onze; for (onze=0; onze <= 10 ; onze++) ; return onze ; +} +int onze_4 (void) { + int onze; for (onze=0; onze != 11 ; onze++) ; return onze ; +} +/***************** cste CMP var **********************/ +int onze_5 (void) { + int onze; for (onze=1000; 12 <= onze ; onze--) ; return onze ; +} +int onze_6 (void) { + int onze; for (onze=1000; 11 < onze; onze--) ; return onze ; +} +int onze_7 (void) { + int onze; for (onze=0; 11 > onze; onze++) ; return onze ; +} +int onze_8 (void) { + int onze; for (onze=0; 10 >= onze; onze++) ; return onze ; +} +int onze_9 (void) { + int onze; for (onze=0; 11 != onze; onze++) ; return onze ; +} + +int r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; +void test_onzes(void) +{ + r0 = onze_0(); + r1 = onze_1(); + r2 = onze_2(); + r3 = onze_3(); + r4 = onze_4(); + r5 = onze_5(); + r6 = onze_6(); + r7 = onze_7(); + r8 = onze_8(); + r9 = onze_9(); +} + +/***************** !(var CMP cste) **********************/ +int cent_onze_0 (void) { + int cent_onze; for (cent_onze=1000; !(cent_onze < 112) ; cent_onze--) ; return cent_onze ; +} +int cent_onze_1 (void) { + int cent_onze; for (cent_onze=1000; !(cent_onze <= 111) ; cent_onze--) ; + return cent_onze ; +} +int cent_onze_2 (void) { + int cent_onze; for (cent_onze=0; !(cent_onze >= 111) ; cent_onze++) ; + return cent_onze ; +} +int cent_onze_3 (void) { + int cent_onze; for (cent_onze=0; !(cent_onze > 110) ; cent_onze++) ; + return cent_onze ; +} +int cent_onze_4 (void) { + int cent_onze; for (cent_onze=0; !(cent_onze == 111) ; cent_onze++) ; + return cent_onze ; +} +/***************** !(cste CMP var) **********************/ +int cent_onze_5 (void) { + int cent_onze; for (cent_onze=1000; !(112 > cent_onze) ; cent_onze--) ; return cent_onze ; +} +int cent_onze_6 (void) { + int cent_onze; for (cent_onze=1000; !(111 >= cent_onze) ; cent_onze--) ; + return cent_onze ; +} +int cent_onze_7 (void) { + int cent_onze; for (cent_onze=0; !(111 <= cent_onze) ; cent_onze++) ; + return cent_onze ; +} +int cent_onze_8 (void) { + int cent_onze; for (cent_onze=0; !(110 < cent_onze) ; cent_onze++) ; + return cent_onze ; +} +int cent_onze_9 (void) { + int cent_onze; for (cent_onze=0; !(111 == cent_onze) ; cent_onze++) ; + return cent_onze ; +} + +/***************** **********************/ + +int c0,c1,c2,c3,c4,c5,c6,c7,c8,c9; +void test_cent_onzes(void) +{ + c0 = cent_onze_0(); + c1 = cent_onze_1(); + c2 = cent_onze_2(); + c3 = cent_onze_3(); + c4 = cent_onze_4(); + c5 = cent_onze_5(); + c6 = cent_onze_6(); + c7 = cent_onze_7(); + c8 = cent_onze_8(); + c9 = cent_onze_9(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/loop_wvar.i frama-c-20111001+nitrogen+dfsg/tests/misc/loop_wvar.i --- frama-c-20110201+carbon+dfsg/tests/misc/loop_wvar.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/loop_wvar.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,43 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -no-annot -val -journal-disable + OPT: -memory-footprint 1 -val -journal-disable + OPT: -memory-footprint 1 -val -main main_err1 -journal-disable + OPT: -memory-footprint 1 -val -main main_err2 -journal-disable +*/ + +int i,j; + +void main(void) +{ int n = 13; +// ceci était une annotation, mais on ne fait pas moins bien sans +// maintenant: +// loop pragma WIDEN_VARIABLES i; + /*@ loop pragma WIDEN_HINTS i, 12, 13; */ + for (i=0; i<n; i++) + { + j = 4 * i + 7; + } +} + + +void main_err1(void) +{ int n = 13; + /*@ loop pragma WIDEN_HINTS 12 ; */ + for (i=0; i<n; i++) + { + j = 4 * i + 7; + } +} + + + + +void main_err2(void) +{ int n = 13; + /*@ loop pragma WIDEN_VARIABLES 12; */ + for (i=0; i<n; i++) + { + j = 4 * i + 7; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/m12_2.i frama-c-20111001+nitrogen+dfsg/tests/misc/m12_2.i --- frama-c-20110201+carbon+dfsg/tests/misc/m12_2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/m12_2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,91 @@ +/* run.config + OPT: -unspecified-access +*/ +// Misra C Enforcement Testing +// +// Rule 12.2 Required +// The value of an expression shall be the same under any order of +// evaluation that the standard permits. +// 1 exp arithmetique qui n'est pas un appel de fct, &&, |-, ?: ni "," +// est evaluee dans un ordre indeterminé. On ne doit pas se baser sur l'ordre +// d'evaluation des termes de ces expressions +// 12.2.1: si un terme d'une exp est un operateur d'increment ou de decrement +// d'une var alors les autres termes ne doivent ni lire ni ecrire cette variable +// 12.2.2: l'ordre d'evaluation des args d'un appel de fct etant indefini, il +// faut que pour toute paire d'args (a,b) wr(a) inter rd(b)=0 et +// rd(a) inter wr(b)=0 +// 12.2.3: +// 12.2.4: +// 12.2.5: +// 12.2.6: +/// + +typedef int SI_32; + +static void func46 ( SI_32 m, SI_32 n ) ; + +static SI_32 func46a ( SI_32 m, SI_32 n ) +{ + return m + n; +} + +static struct st +{ +int st_m; +int st_n; +} local_st; + +SI_32 main ( void ) +{ + + SI_32 i = 3; + SI_32 x = 3; + SI_32 y = 3; + SI_32 z = 3; + + struct st this_st; + + this_st.st_m = 1; + this_st.st_n = 2; + + z = ( y=i,++y ) + i++; // RULE 12.2.1: is est lu dans l'autre terme + + z = ++i + ( y=x,++y ) ; // y n'est PAS lu dans un autre terme + + z = ++i + ( y=i,++y ) ; // RULE 12.2.1: i est lu dans un autre terme + + z = ++i + ( 1 || i++ ) ; + + y = func46a ( x, ( x=3,x++ ) ) ; // RULE 12.2.2: x est lu dans le terme de G + + y = func46a ( x, ( i=2,i+3 ) ) ; // pas de conflits entre arguments effectifs + + z = i + i++; // RULE 12.2.1 + + z = ( y=x,++y ) + i++; + + z = ( i = 3 ) + i + 8; // RULE 12.2.5 + + z = ( this_st.st_m = 3 ) + + this_st.st_m + 8; // RULE 12.2.5 + + z = ( this_st.st_m = 3 ) + + this_st.st_n + 8; + + z = ++i + ( ( y += 2,y ) ,y++ ) ; // pas de conflits + + z = ( ( ++i+i ) >0 ) ? ++i : --i;// RULE 12.2.1: conflits entre terme du + + + z = ( i>0 ) ? ++i : --i; + + z = ++i + ( 3*8*1 && i++ ) ; // RULE 12.2.1: conflits entre terme du + + + z = ++i + ( y, y++ ) ; + + z = ++i + ( 3*8*0 || i++ ) ; // RULE 12.2.1: idem + + z = ++i + ( i, y++ ) ; // le resultat de terme droit ne depend pas de i + + return z; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/memcpy.c frama-c-20111001+nitrogen+dfsg/tests/misc/memcpy.c --- frama-c-20110201+carbon+dfsg/tests/misc/memcpy.c 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/memcpy.c 2011-10-10 08:39:03.000000000 +0000 @@ -1,12 +1,46 @@ +/* run.config + STDOPT: +"-slevel-function" +"init:20" +"-then" +"-report" +*/ #include "share/builtin.h" + +extern int b; +extern unsigned int i; + +char src[20]; +char dst1[20], dst2[20], dst3[20]; +char dst4[20]; + +void init () { + for (int j=0;j<20;j++) { + src[j] = j+1; + dst1[j] = -1; + dst2[j] = -1; + dst3[j] = -1; + dst4[j] = -1; + } +} + + struct t1 { int x; int y; int* p;} v1,v2, v3; struct t1 t[4]; -int main (int a, int b){ +void main (int a, int b){ + init (); + + //@ assert 5 <= b && b <= 15; + Frama_C_memcpy(dst1+1, src+2, b); + + Frama_C_memcpy(dst2+1, src+2, 2*b); + + //@ assert 5 <= b && b <= 14; + Frama_C_memcpy(dst3+5, src+2, b); + + Frama_C_memcpy(dst4+5, src+2, 2*b); + v2 = v2; v2.p = &v1.y; t[1]=v2; - + v1.x = 5; v1.y = 7; Frama_C_memcpy(&v2, &v1, sizeof(v1)); @@ -15,5 +49,5 @@ Frama_C_memcpy(&v3, t+(int)t, sizeof(v1)); - Frama_C_memcpy(&v2 + (int)&v2, &v1, sizeof(v1)); + // Frama_C_memcpy(&v2 + (int)&v2, &v1, sizeof(v1)); } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/merge_bits.i frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bits.i --- frama-c-20110201+carbon+dfsg/tests/misc/merge_bits.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bits.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +char T[] = { 1,0,0,0,1,2,3,4,5,0,1,1,1 } ; +int main() { + CEA_F(*((int*)(T))); + CEA_F(*((int*)(T+1))); + CEA_F(*((int*)(T+4))); + CEA_F(*((int*)(T+9))); + *((int*)(T+2))=2<<31 | 2 << 30 | 2 << 27 | 2 << 3; + CEA_F(*((int*)(T))); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/merge_bts0948_1.i frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bts0948_1.i --- frama-c-20110201+carbon+dfsg/tests/misc/merge_bts0948_1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bts0948_1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +/* run.config + DONTRUN: main test is merge_bts0948.i +*/ + +/*@ requires \valid((char*)dest_1); */ +extern void *memcpy(void * dest_1); diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/merge_bts0948_2.i frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bts0948_2.i --- frama-c-20110201+carbon+dfsg/tests/misc/merge_bts0948_2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bts0948_2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +/* run.config + DONTRUN: main test is merge_bts0948.i +*/ + +/*@ requires \valid((char*)dest_2); */ +extern void *memcpy(void * dest_2); diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/merge_bts0948.i frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bts0948.i --- frama-c-20110201+carbon+dfsg/tests/misc/merge_bts0948.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/merge_bts0948.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +/* run.config + OPT: tests/misc/merge_bts0948_1.i tests/misc/merge_bts0948_2.i -check -print +*/ + +/*@ requires \valid((char*)dest); +*/ +extern void *memcpy(void * dest); + +void* memcpy(void* region1) { return region1; } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/miel.i frama-c-20111001+nitrogen+dfsg/tests/misc/miel.i --- frama-c-20110201+carbon+dfsg/tests/misc/miel.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/miel.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,102 @@ +/* run.config + DONTRUN: cannot find entry point: main +*/ + +void g() { j(); +} + +void j() { j();} + +void h() { + j(); +} + +void h1() { + j(); +} + +void h2() { + j(); +} + +void h3() { + j(); +} + +void h4() { + j(); +} + +void h5() { + j(); + p0(); +} + +void l1() { + l2(); +} + +void l2() { + +} + +void r0() { + l1 (); +} +void r1() { + l1 (); +} +void r2() { + l1 (); +} +void r3() { + l1 (); +} + +/* +void ldkfadl(void) +{ + p1(); +} +*/ + +void p0() { + // p1 (); +} +void p1() { + p2 (); + p3 (); + p0(); +} +void p2() { + p1 (); + p3 (); +} +void p3() { + p1 (); + p2 (); +} + + +void g0() { + g2 (); +} +void g1() { + g2 (); +} +void g2() { + g3 (); +} +void g3() { + g4 (); + g5 (); +} +void g4() { + g6 (); g3 (); +} +void g5() { + g6 (); +} +void g6() { + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/mini_pointrer.i frama-c-20111001+nitrogen+dfsg/tests/misc/mini_pointrer.i --- frama-c-20110201+carbon+dfsg/tests/misc/mini_pointrer.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/mini_pointrer.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +int T[2]; +int**ppp; +int pp[2]; +int p; +void main(int c) { + pp [c] = &T[c]; + if (c) ppp = &pp; else ppp = &T[-1]; + **ppp=9; + + if (c>=0 && c<=5) T[c] = 4; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/misaligned_tabs.i frama-c-20111001+nitrogen+dfsg/tests/misc/misaligned_tabs.i --- frama-c-20110201+carbon+dfsg/tests/misc/misaligned_tabs.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/misaligned_tabs.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,67 @@ +char T[300]; + +struct st { short i1,i2; char c1,c2; short i3,i4 ;}; +struct st S1 = { 0x1111, 0x1111, 0x11,0x11, 0x1111, 0x1111} ; +struct st S2 = { 0x1111, 0x1111, 0x11,0x11, 0x1111, 0x1111} ; +struct st S3 = { 0x1111, 0x1111, 0x11,0x11, 0x1111, 0x1111} ; +struct st S4 = { 0x1111, 0x1111, 0x11,0x11, 0x1111, 0x1111} ; + +misaligned_struct() { + Frama_C_show_each_1 (S1.i1 == *(short*)&S1.c1); // ok + + *( (char *)&S1.i1)= 0x11; + Frama_C_show_each_2 (S1.i1 == 0x1111); // To do + Frama_C_show_each_3 (S1.i1 == S1.i2); // To do + Frama_C_show_each_4 (*(char *)&S1.i1 == S1.c2); // OK + + *( (char *)&S2.i1)= 0x11; + *(1+(char *)&S2.i1)= 0x11; + Frama_C_show_each_5 (S2.i1 == 0x1111); // ok + Frama_C_show_each_6 (S2.i1 == S2.i2); // ok + Frama_C_show_each_7 (*(char *)&S2.i2 == S2.c2); // OK + Frama_C_show_each_8 (*(char *)&S2.i2 == *(char *)&S4.i2); // OK + + *(1+(char *)&S3.i1)= 0x11; + *( (char *)&S3.i2)= 0x11; + *(1+(char *)&S3.i2)= 0x11; + *( (char *)&S3.i3)= 0x11; + *(1+(char *)&S3.i3)= 0x11; + *( (char *)&S3.i4)= 0x11; + + *( (char *)&S4.i1)= 0x11; + *(1+(char *)&S4.i1)= 0x11; + *( (char *)&S4.i2)= 0x11; + *(1+(char *)&S4.i2)= 0x11; + *( (int *)&S4.c1)= 0x1111; + *( (char *)&S4.i3)= 0x11; + *(1+(char *)&S4.i3)= 0x11; + *( (char *)&S4.i4)= 0x11; + *(1+(char *)&S4.i4)= 0x11; + + Frama_C_show_each_9 (S3.i1 == S4.i1); // To do + Frama_C_show_each_a (S3.i2 == S4.i2); // ok + Frama_C_show_each_b (S3.i3 == S4.i3); // ok + Frama_C_show_each_c (*((char *)&S3.i2) == *((char *)&S4.i2)); // OK + Frama_C_show_each_d (S3.c1 == S4.c2); // OK + Frama_C_show_each_e (*((char *)&S3.i2) == S4.c1); // Ok + Frama_C_show_each_f (*((char *)&S3.i1) == S4.c1); // Ok +} + +int main(int c1, int c2) { + int i; + + *(int*)(&T[0])=c1?1:2; + *(int*)(&T[4])=c2?1:2; + T[1]=T[5]; + *(int*)(&T[8])=*(int*)(&T[4]); + + misaligned_struct (); +/* for(i = 0; i < 36800; i++) { + T[i] = 33; + } +*/ + + if (c1) Frama_C_show_each_g (S1.i1 == *(short*)&S1.c1); // to do + + return i; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/mixed_val.i frama-c-20111001+nitrogen+dfsg/tests/misc/mixed_val.i --- frama-c-20110201+carbon+dfsg/tests/misc/mixed_val.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/mixed_val.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +short T[10] = {'a'}; +int a,b,c,d,e; +int main(){ + a=c?57:128073; + d=e?57:128073; + + T[0] = *(short*)(&a); +// T[1] = *((short*)(&a)+1); + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/modifies.i frama-c-20111001+nitrogen+dfsg/tests/misc/modifies.i --- frama-c-20110201+carbon+dfsg/tests/misc/modifies.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/modifies.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main main -journal-disable +*/ + +int TAB[10]; +int G,H,J; +void main () { + if (H) {H= 3; J++;TAB[4]--;}; + if (J) G=6; + if (G) H=1; + if (H) {TAB[1]++; TAB[6]++;}; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/modulo2.i frama-c-20111001+nitrogen+dfsg/tests/misc/modulo2.i --- frama-c-20110201+carbon+dfsg/tests/misc/modulo2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/modulo2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ + +main(int c) +{ + return 13 % (!c); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/modulo.i frama-c-20111001+nitrogen+dfsg/tests/misc/modulo.i --- frama-c-20110201+carbon+dfsg/tests/misc/modulo.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/modulo.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,20 @@ + +int A,B,C,D,E,F,G,H,I,J,K; + +void main (int i) +{ + A = (4 * i) % 4; + B = (4 * i + 1) % 4; + //@ assert ((i>=-100) && (i<=100)) ; + E = (3*i + 1) % 12; + //@ assert ((i>=0) && (i<=100)) ; + + C = (4 * i + 1) % 4; + D = (3*i + 1) % 12; + F = (24*i + 5) % 12; + G = (24*i + 5) % 13; + H = i % 1000; + I = (2 * i+1101) % 1000; + J = (5 * i - 201) % 1000; + K = (5 * i - 201) % 10; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/multi_access.i frama-c-20111001+nitrogen+dfsg/tests/misc/multi_access.i --- frama-c-20110201+carbon+dfsg/tests/misc/multi_access.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/multi_access.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config +STDOPT: +"-unspecified-access" +*/ +struct S { int a; int b; }; + +int main () { + struct S s; + s.a = 0; + s.b = 1; + s.a = s.b = 2; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/nested_struct_init.i frama-c-20111001+nitrogen+dfsg/tests/misc/nested_struct_init.i --- frama-c-20110201+carbon+dfsg/tests/misc/nested_struct_init.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/nested_struct_init.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,57 @@ +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; + +struct S0 { + int8_t f0; + int16_t f1; + int64_t f2; + uint16_t f3; + int8_t f4; + int32_t f5; + int16_t f6; + int32_t f7; + int16_t f8; +}; + +struct S2 { + int8_t f0; + const int16_t f1; + int16_t f2; + int32_t f3; + uint8_t f4; + struct S0 f5; + int64_t f6; + int8_t f7; + int16_t f8; +}; + +struct S1 { + int32_t f0; + uint8_t f1; +}; + +struct S3 { + struct S2 f0; + const uint32_t f1; + const uint32_t f2; + int64_t f3; + struct S0 f4; + const struct S1 f5; + int8_t f6; + const int8_t f7; +}; + + +struct S0 g_3 = {-1L,0x4B54L,6L,7L,0xFFL,1L,-10L,0x67457993L,0x3C7DL}; +struct S3 g_8 = {{0xD5L,-10L,0L,0x900B0881L,0xDAL,{0xDBL,0x846BL,1L,-7L,0xF3L,0xFC0336AEL,6L,0x52E4A6B2L,0x4EB0L},0x117216709E149CFFLL,0x9CL,-1L},0x1636717BL,-4L,4L,{0xE3L,0xECDCL,0xF1FA6F63EEDA781BLL,0xF7A0L,0x7CL,0L,0xA77DL,0x7FC7DF39L,0x3C5AL},{0xA104ACD6L,0xA8L},0xADL,8L}; + +main(){ + Frama_C_dump_each(); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/non_iso_initializer.i frama-c-20111001+nitrogen+dfsg/tests/misc/non_iso_initializer.i --- frama-c-20110201+carbon+dfsg/tests/misc/non_iso_initializer.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/non_iso_initializer.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ +int G0 = 42; +int G1 = G0>>1; +int G2 = G0 ^ G1 ; +int G3 = -1; +void main (void) { + G3=G0+G2; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/noreturn.i frama-c-20111001+nitrogen+dfsg/tests/misc/noreturn.i --- frama-c-20110201+carbon+dfsg/tests/misc/noreturn.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/noreturn.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,37 @@ +void stop(void) __attribute__ ((noreturn)) ; + +int haltme(void) __attribute__ ((noreturn)) ; + + +void never_ends(void) __attribute__ ((noreturn)) +{ while(1) ; + return; +}; + +void should_never_end(int c) __attribute__ ((noreturn)) +{ + if (c) while(1) ;} ; + +void warn_never_ends(void) +{ while(1) ;} ; + +void warn_may_never_end(int c) +{ + if (c) while(1) ;} ; + +static volatile int v=55,w=66; +int main(int c) { + int x=0; + + if (v) warn_may_never_end (v); + if (v) warn_may_never_end (1); + if (v) warn_never_ends (); + if (v) stop(); + if (v) x = haltme (); + if (v) never_ends (); + if (v) should_never_end (v); + if (v) should_never_end (1); + + return x; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/not.i frama-c-20111001+nitrogen+dfsg/tests/misc/not.i --- frama-c-20110201+carbon+dfsg/tests/misc/not.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/not.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,7 @@ +int x; +void main() { + + volatile int loc=0; + x = loc?!(0):0; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/null_lt_valid.i frama-c-20111001+nitrogen+dfsg/tests/misc/null_lt_valid.i --- frama-c-20110201+carbon+dfsg/tests/misc/null_lt_valid.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/null_lt_valid.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,38 @@ +int t[23]; +int *p, *q, *r; + +void f(void){ + if (p < t) + *p = 1; +} + +void g(void){ + int *q1, *q2; + if (q < t+22) + q1 = q; + else + q2 = q; +} + +void h(void){ + int *r1, *r2; + if (r < t+22) + r1 = r; + else + r2 = r; +} + +main(int c){ + if (c&32) + f(); + q = (c&64) ? t+(c&15) : p; + if (c&128) + g(); + r = (c&256) ? t+(c&31) : p; + if (c&512) + h(); + t[0] = (p < t); + t[1] = (q < t + 22); + t[2] = (r < t + 22); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/obfuscate.i frama-c-20111001+nitrogen+dfsg/tests/misc/obfuscate.i --- frama-c-20110201+carbon+dfsg/tests/misc/obfuscate.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/obfuscate.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,30 @@ +/* run.config + OPT: -obfuscate +*/ + +int my_var = 0; + +/*@ global invariant I: my_var >= 0; */ + +enum my_enum { + first, second, third = 4 +}; + +/*@ requires my_var > 0; + ensures my_var > \old(my_var); +*/ +int my_func () { + + enum my_enum x = first; + /*@ assert my_var >= first; */ + my_var++; + return my_var + x; + +} + +/*@ requires \valid(p); + ensures *p == 0; +*/ +void f(int* p); + +int main(int*p) { f(p); } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/offset_neg.i frama-c-20111001+nitrogen+dfsg/tests/misc/offset_neg.i --- frama-c-20110201+carbon+dfsg/tests/misc/offset_neg.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/offset_neg.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,4 @@ +int G[5]; +int main () { + G[-1] = 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/offset_top.i frama-c-20111001+nitrogen+dfsg/tests/misc/offset_top.i --- frama-c-20110201+carbon+dfsg/tests/misc/offset_top.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/offset_top.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -absolute-valid-range 0-0xFF -journal-disable +*/ + +int* T = (int*)0; +int TAB[10]; + +void main() { + int i; + i = &TAB[*T]; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/origin.i frama-c-20111001+nitrogen+dfsg/tests/misc/origin.i --- frama-c-20110201+carbon+dfsg/tests/misc/origin.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/origin.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,130 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -out -deps -main main -journal-disable + OPT: -memory-footprint 1 -val -out -deps -main origin -journal-disable + + +*/ + +int a, b, aa2, *p, *pa1, *pa2, *qa2, *pa3, *q; + +int t[12], tt[10], ta1[10], ta2[10], ta3[10], tta2[10]; + +void origin_arithmetic_1(void) { + pa1 = (int*)(-(int)ta1); + *pa1 = 0; +} +/************/ +void origin_arithmetic_2(int c1) { + pa2 = (int*)(-(int)ta2); + qa2 = c1 ? pa2 : (int*)(-(int)tta2); + *qa2 = &aa2; +} +/************/ +void origin_arithmetic_3(void) { + pa3 = (int*)(-(int)ta3); + *pa3 = 3; +} + + +int g(void); +int *gp(void); + +int l1, l2, l3, *pl; + +void origin_leaf_1 () { + l1 = g(); +} + +int * Tm1[2] ={&a, &b}; +int * Tm2[2] ={&a, &b}; +int * Tm3[2] ={&a, &b}; +int * Tm4[2] ={&a, &b}; +int *pm1, *pm2, *qm2; + +void origin_misalign_1(void) { + pm1 = *(int**)(2 + (char *) Tm1); + *pm1 = 0; +} + +void origin_misalign_2(void) { + pm2 = *(int**)(2 + (char *) Tm2); + qm2 = pm2+1; + *qm2 = (int)&a; +} + +int *pun, *pun2, *qun2; + +void origin_uninitialized_1(int c1) { + int i, * pi ; + if (c1) + pi = &a ; + pun = pi; +} + +void origin_uninitialized_2(int c1, int c2) { + int i, * pi ; + if (c1) + pi = &a ; + pun2 = pi; + + if (c2) + qun2 = pun2 + i; +} + +volatile int random; +int esc1, esc2, esc3, esc4, esc5; +void local_escape_1(int arg) +{ + int local1, local2; + esc1 = (int) &arg; + esc2 = (int) &local1; + esc3 = - (int) &arg; + esc4 = random ? esc2 : 12; + local2 = (int) &local1; + esc5 = (int) &esc1; +} + + +void main(int c1, int c2) +{ + origin_arithmetic_1(); + origin_arithmetic_2(c1); + origin_arithmetic_3(); + origin_leaf_1 (); + l2 = l1; + l2 += g(); + pl = gp(); + l3 = *pl; + origin_misalign_1(); + origin_misalign_2(); + p = *(int**)(2 + (char *) Tm3); + q = c1 ? p : *(int**)(3 + (char *) Tm4); + origin_uninitialized_1(c1); + origin_uninitialized_2(c1, c2); + local_escape_1(12); +} + + +/************************************/ +int x, y; +struct st { + char c; + short i; + int *p, *t[2]; +} v = { 1, 2, &x, &y}; + +struct st origin (int c0) { + struct st r; + int *q1, *q2; + + r.c = f() ; + r.i = c0 ; + r.p = *(int *) (&v.c + 3); + q1 = *(int**)(2 + (char *) v.t); + q2 = c0 ? q1 : *(int**)(3 + (char *) v.t); + r.t[0] = q2 ; + r.t[1] = (int *)(- (int)&x) ; + return r; +} +/************************************/ diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/orig_name.i frama-c-20111001+nitrogen+dfsg/tests/misc/orig_name.i --- frama-c-20110201+carbon+dfsg/tests/misc/orig_name.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/orig_name.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + CMD: bin/toplevel.byte + OPT: -orig-name -journal-disable -print +*/ + +int x = 1; + +int f(int x) { + int y = 0; + if (x == 0) { + int x = 3; + y = x++; + } + y += x; + return y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/output_leafs.i frama-c-20111001+nitrogen+dfsg/tests/misc/output_leafs.i --- frama-c-20110201+carbon+dfsg/tests/misc/output_leafs.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/output_leafs.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,48 @@ + +int *H,G,K,L,M,N,P; + +/*@ assigns G \from G,*H; + @ assigns *H \from P; + @ assigns *x \from \empty; +*/ +void crypt(int*x); + +void main1(int y) +{ + H = &K; + crypt(&L); + +} + +int a, b, c, d; + +//@ assigns *u \from *v; +void g(int *v, const int *u); + +void g1() { + g(&a,&b); +} + +void g2() { + g(&c,&d); +} + +void main2 () { + g1(); + g2(); +} + + +void f(int* x); + +int main3 () { + int x = 0; + f(&x); + return x; +} + +void main(int y) { + main1(y); + main2(); + main3(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/overflow_cast_float_int.i frama-c-20111001+nitrogen+dfsg/tests/misc/overflow_cast_float_int.i --- frama-c-20110201+carbon+dfsg/tests/misc/overflow_cast_float_int.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/overflow_cast_float_int.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ + +int main() +{ +float vf1; +signed int e; +unsigned int d; +d = 0x7FFFFFFFll; +vf1 = d * 1.0; +e = (int)vf1 + 0; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/overflow.i frama-c-20111001+nitrogen+dfsg/tests/misc/overflow.i --- frama-c-20110201+carbon+dfsg/tests/misc/overflow.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/overflow.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,34 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -val-signed-overflow-alarms + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable +*/ +extern int printf (__const char *__restrict __format, ...); +/* L'analyseur déborde et dit i=-1 */ +int main (int c) { + unsigned long long i = 0xFFFFFFFFFFFFFFFFULL; + unsigned long j = 0xFFFFFFFFUL; + + long long is = 0xFFFFFFFFFFFFFFFFULL; + long js = 0xFFFFFFFFUL; + long minjs = - (j/2) -1 ; + long maxjs = j/2 ; + + unsigned long long i1 = i+1; + unsigned long j1 = j+1; + + int y = c?1:100000; + int x = (60000 * y ) / 100000; + int z = y * 1000 * 1000; + int t = (-y) * 10000000; +/* + printf("unsigned long long:%llu (+1:%llu)\nunsigned long:%lu (+1:%lu)\n" + ,i,i1,j,j1); + printf("signed long long:%lld (+1:%lld)\nlong:%ld (+1:%ld)\n" + ,is,is+1,js,js+1); + printf("min signed long:%ld (-1:%ld)\n" + ,minjs,minjs-1L); +*/ + if (-c) {} + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/paths.i frama-c-20111001+nitrogen+dfsg/tests/misc/paths.i --- frama-c-20110201+carbon+dfsg/tests/misc/paths.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/paths.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,53 @@ +/* run.config + OPT: -memory-footprint 1 -experimental-path-deps -deps -journal-disable +*/ +int a,b,c,d,e,i,d1,d2,d3,d4,X1,X2,X3,X4,X5,X; + +void f1(void) +{ + X = X1; + if (d1) X = X4; +} + +void f2(void) +{ + X = X2; +} + +void f3(void) +{ + X = X3; +} + +int f(int fx, int fy, int fz) +{ + d2 = fx; + if (fy) i++; + return d3; +} + +void (*t[3])(void)={f1, f2, f3}; + +/*@ assigns \result \from x ; */ +int unknownfun(int x); + +int main(int r,int s,int u,int v,int w,int x,int y,int z,int ww){ + d1 = x; + c = u?a:b; + d = b + v; + d4 = unknownfun(ww); + if (d4) + i++; + r++; + if (d) + a=1; + (t[w])(); + if (X) + i++; + d3 = z; + if (f(y,s,r)) + i++; + if (d2) + i++; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pb.i frama-c-20111001+nitrogen+dfsg/tests/misc/pb.i --- frama-c-20110201+carbon+dfsg/tests/misc/pb.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pb.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,2 @@ + +void main () { f() ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer2.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer2.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main g -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main h -journal-disable +*/ +int * f (int *r) { + return r; +} + +int * p, *q; +int x,y,z; + +void g() { + p = f(&x); +} + +void h() { + q = f(&y); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer3.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer3.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer3.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer3.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,15 @@ +int x,y,c; +int *p,*q; + +int* f(int * x) { + c=2; + return x; +} + +void main() { + c=1; + p = f(&x); + q = f(&y); + *p = c; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer4.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer4.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer4.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer4.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -absolute-valid-range 0-0x7 -journal-disable +*/ +unsigned short d,e[10]={0},c = 0; + +void main(void) { + + ((int*)0x0)[1] = 1; + ((int*)0x0)[0] = 2; + d = 1; + for (c=0; c<=10; c++){ + e[0] = 1; + d=0; + ((int*)0x0)[c] = 0;} +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer_arg.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_arg.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer_arg.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_arg.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +int main(char*arg,int argc,char *argv[2]) { + arg[0] = 0; + arg[1] = 1; + arg[2] = 1; + if (!argc) arg[1000]=1000; + arg[argc] = 4; + + argv[1] = "5069"; + argv[0] = "5069"; + + argv[0][0] = '0'; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer_comp.c frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_comp.c --- frama-c-20110201+carbon+dfsg/tests/misc/pointer_comp.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_comp.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,48 @@ +extern int v; + +char str1[] = "absd"; +char str2[] = "abdd"; + +struct s { int x; }; +struct s s1; +struct s s2[8]; + +void f(void); +void g(void); + +void* NULL=0; + +void main () { + int i; + void (*p)(void) = (v ? &f : &g); + // Valid + i = (&str1 == &str2); + i = (&s1 == NULL); + i = (&s1+1 == NULL); + i = (&s2[2] == &s2[4]); + i = (&s2[8] == NULL); + i = (&f == NULL); + i = (&s1 == &s2); + i = (&f == &g); + i = (p == NULL); + + // Valid + i = (&s2[2] < &s2[4]); + + // Invalid + i = (&s2[9] == NULL); + i = (&s2[9] == &s2[9]); + + // Invalid + i = (&str1 < &str2); + i = (&s1 < &s2); + i = (&f < &g); + + // ? + i = (&s1 > NULL); + i = (&s1+1 > NULL); + i = (&s2[8] > NULL); + i = (&f > NULL); + i = (p > NULL); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,42 @@ +int x,y,c,*p,*q,T[10]; + +void g() { + p = (int*)(void*)&y; + *p = c; +} + +void f1() { + x = y; + q= &x; + if (c) p = &x; + p = &c; +// p = &T[c]; + *p = *q; +} + +/*@ ensures x > 0; */ +void h() { + p = &x; + c = *p; + *p = y; +} + + +void l(int *y) { + *y = x; +} +void k(int *x) { + l(x); +} + +int cc1, cc2;; + +void main(int en) { + c=17; + x=19; + k(&c); + k(&x); + cc1 = cc2 = 99; + if (en & 1) cc1 = T-1 <= T; + if (en & 2) cc2 = T <= T+12; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer_int_cast.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_int_cast.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer_int_cast.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_int_cast.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main g -journal-disable +*/ +int * q; +int x,y=0; +void g(){ + int i = 0; + if (y==0) i = &y; + q = (int*)i; + *q = x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pointer_loop.i frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_loop.i --- frama-c-20110201+carbon+dfsg/tests/misc/pointer_loop.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pointer_loop.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,53 @@ +/* run.config + OPT: -memory-footprint 1 -val -out -input -deps -journal-disable + */ +int base0=7; +int base1=1; +int base2=2; +int *base_p[2]={&base1,&base2}; +int *ioCtrl_p; +void main () +{ short int i; + int uiNmbrOfElements = 2; + + for (i = 0; i < uiNmbrOfElements; i++) + { + ioCtrl_p = base_p[i]; + *ioCtrl_p = 3+i; + } +} + + +struct auIoCtrl; +typedef struct auIoSlot { + int uiNmbrOfElements; + struct auIoCtrl *const *ioCtrl_p; +} auIoSlot_t; +typedef struct auIoCtrl { + const auIoSlot_t *slot_p; + int inDriverStatus; +} auIoCtrl_t; + +auIoCtrl_t i_auIoCtrl[2]; +static auIoCtrl_t *const auIoCtrl_p[2] = { + &i_auIoCtrl[0], + &i_auIoCtrl[1] +}; +const auIoSlot_t i_auIoSlot[2] = { + { 2, &auIoCtrl_p[0]}, + { 0, (void *) 0} +}; + +void f(void) +{ + int i; + enum counter j; // specific test for pointer_loop.c:42: error: storage size of 'j' isn't known + i=0; + (i_auIoSlot[i].ioCtrl_p[0])->inDriverStatus = 0; + (i_auIoSlot[i].ioCtrl_p[1])->inDriverStatus = 0; + for(j = 0; j < 2; j++) { + (i_auIoSlot[i].ioCtrl_p[j])->inDriverStatus = 1; + + } + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/postcondition.i frama-c-20111001+nitrogen+dfsg/tests/misc/postcondition.i --- frama-c-20110201+carbon+dfsg/tests/misc/postcondition.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/postcondition.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,95 @@ +int G; +int A,B,C,D,E,EX,X; + +//@ ensures -100 <= \result <= 100 ; +int u(void); + +//@ ensures min <= \result <= max ; +int cap(int min, int max); + +/*@ + @ requires 0<=cmd<5; + @ ensures 0<=\result<300; + @*/ +int get_index(int /* in */ cmd) +{ + int ret=0; + Frama_C_show_each_cmd(cmd); + while (ret <= 100*cmd) + { + if (u()) return ret; + ret++; + } + return ret; +} + +/*@ ensures EX <= cmd ; */ +int bound(int cmd) +{ + cmd = 2; /* vicious */ +} + +//@ ensures G == 6; +void t0 () { + G = 6; +} + +//@ ensures G == 7; +void t1 () { + G = 6; +} + +int *p; + +//@ ensures *p == 6 && G == *p && G == 6; +void t2 () { + p = &G; + *p = 6; +} + + +typedef struct { + int a; + int b; + int c; +} st; + +st TAB[10]; + +//@ ensures TAB->a == 12; +void t3 () { + TAB->a = 12; +} + +//@ ensures x<=y; +void t4(int x, int y) { + x++; y--; +} + +/*@ ensures x == \old(x); + ensures \result > \old(X); */ +int t5(int x) { + x = X; + return ++x; +} + +/*@ ensures \result == 0; + @ ensures \false; + @ */ +int f(void) { return 0; } + +void main(){ + B=get_index(1); + EX = u(); /* it is incorrect to affirm that EX<=2 after this line */ + bound(8); + C=get_index(u()?4:6); + D = u(); + E = cap(20, 80); + if (u()) t0(); + if (u()) t1(); + if (u()) t2(); + if (u()) t3(); + t4(3,4); + if (u()) { X = 8; t5(2); } + if (B) f(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ptr_relation.i frama-c-20111001+nitrogen+dfsg/tests/misc/ptr_relation.i --- frama-c-20110201+carbon+dfsg/tests/misc/ptr_relation.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ptr_relation.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,40 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main2 -journal-disable +*/ +long i,j,x,k,l,m,n,d,a,b; +long *ptr; + +//----------------------------------------- +void main(int c) { + a = 333; + ptr = c ? &a : &b ; + *ptr = 77; + i=*ptr+1-1; + return; +// needs relations to be accurate +} +//----------------------------------------- +void main1(int c) { + i = c?3:4; + + x = i; + j = x - i; +} +//----------------------------------------- +// Just a test for dependencies +void f2 (int arg) { + b = arg + l; + a = arg + m ; +} +void g2 (int arg) { + a = arg + n ; +} +void (*tab_ptr_fct2[2])(int) = { &f2, &g2}; +void main2(int c,int arg) { + j = c?0:1; + (*tab_ptr_fct2[j])(arg); // Dependency of j are taken into account. +} +//----------------------------------------- diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/pure_exp.i frama-c-20111001+nitrogen+dfsg/tests/misc/pure_exp.i --- frama-c-20110201+carbon+dfsg/tests/misc/pure_exp.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/pure_exp.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* bug #5877 on gforge */ + + int *t = 0; + + int main(void) + { + /* should lead to an alarm. */ + *t == 42; + + return 0; + } diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/qualified_arrays.i frama-c-20111001+nitrogen+dfsg/tests/misc/qualified_arrays.i --- frama-c-20110201+carbon+dfsg/tests/misc/qualified_arrays.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/qualified_arrays.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +typedef unsigned int TAB120[ 120 ] ; + +extern volatile TAB120 volatile_tab_120_2[ 2 ]; + +volatile unsigned int* const p_first_volatile = &volatile_tab_120_2[0][0] ; + +struct foo { int x; }; + +volatile struct foo f = { 1 }; + +volatile int* x = &f.x; + +/*@ requires p_first_volatile == &volatile_tab_120_2[0][0] ; + requires x == &f.x; + */ +int main(void) { + p_first_volatile = &volatile_tab_120_2[1][112] ; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/raz.i frama-c-20111001+nitrogen+dfsg/tests/misc/raz.i --- frama-c-20110201+carbon+dfsg/tests/misc/raz.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/raz.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +volatile int h; + +int main() { + int n = h?0:10; + int r = 0, i; + // @ ensures i==n + // @ invariant 0 <= i && i <= n + for (i=0; i<n ; i++) + r = 1; + return r; +} +/* +void main0() { + int n = 10; + int r = 1; + //@ ensures r == 0 + if (r) r = 0; + //@ ensures r == 0 + for (int i=11; i<5 ; i++) + r = 0; +} +*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/reading_null.i frama-c-20111001+nitrogen+dfsg/tests/misc/reading_null.i --- frama-c-20110201+carbon+dfsg/tests/misc/reading_null.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/reading_null.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,56 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main main -journal-disable +*/ + +unsigned short AutoTest[1000]={0}; + +int X; +int* T[]={&X,0,}; + + +int X1; +int X2; +int X3; +int X4,X5,X6,X7,X8,X9; + +void main(int c){ + + + int count = 0; + +// int *p=T[c]; +// X = *p; + + while(count<10) { + CEA_F(X,count); + switch (count) { + case 0: X = X1; + break; + case 1: X = X2; + break; + case 2: X = X3; + break; + case 3: X = X4; + break; + case 4: X = X5; + break; + case 5: X = X6; + break; + case 6: X = X7; + break; + case 7: X = X8; + break; + case 8: X = X9; + break; + } + count++; + } +} + +void main1(int c){ + + int X1; + int* X2; + X1 = X2; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/rec.i frama-c-20111001+nitrogen+dfsg/tests/misc/rec.i --- frama-c-20110201+carbon+dfsg/tests/misc/rec.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/rec.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ +void main() { + int X=0; + if (X) main(); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/recursion2.i frama-c-20111001+nitrogen+dfsg/tests/misc/recursion2.i --- frama-c-20110201+carbon+dfsg/tests/misc/recursion2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/recursion2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,23 @@ +/*run.config + OPT: -journal-disable -input -val + */ +int x, y; + +void h2 (int); +void h1 (int); + +void h1 (int i) { + int r = x; + if (i) + h2 (i); +} +void h2 (int i) { + int r = y; + if (!i) + h1 (i); +} + +void main() { + h2(0); + h1(1); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/recursion.i frama-c-20111001+nitrogen+dfsg/tests/misc/recursion.i --- frama-c-20110201+carbon+dfsg/tests/misc/recursion.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/recursion.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +/*run.config + OPT: -lib-entry -main main -val -journal-disable + OPT: -lib-entry -main main -val -val-ignore-recursive-calls -journal-disable + */ +int G; + +int f() { + if (G) f(); + return 5; +} +void main() { + G = f(); + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/reduce_valid.i frama-c-20111001+nitrogen+dfsg/tests/misc/reduce_valid.i --- frama-c-20110201+carbon+dfsg/tests/misc/reduce_valid.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/reduce_valid.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,26 @@ +int t[2]; +int *p,*q,*r, A, offs; + +void main(int c, int d, int e, int f, int g) +{ + + + p = c ? t : (void*)0; + *p = 2; + p[1] = 3; + *p = 4; + + q = (void*)0; + if (d) + { + CEA_ici(0); + *q = 3; + *q = 4; + CEA_la(0); + } + + r = e ? (f ? t : t+1) : (void*)0; + offs = g ? 1 : 2; + A = r[offs]; + Frama_C_show_each_r(r); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/relation_reduction.i frama-c-20111001+nitrogen+dfsg/tests/misc/relation_reduction.i --- frama-c-20110201+carbon+dfsg/tests/misc/relation_reduction.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/relation_reduction.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +int y,t; +int R1,R2,R3,R4; +int c; +int tab[9] = { 101, 102, 103, 104, 105, 106, 103, 102, 101 }; + +void main(int x) +{ + y = x; + t = y + 10; + if (x == 2) + { + R1 = y; + R2 = t; + } + + if (t == 17) + R3 = x; + + if (x>=0 && x<=5) + if (tab[y] == 103) + R4 = x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/relations_difficult.i frama-c-20111001+nitrogen+dfsg/tests/misc/relations_difficult.i --- frama-c-20110201+carbon+dfsg/tests/misc/relations_difficult.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/relations_difficult.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,17 @@ +int x,y,*p; +int A,B,C,Z; + +int main(int c) +{ + x = 0; + y = 1; + p = c ? &x : &y; + *p = 2; + x = 3; + A = *p; /* optimal : {2,3} ; sans relations : {1,2,3} */ + x = 4; + B = (*p) + Z; /* optimal : {2,4} ; sans relations : {1,2,4}; + avec relations actuelles : {2,3,4} */ + C = *p; /* meme chose avec copy-paste */ + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/relation_shift.i frama-c-20111001+nitrogen+dfsg/tests/misc/relation_shift.i --- frama-c-20110201+carbon+dfsg/tests/misc/relation_shift.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/relation_shift.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,28 @@ +int r1,r2,r3,r4; + +void main (int x,int y,int z,int t,int *p,int q[2]) { + x = y ; + x++; + y--; + p=(int*)(&p); + p++; + z = x; + t=5; + z+=t; + *q=3; + q++; + + r1 = x-y; + r2 = z-y; + r3 = *(q-1); + r4 = *q; + CEA_DUMP(); +} + +void main1 (int x,int y,int z,int t,int *p,int *q) { + *q = 3; + q++; + r3 = *(q-1); + r4 = *q; + CEA_DUMP(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/relations.i frama-c-20111001+nitrogen+dfsg/tests/misc/relations.i --- frama-c-20110201+carbon+dfsg/tests/misc/relations.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/relations.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,63 @@ + +int t[3]={1,2,3}; +int *p,x; +int u[20]; +int R1,R2,R3,R4,R5,R6,R7,A7,R8,A8; +int S1,S2,S3,S4,S5,S6,S7,B7,S8,B8; + +typedef struct { +int L0; +int L1; +int T13; +int T; +int L8; +} Cs; + +void main(int c,char d,char e, int f, int g, int h, int i, Cs *pCs) +{ + u[0] = g; + p=&t[1]; + *p=4; + if (c) c=0; + t[0]=t[1]; + x=*(p-1); + e=d; + e=d-e +1; + if (d) (*(char*)&f)=e; else f = x; + + u[1] = u[0]; + if (u[1] == 3) + { + R1 = u[0]; + R2 = g; + } + + u[5] = u[0] + 1; + if (u[5] == 3) + { + R3 = u[0]; + R4 = g; + } + R5 = u[5] - u[0]; + + u[10] = h; + u[11] = i; + if (u[10] == u[11]) + R6 = u[10] - u[11]; + + A7 = u[1] - u[0]; + if (u[1] == u[0]) + R7 = 1; + + A8 = u[5] - u[1]; + if (u[5] == u[1]) + R8 = 1; + + pCs->T13 = pCs->L0 || pCs->L1; + pCs->T = pCs->T13; + pCs->L8 = pCs->L0 || pCs->T13; + + S1 = pCs->T - pCs->T13; + if ( pCs->T == pCs->T13) + S2 = 1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/resolve.i frama-c-20111001+nitrogen+dfsg/tests/misc/resolve.i --- frama-c-20110201+carbon+dfsg/tests/misc/resolve.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/resolve.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ + + +int f( int , int); + +int f(int , int ); + +int f(int , int ); + + +//@ assigns \result; +int main(void) { + return f(0,1); +} + +//@ assigns \result; +int main(void); diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/return.i frama-c-20111001+nitrogen+dfsg/tests/misc/return.i --- frama-c-20110201+carbon+dfsg/tests/misc/return.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/return.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +int G,H; + +int f(int x) { + return (x+G); +} + +int g(int x) { + return 1; +} + +int h(int x) { + return x; +} + +void main (int c) { + + if (c) + H = f(H); + else G = f(G); + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/save_comments.i frama-c-20111001+nitrogen+dfsg/tests/misc/save_comments.i --- frama-c-20110201+carbon+dfsg/tests/misc/save_comments.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/save_comments.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + OPT: -load-script tests/misc/save_comments.ml -keep-comments +*/ + + +int f() { + int x = 0; + /* Hello, I'm the f function */ + return x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/save_comments.ml frama-c-20111001+nitrogen+dfsg/tests/misc/save_comments.ml --- frama-c-20110201+carbon+dfsg/tests/misc/save_comments.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/save_comments.ml 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,40 @@ +open Cil_types +open Cil + +let find_comment () = + let kf = Globals.Functions.find_by_name "f" in + let loc1 = Kernel_function.get_location kf in + let loc2 = Cil_datatype.Stmt.loc (Kernel_function.find_return kf) in + let zone = (fst loc1, snd loc2) in + Format.printf + "@[In project %s, searching for comments between %a and %a:@\n%a\ + @\nEnd of comments@." + (Project.get_name (Project.current())) + Cil.d_loc loc1 + Cil.d_loc loc2 + (Pretty_utils.pp_list ~sep:"@\n" Format.pp_print_string) + (Cabshelper.Comments.get zone) + +let run () = + let ast = Ast.get () in + let vis = object + inherit Visitor.frama_c_inplace + method vglob_aux g = match g with GText s -> Format.printf "got global comment %s@." s; SkipChildren | _ -> DoChildren + end + in + ignore (Visitor.visitFramacFile vis ast); + let fmt = Format.std_formatter in + Format.printf "Printing default project first time:@."; + File.pretty_ast ~fmt (); + Format.printf "Printing default project second time:@."; + File.pretty_ast ~fmt (); + let file = Extlib.temp_file_cleanup_at_exit "save_comments_test" ".sav" in + let name = "saved_project" in + find_comment (); + Project.save file; + let prj = Project.load ~name file in + Project.on prj find_comment (); + Format.printf "Printing saved project:@."; + File.pretty_ast ~prj ~fmt () + +let () = Db.Main.extend run diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/semaphore.i frama-c-20111001+nitrogen+dfsg/tests/misc/semaphore.i --- frama-c-20110201+carbon+dfsg/tests/misc/semaphore.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/semaphore.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,52 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main g -journal-disable +*/ +int Sa; +int Sb; + + +void f (void) +{ + int c = 12; + + if (c) + P (Sa); + + P (Sa); + P (Sb); + + V (Sa); + V (Sb); +} + +void g (void) +{ + int c = -25; + + + while (c--) + while (c) + { + V (Sa); + c++; + } + P (Sb); + P (Sa); + + V (Sa); + V (Sb); + + f(); +} + +/* +void creation_tache( void (*f)(void)) { + (*f)(); +}; +void main (void) +{ + Screation_tache (&f); + Screation_tache (&g); +} +*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/sep.i frama-c-20111001+nitrogen+dfsg/tests/misc/sep.i --- frama-c-20110201+carbon+dfsg/tests/misc/sep.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/sep.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,45 @@ +/* run.config + OPT: -memory-footprint 1 -val -slevel 10 -lib-entry -main f1 -separate-n 0 -separate-of 3 + OPT: -memory-footprint 1 -val -slevel 10 -lib-entry -main f1 -separate-n 1 -separate-of 3 + OPT: -memory-footprint 1 -val -slevel 10 -lib-entry -main f1 -separate-n 2 -separate-of 3 + OPT: -memory-footprint 1 -val -slevel 10 -lib-entry -main f1 -separate-n 3 -separate-of 3 +*/ + +int index; +int tab[5]; + +//@ ensures \result==0 || \result==-1 || \result==1 ; +extern int init2(void); + +int init1(void) +{ + int res; + + res = init2(); + + if (res == 0) + { + index=0; + } + else + { + if (res == 1) + { + res = 0; + index = 0; + } + } + + return res; +} + +//@ requires 0<=n<5; +int f1(int n) +{ + int res; + + res = init1(); + + if (res == 0) + return tab[index+n]; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/serv.i frama-c-20111001+nitrogen+dfsg/tests/misc/serv.i --- frama-c-20110201+carbon+dfsg/tests/misc/serv.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/serv.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + DONTRUN: cannot find entry point: main +*/ + +void f1() { + f3(); +} + +void f2() { + f4(); +} + +void f3() { + f4 (); +} + +void f4() { + f3 (); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/shift.i frama-c-20111001+nitrogen+dfsg/tests/misc/shift.i --- frama-c-20110201+carbon+dfsg/tests/misc/shift.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/shift.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,33 @@ +int a,b,d,e,f,g,h; +unsigned int ua,ub,uc,ud,ue,uf; + +int main(int c, int z, int zz) { + a=5024; + d = 255; + f= -255; + if ((c<=3) && (c>=0)) { + c = 2*c-1; + a = 157 << c; + d=1975; + d = d >> c; + f= -1975; + f = f >> c; + } + + if (z) z=1<<32; + if (zz) zz=1>>5555; + + if (c) { + b = 66; + b = b << b; + }; + + + ua = 5607; + ua >>= 2 ; + ub = (unsigned int)(-3000); + ub >>= 2; + printf("ua:%u\nub:%u\n",ua,ub); + + return b; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/simple_packed.c frama-c-20111001+nitrogen+dfsg/tests/misc/simple_packed.c --- frama-c-20110201+carbon+dfsg/tests/misc/simple_packed.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/simple_packed.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,21 @@ +struct my_unpacked_struct +{ + char c; + int i; +}; + +struct my_packed_struct +{ char c; + int i; + struct my_unpacked_struct s; +} __attribute__ ((__packed__)); + +struct my_packed_struct f(struct my_packed_struct foo) { + struct my_packed_struct bar=foo; + return foo; +} + +struct my_packed_struct main(struct my_packed_struct foo) { + f(foo); + return foo; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/simple_path.i frama-c-20111001+nitrogen+dfsg/tests/misc/simple_path.i --- frama-c-20110201+carbon+dfsg/tests/misc/simple_path.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/simple_path.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +int G,H; +int *p = &G; +int *q = &H; + +void main(void) +{ + G = 4; + *p = 3; + p = &H; + *p = 5; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/simplify_cfg.i frama-c-20111001+nitrogen+dfsg/tests/misc/simplify_cfg.i --- frama-c-20110201+carbon+dfsg/tests/misc/simplify_cfg.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/simplify_cfg.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +/* run.config + OPT: -simplify-cfg -keep-switch -val -check -journal-disable + OPT: -simplify-cfg -val -check -journal-disable +*/ + +int main(int x, int y) { + int z = 0; + char c = 'c'; + switch (x) { + case 0: z=(int)c; + default: z++; + } + return z; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/simp_switch.i frama-c-20111001+nitrogen+dfsg/tests/misc/simp_switch.i --- frama-c-20110201+carbon+dfsg/tests/misc/simp_switch.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/simp_switch.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + OPT: -check -simplify-cfg -print + */ +void main() +{ + switch(0) { + case 0: + break; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/sizeof.i frama-c-20111001+nitrogen+dfsg/tests/misc/sizeof.i --- frama-c-20110201+carbon+dfsg/tests/misc/sizeof.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/sizeof.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +int sz_str,sz_typ,align_str,align_typ; + +void main() +{ + sz_str= sizeof("ONE"); + //@ assert sz_str == sizeof("ONE"); + align_str= __alignof("FOO"); + // assert align_str == __alignof("FOO"); + sz_typ= sizeof(char); + //@ assert sz_typ == sizeof(char); + align_typ= __alignof(char*); + // assert align_typ == __alignof((char*)); + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/slevelex.i frama-c-20111001+nitrogen+dfsg/tests/misc/slevelex.i --- frama-c-20110201+carbon+dfsg/tests/misc/slevelex.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/slevelex.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,90 @@ +/* run.config + STDOPT: +"-slevel 4 -slevel-function main:0 -slevel-function gu:20 -slevel-function ginc:20" +*/ + +volatile int c; + +int f(void) +{ + int x, y; + if (c) + { + x = 1; + y = 1; + } + else + { + x = 2; + y = 2; + } + return x*x - y*y; +} + +void gu(int u) +{ + /*@ assert + u == 1 || + u == 2 || u == 3 || + u == 4 || u == 5 || + u == 6 || u == 7 || + u == 8 || + u == 9 || u == 10 || + u == 11 || + u == 12 || u == 13 || + u == 14 || u == 15 || + u == 16 || u == 17 || + u == 18 || + u == 19 || u == 20 ; + */ + + Frama_C_show_each_u(u); +} + +void ginc(int u) +{ + int inc; + inc = 4 * u; + + /*@ assert + inc == 4 || + inc == 8 || inc == 12 || + inc == 16 || inc == 20 || + inc == 24 || inc == 28 || + inc == 32 || + inc == 36 || + inc == 40 || inc == 44 || + inc == 48 || inc == 52 || + inc == 56 || inc == 60 || + inc == 64 || inc == 68 || + inc == 72 || inc == 76 || + inc == 80 ; + */ + + Frama_C_show_each_inc(inc); +} + + +void main(int un) +{ + int x, y; + if (c) + { + x = 1; + y = 1; + } + else + { + x = 2; + y = 2; + } + //@ assert x*x == y*y ; + + Frama_C_show_each_xy(x,y); + x = f(); + //@ assert x == 0; + + if (un>=20) un = 20; + if (un<=1) un = 1; + gu(un); + ginc(un); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/small_conditionals.i frama-c-20111001+nitrogen+dfsg/tests/misc/small_conditionals.i --- frama-c-20110201+carbon+dfsg/tests/misc/small_conditionals.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/small_conditionals.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,6 @@ +char Y,Z,U ; +void main(char X) { + Y = X?:2; + + Z = U?3:4; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/sort4.i frama-c-20111001+nitrogen+dfsg/tests/misc/sort4.i --- frama-c-20110201+carbon+dfsg/tests/misc/sort4.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/sort4.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,74 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main sort4_1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main sort4_4 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -lib-entry -main sort4_3 -journal-disable +*/ + +/* sort 4 integers */ + +int a, b, c, d; + +void sort4_1() { + + int tmp; + if (a > b) { tmp = a; a = b; b = tmp; } + if (c > d) { tmp = c; c = d; d = tmp; } + if (a > c) { tmp = a; a = c; c = tmp; } + if (b > d) { tmp = b; b = d; d = tmp; } + if (b > c) { tmp = b; b = c; c = tmp; } + /*@ assert a <= b <= c <= d; */ +} + + + +/*@ requires \valid_range(t,0,4); + ensures t[0] <= t[1] <= t[2] <= t[3]; */ +void sort4_4(int t[4]) { + int tmp; + if (t[0] > t[1]) { tmp = t[0]; t[0] = t[1]; t[1] = tmp; } + if (t[2] > t[3]) { tmp = t[2]; t[2] = t[3]; t[3] = tmp; } + if (t[0] > t[2]) { tmp = t[0]; t[0] = t[2]; t[2] = tmp; } + if (t[1] > t[3]) { tmp = t[1]; t[1] = t[3]; t[3] = tmp; } + if (t[1] > t[2]) { tmp = t[1]; t[1] = t[2]; t[2] = tmp; } +} + + +/* commented because of memory explosion */ +#if 0 +/*@ requires \valid(a) && \valid(b) && \valid(c) && \valid(d) && + @ a != b && a != c && a != d && b != c && b != d && c != d; + @ ensures *a <= *b <= *c <= *d; */ +void sort4_2(int *a, int *b, int *c, int *d) { + int tmp; + if (*a > *b) { tmp = *a; *a = *b; *b = tmp; } + if (*c > *d) { tmp = *c; *c = *d; *d = tmp; } + if (*a > *c) { tmp = *a; *a = *c; *c = tmp; } + if (*b > *d) { tmp = *b; *b = *d; *d = tmp; } + if (*b > *c) { tmp = *b; *b = *c; *c = tmp; } +} +#endif + + + +/*@ predicate swap_ord(int a2,int b2,int a1,int b1) = + @ (a1 <= b1 ==> (a2 == a1 && b2 == b1)) && + @ (a1 > b1 ==> (a2 == b1 && b2 == a1)) ; + @*/ + +/*@ requires \valid(a) && \valid(b) && \valid(c) && \valid(d) && + @ a != b && a != c && a != d && b != c && b != d && c != d; + @ ensures *a <= *b <= *c <= *d; */ +void sort4_3(int *a, int *b, int *c, int *d) { + int tmp; + // assigns *a,*b,tmp; ensures swap_ord( *a,*b,\old( *a),\old( *b)); + if (*a > *b) { tmp = *a; *a = *b; *b = tmp; } + // assigns *c,*d,tmp; ensures swap_ord( *c,*d,\old( *c),\old( *d)); + if (*c > *d) { tmp = *c; *c = *d; *d = tmp; } + // assigns *a,*c,tmp; ensures swap_ord( *a,*c,\old( *a),\old( *c)); + if (*a > *c) { tmp = *a; *a = *c; *c = tmp; } + // assigns *b,*d,tmp; ensures swap_ord( *b,*d,\old( *b),\old( *d)); + if (*b > *d) { tmp = *b; *b = *d; *d = tmp; } + // assigns *b,*c,tmp; ensures swap_ord( *b,*c,\old( *b),\old( *c)); + if (*b > *c) { tmp = *b; *b = *c; *c = tmp; } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/statement_contract.i frama-c-20111001+nitrogen+dfsg/tests/misc/statement_contract.i --- frama-c-20110201+carbon+dfsg/tests/misc/statement_contract.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/statement_contract.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +int A; + +/*@ behavior test: + assumes A == 0; + ensures \result == 3; + behavior test2: // invalid + assumes \false; + ensures \result == 0; +*/ +int main() +{ +int d; +d=4; +/*@ + requires d>0; assigns d; ensures d==3; + behavior foo: + assumes d == 0; + ensures d == 42; +*/ +d=3; +return d; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/static.i frama-c-20111001+nitrogen+dfsg/tests/misc/static.i --- frama-c-20110201+carbon+dfsg/tests/misc/static.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/static.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,32 @@ +int * f (void) +{ + static int x; + return &x; +} + +int GLOB={{{{0}}}}; +char T[10]={0}; +int IT[10]={0}; +int G; +char H; +int R; + +int volatile *p; +int a[2]={77}; +int Rv=99; + +int main() { + *(f()) = 3; + R = *f(); + GLOB = sizeof main (); + G = *((int*)&(T[1])); + H = *((char*)&(IT[9])); + + + p = &a; + Rv = *p; + + return T[0]; + +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/strange.i frama-c-20111001+nitrogen+dfsg/tests/misc/strange.i --- frama-c-20110201+carbon+dfsg/tests/misc/strange.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/strange.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,18 @@ +int GG; + +int f (void) +{ int G; + G = 2; + GG = 3; + return 1; } + + +int main (void) +{ int lm = 77; + + int res_f = f(); + GG = lm; + + return 0; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/strings_cond.i frama-c-20111001+nitrogen+dfsg/tests/misc/strings_cond.i --- frama-c-20110201+carbon+dfsg/tests/misc/strings_cond.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/strings_cond.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ + +void foo(char *s) { + Frama_C_dump_each(); + while(*s) { Frama_C_show_each_s(s); s++; } +} + +void main(void) { + foo("Bla"); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/strings.i frama-c-20111001+nitrogen+dfsg/tests/misc/strings.i --- frama-c-20110201+carbon+dfsg/tests/misc/strings.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/strings.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,108 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main main1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main6 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main main7 -journal-disable +*/ + +char s1[]="hello\000 world"; +char s2[]="hello"; +char *s5, *s6; + +int u(void); + +char cc = 'a'; +char Q, R, S, T, U, V, W, X, Y, Z; + +char *strcpy(char*dst, char*src) +{ + char* ldst=dst; + /*@ loop pragma UNROLL_LOOP 20; */ + while (*ldst++ = *src++) + ; + return dst; +} + +unsigned int strlen(char *s) +{ + unsigned int l=0; + /*@ loop pragma UNROLL_LOOP 20; */ + while(*s++ != 0) + l++; + return l; +} + +void main1(void) +{ + char *p; + p = &s1[3]; + if (u()) R=*(p-4); + + p = &s1[3]; + if (u()) S=*(p+12); + + if (u()) + p = &s1[5]; + else + p = &s2[3]; + if (u()) T=*(p-4); + + { + char a[10] = "Not ok"; + char b [5]; + if (u()) strcpy(b,a); + } + + s1[3]=cc; + s1[6]=cc; + return strlen(s1); +} + + +char *s3="tutu"; +char *s4="tutu"; +char *s7="hello\x00 world"; +char *s8="hello"; + +int main6(void) +{ + char *s; + s = "toto"; + cc = *s; + if (u()) + R = (s3 == s4); + if (u()) + S = (s1 == s2); + if (u()) + T = (s1 == s3); + if (u()) + U = (s7 == s8); + if (u()) + V = (s7 == s4); + if (u()) + W = (s7 + 1 == s8 + 1); + if (u()) + X = (s3 == s3); + s5 = (u()?s3:s8); + if (u()) + Y = ((u()?s3:s8) == s5); + s6 = (u()?(u()?s3:s8):s4); + if (u()) + Z = (s5 == s6); + if (u()) + Q = ("oh, hello"+4 == s7); + return cc; +} + +int main7(int d, int e, int f) +{ + char c=-1; + if (d) s5 = s3; else s5 = &c; + *(f ? s5 + 2 : &c) = 'T'; + R=c; + *s5=' '; + if (e) s6 = s3+1; else s6 = &c; + *s6=cc; + c=*s4; + return c; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct2.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct2.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,275 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f_precis -journal-disable +*/ +struct st1 { + int a; + int *b; +}; + +struct st2 { + int a; + int d[10]; + struct st1 b; + struct st1 e[10]; + struct st2 *c; +}; + +struct st1 tabst[10], tabst2[10]; + +struct st2 tab_s[2]; +struct st2 tab_s1[2]; +struct st2 tab_s2[2]; +struct st2 tab_s3[2]; +struct st2 tab_s4[2]; + +struct st2 s1,s2,s4,s5,s6; +struct st1 s8,s7; + +typedef int Ttabl[5+5]; +Ttabl tabl; + +int tab1[2]; +int tab2[2]; +int tab3[2]; +int tab4[2]; +int tab5[2]; +int tab6[2]; + +int *p, *p2, *p3, *p4, *p5, *p6, *p7; +int **q,**r,**s,**t; + +int a,b; + +void f_precis(int x, int i, int j, int k, int l, int m){ + +/* --------------------------- */ +/* Scalaires */ +/* --------------------------- */ + + a = i; + +/* --------------------------- */ +/* Structures */ +/* --------------------------- */ + + s1 = s2; + + s1.a = x; + + s1.b.a = x; + + s1.b = s8; + + s7 = s6.b; + +/* --------------------------- */ +/* Tableaux */ +/* --------------------------- */ + + tab1[0] = 2; + + tab1[1] = 2; + + tab2[i] = 2; + + tab3[i+j] = k; + + tab4[tab2[i]] = 2; + + tab5[tab2[1]] = 2; + + tab6[tab2[i]+j] = 2; + + +/* --------------------------- */ +/* Tableaux de structures */ +/* --------------------------- */ + + tab_s[0] = s2; /* @tab_s[0...] */ + + tab_s[1].a = x; + + tab_s1[i].b = s8; /* @tab_s[?,b...] */ + + tab_s2[tabl[0]] = s1; /* @tab_s[?...] */ + + tab_s3[tabl[1]].a = x; + + tab_s4[tabl[i]+x].a = x; + +/* --------------------------- */ +/* Structures et tableaux */ +/* --------------------------- */ + + s1.d[1] = x; + + s2.d[i] = x; + +/* --------- */ +/* Pointeurs */ +/* --------- */ + + p = &a; + + *p = x; + + *p = *p + x; + + q = (int*)0; + r = (int*)0; + + *q = p; + + **r = a; + + p2 = &tab1[2]; + + p3 = &tab1[i]; + + b = *(p3+2); + + p4 = p; + + p5 = (int *) 0x1000; + + p6 = (int*)0; + + *p6 = *(int *) 0x1000 + i; + + p7 = p2 + 1; + +/* p8 = p2 - i; */ + + s = (int*)0; + + *s = (int *) 0x1000; + + t = (int*)0; + (*t)[i] = 2; + +/* --------- */ + + s8.b = &a; + + *(s8.b) = x; + + s1.c = &s2; + + s1.c->a = x; + + s1.c->b = s8; + + s1.c->b.a = x; + + s1.c->b.b = &a; + + *(s1.c->b.b) = x; + + s1.c->c = &s2; + + s1.c->c->a = x; + + s1.c->c->b = s8; + + s1.c->c->b.a = x; + + s1.c->c->b.b = &a; + + *(s1.c->c->b.b) = x; + + s1.c->c->c = &s2; + + s1.c->c->c->a = x; + + s4.e[tabst[tab1[i+j]].a].a = *(tab2[k] + s5.e[tabst2[tab3[l] + m].a].b); + +/*------------------------------*/ +/* Clauses From attendues */ +/*------------------------------*/ +/* Clause From : @a[] From @i[*]; */ +/* Clause From : @s1[] From @s2[...]; */ +/* Clause From : @s1[a] From @x[*]; */ +/* Clause From : @s1[b,a] From @x[*]; */ +/* Clause From : @s1[b] From @s8[...]; */ +/* Clause From : @s7 From @s6[b...]; */ +/* Clause From : @tab1[(0)] From ; */ +/* Clause From : @tab1[(1)] From ; */ +/* Clause From : @tab2[(?)] From @i[*],@tab2[(?)]; */ +/* Clause From : @tab3[(?)] From @i[*],@j[*],@k[*],@tab3[(?)]; */ +/* Clause From : @tab4[(?)] From @tab2[(?),*],@i[*],@tab4[(?)]; */ +/* Clause From : @tab5[(?)] From @tab2[(2),*],@tab5[(?)]; */ +/* Clause From : @tab6[(?)] From @tab2[(?),*],@i[*],@j[*],@tab6[(?)]; */ +/* Clause From : @tab_s[(0)] From @s2[...]; */ +/* Clause From : @tab_s[(1),a] From @x[*]; */ +/* Clause From : @tab_s1[(?),b] From @i[*],@s8[...],@tab_s1[(?)]; */ +/* Clause From : @tab_s2[(?)] From @tabl[(0),*],@s1[...],@tab_s2[(?)]; */ +/* Clause From : @tab_s3[(?),a] From @tabl[(1),*],@x[*],@tab_s3[(?)]; */ +/* Clause From : @tab_s4[(?),a] From @tabl[(?),*],@i[*],@x[*],@x[*],@tab_s4[(?)]; */ +/* Clause From : @s1[d,(1)] From @x[*]; */ +/* Clause From : @s2[d,(?)] From @i[*],@x[*],@s2[d,(?)]; */ +/* Clause From : @p[] From @a[]; */ +/* Clause From : @p[*] From @x[*]; */ +/* Clause From : @p[*] From @p[*][*],@x[*]; */ +/* Clause From : @q[*] From @p[*]; */ +/* Clause From : @r[*][*] From @a[*]; */ +/* Clause From : @p2[] From @tab1[(2)]; */ +/* Clause From : @p3[] From @tab1[(?)],@i[*]; */ +/* Clause From : @p4[] From @p[*]; */ +/* Clause From : @p5[] From @Pt!4096[*]; */ +/* Clause From : @p6[*] From @Pt!4096[*][*],@i[*]; */ +/* Clause From : @s[*] From @Pt!4096[*]; */ +/* Clause From : @t[*][*][(?)] From @i[*],@t[*][*][(?)]; */ +/* Clause From : @s8[b] From @a[]; */ +/* Clause From : @s8[b,*] From @x[*]; */ +/* Clause From : @s1[c] From @s2[]; */ +/* Clause From : @s1[c,*][a] From @x[*]; */ +/* Clause From : @s1[c,*][b] From @s8[...]; */ +/* Clause From : @s1[c,*][b,a] From @x[*]; */ +/* Clause From : @s1[c,*][b,b] From @a[]; */ +/* Clause From : @s1[c,*][b,b,*] From @x[*]; */ +/* Clause From : @s1[c,*][c] From @s2[]; */ +/* Clause From : @s1[c,*][c,*][a] From @x[*]; */ +/* Clause From : @s1[c,*][c,*][b] From @s8[...]; */ +/* Clause From : @s1[c,*][c,*][b,a] From @x[*]; */ +/* Clause From : @s1[c,*][c,*][b,b] From @a[]; */ + +/* Clause From : @s1[c,*][c,*][b,b,*] From @x[*]; */ +/* Clause From : @s1[c,*][c,*][c] From @s2[]; */ +/* Clause From : @s1[c,*][c,*][c,*][a] From @x[*]; */ +/* Clause From : @s4[e,(?),a] From */ +/* @tabst[(?),a,*],@tab1[(?),*],@i[*],@j[*],@s5[e,(?),b,*][(?),*], */ +/* @tab2[(?),*],@k[*],@tabst2[(?),a,*],@tab3[(?),*],@l[*],@m[*],@s4[e,(?)]; */ + + +} + + +static void fonc (int * p, int x) { + *(p+3) = *p + x; +} + +int Tab[10]; +int * P; + +void f_tab_0 (int y) { + fonc (Tab, y); +} +void f_tab_2 (int y) { + fonc (Tab+2, y); +} +void f_p_0 (int y) { + fonc (P, y); +} +void f_p_2 (int y) { + fonc (P+2, y); +} + +void g (int * p) { + *p = *p+1; +} +int test_g (void) { + int x = 3; + g (&x); + return x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct3.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct3.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct3.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct3.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,42 @@ +struct st1 { + int a; + int *b; +}; + +struct st2 { + int a; + int d[10]; + struct st1 b; + struct st1 e[10]; + struct st2 *c; +}; + +struct st1 tabst[10], tabst2[10]; + +struct st2 tab_s[2]; +struct st2 tab_s1[2]; +struct st2 tab_s2[2]; +struct st2 tab_s3[2]; +struct st2 tab_s4[2]; + +struct st2 s1,s2,s4,s5,s6; +struct st1 s8,s7; + +void main () { + s1.a=2; + s1.c = &s1; + s1.d[0] = 1; + s1.d[1] = 2; + s1.d[2] = 2; + + s1.b.a = 3; + s1.d[8] = 2; + s1.d[9] = 2; + + s1.d[10] = 2; + + + + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct_array.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct_array.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct_array.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct_array.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,14 @@ +struct st1 { + int a; + int b; + int *pp; + int *p; +}; +int *outp; +int x,y,z1,z2,z3,z4; +struct st1 T[22] = { {1,2,0,&x}, {&z1,&z2,&z3,&y},{&z4,2,0,&x},{1,2,0,&x} }; +int main (char c) { + outp = T[c].p; + *outp = 5; + z1++; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct_call.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct_call.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct_call.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct_call.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,36 @@ +/* run.config + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -journal-disable -machdep ppc_32 +*/ +int G= 77; +int GG; + +struct A { int x; int y; }; +struct B { int z; int t; }; + +struct A t[4]; +struct A tt[5]; + +int g(struct A s) +{ + Frama_C_show_each_G(s); + return s.y; // (*((struct B*)(&t[1]))).t; + +} + +struct A create_A() { + struct A r={0,0}; + r.x = 1; +// r.y = 2; + Frama_C_show_each_GG(r); + return r; +} + +int main(void) +{ + int i = 2 - 1; + t[1].y = G; + GG = g(tt[i]); + struct A init = create_A(); + return g(t[i]); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct_deps.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct_deps.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct_deps.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct_deps.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +struct Tstr { int a; int b; }; + +int f (struct Tstr * ps) { + return ps->a; +} + +int f3(int*p) { return *p ;} + +int main (int x, int y) { + struct Tstr s = {x, y}; +// return f3(&s); + return f(&s); +} + +int f2 (struct Tstr s) { + return s.a; +} + +int main2 (int x, int y) { + struct Tstr s = {x, y}; + return f2(s); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,78 @@ +int f (int a, int b){ + int w; + struct t1 { int x; int y;} v1,v2; + v1.x = w; + if (w) w=1; + v1=v2; + if (v1.y) v1.x = a; + v1.y = b; + a = b; + return v1.x; + } +int GG; +int simple (int a, int b){ + int w=3; + struct t1 { int x; int y;} v1,v2; + v2.x=3; + v2.y=5; + v1=v2; + return v1.x; +} + + +int less_simple (int a, int b){ + int w=3; + struct t1 { int x; int y;} v1,v2,v3; + v2.x=3; + v2.y=5; + v3.x=7; + v3.y=9; + v1=a?v2:v3; + return v1.x; +} + + int w; +struct t1 { int x; int y;} v1; + struct t1 v2; + struct t2 { int x; int y;} v3; + +int T[2] = { 1, 1 }; +int R1, R2; + +int main (int a, int b){ + R1 = 1 + *(int*)((char*)T+2); + *(char*)T = 2; + R2 = 1 + T[0]; + v1 = v2; + v1.x = a+b; + w = v1.x; + if (a) +{ + + + v2.x = a; + /* v3.x = b; + w = w + v2.x + v3.x;*/ + } + return w; +} + +int fonc2 (int a, int b){ + int w; + struct t1 { int x; int y;} v1; + v1.x = a+b; + w = v1.x; + return w; +} + +void mune (int a, int b){ + v1=v2; + v1.x = a; +} + +int G; + +void mtwo (int c1,int c2) { + if (c1) v1.x = G; + v1.y = v1.x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct_incl.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct_incl.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct_incl.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct_incl.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,50 @@ +struct st1 { + int a; + long b; +}; + +struct st2 { + int a; + int d[10]; + struct st1 b; + struct st1 e[10]; + struct st2 *c; +}; + +struct st1 tabst[10], tabst2[10]; + +struct st2 tab_s[2]; +struct st2 tab_s1[2]; +struct st2 tab_s2[2]; +struct st2 tab_s3[2]; +struct st2 tab_s4[2]; + +struct st2 s1,s2,s4,s5,s6; +struct st1 s8,s7; + +long x,y,z,t; + +void main () { + x = &s1.d[9]; + y = &s1.d[10]; + z = &s1.b; + + + + s1.a=2; + s1.c = &s1; + s1.d[0] = 2; + s1.d[1] = 2; + s1.d[2] = 2; + + s1.b.a = 3; + + s1.d[5] = 7; + + + s1.d[8] = 8; + s1.d[9] = 8; + + s1.d[10] = 777; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/struct_p_call.i frama-c-20111001+nitrogen+dfsg/tests/misc/struct_p_call.i --- frama-c-20110201+carbon+dfsg/tests/misc/struct_p_call.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/struct_p_call.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ + +typedef struct S {char v; int w;} U; + + +void f(U* G1) { + G1->w = 0; + G1->v = 1; + return; +} + + +char main () { + U H1; + f(&H1); + return H1.v; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/switch2.i frama-c-20111001+nitrogen+dfsg/tests/misc/switch2.i --- frama-c-20110201+carbon+dfsg/tests/misc/switch2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/switch2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,20 @@ +/*run.config + STDOPT: +"-simplify-cfg" +"-check" + */ + +int f(int x) { return x+1; } + +extern void g(int,int); + +int main () { + int exit_loop = 0; + switch (16) { + case 16: + g(exit_loop++,({exit_loop++; exit_loop++;f(exit_loop);})); + break; + default: + exit_loop = 1; + break; + } + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/switch.i frama-c-20111001+nitrogen+dfsg/tests/misc/switch.i --- frama-c-20110201+carbon+dfsg/tests/misc/switch.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/switch.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,55 @@ +/* run.config + OPT: -float-normal -memory-footprint 1 -val -deps -out -input -journal-disable + OPT: -float-normal -memory-footprint 1 -val -deps -out -input -journal-disable -simplify-cfg +*/ + +int result1, result3, result4; +int result2=7; +double d2; + +int main (int c, int d, int e, int f, double d1, long l) { + + switch (d) + { + case 1: + result1 = 1; + break; + case 2: + result1 = 2; + break; + case 3: + result1 = 3; + case 4: + result1 = 4; + break; + } + + switch(c) + { + case 0: CEA_F(c); return c; + case 2: return c; + } + + switch (e) + { + case 0: result2 = e; + } + f = f ? 14 : 42; + switch (f==14) + { + case 0: result3 = f; + } + + switch(d1>=0.0) + { + case 0: d2=-d1;break; + default: d2=d1; break; + } + + switch(l) + { + case 0x0FFFFFFF: result4 = 1; break; + case 0xFFFFFFFF: result4 = 2; break; + } + return 77; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/syntactic_hook.i frama-c-20111001+nitrogen+dfsg/tests/misc/syntactic_hook.i --- frama-c-20110201+carbon+dfsg/tests/misc/syntactic_hook.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/syntactic_hook.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,31 @@ +/* run.config + OPT: -load-script tests/misc/syntactic_hook.ml -print +*/ + +int f(void); + +int f(int); //warns conflicting decls + +int h(const int*); + +int h(int *x) { return *x; } // warns different decls. + +int k(int *); + +int k(int * x) { return (*x)++; } + +int main () { + int x = 0; int y = 0; + int t(void); + x=t(); + x++; + x; // warn ignore pure exp + g(3); // warn implicit proto + x = sizeof(x++); // warn drop side-effect + x = x++ && x; + y = x && x++; // warn conditional side-effect + y = x && (x++ || x); // warn conditional side-effect + y = x && (x || x++); // warn conditional side-effect + y = x ? x++ : x++; // warn conditional side-effect + return x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/syntactic_hook.ml frama-c-20111001+nitrogen+dfsg/tests/misc/syntactic_hook.ml --- frama-c-20110201+carbon+dfsg/tests/misc/syntactic_hook.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/syntactic_hook.ml 2011-10-10 08:39:03.000000000 +0000 @@ -27,20 +27,15 @@ let warn_pure_exp f e = let loc = e.eloc in - let source = { Log.src_file = (fst loc).pos_fname; - Log.src_line = (fst loc).pos_lnum } - in - Kernel.warning ~source "[SH]: function %s, pure expression %a is dropped" + Kernel.warning ~source:(fst loc) + "[SH]: function %s, pure expression %a is dropped" f (!Ast_printer.d_exp) e ;; Cabs2cil.register_ignore_pure_exp_hook warn_pure_exp;; let warn_proto vi = - let source = { Log.src_file = (fst vi.vdecl).pos_fname; - Log.src_line = (fst vi.vdecl).pos_lnum } - in - Kernel.warning ~source "[SH]: implicit declaration for prototype %a" + Kernel.warning ~source:(fst vi.vdecl) "[SH]: implicit declaration for prototype %a" (!Ast_printer.d_ident) vi.vname ;; @@ -48,11 +43,9 @@ ;; let warn_conflict oldvi vi reason = - let source = { Log.src_file = (fst vi.vdecl).pos_fname; - Log.src_line = (fst vi.vdecl).pos_lnum; } - in Kernel.warning - ~source "[SH]: conflict with declaration of %a at line %d: %s" + ~source:(fst vi.vdecl) + "[SH]: conflict with declaration of %a at line %d: %s" !Ast_printer.d_ident vi.vname (fst oldvi.vdecl).pos_lnum reason @@ -61,11 +54,8 @@ Cabs2cil.register_incompatible_decl_hook warn_conflict;; let warn_distinct oldvi vi = - let source = { Log.src_file = (fst vi.vdecl).pos_fname; - Log.src_line = (fst vi.vdecl).pos_lnum; } - in Kernel.warning - ~source + ~source:(fst vi.vdecl) "[SH]: definition of %a does not use exactly the same prototype as \ declared on line %d" !Ast_printer.d_ident vi.vname @@ -75,18 +65,14 @@ Cabs2cil.register_different_decl_hook warn_distinct;; let warn_local_func vi = - let source = { Log.src_file = (fst vi.vdecl).pos_fname; - Log.src_line = (fst vi.vdecl).pos_lnum; } - in - Kernel.warning ~source + Kernel.warning ~source:(fst vi.vdecl) "[SH]: definition of local function %a" !Ast_printer.d_ident vi.vname ;; Cabs2cil.register_local_func_hook warn_local_func;; let warn_drop_effect olde e = - let source = Cil.source e.eloc in - Kernel.warning ~source + Kernel.warning ~source:(fst e.eloc) "[SH]: dropping side effect in sizeof: %a is converted to %a" Cprint.print_expression olde !Ast_printer.d_exp e @@ -95,7 +81,7 @@ Cabs2cil.register_ignore_side_effect_hook warn_drop_effect let warn_cond_effect orig e = - let source = Cil.source e.expr_loc in + let source = fst e.expr_loc in Kernel.warning ~source "[SH]: side effect of expression %a occurs in \ conditional part of expression %a. It is not always executed" diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/syntax.i frama-c-20111001+nitrogen+dfsg/tests/misc/syntax.i --- frama-c-20110201+carbon+dfsg/tests/misc/syntax.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/syntax.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,20 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -ulevel 22 -journal-disable +*/ + +// #include <stdio.h> +int a; +int t[25]; +int main() +{ + int i; + for (i=-10; i< 10; i++) + { + t[i+10] = (int*)(i+10)-(int*)10; + } +} + + + +// diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/tab1.i frama-c-20111001+nitrogen+dfsg/tests/misc/tab1.i --- frama-c-20110201+carbon+dfsg/tests/misc/tab1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/tab1.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +int G[10] ={0}; + +void main (int x) { + + if (0 <= x) + { + G[0] =x; + } + + if (0 >= x) + { + G[1] =x; + } + + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/termination.i frama-c-20111001+nitrogen+dfsg/tests/misc/termination.i --- frama-c-20110201+carbon+dfsg/tests/misc/termination.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/termination.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,35 @@ +int G[10]= {0}; + +int X; + +void loop(int d) { +// int *p = &d; + +// G[1] = 6; + if(d) ; else ; + X=0; + + if(d) X=1; else L:; + + X=2; +// while(1) { X = 2; G[2] = 77; } + return; +} + + + +void main(int c) { +/* + if (c) {loop (c);} + if (c+1) {loop (c);} + if (c+2) {loop (c);} + if (c+3) {loop (c);} + + if (1) loop (0); + G[2] = 5; +*/ + +// c = 1; + loop(c?1:0); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/test_array.i frama-c-20111001+nitrogen+dfsg/tests/misc/test_array.i --- frama-c-20110201+carbon+dfsg/tests/misc/test_array.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/test_array.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main g -journal-disable -unspecified-access +*/ +int j; +int t[10]; + +void g(int i){ + for (i=1; + i < 1000; + i++) + t[i] = j+i++; + + j=1; + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/test.i frama-c-20111001+nitrogen+dfsg/tests/misc/test.i --- frama-c-20110201+carbon+dfsg/tests/misc/test.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/test.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main inst_F6 -absolute-valid-range 0x200-0x199 + OPT: -memory-footprint 1 -val -deps -out -input -main f +*/ +void inst_F6(int *v,int n){ int t[3]; t[1] = 4; + int i,j,ecart,tmp; + { int i = 0 ; i++ ; j = i; }; + for (ecart = n/2; ecart >0; ecart /=2) + for (i = ecart; i < n; i++) + for (j = i-ecart; j>=0 && v[j]>v[j+ecart]; j = j-ecart){ + tmp = v[j]; + v[j] = v[j+ecart]; + v[j+ecart] = tmp; + } +} + +void f() { + int t[88888]; + t[0] = 99; + t[1] = t[100]; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/threat_array.i frama-c-20111001+nitrogen+dfsg/tests/misc/threat_array.i --- frama-c-20110201+carbon+dfsg/tests/misc/threat_array.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/threat_array.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,17 @@ +int T [10]; +int (*p)[10]; +void main (int c) { + +/*@ assert \valid(T + c); // synthesized alarm caused by a memory access +*/ +/*@ assert \valid(T); */ + + p = (int (*)[10])&T[5]; + + if(!c) { + /*@ assert \valid( *p); // means that the first element of *p is valid ! */ + } + + T[c] = 4; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/threat_if.i frama-c-20111001+nitrogen+dfsg/tests/misc/threat_if.i --- frama-c-20110201+carbon+dfsg/tests/misc/threat_if.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/threat_if.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,22 @@ +int *p; +int l,m; +int i; +int X=-992; + +void main(int i) { + int G = 258+128; + signed char c; + + + if(i==0) p = &l; + if(i==0) *p = 1; + + c = (signed char)G; // -126 + G = c; + printf("%d\n",G); + return G; + + for (i=-1000+8; i<2008; i+=100) + X = i; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/typedef_function.i frama-c-20111001+nitrogen+dfsg/tests/misc/typedef_function.i --- frama-c-20110201+carbon+dfsg/tests/misc/typedef_function.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/typedef_function.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,9 @@ +typedef void T(void); +extern T F476 ; + +static T* const G209[] = { 0,& F476}; + +int main () { + int i = (int)G209[0]; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/typeof.i frama-c-20111001+nitrogen+dfsg/tests/misc/typeof.i --- frama-c-20110201+carbon+dfsg/tests/misc/typeof.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/typeof.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,4 @@ +extern void y(); +void main() { + (typeof(y()))0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/ulongvslonglong.i frama-c-20111001+nitrogen+dfsg/tests/misc/ulongvslonglong.i --- frama-c-20110201+carbon+dfsg/tests/misc/ulongvslonglong.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/ulongvslonglong.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + OPT: -memory-footprint 1 -val -journal-disable -machdep x86_64 + OPT: -memory-footprint 1 -val -journal-disable +*/ + +int x; +long x2; +unsigned long x9[6][2]; + +main(){ + x2 = 2793414595; + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < 2; j++) + x9[i][j] = 1U; + } + x = ((0x090E7AF82577C8A6LL | x9[0][1]) <= (~(x2 || x9[0][1]))); + return x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/undef_fct.i frama-c-20111001+nitrogen+dfsg/tests/misc/undef_fct.i --- frama-c-20110201+carbon+dfsg/tests/misc/undef_fct.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/undef_fct.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ +int main() +{ + return f(3); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/undefined_sequence2.i frama-c-20111001+nitrogen+dfsg/tests/misc/undefined_sequence2.i --- frama-c-20110201+carbon+dfsg/tests/misc/undefined_sequence2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/undefined_sequence2.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,71 @@ +/* run.config + STDOPT: +"-unspecified-access" +*/ +/* based on an example from J. Regehr on the why list */ +/* precondition: false */ +int a[2]; + +int +multiple_update_wrong_1 (int *x, int *y) +{ + return (*x = 0) + (*x = 0); +} + +/* precondition: false */ +int +multiple_update_wrong_2 (int i) +{ + i = ++i + 1; + return i; +} + +/* precondition: false */ +int +multiple_update_wrong_3 (int i) +{ + a[i++] = i; + return i; +} + +/* precondition: x != y */ +int +multiple_update_unsafe (int *x, int *y) +{ + return (*x = 0) + (*y = 0); +} + +/* precondition: true */ +int +multiple_update_safe (int *x, int *y) +{ + if (x == y) + { + return 0; + } + else + { + return (*x = 0) + (*y = 0); + } +} + +int main () { + int b,c; + b = 0; + c = 0; + + multiple_update_wrong_1(&b, &c); + + multiple_update_wrong_2(b); + + multiple_update_wrong_3(c); + + multiple_update_unsafe(&b,&c); // does not lead to an alarm + + multiple_update_unsafe(&b, &b); + + multiple_update_safe(&b,&c); // does not lead to an alarm + + multiple_update_safe(&c,&c); // does not lead to an alarm + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/undefined_sequence.i frama-c-20111001+nitrogen+dfsg/tests/misc/undefined_sequence.i --- frama-c-20110201+carbon+dfsg/tests/misc/undefined_sequence.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/undefined_sequence.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,56 @@ +/* run.config + STDOPT: +"-unspecified-access" + STDOPT: +"-no-unspecified-access" +*/ +/* detection of undefined behavior for read/write accesses + in unspecified order +*/ +int G[10]; + +int f (int x) { return x+1;} +int g (int x) { return x+2;} + +int r, H; +int h(int i) +{ + r = r++; //UB + i = r++; //Not UB + H = i; + return i; +} + +int func(int x, int y) { return x + y; } + +int main (int a) { + int x, *y, i,j; + x = 0; + y = &x; + i=(x=0)+(*y=1); + for (i=0; i < 10; i++) G[i] = i; + i=j=0; + while (j<10 && i<10) G[j++] = G[i++]; + i=j=0; + while (j<10 && i<10) G[j++] += G[i++]; + i=j=0; + while(j<10 && i<10) { + G[j] = G[j++]; // UB + G[i++] = G[i]; // UB + } + i=j=0; + while(j<10 && i<10) { + G[j] += G[j++]; // UB + G[i++] += G[i]; // UB + } + i = f(g(3)+x) + x++; //UB + *y = f(g(3)+x); // no UB: x is read to write to x (through an alias) + if (a) + r = h(1) + h(2); // missing alarm! + + y = &G[2]; + + *y = (G[2] < (func((0U || + (((G[2] ^ G[2]) <= G[2]) < ((*y) || G[2]))), 5))); + + int (*my_f) (int) = f; + return (my_f=g, f(1)) + my_f(2); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/uninit.i frama-c-20111001+nitrogen+dfsg/tests/misc/uninit.i --- frama-c-20110201+carbon+dfsg/tests/misc/uninit.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/uninit.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ +int main () { + int i; + i++; + return i; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/uninitialized_gnubody.i frama-c-20111001+nitrogen+dfsg/tests/misc/uninitialized_gnubody.i --- frama-c-20110201+carbon+dfsg/tests/misc/uninitialized_gnubody.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/uninitialized_gnubody.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,5 @@ +int main () { + int x = 0; + x = ({ int y = 0; y++; y + 1;}) + 42; + return x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/unroll.i frama-c-20111001+nitrogen+dfsg/tests/misc/unroll.i --- frama-c-20110201+carbon+dfsg/tests/misc/unroll.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/unroll.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,78 @@ +void main (int c) { + int G=0,i; + int MAX = 12; + int JMAX=5; + int j; + /*@ loop pragma UNROLL_LOOP 14; */ // first loop unrolled 14 times + for (i=0; i<=MAX; i++) + { + G+=i; + } + /*@ loop pragma UNROLL_LOOP 124; */ + for (i=0; i<=10*MAX; i++) + { + G+=i; + } + /*@ loop pragma UNROLL_LOOP 14; */ + for (i=0; i<=MAX; i++) + { + j=0; + /*@ loop pragma UNROLL_LOOP 50; */ + while (j<=JMAX) + { + G+=i; + j++; + } + } + +//@ loop pragma UNROLL_LOOP 128; + do { + G += i; + i++; + j--; + } + while (i<=256 || j>=0); + +//@ loop pragma UNROLL_LOOP 10; + do + { if(c) continue; + + if(c--) goto L; + c++; + L: c++; + } + while(c); + +//@ loop pragma UNROLL_LOOP c; + while(0); + +} + +#if 0 +struct T { unsigned long long addr; + unsigned long long size; + unsigned long type; } t_biosmap[10]; + +struct T * const g_biosmap = t_biosmap; +struct T * biosmap; +int main2(int c,signed char nr_map) { + biosmap = g_biosmap; + if (nr_map<2) return (-1); + +//@ loop pragma UNROLL_LOOP 200; + do { + unsigned long long start = biosmap->addr; + unsigned long long size = biosmap->size; + unsigned long long end = start + size; + unsigned long type = biosmap->type; + CEA_F(nr_map); + if (start>end) return -1; + if (c) { + start = 0x100000L; + size = end - start; continue; }; + } + while (biosmap++,--nr_map); + + return 0; +} +#endif diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/unroll_labels.i frama-c-20111001+nitrogen+dfsg/tests/misc/unroll_labels.i --- frama-c-20110201+carbon+dfsg/tests/misc/unroll_labels.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/unroll_labels.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,31 @@ +/* run.config + OPT: -val -main main -check -print + OPT: -val -main main2 -check -print -slevel 2 +*/ + + +void main () { + int j = 0; + /*@ loop pragma UNROLL_LOOP 4; */ + for (int i=1;i<4;i++) { + switch (i) { + case 1: j+=1; break; + case 2: j+=3; break; + case 3: j+=5; break; + case 4: j+=7; break; + default: j=0; + } + } +} + +void main2 () { + /*@ loop pragma UNROLL_LOOP 2; */ + for (int i=0;i<2;i++) { + for (int j=0;j<2;j++){ + i += 1; + goto foo; + i += 1; + foo: + } + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/unroll_simple.i frama-c-20111001+nitrogen+dfsg/tests/misc/unroll_simple.i --- frama-c-20110201+carbon+dfsg/tests/misc/unroll_simple.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/unroll_simple.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,24 @@ +void main (int c) { + int G=0,i=4; + int MAX = 12; + int JMAX=5; + int j=3; + +//@ loop pragma UNROLL_LOOP 128; + do { + G += i; + i++; + j--; + } + while (i<=256 || j>=0); + +//@ loop pragma UNROLL_LOOP 10; + do + { if(c) continue; + + if(c--) goto L; + c++; + L: c++; + } + while(c); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/unroll_visit.i frama-c-20111001+nitrogen+dfsg/tests/misc/unroll_visit.i --- frama-c-20110201+carbon+dfsg/tests/misc/unroll_visit.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/unroll_visit.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + STDOPT: +"-print" + */ +void main() { + /*@ loop pragma UNROLL_LOOP 2; */ + for(int i=0; i<100; i++) { + i--; + //@ assert i<100; + i++; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/val6.i frama-c-20111001+nitrogen+dfsg/tests/misc/val6.i --- frama-c-20110201+carbon+dfsg/tests/misc/val6.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/val6.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,28 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -absolute-valid-range 0x1-0xFFFFF -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f1 -absolute-valid-range 0x1-0xFFFFF -journal-disable +*/ +char **c,a,*b,**y; +int x; + +int f() { + a = 'b'; + b = &a; + c = &b; + x = (int)c; + y = (char**)x; + *((char**)0x12) = &b; + **((char**)0x12)='a'; + +} + +int f1() { + *((char*)17) = 27; + *((char*)19) = 29; + + x = c?17:19; + b = (char*)x; + *b = 0; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/val9.i frama-c-20111001+nitrogen+dfsg/tests/misc/val9.i --- frama-c-20110201+carbon+dfsg/tests/misc/val9.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/val9.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,59 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable +*/ +int TT[10]={1,2,3}; +int T[10]={1,2,3}; +int i,a,b; +int a7, b7; + +int O1[20]; +int O2[20]; +int *p; + +int x2,*b2,a2; + +void f() { + for (i = 0; i <= 8; i++) { + TT[i] = i; + *((int*)((char*)&(TT[i]) + 1)) = 0; + } + + a = 1; + if (b) i=5; else i=6; + a=3; + if (i>=2) { a = i ; T[i] = 7 ; } + + for (i = 0; i <= 8; i++) { + *(char *) &a = 1; +b = a; + + *((int*)(((char*)&(T[i])) + 1)) = 0; + } + + + + + a7 = 'a'; + *(char *) &a7 = 1; + b7 = (char)a7; + + + ((int*)O1)[1]=17; + ((char*)O1)[1]=18; + + + ((int*)O2)[0]=10; + ((char*)O2)[1]=11; + + O1[6]=0; + p=O1+9; + *p=1; + + + x2 = 777; + a2 = (int)&x2; + b2 = (int*) a2; + *((int*)a2) = 0; + *b2=*b2+1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/val_if.i frama-c-20111001+nitrogen+dfsg/tests/misc/val_if.i --- frama-c-20110201+carbon+dfsg/tests/misc/val_if.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/val_if.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,47 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f2 -journal-disable +*/ +int i,j,x,k,l,m,n,d; +void f(int c){ + int j = 12; + if (c) x=1; else x = -1; + + if (x<=-2) j = x; + + i = 10; +} + +void f1(int c){ + j= 13; + k= 14; + l= 15; + if (c) x=1; else x = -1; + + if (x<=0) + {j = x; + if (x<=-2) k = x; + l=x; + } + + i = 10; +} + +void f2(int c) { + j= 16; + k= 17; + l= 18; + if (c) x=1; else { + if (d) x=2; else x = 3; + } + + if (x <= 1 || x>=3 ) + { x = 2; + j = x; + } + else { x++ ; k = x;}; + + i = 10; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/val_ptr.i frama-c-20111001+nitrogen+dfsg/tests/misc/val_ptr.i --- frama-c-20110201+carbon+dfsg/tests/misc/val_ptr.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/val_ptr.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,55 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main f -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f1 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f3 -journal-disable + OPT: -memory-footprint 1 -val -deps -out -input -main f2 -journal-disable +*/ +int i,j,x,k,l,m,n,d,a,b,c; +int *p; + +void f(int c) { + j= 16; + k= 17; + l= 18; + a= 11; b = 12; d= 13; + + + p = &a; + if (c) p=&a; else { + a = 10; + if (d) p=&b; else p = &d; + } + if (a <= 10) + { j = *p; + k = a; + } + else { k = *p ;}; + + i = 10; +} + +int T[8],*p; +void f1() { + for (p=T;p==&T[8];p++) + *p = 0 ; +} + + +void f3() { + p = T; + if (p + 8 <= &T[8]) + *p = 0 ; +} + +void f2(int c) +{ + j = 3; + a = 1; + b = 2; + c = 0; + if (!c) p = &a; else p = &b; + if (!p) + j = *p; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/video_detect.i frama-c-20111001+nitrogen+dfsg/tests/misc/video_detect.i --- frama-c-20110201+carbon+dfsg/tests/misc/video_detect.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/video_detect.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,33 @@ +int G; + +typedef short u16; + +static int detect_video(void *video_base) +{ + volatile u16 *p = (u16 *)video_base; +// CEA_F(p,p[0]); + u16 saved1 = p[0]; + u16 saved2 = p[1]; + int video_found = 1; + + + p[0] = 0xAA55; + p[1] = 0x55AA; + if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) ) + video_found = 0; + + p[0] = 0x55AA; + p[1] = 0xAA55; + if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) ) + video_found = 0; + + p[0] = saved1; + p[1] = saved2; + + return video_found; +} + +int main(void) { + void * ADDR=(void*)0x20; + return(detect_video(ADDR)); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/vis_spec.i frama-c-20111001+nitrogen+dfsg/tests/misc/vis_spec.i --- frama-c-20110201+carbon+dfsg/tests/misc/vis_spec.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/vis_spec.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + DONTRUN: bts 0727. Not fixed yet + OPT: -load-script tests/misc/vis_spec.i +*/ + +//@ assigns \nothing; +void g () ; + +//@ assigns \nothing; +void f () { g(); } + diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/vis_spec.ml frama-c-20111001+nitrogen+dfsg/tests/misc/vis_spec.ml --- frama-c-20110201+carbon+dfsg/tests/misc/vis_spec.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/vis_spec.ml 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,37 @@ +open Cil_types +open Cil + +class pathcrawlerVisitor prj = +object(self) + inherit Visitor.frama_c_copy prj + + method vspec sp = + Format.printf "Considering spec of function %s@." + (Kernel_function.get_name (Extlib.the self#current_kf)); + (match self#current_func with + | Some f -> + if f.svar.vname ="f" then ( + Format.printf "Funspec of f is '%a' through visitor@." + Cil.d_funspec sp; + Format.printf "It is '%a' through get_spec@." + Cil.d_funspec + (Kernel_function.get_spec (Globals.Functions.get f.svar)); + ) + | None -> + Format.printf "Function prototype; Funspec is '%a'@." + Cil.d_funspec sp; + ); + DoChildren +end + +let startup () = + let cil_file = Ast.get () in + Format.printf "Starting visit@."; + let prj = File.create_project_from_visitor "pcanalyzer" + (fun prj -> new pathcrawlerVisitor prj) + in + Format.printf "End visit@."; + Project.set_current prj; +;; + +let () = Db.Main.extend startup diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/volatile.i frama-c-20111001+nitrogen+dfsg/tests/misc/volatile.i --- frama-c-20110201+carbon+dfsg/tests/misc/volatile.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/volatile.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,47 @@ +int volatile G = 1; +volatile int F, E, X, Y, *pV; + +int k = 1, x = 2, y = 3; +int a,b,c,d,e,f,g,h,i,j,l,m,n,o, *pv; + +struct s { int a; volatile int b; } s1,s2={1,1}; + +struct sv { int a; volatile int b; }; + +volatile struct sv sv1, sv2={1,1}; + +int main () { + G = G; + k = G; + + /* reading an uninitialized volatile variable */ + a = F ? 11 : 12; + + /* relations involving volatile variables */ + b = F; + c = F; + d = b - c; + e = F - F; + g = F; + f = F - g; + l = F + 1; + m = 2 + F; + n = F - l; + o = m - l; + + /* lval to lval assignment to volatile variable */ + h = 1; + E = h; + + /* assignement via pointer */ + X = -1; + Y = -1; + pv = (int *) &X; + *pv = x; /* assignment to volatile X */ + x = *pv; + pV = &Y; + *pV = y; /* assignment to volatile Y */ + y = *pV; + + return Y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/wide_string.c frama-c-20111001+nitrogen+dfsg/tests/misc/wide_string.c --- frama-c-20110201+carbon+dfsg/tests/misc/wide_string.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/wide_string.c 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,13 @@ +#include "share/libc/stddef.h" + +int main() { + + // String literals are lvalues + char (*p)[4] = &("bar"); + wchar_t (*q)[4] = &(L"foO"); + + if((*p)[1] != 'a') return 1; + if((*q)[1] != 'o') return 2; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/misc/with_comment.i frama-c-20111001+nitrogen+dfsg/tests/misc/with_comment.i --- frama-c-20110201+carbon+dfsg/tests/misc/with_comment.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/misc/with_comment.i 2011-10-10 08:39:03.000000000 +0000 @@ -0,0 +1,36 @@ +/* run.config + GCC: + OPT: -memory-footprint 1 -val -deps -out -input -main main2 -journal-disable +*/ +/* Commentaire avant G comment*/ /* Commentaire avant G2 comment*/ +static int G; +/* Commentaire apres G avant main comment*/ + + +int main2 () { +/* Commentaire apres main comment*/ + int i; +/* Commentaire apres int i comment + Big Comment line 1 + Bif Comment line 2 */ + G = 0; + +/* Commentaire avant loop comment*/ + /*@ loop pragma UNROLL_LOOP 0; */ + for(i=0; i<=10; i++) + G++; + +// AVANT j + {int /* milieu jcomment*/ j; + j = /* milieu j 2comment*/ 0; } +// APRES j + + return i; +} + +/* ICI avant H comment*/ +static int H; +/* ICI apres H comment*/ +// fin + +int HHH; diff -Nru frama-c-20110201+carbon+dfsg/tests/occurrence/ptr_assert.i frama-c-20111001+nitrogen+dfsg/tests/occurrence/ptr_assert.i --- frama-c-20110201+carbon+dfsg/tests/occurrence/ptr_assert.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/occurrence/ptr_assert.i 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,18 @@ +/* run.config + GCC: + STDOPT: +"-occurrence" +*/ + +int x, y; + +int main(int z) { + int *p = &x, *q; + *p = 0; + /*@ assert (x == 0); */ + q = &y; + p = q; + *q = 1; + *p = 2; + /*@ assert (y == 2 && *q == 2 && *p == 2 && x == 0); */ + return z; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/annot.c frama-c-20111001+nitrogen+dfsg/tests/pdg/annot.c --- frama-c-20110201+carbon+dfsg/tests/pdg/annot.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/annot.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config - OPT: -fct-pdg f1 -main f1 -journal-disable - OPT: -fct-pdg loop -main loop -journal-disable + OPT: -fct-pdg f1 -main f1 -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg loop -main loop -journal-disable -pdg-print -pdg-verbose 2 */ int G; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/call.c frama-c-20111001+nitrogen+dfsg/tests/pdg/call.c --- frama-c-20110201+carbon+dfsg/tests/pdg/call.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/call.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -lib-entry -main g -pdg -dot-pdg tests/pdg/call -journal-disable + OPT: -lib-entry -main g -pdg -dot-pdg tests/pdg/call -journal-disable -pdg-print -pdg-verbose 2 */ /* Ne pas modifier : exemple utilisé dans le rapport. */ diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/calls_and_implicits.c frama-c-20111001+nitrogen+dfsg/tests/pdg/calls_and_implicits.c --- frama-c-20110201+carbon+dfsg/tests/pdg/calls_and_implicits.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/calls_and_implicits.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config * GCC: - * OPT: -fct-pdg main -inout -journal-disable + * OPT: -fct-pdg main -inout -journal-disable -pdg-print -pdg-verbose 2 * */ diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/calls_and_struct.c frama-c-20111001+nitrogen+dfsg/tests/pdg/calls_and_struct.c --- frama-c-20110201+carbon+dfsg/tests/pdg/calls_and_struct.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/calls_and_struct.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -deps -input -out -inout -pdg -journal-disable + OPT: -deps -input -out -inout -pdg -journal-disable -pdg-print -pdg-verbose 2 */ struct Tstr { int a; int b; int c; }; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/decl_dpds.c frama-c-20111001+nitrogen+dfsg/tests/pdg/decl_dpds.c --- frama-c-20110201+carbon+dfsg/tests/pdg/decl_dpds.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/decl_dpds.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -fct-pdg main -journal-disable + OPT: -fct-pdg main -journal-disable -pdg-print -pdg-verbose 2 */ extern int G; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/doc_dot.c frama-c-20111001+nitrogen+dfsg/tests/pdg/doc_dot.c --- frama-c-20110201+carbon+dfsg/tests/pdg/doc_dot.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/doc_dot.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config -* OPT: -lib-entry -main g -fct-pdg g -dot-pdg tests/pdg/doc -journal-disable + OPT: -lib-entry -main g -fct-pdg g -dot-pdg tests/pdg/doc -journal-disable -pdg-print -pdg-verbose 2 */ /* To build the svg file: * dot -Tsvg tests/pdg/doc.g.dot > tests/pdg/doc.g.svg diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/dpds_intra.c frama-c-20111001+nitrogen+dfsg/tests/pdg/dpds_intra.c --- frama-c-20110201+carbon+dfsg/tests/pdg/dpds_intra.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/dpds_intra.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,15 +1,15 @@ /* run.config GCC: - OPT: -fct-pdg test_struct -journal-disable - OPT: -fct-pdg test_if_simple -journal-disable - OPT: -fct-pdg test_goto_simple -journal-disable - OPT: -fct-pdg test_goto_arriere -journal-disable - OPT: -fct-pdg test_goto_else -journal-disable - OPT: -main test_ctrl_dpd_multiple -journal-disable + OPT: -fct-pdg test_struct -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg test_if_simple -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg test_goto_simple -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg test_goto_arriere -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg test_goto_else -journal-disable -pdg-print -pdg-verbose 2 + OPT: -main test_ctrl_dpd_multiple -journal-disable -pdg-print -pdg-verbose 2 => ne passe pas - OPT: -fct-pdg test_simple_loop -journal-disable - OPT: -fct-pdg main -journal-disable - OPT: -fct-pdg multiple_global_inputs -journal-disable + OPT: -fct-pdg test_simple_loop -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg main -journal-disable -pdg-print -pdg-verbose 2 + OPT: -fct-pdg multiple_global_inputs -journal-disable -pdg-print -pdg-verbose 2 */ /* bin/toplevel.opt -deps -main g tests/slicing/dpds_intra.c */ /* bin/toplevel.opt -fct-pdg test_goto_simple tests/slicing/dpds_intra.c -dot-pdg*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/dyn_dpds.c frama-c-20111001+nitrogen+dfsg/tests/pdg/dyn_dpds.c --- frama-c-20110201+carbon+dfsg/tests/pdg/dyn_dpds.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/dyn_dpds.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/pdg/dyn_dpds.opt CMD: tests/pdg/dyn_dpds.opt - OPT: -deps -journal-disable + OPT: -deps -journal-disable -pdg-print -pdg-verbose 2 */ /* diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/dyn_dpds.ml frama-c-20111001+nitrogen+dfsg/tests/pdg/dyn_dpds.ml --- frama-c-20110201+carbon+dfsg/tests/pdg/dyn_dpds.ml 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/dyn_dpds.ml 2011-10-10 08:39:09.000000000 +0000 @@ -5,12 +5,12 @@ zgrviewer tests/pdg/dyn_dpds_2.dot ; *) -let get_zones str_data (kinst, kf) = - let lval_term = !Db.Properties.Interp.lval kf kinst str_data in +let get_zones str_data (stmt, kf) = + let lval_term = !Db.Properties.Interp.lval kf stmt str_data in let lval = !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term in let loc = !Db.From.find_deps_no_transitivity - (Cil_types.Kstmt kinst) + stmt (Cil.new_exp ~loc:Cil_datatype.Location.unknown (Cil_types.Lval lval)) in loc diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/globals.c frama-c-20111001+nitrogen+dfsg/tests/pdg/globals.c --- frama-c-20110201+carbon+dfsg/tests/pdg/globals.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/globals.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,8 +1,8 @@ /* run.config GCC: - OPT: -val -deps -out -input -main g -journal-disable - OPT: -val -deps -out -input -main h -journal-disable - OPT: -val -deps -out -input -main f -journal-disable + OPT: -val -deps -out -input -main g -journal-disable -pdg-print -pdg-verbose 2 + OPT: -val -deps -out -input -main h -journal-disable -pdg-print -pdg-verbose 2 + OPT: -val -deps -out -input -main f -journal-disable -pdg-print -pdg-verbose 2 */ struct Tstr; extern int X; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/inter_alias2.c frama-c-20111001+nitrogen+dfsg/tests/pdg/inter_alias2.c --- frama-c-20110201+carbon+dfsg/tests/pdg/inter_alias2.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/inter_alias2.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,9 +1,9 @@ /* run.config * GCC: - * OPT: -val -journal-disable - * OPT: -calldeps -fct-pdg incr_ptr -journal-disable - * OPT: -calldeps -fct-pdg f1 -journal-disable - * OPT: -calldeps -fct-pdg f2 -journal-disable + * OPT: -val -journal-disable -pdg-print -pdg-verbose 2 + * OPT: -calldeps -fct-pdg incr_ptr -journal-disable -pdg-print -pdg-verbose 2 + * OPT: -calldeps -fct-pdg f1 -journal-disable -pdg-print -pdg-verbose 2 + * OPT: -calldeps -fct-pdg f2 -journal-disable -pdg-print -pdg-verbose 2 */ void incr_ptr (int *p) { *p += 1; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/inter_alias.c frama-c-20111001+nitrogen+dfsg/tests/pdg/inter_alias.c --- frama-c-20110201+carbon+dfsg/tests/pdg/inter_alias.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/inter_alias.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -val -out -input -calldeps -pdg -journal-disable + OPT: -val -out -input -calldeps -pdg -journal-disable -pdg-print -pdg-verbose 2 */ int G; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/loops.c frama-c-20111001+nitrogen+dfsg/tests/pdg/loops.c --- frama-c-20110201+carbon+dfsg/tests/pdg/loops.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/loops.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,14 +1,14 @@ /* run.config GCC: - OPT: -lib-entry -main simple -fct-pdg simple -journal-disable - OPT: -lib-entry -main simple_with_break -fct-pdg simple_with_break -journal-disable - OPT: -lib-entry -main infinite -fct-pdg infinite -journal-disable - OPT: -lib-entry -main infinite2 -fct-pdg infinite2 -journal-disable - OPT: -lib-entry -main maybe_infinite -fct-pdg maybe_infinite -journal-disable - OPT: -lib-entry -main two_infinite_loops -fct-pdg two_infinite_loops -journal-disable - OPT: -lib-entry -main loop_with_goto -fct-pdg loop_with_goto -journal-disable - OPT: -lib-entry -main non_natural_loop -fct-pdg non_natural_loop -journal-disable - OPT: -lib-entry -main dead_code -fct-pdg dead_code -journal-disable + OPT: -lib-entry -main simple -fct-pdg simple -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main simple_with_break -fct-pdg simple_with_break -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main infinite -fct-pdg infinite -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main infinite2 -fct-pdg infinite2 -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main maybe_infinite -fct-pdg maybe_infinite -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main two_infinite_loops -fct-pdg two_infinite_loops -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main loop_with_goto -fct-pdg loop_with_goto -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main non_natural_loop -fct-pdg non_natural_loop -journal-disable -pdg-print -pdg-verbose 2 + OPT: -lib-entry -main dead_code -fct-pdg dead_code -journal-disable -pdg-print -pdg-verbose 2 diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/multiple_calls.c frama-c-20111001+nitrogen+dfsg/tests/pdg/multiple_calls.c --- frama-c-20110201+carbon+dfsg/tests/pdg/multiple_calls.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/multiple_calls.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config GCC: - OPT: -inout -deps -main appel_ptr_fct -fct-pdg appel_ptr_fct -journal-disable - OPT: -inout -deps -main appel_ptr_fct_bis -fct-pdg appel_ptr_fct_bis -journal-disable + OPT: -inout -deps -main appel_ptr_fct -fct-pdg appel_ptr_fct -journal-disable -pdg-print -pdg-verbose 2 + OPT: -inout -deps -main appel_ptr_fct_bis -fct-pdg appel_ptr_fct_bis -journal-disable -pdg-print -pdg-verbose 2 */ extern int G1, G2, G3, G4; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/no_body.c frama-c-20111001+nitrogen+dfsg/tests/pdg/no_body.c --- frama-c-20110201+carbon+dfsg/tests/pdg/no_body.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/no_body.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config * GCC: -* OPT: -fct-pdg main -inout -journal-disable +* OPT: -fct-pdg main -inout -journal-disable -pdg-print -pdg-verbose 2 */ /* * ledit bin/toplevel.top tests/slicing/no_body.c -fct-pdg main diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/pb_infinite_loop.c frama-c-20111001+nitrogen+dfsg/tests/pdg/pb_infinite_loop.c --- frama-c-20110201+carbon+dfsg/tests/pdg/pb_infinite_loop.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/pb_infinite_loop.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,8 +1,8 @@ /* run.config GCC: - OPT: -main test_infinite_loop -fct-pdg test_infinite_loop -journal-disable - OPT: -main test_infinite_loop_2 -fct-pdg test_infinite_loop_2 -journal-disable - OPT: -main test_exit -fct-pdg test_exit -journal-disable + OPT: -main test_infinite_loop -fct-pdg test_infinite_loop -journal-disable -pdg-print -pdg-verbose 2 + OPT: -main test_infinite_loop_2 -fct-pdg test_infinite_loop_2 -journal-disable -pdg-print -pdg-verbose 2 + OPT: -main test_exit -fct-pdg test_exit -journal-disable -pdg-print -pdg-verbose 2 */ /* This test is a problem at the moment because the postdominators are Top diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/sets.c frama-c-20111001+nitrogen+dfsg/tests/pdg/sets.c --- frama-c-20110201+carbon+dfsg/tests/pdg/sets.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/sets.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/pdg/sets.opt CMD: tests/pdg/sets.opt - OPT: -lib-entry -main f -pdg -inout -journal-disable + OPT: -lib-entry -main f -pdg -inout -journal-disable -pdg-print -pdg-verbose 2 */ int b, c, x, y, z, t; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/sets.ml frama-c-20111001+nitrogen+dfsg/tests/pdg/sets.ml --- frama-c-20110201+carbon+dfsg/tests/pdg/sets.ml 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/sets.ml 2011-10-10 08:39:09.000000000 +0000 @@ -2,8 +2,8 @@ open Cil_types;; let pp_nodes msg nodes = - Cil.log "%s" msg ; - List.iter (fun n -> Cil.log "%a" (!Pdg.pretty_node false) n) nodes;; + Kernel.result "%s" msg ; + List.iter (fun n -> Kernel.result "%a" (!Pdg.pretty_node false) n) nodes;; exception Find of varinfo;; @@ -30,8 +30,11 @@ v in - let y_zone = Locations.valid_enumerate_bits (Locations.loc_of_varinfo y) in - + let y_zone = + Locations.valid_enumerate_bits + ~for_writing:false + (Locations.loc_of_varinfo y) + in let y_at_11_nodes, undef = (* y=5 *) !Pdg.find_location_nodes_at_stmt pdg (fst (Kernel_function.find_from_sid 11)) ~before:false y_zone diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/simple_call.c frama-c-20111001+nitrogen+dfsg/tests/pdg/simple_call.c --- frama-c-20110201+carbon+dfsg/tests/pdg/simple_call.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/simple_call.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,9 +1,9 @@ /* run.config GCC: - OPT: -fct-pdg main -journal-disable - OPT: -main call_in_loop -fct-pdg call_in_loop -journal-disable - OPT: -main call_mix_G1_G2 -fct-pdg call_mix_G1_G2 -journal-disable - OPT: -main call_multiple_global_outputs -fct-pdg call_multiple_global_outputs -journal-disable + OPT: -fct-pdg main -journal-disable -pdg-print -pdg-verbose 2 + OPT: -main call_in_loop -fct-pdg call_in_loop -journal-disable -pdg-print -pdg-verbose 2 + OPT: -main call_mix_G1_G2 -fct-pdg call_mix_G1_G2 -journal-disable -pdg-print -pdg-verbose 2 + OPT: -main call_multiple_global_outputs -fct-pdg call_multiple_global_outputs -journal-disable -pdg-print -pdg-verbose 2 */ extern int G, G1, G2; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/simple_intra_slice.c frama-c-20111001+nitrogen+dfsg/tests/pdg/simple_intra_slice.c --- frama-c-20110201+carbon+dfsg/tests/pdg/simple_intra_slice.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/simple_intra_slice.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config GCC: - OPT: -pdg -journal-disable + OPT: -pdg -journal-disable -pdg-print -pdg-verbose 2 */ /* test conçu initialement comme test pour le slicing */ int Unknown; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/top_pdg_input.c frama-c-20111001+nitrogen+dfsg/tests/pdg/top_pdg_input.c --- frama-c-20110201+carbon+dfsg/tests/pdg/top_pdg_input.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/top_pdg_input.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -val -out -input -deps -pdg -journal-disable + OPT: -val -out -input -deps -pdg -journal-disable -pdg-print -pdg-verbose 2 */ int ** top_input() ; diff -Nru frama-c-20110201+carbon+dfsg/tests/pdg/variadic.c frama-c-20111001+nitrogen+dfsg/tests/pdg/variadic.c --- frama-c-20110201+carbon+dfsg/tests/pdg/variadic.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/pdg/variadic.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config * GCC: -* OPT: -pdg -journal-disable +* OPT: -pdg -journal-disable -pdg-print -pdg-verbose 2 */ #include <stdarg.h> @@ -17,16 +17,18 @@ return s; } +int lib_f (int n, ...); + int f1 (int a) { - return f (1, a); + return lib_f (1, a); } int f2 (int a, int b) { - return f (2, a, b); + return lib_f (2, a, b); } int f3 (int a, int b, int c) { - return f (3, a, b, c); + return lib_f (3, a, b, c); } int main (void) { diff -Nru frama-c-20110201+carbon+dfsg/tests/rte/assign7.c frama-c-20111001+nitrogen+dfsg/tests/rte/assign7.c --- frama-c-20110201+carbon+dfsg/tests/rte/assign7.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/rte/assign7.c 2011-10-10 08:38:51.000000000 +0000 @@ -0,0 +1,33 @@ +/* run.config + OPT: -rte -rte-print -rte-no-all -rte-precond -journal-disable +*/ + +//@ assigns *p \from \union(*(char*)p,*q); +extern void f(int* p, int* q); + +//@ assigns *p \from \union(*p, \union(*r,*q)); +extern void ff(int* p, int* q, int* r); + +//@ assigns *p \from \inter(*(char*)p,*q); +extern void h(int* p, int* q); + +//@ assigns \union(*p,*q); +extern void g(int* p, int* q); + +/*@ assigns \at(*p,Post), \at(*p,Pre), *p ; + */ +extern void gg(int* p); + +int X, Y ; +//@ assigns \union(X, Y) ; +void hh(); + +int main() { + int x,y,z; + f(&x,&y); + ff(&x,&y,&z); + g(&x,&y); + h(&x,&y); + gg(&x); + hh(); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/rte/bts0567.c frama-c-20111001+nitrogen+dfsg/tests/rte/bts0567.c --- frama-c-20110201+carbon+dfsg/tests/rte/bts0567.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/rte/bts0567.c 2011-10-10 08:38:51.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -rte -print -journal-disable + OPT: -rte -rte-precond -print -journal-disable */ int tab [2] ; diff -Nru frama-c-20110201+carbon+dfsg/tests/rte/bts0576.c frama-c-20111001+nitrogen+dfsg/tests/rte/bts0576.c --- frama-c-20110201+carbon+dfsg/tests/rte/bts0576.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/rte/bts0576.c 2011-10-10 08:38:51.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -rte -rte-print -journal-disable + OPT: -rte -rte-print -rte-precond -journal-disable */ typedef double typetab[2]; diff -Nru frama-c-20110201+carbon+dfsg/tests/rte/bts0580.i frama-c-20111001+nitrogen+dfsg/tests/rte/bts0580.i --- frama-c-20110201+carbon+dfsg/tests/rte/bts0580.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/rte/bts0580.i 2011-10-10 08:38:51.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + OPT: -rte -rte-no-all -rte-mem -print -journal-disable +*/ +struct ArrayStruct { + int data[10]; +} buff; + +int main (int i) { + return buff.data[i] ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/rte/castoncall.c frama-c-20111001+nitrogen+dfsg/tests/rte/castoncall.c --- frama-c-20110201+carbon+dfsg/tests/rte/castoncall.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/rte/castoncall.c 2011-10-10 08:38:51.000000000 +0000 @@ -0,0 +1,26 @@ +/* run.config + OPT: -rte -rte-precond -rte-print -journal-disable + OPT: -rte -rte-precond -no-collapse-call-cast -rte-print -journal-disable +*/ + +/*@ + ensures (\result == a) || (\result == b); + assigns \result \from a,b; + */ +int nondet(int a, int b); + +/*@ + ensures (\result == a) || (\result == b); + assigns \result \from a,b; + */ +void *nondet_ptr(void *a, void *b) { + return (void*) nondet((int)a, (int)b); +} + +//@ ensures \result == 1; +int f(); + +void g() { + char c = f(); + return; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/rte/fptr_assert.c frama-c-20111001+nitrogen+dfsg/tests/rte/fptr_assert.c --- frama-c-20110201+carbon+dfsg/tests/rte/fptr_assert.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/rte/fptr_assert.c 2011-10-10 08:38:51.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -rte -rte-print -journal-disable + OPT: -rte -rte-precond -rte-print -journal-disable */ typedef int (*fptr)(int); diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/basic.i frama-c-20111001+nitrogen+dfsg/tests/saveload/basic.i --- frama-c-20110201+carbon+dfsg/tests/saveload/basic.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/basic.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,23 @@ +/* run.config + EXECNOW: make -s ./tests/saveload/basic.opt + EXECNOW: LOG basic_sav.res LOG basic_sav.err BIN basic.sav ./tests/saveload/basic.opt -val -out -input -deps ./tests/saveload/basic.i -save ./tests/saveload/result/basic.sav > ./tests/saveload/result/basic_sav.res 2> ./tests/saveload/result/basic_sav.err + EXECNOW: LOG basic_sav.1.res LOG basic_sav.1.err BIN basic.1.sav ./bin/toplevel.opt -save ./tests/saveload/result/basic.1.sav ./tests/saveload/basic.i -val -out -input -deps > ./tests/saveload/result/basic_sav.1.res 2> ./tests/saveload/result/basic_sav.1.err + OPT: -load ./tests/saveload/result/basic.sav -val -out -input -deps -journal-disable + CMD: ./tests/saveload/basic.opt + OPT: -load ./tests/saveload/result/basic.1.sav -val -out -input -deps -journal-disable -print + OPT: -load ./tests/saveload/result/basic.1.sav -val -out -input -deps -journal-disable + EXECNOW: LOG status_sav.res LOG status_sav.err BIN status.sav ./bin/toplevel.byte -load-script tests/saveload/status.ml -save ./tests/saveload/result/status.sav ./tests/saveload/basic.i > ./tests/saveload/result/status_sav.res 2> ./tests/saveload/result/status_sav.err + CMD: ./bin/toplevel.byte + OPT: -load-script tests/saveload/status.ml -load ./tests/saveload/result/status.sav +*/ + +int main() { + int i, j; + + i = 10; + /*@ assert (i == 10); */ + while(i--); + j = 5; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/basic.ml frama-c-20111001+nitrogen+dfsg/tests/saveload/basic.ml --- frama-c-20110201+carbon+dfsg/tests/saveload/basic.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/basic.ml 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,11 @@ +module StateA = + State_builder.Ref + (Datatype.Int) + (struct + let name = "Project.Test.StateA" + let dependencies = [] + let kind = `Internal + let default () = 0 + end) + +let () = StateA.set 10 diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/deps.i frama-c-20111001+nitrogen+dfsg/tests/saveload/deps.i --- frama-c-20110201+carbon+dfsg/tests/saveload/deps.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/deps.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,22 @@ +/* run.config + EXECNOW: make -s ./tests/saveload/deps_A.opt ./tests/saveload/deps_B.opt ./tests/saveload/deps_C.opt ./tests/saveload/deps_D.opt + EXECNOW: LOG deps_sav.res LOG deps_sav.err BIN deps.sav ./tests/saveload/deps_A.opt -val -out -input -deps ./tests/saveload/deps.i -save ./tests/saveload/result/deps.sav > ./tests/saveload/result/deps_sav.res 2> ./tests/saveload/result/deps_sav.err + CMD: ./tests/saveload/deps_A.opt + OPT: -load ./tests/saveload/result/deps.sav -val -out -input -deps + CMD: ./tests/saveload/deps_B.opt + OPT: -load ./tests/saveload/result/deps.sav -val -out -input -deps + CMD: ./tests/saveload/deps_C.opt + OPT: -load ./tests/saveload/result/deps.sav -val -out -input -deps + CMD: ./tests/saveload/deps_D.opt + OPT: -load ./tests/saveload/result/deps.sav -val -out -input -deps +*/ + +int main() { + int i, j; + + i = 10; + while(i--); + j = 5; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/load_one.i frama-c-20111001+nitrogen+dfsg/tests/saveload/load_one.i --- frama-c-20110201+carbon+dfsg/tests/saveload/load_one.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/load_one.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,29 @@ +/* run.config_no_native_dynlink + CMD: bin/toplevel.byte + OPT: -load-script tests/saveload/load_one.ml +*/ +/* run.config + OPT: -load-script tests/saveload/load_one.ml +*/ + +int G; + +int f (int x, int y) { + G = y; + return x; +} + +int main (void) { + int a = 1; + int b = 1; + + /*@ assert a == 1; */ + + f (0, 0); /* this call is useless : should be removed */ + a = f (a, b); /* the result of this call is useless */ + a = f (G + 1, b); + + G = 0; /* don't use the G computed by f */ + + return a; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/multi_project.i frama-c-20111001+nitrogen+dfsg/tests/saveload/multi_project.i --- frama-c-20110201+carbon+dfsg/tests/saveload/multi_project.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/multi_project.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,17 @@ +/* run.config + EXECNOW: BIN multi_project.sav LOG multi_project_sav.res LOG multi_project_sav.err ./bin/toplevel.opt -save ./tests/saveload/result/multi_project.sav -semantic-const-folding ./tests/saveload/multi_project.i > tests/saveload/result/multi_project_sav.res 2> tests/saveload/result/multi_project_sav.err + EXECNOW: make -s ./tests/saveload/multi_project.opt + OPT: -load ./tests/saveload/result/multi_project.sav -journal-disable + CMD: ./tests/saveload/multi_project.opt -val + OPT: +*/ +int f(int x) { + return x + x; +} + +int main() { + int x = 2; + int y = f(x); + /*@ assert y == 4; */ + return x * y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/multi_project.ml frama-c-20111001+nitrogen+dfsg/tests/saveload/multi_project.ml --- frama-c-20110201+carbon+dfsg/tests/saveload/multi_project.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/multi_project.ml 2011-10-10 08:39:04.000000000 +0000 @@ -2,7 +2,7 @@ Kernel.log "Checking %S@." name; Project.on (Project.from_unique_name name) - (fun () -> assert (test (Parameters.Files.get ()) [])) () + (fun () -> assert (test (Kernel.Files.get ()) [])) () let main () = ignore (Project.create_by_copy "foo"); @@ -11,7 +11,7 @@ check "foo" (<>); check "foobar" (=); check "default" (<>); - Parameters.Files.set []; + Kernel.Files.set []; Project.load_all "foo.sav"; Extlib.safe_remove "foo.sav"; ignore (Project.create_by_copy "bar"); diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/segfault_datatypes.i frama-c-20111001+nitrogen+dfsg/tests/saveload/segfault_datatypes.i --- frama-c-20110201+carbon+dfsg/tests/saveload/segfault_datatypes.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/segfault_datatypes.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,17 @@ +/* run.config + EXECNOW: make -s ./tests/saveload/segfault_datatypes_A.opt + EXECNOW: make -s ./tests/saveload/segfault_datatypes_B.opt + EXECNOW: LOG segfault_datatypes_sav.res LOG segfault_datatypes_sav.err BIN segfault_datatypes.sav ./tests/saveload/segfault_datatypes_A.opt -val -out -input -deps ./tests/saveload/segfault_datatypes.i -save ./tests/saveload/result/segfault_datatypes.sav > ./tests/saveload/result/segfault_datatypes_sav.res 2> ./tests/saveload/result/segfault_datatypes_sav.err + CMD: ./tests/saveload/segfault_datatypes_B.opt + OPT: -load ./tests/saveload/result/segfault_datatypes.sav -val -out -input -deps -journal-disable +*/ + +int main() { + int i, j; + + i = 10; + while(i--); + j = 5; + + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/size.ml frama-c-20111001+nitrogen+dfsg/tests/saveload/size.ml --- frama-c-20110201+carbon+dfsg/tests/saveload/size.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/size.ml 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -module StateA = - State_builder.Ref - (Datatype.Int) - (struct - let name = "Project.Test.StateA" - let dependencies = [] - let kind = `Internal - let default () = 0 - end) - -let () = StateA.set 10 diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/sparecode.i frama-c-20111001+nitrogen+dfsg/tests/saveload/sparecode.i --- frama-c-20110201+carbon+dfsg/tests/saveload/sparecode.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/sparecode.i 2011-10-10 08:39:04.000000000 +0000 @@ -0,0 +1,23 @@ +/* run.config + EXECNOW: BIN sparecode.sav LOG sparecode_sav.res LOG sparecode_sav.err ./bin/toplevel.opt -slicing-level 2 -slice-return main -save ./tests/saveload/result/sparecode.sav tests/saveload/sparecode.i -then-on 'Slicing export' -print > tests/saveload/result/sparecode_sav.res 2> tests/saveload/result/sparecode_sav.err + OPT: -load ./tests/saveload/result/sparecode.sav +*/ +int G; + +int f (int x, int y) { + G = y; + return x; +} + +int main (void) { + int a = 1; + int b = 1; + + f (0, 0); /* this call is useless : should be removed */ + a = f (a, b); /* the result of this call is useless */ + a = f (G + 1, b); + + G = 0; /* don't use the G computed by f */ + + return a; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/saveload/status.ml frama-c-20111001+nitrogen+dfsg/tests/saveload/status.ml --- frama-c-20110201+carbon+dfsg/tests/saveload/status.ml 2011-02-07 13:41:50.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/saveload/status.ml 2011-10-10 08:39:04.000000000 +0000 @@ -1,41 +1,23 @@ open Cil_types -module Self = - State_builder.False_ref - (struct - let name = "Test" - let dependencies = [] - let kind = `Correctness - end) - -module Up = - Properties_status.Make_updater - (struct let name = "Test" let emitter = Self.self end) - -module Blob = - State_builder.False_ref - (struct - let name = "Blob" - let dependencies = [] - let kind = `Correctness - end) +let emitter = Emitter.create "Test" ~correctness:[] ~tuning:[] let main () = Ast.compute (); Annotations.iter (fun s _ (ca, _) -> - let s', kf = Kernel_function.find_from_sid s.Cil_types.sid in - assert (Cil_datatype.Stmt.equal s s'); + let kf = Kernel_function.find_englobing_kf s in let ps = Property.ip_of_code_annot kf s (Annotations.get_code_annotation ca) in List.iter (fun p -> - Up.set + Property_status.emit + emitter p - [ Property.ip_blob Blob.self ] - (Checked { emitter = "Test emitter"; valid = Maybe }); - Format.printf "%a@." Properties_status.pretty_all p) + ~hyps:[ Property.ip_other "Blob" None Kglobal ] + Property_status.Dont_know; + Format.printf "%a@." Property_status.pretty (Property_status.get p)) ps) let () = Db.Main.extend main diff -Nru frama-c-20110201+carbon+dfsg/tests/scope/bts383.c frama-c-20111001+nitrogen+dfsg/tests/scope/bts383.c --- frama-c-20110201+carbon+dfsg/tests/scope/bts383.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/scope/bts383.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -val -print -journal-disable -scope-verbose 1 -scope-debug 1 + OPT: -val -print -journal-disable -scope-verbose 1 -scope-debug 1 -remove-redundant-alarms */ /* echo '!Db.Scope.check_asserts();;' \ diff -Nru frama-c-20110201+carbon+dfsg/tests/scope/bts971.c frama-c-20111001+nitrogen+dfsg/tests/scope/bts971.c --- frama-c-20110201+carbon+dfsg/tests/scope/bts971.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/scope/bts971.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,32 @@ +/* run.config + OPT: -journal-disable -load-script tests/scope/bts971.ml +*/ + + +volatile foo; +int v; + +void f1 () { + v += 1; +} + +void f () { + f1 (); +} + +void g1 () { + v += 2; + v += 3; +} + +void g () { + g1 (); +} + +void main (int c) { + v += 0; + while (c) { + if (foo) {f ();}; + if (foo) {g ();}; + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/scope/bts971.ml frama-c-20111001+nitrogen+dfsg/tests/scope/bts971.ml --- frama-c-20110201+carbon+dfsg/tests/scope/bts971.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/scope/bts971.ml 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,55 @@ + +let find_pp kf_name = + let kf = Globals.Functions.find_by_name kf_name in + let stmt = Kernel_function.find_first_stmt kf in + Format.printf "Current program point = first one in function '%s'@\n" + kf_name; + stmt, kf +;; + +let compute_and_print pp str_data = + let stmt, kf = pp in + let lval_term = !Db.Properties.Interp.lval kf stmt str_data in + let lval = !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term in + let defs = !Db.Scope.get_defs kf stmt lval in + Format.printf "* @[<v 2>Defs for (%s) at current program point=@[<v 2>@." + str_data; + let _ = match defs with + | None -> Format.printf "computation problem.@." + | Some (defs, _undef) when Cil_datatype.Stmt.Set.is_empty defs -> + Format.printf "no Defs found@." + | Some (defs, _undef) -> + Cil_datatype.Stmt.Set.iter + (fun s -> + Format.printf "%a: %a@\n" Cil.d_loc (Cil_datatype.Stmt.loc s) + Cil_datatype.Stmt.pretty s) defs + in Format.printf "@]@]@.@." +;; + +let tests () = + let pp = find_pp "f1" in compute_and_print pp "v"; + let stmt, kf as pp = find_pp "g1" in compute_and_print pp "v"; + let stmt = match stmt.Cil_types.succs with s::_ -> s | _ -> assert false in + Format.printf "Current program point = 2d one in function '%s'@\n" "g1"; + compute_and_print (stmt, kf) "v"; + let pp = find_pp "f" in compute_and_print pp "v" + +let main _ = + Format.printf "=== Tests for Scope.Defs@."; + Ast.compute (); + Dynamic.Parameter.Bool.set "-val-show-progress" false ; + Dynamic.Parameter.Int.set "-value-verbose" 0 ; + Dynamic.Parameter.Int.set "-from-verbose" 0 ; + Dynamic.Parameter.Int.set "-pdg-verbose" 0 ; + + Format.printf "--- Intraprocedural mode (-scope-no-defs-interproc)@."; + Dynamic.Parameter.Bool.set "-scope-defs-interproc" false ; + tests (); + + Format.printf "--- Interprocedural mode (-scope-defs-interproc)@."; + Dynamic.Parameter.Bool.set "-scope-defs-interproc" true ; + tests () +;; + +let _ = Db.Main.extend main + diff -Nru frama-c-20110201+carbon+dfsg/tests/scope/zones.ml frama-c-20111001+nitrogen+dfsg/tests/scope/zones.ml --- frama-c-20110201+carbon+dfsg/tests/scope/zones.ml 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/scope/zones.ml 2011-10-10 08:39:09.000000000 +0000 @@ -22,7 +22,7 @@ let find_sid sid = let stmt, kf = Kernel_function.find_from_sid sid in Format.printf "Current program point = before stmt %d in function %a@\n" - sid Kernel_function.pretty_name kf; + sid Kernel_function.pretty kf; stmt, kf ;; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts0184.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts0184.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts0184.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts0184.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -slice-pragma x -journal-disable + OPT: -check -slice-pragma x -journal-disable **/ int x(int y, int z) { diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts0190.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts0190.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts0190.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts0190.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config -OPT: -slice-rd y +OPT: -check -slice-rd y */ int x(int y, int z) diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts0950_annot.i frama-c-20111001+nitrogen+dfsg/tests/slicing/bts0950_annot.i --- frama-c-20110201+carbon+dfsg/tests/slicing/bts0950_annot.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts0950_annot.i 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + OPT: -val -slice-value a -then-on "Slicing export" -print + */ +/*@ requires \valid(dest); */ +extern void cpy(int *dest, const int *src); + +void cpy(int* region1, const int* region2) { + *(region1) = *region2; +} + +int a=1, b=2; + +void main() { + cpy(&a,&b); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts179.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts179.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts179.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts179.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config - OPT: -slice-return main -slice-print -journal-disable - OPT: -slice-pragma main -slice-print -journal-disable - OPT: -sparecode-analysis -journal-disable + OPT: -check -slice-return main -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-pragma main -journal-disable -then-on 'Slicing export' -print + OPT: -check -sparecode-analysis -journal-disable */ struct {int a; int ab; int b; int c ; int d;} S; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts283.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts283.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts283.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts283.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -slice-print -slice-return main -slice-undef-functions -journal-disable + OPT: -check -slice-return main -slice-undef-functions -journal-disable -then-on 'Slicing export' -print */ int x,y,z; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts326.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts326.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts326.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts326.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -calldeps -slice-print -slice-return main -journal-disable + OPT: -check -calldeps -slice-return main -journal-disable -then-on 'Slicing export' -print */ /* Problem : f(1) should be sliced out. See BTS#326 */ int t[2] ; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts335b.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts335b.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts335b.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts335b.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -slice-return main -calldeps -slicing-level 3 -slice-print -slicing-verbose 2 -slicing-debug 1 -journal-disable + OPT: -check -slice-return main -calldeps -slicing-level 3 -slicing-verbose 2 -journal-disable -then-on 'Slicing export' -print */ int X, Y; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts335.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts335.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts335.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts335.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,9 +1,9 @@ /* run.config - OPT: -slice-pragma g -calldeps -slicing-level 3 + OPT: -check -slice-pragma g -calldeps -slicing-level 3 */ /* -bin/toplevel.opt -slice-pragma g -calldeps -slicing-level 3 tests/slicing/bts335.c -debug 2 +bin/toplevel.opt -check -slice-pragma g -calldeps -slicing-level 3 tests/slicing/bts335.c -debug 2 bin/toplevel.opt -pdg-debug -pdg -pdg-debug "-dot-pdg bts335" tests/slicing/bts335.c */ int T[2] = {0, 0}; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts336.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts336.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts336.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts336.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,8 +1,8 @@ /* run.config - OPT: -slice-return main -slice-print -calldeps -journal-disable - OPT: -main main2 -slice-return main2 -slice-print -calldeps -journal-disable - OPT: -main main3 -slice-return main3 -slice-print -journal-disable - OPT: -main main3 -slice-return main3 -slice-print -calldeps -journal-disable + OPT: -check -slice-return main -calldeps -journal-disable -then-on 'Slicing export' -print + OPT: -check -main main2 -slice-return main2 -calldeps -journal-disable -then-on 'Slicing export' -print + OPT: -check -main main3 -slice-return main3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main main3 -slice-return main3 -calldeps -journal-disable -then-on 'Slicing export' -print */ //-------------------------------------- // something to do to have better results... diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts341.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts341.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts341.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts341.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -slice-print -slice-assert main -journal-disable + OPT: -check -slice-assert main -journal-disable -then-on 'Slicing export' -print */ int main (int c) { if (c) diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts344.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts344.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts344.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts344.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config - OPT: -slice-print -slice-return main -journal-disable - OPT: -slice-print -slice-return main_bis -main main_bis -journal-disable + OPT: -check -slice-return main -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return main_bis -main main_bis -journal-disable -then-on 'Slicing export' -print */ int X, Y ; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts345.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts345.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts345.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts345.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,9 +1,9 @@ /* run.config - OPT: -slice-print -slice-return call_top -main call_top -journal-disable - OPT: -slice-print -slice-return top -main top -journal-disable - OPT: -slice-print -slice-return top -main call_top -journal-disable - OPT: -slice-return called_by_top -main top -journal-disable - OPT: -slice-return called_by_top -main call_top -journal-disable + OPT: -check -slice-return call_top -main call_top -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return top -main top -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return top -main call_top -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return called_by_top -main top -journal-disable + OPT: -check -slice-return called_by_top -main call_top -journal-disable */ int called_indirectly_by_top (int x) { diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts709.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts709.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts709.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts709.c 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,56 @@ +/* run.config + OPT: -check -slice-pragma func -no-unicode -journal-disable -then-on 'Slicing export' -print + */ + +int inputsOf_testcase_func (); +int inp1, var1,var2; + +void func( void ) +{ + if ( 1 == inp1 ) + { + // Block-1 + var1 = 1 ; + var2 = 1 ; + } + else + { + if ( 2== inp1 ) + { + // Block-2 + var1 = 2 ; + var2 = 2 ; + } + else + { + // Block-3 + if ( 3== inp1 ) + { + var1 = 3; + var2 = 3 ; + } + } + } + + //@slice pragma stmt; + 65 != var2 ? assert ( 5 != var1):1; +} + + +int main( ) { + + + int _noOfIter_ = 0; + for (_noOfIter_=0; _noOfIter_ < 1; _noOfIter_++ ) { + inputsOf_testcase_func ( ); + func (); + } +} + +int inputsOf_testcase_func () +{ + int nondet_int ( ); + inp1 = nondet_int ( ); + var1 = nondet_int ( ); // This required line is getting knocked off + var2 = nondet_int ( ); // This required line is getting knocked off +} diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts808.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts808.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts808.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts808.c 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,22 @@ +/* run.config +* OPT: -check -slice-return main -journal-disable -then-on 'Slicing export' -print +*/ + +int f0 (void) { + int i = 0; + int x; + if (i) { x = 1; L: x++; } + else { x = 0; goto L; } + return x; +} +int f1 (void) { + int i = 1; + int x; + if (i) { x = 1; goto L; } + else { x = 0; L: x++; } + return x; +} + +int main (int n) { + return f0 () + f1 (); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/bts827.c frama-c-20111001+nitrogen+dfsg/tests/slicing/bts827.c --- frama-c-20110201+carbon+dfsg/tests/slicing/bts827.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/bts827.c 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,19 @@ +/* run.config + OPT: -check -slice-return main -journal-disable -then-on 'Slicing export' -print +*/ + +/* The problem was a mix-up between f outputs and retrun value. */ + +int G; + +int f (void) { + G = 3; + return 5; +} + +int main (void) { + G = 1; + G += f (); + return G; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/call_accuracy.c frama-c-20111001+nitrogen+dfsg/tests/slicing/call_accuracy.c --- frama-c-20110201+carbon+dfsg/tests/slicing/call_accuracy.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/call_accuracy.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -calldeps -slice-return main -slicing-level 3 -slice-print -journal-disable + OPT: -check -calldeps -slice-return main -slicing-level 3 -journal-disable -then-on 'Slicing export' -print */ int f_cond (int c, int a, int b) { ++a; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/call_demo.c frama-c-20111001+nitrogen+dfsg/tests/slicing/call_demo.c --- frama-c-20110201+carbon+dfsg/tests/slicing/call_demo.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/call_demo.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,6 @@ /* run.config - GCC: - OPT: -slice-print -slice-calls call1 -journal-disable - OPT: -slice-print -slice-calls call2 -journal-disable + OPT: -check -slice-calls call1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls call2 -journal-disable -then-on 'Slicing export' -print */ //@ assigns \result \from v; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/callwise.c frama-c-20111001+nitrogen+dfsg/tests/slicing/callwise.c --- frama-c-20110201+carbon+dfsg/tests/slicing/callwise.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/callwise.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,6 +1,5 @@ /* run.config - GCC: - OPT: -calldeps -slice-return main -slicing-level 2 -slice-print -journal-disable + OPT: -check -calldeps -slice-return main -slicing-level 2 -journal-disable -then-on 'Slicing export' -print */ int a = 1, b = 1, c = 1, d = 1, *p; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/combine.c frama-c-20111001+nitrogen+dfsg/tests/slicing/combine.c --- frama-c-20110201+carbon+dfsg/tests/slicing/combine.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/combine.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/combine.opt CMD: tests/slicing/combine.opt - OPT: -deps -journal-disable + OPT: -check -deps -journal-disable */ //@ assigns \result \from x; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/csmith.c frama-c-20111001+nitrogen+dfsg/tests/slicing/csmith.c --- frama-c-20110201+carbon+dfsg/tests/slicing/csmith.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/csmith.c 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,222 @@ +/* run.config + OPT: -slice-return main -journal-disable -then-on 'Slicing export' -print +COMMENT: TODO add -check to the command, but it fails at the moment... + **/ + + +int G1; +void f1 (int c) { + for (int x = 0; x < 10; x++) { + G1 = 3; + if (G1) break; + return; + } +} + +int G1b; +void f1b (void) { +W: { { + G1b = 3; + if (G1b) goto B; + return; + } + goto W; + } +B: ; +} + +int G2; +void f2(void) { + while (1) { + G2 = 3; + if (G2) break; + } +} + +int bts181 (int c) { + int x = 0, y = 0; + if (c) { + x = 1; + if (x>0) + y = 3; + } + return y; +} +int bts181b (int c) { + int x = 0, y = 0; + if (c) { + x = 1; + if (x>0) + y = 3; + else + y = 4; + } + return y; +} + +int bts807 (void) { + int g = 0; + int b = 7; + int a = 2; + if ((( a || 42) && b)) { + while (1) { + g = 21; + return g; + } + } + return g; +} + +int bts809 (void) { + int x; + while (1) { + x = 10; + goto L; + while (x) { +L: return x; + } + } +} + +// TODO: see COMMENT above. +int bts879 (int c) { + int g = 0; + int p = c ? 0 : 10; + + if (p || (g && G1) ) { + return 1; + } + return 0; +} + +// This one looks similar to the previous one, but without the block, +// Cil doesn't generate a goto from the then branch to the else branch... +int bts879b (int c) { + int g = 0; + int p = c ? 0 : 10; + + if (p || (g && G1) ) + return 1; + + return 0; +} + +int one_time_loop_with_break () { + int x; + while (1) { + x = 3; + if (x > 0) break; + x++; + } + return x; +} + +/* TODO: find an example... I didn't manage to build one. +int one_time_loop_with_continue () { + int x = 0; + while (1) { + x++; + if (x == 2) break; + if (x == 1) continue; + } + return x; +} +*/ + +int bts899 (void ) { + int vrai = 1; + int x = 254; + for (int i = 17; (i != (-9)); i--) { + if (! i) { + if (vrai) + continue; + continue; // unreachable but disturb ctrl dependencies... + } + x ++; + } + return x; +} + +int bts906 (void) { + int x = 0; + int i = 2; + while (i >= 0) { + while (1) { + if (i) + goto B; + else { + x ++; + return x; + if (x) + goto B; + } + } +B : i --; + } + return 0; +} + +int bts906b (void) { + int x = 0; + int i = 2; + while (i >= 0) { + while (1) { + if (i) + goto B; + else { + x ++; + return x; + x++; + if (x) + goto B; + } + } +B : i --; + } + return 0; +} + +int bts963 (void) { + int x = 0; + int i; +L: i = 0; + while (i < 10) { + x++; + if (x < 3) goto L; + else return x; + } + return x; +} + +int bts963b (void) { + int x = 0; + int i; +L: i = 0; + while (i < 10) { + x++; + if (x < 3) goto L; + else return x; + i++; + } + return x; +} + +int main (int n) { + int x = 0; + f1 (n); x += G1; + f1b (); x += G1b; + f2 (); x += G2; + x += bts181 (n); + x += bts181b (n); + x += bts807 (); + x += bts809 (); + x += bts879 (n); + x += bts879b (n); + x += bts899 (); + x += bts906 (); + x += bts906b (); + x += bts963 (); + x += bts963b (); + return x; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/ex_spec_interproc.c frama-c-20111001+nitrogen+dfsg/tests/slicing/ex_spec_interproc.c --- frama-c-20110201+carbon+dfsg/tests/slicing/ex_spec_interproc.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/ex_spec_interproc.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/ex_spec_interproc.opt CMD: tests/slicing/ex_spec_interproc.opt - OPT: -deps -journal-disable + OPT: -check -deps -journal-disable */ int X, Y; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/ex_spec_interproc.ml frama-c-20111001+nitrogen+dfsg/tests/slicing/ex_spec_interproc.ml --- frama-c-20110201+carbon+dfsg/tests/slicing/ex_spec_interproc.ml 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/ex_spec_interproc.ml 2011-10-10 08:38:44.000000000 +0000 @@ -75,7 +75,7 @@ (* VP: initial value of 34 does not refer to d++ (was 30) 9 corresponds to d++. old ki 34 corresponds to return(X), new ki 13 *) print_stmt project kf_f; - let ki,_ = Kernel_function.find_from_sid 10(*34*) in (* d++ *) + let ki = get_stmt 10(*34*) in (* d++ *) let select = select_data_before_stmt "a" ki project kf_f in !S.Request.add_slice_selection_internal project ff_f select; print_requests project; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/filter.c frama-c-20111001+nitrogen+dfsg/tests/slicing/filter.c --- frama-c-20110201+carbon+dfsg/tests/slicing/filter.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/filter.c 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,45 @@ +/* run.config + OPT: -check -slice-return main -journal-disable -then-on 'Slicing export' -print + **/ + +/* TESTS: this is about [filter] optimisations since sometimes, + * slicing results are ok, but the generated new project is not correct. */ + +int T[10]; + +/* When removing branches, one should take care about local variables. */ +int bts806 () { + int c = 0; + int x = 0; + + if (c) { + int y; + { y = x+1; + x = y; + } + } + else { + int z; + { z = x+1; + x = z; + } + } + return x; +} + + +int unspec () { + int c = 0; + if (c) + T[1] += f (T[1]); + else + T[2] += f (T[2]); + return T[1] + T[2]; +} + +int main (int c) { + int r = 0; + r += bts806 (); + r += unspec (); + return r; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/horwitz.c frama-c-20111001+nitrogen+dfsg/tests/slicing/horwitz.c --- frama-c-20110201+carbon+dfsg/tests/slicing/horwitz.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/horwitz.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/horwitz.opt CMD: tests/slicing/horwitz.opt - OPT: -deps -slicing-level 0 -journal-disable + OPT: -check -deps -slicing-level 0 -journal-disable */ /* bin/toplevel.opt -deps -val tests/slicing/horwitz.c */ diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/if_many_values.c frama-c-20111001+nitrogen+dfsg/tests/slicing/if_many_values.c --- frama-c-20110201+carbon+dfsg/tests/slicing/if_many_values.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/if_many_values.c 2011-10-10 08:38:44.000000000 +0000 @@ -0,0 +1,14 @@ +/* run.config + OPT: -check -slice-value r -journal-disable -slevel 100 -then-on 'Slicing export' -print + **/ + +int r=1; + +int main() { + for (int i = -100; i < 100; i++) { + if (i != 0) + if (i) + r += 1; + } + return r; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/keep_annot.c frama-c-20111001+nitrogen+dfsg/tests/slicing/keep_annot.c --- frama-c-20110201+carbon+dfsg/tests/slicing/keep_annot.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/keep_annot.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,8 +1,8 @@ /* run.config - OPT: -context-valid-pointers -lib-entry -main f -slice-print -slice-assert f - OPT: -context-valid-pointers -lib-entry -main f -slice-print -slice-assert f -slicing-keep-annotations - OPT: -context-valid-pointers -lib-entry -main L -slice-print -slice-pragma L -slicing-keep-annotations - OPT: -context-valid-pointers -lib-entry -main L -slice-print -slice-pragma L + OPT: -check -context-valid-pointers -lib-entry -main f -slice-assert f -then-on 'Slicing export' -print + OPT: -check -context-valid-pointers -lib-entry -main f -slice-assert f -slicing-keep-annotations -then-on 'Slicing export' -print + OPT: -check -context-valid-pointers -lib-entry -main L -slice-pragma L -slicing-keep-annotations -then-on 'Slicing export' -print + OPT: -check -context-valid-pointers -lib-entry -main L -slice-pragma L -then-on 'Slicing export' -print */ typedef struct { int a; double b; } las; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/libSelect.ml frama-c-20111001+nitrogen+dfsg/tests/slicing/libSelect.ml --- frama-c-20110201+carbon+dfsg/tests/slicing/libSelect.ml 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/libSelect.ml 2011-10-10 08:38:44.000000000 +0000 @@ -63,7 +63,7 @@ (* let load_source_file ?entry_point filename = Db.Files.clear (); - Db.Files.add [ Db_types.NeedCPP (filename, Db.get_preprocessor_command()) ]; + Db.Files.add [ Cil_types.NeedCPP (filename, Db.get_preprocessor_command()) ]; let entry_point, library = match entry_point with | None | Some "main" -> "main", false | Some f -> f, true @@ -83,7 +83,7 @@ let lval_term = !Db.Properties.Interp.lval kf kinst str_data in let lval = !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term in let loc = !Db.Value.lval_to_loc ~with_alarms:CilE.warn_none_mode (Cil_types.Kstmt kinst) lval in - Locations.valid_enumerate_bits loc + Locations.valid_enumerate_bits ~for_writing:false loc ;; let select_data_before_stmt str_data kinst _project kf = @@ -97,7 +97,11 @@ let ki = Kernel_function.find_return kf in try let loc = Db.Value.find_return_loc kf in - let zone = Locations.valid_enumerate_bits loc in + let zone = + Locations.valid_enumerate_bits + ~for_writing:false + loc + in let mark = !S.Mark.make ~data:true ~addr:false ~ctrl:false in let before = false in !S.Select.select_stmt_zone_internal kf ki before zone mark @@ -119,12 +123,12 @@ * [numstmt]*) let select_ctrl numstmt _project kf = try - let ki,_ = Kernel_function.find_from_sid numstmt in + let s = get_stmt numstmt in (* let mark = !S.Mark.make ~data:false ~addr:false ~ctrl:true in !S.Select.select_stmt_internal kf ki mark *) - !S.Select.select_stmt_ctrl_internal kf ki + !S.Select.select_stmt_ctrl_internal kf s with _ -> raise (Unknown_stmt numstmt) ;; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/loop_infinite.c frama-c-20111001+nitrogen+dfsg/tests/slicing/loop_infinite.c --- frama-c-20110201+carbon+dfsg/tests/slicing/loop_infinite.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/loop_infinite.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -deps -slice-print -slice-return main -journal-disable + OPT: -check -deps -slice-return main -journal-disable -then-on 'Slicing export' -print */ int main() { volatile int a=0,b,c; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/loops.c frama-c-20111001+nitrogen+dfsg/tests/slicing/loops.c --- frama-c-20110201+carbon+dfsg/tests/slicing/loops.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/loops.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,28 +1,28 @@ /* run.config - OPT: -slice-print -deps -lib-entry -main f1 -slice-pragma f1 -journal-disable - OPT: -slice-print -deps -lib-entry -main f1 -slice-assert f1 -journal-disable - OPT: -slice-print -deps -lib-entry -main f2 -slice-pragma f2 -journal-disable - OPT: -slice-print -deps -lib-entry -main f2 -slice-assert f2 -journal-disable - OPT: -slice-print -deps -main test_infinite_loop_3 -slice-value G -journal-disable - OPT: -slice-print -deps -main test_infinite_loop_4 -slice-value G -journal-disable - OPT: -slice-print -deps -main test_infinite_loop_5 -slice-value G -journal-disable - OPT: -slice-print -deps -main loop -slice-value Z -journal-disable - OPT: -slice-print -deps -slice-calls loop -journal-disable - OPT: -slice-print -deps -slice-pragma loop -journal-disable - OPT: -slice-print -deps -slice-assert loop -journal-disable - OPT: -slice-print -deps -main loop -slice-rd Y -journal-disable - OPT: -slice-print -deps -main loop -slice-rd Z -journal-disable - OPT: -slice-print -deps -main loop -slice-wr Y -journal-disable - OPT: -slice-print -deps -main loop -slice-wr Z -journal-disable - OPT: -slice-print -deps -lib-entry -main stop_f1 -slice-pragma stop_f1 -journal-disable - OPT: -slice-print -deps -lib-entry -main stop_f1 -slice-assert stop_f1 -journal-disable - OPT: -slice-print -deps -lib-entry -main stop_f2 -slice-pragma stop_f2 -journal-disable - OPT: -slice-print -deps -lib-entry -main stop_f2 -slice-assert stop_f2 -journal-disable - OPT: -slice-print -deps -slice-value Z -journal-disable - OPT: -slice-print -deps -slice-rd Y -journal-disable - OPT: -slice-print -deps -slice-rd Z -journal-disable - OPT: -slice-print -deps -slice-wr Y -journal-disable - OPT: -slice-print -deps -slice-wr Z -journal-disable + OPT: -check -deps -lib-entry -main f1 -slice-pragma f1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main f1 -slice-assert f1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main f2 -slice-pragma f2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main f2 -slice-assert f2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main test_infinite_loop_3 -slice-value G -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main test_infinite_loop_4 -slice-value G -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main test_infinite_loop_5 -slice-value G -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main loop -slice-value Z -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-calls loop -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-pragma loop -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-assert loop -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main loop -slice-rd Y -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main loop -slice-rd Z -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main loop -slice-wr Y -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -main loop -slice-wr Z -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main stop_f1 -slice-pragma stop_f1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main stop_f1 -slice-assert stop_f1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main stop_f2 -slice-pragma stop_f2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main stop_f2 -slice-assert stop_f2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-value Z -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-rd Y -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-rd Z -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-wr Y -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-wr Z -journal-disable -then-on 'Slicing export' -print diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/loop_simple.c frama-c-20111001+nitrogen+dfsg/tests/slicing/loop_simple.c --- frama-c-20110201+carbon+dfsg/tests/slicing/loop_simple.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/loop_simple.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -deps -slice-print -slice-return main -journal-disable + OPT: -check -deps -slice-return main -journal-disable -then-on 'Slicing export' -print */ int main() { int a,c; volatile int b = 0; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/mark_all_slices.c frama-c-20111001+nitrogen+dfsg/tests/slicing/mark_all_slices.c --- frama-c-20110201+carbon+dfsg/tests/slicing/mark_all_slices.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/mark_all_slices.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/mark_all_slices.opt CMD: tests/slicing/mark_all_slices.opt - OPT: -deps -slicing-level 3 -no-slice-callers -journal-disable + OPT: -check -deps -slicing-level 3 -no-slice-callers -journal-disable */ int A, B, C, D; int A2, B2, C2, D2; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/mark_all_slices.ml frama-c-20111001+nitrogen+dfsg/tests/slicing/mark_all_slices.ml --- frama-c-20110201+carbon+dfsg/tests/slicing/mark_all_slices.ml 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/mark_all_slices.ml 2011-10-10 08:38:44.000000000 +0000 @@ -11,7 +11,7 @@ (* we are interesting in having several slices, * so use mode PreciseSlices *) - (* SlicingParameters.Mode.Calls.set 3; *) + (* SlicingKernel.Mode.Calls.set 3; *) (*~~~~~~~~~~~~ Project 1 : *) diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/merge.c frama-c-20111001+nitrogen+dfsg/tests/slicing/merge.c --- frama-c-20110201+carbon+dfsg/tests/slicing/merge.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/merge.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/merge.opt CMD: tests/slicing/merge.opt - OPT: -deps -slicing-level 3 -journal-disable + OPT: -check -deps -slicing-level 3 -journal-disable */ int G1, G2, G3; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/min_call.c frama-c-20111001+nitrogen+dfsg/tests/slicing/min_call.c --- frama-c-20110201+carbon+dfsg/tests/slicing/min_call.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/min_call.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/min_call.opt CMD: tests/slicing/min_call.opt - OPT: -deps -lib-entry -main g -journal-disable -slicing-level 3 + OPT: -check -deps -lib-entry -main g -journal-disable -slicing-level 3 */ /* dummy source file in order to test minimal calls feature diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/min_call.ml frama-c-20111001+nitrogen+dfsg/tests/slicing/min_call.ml --- frama-c-20110201+carbon+dfsg/tests/slicing/min_call.ml 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/min_call.ml 2011-10-10 08:38:44.000000000 +0000 @@ -6,7 +6,7 @@ include LibSelect;; let main _ = - (* SlicingParameters.Mode.Calls.set 3; *) + (* SlicingKernel.Mode.Calls.set 3; *) let _kf_get = Globals.Functions.find_by_name "get" in let _kf_send = Globals.Functions.find_by_name "send" in let kf_send_bis = Globals.Functions.find_by_name "send_bis" in @@ -38,11 +38,11 @@ let select = !S.Select.select_stmt_internal kf_k sb_call mark in !S.Request.add_selection_internal project select ; !S.Request.apply_all_internal project; - Log.print_on_output "@[Project1 - result1 :@\n@]"; + Log.print_on_output (fun fmt -> Format.fprintf fmt "@[Project1 - result1 :@\n@]") ; extract_and_print project; let _ff2_k = !S.Slice.create project kf_k in - Log.print_on_output "@[Project1 - result2 :@\n@]"; + Log.print_on_output (fun fmt -> Format.fprintf fmt "@[Project1 - result2 :@\n@]") ; !S.Project.pretty fmt project; extract_and_print project; @@ -60,7 +60,7 @@ !S.Request.add_selection_internal project select ; print_requests project; !S.Request.apply_all_internal project; - Log.print_on_output "@[Project3 - result :@\n@]"; + Log.print_on_output (fun fmt -> Format.fprintf fmt "@[Project3 - result :@\n@]") ; !S.Project.pretty fmt project; extract_and_print project; @@ -77,7 +77,7 @@ !S.Request.apply_next_internal project; print_requests project; !S.Request.apply_all_internal project; - Log.print_on_output "@[Project3 - result :@\n@]"; + Log.print_on_output (fun fmt -> Format.fprintf fmt "@[Project3 - result :@\n@]") ; !S.Project.pretty fmt project; extract_and_print project diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/ptr_fct.c frama-c-20111001+nitrogen+dfsg/tests/slicing/ptr_fct.c --- frama-c-20110201+carbon+dfsg/tests/slicing/ptr_fct.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/ptr_fct.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -main h -slice-return h -slice-print -slicing-level 1 -journal-disable + OPT: -check -main h -slice-return h -slicing-level 1 -journal-disable -then-on 'Slicing export' -print */ int X ; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/select_by_annot.c frama-c-20111001+nitrogen+dfsg/tests/slicing/select_by_annot.c --- frama-c-20110201+carbon+dfsg/tests/slicing/select_by_annot.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/select_by_annot.c 2011-10-10 08:38:44.000000000 +0000 @@ -3,20 +3,20 @@ CMD: tests/slicing/select_by_annot.opt OPT: -deps -lib-entry -main main -journal-disable CMD: bin/toplevel.opt - OPT: -deps -lib-entry -main main -slice-print -slice-pragma main -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-assert main -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma modifS -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f1 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f2 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f3 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f4 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f5 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f6 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f7 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-loop-inv f8 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f8 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-assert f8 -no-slice-callers -journal-disable - OPT: -deps -lib-entry -main main -slice-print -slice-pragma f9 -no-slice-callers -journal-disable + OPT: -check -deps -lib-entry -main main -slice-pragma main -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-assert main -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma modifS -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f4 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f5 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f6 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f7 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-loop-inv f8 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f8 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-assert f8 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -lib-entry -main main -slice-pragma f9 -no-slice-callers -journal-disable -then-on 'Slicing export' -print */ diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/select_calls.c frama-c-20111001+nitrogen+dfsg/tests/slicing/select_calls.c --- frama-c-20110201+carbon+dfsg/tests/slicing/select_calls.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/select_calls.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,6 @@ /* run.config - GCC: - OPT: -lib-entry -main f -slice-calls send -slice-print -journal-disable - OPT: -lib-entry -main g -slice-calls nothing -slice-print -journal-disable + OPT: -check -lib-entry -main f -slice-calls send -journal-disable -then-on 'Slicing export' -print + OPT: -check -lib-entry -main g -slice-calls nothing -journal-disable -then-on 'Slicing export' -print */ void nothing (void); diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/select_return_bis.c frama-c-20111001+nitrogen+dfsg/tests/slicing/select_return_bis.c --- frama-c-20110201+carbon+dfsg/tests/slicing/select_return_bis.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/select_return_bis.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,15 +1,15 @@ /* run.config - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 0 -no-slice-callers -journal-disable - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 0 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 1 -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 2 -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 3 -journal-disable + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 0 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 0 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 3 -journal-disable -then-on 'Slicing export' -print */ int G,H,I; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/select_return.c frama-c-20111001+nitrogen+dfsg/tests/slicing/select_return.c --- frama-c-20110201+carbon+dfsg/tests/slicing/select_return.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/select_return.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,26 +1,26 @@ /* run.config - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 0 -no-slice-callers -journal-disable - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-calls send -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 0 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-calls send,send_bis -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable - OPT: -slice-calls "send , send_bis" -lib-entry -main g -slice-print -slicing-level 1 -journal-disable - OPT: -slice-calls "send, send_bis" -lib-entry -main g -slice-print -slicing-level 2 -journal-disable - OPT: -slice-calls "send ,send_bis" -lib-entry -main g -slice-print -slicing-level 3 -journal-disable - OPT: -slice-return f -lib-entry -main g -slice-print -slicing-level 0 -no-slice-callers -journal-disable - OPT: -slice-return f -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-return f -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-return f -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable - OPT: -slice-pragma f -lib-entry -main g -slice-print -slicing-level 0 -no-slice-callers -journal-disable - OPT: -slice-pragma f -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-pragma f -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-pragma f -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable - OPT: -slice-value H -lib-entry -main g -slice-print -slicing-level 1 -no-slice-callers -journal-disable - OPT: -slice-value H -lib-entry -main g -slice-print -slicing-level 2 -no-slice-callers -journal-disable - OPT: -slice-value H -lib-entry -main g -slice-print -slicing-level 3 -no-slice-callers -journal-disable + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 0 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 0 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls send,send_bis -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls "send , send_bis" -lib-entry -main g -slicing-level 1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls "send, send_bis" -lib-entry -main g -slicing-level 2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-calls "send ,send_bis" -lib-entry -main g -slicing-level 3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return f -lib-entry -main g -slicing-level 0 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return f -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return f -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return f -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-pragma f -lib-entry -main g -slicing-level 0 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-pragma f -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-pragma f -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-pragma f -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-value H -lib-entry -main g -slicing-level 1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-value H -lib-entry -main g -slicing-level 2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-value H -lib-entry -main g -slicing-level 3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print */ int G,H,I; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/select_simple.c frama-c-20111001+nitrogen+dfsg/tests/slicing/select_simple.c --- frama-c-20110201+carbon+dfsg/tests/slicing/select_simple.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/select_simple.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/select_simple.opt CMD: tests/slicing/select_simple.opt - OPT: -deps -journal-disable + OPT: -check -deps -journal-disable */ /* dummy source file in order to test select_simple.ml */ diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/simple_intra_slice.c frama-c-20111001+nitrogen+dfsg/tests/slicing/simple_intra_slice.c --- frama-c-20110201+carbon+dfsg/tests/slicing/simple_intra_slice.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/simple_intra_slice.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/simple_intra_slice.opt CMD: tests/slicing/simple_intra_slice.opt - OPT: -deps -slicing-level 2 -no-slice-callers -journal-disable + OPT: -check -deps -slicing-level 2 -no-slice-callers -journal-disable */ int Unknown; int G; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/simple_intra_slice.ml frama-c-20111001+nitrogen+dfsg/tests/slicing/simple_intra_slice.ml --- frama-c-20110201+carbon+dfsg/tests/slicing/simple_intra_slice.ml 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/simple_intra_slice.ml 2011-10-10 08:38:44.000000000 +0000 @@ -58,7 +58,7 @@ let kf = get_fct "f2" in Format.printf "@[%a@]@\n" pretty_pdg kf; print_fct_stmts kf; - select_stmt_and_print kf 8; (* c=3; *) + select_stmt_and_print kf 9; (* c=3; *) let kf = get_fct "f3" in Format.printf "@[%a@]@\n" pretty_pdg kf; @@ -69,7 +69,7 @@ Format.printf "@[%a@]@\n" pretty_pdg kf; print_fct_stmts kf; select_out0_and_print kf; - select_stmt_and_print kf 24; (* G=a; in then branch of if (c>Unknown) *) + select_stmt_and_print kf 27; (* G=a; in then branch of if (c>Unknown) *) let kf = get_fct "f5" in print_outputs "f5"; @@ -77,19 +77,20 @@ Format.printf "@[%a@]@\n" pretty_pdg kf; print_fct_stmts kf; select_out0_and_print kf; - select_ctrl_and_print kf 34; + select_ctrl_and_print kf 38; (* G++. VP 2008-02-04: Was ki 113, and corresponded to if(c<Unknown) { goto L2; }, not to G++ Fixed ki number to the test instead of the incrementation. As of this date, ki for G++ is 31. VP 2008-06-25 ki for G++ is 32 VP 2008-07-17 ki for G++ is 37 + BY 2011-04-14 sid for G++ is 38 *) let kf = get_fct "f6" in Format.printf "@[%a@]@\n" pretty_pdg kf; print_fct_stmts kf; - select_ctrl_and_print kf 58; + select_ctrl_and_print kf 64; (* return_label VP 2008-02-04: Was ki 135, corresponding to first stmt in the else branch of if (i) { __retres = 0; goto return_label; } @@ -98,6 +99,7 @@ As of this date, ki for return_label is 92 VP 2008-06-25: ki for return_label is 96 VP 2008-07-17: ki for return_label is 112 +BY 2011-04-14 sid for return_label is 128 *) !S.Project.pretty Format.std_formatter project diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/sizeof.c frama-c-20111001+nitrogen+dfsg/tests/slicing/sizeof.c --- frama-c-20110201+carbon+dfsg/tests/slicing/sizeof.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/sizeof.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,17 +1,17 @@ /* run.config - OPT: -deps -slice-print -slice-return main -journal-disable - OPT: -deps -slice-print -slice-return SizeOf_1 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOf_2 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_pt1 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_pt2 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_pt3 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_pt_deref_1 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_tab_1 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_pt_tab_1 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_pt_tab_2 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-return SizeOfE_tab_acces_1 -no-slice-callers -journal-disable - OPT: -deps -slice-print -slice-pragma main -journal-disable - OPT: -deps -slice-print -slice-assert main -journal-disable + OPT: -check -deps -slice-return main -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOf_1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOf_2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_pt1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_pt2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_pt3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_pt_deref_1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_tab_1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_pt_tab_1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_pt_tab_2 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-return SizeOfE_tab_acces_1 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-pragma main -journal-disable -then-on 'Slicing export' -print + OPT: -check -deps -slice-assert main -journal-disable -then-on 'Slicing export' -print */ struct St { int i, *p, tab[5] ; } st ; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/slice_behavior.c frama-c-20111001+nitrogen+dfsg/tests/slicing/slice_behavior.c --- frama-c-20110201+carbon+dfsg/tests/slicing/slice_behavior.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/slice_behavior.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -val -slice-assert f -slice-print -slicing-level 0 -journal-disable + OPT: -check -val -slice-assert f -slicing-level 0 -journal-disable -then-on 'Slicing export' -print */ /*@ requires a > 0; */ int f(int a) { diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/slice_no_body.c frama-c-20111001+nitrogen+dfsg/tests/slicing/slice_no_body.c --- frama-c-20110201+carbon+dfsg/tests/slicing/slice_no_body.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/slice_no_body.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/slice_no_body.opt CMD: tests/slicing/slice_no_body.opt - OPT: -deps -lib-entry -main h -journal-disable + OPT: -check -deps -lib-entry -main h -journal-disable */ int G; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/slice_pragma_stmt.c frama-c-20111001+nitrogen+dfsg/tests/slicing/slice_pragma_stmt.c --- frama-c-20110201+carbon+dfsg/tests/slicing/slice_pragma_stmt.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/slice_pragma_stmt.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,27 +1,27 @@ /* run.config - OPT: -print -journal-disable - OPT: -main nop1 -slice-pragma nop1 -slice-print -journal-disable - OPT: -main nop2 -slice-pragma nop2 -slice-print -journal-disable - OPT: -main nop3 -slice-pragma nop3 -slice-print -journal-disable - OPT: -main nop4 -slice-pragma nop4 -slice-print -journal-disable - OPT: -main nop5 -slice-pragma nop5 -slice-print -journal-disable - OPT: -main nop6 -slice-pragma nop6 -slice-print -journal-disable - OPT: -main nop7 -slice-pragma nop7 -slice-print -journal-disable - OPT: -main nop8 -slice-pragma nop8 -slice-print -journal-disable - OPT: -main double_effect1 -slice-pragma double_effect1 -slice-print -journal-disable - OPT: -main double_effect2 -slice-pragma double_effect2 -slice-print -journal-disable - OPT: -main double_effect3 -slice-pragma double_effect3 -slice-print -journal-disable - OPT: -main double_effect4 -slice-pragma double_effect4 -slice-print -journal-disable - OPT: -main double_effect5 -slice-pragma double_effect5 -slice-print -journal-disable - OPT: -main test1 -slice-pragma test1 -slice-print -journal-disable - OPT: -main test2 -slice-pragma test2 -slice-print -journal-disable - OPT: -main test3 -slice-pragma test3 -slice-print -journal-disable - OPT: -main test4 -slice-pragma test4 -slice-print -journal-disable - OPT: -main test5 -slice-pragma test5 -slice-print -journal-disable - OPT: -main test6 -slice-pragma test6 -slice-print -journal-disable - OPT: -main test7 -slice-pragma test7 -slice-print -journal-disable - OPT: -main test8 -slice-pragma test8 -slice-print -journal-disable - OPT: -main test9 -slice-pragma test9 -slice-print -journal-disable + OPT: -check -print -journal-disable + OPT: -check -main nop1 -slice-pragma nop1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop2 -slice-pragma nop2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop3 -slice-pragma nop3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop4 -slice-pragma nop4 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop5 -slice-pragma nop5 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop6 -slice-pragma nop6 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop7 -slice-pragma nop7 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main nop8 -slice-pragma nop8 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main double_effect1 -slice-pragma double_effect1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main double_effect2 -slice-pragma double_effect2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main double_effect3 -slice-pragma double_effect3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main double_effect4 -slice-pragma double_effect4 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main double_effect5 -slice-pragma double_effect5 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test1 -slice-pragma test1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test2 -slice-pragma test2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test3 -slice-pragma test3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test4 -slice-pragma test4 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test5 -slice-pragma test5 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test6 -slice-pragma test6 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test7 -slice-pragma test7 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test8 -slice-pragma test8 -journal-disable -then-on 'Slicing export' -print + OPT: -check -main test9 -slice-pragma test9 -journal-disable -then-on 'Slicing export' -print */ typedef int stmt, expr, slice; int x, y ; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/switch.c frama-c-20111001+nitrogen+dfsg/tests/slicing/switch.c --- frama-c-20110201+carbon+dfsg/tests/slicing/switch.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/switch.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing/switch.opt CMD: tests/slicing/switch.opt - OPT: -deps -journal-disable + OPT: -check -deps -journal-disable */ int main (char choix) { int x = 0, y = 0, z = 0; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/top2.c frama-c-20111001+nitrogen+dfsg/tests/slicing/top2.c --- frama-c-20110201+carbon+dfsg/tests/slicing/top2.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/top2.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config -* OPT: -slicing-level 2 -slice-pragma main -slice-print -journal-disable -* OPT: -slicing-level 2 -slice-return main -slice-print -journal-disable +* OPT: -check -slicing-level 2 -slice-pragma main -journal-disable -then-on 'Slicing export' -print +* OPT: -check -slicing-level 2 -slice-return main -journal-disable -then-on 'Slicing export' -print */ diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/top.c frama-c-20111001+nitrogen+dfsg/tests/slicing/top.c --- frama-c-20110201+carbon+dfsg/tests/slicing/top.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/top.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config -* OPT: -slicing-level 0 -slice-return uncalled -slice-print -no-slice-callers -journal-disable -* OPT: -slicing-level 2 -slice-return main -slice-print -journal-disable -* OPT: -slicing-level 2 -slice-return strlen -slice-print -journal-disable +* OPT: -check -slicing-level 0 -slice-return uncalled -no-slice-callers -journal-disable -then-on 'Slicing export' -print +* OPT: -check -slicing-level 2 -slice-return main -journal-disable -then-on 'Slicing export' -print +* OPT: -check -slicing-level 2 -slice-return strlen -journal-disable -then-on 'Slicing export' -print * * * diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/undef-fun.c frama-c-20111001+nitrogen+dfsg/tests/slicing/undef-fun.c --- frama-c-20110201+carbon+dfsg/tests/slicing/undef-fun.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/undef-fun.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,5 +1,5 @@ /* run.config - OPT: -slice-print -slice-undef-functions -slice-return f -journal-disable + OPT: -check -slice-undef-functions -slice-return f -journal-disable -then-on 'Slicing export' -print diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/unitialized.c frama-c-20111001+nitrogen+dfsg/tests/slicing/unitialized.c --- frama-c-20110201+carbon+dfsg/tests/slicing/unitialized.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/unitialized.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,8 +1,8 @@ /* run.config - OPT: -slice-print -slice-pragma g -journal-disable - OPT: -slice-print -slice-assert g -journal-disable - OPT: -slice-print -slice-assert main -journal-disable - OPT: -slice-print -slice-return g -journal-disable + OPT: -check -slice-pragma g -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-assert g -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-assert main -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return g -journal-disable -then-on 'Slicing export' -print */ int X1, X2 ; diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/unravel-flavors.c frama-c-20111001+nitrogen+dfsg/tests/slicing/unravel-flavors.c --- frama-c-20110201+carbon+dfsg/tests/slicing/unravel-flavors.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/unravel-flavors.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,9 +1,8 @@ /* run.config - GCC: - OPT: -slice-print -slice-undef-functions -slice-return send1 -journal-disable - OPT: -slice-print -slice-undef-functions -slice-return send2 -journal-disable - OPT: -slice-print -slice-undef-functions -slice-return send3 -journal-disable - OPT: -slice-print -slice-undef-functions -slice-return send4 -journal-disable + OPT: -check -slice-undef-functions -slice-return send1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-undef-functions -slice-return send2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-undef-functions -slice-return send3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-undef-functions -slice-return send4 -journal-disable -then-on 'Slicing export' -print */ /* Small example derived from examples given for UNRAVEL tool : */ diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/unravel-point.c frama-c-20111001+nitrogen+dfsg/tests/slicing/unravel-point.c --- frama-c-20110201+carbon+dfsg/tests/slicing/unravel-point.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/unravel-point.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,10 +1,9 @@ /* run.config - GCC: - OPT: -slice-print -calldeps -slice-return send1 -journal-disable - OPT: -slice-print -calldeps -slice-return send2 -journal-disable - OPT: -slice-print -calldeps -slice-return send3 -journal-disable - OPT: -slice-print -calldeps -slice-return send4 -journal-disable - + OPT: -check -calldeps -slice-return send1 -journal-disable -then-on 'Slicing export' -print + OPT: -check -calldeps -slice-return send2 -journal-disable -then-on 'Slicing export' -print + OPT: -check -calldeps -slice-return send3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -calldeps -slice-return send4 -journal-disable -then-on 'Slicing export' -print + OPT: -check -calldeps -slice-return send1 -slice-return send4 -journal-disable -then-on 'Slicing export' -check -calldeps -slice-return send1_slice_1 -print -then-on 'Slicing export 2' -print diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/unravel-variance.c frama-c-20111001+nitrogen+dfsg/tests/slicing/unravel-variance.c --- frama-c-20110201+carbon+dfsg/tests/slicing/unravel-variance.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/unravel-variance.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,10 +1,9 @@ /* run.config - GCC: - OPT: -slice-print -slice-calls printf1 -journal-disable -float-normal - OPT: -slice-print -slice-calls printf2 -journal-disable -float-normal - OPT: -slice-print -slice-calls printf3 -journal-disable -float-normal - OPT: -slice-print -slice-calls printf4 -journal-disable -float-normal - OPT: -slice-print -slice-calls printf5 -journal-disable -float-normal + OPT: -check -slice-calls printf1 -journal-disable -float-normal -then-on 'Slicing export' -print + OPT: -check -slice-calls printf2 -journal-disable -float-normal -then-on 'Slicing export' -print + OPT: -check -slice-calls printf3 -journal-disable -float-normal -then-on 'Slicing export' -print + OPT: -check -slice-calls printf4 -journal-disable -float-normal -then-on 'Slicing export' -print + OPT: -check -slice-calls printf5 -journal-disable -float-normal -then-on 'Slicing export' -print */ /* Small example devired from examples given for UNRAVEL tool : */ diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing/variadic.c frama-c-20111001+nitrogen+dfsg/tests/slicing/variadic.c --- frama-c-20110201+carbon+dfsg/tests/slicing/variadic.c 2011-02-07 13:41:41.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing/variadic.c 2011-10-10 08:38:44.000000000 +0000 @@ -1,9 +1,8 @@ /* run.config -* GCC: -* OPT: -slice-return f3 -slice-print -no-slice-callers -journal-disable -* OPT: -slice-return f3 -slice-print -journal-disable -* OPT: -slice-return main -slice-print -journal-disable -* OPT: -slice-return main -slice-print -slicing-level 3 -journal-disable + OPT: -check -slice-return f3 -no-slice-callers -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return f3 -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return main -journal-disable -then-on 'Slicing export' -print + OPT: -check -slice-return main -slicing-level 3 -journal-disable -then-on 'Slicing export' -print */ #include "../pdg/variadic.c" diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing2/adpcm.c frama-c-20111001+nitrogen+dfsg/tests/slicing2/adpcm.c --- frama-c-20110201+carbon+dfsg/tests/slicing2/adpcm.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing2/adpcm.c 2011-10-10 08:39:10.000000000 +0000 @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s tests/slicing2/adpcm.opt CMD: tests/slicing2/adpcm.opt - OPT: -no-annot -deps -slicing-level 2 -journal-disable + OPT: -check -no-annot -deps -slicing-level 2 -journal-disable */ #include "tests/test/adpcm.c" diff -Nru frama-c-20110201+carbon+dfsg/tests/slicing2/adpcm.ml frama-c-20111001+nitrogen+dfsg/tests/slicing2/adpcm.ml --- frama-c-20110201+carbon+dfsg/tests/slicing2/adpcm.ml 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/slicing2/adpcm.ml 2011-10-10 08:39:10.000000000 +0000 @@ -5,7 +5,7 @@ include LibSelect;; -(* Parameters.slicing_level := 2;; = MinimizeNbCalls *) +(* Kernel.slicing_level := 2;; = MinimizeNbCalls *) (* let resname = "tests/slicing2/adpcm.sliced" in diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/bts334.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/bts334.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/bts334.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/bts334.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,7 +1,7 @@ /*run.config OPT: -main main_init -sparecode-analysis -sparecode-no-annot -journal-disable - OPT: -main main_init -slice-print -slice-pragma loop_body -journal-disable - OPT: -main main_init -slice-print -slice-pragma loop_body -calldeps -journal-disable + OPT: -main main_init -slice-pragma loop_body -journal-disable -then-on 'Slicing export' -print + OPT: -main main_init -slice-pragma loop_body -calldeps -journal-disable -then-on 'Slicing export' -print */ int kf ; int k[2] ; diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/bts927.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/bts927.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/bts927.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/bts927.c 2011-10-10 08:39:09.000000000 +0000 @@ -0,0 +1,25 @@ +/* run.config + OPT: -journal-disable -sparecode + OPT: -journal-disable -val-signed-overflow-alarms -sparecode +*/ + +/* The purpose of these tests is to check if the conditions are removed + * when the branch is statically known. */ + +int f (int a) { + int c = a+1; + return (c > 0) ? 1 : 0; +} + +int main (int x) { + //@ assert x>5; + if (x > 5) { + int y = f(x); + if (y < 2) // always true + return f(x); + else return -1; + } else { + return 4; + } +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/calls.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/calls.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/calls.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/calls.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable - OPT: -slicing-level 2 -slice-return main -slice-print -journal-disable + OPT: -slicing-level 2 -slice-return main -journal-disable -then-on 'Slicing export' -print */ int G; diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/dead_code.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/dead_code.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/dead_code.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/dead_code.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config - OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable - OPT: -slicing-level 2 -slice-return main -slice-print -journal-disable + OPT: -sparecode-debug 1 -sparecode -journal-disable + OPT: -slicing-level 2 -slice-return main -journal-disable -then-on 'Slicing export' -print */ int main (void) { diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/glob_decls.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/glob_decls.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/glob_decls.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/glob_decls.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config OPT: -lib-entry -journal-disable -sparecode-debug 1 -sparecode-analysis - OPT: -lib-entry -slice-pragma main -slice-return main -slice-print -journal-disable + OPT: -lib-entry -slice-pragma main -slice-return main -journal-disable -then-on 'Slicing export' -print OPT: -journal-disable -sparecode-debug 1 -rm-unused-globals */ @@ -36,11 +36,17 @@ Tx X = sizeof (Size); int Y; +int use_in_PX_init; +int * PX; + /*@ requires S2.a > S2.b ; */ int main (int x, Ts s) { //@ slice pragma expr S2 ; int y = 3; y += Y; + y += *PX; //@ assert X > 0; return X + x; } + +int * PX = &use_in_PX_init; diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/intra.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/intra.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/intra.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/intra.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,9 +1,9 @@ /* run.config OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable - OPT: -slicing-level 2 -slice-return main -slice-print -journal-disable + OPT: -slicing-level 2 -slice-return main -journal-disable -then-on 'Slicing export' -print OPT: -main main2 -sparecode-analysis -journal-disable - OPT: -main main2 -slice-return main2 -slice-print -journal-disable - OPT: -main main2 -slice-return main2 -slice-assert f10 -slice-print -journal-disable + OPT: -main main2 -slice-return main2 -journal-disable -then-on 'Slicing export' -print + OPT: -main main2 -slice-return main2 -slice-assert f10 -journal-disable -then-on 'Slicing export' -print */ /* Waiting for results such as: diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/params.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/params.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/params.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/params.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,6 +1,6 @@ /* run.config OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable - OPT: -slicing-level 2 -slice-return main -slice-print -journal-disable + OPT: -slicing-level 2 -slice-return main -journal-disable -then-on 'Slicing export' -print */ /* This is an example from #529. 'y' in [main1] should be visible to get a diff -Nru frama-c-20110201+carbon+dfsg/tests/sparecode/top.c frama-c-20111001+nitrogen+dfsg/tests/sparecode/top.c --- frama-c-20110201+carbon+dfsg/tests/sparecode/top.c 2011-02-07 13:41:51.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/sparecode/top.c 2011-10-10 08:39:09.000000000 +0000 @@ -1,9 +1,17 @@ /* run.config - DONTRUN: don't run a test which raises an exception (PdgTypes.Pdg.Top) OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable -main main_top OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable -main main_call_top + OPT: -sparecode-debug 1 -sparecode-analysis -journal-disable -main main_top_not_used */ +void print (int x); + +int not_used_in_main_top (int x) { + print (x); + return x+2; +} + + int f (int a) { return a+1; } @@ -16,5 +24,14 @@ int main_call_top (void) { int x = main_top (2, 0, 1); + x = not_used_in_main_top (x); return x; } + +int main_top_not_used (void) { + int a = main_top (2, 0, 1); + int x = f (2); + return x; +} + + diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/abrupt.i frama-c-20111001+nitrogen+dfsg/tests/spec/abrupt.i --- frama-c-20110201+carbon+dfsg/tests/spec/abrupt.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/abrupt.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,37 @@ +/* run.config + STDOPT: +"-simplify-cfg" +*/ + +int f (int c) { + int x = 0; + switch (c) { + /*@ breaks x == 1; */ + { + case 0: x = 1; break; + case 1: x = 3; + case 2: x++; + default: x++; + }} + while (1) { + /*@ breaks x == \old(x); + continues x == \old(x) + 1; + */ + { + if (x < c) { x++; continue; } + break; + } + } + return x; +} + +/*@ ensures x==1 ==> \result==1; */ +int f5 (int x){ + int y = 0; + + switch (x) { + case 1 : + while (x>0) /*@ breaks x > 0; */ break ; + y = 1; + } + return y; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/all.c frama-c-20111001+nitrogen+dfsg/tests/spec/all.c --- frama-c-20110201+carbon+dfsg/tests/spec/all.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/all.c 2011-10-10 08:38:50.000000000 +0000 @@ -1,9 +1,10 @@ /* Terms */ -/*@ lemma a: \forall int x ; x --> x == -1 ; */ // KO -/*@ lemma b: \forall int x ; x <--> x == -1 ; */ // KO -/*@ lemma c: (\let x = 0 ; x+1) == 1 ; */ // OK -/*@ lemma d: (name:77) == 76+1 ; */ // OK +/*@ lemma e: \forall int x ; (x & x) == x ; */ // KO pretty printing priority +/*@ lemma a: \forall int x ; (x --> x) == -1 ; */ // KO pretty printing priority +/*@ lemma b: \forall int x ; (x <--> x) == -1 ; */ // KO pretty printing priority +/*@ lemma c: (\let x = 0 ; x+1) == 1 ; */ // OK +/*@ lemma d: (name:77) == 76+1 ; */ // OK /* Predicates */ /*@ diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/array_conversion.c frama-c-20111001+nitrogen+dfsg/tests/spec/array_conversion.c --- frama-c-20110201+carbon+dfsg/tests/spec/array_conversion.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/array_conversion.c 2011-10-10 08:38:50.000000000 +0000 @@ -24,3 +24,15 @@ int f1(foo x) { return x[3]; } int g1() { return f1(X); } + +//@ axiomatic ax { logic boolean p{L}(int *b); } + +int a[10]; + +void ftest(void) { + //@ assert p(&a[0]); + //@ assert p( a ); +} + + +//@ lemma array_not_null: a != \null; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/assigns_result.i frama-c-20111001+nitrogen+dfsg/tests/spec/assigns_result.i --- frama-c-20110201+carbon+dfsg/tests/spec/assigns_result.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/assigns_result.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + STDOPT: +"-deps" +*/ +int X,Y; + +/*@ assigns \result; + assigns \exit_status; +*/ +int f(void); + +/*@ assigns \result \from X; + assigns \exit_status \from Y; +*/ +int g(void); + +void main(void) { f(); g(); } diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/behavior_assert.c frama-c-20111001+nitrogen+dfsg/tests/spec/behavior_assert.c --- frama-c-20110201+carbon+dfsg/tests/spec/behavior_assert.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/behavior_assert.c 2011-10-10 08:38:50.000000000 +0000 @@ -32,7 +32,50 @@ G = i; } + +int abs(short x) { + if (x <= 0) + return -x; + else return x; +} + +/*@ + behavior not_null: + assumes a != 0; + ensures \result > 0; + behavior null: + assumes a == 0; + ensures \result == 0; + complete behaviors not_null, null; +*/ +int h1(short a) { + int r = abs((a-a)+a); + int r2 = r; + /*@ for not_null: + assert r != 0; */ + return r; +} + +extern int c; + +void h2 () { + int a, b; + if (c) + if (c+1) + if (c+2) + a = -2; + else + a = 3; + else + a = -4; + else + a = -1; + b = h1 (a); + //@ assert b > 0; +} + void main(void) { f(); g(); + h2(); } diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0440.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0440.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0440.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0440.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,10 @@ +int fact(int n) { + int r = 1 ; + while ( n > 0 ) { + //@ ensures n >= 0 ; + before: + r *= n-- ; + //@ assert r == \at(r*n,before) ; + } + return r ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0549.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0549.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0549.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0549.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,29 @@ +int t1[10], t2[10] ; + +//@ logic int * a1 = t1 + 0; +//@ logic int * a2 = &t1[0]; +//@ logic int * a3 = &*t1 ; +//@ logic int * a4 = t1 ; // should not be accepted +//@ logic int * a5 = (int *)t1; +//@ logic int * b1 = \let x = t1 + 0; x ; +//@ logic int * b2 = \let x = &t1[0]; x ; +//@ logic int * b3 = \let x = &*t1 ; x ; +//@ logic int * b4 = \let x = t1 ; x ; // should not be accepted + +int main () { + int i ; + for (i=0 ; i < 10 ; i++) { + t1[i] = 0 ; + t2[i] = 0 ; + } + if (t1 == t2) { + /* C tests the address of the first elements, + * so the then-branch is dead. */ + //@ assert \false; + } + else { + /* ACSL tests the contents of the arrays, + * here they are the same. */ + //@ assert (t1==t2) ; // even with the previous C + } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0570.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0570.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0570.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0570.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,5 @@ +int main(char *data ) +{ + //@ assert \pointer_comparable(data, (void *)0); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0578.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0578.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0578.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0578.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,12 @@ +/* run.config + OPT: -print -load-script ./tests/spec/bts0578.ml +*/ + +/*@ behavior foo: ensures \true; */ +void main(void) { + int i, t[10]; + /*@ loop assigns t[0..i]; + for foo: loop assigns t[0..i]; + */ + for (i = 0; i < 10; i++) { t[i] = 0; } +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0578.ml frama-c-20111001+nitrogen+dfsg/tests/spec/bts0578.ml --- frama-c-20110201+carbon+dfsg/tests/spec/bts0578.ml 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0578.ml 2011-10-10 08:38:50.000000000 +0000 @@ -1,10 +1,9 @@ open Cil_types -open Db_types open Logic_const let main () = - let s, _ = Kernel_function.find_from_sid 2 in - let add a = Annotations.add s [] (Before (User (new_code_annotation a))) in + let s, kf = Kernel_function.find_from_sid 2 in + let add a = Annotations.add kf s [] (User (new_code_annotation a)) in add (AInvariant(["foo"], true, ptrue)); add (AVariant(tinteger 0, None)); add (AInvariant([], true, ptrue)); diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0589.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0589.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0589.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0589.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,9 @@ +int x; + +int g(void) +{ int a; + //@ assigns a,x ; + a = x++ ; + return a; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0655.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0655.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0655.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0655.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,17 @@ +/* run.config + DONTRUN: bug fix in progress + OPT: -load-script tests/spec/bts0655.ml +*/ +/*@ + @ ensures \result == \max( a, b ); + @ ensures \result != \min( a, b ); + @ ensures \max(a,b) != \min(a+1,b); + @ ensures a == \abs( a ); + @*/ +unsigned int +max( unsigned int a, unsigned int b ) +{ + int i = a > b ? a : b; + //@ assert i == \max( \at(a,Pre), \at(b,Pre) ); + return i; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0655.ml frama-c-20111001+nitrogen+dfsg/tests/spec/bts0655.ml --- frama-c-20110201+carbon+dfsg/tests/spec/bts0655.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0655.ml 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,25 @@ +include + Plugin.Register( + struct + let name = "bts0655" + let shortname = "bts0655" + let help = "inspects relevant AST parts of bts0655.i" + end) + + +class check_float = +object +inherit Visitor.frama_c_inplace + method vterm t = + result "term %a has type %a" + !Ast_printer.d_term t !Ast_printer.d_logic_type t.Cil_types.term_type; + Cil.DoChildren +end + +let run () = + let f = Ast.get () in + Visitor.visitFramacFileSameGlobals (new check_float) f +;; + +Db.Main.extend run +;; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0698.i frama-c-20111001+nitrogen+dfsg/tests/spec/bts0698.i --- frama-c-20110201+carbon+dfsg/tests/spec/bts0698.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0698.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,31 @@ +/* -------------------------------------------------------------------------- */ +/* --- Testing logic casts on array types --- */ +/* -------------------------------------------------------------------------- */ + +//@ predicate P(int x[2]) = x[0] < x[1] ; + +//@ predicate Q{L}(int *x) = x[0] < x[1] ; + +//@ predicate Correct{L}(int *x) = P((int[2]) x) ; + +//@ predicate Incorrect{L}(int x[2]) = Q{L}((int *) x) ; + +int t[2] ; +int * a ; + +void f(void) +{ + t[0] = 10 ; + t[1] = 20 ; + //@ assert P(t) ; + //@ assert Q((int *)t) ; +} + +//@ requires \valid(a+(0..1)) ; +void g(void) +{ + a[0] = 10 ; + a[1] = 20 ; + //@ assert P((int[2])a) ; + //@ assert Q(a) ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/bts0812.c frama-c-20111001+nitrogen+dfsg/tests/spec/bts0812.c --- frama-c-20110201+carbon+dfsg/tests/spec/bts0812.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/bts0812.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,8 @@ +/*@ lemma fib_3: \true; // proved automatically */ +/*@ lemma fib_46: \true; */ + +/*@ assigns \nothing; +// Bla */ +void main() { +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/char_cst.c frama-c-20111001+nitrogen+dfsg/tests/spec/char_cst.c --- frama-c-20110201+carbon+dfsg/tests/spec/char_cst.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/char_cst.c 2011-10-10 08:38:50.000000000 +0000 @@ -1,7 +1,10 @@ -/* see bug #137 */ /*@ requires c != '0'; - behavior default: assumes c!='\''; - behavior hexa: assumes c != '\xAB'; - behavior oct: assumes c!= '\123'; + behavior quote: assumes c=='\'' ; + behavior default: assumes c!='\'' && c!='a'; + behavior slash: assumes c=='\\' ; + behavior other: assumes c!='\\' && c!='a'; + behavior hexa: assumes c!='\xAB'; + behavior oct: assumes c!='\123'; + behavior string: assumes ""!="\"" && ""=="" ; */ void f(char c) { } diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/comparison.i frama-c-20111001+nitrogen+dfsg/tests/spec/comparison.i --- frama-c-20110201+carbon+dfsg/tests/spec/comparison.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/comparison.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,15 @@ +/* run.config + OPT: -load-script tests/spec/comparison.ml +*/ + +/*@ predicate foo(boolean a, boolean b) = a == b; */ + +void main(void) { + int x = 0, y = 0; + long z = 0L; + /*@ assert x == y; */ + /*@ assert x == z; */ + /*@ assert (long)x == z; */ + /*@ assert foo(x==y,x==z); */ + /*@ assert foo(z==(long)y, y == x); */ +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/comparison.ml frama-c-20111001+nitrogen+dfsg/tests/spec/comparison.ml --- frama-c-20110201+carbon+dfsg/tests/spec/comparison.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/comparison.ml 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,31 @@ +open Cil_types +open Cil + +let run () = + let vis = + object + inherit Visitor.frama_c_inplace + method vterm t = + match t.term_node with + | TBinOp ((Lt | Gt | Le | Ge | Eq | Ne), t1, t2) -> + Kernel.result + "Term comparison between %a of type %a and %a of type %a" + !Ast_printer.d_term t1 !Ast_printer.d_logic_type t1.term_type + !Ast_printer.d_term t2 !Ast_printer.d_logic_type t2.term_type; + DoChildren + | _ -> DoChildren + method vpredicate p = + match p with + | Prel ((Rlt | Rgt | Rle | Rge | Req | Rneq), t1, t2) -> + Kernel.result + "Predicate comparison between %a of type %a and %a of type %a" + !Ast_printer.d_term t1 !Ast_printer.d_logic_type t1.term_type + !Ast_printer.d_term t2 !Ast_printer.d_logic_type t2.term_type; + DoChildren + | _ -> DoChildren + end + in + Visitor.visitFramacFileSameGlobals vis (Ast.get()) +;; + +let () = Db.Main.extend run diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/constant_predicate.i frama-c-20111001+nitrogen+dfsg/tests/spec/constant_predicate.i --- frama-c-20110201+carbon+dfsg/tests/spec/constant_predicate.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/constant_predicate.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,15 @@ +int x; + +/*@ predicate P{A} = x == 42; */ + +/*@ logic integer f{B} = x + 42; */ + +/*@ lemma foo{C}: P ==> f == 84; */ + +/*@ ensures f == 84; */ +void g () { + + x = 42; + /*@ assert P; */ + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/dec.h frama-c-20111001+nitrogen+dfsg/tests/spec/dec.h --- frama-c-20110201+carbon+dfsg/tests/spec/dec.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/dec.h 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef __DEC +#define __DEC + +/*@ axiomatic S { logic integer F(integer x) ; } */ + +//@ logic integer X = 42; + +#endif diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/default_assigns_bts0966.i frama-c-20111001+nitrogen+dfsg/tests/spec/default_assigns_bts0966.i --- frama-c-20110201+carbon+dfsg/tests/spec/default_assigns_bts0966.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/default_assigns_bts0966.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,35 @@ +/* run.config + OPT: -val -print + */ + +int auto_states[4] ; // = { 1 , 0 , 0, 0 }; + +enum states { + Init = 0, + Copy = 1, + Set=2, + Final = 3 +}; + +// contract with missing "complete behaviors" +/*@ + ensures \true; + behavior from_init: + assumes auto_states[Init] == 1; + ensures (auto_states[Copy] == 1) && (auto_states[Init] == 0); + assigns auto_states[Init], auto_states[Copy]; + + behavior from_other: + assumes (auto_states[Init] == 0); + assigns \nothing; + +*/ +void copy(int x); + +int main() { + auto_states[Init] = 1; + auto_states[Copy] = 0; + auto_states[Set] = 0; + auto_states[Final] = 0; + copy(0); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/exit_clause.c frama-c-20111001+nitrogen+dfsg/tests/spec/exit_clause.c --- frama-c-20110201+carbon+dfsg/tests/spec/exit_clause.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/exit_clause.c 2011-10-10 08:38:50.000000000 +0000 @@ -17,3 +17,14 @@ exits \exit_status==x; */ int may_exit(int x) { if (x) exit(0); return 0; } + +// Following spec must be rejected + +//@ exits \result == 0; +int f () { return 0; } + +//@ requires \exit_status == 0; ensures \exit_status == 0; +void g () { + //@ assert \exit_status == 0; + exit(0); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/first.c frama-c-20111001+nitrogen+dfsg/tests/spec/first.c --- frama-c-20110201+carbon+dfsg/tests/spec/first.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/first.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + OPT: -print tests/spec/third.c tests/spec/second.c -journal-disable +*/ +/*@ behavior b: + requires \valid(first); + ensures \result == 0;*/ +int bar(int *first); + +void main (int * c) { + bar(c); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/local.c frama-c-20111001+nitrogen+dfsg/tests/spec/local.c --- frama-c-20110201+carbon+dfsg/tests/spec/local.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/local.c 2011-10-10 08:38:50.000000000 +0000 @@ -14,3 +14,7 @@ P(f(x,y),\result); */ int g(int x, int y) { return (x+y+1); } + +//@ axiomatic a { predicate P(integer v); } +//@ lemma l1: \let p=\lambda integer x; P(x); p(1); +//@ lemma l2: \let p=P(1); p ; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/merge_1.i frama-c-20111001+nitrogen+dfsg/tests/spec/merge_1.i --- frama-c-20110201+carbon+dfsg/tests/spec/merge_1.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/merge_1.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + STDOPT: +"tests/spec/merge_2.i" + */ +/*@ requires \valid(s); + @ assigns \nothing; + @ ensures \result == 0 && \valid(s); + @*/ +extern int slen(const char* s); + +/*@ requires x>=0; */ +extern int f(int x); diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/merge_2.i frama-c-20111001+nitrogen+dfsg/tests/spec/merge_2.i --- frama-c-20110201+carbon+dfsg/tests/spec/merge_2.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/merge_2.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,23 @@ +/* run.config + * DONTRUN: part of merge_1.i + */ +/*@ requires \valid(str2); + @ assigns \nothing; + @ + @*/ +int slen(const char* str2); + +/*@ + @ assigns \nothing; + @ ensures \result == 0 && \valid(str); + @*/ +int slen(const char* str) { + const char *s; + for (s = str; *s; ++s); + return(s - str); +} + +//@ requires y>=0; +int f(int y); + +int f(int z) { return z-1; } diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/merge_bts938_1.c frama-c-20111001+nitrogen+dfsg/tests/spec/merge_bts938_1.c --- frama-c-20110201+carbon+dfsg/tests/spec/merge_bts938_1.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/merge_bts938_1.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,5 @@ +/* run.config + DONTRUN: main test is merge_bts938.c +*/ + +#include "tests/spec/merge_bts938.h" diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/merge_bts938.c frama-c-20111001+nitrogen+dfsg/tests/spec/merge_bts938.c --- frama-c-20110201+carbon+dfsg/tests/spec/merge_bts938.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/merge_bts938.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,5 @@ +/* run.config + STDOPT: +"tests/spec/merge_bts938_1.c" +*/ + +#include "tests/spec/merge_bts938.h" diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/merge_bts938.h frama-c-20111001+nitrogen+dfsg/tests/spec/merge_bts938.h --- frama-c-20110201+carbon+dfsg/tests/spec/merge_bts938.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/merge_bts938.h 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,3 @@ +extern int tab[10]; +//@ ensures tab == {tab \with [0]= (int)0} ; +int main(void) ; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/multi_labels.i frama-c-20111001+nitrogen+dfsg/tests/spec/multi_labels.i --- frama-c-20110201+carbon+dfsg/tests/spec/multi_labels.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/multi_labels.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,6 @@ +int labels (void) { + int x = 0 ; + L1: L2: + //@ assert \at(x,L1) == \at(x,L2) ; + return x ; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/old_prm.i frama-c-20111001+nitrogen+dfsg/tests/spec/old_prm.i --- frama-c-20110201+carbon+dfsg/tests/spec/old_prm.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/old_prm.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,7 @@ +struct st { int t[10]; } S; +int i,j ; + +//@ ensures S.t[i] == s.t[j] + y[x]; +void main (struct st s, int x, int *y) { + S.t[i] = s.t[j] + y[x]; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/pragma.i frama-c-20111001+nitrogen+dfsg/tests/spec/pragma.i --- frama-c-20110201+carbon+dfsg/tests/spec/pragma.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/pragma.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,20 @@ +#typedef int B +#pragma +#pragma A +#pragma A() +#pragma A("A" "A", A, B, 2:4) +#pragma B +#pragma B() +#pragma B("A" "A", A, B, 2:4) + +#pragma 1:3 +#pragma default:1 +#pragma (1 ? A : B) + +#pragma "A" +#pragma 1 +#pragma A 0 +#pragma A B "C" +#pragma B A "C" 4 "E" +#pragma 0 A B "C" D 5 + diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/precedence.i frama-c-20111001+nitrogen+dfsg/tests/spec/precedence.i --- frama-c-20110201+carbon+dfsg/tests/spec/precedence.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/precedence.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,5 @@ +int x[10] ; +//@lemma prio_unary_plus: 3 - +2 +2 == 3; +//@lemma prio_unary_minus: 3 - -2 -2 == 3; +//@lemma prio_unary_amp: (&x[1] - &x[0] & &x[2] - &x[2]) == 0; +//@lemma prio_unary_star: 0 * *&x[2] * *&x[2] == 0; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/pred_def.i frama-c-20111001+nitrogen+dfsg/tests/spec/pred_def.i --- frama-c-20110201+carbon+dfsg/tests/spec/pred_def.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/pred_def.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1 @@ +//@ predicate f(integer x) = x+1; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/predicates.c frama-c-20111001+nitrogen+dfsg/tests/spec/predicates.c --- frama-c-20110201+carbon+dfsg/tests/spec/predicates.c 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/predicates.c 2011-10-10 08:38:50.000000000 +0000 @@ -12,3 +12,5 @@ /*@ predicate S(int *p) = \let z = 0 ; *p == \let x = 0 ; ((\let y = z ; x < y) ? 1 + 2 : (\let y = x ; y)) + 2 ; */ +//@ axiomatic a { predicate P(integer v); } +//@ lemma l: P(1)?P(2):P(3) ; diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/property_test.i frama-c-20111001+nitrogen+dfsg/tests/spec/property_test.i --- frama-c-20110201+carbon+dfsg/tests/spec/property_test.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/property_test.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,14 @@ +/* run.config + OPT: -load-script tests/spec/property_test.ml +*/ + +int X; + +/*@ requires X >= 0; + ensures X >= 0; +*/ +int main (int c) { + if (c) X++; + /*@ assert X >= \at(X,Pre); */ + return X; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/property_test.ml frama-c-20111001+nitrogen+dfsg/tests/spec/property_test.ml --- frama-c-20110201+carbon+dfsg/tests/spec/property_test.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/property_test.ml 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,37 @@ +open Cil +open Cil_types + +class visit prj = + object(self) + inherit Visitor.frama_c_copy prj + method vbehavior b = + let x = Globals.Vars.find_from_astinfo "X" VGlobal in + let x = Cil.cvar_to_lvar x in + let c = + Globals.Vars.find_from_astinfo + "c" (VFormal (Extlib.the self#current_kf)) + in + let c = Cil.cvar_to_lvar c in + b.b_assigns <- + Writes + [ Logic_const.new_identified_term (Logic_const.tvar x), + From [ Logic_const.new_identified_term (Logic_const.tvar x); + Logic_const.new_identified_term (Logic_const.tvar c)] + ]; + DoChildren + end + +let show_properties () = + Format.printf "In project %a:@." Project.pretty (Project.current()); + Property_status.iter + (fun p -> Format.printf "Status of %a: %a@." + Property.pretty p Property_status.pretty (Property_status.get p)) + +let run () = + let prj = + File.create_project_from_visitor "property_test" (fun p -> new visit p) + in + show_properties (); + Project.on prj show_properties () + +let () = Db.Main.extend run diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/returns.i frama-c-20111001+nitrogen+dfsg/tests/spec/returns.i --- frama-c-20110201+carbon+dfsg/tests/spec/returns.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/returns.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,23 @@ +/*@ ensures \result != c; */ +int f (int c) { + + /*@ returns \result == 0; */ + if (c) return 0; + return 42; + +} + +/*@ requires \valid(a); + ensures *a > 0; +*/ +int g(int *a) { + *a++; + /*@ + behavior neg: + assumes *a < 0; + returns \old(*a) == -*a; + */ + if (*a < 0) { *a = -*a; return -1; } + if (*a != 0) { *a++; return 0; } + return 1; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/rewrite_ensures.ml frama-c-20111001+nitrogen+dfsg/tests/spec/rewrite_ensures.ml --- frama-c-20110201+carbon+dfsg/tests/spec/rewrite_ensures.ml 2011-02-07 13:41:42.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/rewrite_ensures.ml 2011-10-10 08:38:50.000000000 +0000 @@ -1,9 +1,10 @@ (* dynamic plug-in to test rewriting of formals in ensures clauses *) -let rewrite _ = +let rewrite () = Ast.compute (); Globals.Functions.iter - (fun kf -> kf.Db_types.spec <- Logic_interp.formals_in_ensures kf) + (fun kf -> + Kernel_function.set_spec kf (fun _ -> Logic_interp.formals_in_ensures kf)) include Plugin.Register (struct @@ -12,6 +13,5 @@ let help = "test purposes only" let module_name = "Rewrite_ensures" end) -;; -Db.Main.extend rewrite;; +let () = Db.Main.extend rewrite diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/second.c frama-c-20111001+nitrogen+dfsg/tests/spec/second.c --- frama-c-20110201+carbon+dfsg/tests/spec/second.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/second.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,13 @@ +/* run.config + DONTRUN: linked with first which is the real test. +*/ + +/*@ behavior b: + requires \valid(second); + ensures \result == 0;*/ +int bar(int *second); + +void sub (char * c) { + bar(c); + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/stmt_contract.i frama-c-20111001+nitrogen+dfsg/tests/spec/stmt_contract.i --- frama-c-20110201+carbon+dfsg/tests/spec/stmt_contract.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/stmt_contract.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,11 @@ +int main(void) { + int x = 5, y = 2; + + /*@ requires x == 5; */ + /*@ requires y == 2; */ + x = x + y; + + /*@ requires x == 7; */ + /*@ ensures x == 7; */ + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/temporal.i frama-c-20111001+nitrogen+dfsg/tests/spec/temporal.i --- frama-c-20110201+carbon+dfsg/tests/spec/temporal.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/temporal.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,468 @@ +/* Generated by Frama-C */ +extern int g_calls ; +int g(int x ) ; +void h(void) ; +extern int random() ; +extern int NB ; +extern int G_i ; +enum aorai_States { + S5 = 4, + S4 = 6, + S3 = 5, + S2 = 3, + S1 = 0, + OK = 2, + S0 = 1 +} ; +//**************** +//* BEGIN Primitives generated for LTL verification +//* +//* States and Trans Variables +int aorai_CurStates[7] = {1, 0, 0, 0, 0, 0, 0}; +int aorai_CurTrans[9] = + {1, 0, 0, 0, 0, 0, 0, 0, 0}; +int aorai_CurStates_old[7] = {0, 1, 0, 0, 0, 0, 0}; +//* +//* +//* Some constants +enum aorai_ListOper { + op_g = 2, + op_f = 1, + op_h = 0 +} ; +enum aorai_ListOper aorai_CurOperation = op_f; +enum aorai_OpStatusList { + aorai_Terminated = 1, + aorai_Called = 0 +} ; +enum aorai_OpStatusList aorai_CurOpStatus = aorai_Called; +//* +//* Loops management +int aorai_Loop_Init_38 = 0; +//* +//**************** +//* Axiomatized transitions automata +/*@ +axiomatic + aorai_Trans_Start { + logic integer aorai_Trans_Start(integer tr) ; + + axiom aorai_Trans_Start0: (aorai_Trans_Start(0) == 1); + + axiom aorai_Trans_Start1: (aorai_Trans_Start(1) == 0); + + axiom aorai_Trans_Start2: (aorai_Trans_Start(2) == 0); + + axiom aorai_Trans_Start3: (aorai_Trans_Start(3) == 3); + + axiom aorai_Trans_Start4: (aorai_Trans_Start(4) == 3); + + axiom aorai_Trans_Start5: (aorai_Trans_Start(5) == 3); + + axiom aorai_Trans_Start6: (aorai_Trans_Start(6) == 5); + + axiom aorai_Trans_Start7: (aorai_Trans_Start(7) == 6); + + axiom aorai_Trans_Start8: (aorai_Trans_Start(8) == 4); + + } + */ +/*@ +axiomatic + aorai_Trans_Stop { + logic integer aorai_Trans_Stop(integer tr) ; + + axiom aorai_Trans_Stop0: (aorai_Trans_Stop(0) == 0); + + axiom aorai_Trans_Stop1: (aorai_Trans_Stop(1) == 2); + + axiom aorai_Trans_Stop2: (aorai_Trans_Stop(2) == 3); + + axiom aorai_Trans_Stop3: (aorai_Trans_Stop(3) == 0); + + axiom aorai_Trans_Stop4: (aorai_Trans_Stop(4) == 4); + + axiom aorai_Trans_Stop5: (aorai_Trans_Stop(5) == 5); + + axiom aorai_Trans_Stop6: (aorai_Trans_Stop(6) == 6); + + axiom aorai_Trans_Stop7: (aorai_Trans_Stop(7) == 4); + + axiom aorai_Trans_Stop8: (aorai_Trans_Stop(8) == 2); + + } + */ +/*@ +predicate aorai_Trans_Cond_param{L}(integer _aorai_numTrans, integer + _aorai_op, integer _aorai_status) = + (((_aorai_numTrans == 0) ==> + ((_aorai_op == op_f) && (_aorai_status == aorai_Called))) + && + (((_aorai_numTrans == 1) ==> + (((_aorai_op == op_f) && (_aorai_status == aorai_Terminated)) && (NB <= 0))) + && + (((_aorai_numTrans == 2) ==> + (((((_aorai_op == op_g) && (_aorai_status == aorai_Called)) && (NB > 0)) && + (g_calls < NB)) + && (0 <= g_calls))) + && + (((_aorai_numTrans == 3) ==> + (((G_i == 0) && (g_calls < NB)) && + ((_aorai_op == op_g) && (_aorai_status == aorai_Terminated)))) + && + (((_aorai_numTrans == 4) ==> + (((G_i == 0) && (g_calls == NB)) && + ((_aorai_op == op_g) && (_aorai_status == aorai_Terminated)))) + && + (((_aorai_numTrans == 5) ==> + ((G_i != 0) && + ((_aorai_op == op_g) && (_aorai_status == aorai_Terminated)))) + && + (((_aorai_numTrans == 6) ==> + ((_aorai_op == op_h) && (_aorai_status == aorai_Called))) + && + (((_aorai_numTrans == 7) ==> + ((_aorai_op == op_h) && (_aorai_status == aorai_Terminated))) + && + ((_aorai_numTrans == 8) ==> + ((_aorai_op == op_f) && (_aorai_status == aorai_Terminated))))))))))); + */ +/*@ +predicate aorai_Trans_Cond{L}(integer _aorai_numTrans) = + aorai_Trans_Cond_param{L}(_aorai_numTrans, aorai_CurOperation, + aorai_CurOpStatus); + +*/ +//* +//**************** +//* Safety invariants +//* +//* Inv 2.1 : Not crossable transitions (cond = false) are not crossed over +/*@ +global +invariant _Buch_not_crossable_cond: + (\forall integer _buch_tr; + ((((0 <= _buch_tr) && (_buch_tr < 9)) && + !(aorai_Trans_Cond(_buch_tr))) + ==> (aorai_CurTrans[_buch_tr] == 0))); + +*/ +//* Inv 2.2 : Not crossable transitions (start state not active) are not crossed over +/*@ +global +invariant _Buch_not_crossable_start: + (\forall integer _buch_tr; + ((((0 <= _buch_tr) && (_buch_tr < 9)) && + (aorai_CurStates_old[aorai_Trans_Start + (_buch_tr)] + == 0)) + ==> (aorai_CurTrans[_buch_tr] == 0))); + */ +//* Inv 4 : Each not reachable state is not reached +/*@ +global +invariant _Buch_not_reachable: + (\forall integer _buch_st; + ((((0 <= _buch_st) && (_buch_st < 7)) && + (\forall integer _buch_tr; + (((0 <= _buch_tr) && (_buch_tr < 9)) ==> + ((aorai_CurTrans[_buch_tr] == 0) || + (aorai_Trans_Stop(_buch_tr) != _buch_st))))) + ==> (aorai_CurStates[_buch_st] == 0))); + +*/ +//* +//* END Primitives generated for LTL verification +//**************** +/*@ requires ((((((((0 == aorai_CurTrans[0]) && (0 == aorai_CurTrans[1])) && + (0 == aorai_CurTrans[3])) + && (0 == aorai_CurTrans[4])) + && (0 == aorai_CurTrans[5])) + && (0 == aorai_CurTrans[6])) + && (0 == aorai_CurTrans[7])) + && (0 == aorai_CurTrans[8])); + requires (0 != aorai_CurTrans[2]); + requires ((((((0 == aorai_CurStates[S1]) && (0 == aorai_CurStates[S0])) && + (0 == aorai_CurStates[OK])) + && (0 == aorai_CurStates[S5])) + && (0 == aorai_CurStates[S3])) + && (0 == aorai_CurStates[S4])); + requires (0 != aorai_CurStates[S2]); + requires ((aorai_CurTrans[2] != 0) ==> + (((NB > 0) && (g_calls < NB)) && (0 <= g_calls))); + behavior Buchi_property_behavior_3: + ensures (((aorai_CurTrans[5] != 0) ==> (G_i != 0)) && + (((aorai_CurTrans[4] != 0) ==> ((G_i == 0) && (g_calls == NB))) + && + ((aorai_CurTrans[3] != 0) ==> ((G_i == 0) && (g_calls < NB))))); + ensures ((((((0 == aorai_CurTrans[0]) && (0 == aorai_CurTrans[1])) && + (0 == aorai_CurTrans[2])) + && (0 == aorai_CurTrans[6])) + && (0 == aorai_CurTrans[7])) + && (0 == aorai_CurTrans[8])); + ensures (((0 != aorai_CurTrans[3]) || (0 != aorai_CurTrans[4])) || + (0 != aorai_CurTrans[5])); + ensures ((((0 == aorai_CurStates[S0]) && (0 == aorai_CurStates[OK])) && + (0 == aorai_CurStates[S2])) + && (0 == aorai_CurStates[S4])); + ensures (((0 != aorai_CurStates[S1]) || (0 != aorai_CurStates[S5])) || + (0 != aorai_CurStates[S3])); + + behavior default: + ensures (g_calls == \old(g_calls)+1); + assigns g_calls; + +*/ +int g(int x ) +{ + int tmp ; + g_calls ++; + tmp = random(); + aorai_CurOperation = op_g; + aorai_CurOpStatus = aorai_Terminated; + aorai_CurStates_old[S5] = 0; + aorai_CurStates_old[S4] = 0; + aorai_CurStates_old[S3] = 0; + aorai_CurStates_old[S2] = aorai_CurStates[3]; + aorai_CurStates_old[S1] = 0; + aorai_CurStates_old[OK] = 0; + aorai_CurStates_old[S0] = 0; + aorai_CurTrans[0] = 0; + aorai_CurTrans[1] = 0; + aorai_CurTrans[2] = 0; + aorai_CurTrans[3] = (G_i == 0 && g_calls < NB) && aorai_CurStates_old[3]; + aorai_CurTrans[4] = (G_i == 0 && g_calls == NB) && aorai_CurStates_old[3]; + aorai_CurTrans[5] = G_i != 0 && aorai_CurStates_old[3]; + aorai_CurTrans[6] = 0; + aorai_CurTrans[7] = 0; + aorai_CurTrans[8] = 0; + aorai_CurStates[S5] = aorai_CurTrans[4]; + aorai_CurStates[S4] = 0; + aorai_CurStates[S3] = aorai_CurTrans[5]; + aorai_CurStates[S2] = 0; + aorai_CurStates[S1] = aorai_CurTrans[3]; + aorai_CurStates[OK] = 0; + aorai_CurStates[S0] = 0; + return (tmp); +} + +/*@ requires ((((((((0 == aorai_CurTrans[0]) && (0 == aorai_CurTrans[1])) && + (0 == aorai_CurTrans[2])) + && (0 == aorai_CurTrans[3])) + && (0 == aorai_CurTrans[4])) + && (0 == aorai_CurTrans[5])) + && (0 == aorai_CurTrans[7])) + && (0 == aorai_CurTrans[8])); + requires (0 != aorai_CurTrans[6]); + requires ((((((0 == aorai_CurStates[S1]) && (0 == aorai_CurStates[S0])) && + (0 == aorai_CurStates[OK])) + && (0 == aorai_CurStates[S2])) + && (0 == aorai_CurStates[S5])) + && (0 == aorai_CurStates[S3])); + requires (0 != aorai_CurStates[S4]); + behavior Buchi_property_behavior_6: + ensures ((((((((0 == aorai_CurTrans[0]) && (0 == aorai_CurTrans[1])) && + (0 == aorai_CurTrans[2])) + && (0 == aorai_CurTrans[3])) + && (0 == aorai_CurTrans[4])) + && (0 == aorai_CurTrans[5])) + && (0 == aorai_CurTrans[6])) + && (0 == aorai_CurTrans[8])); + ensures (0 != aorai_CurTrans[7]); + ensures ((((((0 == aorai_CurStates[S1]) && (0 == aorai_CurStates[S0])) + && (0 == aorai_CurStates[OK])) + && (0 == aorai_CurStates[S2])) + && (0 == aorai_CurStates[S3])) + && (0 == aorai_CurStates[S4])); + ensures (0 != aorai_CurStates[S5]); + + behavior default: + assigns \nothing; + +*/ +void h(void) +{ + aorai_CurOperation = op_h; + aorai_CurOpStatus = aorai_Terminated; + aorai_CurStates_old[S5] = 0; + aorai_CurStates_old[S4] = aorai_CurStates[6]; + aorai_CurStates_old[S3] = 0; + aorai_CurStates_old[S2] = 0; + aorai_CurStates_old[S1] = 0; + aorai_CurStates_old[OK] = 0; + aorai_CurStates_old[S0] = 0; + aorai_CurTrans[0] = 0; + aorai_CurTrans[1] = 0; + aorai_CurTrans[2] = 0; + aorai_CurTrans[3] = 0; + aorai_CurTrans[4] = 0; + aorai_CurTrans[5] = 0; + aorai_CurTrans[6] = 0; + aorai_CurTrans[7] = aorai_CurStates_old[6]; + aorai_CurTrans[8] = 0; + aorai_CurStates[S5] = aorai_CurTrans[7]; + aorai_CurStates[S4] = 0; + aorai_CurStates[S3] = 0; + aorai_CurStates[S2] = 0; + aorai_CurStates[S1] = 0; + aorai_CurStates[OK] = 0; + aorai_CurStates[S0] = 0; + return; +} + +/*@ requires ((((((((0 == aorai_CurTrans[1]) && (0 == aorai_CurTrans[2])) && + (0 == aorai_CurTrans[3])) + && (0 == aorai_CurTrans[4])) + && (0 == aorai_CurTrans[5])) + && (0 == aorai_CurTrans[6])) + && (0 == aorai_CurTrans[7])) + && (0 == aorai_CurTrans[8])); + requires (0 != aorai_CurTrans[0]); + requires ((((((0 == aorai_CurStates[S0]) && (0 == aorai_CurStates[OK])) && + (0 == aorai_CurStates[S2])) + && (0 == aorai_CurStates[S5])) + && (0 == aorai_CurStates[S3])) + && (0 == aorai_CurStates[S4])); + requires (0 != aorai_CurStates[S1]); + behavior Buchi_property_behavior_0: + ensures ((aorai_CurTrans[1] != 0) ==> (NB <= 0)); + ensures (((((((0 == aorai_CurTrans[0]) && (0 == aorai_CurTrans[2])) && + (0 == aorai_CurTrans[3])) + && (0 == aorai_CurTrans[4])) + && (0 == aorai_CurTrans[5])) + && (0 == aorai_CurTrans[6])) + && (0 == aorai_CurTrans[7])); + ensures ((0 != aorai_CurTrans[1]) || (0 != aorai_CurTrans[8])); + ensures ((((((0 == aorai_CurStates[S1]) && (0 == aorai_CurStates[S0])) + && (0 == aorai_CurStates[S2])) + && (0 == aorai_CurStates[S5])) + && (0 == aorai_CurStates[S3])) + && (0 == aorai_CurStates[S4])); + ensures (0 != aorai_CurStates[OK]); + + +*/ +void f(int N ) +{ + int i ; + int t ; + i = 0; + t = 0; + { /*undefined sequence*/ G_i = 0; g_calls = G_i; } + NB = N; + aorai_Loop_Init_38 = 1; + /*@ loop invariant + ((((0 != aorai_CurStates[S1]) || (0 != aorai_CurStates[S5])) || + (0 != aorai_CurStates[S3])) + && + (((((0 == aorai_CurStates[S0]) && (0 == aorai_CurStates[OK])) && + (0 == aorai_CurStates[S2])) + && (0 == aorai_CurStates[S4])) + && + (((((0 != aorai_CurTrans[0]) || (0 != aorai_CurTrans[3])) || + (0 != aorai_CurTrans[4])) + || (0 != aorai_CurTrans[5])) + && + (((((0 == aorai_CurTrans[1]) && (0 == aorai_CurTrans[2])) && + (0 == aorai_CurTrans[6])) + && (0 == aorai_CurTrans[7])) + && (0 == aorai_CurTrans[8]))))); + loop invariant + ((aorai_Loop_Init_38 != 0) ==> + ((aorai_CurStates[4] == 0) && + ((aorai_CurStates[5] == 0) && + ((aorai_CurTrans[3] == 0) && + ((aorai_CurTrans[4] == 0) && (aorai_CurTrans[5] == 0)))))); + loop invariant ((aorai_Loop_Init_38 == 0) ==> (aorai_CurTrans[0] == 0)); + */ + while (1) { + if (i < N) { if (! (! t)) { goto while_0_break; } } + else { goto while_0_break; } + aorai_Loop_Init_38 = 0; + aorai_CurOperation = op_g; + aorai_CurOpStatus = aorai_Called; + aorai_CurStates_old[S5] = 0; + aorai_CurStates_old[S4] = 0; + aorai_CurStates_old[S3] = 0; + aorai_CurStates_old[S2] = 0; + aorai_CurStates_old[S1] = aorai_CurStates[0]; + aorai_CurStates_old[OK] = 0; + aorai_CurStates_old[S0] = 0; + aorai_CurTrans[0] = 0; + aorai_CurTrans[1] = 0; + aorai_CurTrans[2] = ((NB > 0 && g_calls < NB) && 0 <= g_calls) && aorai_CurStates_old[0]; + aorai_CurTrans[3] = 0; + aorai_CurTrans[4] = 0; + aorai_CurTrans[5] = 0; + aorai_CurTrans[6] = 0; + aorai_CurTrans[7] = 0; + aorai_CurTrans[8] = 0; + aorai_CurStates[S5] = 0; + aorai_CurStates[S4] = 0; + aorai_CurStates[S3] = 0; + aorai_CurStates[S2] = aorai_CurTrans[2]; + aorai_CurStates[S1] = 0; + aorai_CurStates[OK] = 0; + aorai_CurStates[S0] = 0; + t = g(i); + G_i = t; + i ++; + g_calls = i; + } + while_0_break: /* internal */ ; + if (t) { + aorai_CurOperation = op_h; + aorai_CurOpStatus = aorai_Called; + aorai_CurStates_old[S5] = 0; + aorai_CurStates_old[S4] = 0; + aorai_CurStates_old[S3] = aorai_CurStates[5]; + aorai_CurStates_old[S2] = 0; + aorai_CurStates_old[S1] = 0; + aorai_CurStates_old[OK] = 0; + aorai_CurStates_old[S0] = 0; + aorai_CurTrans[0] = 0; + aorai_CurTrans[1] = 0; + aorai_CurTrans[2] = 0; + aorai_CurTrans[3] = 0; + aorai_CurTrans[4] = 0; + aorai_CurTrans[5] = 0; + aorai_CurTrans[6] = aorai_CurStates_old[5]; + aorai_CurTrans[7] = 0; + aorai_CurTrans[8] = 0; + aorai_CurStates[S5] = 0; + aorai_CurStates[S4] = aorai_CurTrans[6]; + aorai_CurStates[S3] = 0; + aorai_CurStates[S2] = 0; + aorai_CurStates[S1] = 0; + aorai_CurStates[OK] = 0; + aorai_CurStates[S0] = 0; + h(); + } + aorai_CurOperation = op_f; + aorai_CurOpStatus = aorai_Terminated; + aorai_CurStates_old[S5] = aorai_CurStates[4]; + aorai_CurStates_old[S4] = 0; + aorai_CurStates_old[S3] = 0; + aorai_CurStates_old[S2] = 0; + aorai_CurStates_old[S1] = aorai_CurStates[0]; + aorai_CurStates_old[OK] = 0; + aorai_CurStates_old[S0] = 0; + aorai_CurTrans[0] = 0; + aorai_CurTrans[1] = NB <= 0 && aorai_CurStates_old[0]; + aorai_CurTrans[2] = 0; + aorai_CurTrans[3] = 0; + aorai_CurTrans[4] = 0; + aorai_CurTrans[5] = 0; + aorai_CurTrans[6] = 0; + aorai_CurTrans[7] = 0; + aorai_CurTrans[8] = aorai_CurStates_old[4]; + aorai_CurStates[S5] = 0; + aorai_CurStates[S4] = 0; + aorai_CurStates[S3] = 0; + aorai_CurStates[S2] = 0; + aorai_CurStates[S1] = 0; + aorai_CurStates[OK] = aorai_CurTrans[8] || aorai_CurTrans[1]; + aorai_CurStates[S0] = 0; + return; +} + diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/third.c frama-c-20111001+nitrogen+dfsg/tests/spec/third.c --- frama-c-20110201+carbon+dfsg/tests/spec/third.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/third.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + DONTRUN: linked with first which is the real test. +*/ +/*@ behavior b: + requires \valid(third); + ensures \result == 0;*/ +int bar(int *third) { + third=(int*)*third; + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/type_of_term.i frama-c-20111001+nitrogen+dfsg/tests/spec/type_of_term.i --- frama-c-20110201+carbon+dfsg/tests/spec/type_of_term.i 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/type_of_term.i 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,16 @@ +/* run.config + OPT: -load-script tests/spec/type_of_term.ml -print +*/ + +int t [42]; + +struct S { int x; int y[]; } s; + +/*@ assigns *(p+(..)), t[..], s[..].x, s[..].y[..]; +*/ +void f(int *p, struct S* s); + +int main() { + f(t,&s); + return 0; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/type_of_term.ml frama-c-20111001+nitrogen+dfsg/tests/spec/type_of_term.ml --- frama-c-20110201+carbon+dfsg/tests/spec/type_of_term.ml 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/type_of_term.ml 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,36 @@ +open Cil_types + +include Plugin.Register + (struct + let name = "type_of_term" + let shortname = "type_of_term" + let help = "checks typeOfTermLval over sets" + end) + +class visitor = + object + inherit Visitor.frama_c_inplace + method vterm t = + result "Term: %a, type is %a" + !Ast_printer.d_term t !Ast_printer.d_logic_type t.Cil_types.term_type; + Cil.DoChildren + method vterm_lval (host,off as lv) = + let ty = Cil.typeOfTermLval lv in + let plain_lval = (host,TNoOffset) in + let tyh = Cil.typeOfTermLval plain_lval in + let tyoff = Cil.typeTermOffset tyh off in + result "Host: %a, type is %a" + !Ast_printer.d_term_lval plain_lval !Ast_printer.d_logic_type tyh; + result "Offset: %a, type is %a" + !Ast_printer.d_term_offset off !Ast_printer.d_logic_type tyoff; + result "Lval: %a, type is %a" + !Ast_printer.d_term_lval lv !Ast_printer.d_logic_type ty; + Cil.DoChildren + end + +let run () = + let ast = Ast.get () in + Visitor.visitFramacFileSameGlobals (new visitor) ast +;; + +Db.Main.extend run diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/use2.c frama-c-20111001+nitrogen+dfsg/tests/spec/use2.c --- frama-c-20110201+carbon+dfsg/tests/spec/use2.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/use2.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,8 @@ +/* run.config + DONTRUN: main test is in use.c +*/ + +#include "tests/spec/dec.h" + +//@ ensures X > 0 ; ensures F(1)>0 ; +void g(void) {} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/use.c frama-c-20111001+nitrogen+dfsg/tests/spec/use.c --- frama-c-20110201+carbon+dfsg/tests/spec/use.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/use.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,10 @@ +/* run.config + STDOPT: +"tests/spec/use2.c" +*/ + +// BTS 0887 + +#include "tests/spec/dec.h" + +//@ ensures X > 0 ; ensures F(1) > 0 ; +void f(void) {} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/va.c frama-c-20111001+nitrogen+dfsg/tests/spec/va.c --- frama-c-20110201+carbon+dfsg/tests/spec/va.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/va.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,8 @@ +#include "../../share/libc/stdio.h" + +void main(int x, ...) { + int x,y; + va_list p; + va_start(p,x); + vscanf("FOO %d %d",p); +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/volatile_aux.c frama-c-20111001+nitrogen+dfsg/tests/spec/volatile_aux.c --- frama-c-20110201+carbon+dfsg/tests/spec/volatile_aux.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/volatile_aux.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,11 @@ +/* run.config + DONTRUN: main test file is volatile.c +*/ + +#include "tests/spec/volatile.h" + +int f (int x) { + x++; + v = x; + return v+x; +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/volatile.c frama-c-20111001+nitrogen+dfsg/tests/spec/volatile.c --- frama-c-20110201+carbon+dfsg/tests/spec/volatile.c 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/volatile.c 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,20 @@ +/* run.config + OPT: tests/spec/volatile_aux.c -print -check -copy +*/ + +#include "tests/spec/volatile.h" +const int c = 1 ; +volatile int v ; +int * p; +//@lemma comp_const_addr: p==&c; +//@lemma comp_volatile_addr: p==&v; +//@lemma volatile_in_annot_is_illegal: v == 1 ==> v==1; + +int main () { + + int x = v; + v = f(x); + + return 0; + +} diff -Nru frama-c-20110201+carbon+dfsg/tests/spec/volatile.h frama-c-20111001+nitrogen+dfsg/tests/spec/volatile.h --- frama-c-20110201+carbon+dfsg/tests/spec/volatile.h 1970-01-01 00:00:00.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/spec/volatile.h 2011-10-10 08:38:50.000000000 +0000 @@ -0,0 +1,22 @@ +typedef volatile int VINT; + +extern int f(int); + +inline int r(VINT* v) { return *v; } + +inline int w(volatile int* v, int new) { *v = new; return new; } + +volatile int v, tab[10]; +VINT *pt; + +struct st { int a ; volatile int v ; } s ; +//@ volatile v, tab[..] reads r writes w; +//@ volatile *pt writes w; +//@ volatile s.v reads r; + +typedef struct st ST ; +struct vst { int b ; ST v ; } vs ; +// some parts of vs have volatile qualifier +struct vst rs (struct vst * p) ; +struct vst ws (struct vst * p, struct vst v) ; +//@volatile vs reads rs writes ws ; diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/access.c frama-c-20111001+nitrogen+dfsg/tests/wp/access.c --- frama-c-20110201+carbon+dfsg/tests/wp/access.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/access.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Out of Scope - */ - - - - -struct Tb { int b ; } ; -struct Ta { - struct Tb *a ; -} x ; - - -/*@ requires \valid((x.a+i)) ; - ensures x.a[i].b == v; - ensures (*((x.a)+i)).b == x.a[i].b ; */ -int main (int i, int v) { - (*((x.a)+i)).b = v+1 ; - x.a[i].b = v; - return 1; -} - - - -int *p; -/*@ ensures *p == 0; -*/ -void main2 () { - int tmp; - *p = 0; - tmp=1; -} - -int j; -//@ ensures *\result == 4; -int * result_offset_val (void) -{ - int *p; - p = &j; - j=4; - return p; -} - - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/AddressTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/AddressTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/AddressTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/AddressTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - kind : Positive - model name : Store; bhv : Provable - model name : Hoare; bhv : Out of Scope -*/ - -int * t[2]; - -//@ ensures *(t[0])== 4; -int main() -{ - - int i=4; - int j=3; - int * p; - int * q; - - p = &i ; - q = &j; - t[0]= p; - t[1]= q; - return 0; - -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/addrof.c frama-c-20111001+nitrogen+dfsg/tests/wp/addrof.c --- frama-c-20110201+carbon+dfsg/tests/wp/addrof.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/addrof.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Proved with alt_ergo - model name : Hoare ; bhv : Out of Scope - */ -int A; - -/*@ ensures A == 5 ; */ -int main() { - int *p = &A; - *p = 5; - return *p; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/adjacent_find.c frama-c-20111001+nitrogen+dfsg/tests/wp/adjacent_find.c --- frama-c-20110201+carbon+dfsg/tests/wp/adjacent_find.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/adjacent_find.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Out of Scope - */ - - -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ - -/*@ - predicate - adjacent_found{Label}(int* a, int n) = - \exists int i; 0 <= i < n-1 && a[i] == a[i+1]; -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - behavior some: - assumes adjacent_found(a, n); - ensures 0 <= \result < n-1; - ensures a[\result] == a[\result+1]; - ensures !adjacent_found(a, \result); - - behavior none: - assumes !adjacent_found(a, n); - ensures \result == n; - - complete behaviors some, none; - disjoint behaviors some, none; -*/ -int adjacent_find(int* a, int n) -{ - if (0 == n) return n; - - /*@ - loop assigns i; - loop invariant 0 <= i < n; - loop invariant !adjacent_found(a, i); - loop invariant 0 < i ==> a[i-1] != a[i]; - loop variant n-i; - */ - for (int i = 0; i < n-1; i++) - if (a[i] == a[i+1]) - return i; - - return n; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/ArrayTest.c frama-c-20111001+nitrogen+dfsg/tests/wp/ArrayTest.c --- frama-c-20110201+carbon+dfsg/tests/wp/ArrayTest.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/ArrayTest.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Out of Scope - */ - -int x[2][3][5] = - { - {{ 111,112,113,114,115 }, - { 121,122,123,124,125 }, - { 131,132,133,134,135 }} , - {{ 211,212,213,214,215 }, - { 221,222,223,224,225 }, - { 231,232,233,234,235 }} - }; - -int *p1; -int *p2; -int *p3; - -int x1; -int x2; -int x3; - -/*@ - ensures x1 == 211 ; - ensures x2 == 212 ; - ensures x3 == 123 ; -*/ -void main () { - - p1 = (int *)(x+1); - x1 = (*p1); - - p2 = p1+1; - x2 = *p2; - - p3 = x[0][1]+2; - x3 = *p3; - -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/AssignsLoop.c frama-c-20111001+nitrogen+dfsg/tests/wp/AssignsLoop.c --- frama-c-20110201+carbon+dfsg/tests/wp/AssignsLoop.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/AssignsLoop.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Not Sure About - model name : Hoare ; bhv : Not Sure About - */ - -int r; - -//@ requires i==1; ensures r==3; -void no_loop_assigns (int i) -{ - while(i!=4) {r=i ; i++;} -} - -//@ requires i==1; ensures r==3; -void loop_with_assigns (int i) -{ - //@ loop assigns r,i; - while(i!=4) {r=i ; i++;} -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/assigns_meth.c frama-c-20111001+nitrogen+dfsg/tests/wp/assigns_meth.c --- frama-c-20110201+carbon+dfsg/tests/wp/assigns_meth.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/assigns_meth.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -/* - run.config - OPT: -wp-proof none -wp-print -wp-prop assigns -wp-assigns memory - OPT: -wp-proof none -wp-print -wp-prop assigns -wp-assigns effect -*/ - - - -//@ predicate P (integer i) = i >= 0; - -int t [4]; -int a,b ; - -/*@ - requires P(a); - assigns a , b, t[0..2] ; - ensures P(b); - */ -void f (void){ - - a =0 ; b =0 ; - t[0] = 0 ; - t[1] = 0; - t[2] = 2; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/AssignsTestPos1.c frama-c-20111001+nitrogen+dfsg/tests/wp/AssignsTestPos1.c --- frama-c-20110201+carbon+dfsg/tests/wp/AssignsTestPos1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/AssignsTestPos1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Proved with alt_ergo - model name : Hoare ; bhv : Proved with all - */ - -//@ assigns \nothing; -int assigns_nothing(void) -{ return 5; -} - -int r,g; - -// two tset -//@ assigns r,g ; -void assigns_two_loc(void) -{ r=5; g=8;} - -//@ assigns \union(r,g) ; -void assigns_union_of_two_loc(void) -{ r=1; g=2;} - -//@ assigns r; -void assigns_no_cst(void) -{ r=g;} - - -/*@ - behavior NULL : assumes i==0; assigns r; - behavior OTHER : assumes i!=0;assigns \nothing; - */ -void assigns_cond(int i) -{ - if (i==0) r=12 ; -} - -//@ requires i>0; ensures i>0; -void no_assigns (int i) -{ - if (i==0) r=12 ; -} - -int main (void) {return 0;} - - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/assigns_tests.c frama-c-20111001+nitrogen+dfsg/tests/wp/assigns_tests.c --- frama-c-20110201+carbon+dfsg/tests/wp/assigns_tests.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/assigns_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Out of Scope - */ -/*@ ensures *x == 3; - assigns *x; - */ -void ptr_deref_assigns (int * x) { - *x = 3; -} - - -int * p; -int a; - -//@ assigns p, *p , a ; -/* CORRECT */ -void ptr_deref_ptr_assigns_1 (void) -{ - p = &a; - *p = 5; -} - -//@ assigns p,*p; -/* CORRECT, because ensures p == &a */ -void ptr_deref_ptr_assigns_2 (void) -{ - p = &a; - *p = 5; -} - -//@ assigns p; -/* INCORRECT, because missing a */ -void ptr_deref_ptr_assigns_3 (void) -{ - p = &a; - *p = 5; -} - -//@ assigns p , *\old(p); -/* CORRECT */ -void deref_ptr_ptr_assigns_1 (void) -{ - *p=5; - p=&a; -} - -//@ assigns p , *p; -/* INCORRECT sauf si \old(p==&a) */ -void deref_ptr_ptr_assigns_2 (void) -{ - *p=5; - p=&a; -} - - -int main () { return 0;} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/axioms.c frama-c-20111001+nitrogen+dfsg/tests/wp/axioms.c --- frama-c-20110201+carbon+dfsg/tests/wp/axioms.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/axioms.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -/* run.config - OPT: -wp -wp-assigns effect -wp-axioms -wp-print -*/ -/* run.config_why - OPT: -wp -wp-assigns effect -wp-axioms -wp-timeout 5 -wp-proof alt-ergo -wp-par 1 - -*/ - -// Test for the instanciation of axioms with labels. -// The axiomatic A is equivalent (in spirit) to the definition of predicate Q. -// Both should be provable with alt-ergo immediately, under the hypothesis of the loop-assign. -// This last property can be discharged in Coq with the provided proof. - - -/*@ axiomatic A { - @ predicate P{L}(int *t,int a,int b) reads *t ; - @ axiom D{L}: - @ \forall int * t ; \forall int a,b ; - @ (\forall int k ; a<=k<=b ==> \valid(t+k) ==> t[k] > 0) ==> P(t,a,b) ; - @ } - @ */ - -/*@ predicate Q(int *t,int a,int b) = - @ \forall int k ; a<=k<=b ==> \valid(t+k) ==> t[k] > 0 ; - @ */ - - -/*@ requires \valid(t+(a..b)) ; - @ ensures P : P(t,a,b) ; - @ ensures Q : Q(t,a,b) ; - @ assigns t[a..b] ; - @ */ - -void f(int *t , int a, int b) -{ - - /*@ loop invariant Index: a<=i<=b+1 ; - @ loop invariant Positive: \forall int k ; a<=k<i ==> t[k] > 0 ; - @ loop assigns i,t[a..i-1] ; - @ */ - for(int i=a; i<=b; i++) t[i] = 1 ; - -} - -/* -------------------------------------------------------------------------- */ -/* --- Coq Proof for loop assigns --- */ -/* -------------------------------------------------------------------------- */ - -/* -Proof. -intros. unfold ze1. apply inc_union_left. -rewrite right_empty. unfold ze0. unfold ze. -repeat ( try rewrite union_assoc ; try rewrite right_empty ; try rewrite left_empty ). -apply inc_union_union. - apply inc_same. - apply inc_union_left. unfold address_zone. unfold address_range. - repeat (try rewrite addr_base ; try repeat rewrite addr_offset ; repeat rewrite addr_sizeof ). - rewrite inc_range_range. intros. split. auto. split. omega. unfold i. omega. - unfold address_zone. unfold address_range. - repeat (try rewrite addr_base ; try repeat rewrite addr_offset ; try rewrite addr_sizeof). - rewrite inc_range_range. intros. split. - unfold address_shift. rewrite addr_base. auto. split. unfold address_shift. - rewrite addr_offset. omega. unfold address_shift. rewrite addr_offset. unfold i. omega. - rewrite right_empty. apply inc_union_right. left. apply inc_same. -Save. -*/ - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bhv_for_code_annot.c frama-c-20111001+nitrogen+dfsg/tests/wp/bhv_for_code_annot.c --- frama-c-20110201+carbon+dfsg/tests/wp/bhv_for_code_annot.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bhv_for_code_annot.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -int Tab[10]; -/*@ requires n < 10 ; - behavior foo: - assumes reset; - assigns Tab[0..n-1]; - behavior bar: - assumes !reset; - assigns \nothing; -*/ -int h(int reset, int n) { - int i, r = 0 ; - /*@ - for foo: - loop assigns Tab[0..i]; - for bar: - loop assigns \nothing; - */ - for (i = 0 ; i < n ; i++) { - r += Tab[i] ; - if (reset) - Tab[i] = 0 ; - } - return r ; -} - -// Notice that even if g() assigns nothing, it still return an unknown result. -/*@ - assigns \nothing; -*/ -int g(); - -/*@ assigns \nothing ; - ensures (reset?\result == 3 : \result == 2); - behavior foo: - assumes reset; ensures \result==3; - behavior bar: - assumes !reset; ensures \result == 2; -*/ -int f (int reset) -{ - int r=2; - if(reset){ - r= g(); - //@ assert r == 3; - } - return r; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bidim_array.c frama-c-20111001+nitrogen+dfsg/tests/wp/bidim_array.c --- frama-c-20110201+carbon+dfsg/tests/wp/bidim_array.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bidim_array.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Out of Scope - */ - -int a[5][10] = {0, }; - -/*@ assigns a[..][..]; - ensures a[1][3] == 42; - */ -void f(void) -{ - a[1][3] = 42; -} - -int x[3][3] = { {1, 2, 3} , {4, 5, 6} , {7, 8, 9} }; - -//@ requires x[0][1] == 2; ensures \result == 2; -int f0 (void) { - int * p = &(x[0][0]); - p++; - return *p; -} - -//@ requires x[1][0] == 4; ensures \result == 4; -int f1 (void) { - int (*pt)[3] = x; - pt++; - return (*pt)[0]; -} -//@ requires x[1][1] == 5; ensures \result == 5; -int f2 (void) { - int (*pt)[3] = x + 1; - int * p = (*pt) + 1; - return *p; -} - -//@ requires x[0][1] == 2; ensures \result == 2; -int read_tab (void) { - return x[0][1]; -} - -int main (void){return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bresenham.c frama-c-20111001+nitrogen+dfsg/tests/wp/bresenham.c --- frama-c-20110201+carbon+dfsg/tests/wp/bresenham.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bresenham.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/**************************************************************************/ -/* */ -/* Proof of the Bresenham line drawing algorithm. */ -/* (see examples/bresenham/ for the Why proof) */ -/* */ -/* Jean-Christophe Filliâtre (LRI, Université Paris Sud) */ -/* June 2008 */ -/* */ -/**************************************************************************/ - -int x2, y2; - -/*@ axiomatic Abs { - @ logic integer abs(integer x); - @ axiom abs_def: - @ \forall integer x; - @ (x >= 0 && abs(x) == x) || (x <= 0 && abs(x) == -x); - @ } - @*/ - -/*@ predicate best(integer x2,integer y2,integer x, integer y) = - @ \forall integer yp; abs(x2 * y - x * y2) <= abs (x2 * yp - x * y2) - @ ; */ - -/*@ predicate Invariant(integer x2,integer y2,integer x, integer y, integer e) = - @ e == 2 * (x + 1) * y2 - (2 * y + 1) * x2 && - @ 2 * (y2 - x2) <= e <= 2 * y2 - @ ; */ - -/*@ lemma invariant_is_ok : - @ \forall integer x2,y2,x, y, e; Invariant(x2,y2,x,y,e) ==> best(x2,y2,x,y); - @*/ - -//@ lemma z_ring_0 : \forall integer a, b, c; a * (b+c) == a*b + a*c; -//@ lemma z_ring_1 : \forall integer a, b, c; (b+c) * a == b*a + c*a; - -//@requires 0 <= y2 <= x2; -void bresenham() { - int x = 0; - int y = 0; - int e = 2 * y2 - x2; - /*@ loop invariant INV: 0 <= x <= x2 + 1 && Invariant(x2,y2,x,y,e); - @*/ - for (x = 0; x <= x2; x++) { - // plot (x,y) at this point - //@ assert BEST: best(x2,y2,x,y); - if (e < 0) - e += 2 * y2; - else { - y++; - e += 2 * (y2 - x2); - } - } -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0055.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0055.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0055.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0055.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -int T[10]; - -// acces to *(\result) -/*@ requires 0 <= x < 10; - ensures *\result == x && \base_addr (\result) == \base_addr(T); - assigns T[x]; -*/ -int * ret_ptr (int x) { - T[x] = x; - return T+x; -} - -//@ ensures \result == 0; -int call_ret_ptr (void) { - int * p = ret_ptr (0); - return *p; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0056.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0056.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0056.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0056.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -int T[10]; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// loop assigns not translatable to C lval - -/*@ assigns T[0..4]; - ensures T[5] == \old(T[5]); -*/ -void assign_T (void) { - int i; - /*@ loop assigns i, T[0..4]; - @ loop invariant 0 <= i; - */ - for (i = 0; i < 5; i++) { - T[i] ++; - } -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -struct Ts { int a; int t[10]; }; -struct Ts S; - -//@ ensures (T[5] == \old(T[5])) && (S.a == \old(S.a)); -void assign_S (void) { - int i; - //@ loop assigns i, S; - for (i = 0; i < 5; i++) { - S.t[i] = T[i]; - } -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0057.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0057.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0057.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0057.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ - -// generated assigns contains not handled \at(\result, Post) -int g (int); - -int f (int x) { - return g (x); -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0058.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0058.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0058.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0058.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -int T[10]; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// loop assigns can specify a loop invariant - -//@ ensures T[5] == \old(T[5]); -void assign_T (void) { - int i; - /*@ loop assigns i, T[0..i-1]; - @ loop invariant 0 <= i <= 5; - */ - for (i = 0; i < 5; i++) { - T[i] ++; - } - //@ assert i==5; -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -void assign_to_inv (void) { - int i; - /*@ loop invariant 0 <= i; - @ loop invariant \forall int j; j > i-1 ==> T[j] == \at(T[j], Pre); - @ loop assigns i, T[0..4]; - */ - for (i = 0; i < 5; i++) { - T[i] ++; - } -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0085.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0085.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0085.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0085.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-proof z3 -wp-print -wp-verbose 2 - OPT: -wp -wp-model Runtime -wp-logicvar -journal-disable -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -int * P; -int X; - -/*@ requires \valid (P); - ensures \result == 0; - */ -// how can we say that if \valid (P), P cannot point on local variable x... -int ptr_glob_on_loc (void) { - int x = 0; - *P = 3; - return x; -} - -/*@ behavior ok: - assumes \valid (P); - ensures \old(*P) == *P; - @ behavior logicvar: - // LC: with -wp-logicvar, we have the implicit property that - // local variables never escape the call-frame ; hence we - // have separated(&x,p). See ptr_param_vs_glob function below. - // Hence, the goal should be proved with -wp-logicvar - ensures \old(*P) == *P; - */ -int ptr_glob_on_loc_2 (void) { - int x = 0; - return x; -} - -/*@ requires \valid (p); - @ ensures \result == 0; - */ -int ptr_param_on_loc (int * p) { - int x = 0; - *p = 3; - return x; -} - -/*@ behavior ok: - assumes \valid (p); - ensures \old(*p) == *p; - @ behavior logicvar: - // LC: with -wp-logicvar, we have the implicit property that - // local variables never escape the call-frame ; hence we - // have separated(&x,p). See ptr_param_vs_glob function below. - // Hence, the goal should be proved with -wp-logicvar - ensures \old(*p) == *p; - */ -int ptr_param_on_loc_2 (int * p) { - int x = 0; - return x; -} - -/*@ requires \valid (P); - @ ensures \result == 0; - */ -int ptr_glob_on_param (int x) { - x = 0; - *P = 3; - return x; -} - -/*@ requires \valid (p); - @ ensures \result == 0; - */ -int ptr_param_on_param (int * p, int x) { - x = 0; - *p = 3; - return x; -} - -/*@ ensures \result == 3; - */ -int addr_loc_vs_addr_loc (void) { - int x, y; - x = 0; - y = 3; - return x + y; -} - -/*@ ensures \result == 3; - */ -int addr_loc_vs_addr_param (int x) { - int y; - x = 0; - y = 3; - return x + y; -} - -/*@ ensures \result == 3; - */ -int addr_loc_vs_addr_glob (void) { - int y; - X = 0; - y = 3; - return X + y; -} - -/*@ ensures \result == 3; - */ -int addr_param_vs_addr_glob (int x) { - x = 0; - X = 3; - return x + X; -} - -//@ ensures ! \valid(P); -void invalid_local_addr (void) { - int x; - P = &x; -} - -//@ ensures ! \valid(P); -void invalid_param_addr (int x) { - P = &x; -} - -/*@ requires \valid (P); */ -void disj_glob_addr_param (int x) { - //@ assert (P != &x); -} - -/*@ ensures ok: \separated (p, &X) ==> X == \old(X); - ensures ko: X == \old(X); -*/ -int ptr_param_vs_glob (int * p) { - *p = 0; - return *p; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0093.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0093.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0093.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0093.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/*@ ensures *x == 3; - assigns *x; - */ -void f (int * x) { - *x = 3; -} - -//@ ensures \result == 3; -int g_loc (void) { - int x; - f (&x); - return x; -} -//@ ensures \result == 3; -int g_param (int x) { - f (&x); - return x; -} - -// don't define 'x' as a global variable because CIL then renames other 'x' -// and it hides the problem. -int y; - -//@ ensures *y == 3; -void fy (int * y) { - *y = 3; -} - -//@ ensures y == 3; -void g_glob (void) { - f (&y); -} -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0269.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0269.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0269.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0269.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* --- NON CONCLUSIVE TEST --- */ -/* -------------------------------------------------------------------------- */ -// WP aborts because logic variable S0 appears to be typed 'void' by CIL -// BTS #428 -/* -------------------------------------------------------------------------- */ - -typedef struct _S S; -/*@ axiomatic A { -logic S S0; -logic S S1(integer e); -logic S S2(S seq, integer e); - -axiom A1: \forall integer e; S1(e)!=S0; -axiom A2: \forall integer e1,e2; S1(e1)==S1(e2) <==> e1==e2; -axiom A3: \forall integer e; S1(e)==S2(S0,e); -axiom A4: \forall integer e1,e2, S s1,s2; S2(s1,e1)==S2(s2,e2) <==> (s1==s2&&e1==e2); -} */ - -S s; - -//@ ensures s==S2(\old(s),e); -extern void g(const int e); - -/*@ requires s==S0; - @ ensures s==S1(1); - @*/ -void f1(void) { - g(1); -} -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0281.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0281.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0281.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0281.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -/* run.config_pruntime -OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-verbose 2 -wp-proof z3 - - */ - -typedef int TAB32[32]; -TAB32 tab[32]; -int * p = &tab[0][0]; - -/*@ requires p == &tab[0][0] ; - ensures \true ; -*/ -int main() { - return 1 ; -} - -//@ ensures \result == 1; -int f (void) { - int x = 1; - // check if M2 detects that it doesn't know how to do this : - *((int *)(0x1234)) = 3; - return x; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0286.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0286.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0286.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0286.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -int cpt0 ; - -/*@ -requires cpt0==0; -ensures \false ; -*/ -void exit (int status); - -int cpt1 ; -extern int tab1[] ; - -/*@ -requires cpt1==0; -assigns tab1[..] ; -*/ -void f1 (int arg); - -/*@ -requires cpt0==0; -requires cpt1==0; -ensures \false ; -*/ -void g (int x) { - f1(4); - exit(1); -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0287.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0287.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0287.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0287.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ - -int s ; -//@ assigns s; -void g(int x); -//@ assigns s ; //<- doit être prouvable -void f(void) { - g(1); -} -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0288.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0288.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0288.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0288.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -int cpt, loc, *p ; -/*@ assigns p[..], cpt ; - ensures \forall int * q ; q != &cpt ==> *q == \old(*q); - ensures \forall int * q ; q == &loc ==> *q == \old(*q); -*/ -void f1(int x) { - p[1] = x ; - cpt = 1; -} -/* -Proof. -intros. -subst mem_379. -subst q_370. -rewrite acc_upd_disj; - [ | apply disj_base; rewrite base_id_cpt; rewrite base_id_loc; auto with zarith]. -subst mem_383. - -rename mem_386 into m. -rename addr_x_381 into ad_x. - -1 subgoal -m : memory -ad_x : pointer Z -H : int_base_addr ad_x = 368 -______________________________________(1/1) -acc (upd m (shift_pointer (acc m addr_p_382) 1) (acc m ad_x)) addr_loc_374 = -acc m addr_loc_374 -*/ - -/*~~~ autres essais ~~~*/ - -/* This property is nor true because we don't know if (&loc # p) */ -/*@ ensures \forall int * q ; q == &loc ==> *q == \old(*q); -*/ -void f2 (void) { - p[1] = 0; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0295.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0295.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0295.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0295.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ - -int i=0; - -/*@ requires i==0; - */ -int f(void); - -int main() -{ - //@ assert i==0; - return f(); -} - -int X = 3; -int Y = X+1; - -//@ ensures \result == 4; -int other_main (void) { - return Y; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0350.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0350.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0350.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0350.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -struct Ts {int x; int y; }; -struct Tstr {int a; struct Ts s; int t[10]; struct Tstr * p; } S; - -/*@ requires S.p == &S || \separated (S.p, &S); - @ ensures S.p->a == x ; - @ ensures \forall int i; (*(S.p)).t[i] == \old((*(S.p)).t[i]); - */ - -void rw_ptr_field(int x ) -{ - (S.p)->a = x; - return; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0351.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0351.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0351.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0351.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -struct Ts {int x; int y; }; -struct Tstr {int a; struct Ts s; int t[10]; struct Tstr * p; } S; - -//@ ensures S.s.x == x && S.s == { \old(S.s) \with .x = x }; -void rw_field_field (int x) { - S.s.x = x; -} -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0352.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0352.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0352.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0352.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -int G; - -/*@ behavior default: - ensures \separated(\result, &G); -*/ -int *ptrX(int *p ) -{ - p = & G; - return (p); -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0352_false.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0352_false.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0352_false.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0352_false.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -int G; -int X; - - - -/*@ behavior default: - ensures \separated(\result, &X); -*/ -int *ptrX(int *p ) -{ - p = & G; - return (p); -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0354.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0354.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0354.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0354.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -union U { int a; int b; char c; } Gu; -union U Ggu; -void fu2 () { - Gu.a = 0; - Gu.b = 1; - //@ assert Gu.a == 1; - // this one is ok but need M3 (or maybe M2 ???) - //@ assert Gu.a == 0; - // the last one is false ! - Gu.c = 2; - Ggu.a=0; - Ggu.b=1; - Ggu.c = 2; - // //@ assert SI_PAS_PADDING : Ggu==Gu; // <--- doit être prouvable -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0355.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0355.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0355.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0355.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -int * P; -int X; -/*@ requires \separated(P, &X); - behavior default: ensures (*P > X); */ -void f_with_hyp(void) -{ - int x ; - x = X; - *P = x + 1; - return; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0356.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0356.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0356.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0356.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -/*@ requires \valid_range(p,0,i); - behavior default: ensures (\old(p)[i] == 78); */ -void main(int *p , int i ) -{ - p ++; p ++; p ++; *((p + i) - 3) = 78; - return; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0427.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0427.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0427.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0427.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -#include <stddef.h> - -typedef struct stack_t { - int *data; - unsigned long size; - unsigned long used; -} stack_t; - -void stack_init (stack_t *, int *, unsigned long); -int stack_valid (const stack_t *stack); -int stack_push (stack_t *, int); -int stack_pop (stack_t *, int *); - -/*@ predicate stack_initialized (stack_t s) = - @ (0 < s.size) && \valid (s.data) && \valid_range (s.data, 0, s.size); - @ - @ predicate stack_full (stack_t s) = - @ stack_initialized (s) && (s.used == s.size); - @ - @ predicate stack_empty (stack_t s) = - @ stack_initialized (s) && (s.used == 0); - @ */ - -/*@ requires \valid (stack); - @ ensures 0 <= \result <= 1; - @ ensures stack_initialized (*stack) ==> \result == 1; - @ */ - -int -stack_valid (const stack_t *stack) -{ - return ((stack->data != NULL) && (stack->size != 0)); -} - -/*@ requires \valid (stack); - @ requires \valid (data); - @ requires \valid_range (data, 0, size); - @ requires 0 < size; - @ ensures stack_initialized (*stack); - @ ensures stack->used == 0; - @ */ - -void -stack_init (stack_t *stack, int *data, unsigned long size) -{ - stack->data = data; - stack->size = size; - stack->used = 0; -} - -/*@ requires \valid (stack); - @ requires stack_initialized (*stack); - @ ensures !stack_full (\old (*stack)) ==> \old(stack->used) < stack->used; - @ */ - -int -stack_push (stack_t *stack, int item) -{ - if (stack->used < stack->size) { - stack->used++; - stack->data [stack->used] = item; - return 1; - } else - return 0; -} - -/*@ requires \valid (stack); - @ requires stack_initialized (*stack); - @ requires \valid (item); */ - -int -stack_pop (stack_t *stack, int *item) -{ - if (stack->used > 0) { - *item = stack->data [stack->used]; - stack->used--; - return 1; - } else - return 0; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0463.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0463.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0463.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0463.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -extern int Tab[] ; -/*@ behavior default: - ensures (Tab[\at(i,Old)] == \at(v,Old)); - */ -extern void writeTab(int i , int v ) ; -/*@ behavior default: - ensures (Tab[\at(j,Old)] == \at(x,Old)); - */ -void main(int j , int x ) -{ - writeTab(j,x); - return; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0492.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0492.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0492.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0492.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-verbose 2 -*/ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-verbose 2 -wp-proof simplify -*/ - - - -//@ logic int * Shift_Ptr(int * p, integer i) = p + i ; - -//@ ensures bug:\result == Shift_Ptr(p, i); -int * p_shift (int * p, int i) { - return p + i; -} - - -typedef int Array[12] ; -struct st { Array t ; int a ;} s1 , s2; - -//@ logic Array Mk_Array (Array x) = x ; - -/*@ ensures bug1: s1 == { s1 \with .t = Mk_Array(s2.t) } ; - ensures ok1: s1 == { s1 \with .t = s2.t } ; - - ensures bug2: \let v = \old(s1.a) ; - s1 == { s2 \with .a = v } ; - ensures ok2: s1 == { s2 \with .a = \old(s1.a) } ; -*/ -void wr_struct (int x) { - int a = s1.a ; - s1 = s2 ; - s1.a = a ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0493.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0493.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0493.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0493.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -//@ ensures \result == p + (\let idx = i ; idx + 0); -int * f(int * p, int i) { - return p + i; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts0657.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts0657.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts0657.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts0657.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -int i; - -//@ requires 1100000000<=i<=1100000001; -int f() -{ - //@ assert 1100000000<=i<=1100000001; - return i; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/bts494.c frama-c-20111001+nitrogen+dfsg/tests/wp/bts494.c --- frama-c-20110201+carbon+dfsg/tests/wp/bts494.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/bts494.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -//@ ensures \result >= n; -int loop_invariant(int n) { - int i = 0 ; - //@ loop invariant n== \at(n,Pre) && 0 <= i && (0 <=n ==> i <= n); - while (i < n) - i++ ; - return i; -} - - -//@ ensures \result >= n; -int invariant_as_loop_invariant(int n) { - int i = 0 ; - while (i < n) - //@ invariant n== \at(n,Pre) && 0 <= i && i <= n; - i++ ; - return i; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/CallTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/CallTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/CallTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/CallTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Proved with all - */ - -int z ; -/*@ assigns z; - ensures z==x ; -*/ -void g(int x,int y); - -void call_void(void) -{ - g(4,5); - - //@ assert z==4; -} - - -int pre; -/*@ - requires pre!= 0; - assigns pre ; - ensures \result == post ; -*/ -int f (int x, int post) -{ - pre = x ; - return post; - -} - -void call_with_ret(void) -{ - int x ; - x = f(1,2); - //@ assert x == 2; -} - - -int a; - -/*@ assigns a; - @ ensures (x>= y ==> \result == x) && (x<y ==> \result ==y); -*/ -int f1(int x,int y); - -void call_with_ret_sig(void) -{ - int x = 1; - int y = 2; - x = f1(x,y); - //@assert x==y; - -} - - - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/ConditionalTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/ConditionalTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/ConditionalTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/ConditionalTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Proved with all - */ - - -//@ ensures \result == 0; -int and_op(void) -{ - return (1==5 && 2 == 2); -} - -//@ ensures \result == 1; -int or_op(void) -{ - return (1==5 || 2 == 2); -} - - -/*@ - behavior Case_True : - ensures x==5 ==> \result == 1; - behavior Case_False : - ensures x!=5 ==> \result ==0; -*/ -int cond_op(int x) -{ - - return (x==5?1:0); -} - - -int blue; -int green; -int yellow; - -/*@ - - behavior Case_2 : - ensures x==-2 ==> \result == blue ; - - behavior Case_3: - ensures x==-1 ==> \result == yellow; - - behavior default : - ensures (x >-1|| x <-2 )==> \result == green; - */ - -int other_color(int x) -{ - int r = x+2 ; - if (r==1) return yellow; else - if(r==0) return blue ; else return green; -} - -int main (void) {return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/copy.c frama-c-20111001+nitrogen+dfsg/tests/wp/copy.c --- frama-c-20110201+carbon+dfsg/tests/wp/copy.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/copy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - requires is_valid_int_range(b, n); - - assigns b[0..n-1]; - - ensures \forall int i; 0 <= i < n ==> b[i] == a[i]; -*/ -void copy(const int* a, int n, int* b) -{ - /*@ - loop assigns b[0..i-1]; - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> a[k] == b[k]; - loop variant n-i; - */ - for (int i = 0; i < n; ++i) - b[i] = a[i]; -} - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/count.c frama-c-20111001+nitrogen+dfsg/tests/wp/count.c --- frama-c-20110201+carbon+dfsg/tests/wp/count.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/count.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - axiomatic counting_axioms - { - logic integer counting{L}(int* a, integer n, int val) - reads a[0..n-1]; - - axiom counting_empty{L}: - \forall int* a, integer n, int val; n <= 0 ==> - counting(a, n, val) == 0; - - axiom counting_hit{L}: - \forall int* a, integer n, int val; n >= 0 && a[n] == val ==> - counting(a, n+1, val) == counting(a, n, val) + 1; - - axiom counting_miss{L}: - \forall int* a, integer n, int val; n >= 0 && a[n] != val ==> - counting(a, n+1, val) == counting(a, n, val); - } -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - ensures \result == counting(a, n, val); -*/ -int count(const int* a, int n, int val) -{ - int cnt = 0; - /*@ - loop invariant 0 <= i <= n; - loop invariant 0 <= cnt <= i; - loop invariant cnt == counting(a, i, val); - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[i] == val) - cnt++; - - return cnt; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/div.c frama-c-20111001+nitrogen+dfsg/tests/wp/div.c --- frama-c-20110201+carbon+dfsg/tests/wp/div.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/div.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - -/*@ - behavior pos_pos : - assumes (a == 3) && (b == 2); - ensures \result == 1; - - behavior neg_neg : - assumes (a == -3) && (b == -2); - ensures \result == 1; - - behavior neg_pos : - assumes (a == -3) && (b == 2) ; - ensures \result == -1; - - behavior pos_neg : - assumes (a == 3) && (b == -2); - ensures \result == -1; -*/ - - -int f (int a,int b) {return (a/b);} - - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/DivEx1.c frama-c-20111001+nitrogen+dfsg/tests/wp/DivEx1.c --- frama-c-20110201+carbon+dfsg/tests/wp/DivEx1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/DivEx1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -typedef struct {int ch11[10]; int ch12;} T1; -typedef struct {int ch21; T1 ch22;} T2; - -/*@ assigns p[0..19].ch21, p[0..19].ch22.ch11[0..9]; - exits never: oracle_ok: \false; - - @ behavior ch21: - ensures ch21: oracle_ok: - \forall int k ; 0 <= k < 20 ==> p[k].ch21 == 0 ; - @ behavior ch22: - ensures ch22_11: oracle_ok: - \forall int k,l ; - 0 <= k < 20 && 0 <= l < 10 - ==> p[k].ch22.ch11[l] == 0 ; - ensures ch22_other: oracle_ok: - \forall int k ; - 0 <= k < 20 - ==> p[k].ch22 == {\old(p[k].ch22) \with .ch11=p[k].ch22.ch11} ; - @*/ -void DivEx1 (T2 *p) { - int i, j ; - - /*@ loop assigns i, j, p[0..i-1].ch21, p[0..i-1].ch22.ch11[0..9]; - loop invariant I0: oracle_ok: 0 <= i <= 20; - - @ for ch21: - loop invariant reset_21: oracle_ok: - \forall int k ; - 0 <= k < i ==> p[k].ch21 == 0; - @ for ch22: - loop invariant old_part_22: oracle_ok: - \forall int k ; - 0 <= k < i - ==> p[k].ch22 == {\at(p[k].ch22,Pre) \with .ch11=p[k].ch22.ch11} ; - loop invariant new_part_22: oracle_ok: - \forall int k,l ; - 0 <= k < i && 0 <= l < 10 ==> p[k].ch22.ch11[l] == 0 ; - - @ loop variant Idecr: oracle_ok: 20 - i ; - */ - for (i = 0 ; i < 20 ; i++) { - p[i].ch21 = 0 ; - /*@ loop assigns j, p[i].ch22.ch11[0..j-1]; - loop invariant J0: oracle_ok: 0 <= j <= 10; - - @ for ch22: - loop invariant reset_11: oracle_ok: - \forall int k ; 0 <= k < j ==> p[i].ch22.ch11[k] == 0; - - @ loop variant Jdecr: oracle_ok: 10 - j ; - @*/ - for (j = 0 ; j < 10 ; j++) - p[i].ch22.ch11[j] = 0 ; - } -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/endian.c frama-c-20111001+nitrogen+dfsg/tests/wp/endian.c --- frama-c-20110201+carbon+dfsg/tests/wp/endian.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/endian.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - -//@ requires \valid(x); -// void change_endianness(int * x) { -void main (int * x) { -char * p = (char* ) x; -int t; - - /*@ assert \valid(p); */ - /*@ assert \valid(p+1); */ - /*@ assert \valid(p+2); */ - /*@ assert \valid(p+3); */ - /*@ assert ((8+(int )p[1] >= 0) && (8+(int )p[1] < 32)); */ - /*@ assert ((16+(int )*p >= 0) && (16+(int )*p < 32)); */ - - -t = *(p+3) + *(p+2)<<8 + *(p+1)<<16 + *p<<24; -*x = t; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/equal.c frama-c-20111001+nitrogen+dfsg/tests/wp/equal.c --- frama-c-20110201+carbon+dfsg/tests/wp/equal.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/equal.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ - - -/*@ - requires is_valid_int_range(a, n); - requires is_valid_int_range(b, n); - - assigns \nothing; - - behavior all_equal: - assumes \forall int i; 0 <= i < n ==> a[i] == b[i]; - ensures \result == 1; - - behavior some_not_equal: - assumes \exists int i; 0 <= i < n && a[i] != b[i]; - ensures \result == 0; - - complete behaviors all_equal, some_not_equal; - disjoint behaviors all_equal, some_not_equal; -*/ -int equal(const int* a, int n, const int* b) -{ - /*@ - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> a[k] == b[k]; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[i] != b[i]) - return 0; - - return 1; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/fcts_bhv.c frama-c-20111001+nitrogen+dfsg/tests/wp/fcts_bhv.c --- frama-c-20110201+carbon+dfsg/tests/wp/fcts_bhv.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/fcts_bhv.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - run.config - OPT: -wp-proof none -wp-print -wp-fct f,g - OPT: -wp-proof none -wp-print -wp-fct f,g -wp-bhv B1 - OPT: -wp-proof none -wp-print -wp-bhv B1 - -*/ - -//@ predicate P (integer x)= x/2 > 0 ; -//@ predicate P1 (integer x) = x/2 > 0; -//@ predicate P2 (integer x) = x/2 > 0; - -/*@ - requires P(1); - assigns \nothing; - behavior B1: - assumes P1(2); - assigns \nothing; - ensures P1(3); - behavior B2: - assumes P2(4); - assigns \nothing; - ensures P2(5); - ensures P(6); - */ -void f(void) -{ - int x ; x =1 ; - } - - - -/*@ - requires P(7); - assigns \nothing; - behavior B1: - assumes P1(9); - assigns \nothing; - ensures P1(10); - behavior B2: - assumes P2(11); - assigns \nothing; - ensures P2(12); - ensures P(13); - */ -void g(void) -{ - int x ; x =1 ; - } - -/*@ - requires P(14); - assigns \nothing; - ensures P(15); - */ -void h(void) -{ - int x ; x =1 ; - } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/fill.c frama-c-20111001+nitrogen+dfsg/tests/wp/fill.c --- frama-c-20110201+carbon+dfsg/tests/wp/fill.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/fill.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns a[0..n-1]; - - ensures \forall int i; 0 <= i < n ==> a[i] == val; -*/ -void fill(int* a, int n, int val) -{ - /*@ - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> a[k] == val; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - a[i] = val; -} - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/find2.c frama-c-20111001+nitrogen+dfsg/tests/wp/find2.c --- frama-c-20110201+carbon+dfsg/tests/wp/find2.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/find2.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - behavior some: - assumes found(a, n, val); - ensures 0 <= \result < n; - ensures a[\result] == val; - ensures !found(a, \result, val); - - behavior none: - assumes !found(a, n, val); - ensures \result == n; - - complete behaviors some, none; - disjoint behaviors some, none; -*/ -int find2(const int* a, int n, int val) -{ - /*@ - loop invariant 0 <= i <= n; - loop invariant !found(a, i, val); - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[i] == val) - return i; - - return n; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/find.c frama-c-20111001+nitrogen+dfsg/tests/wp/find.c --- frama-c-20110201+carbon+dfsg/tests/wp/find.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/find.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - behavior some: - assumes \exists int i; 0 <= i < n && a[i] == val; - ensures 0 <= \result < n; - ensures a[\result] == val; - ensures \forall int i; 0 <= i < \result ==> a[i] != val; - - behavior none: - assumes \forall int i; 0 <= i < n ==> a[i] != val; - ensures \result == n; - - complete behaviors some, none; - disjoint behaviors some, none; -*/ -int find(const int* a, int n, int val) -{ - /*@ - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> a[k] != val; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[i] == val) - return i; - - return n; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/find_first_of.c frama-c-20111001+nitrogen+dfsg/tests/wp/find_first_of.c --- frama-c-20110201+carbon+dfsg/tests/wp/find_first_of.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/find_first_of.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ - -int find(const int* a, int n, int val) -{ - /*@ - loop assigns i; - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> a[k] != val; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[i] == val) - return i; - - return n; -} - -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ -/*@ - requires is_valid_int_range(a, m); - requires is_valid_int_range(b, n); - - assigns \nothing; - - behavior found: - assumes found_first_of(a, m, b, n); - ensures 0 <= \result < m; - ensures found(b, n, a[\result]); - ensures !found_first_of(a, \result, b, n); - - behavior not_found: - assumes !found_first_of(a, m, b, n); - ensures \result == m; - - complete behaviors found, not_found; - disjoint behaviors found, not_found; -*/ -int find_first_of(const int* a, int m, const int* b, int n) -{ - /*@ - loop invariant 0 <= i <= m; - loop invariant !found_first_of(a, i, b, n); - loop variant m-i; - */ - for(int i = 0; i < m; i++) - if (find(b, n, a[i]) < n) - return i; - - return m; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/huge.c frama-c-20111001+nitrogen+dfsg/tests/wp/huge.c --- frama-c-20110201+carbon+dfsg/tests/wp/huge.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/huge.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* run.config - OPT: -wp -wp-huge 9 -wp-print - OPT: -wp -wp-huge 10 -wp-print - */ - -int a[5] ; - -//@ensures \result >= 0 ; -int f(void) -{ - int k = 0 ; - int r = 0 ; - if (a[k++]) r++ ; // 0 - if (a[k++]) r++ ; // 1 - if (a[k++]) r++ ; // 2 - if (a[k++]) r++ ; // 3 - if (a[k++]) r++ ; // 4 - return r ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/implicit_prototype.c frama-c-20111001+nitrogen+dfsg/tests/wp/implicit_prototype.c --- frama-c-20110201+carbon+dfsg/tests/wp/implicit_prototype.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/implicit_prototype.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - - -//@ ensures \result ==a; -int f(int a) -{ return g(3,4,a);} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/IncrDecrTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/IncrDecrTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/IncrDecrTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/IncrDecrTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Proved with all - */ - -int i,b; - -//@ ensures b == 0; -int res_post_incr(void) -{ - i =0; - b = i++; - return i; -} - -//@ ensures b == 0; -int res_post_decr(void) -{ - i =0; - b = i--; - return i; -} - -//@ ensures b == 1; -int res_pre_incr(void) -{ - i =0; - b = ++i; - return i; -} - -//@ ensures b == 0; -int res_pre_decr(void) -{ - i =1; - b = --i; - return i; -} - -//@ ensures b == \old(i); -int res_post_incr_old(void) -{ - - b = i++; - return i; -} - -//@ ensures b == \old(i); -int res_post_decr_old(void) -{ - b = i--; - return i; -} - -//@ ensures b == i; -int res_pre_incr_old(void) -{ - b = ++i; - return i; -} - -//@ ensures b == i; -int res_pre_decr_old(void) -{ - b = --i; - return i; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/iota.c frama-c-20111001+nitrogen+dfsg/tests/wp/iota.c --- frama-c-20110201+carbon+dfsg/tests/wp/iota.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/iota.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - requires val + n < ((1<<31)-1); // INT_MAX; - - assigns a[0..n-1]; - - ensures \forall int k; 0 <= k < n ==> a[k] == val + k; -*/ -void iota(int* a, int n, int val) -{ - /*@ - loop assigns a[0..i-1]; - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> a[k] == val+k; - loop variant n-i; - */ - for(int i = 0; i < n; ++i) - a[i] = val + i; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Loop_bhv.c frama-c-20111001+nitrogen+dfsg/tests/wp/Loop_bhv.c --- frama-c-20110201+carbon+dfsg/tests/wp/Loop_bhv.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Loop_bhv.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -/*@ - assigns \nothing; - ensures \result == n; -*/ -int find(int n) -{ - /*@ - loop assigns \nothing; - loop invariant 0 <= i <= n; - loop variant n-i; - */ - for (int i = 0; i < n; i++) ; - return n; -} - - -/*@ - assigns \nothing; - behavior DUMMY : - ensures \result == n; - behavior FOO : - ensures \result == n; -*/ -int find_behav(int n) -{ - /*@ - loop assigns i; - loop invariant 0 <= i <= n; - loop variant n-i; - */ - for (int i = 0; i < n; i++) ; - return n; -} - -int G; -//@ ensures \at(G,Old) == \at(G,Here); -void skip(void) -{ - int i ; i++; -} - - -//@ ensures \result == 0; -int call_find_behav() -{ - int i = find_behav(0); - return i; - -} - - -/*@ - assigns G; - ensures G == 5; -*/ -int res(int n) -{ - G =5; - /*@ - loop assigns \nothing; - loop invariant 0 <= i <= n; - loop variant n-i; - */ - for (int i = 0; i < n; i++) ; - return n; -} - -/*@ - assigns G; - behavior TEST: - ensures G == 5; -*/ -int res_with_behavior(int n) -{ - G =5; - /*@ - loop assigns \nothing; - loop invariant 0 <= i <= n; - loop variant n-i; - */ - for (int i = 0; i < n; i++) ; - return n; -} - - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/loop_test.c frama-c-20111001+nitrogen+dfsg/tests/wp/loop_test.c --- frama-c-20110201+carbon+dfsg/tests/wp/loop_test.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/loop_test.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -//@ requires 0 <= n; // notice that we should be able to relax that. -int loop_var (int n) { - int i, s = 0; - /*@ - loop assigns i, s; - loop variant (n - i); - */ - for (i = 0; i < n; i++) { - s++; - } - return s; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Loop_with_call.c frama-c-20111001+nitrogen+dfsg/tests/wp/Loop_with_call.c --- frama-c-20110201+carbon+dfsg/tests/wp/Loop_with_call.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Loop_with_call.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/*@ - assigns \nothing; - behavior DUMMY : - assumes n == 0 ; - ensures \result == n; - behavior FOO : - ensures \result == n-4+4; -*/ -int find_behav(int n) -{ - /*@ - loop assigns i; - loop invariant 0 <= i <= n; - loop variant n-i; - */ - for (int i = 0; i < n; i++) ; - return n; -} - -//@ ensures \result == 0; - -int call_find_behav(void) -{ - int i = find_behav(0); - return i; - -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/max_element.c frama-c-20111001+nitrogen+dfsg/tests/wp/max_element.c --- frama-c-20110201+carbon+dfsg/tests/wp/max_element.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/max_element.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - behavior empty: - assumes n == 0; - ensures \result == 0; - - behavior not_empty: - assumes 0 < n; - ensures 0 <= \result < n; - ensures \forall int i; 0 <= i < n ==> a[i] <= a[\result]; - ensures \forall int i; 0 <= i < \result ==> a[i] < a[\result]; - - complete behaviors empty, not_empty; - disjoint behaviors empty, not_empty; -*/ -int max_element(const int* a, int n) -{ - if (n == 0) return 0; - int max = 0; - /*@ - loop invariant 0 <= i <= n; - loop invariant 0 <= max < n; - loop invariant \forall int k; 0 <= k < i ==> a[k] <= a[max]; - loop invariant \forall int k; 0 <= k < max ==> a[k] < a[max]; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[max] < a[i]) - max = i; - - return max; -} - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/max_seq.c frama-c-20111001+nitrogen+dfsg/tests/wp/max_seq.c --- frama-c-20110201+carbon+dfsg/tests/wp/max_seq.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/max_seq.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - behavior empty: - assumes n == 0; - ensures \result == 0; - - behavior not_empty: - assumes 0 < n; - ensures 0 <= \result < n; - ensures \forall int i; 0 <= i < n ==> a[i] <= a[\result]; - ensures \forall int i; 0 <= i < \result ==> a[i] < a[\result]; - - complete behaviors empty, not_empty; - disjoint behaviors empty, not_empty; -*/ -int max_element(const int* a, int n) -{ - if (n == 0) return 0; - int max = 0; - /*@ - loop assigns i,max; - loop invariant 0 <= i <= n; - loop invariant 0 <= max < n; - loop invariant \forall int k; 0 <= k < i ==> a[k] <= a[max]; - loop invariant \forall int k; 0 <= k < max ==> a[k] < a[max]; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[max] < a[i]) - max = i; - - return max; -} - - - -/*@ - requires n > 0; - requires \valid(p+ (0..n-1)); - - assigns \nothing; - - ensures \forall int i; 0 <= i <= n-1 ==> \result >= p[i]; - ensures \exists int e; 0 <= e <= n-1 && \result == p[e]; -*/ -int max_seq(const int* p, int n) -{ - return p[max_element(p, n)]; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/min_element.c frama-c-20111001+nitrogen+dfsg/tests/wp/min_element.c --- frama-c-20110201+carbon+dfsg/tests/wp/min_element.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/min_element.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - predicate - adjacent_found{Label}(int* a, int n) = - \exists int i; 0 <= i < n-1 && a[i] == a[i+1]; -*/ - -/*@ - requires is_valid_int_range(a, n); - - assigns \nothing; - - behavior empty: - assumes n == 0; - ensures \result == 0; - - behavior not_empty: - assumes 0 < n; - ensures 0 <= \result < n; - ensures \forall int i; 0 <= i < n ==> a[\result] <= a[i]; - ensures \forall int i; 0 <= i < \result ==> a[\result] < a[i]; -*/ -int min_element(int* a, int n) -{ - if (0 == n) return n; - - int min = 0; - /*@ - loop invariant 0 <= i <= n; - loop invariant 0 <= min < n; - loop invariant \forall int k; 0 <= k < i ==> a[min] <= a[k]; - loop invariant \forall int k; 0 <= k < min ==> a[min] < a[k]; - loop variant n-i; - */ - for (int i = 0; i < n; i++) - if (a[i] < a[min]) - min = i; - - return min; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/minus_of_set.c frama-c-20111001+nitrogen+dfsg/tests/wp/minus_of_set.c --- frama-c-20110201+carbon+dfsg/tests/wp/minus_of_set.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/minus_of_set.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ - - -//@assigns *( \union(p,q)-1); -void f(int * p, int * q) -{ *(p-1) = 0 ; *(q-1)=0;} - -//@assigns *(p-(0..2)); -void f2(int * p, int * q) -{ *(p-1) = 0 ; *(q-1)=0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Mtu.c frama-c-20111001+nitrogen+dfsg/tests/wp/Mtu.c --- frama-c-20110201+carbon+dfsg/tests/wp/Mtu.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Mtu.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -/* -note: property named "c" is also decomposed into 5 properties - named "case1"..."case5" -*/ -typedef struct {int a,b,c ; } TMtu; -/*@ - assigns pt->c ; - -behavior oracle_ok: - ensures result: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - ((x==0)?\result==0 - :((x==p)?\result==e - :\result!=0)) ; - - ensures c: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - ((x==0)?((e==0)?pt->c==p - :pt->c==0) - :((x==p)?((e!=0)?pt->c==p-1 - :pt->c==p) - :pt->c==x-1)) ; - ensures case1: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x==0 && e==0 ==> pt->c==p ; - ensures case2: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x==0 && e!=0 ==> pt->c==0 ; - ensures case3: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x!=0 && x==p && e!=0 ==> pt->c==p-1 ; - ensures case4: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x!=0 && x==p && e==0 ==> pt->c==p ; - ensures case5: oracle_ok: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x!=0 && x!=p ==> pt->c==x-1 ; - -behavior oracle_ko: - ensures result: oracle_ko: - \let x = ((c==0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - ((x==0)?\result==0 - :((x==p)?\result==e - :\result!=0)) ; - - ensures c: oracle_ko: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - ((x!=0)?((e==0)?pt->c==p - :pt->c==0) - :((x==p)?((e!=0)?pt->c==p-1 - :pt->c==p) - :pt->c==x-1)) ; - ensures case1: oracle_ko: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x==0 && e==0 ==> pt->c==\old(pt->c) ; - ensures case2: oracle_ko: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x==0 && e!=0 ==> pt->c!=0 ; - ensures case3: oracle_ko: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x!=0 && x==p && e!=0 ==> pt->c==p ; - ensures case4: oracle_ko: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x!=0 && x==p && e==0 ==> pt->c==p-1 ; - ensures case5: oracle_ko: - \let x = ((c!=0)?((e!=0)?(p-m) - :0) - :\old(pt->c)) ; - x!=0 && x!=p ==> pt->c==x ; -*/ -int Mtu( TMtu *pt, int e, int c, int p, int m ) { - int r; - - if (c) - if (e) - pt->c = p - m; - else - pt->c = 0; - - if (!pt->c) { - r = 0; - if ( !e ) - pt->c = p; - } - else if (pt->c == p) { - r = e; - if (e) - pt->c = pt->c - 1; - } - else { - r = 1; - pt->c = pt->c - 1; - } - return r; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/NullCmpTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/NullCmpTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/NullCmpTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/NullCmpTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ - - -int *p; -/*@ requires \valid (p); - ensures \result == 0; -*/ -int main(void) -{ - - return (p == (char *) 0); -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/numeric_addr.c frama-c-20111001+nitrogen+dfsg/tests/wp/numeric_addr.c --- frama-c-20110201+carbon+dfsg/tests/wp/numeric_addr.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/numeric_addr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-proof z3 -wp-print -wp-verbose 2 -*/ - - -/*@ requires (no_rte: \valid(Valeur)); - requires (no_rte: \valid((unsigned int *)0x12345678)); - requires (no_rte: \separated(Valeur, (unsigned int *)0x12345678)); - ensures *Valeur == \old(*(unsigned int *)0x12345678); -*/ -void LireStatusCpu(unsigned int *Valeur ) { - /*@ assert (rte: \valid(Valeur)); */ - /*@ assert (rte: \valid((unsigned int *)0x12345678)); */ - *Valeur = *((unsigned int *)0x12345678); - return; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/pointer_arith.c frama-c-20111001+nitrogen+dfsg/tests/wp/pointer_arith.c --- frama-c-20110201+carbon+dfsg/tests/wp/pointer_arith.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/pointer_arith.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ - - - - -int T[10]; - -int x; - -/*@ behavior no_alias : - assumes i != j; - ensures \result == \old(T[j]); - behavior with_alias : - assumes i == j; - ensures \result == 1; -*/ -int tab_read_write (int i, int j) { - T[i] = 1; - return T[j]; -} - -/*@ requires \valid (p) && \valid (q) && p != q; - ensures \result == \old(*q) && *p == 3; */ -int no_alias (int * p, int * q) { - *p = 3; - return *q; -} - -/*@ - requires \valid (p) ; - ensures \result == 3 ; -*/ -int wptr (int *p) { - - *p = 3; - x = *p; - return *p; - -} - -void cmp_addr_loc () { - int i, j; - //@ assert &i != &j; - if (&i < &j) return; - //@ assert &i >= &j; - if (&i - &j > 0) return; - //@ assert \false; -} - -//@ ensures i == j ==> \result == 0; -int cmp_ptr (int i, int j) { - int * pi = T+i; - int * pj = T+j; - if (pi < pj) return -1; - if (pi - pj > 0) return 1; - return 0; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/prop_n.c frama-c-20111001+nitrogen+dfsg/tests/wp/prop_n.c --- frama-c-20110201+carbon+dfsg/tests/wp/prop_n.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/prop_n.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - run.config - OPT: -wp-proof none -wp-print -wp-prop A - OPT: -wp-proof none -wp-print -wp-prop A,B - - */ - - - - -//@ predicate P(integer i) = i >= 0 ; - -int y; - -/*@ - requires P(x); - assigns \nothing; - ensures A:P(y); - ensures B:P(z); - ensures P(y+z); -*/ - int f(int x, int z) - { return z; } - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/ptr_incr.c frama-c-20111001+nitrogen+dfsg/tests/wp/ptr_incr.c --- frama-c-20110201+carbon+dfsg/tests/wp/ptr_incr.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/ptr_incr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -# pragma SeparationPolicy(none) -/*@ - requires \valid(p); - requires \valid(q); - ensures *p==\old(*p)+1; - ensures *q==\old(*q)+1; - */ -void ptr_incr(int *p,int *q) -{ - *p+=1; *q+=1; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/range_test1.c frama-c-20111001+nitrogen+dfsg/tests/wp/range_test1.c --- frama-c-20110201+carbon+dfsg/tests/wp/range_test1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/range_test1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-verbose 2 -*/ - -int T[10]; - -/*@ assigns T[0..4]; - ensures T[5] == \old(T[5]); -*/ -void assign_T (void) { - int i; - /*@ loop assigns i, T[0..4]; - @ loop invariant 0 <= i; - */ - for (i = 0; i < 5; i++) { - T[i] ++; - } -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -struct Ts { int a; int t[10]; }; -struct Ts S; - -/*@ ensures (T[5] == \old(T[5])); - ensures (S.a == \old(S.a)); -*/ -void assign_S (void) { - int i; - //@ loop assigns i, S.t[..]; - for (i = 0; i < 5; i++) { - S.t[i] = T[i]; - } -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/remove_copy.c frama-c-20111001+nitrogen+dfsg/tests/wp/remove_copy.c --- frama-c-20110201+carbon+dfsg/tests/wp/remove_copy.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/remove_copy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -/* run.config - DONTRUN: invalid ACSL annotations (unbound function counting) -*/ - -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - requires is_valid_int_range(b, n); - - assigns b[0 .. n-1]; - - ensures \forall int k; \result <= k < n ==> b[k] == \old(b[k]); - ensures \forall int k; 0 <= k < \result ==> b[k] != val; - ensures \forall int x; x != val ==> - counting(a, n, x) == counting(b, \result, x); - ensures \result == n - counting(a, n, val); - ensures 0 <= \result <= n; -*/ -int remove_copy(const int* a, int n, int* b, int val) -{ - int j = 0; - /*@ - loop assigns b[0..j-1]; - - loop invariant 0 <= j <= i <= n; - loop invariant \forall int k; j <= k < n ==> - b[k] == \at(b[k],Pre); - loop invariant \forall int k; 0 <= k < j ==> b[k] != val; - loop invariant \forall int x; x != val ==> - counting(a,i,x) == counting(b,j,x); - loop invariant j == i - counting(a,i,val); - - loop variant n-i; - */ - for (int i = 0; i < n; ++i) - if (a[i] != val) - b[j++] = a[i]; - return j; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/replace_copy.c frama-c-20111001+nitrogen+dfsg/tests/wp/replace_copy.c --- frama-c-20110201+carbon+dfsg/tests/wp/replace_copy.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/replace_copy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); - -*/ -/*@ - predicate - found{A}(int* a, int n, int val) = - \exists int i; 0 <= i < n && a[i] == val; -*/ -/*@ - predicate - found_first_of{A}(int* a, int m, int* b, int n) = - \exists int i; 0 <= i < m && found{A}(b, n, \at(a[i],A)); -*/ - -/*@ - requires is_valid_int_range(a, n); - requires is_valid_int_range(b, n); - - assigns b[0 .. n-1]; - - ensures \forall int j; 0 <= j < n ==> - a[j] == old_val && b[j] == new_val || - a[j] != old_val && b[j] == a[j]; - ensures \result == n; -*/ -int replace_copy(const int* a, int n, int* b, int old_val, int - new_val) -{ - /*@ - loop assigns b[0..i-1]; - loop invariant 0 <= i <= n; - loop invariant \forall int j; 0 <= j < i ==> - a[j] == old_val && b[j] == new_val || - a[j] != old_val && b[j] == a[j]; - loop variant n-i; - */ - for (int i = 0; i < n; ++i) - b[i] = (a[i] == old_val ? new_val : a[i]); - - return n; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/ResultLogicStructArray.c frama-c-20111001+nitrogen+dfsg/tests/wp/ResultLogicStructArray.c --- frama-c-20110201+carbon+dfsg/tests/wp/ResultLogicStructArray.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/ResultLogicStructArray.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Not Yet Translated - model name : Hoare ; bhv : Out of Scope - */ - -int x,y; -struct S { int * a; }; - -//@ assigns *(\result.a); -struct S result_field (void) -{ - struct S s; - s.a = &x; - x=4; - return s; -} - -int main (void) { return 0;} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/RstarS.c frama-c-20111001+nitrogen+dfsg/tests/wp/RstarS.c --- frama-c-20110201+carbon+dfsg/tests/wp/RstarS.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/RstarS.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -/* note: properties named "oracle_ko" are not true ! -*/ -/*@ requires \valid(RstarSQ); - assigns *RstarSQ ; - ensures \result == *RstarSQ; - - behavior b1: - assumes R==0 && S!=0 ; - ensures oracle_ok: *RstarSQ!=0; - ensures oracle_ko: *RstarSQ==0; - - behavior b2: - assumes R==0 && S==0 ; - ensures oracle_ok: *RstarSQ==\old(*RstarSQ); - ensures oracle_ko: *RstarSQ!=\old(*RstarSQ); - - behavior b3: - assumes R!=0 ; - ensures oracle_ok: *RstarSQ==0; - ensures oracle_ko: *RstarSQ!=0; - - complete behaviors ; - disjoint behaviors ; -*/ -int RstarS(int *RstarSQ, int R, int S) { - if (!R && S) - *RstarSQ=1; - else if (R) - *RstarSQ=0; - return *RstarSQ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/SimpleExpTestNeg.c frama-c-20111001+nitrogen+dfsg/tests/wp/SimpleExpTestNeg.c --- frama-c-20110201+carbon+dfsg/tests/wp/SimpleExpTestNeg.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/SimpleExpTestNeg.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -//@ ensures \result > 4; -int res_lt(void) -{ - return 4; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/SimpleExpTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/SimpleExpTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/SimpleExpTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/SimpleExpTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* - kind : Positive - model name : Store ; bhv : Provable - model name : Hoare ; bhv : Proved with alt-ergo - */ - -//@ ensures \result == 4; -int res_int_cst(void) -{ - return 4; -} - -//@ ensures \result >= 4; -int res_int_cst_lt() -{ - return 4; -} - - - -//@ ensures \result == -4; -int res_unop_neg(void) -{ - int i = 4; return -i; -} - - -//@ ensures \result == 4; -int res_unop_pos(void) -{ - int i = 4; return +i; -} - -/* -//@ensures \result == 1 && z == 1; -int res_unop_not(void) -{ int z; - z = !0; - return !4 ; } -*/ - -//@ ensures \result == 4; -int res_additive_operator(void) -{ - return (4+5-5); -} - - -//@ ensures \result == 4; -int res_multiplicative_operator(void) -{ - return (4*5/5); -} - -//@ ensures \result != 0; -int res_equality(void) -{ - - int c,d,e; - c=5 ; - e=3 ; - d= (c+e); - return (d==8); -} - - -//@ ensures \result == 1; -int res_relation(void) -{ - - int c,d,e; - c=5 ; - e=3 ; - d= (c+e); - return (d>=8); -} - - - - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/struct.c frama-c-20111001+nitrogen+dfsg/tests/wp/struct.c --- frama-c-20110201+carbon+dfsg/tests/wp/struct.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/struct.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* run.config -CMD: FRAMAC_SHARE=./share ./bin/toplevel.opt -OPT: -no-lib-entry -wp -wp-model Store -wp-proof none -wp-print -wp-verbose 2 -wp-assigns effect -OPT: -no-lib-entry -wp -wp-model Hoare -wp-proof none -wp-print -wp-verbose 2 -OPT: -no-lib-entry -wp -wp-model UnsafeCaveat -wp-proof none -wp-print -wp-verbose 2 -OPT: -no-lib-entry -wp -wp-model Runtime -wp-proof none -wp-print -wp-verbose 2 -wp-assigns effect -FILTER: tests/wp/filter_wp_res -*/ - -/* run.config_why - OPT: -wp -wp-assigns effect -wp-timeout 1 -wp-proof alt-ergo -wp-par 1 - */ - -struct S { int i; }; - -/*@ ensures p1: oracle_ok: \forall struct S v ; (v.i == 0 ==> \result == v); - ensures p2: oracle_ok: \forall struct S v ; \result == { v \with .i = (int)0 } ; - assigns \nothing ; - @ */ -struct S f(void) { - struct S s = { 0 }; - return s; -} - -struct S2 { int a; struct S s; int t[2]; struct S ts[5]; } Gs, Ps; -struct S Gs1, Gs2; -/*@ensures p1: oracle_ok: Gs.a == 1 ; - ensures p2: oracle_ok: Gs.s.i == 1 ; - ensures p3: oracle_ok: Gs.t[0] == 3 && Gs.t[1] == 3 ; - ensures p4: oracle_ok: Gs.ts[3].i == 4; - - ensures p5: oracle_ok: Gs1 == {\old(Gs1) \with .i = (int) 1 } ; - ensures p6: oracle_ok: Gs.s == {\old(Gs.s) \with .i = (int) 1 } ; - - // assigns Gs.a, Gs.s.i, Gs.t[0], Gs.t[1], Gs.ts[3].i; <----- FAUX - assigns Gs.a, Gs.s.i, Gs.t[0], Gs.t[1], Gs.ts[3].i, Gs1.i, Gs2.i ; - @ */ -void f2 () { - Gs.a = 1; - Gs.s.i = Gs.a; - Gs.t[0] = 3; - Gs.t[Gs.a] = 3; - Gs.ts[3].i = Gs.t[0] + 1; - Gs1.i = 1; - Gs2.i = 1; - //@ assert a1: SI_PAS_DE_PADDING: oracle_ok: Gs1==Gs2; // <--- should be prouvable -} - -union U { int a; int b; char c; } Gu; - -void fu () { - Gu.a = 0; - //@ assert a1: oracle_ok: Gu.a == 0; - Gu.b = 1; - //@ assert a2: oracle_ok: Gu.b == 1; -} -union U Ggu; -void fu2 () { - Gu.a = 0; - Gu.b = 1; - //@ assert a1: oracle_ok: Gu.a == 1; - // this one is ok but need M3 (or maybe M2 ???) - //@ assert a2: oracle_ko: Gu.a == 0; - // the last one is false ! - Gu.c = 2; - Ggu.a=0; - Ggu.b=1; - Ggu.c = 2; - //@ assert a3: SI_PAS_PADDING: oracle_ok: Ggu==Gu; // <--- should be prouvable -} -int main (void) { return 0 ; } - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/struct_store.c frama-c-20111001+nitrogen+dfsg/tests/wp/struct_store.c --- frama-c-20110201+carbon+dfsg/tests/wp/struct_store.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/struct_store.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -struct R {int a; int b;}; - -struct S {struct R f;} ; - - -struct R r; -struct S s; - -//@ ensures oracle_ok:s == { \old(s) \with .f = r}; -int f (void) -{ s.f = r ; - return s.f.a; -} - -//@ ensures oracle_ok:s == { \old(s) \with .f = r1}; -int f2 (struct R r1) -{ - r = r1; - s.f = r ; - return 1; -} - -struct R r3; - -//@ ensures oracle_ko: s == { \old(s) \with .f = r3}; -int f3_false (struct R r1) -{ - r = r1; - s.f = r ; - return 1; -} - -/*@ ensures oracle_ok: s == { \old(s) \with .f = r1}; - @ ensures oracle_ok: s == { s1 \with .f = r1}; - */ -int f4_true (struct S s1, struct R r1) -{ - s1.f = r1; - s =s1 ; - s1.f = r; - return 0; -} - -//@ ensures oracle_ko: s == { \old(s) \with .f = r}; -int f4_false (struct S s1, struct R r1) -{ - s1.f = r1; - s =s1 ; - s1.f = r; - return 0; -} - -//@ ensures oracle_ok: \result == r1; -struct R struct_copy (struct R r1) -{ - struct R tmp; - tmp.a = r1.a; - tmp.b = r1.b; - return tmp; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/StructTestPos.c frama-c-20111001+nitrogen+dfsg/tests/wp/StructTestPos.c --- frama-c-20110201+carbon+dfsg/tests/wp/StructTestPos.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/StructTestPos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -struct s {int a;}; - -//@ ensures \result == 4; -int field_eq_load(void) -{ - struct s s1,s2; - s1.a =4; - s2 = s1; - return s2.a; -} - -struct s s1,s2; -//@ ensures s2 == s1; -void equal_record_test(void) -{ - s2 =s1 ; - -} - -struct Ts {struct s s1; int t[10];} ; - -struct Ts ts1, ts2; -//@ ensures \result == ts1.t[0] ; -int equal_with_array_field (void) -{ - ts1=ts2; - return ts2.t[0]; -} - -struct S {int a;}; - -struct S s; - - -/*@ requires s.a == 5; - assigns s.a; - ensures \result == {s \with .a = (int)4 }; -*/ -struct S ret_struct(void) -{ - s.a = 4; - return s; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/swap.c frama-c-20111001+nitrogen+dfsg/tests/wp/swap.c --- frama-c-20110201+carbon+dfsg/tests/wp/swap.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/swap.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -# pragma SeparationPolicy(none) - -/*@ - requires \valid(p); - requires \valid(q); - - - assigns *p; - assigns *q; - - ensures *p == \old(*q); - ensures *q == \old(*p); -*/ -void swap(int* p, int* q) -{ - int const save = *p; - *p = *q; - *q = save; -} - -int main () { - int p[2] = { 0,1}; - int *q = (int *)((char*)q+1); - swap(p,q); -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/swap_range.c frama-c-20111001+nitrogen+dfsg/tests/wp/swap_range.c --- frama-c-20110201+carbon+dfsg/tests/wp/swap_range.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/swap_range.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/*@ - predicate is_valid_int_range(int* p, int n) = - (0 <= n) && \valid_range(p,0,n-1); - - lemma foo: \forall int* p,n; is_valid_int_range(p,n) <==> \valid_range(p,0,n-1); -*/ - -/*@ - requires \valid(p); - requires \valid(q); - requires \separated(p,q); - - assigns *p; - assigns *q; - - ensures *p == \old(*q); - ensures *q == \old(*p); -*/ -void swap(int* p, int* q) -{ - int const save = *p; - p++;p--; - *p = *q; - *q = save; -} - - - -/*@ - requires is_valid_int_range(a, n); - requires is_valid_int_range(b, n); - //requires \separated(a, b); - - assigns a[0..n-1]; - assigns b[0..n-1]; - - ensures \forall int k; 0 <= k < n ==> a[k] == \old(b[k]); - ensures \forall int k; 0 <= k < n ==> b[k] == \old(a[k]); -*/ -void swap_ranges(int* a, int n, int* b) -{ - /*@ - loop assigns a[0..i-1]; - loop assigns b[0..i-1]; - - loop invariant 0 <= i <= n; - loop invariant \forall int k; 0 <= k < i ==> - a[k] == \at(b[k],Pre); - loop invariant \forall int k; 0 <= k < i ==> - b[k] == \at(a[k],Pre); - - loop variant n-i; - */ - for (int i = 0; i < n; i++) - swap(&a[i], &b[i]); -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/swap_sep.c frama-c-20111001+nitrogen+dfsg/tests/wp/swap_sep.c --- frama-c-20110201+carbon+dfsg/tests/wp/swap_sep.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/swap_sep.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ - - -/*@ - requires \valid(p); - requires \valid(q); - requires \separated(p,q); - - assigns *p; - assigns *q; - - ensures *p == \old(*q); - ensures *q == \old(*p); -*/ -void swap(int* p, int* q) -{ - int const save = *p; - p++;p--; - *p = *q; - *q = save; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/TCA_Automaton_pp.c frama-c-20111001+nitrogen+dfsg/tests/wp/TCA_Automaton_pp.c --- frama-c-20110201+carbon+dfsg/tests/wp/TCA_Automaton_pp.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/TCA_Automaton_pp.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1348 +0,0 @@ -# 1 "TCA_Automaton.c" -# 1 "<interne>" -# 1 "<ligne de commande>" -# 1 "TCA_Automaton.c" -/******************************************************************** -* MACHINE TERMINALE TCA_Automaton -******************************************************************** -* Descriptif : -* TCA_Automaton is a terminal machine and is in charge of managing the states -* depending on the input events generated by TCR_FileReader or TCW_FileWriter. -* and also emitting the events based on the state transition. -* -*********************************************************************/ -/******************************************************************** -*CONTEXTE -*********************************************************************/ - -# 1 "TCA_Automaton.i" 1 -/******************************************************************** -* MACHINE TERMINALE TCA_Automaton -******************************************************************** -* Mnemonique : -* TCA -* -* Definition : -* TCA_Automaton is a terminal machine and is in charge of managing the states -* depending on the input events generated by TCR_FileReader or TCW_FileWriter. -* and also emitting the events based on the state transition. -* -* Particularites : -* AUCUNE -*********************************************************************/ -# 1 "/projets/u3cat/ETUDES/ASF/DLAC_V1_3/DLAC/src/frama-c/inc/STANDARD_C.h" 1 - - - - -/******************************************************************** -* MACHINE TERMINALE STANDARD_C -******************************************************************** -* Mnemonique : -* UST -* -* Definition : -* STANDARD_C abstract machine is makes to replace services of standard -* C library, to allow -* to perform all covering tests on embedded code -* It also define: -* - all basic types used by subsets of CMS-ACD function -* - PORTABLES services, independant on the storing mode of bytes in memory, -* -* performed by the CPU -* - a CRC computation service, used by several subsets -* - a formatting service, allowing to switch from a LittelEndian or BigEndian -* -* platform (PACK) to AFDX (BigEndian) world, -* - a unformattind service, allowing to switch from AFDS world (BigEndian) -* to -* LittelEndian or BigEndian platform (UNPACK). -* -* A data coded on serveral bytes respecting the Big-Edian convention means -* that -* le most significant byte of the data is located at the lowest adress. -* A data coded on serveral bytes respecting the Little-Edian convention -* means -* that le less significant byte of the data is located at the lowest adress. -* -* For example, 32 bytes data which value is 0xDEADBEEF will be represented -* in -* memory as follow: -* Big-endian memory Little-endian memory -* storing convention storing convention -* Address Value Address Value -* ------- ----- ------- ----- -* @Base DE @Base EF -* @Base+1 AD @Base+1 BE -* @Base+2 BE @Base+2 AD -* @Base+3 EF @Base+3 DE -* -* Of course the principle is the same for a data coded on 16 binary digits -* (2 bytes), -* or 64 binary digits (8 bytes). -* Remark: The order of binary digit of each byte remains unchanged. -* -* For CMS-ACD needs, only services PACK/UNPACK for 16, 32 et 64 binary -* digits data are -* implemented. -* -* Particularites : -* AUCUNE -*********************************************************************/ - -/******************************************************************** -*TYPES, RESSOURCES, CONSTANTES EXPORTES -*********************************************************************/ - -typedef enum {FALSE=0, TRUE=1} BOOLEAN; - -typedef char CHAR; - -typedef unsigned char BYTE; - -typedef BYTE * TP_BYTE; - -typedef TP_BYTE const TP_BYTE_CST; - -typedef char* STRING; - -typedef STRING const STRING_CST; - -typedef float FLOAT32; - -typedef FLOAT32 * TP_FLOAT32; - -typedef double FLOAT64; - -typedef FLOAT64 * TP_FLOAT64; - -typedef signed char INT8; - -typedef INT8 * TP_INT8; - -typedef signed short INT16; - -typedef INT16 * TP_INT16; - -typedef signed int INT32; - -typedef INT32 * TP_INT32; - -typedef unsigned char UINT8; - -typedef unsigned char * TP_UINT8; - -typedef unsigned short int UINT16; - -typedef UINT16 * TP_UINT16; - -typedef unsigned int UINT32; - -typedef UINT32 * TP_UINT32; - -typedef void VOID; - -typedef void * TP_VOID; - -typedef void * const TP_VOID_CST; - -typedef unsigned short WORD16; - -typedef WORD16 * TP_WORD16; - -typedef unsigned int WORD32; - -typedef WORD32 * TP_WORD32; - -typedef unsigned long long WORD64; - -typedef WORD64 * TP_WORD64; - -typedef unsigned long long INT64; - -typedef char ** STRING_ARRAY; -# 164 "/projets/u3cat/ETUDES/ASF/DLAC_V1_3/DLAC/src/frama-c/inc/STANDARD_C.h" -/******************************************************************** -*SERVICES EXPORTES -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Me_PackBigEndian16 -******************************************************************** -* -* Fonction : -* Function : -* This macro convert a data of any type coded on 16 binary digits (Value16digits) -* into a table of 2 bytes (ValBigEndian), coded on BigEndian convention. -* This macro is independant of the platform architecture (on LittleEndian -* or BigEndian -* convention) and must be used when ever the user shall export a data coded -* on 16 binary -* digits, directlly or indirectly. -* -* Input parameters : -* - Value16digits : variable to be converted (its type doesn't matter, -* its shall -* be coded 16 binary digits) -* -* Output parameters : -* - ValBigEndian : table of 2 bytes, allocated by the user, containing -* the variable -* after conversion. -* -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Me_PackBigEndian32 -******************************************************************** -* -* Fonction : -* Function : -* This macro convert a data of any type of 32 binary digits (Value32digits) -* in a table of 4 bytes (ValBigEndian) on BigEndian convention -* This macro is not dependant on platform architecture (LittleEndian or -* BigEndian convention), -* and must be used when ever the user shall export a data of 32 binary -* digits, -* directly or indirectly. -* -* Input parameters: -* - Value32digits : variable to be convert (the type of the variable -* doesn't matter, the variable -* just needs to be coded on 32 binary digits) -* -* Ouput parameters: -* - ValBigEndian : table of 4 bytes, allocated by the user, containing -* -* the variable after conversion. -* -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Me_PackBigEndian64 -******************************************************************** -* -* Fonction : -* Function : -* This macro convert a data of any type coded on 64 binary digits (Value64digits) -* into a table of 8 bytes (ValBigEndian) on BigEndian convention. -* This macro is not dependent on the platform architecture (on LittleEndian -* or BigEndian convention) and must be used -* when ever the user shall export a data on 64 binary digits, directly -* ou indirectly. -* -* Input parameters : -* - Value64digits : variable to be converted (its type doesn't matter, -* it just -* need to be coded on 64 binary digits) -* -* Ouput parameters : -* - ValBigEndian : table of 8 octets, allocated by the user, containing -* the variable after conversion. -* -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Me_UnpackBigEndian16 -******************************************************************** -* -* Fonction : -* Function : -* This macro converts a table of 2 bytes (ValBigEndian) on BigEndian -* convention into a data of any type on 16 binary digits -* (Value16digits). -* This macro does not depend on the platform architecture -* (on LittleEndian or BigEndian convention)and must be used when ever -* the user shall interpret a data coded on 16 bits -* -* Input parameters : -* - ValBigEndian : table of 2 bytes, containing the value to convert. -* -* Ouput parameters : -* - Value16digits : converted result (whatever the type is) -* -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Me_UnpackBigEndian32 -******************************************************************** -* -* Fonction : -* Function : -* This macro converts a table of 4 bytes (ValBigEndian) on BigEndian -* convention into a data of any type on 32 binary digits -* (Value32digits). -* This macro does not depend on the platform architecture -* (on LittleEndian or BigEndian convention)and must be used when ever -* the user shall interpret a data coded on 32 bits -* -* Input parameters : -* - ValBigEndian : table of 4 bytes, containing the value to convert. -* -* Ouput parameters : -* - Value32digits : converted result (whatever the type is) -* -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Me_UnpackBigEndian64 -******************************************************************** -* -* Fonction : -* Function : -* This macro converts a table of 8 bytes (ValBigEndian) on BigEndian -* convention into a data of any type on 64 binary digits -* (Value64digits). -* This macro does not depend on the platform architecture -* (on LittleEndian or BigEndian convention)and must be used when ever -* the user shall interpret a data coded on 64 bits -* -* Input parameters : -* - ValBigEndian : table of 8 bytes, containing the value to convert. -* -* Ouput parameters : -* - Value64digits : converted result (whatever the type is) -* -*********************************************************************/ - - - -/******************************************************************** -* SERVICE UST_Se_MemCmp -******************************************************************** -* -* Fonction : -* Function : -* This service compares byte by byte, 2 blocks of NbByt bytes stored -* respectively in addresses BlocMem1 and BlocMem2. The contain of each -* byte -* is interpreted as a natural integer belonging to the range 0..255. -* -* Input parameters : -* - BlocMem1 : memory address of one of blocks to be compared -* ; -* - BlocMem2 : memory address of the other block ; -* - NbByt : number of bytes on wich the comparaison shall be done. -* -* Ouput parameters : -* -* Returned value : -* The function returns a signed integer which report the comparaison -* result: -* 0 if block1 = block2 or if NbByt is null ; -* >0 si block1 > block2 ; -* <0 si block1 < block2. -* -*********************************************************************/ -extern INT32 UST_Se_MemCmp - (const void * const /* in */ string1, - const void * const /* in */ string2, - const INT32 /* in */ size); - - -/******************************************************************** -* SERVICE UST_Se_MemCpy -******************************************************************** -* -* Fonction : -* Function : -* This service copies to memory address BlocMem1 (destination) a block -* of NbByt -* consecutive bytes stored at memory address BlocMem2 (source). -* If NbByt is null, BlocMem1 remains unchanged. -* -* Input parameters : -* - dest : address of memory block to be crushed; -* - src : address of memory block to be copied ; -* - size : number of bytes to be copied. -* -* Ouput parameters : -* -*********************************************************************/ -//extern void UST_Se_MemCpy -// (VOID * const /* out */ dest, -// const void * const /* in */ src, -// const INT32 /* in */ size); - - - -/******************************************************************** -* SERVICE UST_Se_MemMove -******************************************************************** -* -* Fonction : -* Function : -* This function copies NbOctets bytes of the area ZoneMem2 (source) in -* area ZoneMem1 -* (destination) while managing any possible overlap between the two memory -* areas. -* If NbBytes is nul, ZoneMem1 remains unchanged. -* -* Input parameters : -* - ZoneMem1 : address of the memory area which will be crushed ; -* - ZoneMem2 : address of the memory area which will be copied ; -* - NbBytes : number of bytes to be copied. -* -* Ouput parameters : -* -*********************************************************************/ -//extern void UST_Se_MemMove -// (VOID * const /* out */ dest, -// const void * const /* in */ src, -// const INT32 /* in */ size); - - - -/******************************************************************** -* SERVICE UST_Se_MemSet -******************************************************************** -* -* Fonction : -* Function : -* This service initialises a memory block of NbByt consecutive bytes located -* -* a the address BlocMem with the value ValByt. -* If NbByt is null, BlocMem remains uninitialised. -* -* Input parameters : -* - BlocMem : address of the memory area to be initialised ; -* - ValByt : value to initialise all bytes of the memory area with; -* - NbByt : number of bytes to be initialised. -* -* Ouput parameters : -* -*********************************************************************/ -//extern void UST_Se_MemSet -// (VOID * const /* out */ s, -// const INT32 /* in */ c, -// const INT32 /* in */ size); - - - -/******************************************************************** -* SERVICE UST_Se_StrCat -******************************************************************** -* -* Fonction : -* Function : -* This service concatenates a copy of string String2 (source) -* with string String1 (destination), in the order "String1String2", -* and add the character "enf of string" at the end of the result . -* The first character of String2 crushs the character end of string String1. -* The result of the concatenation is stored in String1. -* -* Input parameters : -* - String1 : address of the destination string ; -* - String2 : address of the source string. -* -* Ouput parameters : -* -* Returned code : -* -*********************************************************************/ -extern void UST_Se_StrCat - (CHAR * const /* out */ dest, - const char * const /* in */ src); - - -/******************************************************************** -* SERVICE UST_Se_StrCmp -******************************************************************** -* -* Fonction : -* Function : -* This service compares character by character the strings String1 -* and String2 by comparing their ASCII value. -* -* The comparison stops if the character "end of string" is found in one -* of -* the two strings. -* -* Input parameters : -* - String1 : address of one strings to be compared ; -* - String2 : address of the other string. -* -* Ouput parameters : -* -* Returned value : -* The function returns a signed integer which reports the result of the -* -* comparison : -* 0 if String1 = String2 -* >0 if String1 > String2 -* <0 if String1 < String2. -* -*********************************************************************/ -extern INT32 UST_Se_StrCmp - (const char * const /* in */ string1, - const char * const /* in */ string2); - - -/******************************************************************** -* SERVICE UST_Se_StrCpy -******************************************************************** -* -* Fonction : -* Function : -* This service copies the string String2 (source) int the string String1 -* (destination), until and including the characer "end of string". -* The copy stops as soon as the character "end of string" of String2(source) -* -* is encountered. -* The result od the copy is strored in String1. -* -* Input parameters : -* - String1 : address of the string to be crushed ; -* - String2 : address of the string to be copied. -* -* Ouput parameters : -* -* Returned code : -* -*********************************************************************/ - -extern void UST_Se_BisStrCpy - (CHAR * const /* out */ dest, - const char * const /* in */ src); - - -/******************************************************************** -* SERVICE UST_Se_StrLen -******************************************************************** -* -* Fonction : -* Function : -* This service returns the number of characters hold in the string "String", -* excluding the character "end of string". -* -* Input parameters : -* - String : address of the string, which the size is to be measured. -* -* Ouput parameters : -* -* Returned value : -* - the length of the string, expressed in number of bytes. -* -*********************************************************************/ -extern INT32 UST_Se_StrLen - (const char * const /* in */ string); - - -/******************************************************************** -* SERVICE UST_Se_StrnCat -******************************************************************** -* -* Fonction : -* Function : -* This service concatenates at most the NbChar firsts characters of String2 -* (source) -* after the string String1 (destination) and add the character "end of -* string" at the -* end of the result . -* The first character of String2 crushes the character "enf of string" -* of String1. -* The result of the concatenation is stored in String1. -* If NbChar is null, String remains unchanged. -* -* Input parameters : -* - String1 : address of the destination string ; -* - String2 : address of the source string ; -* - NbChar : number of characters of String2 to be concatenate after -* String1. -* -* Ouput parameters : -* -* Returned code : -* -*********************************************************************/ -extern void UST_Se_StrnCat - (CHAR * const /* out */ dest, - const char * const /* in */ src, - const INT32 /* in */ size); - - -/******************************************************************** -* SERVICE UST_Se_StrnCmp -******************************************************************** -* -* Fonction : -* Function : -* This service compares character by character at most the NbChar first -* characters of strings String1 and String2 by comparing their ASCII value. -* The comparison stops if the character "end of string" is encountered -* -* in one of the two strings. -* If NbChar is null, the service returns 0. -* -* Input parameters : -* - String1 : address of one the two strings to be compared ; -* - String2 : address of the other string ; -* - NbChar : number of characters on which the comparison must be -* done. -* -* Ouput parameters : -* -* Returned value : -* The function returns a signed integer which reports the result of -* the comparison : -* 0 if String1 = String2 or if NbByt is null ; -* >0 if String1 > String2 ; -* <0 if String1 < String2. -* -*********************************************************************/ -extern INT32 UST_Se_StrnCmp - (const char * const /* in */ string1, - const char * const /* in */ string2, - const INT32 /* in */ size); - - -/******************************************************************** -* SERVICE UST_Se_StrnCpy -******************************************************************** -* -* Fonction : -* Function : -* This service copies exactly the NbChar first characters of String2 -* (source) in String1 (destination), truncking String2 (source) or adding -* to -* String1 (destination) the character '\0' if necessary. -* If the number of characters to be copied (NbChar) is bigger than the -* number of -* characters of String2 (source), String1 (destination) is completed with -* le character '\0' until NbChar. -* If the number of characters to be copied (NbChar) is lower than the number -* of -* characters of String2 (source) AND bigger than the number of characters -* de -* String1 (destination), the character '\0' is inserted at end of copy. -* If those two conditions are not fulfilled, the character '\0' is not -* inserted at end of the copy. -* -* The result of the copy is stored in String1. -* If NbChar is null, String1 ramains unchanged. -* -* Input parameters : -* - String1 : address of the string to be crushed ; -* - String2 : address of the string to be copied ; -* - NbChar : number of characters to be copied. -* -* Ouput parameters : -* -* Returned code : -* -*********************************************************************/ -extern void UST_Se_StrnCpy - (CHAR * const /* out */ dest, - const char * const /* in */ src, - const INT32 /* in */ size); - - - -/******************************************************************** -* SERVICE UST_Me_Assert -******************************************************************** -* -* Fonction : -* assertion Macro -* -*********************************************************************/ -# 16 "TCA_Automaton.i" 2 -# 1 "TCA_Automaton.h" 1 - - - - -/******************************************************************** -* MACHINE TERMINALE TCA_Automaton -******************************************************************** -* Mnemonique : -* TCA -* -* Definition : -* TCA_Automaton is a terminal machine and is in charge of managing the states -* depending on the input events generated by TCR_FileReader or TCW_FileWriter. -* and also emitting the events based on the state transition. -* -* Particularites : -* AUCUNE -*********************************************************************/ - -/******************************************************************** -*TYPES, RESSOURCES, CONSTANTES EXPORTES -*********************************************************************/ - -typedef enum { -TCA_E_INIT=0, -TCA_E_TX_WAIT, -TCA_E_RX_WAIT, -TCA_E_TX_DATA, -TCA_E_RX_DATA -}TCA_Te_States; -/* -typedef enum{ -TCA_E_RD_BLK_KO, -TCA_E_WR_BLK_KO, -TCA_E_RD_BLK_OK, -TCA_E_WR_BLK_OK, -TCA_E_RD_FILE_REQ, -TCA_E_WR_FILE_REQ, -TCA_E_DATA, -TCA_E_TIMER_EXP, -TCA_E_OACK, -TCA_E_ACK, -TCA_E_BLK_SIZE_KO, -TCA_E_MAX_RETRY_REACHED, -TCA_E_DONE, -TCA_E_ERROR -}TCA_Te_Events; - -typedef enum{ -TCA_E_SEND_ERROR, -TCA_E_WR_BLK, -TCA_E_CLOSE_CONN, -TCA_E_START_TIMER, -TCA_E_RD_BLK, -TCA_E_SEND_WRQ, -TCA_E_SEND_RRQ, -TCA_E_SEND_ACK, -TCA_E_SEND_DATA, -TCA_E_RESEND -}TCA_Te_Emissions; - -typedef WORD32 TCA_Td_AutomatonInputs; - -typedef WORD32 TCA_Td_AutomatonOutputs; - -typedef struct{ -TCA_Td_AutomatonInputs InputEvents; -TCA_Td_AutomatonOutputs OutputEvents; -TCA_Te_States CurrentState; -}TCA_Ts_Automaton; -*/ -/******************************************************************** -*SERVICES EXPORTES -*********************************************************************/ - - - -/******************************************************************** -* SERVICE TCA_Se_Init -******************************************************************** -* -* Fonction : -* TCA_Se_Init Initializes the Client Automaton default state to INIT -* - Initialize the default maximum retry number -* -* In Parameters -* none -* -* Out Parameters -* Automaton: Automaton state information. -* -*********************************************************************/ -extern void TCA_Se_Init(); - //(TCA_Ts_Automaton * const /* out */ Automaton); - - -/******************************************************************** -* SERVICE TCA_Se_Reset -******************************************************************** -* -* Fonction : -* TCA_Se_Reset re-initialize the state to default, and turns off all the -* in and out events. -* -* Out Parameters -* Automaton: Automaton state information. -* -*********************************************************************/ -extern void TCA_Se_Reset(); - //(TCA_Ts_Automaton * const /* out */ Automaton); - - -/******************************************************************** -* SERVICE TCA_Se_Automate -******************************************************************** -* -* Fonction : -* TCA_Se_Automate evaluates the input events and change the state if necessary -* to next state -* and emits the out events. -* -* Out Parameters -* Automaton: Automaton state information. -* -*********************************************************************/ -extern void TCA_Se_Automate(); - //(TCA_Ts_Automaton * const /* in out */ Automaton); - - -/******************************************************************** -* SERVICE TCA_Se_SetEvent -******************************************************************** -* -* Fonction : -* TCA_Se_SetEvent asserts the given event. -* -* In Parameters -* Event input event raised. -* -* Out Parameters -* Automaton: Automaton state information. -* -*********************************************************************/ - -//extern void TCA_Se_SetEvent - //(const TCA_Te_Events /* in */ Event, - //TCA_Ts_Automaton * const /* out */ Automaton); - - -/******************************************************************** -* SERVICE TCA_Se_IsEventSet -******************************************************************** -* -* Fonction : -* TCA_Se_IsEvebtSet returns TRUE if the corresponding event is asserted, -* else FALSE. -* -* In Parameters -* Event: output event raised by automaton. -* -* Out Parameters -* Automaton: Automaton state information. -* -* Return Code -* returns TRUE if the corresponding event is asserted, else FALSE(BOOLEAN). -* -*********************************************************************/ -//extern BOOLEAN TCA_Se_IsEventSet - //(const TCA_Te_Emissions /* in */ Event, - //const TCA_Ts_Automaton /* in */ Automaton); -# 17 "TCA_Automaton.i" 2 -# 15 "TCA_Automaton.c" 2 - -/******************************************************************** -*RESSOURCES et CONSTANTES EXPORTEES -*********************************************************************/ - - - -// Input ports -int TCA_E_RD_BLK_KO=0; -int TCA_E_WR_BLK_KO=0; -int TCA_E_RD_BLK_OK=0; -int TCA_E_WR_BLK_OK=0; -int TCA_E_RD_FILE_REQ=0; -int TCA_E_WR_FILE_REQ=0; -int TCA_E_DATA=0; -int TCA_E_TIMER_EXP=0; -int TCA_E_OACK=0; -int TCA_E_ACK=0; -int TCA_E_BLK_SIZE_KO=0; -int TCA_E_MAX_RETRY_REACHED=0; -int TCA_E_DONE=0; -int TCA_E_ERROR=0; - -// Output ports -int TCA_E_SEND_ERROR=0; -int TCA_E_WR_BLK=0; -int TCA_E_CLOSE_CONN=0; -int TCA_E_START_TIMER=0; -int TCA_E_RD_BLK=0; -int TCA_E_SEND_WRQ=0; -int TCA_E_SEND_RRQ=0; -int TCA_E_SEND_ACK=0; -int TCA_E_SEND_DATA=0; -int TCA_E_RESEND=0; - -TCA_Te_States CurrentState; - -/******************************************************************** -*TYPES, DONNEES, CONSTANTES INTERNES -*********************************************************************/ - - - -/******************************************************************** -*TYPES, DONNEES, CONSTANTES MANUELLES -*********************************************************************/ - - - -/******************************************************************** -*SERVICES INTERNES -*********************************************************************/ -/******************************************************************** -* SERVICE TCA_Si_SetOutputEvent -******************************************************************** -* -* Fonction : -* TCA_Si_SetOutputEvent asserts output event. -* -*********************************************************************/ -//void TCA_Si_SetOutputEvent -//(const TCA_Te_Emissions /* in */ Event,TCA_Ts_Automaton* Automaton); - - -/******************************************************************** -* SERVICE TCA_Si_ClearOutputEvents -******************************************************************** -* -* Fonction : -* TCA_Si_ClearOutputEvents Clears all output events aserted. -* -*********************************************************************/ -void TCA_Si_ClearOutputEvents();//TCA_Ts_Automaton* /*out*/Automaton); - - -/******************************************************************** -* SERVICE TCA_Si_IsInputEventSet -******************************************************************** -* -* Fonction : -* TCA_Si_IsInputEventSet Returns TRUE if the given input event is -*asserted, else returns FALSE. -* -*********************************************************************/ -/* */ -//BOOLEAN TCA_Si_IsInputEventSet(const TCA_Te_Events /* in */ Event, -// TCA_Ts_Automaton* /*out*/Automaton); - -/******************************************************************** -* SERVICE TCA_Si_ClearInputEvents -******************************************************************** -* -* Fonction : -* TCA_Si_ClearInputEvents Clears all the input events -* -*********************************************************************/ -void TCA_Si_ClearInputEvents();//TCA_Ts_Automaton * /*out*/Automaton); - -/******************************************************************** -*CORPS DES SERVICES EXPORTES -*********************************************************************/ - -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Se_Init*/ -/*$********************************************************************/ -/* Description -*TCA_Se_Init Initializes the Client Automaton default state to INIT -* - Initialize the default maximum retry number -* -* In Parameters -* none -* -* Out Parameters -* Automaton: Automaton state information. -* -* Flots de controle et de donnees -*[initializes the automaton state and events to default values] -* -* Contraintes : -*********************************************************************/ -void TCA_Se_Init() -//(TCA_Ts_Automaton * const /* out */ Automaton) -{ - /*initialize the automaton to default values*/ - CurrentState = TCA_E_INIT; - - /*clear input events*/ - //Automaton->InputEvents = 0x0; - /*clear output events*/ - //Automaton->OutputEvents = 0x0; - - TCA_Si_ClearInputEvents(); - TCA_Si_ClearOutputEvents(); - -} -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Se_Reset*/ -/*$********************************************************************/ -/* Description -*TCA_Se_Reset re-initialize the state to default, and turns off all the -* in and out events. -* -* Out Parameters -* Automaton: Automaton state information. -* -* Flots de controle et de donnees -*[clears all the input events and output events, reset state to INIT] -* -* Contraintes : -*********************************************************************/ -void TCA_Se_Reset() -//(TCA_Ts_Automaton * const /* out */ Automaton) -{ - /*initialize the automaton to default values*/ - //CurrentState = TCA_E_INIT; - /*clear input events*/ - //Automaton->InputEvents = 0x0; - /*clear output events*/ - //Automaton->OutputEvents = 0x0; - - /*initialize the automaton to default values*/ - CurrentState = TCA_E_INIT; - TCA_Si_ClearInputEvents(); - TCA_Si_ClearOutputEvents(); -} -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Se_Automate*/ -/*$********************************************************************/ -/* Description -*TCA_Se_Automate evaluates the input events and change the state if necessary -* to next state -* and emits the out events. -* -* Out Parameters -* Automaton: Automaton state information. -* -* Flots de controle et de donnees -*[automates the input events depending on the current state of the automaton] -* -* Contraintes : -*********************************************************************/ -/*@ -@ requires TCA_E_RD_FILE_REQ==0 || TCA_E_RD_FILE_REQ==1; -@ requires TCA_E_WR_FILE_REQ==0 || TCA_E_WR_FILE_REQ==1; -@ requires TCA_E_DATA==0 || TCA_E_DATA==1; -@ requires TCA_E_ACK==0 || TCA_E_ACK==1; -@ requires TCA_E_TIMER_EXP==0 || TCA_E_TIMER_EXP==1; -@ requires TCA_E_WR_BLK_OK==0 || TCA_E_WR_BLK_OK==1; -@ requires TCA_E_RD_BLK_OK==0 || TCA_E_RD_BLK_OK==1; -@ requires TCA_E_RD_BLK_KO==0 || TCA_E_RD_BLK_KO==1; -@ requires TCA_E_WR_BLK_KO==0 || TCA_E_WR_BLK_KO==1; -@ requires TCA_E_BLK_SIZE_KO==0 || TCA_E_BLK_SIZE_KO==1; -@ requires TCA_E_MAX_RETRY_REACHED==0 || TCA_E_MAX_RETRY_REACHED==1; -@ requires TCA_E_DONE==0 || TCA_E_DONE==1; -@ requires TCA_E_OACK==0 || TCA_E_OACK==1; -@ requires TCA_E_ERROR==0 || TCA_E_ERROR==1; -@ requires TCA_E_SEND_RRQ==0 || TCA_E_SEND_RRQ==1; -@ requires TCA_E_SEND_WRQ==0 || TCA_E_SEND_WRQ==1; -@ requires TCA_E_START_TIMER==0 || TCA_E_START_TIMER==1; -@ requires TCA_E_SEND_DATA==0 || TCA_E_SEND_DATA==1; -@ requires TCA_E_CLOSE_CONN==0 || TCA_E_CLOSE_CONN==1; -@ requires TCA_E_RD_BLK==0 || TCA_E_RD_BLK==1; -@ requires TCA_E_WR_BLK==0 || TCA_E_WR_BLK==1; -@ requires TCA_E_RESEND==0 || TCA_E_RESEND==1; -@ requires TCA_E_SEND_ERROR==0 || TCA_E_SEND_ERROR==1; -@ requires TCA_E_SEND_ACK==0 || TCA_E_SEND_ACK==1; -@ behavior state_RX_WAIT: -@ assumes CurrentState==TCA_E_RX_WAIT; -@ ensures from_RX_WAIT_to_INIT2_1 : (\old(TCA_E_BLK_SIZE_KO)) && !(\old(TCA_E_OACK) && ! (\old(TCA_E_BLK_SIZE_KO))) ==> CurrentState==TCA_E_INIT; -@*/ -void TCA_Se_Automate() -//(TCA_Ts_Automaton * const /* in out */ Automaton) -{ - /*temparry flag to store the event status*/ - BOOLEAN TempFlag=FALSE; - - /* Clear output events.*/ - TCA_Si_ClearOutputEvents();//Automaton); - - /*automate the emission and chagne of state depending on the current state - * and input event.*/ - switch(CurrentState) - { - - - - case TCA_E_RX_WAIT: - /*If the block size negotiation failed*/ - if(TCA_E_BLK_SIZE_KO == TRUE) - { - /* send error, close connection and change state to init*/ - TCA_E_SEND_ERROR = TRUE; - - /*raise close connectin event*/ - TCA_E_CLOSE_CONN = TRUE; - - /* change state to TCA_E_INIT*/ - CurrentState = TCA_E_INIT; - } - /*when OACK event is raised*/ - if(TCA_E_OACK == TRUE) - { - /*if block size is ok*/ - if(!(TCA_E_BLK_SIZE_KO == TRUE)) - { - /* raise send ACK and start timer event */ - TCA_E_SEND_ACK = TRUE; - - /*raise TCA_E_START_TIMER event*/ - TCA_E_START_TIMER = TRUE; - } - - } - /* when DATA event is raised*/ - else if(TCA_E_DATA == TRUE) - { - - /*if not final ack*/ - if(!(TCA_E_DONE == TRUE)) - { - /*raise write block event and change state to RX_DATA*/ - TCA_E_WR_BLK = TRUE; - CurrentState = TCA_E_RX_DATA; - } - } - /* when timer exp event is raised */ - else if(TCA_E_TIMER_EXP == TRUE) - { - /*store TCA_E_MAX_RETRY_REACHED status in to TempFlag*/ - TempFlag = - (TCA_E_MAX_RETRY_REACHED == TRUE); - /*if neither maximum retry reached nor transfer is completed*/ - if(! (TempFlag==TRUE - || (TCA_E_DONE == TRUE))) - { - /* raise resend event*/ - TCA_E_RESEND = TRUE; - } - } - /* wehen timer expire event is raised and */ - else if(TCA_E_TIMER_EXP == TRUE) - { - TempFlag = - (TCA_E_MAX_RETRY_REACHED == TRUE); - /*if either maximum retry reached or transfer is completed*/ - if(TempFlag==TRUE - || (TCA_E_DONE == TRUE)) - { - /*raise close connection and change state to INIT*/ - TCA_E_CLOSE_CONN = TRUE; - - /* change state to TCA_E_INIT*/ - CurrentState = TCA_E_INIT; - } - - } - else - { - /*Invalid input event.*/ - } - - break; - - default: - break; - } - - /*clear all the input events as ther processing is comleted*/ - TCA_Si_ClearInputEvents();//Automaton); -} -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Se_SetEvent*/ -/*$********************************************************************/ -/* Description -*TCA_Se_SetEvent asserts the given event. -* -* In Parameters -* Event input event raised. -* -* Out Parameters -* Automaton: Automaton state information. -* -* Flots de controle et de donnees -*[set the corresponding event to TRUE, to say it is raised] -* -* Contraintes : -*********************************************************************/ -//void TCA_Se_SetEvent -//(const TCA_Te_Events /* in */ Event, -// TCA_Ts_Automaton * const /* out */ Automaton) -//{ -// /* Set Event raised indication in Automaton->InputEvents */ -// Automaton->InputEvents = (TCA_Td_AutomatonInputs) -// ((1<<(WORD32)Event)|Automaton->InputEvents); -// -//} -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Se_IsEventSet*/ -/*$********************************************************************/ -/* Description -*TCA_Se_IsEvebtSet returns TRUE if the corresponding event is asserted, -* else FALSE. -* -* In Parameters -* Event: output event raised by automaton. -* -* Out Parameters -* Automaton: Automaton state information. -* -* Return Code -* returns TRUE if the corresponding event is asserted, else FALSE. -* -* Flots de controle et de donnees -*[returns TRUE if the requested event is raised] -* -* Contraintes : -*********************************************************************/ -//BOOLEAN TCA_Se_IsEventSet -//(const TCA_Te_Emissions /* in */ Event, -// const TCA_Ts_Automaton /* in */ Automaton) -//{ -// /*TRUE if the corresponding event is asserted, else FALSE*/ -// return (BOOLEAN)((0x0001) & (Automaton.OutputEvents>>(INT32)Event)); -//} - -/*$*/ -/******************************************************************** -*CORPS DES SERVICES INTERNES -*********************************************************************/ -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Si_SetOutputEvent*/ -/*$********************************************************************/ -/* Description -*TCA_Si_SetOutputEvent asserts the given event in to output event list. -* -* In Parameters -* Event output event raised. -* -* Flots de controle et de donnees -* AUCUN -* Contraintes : -*********************************************************************/ -//void TCA_Si_SetOutputEvent -//(const TCA_Te_Emissions /* in */Event,TCA_Ts_Automaton* /*out*/ Automaton) -//{ -// -// /* Set Event raised indication in Automaton->InputEvents */ -// Automaton->OutputEvents = (TCA_Td_AutomatonOutputs) -// ((1<<(WORD32)Event)|Automaton->OutputEvents); -// -//} - -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Si_ClearOutputEvents*/ -/*$********************************************************************/ -/* Description -*TCA_Si_ClearOutputEvents clears output events list. -* -* Flots de controle et de donnees -* AUCUN -* Contraintes : -*********************************************************************/ -/*@ ensures (TCA_E_SEND_ERROR==0); - @ ensures (TCA_E_WR_BLK==0); - @ ensures (TCA_E_CLOSE_CONN==0); - @ ensures (TCA_E_START_TIMER==0); - @ ensures (TCA_E_RD_BLK==0); - @ ensures (TCA_E_SEND_WRQ==0); - @ ensures (TCA_E_SEND_RRQ==0); - @ ensures (TCA_E_SEND_ACK==0); - @ ensures (TCA_E_SEND_DATA==0); - @ ensures (TCA_E_RESEND==0); - @*/ -void TCA_Si_ClearOutputEvents() -//(TCA_Ts_Automaton* /*out*/Automaton) -{ - - /* Cleare output events list */ - //Automaton->OutputEvents = 0; - - TCA_E_SEND_ERROR=0; - TCA_E_WR_BLK=0; - TCA_E_CLOSE_CONN=0; - TCA_E_START_TIMER=0; - TCA_E_RD_BLK=0; - TCA_E_SEND_WRQ=0; - TCA_E_SEND_RRQ=0; - TCA_E_SEND_ACK=0; - TCA_E_SEND_DATA=0; - TCA_E_RESEND=0; -} - -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Si_SetOutputEvent*/ -/*$********************************************************************/ -/* Description -*TCA_Se_IsEvebtSet returns TRUE if the corresponding event is asserted, -* else FALSE. -* -* In Parameters -* Event: input event. -* -* Retur Code -* returns TRUE if the corresponding event is asserted, else FALSE -* -* Flots de controle et de donnees -* AUCUN -* Contraintes : -*********************************************************************/ -//BOOLEAN TCA_Si_IsInputEventSet -//(const TCA_Te_Events /* in */ Event,TCA_Ts_Automaton*/*out*/ Automaton) -//{ -// /*TRUE if the corresponding event is asserted, else FALSE*/ -// return ((BOOLEAN)((0x0001) & (Automaton->InputEvents>>(INT32)Event))); -// -//} - - -/*$*/ -/*$********************************************************************/ -/*$ SERVICE TCA_Si_ClearInputEvents*/ -/*$********************************************************************/ -/* Description -*TCA_Si_ClearInputEvents clears input events list. -* -* Flots de controle et de donnees -* AUCUN -* Contraintes : -*********************************************************************/ -/*@ - @ ensures (TCA_E_RD_BLK_KO == 0); - @ ensures (TCA_E_WR_BLK_KO == 0); - @ ensures (TCA_E_RD_BLK_OK == 0); - @ ensures (TCA_E_WR_BLK_OK == 0); - @ ensures (TCA_E_RD_FILE_REQ == 0); - @ ensures (TCA_E_WR_FILE_REQ == 0); - @ ensures (TCA_E_DATA == 0); - @ ensures (TCA_E_TIMER_EXP == 0); - @ ensures (TCA_E_OACK == 0); - @ ensures (TCA_E_ACK == 0); - @ ensures (TCA_E_BLK_SIZE_KO == 0); - @ ensures (TCA_E_MAX_RETRY_REACHED == 0); - @ ensures (TCA_E_DONE == 0); - @ ensures (TCA_E_ERROR == 0); - @*/ -void TCA_Si_ClearInputEvents()//TCA_Ts_Automaton*/*out*/ Automaton) -{ - - /* Cleare output events list */ - //Automaton->InputEvents = 0; - - TCA_E_RD_BLK_KO=0; - TCA_E_WR_BLK_KO=0; - TCA_E_RD_BLK_OK=0; - TCA_E_WR_BLK_OK=0; - TCA_E_RD_FILE_REQ=0; - TCA_E_WR_FILE_REQ=0; - TCA_E_DATA=0; - TCA_E_TIMER_EXP=0; - TCA_E_OACK=0; - TCA_E_ACK=0; - TCA_E_BLK_SIZE_KO=0; - TCA_E_MAX_RETRY_REACHED=0; - TCA_E_DONE=0; - TCA_E_ERROR=0; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/test_result1.c frama-c-20111001+nitrogen+dfsg/tests/wp/test_result1.c --- frama-c-20110201+carbon+dfsg/tests/wp/test_result1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/test_result1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -int * r; - -/*@ ensures *r == 1; */ -int g2() { - r = (int*)malloc(sizeof(int)); - return *r; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/threat.c frama-c-20111001+nitrogen+dfsg/tests/wp/threat.c --- frama-c-20110201+carbon+dfsg/tests/wp/threat.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/threat.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -int main(int x, int y) { - - if (x >= 10) x = 10; else if (x <= 0) x = 0; - - if (x*x-10 > 0) - //@ assert (x*x-8) != 0; - return 1/(x*x-8); - - return 0; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Type2Ex1.c frama-c-20111001+nitrogen+dfsg/tests/wp/Type2Ex1.c --- frama-c-20110201+carbon+dfsg/tests/wp/Type2Ex1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Type2Ex1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -char Buffer[1040] ; - -// note: properties named "oracle_ko" are not true ! -/*@ - -assigns Buffer[..]; - -exits never: oracle_ok: \false; - -behavior b1: - ensures p1: oracle_ok: - \forall integer k ; 0 <= k < 3 - ==> Buffer[k] == \old(Buffer[k]); - ensures p1_ko: oracle_ko: - \forall integer k ; 0 <= k < 4 - ==> Buffer[k] == \old(Buffer[k]); - -behavior b2: - ensures p2: oracle_ok: - \forall integer k ; 0 <= k < nb - ==> Buffer[k+3] == \old(buffer[k]); - ensures p2_ko: oracle_ko: - \forall integer k ; 0 <= k < nb - ==> Buffer[k] == \old(buffer[k]); - -behavior b3: - ensures p3: oracle_ok: - \forall integer k ; nb+3 <= k < 1040 - ==> Buffer[k] == \old(Buffer[k]); - ensures p3_ko: oracle_ko: - \forall integer k ; nb <= k < 1040 - ==> Buffer[k] == \old(Buffer[k]); - - - */ -void Type2Ex1 (const char * buffer, int nb) -{ - int i ; - /*@ loop assigns i, Buffer[3..(3+(i-1))]; - loop invariant i0: oracle_ok: 0 <= i && (0 <= nb ==> i <= nb) ; - for b1: loop invariant b1: oracle_ok: - \forall integer k ; 0 <= k < 3 - ==> Buffer[k] == \at(Buffer[k],Pre); - for b2: loop invariant b2: oracle_ok: - \forall integer k ; 0 <= k < i - ==> Buffer[k+3] == \at(buffer[k],Pre); - for b3: loop invariant b3: oracle_ok: - \forall integer k ; nb+3 <= k < 1040 - ==> Buffer[k] == \at(Buffer[k],Pre); - loop variant decr: oracle_ok: nb - i ; - */ - for (i = 0 ; i < nb ; i++) - Buffer[3+i] = buffer[i] ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Type3Ex3.c frama-c-20111001+nitrogen+dfsg/tests/wp/Type3Ex3.c --- frama-c-20110201+carbon+dfsg/tests/wp/Type3Ex3.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Type3Ex3.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -typedef float Numeric ; -/*@ assigns \nothing ; - @*/ -Numeric f (Numeric num1,Numeric num1) ; - -typedef const struct { Numeric i; Numeric j;} Numeric2; -void Type3Ex3 (int e1, Numeric *p1, Numeric2 t1[], Numeric t2[]) { - - int s ; - while ((s < (sizeof (t1) / sizeof (Numeric2)) - 2) && - (e1 >= t1[s + 1].i)) - //@ assert \false; - s = s + 1 ; - *p1 = f (e1 - t1[s].i, t2[s]) + t1[s].j ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Type4Ex2.c frama-c-20111001+nitrogen+dfsg/tests/wp/Type4Ex2.c --- frama-c-20110201+carbon+dfsg/tests/wp/Type4Ex2.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Type4Ex2.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -/*@ assigns \nothing; - exits never: oracle_ok: \false ; -// behavior found: -// assumes \exists int k ; 0 <= k < 15 && t1[k] != t2[k] ; -// ensures oracle_ok: \result == 0 ; -// behavior not_found: -// assumes \forall int k ; 0 <= k < 15 ==> t1[k] == t2[k] ; -// ensures oracle_ok: \result == 1 ; -// complete behaviors found, not_found ; -// disjoint behaviors found, not_found ; - */ -int Type4Ex2 (int t1[], int t2[]) { - int i ; - -// /*@ loop assigns i; -// loop invariant I0: oracle_ok: 0 <= i <= 15 ; -// loop invariant not_yet_found: oracle_ok: \forall int k ; 0 <= k < i ==> t1[k] == t2[k] ; -// */ - for (i = 0 ; i < 15 ; i++) - /*@ assigns \nothing; - */ - if (t1[i] != t2[i]) - return 0 ; - return 1 ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/Type6Ex1.c frama-c-20111001+nitrogen+dfsg/tests/wp/Type6Ex1.c --- frama-c-20110201+carbon+dfsg/tests/wp/Type6Ex1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/Type6Ex1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* run.config - DONTRUN: test under construction -*/ - -/*@ axiomatic DISTANCE_INT { - @ logic int Distance_int (int x, int y) ; - @ axiom r: - \forall int x ; - Distance_int (x,x) == 0 ; - @ axiom s: - \forall int x, y ; - Distance_int (x,y) + Distance_int (y,x) == 0 ; - @ } - @*/ - -/*@ assigns \nothing ; - ensures result: \result == Distance_int (val1, val2) ; - exits never: \false ; - @*/ -int distance_int (int val1, int val2) ; - -/*@ assigns \nothing ; - exits never: oracle_ok: \false ; - - @ behavior not_found: - assumes \forall int k ; 0 <= k < 10 ==> 0 == Distance_int (tab[k], tabref[k]) ; - ensures oracle_ok: \result == 1 ; - - @ behavior found: - assumes \exists int k ; 0 <= k < 10 && 0 != Distance_int (tab[k], tabref[k]) ; - ensures oracle_ok: \result == 0 ; - - @ complete behaviors not_found, found ; - @ disjoint behaviors not_found, found ; - @*/ -char Type6Ex1(int tab [10], int tabref[10]) { - int i = 0 ; - char control_ok = 1 ; - - /*@ loop assigns i, control_ok ; - loop invariant I0: oracle_ok: 0 <= i <= 10 ; - loop invariant C0: oracle_ok: 0 == control_ok || control_ok == 1 ; - loop invariant I0_C0: oracle_ok: 0 == control_ok ==> i < 10 ; - loop invariant not_yet_found: oracle_ok: - control_ok==1 ==> \forall int k ; 0 <= k < i ==> 0 == Distance_int (tab[k], tabref[k]) ; - loop invariant not_found_before: oracle_ok: - control_ok==0 ==> 0 != Distance_int (tab[i], tabref[i]) ; - @ loop variant decr: oracle_ok: (control_ok==1) ? (10 - i) : 0; - @*/ - while (i < 10 && control_ok) - if (0 == distance_int (tab[i], tabref[i])) - i++ ; - else - control_ok = 0 ; - return control_ok ; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_acsl.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_acsl.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_acsl.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_acsl.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ - -// Be carreful : this is not the real definition (TODO : change that) -int * NULL = (int*) 0; - //@ global invariant null_inv : NULL == \null; - -int G, X, T[10]; - -void tnull () { - int * p; - p = &G; - //@ assert (p != \null) ; - p = NULL; - //@ assert (p == \null) ; -} - -// @ ensures \result == \min(x, y); TODO : at the moment \min has a wrong type -int min (int x, int y) { - return x < y ? x : y; -} - -/*@ ensures \separated (\result, &X); */ -int * ptrX (int * p) { - p = &G; - return p; -} - -/*@ requires 0 < n; - ensures \result <= n; -*/ -int loop (int n) { - int i, s = 0; - /*@ loop invariant s <= i && 0<= i <= n; - loop assigns i, s; - loop variant (n - i); - */ - for (i = 0; i < n; i++) { - if (T[i] == 0) s++; - } - - return s; -} - -//@ ensures \result <= n; -int stmt_contract (int n) { - int i, s = 0; - /*@ ensures s <= n; - assigns i, s; - */ - //@ loop invariant s <= i && 0<= i <= n; - for (i = 0; i < n; i++) { - if (T[i] == 0) s++; - } - - return s; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_arith.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_arith.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_arith.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_arith.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* run.config - OPT: -journal-disable -wp -wp-model Hoare -wp-proof none -wp-print -*/ - -/* run.config_phoare - OPT: -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -// Tests on arithmertic problem : only needs Hoare. -// See [wp_bits.c] for examples on bit representation. - - -/*@ behavior KO : ensures \result == 10; - behavior ok : ensures \result == 0; -*/ -char implicit_char_cast (void) { - unsigned char i = 0; - signed char x = -1; - // in this example, both [char] are first promoted to [int], - // so the comparition gives the intuitive result (see [implicit_cast] below) - return (x < i) ? 0 : 10; -} - -/*@ behavior ok : ensures \result == 10; - behavior KO : ensures \result == 0; -*/ -int implicit_cast (void) { - unsigned int i = 0; - signed int x = -1; - // in this example, both variables are converted to [unsigned int], - // so the result of the comparison looks strange... - return (x < i) ? 0 : 10; -} - -/*@ behavior KO : ensures \result < 0; - behavior ok : ensures \result >= 0; -*/ -unsigned char cast_sgn_usgn (void) { - char x = -1; - return x; -} - -// This one is ok. -unsigned char uchar_range (unsigned char i) { - //@ assert i >= 0; - //@ assert i <= 255; - return i; -} - - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_array.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_array.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_array.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_array.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -typedef struct S { - int r ; - int f[7] ; - int g[5] ; -} ; - - -int a[10] ; -struct S s ; - -void f(void) -{ - //@assert s.g == s.f + 7 ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_assign.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_assign.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_assign.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_assign.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-proof simplify -wp-print -wp-verbose 2 -*/ - - -int C; - -/*@ behavior ok : - ensures C == \at(c, Pre); - ensures \at(c, Pre) == c; // param cannot be modified by a function. - behavior ko : - ensures C == \at(C, Pre); // false : global var has been modified. -*/ -void f0 (int x,int c) { - C = c; - c = x; - c++; - //@ assert x == c-1; -} - -//@ ensures \result == x+3; -char fchar (char x) { - char y = 3; - return x+y; -} - -// simplest example of assignment... -int f1() { - int x; - x = 0; - x++; - //@ assert x == 1; - return 0; -} - -/*@ requires y == 12 ; */ -int f2(int y) { - int x; - x = y; - //@ assert x == 12; - if (x == 0) x++; else x = 1; - //@ assert x == 1; - return 0; -} - -//@ ensures (x < 3) ==> \result == 0; -int f3a (int x) { - return (x > 3) ? 1 : 0; -} - -//@ ensures (x < 3) ==> \result == 0; -int f3b (int x) { - int c = (x > 3); - return c; -} - -/*@ ensures (x != 0) ==> \result == 1; - ensures (x == 0) ==> \result == 0; - */ -int f3c (int x) { - return x ? 1 : 0; -} - -struct Ts {int x; int y; }; -struct Tstr {int a; struct Ts s; int t[10]; struct Tstr * p; } S; - -/*@ ensures S.a == x ; - ensures S.p == \old(S.p) ; - ensures S == { \old(S) \with .a = x }; - */ -void rw_int_field (int x) { - S.a = x; -} -//@ ensures S.s.x == x && S.s == { \old(S.s) \with .x = x }; -void rw_field_field (int x) { - S.s.x = x; -} -/*@ ensures S.a == \old(S.a) && S.t[i] == x; - // TODO: ensures S == { \old(S) \with .t[i] = x }; -*/ -void rw_tab_field (int i, int x) { - S.t[i] = x; -} -/*@ requires S.p == &S || \separated (S.p, &S); - @ ensures S.p->a == x ; - @ ensures \forall int i; (*(S.p)).t[i] == \old((*(S.p)).t[i]); - */ -void rw_ptr_field (int x) { - S.p->a = x; -} - -int T[10]; - -/*@ ensures T[i] == x; - ensures \forall int j; i != j ==> T[j] == \old(T[j]); - ensures T == { \old(T) \with [i] = x}; -*/ -void rw_array_elem (int i, int x) { - T[i] = x; -} - -int * P; - -//@ ensures *P == x && P == \old(P); -void rw_pointer (int x) { - *P = x; -} - -/*@ requires \valid(P+i) && \separated(&P, P+i); - @ ensures *(P + i) == x && P == \old(P); - @ ensures \forall int j; i != j ==> *(P + j) == \old(*(P + j)); -*/ -void rw_shift_pointer (int i, int x) { - *(P+i) = x; -} - -/*@ ensures ko: \forall int k; k == i+j ==> *(P + k) == x; - ensures ok1: \forall int k; k == i+j ==> *(\old(P) + k) == x; - behavior ok: - assumes \valid (P+i+j); - ensures ok2: \forall int k; k == i+j ==> *(P + k) == x; -*/ -void rw_shift_shift_pointer (int i, int j, int x) { - *(P+i+j) = x; -} - -// Notice that there is no real indirect access : should be checked by M0... -/*@ ensures T[i+j] == x; - @ ensures *(T+(i+j)) == x; - @ ensures *(T+i+j) == x; -*/ -void rm_shift_array_elem (int i, int j, int x) { - *(T+i+j) = x; -} - -// No indirect access -//@ ensures \result == &(T[i]); -int * return_ptr (int i) { - return T+i; -} - -// No indirect access -//@ ensures P == T+(i+1); -void assign_pointer (int i) { - P = T+i; - P++; -} - -// No indirect access -//@ ensures \result == &(S.t[1]); -int * return_St1 (void) { - int * p = S.t; - return p+1; -} - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_behav.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_behav.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_behav.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_behav.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,167 +0,0 @@ - -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-fct assert_needed -wp-prop ok_with_hyp -wp-print -wp-verbose 2 - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -wp-prop ko1 -OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -wp-prop e1 -COMMENT: next test should be elsewhere in a wp_options.c test file because it is made to test -wp-prop for une assign property (nothing to do with phoare...) -OPT: -journal-disable -rte -wp -wp-model Store -wp-proof alt-ergo -wp-print -wp-verbose 2 -wp-prop asgn_ok -wp-fct stmt_contract_assigns -*/ - -int X, Y, Z; - -/*@ - @ ensures \result > x; - @ behavior x1: - @ assumes x == 1; - @ ensures \result == 3; - @ behavior x2: - @ assumes x == 2; - @ ensures \result == 4; - @ -*/ -int f (int x) { - x++; - //@ for x1: assert x == 2; - //@ for x2: assert x == 3; - return x+1; -} - -/*@ - behavior bx : - assumes x <= y; - ensures \result == x; - behavior by : - assumes x > y; - ensures \result == y; - complete behaviors bx, by; - disjoint behaviors bx, by; -*/ -int min (int x, int y) { - return (x < y) ? x : y; -} - -/*@ requires n != 0; - behavior pos : - assumes n > 0; - ensures \result == x/n; - behavior neg : - assumes n < 0; - ensures \result == x/-n; - complete behaviors pos, neg; // notice that this needs the requires hyp -*/ -int bhv (int x, int n) { - n = (n<0) ? -n : n; - return x/n; -} - -/*@ behavior ok: ensures \result > 0; - behavior ko : ensures \result > 2; - behavior ko_without_asgn : ensures \result > Y; -*/ -int stmt_contract (int c) { - int x = 0; - Y = 0; - - /*@ requires x == 0; - @ ensures x > 0; - */ - if (c) - x = 3; - else - x = 5; - return x; -} - -//@ ensures \result >= 0; -int stmt_contract_label (int c) { - int x = 0; - - //@ ensures x >= \old(x); - if (c) x++; - - return x; -} - -/*@ behavior ok: ensures \result > 0; - behavior ko : ensures \result > 2; - behavior ok_asgn : ensures \result > Y; -*/ -int stmt_contract_assigns (int c) { - int x = 0; - Y = 0; - - /*@ requires x == 0; - @ ensures x > 0; - @ assigns asgn_ok: x; - */ - if (c) - x = 3; - else - x = 5; - return x; -} - -int local_named_behavior (int x) { - int y = 3; - /*@ behavior xpos : - assumes x > 0; - ensures x > 3; - */ - x += y; - return x; -} - -void assert_needed (int x) { - //@ assert ko : x > 0; - int a = 0; - a += x; - //@ assert ok_with_hyp : a > 0; -} - -/* we shouldn't be able to prove ko1 from ko2 and then ko2 from ko1 */ -/*@ ensures ko1 : \result == x+1; - ensures ko2 : \result == x+1; -*/ -int bts0513 (int x) { - return x; -} - -//@ assigns X, Y; -void unknown (int, int); - -//@ ensures \result > X; -int stmt_assigns (int a) { - int x = 0; - int y = 3; - X = x; - //@ assigns Y; - unknown (x, y); - x = x+1; - return x; -} - -int T[10]; - -// use Inv as Hyp for Bhp props -/*@ requires n < 10; - behavior b1 : assumes 0<n; ensures e1: T[0] == 0; - */ -void razT (int n) { - - //@ loop invariant \forall int k; 0<= k < i ==> T[k] == 0; - for (int i = 0; i < n; i++) - T[i] = 0; -} - -//@ ensures ok_with_hoare: T[1] == \old(T[1]); -int more_stmt_assigns (int x) { - x = 0; - //@ behavior blk: assigns x, T[x]; - { - T[x] = 1; - x = 1; - } - return x; -} -//============================================================================== diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_bits.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_bits.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_bits.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_bits.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ - -void test_bw_and() { - //@ assert (3&1) == 1; -} - -//@ ensures \result == ~1; -int main() -{ - char c1 = 1, c2 = 2; - char c3,c4,c5,c6,c7,c8; - c3 = c1 & c2; - //@ assert c3 == 0 ; - c4 = c1 | c2; - //@ assert c4 == 3 ; - c5 = c1 ^ c2; - //@ assert c5 == 3 ; - c6 = ~c1; - //@ assert c6 == 254 ; - c7 = c1<<2; - //@ assert c7 == 4 ; - c8 = c1>>2; - //@ assert c8 == 0; - return (1^-1); -} - - - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_call.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_call.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_call.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_call.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 - OPT: -rte -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -struct Ts { int a; int b; }; -int G; -struct Ts S; -int * P; -int T[10]; -int X; - -//------------------------------------------------------------------------------ -/*@ - requires \true; - assigns G, S.b; - ensures G == \old(G) + x + 1 - && S.b == \old(S.b) + 1 - && \result == x + 1; -*/ -int add_G (int x) { - x++; - G += x ; - S.b++; - return x; -} - -/*@ - requires G == 0; - ensures G == 6 && S.a == 1 && S.b == 1 && \result == 6; -*/ -int main(void) { - int r; - - S.a = 1; - S.b = 0; - - r = add_G (5); - - return r; -} -//------------------------------------------------------------------------------ - -// this is to test the assigns order : T[X] is T[\old(X)] ! -//@ assigns T[X], T[X+1], X; -void f (int x) { - T[X] = 0; - T[X+1] = 0; - X = x; -} - -// Be carreful : wrong translation of quantification in M2 -//@ ensures (\forall int i; 2 <= i < 10 ==> T[i] == \old(T[i])); -void call_f (void) { - int a = 3; - X = 0; - f (a); -} - -/*@ ensures ko0: (T[0] == \old(T[0])); //false - ensures ko1: (T[1] == \old(T[1])); // false - ensures ok: (T[2] == \old(T[2])); //true - */ -void call_f_1 (void) { - int a = 3; - X = 0; - f (a); -} - -//@ assigns T[m..M]; -void array_range (int m, int M); - -/*@ ensures ok: (T[1] == \old(T[1])); - ensures ko: (T[5] == \old(T[5])); - assigns T[2..5]; -*/ -void call_array_range (void) { - int i = 2; - int j = 5; - array_range (i, j); -} - -//------------------------------------------------------------------------------ -/* This is to test that M0 is able to handle a call with a pointer parameter - * as long as it takes an address as argument. */ -/*@ requires \valid(p); - ensures *p == \old(*p) + 1; - assigns *p; -*/ -void incr (int * p) { - (*p) ++; -} -//@ ensures \result == x + 1; -int call_incr (int x) { - incr (&x); - return x; -} -//@ ensures S.a == \old(S.a) + 1; -void call_incr_on_S (void) { - incr (&(S.a)); -} -//@ ensures T[i] == \old(T[i]) + 1; -void call_incr_on_Ti (int i) { - incr (T+i); -} -//@ ensures T[0] == \old(T[0]) + 1; -void call_incr_on_T (void) { - incr (T); -} -//------------------------------------------------------------------------------ -// This is to test [assigns \nothing] -//@ assigns \nothing; -void print (int); - -//@ ensures \result == \old(X) + x; -int just_print (int x) { - print (x); - return X + x; -} -//------------------------------------------------------------------------------ -// This is to test call when assigns are not specified. -// We have to provide a body, else the kernel add a default assigns nothing ! -void unknown (void) { return; } - -// TODO : this test is wrong at the moment ! -/*@ -@ ensures ko: X == \old(X); - // this one is not provable since we don't know whether [unknown] modifies X -@ ensures ok: \result == X; -*/ -int call_unknown (void) { - unknown (); - return X; -} -//------------------------------------------------------------------------------ - -/*@ - requires x >0 ; - ensures \result == x; - */ - -int f1 (int x) -{ - return x; -} - -/*@ ensures \result == 1; - */ -int call_f1 (void) -{ int a = 1 ; return f1(a);} - -//------------------------------------------------------------------------------ -// This is to check that the result is processed even if it is not specified. - -//@ assigns \nothing; -int unknown_result (void); - -//@ ensures KO : \result == 0; -int call_unknown_result (void) { - int x = 0; - x = unknown_result (); - return x; -} -//------------------------------------------------------------------------------ -// This is to check that the result is correctly processed -// even if it is specified in 2 post-conditions. - -/*@ assigns \nothing; - ensures \result >= 0; - ensures \result < 10; -*/ -int spec2_result (void); - -//@ ensures ok : \result < 20; -int call_spec2_result (void) { - int x = 0; - x = spec2_result (); - return x; -} -//------------------------------------------------------------------------------ diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_call_ptr.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_call_ptr.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_call_ptr.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_call_ptr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* assigns *p; */ -int * P; -/*@ - ensures *P == 0; -*/ -void razP (void) { - *P = 0; -} -/*@ - ensures *p == 0; -*/ -void raz (int * p) { - *p = 0; -} -/*@ assigns *p; - ensures *p == \old(*p) + 1; -*/ -void incr (int * p) { - (*p)++; -} - -//@ ensures \result == 0; -int call_raz (void) { - int x; - raz (&x); - return x; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_caveat_subst.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_caveat_subst.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_caveat_subst.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_caveat_subst.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ - -/* - model name : UnsafeCaveat - kind : Positive - bhv : first part Provable; last part not yet finished -*/ - -int X; -int *P; - -void var_subst_const (void) { - int x = 3; - //@ assert ok: x == 3; -} - -void var_subst_var (int x) { - int y = x + 1; - //@ assert ok: y == x + 1; - x = x + 1; - //@ assert ok: y == x; -} -void assign_ptr (void) { - int x; - int * p = &x; - //@ assert ok: p == &x; -} -//@ ensures ok: \result == &X; -int * return_addr (void) { - return &X; -} - -//@ ensures should_be_ok: *p == 3; -void ptr_subst (int * p) { - *p = 3; - //@ assert ok: *p == 3; -} -void ptr_on_var (void) { - int x = 0; - int * p = &x; - //@ assert ok1: *p == 0; - *p = 3; - //@ assert ok2: *p == 3; - //@ assert not_supported: x == 3; - //@ assert unsafe_err_ok: x == 0; -} -//@ ensures should_be_ok: \result == *p; -int read_ptr (int * p) { - int y = *p; - //@ assert ok: y == *p; - return y; -} -int read_ptr_shift (int * p) { - int i = 3; - int y = *(p + i); - //@ assert ok: y == *(p+3); - return y; -} -void shift_ptr (int * p) { - *p = 1; -L: p++; - *p = 2; - //@ assert ok1: *p == 2; - //@ assert ok2: *(p-1) == 1; - //@ assert not_supported: \at(p, Pre)[1] == 2; - //@ assert ok3: \at(*p, L) == 1; -} - -struct Tstr { int a; int b; int * p; int t[10]; }; - -void caveat_havoc_field (struct Tstr * p) { - //@ assigns p->a; - { - p->a = 0; - } - //@ assert ok1: p->t[1] == \at(p->t[1], Pre); - //@ assert ok2: p->b == \at(p->b, Pre); - //@ assert KO: p->a == 0; // not provable this because of stmt spec -} - -void caveat_havoc_shift (int * p) { - //@ assigns p[0]; - { - p[0] = 0; - } - //@ assert ok_with_caveat: p[1] == \at(p[1], Pre); - //@ assert KO: p[0] == 0; -} -void caveat_havoc_range (int * p) { - //@ assigns p[1..3]; - { - p[1] = 0; p[3] = 0; - } - //@ assert ok_with_caveat: p[0] == \at(p[0], Pre); - //@ assert KO: p[1] == 0; // not provable this because of stmt spec -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_exit.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_exit.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_exit.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_exit.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//------ example from BTS #312 -/*@ exits never_exits: oracle_ok: \false; - behavior oracle_ko : - ensures oracle_ko: \false; // <- invalid property -*/ -int main() { - return 1; -} - -/*@ assigns \nothing ; - ensures never_returns: \false; - exits exit_status: \exit_status==status; - */ -extern void exit(int status); - -int X ; -/*@ behavior never_exits: - assumes x>=0; - exits never_returns: oracle_ok: \false; - behavior never_returns: - assumes x<0; - assigns \nothing ; - ensures never_returns: oracle_ok: \false; - exits exit_status: oracle_ok: \exit_status==1; - behavior oracle_ko : - assumes x<0; - exits oracle_ko: \false; // <- invalid property -*/ -int may_exit(int x) { - if (x < 0) - exit(1); - X = 1; - return 0 ; -} - -/*@ behavior never_returns : - assumes x<0; - assigns oracle_ok: X; - behavior all : - assigns oracle_ok: X; - ensures result_value: oracle_ok: \result == 0; - exits exit_status: oracle_ok: \exit_status==1; - behavior oracle_ko: - assumes x<0; - assigns \nothing ; // <- invalid property - behavior oracle_bis_ko : - ensures oracle_ko: \false; // <- invalid property - exits oracle_ko: \false; // <- invalid property -*/ -int may_exit_bis(int x) { - X = 1; - if (x < 0) - exit(1); - return 0 ; -} - -/*@ assigns \nothing ; - @ ensures never_returns: \false ; - @ exits exit_status: \exit_status == status ; - @ */ -void exit (int status); -int status ; - -/*@ assigns oracle_ok: status ; - @ exits oracle_ok: ! cond && \exit_status == 1 && status == val ; - @ */ -void may_exit2 ( int cond , int val ) { - if (! cond ) { - status = val ; - exit (1); - } -} - -int stmt_never_exit (int c) { - int x; - - /*@behavior ok: exits oracle_ok: 1 == 2; */ - if (c) x = 1; - else x = 0; - - return x; -} - -int stmt_may_exit (int c) { - int x; - - /*@behavior ok: exits oracle_ok: c && \exit_status == 1; */ - if (c) exit (1); - else x = 0; - return x; -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_froms.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_froms.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_froms.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_froms.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -/* run.config - DONTRUN: not available for Carbon release. - OPT: -wp -wp-froms -wp-print -*/ - -/*@ axiomatic A { - logic int D_FI_fext_1 (int c, int x, int y); - logic char test (char x); - } -*/ - -struct Tstr {int a; int b; int c; } S; -int x ,y ,z , * p ; -int T[100]; - -/*@ - assigns \result \from c, x, y; - assigns x \from c, y; - behavior c_true : - assumes c != 0; - assigns x \from \nothing; - assigns \result \from x; - behavior c_false: - assumes c == 0; - assigns x \from y; - assigns \result \from y; -*/ -int fh (int c) { - int a = c ? x : y; - x = c ? 0 : a; - return a; -} -/*@ - assigns \result \from c, x, y; - assigns x \from c, y; -*/ -int fext (int c); - -/*@ - assigns \result \from c, x, y; - assigns x \from c, y; - assigns y \from y; -*/ -int call (int c) { - int xa; - c++; - xa = fext (c); - y++; - return xa; -} - -int unknown (int); - -//@ assigns \result \from x, y; // test comment... -int spec () { - int a = 0; - int b = x; - - //@ assigns b \from y, a; - if (y > 0) - b = unknown (a); - - return b; -} - -/*@ assigns \result \from x, n; -*/ -int loop (int n) { - int s = 0; - /*@ loop assigns s \from i, x; - loop assigns i \from i; - */ - for (int i = 0; i < n; i++) { - s += x; - } - return s; -} - -int loop2 (int n) { - int s = 0; - /*@ loop assigns s \from s, T[0..(i-1)]; - @ loop assigns T[0..(i-1)] \from \nothing; - @ loop assigns i \from i; - */ - for (int i = 0; i < n; i++) { - s += T[i]; - T[i] = 0; - } - return s; -} - -/*@ assigns \result \from S; -*/ -int * maxS (void) { - int * p = &(S.a); - if (*p < S.b) p = &(S.b); - if (*p < S.c) p = &(S.c); - return p; -} - - -/*@ - assigns x \from c , y , x ; - assigns z \from c , x , z ; - assigns p \from c ; - - behavior c_true : - assumes c ; - assigns x \from y ; - assigns p \from \nothing ; - - behavior c_false : // et ça behavior - assumes ! c ; - assigns z \from x ; - assigns p \from \nothing ; -*/ -void f ( int c ) { - if ( c ) p = & y ; - else p = & z ; - - if (! c ) * p = x + 1; - else x = * p + 1; -} - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_globs.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_globs.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_globs.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_globs.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -/*@ logic boolean ok0 (integer i) = (0<= i) ; - @ logic boolean ok1 (integer i) = (i <= 10) ; - @ logic boolean ok (integer i) = ok0 (i) && ok1 (i) ; - */ - -//@ predicate is_ok (int i) = (0 <= i && i <= 10) ; - -/* TODO : test ok with GUI but incorrect interpretation of alt-erdo results - * with why-dp... - */ - -/*@ behavior b_logic : ensures ok (\result); - @ behavior b_predicate : ensures is_ok (\result); -*/ -int test (int x) { - if (x < 0) return 0; - //@ for b_logic : assert ok0 (x); - if (10 < x) return 10; - //@ for b_logic : assert ok1 (x); - return x; -} - -//WARNING : predicate pos_at{L} (integer n) = (0<= n) ; -// doesn't means : 0 <= \at(n, L) ! -// because 'n' is a value; it is not related to a memory state... - -//@ predicate positive (integer n) = (0 < n) ; - -/*@ ensures positive (x) ==> positive (\result); - */ -int labpred (int x) { - return x+1; -} - -int G; - -//@ predicate gtG_at{L} (integer n) = (G < n) ; - -/*@ ensures gtG_at{Old}(x) ==> gtG_at (\result); - */ -int labpredGat (int x) { - G--; - return x-1; -} - -//@ predicate Gincr{L1,L2} = (\at(G, L1) < \at(G, L2)) ; - -/*@ requires positive(x); - @ ensures Gincr{Old,Here}; - */ -void labpred2 (int x) { - G += x; -} - - -#if 0 -/*@ axiomatic A1 { - predicate ok_with_G{L}(integer n) reads G ; - axiom gt_ok{L} : - \forall integer x; x > \at(G,L) ==> ok_with_G{L}(x); - } -*/ -/*@ axiomatic A2 {*/ - predicate biggerG{L1, L2}(integer n) reads G ; - axiom ax_biggerG {L1,L2} : - \forall integer x; \at(G,L1) + x <= \at(G,L2) ==> biggerG{L1,L2}(x); - /* - } -*/ -#endif - -int T [10]; - -//@ predicate Tn{LT, LG}(integer i) = \at(T[\at(G,LG)], LT) > i; - -void testTn () { - T[G] = 1; - G ++; - //@ assert Tn{Here,Pre}(0); -} -//------------------------------------------------------------------------------ -// Logic functions + axioms with label -//@ logic boolean eq_ptr{L} (int * p, integer x) = *p == x; - -/*@ requires \valid (p); - behavior test: assumes eq_ptr (p, 3); ensures \result == 3; -*/ -int read_p (int * p) { - return *p; -} -//------------------------------------------------------------------------------ -/*@ axiomatic Cpt { - @ - @ logic integer cpt_le_u{L} (int *t, integer u, integer n, integer m); - @ - @ axiom c1{L} : \forall int *t, integer u, integer i; - @ i >= 0 && u >= t[i] ==> - @ cpt_le_u{L}(t, u, 0, i) == cpt_le_u{L}(t, u, 0, i-1) + 1; - @ - @ axiom c2{L} : \forall int *t, integer u, integer i; - @ i >= 0 && u < t[i] ==> - @ cpt_le_u{L}(t, u, 0, i) == cpt_le_u{L}(t, u, 0, i-1); - @ - @ axiom c3{L} : \forall int *t, integer u, integer i; - @ i < 0 ==> cpt_le_u{L}(t, u, 0, i) == 0; - @ } - @*/ - -//@ ensures \result == cpt_le_u{Here}(t, M, 0, 9); -int cpt (int * t, int M) -{ - int s = 0; - -/*@ loop invariant 0 <= i && i <= 10; - loop invariant I2: s == cpt_le_u{Here}(t, M, 0, i-1); - loop assigns i, s; -*/ - for (int i = 0; i < 10; i++) { - if (t[i] <= M) - s++; - } - return s; -} -//------------------------------------------------------------------------------ -/*@ axiomatic Le { - @ logic boolean le_G{L} (int x) reads G; - @ } -*/ - -void logic_with_reads (int x) { - G = 0; - //@ assert ko: le_G{Here}(x) == le_G{Pre}(x); -} - - -//------------------------------------------------------------------------------ -int main (void) { return 0 ; } -//------------------------------------------------------------------------------ diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_guard_m1.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_guard_m1.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_guard_m1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_guard_m1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ - -int X, Y; -int T[10]; -int * P; - -struct Tstr { int a; int * p; } S; - -// notice that no guard is generated because there are only direct assigns, -// and direct access in the predicate. So M1 <==> M0. -//@ ensures X + Y + S.a + T[0] == \old(X + Y + S.a + T[0]) + 4; -void vars (void) { - X ++; - S.a ++; - T[0] ++; - Y ++; -} - -// This one cannot be proved because we don't know if P points on X -/*@ ensures *P > X; */ -void f_no_hyp (void) { - int x = X; - *P = x + 1; -} -/*@ requires \separated (P, &X) && \separated (P, &P); - ensures *P > X; -*/ -void f_with_hyp (void) { - int x = X; - *P = x + 1; -} -//@ ensures \result == 0; -int ptr_tab () { - P = &X; - T[2] = 0; - *P = 3; - return T[2]; -} -// Rem : even if the postcondition is about the case where P points on X, -// we cannot prove it with M1 because the guard has to be verified in all cases. -//@ ensures c != 0 ==> \result == 0; -int ptr_tab_2 (int c) { - if (c) - P = &X; - T[2] = 0; - *P = 3; - return T[2]; -} -/*@ requires \valid(P); - ensures *P == \old(*P) + 1 && \result == 3; -*/ -int locvar_globptr (void) { - int x = 3; - (*P)++; - return x; -} -/* TODO : there is a problem here with M1 because (*p) in ensure is (*(\old(p)) - * and then p is an alias of old_p --> assign (*p)++ is not ok ! */ -/*@ requires \valid(p); - ensures *p == \old(*p) + 1 && \result == 3; - */ -int locvar_vs_paramptr (int * p) { - int x = 3; - (*p)++; - return x; -} -void cmp_shift (int * p, int i, int j) { - *(p+i) = 1; - *(p+j) = 2; - //@ assert i != j ==> *(p+i) == 1; -} -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_if1.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_if1.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_if1.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_if1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -int c; - -//@ ensures ( (!(c==0)) ==> \result == 1) && ((c==0) ==> \result == 2); -int main(void) { - int x; - x = x; - if (c) x = 1; else x = 2; - return x; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_inv_in_loop.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_inv_in_loop.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_inv_in_loop.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_inv_in_loop.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -// cf aussi bts494 examples in wp_loop.c - -//@ensures \result == 5; -int simple_inv (void) { - int i = 0; - while (i < 5) { - //@ invariant 0 <= i < 5 ; - i++; - } - return i; -} -int inv_from_init (void) { - int x = 5; - int i = 0; - //@ loop assigns i ; - while (i < 5) { - //@ invariant i < x ; - i++; - } - return i; -} -/* -int caveat_inv (int n) { - int i, s = 0; - //@ loop assigns i, s; - for (i = 0; i < n; i++) { - //@ invariant 0 <= i < n ; - s++; - } - return s; -} -*/ -int double_loop (void) { - for (int i = 0; i < 10; i++) { - //@ invariant 0 <= i < 10 ; - //@ loop assigns j; - for (int j = 0; j < i; j++) { - //@ invariant 0 <= j < i ; - ; - } - } - return 0; -} - -int T[10][20]; -/*@ ensures post: - \forall int i, j; 0 <= i < 10 ==> 0 <= j < 20 ==> T[i][j] == 0; -*/ -void razT2 (void) { - for (int i = 0; i < 10; i++) { - /*@ invariant Ii: \forall int i0, j; 0 <= i0 < i ==> 0 <= j < 20 - ==>T[i0][j] == 0; - */ - //@ loop assigns j, T[i][0..19]; - for (int j = 0; j < 20; j++) { - /*@ invariant \forall int i0, j0; 0 <= i0 < i ==> 0 <= j0 < 20 - ==> T[i0][j0] == 0; */ - /*@ invariant \forall int j0; 0 <= j0 < j ==> T[i][j0] == 0; */ - T[i][j] = 0; - } - } -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_ll2.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_ll2.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_ll2.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_ll2.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-proof z3 -wp-print -wp-verbose 2 -*/ - -/* ---------------------------------------------------------------------------*/ - -#define INT2DOUBLE(E,S) \ -{\ - register int i1;\ - register double f1;\ - i1=(E);\ - i1=(i1<<3)>>15;\ - f1=(double)i1;\ - (S)=f1;\ -} - -/*@ logic integer read_bit(integer x, integer i) = - ((x & (1<<(i-1))) == 0) ? 0 : 1; */ - -/*@ -behavior x_29_13_positive : - assumes read_bit(x,29) == 0; - ensures \result == \sum(1, 16, - \lambda integer k; read_bit(x,12+k) * (1<<(k-1))); - -behavior x_29_13_negative : - assumes read_bit(x,29) == 1; - ensures \result == 1 + \sum(1, 16, - \lambda integer k; (1-read_bit(x,12+k)) * (1<<(k-1))); -*/ -double INT2DOUBLE_wrapper(unsigned int x) { - double y; - INT2DOUBLE(x,y) - return y; -} - -/* ---------------------------------------------------------------------------*/ - - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_ll.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_ll.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_ll.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_ll.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,254 +0,0 @@ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-proof simplify -wp-print -wp-verbose 2 -*/ - - -/* ---------------------------------------------------------------------------*/ -/* TODO: many funny examples at - * http://graphics.stanford.edu/~seander/bithacks.html. - */ -/* ---------------------------------------------------------------------------*/ -int X,Y; -char T[10]; - -struct str { char c; int i; }; -struct str1 { int a; int b; int c; int d; } S1; -struct str2 { int x; int y; int z; } S2; - -/* ---------------------------------------------------------------------------*/ - -#define NULL ((void*)0) - - -//@ ensures \result == 0; -int null_is_zero (void) { - void * p = NULL; - return (int) p; -} - -//@ ensures c == 0 ==> \result == \null; -int * null (int c) { - int * p = c ? &X : NULL; - return p; -} -/* ---------------------------------------------------------------------------*/ - -/* For numeric address as pointeur, see [tests/wp/numeric_addr.c] */ - -/*@ behavior bigendian : ensures \result == 1; - */ -char ch_interp (void) { - int x = 0x01020304; - char * p = &x; - char c = *p; - return c; -} -/* -Lemma wp_ch_interp_bigendian_post_1 : - -intros M2 M3 M4 M5. -subst M5. -rewrite bits_of_sint8_of_bits. -subst M4. -repeat rewrite load_store_same. -rewrite uint32_of_bits_of_uint32. -subst M3. -rewrite load_store_disj; - [ | apply base_sep; rewrite x_0_name; rewrite p_0_name; - rewrite uniq_name; auto with zarith ]. -rewrite load_store_incl_part; unfold rt_incl; auto with zarith. -rewrite Zminus_diag. - -Remains : - sint8_of_bits (bits_part (bits_of_sint32 16909060) 0 8) = 1 -*/ - -//@ assigns T[1..3]; -void range (void) { - T[1] = 1; - T[2] = 2; - T[3] = 3; -} - -/*@ behavior bigendian : ensures \result == 3; - */ -int cast4 (void) { - int * p = T; - T[0] = 0; T[1] = 0; T[2] = 0; T[3] = 3; - return *p; -} -/* - - -intros. -subst __retres mb3 mb2 mb1 mb0 p. -rewrite addr_of_pointer_of_addr. -unfold rt_shift. -repeat (rewrite simpl_as_int; [ | rewrite is_in_format_sint8; omega]). - -replace (rt_vaddr ma X_T + 0) with (rt_vaddr ma X_T) by omega. - -Hint Rewrite bits_concat_size rt_to_bits_size sint8_format_size : smp_rt_size. - -erewrite (store_concat mb); eauto. -3: erewrite (store_concat mb); eauto. -4: erewrite (store_concat mb); eauto. - -4: autorewrite with smp_rt_size; auto with zarith. -3: autorewrite with smp_rt_size; auto with zarith. -2: autorewrite with smp_rt_size; auto with zarith. - -rewrite load_store_same; autorewrite with smp_rt_size; auto with zarith. - -rewrite rt_int_from_bits. -rewrite big_b32_to_bbits; - [ |autorewrite with smp_rt_size; omega | ]. - -rewrite bits_concat_nth_byte_left; [ | autorewrite with smp_rt_size; omega]. -rewrite bits_concat_nth_byte_left; [ | autorewrite with smp_rt_size; omega]. -rewrite bits_concat_nth_byte_left; [ | autorewrite with smp_rt_size; omega]. - -rewrite bits_concat_nth_byte_left; [ | autorewrite with smp_rt_size; omega]. -rewrite bits_concat_nth_byte_left; [ | autorewrite with smp_rt_size; omega]. -erewrite (bits_concat_nth_byte_right _ _ 1); eauto; autorewrite with smp_rt_size; try omega. - -rewrite bits_concat_nth_byte_left; [ | autorewrite with smp_rt_size; omega]. -erewrite (bits_concat_nth_byte_right _ _ 2); eauto; autorewrite with smp_rt_size; try omega. - -erewrite (bits_concat_nth_byte_right _ _ 3); eauto; autorewrite with smp_rt_size; try omega. - -repeat rewrite nth_byte_0; autorewrite with smp_rt_size; auto. - -unfold cint_of_bits. -rewrite sint32_format_sign. -rewrite ite_true. -rewrite sint32_format_size. -rewrite sint_of_bits_def; [ | omega]. -repeat (rewrite concat_bytes_left; [ | omega]). -rewrite mbyte_to_bbits_def; autorewrite with smp_rt_size; try omega. -erewrite rt_to_bits_zero; eauto; autorewrite with smp_rt_size; try omega. -rewrite bit_of_bool_false; ring_simplify. - ---------------------- -Another one : - - - - -*/ - -/* ---------------------------------------------------------------------------*/ - -/*@ requires \valid (p1); - ensures p1->b == 0; -*/ -void struct_cast (struct str1 * p1) { - struct str2 * p2 = (struct str2 *) p1; - //@ assert \valid (p2); - p2->y = 0; -} -//@ requires \valid (p2); -void invalid_struct_cast (struct str2 * p2) { - struct str1 * p1 = (struct str1 *) p2; - //@ assert ko : \valid(p1); -} - -/* === About memcpy ----------------------------------------------------------*/ - -/*@ - requires \valid (src + (0..n-1)); - requires \valid (dest+(0..n-1)); - requires \separated (src + (0..n-1), dest+(0..n-1)); - - ensures \forall integer i; 0 <= i < n ==> dest[i] == \old(src[i]); - assigns dest[0..n-1] \from src[0..n-1] ; -*/ -void memcpy(char *dest, char *src, unsigned long n); - -void use_memcpy_on_int (int * p) { - int x; - memcpy (&x, p, sizeof (x)); - //@ assert x == \at(*p,Pre); -} -/* -Proof. - -intros. -apply same_bits_same_val. -subst mb_3. -unfold rt_shift in *; simpl; rewrite Zplus_0_r. -unfold rt_vzone. -erewrite rt_valloc_size; [ | subst ma0; eauto]. -rewrite load_store_same. - - -(* 1st byte 8 *) -eapply (eq_bits_split _ _ 32 _ _ 8 24); auto with zarith. - -eapply same_int_val_same_bits in H1; - try instantiate (1 := 0); - try rewrite sint8_format_size; - try rewrite bits_part_size; - try rewrite rt_load_size; - try rewrite size_zone; - auto with zarith. - -rewrite load_store_incl_part in H1; [ | - unfold rt_incl; repeat rewrite addr_zone; repeat rewrite size_zone; auto with zarith]. -repeat rewrite addr_zone in H1; rewrite size_zone in H1. -unfold rt_shift in *. - simpl in H1; repeat rewrite Zplus_0_r in H1; - rewrite Zminus_diag in H1. - -rewrite H1. -eapply bits_part_rt_load; eauto; [ | - unfold rt_incl; repeat rewrite addr_zone; repeat rewrite size_zone; auto with zarith]. -rewrite addr_zone; rewrite Zplus_0_r; auto. - -auto with zarith. - -(* Same thing for 2d 3rd 4th byte ... *) - -eapply (eq_bits_split _ _ 24 _ _ 8 16); auto with zarith; - repeat rewrite bits_part_of_bits_part; simpl. - -Save. - - */ - -void use_memcpy_on_struct (struct str * p) { - struct str x; - memcpy (&x, p, sizeof (x)); - //@ assert x == \at(*p, Pre); -} -/* - -intros. - -rewrite EqrecDef_str. -split; erewrite <- bits_part_vs_access; eauto; - [ rewrite Loaded_str_c; - destruct Finfo_str_c as [Hf1 [Hf2 Hf3]]; - rewrite Hf1; rewrite Hf2; rewrite Hf3 - | rewrite Loaded_str_i; - destruct Finfo_str_i as [Hf1 [Hf2 Hf3]]; - rewrite Hf1; rewrite Hf2; rewrite Hf3 -]; clear Hf1 Hf2 Hf3 . - -(* 1st field is a [char] *) - -replace 0 with (8*0) by auto with zarith . -rewrite <- (H2 0); auto with zarith; clear H2. -apply same_bits_same_val. -symmetry. eapply bits_part_rt_load; eauto; - unfold rt_vzone, rt_incl, rt_shift; - repeat rewrite addr_zone; repeat rewrite size_zone; split; auto with zarith. - -erewrite rt_valloc_size; subst ma0; eauto; auto with zarith. - -(* 2d field *) - -see. use_memcpy_on_int - - */ -/* ---------------------------------------------------------------------------*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_localaddr.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_localaddr.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_localaddr.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_localaddr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* run.config_pruntime - OPT: -wp -wp-model Runtime -wp-no-logicvar -journal-disable -wp-proof simplify -wp-print -wp-verbose 2 -*/ - -//@ensures \result ; -int f(void) -{ - int *p; - int *q; - - { int x=1 ; p = &x ; } - { int y=2 ; q = &y ; } - - //@assert p_invalid_ok: !\valid(p) ; - //@assert q_invalid_ok: !\valid(q) ; - //@assert p_q_compare_ko: p != q ; - //@assert p_q_compare_ok: \valid(p) ==> \valid(q) ==> p!=q ; - - //@assert p_read_ko: *p == 1 ; - //@assert q_read_ko: *q == 2 ; - - return *p == 1 && *q == 2 ; - -} - -/*@ ensures ok : \result == 0 || \result == 1; - ensures ko1 : \result == 0; - ensures ko2 : \result == 1; -*/ -int cmp_invalid_addr (void) { - int *p; - int *q; - - { int x=1 ; p = &x ; } - { int y=2 ; q = &y ; } - - return (p == q) ? 1 : 0; -} - -/*@ ensures ok : \result == 0 || \result == 1; - ensures ko1 : \result == 0; - ensures ko2 : \result == 1; -*/ -int cmp_invalid_addr_as_int (void) { - int p; - int q; - - { int x=1 ; p = (int) &x ; } - { int y=2 ; q = (int) &y ; } - - return (p == q) ? 1 : 0; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_loop.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_loop.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_loop.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_loop.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,399 +0,0 @@ - -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -//@ assigns \nothing; -void infinite (int c) { - int s = 0; - if (c) { - //@ loop assigns s; - while (1) - s++; - //@ assert 2 > 1; - } - //@ assert c == 0; -} - -//@ assigns \nothing; -void loops (int c) { - int x; - - if (c) x=0; - x=3; - - - //@ loop assigns x; - while (c) { x=0;} - x=1; - - - if (c) - //@ loop assigns x; - while(c) x=0; - x=1; - - - if (c) - //@ loop assigns x; - do {x=0; } while(c); - x=1; - //@ assert x == 1; - -} - -/*@ assigns \nothing; - ensures \result == 9 ; */ -int classical_loop () { - int i; - int s = -1; - - /*@ loop invariant s + 1 == i && i <= 10; - @ loop assigns i, s; - */ - for (i=0; i< 10; i++) s = i ; - - return s; -} - -/*@ assigns \nothing; - ensures \result == 5; */ -int simple_loop (int c) { - int x; - int c = 0; - - /*@ loop invariant 0 <= c <= 6 && ((c==0 || x == c-1)); - @ loop assigns c, x; - */ - for(c=0;c<=5;) { - // CEA_DUMP(); - x = c; - c++; - // CEA_DUMP(); - } -// CEA_DUMP(); -//@ assert c == 6; - return x; -} - -/*@ assigns \nothing; - ensures \result == 6; */ -int goto_natural_loop (int c) { - int c = 0; -L : if (c > 5) goto R; - c++; - goto L; -R : return c; -} - -int T[10]; - -//@ ensures \result == T + 5; -int * ptr_on_array () { - int * p = T; - int i; - /*@ loop invariant i <= 5 && p == T+i; - @ loop assigns i, p; - */ - for (i = 0; i < 5; i++) - p++; - return p; -} - -void assigns_loop_tab (void) { - //@ loop assigns i, T[0..i-1]; - for (int i = 0; i < 10; i++) { - T[i] = 0; - } -} -//@ requires \valid (&(t[0..9])); -void assigns_loop_ptr (int * t) { - /*@ loop assigns i, t[0..i-1]; - loop invariant (10 >= i >= 0); - */ - for (int i = 0; i < 10; i++) { - t[i] = 0; - } -} - -/*@ ensures p_ok : T[9] == \old(T[9]); - ensures p_ko : T[3] == \old(T[3]); -*/ -void post_using_loop_assigns (void) { - /*@ loop invariant i <= 7; - loop assigns i, T[0..i-1]; - */ - for (int i = 0; i < 7; i++) { - T[i] = 0; - } -} - -/*@ ensures p_ok : T[9] == \old(T[9]); - ensures p_ko : T[3] == \old(T[3]); -*/ -void post_using_loop_assigns_no_inv (void) { - /*@ loop assigns i, T[0..6]; */ - for (int i = 0; i < 7; i++) { - T[i] = 0; - } -} - - -void loop_assert () { - int i = 0; - /*@ loop invariant i >= 0; - @ loop assigns i; */ - while (i < 10) { - ++i; - //@ assert 0 < i <= 10; - } -} - -int loop_assigns () { - int i = 0; - int s = 0; - /*@ loop assigns i, s; - */ - while (i < 10) { - s += i; - i++; - } - return s; -} -int loop_assigns_ko (void) { - int s = 0; - int i; - //@ loop assigns s; - for (i = 0; i < 10; i++) { - s++; - } - return s; -} - -int loop_var (int n) { - int i, s = 0; - /*@ loop assigns i, s; - @ loop variant (n - i); - */ - for (i = 0; i < n; i++) { - s++; - } - return s; -} - -int loop_inv_only (int n) { - int i, s = 0; - /*@ loop invariant 0 <= i && s == i; - loop assigns i,s ; */ - for (i = 0; i < n; i++) { - s++; - } - return s; -} - -//@ ensures \result == -1 || T[\result] == a; -int find (int a) { - int i; - //@ loop assigns i; - for (i = 0; i < 10; i++) { - if (T[i] == a) return i; - } - return -1; -} -int inv_need_init () { - int k = 4; - int i = 0; - /*@ loop invariant i <= 4; - loop assigns i; - */ - while (i < k) - i++; - return i; -} - -/*@ requires 0 <= m && m < M && M <= 10; - @ ensures \forall int k; m <= k && k < M ==> T[k] == 0; -*/ -void raz (int m, int M) { - /*@ loop invariant m <= i && i <= M; - loop invariant \forall int k; m <= k && k < i ==> T[k] == 0; - loop assigns i, T[m..(i-1)]; - */ - for (int i = m; i < M; i++) { - T[i] = 0; - } -} -void loop_assigns_limit (void) { - /*@ loop invariant T[i] == \at(T, Pre)[i]; - loop invariant 0 <= i; - loop assigns i, T[0..(i-1)]; - */ - for (int i = 0; i < 10; i++) - T[i] = 0; -} -/*----------------------------------------------------------------------------*/ - -//@ ensures \result >= n; -int bts494a (int n) { - int i = 0 ; - //@ loop invariant 0 <= i && (0 <= n ==> i <= n) && n == \at(n, Pre); - while (i < n) - i++ ; - return i; -} - -//@ ensures \result >= n; -int bts494b (int n) { - int i = 0 ; - /*@ loop invariant 0 <= i && (0 <= n ==> i <= n); - loop assigns i; - */ - while (i < n) - i++ ; - return i; -} - -//@ ensures \result >= n; -int bts494c (int n) { - int i = 0 ; - while (i < n) - //@ invariant 0 <= i < n && n == \at(n, Pre); - i++ ; - return i; -} - -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/* Examples from DivEx1.c but adapted to substitute pointer by array - * to be able to test is with Hoare. */ - -typedef struct {int ch11[10]; int ch12;} T1; -typedef struct {int ch21; T1 ch22;} T2; - -T2 t[20]; - -void loops_simple_assigns (void) { - int i, j ; - - /*@ loop assigns i, j, t[0..19].ch21, t[0..19].ch22.ch11[..]; - loop invariant I0: oracle_ok: 0 <= i && i <= 20; - loop invariant I1 : oracle_ok: - \forall int k; 0 <= k && k < i ==> t[k].ch21 == 0; - */ - for (i = 0 ; i < 20 ; i++) { - t[i].ch21 = 0 ; - /*@ loop assigns j, t[i].ch22.ch11[0..9]; - loop invariant J0: oracle_ok: 0 <= j && j <= 10; - */ - for (j = 0 ; j < 10 ; j++) - t[i].ch22.ch11[j] = 0 ; - } -} - -void loops_var_assigns (void) { - int i, j ; - - /*@ loop assigns i, j, t[0..i-1].ch21, t[0..i-1].ch22.ch11[..]; - loop invariant I0: oracle_ok: 0 <= i && i <= 20; - loop invariant I1 : oracle_ok: - \forall int k; 0 <= k && k < i ==> t[k].ch21 == 0; - */ - for (i = 0 ; i < 20 ; i++) { - t[i].ch21 = 0 ; - /*@ loop assigns j, t[i].ch22.ch11[0..j-1]; - loop invariant J0: oracle_ok: 0 <= j && j <= 10; - */ - for (j = 0 ; j < 10 ; j++) - t[i].ch22.ch11[j] = 0 ; - } -} - -/*----------------------------------------------------------------------------*/ -/* This is the example of loop variant given in ACSL document. - * Notive that this loop variant is ok even for \at(Pre, x < 0). - * Notice also that the variant can be negative at the last iteration. */ -void doc_acsl_variant (int x) { - //@ loop variant x; - while (x >= 0) { - x -= 2; - } -} -/*----------------------------------------------------------------------------*/ -/* The ensures of [incr_tab] is proved, - * and it should be proved in [incr_tab] too, - * but it seems that we don't manage to use the loop assigns... */ - -//@ ensures \forall integer k; 0 <= k < 10 ==> T[k] == \old(T[k]) + 1; -void incr_tab (void) { - int x = 1; - /*@ loop invariant @ 0 <= i <= 10 - @ && (\forall integer k; 0 <= k < i ==> T[k] == \at(T[k],Pre) + x) - @ && x == 1 - @ && (\forall integer k; i <= k ==> T[k] == \at(T[k],Pre)) - @ ; - */ - for (int i = 0; i < 10; i++) { - T[i] = T[i] + x; - } -} - -//@ ensures \forall integer k; 0 <= k < 10 ==> T[k] == \old(T[k]) + 1; -void incr_tab_assigns (void) { - int x = 1; - /*@ loop invariant @ 0 <= i <= 10 - @ && (\forall integer k; 0 <= k < i ==> T[k] == \at(T[k],Pre) + x) - // @ && x == 1 - // @ && (\forall integer k; i <= k ==> T[k] == \at(T[k],Pre)) - @ ; - @ loop assigns i, T[0..i-1]; - */ - for (int i = 0; i < 10; i++) { - T[i] = T[i] + x; - } -} - -/*@ requires \valid(t) - && \forall integer k; 0 <= k < 10 ==> \separated (&t, t+k); - @ ensures \forall integer k; 0 <= k < 10 ==> t[k] == \old(t[k]) + 1; -*/ -void incr_ptab (int * t) { - int x = 1; - /*@ loop invariant @ 0 <= i <= 10 - @ && (\forall integer k; 0 <= k < i ==> t[k] == \at(t[k],Pre) + x) - @ && t == \at(t, Pre) - @ && \forall integer k; 0 <= k < 10 ==> \separated (&t, t+k) - @ && x == 1 - @ && (\forall integer k; i <= k ==> t[k] == \at(t[k],Pre)) - @ ; - */ - for (int i = 0; i < 10; i++) { - t[i] = t[i] + x; - } -} - -/*@ requires \valid(t); - @ ensures \forall integer k; 0 <= k < 10 ==> t[k] == \old(t[k]) + 1; -*/ -void incr_ptab_assigns (int * t) { - int x = 1; - /*@ loop invariant @ 0 <= i <= 10 - @ && (\forall integer k; 0 <= k < i ==> t[k] == \at(t[k],Pre) + x) - // @ && x == 1 - // @ && (\forall integer k; i <= k ==> t[k] == \at(t[k],Pre)) - @ ; - @ loop assigns i, t[0..i-1]; - */ - for (int i = 0; i < 10; i++) { - t[i] = t[i] + x; - } -} -/*----------------------------------------------------------------------------*/ -//@ requires \valid (&t[0..n-1]); -void valid_range_inv (int *t, int n) { - //@ loop invariant n == \at(n,Pre); - for (int i = 0; i < n; i++) { - //@ assert \valid (t+i); - t[i] = 0; - } -} -/*----------------------------------------------------------------------------*/ diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_niy.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_niy.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_niy.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_niy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/*@ - requires n >= 0; - terminates \true; - decreases 101 - n; - assigns \nothing; - behavior b91 : - assumes n <= 101; - ensures \result == 91; - behavior b100 : - assumes n > 100; - ensures \result == n - 10; -*/ -int f91 (int n) { - if ( n > 100 ) - return n - 10; - else - return f91(f91(n+11)); -} - -// This is not handled yet, -// but I am not sure that we should accept to take the address of \result... -//@ ensures \valid (&(\result)); -int addr_result (void) { - return 0; -} - -int loop2 (int n) { - int i, s = 0; - for (i = 0; i < n; i++) { - //@ invariant 0 <= i < n ; - s++; - } - return s; -} - -/*@ requires c > 0; - */ -int goto_loop (int c) { - int x = 1; - L : x++; - //@ invariant (0 < c <= \at(c, Pre)) && x == 2 + (\at(c, Pre) - c); - if (--c > 0) goto L; - return x; -} - -/* Doc example 2.45 */ -int abrupt (int x) { - while (x > 0) { - /*@ breaks x % 11 == 0 && x == \old (x ); - @ continues (x +1) % 11 != 0 && x % 7 == 0 && x == \old (x ) -1; - @ returns ( \result +2) % 11 != 0 && ( \result +1) % 7 != 0 - @ && \result % 5 == 0 && \result == \old (x ) -2; - @ ensures (x +3) % 11 != 0 && ( x +2) % 7 != 0 && (x +1) % 5 != 0 - @ && x == \old (x ) -3; - @ */ - { - if (x % 11 == 0) break ; - x--; - if (x % 7 == 0) continue ; - x--; - if (x % 5 == 0) return x; - x--; - } - } - return x; -} - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_object.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_object.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_object.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_object.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - -typedef struct S { - int f ; - int t[10] ; -} ; - -struct S s; -int a[10] ; - -//@ensures (*s) == { \old(*s) \with .t = a } ; -void f(struct S * s) -{ - /*@loop assigns i,s->t[0..(i-1)] ; - @loop invariant 0 <= i <= 10 ; - @loop invariant \forall int k ; 0<=k<i ==> s->t[k] == a[k] ; - @*/ - for (int i=0; i<10; i++) - s->t[i] = a[i] ; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_old_at.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_old_at.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_old_at.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_old_at.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ - -int G, X, T[10]; - -// Notice that \result is in fact a shortcut for \at(\result, Post) -/*@ ensures \old(\result - (X + 1)) == 0 ; // test of frama-c comment -*/ -int test_at_old (int i) { - X++; -L : i++; - T[X] ++ ; - //@ assert i > \at(i, L) && \at(i, Here) == \at(i, Pre) + 1; - // Invalid assert Old is forbiden in 'assert' - // @ assert i > \at(i, Old); - return X; -} - -// this one seem problematic, but it is not because we push downward -// the \at to the data. -void at_imbric_ok (int a, int b) { - a = 0; -La : a = 1; - b = 0; -Lb : b = 1; - //@ assert \at(a + \at(b, Lb), La) == 0; - // Notice that La and Lb have to be in that order to see the problem, - // because if La appears before in WP computation, it then makes Lb visible - // without need of special processing. -} - -void at_imbric_ko (int a, int b) { - a = 0; - T[a] = 0; -La : a = 1; - b = 0; -Lb : b = 1; - //@ assert \at(T[ \at(b, Lb)], La) == 0; -} - -// label are normalized by cil -> Lb disapear. -void at_same_point (int a, int b) { - a = 0; - b = 0; - T[b] = 0; -La : -Lb : a = 1; - b = 1; - //@ assert \at(T[ \at(b, Lb)], La) == 0; -} - - -//@ ensures \old(T[\at(X,Here)] + 1) == \at(T[X], Post) ; -void test_at_imbric (void) { - X++; - T[X] ++; -} - -void labels_in_index (int a, int b) { -La : a = a+ 1; - b = 0; -Lb : b = 1; - T[a-1] = 0; -Lt : T[a-1] = 1; - //@ assert \at(T[\at(a + \at(b, Lb), Pre)], Lt) == 0; -} - - -//@ ensures \result[\at(i, Pre)] == 0; -int * result_and_pre (int i) { - int * p0, * pi; - p0 = T; - pi = p0 + i; - i = 0; - *pi = i; - return p0; -} - -// result_and_pre contient no_itself_pointer : -// manque hypothèse qu'un pointeur ne peut pointé -// sur lui-même en l'absence de cast. - -int *p; -int i; -/*@ assigns *p; - ensures p==\old(p); */ -void no_itself_pointer(){*p=0;} - -void labels_in_stmt_annot (void) { - X ++; - /*@ requires X > \at(X, Pre); - behavior B: - ensures X == \old(X) + 1; - ensures X == \at(X,Pre) + 2; - ensures X == \at(X,Post); - */ - X++; - X++; - //@ assert X == \at(X,Pre) + 3; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_pointer.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_pointer.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_pointer.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_pointer.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - -/*@ requires \valid(p+1) ; - ensures *(p+1) == 56 ; */ -int main(int *p) { - int x = 55; - *(p+1) = x + 1 ; - //@ assert 56 == *(p+1) ; - x++; - return 0; -} - -int G; -/*@ behavior b1 : - @ ensures \old(G) >=0 ==> G == \old(G); - @ behavior b2 : // this one seems similar to b1 - @ assumes G >= 0; - @ ensures G == \old(G); -*/ -void f () { - int * p; - p = &G; - if (G < 0) - *p = 0; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_pre_bhv.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_pre_bhv.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_pre_bhv.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_pre_bhv.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -/* run.config - OPT: -wp -wp-model Hoare -wp-print - */ - -// ORACLES FAUX pour les preuves des preconditions de main. -// On attend le but Start => A => U -// On obtient les buts Start, A et U - -//@ predicate P(integer x) ; - -int x = 0; - -/*@ requires Start: P(x) ; - @ ensures Final: P(x+1) ; - @ behavior useless: - @ assumes A: P(x+2) ; - @ requires U: P(x+3) ; - @ ensures B: P(x+4) ; - @ */ -int main(void) { - -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_pre.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_pre.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_pre.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_pre.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -/* run.config - OPT: -wp -wp-model Hoare -wp-print - - run.config_phoare - OPT: -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -//------------------------------------------------------------------------------ -// This file is to test the preconditions verification -//------------------------------------------------------------------------------ - -int X; // even if not initialized, we should be able to check that it is 0. -int X2 = 2; -int T[10]; - -//@ requires X >= 0; ensures X > 0; -void f (void) { - X++; -} - -/*@ requires X2 == 2; - @ requires X == 0; - @ requires \valid (&X); - @ requires \valid (&(T[0..9])); -*/ -int main (void) { - f (); - return 0; -} - -//------------------------------------------------------------------------------ diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_range.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_range.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_range.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_range.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -// le tout passe avec z3 -// frama-c-gui -wp-mm 2 -wp-prover z3 wp_range.c & - - -int T[10]; - -/*@ requires 0 <= i < 10; - @ ensures T[i] == \old(T[i]) + 1; - */ -void incr_elem_tab (int i) { - T[i]++; -} - -/*@ requires \valid_range(p,0,i) ; - ensures *(\old(p)+i) == 78; -*/ -void main (int *p,int i) { - p++; - p++; - p++; - *(p+i-3) = 78; -} - -/*@ requires 0 <= i < 5; - @ ensures \result == i; - */ -int local_tab (int i) { - int t[5]; - //@ assert \valid (t+i); - t[i] = i; - return t[i]; -} - -int * P; - -//@ ensures \forall int j; n <= j ==> *(P + j) == \old(*(P + j)); -int loop_assign (int n) { - int i; - //@ loop assigns i, P[0..(n-1)]; - for (i = 0; i < n; P++, i++) - *P = 0; - return i; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_rte.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_rte.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_rte.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_rte.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -/* run.config_phoare - OPT: -journal-disable -rte -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 - */ - -int T[10]; - -int read5 (void) { - return T[5]; -} - -/*@ requires 0 <= i < 10; - */ -int read (int i) { - return T[i]; -} - -int local_array (void) { - int t [8]; - return t[5]; -} - -int fext (); - -//@ ensures T[0] == \old(T[0]); -int call_fext () { if (fnd()) return 1; else return 0; } - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_show.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_show.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_show.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_show.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ - -/* ~~~ First of all, let's launch the tool : - cd ~/frama-c; FRAMAC_SHARE=share bin/viewer.opt tests/wp/wp_show.c - */ - -/* ~~~ Let's start with model 0 (no matter wp_bottom) */ - -/*@ - requires min <= max; - ensures min <= \result <= max; - - behavior Cmin : assumes x < min; ensures \result == min; - behavior Cmax : assumes x > max; ensures \result == max; - behavior Cx : assumes min <= x <= max; ensures \result == x; - - complete behaviors Cmin, Cmax, Cx; - disjoint behaviors Cmin, Cmax, Cx; - */ -int threshold (int min, int max, int x) { - if (max < x) - x = max; - if (x < min) - x = min; - return x; -} - -/* ~~~ M0 also works with arrays, structures and union */ - -int T [10]; -typedef struct _Tstr { char a; int t[50]; float x; char * p; } Tstr; -Tstr S; - -//@ ensures 0 <= j && j < 10 && i != j ==> \result == \old(T[j]); -int fstruct (int i, int j) { - int j2 = (0 <= j && j < 10) ? j : 0; - if (0 <= i && i < 10) - T[i] = S.t[i]; - return T[j2]; -} - -/* ~~~ loops are handled */ - -//@ ensures \forall int i; 0 <= i < 10 ==> T[i] == 0; -void razT (void) { - int i; - //@ loop invariant \forall int k; 0<= k < i ==> T[k] == 0; - for (i = 0; i < 10; i++) - T[i] = 0; -} - -/* ~~~ if one wants to use a light invariant, [loop assigns] should be used. */ - -void stat (int n) { - int i_min = 0, i_max = 0; - int min = S.t[0], max = S.t[0]; - int i, s = 0; - /*@ loop invariant \forall int k; 0<= k < i ==> min <= S.t[k]; - loop assigns S; - */ - for (i = 1; i < n; i++) { - s += S.t[i]; - if (S.t[i] < min) { min = S.t[i]; i_min = i; } - if (S.t[i] > max) { max = S.t[i]; i_max = i; } - } -} - -/* ~~~ calls are handled, but [assigns] specification is needed */ - - -/* ~~~ M0 can also deal with pointer computation, as long there is no access */ - -/*@ behavior B0: ensures \result == &(T[i]) || \result == &(S.t[i]); - behavior B1: ensures *\result >= T[i]; - */ -int * fptr (int i) { - int * p = (T[i] > S.t[i]) ? T : S.t; - return p + i; -} - -/* ~~~ let's now test [wp_bottom] option : */ - -/* ~~~ with bottom we can prove this property */ - -//@ behavior xpos : assumes x > 0; ensures \result == 1; -int fbot (int x) { - if (x > 0) - x = 1; - else { - x = *(S.p); - *(S.p) = 0; - } - return x; -} - -/* ~~~ we can prove some properties with a simple model, and then use them - * as hypotheses to prove some others. */ - -int main (void) { return 0 ; } diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_split.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_split.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_split.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_split.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -/* run.config - OPT: -wp -wp-model Hoare -wp-split -wp-print -wp-split-dim 2 -*/ -int a, b, c, d, e; - -/*@ - assigns \nothing; - - behavior split_and: - assumes a==0 && b==0 && c==0 && d==0 && e==0; - ensures ok:a==0 && b==0 && c==0 && d==0 && e==0; - - behavior split_if: - assumes (a==0 ==> b==0) && (a!=0 ==> c==0); - ensures ok:(a==0 ? b==0 : c==0) ; - - behavior split_forall: - assumes (\forall integer x ; (0<x<a ==> x<b)) && c==0; - ensures ok: \forall integer x ; (0<x<a ==> (x<b && c==0)) ; - - behavior split_not: - assumes !a==0; - ensures ok:!a==0; - - behavior split_not_not: - assumes a==0 && b==0; - ensures ok:!(!a==0 || !b==0); - - behavior split_not_or: - assumes !(a==0 || b==0); - ensures ok:!(a==0 || b==0); - - behavior split_not_if: - assumes (a==0 ==> b!=0) && (a!=0 ==> c!=0); - ensures ok:!(a==0 ? b==0 : c==0) ; - - behavior split_not_exists: - assumes (\forall integer x ; (0<x<a ==> x<b)) && c==0; - ensures ok: !\exists integer x ;(0<x<a && (!(x<b) || c!=0) ) ; - - */ -void f(void) { - -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_strategy.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_strategy.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_strategy.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_strategy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -/* run.config -OPT: -journal-disable -wp -wp-model Hoare -wp-print -wp-verbose 2 -OPT: -journal-disable -wp -wp-model Store -wp-print -wp-verbose 2 -wp-prop assigns -wp-assigns memory -*/ -/* run.config_phoare -OPT: -journal-disable -rte -wp -wp-model Hoare -wp-print -wp-verbose 2 -wp-proof alt-ergo -*/ - -/*----------------------------------------------------------------------------*/ - -/* This file is to test the strategy generation, so it doesn't need to be tested - * for different models. Let's choose examples that work with Hoare, - * except to test assign properties that need Store. - */ - -/*----------------------------------------------------------------------------*/ -/* we shouldn't be able to prove ko1 from ko2 and then ko2 from ko1 */ -/*@ ensures ko1 : \result == x+1; - ensures ko2 : \result == x+1; -*/ -int bts0513 (int x) { - return x; -} - -int bts0513_bis (int x) { - int i; - //@ assert ko1 : x > 0; - //@ assert ok : x > 0; - return x; -} -/*----------------------------------------------------------------------------*/ -// Problem of dependancies : we should be able to prove A, and the proof -// of E shouldn't depend on A ! - -void dpd1 (int x) { - //@ ensures Eko: x>0; - ; - //@ assert A: x>0; -} - -// workaround : -//@ behavior P: -void dpd2 (int x) { - //@ ensures Eko: x>0; - ; - //@ for P: assert A: x>0; -} -//============================================================================== -// specification of an IF block : notice that the proof of the ensures property -// shouldn't depend on [spec_if_f] properties. - -int Z; -int T[10]; - -/*@ assigns T[i]; ensures T[i] > i; */ -void spec_if_f (int i); - -//@ ensures T[0] > 0; -void spec_if (int c0, int c1, int c2) { - //@ assigns T[0], Z; ensures T[0] > 0; - if (c0) { spec_if_f (0); } else { T[0] = 5; } - //@ assigns T[1], Z; - if (c1) { spec_if_f (1); } else { Z++; } - //@ assigns T[2], Z; - if (c2) { spec_if_f (2); } else { Z++; } -} - -//============================================================================== -// when a IF condition is a negation, the AST doesn't have the same structure ! -// -void spec_if_cond (int c0) { - int i; - //@ ensures i > 0; - if (c0) { i = 2; } else { i = 1; } -} - -void spec_if_not_cond (int c0) { - int i; - //@ ensures i > 0; - if (!c0) { i = 2; } else { i = 1; } -} - -//============================================================================== -// Test is unnamed (default) behavior for function and blocks are not mixed -// together. - -//@ requires c == 0 ==> x >= 0; ensures \result > 0; -int default_behaviors (int c, int x) { - int y; - - //@ ensures stmt_p: x > 0; - if (c) x = 1; - else { - //@ assert x >= 0; - x++; - } - y = 0; - //@ assert x > y; - return x; -} -//============================================================================== diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_swap.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_swap.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_swap.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_swap.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - -/* run.config_phoare - OPT: -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -int G; -void main(int a, int b) { - if (a > b) { int tmp = a; a = b; b = tmp; } - /*@ assert a <= b; */ -} - -void main1( int a, int b, int c, int d) { - int tmp; - - if (a > b) { tmp = a; a = b; b = tmp; } - if (c > d) { tmp = c; c = d; d = tmp; } - if (a > c) { tmp = a; a = c; c = tmp; } - if (b > d) { tmp = b; b = d; d = tmp; } - if (b > c) { tmp = b; b = c; c = tmp; } - /*@ assert a <= b <= c <= d; */ -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_switch.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_switch.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_switch.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_switch.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ - -/* run.config_phoare - OPT: -journal-disable -wp -wp-model Hoare -wp-proof alt-ergo -wp-print -wp-verbose 2 -*/ - -/* - * To test [switch] in CFG : only need to test with one model. - * To view the graph : - FCT=simple; ./frama-c -wp -wp-dot -wp-fct $FCT tests/wp/wp_switch.c; \ - zgrviewer $FCT.cfg.dot - */ - -/*@ - behavior x1 : assumes x == 1; ensures \result == 2; - behavior x2 : assumes x == 2; ensures \result == 3; - behavior df : assumes x != 1 && x !=2; ensures \result == 11; - complete behaviors; disjoint behaviors; -*/ - -int simple (int x) { - int res = 0; - switch (x) { - case 1: res = 1; break; - case 2: res = 2; break; - default : res = 10; - } - res = res+1; - return res; -} -/*@ - behavior x1 : assumes x == 1; ensures \result == 2; - behavior x2 : assumes x == 2; ensures \result == 3; - behavior df : assumes x != 1 && x !=2; ensures \result == 1; - complete behaviors; disjoint behaviors; -*/ - -int no_default (int x) { - int res = 0; - switch (x) { - case 1: res = 1; break; - case 2: res = 2; break; - } - res = res+1; - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 3; - behavior x2 : assumes x == 2; ensures \result == 2; - behavior df : assumes x != 1 && x !=2; ensures \result == 1; - complete behaviors; disjoint behaviors; -*/ -int no_break (int x) { - int res = 0; - switch (x) { - case 1: res++; - case 2: res++; - } - res++; - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 1; - behavior x2_KO : assumes x == 2; ensures \result == 2; - behavior df : assumes x != 1 && x !=2; ensures \result == 0; - complete behaviors; disjoint behaviors; -*/ -int same_case (int x) { - int res = 0; - switch (x) { - case 1: res=1; break; - case 2: res=2; break; - case 1+1: res=4; break; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1 || x == 2; ensures \result == 1; - behavior x2 : assumes x == 4; ensures \result == 4; - behavior df : assumes x != 1 && x !=2 && x != 4; ensures \result == 0; - complete behaviors; disjoint behaviors; -*/ -int multi_case (int x) { - int res = 0; - switch (x) { - case 1: case 2: res=1; break; - case 4: res = 4; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 1; - behavior df : assumes x != 1; ensures \result == 2; - complete behaviors; disjoint behaviors; -*/ -int case_and_default (int x) { - int res = 0; - switch (x) { - case 1: res=1; break; - case 2: - default: res = 2; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 1; - behavior df : assumes x != 1; ensures \result == 2; - complete behaviors; disjoint behaviors; -*/ -int dead_inst (int x) { - int res = 0; - switch (x) { - case 1: res=1; break; - default: res = 2; break; - res = 3; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 1; - behavior x2 : assumes x == 2; ensures \result == 0; - behavior df : assumes x != 1 && x !=2; ensures \result == 3; - complete behaviors; disjoint behaviors; -*/ -int empty_case (int x) { - int res = 0; - switch (x) { - case 1: res=1; break; - case 2: break; - default: res=3; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 1; - behavior df : assumes x != 1; ensures \result == 2; - complete behaviors; disjoint behaviors; -*/ -int default_before (int x) { - int res = 0; - switch (x) { - default: res=2; break; - case 1: res=1; break; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 1; - behavior df : assumes x != 1; ensures \result == 2; - complete behaviors; disjoint behaviors; -*/ -int default_before_no_break (int x) { - int res = 0; - switch (x) { - default: res++; - case 1: res++; - } - return res; -} - -/*@ - behavior x1 : assumes x == 1; ensures \result == 5; - behavior x2 : assumes x == 2; ensures \result == 1; - behavior x3 : assumes x == 3; ensures \result == 11; - behavior df : assumes x != 1 && x !=2 && x !=3; ensures \result == 0; - complete behaviors; disjoint behaviors; -*/ -int another_label (int x) { - int res = 0; - switch (x) { - case 1: res=5; break; - case 2: L: res++; break; - case 3: res = 10; goto L; - } - return res; -} - diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_types.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_types.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_types.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_types.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -typedef enum _Color { Blue, Red, Black = 0 } Color; - -int int_of_color (Color col) { - int x; - if (col != Black) { - x = col; //@ assert x != 0; - } - else { - x = Black; //@ assert x == Blue; // strange property, isn't it? - } - return x; -} - - -//@ ensures \exists Color c; \result == c; // strange property, isn't it? -Color unspecified_color (void) { - return 10; // Unfortunatly, this is not forbidden! -} - -//@ ensures \result == Blue; -Color enum_in_annot (void) { - return Blue; -} diff -Nru frama-c-20110201+carbon+dfsg/tests/wp/wp_valid.c frama-c-20111001+nitrogen+dfsg/tests/wp/wp_valid.c --- frama-c-20110201+carbon+dfsg/tests/wp/wp_valid.c 2011-02-07 13:41:40.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/tests/wp/wp_valid.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -// see also : tests/wp/bts0085.c for a lot of tests about valid pointers - -int * P; -int T[10]; - -//@ requires \valid(P); -void f (void) { - int x; //@ assert P != &x; -} - -// If we don't know that \valid(p), we sould not be able to proof this. -//@ ensures \result == \old(*p); -int disj (int * p) { - int x = 3; - return *p; -} - -/*@ ensures ok1: 0 <= i < 10 ==> \valid (\result); - ensures ko: i == 10 ==> \valid (\result); - */ -int * valid_in_global_array (int i) { - return T+i; -} diff -Nru frama-c-20110201+carbon+dfsg/VERSION frama-c-20111001+nitrogen+dfsg/VERSION --- frama-c-20110201+carbon+dfsg/VERSION 2011-02-07 13:45:55.000000000 +0000 +++ frama-c-20111001+nitrogen+dfsg/VERSION 2011-10-10 08:40:09.000000000 +0000 @@ -1 +1 @@ -Carbon-20110201 +Nitrogen-20111001